From 7d4da6728bf09481602866d14c980c4f2ec411a7 Mon Sep 17 00:00:00 2001 From: Tobias Klausmann Date: Tue, 2 Jun 2026 13:22:59 +0200 Subject: [PATCH 1/2] Fix `|` vs. `&` logic error on check of retval from stat() Comparing this to the other stat() callsites (l.469 and l.734) made me wonder if `|` is actually the right operation here: we want to make sure the basic fields are there, but with `|` the inner part will always be nonzero (and thus `!()` will always be as-zero, defeating the entire check. I think this is a simple typo and should be `&` instead. --- file_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file_scan.c b/file_scan.c index 0760b9cd9ee8..42d969b4e04c 100644 --- a/file_scan.c +++ b/file_scan.c @@ -541,7 +541,7 @@ static int walk_dir(char *path, struct dbhandle *db) sprintf(child, "%s/%s", path, entry->d_name); ret = statx(0, child, 0, STATX_BASIC_STATS, &st); - if (ret || !(st.stx_mask | STATX_BASIC_STATS)) { + if (ret || !(st.stx_mask & STATX_BASIC_STATS)) { eprintf("Failed to stat %s: %s\n", path, strerror(errno)); continue; From 0326c3f663cef519d4231e0cabc5cd86d8e4b031 Mon Sep 17 00:00:00 2001 From: Tobias Klausmann Date: Tue, 2 Jun 2026 13:33:14 +0200 Subject: [PATCH 2/2] Fix deeper logic error in file_scan stat call checks THinking this over some more, I relaized that the lgoic is not quite correct. As it is (ignoring the earlier `|` vs. `&` bug), we don't check if the fields we are about are _all_ there (we specifically care about e.g. st.stx_ino, st.stx_siz and st.stx_size); instead any of the budled fields in STATX_BASIC_STATS are sufficient to make the check pass. In reality, only some of the basic fields being there but not all is extremely unlikely if not impossible. Still, I think the code should reflect the intended logic, rather than a proximate check as it is now. So I fixed all three occasions of this check in file_scan.c. --- file_scan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/file_scan.c b/file_scan.c index 42d969b4e04c..e1a2b060570b 100644 --- a/file_scan.c +++ b/file_scan.c @@ -466,7 +466,7 @@ static int get_dirent_type(struct dirent *entry, int fd, const char *path) * convenience of the caller. */ ret = statx(fd, entry->d_name, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS, &st); - if (ret || !(st.stx_mask & STATX_BASIC_STATS)) { + if (ret || (st.stx_mask & STATX_BASIC_STATS) != STATX_BASIC_STATS) { eprintf("Error %d: %s while getting type of file %s/%s. " "Skipping.\n", errno, strerror(errno), path, entry->d_name); @@ -541,7 +541,7 @@ static int walk_dir(char *path, struct dbhandle *db) sprintf(child, "%s/%s", path, entry->d_name); ret = statx(0, child, 0, STATX_BASIC_STATS, &st); - if (ret || !(st.stx_mask & STATX_BASIC_STATS)) { + if (ret || (st.stx_mask & STATX_BASIC_STATS) != STATX_BASIC_STATS) { eprintf("Failed to stat %s: %s\n", path, strerror(errno)); continue; @@ -731,7 +731,7 @@ int scan_file(char *in_path, struct dbhandle *db) } ret = statx(0, path, 0, STATX_BASIC_STATS, &st); - if (ret || !(st.stx_mask & STATX_BASIC_STATS)) { + if (ret || (st.stx_mask & STATX_BASIC_STATS) != STATX_BASIC_STATS) { eprintf("Error %d: %s while stating file %s. " "Skipping.\n", errno, strerror(errno), path);