]> Sergey Matveev's repositories - bfs.git/commitdiff
parse: Set BFTW_WHITEOUTS when parsing -type w
authorTavian Barnes <tavianator@tavianator.com>
Tue, 17 Oct 2023 15:55:31 +0000 (11:55 -0400)
committerTavian Barnes <tavianator@tavianator.com>
Tue, 17 Oct 2023 16:33:39 +0000 (12:33 -0400)
src/parse.c
tests/bsd/type_w.out [new file with mode: 0644]
tests/bsd/type_w.sh [new file with mode: 0644]

index 976f7cb7e767dc41272a6d75d50967d8ed6f7313..fafd7871f5956ac9f4057e870d82f9843912a2a4 100644 (file)
@@ -2514,6 +2514,8 @@ static struct bfs_expr *parse_status(struct parser_state *state, int arg1, int a
  * Parse -x?type [bcdpflsD].
  */
 static struct bfs_expr *parse_type(struct parser_state *state, int x, int arg2) {
+       struct bfs_ctx *ctx = state->ctx;
+
        bfs_eval_fn *eval = x ? eval_xtype : eval_type;
        struct bfs_expr *expr = parse_unary_test(state, eval);
        if (!expr) {
@@ -2551,6 +2553,7 @@ static struct bfs_expr *parse_type(struct parser_state *state, int x, int arg2)
                        break;
                case 'w':
                        expr->num |= 1 << BFS_WHT;
+                       ctx->flags |= BFTW_WHITEOUTS;
                        break;
 
                case '\0':
diff --git a/tests/bsd/type_w.out b/tests/bsd/type_w.out
new file mode 100644 (file)
index 0000000..d383f69
--- /dev/null
@@ -0,0 +1,38 @@
+1: -rw-r--r-- scratch/mnt/lower/bar
+1: -rw-r--r-- scratch/mnt/lower/baz
+1: -rw-r--r-- scratch/mnt/lower/foo
+1: -rw-r--r-- scratch/mnt/upper/baz/qux
+1: -rw-r--r-- scratch/mnt/upper/foo
+1: drwxr-xr-x scratch/mnt
+1: drwxr-xr-x scratch/mnt/lower
+1: drwxr-xr-x scratch/mnt/upper
+1: drwxr-xr-x scratch/mnt/upper/baz
+2: w--------- scratch/mnt/upper/bar
+3: -rw-r--r-- scratch/mnt/lower/bar
+3: -rw-r--r-- scratch/mnt/lower/baz
+3: -rw-r--r-- scratch/mnt/lower/foo
+3: -rw-r--r-- scratch/mnt/upper/baz/qux
+3: -rw-r--r-- scratch/mnt/upper/foo
+3: drwxr-xr-x scratch/mnt
+3: drwxr-xr-x scratch/mnt/lower
+3: drwxr-xr-x scratch/mnt/upper
+3: drwxr-xr-x scratch/mnt/upper/baz
+3: w--------- scratch/mnt/upper/bar
+4: -rw-r--r-- scratch/mnt/lower/bar
+4: -rw-r--r-- scratch/mnt/lower/baz
+4: -rw-r--r-- scratch/mnt/lower/foo
+4: -rw-r--r-- scratch/mnt/upper/baz/qux
+4: drwxr-xr-x scratch/mnt
+4: drwxr-xr-x scratch/mnt/lower
+4: drwxr-xr-x scratch/mnt/upper
+4: drwxr-xr-x scratch/mnt/upper/baz
+5: w--------- scratch/mnt/upper/bar
+6: -rw-r--r-- scratch/mnt/lower/bar
+6: -rw-r--r-- scratch/mnt/lower/baz
+6: -rw-r--r-- scratch/mnt/lower/foo
+6: -rw-r--r-- scratch/mnt/upper/baz/qux
+6: drwxr-xr-x scratch/mnt
+6: drwxr-xr-x scratch/mnt/lower
+6: drwxr-xr-x scratch/mnt/upper
+6: drwxr-xr-x scratch/mnt/upper/baz
+6: w--------- scratch/mnt/upper/bar
diff --git a/tests/bsd/type_w.sh b/tests/bsd/type_w.sh
new file mode 100644 (file)
index 0000000..d0cb58c
--- /dev/null
@@ -0,0 +1,64 @@
+# Only ffs supports whiteouts on FreeBSD
+command -v mdconfig &>/dev/null || skip
+command -v newfs &>/dev/null || skip
+
+cleanup=()
+do_cleanup() {
+    # Run cleanup hooks in reverse order
+    while ((${#cleanup[@]} > 0)); do
+        cmd="${cleanup[-1]}"
+        unset 'cleanup[-1]'
+        eval "bfs_sudo $cmd"
+    done
+}
+trap do_cleanup EXIT
+
+clean_scratch
+
+# Create a ramdisk
+truncate -s1M scratch/img
+md=$(bfs_sudo mdconfig scratch/img) || skip
+cleanup+=("mdconfig -du $md")
+
+# Make an ffs filesystem
+bfs_sudo newfs -n "/dev/$md" >&2 || skip
+mkdir scratch/mnt
+
+# Mount it
+bfs_sudo mount "/dev/$md" scratch/mnt || skip
+cleanup+=("umount scratch/mnt")
+
+# Make it owned by us
+bfs_sudo chown "$(id -u):$(id -g)" scratch/mnt
+"$XTOUCH" -p scratch/mnt/{lower/{foo,bar,baz},upper/{bar,baz/qux}}
+
+# Mount a union filesystem within it
+bfs_sudo mount -t unionfs -o below scratch/mnt/{lower,upper}
+cleanup+=("umount scratch/mnt/upper")
+
+# Create a whiteout
+rm scratch/mnt/upper/bar
+
+# FreeBSD find doesn't have -printf, so munge -ls output
+munge_ls() {
+    sed -En 's|.*([-drwx]{10}).*(scratch/.*)|'"$1"': \1 \2|p'
+}
+
+# Do a few tests in one
+{
+    # Normally, we shouldn't see the whiteouts
+    invoke_bfs scratch/mnt -ls | munge_ls 1
+    # -type w adds whiteouts to the output
+    invoke_bfs scratch/mnt -type w -ls | munge_ls 2
+    # So this is not the same as test 1
+    invoke_bfs scratch/mnt \( -type w -or -not -type w \) -ls | munge_ls 3
+    # Unmount the unionfs
+    bfs_sudo umount scratch/mnt/upper
+    unset 'cleanup[-1]'
+    # Now repeat the same tests
+    invoke_bfs scratch/mnt -ls | munge_ls 4
+    invoke_bfs scratch/mnt -type w -ls | munge_ls 5
+    invoke_bfs scratch/mnt \( -type w -or -not -type w \) -ls | munge_ls 6
+} >"$OUT"
+sort_output
+diff_output