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

📄 fusermount.c

📁 FUSE文件系统开发工具,将内核层面的文件系统开发过程平移到应用层面上来。
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -