📄 fusermount.c
字号:
!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 (!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()); source = malloc((fsname ? strlen(fsname) : 0) + strlen(dev) + 32); type = malloc(32); if (!type || !source) { fprintf(stderr, "%s: failed to allocate memory\n", progname); goto err; } strcpy(type, blkdev ? "fuseblk" : "fuse"); if (fsname) strcpy(source, fsname); else strcpy(source, dev); if (restore_privs()) goto err; 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 (drop_privs()) goto err; 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)); if (errno_save == EPERM) fprintf(stderr, "User doesn't have privilege to mount. " "For more information\nplease see: " "http://ntfs-3g.org/support.html#unprivileged\n"); } goto err; } else { *sourcep = source; *typep = type; *mnt_optsp = mnt_opts; }out: free(fsname); free(optbuf); return res;err: free(source); free(type); free(mnt_opts); res = -1; goto out;}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 = stat(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 fd; if (restore_privs()) return -1; fd = open(dev, O_RDWR); if (drop_privs()) return -1; 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 { fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev, strerror(errno)); } return fd;}static int open_fuse_device(char **devp){ int fd; fd = try_open(FUSE_DEV_NEW, devp); if (fd >= -1) return fd; fprintf(stderr, "%s: fuse device is missing, try 'modprobe fuse' as root\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; if (getuid() != 0 && mount_max != -1) { if (count_fuse_fs() >= mount_max) { fprintf(stderr, "%s: too many mounted FUSE filesystems (%d+)\n", progname, mount_max); goto err; } } res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd); if (res != -1) res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, fd, opts, dev, &source, &mnt_opts); if (currdir_fd != -1) { fchdir(currdir_fd); close(currdir_fd); } if (mountpoint_fd != -1) close(mountpoint_fd); if (res == -1) goto err; if (restore_privs()) goto err; if (geteuid() == 0) { if (setgroups(0, NULL) == -1) { perror("priv drop: setgroups failed"); goto err; } res = add_mount(source, mnt, type, mnt_opts); if (res == -1) { umount2(mnt, 2); /* lazy umount */ drop_privs(); goto err; } } if (drop_privs()) goto err;out: free(source); free(type); free(mnt_opts); free(dev); return fd;err: close(fd); fd = -1; goto out;}int fusermount(int unmount, int quiet, int lazy, const char *opts, const char *origmnt){ int res = -1; char *mnt; mode_t old_umask; mnt = fuse_mnt_resolve_path(progname, origmnt); if (mnt == NULL) return -1; old_umask = umask(033); if (unmount) { if (restore_privs()) goto out; if (geteuid() == 0) res = fuse_mnt_umount(progname, mnt, 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 (drop_privs()) res = -1; } else res = mount_fuse(mnt, opts);out: umask(old_umask); free(mnt); return res; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -