Fix returning inode numbers from readdir() in offset==0 mode. (#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 #583.
This commit is contained in:
Martin Pärtel 2021-02-03 11:53:21 +02:00 committed by GitHub
parent b9e3ea01db
commit 5012a05ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 3 deletions

View File

@ -4,6 +4,7 @@ Unreleased Changes
* Allow "nonempty" as a mount option, for backwards compatibility with
fusermount 2. The option has no effect since mounting over non-empty
directories is allowed by default.
* Fix returning inode numbers from readdir() in offset==0 mode.
libfuse 3.10.1 (2020-12-07)
===========================

View File

@ -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;
}

View File

@ -3566,7 +3566,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)) {

View File

@ -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' ]

45
test/readdir_inode.c Normal file
View File

@ -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;
}

View File

@ -72,6 +72,15 @@ class raii_tmpdir:
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))
@ -602,6 +611,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)
@ -623,6 +636,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))
@ -631,7 +648,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