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

📄 fusermount.c

📁 linux下的用户文件系统fuse-2.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
        const char *fsname_str = "fsname=";        for (len = 0; s[len] && s[len] != ','; len++);        if (begins_with(s, fsname_str)) {            unsigned fsname_str_len = strlen(fsname_str);            if (fsname)                free(fsname);            fsname = (char *) malloc(len - fsname_str_len + 1);            if (!fsname) {                fprintf(stderr, "%s: failed to allocate memory\n", progname);                goto err;            }            memcpy(fsname, s + fsname_str_len, len - fsname_str_len);            fsname[len - fsname_str_len] = '\0';        } 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 (fsname == NULL) {        fsname = strdup(dev);        if (!fsname) {            fprintf(stderr, "%s: failed to allocate memory\n", progname);            goto err;        }    }    if (check_empty && check_mountpoint_empty(mnt, rootmode, rootsize) == -1)        goto err;    res = mount(fsname, 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(fsname, mnt, type, flags, optbuf);    }    if (res == -1) {        fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno));        goto err;    } else {        *fsnamep = fsname;        *mnt_optsp = mnt_opts;    }    free(optbuf);    return res; err:    free(fsname);    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;}static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_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;}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)        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;    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;    return err;}static int open_fuse_device(char **devp){    int fd = try_open_fuse_device(devp);    if (fd >= 0)        return fd;    if (fd == -2)        fprintf(stderr,                "%s: fuse device not found, try 'modprobe fuse' first\n",                progname);    return -1;}static int mount_fuse(const char *mnt, const char *opts){    int res;    int fd;    char *dev;    const char *type = "fuse";    struct stat stbuf;    char *fsname = NULL;    char *mnt_opts = NULL;    const char *real_mnt = mnt;    int currdir_fd = -1;    int mountpoint_fd = -1;    int mtablock = -1;    fd = open_fuse_device(&dev);    if (fd == -1)        return -1;    if (geteuid() == 0) {        mtablock = lock_mtab();        if (mtablock < 0) {            close(fd);            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);            unlock_mtab(mtablock);            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, &fsname, &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);        unlock_mtab(mtablock);        return -1;    }    if (geteuid() == 0) {        res = add_mount(fsname, mnt, type, mnt_opts);        unlock_mtab(mtablock);        if (res == -1) {            umount2(mnt, 2); /* lazy umount */            close(fd);            return -1;        }    }    free(fsname);    free(mnt_opts);    free(dev);    return fd;}static char *resolve_path(const char *orig){    char buf[PATH_MAX];    char *copy;    char *dst;    char *end;    char *lastcomp;    const char *toresolv;    if (!orig[0]) {        fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname, orig);        return NULL;    }    copy = strdup(orig);    if (copy == NULL) {        fprintf(stderr, "%s: failed to allocate memory\n", progname);        return NULL;    }    toresolv = copy;    lastcomp = NULL;    for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);    if (end[0] != '/') {        char *tmp;        end[1] = '\0';        tmp = strrchr(copy, '/');        if (tmp == NULL) {            lastcomp = copy;            toresolv = ".";        } else {            lastcomp = tmp + 1;            if (tmp == copy)                toresolv = "/";        }        if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {            lastcomp = NULL;            toresolv = copy;        }        else if (tmp)            tmp[0] = '\0';    }    if (realpath(toresolv, buf) == NULL) {        fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,                strerror(errno));        free(copy);        return NULL;    }    if (lastcomp == NULL)        dst = strdup(buf);    else {        dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);        if (dst) {            unsigned buflen = strlen(buf);            if (buflen && buf[buflen-1] == '/')                sprintf(dst, "%s%s", buf, lastcomp);            else                sprintf(dst, "%s/%s", buf, lastcomp);        }    }    free(copy);    if (dst == NULL)        fprintf(stderr, "%s: failed to allocate memory\n", progname);    return dst;}static int send_fd(int sock_fd, int fd){    int retval;    struct msghdr msg;    struct cmsghdr *p_cmsg;    struct iovec vec;    char cmsgbuf[CMSG_SPACE(sizeof(fd))];    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);}static void show_version(void){    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 = resolve_path(origmnt);    restore_privs();    if (mnt == NULL)        exit(1);    umask(033);    if (unmount) {        if (geteuid() == 0) {            int mtablock = lock_mtab();            res = unmount_fuse(mnt, quiet, lazy);            unlock_mtab(mtablock);        } else            res = do_unmount(mnt, quiet, lazy);        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;}

⌨️ 快捷键说明

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