diff --git a/example/test.sh b/example/test.sh index 80bda65..53aceb5 100755 --- a/example/test.sh +++ b/example/test.sh @@ -109,9 +109,11 @@ test_mount() { work="$(mktemp -d)" img="slim-test-mount" share_dir="$work/share" + share_dir2="$work/share2" - mkdir -p "$share_dir" + mkdir -p "$share_dir" "$share_dir2" echo "hello from host" > "$share_dir/testfile.txt" + echo "second share" > "$share_dir2/testfile2.txt" cat > "$work/Containerfile" <<'EOF' FROM alpine:latest @@ -136,16 +138,20 @@ EOF # The 9p share appears at the same path inside the VM as on the host. # Use --cmd to run the verification snippet with the canonical path. share_canon=$(readlink -f "$share_dir") + share_canon2=$(readlink -f "$share_dir2") - echo "-- Booting VM with --mount $share_dir ..." + echo "-- Booting VM with --mount $share_dir --mount $share_dir2 ..." output=$(timeout "$TIMEOUT" "$SLIM_BIN" run "$img" \ --mount "$share_dir" \ - --cmd "echo Available 9p shares:; for f in /sys/bus/virtio/drivers/9pnet_virtio/virtio*/mount_tag; do [ -f \"\$f\" ] && echo \"\$f: \$(tr -d '\\0' < \"\$f\")\"; done; echo Mounts:; mount -v; cat \"${share_canon}/testfile.txt\" 2>/dev/null || echo NO_FILE; echo MOUNT_VERIFY_DONE; poweroff -f" \ + --mount "$share_dir2" \ + --cmd "echo Available 9p shares:; for f in /sys/bus/virtio/drivers/9pnet_virtio/virtio*/mount_tag; do [ -f \"\$f\" ] && echo \"\$f: \$(tr -d '\\0' < \"\$f\")\"; done; echo Mounts:; mount -v; cat \"${share_canon}/testfile.txt\" 2>/dev/null || echo NO_FILE; cat \"${share_canon2}/testfile2.txt\" 2>/dev/null || echo NO_FILE2; echo MOUNT_VERIFY_DONE; poweroff -f" \ 2>&1 || true) check_output "$output" "mount_tag: slim0" "--mount 9p share detected" + check_output "$output" "mount_tag: slim1" "--mount second 9p share detected" check_output "$output" "type 9p" "--mount 9p filesystem in mount list" check_output "$output" "hello from host" "--mount file accessible in VM" + check_output "$output" "second share" "--mount second share file accessible in VM" check_output "$output" "MOUNT_VERIFY_DONE" "--mount VM ran to completion" cleanup "$img" "$img" diff --git a/src/qemu.rs b/src/qemu.rs index e794f16..7780e01 100644 --- a/src/qemu.rs +++ b/src/qemu.rs @@ -101,9 +101,12 @@ pub(crate) fn run( let tag = format!("slim{i}"); let dest_b64 = base64::engine::general_purpose::STANDARD.encode(path_str.as_bytes()); + // QEMU's QemuOpts splits on commas — escape literal commas in the + // path as ",," per QEMU convention. + let path_escaped = path_str.replace(',', ",,"); virtfs_args.push("-virtfs".into()); virtfs_args.push(format!( - "local,path={path_str},mount_tag={tag},security_model=mapped-xattr" + "local,path={path_escaped},mount_tag={tag},security_model=mapped-xattr" )); cmdline.push(format!("slim.mount={tag}:{dest_b64}")); } diff --git a/src/scripts/slim-init.sh b/src/scripts/slim-init.sh index 7685e22..483dd6b 100644 --- a/src/scripts/slim-init.sh +++ b/src/scripts/slim-init.sh @@ -2,6 +2,11 @@ # slim universal init - distro-agnostic VM bootstrap. # Injected by `slim build` at /slim/init and invoked via init=/slim/init. +# === Helpers === +b64dec() { + printf '%s' "$1" | base64 -d 2>/dev/null || printf '%s' "$1" | openssl base64 -d 2>/dev/null +} + # === Devices & special filesystems === [ -c /dev/console ] || mknod -m 600 /dev/console c 5 1 mkdir -p /proc /sys /dev/pts /dev/shm @@ -45,9 +50,7 @@ for tok in $(cat /proc/cmdline 2>/dev/null); do v=${tok#slim.mount=} tag=${v%%:*} dest_b64=${v#*:} - dest=$(printf '%s' "$dest_b64" | base64 -d 2>/dev/null) \ - || dest=$(printf '%s' "$dest_b64" | openssl base64 -d 2>/dev/null) \ - || echo "base64 decode failed" + dest=$(b64dec "$dest_b64") || echo "base64 decode failed" if [ -n "$tag" ] && [ -n "$dest" ]; then mkdir -p "$dest" mount -t 9p "$tag" "$dest" -o trans=virtio,version=9p2000.L 2>/dev/null \ @@ -66,9 +69,7 @@ for tok in $(cat /proc/cmdline 2>/dev/null); do case "$tok" in slim.cmd=*) v=${tok#slim.cmd=} - decoded=$(printf '%s' "$v" | base64 -d 2>/dev/null) \ - || decoded=$(printf '%s' "$v" | openssl base64 -d 2>/dev/null) \ - || echo "base64 decode failed" + decoded=$(b64dec "$v") || echo "base64 decode failed" if [ -n "$decoded" ]; then exec /bin/sh -c "$decoded" fi