From 6bf2e6f07c133f7b145a4726c5d962f14c650ca7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 5 Mar 2014 14:45:44 +0100 Subject: libfuse: implement readdirplus for high-level API Reuse the old "readdir" callback, but add a flags argument, that has FUSE_READDIR_PLUS in case this is a "plus" version. Filesystems can safely ignore this flag, but if they want they can add optimizations based on it: i.e. only retrieve the full attributes in PLUS mode. The filler function is also given a flags argument and the filesystem can set FUSE_FILL_DIR_PLUS if all the attributes in "stat" are valid. --- example/fusexmp_fh.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'example/fusexmp_fh.c') diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index ba6789b..531438f 100755 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -128,7 +128,8 @@ static inline struct xmp_dirp *get_dirp(struct fuse_file_info *fi) } static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, - off_t offset, struct fuse_file_info *fi) + off_t offset, struct fuse_file_info *fi, + enum fuse_readdir_flags flags) { struct xmp_dirp *d = get_dirp(fi); @@ -141,18 +142,30 @@ static int xmp_readdir(const char *path, void *buf, fuse_fill_dir_t filler, while (1) { struct stat st; off_t nextoff; + enum fuse_fill_dir_flags fill_flags = 0; if (!d->entry) { d->entry = readdir(d->dp); if (!d->entry) break; } - - memset(&st, 0, sizeof(st)); - st.st_ino = d->entry->d_ino; - st.st_mode = d->entry->d_type << 12; +#ifdef HAVE_FSTATAT + if (flags & FUSE_READDIR_PLUS) { + int res; + + res = fstatat(dirfd(d->dp), d->entry->d_name, &st, + AT_SYMLINK_NOFOLLOW); + if (res != -1) + fill_flags |= FUSE_FILL_DIR_PLUS; + } +#endif + if (!(fill_flags & FUSE_FILL_DIR_PLUS)) { + memset(&st, 0, sizeof(st)); + st.st_ino = d->entry->d_ino; + st.st_mode = d->entry->d_type << 12; + } nextoff = telldir(d->dp); - if (filler(buf, d->entry->d_name, &st, nextoff)) + if (filler(buf, d->entry->d_name, &st, nextoff, fill_flags)) break; d->entry = NULL; -- cgit v1.2.3