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

📄 ntfs-3g.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (size) {		if (size >= na->data_size) {			res = ntfs_attr_pread(na, 0, na->data_size, value);			if (res != na->data_size)				res = -errno;		} else			res = -ERANGE;	} else		res = na->data_size;exit:	if (na)		ntfs_attr_close(na);	free(lename);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}static int ntfs_fuse_setxattr(const char *path, const char *name,				const char *value, size_t size, int flags){	ntfs_volume *vol;	ntfs_inode *ni;	ntfs_attr *na = NULL;	ntfschar *lename = NULL;	int res, lename_len;	if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)		return -EOPNOTSUPP;	if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||			strlen(name) == (size_t)nf_ns_xattr_preffix_len)		return -EACCES;	vol = ctx->vol;	if (!vol)		return -ENODEV;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni)		return -errno;	lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename, 0);	if (lename_len == -1) {		res = -errno;		goto exit;	}	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);	if (na && flags == XATTR_CREATE) {		res = -EEXIST;		goto exit;	}	ntfs_fuse_mark_free_space_outdated();	if (!na) {		if (flags == XATTR_REPLACE) {			res = -ENODATA;			goto exit;		}		if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {			res = -errno;			goto exit;		}		na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);		if (!na) {			res = -errno;			goto exit;		}	}	res = ntfs_attr_pwrite(na, 0, size, value);	if (res != (s64) size)		res = -errno;	else		res = 0;exit:	if (na)		ntfs_attr_close(na);	free(lename);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}static int ntfs_fuse_removexattr(const char *path, const char *name){	ntfs_volume *vol;	ntfs_inode *ni;	ntfs_attr *na = NULL;	ntfschar *lename = NULL;	int res = 0, lename_len;	if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)		return -EOPNOTSUPP;	if (strncmp(name, nf_ns_xattr_preffix, nf_ns_xattr_preffix_len) ||			strlen(name) == (size_t)nf_ns_xattr_preffix_len)		return -ENODATA;	vol = ctx->vol;	if (!vol)		return -ENODEV;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni)		return -errno;	lename_len = ntfs_mbstoucs(name + nf_ns_xattr_preffix_len, &lename, 0);	if (lename_len == -1) {		res = -errno;		goto exit;	}	na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);	if (!na) {		res = -ENODATA;		goto exit;	}	ntfs_fuse_mark_free_space_outdated();	if (ntfs_attr_rm(na))		res = -errno;	else		na = NULL;exit:	if (na)		ntfs_attr_close(na);	free(lename);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}#endif /* HAVE_SETXATTR */static struct fuse_operations ntfs_fuse_oper = {	.getattr	= ntfs_fuse_getattr,	.readlink	= ntfs_fuse_readlink,	.readdir	= ntfs_fuse_readdir,	.open		= ntfs_fuse_open,	.read		= ntfs_fuse_read,	.write		= ntfs_fuse_write,	.truncate	= ntfs_fuse_truncate,	.statfs		= ntfs_fuse_statfs,	.chmod		= ntfs_fuse_chmod,	.chown		= ntfs_fuse_chown,	.mknod		= ntfs_fuse_mknod,	.symlink	= ntfs_fuse_symlink,	.link		= ntfs_fuse_link,	.unlink		= ntfs_fuse_unlink,	.rename		= ntfs_fuse_rename,	.mkdir		= ntfs_fuse_mkdir,	.rmdir		= ntfs_fuse_rmdir,	.utime		= ntfs_fuse_utime,#ifdef HAVE_SETXATTR	.getxattr	= ntfs_fuse_getxattr,	.setxattr	= ntfs_fuse_setxattr,	.removexattr	= ntfs_fuse_removexattr,	.listxattr	= ntfs_fuse_listxattr,#endif /* HAVE_SETXATTR */};static int ntfs_fuse_init(void){	ctx = ntfs_malloc(sizeof(ntfs_fuse_context_t));	if (!ctx)		return -1;		*ctx = (ntfs_fuse_context_t) {		.state = NF_FreeClustersOutdate | NF_FreeMFTOutdate,		.uid = geteuid(),		.gid = getegid(),		.fmask = 0177,		.dmask = 0077,		.streams = NF_STREAMS_INTERFACE_NONE,	};	return 0;}static int ntfs_fuse_mount(const char *device){	ntfs_volume *vol;	vol = utils_mount_volume(device, ((ctx->ro) ? MS_RDONLY : 0) |			((ctx->noatime) ? MS_NOATIME : 0), ctx->force);	if (!vol) {		ntfs_log_error("Mount failed.\n");		return -1;	}	ctx->vol = vol;	return 0;}static void ntfs_fuse_destroy(void){	if (ctx->vol) {		ntfs_log_info("Unmounting %s (%s)\n", opts.device,				ctx->vol->vol_name);		if (ntfs_umount(ctx->vol, FALSE))			ntfs_log_perror("Failed to unmount volume");	}	free(ctx);	free(opts.device);}static void signal_handler(int arg __attribute__((unused))){	fuse_exit((fuse_get_context())->fuse);}static char *parse_mount_options(const char *org_options){	char *options, *s, *opt, *val, *ret;	BOOL no_def_opts = FALSE;	/*	 * +7		for "fsname=".	 * +1		for comma.	 * +1		for null-terminator.	 * +PATH_MAX	for resolved by realpath() device name.	 */	ret = ntfs_malloc(strlen(def_opts) + strlen(org_options) + 9 + PATH_MAX);	if (!ret)		return NULL;		*ret = 0;	options = strdup(org_options);	if (!options) {		ntfs_log_perror("strdup failed");		return NULL;	}		/*	 * FIXME: Due to major performance hit and interference	 * issues, always use the 'noatime' options for now.	 */	ctx->noatime = TRUE;	strcat(ret, "noatime,");		s = options;	while ((val = strsep(&s, ","))) {		opt = strsep(&val, "=");		if (!strcmp(opt, "ro")) { /* Read-only mount. */			if (val) {				ntfs_log_error("'ro' option should not have "						"value.\n");				goto err_exit;			}			ctx->ro = TRUE;			strcat(ret, "ro,");		} else if (!strcmp(opt, "noatime")) {			if (val) {				ntfs_log_error("'noatime' option should not "						"have value.\n");				goto err_exit;			}		} else if (!strcmp(opt, "fake_rw")) {			if (val) {				ntfs_log_error("'fake_rw' option should not "						"have value.\n");				goto err_exit;			}			ctx->ro = TRUE;		} else if (!strcmp(opt, "fsname")) { /* Filesystem name. */			/*			 * We need this to be able to check whether filesystem			 * mounted or not.			 */			ntfs_log_error("'fsname' is unsupported option.\n");			goto err_exit;		} else if (!strcmp(opt, "no_def_opts")) {			if (val) {				ntfs_log_error("'no_def_opts' option should "						"not have value.\n");				goto err_exit;			}			no_def_opts = TRUE; /* Don't add default options. */		} else if (!strcmp(opt, "umask")) {			if (!val) {				ntfs_log_error("'umask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->fmask);			ctx->dmask = ctx->fmask;		} else if (!strcmp(opt, "fmask")) {			if (!val) {				ntfs_log_error("'fmask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->fmask);		} else if (!strcmp(opt, "dmask")) {			if (!val) {				ntfs_log_error("'dmask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->dmask);		} else if (!strcmp(opt, "uid")) {			if (!val) {				ntfs_log_error("'uid' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->uid);		} else if (!strcmp(opt, "gid")) {			if (!val) {				ntfs_log_error("'gid' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->gid);		} else if (!strcmp(opt, "show_sys_files")) {			if (val) {				ntfs_log_error("'show_sys_files' option should "						"not have value.\n");				goto err_exit;			}			ctx->show_sys_files = TRUE;		} else if (!strcmp(opt, "silent")) {			if (val) {				ntfs_log_error("'silent' option should "						"not have value.\n");				goto err_exit;			}			ctx->silent = TRUE;		} else if (!strcmp(opt, "force")) {			if (val) {				ntfs_log_error("'force' option should not "						"have value.\n");				goto err_exit;			}			ctx->force = TRUE;		} else if (!strcmp(opt, "locale")) {			if (!val) {				ntfs_log_error("'locale' option should have "						"value.\n");				goto err_exit;			}			if (!setlocale(LC_ALL, val))				ntfs_log_error("Couldn't set locale to %s thus "						"you may not see properly or "						"at all some files.\n", val);		} else if (!strcmp(opt, "streams_interface")) {			if (!val) {				ntfs_log_error("'streams_interface' option "						"should have value.\n");				goto err_exit;			}			if (!strcmp(val, "none"))				ctx->streams = NF_STREAMS_INTERFACE_NONE;			else if (!strcmp(val, "xattr"))				ctx->streams = NF_STREAMS_INTERFACE_XATTR;			else if (!strcmp(val, "windows"))				ctx->streams = NF_STREAMS_INTERFACE_WINDOWS;			else {				ntfs_log_error("Invalid named data streams "						"access interface.\n");				goto err_exit;			}		} else if (!strcmp(opt, "noauto")) {			/* Don't pass noauto option to fuse. */		} else if (!strcmp(opt, "debug")) {			if (val) {				ntfs_log_error("'debug' option should not have "						"value.\n");				goto err_exit;			}			ctx->debug = TRUE;			ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);			ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);		} else if (!strcmp(opt, "no_detach")) {			if (val) {				ntfs_log_error("'no_detach' option should not "						"have value.\n");				goto err_exit;			}			ctx->no_detach = TRUE;		} else if (!strcmp(opt, "remount")) {			ntfs_log_error("Remounting is not supported at present."					" You have to umount volume and then "					"mount it once again.\n");			goto err_exit;		} else { /* Probably FUSE option. */			strcat(ret, opt);			if (val) {				strcat(ret, "=");				strcat(ret, val);			}			strcat(ret, ",");		}	}	if (!no_def_opts)		strcat(ret, def_opts);	strcat(ret, "fsname=");	strcat(ret, opts.device);exit:	free(options);	return ret;err_exit:	free(ret);	ret = NULL;	goto exit;}static void usage(void){	ntfs_log_info("\n%s v%s - Third Generation NTFS Driver\n\n",			EXEC_NAME, VERSION);	ntfs_log_info("Copyright (C) 2005-2006 Yura Pakhuchiy\n");	ntfs_log_info("Copyright (C) 2006 Szabolcs Szakacsits\n\n");	ntfs_log_info("Usage:    %s device mount_point [-o options]\n\n", 		      EXEC_NAME);	ntfs_log_info("Options:  force, no_def_opts, umask, "		      "fmask, dmask, uid, gid, show_sys_files\n\t"		      "  silent, locale, streams_interface. "		      "See the details in the manual.\n\n");	ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);}#ifndef HAVE_REALPATH/* If there is no realpath() on the system, provide a dummy one. */static char *realpath(const char *path, char *resolved_path){	strncpy(resolved_path, path, PATH_MAX);	resolved_path[PATH_MAX] = '\0';	return resolved_path;}#endif/** * parse_options - Read and validate the programs command line * * Read the command line, verify the syntax and parse the options. * This function is very long, but quite simple. * * Return:  1 Success *	    0 Error, one or more problems */static int parse_options(int argc, char *argv[]){	int err = 0, help = 0;	int c = -1;	static const char *sopt = "-o:h?qv";	static const struct option lopt[] = {		{ "options",	 required_argument,	NULL, 'o' },		{ "help",	 no_argument,		NULL, 'h' },		{ "quiet",	 no_argument,		NULL, 'q' },		{ "verbose",	 no_argument,		NULL, 'v' },		{ NULL,		 0,			NULL,  0  }	};	opterr = 0; /* We'll handle the errors, thank you. */	opts.mnt_point = NULL;	opts.options = NULL;	opts.device = NULL;	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {		switch (c) {		case 1:	/* A non-option argument */			if (!opts.device) {				opts.device = ntfs_malloc(PATH_MAX + 1);				if (!opts.device) {					err++;					break;				}				/* We don't want relative path in /etc/mtab. */				if (argv[optind - 1][0] != '/') {					if (!realpath(argv[optind - 1],							opts.device)) {						ntfs_log_perror("realpath");						free(opts.device);						opts.device = NULL;						err++;						break;					}				} else					strcpy(opts.device, argv[optind - 1]);			} else if (!opts.mnt_point)				opts.mnt_point = argv[optind - 1];			else {				ntfs_log_error("You must specify exactly one "						"device and exactly one mount "						"point.\n");				err++;			}			break;		case 'o':			if (!opts.options)				opts.options = argv[optind - 1];			else {				ntfs_log_error("You must specify exactly one "						"set of options.\n");				err++;			}			break;		case 'h':		case '?':			help++;			break;		case 'q':			opts.quiet++;			break;		case 'v':			opts.verbose++;			break;		default:			ntfs_log_error("Unknown option '%s'.\n",					argv[optind - 1]);			err++;			break;		}	}	if (help) {		opts.quiet = 0;	} else {		if (!opts.device) {			ntfs_log_error("No device specified.\n");			err++;		}		if (opts.quiet && opts.verbose) {			ntfs_log_error("You may not use --quiet and --verbose "					"at the same time.\n");			err++;		}	}	if (help || err)		usage();	return (!help && !err);}int main(int argc, char *argv[]){	char *parsed_options;	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);	struct fuse *fh;	int ffd = 0;	utils_set_locale();	ntfs_log_set_handler(ntfs_log_handler_stderr);	signal(SIGINT, signal_handler);	signal(SIGTERM, signal_handler);	if (!parse_options(argc, argv))		return 1;	ntfs_fuse_init();	/* Parse options. */	parsed_options = parse_mount_options((opts.options) ?			opts.options : "");	if (!parsed_options) {		ntfs_fuse_destroy();		return 3;	}	/* Mount volume. */	if (ntfs_fuse_mount(opts.device)) {		ntfs_fuse_destroy();		return 4;	}	/* Libfuse can't always find fusermount, so let's help it. */	if (setenv("PATH", ":/bin:/usr/bin:/usr/local/bin", 0) == -1)		ntfs_log_perror("WARNING: Failed to set $PATH\n");	/* Create filesystem. */	if ((fuse_opt_add_arg(&margs, "") == -1 ||			fuse_opt_add_arg(&margs, "-o") == -1 ||			fuse_opt_add_arg(&margs, parsed_options) == -1))		ffd = -1;	if (ffd != -1)		ffd = fuse_mount(opts.mnt_point, &margs);	fuse_opt_free_args(&margs);	if (ffd == -1) {		ntfs_log_error("fuse_mount failed.\n");		ntfs_fuse_destroy();		return 5;	}	free(parsed_options);	fh = (struct fuse *)1; /* Cast anything except NULL to handle errors. */	margs = (struct fuse_args)FUSE_ARGS_INIT(0, NULL);	if (fuse_opt_add_arg(&margs, "") == -1 ||			fuse_opt_add_arg(&margs, "-o") == -1)		    fh = NULL;	if (!ctx->debug && !ctx->no_detach) {		if (fuse_opt_add_arg(&margs, "use_ino,kernel_cache") == -1)			fh = NULL;	} else {		if (fuse_opt_add_arg(&margs, "use_ino,debug") == -1)			fh = NULL;	}	if (fh)		fh = fuse_new(ffd, &margs , &ntfs_fuse_oper,				sizeof(ntfs_fuse_oper));	fuse_opt_free_args(&margs);	if (!fh) {		ntfs_log_error("fuse_new failed.\n");		close(ffd);		fuse_unmount(opts.mnt_point);		ntfs_fuse_destroy();		return 6;	}	if (!ctx->no_detach) {		if (daemon(0, ctx->debug))			ntfs_log_error("Failed to daemonize.\n");		else if (!ctx->debug) {#ifndef DEBUG			ntfs_log_set_handler(ntfs_log_handler_syslog);			/* Override default libntfs identify. */			openlog(EXEC_NAME, LOG_PID, LOG_DAEMON);#endif		}	}	ntfs_log_info("Version %s\n", VERSION);	ntfs_log_info("Mounted %s (%s, label \"%s\", NTFS %d.%d)\n",			opts.device, (ctx->ro) ? "Read-Only" : "Read-Write",			ctx->vol->vol_name, ctx->vol->major_ver,			ctx->vol->minor_ver);	/* Main loop. */	fuse_loop(fh);	/* Destroy. */	fuse_destroy(fh);	close(ffd);	fuse_unmount(opts.mnt_point);	ntfs_fuse_destroy();	return 0;}

⌨️ 快捷键说明

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