aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2007-12-12 14:25:40 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2007-12-12 14:25:40 +0000
commitcdb8b79bad5fea81b74931a9027f1d5ca344af8e (patch)
tree11ab550f265dc3eb546b7c26f3745e6d139b1fcc /util
parent918f0ad95b73e506d20488cb8ddd35d1a2524c7c (diff)
change indenting
Diffstat (limited to 'util')
-rw-r--r--util/fusermount.c1533
-rw-r--r--util/mount.fuse.c353
-rw-r--r--util/ulockmgr_server.c671
3 files changed, 1305 insertions, 1252 deletions
diff --git a/util/fusermount.c b/util/fusermount.c
index 716caff..e3c98c5 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -1,9 +1,9 @@
/*
- FUSE: Filesystem in Userspace
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
- This program can be distributed under the terms of the GNU GPL.
- See the file COPYING.
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
*/
/* This program does the mounting and unmounting of FUSE filesystems */
@@ -27,7 +27,7 @@
#include <sys/socket.h>
#include <sys/utsname.h>
-#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
#define FUSE_DEV_NEW "/dev/fuse"
@@ -45,13 +45,13 @@ static int mount_max = 1000;
static const char *get_user_name(void)
{
- struct passwd *pw = getpwuid(getuid());
- if (pw != NULL && pw->pw_name != NULL)
- return pw->pw_name;
- else {
- fprintf(stderr, "%s: could not determine username\n", progname);
- return NULL;
- }
+ struct passwd *pw = getpwuid(getuid());
+ if (pw != NULL && pw->pw_name != NULL)
+ return pw->pw_name;
+ else {
+ fprintf(stderr, "%s: could not determine username\n", progname);
+ return NULL;
+ }
}
static uid_t oldfsuid;
@@ -59,868 +59,897 @@ static gid_t oldfsgid;
static void drop_privs(void)
{
- if (getuid() != 0) {
- oldfsuid = setfsuid(getuid());
- oldfsgid = setfsgid(getgid());
- }
+ if (getuid() != 0) {
+ oldfsuid = setfsuid(getuid());
+ oldfsgid = setfsgid(getgid());
+ }
}
static void restore_privs(void)
{
- if (getuid() != 0) {
- setfsuid(oldfsuid);
- setfsgid(oldfsgid);
- }
+ if (getuid() != 0) {
+ setfsuid(oldfsuid);
+ setfsgid(oldfsgid);
+ }
}
#ifndef IGNORE_MTAB
static int add_mount(const char *source, const char *mnt, const char *type,
- const char *opts)
+ const char *opts)
{
- return fuse_mnt_add_mount(progname, source, mnt, type, opts);
+ return fuse_mnt_add_mount(progname, source, mnt, type, opts);
}
static int unmount_fuse(const char *mnt, int quiet, int lazy)
{
- if (getuid() != 0) {
- struct mntent *entp;
- FILE *fp;
- const char *user = NULL;
- char uidstr[32];
- unsigned uidlen = 0;
- int found;
- const char *mtab = _PATH_MOUNTED;
-
- user = get_user_name();
- if (user == NULL)
- return -1;
-
- fp = setmntent(mtab, "r");
- if (fp == NULL) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
- strerror(errno));
- return -1;
- }
-
- uidlen = sprintf(uidstr, "%u", getuid());
-
- found = 0;
- while ((entp = getmntent(fp)) != NULL) {
- if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
- (strcmp(entp->mnt_type, "fuse") == 0 ||
- strcmp(entp->mnt_type, "fuseblk") == 0 ||
- strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
- strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
- char *p = strstr(entp->mnt_opts, "user=");
- if (p && (p == entp->mnt_opts || *(p-1) == ',') &&
- strcmp(p + 5, user) == 0) {
- found = 1;
- break;
- }
- /* /etc/mtab is a link pointing to /proc/mounts: */
- else if ((p = strstr(entp->mnt_opts, "user_id=")) &&
- (p == entp->mnt_opts || *(p-1) == ',') &&
- strncmp(p + 8, uidstr, uidlen) == 0 &&
- (*(p+8+uidlen) == ',' || *(p+8+uidlen) == '\0')) {
- found = 1;
- break;
- }
- }
- }
- endmntent(fp);
-
- if (!found) {
- if (!quiet)
- fprintf(stderr, "%s: entry for %s not found in %s\n", progname,
- mnt, mtab);
- return -1;
- }
- }
-
- return fuse_mnt_umount(progname, mnt, lazy);
+ if (getuid() != 0) {
+ struct mntent *entp;
+ FILE *fp;
+ const char *user = NULL;
+ char uidstr[32];
+ unsigned uidlen = 0;
+ int found;
+ const char *mtab = _PATH_MOUNTED;
+
+ user = get_user_name();
+ if (user == NULL)
+ return -1;
+
+ fp = setmntent(mtab, "r");
+ if (fp == NULL) {
+ fprintf(stderr,
+ "%s: failed to open %s: %s\n", progname, mtab,
+ strerror(errno));
+ return -1;
+ }
+
+ uidlen = sprintf(uidstr, "%u", getuid());
+
+ found = 0;
+ while ((entp = getmntent(fp)) != NULL) {
+ if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
+ (strcmp(entp->mnt_type, "fuse") == 0 ||
+ strcmp(entp->mnt_type, "fuseblk") == 0 ||
+ strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
+ strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
+ char *p = strstr(entp->mnt_opts, "user=");
+ if (p &&
+ (p == entp->mnt_opts || *(p-1) == ',') &&
+ strcmp(p + 5, user) == 0) {
+ found = 1;
+ break;
+ }
+ /* /etc/mtab is a link pointing to
+ /proc/mounts: */
+ else if ((p =
+ strstr(entp->mnt_opts, "user_id=")) &&
+ (p == entp->mnt_opts ||
+ *(p-1) == ',') &&
+ strncmp(p + 8, uidstr, uidlen) == 0 &&
+ (*(p+8+uidlen) == ',' ||
+ *(p+8+uidlen) == '\0')) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ endmntent(fp);
+
+ if (!found) {
+ if (!quiet)
+ fprintf(stderr,
+ "%s: entry for %s not found in %s\n",
+ progname, mnt, mtab);
+ return -1;
+ }
+ }
+
+ return fuse_mnt_umount(progname, mnt, lazy);
}
static int count_fuse_fs(void)
{
- struct mntent *entp;
- int count = 0;
- const char *mtab = _PATH_MOUNTED;
- FILE *fp = setmntent(mtab, "r");
- if (fp == NULL) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
- strerror(errno));
- return -1;
- }
- while ((entp = getmntent(fp)) != NULL) {
- if (strcmp(entp->mnt_type, "fuse") == 0 ||
- strncmp(entp->mnt_type, "fuse.", 5) == 0)
- count ++;
- }
- endmntent(fp);
- return count;
+ struct mntent *entp;
+ int count = 0;
+ const char *mtab = _PATH_MOUNTED;
+ FILE *fp = setmntent(mtab, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
+ strerror(errno));
+ return -1;
+ }
+ while ((entp = getmntent(fp)) != NULL) {
+ if (strcmp(entp->mnt_type, "fuse") == 0 ||
+ strncmp(entp->mnt_type, "fuse.", 5) == 0)
+ count ++;
+ }
+ endmntent(fp);
+ return count;
}
#else /* IGNORE_MTAB */
static int count_fuse_fs()
{
- return 0;
+ return 0;
}
static int add_mount(const char *source, const char *mnt, const char *type,
- const char *opts)
+ const char *opts)
{
- (void) source;
- (void) mnt;
- (void) type;
- (void) opts;
- return 0;
+ (void) source;
+ (void) mnt;
+ (void) type;
+ (void) opts;
+ return 0;
}
static int unmount_fuse(const char *mnt, int quiet, int lazy)
{
- return fuse_mnt_umount(progname, mnt, lazy);
+ return fuse_mnt_umount(progname, mnt, lazy);
}
#endif /* IGNORE_MTAB */
static void strip_line(char *line)
{
- char *s = strchr(line, '#');
- if (s != NULL)
- s[0] = '\0';
- for (s = line + strlen(line) - 1; s >= line && isspace((unsigned char) *s); s--);
- s[1] = '\0';
- for (s = line; isspace((unsigned char) *s); s++);
- if (s != line)
- memmove(line, s, strlen(s)+1);
+ char *s = strchr(line, '#');
+ if (s != NULL)
+ s[0] = '\0';
+ for (s = line + strlen(line) - 1;
+ s >= line && isspace((unsigned char) *s); s--);
+ s[1] = '\0';
+ for (s = line; isspace((unsigned char) *s); s++);
+ if (s != line)
+ memmove(line, s, strlen(s)+1);
}
static void parse_line(char *line, int linenum)
{
- int tmp;
- if (strcmp(line, "user_allow_other") == 0)
- user_allow_other = 1;
- else if (sscanf(line, "mount_max = %i", &tmp) == 1)
- mount_max = tmp;
- else if(line[0])
- fprintf(stderr, "%s: unknown parameter in %s at line %i: '%s'\n",
- progname, FUSE_CONF, linenum, line);
+ int tmp;
+ if (strcmp(line, "user_allow_other") == 0)
+ user_allow_other = 1;
+ else if (sscanf(line, "mount_max = %i", &tmp) == 1)
+ mount_max = tmp;
+ else if(line[0])
+ fprintf(stderr,
+ "%s: unknown parameter in %s at line %i: '%s'\n",
+ progname, FUSE_CONF, linenum, line);
}
static void read_conf(void)
{
- FILE *fp = fopen(FUSE_CONF, "r");
- if (fp != NULL) {
- int linenum = 1;
- char line[256];
- int isnewline = 1;
- while (fgets(line, sizeof(line), fp) != NULL) {
- if (isnewline) {
- if (line[strlen(line)-1] == '\n') {
- strip_line(line);
- parse_line(line, linenum);
- } else {
- fprintf(stderr, "%s: reading %s: line %i too long\n",
- progname, FUSE_CONF, linenum);
- isnewline = 0;
- }
- } else if(line[strlen(line)-1] == '\n')
- isnewline = 1;
- if (isnewline)
- linenum ++;
- }
- fclose(fp);
- } else if (errno != ENOENT) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, FUSE_CONF,
- strerror(errno));
- }
+ FILE *fp = fopen(FUSE_CONF, "r");
+ if (fp != NULL) {
+ int linenum = 1;
+ char line[256];
+ int isnewline = 1;
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (isnewline) {
+ if (line[strlen(line)-1] == '\n') {
+ strip_line(line);
+ parse_line(line, linenum);
+ } else {
+ fprintf(stderr, "%s: reading %s: line %i too long\n",
+ progname, FUSE_CONF, linenum);
+ isnewline = 0;
+ }
+ } else if(line[strlen(line)-1] == '\n')
+ isnewline = 1;
+ if (isnewline)
+ linenum ++;
+ }
+ fclose(fp);
+ } else if (errno != ENOENT) {
+ fprintf(stderr, "%s: failed to open %s: %s\n",
+ progname, FUSE_CONF, strerror(errno));
+ }
}
static int begins_with(const char *s, const char *beg)
{
- if (strncmp(s, beg, strlen(beg)) == 0)
- return 1;
- else
- return 0;
+ if (strncmp(s, beg, strlen(beg)) == 0)
+ return 1;
+ else
+ return 0;
}
struct mount_flags {
- const char *opt;
- unsigned long flag;
- int on;
- int safe;
+ const char *opt;
+ unsigned long flag;
+ int on;
+ int safe;
};
static struct mount_flags mount_flags[] = {
- {"rw", MS_RDONLY, 0, 1},
- {"ro", MS_RDONLY, 1, 1},
- {"suid", MS_NOSUID, 0, 0},
- {"nosuid", MS_NOSUID, 1, 1},
- {"dev", MS_NODEV, 0, 0},
- {"nodev", MS_NODEV, 1, 1},
- {"exec", MS_NOEXEC, 0, 1},
- {"noexec", MS_NOEXEC, 1, 1},
- {"async", MS_SYNCHRONOUS, 0, 1},
- {"sync", MS_SYNCHRONOUS, 1, 1},
- {"atime", MS_NOATIME, 0, 1},
- {"noatime", MS_NOATIME, 1, 1},
- {"dirsync", MS_DIRSYNC, 1, 1},
- {NULL, 0, 0, 0}
+ {"rw", MS_RDONLY, 0, 1},
+ {"ro", MS_RDONLY, 1, 1},
+ {"suid", MS_NOSUID, 0, 0},
+ {"nosuid", MS_NOSUID, 1, 1},
+ {"dev", MS_NODEV, 0, 0},
+ {"nodev", MS_NODEV, 1, 1},
+ {"exec", MS_NOEXEC, 0, 1},
+ {"noexec", MS_NOEXEC, 1, 1},
+ {"async", MS_SYNCHRONOUS, 0, 1},
+ {"sync", MS_SYNCHRONOUS, 1, 1},
+ {"atime", MS_NOATIME, 0, 1},
+ {"noatime", MS_NOATIME, 1, 1},
+ {"dirsync", MS_DIRSYNC, 1, 1},
+ {NULL, 0, 0, 0}
};
static int find_mount_flag(const char *s, unsigned len, int *on, int *flag)
{
- int i;
-
- for (i = 0; mount_flags[i].opt != NULL; i++) {
- const char *opt = mount_flags[i].opt;
- if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
- *on = mount_flags[i].on;
- *flag = mount_flags[i].flag;
- if (!mount_flags[i].safe && getuid() != 0) {
- *flag = 0;
- fprintf(stderr, "%s: unsafe option %s ignored\n",
- progname, opt);
- }
- return 1;
- }
- }
- return 0;
+ int i;
+
+ for (i = 0; mount_flags[i].opt != NULL; i++) {
+ const char *opt = mount_flags[i].opt;
+ if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
+ *on = mount_flags[i].on;
+ *flag = mount_flags[i].flag;
+ if (!mount_flags[i].safe && getuid() != 0) {
+ *flag = 0;
+ fprintf(stderr,
+ "%s: unsafe option %s ignored\n",
+ progname, opt);
+ }
+ return 1;
+ }
+ }
+ return 0;
}
static int add_option(char **optsp, const char *opt, unsigned expand)
{
- char *newopts;
- if (*optsp == NULL)
- newopts = strdup(opt);
- else {
- unsigned oldsize = strlen(*optsp);
- unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
- newopts = (char *) realloc(*optsp, newsize);
- if (newopts)
- sprintf(newopts + oldsize, ",%s", opt);
- }
- if (newopts == NULL) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- return -1;
- }
- *optsp = newopts;
- return 0;
+ char *newopts;
+ if (*optsp == NULL)
+ newopts = strdup(opt);
+ else {
+ unsigned oldsize = strlen(*optsp);
+ unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
+ newopts = (char *) realloc(*optsp, newsize);
+ if (newopts)
+ sprintf(newopts + oldsize, ",%s", opt);
+ }
+ if (newopts == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return -1;
+ }
+ *optsp = newopts;
+ return 0;
}
static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
{
- int i;
- int l;
-
- if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
- return -1;
-
- for (i = 0; mount_flags[i].opt != NULL; i++) {
- if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
- add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
- return -1;
- }
-
- if (add_option(mnt_optsp, opts, 0) == -1)
- return -1;
- /* remove comma from end of opts*/
- l = strlen(*mnt_optsp);
- if ((*mnt_optsp)[l-1] == ',')
- (*mnt_optsp)[l-1] = '\0';
- if (getuid() != 0) {
- const char *user = get_user_name();
- if (user == NULL)
- return -1;
-
- if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
- return -1;
- strcat(*mnt_optsp, user);
- }
- return 0;
+ int i;
+ int l;
+
+ if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
+ return -1;
+
+ for (i = 0; mount_flags[i].opt != NULL; i++) {
+ if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
+ add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
+ return -1;
+ }
+
+ if (add_option(mnt_optsp, opts, 0) == -1)
+ return -1;
+ /* remove comma from end of opts*/
+ l = strlen(*mnt_optsp);
+ if ((*mnt_optsp)[l-1] == ',')
+ (*mnt_optsp)[l-1] = '\0';
+ if (getuid() != 0) {
+ const char *user = get_user_name();
+ if (user == NULL)
+ return -1;
+
+ if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
+ return -1;
+ strcat(*mnt_optsp, user);
+ }
+ return 0;
}
static int opt_eq(const char *s, unsigned len, const char *opt)
{
- if(strlen(opt) == len && strncmp(s, opt, len) == 0)
- return 1;
- else
- return 0;
+ if(strlen(opt) == len && strncmp(s, opt, len) == 0)
+ return 1;
+ else
+ return 0;
}
static int get_string_opt(const char *s, unsigned len, const char *opt,
- char **val)
+ char **val)
{
- unsigned opt_len = strlen(opt);
-
- if (*val)
- free(*val);
- *val = (char *) malloc(len - opt_len + 1);
- if (!*val) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- return 0;
- }
-
- memcpy(*val, s + opt_len, len - opt_len);
- (*val)[len - opt_len] = '\0';
- return 1;
+ unsigned opt_len = strlen(opt);
+
+ if (*val)
+ free(*val);
+ *val = (char *) malloc(len - opt_len + 1);
+ if (!*val) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return 0;
+ }
+
+ memcpy(*val, s + opt_len, len - opt_len);
+ (*val)[len - opt_len] = '\0';
+ return 1;
}
static int do_mount(const char *mnt, char **typep, mode_t rootmode,
- int fd, const char *opts, const char *dev, char **sourcep,
- char **mnt_optsp, off_t rootsize)
+ int fd, const char *opts, const char *dev, char **sourcep,
+ char **mnt_optsp, off_t rootsize)
{
- int res;
- int flags = MS_NOSUID | MS_NODEV;
- char *optbuf;
- char *mnt_opts = NULL;
- const char *s;
- char *d;
- char *fsname = NULL;
- char *subtype = NULL;
- char *source = NULL;
- char *type = NULL;
- int check_empty = 1;
- int blkdev = 0;
-
- optbuf = (char *) malloc(strlen(opts) + 128);
- if (!optbuf) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- return -1;
- }
-
- for (s = opts, d = optbuf; *s;) {
- unsigned len;
- const char *fsname_str = "fsname=";
- const char *subtype_str = "subtype=";
- for (len = 0; s[len] && s[len] != ','; len++);
- if (begins_with(s, fsname_str)) {
- if (!get_string_opt(s, len, fsname_str, &fsname))
- goto err;
- } else if (begins_with(s, subtype_str)) {
- if (!get_string_opt(s, len, subtype_str, &subtype))
- goto err;
- } else if (opt_eq(s, len, "blkdev")) {
- if (getuid() != 0) {
- fprintf(stderr, "%s: option blkdev is privileged\n", progname);
- goto err;
- }
- blkdev = 1;
- } else if (opt_eq(s, len, "nonempty")) {
- check_empty = 0;
- } else if (!begins_with(s, "fd=") &&
- !begins_with(s, "rootmode=") &&
- !begins_with(s, "user_id=") &&
- !begins_with(s, "group_id=")) {
- int on;
- int flag;
- int skip_option = 0;
- if (opt_eq(s, len, "large_read")) {
- struct utsname utsname;
- unsigned kmaj, kmin;
- res = uname(&utsname);
- if (res == 0 &&
- sscanf(utsname.release, "%u.%u", &kmaj, &kmin) == 2 &&
- (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
- fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
- skip_option = 1;
- }
- }
- if (getuid() != 0 && !user_allow_other &&
- (opt_eq(s, len, "allow_other") ||
- opt_eq(s, len, "allow_root"))) {
- fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s);
- goto err;
- }
- if (!skip_option) {
- if (find_mount_flag(s, len, &on, &flag)) {
- if (on)
- flags |= flag;
- else
- flags &= ~flag;
- } else {
- memcpy(d, s, len);
- d += len;
- *d++ = ',';
- }
- }
- }
- s += len;
- if (*s)
- s++;
- }
- *d = '\0';
- res = get_mnt_opts(flags, optbuf, &mnt_opts);
- if (res == -1)
- goto err;
-
- sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
- fd, rootmode, getuid(), getgid());
-
- if (check_empty &&
- fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1)
- goto err;
-
- source = malloc((fsname ? strlen(fsname) : 0) +
- (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
-
- type = malloc((subtype ? strlen(subtype) : 0) + 32);
- if (!type || !source) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- goto err;
- }
-
- if (subtype)
- sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
- else
- strcpy(type, blkdev ? "fuseblk" : "fuse");
-
- if (fsname)
- strcpy(source, fsname);
- else
- strcpy(source, subtype ? subtype : dev);
-
- res = mount(source, mnt, type, flags, optbuf);
- if (res == -1 && errno == ENODEV && subtype) {
- /* Probably missing subtype support */
- strcpy(type, blkdev ? "fuseblk" : "fuse");
- if (fsname) {
- if (!blkdev)
- sprintf(source, "%s#%s", subtype, fsname);
- } else {
- strcpy(source, type);
- }
-
- res = mount(source, mnt, type, flags, optbuf);
- }
- if (res == -1 && errno == EINVAL) {
- /* It could be an old version not supporting group_id */
- sprintf(d, "fd=%i,rootmode=%o,user_id=%i", fd, rootmode, getuid());
- res = mount(source, mnt, type, flags, optbuf);
- }
- if (res == -1) {
- int errno_save = errno;
- if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
- fprintf(stderr, "%s: 'fuseblk' support missing\n", progname);
- else
- fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save));
- goto err;
- } else {
- *sourcep = source;
- *typep = type;
- *mnt_optsp = mnt_opts;
- }
- free(optbuf);
-
- return res;
-
- err:
- free(fsname);
- free(subtype);
- free(source);
- free(type);
- free(mnt_opts);
- free(optbuf);
- return -1;
+ int res;
+ int flags = MS_NOSUID | MS_NODEV;
+ char *optbuf;
+ char *mnt_opts = NULL;
+ const char *s;
+ char *d;
+ char *fsname = NULL;
+ char *subtype = NULL;
+ char *source = NULL;
+ char *type = NULL;
+ int check_empty = 1;
+ int blkdev = 0;
+
+ optbuf = (char *) malloc(strlen(opts) + 128);
+ if (!optbuf) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ return -1;
+ }
+
+ for (s = opts, d = optbuf; *s;) {
+ unsigned len;
+ const char *fsname_str = "fsname=";
+ const char *subtype_str = "subtype=";
+ for (len = 0; s[len] && s[len] != ','; len++);
+ if (begins_with(s, fsname_str)) {
+ if (!get_string_opt(s, len, fsname_str, &fsname))
+ goto err;
+ } else if (begins_with(s, subtype_str)) {
+ if (!get_string_opt(s, len, subtype_str, &subtype))
+ goto err;
+ } else if (opt_eq(s, len, "blkdev")) {
+ if (getuid() != 0) {
+ fprintf(stderr,
+ "%s: option blkdev is privileged\n",
+ progname);
+ goto err;
+ }
+ blkdev = 1;
+ } else if (opt_eq(s, len, "nonempty")) {
+ check_empty = 0;
+ } else if (!begins_with(s, "fd=") &&
+ !begins_with(s, "rootmode=") &&
+ !begins_with(s, "user_id=") &&
+ !begins_with(s, "group_id=")) {
+ int on;
+ int flag;
+ int skip_option = 0;
+ if (opt_eq(s, len, "large_read")) {
+ struct utsname utsname;
+ unsigned kmaj, kmin;
+ res = uname(&utsname);
+ if (res == 0 &&
+ sscanf(utsname.release, "%u.%u",
+ &kmaj, &kmin) == 2 &&
+ (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
+ fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
+ skip_option = 1;
+ }
+ }
+ if (getuid() != 0 && !user_allow_other &&
+ (opt_eq(s, len, "allow_other") ||
+ opt_eq(s, len, "allow_root"))) {
+ fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in /etc/fuse.conf\n", progname, len, s);
+ goto err;
+ }
+ if (!skip_option) {
+ if (find_mount_flag(s, len, &on, &flag)) {
+ if (on)
+ flags |= flag;
+ else
+ flags &= ~flag;
+ } else {
+ memcpy(d, s, len);
+ d += len;
+ *d++ = ',';
+ }
+ }
+ }
+ s += len;
+ if (*s)
+ s++;
+ }
+ *d = '\0';
+ res = get_mnt_opts(flags, optbuf, &mnt_opts);
+ if (res == -1)
+ goto err;
+
+ sprintf(d, "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
+ fd, rootmode, getuid(), getgid());
+
+ if (check_empty &&
+ fuse_mnt_check_empty(progname, mnt, rootmode, rootsize) == -1)
+ goto err;
+
+ source = malloc((fsname ? strlen(fsname) : 0) +
+ (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
+
+ type = malloc((subtype ? strlen(subtype) : 0) + 32);
+ if (!type || !source) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ goto err;
+ }
+
+ if (subtype)
+ sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
+ else
+ strcpy(type, blkdev ? "fuseblk" : "fuse");
+
+ if (fsname)
+ strcpy(source, fsname);
+ else
+ strcpy(source, subtype ? subtype : dev);
+
+ res = mount(source, mnt, type, flags, optbuf);
+ if (res == -1 && errno == ENODEV && subtype) {
+ /* Probably missing subtype support */
+ strcpy(type, blkdev ? "fuseblk" : "fuse");
+ if (fsname) {
+ if (!blkdev)
+ sprintf(source, "%s#%s", subtype, fsname);
+ } else {
+ strcpy(source, type);
+ }
+
+ res = mount(source, mnt, type, flags, optbuf);
+ }
+ if (res == -1 && errno == EINVAL) {
+ /* It could be an old version not supporting group_id */
+ sprintf(d, "fd=%i,rootmode=%o,user_id=%i",
+ fd, rootmode, getuid());
+ res = mount(source, mnt, type, flags, optbuf);
+ }
+ if (res == -1) {
+ int errno_save = errno;
+ if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
+ fprintf(stderr, "%s: 'fuseblk' support missing\n",
+ progname);
+ else
+ fprintf(stderr, "%s: mount failed: %s\n", progname,
+ strerror(errno_save));
+ goto err;
+ } else {
+ *sourcep = source;
+ *typep = type;
+ *mnt_optsp = mnt_opts;
+ }
+ free(optbuf);
+
+ return res;
+
+err:
+ free(fsname);
+ free(subtype);
+ free(source);
+ free(type);
+ free(mnt_opts);
+ free(optbuf);
+ return -1;
}
static int check_version(const char *dev)
{
- int res;
- int majorver;
- int minorver;
- const char *version_file;
- FILE *vf;
-
- if (strcmp(dev, FUSE_DEV_OLD) != 0)
- return 0;
-
- version_file = FUSE_VERSION_FILE_OLD;
- vf = fopen(version_file, "r");
- if (vf == NULL) {
- fprintf(stderr, "%s: kernel interface too old\n", progname);
- return -1;
- }
- res = fscanf(vf, "%i.%i", &majorver, &minorver);
- fclose(vf);
- if (res != 2) {
- fprintf(stderr, "%s: error reading %s\n", progname, version_file);
- return -1;
- }
- if (majorver < 3) {
- fprintf(stderr, "%s: kernel interface too old\n", progname);
- return -1;
- }
- return 0;
+ int res;
+ int majorver;
+ int minorver;
+ const char *version_file;
+ FILE *vf;
+
+ if (strcmp(dev, FUSE_DEV_OLD) != 0)
+ return 0;
+
+ version_file = FUSE_VERSION_FILE_OLD;
+ vf = fopen(version_file, "r");
+ if (vf == NULL) {
+ fprintf(stderr, "%s: kernel interface too old\n", progname);
+ return -1;
+ }
+ res = fscanf(vf, "%i.%i", &majorver, &minorver);
+ fclose(vf);
+ if (res != 2) {
+ fprintf(stderr, "%s: error reading %s\n", progname,
+ version_file);
+ return -1;
+ }
+ if (majorver < 3) {
+ fprintf(stderr, "%s: kernel interface too old\n", progname);
+ return -1;
+ }
+ return 0;
}
static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
- int *mountpoint_fd)
+ int *mountpoint_fd)
{
- int res;
- const char *mnt = *mntp;
- const char *origmnt = mnt;
-
- res = lstat(mnt, stbuf);
- if (res == -1) {
- fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
- progname, mnt, strerror(errno));
- return -1;
- }
-
- /* No permission checking is done for root */
- if (getuid() == 0)
- return 0;
-
- if (S_ISDIR(stbuf->st_mode)) {
- *currdir_fd = open(".", O_RDONLY);
- if (*currdir_fd == -1) {
- fprintf(stderr, "%s: failed to open current directory: %s\n",
- progname, strerror(errno));
- return -1;
- }
- res = chdir(mnt);
- if (res == -1) {
- fprintf(stderr, "%s: failed to chdir to mountpoint: %s\n",
- progname, strerror(errno));
- return -1;
- }
- mnt = *mntp = ".";
- res = lstat(mnt, stbuf);
- if (res == -1) {
- fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
- progname, origmnt, strerror(errno));
- return -1;
- }
-
- if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
- fprintf(stderr, "%s: mountpoint %s not owned by user\n",
- progname, origmnt);
- return -1;
- }
-
- res = access(mnt, W_OK);
- if (res == -1) {
- fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
- progname, origmnt);
- return -1;
- }
- } else if (S_ISREG(stbuf->st_mode)) {
- static char procfile[256];
- *mountpoint_fd = open(mnt, O_WRONLY);
- if (*mountpoint_fd == -1) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, mnt,
- strerror(errno));
- return -1;
- }
- res = fstat(*mountpoint_fd, stbuf);
- if (res == -1) {
- fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
- progname, mnt, strerror(errno));
- return -1;
- }
- if (!S_ISREG(stbuf->st_mode)) {
- fprintf(stderr, "%s: mountpoint %s is no longer a regular file\n",
- progname, mnt);
- return -1;
- }
-
- sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
- *mntp = procfile;
- } else {
- fprintf(stderr,
- "%s: mountpoint %s is not a directory or a regular file\n",
- progname, mnt);
- return -1;
- }
-
-
- return 0;
+ int res;
+ const char *mnt = *mntp;
+ const char *origmnt = mnt;
+
+ res = lstat(mnt, stbuf);
+ if (res == -1) {
+ fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+
+ /* No permission checking is done for root */
+ if (getuid() == 0)
+ return 0;
+
+ if (S_ISDIR(stbuf->st_mode)) {
+ *currdir_fd = open(".", O_RDONLY);
+ if (*currdir_fd == -1) {
+ fprintf(stderr,
+ "%s: failed to open current directory: %s\n",
+ progname, strerror(errno));
+ return -1;
+ }
+ res = chdir(mnt);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to chdir to mountpoint: %s\n",
+ progname, strerror(errno));
+ return -1;
+ }
+ mnt = *mntp = ".";
+ res = lstat(mnt, stbuf);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to access mountpoint %s: %s\n",
+ progname, origmnt, strerror(errno));
+ return -1;
+ }
+
+ if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
+ fprintf(stderr, "%s: mountpoint %s not owned by user\n",
+ progname, origmnt);
+ return -1;
+ }
+
+ res = access(mnt, W_OK);
+ if (res == -1) {
+ fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
+ progname, origmnt);
+ return -1;
+ }
+ } else if (S_ISREG(stbuf->st_mode)) {
+ static char procfile[256];
+ *mountpoint_fd = open(mnt, O_WRONLY);
+ if (*mountpoint_fd == -1) {
+ fprintf(stderr, "%s: failed to open %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ res = fstat(*mountpoint_fd, stbuf);
+ if (res == -1) {
+ fprintf(stderr,
+ "%s: failed to access mountpoint %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ if (!S_ISREG(stbuf->st_mode)) {
+ fprintf(stderr,
+ "%s: mountpoint %s is no longer a regular file\n",
+ progname, mnt);
+ return -1;
+ }
+
+ sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
+ *mntp = procfile;
+ } else {
+ fprintf(stderr,
+ "%s: mountpoint %s is not a directory or a regular file\n",
+ progname, mnt);
+ return -1;
+ }
+
+
+ return 0;
}
static int try_open(const char *dev, char **devp, int silent)
{
- int fd = open(dev, O_RDWR);
- if (fd != -1) {
- *devp = strdup(dev);
- if (*devp == NULL) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- close(fd);
- fd = -1;
- }
- } else if (errno == ENODEV ||
- errno == ENOENT) /* check for ENOENT too, for the udev case */
- return -2;
- else if (!silent) {
- fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
- strerror(errno));
- }
- return fd;
+ int fd = open(dev, O_RDWR);
+ if (fd != -1) {
+ *devp = strdup(dev);
+ if (*devp == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n",
+ progname);
+ close(fd);
+ fd = -1;
+ }
+ } else if (errno == ENODEV ||
+ errno == ENOENT)/* check for ENOENT too, for the udev case */
+ return -2;
+ else if (!silent) {
+ fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
+ strerror(errno));
+ }
+ return fd;
}
static int try_open_fuse_device(char **devp)
{
- int fd;
- int err;
+ int fd;
+ int err;
- drop_privs();
- fd = try_open(FUSE_DEV_NEW, devp, 0);
- restore_privs();
- if (fd >= 0)
- return fd;
+ drop_privs();
+ fd = try_open(FUSE_DEV_NEW, devp, 0);
+ restore_privs();
+ if (fd >= 0)
+ return fd;
- err = fd;
- fd = try_open(FUSE_DEV_OLD, devp, 1);
- if (fd >= 0)
- return fd;
+ err = fd;
+ fd = try_open(FUSE_DEV_OLD, devp, 1);
+ if (fd >= 0)
+ return fd;
- return err;
+ return err;
}
static int open_fuse_device(char **devp)
{
- int fd = try_open_fuse_device(devp);
- if (fd >= -1)
- return fd;
+ int fd = try_open_fuse_device(devp);
+ if (fd >= -1)
+ return fd;
- fprintf(stderr, "%s: fuse device not found, try 'modprobe fuse' first\n",
- progname);
+ fprintf(stderr,
+ "%s: fuse device not found, try 'modprobe fuse' first\n",
+ progname);
- return -1;
+ return -1;
}
static int mount_fuse(const char *mnt, const char *opts)
{
- int res;
- int fd;
- char *dev;
- struct stat stbuf;
- char *type = NULL;
- char *source = NULL;
- char *mnt_opts = NULL;
- const char *real_mnt = mnt;
- int currdir_fd = -1;
- int mountpoint_fd = -1;
-
- fd = open_fuse_device(&dev);
- if (fd == -1)
- return -1;
-
- drop_privs();
- read_conf();
-
- if (getuid() != 0 && mount_max != -1) {
- int mount_count = count_fuse_fs();
- if (mount_count >= mount_max) {
- fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
- close(fd);
- return -1;
- }
- }
-
- res = check_version(dev);
- if (res != -1) {
- res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd);
- restore_privs();
- if (res != -1)
- res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts,
- dev, &source, &mnt_opts, stbuf.st_size);
- } else
- restore_privs();
-
- if (currdir_fd != -1) {
- fchdir(currdir_fd);
- close(currdir_fd);
- }
- if (mountpoint_fd != -1)
- close(mountpoint_fd);
-
- if (res == -1) {
- close(fd);
- return -1;
- }
-
- if (geteuid() == 0) {
- res = add_mount(source, mnt, type, mnt_opts);
- if (res == -1) {
- umount2(mnt, 2); /* lazy umount */
- close(fd);
- return -1;
- }
- }
-
- free(source);
- free(type);
- free(mnt_opts);
- free(dev);
-
- return fd;
+ int res;
+ int fd;
+ char *dev;
+ struct stat stbuf;
+ char *type = NULL;
+ char *source = NULL;
+ char *mnt_opts = NULL;
+ const char *real_mnt = mnt;
+ int currdir_fd = -1;
+ int mountpoint_fd = -1;
+
+ fd = open_fuse_device(&dev);
+ if (fd == -1)
+ return -1;
+
+ drop_privs();
+ read_conf();
+
+ if (getuid() != 0 && mount_max != -1) {
+ int mount_count = count_fuse_fs();
+ if (mount_count >= mount_max) {
+ fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname);
+ close(fd);
+ return -1;
+ }
+ }
+
+ res = check_version(dev);
+ if (res != -1) {
+ res = check_perm(&real_mnt, &stbuf, &currdir_fd,
+ &mountpoint_fd);
+ restore_privs();
+ if (res != -1)
+ res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
+ fd, opts, dev, &source, &mnt_opts,
+ stbuf.st_size);
+ } else
+ restore_privs();
+
+ if (currdir_fd != -1) {
+ fchdir(currdir_fd);
+ close(currdir_fd);
+ }
+ if (mountpoint_fd != -1)
+ close(mountpoint_fd);
+
+ if (res == -1) {
+ close(fd);
+ return -1;
+ }
+
+ if (geteuid() == 0) {
+ res = add_mount(source, mnt, type, mnt_opts);
+ if (res == -1) {
+ umount2(mnt, 2); /* lazy umount */
+ close(fd);
+ return -1;
+ }
+ }
+
+ free(source);
+ free(type);
+ free(mnt_opts);
+ free(dev);
+
+ return fd;
}
static int send_fd(int sock_fd, int fd)
{
- int retval;
- struct msghdr msg;
- struct cmsghdr *p_cmsg;
- struct iovec vec;
- size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
- int *p_fds;
- char sendchar = 0;
-
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = sizeof(cmsgbuf);
- p_cmsg = CMSG_FIRSTHDR(&msg);
- 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 = fd;
- msg.msg_controllen = p_cmsg->cmsg_len;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &vec;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- /* "To pass file descriptors or credentials you need to send/read at
- * least one byte" (man 7 unix) */
- vec.iov_base = &sendchar;
- vec.iov_len = sizeof(sendchar);
- while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
- if (retval != 1) {
- perror("sending file descriptor");
- return -1;
- }
- return 0;
+ int retval;
+ struct msghdr msg;
+ struct cmsghdr *p_cmsg;
+ struct iovec vec;
+ size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
+ int *p_fds;
+ char sendchar = 0;
+
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = sizeof(cmsgbuf);
+ p_cmsg = CMSG_FIRSTHDR(&msg);
+ 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 = fd;
+ msg.msg_controllen = p_cmsg->cmsg_len;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ /* "To pass file descriptors or credentials you need to send/read at
+ * least one byte" (man 7 unix) */
+ vec.iov_base = &sendchar;
+ vec.iov_len = sizeof(sendchar);
+ while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
+ if (retval != 1) {
+ perror("sending file descriptor");
+ return -1;
+ }
+ return 0;
}
static void usage(void)
{
- fprintf(stderr,
- "%s: [options] mountpoint\n"
- "Options:\n"
- " -h print help\n"
- " -V print version\n"
- " -o opt[,opt...] mount options\n"
- " -u unmount\n"
- " -q quiet\n"
- " -z lazy unmount\n",
- progname);
- exit(1);
+ fprintf(stderr,
+ "%s: [options] mountpoint\n"
+ "Options:\n"
+ " -h print help\n"
+ " -V print version\n"
+ " -o opt[,opt...] mount options\n"
+ " -u unmount\n"
+ " -q quiet\n"
+ " -z lazy unmount\n",
+ progname);
+ exit(1);
}
static void show_version(void)
{
- printf("fusermount version: %s\n", PACKAGE_VERSION);
- exit(0);
+ printf("fusermount version: %s\n", PACKAGE_VERSION);
+ exit(0);
}
int main(int argc, char *argv[])
{
- int ch;
- int fd;
- int res;
- char *origmnt;
- char *mnt;
- static int unmount = 0;
- static int lazy = 0;
- static int quiet = 0;
- char *commfd;
- int cfd;
- const char *opts = "";
-
- static const struct option long_opts[] = {
- {"unmount", no_argument, NULL, 'u'},
- {"lazy", no_argument, NULL, 'z'},
- {"quiet", no_argument, NULL, 'q'},
- {"help", no_argument, NULL, 'h'},
- {"version", no_argument, NULL, 'V'},
- {0, 0, 0, 0}};
-
- progname = strdup(argv[0]);
- if (progname == NULL) {
- fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
- exit(1);
- }
-
- while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts, NULL)) != -1) {
- switch (ch) {
- case 'h':
- usage();
- break;
-
- case 'V':
- show_version();
- break;
-
- case 'o':
- opts = optarg;
- break;
-
- case 'u':
- unmount = 1;
- break;
-
- case 'z':
- lazy = 1;
- break;
-
- case 'q':
- quiet = 1;
- break;
-
- default:
- exit(1);
- }
- }
-
- if (lazy && !unmount) {
- fprintf(stderr, "%s: -z can only be used with -u\n", progname);
- exit(1);
- }
-
- if (optind >= argc) {
- fprintf(stderr, "%s: missing mountpoint argument\n", progname);
- exit(1);
- }
-
- origmnt = argv[optind];
-
- drop_privs();
- mnt = fuse_mnt_resolve_path(progname, origmnt);
- restore_privs();
- if (mnt == NULL)
- exit(1);
-
- umask(033);
- if (unmount) {
- if (geteuid() == 0)
- res = unmount_fuse(mnt, quiet, lazy);
- else {
- res = umount2(mnt, lazy ? 2 : 0);
- if (res == -1 && !quiet)
- fprintf(stderr, "%s: failed to unmount %s: %s\n", progname,
- mnt, strerror(errno));
- }
- if (res == -1)
- exit(1);
- return 0;
- }
-
- commfd = getenv(FUSE_COMMFD_ENV);
- if (commfd == NULL) {
- fprintf(stderr, "%s: old style mounting not supported\n", progname);
- exit(1);
- }
-
- fd = mount_fuse(mnt, opts);
- if (fd == -1)
- exit(1);
-
- cfd = atoi(commfd);
- res = send_fd(cfd, fd);
- if (res == -1)
- exit(1);
-
- return 0;
+ int ch;
+ int fd;
+ int res;
+ char *origmnt;
+ char *mnt;
+ static int unmount = 0;
+ static int lazy = 0;
+ static int quiet = 0;
+ char *commfd;
+ int cfd;
+ const char *opts = "";
+
+ static const struct option long_opts[] = {
+ {"unmount", no_argument, NULL, 'u'},
+ {"lazy", no_argument, NULL, 'z'},
+ {"quiet", no_argument, NULL, 'q'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {0, 0, 0, 0}};
+
+ progname = strdup(argv[0]);
+ if (progname == NULL) {
+ fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
+ exit(1);
+ }
+
+ while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
+ NULL)) != -1) {
+ switch (ch) {
+ case 'h':
+ usage();
+ break;
+
+ case 'V':
+ show_version();
+ break;
+
+ case 'o':
+ opts = optarg;
+ break;
+
+ case 'u':
+ unmount = 1;
+ break;
+
+ case 'z':
+ lazy = 1;
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ default:
+ exit(1);
+ }
+ }
+
+ if (lazy && !unmount) {
+ fprintf(stderr, "%s: -z can only be used with -u\n", progname);
+ exit(1);
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "%s: missing mountpoint argument\n", progname);
+ exit(1);
+ }
+
+ origmnt = argv[optind];
+
+ drop_privs();
+ mnt = fuse_mnt_resolve_path(progname, origmnt);
+ restore_privs();
+ if (mnt == NULL)
+ exit(1);
+
+ umask(033);
+ if (unmount) {
+ if (geteuid() == 0)
+ res = unmount_fuse(mnt, quiet, lazy);
+ else {
+ res = umount2(mnt, lazy ? 2 : 0);
+ if (res == -1 && !quiet)
+ fprintf(stderr,
+ "%s: failed to unmount %s: %s\n",
+ progname, mnt, strerror(errno));
+ }
+ if (res == -1)
+ exit(1);
+ return 0;
+ }
+
+ commfd = getenv(FUSE_COMMFD_ENV);
+ if (commfd == NULL) {
+ fprintf(stderr, "%s: old style mounting not supported\n",
+ progname);
+ exit(1);
+ }
+
+ fd = mount_fuse(mnt, opts);
+ if (fd == -1)
+ exit(1);
+
+ cfd = atoi(commfd);
+ res = send_fd(cfd, fd);
+ if (res == -1)
+ exit(1);
+
+ return 0;
}
diff --git a/util/mount.fuse.c b/util/mount.fuse.c
index 4cc0394..7bd0e83 100644
--- a/util/mount.fuse.c
+++ b/util/mount.fuse.c
@@ -1,3 +1,11 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -8,184 +16,193 @@ static char *progname;
static char *xstrdup(const char *s)
{
- char *t = strdup(s);
- if (!t) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- exit(1);
- }
- return t;
+ char *t = strdup(s);
+ if (!t) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ exit(1);
+ }
+ return t;
}
static void *xrealloc(void *oldptr, size_t size)
{
- void *ptr = realloc(oldptr, size);
- if (!ptr) {
- fprintf(stderr, "%s: failed to allocate memory\n", progname);
- exit(1);
- }
- return ptr;
+ void *ptr = realloc(oldptr, size);
+ if (!ptr) {
+ fprintf(stderr, "%s: failed to allocate memory\n", progname);
+ exit(1);
+ }
+ return ptr;
}
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 *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;
+ size_t optlen = strlen(opt);
+ size_t cmdlen = *cmdp ? strlen(*cmdp) : 0;
+ char *cmd = 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;
}
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;
-
- progname = argv[0];
- basename = strrchr(argv[0], '/');
- if (basename)
- basename++;
- else
- basename = argv[0];
-
- if (strncmp(basename, "mount.fuse.", 11) == 0)
- type = basename + 11;
- if (strncmp(basename, "mount.fuseblk.", 14) == 0)
- type = basename + 14;
-
- if (type && !type[0])
- type = NULL;
-
- if (argc < 3) {
- fprintf(stderr, "usage: %s %s destination [-t type] [-o opt[,opts...]]\n",
- progname, type ? "source" : "type#[source]");
- exit(1);
- }
-
- source = argv[1];
- if (!source[0])
- source = NULL;
-
- mountpoint = argv[2];
-
- for (i = 3; i < argc; i++) {
- if (strcmp(argv[i], "-v") == 0) {
- continue;
- } else if (strcmp(argv[i], "-t") == 0) {
- i++;
-
- if (i == argc) {
- fprintf(stderr,
- "%s: missing argument to option '-t'\n", progname);
- exit(1);
- }
- type = argv[i];
- if (strncmp(type, "fuse.", 5) == 0)
- type += 5;
- else if (strncmp(type, "fuseblk.", 8) == 0)
- type += 8;
-
- if (!type[0]) {
- fprintf(stderr,
- "%s: empty type given as argument to option '-t'\n",
- progname);
- exit(1);
- }
- } else if (strcmp(argv[i], "-o") == 0) {
- char *opts;
- char *opt;
- i++;
- if (i == argc)
- break;
-
- opts = xstrdup(argv[i]);
- opt = strtok(opts, ",");
- while (opt) {
- int j;
- int ignore = 0;
- const char *ignore_opts[] = { "", "user", "nouser", "users",
- "auto", "noauto", "_netdev",
- NULL};
- if (strncmp(opt, "setuid=", 7) == 0) {
- setuid = xstrdup(opt + 7);
- ignore = 1;
- }
- for (j = 0; ignore_opts[j]; j++)
- if (strcmp(opt, ignore_opts[j]) == 0)
- ignore = 1;
-
- if (!ignore) {
- int oldlen = options ? strlen(options) : 0;
- options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
- if (!oldlen)
- strcpy(options, opt);
- else {
- strcat(options, ",");
- strcat(options, opt);
- }
- }
- opt = strtok(NULL, ",");
- }
- }
- }
-
- if (!type) {
- type = xstrdup(source);
- source = strchr(type, '#');
- if (source)
- *source++ = '\0';
-
- if (!type[0]) {
- fprintf(stderr, "%s: empty filesystem type\n", progname);
- exit(1);
- }
- }
-
- add_arg(&command, type);
- if (source)
- add_arg(&command, source);
- add_arg(&command, mountpoint);
- if (options) {
- add_arg(&command, "-o");
- add_arg(&command, 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);
- } 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);
- fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
- strerror(errno));
- return 1;
+ char *type = NULL;
+ char *source;
+ const char *mountpoint;
+ char *basename;
+ char *options = NULL;
+ char *command = NULL;
+ char *setuid = NULL;
+ int i;
+
+ progname = argv[0];
+ basename = strrchr(argv[0], '/');
+ if (basename)
+ basename++;
+ else
+ basename = argv[0];
+
+ if (strncmp(basename, "mount.fuse.", 11) == 0)
+ type = basename + 11;
+ if (strncmp(basename, "mount.fuseblk.", 14) == 0)
+ type = basename + 14;
+
+ if (type && !type[0])
+ type = NULL;
+
+ if (argc < 3) {
+ fprintf(stderr,
+ "usage: %s %s destination [-t type] [-o opt[,opts...]]\n",
+ progname, type ? "source" : "type#[source]");
+ exit(1);
+ }
+
+ source = argv[1];
+ if (!source[0])
+ source = NULL;
+
+ mountpoint = argv[2];
+
+ for (i = 3; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0) {
+ continue;
+ } else if (strcmp(argv[i], "-t") == 0) {
+ i++;
+
+ if (i == argc) {
+ fprintf(stderr,
+ "%s: missing argument to option '-t'\n",
+ progname);
+ exit(1);
+ }
+ type = argv[i];
+ if (strncmp(type, "fuse.", 5) == 0)
+ type += 5;
+ else if (strncmp(type, "fuseblk.", 8) == 0)
+ type += 8;
+
+ if (!type[0]) {
+ fprintf(stderr,
+ "%s: empty type given as argument to option '-t'\n",
+ progname);
+ exit(1);
+ }
+ } else if (strcmp(argv[i], "-o") == 0) {
+ char *opts;
+ char *opt;
+ i++;
+ if (i == argc)
+ break;
+
+ opts = xstrdup(argv[i]);
+ opt = strtok(opts, ",");
+ while (opt) {
+ int j;
+ int ignore = 0;
+ const char *ignore_opts[] = { "",
+ "user",
+ "nouser",
+ "users",
+ "auto",
+ "noauto",
+ "_netdev",
+ NULL};
+ if (strncmp(opt, "setuid=", 7) == 0) {
+ setuid = xstrdup(opt + 7);
+ ignore = 1;
+ }
+ for (j = 0; ignore_opts[j]; j++)
+ if (strcmp(opt, ignore_opts[j]) == 0)
+ ignore = 1;
+
+ if (!ignore) {
+ int oldlen =
+ options ? strlen(options) : 0;
+ options = xrealloc(options, oldlen + 1 + strlen(opt) + 1);
+ if (!oldlen)
+ strcpy(options, opt);
+ else {
+ strcat(options, ",");
+ strcat(options, opt);
+ }
+ }
+ opt = strtok(NULL, ",");
+ }
+ }
+ }
+
+ if (!type) {
+ type = xstrdup(source);
+ source = strchr(type, '#');
+ if (source)
+ *source++ = '\0';
+
+ if (!type[0]) {
+ fprintf(stderr, "%s: empty filesystem type\n",
+ progname);
+ exit(1);
+ }
+ }
+
+ add_arg(&command, type);
+ if (source)
+ add_arg(&command, source);
+ add_arg(&command, mountpoint);
+ if (options) {
+ add_arg(&command, "-o");
+ add_arg(&command, 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);
+ } 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);
+ fprintf(stderr, "%s: failed to execute /bin/sh: %s\n", progname,
+ strerror(errno));
+ return 1;
}
diff --git a/util/ulockmgr_server.c b/util/ulockmgr_server.c
index 4f831b0..8ffdfef 100644
--- a/util/ulockmgr_server.c
+++ b/util/ulockmgr_server.c
@@ -1,9 +1,9 @@
/*
- ulockmgr_server: Userspace Lock Manager Server
- Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu>
+ ulockmgr_server: Userspace Lock Manager Server
+ Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu>
- This program can be distributed under the terms of the GNU GPL.
- See the file COPYING.
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
*/
/* #define DEBUG 1 */
@@ -23,381 +23,388 @@
#include <sys/wait.h>
struct message {
- unsigned intr : 1;
- unsigned nofd : 1;
- pthread_t thr;
- int cmd;
- int fd;
- struct flock lock;
- int error;
+ unsigned intr : 1;
+ unsigned nofd : 1;
+ pthread_t thr;
+ int cmd;
+ int fd;
+ struct flock lock;
+ int error;
};
struct fd_store {
- struct fd_store *next;
- int fd;
- int origfd;
- int inuse;
+ struct fd_store *next;
+ int fd;
+ int origfd;
+ int inuse;
};
struct owner {
- struct fd_store *fds;
- pthread_mutex_t lock;
+ struct fd_store *fds;
+ pthread_mutex_t lock;
};
struct req_data {
- struct owner *o;
- int cfd;
- struct fd_store *f;
- struct message msg;
+ struct owner *o;
+ int cfd;
+ struct fd_store *f;
+ struct message msg;
};
#define MAX_SEND_FDS 2
static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
- int *numfds)
+ int *numfds)
{
- struct msghdr msg;
- struct iovec iov;
- size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
- struct cmsghdr *cmsg;
- int res;
- int i;
-
- assert(*numfds <= MAX_SEND_FDS);
- iov.iov_base = buf;
- iov.iov_len = buflen;
-
- memset(&msg, 0, sizeof(msg));
- memset(ccmsg, -1, sizeof(ccmsg));
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = ccmsg;
- msg.msg_controllen = sizeof(ccmsg);
-
- res = recvmsg(sock, &msg, MSG_WAITALL);
- if (!res) {
- /* retry on zero return, see do_recv() in ulockmgr.c */
- res = recvmsg(sock, &msg, MSG_WAITALL);
- if (!res)
- return 0;
- }
- if (res == -1) {
- perror("ulockmgr_server: recvmsg");
- return -1;
- }
- if ((size_t) res != buflen) {
- fprintf(stderr, "ulockmgr_server: short message received\n");
- return -1;
- }
-
- cmsg = CMSG_FIRSTHDR(&msg);
- if (cmsg) {
- if (!cmsg->cmsg_type == SCM_RIGHTS) {
- fprintf(stderr, "ulockmgr_server: unknown control message %d\n",
- cmsg->cmsg_type);
- return -1;
- }
- memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
- if (msg.msg_flags & MSG_CTRUNC) {
- fprintf(stderr, "ulockmgr_server: control message truncated\n");
- for (i = 0; i < *numfds; i++)
- close(fdp[i]);
- *numfds = 0;
- }
- } else {
- if (msg.msg_flags & MSG_CTRUNC) {
- fprintf(stderr, "ulockmgr_server: control message truncated(*)\n");
-
- /* There's a bug in the Linux kernel, that if not all file
- descriptors were allocated, then the cmsg header is not
- filled in */
- cmsg = (struct cmsghdr *) ccmsg;
- memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
- for (i = 0; i < *numfds; i++)
- close(fdp[i]);
- }
- *numfds = 0;
- }
- return res;
+ struct msghdr msg;
+ struct iovec iov;
+ size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
+ struct cmsghdr *cmsg;
+ int res;
+ int i;
+
+ assert(*numfds <= MAX_SEND_FDS);
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(ccmsg, -1, sizeof(ccmsg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof(ccmsg);
+
+ res = recvmsg(sock, &msg, MSG_WAITALL);
+ if (!res) {
+ /* retry on zero return, see do_recv() in ulockmgr.c */
+ res = recvmsg(sock, &msg, MSG_WAITALL);
+ if (!res)
+ return 0;
+ }
+ if (res == -1) {
+ perror("ulockmgr_server: recvmsg");
+ return -1;
+ }
+ if ((size_t) res != buflen) {
+ fprintf(stderr, "ulockmgr_server: short message received\n");
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg) {
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ fprintf(stderr,
+ "ulockmgr_server: unknown control message %d\n",
+ cmsg->cmsg_type);
+ return -1;
+ }
+ memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
+ if (msg.msg_flags & MSG_CTRUNC) {
+ fprintf(stderr,
+ "ulockmgr_server: control message truncated\n");
+ for (i = 0; i < *numfds; i++)
+ close(fdp[i]);
+ *numfds = 0;
+ }
+ } else {
+ if (msg.msg_flags & MSG_CTRUNC) {
+ fprintf(stderr,
+ "ulockmgr_server: control message truncated(*)\n");
+
+ /* There's a bug in the Linux kernel, that if
+ not all file descriptors were allocated,
+ then the cmsg header is not filled in */
+ cmsg = (struct cmsghdr *) ccmsg;
+ memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
+ for (i = 0; i < *numfds; i++)
+ close(fdp[i]);
+ }
+ *numfds = 0;
+ }
+ return res;
}
static int closefrom(int minfd)
{
- DIR *dir = opendir("/proc/self/fd");
- if (dir) {
- int dfd = dirfd(dir);
- struct dirent *ent;
- while ((ent = readdir(dir))) {
- char *end;
- int fd = strtol(ent->d_name, &end, 10);
- if (ent->d_name[0] && !end[0] && fd >= minfd && fd != dfd)
- close(fd);
- }
- closedir(dir);
- }
- return 0;
+ DIR *dir = opendir("/proc/self/fd");
+ if (dir) {
+ int dfd = dirfd(dir);
+ struct dirent *ent;
+ while ((ent = readdir(dir))) {
+ char *end;
+ int fd = strtol(ent->d_name, &end, 10);
+ if (ent->d_name[0] && !end[0] && fd >= minfd &&
+ fd != dfd)
+ close(fd);
+ }
+ closedir(dir);
+ }
+ return 0;
}
static void send_reply(int cfd, struct message *msg)
{
- int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
- if (res == -1)
- perror("ulockmgr_server: sending reply");
+ int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
+ if (res == -1)
+ perror("ulockmgr_server: sending reply");
#ifdef DEBUG
- fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
+ fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
#endif
}
static void *process_request(void *d_)
{
- struct req_data *d = d_;
- int res;
-
- assert(d->msg.cmd == F_SETLKW);
- res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
- if (res == -1 && errno == EAGAIN) {
- d->msg.error = EAGAIN;
- d->msg.thr = pthread_self();
- send_reply(d->cfd, &d->msg);
- res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
- }
- d->msg.error = (res == -1) ? errno : 0;
- pthread_mutex_lock(&d->o->lock);
- d->f->inuse--;
- pthread_mutex_unlock(&d->o->lock);
- send_reply(d->cfd, &d->msg);
- close(d->cfd);
- free(d);
-
- return NULL;
+ struct req_data *d = d_;
+ int res;
+
+ assert(d->msg.cmd == F_SETLKW);
+ res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
+ if (res == -1 && errno == EAGAIN) {
+ d->msg.error = EAGAIN;
+ d->msg.thr = pthread_self();
+ send_reply(d->cfd, &d->msg);
+ res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
+ }
+ d->msg.error = (res == -1) ? errno : 0;
+ pthread_mutex_lock(&d->o->lock);
+ d->f->inuse--;
+ pthread_mutex_unlock(&d->o->lock);
+ send_reply(d->cfd, &d->msg);
+ close(d->cfd);
+ free(d);
+
+ return NULL;
}
static void process_message(struct owner *o, struct message *msg, int cfd,
- int fd)
+ int fd)
{
- struct fd_store *f = NULL;
- struct fd_store *newf = NULL;
- struct fd_store **fp;
- struct req_data *d;
- pthread_t tid;
- int res;
+ struct fd_store *f = NULL;
+ struct fd_store *newf = NULL;
+ struct fd_store **fp;
+ struct req_data *d;
+ pthread_t tid;
+ int res;
#ifdef DEBUG
- fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
- msg->cmd, msg->lock.l_type, msg->lock.l_whence, msg->lock.l_start,
- msg->lock.l_len);
+ fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
+ msg->cmd, msg->lock.l_type, msg->lock.l_whence,
+ msg->lock.l_start, msg->lock.l_len);
#endif
- if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
- msg->lock.l_start == 0 && msg->lock.l_len == 0) {
- for (fp = &o->fds; *fp;) {
- f = *fp;
- if (f->origfd == msg->fd && !f->inuse) {
- close(f->fd);
- *fp = f->next;
- free(f);
- } else
- fp = &f->next;
- }
- if (!msg->nofd)
- close(fd);
-
- msg->error = 0;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
-
- if (msg->nofd) {
- for (fp = &o->fds; *fp; fp = &(*fp)->next) {
- f = *fp;
- if (f->origfd == msg->fd)
- break;
- }
- if (!*fp) {
- fprintf(stderr, "ulockmgr_server: fd %i not found\n", msg->fd);
- msg->error = EIO;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
- } else {
- newf = f = malloc(sizeof(struct fd_store));
- if (!f) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
-
- f->fd = fd;
- f->origfd = msg->fd;
- f->inuse = 0;
- }
-
- if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
- msg->lock.l_type == F_UNLCK) {
- res = fcntl(f->fd, msg->cmd, &msg->lock);
- msg->error = (res == -1) ? errno : 0;
- send_reply(cfd, msg);
- close(cfd);
- if (newf) {
- newf->next = o->fds;
- o->fds = newf;
- }
- return;
- }
-
- d = malloc(sizeof(struct req_data));
- if (!d) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- free(newf);
- return;
- }
-
- f->inuse++;
- d->o = o;
- d->cfd = cfd;
- d->f = f;
- d->msg = *msg;
- res = pthread_create(&tid, NULL, process_request, d);
- if (res) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- free(d);
- f->inuse--;
- free(newf);
- return;
- }
-
- if (newf) {
- newf->next = o->fds;
- o->fds = newf;
- }
- pthread_detach(tid);
+ if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
+ msg->lock.l_start == 0 && msg->lock.l_len == 0) {
+ for (fp = &o->fds; *fp;) {
+ f = *fp;
+ if (f->origfd == msg->fd && !f->inuse) {
+ close(f->fd);
+ *fp = f->next;
+ free(f);
+ } else
+ fp = &f->next;
+ }
+ if (!msg->nofd)
+ close(fd);
+
+ msg->error = 0;
+ send_reply(cfd, msg);
+ close(cfd);
+ return;
+ }
+
+ if (msg->nofd) {
+ for (fp = &o->fds; *fp; fp = &(*fp)->next) {
+ f = *fp;
+ if (f->origfd == msg->fd)
+ break;
+ }
+ if (!*fp) {
+ fprintf(stderr, "ulockmgr_server: fd %i not found\n",
+ msg->fd);
+ msg->error = EIO;
+ send_reply(cfd, msg);
+ close(cfd);
+ return;
+ }
+ } else {
+ newf = f = malloc(sizeof(struct fd_store));
+ if (!f) {
+ msg->error = ENOLCK;
+ send_reply(cfd, msg);
+ close(cfd);
+ return;
+ }
+
+ f->fd = fd;
+ f->origfd = msg->fd;
+ f->inuse = 0;
+ }
+
+ if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
+ msg->lock.l_type == F_UNLCK) {
+ res = fcntl(f->fd, msg->cmd, &msg->lock);
+ msg->error = (res == -1) ? errno : 0;
+ send_reply(cfd, msg);
+ close(cfd);
+ if (newf) {
+ newf->next = o->fds;
+ o->fds = newf;
+ }
+ return;
+ }
+
+ d = malloc(sizeof(struct req_data));
+ if (!d) {
+ msg->error = ENOLCK;
+ send_reply(cfd, msg);
+ close(cfd);
+ free(newf);
+ return;
+ }
+
+ f->inuse++;
+ d->o = o;
+ d->cfd = cfd;
+ d->f = f;
+ d->msg = *msg;
+ res = pthread_create(&tid, NULL, process_request, d);
+ if (res) {
+ msg->error = ENOLCK;
+ send_reply(cfd, msg);
+ close(cfd);
+ free(d);
+ f->inuse--;
+ free(newf);
+ return;
+ }
+
+ if (newf) {
+ newf->next = o->fds;
+ o->fds = newf;
+ }
+ pthread_detach(tid);
}
static void sigusr1_handler(int sig)
{
- (void) sig;
- /* Nothing to do */
+ (void) sig;
+ /* Nothing to do */
}
static void process_owner(int cfd)
{
- struct owner o;
- struct sigaction sa;
-
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = sigusr1_handler;
- sigemptyset(&sa.sa_mask);
-
- if (sigaction(SIGUSR1, &sa, NULL) == -1) {
- perror("ulockmgr_server: cannot set sigusr1 signal handler");
- exit(1);
- }
-
- memset(&o, 0, sizeof(struct owner));
- pthread_mutex_init(&o.lock, NULL);
- while (1) {
- struct message msg;
- int rfds[2];
- int res;
- int numfds = 2;
-
- res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
- if (!res)
- break;
- if (res == -1)
- exit(1);
-
- if (msg.intr) {
- if (numfds != 0)
- fprintf(stderr, "ulockmgr_server: too many fds for intr\n");
- pthread_kill(msg.thr, SIGUSR1);
- } else {
- if (numfds != 2)
- continue;
-
- pthread_mutex_lock(&o.lock);
- process_message(&o, &msg, rfds[0], rfds[1]);
- pthread_mutex_unlock(&o.lock);
- }
- }
- if (o.fds)
- fprintf(stderr, "ulockmgr_server: open file descriptors on exit\n");
+ struct owner o;
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_handler = sigusr1_handler;
+ sigemptyset(&sa.sa_mask);
+
+ if (sigaction(SIGUSR1, &sa, NULL) == -1) {
+ perror("ulockmgr_server: cannot set sigusr1 signal handler");
+ exit(1);
+ }
+
+ memset(&o, 0, sizeof(struct owner));
+ pthread_mutex_init(&o.lock, NULL);
+ while (1) {
+ struct message msg;
+ int rfds[2];
+ int res;
+ int numfds = 2;
+
+ res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
+ if (!res)
+ break;
+ if (res == -1)
+ exit(1);
+
+ if (msg.intr) {
+ if (numfds != 0)
+ fprintf(stderr,
+ "ulockmgr_server: too many fds for intr\n");
+ pthread_kill(msg.thr, SIGUSR1);
+ } else {
+ if (numfds != 2)
+ continue;
+
+ pthread_mutex_lock(&o.lock);
+ process_message(&o, &msg, rfds[0], rfds[1]);
+ pthread_mutex_unlock(&o.lock);
+ }
+ }
+ if (o.fds)
+ fprintf(stderr,
+ "ulockmgr_server: open file descriptors on exit\n");
}
int main(int argc, char *argv[])
{
- int nullfd;
- char *end;
- int cfd;
- sigset_t empty;
-
- if (argc != 2 || !argv[1][0])
- goto out_inval;
-
- cfd = strtol(argv[1], &end, 10);
- if (*end)
- goto out_inval;
-
- if (daemon(0, 1) == -1) {
- perror("ulockmgr_server: daemon");
- exit(1);
- }
-
- sigemptyset(&empty);
- sigprocmask(SIG_SETMASK, &empty, NULL);
-
- if (dup2(cfd, 4) == -1) {
- perror("ulockmgr_server: dup2");
- exit(1);
- }
- cfd = 4;
- nullfd = open("/dev/null", O_RDWR);
- dup2(nullfd, 0);
- dup2(nullfd, 1);
- close(3);
- closefrom(5);
- while (1) {
- char c;
- int sock;
- int pid;
- int numfds = 1;
- int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
- if (!res)
- break;
- if (res == -1)
- exit(1);
- assert(numfds == 1);
-
- pid = fork();
- if (pid == -1) {
- perror("ulockmgr_server: fork");
- close(sock);
- continue;
- }
- if (pid == 0) {
- close(cfd);
- pid = fork();
- if (pid == -1) {
- perror("ulockmgr_server: fork");
- _exit(1);
- }
- if (pid == 0)
- process_owner(sock);
- _exit(0);
- }
- waitpid(pid, NULL, 0);
- close(sock);
- }
- return 0;
-
- out_inval:
- fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
- return 1;
+ int nullfd;
+ char *end;
+ int cfd;
+ sigset_t empty;
+
+ if (argc != 2 || !argv[1][0])
+ goto out_inval;
+
+ cfd = strtol(argv[1], &end, 10);
+ if (*end)
+ goto out_inval;
+
+ if (daemon(0, 1) == -1) {
+ perror("ulockmgr_server: daemon");
+ exit(1);
+ }
+
+ sigemptyset(&empty);
+ sigprocmask(SIG_SETMASK, &empty, NULL);
+
+ if (dup2(cfd, 4) == -1) {
+ perror("ulockmgr_server: dup2");
+ exit(1);
+ }
+ cfd = 4;
+ nullfd = open("/dev/null", O_RDWR);
+ dup2(nullfd, 0);
+ dup2(nullfd, 1);
+ close(3);
+ closefrom(5);
+ while (1) {
+ char c;
+ int sock;
+ int pid;
+ int numfds = 1;
+ int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
+ if (!res)
+ break;
+ if (res == -1)
+ exit(1);
+ assert(numfds == 1);
+
+ pid = fork();
+ if (pid == -1) {
+ perror("ulockmgr_server: fork");
+ close(sock);
+ continue;
+ }
+ if (pid == 0) {
+ close(cfd);
+ pid = fork();
+ if (pid == -1) {
+ perror("ulockmgr_server: fork");
+ _exit(1);
+ }
+ if (pid == 0)
+ process_owner(sock);
+ _exit(0);
+ }
+ waitpid(pid, NULL, 0);
+ close(sock);
+ }
+ return 0;
+
+out_inval:
+ fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
+ return 1;
}