diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2007-12-12 14:25:40 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2007-12-12 14:25:40 +0000 |
commit | cdb8b79bad5fea81b74931a9027f1d5ca344af8e (patch) | |
tree | 11ab550f265dc3eb546b7c26f3745e6d139b1fcc /util | |
parent | 918f0ad95b73e506d20488cb8ddd35d1a2524c7c (diff) | |
download | android_external_fuse-cdb8b79bad5fea81b74931a9027f1d5ca344af8e.tar.gz android_external_fuse-cdb8b79bad5fea81b74931a9027f1d5ca344af8e.tar.bz2 android_external_fuse-cdb8b79bad5fea81b74931a9027f1d5ca344af8e.zip |
change indenting
Diffstat (limited to 'util')
-rw-r--r-- | util/fusermount.c | 1533 | ||||
-rw-r--r-- | util/mount.fuse.c | 353 | ||||
-rw-r--r-- | util/ulockmgr_server.c | 671 |
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; } |