ntfsmount: Cache directory in which was performed last operation
parent
36b8f621f9
commit
42f475f552
|
@ -117,6 +117,9 @@ typedef struct {
|
|||
BOOL noatime;
|
||||
BOOL relatime;
|
||||
BOOL blkdev;
|
||||
char cached_path[PATH_MAX];
|
||||
ntfs_inode *cached_ni;
|
||||
ntfs_inode *root_ni;
|
||||
} ntfs_fuse_context_t;
|
||||
|
||||
#define NTFS_FUSE_OPT(t, p) { t, offsetof(ntfs_fuse_context_t, p), TRUE }
|
||||
|
@ -287,6 +290,68 @@ static int ntfs_fuse_parse_path(const char *org_path, char **path,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_fuse_cache_get_dir
|
||||
*
|
||||
* WARNING: Do not close inodes obtained with this function. They will be closed
|
||||
* automatically upon to next call to this function with different path or in
|
||||
* .destroy().
|
||||
*/
|
||||
static ntfs_inode *ntfs_fuse_cache_get_dir(const char *path)
|
||||
{
|
||||
ntfs_inode *ni;
|
||||
|
||||
if (!*path)
|
||||
path = "/";
|
||||
|
||||
if (ctx->cached_ni && !strcmp(ctx->cached_path, path)) {
|
||||
ntfs_log_trace("Got '%s' from cache.\n", path);
|
||||
return ctx->cached_ni;
|
||||
}
|
||||
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
if (!ni)
|
||||
return NULL;
|
||||
ntfs_inode_close(ctx->cached_ni);
|
||||
ctx->cached_ni = ni;
|
||||
strncpy(ctx->cached_path, path, sizeof(ctx->cached_path));
|
||||
if (ctx->cached_path[sizeof(ctx->cached_path) - 1]) {
|
||||
/* Path was truncated, invalidate it since we can not use it. */
|
||||
ctx->cached_path[sizeof(ctx->cached_path) - 1] = 0;
|
||||
*ctx->cached_path = 0;
|
||||
}
|
||||
ntfs_log_trace("Cached '%s'.\n", path);
|
||||
return ni;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_fuse_cache_get_file
|
||||
*
|
||||
* WARNING: This function changes @path during execution, but restores it
|
||||
* original value upon exit. Do *NOT* pass constant strings to this function!
|
||||
*
|
||||
* WARNING: You should close inode obtained with this function vice-versa to
|
||||
* inodes obtained with ntfs_fuse_cache_get_dir().
|
||||
*/
|
||||
static ntfs_inode *ntfs_fuse_cache_get_file(char *path)
|
||||
{
|
||||
ntfs_inode *dir_ni;
|
||||
char *file;
|
||||
|
||||
file = strrchr(path, '/');
|
||||
if (file == path)
|
||||
return ntfs_pathname_to_inode(ctx->vol, NULL, file);
|
||||
*file = 0;
|
||||
dir_ni = ntfs_fuse_cache_get_dir(path);
|
||||
*file = '/';
|
||||
file++;
|
||||
|
||||
if (dir_ni)
|
||||
return ntfs_pathname_to_inode(ctx->vol, dir_ni, file);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
|
||||
{
|
||||
int res = 0;
|
||||
|
@ -300,7 +365,7 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
|
|||
if (stream_name_len < 0)
|
||||
return stream_name_len;
|
||||
memset(stbuf, 0, sizeof(struct stat));
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
ni = ntfs_fuse_cache_get_file(path);
|
||||
if (!ni) {
|
||||
res = -ENOENT;
|
||||
goto exit;
|
||||
|
@ -447,7 +512,7 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size)
|
|||
res = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
ni = ntfs_fuse_cache_get_file(path);
|
||||
if (!ni) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
|
@ -548,14 +613,13 @@ static int ntfs_fuse_readdir(const char *path, void *buf,
|
|||
|
||||
fill_ctx.filler = filler;
|
||||
fill_ctx.buf = buf;
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
ni = ntfs_fuse_cache_get_dir(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);
|
||||
ntfs_inode_close(ni);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -571,7 +635,7 @@ static int ntfs_fuse_open(const char *org_path, struct fuse_file_info *fi)
|
|||
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);
|
||||
ni = ntfs_fuse_cache_get_file(path);
|
||||
if (ni) {
|
||||
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
|
||||
if (na) {
|
||||
|
@ -585,10 +649,8 @@ static int ntfs_fuse_open(const char *org_path, struct fuse_file_info *fi)
|
|||
if (stream_name_len)
|
||||
free(stream_name);
|
||||
if (res) {
|
||||
if (ni)
|
||||
ntfs_inode_close(ni);
|
||||
if (na)
|
||||
ntfs_attr_close(na);
|
||||
ntfs_inode_close(ni);
|
||||
ntfs_attr_close(na);
|
||||
} else
|
||||
fi->fh = (uintptr_t)na;
|
||||
return res;
|
||||
|
@ -687,7 +749,7 @@ static int ntfs_fuse_truncate(const char *org_path, off_t size)
|
|||
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);
|
||||
ni = ntfs_fuse_cache_get_file(path);
|
||||
if (!ni) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
|
@ -767,6 +829,7 @@ static int __ntfs_fuse_mknod(const char *org_path, dev_t type, dev_t dev,
|
|||
return -errno;
|
||||
/* Generate unicode filename. */
|
||||
name = strrchr(path, '/');
|
||||
*name = 0;
|
||||
name++;
|
||||
uname_len = ntfs_mbstoucs(name, &uname, 0);
|
||||
if (uname_len < 0) {
|
||||
|
@ -774,8 +837,7 @@ static int __ntfs_fuse_mknod(const char *org_path, dev_t type, dev_t dev,
|
|||
goto exit;
|
||||
}
|
||||
/* Open parent directory. */
|
||||
*name = 0;
|
||||
dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
dir_ni = ntfs_fuse_cache_get_dir(path);
|
||||
if (!dir_ni) {
|
||||
res = -errno;
|
||||
if (res == -ENOENT)
|
||||
|
@ -813,8 +875,6 @@ static int __ntfs_fuse_mknod(const char *org_path, dev_t type, dev_t dev,
|
|||
res = -errno;
|
||||
exit:
|
||||
free(uname);
|
||||
if (dir_ni)
|
||||
ntfs_inode_close(dir_ni);
|
||||
if (utarget)
|
||||
free(utarget);
|
||||
free(path);
|
||||
|
@ -983,13 +1043,14 @@ static int ntfs_fuse_rm(const char *org_path)
|
|||
if (!path)
|
||||
return -errno;
|
||||
/* Open object for delete. */
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
ni = ntfs_fuse_cache_get_file(path);
|
||||
if (!ni) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
/* Generate unicode filename. */
|
||||
name = strrchr(path, '/');
|
||||
*name = 0;
|
||||
name++;
|
||||
uname_len = ntfs_mbstoucs(name, &uname, 0);
|
||||
if (uname_len < 0) {
|
||||
|
@ -997,8 +1058,7 @@ static int ntfs_fuse_rm(const char *org_path)
|
|||
goto exit;
|
||||
}
|
||||
/* Open parent directory. */
|
||||
*name = 0;
|
||||
dir_ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
dir_ni = ntfs_fuse_cache_get_dir(path);
|
||||
if (!dir_ni) {
|
||||
res = -errno;
|
||||
if (res == -ENOENT)
|
||||
|
@ -1015,11 +1075,8 @@ static int ntfs_fuse_rm(const char *org_path)
|
|||
NTFS_UPDATE_MTIME);
|
||||
}
|
||||
exit:
|
||||
if (ni)
|
||||
ntfs_inode_close(ni);
|
||||
ntfs_inode_close(ni);
|
||||
free(uname);
|
||||
if (dir_ni)
|
||||
ntfs_inode_close(dir_ni);
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
@ -1460,6 +1517,8 @@ exit:
|
|||
static void ntfs_fuse_destroy(void *priv __attribute__((unused)))
|
||||
{
|
||||
if (ctx->vol) {
|
||||
ntfs_inode_close(ctx->cached_ni);
|
||||
ntfs_inode_close(ctx->root_ni);
|
||||
ntfs_log_info("Unmounting %s (%s)\n", ctx->device,
|
||||
ctx->vol->vol_name);
|
||||
if (ntfs_umount(ctx->vol, FALSE))
|
||||
|
@ -1727,6 +1786,7 @@ static int ntfs_fuse_mount(void)
|
|||
return -1;
|
||||
}
|
||||
ctx->vol = vol;
|
||||
ctx->root_ni = ntfs_inode_open(vol, FILE_root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue