summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-10-17 11:55:31 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-10-17 12:33:39 -0400
commitdd1c8c2f08d232d5745dc1f5fe483ec4072fe454 (patch)
treee4b1b5720d7df0bc3ca9aa0fb9fdc0d50636d019
parent68949cf1b9cb5336ea06ad7f87db8e28b620f2ac (diff)
downloadbfs-dd1c8c2f08d232d5745dc1f5fe483ec4072fe454.tar.xz
parse: Set BFTW_WHITEOUTS when parsing -type w
-rw-r--r--src/parse.c3
-rw-r--r--tests/bsd/type_w.out38
-rw-r--r--tests/bsd/type_w.sh64
3 files changed, 105 insertions, 0 deletions
diff --git a/src/parse.c b/src/parse.c
index 976f7cb..fafd787 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -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
index 0000000..d383f69
--- /dev/null
+++ b/tests/bsd/type_w.out
@@ -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
index 0000000..d0cb58c
--- /dev/null
+++ b/tests/bsd/type_w.sh
@@ -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