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

📄 ntfs-3g.c

📁 添加linux下对NTFS格式文件系统访问支持的源代码ntfs-3g
💻 C
📖 第 1 页 / 共 4 页
字号:
	return res;}static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,		const ntfschar *name, const int name_len, const int name_type,		const s64 pos __attribute__((unused)), const MFT_REF mref,		const unsigned dt_type __attribute__((unused))){	char *filename = NULL;	if (name_type == FILE_NAME_DOS)		return 0;	if (ntfs_ucstombs(name, name_len, &filename, 0) < 0) {		ntfs_log_perror("Skipping unrepresentable filename (inode %llu)",				(unsigned long long)MREF(mref));		return 0;	}	if (ntfs_fuse_is_named_data_stream(filename)) {		ntfs_log_error("Unable to access '%s' (inode %llu) with "				"current named streams access interface.\n",				filename, (unsigned long long)MREF(mref));		free(filename);		return 0;	}	if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user ||			ctx->show_sys_files) {		struct stat st = { .st_ino = MREF(mref) };				fill_ctx->filler(fill_ctx->buf, filename, &st, 0);	}	free(filename);	return 0;}static int ntfs_fuse_readdir(const char *path, void *buf,		fuse_fill_dir_t filler, off_t offset __attribute__((unused)),		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_inode_close(ni);	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;		ntfs_inode_close(ni);	} 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_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;	}	if (offset + size > na->data_size)		size = na->data_size - offset;	while (size) {		res = ntfs_attr_pread(na, offset, size, buf);		if (res < (s64)size)			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) {		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 && errno != ENOSPC)			ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "				"%lld <> %d)", (s64)offset, (s64)size, res);		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);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;	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;	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))		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_safe_rename(const char *old_path, 				 const char *new_path, 				 const char *tmp){	int ret;	ntfs_log_trace("Entering");		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);	}

⌨️ 快捷键说明

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