diff options
author | Martin Pärtel <martin.partel@gmail.com> | 2016-10-15 01:44:45 +0100 |
---|---|---|
committer | Martin Pärtel <martin.partel@gmail.com> | 2016-10-15 01:44:45 +0100 |
commit | 9b37e64eb3e625535a1a20f315d7932f2e74b399 (patch) | |
tree | ec9792c2b77478442b18a969043c9967f1be90c8 /src/bindfs.c | |
parent | 3285e0aee6ea92da2eef119cb66c54cf74c255dc (diff) | |
download | bindfs-9b37e64eb3e625535a1a20f315d7932f2e74b399.tar.gz |
Fix #41 (seeking in directory).
Since version 1.31.1, bindfs has implemented readdir by always
reading the entire directory and passing 0 offset to filler,
but this does not work if the same directory pointer is rewound
and reused.
We remove the opendir and closedir implementations (which FUSE permits)
and now always opendir() and closedir() in readdir. Alternatively we
could have added a rewinddir() to our readdir.
Diffstat (limited to 'src/bindfs.c')
-rw-r--r-- | src/bindfs.c | 64 |
1 files changed, 16 insertions, 48 deletions
diff --git a/src/bindfs.c b/src/bindfs.c index 460f362..28c9dfe 100644 --- a/src/bindfs.c +++ b/src/bindfs.c @@ -215,11 +215,8 @@ static int bindfs_getattr(const char *path, struct stat *stbuf); static int bindfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi); static int bindfs_readlink(const char *path, char *buf, size_t size); -static int bindfs_opendir(const char *path, struct fuse_file_info *fi); -static inline DIR *get_dirp(struct fuse_file_info *fi); static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi); -static int bindfs_releasedir(const char *path, struct fuse_file_info *fi); static int bindfs_mknod(const char *path, mode_t mode, dev_t rdev); static int bindfs_mkdir(const char *path, mode_t mode); static int bindfs_unlink(const char *path); @@ -627,53 +624,32 @@ static int bindfs_readlink(const char *path, char *buf, size_t size) return 0; } -static int bindfs_opendir(const char *path, struct fuse_file_info *fi) -{ - DIR *dp; - char *real_path; - - real_path = process_path(path, true); - if (real_path == NULL) - return -errno; - - dp = opendir(real_path); - free(real_path); - if (dp == NULL) - return -errno; - - fi->fh = (unsigned long) dp; - return 0; -} - -static inline DIR *get_dirp(struct fuse_file_info *fi) -{ - return (DIR *) (uintptr_t) fi->fh; -} - static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { - DIR *dp = get_dirp(fi); - struct dirent *de_buf; - struct dirent *de; - struct stat st; - int result = 0; - long pc_ret; - char *real_path; + char *real_path = process_path(path, true); + if (real_path == NULL) { + return -errno; + } - real_path = process_path(path, true); - if (real_path == NULL) + DIR *dp = opendir(real_path); + if (dp == NULL) { + free(real_path); return -errno; - pc_ret = pathconf(real_path, _PC_NAME_MAX); - free(real_path); + } + long pc_ret = pathconf(real_path, _PC_NAME_MAX); + free(real_path); if (pc_ret < 0) { DPRINTF("pathconf failed: %s (%d)", strerror(errno), errno); pc_ret = NAME_MAX; } - de_buf = malloc(offsetof(struct dirent, d_name) + pc_ret + 1); + struct dirent *de_buf = + malloc(offsetof(struct dirent, d_name) + pc_ret + 1); + int result = 0; while (1) { + struct dirent *de; result = readdir_r(dp, de_buf, &de); if (result != 0) { result = -result; @@ -683,6 +659,7 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, break; } + struct stat st; memset(&st, 0, sizeof(st)); st.st_ino = de->d_ino; st.st_mode = de->d_type << 12; @@ -702,15 +679,8 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, } free(de_buf); - return result; -} - -static int bindfs_releasedir(const char *path, struct fuse_file_info *fi) -{ - DIR *dp = get_dirp(fi); - (void) path; closedir(dp); - return 0; + return result; } static int bindfs_mknod(const char *path, mode_t mode, dev_t rdev) @@ -1361,9 +1331,7 @@ static struct fuse_operations bindfs_oper = { .fgetattr = bindfs_fgetattr, /* no access() since we always use -o default_permissions */ .readlink = bindfs_readlink, - .opendir = bindfs_opendir, .readdir = bindfs_readdir, - .releasedir = bindfs_releasedir, .mknod = bindfs_mknod, .mkdir = bindfs_mkdir, .symlink = bindfs_symlink, |