⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fusermount.c

📁 UNIX/LINUX下面的用户文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    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 does the mounting and unmounting of FUSE filesystems */#include <config.h>#include "mount_util.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <getopt.h>#include <errno.h>#include <fcntl.h>#include <pwd.h>#include <mntent.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/fsuid.h>#include <sys/socket.h>#include <sys/utsname.h>#define FUSE_COMMFD_ENV         "_FUSE_COMMFD"#define FUSE_DEV_OLD "/proc/fs/fuse/dev"#define FUSE_DEV_NEW "/dev/fuse"#define FUSE_VERSION_FILE_OLD "/proc/fs/fuse/version"#define FUSE_CONF "/etc/fuse.conf"#ifndef MS_DIRSYNC#define MS_DIRSYNC 128#endifstatic const char *progname;static int user_allow_other = 0;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;    }}static uid_t oldfsuid;static gid_t oldfsgid;static void drop_privs(void){    if (getuid() != 0) {        oldfsuid = setfsuid(getuid());        oldfsgid = setfsgid(getgid());    }}static void restore_privs(void){    if (getuid() != 0) {        setfsuid(oldfsuid);        setfsgid(oldfsgid);    }}#ifndef IGNORE_MTABstatic int add_mount(const char *source, const char *mnt, const char *type,                     const char *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);}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;}#else /* IGNORE_MTAB */static int count_fuse_fs(){    return 0;}static int add_mount(const char *source, const char *mnt, const char *type,                     const char *opts){    (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);}#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);}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);}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));    }}static int begins_with(const char *s, const char *beg){    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;};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}};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;}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;}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;}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;}static int get_string_opt(const char *s, unsigned len, const char *opt,                          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;}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 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) +

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -