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

📄 fusermount.c

📁 UNIX/LINUX下面的用户文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
                    (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;}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 ||               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;    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 >= -1)        return fd;    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;    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;}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 = 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;}

⌨️ 快捷键说明

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