mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-19 16:16:48 +00:00
Convert vendored/libfuse C sources to C++17
Convert all C source files in vendored/libfuse/ to C++17: - lib/crc32b.c -> crc32b.cpp (const void* cast) - lib/fuse_opt.c -> fuse_opt.cpp (designated init, void* arithmetic) - lib/fuse_signals.c -> fuse_signals.cpp - lib/helper.c -> helper.cpp (void* data cast) - lib/mount.c -> mount.cpp (thin wrapper) - lib/mount_generic.c -> mount_generic.h (static inline, #pragma once) - lib/mount_bsd.c -> mount_bsd.h (static inline, #pragma once) - lib/mount_util.c -> mount_util.h (static inline, #pragma once) - util/fusermount.c -> fusermount.cpp - util/mount.mergerfs.c -> mount.mergerfs.cpp Key changes: - Replace C99 designated initializer in fuse_opt_parse with field-by-field init - Fix void* pointer arithmetic via char* base + offset pattern - All C-style (T*)voidptr casts replaced with static_cast/reinterpret_cast - Remove redundant #define _GNU_SOURCE (already in FUSE_FLAGS) - Wrap __clone2 declaration in extern "C" for ia64 path - Update Makefile: empty SRC_C, build utils with $(CXX) instead of $(CC) - Remove stale .c files now replaced by .cpp/.h counterparts All binaries build cleanly: mergerfs, mergerfs-fusermount, mount.mergerfs
This commit is contained in:
committed by
trapexit
parent
96eb51eecb
commit
21966ade97
@@ -76,12 +76,7 @@ INSTALLMAN1DIR ?= $(DESTDIR)$(MAN1DIR)
|
||||
|
||||
BUILDDIR := build
|
||||
|
||||
SRC_C = \
|
||||
lib/crc32b.c \
|
||||
lib/fuse_opt.c \
|
||||
lib/fuse_signals.c \
|
||||
lib/helper.c \
|
||||
lib/mount.c
|
||||
SRC_C =
|
||||
SRC_CXX = $(wildcard lib/*.cpp)
|
||||
|
||||
OBJS := $(SRC_C:lib/%.c=$(BUILDDIR)/.objs/%.c.o)
|
||||
@@ -144,14 +139,14 @@ $(BUILDDIR)/libfuse.a: $(OBJS)
|
||||
.PHONY: utils
|
||||
utils: mergerfs-fusermount mount.mergerfs
|
||||
|
||||
$(BUILDDIR)/mergerfs-fusermount: util/fusermount.c lib/mount_util.c
|
||||
$(CC) $(CFLAGS) $(FUSE_FLAGS) -Ilib -o $(BUILDDIR)/mergerfs-fusermount util/fusermount.c lib/mount_util.c
|
||||
$(BUILDDIR)/mergerfs-fusermount: util/fusermount.cpp
|
||||
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) -Ilib -o $(BUILDDIR)/mergerfs-fusermount util/fusermount.cpp
|
||||
|
||||
mergerfs-fusermount: $(BUILDDIR)/mergerfs-fusermount
|
||||
|
||||
$(BUILDDIR)/mount.mergerfs: $(BUILDDIR)/libfuse.a util/mount.mergerfs.c
|
||||
$(BUILDDIR)/mount.mergerfs: $(BUILDDIR)/libfuse.a util/mount.mergerfs.cpp
|
||||
echo STATIC=$(STATIC) $(STATIC_FLAGS)
|
||||
$(CC) $(CFLAGS) $(FUSE_FLAGS) -o $(BUILDDIR)/mount.mergerfs util/mount.mergerfs.c $(BUILDDIR)/libfuse.a $(LDFLAGS)
|
||||
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) -o $(BUILDDIR)/mount.mergerfs util/mount.mergerfs.cpp $(BUILDDIR)/libfuse.a $(LDFLAGS)
|
||||
|
||||
mount.mergerfs: $(BUILDDIR)/mount.mergerfs
|
||||
|
||||
|
||||
@@ -78,12 +78,12 @@ crc32b_continue(const void *buf_,
|
||||
const crc32b_t len_,
|
||||
const crc32b_t crc_)
|
||||
{
|
||||
char *buf;
|
||||
const char *buf;
|
||||
crc32b_t i;
|
||||
crc32b_t crc;
|
||||
|
||||
crc = crc_;
|
||||
buf = (char*)buf_;
|
||||
buf = static_cast<const char*>(buf_);
|
||||
for(i = 0; i < len_; i++)
|
||||
{
|
||||
crc = (CRC32BTABLE[(crc ^ buf[i]) & 0xFFL] ^ (crc >> 8));
|
||||
@@ -64,7 +64,7 @@ fuse_opt_add_arg(struct fuse_args *args, const char *arg)
|
||||
if (!newarg)
|
||||
return alloc_failed();
|
||||
|
||||
newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
|
||||
newargv = static_cast<char**>(realloc(args->argv, (args->argc + 2) * sizeof(char *)));
|
||||
if (!newargv)
|
||||
{
|
||||
free(newarg);
|
||||
@@ -120,7 +120,7 @@ static int add_arg(struct fuse_opt_context *ctx, const char *arg)
|
||||
static int add_opt_common(char **opts, const char *opt, int esc)
|
||||
{
|
||||
unsigned oldlen = *opts ? strlen(*opts) : 0;
|
||||
char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1);
|
||||
char *d = static_cast<char*>(realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1));
|
||||
|
||||
if (!d)
|
||||
return alloc_failed();
|
||||
@@ -224,9 +224,9 @@ static int process_opt_param(void *var, const char *format, const char *param,
|
||||
if (!copy)
|
||||
return alloc_failed();
|
||||
|
||||
*(char **) var = copy;
|
||||
*static_cast<char**>(var) = copy;
|
||||
} else {
|
||||
if (sscanf(param, format, var) != 1) {
|
||||
if (sscanf(param, format, static_cast<int*>(var)) != 1) {
|
||||
fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg);
|
||||
return -1;
|
||||
}
|
||||
@@ -243,7 +243,7 @@ static int process_opt(struct fuse_opt_context *ctx,
|
||||
if (call_proc(ctx, arg, opt->value, iso) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
void *var = ctx->data + opt->offset;
|
||||
char *var = static_cast<char*>(ctx->data) + opt->offset;
|
||||
if (sep && opt->templ[sep + 1])
|
||||
{
|
||||
const char *param = arg + sep;
|
||||
@@ -253,7 +253,7 @@ static int process_opt(struct fuse_opt_context *ctx,
|
||||
param, arg) == -1)
|
||||
return -1;
|
||||
} else
|
||||
*(int *)var = opt->value;
|
||||
*static_cast<int*>(static_cast<void*>(var)) = opt->value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -270,7 +270,7 @@ static int process_opt_sep_arg(struct fuse_opt_context *ctx,
|
||||
return -1;
|
||||
|
||||
param = ctx->argv[ctx->argctr];
|
||||
newarg = malloc(sep + strlen(param) + 1);
|
||||
newarg = static_cast<char*>(malloc(sep + strlen(param) + 1));
|
||||
if (!newarg)
|
||||
return alloc_failed();
|
||||
|
||||
@@ -423,11 +423,16 @@ int fuse_opt_parse(struct fuse_args *args, void *data,
|
||||
const struct fuse_opt opts[], fuse_opt_proc_t proc)
|
||||
{
|
||||
int res;
|
||||
struct fuse_opt_context ctx = {
|
||||
.data = data,
|
||||
.opt = opts,
|
||||
.proc = proc,
|
||||
};
|
||||
struct fuse_opt_context ctx;
|
||||
ctx.data = data;
|
||||
ctx.opt = opts;
|
||||
ctx.proc = proc;
|
||||
ctx.argctr = 0;
|
||||
ctx.argc = 0;
|
||||
ctx.argv = nullptr;
|
||||
ctx.outargs = {};
|
||||
ctx.opts = nullptr;
|
||||
ctx.nonopt = 0;
|
||||
|
||||
if (!args || !args->argv || !args->argc)
|
||||
return 0;
|
||||
@@ -56,7 +56,7 @@ fuse_helper_opt_proc(void *data,
|
||||
int key,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
struct helper_opts *hopts = data;
|
||||
struct helper_opts *hopts = static_cast<struct helper_opts*>(data);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2019, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mount.hpp"
|
||||
@@ -16,9 +16,11 @@
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__
|
||||
# include "mount_bsd.c"
|
||||
# include "mount_bsd.h"
|
||||
#else
|
||||
# include "mount_generic.c"
|
||||
# include "mount_util.c"
|
||||
# include "mount_generic.h"
|
||||
# include "mount_util.h"
|
||||
#endif
|
||||
@@ -6,6 +6,8 @@
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fuse_opt.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
@@ -106,7 +108,7 @@ static void mount_version(void)
|
||||
static int fuse_mount_opt_proc(void *data, const char *arg, int key,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
struct mount_opts *mo = data;
|
||||
struct mount_opts *mo = static_cast<struct mount_opts*>(data);
|
||||
|
||||
switch (key) {
|
||||
case KEY_RO:
|
||||
@@ -6,6 +6,8 @@
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fuse_opt.h"
|
||||
#include "mount_util.h"
|
||||
|
||||
@@ -189,7 +191,7 @@ set_mount_flag(const char *s,
|
||||
static int fuse_mount_opt_proc(void *data, const char *arg, int key,
|
||||
struct fuse_args *outargs)
|
||||
{
|
||||
struct mount_opts *mo = data;
|
||||
struct mount_opts *mo = static_cast<struct mount_opts*>(data);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
@@ -273,7 +275,7 @@ static int receive_fd(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return *(int*)CMSG_DATA(cmsg);
|
||||
return *reinterpret_cast<int*>(CMSG_DATA(cmsg));
|
||||
}
|
||||
|
||||
void fuse_kern_unmount(const char *mountpoint, int fd)
|
||||
@@ -476,11 +478,11 @@ fuse_mount_sys(const char *mnt,
|
||||
if (res == -1)
|
||||
goto out_close;
|
||||
|
||||
source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
|
||||
source = static_cast<char*>(malloc((mo->fsname ? strlen(mo->fsname) : 0) +
|
||||
(mo->subtype ? strlen(mo->subtype) : 0) +
|
||||
strlen(devname) + 32);
|
||||
strlen(devname) + 32));
|
||||
|
||||
type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
|
||||
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;
|
||||
@@ -1,331 +0,0 @@
|
||||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#include "mount_util.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#ifndef __NetBSD__
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
|
||||
#define mtab_needs_update(mnt) 0
|
||||
#else
|
||||
static int mtab_needs_update(const char *mnt)
|
||||
{
|
||||
int res;
|
||||
struct stat stbuf;
|
||||
|
||||
/* If mtab is within new mount, don't touch it */
|
||||
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
|
||||
_PATH_MOUNTED[strlen(mnt)] == '/')
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Skip mtab update if /etc/mtab:
|
||||
*
|
||||
* - doesn't exist,
|
||||
* - is a symlink,
|
||||
* - is on a read-only filesystem.
|
||||
*/
|
||||
res = lstat(_PATH_MOUNTED, &stbuf);
|
||||
if (res == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
} else {
|
||||
uid_t ruid;
|
||||
int err;
|
||||
|
||||
if (S_ISLNK(stbuf.st_mode))
|
||||
return 0;
|
||||
|
||||
ruid = getuid();
|
||||
if (ruid != 0)
|
||||
setreuid(0, -1);
|
||||
|
||||
res = access(_PATH_MOUNTED, W_OK);
|
||||
err = (res == -1) ? errno : 0;
|
||||
if (ruid != 0)
|
||||
setreuid(ruid, -1);
|
||||
|
||||
if (err == EROFS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
static int add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
|
||||
"-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return add_mount(progname, fsname, mnt, type, opts);
|
||||
}
|
||||
|
||||
static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
if (lazy) {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
"-l", NULL, &env);
|
||||
} else {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
NULL, &env);
|
||||
}
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0) {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int fuse_mnt_umount(const char *progname, const char *abs_mnt,
|
||||
const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!mtab_needs_update(abs_mnt)) {
|
||||
res = umount2(rel_mnt, lazy ? MNT_DETACH : 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: failed to unmount %s: %s\n",
|
||||
progname, abs_mnt, strerror(errno));
|
||||
return res;
|
||||
}
|
||||
|
||||
return exec_umount(progname, rel_mnt, lazy);
|
||||
}
|
||||
|
||||
static int remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
|
||||
"--fake", mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return remove_mount(progname, 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,
|
||||
orig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy = strdup(orig);
|
||||
if (copy == NULL) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
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 = (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;
|
||||
}
|
||||
|
||||
int fuse_mnt_check_fuseblk(void)
|
||||
{
|
||||
char buf[256];
|
||||
FILE *f = fopen("/proc/filesystems", "r");
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
if (strstr(buf, "fuseblk\n")) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
@@ -8,12 +8,325 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#ifndef __NetBSD__
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
|
||||
#define mtab_needs_update(mnt) 0
|
||||
#else
|
||||
static int mtab_needs_update(const char *mnt)
|
||||
{
|
||||
int res;
|
||||
struct stat stbuf;
|
||||
|
||||
/* If mtab is within new mount, don't touch it */
|
||||
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
|
||||
_PATH_MOUNTED[strlen(mnt)] == '/')
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Skip mtab update if /etc/mtab:
|
||||
*
|
||||
* - doesn't exist,
|
||||
* - is a symlink,
|
||||
* - is on a read-only filesystem.
|
||||
*/
|
||||
res = lstat(_PATH_MOUNTED, &stbuf);
|
||||
if (res == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
} else {
|
||||
uid_t ruid;
|
||||
int err;
|
||||
|
||||
if (S_ISLNK(stbuf.st_mode))
|
||||
return 0;
|
||||
|
||||
ruid = getuid();
|
||||
if (ruid != 0)
|
||||
setreuid(0, -1);
|
||||
|
||||
res = access(_PATH_MOUNTED, W_OK);
|
||||
err = (res == -1) ? errno : 0;
|
||||
if (ruid != 0)
|
||||
setreuid(ruid, -1);
|
||||
|
||||
if (err == EROFS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
static int add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
|
||||
"-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts);
|
||||
int fuse_mnt_remove_mount(const char *progname, const char *mnt);
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return add_mount(progname, fsname, mnt, type, opts);
|
||||
}
|
||||
|
||||
static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
if (lazy) {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
"-l", NULL, &env);
|
||||
} else {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
NULL, &env);
|
||||
}
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0) {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int fuse_mnt_umount(const char *progname, const char *abs_mnt,
|
||||
const char *rel_mnt, int lazy);
|
||||
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
|
||||
int fuse_mnt_check_fuseblk(void);
|
||||
const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!mtab_needs_update(abs_mnt)) {
|
||||
res = umount2(rel_mnt, lazy ? MNT_DETACH : 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: failed to unmount %s: %s\n",
|
||||
progname, abs_mnt, strerror(errno));
|
||||
return res;
|
||||
}
|
||||
|
||||
return exec_umount(progname, rel_mnt, lazy);
|
||||
}
|
||||
|
||||
static int remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
|
||||
"--fake", mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return remove_mount(progname, 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,
|
||||
orig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy = strdup(orig);
|
||||
if (copy == NULL) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
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;
|
||||
}
|
||||
|
||||
int fuse_mnt_check_fuseblk(void)
|
||||
{
|
||||
char buf[256];
|
||||
FILE *f = fopen("/proc/filesystems", "r");
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
if (strstr(buf, "fuseblk\n")) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
*/
|
||||
/* This program does the mounting and unmounting of FUSE filesystems */
|
||||
|
||||
#define _GNU_SOURCE /* for clone */
|
||||
|
||||
#include "mount_util.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -234,7 +232,7 @@ static int may_unmount(const char *mnt, int quiet)
|
||||
*/
|
||||
static int check_is_mount_child(void *p)
|
||||
{
|
||||
const char **a = p;
|
||||
const char **a = static_cast<const char**>(p);
|
||||
const char *last = a[0];
|
||||
const char *mnt = a[1];
|
||||
int res;
|
||||
@@ -305,10 +303,12 @@ static pid_t clone_newns(void *a)
|
||||
char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15));
|
||||
|
||||
#ifdef __ia64__
|
||||
extern "C" {
|
||||
extern int __clone2(int (*fn)(void *),
|
||||
void *child_stack_base, size_t stack_size,
|
||||
int flags, void *arg, pid_t *ptid,
|
||||
void *tls, pid_t *ctid);
|
||||
}
|
||||
|
||||
return __clone2(check_is_mount_child, stack, sizeof(buf) / 2,
|
||||
CLONE_NEWNS, a, NULL, NULL, NULL);
|
||||
@@ -649,7 +649,7 @@ static int add_option(char **optsp, const char *opt, unsigned expand)
|
||||
else {
|
||||
unsigned oldsize = strlen(*optsp);
|
||||
unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
|
||||
newopts = (char *) realloc(*optsp, newsize);
|
||||
newopts = static_cast<char*>(realloc(*optsp, newsize));
|
||||
if (newopts)
|
||||
sprintf(newopts + oldsize, ",%s", opt);
|
||||
}
|
||||
@@ -713,7 +713,7 @@ get_string_opt(const char *s,
|
||||
|
||||
if (*val)
|
||||
free(*val);
|
||||
*val = (char *) malloc(len - opt_len + 1);
|
||||
*val = static_cast<char*>(malloc(len - opt_len + 1));
|
||||
if (!*val) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
return 0;
|
||||
@@ -747,7 +747,7 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
|
||||
char *type = NULL;
|
||||
int blkdev = 0;
|
||||
|
||||
optbuf = (char *) malloc(strlen(opts) + 128);
|
||||
optbuf = static_cast<char*>(malloc(strlen(opts) + 128));
|
||||
if (!optbuf) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
return -1;
|
||||
@@ -827,10 +827,10 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
|
||||
sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
|
||||
fd, rootmode, getuid(), getgid());
|
||||
|
||||
source = malloc((fsname ? strlen(fsname) : 0) +
|
||||
(subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
|
||||
source = static_cast<char*>(malloc((fsname ? strlen(fsname) : 0) +
|
||||
(subtype ? strlen(subtype) : 0) + strlen(dev) + 32));
|
||||
|
||||
type = malloc((subtype ? strlen(subtype) : 0) + 32);
|
||||
type = static_cast<char*>(malloc((subtype ? strlen(subtype) : 0) + 32));
|
||||
if (!type || !source) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
goto err;
|
||||
@@ -1147,7 +1147,7 @@ static int send_fd(int sock_fd, int fd)
|
||||
p_cmsg->cmsg_level = SOL_SOCKET;
|
||||
p_cmsg->cmsg_type = SCM_RIGHTS;
|
||||
p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
|
||||
p_fds = (int *) CMSG_DATA(p_cmsg);
|
||||
p_fds = reinterpret_cast<int*>(CMSG_DATA(p_cmsg));
|
||||
*p_fds = fd;
|
||||
msg.msg_controllen = p_cmsg->cmsg_len;
|
||||
msg.msg_name = NULL;
|
||||
@@ -38,7 +38,7 @@ static void add_arg(char **cmdp, const char *opt)
|
||||
{
|
||||
size_t optlen = strlen(opt);
|
||||
size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
|
||||
char *cmd = xrealloc(*cmdp, cmdlen + optlen * 4 + 4);
|
||||
char *cmd = static_cast<char*>(xrealloc(*cmdp, cmdlen + optlen * 4 + 4));
|
||||
char *s;
|
||||
s = cmd + cmdlen;
|
||||
if (*cmdp)
|
||||
@@ -63,7 +63,7 @@ static char *add_option(const char *opt, char *options)
|
||||
{
|
||||
int oldlen = options ? strlen(options) : 0;
|
||||
|
||||
options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
|
||||
options = static_cast<char*>(xrealloc(options, oldlen + 1 + strlen(opt) + 1));
|
||||
if (!oldlen)
|
||||
strcpy(options, opt);
|
||||
else {
|
||||
@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
basename = argv[0];
|
||||
|
||||
type = "mergerfs";
|
||||
type = const_cast<char*>("mergerfs");
|
||||
if (strncmp(basename, "mount.fuse.", 11) == 0)
|
||||
type = basename + 11;
|
||||
if (strncmp(basename, "mount.fuseblk.", 14) == 0)
|
||||
@@ -1,330 +0,0 @@
|
||||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB.
|
||||
*/
|
||||
|
||||
#include "mount_util.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#ifndef __NetBSD__
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
|
||||
#define mtab_needs_update(mnt) 0
|
||||
#else
|
||||
static int mtab_needs_update(const char *mnt)
|
||||
{
|
||||
int res;
|
||||
struct stat stbuf;
|
||||
|
||||
/* If mtab is within new mount, don't touch it */
|
||||
if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
|
||||
_PATH_MOUNTED[strlen(mnt)] == '/')
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Skip mtab update if /etc/mtab:
|
||||
*
|
||||
* - doesn't exist,
|
||||
* - is a symlink,
|
||||
* - is on a read-only filesystem.
|
||||
*/
|
||||
res = lstat(_PATH_MOUNTED, &stbuf);
|
||||
if (res == -1) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
} else {
|
||||
uid_t ruid;
|
||||
int err;
|
||||
|
||||
if (S_ISLNK(stbuf.st_mode))
|
||||
return 0;
|
||||
|
||||
ruid = getuid();
|
||||
if (ruid != 0)
|
||||
setreuid(0, -1);
|
||||
|
||||
res = access(_PATH_MOUNTED, W_OK);
|
||||
err = (res == -1) ? errno : 0;
|
||||
if (ruid != 0)
|
||||
setreuid(ruid, -1);
|
||||
|
||||
if (err == EROFS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
static int add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
|
||||
"-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_add_mount(const char *progname, const char *fsname,
|
||||
const char *mnt, const char *type, const char *opts)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return add_mount(progname, fsname, mnt, type, opts);
|
||||
}
|
||||
|
||||
static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
if (lazy) {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
"-l", NULL, &env);
|
||||
} else {
|
||||
execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
|
||||
NULL, &env);
|
||||
}
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0) {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
int fuse_mnt_umount(const char *progname, const char *abs_mnt,
|
||||
const char *rel_mnt, int lazy)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!mtab_needs_update(abs_mnt)) {
|
||||
res = umount2(rel_mnt, lazy ? 2 : 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: failed to unmount %s: %s\n",
|
||||
progname, abs_mnt, strerror(errno));
|
||||
return res;
|
||||
}
|
||||
|
||||
return exec_umount(progname, rel_mnt, lazy);
|
||||
}
|
||||
|
||||
static int remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
int res;
|
||||
int status;
|
||||
sigset_t blockmask;
|
||||
sigset_t oldmask;
|
||||
|
||||
sigemptyset(&blockmask);
|
||||
sigaddset(&blockmask, SIGCHLD);
|
||||
res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fork();
|
||||
if (res == -1) {
|
||||
fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
|
||||
goto out_restore;
|
||||
}
|
||||
if (res == 0) {
|
||||
char *env = NULL;
|
||||
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
setuid(geteuid());
|
||||
execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
|
||||
"--fake", mnt, NULL, &env);
|
||||
fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
|
||||
progname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
res = waitpid(res, &status, 0);
|
||||
if (res == -1)
|
||||
fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
|
||||
|
||||
if (status != 0)
|
||||
res = -1;
|
||||
|
||||
out_restore:
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_mnt_remove_mount(const char *progname, const char *mnt)
|
||||
{
|
||||
if (!mtab_needs_update(mnt))
|
||||
return 0;
|
||||
|
||||
return remove_mount(progname, 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,
|
||||
orig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
copy = strdup(orig);
|
||||
if (copy == NULL) {
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
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 {
|
||||
dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
|
||||
if (dst) {
|
||||
unsigned buflen = strlen(buf);
|
||||
if (buflen && buf[buflen-1] == '/')
|
||||
sprintf(dst, "%s%s", buf, lastcomp);
|
||||
else
|
||||
sprintf(dst, "%s/%s", buf, lastcomp);
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
if (dst == NULL)
|
||||
fprintf(stderr, "%s: failed to allocate memory\n", progname);
|
||||
return dst;
|
||||
}
|
||||
|
||||
int fuse_mnt_check_fuseblk(void)
|
||||
{
|
||||
char buf[256];
|
||||
FILE *f = fopen("/proc/filesystems", "r");
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
while (fgets(buf, sizeof(buf), f))
|
||||
if (strstr(buf, "fuseblk\n")) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user