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

📄 fusermount.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 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) +			(subtype ? strlen(subtype) : 0) + strlen(dev) + 32);

⌨️ 快捷键说明

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