From: Amir Goldstein <amir73il@gmail.com>
Date: Thu, 2 Jan 2025 20:14:01 +0000 (+0100)
Subject: Fix junk readdirplus results when filesystem not filling stat info
X-Git-Tag: fuse-3.17.1-rc0~24
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=e18535657101f79ab742d81c567bb03f108acae0;p=qemu-gpiodev%2Flibfuse.git

Fix junk readdirplus results when filesystem not filling stat info

Commit dd95d13a ("fix readdirplus when filler is called with zero offset
(#896)) broke readdirplus with passthrough example command:

    passthrough -o auto_cache,modules=subdir,subdir=/src /mnt

The /src directory looks like this:

    ~# ls -l /src
    total 0
    drwx------ 3 root root 60 Jan  2 17:51 testdir

And the fuse directory looks like this:

    ~# ls -l /mnt
    total 0
    d--------- 0 root root 0 Jan  1  1970 testdir

Because readdir_fill_from_list() ignores the fact that filesystem
did not pass the FUSE_FILL_DIR_PLUS flag with valid stat info.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---

diff --git a/lib/fuse.c b/lib/fuse.c
index a1537af..aa5c611 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -163,6 +163,7 @@ struct node_lru {
 
 struct fuse_direntry {
 	struct stat stat;
+	enum fuse_fill_dir_flags flags;
 	char *name;
 	struct fuse_direntry *next;
 };
@@ -3437,7 +3438,7 @@ static int extend_contents(struct fuse_dh *dh, unsigned minsize)
 }
 
 static int fuse_add_direntry_to_dh(struct fuse_dh *dh, const char *name,
-				   struct stat *st)
+				   struct stat *st, enum fuse_fill_dir_flags flags)
 {
 	struct fuse_direntry *de;
 
@@ -3452,6 +3453,7 @@ static int fuse_add_direntry_to_dh(struct fuse_dh *dh, const char *name,
 		free(de);
 		return -1;
 	}
+	de->flags = flags;
 	de->stat = *st;
 	de->next = NULL;
 
@@ -3529,7 +3531,7 @@ static int fill_dir(void *dh_, const char *name, const struct stat *statp,
 	} else {
 		dh->filled = 1;
 
-		if (fuse_add_direntry_to_dh(dh, name, &stbuf) == -1)
+		if (fuse_add_direntry_to_dh(dh, name, &stbuf, flags) == -1)
 			return 1;
 	}
 	return 0;
@@ -3607,7 +3609,7 @@ static int fill_dir_plus(void *dh_, const char *name, const struct stat *statp,
 	} else {
 		dh->filled = 1;
 
-		if (fuse_add_direntry_to_dh(dh, name, &e.attr) == -1)
+		if (fuse_add_direntry_to_dh(dh, name, &e.attr, flags) == -1)
 			return 1;
 	}
 
@@ -3695,7 +3697,8 @@ static int readdir_fill_from_list(fuse_req_t req, struct fuse_dh *dh,
 				.attr = de->stat,
 			};
 
-			if (!is_dot_or_dotdot(de->name)) {
+			if (de->flags & FUSE_FILL_DIR_PLUS &&
+			    !is_dot_or_dotdot(de->name)) {
 				res = do_lookup(dh->fuse, dh->nodeid,
 						de->name, &e);
 				if (res) {