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 /tests | |
| 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 'tests')
| -rw-r--r-- | tests/Makefile.am | 6 | ||||
| -rwxr-xr-x | tests/test_bindfs.rb | 12 | ||||
| -rw-r--r-- | tests/test_dir_rewind.c | 80 |
3 files changed, 97 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 66713e2..0a52108 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,10 +1,14 @@ UNAME_S := $(shell uname -s) -noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker +AM_CPPFLAGS = ${my_CPPFLAGS} +AM_CFLAGS = ${my_CFLAGS} + +noinst_PROGRAMS = readdir_inode utimens_nofollow fcntl_locker test_dir_rewind readdir_inode_SOURCES = readdir_inode.c utimens_nofollow_SOURCES = utimens_nofollow.c fcntl_locker_SOURCES = fcntl_locker.c +test_dir_rewind_SOURCES = test_dir_rewind.c TESTS = test_bindfs.rb SUBDIRS = internals diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb index c0ae5dd..e355e2a 100755 --- a/tests/test_bindfs.rb +++ b/tests/test_bindfs.rb @@ -678,6 +678,18 @@ root_testenv("", :title => "ioctl not enabled by default") do assert { `chattr +a mnt/file 2>&1`; !$?.success? } end +# Issue #41 +testenv("", :title => "reading directory with rewind") do + touch('mnt/file1') + touch('mnt/file2') + mkdir('mnt/subdir') + + Dir.chdir 'mnt' do + system("#{$tests_dir}/test_dir_rewind") + assert { $?.success? } + end +end + # FIXME: this stuff around testenv is a hax, and testenv may also exit(), which defeats the 'ensure' below. # the test setup ought to be refactored. It might well use MiniTest or something. if Process.uid == 0 diff --git a/tests/test_dir_rewind.c b/tests/test_dir_rewind.c new file mode 100644 index 0000000..d4050f9 --- /dev/null +++ b/tests/test_dir_rewind.c @@ -0,0 +1,80 @@ +// Tests that opening the current directory, reading its entries +// rewinding and reading its entries again gives the same entries both times. +// +// https://github.com/mpartel/bindfs/issues/41 + +#ifdef __linux__ + +#define _GNU_SOURCE +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/syscall.h> +#include <unistd.h> + +#define BUF_SIZE 4096 + +int main() +{ + int fd = open(".", O_RDONLY | O_DIRECTORY); + if (fd == -1) { + perror("failed to open '.'"); + return 1; + } + + char buf1[BUF_SIZE]; + char buf2[BUF_SIZE]; + memset(buf1, 0, BUF_SIZE); + memset(buf2, 0, BUF_SIZE); + + int amt_read1 = syscall(SYS_getdents, fd, buf1, BUF_SIZE); + if (amt_read1 <= 0) { + fprintf(stderr, "amt_read1=%d\n", amt_read1); + close(fd); + return 1; + } + + off_t seek_res = lseek(fd, 0, SEEK_SET); + if (seek_res == (off_t)-1) { + perror("failed to lseek to 0"); + close(fd); + return 1; + } + + int amt_read2 = syscall(SYS_getdents, fd, buf2, BUF_SIZE); + if (amt_read2 <= 0) { + fprintf(stderr, "amt_read2=%d\n", amt_read2); + close(fd); + return 1; + } + + if (amt_read1 != amt_read2) { + fprintf(stderr, + "First read gave %d bytes, second read gave %d bytes.\n", + amt_read1, amt_read2); + close(fd); + return 1; + } + if (memcmp(buf1, buf2, BUF_SIZE) != 0) { + fprintf(stderr, "First and second read results differ.\n"); + close(fd); + return 1; + } + + close(fd); + return 0; +} + +#else // #ifdef __linux__ + +int main() +{ + printf("This test (probably) only compiles on Linux.\n"); + printf("Skipping by just returning successfully.\n"); + return 0; +} + +#endif // #ifdef __linux__ |
