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

📄 ntfs-3g.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
{	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;		}				if (ntfs_inode_close(ni)) {			set_fuse_error(&ret);			goto out;		}				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. */	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. */	return ntfs_fuse_rm(path);}static int ntfs_fuse_utime(const char *path, struct utimbuf *buf){	ntfs_inode *ni;	int res = 0;	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;		ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);	} else		ntfs_inode_update_times(ni, NTFS_UPDATE_AMCTIME);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	return res;}static int ntfs_fuse_bmap(const char *path, size_t blocksize, uint64_t *idx){	ntfs_inode *ni;	ntfs_attr *na;	LCN lcn;	int ret = 0; 	int 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;	close_attr:	ntfs_attr_close(na);close_inode:	if (ntfs_inode_close(ni))		set_fuse_error(&ret);	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);	if (ntfs_inode_close(ni))		set_fuse_error(&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 = '\0';					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);	if (ntfs_inode_close(ni))		set_fuse_error(&ret);	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);	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))		set_fuse_error(&res);	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);	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;	}	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))		set_fuse_error(&res);	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);	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;	}	exit:	free(lename);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	return res;}#endif /* HAVE_SETXATTR */static void ntfs_close(void){	if (!ctx)		return;		if (!ctx->vol)		return;		if (ctx->mounted)		ntfs_log_info("Unmounting %s (%s)\n", opts.device, 			      ctx->vol->vol_name);		if (ntfs_umount(ctx->vol, FALSE))		ntfs_log_perror("Failed to close volume %s", opts.device);		ctx->vol = NULL;}static void ntfs_fuse_destroy2(void *unused __attribute__((unused))){	ntfs_close();}static struct fuse_operations ntfs_3g_ops = {	.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,	.create		= ntfs_fuse_create_file,	.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_calloc(sizeof(ntfs_fuse_context_t));	if (!ctx)		return -1;		*ctx = (ntfs_fuse_context_t) {		.uid = getuid(),		.gid = getgid(),		.streams = NF_STREAMS_INTERFACE_NONE,	};	return 0;}static int ntfs_open(const char *device){	unsigned long flags = 0;		if (!ctx->blkdev)		flags |= MS_EXCLUSIVE;	if (ctx->ro)		flags |= MS_RDONLY;	if (ctx->force)		flags |= MS_FORCE;	if (ctx->hiberfile)		flags |= MS_IGNORE_HIBERFILE;	ctx->vol = ntfs_mount(device, flags);	if (!ctx->vol) {		ntfs_log_perror("Failed to mount '%s'", device);		goto err_out;	}		ctx->vol->free_clusters = ntfs_attr_get_free_bits(ctx->vol->lcnbmp_na);	if (ctx->vol->free_clusters < 0) {		ntfs_log_perror("Failed to read NTFS $Bitmap");		goto err_out;	}	ctx->vol->free_mft_records = ntfs_get_nr_free_mft_records(ctx->vol);	if (ctx->vol->free_mft_records < 0) {		ntfs_log_perror("Failed to calculate free MFT records");		goto err_out;	}	if (ctx->hiberfile && ntfs_volume_check_hiberfile(ctx->vol, 0)) {		if (errno != EPERM)			goto err_out;		if (ntfs_fuse_rm("/hiberfil.sys"))			goto err_out;	}		errno = 0;err_out:	return ntfs_volume_error(errno);	}#define STRAPPEND_MAX_INSIZE   8192#define strappend_is_large(x) ((x) > STRAPPEND_MAX_INSIZE)static int strappend(char **dest, const char *append){	char *p;	size_t size_append, size_dest = 0;		if (!dest)		return -1;	if (!append)		return 0;	size_append = strlen(append);	if (*dest)		size_dest = strlen(*dest);		if (strappend_is_large(size_dest) || strappend_is_large(size_append)) {		errno = EOVERFLOW;		ntfs_log_perror("%s: Too large input buffer", EXEC_NAME);		return -1;	}		p = realloc(*dest, size_dest + size_append + 1);    	if (!p) {		ntfs_log_perror("%s: Memory realloction failed", EXEC_NAME);		return -1;	}		*dest = p;	strcpy(*dest + size_dest, append);		return 0;}static int bogus_option_value(char *val, const char *s){	if (val) {		ntfs_log_error("'%s' option shouldn't have value.\n", s);		return -1;	}	return 0;}static int missing_option_value(char *val, const char *s){	if (!val) {		ntfs_log_error("'%s' option should have a value.\n", s);		return -1;	}	return 0;}static char *parse_mount_options(const char *orig_opts){	char *options, *s, *opt, *val, *ret = NULL;	BOOL no_def_opts = FALSE;	int default_permissions = 0;	options = strdup(orig_opts ? orig_opts : "");	if (!options) {		ntfs_log_perror("%s: strdup failed", EXEC_NAME);

⌨️ 快捷键说明

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