diff options
Diffstat (limited to 'src/unionfs.c')
-rw-r--r-- | src/unionfs.c | 337 |
1 files changed, 186 insertions, 151 deletions
diff --git a/src/unionfs.c b/src/unionfs.c index 0d08721..26e3b98 100644 --- a/src/unionfs.c +++ b/src/unionfs.c @@ -16,6 +16,7 @@ #endif #include <fuse.h> +#include <fuse/fuse_common.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -27,13 +28,14 @@ #include <errno.h> #include <sys/types.h> #include <sys/time.h> +#include <inttypes.h> #ifdef linux #include <sys/vfs.h> #else #include <sys/statvfs.h> #endif -#ifdef HAVE_SETXATTR +#ifdef HAVE_XATTR #include <sys/xattr.h> #endif @@ -48,52 +50,59 @@ #include "rmdir.h" #include "readdir.h" #include "cow.h" +#include "string.h" +#include "usyslog.h" static struct fuse_opt unionfs_opts[] = { + FUSE_OPT_KEY("chroot=%s,", KEY_CHROOT), + FUSE_OPT_KEY("cow", KEY_COW), + FUSE_OPT_KEY("-d", KEY_DEBUG), + FUSE_OPT_KEY("debug_file=%s", KEY_DEBUG_FILE), + FUSE_OPT_KEY("dirs=%s", KEY_DIRS), FUSE_OPT_KEY("--help", KEY_HELP), - FUSE_OPT_KEY("--version", KEY_VERSION), FUSE_OPT_KEY("-h", KEY_HELP), - FUSE_OPT_KEY("-V", KEY_VERSION), - FUSE_OPT_KEY("dirs=%s", KEY_DIRS), - FUSE_OPT_KEY("stats", KEY_STATS), - FUSE_OPT_KEY("cow", KEY_COW), + FUSE_OPT_KEY("hide_meta_dir", KEY_HIDE_METADIR), + FUSE_OPT_KEY("hide_meta_files", KEY_HIDE_META_FILES), + FUSE_OPT_KEY("max_files=%s", KEY_MAX_FILES), FUSE_OPT_KEY("noinitgroups", KEY_NOINITGROUPS), + FUSE_OPT_KEY("relaxed_permissions", KEY_RELAXED_PERMISSIONS), FUSE_OPT_KEY("statfs_omit_ro", KEY_STATFS_OMIT_RO), - FUSE_OPT_KEY("chroot=%s,", KEY_CHROOT), - FUSE_OPT_KEY("max_files=%s", KEY_MAX_FILES), + FUSE_OPT_KEY("stats", KEY_STATS), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-V", KEY_VERSION), FUSE_OPT_END }; static int unionfs_chmod(const char *path, mode_t mode) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = chmod(p, mode); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } static int unionfs_chown(const char *path, uid_t uid, gid_t gid) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = lchown(p, uid, gid); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } /** @@ -101,20 +110,20 @@ static int unionfs_chown(const char *path, uid_t uid, gid_t gid) { * libfuse will call this to create regular files */ static int unionfs_create(const char *path, mode_t mode, struct fuse_file_info *fi) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cutlast(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); // NOTE: We should do: // Create the file with mode=0 first, otherwise we might create // a file as root + x-bit + suid bit set, which might be used for // security racing! int res = open(p, fi->flags, 0); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); set_owner(p); // no error check, since creating the file succeeded @@ -124,7 +133,8 @@ static int unionfs_create(const char *path, mode_t mode, struct fuse_file_info * fi->fh = res; remove_hidden(path, i); - return 0; + DBG("fd = %" PRIx64 "\n", fi->fh); + RETURN(0); } @@ -134,32 +144,32 @@ static int unionfs_create(const char *path, mode_t mode, struct fuse_file_info * * which flush the data/metadata on close() */ static int unionfs_flush(const char *path, struct fuse_file_info *fi) { - DBG_IN(); + DBG("fd = %"PRIx64"\n", fi->fh); - if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) return 0; + if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) RETURN(0); int fd = dup(fi->fh); if (fd == -1) { // What to do now? - if (fsync(fi->fh) == -1) return -EIO; + if (fsync(fi->fh) == -1) RETURN(-EIO); - return -errno; + RETURN(-errno); } int res = close(fd); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } /** * Just a stub. This method is optional and can safely be left unimplemented */ static int unionfs_fsync(const char *path, int isdatasync, struct fuse_file_info *fi) { - DBG_IN(); + DBG("fd = %"PRIx64"\n", fi->fh); - if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) return 0; + if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) RETURN(0); int res; if (isdatasync) { @@ -172,30 +182,30 @@ static int unionfs_fsync(const char *path, int isdatasync, struct fuse_file_info res = fsync(fi->fh); } - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } static int unionfs_getattr(const char *path, struct stat *stbuf) { - DBG_IN(); + DBG("%s\n", path); if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) { memset(stbuf, 0, sizeof(stbuf)); stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = STATS_SIZE; - return 0; + RETURN(0); } - + int i = find_rorw_branch(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = lstat(p, stbuf); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); /* This is a workaround for broken gnu find implementations. Actually, * n_links is not defined at all for directories by posix. However, it @@ -206,7 +216,7 @@ static int unionfs_getattr(const char *path, struct stat *stbuf) { */ if (S_ISDIR(stbuf->st_mode)) stbuf->st_nlink = 1; - return 0; + RETURN(0); } /** @@ -222,7 +232,7 @@ static void * unionfs_init(struct fuse_conn_info *conn) { if (uopt.chroot) { int res = chroot(uopt.chroot); if (res) { - usyslog("Chdir to %s failed: %s ! Aborting!\n", + USYSLOG(LOG_WARNING, "Chdir to %s failed: %s ! Aborting!\n", uopt.chroot, strerror(errno)); exit(1); } @@ -231,27 +241,28 @@ static void * unionfs_init(struct fuse_conn_info *conn) { } static int unionfs_link(const char *from, const char *to) { - DBG_IN(); + DBG("from %s to %s\n", from, to); // hardlinks do not work across different filesystems so we need a copy of from first int i = find_rw_branch_cow(from); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); - // FIXME, we actually MUST COW to i - int j = find_rw_branch_cutlast(to); - if (j == -1) return -errno; + int j = __find_rw_branch_cutlast(to, i); + if (j == -1) RETURN(-errno); + + DBG("from branch: %d to branch: %d\n", i, j); char f[PATHLEN_MAX], t[PATHLEN_MAX]; - snprintf(f, PATHLEN_MAX, "%s%s", uopt.branches[i].path, from); - snprintf(t, PATHLEN_MAX, "%s%s", uopt.branches[j].path, to); + if (BUILD_PATH(f, uopt.branches[i].path, from)) RETURN(-ENAMETOOLONG); + if (BUILD_PATH(t, uopt.branches[j].path, to)) RETURN(-ENAMETOOLONG); int res = link(f, t); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); // no need for set_owner(), since owner and permissions are copied over by link() remove_hidden(to, i); // remove hide file (if any) - return 0; + RETURN(0); } /** @@ -261,32 +272,32 @@ static int unionfs_link(const char *from, const char *to) { * make already hidden sub-branches visible again. */ static int unionfs_mkdir(const char *path, mode_t mode) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cutlast(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = mkdir(p, 0); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); set_owner(p); // no error check, since creating the file succeeded // NOW, that the file has the proper owner we may set the requested mode chmod(p, mode); - return 0; + RETURN(0); } static int unionfs_mknod(const char *path, mode_t mode, dev_t rdev) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cutlast(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int file_type = mode & S_IFMT; int file_perm = mode & (S_PROT_MASK); @@ -298,15 +309,15 @@ static int unionfs_mknod(const char *path, mode_t mode, dev_t rdev) { // since we now have the unionfs_create() method // So can we remove it? - usyslog (LOG_INFO, "deprecated mknod workaround, tell the unionfs-fuse authors if you see this!\n"); + USYSLOG (LOG_INFO, "deprecated mknod workaround, tell the unionfs-fuse authors if you see this!\n"); res = creat(p, 0); - if (res > 0 && close(res) == -1) usyslog(LOG_WARNING, "Warning, cannot close file\n"); + if (res > 0 && close(res) == -1) USYSLOG(LOG_WARNING, "Warning, cannot close file\n"); } else { res = mknod(p, file_type, rdev); } - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); set_owner(p); // no error check, since creating the file succeeded // NOW, that the file has the proper owner we may set the requested mode @@ -314,19 +325,19 @@ static int unionfs_mknod(const char *path, mode_t mode, dev_t rdev) { remove_hidden(path, i); - return 0; + RETURN(0); } static int unionfs_open(const char *path, struct fuse_file_info *fi) { - DBG_IN(); + DBG("%s\n", path); if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) { if ((fi->flags & 3) == O_RDONLY) { // This makes exec() fail //fi->direct_io = 1; - return 0; + RETURN(0); } - return -EACCES; + RETURN(-EACCES); } int i; @@ -336,13 +347,13 @@ static int unionfs_open(const char *path, struct fuse_file_info *fi) { i = find_rorw_branch(path); } - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int fd = open(p, fi->flags); - if (fd == -1) return -errno; + if (fd == -1) RETURN(-errno); if (fi->flags & (O_WRONLY | O_RDWR)) { // There might have been a hide file, but since we successfully @@ -354,11 +365,12 @@ static int unionfs_open(const char *path, struct fuse_file_info *fi) { //fi->direct_io = 1; fi->fh = (unsigned long)fd; - return 0; + DBG("fd = %"PRIx64"\n", fi->fh); + RETURN(0); } static int unionfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { - DBG_IN(); + DBG("fd = %"PRIx64"\n", fi->fh); if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) { char out[STATS_SIZE] = ""; @@ -377,40 +389,40 @@ static int unionfs_read(const char *path, char *buf, size_t size, off_t offset, int res = pread(fi->fh, buf, size, offset); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); if (uopt.stats_enabled) stats_add_read(&stats, size); - return res; + RETURN(res); } static int unionfs_readlink(const char *path, char *buf, size_t size) { - DBG_IN(); + DBG("%s\n", path); int i = find_rorw_branch(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = readlink(p, buf, size - 1); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); buf[res] = '\0'; - return 0; + RETURN(0); } static int unionfs_release(const char *path, struct fuse_file_info *fi) { - DBG_IN(); + DBG("fd = %"PRIx64"\n", fi->fh); - if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) return 0; + if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) RETURN(0); int res = close(fi->fh); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } /** @@ -419,34 +431,34 @@ static int unionfs_release(const char *path, struct fuse_file_info *fi) { * all files to the renamed directory on the read-write branch. */ static int unionfs_rename(const char *from, const char *to) { - DBG_IN(); + DBG("from %s to %s\n", from, to); bool is_dir = false; // is 'from' a file or directory int j = find_rw_branch_cutlast(to); - if (j == -1) return -errno; + if (j == -1) RETURN(-errno); int i = find_rorw_branch(from); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); if (!uopt.branches[i].rw) { i = find_rw_branch_cow(from); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); } if (i != j) { - usyslog(LOG_ERR, "%s: from and to are on different writable branches %d vs %d, which" + USYSLOG(LOG_ERR, "%s: from and to are on different writable branches %d vs %d, which" "is not supported yet.\n", __func__, i, j); - return -EXDEV; + RETURN(-EXDEV); } char f[PATHLEN_MAX], t[PATHLEN_MAX]; - snprintf(f, PATHLEN_MAX, "%s%s", uopt.branches[i].path, from); - snprintf(t, PATHLEN_MAX, "%s%s", uopt.branches[i].path, to); + if (BUILD_PATH(f, uopt.branches[i].path, from)) RETURN(-ENAMETOOLONG); + if (BUILD_PATH(t, uopt.branches[i].path, to)) RETURN(-ENAMETOOLONG); filetype_t ftype = path_is_dir(f); if (ftype == NOT_EXISTING) - return -ENOENT; + RETURN(-ENOENT); else if (ftype == IS_DIR) is_dir = true; @@ -458,7 +470,7 @@ static int unionfs_rename(const char *from, const char *to) { res = hide_dir(from, i); else res = hide_file(from, i); - if (res) return -errno; + if (res) RETURN(-errno); } res = rename(f, t); @@ -468,14 +480,14 @@ static int unionfs_rename(const char *from, const char *to) { // if from was on a read-only branch we copied it, but now rename failed so we need to delete it if (!uopt.branches[i].rw) { if (unlink(f)) - usyslog(LOG_ERR, "%s: cow of %s succeeded, but rename() failed and now " + USYSLOG(LOG_ERR, "%s: cow of %s succeeded, but rename() failed and now " "also unlink() failed\n", __func__, from); if (remove_hidden(from, i)) - usyslog(LOG_ERR, "%s: cow of %s succeeded, but rename() failed and now " + USYSLOG(LOG_ERR, "%s: cow of %s succeeded, but rename() failed and now " "also removing the whiteout failed\n", __func__, from); } - return -err; + RETURN(-err); } if (uopt.branches[i].rw) { @@ -489,7 +501,7 @@ static int unionfs_rename(const char *from, const char *to) { } remove_hidden(to, i); // remove hide file (if any) - return 0; + RETURN(0); } /** @@ -508,7 +520,7 @@ static int statvfs_local(const char *path, struct statvfs *stbuf) { */ struct statfs stfs; int res = statfs(path, &stfs); - if (res == -1) return res; + if (res == -1) RETURN(res); memset(stbuf, 0, sizeof(*stbuf)); stbuf->f_bsize = stfs.f_bsize; @@ -532,9 +544,9 @@ static int statvfs_local(const char *path, struct statvfs *stbuf) { stbuf->f_flag = 0; stbuf->f_namemax = stfs.f_namelen; - return 0; + RETURN(0); #else - return statvfs(path, stbuf); + RETURN(statvfs(path, stbuf)); #endif } @@ -549,7 +561,7 @@ static int statvfs_local(const char *path, struct statvfs *stbuf) { static int unionfs_statfs(const char *path, struct statvfs *stbuf) { (void)path; - DBG_IN(); + DBG("%s\n", path); int first = 1; @@ -610,139 +622,139 @@ static int unionfs_statfs(const char *path, struct statvfs *stbuf) { } } - return 0; + RETURN(0); } static int unionfs_symlink(const char *from, const char *to) { - DBG_IN(); + DBG("from %s to %s\n", from, to); int i = find_rw_branch_cutlast(to); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char t[PATHLEN_MAX]; - snprintf(t, PATHLEN_MAX, "%s%s", uopt.branches[i].path, to); + if (BUILD_PATH(t, uopt.branches[i].path, to)) RETURN(-ENAMETOOLONG); int res = symlink(from, t); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); set_owner(t); // no error check, since creating the file succeeded remove_hidden(to, i); // remove hide file (if any) - return 0; + RETURN(0); } static int unionfs_truncate(const char *path, off_t size) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = truncate(p, size); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } static int unionfs_utimens(const char *path, const struct timespec ts[2]) { - DBG_IN(); + DBG("%s\n", path); - if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) return 0; + if (uopt.stats_enabled && strcmp(path, STATS_FILENAME) == 0) RETURN(0); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = utimensat(0, p, ts, AT_SYMLINK_NOFOLLOW); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return 0; + RETURN(0); } static int unionfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { (void)path; - DBG_IN(); + DBG("fd = %"PRIx64"\n", fi->fh); int res = pwrite(fi->fh, buf, size, offset); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); if (uopt.stats_enabled) stats_add_written(&stats, size); - return res; + RETURN(res); } -#ifdef HAVE_SETXATTR +#ifdef HAVE_XATTR static int unionfs_getxattr(const char *path, const char *name, char *value, size_t size) { - DBG_IN(); + DBG("%s\n", path); int i = find_rorw_branch(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = lgetxattr(p, name, value, size); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return res; + RETURN(res); } static int unionfs_listxattr(const char *path, char *list, size_t size) { - DBG_IN(); + DBG("%s\n", path); int i = find_rorw_branch(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = llistxattr(p, list, size); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return res; + RETURN(res); } static int unionfs_removexattr(const char *path, const char *name) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = lremovexattr(p, name); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return res; + RETURN(res); } static int unionfs_setxattr(const char *path, const char *name, const char *value, size_t size, int flags) { - DBG_IN(); + DBG("%s\n", path); int i = find_rw_branch_cow(path); - if (i == -1) return -errno; + if (i == -1) RETURN(-errno); char p[PATHLEN_MAX]; - snprintf(p, PATHLEN_MAX, "%s%s", uopt.branches[i].path, path); + if (BUILD_PATH(p, uopt.branches[i].path, path)) RETURN(-ENAMETOOLONG); int res = lsetxattr(p, name, value, size, flags); - if (res == -1) return -errno; + if (res == -1) RETURN(-errno); - return res; + RETURN(res); } -#endif // HAVE_SETXATTR +#endif // HAVE_XATTR static struct fuse_operations unionfs_oper = { .chmod = unionfs_chmod, @@ -768,7 +780,7 @@ static struct fuse_operations unionfs_oper = { .unlink = unionfs_unlink, .utimens = unionfs_utimens, .write = unionfs_write, -#ifdef HAVE_SETXATTR +#ifdef HAVE_XATTR .getxattr = unionfs_getxattr, .listxattr = unionfs_listxattr, .removexattr = unionfs_removexattr, @@ -779,17 +791,17 @@ static struct fuse_operations unionfs_oper = { int main(int argc, char *argv[]) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); - int res = debug_init(); - if (res != 0) return res; - + init_syslog(); uopt_init(); - if (fuse_opt_parse(&args, NULL, unionfs_opts, unionfs_opt_proc) == -1) return 1; + if (fuse_opt_parse(&args, NULL, unionfs_opts, unionfs_opt_proc) == -1) RETURN(1); + + if (uopt.debug) debug_init(); if (!uopt.doexit) { if (uopt.nbranches == 0) { printf("You need to specify at least one branch!\n"); - return 1; + RETURN(1); } if (uopt.stats_enabled) stats_init(&stats); @@ -797,13 +809,36 @@ int main(int argc, char *argv[]) { // enable fuse permission checks, we need to set this, even we we are // not root, since we don't have our own access() function - if (fuse_opt_add_arg(&args, "-odefault_permissions")) { - fprintf(stderr, "Severe failure, can't enable permssion checks, aborting!\n"); + int uid = getuid(); + int gid = getgid(); + bool default_permissions = true; + + if (uid != 0 && gid != 0 && uopt.relaxed_permissions) { + default_permissions = false; + } else if (uopt.relaxed_permissions) { + // protec the user of a very critical security issue + fprintf(stderr, "Relaxed permissions disallowed for root!\n"); exit(1); } + + if (default_permissions) { + if (fuse_opt_add_arg(&args, "-odefault_permissions")) { + fprintf(stderr, "Severe failure, can't enable permssion checks, aborting!\n"); + exit(1); + } + } unionfs_post_opts(); +#ifdef FUSE_CAP_BIG_WRITES + /* libfuse > 0.8 supports large IO, also for reads, to increase performance + * We support any IO sizes, so lets enable that option */ + if (fuse_opt_add_arg(&args, "-obig_writes")) { + fprintf(stderr, "Failed to enable big writes!\n"); + exit(1); + } +#endif + umask(0); - res = fuse_main(args.argc, args.argv, &unionfs_oper, NULL); - return uopt.doexit ? uopt.retval : res; + int res = fuse_main(args.argc, args.argv, &unionfs_oper, NULL); + RETURN(uopt.doexit ? uopt.retval : res); } |