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

📄 ntfs-3g.c

📁 LINUX下读写NTFS分区的工具。 已经集成了通过LIBCONV库支持中文的代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
		struct fuse_file_info *fi __attribute__((unused))){	ntfs_fuse_fill_context_t fill_ctx;	ntfs_volume *vol;	ntfs_inode *ni;	s64 pos = 0;	int err = 0;	vol = ctx->vol;	fill_ctx.filler = filler;	fill_ctx.buf = buf;	ni = ntfs_pathname_to_inode(vol, NULL, path);	if (!ni)		return -errno;	if (ntfs_readdir(ni, &pos, &fill_ctx,			(ntfs_filldir_t)ntfs_fuse_filler))		err = -errno;	ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);	if (ntfs_inode_close(ni))		set_fuse_error(&err);	return err;}static int ntfs_fuse_open(const char *org_path,		struct fuse_file_info *fi __attribute__((unused))){	ntfs_volume *vol;	ntfs_inode *ni;	ntfs_attr *na;	int res = 0;	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) {		na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);		if (na) {			if (NAttrEncrypted(na))				res = -EACCES;			ntfs_attr_close(na);		} else			res = -errno;		if (ntfs_inode_close(ni))			set_fuse_error(&res);	} else		res = -errno;	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_read(const char *org_path, char *buf, size_t size,		off_t offset, struct fuse_file_info *fi __attribute__((unused))){	ntfs_inode *ni = NULL;	ntfs_attr *na = NULL;	char *path = NULL;	ntfschar *stream_name;	int stream_name_len, res;	s64 total = 0;	if (!size)		return 0;	stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);	if (stream_name_len < 0)		return stream_name_len;	ni = ntfs_pathname_to_inode(ctx->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;	}	if (offset + size > na->data_size) {		if (na->data_size < offset)			goto ok;		size = na->data_size - offset;	}	while (size > 0) {		s64 ret = ntfs_attr_pread(na, offset, size, buf);		if (ret != (s64)size)			ntfs_log_perror("ntfs_attr_pread error reading '%s' at "				"offset %lld: %lld <> %lld", org_path, 				(long long)offset, (long long)size, (long long)ret);		if (ret <= 0 || ret > (s64)size) {			res = (ret < 0) ? -errno : -EIO;			goto exit;		}		size -= ret;		offset += ret;		total += ret;	}ok:	ntfs_fuse_update_times(na->ni, NTFS_UPDATE_ATIME);	res = total;exit:	if (na)		ntfs_attr_close(na);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	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) {		res = stream_name_len;		goto out;	}	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_perror("ntfs_attr_pwrite partial write (%lld: "				"%lld <> %d)", (long long)offset, (long long)size, res);		if (res <= 0) {			res = -errno;			goto exit;		}		size -= res;		offset += res;		total += res;	}	res = total;	if (res > 0)		ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);exit:	if (na)		ntfs_attr_close(na);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	free(path);	if (stream_name_len)		free(stream_name);out:		return res;}static int ntfs_fuse_truncate(const char *org_path, off_t size){	ntfs_volume *vol;	ntfs_inode *ni = NULL;	ntfs_attr *na = NULL;	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)		goto exit;	na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);	if (!na)		goto exit;	if (ntfs_attr_truncate(na, size))		goto exit;		ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME);	errno = 0;exit:	res = -errno;	ntfs_attr_close(na);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	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);	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);			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) {		if (ntfs_inode_close(ni))			set_fuse_error(&res);		ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);	} else		res = -errno;exit:	free(uname);	if (ntfs_inode_close(dir_ni))		set_fuse_error(&res);	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))		set_fuse_error(&res);	return res;}static int ntfs_fuse_create_file(const char *org_path, mode_t mode, 			struct fuse_file_info *fi __attribute__((unused))){	char *path = NULL;	ntfschar *stream_name;	int stream_name_len;	int res;	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_create(path, mode & S_IFMT, 0, NULL);	else		res = ntfs_fuse_create_stream(path, stream_name,				stream_name_len);	free(path);	if (stream_name_len)		free(stream_name);	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);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. */	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);	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;	}	if (ntfs_link(ni, dir_ni, uname, uname_len)) {		res = -errno;		goto exit;	}	ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);	ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);exit:	/* 	 * Must close dir_ni first otherwise ntfs_inode_sync_file_name(ni)	 * may fail because ni may not be in parent's index on the disk yet.	 */	if (ntfs_inode_close(dir_ni))		set_fuse_error(&res);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	free(uname);	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);	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;	}		if (ntfs_delete(ni, dir_ni, uname, uname_len))		res = -errno;	/* ntfs_delete() always closes ni and dir_ni */	ni = dir_ni = NULL;exit:	if (ntfs_inode_close(dir_ni))		set_fuse_error(&res);	if (ntfs_inode_close(ni))		set_fuse_error(&res);	free(uname);	free(path);	return res;}static int ntfs_fuse_rm_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)		return -errno;		if (ntfs_attr_remove(ni, AT_DATA, stream_name, stream_name_len))		res = -errno;	if (ntfs_inode_close(ni))		set_fuse_error(&res);	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);	free(path);	if (stream_name_len)		free(stream_name);	return res;}static int ntfs_fuse_safe_rename(const char *old_path, 				 const char *new_path, 				 const char *tmp){	int ret;	ntfs_log_trace("Entering\n");		ret = ntfs_fuse_link(new_path, tmp);	if (ret)		return ret;		ret = ntfs_fuse_unlink(new_path);	if (!ret) {				ret = ntfs_fuse_link(old_path, new_path);		if (ret)			goto restore;				ret = ntfs_fuse_unlink(old_path);		if (ret) {			if (ntfs_fuse_unlink(new_path))				goto err;			goto restore;		}	}		goto cleanup;restore:	if (ntfs_fuse_link(tmp, new_path)) {err:		ntfs_log_perror("Rename failed. Existing file '%s' was renamed "				"to '%s'", new_path, tmp);	} else {cleanup:		ntfs_fuse_unlink(tmp);	}	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\n");		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)

⌨️ 快捷键说明

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