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

📄 ntfs-3g.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
			ntfs_log_error("ntfs_attr_pread returned less bytes "					"than requested.\n");		if (res <= 0) {			res = -errno;			goto exit;		}		size -= res;		offset += res;		total += res;	}	res = total;exit:	if (na)		ntfs_attr_close(na);	if (ni && ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size,		off_t offset, struct fuse_file_info *fi __attribute__((unused))){	ntfs_volume *vol;	ntfs_inode *ni = NULL;	ntfs_attr *na = NULL;	char *path = NULL;	ntfschar *stream_name;	int stream_name_len, res, total = 0;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	vol = ctx->vol;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni) {		res = -errno;		goto exit;	}	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);	if (!na) {		res = -errno;		goto exit;	}	while (size) {		res = ntfs_attr_pwrite(na, offset, size, buf);		if (res < (s64)size)			ntfs_log_error("ntfs_attr_pwrite returned less bytes "					"than requested.\n");		if (res <= 0) {			res = -errno;			goto exit;		}		size -= res;		offset += res;		total += res;	}	res = total;exit:	ntfs_fuse_mark_free_space_outdated();	if (na)		ntfs_attr_close(na);	if (ni && ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_truncate(const char *org_path, off_t size){	ntfs_volume *vol;	ntfs_inode *ni = NULL;	ntfs_attr *na;	int res;	char *path = NULL;	ntfschar *stream_name;	int stream_name_len;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	vol = ctx->vol;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni) {		res = -errno;		goto exit;	}	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);	if (!na) {		res = -errno;		goto exit;	}	res = ntfs_attr_truncate(na, size);	// FIXME: check the usage and the importance of the return value	if (res)		res = -1;	ntfs_fuse_mark_free_space_outdated();	ntfs_attr_close(na);exit:	if (ni && ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_chmod(const char *path,		mode_t mode __attribute__((unused))){	if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL; /* n/a for named data streams. */	if (ctx->silent)		return 0;	return -EOPNOTSUPP;}static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid){	if (ntfs_fuse_is_named_data_stream(path))		return -EINVAL; /* n/a for named data streams. */	if (ctx->silent)		return 0;	if (uid == ctx->uid && gid == ctx->gid)		return 0;	return -EOPNOTSUPP;}static int ntfs_fuse_create(const char *org_path, dev_t type, dev_t dev,		const char *target){	char *name;	ntfschar *uname = NULL, *utarget = NULL;	ntfs_inode *dir_ni = NULL, *ni;	char *path;	int res = 0, uname_len, utarget_len;	path = strdup(org_path);	if (!path)		return -errno;	/* Generate unicode filename. */	name = strrchr(path, '/');	name++;	uname_len = ntfs_mbstoucs(name, &uname, 0);	if (uname_len < 0) {		res = -errno;		goto exit;	}	/* Open parent directory. */	*name = 0;	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!dir_ni) {		res = -errno;		goto exit;	}	/* Create object specified in @type. */	switch (type) {		case S_IFCHR:		case S_IFBLK:			ni = ntfs_create_device(dir_ni, uname, uname_len, type,					dev);			break;		case S_IFLNK:			utarget_len = ntfs_mbstoucs(target, &utarget, 0);			if (utarget_len < 0) {				res = -errno;				goto exit;			}			ni = ntfs_create_symlink(dir_ni, uname, uname_len,					utarget, utarget_len);			break;		default:			ni = ntfs_create(dir_ni, uname, uname_len, type);			break;	}	if (ni)		ntfs_inode_close(ni);	else		res = -errno;exit:	free(uname);	if (dir_ni)		ntfs_inode_close(dir_ni);	if (utarget)		free(utarget);	free(path);	return res;}static int ntfs_fuse_create_stream(const char *path,		ntfschar *stream_name, const int stream_name_len){	ntfs_inode *ni;	int res = 0;	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni) {		res = -errno;		if (res == -ENOENT) {			/*			 * If such file does not exist, create it and try once			 * again to add stream to it.			 */			res = ntfs_fuse_create(path, S_IFREG, 0, NULL);			if (!res)				return ntfs_fuse_create_stream(path,						stream_name, stream_name_len);			else				res = -errno;		}		return res;	}	if (ntfs_attr_add(ni, AT_DATA, stream_name, stream_name_len, NULL, 0))		res = -errno;	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}static int ntfs_fuse_mknod(const char *org_path, mode_t mode, dev_t dev){	char *path = NULL;	ntfschar *stream_name;	int stream_name_len;	int res = 0;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	if (stream_name_len && !S_ISREG(mode)) {		res = -EINVAL;		goto exit;	}	if (!stream_name_len)		res = ntfs_fuse_create(path, mode & S_IFMT, dev, NULL);	else		res = ntfs_fuse_create_stream(path, stream_name,				stream_name_len);	ntfs_fuse_mark_free_space_outdated();exit:	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_symlink(const char *to, const char *from){	if (ntfs_fuse_is_named_data_stream(from))		return -EINVAL; /* n/a for named data streams. */	ntfs_fuse_mark_free_space_outdated();	return ntfs_fuse_create(from, S_IFLNK, 0, to);}static int ntfs_fuse_link(const char *old_path, const char *new_path){	char *name;	ntfschar *uname = NULL;	ntfs_inode *dir_ni = NULL, *ni;	char *path;	int res = 0, uname_len;	if (ntfs_fuse_is_named_data_stream(old_path))		return -EINVAL; /* n/a for named data streams. */	if (ntfs_fuse_is_named_data_stream(new_path))		return -EINVAL; /* n/a for named data streams. */	path = strdup(new_path);	if (!path)		return -errno;	/* Open file for which create hard link. */	ni = ntfs_pathname_to_inode(ctx->vol, NULL, old_path);	if (!ni) {		res = -errno;		goto exit;	}	/* Generate unicode filename. */	name = strrchr(path, '/');	name++;	uname_len = ntfs_mbstoucs(name, &uname, 0);	if (uname_len < 0) {		res = -errno;		goto exit;	}	/* Open parent directory. */	*name = 0;	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!dir_ni) {		res = -errno;		goto exit;	}	ntfs_fuse_mark_free_space_outdated();	/* Create hard link. */	if (ntfs_link(ni, dir_ni, uname, uname_len))		res = -errno;exit:	if (ni)		ntfs_inode_close(ni);	free(uname);	if (dir_ni)		ntfs_inode_close(dir_ni);	free(path);	return res;}static int ntfs_fuse_rm(const char *org_path){	char *name;	ntfschar *uname = NULL;	ntfs_inode *dir_ni = NULL, *ni;	char *path;	int res = 0, uname_len;	path = strdup(org_path);	if (!path)		return -errno;	/* Open object for delete. */	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni) {		res = -errno;		goto exit;	}	/* Generate unicode filename. */	name = strrchr(path, '/');	name++;	uname_len = ntfs_mbstoucs(name, &uname, 0);	if (uname_len < 0) {		res = -errno;		goto exit;	}	/* Open parent directory. */	*name = 0;	dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!dir_ni) {		res = -errno;		goto exit;	}	/* Delete object. */	if (ntfs_delete(ni, dir_ni, uname, uname_len))		res = -errno;	ni = NULL;exit:	if (ni)		ntfs_inode_close(ni);	free(uname);	if (dir_ni)		ntfs_inode_close(dir_ni);	free(path);	return res;}static int ntfs_fuse_rm_stream(const char *path, ntfschar *stream_name,		const int stream_name_len){	ntfs_inode *ni;	ntfs_attr *na;	int res = 0;	ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);	if (!ni)		return -errno;	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);	if (!na) {		res = -errno;		goto exit;	}	if (ntfs_attr_rm(na)) {		res = -errno;		ntfs_attr_close(na);	}exit:	if (ntfs_inode_close(ni))		ntfs_log_perror("Failed to close inode");	return res;}static int ntfs_fuse_unlink(const char *org_path){	char *path = NULL;	ntfschar *stream_name;	int stream_name_len;	int res = 0;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	if (!stream_name_len)		res = ntfs_fuse_rm(path);	else		res = ntfs_fuse_rm_stream(path, stream_name, stream_name_len);	ntfs_fuse_mark_free_space_outdated();	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_rename(const char *old_path, const char *new_path){	int ret;	if ((ret = ntfs_fuse_link(old_path, new_path)))		return ret;	if ((ret = ntfs_fuse_unlink(old_path))) {		ntfs_fuse_unlink(new_path);		return ret;	}	return 0;}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;}#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;	}

⌨️ 快捷键说明

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