summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-10-17 11:43:43 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-10-17 12:33:39 -0400
commit332f38aff0e6b7bc1a3a648eb66437d2d043ad21 (patch)
treead773f27729262bff9b07314f11e080a9bb544c8
parent3ac3bee7b0d9c9be693415206efa664bf4a7d4a7 (diff)
downloadbfs-332f38aff0e6b7bc1a3a648eb66437d2d043ad21.tar.xz
dir: New flag to control whiteout visibility
-rw-r--r--src/dir.c12
-rw-r--r--src/dir.h4
2 files changed, 13 insertions, 3 deletions
diff --git a/src/dir.c b/src/dir.c
index 371696f..98518f2 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -259,7 +259,8 @@ static int bfs_getdent(struct bfs_dir *dir, const sys_dirent **de) {
/** Skip ".", "..", and deleted/empty dirents. */
static int bfs_skipdent(struct bfs_dir *dir, const sys_dirent *de) {
-#if BFS_USE_GETDENTS && __FreeBSD__
+#if BFS_USE_GETDENTS
+# if __FreeBSD__
// Union mounts on FreeBSD have to be de-duplicated in userspace
if (dir->flags & BFS_DIR_UNION) {
struct trie_leaf *leaf = trie_insert_str(&dir->trie, de->d_name);
@@ -276,7 +277,14 @@ static int bfs_skipdent(struct bfs_dir *dir, const sys_dirent *de) {
if (de->d_ino == 0) {
return 1;
}
-#endif
+# endif
+
+# ifdef DT_WHT
+ if (de->d_type == DT_WHT && !(dir->flags & BFS_DIR_WHITEOUTS)) {
+ return 1;
+ }
+# endif
+#endif // BFS_USE_GETDENTS
const char *name = de->d_name;
return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
diff --git a/src/dir.h b/src/dir.h
index 7e0cbba..b11d454 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -90,8 +90,10 @@ void bfs_dir_arena(struct arena *arena);
* bfs_opendir() flags.
*/
enum bfs_dir_flags {
+ /** Include whiteouts in the results. */
+ BFS_DIR_WHITEOUTS = 1 << 0,
/** @internal Start of private flags. */
- BFS_DIR_PRIVATE = 1 << 0,
+ BFS_DIR_PRIVATE = 1 << 1,
};
/**