📄 fusermount.c
字号:
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 check_mountpoint_empty(const char *mnt, mode_t rootmode, off_t rootsize){ int isempty = 1; if (S_ISDIR(rootmode)) { struct dirent *ent; DIR *dp = opendir(mnt); if (dp == NULL) { fprintf(stderr, "%s: failed to open mountpoint for reading: %s\n", progname, strerror(errno)); return -1; } while ((ent = readdir(dp)) != NULL) { if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) { isempty = 0; break; } } closedir(dp); } else if (rootsize) isempty = 0; if (!isempty) { fprintf(stderr, "%s: mountpoint is not empty\n", progname); fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname); return -1; } return 0;}static int has_fuseblk(void){ char buf[256]; FILE *f = fopen("/proc/filesystems", "r"); if (!f) return 1; while (fgets(buf, sizeof(buf), f)) if (strstr(buf, "fuseblk\n")) { fclose(f); return 1; } fclose(f); return 0;}static int do_mount(const char *mnt, const char **type, mode_t rootmode, int fd, const char *opts, const char *dev, char **fsnamep, 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; 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="; 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, "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 (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; if (blkdev) *type = "fuseblk"; 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) { int errno_save = errno; if (blkdev && errno == ENODEV && !has_fuseblk()) fprintf(stderr, "%s: 'fuseblk' support missing; try the kernel module from fuse-2.6.0 or later\n", progname); else fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save)); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -