mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-19 16:16:48 +00:00
replace raw C-strings with std::string in converted libfuse files
util/mount.mergerfs.cpp: - Remove xstrdup/xrealloc wrappers entirely - Convert type, source, options, command, setuid to std::string - Replace add_arg() pointer-rewriting with shell_quote() returning std::string - Replace add_option() with simple std::string += concatenation - Fix const_cast UB on string literal assignment lib/helper.cpp: - Convert add_default_subtype local subtype_opt: malloc+snprintf+free -> std::string construction lib/mount_generic.h: - Convert fuse_mount_sys locals source/type: malloc+strcpy+strcat -> std::string - Remove 4 unnecessary free() calls (RAII cleanup) - .c_str() at mount() and fuse_mnt_add_mount() boundaries lib/mount_util.h: - Rewrite fuse_mnt_resolve_path internals using std::string: rfind/substr instead of manual pointer arithmetic, strrchr, strlen chains
This commit is contained in:
committed by
trapexit
parent
21966ade97
commit
0cfab60f37
@@ -13,6 +13,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
@@ -86,24 +87,14 @@ fuse_helper_opt_proc(void *data,
|
||||
|
||||
static int add_default_subtype(const char *progname, struct fuse_args *args)
|
||||
{
|
||||
int res;
|
||||
char *subtype_opt;
|
||||
const char *basename = strrchr(progname, '/');
|
||||
if (basename == NULL)
|
||||
basename = progname;
|
||||
else if (basename[1] != '\0')
|
||||
basename++;
|
||||
|
||||
size_t optlen = strlen(basename) + 64;
|
||||
subtype_opt = (char *) malloc(optlen);
|
||||
if (subtype_opt == NULL) {
|
||||
fprintf(stderr, "fuse: memory allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(subtype_opt, optlen, "-osubtype=%s", basename);
|
||||
res = fuse_opt_add_arg(args, subtype_opt);
|
||||
free(subtype_opt);
|
||||
return res;
|
||||
std::string subtype_opt = "-osubtype=" + std::string(basename);
|
||||
return fuse_opt_add_arg(args, subtype_opt.c_str());
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
@@ -407,8 +408,8 @@ fuse_mount_sys(const char *mnt,
|
||||
{
|
||||
char tmp[128];
|
||||
const char *devname = "/dev/fuse";
|
||||
char *source = NULL;
|
||||
char *type = NULL;
|
||||
std::string source;
|
||||
std::string type;
|
||||
struct stat stbuf;
|
||||
int fd;
|
||||
int res;
|
||||
@@ -478,36 +479,23 @@ fuse_mount_sys(const char *mnt,
|
||||
if (res == -1)
|
||||
goto out_close;
|
||||
|
||||
source = static_cast<char*>(malloc((mo->fsname ? strlen(mo->fsname) : 0) +
|
||||
(mo->subtype ? strlen(mo->subtype) : 0) +
|
||||
strlen(devname) + 32));
|
||||
type = mo->blkdev ? "fuseblk" : "fuse";
|
||||
if (mo->subtype)
|
||||
type += "." + std::string(mo->subtype);
|
||||
|
||||
type = static_cast<char*>(malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32));
|
||||
if (!type || !source) {
|
||||
fprintf(stderr, "mergerfs: failed to allocate memory\n");
|
||||
goto out_close;
|
||||
}
|
||||
source = mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname);
|
||||
|
||||
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
|
||||
if (mo->subtype) {
|
||||
strcat(type, ".");
|
||||
strcat(type, mo->subtype);
|
||||
}
|
||||
strcpy(source,
|
||||
mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));
|
||||
|
||||
res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
|
||||
res = mount(source.c_str(), mnt, type.c_str(), mo->flags, mo->kernel_opts);
|
||||
if (res == -1 && errno == ENODEV && mo->subtype) {
|
||||
/* Probably missing subtype support */
|
||||
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
|
||||
type = mo->blkdev ? "fuseblk" : "fuse";
|
||||
if (mo->fsname) {
|
||||
if (!mo->blkdev)
|
||||
sprintf(source, "%s#%s", mo->subtype,
|
||||
mo->fsname);
|
||||
source = std::string(mo->subtype) + "#" + mo->fsname;
|
||||
} else {
|
||||
strcpy(source, type);
|
||||
source = type;
|
||||
}
|
||||
res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
|
||||
res = mount(source.c_str(), mnt, type.c_str(), mo->flags, mo->kernel_opts);
|
||||
}
|
||||
if (res == -1) {
|
||||
/*
|
||||
@@ -543,7 +531,7 @@ fuse_mount_sys(const char *mnt,
|
||||
if (!newmnt)
|
||||
goto out_umount;
|
||||
|
||||
res = fuse_mnt_add_mount("fuse", source, newmnt, type,
|
||||
res = fuse_mnt_add_mount("fuse", source.c_str(), newmnt, type.c_str(),
|
||||
mnt_opts);
|
||||
free(newmnt);
|
||||
if (res == -1)
|
||||
@@ -551,16 +539,12 @@ fuse_mount_sys(const char *mnt,
|
||||
}
|
||||
#endif /* IGNORE_MTAB */
|
||||
#endif /* __NetBSD__ */
|
||||
free(type);
|
||||
free(source);
|
||||
|
||||
return fd;
|
||||
|
||||
out_umount:
|
||||
umount2(mnt, 2); /* lazy umount */
|
||||
out_close:
|
||||
free(type);
|
||||
free(source);
|
||||
close(fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
@@ -249,11 +250,6 @@ int fuse_mnt_remove_mount(const char *progname, const char *mnt)
|
||||
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
char *copy;
|
||||
char *dst;
|
||||
char *end;
|
||||
char *lastcomp;
|
||||
const char *toresolv;
|
||||
|
||||
if (!orig[0]) {
|
||||
fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
|
||||
@@ -261,57 +257,46 @@ char *fuse_mnt_resolve_path(const char *progname, const char *orig)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy = strdup(orig);
|
||||
if (copy == NULL) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
std::string copy = orig;
|
||||
std::string lastcomp;
|
||||
std::string toresolv;
|
||||
|
||||
while (!copy.empty() && copy.back() == '/')
|
||||
copy.pop_back();
|
||||
|
||||
if (!copy.empty() && copy.find('/') != std::string::npos) {
|
||||
size_t last_slash = copy.find_last_of('/');
|
||||
lastcomp = copy.substr(last_slash + 1);
|
||||
toresolv = copy.substr(0, last_slash);
|
||||
if(toresolv.empty())
|
||||
toresolv = "/";
|
||||
|
||||
if (lastcomp == "." || lastcomp == "..") {
|
||||
lastcomp.clear();
|
||||
toresolv = copy;
|
||||
}
|
||||
} else if (!copy.empty()) {
|
||||
lastcomp = copy;
|
||||
toresolv = ".";
|
||||
} else {
|
||||
toresolv = "/";
|
||||
}
|
||||
|
||||
if (realpath(toresolv.c_str(), buf) == NULL) {
|
||||
fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
toresolv = copy;
|
||||
lastcomp = NULL;
|
||||
for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
|
||||
if (end[0] != '/') {
|
||||
char *tmp;
|
||||
end[1] = '\0';
|
||||
tmp = strrchr(copy, '/');
|
||||
if (tmp == NULL) {
|
||||
lastcomp = copy;
|
||||
toresolv = ".";
|
||||
} else {
|
||||
lastcomp = tmp + 1;
|
||||
if (tmp == copy)
|
||||
toresolv = "/";
|
||||
}
|
||||
if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
|
||||
lastcomp = NULL;
|
||||
toresolv = copy;
|
||||
}
|
||||
else if (tmp)
|
||||
tmp[0] = '\0';
|
||||
}
|
||||
if (realpath(toresolv, buf) == NULL) {
|
||||
fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
|
||||
strerror(errno));
|
||||
free(copy);
|
||||
return NULL;
|
||||
}
|
||||
if (lastcomp == NULL)
|
||||
dst = strdup(buf);
|
||||
else {
|
||||
unsigned buflen = strlen(buf);
|
||||
size_t dstlen = buflen + 1 + strlen(lastcomp) + 1;
|
||||
dst = static_cast<char*>(malloc(dstlen));
|
||||
if (dst) {
|
||||
if (buflen && buf[buflen-1] == '/')
|
||||
snprintf(dst, dstlen, "%s%s", buf, lastcomp);
|
||||
else
|
||||
snprintf(dst, dstlen, "%s/%s", buf, lastcomp);
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
if (dst == NULL)
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
return dst;
|
||||
std::string dst;
|
||||
if (lastcomp.empty())
|
||||
dst = buf;
|
||||
else if (buf[strlen(buf) - 1] == '/')
|
||||
dst = std::string(buf) + lastcomp;
|
||||
else
|
||||
dst = std::string(buf) + "/" + lastcomp;
|
||||
|
||||
return strdup(dst.c_str());
|
||||
}
|
||||
|
||||
int fuse_mnt_check_fuseblk(void)
|
||||
|
||||
@@ -11,111 +11,73 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string>
|
||||
|
||||
static char *progname;
|
||||
static const char *progname;
|
||||
|
||||
static char *xstrdup(const char *s)
|
||||
static std::string shell_quote(const std::string &s)
|
||||
{
|
||||
char *t = strdup(s);
|
||||
if (!t) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
exit(1);
|
||||
std::string r = "'";
|
||||
|
||||
for (char c : s) {
|
||||
if (c == '\'')
|
||||
r += "'\\''";
|
||||
else
|
||||
r += c;
|
||||
}
|
||||
return t;
|
||||
r += "'";
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void *xrealloc(void *oldptr, size_t size)
|
||||
static std::string add_option(const std::string &opt,
|
||||
const std::string &options)
|
||||
{
|
||||
void *ptr = realloc(oldptr, size);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
if (options.empty())
|
||||
return opt;
|
||||
|
||||
static void add_arg(char **cmdp, const char *opt)
|
||||
{
|
||||
size_t optlen = strlen(opt);
|
||||
size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
|
||||
char *cmd = static_cast<char*>(xrealloc(*cmdp, cmdlen + optlen * 4 + 4));
|
||||
char *s;
|
||||
s = cmd + cmdlen;
|
||||
if (*cmdp)
|
||||
*s++ = ' ';
|
||||
|
||||
*s++ = '\'';
|
||||
for (; *opt; opt++) {
|
||||
if (*opt == '\'') {
|
||||
*s++ = '\'';
|
||||
*s++ = '\\';
|
||||
*s++ = '\'';
|
||||
*s++ = '\'';
|
||||
} else
|
||||
*s++ = *opt;
|
||||
}
|
||||
*s++ = '\'';
|
||||
*s = '\0';
|
||||
*cmdp = cmd;
|
||||
}
|
||||
|
||||
static char *add_option(const char *opt, char *options)
|
||||
{
|
||||
int oldlen = options ? strlen(options) : 0;
|
||||
|
||||
options = static_cast<char*>(xrealloc(options, oldlen + 1 + strlen(opt) + 1));
|
||||
if (!oldlen)
|
||||
strcpy(options, opt);
|
||||
else {
|
||||
strcat(options, ",");
|
||||
strcat(options, opt);
|
||||
}
|
||||
return options;
|
||||
return options + "," + opt;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *type = NULL;
|
||||
char *source;
|
||||
const char *mountpoint;
|
||||
char *basename;
|
||||
char *options = NULL;
|
||||
char *command = NULL;
|
||||
char *setuid = NULL;
|
||||
int i;
|
||||
std::string type;
|
||||
std::string source;
|
||||
std::string mountpoint;
|
||||
std::string basename;
|
||||
std::string options;
|
||||
std::string command;
|
||||
std::string setuid;
|
||||
int dev = 1;
|
||||
int suid = 1;
|
||||
|
||||
progname = argv[0];
|
||||
basename = strrchr(argv[0], '/');
|
||||
if (basename)
|
||||
basename++;
|
||||
else
|
||||
basename = argv[0];
|
||||
{
|
||||
const char *slash = strrchr(argv[0], '/');
|
||||
basename = slash ? (slash + 1) : argv[0];
|
||||
}
|
||||
|
||||
type = const_cast<char*>("mergerfs");
|
||||
if (strncmp(basename, "mount.fuse.", 11) == 0)
|
||||
type = basename + 11;
|
||||
if (strncmp(basename, "mount.fuseblk.", 14) == 0)
|
||||
type = basename + 14;
|
||||
type = "mergerfs";
|
||||
if (strncmp(basename.c_str(), "mount.fuse.", 11) == 0)
|
||||
type = basename.substr(11);
|
||||
if (strncmp(basename.c_str(), "mount.fuseblk.", 14) == 0)
|
||||
type = basename.substr(14);
|
||||
|
||||
if (type && !type[0])
|
||||
type = NULL;
|
||||
if (type.empty())
|
||||
type = "";
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr,
|
||||
"usage: %s %s destination [-t type] [-o opt[,opts...]]\n",
|
||||
progname, type ? "source" : "type#[source]");
|
||||
progname, type.empty() ? "type#[source]" : "source");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
source = argv[1];
|
||||
if (!source[0])
|
||||
source = NULL;
|
||||
|
||||
mountpoint = argv[2];
|
||||
|
||||
for (i = 3; i < argc; i++) {
|
||||
for (int i = 3; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-v") == 0) {
|
||||
continue;
|
||||
} else if (strcmp(argv[i], "-t") == 0) {
|
||||
@@ -128,25 +90,25 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
type = argv[i];
|
||||
if (strncmp(type, "fuse.", 5) == 0)
|
||||
type += 5;
|
||||
else if (strncmp(type, "fuseblk.", 8) == 0)
|
||||
type += 8;
|
||||
if (strncmp(type.c_str(), "fuse.", 5) == 0)
|
||||
type = type.substr(5);
|
||||
else if (strncmp(type.c_str(), "fuseblk.", 8) == 0)
|
||||
type = type.substr(8);
|
||||
|
||||
if (!type[0]) {
|
||||
if (type.empty()) {
|
||||
fprintf(stderr,
|
||||
"%s: empty type given as argument to option '-t'\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
} else if (strcmp(argv[i], "-o") == 0) {
|
||||
} else if (strcmp(argv[i], "-o") == 0) {
|
||||
char *opts;
|
||||
char *opt;
|
||||
i++;
|
||||
if (i == argc)
|
||||
break;
|
||||
|
||||
opts = xstrdup(argv[i]);
|
||||
opts = strdup(argv[i]);
|
||||
opt = strtok(opts, ",");
|
||||
while (opt)
|
||||
{
|
||||
@@ -165,7 +127,7 @@ int main(int argc, char *argv[])
|
||||
NULL
|
||||
};
|
||||
if (strncmp(opt, "setuid=", 7) == 0) {
|
||||
setuid = xstrdup(opt + 7);
|
||||
setuid = opt + 7;
|
||||
ignore = 1;
|
||||
}
|
||||
for (j = 0; ignore_opts[j]; j++)
|
||||
@@ -182,6 +144,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
opt = strtok(NULL, ",");
|
||||
}
|
||||
free(opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,13 +153,17 @@ int main(int argc, char *argv[])
|
||||
if (suid)
|
||||
options = add_option("suid", options);
|
||||
|
||||
if (!type) {
|
||||
if (source) {
|
||||
type = xstrdup(source);
|
||||
source = strchr(type, '#');
|
||||
if (source)
|
||||
*source++ = '\0';
|
||||
if (!type[0]) {
|
||||
if (type.empty()) {
|
||||
if (!source.empty()) {
|
||||
size_t hash_pos = source.find('#');
|
||||
if (hash_pos != std::string::npos) {
|
||||
type = source.substr(0, hash_pos);
|
||||
source = source.substr(hash_pos + 1);
|
||||
} else {
|
||||
type = source;
|
||||
source.clear();
|
||||
}
|
||||
if (type.empty()) {
|
||||
fprintf(stderr, "%s: empty filesystem type\n",
|
||||
progname);
|
||||
exit(1);
|
||||
@@ -207,29 +174,27 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
add_arg(&command, type);
|
||||
if (source)
|
||||
add_arg(&command, source);
|
||||
add_arg(&command, mountpoint);
|
||||
if (options) {
|
||||
add_arg(&command, "-o");
|
||||
add_arg(&command, options);
|
||||
command += shell_quote(type);
|
||||
if (!source.empty())
|
||||
command += " " + shell_quote(source);
|
||||
command += " " + shell_quote(mountpoint);
|
||||
if (!options.empty()) {
|
||||
command += " " + shell_quote("-o");
|
||||
command += " " + shell_quote(options);
|
||||
}
|
||||
|
||||
if (setuid && setuid[0]) {
|
||||
char *sucommand = command;
|
||||
command = NULL;
|
||||
add_arg(&command, "su");
|
||||
add_arg(&command, "-");
|
||||
add_arg(&command, setuid);
|
||||
add_arg(&command, "-c");
|
||||
add_arg(&command, sucommand);
|
||||
if (!setuid.empty()) {
|
||||
std::string sucommand = command;
|
||||
command = "su";
|
||||
command += " -";
|
||||
command += " " + shell_quote(setuid);
|
||||
command += " -c";
|
||||
command += " " + shell_quote(sucommand);
|
||||
} else if (!getenv("HOME")) {
|
||||
/* Hack to make filesystems work in the boot environment */
|
||||
setenv("HOME", "/root", 0);
|
||||
}
|
||||
|
||||
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
|
||||
execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL);
|
||||
fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
|
||||
strerror(errno));
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user