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

📄 ntfs-3g.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 4 页
字号:
	return 	ret;}static int ntfs_fuse_rename_existing_dest(const char *old_path, const char *new_path){	int ret, len;	char *tmp;	const char *ext = ".ntfs-3g-";	ntfs_log_trace("Entering");		len = strlen(new_path) + strlen(ext) + 10 + 1; /* wc(str(2^32)) + \0 */	tmp = ntfs_malloc(len);	if (!tmp)		return -errno;		ret = snprintf(tmp, len, "%s%s%010d", new_path, ext, ++ntfs_sequence);	if (ret != len - 1) {		ntfs_log_error("snprintf failed: %d != %d\n", ret, len - 1);		ret = -EOVERFLOW;	} else		ret = ntfs_fuse_safe_rename(old_path, new_path, tmp);		free(tmp);	return 	ret;}static int ntfs_fuse_rename(const char *old_path, const char *new_path){	int ret, stream_name_len;	char *path = NULL;	ntfschar *stream_name;	ntfs_inode *ni;		ntfs_log_debug("rename: old: '%s'  new: '%s'\n", old_path, new_path);		/*	 *  FIXME: Rename should be atomic.	 */	stream_name_len = ntfs_fuse_parse_path(new_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;		ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (ni) {		ret = ntfs_check_empty_dir(ni);		if (ret < 0) {			ret = -errno;			ntfs_inode_close(ni);			goto out;		}				ntfs_inode_close(ni);				ret = ntfs_fuse_rename_existing_dest(old_path, new_path);		goto out;	}	ret = ntfs_fuse_link(old_path, new_path);	if (ret)		goto out;		ret = ntfs_fuse_unlink(old_path);	if (ret)		ntfs_fuse_unlink(new_path);out:	free(path);	if (stream_name_len)		free(stream_name);	return ret;}static int ntfs_fuse_mkdir(const char *path,		mode_t mode __attribute__((unused))){	if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL; /* n/a for named data streams. */	ntfs_fuse_mark_free_space_outdated();	return ntfs_fuse_create(path, S_IFDIR, 0, NULL);}static int ntfs_fuse_rmdir(const char *path){	if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL; /* n/a for named data streams. */	ntfs_fuse_mark_free_space_outdated();	return ntfs_fuse_rm(path);}static int ntfs_fuse_utime(const char *path, struct utimbuf *buf){	ntfs_inode *ni;	if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL; /* n/a for named data streams. */	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni)		return -errno;	if (buf) {		ni->last_access_time = buf->actime;		ni->last_data_change_time = buf->modtime;		ni->last_mft_change_time = buf->modtime;	} else {		time_t now;		now = time(NULL);		ni->last_access_time = now;		ni->last_data_change_time = now;		ni->last_mft_change_time = now;	}	NInoFileNameSetDirty(ni);	NInoSetDirty(ni);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return 0;}static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx){	ntfs_inode *ni;	ntfs_attr *na;	LCN lcn;	int ret, cl_per_bl = ctx->vol->cluster_size / blocksize;	if (blocksize > ctx->vol->cluster_size)		return -EINVAL;		if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL;		ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni)		return -errno;	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);	if (!na) {		ret = -errno;		goto close_inode;	}		if (NAttrCompressed(na) || NAttrEncrypted(na) || !NAttrNonResident(na)){		ret = -EINVAL;		goto close_attr;	}		if (ntfs_attr_map_whole_runlist(na)) {		ret = -errno;		goto close_attr;	}		lcn = ntfs_rl_vcn_to_lcn(na->rl, *idx / cl_per_bl);	*idx = (lcn > 0) ? lcn * cl_per_bl + *idx % cl_per_bl : 0;		ret = 0;	close_attr:	ntfs_attr_close(na);close_inode:	if (ntfs_inode_close(ni))		ntfs_log_perror("bmap: failed to close inode");	return ret;}#ifdef HAVE_SETXATTRstatic const char nf_ns_xattr_preffix[] = "user.";static const int nf_ns_xattr_preffix_len = 5;static int ntfs_fuse_listxattr(const char *path, char *list, size_t size){	ntfs_attr_search_ctx *actx = NULL;	ntfs_volume *vol;	ntfs_inode *ni;	char *to = list;	int ret = 0;	if (ctx->streams != NF_STREAMS_INTERFACE_XATTR)		return -EOPNOTSUPP;	vol = ctx->vol;	if (!vol)		return -ENODEV;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni)		return -errno;	actx = ntfs_attr_get_search_ctx(ni, NULL);	if (!actx) {		ret = -errno;		ntfs_inode_close(ni);		goto exit;	}	while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,				0, NULL, 0, actx)) {		char *tmp_name = NULL;		int tmp_name_len;		if (!actx->attr->name_length)			continue;		tmp_name_len = ntfs_ucstombs((ntfschar *)((u8*)actx->attr +				le16_to_cpu(actx->attr->name_offset)),				actx->attr->name_length, &tmp_name, 0);		if (tmp_name_len < 0) {			ret = -errno;			goto exit;		}		ret += tmp_name_len + nf_ns_xattr_preffix_len + 1;		if (size) {			if ((size_t)ret <= size) {				strcpy(to, nf_ns_xattr_preffix);				to += nf_ns_xattr_preffix_len;				strncpy(to, tmp_name, tmp_name_len);				to += tmp_name_len;				*to = 0;				to++;			} else {				free(tmp_name);				ret = -ERANGE;				goto exit;			}		}		free(tmp_name);	}	if (errno != ENOENT)		ret = -errno;exit:	if (actx)		ntfs_attr_put_search_ctx(actx);	ntfs_inode_close(ni);	ntfs_log_debug("return %d\n", ret);	return ret;}static int ntfs_fuse_getxattr_windows(const char *path, const char *name,				char *value, size_t size){	ntfs_attr_search_ctx *actx = NULL;	ntfs_volume *vol;	ntfs_inode *ni;	char *to = value;	int ret = 0;	if (strcmp(name, "ntfs.streams.list"))		return -EOPNOTSUPP;	vol = ctx->vol;	if (!vol)		return -ENODEV;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni)		return -errno;	actx = ntfs_attr_get_search_ctx(ni, NULL);	if (!actx) {		ret = -errno;		ntfs_inode_close(ni);		goto exit;	}	while (!ntfs_attr_lookup(AT_DATA, NULL, 0, CASE_SENSITIVE,				0, NULL, 0, actx)) {		char *tmp_name = NULL;		int tmp_name_len;		if (!actx->attr->name_length)			continue;		tmp_name_len = ntfs_ucstombs((ntfschar *)((u8*)actx->attr +				le16_to_cpu(actx->attr->name_offset)),				actx->attr->name_length, &tmp_name, 0);		if (tmp_name_len < 0) {			ret = -errno;			goto exit;		}		if (ret)			ret++; /* For space delimiter. */		ret += tmp_name_len;		if (size) {			if ((size_t)ret <= size) {				/* Don't add space to the beginning of line. */				if (to != value) {					*to = ' ';					to++;				}				strncpy(to, tmp_name, tmp_name_len);				to += tmp_name_len;			} else {				free(tmp_name);				ret = -ERANGE;				goto exit;			}		}		free(tmp_name);	}	if (errno != ENOENT)		ret = -errno;exit:	if (actx)		ntfs_attr_put_search_ctx(actx);	ntfs_inode_close(ni);	return ret;}static int ntfs_fuse_getxattr(const char *path, const char *name,				char *value, size_t size){	ntfs_volume *vol;	ntfs_inode *ni;	ntfs_attr *na = NULL;	ntfschar *lename = NULL;	int res, lename_len;	if (ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)		return ntfs_fuse_getxattr_windows(path, name, value, size);	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;	}	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;	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;	}	if (ntfs_attr_remove(ni, AT_DATA, lename, lename_len)) {		if (errno == ENOENT)			errno = ENODATA;		res = -errno;	}		ntfs_fuse_mark_free_space_outdated();exit:	free(lename);	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}#endif /* HAVE_SETXATTR */static void ntfs_fuse_destroy(void){	if (!ctx)		return;		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);	ctx = NULL;	free(opts.device);}static void ntfs_fuse_destroy2(void *unused __attribute__((unused))){	ntfs_fuse_destroy();}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,	.bmap		= ntfs_fuse_bmap,	.destroy        = ntfs_fuse_destroy2,#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 = 0,		.dmask = 0,		.streams = NF_STREAMS_INTERFACE_NONE,	};	return 0;}static ntfs_volume *ntfs_open(const char *device, char *mntpoint, int blkdev){	unsigned long flags = 0;		if (!blkdev)		flags |= MS_EXCLUSIVE;	if (ctx->ro)		flags |= MS_RDONLY;	if (ctx->noatime)		flags |= MS_NOATIME;	ctx->vol = utils_mount_volume(device, mntpoint, flags, ctx->force);	return ctx->vol;}static void signal_handler(int arg __attribute__((unused))){	fuse_exit((fuse_get_context())->fuse);}static char *parse_mount_options(const char *orig_opts){	char *options, *s, *opt, *val, *ret;	BOOL no_def_opts = FALSE;	int default_permissions = 0;	/*	 * +7		fsname=	 * +1		comma	 * +1		null-terminator	 * +21          ,blkdev,blksize=65536	 * +20          ,default_permissions	 * +PATH_MAX	resolved realpath() device name	 */	ret = ntfs_malloc(strlen(def_opts) + strlen(orig_opts) + 64 + PATH_MAX);	if (!ret)		return NULL;	

⌨️ 快捷键说明

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