Skip to content

Commit

Permalink
Fix returning inode numbers from readdir() in offset==0 mode. (libfus…
Browse files Browse the repository at this point in the history
…e#584)

- Test added for all passthrough examples.
- passthrough.c uses offset==0 mode. The others don't.
- passthrough.c changed to set FUSE_FILL_DIR_PLUS to make the test pass.
- This fixes libfuse#583.

(cherry picked from commit 5012a05)
  • Loading branch information
mpartel authored and amir73il committed Jun 21, 2021
1 parent 364d9fc commit 4c75c38
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 3 deletions.
2 changes: 1 addition & 1 deletion example/passthrough.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
memset(&st, 0, sizeof(st));
st.st_ino = de->d_ino;
st.st_mode = de->d_type << 12;
if (filler(buf, de->d_name, &st, 0, 0))
if (filler(buf, de->d_name, &st, 0, FUSE_FILL_DIR_PLUS))
break;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/fuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -3548,7 +3548,7 @@ static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp,
return 1;
}

if (off && statp && (flags & FUSE_FILL_DIR_PLUS)) {
if (statp && (flags & FUSE_FILL_DIR_PLUS)) {
e.attr = *statp;

if (!is_dot_or_dotdot(name)) {
Expand Down
3 changes: 3 additions & 0 deletions test/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ endforeach
td += executable('test_syscalls', 'test_syscalls.c',
include_directories: include_dirs,
install: false)
td += executable('readdir_inode', 'readdir_inode.c',
include_directories: include_dirs,
install: false)

test_scripts = [ 'conftest.py', 'pytest.ini', 'test_examples.py',
'util.py', 'test_ctests.py' ]
Expand Down
45 changes: 45 additions & 0 deletions test/readdir_inode.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Prints each directory entry and its inode as returned by 'readdir'.
* Skips '.' and '..' because readdir is not required to return them and
* some of our examples don't.
*/

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

int main(int argc, char* argv[])
{
DIR* dirp;
struct dirent* dent;

if (argc != 2) {
fprintf(stderr, "Usage: readdir_inode dir\n");
return 1;
}

dirp = opendir(argv[1]);
if (dirp == NULL) {
perror("failed to open directory");
return 2;
}

errno = 0;
dent = readdir(dirp);
while (dent != NULL) {
if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) {
printf("%llu %s\n", (unsigned long long)dent->d_ino, dent->d_name);
}
dent = readdir(dirp);
}
if (errno != 0) {
perror("failed to read directory entry");
return 3;
}

closedir(dirp);

return 0;
}
19 changes: 18 additions & 1 deletion test/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ def mkdir(self, path):
def short_tmpdir():
return raii_tmpdir()

def readdir_inode(dir):
cmd = base_cmdline + [ pjoin(basename, 'test', 'readdir_inode'), dir ]
with subprocess.Popen(cmd, stdout=subprocess.PIPE,
universal_newlines=True) as proc:
lines = proc.communicate()[0].splitlines()
lines.sort()
return lines


@pytest.mark.parametrize("cmdline_builder", (invoke_directly, invoke_mount_fuse,
invoke_mount_fuse_drop_privileges))
@pytest.mark.parametrize("options", powerset(options))
Expand Down Expand Up @@ -606,6 +615,10 @@ def tst_readdir(src_dir, mnt_dir):
listdir_should.sort()
assert listdir_is == listdir_should

inodes_is = readdir_inode(mnt_newdir)
inodes_should = readdir_inode(src_newdir)
assert inodes_is == inodes_should

os.unlink(file_)
os.unlink(subfile)
os.rmdir(subdir)
Expand All @@ -627,6 +640,10 @@ def tst_readdir_big(src_dir, mnt_dir):
listdir_should = sorted(os.listdir(src_dir))
assert listdir_is == listdir_should

inodes_is = readdir_inode(mnt_dir)
inodes_should = readdir_inode(src_dir)
assert inodes_is == inodes_should

for fname in fnames:
stat_src = os.stat(pjoin(src_dir, fname))
stat_mnt = os.stat(pjoin(mnt_dir, fname))
Expand All @@ -635,7 +652,7 @@ def tst_readdir_big(src_dir, mnt_dir):
assert stat_src.st_ctime == stat_mnt.st_ctime
assert stat_src.st_size == stat_mnt.st_size
os.unlink(pjoin(src_dir, fname))

def tst_truncate_path(mnt_dir):
assert len(TEST_DATA) > 1024

Expand Down

0 comments on commit 4c75c38

Please sign in to comment.