diff options
author | Martin Pärtel <martin.partel@gmail.com> | 2019-06-26 11:41:46 +0300 |
---|---|---|
committer | Martin Pärtel <martin.partel@gmail.com> | 2019-06-26 11:41:46 +0300 |
commit | 74427b94fcf53b3a3c4c87b26051a55c69aac093 (patch) | |
tree | d126cc92a676178d293e3a1b87f600c866f367bd /src/bindfs.c | |
parent | acca303e4b603614afb51552d38da6de9213be29 (diff) | |
download | bindfs-74427b94fcf53b3a3c4c87b26051a55c69aac093.tar.gz |
Resolve symlinks in readdir() so correct attributes are returned.
Fixes #76
Diffstat (limited to 'src/bindfs.c')
-rw-r--r-- | src/bindfs.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/bindfs.c b/src/bindfs.c index dc8e25c..22b446e 100644 --- a/src/bindfs.c +++ b/src/bindfs.c @@ -1,5 +1,5 @@ /* - Copyright 2006,2007,2008,2009,2010,2012 Martin Pärtel <martin.partel@gmail.com> + Copyright 2006,2007,2008,2009,2010,2012,2019 Martin Pärtel <martin.partel@gmail.com> This file is part of bindfs. @@ -615,7 +615,6 @@ static size_t round_up_buffer_size_for_direct_io(size_t size) } #endif - static void *bindfs_init() { assert(settings.permchain != NULL); @@ -715,7 +714,6 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, } 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; @@ -725,6 +723,17 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, pc_ret = NAME_MAX; } + // Path buffer for resolving symlinks + struct memory_block resolve_buf = MEMORY_BLOCK_INITIALIZER; + if (settings.resolve_symlinks) { + int len = strlen(real_path); + append_to_memory_block(&resolve_buf, real_path, len + 1); + resolve_buf.ptr[len] = '/'; + } + + free(real_path); + real_path = NULL; + int result = 0; while (1) { errno = 0; @@ -741,6 +750,21 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, st.st_ino = de->d_ino; st.st_mode = de->d_type << 12; + if (settings.resolve_symlinks && (st.st_mode & S_IFLNK) == S_IFLNK) { + int file_len = strlen(de->d_name) + 1; // (include null terminator) + append_to_memory_block(&resolve_buf, de->d_name, file_len); + char *resolved = realpath(resolve_buf.ptr, NULL); + resolve_buf.size -= file_len; + + if (resolved) { + if (lstat(resolved, &st) == -1) { + result = -errno; + break; + } + free(resolved); + } + } + // See issue #28 for why we pass a 0 offset to `filler` and ignore // `offset`. // @@ -754,6 +778,10 @@ static int bindfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, } } + if (settings.resolve_symlinks) { + free_memory_block(&resolve_buf); + } + closedir(dp); return result; } |