diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2018-08-14 21:37:02 +0200 |
---|---|---|
committer | Nikolaus Rath <Nikolaus@rath.org> | 2018-10-10 10:49:48 +0100 |
commit | 49676ed9cc2f21d52eabc464e8ab2eea6374eb34 (patch) | |
tree | 734db5e9d4b6c7cc1e7acf898e83052fc2e388de /example | |
parent | c3fa8578867fc45ca3d842b5641a48cacbc8eea1 (diff) | |
download | libfuse-49676ed9cc2f21d52eabc464e8ab2eea6374eb34.tar.gz |
passthrough_ll: fix refcount for "." and ".." entries
Kernel is not expecting an elevated lookup count for the "." and ".."
entries when doing READDIRPLUS.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'example')
-rw-r--r-- | example/passthrough_ll.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/example/passthrough_ll.c b/example/passthrough_ll.c index f358e55..0b92d9c 100644 --- a/example/passthrough_ll.c +++ b/example/passthrough_ll.c @@ -342,6 +342,12 @@ out_err: fuse_reply_err(req, error); } +static int is_dot_or_dotdot(const char *name) +{ + return name[0] == '.' && (name[1] == '\0' || + (name[1] == '.' && name[2] == '\0')); +} + static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info *fi, int plus) { @@ -367,6 +373,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, while (1) { size_t entsize; off_t nextoff; + const char *name; if (!d->entry) { errno = 0; @@ -380,23 +387,28 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, } } nextoff = telldir(d->dp); + name = d->entry->d_name; if (plus) { struct fuse_entry_param e; - err = lo_do_lookup(req, ino, d->entry->d_name, &e); - if (err) - goto error; + if (is_dot_or_dotdot(name)) { + e.ino = 0; + e.attr.st_ino = d->entry->d_ino; + e.attr.st_mode = d->entry->d_type << 12; + } else { + err = lo_do_lookup(req, ino, name, &e); + if (err) + goto error; + } - entsize = fuse_add_direntry_plus(req, p, rem, - d->entry->d_name, + entsize = fuse_add_direntry_plus(req, p, rem, name, &e, nextoff); } else { struct stat st = { .st_ino = d->entry->d_ino, .st_mode = d->entry->d_type << 12, }; - entsize = fuse_add_direntry(req, p, rem, - d->entry->d_name, + entsize = fuse_add_direntry(req, p, rem, name, &st, nextoff); } if (entsize > rem) |