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

📄 ntfs-3g.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 4 页
字号:
	*ret = 0;	options = strdup(orig_opts);	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,");		ctx->silent = TRUE;		s = options;	while (s && *s && (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, "default_permissions")) {			default_permissions = 1;		} else if (!strcmp(opt, "umask")) {			if (!val) {				ntfs_log_error("'umask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%o", &ctx->fmask);			ctx->dmask = ctx->fmask;		       	default_permissions = 1;		} else if (!strcmp(opt, "fmask")) {			if (!val) {				ntfs_log_error("'fmask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%o", &ctx->fmask);		       	default_permissions = 1;		} else if (!strcmp(opt, "dmask")) {			if (!val) {				ntfs_log_error("'dmask' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%o", &ctx->dmask);		       	default_permissions = 1;		} else if (!strcmp(opt, "uid")) {			if (!val) {				ntfs_log_error("'uid' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->uid);		       	default_permissions = 1;		} else if (!strcmp(opt, "gid")) {			if (!val) {				ntfs_log_error("'gid' option should have "						"value.\n");				goto err_exit;			}			sscanf(val, "%i", &ctx->gid);		       	default_permissions = 1;		} 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(locale_msg, 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 if (!strcmp(opt, "blksize")) {			ntfs_log_info("WARNING: blksize option is ignored "				      "because ntfs-3g must calculate it.\n");		} else { /* Probably FUSE option. */			strcat(ret, opt);			if (val) {				strcat(ret, "=");				strcat(ret, val);			}			strcat(ret, ",");		}	}	if (!no_def_opts)		strcat(ret, def_opts);	if (default_permissions)		strcat(ret, "default_permissions,");	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 %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-2007 Szabolcs Szakacsits\n\n");	ntfs_log_info("Usage:    %s device mount_point [-o options]\n\n", 		      EXEC_NAME);	ntfs_log_info("Options:  ro, force, locale, uid, gid, umask, fmask, "		      "dmask, \n\t"		      "  show_sys_files, no_def_opts, streams_interface.\n\t"		      "  Please see the details in the manual.\n\n");	ntfs_log_info("%s\n", 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 (optarg[0] != '/') {					if (!realpath(optarg, opts.device)) {						ntfs_log_perror("Cannot mount "								"'%s'", optarg);						free(opts.device);						opts.device = NULL;						err++;						break;					}				} else					strcpy(opts.device, optarg);			} else if (!opts.mnt_point)				opts.mnt_point = optarg;			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 = optarg;			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);}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 void create_dev_fuse(void){	struct stat st;		if (stat("/dev/fuse", &st) && (errno == ENOENT)) {		if (mknod("/dev/fuse", S_IFCHR | 0666, makedev(10, 229)))			ntfs_log_perror("Failed to create /dev/fuse");	}}static fuse_fstype load_fuse_module(void){	int i;	struct stat st;	const char *load_fuse_cmd = "/sbin/modprobe fuse";	struct timespec req = { 0, 100000000 };   /* 100 msec */	fuse_fstype fstype;		if (stat("/sbin/modprobe", &st) == -1)		load_fuse_cmd = "modprobe fuse";		if (getuid() == 0)		system(load_fuse_cmd);		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;}static 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, "") == -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);	if (!fc)		ntfs_log_error("FUSE mount point creation failed\n");free_args:	fuse_opt_free_args(&margs);	return fc;		}		static void 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;		/* parsed_options already allocated enough space. */	snprintf(options, sizeof(options), ",blkdev,blksize=%u", blksize);	strcat(parsed_options, options);}int main(int argc, char *argv[]){	char *parsed_options = NULL;	struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);	struct fuse *fh;	struct fuse_chan *fc;	fuse_fstype fstype;	struct stat sbuf;	int use_blkdev = 0;	uid_t uid, euid;	int err = 10;	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;	if (ntfs_fuse_init())		return 2;		parsed_options = parse_mount_options(opts.options ? opts.options : "");	if (!parsed_options)		goto err_out;	uid  = getuid();	euid = geteuid();		if (setuid(euid)) {		ntfs_log_perror("Failed to set user ID to %d", euid);		goto err_out;	}	fstype = get_fuse_fstype();	if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)		fstype = load_fuse_module();		create_dev_fuse();		if (stat(opts.device, &sbuf)) {		ntfs_log_perror("Failed to access '%s'", opts.device);		goto err_out;	}	/* Always use fuseblk for block devices unless it's surely missing. */	if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))		use_blkdev = 1;	if (!ntfs_open(opts.device, opts.mnt_point, use_blkdev))		goto err_out;		if (use_blkdev)	    set_fuseblk_options(parsed_options);		/* Libfuse can't always find fusermount, so let's help it. */	if (setenv("PATH", ":/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin", 0))		ntfs_log_perror("WARNING: Failed to set $PATH\n");		fc = try_fuse_mount(parsed_options);	if (!fc)		goto err_out;		fh = (struct fuse *)1; /* Cast anything except NULL to handle errors. */	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(fc, &margs , &ntfs_fuse_oper,				sizeof(ntfs_fuse_oper), NULL);	fuse_opt_free_args(&margs);	if (!fh) {		ntfs_log_error("fuse_new failed.\n");		fuse_unmount(opts.mnt_point, fc);		goto err_out;	}		if (setuid(uid)) {		ntfs_log_perror("Failed to set user ID to %d", uid);		fuse_unmount(opts.mnt_point, fc);		goto err_out;	}	if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))		ntfs_log_info(fuse26_kmod_msg);		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);	ntfs_log_info("Options: %s\n", parsed_options);		fuse_loop(fh);		fuse_unmount(opts.mnt_point, fc);	fuse_destroy(fh);	err = 0;err_out:	free(parsed_options);	ntfs_fuse_destroy();	return err;}

⌨️ 快捷键说明

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