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

📄 ntfs-3g.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
		return NULL;	}		ctx->silent = TRUE;	ctx->atime  = ATIME_RELATIVE;		s = options;	while (s && *s && (val = strsep(&s, ","))) {		opt = strsep(&val, "=");		if (!strcmp(opt, "ro")) { /* Read-only mount. */			if (bogus_option_value(val, "ro"))				goto err_exit;			ctx->ro = TRUE;			if (strappend(&ret, "ro,"))				goto err_exit;		} else if (!strcmp(opt, "noatime")) {			if (bogus_option_value(val, "noatime"))				goto err_exit;			ctx->atime = ATIME_DISABLED;		} else if (!strcmp(opt, "atime")) {			if (bogus_option_value(val, "atime"))				goto err_exit;			ctx->atime = ATIME_ENABLED;		} else if (!strcmp(opt, "relatime")) {			if (bogus_option_value(val, "relatime"))				goto err_exit;			ctx->atime = ATIME_RELATIVE;		} else if (!strcmp(opt, "fake_rw")) {			if (bogus_option_value(val, "fake_rw"))				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 (bogus_option_value(val, "no_def_opts"))				goto err_exit;			no_def_opts = TRUE; /* Don't add default options. */		} else if (!strcmp(opt, "default_permissions")) {			default_permissions = 1;		} else if (!strcmp(opt, "umask")) {			if (missing_option_value(val, "umask"))				goto err_exit;			sscanf(val, "%o", &ctx->fmask);			ctx->dmask = ctx->fmask;			if (ctx->fmask)				default_permissions = 1;		} else if (!strcmp(opt, "fmask")) {			if (missing_option_value(val, "fmask"))				goto err_exit;			sscanf(val, "%o", &ctx->fmask);			if (ctx->fmask)				default_permissions = 1;		} else if (!strcmp(opt, "dmask")) {			if (missing_option_value(val, "dmask"))				goto err_exit;			sscanf(val, "%o", &ctx->dmask);			if (ctx->dmask)				default_permissions = 1;		} else if (!strcmp(opt, "uid")) {			if (missing_option_value(val, "uid"))				goto err_exit;			sscanf(val, "%i", &ctx->uid);		       	default_permissions = 1;		} else if (!strcmp(opt, "gid")) {			if (missing_option_value(val, "gid"))				goto err_exit;			sscanf(val, "%i", &ctx->gid);		       	default_permissions = 1;		} else if (!strcmp(opt, "show_sys_files")) {			if (bogus_option_value(val, "show_sys_files"))				goto err_exit;			ctx->show_sys_files = TRUE;		} else if (!strcmp(opt, "silent")) {			if (bogus_option_value(val, "silent"))				goto err_exit;			ctx->silent = TRUE;		} else if (!strcmp(opt, "force")) {			if (bogus_option_value(val, "force"))				goto err_exit;			ctx->force = TRUE;		} else if (!strcmp(opt, "remove_hiberfile")) {			if (bogus_option_value(val, "remove_hiberfile"))				goto err_exit;			ctx->hiberfile = TRUE;		} else if (!strcmp(opt, "locale")) {			if (missing_option_value(val, "locale"))				goto err_exit;			if (!setlocale(LC_ALL, val))				ntfs_log_error(locale_msg, val);		} else if (!strcmp(opt, "streams_interface")) {			if (missing_option_value(val, "streams_interface"))				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 (bogus_option_value(val, "debug"))				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 (bogus_option_value(val, "no_detach"))				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 if (!strcmp(opt, "blksize")) {			ntfs_log_info("WARNING: blksize option is ignored "				      "because ntfs-3g must calculate it.\n");		} else { /* Probably FUSE option. */			if (strappend(&ret, opt))				goto err_exit;			if (val) {				if (strappend(&ret, "="))					goto err_exit;				if (strappend(&ret, val))					goto err_exit;			}			if (strappend(&ret, ","))				goto err_exit;		}	}	if (!no_def_opts && strappend(&ret, def_opts))		goto err_exit;	if (default_permissions && strappend(&ret, "default_permissions,"))		goto err_exit;		if (ctx->atime == ATIME_RELATIVE && strappend(&ret, "relatime,"))		goto err_exit;	else if (ctx->atime == ATIME_ENABLED && strappend(&ret, "atime,"))		goto err_exit;	else if (ctx->atime == ATIME_DISABLED && strappend(&ret, "noatime,"))		goto err_exit;		if (strappend(&ret, "fsname="))		goto err_exit;	if (strappend(&ret, opts.device))		goto err_exit;exit:	free(options);	return ret;err_exit:	free(ret);	ret = NULL;	goto exit;}static void usage(void){	ntfs_log_info(usage_msg, EXEC_NAME, VERSION, FUSE_TYPE, fuse_version(),		      EXEC_NAME, 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. * * Return:   0 success, -1 error. */static int parse_options(int argc, char *argv[]){	int c;	static const char *sopt = "-o:hv";	static const struct option lopt[] = {		{ "options",	 required_argument,	NULL, 'o' },		{ "help",	 no_argument,		NULL, 'h' },		{ "verbose",	 no_argument,		NULL, 'v' },		{ NULL,		 0,			NULL,  0  }	};	opterr = 0; /* We'll handle the errors, thank you. */	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)					return -1;								/* Canonicalize device name (mtab, etc) */				if (!realpath(optarg, opts.device)) {					ntfs_log_perror("%s: Failed to access "					     "volume '%s'", EXEC_NAME, optarg);					free(opts.device);					opts.device = NULL;					return -1;				}			} else if (!opts.mnt_point) {				opts.mnt_point = optarg;			} else {				ntfs_log_error("%s: You must specify exactly one "						"device and exactly one mount "						"point.\n", EXEC_NAME);				return -1;			}			break;		case 'o':			if (opts.options)				if (strappend(&opts.options, ","))					return -1;			if (strappend(&opts.options, optarg))				return -1;			break;		case 'h':			usage();			exit(9);		case 'v':			/*			 * We must handle the 'verbose' option even if			 * we don't use it because mount(8) passes it.			 */			break;		default:			ntfs_log_error("%s: Unknown option '%s'.\n", EXEC_NAME,				       argv[optind - 1]);			return -1;		}	}	if (!opts.device) {		ntfs_log_error("%s: No device is specified.\n", EXEC_NAME);		return -1;	}	if (!opts.mnt_point) {		ntfs_log_error("%s: No mountpoint is specified.\n", EXEC_NAME);		return -1;	}	return 0;}#if defined(linux) || defined(__uClinux__)static const char *dev_fuse_msg ="HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n""      kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'""      or insmod <path_to>/fuse.o'). Make also sure that the fuse device""      exists. It's usually either /dev/fuse or /dev/misc/fuse.";static const char *fuse26_kmod_msg ="WARNING: Deficient Linux kernel detected. Some driver features are\n""         not available (swap file on NTFS, boot from NTFS by LILO), and\n""         unmount is not safe unless it's made sure the ntfs-3g process\n""         naturally terminates after calling 'umount'. If you wish this\n""         message to disappear then you should upgrade to at least kernel\n""         version 2.6.20, or request help from your distribution to fix\n""         the kernel problem. The below web page has more information:\n""         http://ntfs-3g.org/support.html#fuse26\n""\n";static void mknod_dev_fuse(const char *dev){	struct stat st;		if (stat(dev, &st) && (errno == ENOENT)) {		mode_t mask = umask(0); 		if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {			ntfs_log_perror("Failed to create '%s'", dev);			if (errno == EPERM)				ntfs_log_error(dev_fuse_msg);		}		umask(mask);	}}static void create_dev_fuse(void){	mknod_dev_fuse("/dev/fuse");#ifdef __UCLIBC__	{		struct stat st;		/* The fuse device is under /dev/misc using devfs. */		if (stat("/dev/misc", &st) && (errno == ENOENT)) {			mode_t mask = umask(0); 			mkdir("/dev/misc", 0775);			umask(mask);		}		mknod_dev_fuse("/dev/misc/fuse");	}#endif}static fuse_fstype get_fuse_fstype(void){	char buf[256];	fuse_fstype fstype = FSTYPE_NONE;		FILE *f = fopen("/proc/filesystems", "r");	if (!f) {		ntfs_log_perror("Failed to open /proc/filesystems");		return FSTYPE_UNKNOWN;	}		while (fgets(buf, sizeof(buf), f)) {		if (strstr(buf, "fuseblk\n")) {			fstype = FSTYPE_FUSEBLK;			break;		}		if (strstr(buf, "fuse\n"))			fstype = FSTYPE_FUSE;	}		fclose(f);	return fstype;}static fuse_fstype load_fuse_module(void){	int i;	struct stat st;	pid_t pid;	const char *cmd = "/sbin/modprobe";	struct timespec req = { 0, 100000000 };   /* 100 msec */	fuse_fstype fstype;		if (!stat(cmd, &st) && !geteuid()) {		pid = fork();		if (!pid) {			execl(cmd, cmd, "fuse", NULL);			_exit(1);		} else if (pid != -1)			waitpid(pid, NULL, 0);	}		for (i = 0; i < 10; i++) {		/* 		 * We sleep first because despite the detection of the loaded		 * FUSE kernel module, fuse_mount() can still fail if it's not 		 * fully functional/initialized. Note, of course this is still		 * unreliable but usually helps.		 */  		nanosleep(&req, NULL);		fstype = get_fuse_fstype();		if (fstype != FSTYPE_NONE)			break;	}	return fstype;}#endifstatic struct fuse_chan *try_fuse_mount(char *parsed_options){	struct fuse_chan *fc = NULL;	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);		/* The fuse_mount() options get modified, so we always rebuild it */	if ((fuse_opt_add_arg(&margs, EXEC_NAME) == -1 ||	     fuse_opt_add_arg(&margs, "-o") == -1 ||	     fuse_opt_add_arg(&margs, parsed_options) == -1)) {		ntfs_log_error("Failed to set FUSE options.\n");		goto free_args;	}		fc = fuse_mount(opts.mnt_point, &margs);free_args:	fuse_opt_free_args(&margs);	return fc;		}		static int set_fuseblk_options(char **parsed_options){	char options[64];	long pagesize; 	u32 blksize = ctx->vol->cluster_size;		pagesize = sysconf(_SC_PAGESIZE);	if (pagesize < 1)		pagesize = 4096;		if (blksize > (u32)pagesize)		blksize = pagesize;		snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);	if (strappend(parsed_options, options))		return -1;	return 0;}static struct fuse *mount_fuse(char *parsed_options){	struct fuse *fh = NULL;	struct fuse_args args = FUSE_ARGS_INIT(0, NULL);		ctx->fc = try_fuse_mount(parsed_options);	if (!ctx->fc)		return NULL;		if (fuse_opt_add_arg(&args, "") == -1)		goto err;	if (fuse_opt_add_arg(&args, "-ouse_ino,kernel_cache,attr_timeout=0") == -1)		goto err;	if (ctx->debug)		if (fuse_opt_add_arg(&args, "-odebug") == -1)			goto err;		fh = fuse_new(ctx->fc, &args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);	if (!fh)		goto err;		if (fuse_set_signal_handlers(fuse_get_session(fh)))		goto err_destory;out:	fuse_opt_free_args(&args);	return fh;err_destory:	fuse_destroy(fh);	fh = NULL;err:		fuse_unmount(opts.mnt_point, ctx->fc);	goto out;}static void setup_logging(char *parsed_options){	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 %s %d\n", VERSION, FUSE_TYPE, fuse_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);	ntfs_log_info("Cmdline options: %s\n", opts.options);	ntfs_log_info("Mount options: %s\n", parsed_options);}int main(int argc, char *argv[]){	char *parsed_options = NULL;	struct fuse *fh;	fuse_fstype fstype = FSTYPE_UNKNOWN;	struct stat sbuf;	int err, fd;	/*	 * Make sure file descriptors 0, 1 and 2 are open, 	 * otherwise chaos would ensue.	 */	do {		fd = open("/dev/null", O_RDWR);		if (fd > 2)			close(fd);	} while (fd >= 0 && fd <= 2);#ifndef FUSE_INTERNAL	if ((getuid() != geteuid()) || (getgid() != getegid())) {		fprintf(stderr, "%s", setuid_msg);		return NTFS_VOLUME_INSECURE;	}#endif	if (drop_privs())		return NTFS_VOLUME_NO_PRIVILEGE;		utils_set_locale();	ntfs_log_set_handler(ntfs_log_handler_stderr);	if (parse_options(argc, argv)) {		ntfs_log_error("Please type '%s --help' for more "			       "information.\n", argv[0]);		return NTFS_VOLUME_SYNTAX_ERROR;	}	if (ntfs_fuse_init()) {		err = NTFS_VOLUME_OUT_OF_MEMORY;		goto err2;	}		parsed_options = parse_mount_options(opts.options);	if (!parsed_options) {		err = NTFS_VOLUME_SYNTAX_ERROR;		goto err_out;	}	#if defined(linux) || defined(__uClinux__)	fstype = get_fuse_fstype();	err = NTFS_VOLUME_NO_PRIVILEGE;	if (restore_privs())		goto err_out;	if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)		fstype = load_fuse_module();		create_dev_fuse();	if (drop_privs())		goto err_out;#endif			if (stat(opts.device, &sbuf)) {		ntfs_log_perror("Failed to access '%s'", opts.device);		err = NTFS_VOLUME_NO_PRIVILEGE;		goto err_out;	}	/* Always use fuseblk for block devices unless it's surely missing. */	if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))		ctx->blkdev = TRUE;#ifndef FUSE_INTERNAL	if (getuid() && ctx->blkdev) {		ntfs_log_error("%s", unpriv_fuseblk_msg);		goto err2;	}#endif	err = ntfs_open(opts.device);	if (err)		goto err_out;		/* We must do this after ntfs_open() to be able to set the blksize */	if (ctx->blkdev && set_fuseblk_options(&parsed_options))		goto err_out;		fh = mount_fuse(parsed_options);	if (!fh) {		err = NTFS_VOLUME_FUSE_ERROR;		goto err_out;	}		ctx->mounted = TRUE;#if defined(linux) || defined(__uClinux__)	if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))		ntfs_log_info(fuse26_kmod_msg);#endif		setup_logging(parsed_options);		fuse_loop(fh);		err = 0;	fuse_unmount(opts.mnt_point, ctx->fc);	fuse_destroy(fh);err_out:	utils_mount_error(opts.device, opts.mnt_point, err);err2:	ntfs_close();	free(ctx);	free(parsed_options);	free(opts.options);	free(opts.device);	return err;}

⌨️ 快捷键说明

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