diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d24cac9b9..1e6603fb9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -240,7 +240,7 @@ jobs:
run: >
dotnet test Compression.Tests
--configuration Release --no-build
- --filter "FullyQualifiedName~Compression.Tests.Reiser4.Reiser4ProfileExternalTests|FullyQualifiedName~Compression.Tests.Reiser4.Reiser4MutationExternalTests|FullyQualifiedName~Compression.Tests.Reiser4.Reiser4NativeTreeExternalTests"
+ --filter "FullyQualifiedName~Compression.Tests.Reiser4.Reiser4ProfileExternalTests|FullyQualifiedName~Compression.Tests.Reiser4.Reiser4MutationExternalTests|FullyQualifiedName~Compression.Tests.Reiser4.Reiser4NativeTreeExternalTests|FullyQualifiedName~Compression.Tests.Reiser4.Reiser4FeatureExternalTests"
--logger "trx;LogFileName=reiser4-oracle-tests.trx"
# bcachefs-tools' own checker judges every volume this package writes or
diff --git a/Compression.Tests/Compression.Tests.csproj b/Compression.Tests/Compression.Tests.csproj
index 70f1d79a1..428d92d14 100644
--- a/Compression.Tests/Compression.Tests.csproj
+++ b/Compression.Tests/Compression.Tests.csproj
@@ -67,6 +67,13 @@
Exclude="StructuredPseudoArchives\ReferenceVectors\*.py;StructuredPseudoArchives\ReferenceVectors\*.pl;StructuredPseudoArchives\ReferenceVectors\*.ps1;StructuredPseudoArchives\ReferenceVectors\README.md">
ReferenceVectors.%(Filename)%(Extension)
+
+
+ Reiser4Vectors.%(Filename)%(Extension)
+
+
+
BtrfsVectors.%(Filename)%(Extension)
diff --git a/Compression.Tests/FirmwareHex/FirmwareHexPayloadTests.cs b/Compression.Tests/FirmwareHex/FirmwareHexPayloadTests.cs
new file mode 100644
index 000000000..bbbc898af
--- /dev/null
+++ b/Compression.Tests/FirmwareHex/FirmwareHexPayloadTests.cs
@@ -0,0 +1,37 @@
+using Compression.Registry;
+using FileFormat.FirmwareHex;
+
+namespace Compression.Tests.FirmwareHex;
+
+[TestFixture]
+public sealed class FirmwareHexPayloadTests {
+ [TestCase(false)]
+ [TestCase(true)]
+ public void Create_RejectsMultiplePayloadsWithoutWritingOutput(bool emptyFirst) {
+ var descriptor = new IntelHexFormatDescriptor();
+ using var output = new MemoryStream();
+ var inputs = new[] {
+ ArchiveInputInfo.InMemory("first.bin", emptyFirst ? [] : [1, 2, 3]),
+ ArchiveInputInfo.InMemory("second.bin", [9, 8, 7]),
+ };
+
+ Assert.Throws(() =>
+ ((IArchiveCreatable)descriptor).Create(output, inputs, new FormatCreateOptions()));
+ Assert.That(output.Length, Is.Zero);
+ }
+
+ [Test]
+ public void Add_RejectsAnotherPayloadWithoutChangingTheArchive() {
+ var descriptor = new IntelHexFormatDescriptor();
+ using var archive = new MemoryStream();
+ ((IArchiveCreatable)descriptor).Create(archive,
+ [ArchiveInputInfo.InMemory("firmware.bin", [1, 2, 3])], new FormatCreateOptions());
+ var original = archive.ToArray();
+ archive.Position = 0;
+
+ Assert.Throws(() => ((IArchiveModifiable)descriptor).Add(archive,
+ [ArchiveInputInfo.InMemory("ADD.BIN", [9, 8, 7])]));
+ Assert.That(archive.ToArray(), Is.EqualTo(original));
+ }
+
+}
diff --git a/Compression.Tests/Reiser4/KernelOracle/.gitattributes b/Compression.Tests/Reiser4/KernelOracle/.gitattributes
new file mode 100644
index 000000000..3b14496fb
--- /dev/null
+++ b/Compression.Tests/Reiser4/KernelOracle/.gitattributes
@@ -0,0 +1,2 @@
+# Run by bash under Linux or WSL.
+*.sh text eol=lf
diff --git a/Compression.Tests/Reiser4/KernelOracle/kernel-run.sh b/Compression.Tests/Reiser4/KernelOracle/kernel-run.sh
new file mode 100644
index 000000000..cd4d5eb1f
--- /dev/null
+++ b/Compression.Tests/Reiser4/KernelOracle/kernel-run.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+# Boots a Reiser4-enabled Linux kernel under QEMU with an image as /dev/vda and runs a shell
+# script inside it; the script's output is printed between ===GUEST-BEGIN=== and ===GUEST-END===.
+#
+# kernel-run.sh [payload-dir]
+#
+# The kernel is Metztli's Debian build of Linux 5.4.18 with the Reiser4 (SFRN 4.0.2) patch
+# (linux-image-5.4.0-3+reizer4.0.2-cloud-amd64). It is fetched once into $CWB_REISER4_KERNEL
+# (default ~/.cache/cwb/reiser4-kernel) together with Ubuntu's busybox-static for the initramfs.
+# Nothing here is a build input: the tests that use it skip when it cannot run.
+set -e
+K=${CWB_REISER4_KERNEL:-$HOME/.cache/cwb/reiser4-kernel}
+KV=5.4.0-3+reizer4.0.2-cloud-amd64
+DEB_URL='https://sourceforge.net/projects/metztli-reiser4/files/RyzenEpyc_Reiser4-SFRN-4.0.2_Linux-5.4.18-1_for-Debian_Buster/linux-image-5.4.0-3%2Breizer4.0.2-cloud-amd64_5.4.18-1%2Breizer4.0.2_amd64.deb/download'
+
+if [ "$1" = "--check" ]; then
+ [ -f "$K/x/boot/vmlinuz-$KV" ] && [ -x "$K/bb/usr/bin/busybox" ] && command -v qemu-system-x86_64 >/dev/null
+ exit $?
+fi
+if [ "$1" = "--prepare" ]; then
+ mkdir -p "$K"
+ if [ ! -f "$K/x/boot/vmlinuz-$KV" ]; then
+ curl -sfL -A "Wget/1.21" -o "$K/kernel.deb" "$DEB_URL"
+ mkdir -p "$K/x" && dpkg-deb -x "$K/kernel.deb" "$K/x"
+ fi
+ if [ ! -x "$K/bb/usr/bin/busybox" ]; then
+ (cd "$K" && apt-get download busybox-static >/dev/null 2>&1 && mkdir -p bb && dpkg-deb -x busybox-static*.deb bb)
+ fi
+ [ -f "$K/x/boot/vmlinuz-$KV" ] && [ -x "$K/bb/usr/bin/busybox" ] && command -v qemu-system-x86_64 >/dev/null
+ exit $?
+fi
+
+M=$K/x/lib/modules/$KV/kernel
+R=$(mktemp -d)
+trap 'rm -rf "$R" "$R.cpio.gz" "$R.log"' EXIT
+mkdir -p "$R/bin" "$R/mods" "$R/dev" "$R/proc" "$R/sys" "$R/mnt" "$R/payload"
+cp "$K/bb/usr/bin/busybox" "$R/bin/"
+for a in $("$K/bb/usr/bin/busybox" --list); do [ "$a" = busybox ] || ln -s busybox "$R/bin/$a"; done
+for m in drivers/virtio/virtio.ko drivers/virtio/virtio_ring.ko drivers/virtio/virtio_pci.ko drivers/block/virtio_blk.ko \
+ lib/xxhash.ko lib/zstd/zstd_compress.ko lib/zstd/zstd_decompress.ko crypto/crc32c_generic.ko fs/reiser4/reiser4.ko; do
+ cp "$M/$m" "$R/mods/"
+done
+cp "$2" "$R/run.sh"
+[ -n "$3" ] && cp -a "$3"/. "$R/payload/"
+cat > "$R/init" <<'EOF'
+#!/bin/busybox sh
+export PATH=/bin
+mount -t proc proc /proc; mount -t sysfs sys /sys; mount -t devtmpfs dev /dev
+echo "===GUEST-BEGIN==="
+for m in virtio virtio_ring virtio_pci virtio_blk xxhash zstd_compress zstd_decompress crc32c_generic reiser4; do
+ insmod /mods/$m.ko || echo "insmod $m failed"
+done
+sleep 0.3
+sh /run.sh 2>&1
+echo "===GUEST-END rc=$?==="
+dmesg | grep -i -E "reiser4|bug|oops" | grep -v "loading out-of-tree" | sed 's/^/dmesg: /'
+sync
+poweroff -f
+EOF
+chmod +x "$R/init"
+(cd "$R" && find . | cpio -o -H newc 2>/dev/null | gzip -1) > "$R.cpio.gz"
+ACC=-enable-kvm; [ -w /dev/kvm ] || ACC="-accel tcg"
+timeout ${CWB_REISER4_KERNEL_TIMEOUT:-900} qemu-system-x86_64 $ACC -m 1024 -nographic -no-reboot \
+ -kernel "$K/x/boot/vmlinuz-$KV" -initrd "$R.cpio.gz" \
+ -append "console=ttyS0 quiet panic=-1" \
+ -drive file="$1",format=raw,if=virtio,cache=unsafe 2>&1 | tr -d '\r' > "$R.log" || true
+sed -n '/===GUEST-BEGIN===/,$p' "$R.log" | grep -v '^\s*$'
+grep -q '===GUEST-END' "$R.log"
diff --git a/Compression.Tests/Reiser4/KernelOracle/manifest.sh b/Compression.Tests/Reiser4/KernelOracle/manifest.sh
new file mode 100644
index 000000000..497b08a89
--- /dev/null
+++ b/Compression.Tests/Reiser4/KernelOracle/manifest.sh
@@ -0,0 +1,14 @@
+# Guest script: mounts /dev/vda and prints one line per object the kernel resolves, reading every
+# regular file whole: path|type|mode|uid|gid|size|nlink|mtime|major:minor|md5-or-link-target
+mount -t reiser4 /dev/vda /mnt || { echo MOUNTFAIL; exit 1; }
+cd /mnt
+echo "===MANIFEST==="
+find . | sort | while read p; do
+ t=$(stat -c '%F|%a|%u|%g|%s|%h|%Y|%t:%T' "$p")
+ if [ -L "$p" ]; then echo "$p|$t|$(readlink "$p")"
+ elif [ -f "$p" ]; then echo "$p|$t|$(md5sum < "$p" | cut -d' ' -f1)"
+ else echo "$p|$t|"; fi
+done
+echo "===END-MANIFEST==="
+cd /
+umount /mnt || echo UMOUNTFAIL
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/.gitattributes b/Compression.Tests/Reiser4/ReferenceVectors/.gitattributes
new file mode 100644
index 000000000..95db9d93d
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/.gitattributes
@@ -0,0 +1,5 @@
+# Volumes a Reiser4 kernel wrote, gzip-compressed: the bytes are the fixture.
+*.gz -text
+# Manifests and scripts are read by Linux tools and compared byte for byte.
+*.manifest text eol=lf
+*.sh text eol=lf
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/README.md b/Compression.Tests/Reiser4/ReferenceVectors/README.md
new file mode 100644
index 000000000..c275cf8a1
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/README.md
@@ -0,0 +1,41 @@
+# Reiser4 reference volumes
+
+Volumes a Reiser4 kernel wrote, checked in so the reader and editor tests run without Linux tools.
+`generate.sh` documents how they were made; it is not a build input.
+
+Each volume was formatted by `mkfs.reiser4 -fffy` (reiser4progs 1.2.2, 16 MiB, UUID
+`11111111-2222-3333-4444-555555555555`) with the plugin options below, then filled by `populate.sh`
+inside the kernel — Metztli's Debian build of Linux 5.4.18 with the Reiser4 SFRN 4.0.2 patch
+(`linux-image-5.4.0-3+reizer4.0.2-cloud-amd64`), booted under QEMU by
+`../KernelOracle/kernel-run.sh`. The tree holds files of 0 to 200 705 bytes (random, and a 69 559-byte text that spans two 64 KiB clusters), nested
+and empty directories, names of 35, 46 and 255 bytes, names ending in `.c`, `.o` and `.abc`,
+a short and a 423-byte symlink, a file with three names, a FIFO, character device 1:3, block device
+7:0, a file with a hole, a 300-entry directory, an owner of 1234:5678 with mode 0751, and a
+modification time in 2001.
+
+| File | mkfs.reiser4 options | What it exercises |
+|------|------------------|-------------------|
+| `default` | — | cryptcompress files (lzo1, conv mode, 64 KiB clusters), the kernel turning incompressible ones into extents |
+| `gzip1-force-8k` | `compress=gzip1,compressMode=force,cluster=8K` | raw-deflate clusters with their Adler-32 |
+| `zstd1-latt-16k` | `compress=zstd1,compressMode=latt,cluster=16K` | Zstandard clusters |
+| `lzo1-none-4k` | `compressMode=none,cluster=4K` | uncompressed clusters |
+| `reg40-smart` | `create=reg40` | tails up to four blocks, extents above |
+| `reg40-tails` | `create=reg40,formatting=tails` | tails only |
+| `reg40-node41` | `create=reg40,formatting=extents,node=node41` | checksummed nodes, extents only |
+| `node41` | `node=node41` | checksummed nodes with cryptcompress files |
+| `tea-lexic` | `create=reg40,hash=tea_hash,fibration=lexic_fibre` | TEA-hashed long names, no fibres |
+| `fnv1-dot-o` | `create=reg40,hash=fnv1_hash,fibration=dot_o_fibre` | FNV-1 long names, `.o` fibre |
+| `deg-ext-3` | `create=reg40,hash=deg_hash,fibration=ext_3_fibre` | degenerate hash, three-letter extension fibres |
+| `rupasov` | `create=reg40,hash=rupasov_hash` | read only: `fsck.reiser4` disagrees with the kernel's Rupasov keys |
+| `journal-replay` | `create=reg40` | a commit the kernel had not yet written back: block 19 names transaction 181, block 20 transaction 130 |
+
+`.manifest` is what the kernel read back after unmounting and mounting again: one line per
+object, `path|type|mode|uid|gid|size|nlink|mtime|major:minor|md5-or-link-target`, every regular file
+read whole. For `journal-replay` the kernel replayed the journal at mount, so the manifest is the
+post-replay state. `default` and `node41` list two fewer `many/` files than the others and
+`gzip1-force-8k` one fewer: the kernel itself did not keep them, and the reader agrees with what it
+did keep.
+
+Every volume except `rupasov` passed `fsck.reiser4 --check` (`journal-replay` after the replay that
+check performs). Captured 2026-10-19 on Ubuntu 24.04 under WSL2 (the WSL kernel has no Reiser4
+driver; the QEMU guest is the only writer). Compressed with `gzip -9 -n`.
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/default.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/default.img.gz
new file mode 100644
index 000000000..4b89e0358
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/default.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/default.manifest b/Compression.Tests/Reiser4/ReferenceVectors/default.manifest
new file mode 100644
index 000000000..3029c1d38
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/default.manifest
@@ -0,0 +1,325 @@
+.|directory|755|1000|1000|19|6|1792402634|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402634|7:0|
+./chardev|character special file|644|0|0|0|1|1792402634|1:3|
+./dir|directory|755|0|0|9|3|1792402634|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402634|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402634|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402634|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402634|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402634|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402634|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402634|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402634|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402634|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402634|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402634|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402634|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402634|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402634|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402634|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402634|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402634|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402634|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|300|2|1792402635|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402634|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402634|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402634|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402634|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402634|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402634|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402634|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402634|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402634|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402634|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402634|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402634|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402634|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402634|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402634|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402634|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402634|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402634|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402634|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402634|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402634|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402634|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402634|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402634|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402634|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402634|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402634|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402634|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402634|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402634|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402634|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402634|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402634|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402634|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402634|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402634|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402634|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402634|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402634|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402634|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402634|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402634|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402634|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402634|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402634|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402634|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402634|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402634|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402634|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402634|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402634|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402634|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402634|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402634|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402634|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402634|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402634|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402634|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402634|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402634|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402634|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402634|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402634|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402634|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402634|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402634|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402634|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402634|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402634|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402634|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402634|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402634|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402634|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402634|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402634|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402634|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402634|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402634|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402634|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402634|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402634|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402634|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402634|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402634|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402634|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m176|regular file|644|0|0|9|1|1792402635|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402635|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402635|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402635|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402634|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402635|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402635|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402635|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402635|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402635|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402635|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402635|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402635|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402635|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402635|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402634|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402635|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402635|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402635|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402635|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402635|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402635|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402635|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402635|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402635|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402635|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402634|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402634|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402635|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402635|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402635|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402635|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402635|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402635|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402635|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402635|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402635|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402635|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402634|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402635|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402635|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402635|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402635|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402635|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402635|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402635|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402635|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402635|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402635|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402634|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402635|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402635|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402635|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402635|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402635|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402635|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402635|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402635|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402635|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402635|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402634|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402635|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402635|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402635|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402635|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402635|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402635|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402635|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402635|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402635|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402635|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402634|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402635|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402635|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402635|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402635|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402635|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402635|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402635|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402635|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402635|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402635|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402634|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402635|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402635|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402635|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402635|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402635|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402635|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402635|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402635|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402635|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402635|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402634|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402635|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402635|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402635|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402635|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402635|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402635|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402635|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402635|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402635|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402635|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402634|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402635|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m272|regular file|644|0|0|9|1|1792402635|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402635|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402635|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402635|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402635|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402635|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402635|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402635|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402634|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402635|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402635|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402635|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402635|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402635|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402635|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402635|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402635|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402635|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402635|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402634|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402635|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402635|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402635|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402635|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402635|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402635|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402635|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402635|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402635|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402635|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402634|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402634|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402634|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402634|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402634|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402634|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402634|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402634|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402634|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402634|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402634|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402634|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402634|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402634|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402634|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402634|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402634|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402634|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402634|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402634|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402634|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402634|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402634|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402634|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402634|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402634|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402634|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402634|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402634|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402634|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402634|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402634|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402634|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402634|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402634|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402634|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402634|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402634|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402634|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402634|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402634|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402634|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402634|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402634|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402634|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402634|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402634|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402634|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402634|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402634|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402634|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402634|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402634|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402634|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402634|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402634|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402634|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402634|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402634|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402634|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402634|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402634|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402634|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402634|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402634|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402634|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402634|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402634|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402634|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402634|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402634|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402634|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402634|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402634|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402634|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402634|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402634|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402634|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402634|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402634|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.img.gz
new file mode 100644
index 000000000..a9d67f2b4
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.manifest b/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.manifest
new file mode 100644
index 000000000..ddf098b85
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/deg-ext-3.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402840|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402840|7:0|
+./chardev|character special file|644|0|0|0|1|1792402840|1:3|
+./dir|directory|755|0|0|9|3|1792402840|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402840|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402840|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402840|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402840|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402840|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402840|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402840|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402840|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402840|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402840|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402840|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402840|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402840|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402840|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402840|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402840|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402840|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402840|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402840|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402840|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402840|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402840|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402840|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402840|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402840|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402840|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402840|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402840|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402840|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402840|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402840|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402840|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402840|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402840|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402840|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402840|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402840|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402840|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402840|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402840|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402840|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402840|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402840|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402840|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402840|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402840|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402840|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402840|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402840|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402840|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402840|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402840|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402840|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402840|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402840|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402840|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402840|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402840|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402840|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402840|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402840|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402840|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402840|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402840|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402840|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402840|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402840|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402840|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402840|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402840|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402840|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402840|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402840|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402840|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402840|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402840|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402840|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402840|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402840|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402840|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402840|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402840|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402840|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402840|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402840|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402840|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402840|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402840|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402840|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402840|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402840|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402840|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402840|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402840|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402840|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402840|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402840|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402840|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402840|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402840|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402840|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402840|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402840|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402840|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402840|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402840|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402840|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402840|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402840|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402840|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402840|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402840|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402840|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402840|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402840|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402840|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402840|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402840|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402840|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402840|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402840|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402840|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402840|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402840|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402840|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402840|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402840|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402840|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402840|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402840|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402840|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402840|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402840|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402840|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402840|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402840|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402840|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402840|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402840|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402840|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402840|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402840|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402840|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402840|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402840|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402840|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402840|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402840|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402840|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402840|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402840|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402840|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402840|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402840|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402840|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402840|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402840|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402840|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402840|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402840|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402840|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402840|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402840|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402840|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402840|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402840|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402840|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402840|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402840|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402840|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402840|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402840|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402840|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402840|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402840|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402840|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402840|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402840|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402840|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402840|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402840|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402840|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402840|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402840|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402840|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402840|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402840|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402840|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402840|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402840|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402840|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402840|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402840|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402840|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402840|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402840|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402840|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402840|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402840|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402840|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402840|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402840|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402840|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402840|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402840|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402840|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402840|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402840|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402840|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402840|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402840|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402840|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402840|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402840|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402840|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402840|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402840|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402840|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402840|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402840|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402840|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402840|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402840|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402840|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402840|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402840|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402840|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402840|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402840|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402840|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402840|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402840|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402840|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402840|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402840|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402840|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402840|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402840|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402840|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402840|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402840|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402840|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402840|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402840|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402840|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402840|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402840|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402840|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402840|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402840|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402840|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402840|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402840|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402840|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402840|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402840|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402840|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402840|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402840|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402840|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402840|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402840|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402840|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402840|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402840|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402840|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402840|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402840|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402840|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402840|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402840|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402840|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402840|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402840|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402840|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402840|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402840|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402840|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402840|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402840|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402840|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402840|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402840|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402840|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402840|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402840|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402840|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402840|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402840|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402840|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402840|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402840|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402840|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402840|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402840|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402840|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402840|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402840|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402840|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402840|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402840|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402840|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402840|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402840|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402840|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402840|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402840|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402840|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402840|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402840|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402840|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402840|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402840|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402840|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402840|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402840|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402840|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402840|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402840|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402840|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402840|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402840|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.img.gz
new file mode 100644
index 000000000..cfab1b7bb
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.manifest b/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.manifest
new file mode 100644
index 000000000..70f10dcfe
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/fnv1-dot-o.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402821|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402821|7:0|
+./chardev|character special file|644|0|0|0|1|1792402821|1:3|
+./dir|directory|755|0|0|9|3|1792402821|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402821|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402821|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402821|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402821|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402821|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402821|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402821|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402821|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402821|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402821|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402821|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402821|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402821|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402821|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402821|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402821|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402821|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402821|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402821|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402821|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402821|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402821|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402821|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402821|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402821|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402821|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402821|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402821|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402821|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402821|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402821|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402821|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402821|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402821|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402821|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402821|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402821|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402821|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402821|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402821|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402821|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402821|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402821|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402821|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402821|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402821|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402821|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402821|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402821|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402821|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402821|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402821|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402821|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402821|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402821|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402821|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402821|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402821|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402821|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402821|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402821|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402821|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402821|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402821|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402821|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402821|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402821|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402821|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402821|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402821|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402821|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402821|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402821|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402821|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402821|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402821|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402821|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402821|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402821|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402821|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402821|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402821|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402821|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402821|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402821|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402821|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402821|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402821|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402821|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402821|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402821|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402821|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402821|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402821|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402821|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402821|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402821|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402821|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402821|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402821|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402821|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402821|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402821|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402821|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402821|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402821|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402821|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402821|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402821|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402821|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402821|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402821|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402821|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402821|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402821|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402821|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402821|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402821|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402821|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402821|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402821|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402821|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402821|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402821|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402821|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402821|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402821|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402821|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402821|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402821|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402821|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402821|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402821|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402821|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402821|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402821|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402821|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402821|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402821|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402821|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402821|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402821|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402821|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402821|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402821|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402821|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402821|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402821|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402821|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402821|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402821|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402821|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402821|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402821|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402821|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402821|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402821|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402821|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402821|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402821|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402821|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402821|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402821|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402821|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402821|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402821|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402821|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402821|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402821|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402821|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402821|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402821|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402821|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402821|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402821|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402821|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402821|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402821|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402821|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402821|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402821|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402821|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402821|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402821|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402821|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402821|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402821|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402821|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402821|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402821|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402821|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402821|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402821|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402821|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402821|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402821|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402821|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402821|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402821|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402821|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402821|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402821|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402821|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402821|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402821|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402821|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402821|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402821|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402821|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402821|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402821|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402821|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402821|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402821|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402821|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402821|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402821|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402821|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402821|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402821|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402821|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402821|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402821|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402821|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402821|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402821|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402821|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402821|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402821|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402821|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402821|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402821|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402821|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402821|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402821|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402821|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402821|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402821|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402821|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402821|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402821|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402821|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402821|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402821|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402821|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402821|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402821|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402821|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402821|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402821|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402821|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402821|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402821|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402821|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402821|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402821|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402821|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402821|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402821|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402821|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402821|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402821|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402821|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402821|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402821|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402821|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402821|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402821|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402821|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402821|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402821|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402821|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402821|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402821|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402821|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402821|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402821|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402821|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402821|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402821|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402821|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402821|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402821|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402821|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402821|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402821|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402821|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402821|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402821|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402821|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402821|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402821|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402821|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402821|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402821|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402821|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402821|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402821|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402821|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402821|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402821|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402821|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402821|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402821|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402821|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402821|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402821|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402821|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402821|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402821|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402821|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402821|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402821|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402821|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402821|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402821|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402821|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402821|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402821|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402821|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402821|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402821|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/generate.sh b/Compression.Tests/Reiser4/ReferenceVectors/generate.sh
new file mode 100644
index 000000000..de6371067
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/generate.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+# Regenerates the Reiser4 reference volumes: mkfs.reiser4 (reiser4progs 1.2.2) formats each one
+# with a plugin profile, a Reiser4 kernel fills it through its own write path (populate.sh, run by
+# ../KernelOracle/kernel-run.sh), and the kernel's read-back is kept as .manifest.
+# journal-replay.img is captured between a kernel commit and its write-back. Documentation, not a
+# build input; run from this directory under Linux or WSL with qemu-system-x86_64.
+set -e
+HERE=$(cd "$(dirname "$0")" && pwd)
+RUN="$HERE/../KernelOracle/kernel-run.sh"
+bash "$RUN" --prepare
+W=$(mktemp -d)
+trap 'rm -rf "$W"' EXIT
+mkdir -p "$W/payload"
+for n in 0 1 100 4095 4096 4097; do head -c $n /dev/urandom > "$W/payload/f_$n"; done
+for i in $(seq 1 1200); do echo "line $i: the quick brown fox jumps over the lazy dog $((i*7919 % 1000))"; done > "$W/payload/f_text"
+
+volume() {
+ local name=$1; shift
+ truncate -s 0 "$W/$name.img"; truncate -s 16M "$W/$name.img"
+ mkfs.reiser4 -fffy -U 11111111-2222-3333-4444-555555555555 -L ref "$@" "$W/$name.img" >/dev/null
+ bash "$RUN" "$W/$name.img" "$HERE/populate.sh" "$W/payload" > "$W/$name.log"
+ sed -n '/===MANIFEST===/,/===END-MANIFEST===/p' "$W/$name.log" | grep -v '===' > "$HERE/$name.manifest"
+ gzip -9 -n -c "$W/$name.img" > "$HERE/$name.img.gz"
+ echo "$name: $(wc -l < "$HERE/$name.manifest") objects; $(fsck.reiser4 --check -y "$W/$name.img" 2>&1 | grep -E 'consistent|corrupt' | head -1)"
+}
+
+if [ -z "$JOURNAL_ONLY" ]; then
+volume default
+volume gzip1-force-8k -o compress=gzip1,compressMode=force,cluster=8K
+volume zstd1-latt-16k -o compress=zstd1,compressMode=latt,cluster=16K
+volume lzo1-none-4k -o compressMode=none,cluster=4K
+volume reg40-smart -o create=reg40
+volume reg40-tails -o create=reg40,formatting=tails
+volume reg40-node41 -o create=reg40,formatting=extents,node=node41
+volume node41 -o node=node41
+volume tea-lexic -o create=reg40,hash=tea_hash,fibration=lexic_fibre
+volume fnv1-dot-o -o create=reg40,hash=fnv1_hash,fibration=dot_o_fibre
+volume deg-ext-3 -o create=reg40,hash=deg_hash,fibration=ext_3_fibre
+volume rupasov -o create=reg40,hash=rupasov_hash
+fi
+
+# A transaction the kernel committed but had not yet written back: writes are throttled so the
+# write-back takes seconds, and the image is copied the moment the journal header moves past the
+# footer.
+cat > "$W/journal.sh" <<'EOF'
+mount -t reiser4 /dev/vda /mnt || exit 1
+i=0; while [ $i -lt 10 ]; do head -c 40000 /payload/f_text > /mnt/big$i; echo "small $i" > /mnt/s$i; i=$((i+1)); done
+mkdir /mnt/dir
+sync
+i=0; while [ $i -lt 10 ]; do dd if=/payload/f_text of=/mnt/big$i bs=4096 skip=$((i+1)) seek=2 count=5 conv=notrunc 2>/dev/null; echo "changed $i" > /mnt/s$i; mv /mnt/s$i /mnt/dir/; i=$((i+1)); done
+sync
+umount /mnt
+EOF
+sed 's/cache=unsafe/cache=unsafe,throttling.bps-write=100000/' "$RUN" > "$W/slow.sh"
+# A capture counts only when it is a later commit (the footer has moved once), fsck.reiser4 replays
+# it to a consistent volume, and the kernel mounts it.
+for attempt in $(seq 1 12); do
+ truncate -s 0 "$W/j.img"; truncate -s 16M "$W/j.img"
+ mkfs.reiser4 -fffy -U 11111111-2222-3333-4444-555555555555 -L journal -o create=reg40 "$W/j.img" >/dev/null
+ rm -f "$W/journal-replay.img"
+ ( bash "$W/slow.sh" "$W/j.img" "$W/journal.sh" "$W/payload" > /dev/null ) &
+ P=$!
+ while kill -0 $P 2>/dev/null; do
+ c=$(od -An -t u8 -j $((19*4096)) -N 8 "$W/j.img" | tr -d ' ')
+ f=$(od -An -t u8 -j $((20*4096)) -N 8 "$W/j.img" | tr -d ' ')
+ if [ "$c" != "$f" ] && [ "$f" != "0" ]; then cp "$W/j.img" "$W/journal-replay.img"; break; fi
+ sleep 0.02
+ done
+ wait $P
+ [ -f "$W/journal-replay.img" ] || continue
+ cp "$W/journal-replay.img" "$W/f.img"
+ fsck.reiser4 --check -y "$W/f.img" > "$W/f.log" 2>&1 || true
+ grep -q "Replaying transaction" "$W/f.log" && grep -q "FS is consistent" "$W/f.log" || continue
+ cp "$W/journal-replay.img" "$W/k.img"
+ bash "$RUN" "$W/k.img" "$HERE/../KernelOracle/manifest.sh" > "$W/k.log"
+ sed -n '/===MANIFEST===/,/===END-MANIFEST===/p' "$W/k.log" | grep -v '===' > "$W/journal-replay.manifest"
+ grep -q '^./big9|' "$W/journal-replay.manifest" && break
+done
+cp "$W/journal-replay.manifest" "$HERE/journal-replay.manifest"
+gzip -9 -n -c "$W/journal-replay.img" > "$HERE/journal-replay.img.gz"
+echo "journal-replay: $(debugfs.reiser4 -j "$W/journal-replay.img" /dev/null | grep last | tr '\n' ' ')"
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.img.gz
new file mode 100644
index 000000000..92212c3bf
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.manifest b/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.manifest
new file mode 100644
index 000000000..efdff7294
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/gzip1-force-8k.manifest
@@ -0,0 +1,326 @@
+.|directory|755|1000|1000|19|6|1792402650|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402650|7:0|
+./chardev|character special file|644|0|0|0|1|1792402650|1:3|
+./dir|directory|755|0|0|9|3|1792402650|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402650|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402650|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402650|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402650|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402650|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402650|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402650|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402650|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402650|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402650|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402650|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402650|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402650|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402650|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402650|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402650|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402650|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402650|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|301|2|1792402651|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402650|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402650|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402650|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402650|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402650|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402650|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402650|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402650|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402650|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402650|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402650|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402650|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402650|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402650|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402650|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402650|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402650|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402650|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402650|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402650|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402650|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402650|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402650|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402650|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402650|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402650|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402650|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402650|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402650|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402650|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402650|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402650|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402650|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402650|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402650|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402650|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402650|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402650|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402650|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402650|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402650|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402650|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402650|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402650|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402650|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402650|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402650|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402650|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402650|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402650|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402650|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402650|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402650|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402650|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402650|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402650|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402650|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402650|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402650|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402650|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402650|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402650|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402650|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402650|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402650|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402650|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402650|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402650|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402650|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402650|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402650|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402650|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402650|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402650|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402650|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402650|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402650|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402650|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402650|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402650|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402650|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402650|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402650|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402650|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402650|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402650|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402650|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402650|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402650|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402650|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402650|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402650|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402650|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402650|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402650|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402650|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402650|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402650|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402650|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402650|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402650|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402650|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402650|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402650|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402650|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402650|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402650|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402650|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402650|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402650|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402650|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402650|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402650|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402650|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402650|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402650|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402650|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402650|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402650|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402650|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402650|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402650|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402650|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402650|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402650|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402650|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402650|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402650|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402650|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402650|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402650|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402650|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402650|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402650|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402650|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402650|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402650|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402650|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402650|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402650|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402650|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402650|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402650|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402650|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402650|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402650|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402650|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402650|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402650|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402650|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402650|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402650|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402650|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402650|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402650|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402650|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402650|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402650|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402650|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402650|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402650|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402650|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402650|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402650|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402650|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402650|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402650|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402650|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402650|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402650|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402650|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402650|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402650|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402650|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402650|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402650|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402650|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402650|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402650|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402650|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402650|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402650|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402650|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402650|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402650|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402650|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402651|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402651|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402651|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402651|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402650|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402651|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402651|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402651|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402651|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402651|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402651|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402651|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402651|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402651|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402651|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402650|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402651|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402651|0:0|8732532455011bf125603f98ff251200
+./many/m283|regular file|644|0|0|9|1|1792402651|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402651|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402651|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402651|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402651|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402651|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402651|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402650|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402651|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402651|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402651|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402651|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402651|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402651|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402651|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402651|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402651|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402651|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402650|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402650|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402650|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402650|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402650|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402650|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402650|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402650|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402650|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402650|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402650|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402650|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402650|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402650|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402650|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402650|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402650|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402650|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402650|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402650|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402650|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402650|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402650|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402650|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402650|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402650|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402650|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402650|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402650|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402650|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402650|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402650|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402650|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402650|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402650|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402650|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402650|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402650|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402650|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402650|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402650|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402650|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402650|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402650|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402650|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402650|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402650|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402650|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402650|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402650|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402650|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402650|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402650|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402650|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402650|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402650|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402650|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402650|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402650|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402650|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402650|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402650|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402650|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402650|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402650|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402650|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402650|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402650|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402650|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402650|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402650|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402650|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402650|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402650|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402650|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402650|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402650|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402650|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402650|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402650|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.img.gz
new file mode 100644
index 000000000..538f7dd4c
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.manifest b/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.manifest
new file mode 100644
index 000000000..b803902b0
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/journal-replay.manifest
@@ -0,0 +1,22 @@
+.|directory|755|1000|1000|13|4|1792403737|0:0|
+./big0|regular file|644|0|0|40000|1|1792403737|0:0|166bb66b12fbf03ba0e3202ce39932c6
+./big1|regular file|644|0|0|40000|1|1792403737|0:0|357da225bb3383d31eadf6e95ab7920b
+./big2|regular file|644|0|0|40000|1|1792403737|0:0|2a83d68011654889aab2c9da5fc1e875
+./big3|regular file|644|0|0|40000|1|1792403737|0:0|3bae70f526d3657dc517dea0db06a140
+./big4|regular file|644|0|0|40000|1|1792403737|0:0|1738c13dc76f07ab319387ca93e6639a
+./big5|regular file|644|0|0|40000|1|1792403737|0:0|804ce007a9f540c27f02f825b77d73a1
+./big6|regular file|644|0|0|40000|1|1792403737|0:0|8338ed00ccc09019d816c7f2ad2bbd64
+./big7|regular file|644|0|0|40000|1|1792403737|0:0|58b1b6f7ab1c3bc83ca568c2a1d43774
+./big8|regular file|644|0|0|40000|1|1792403737|0:0|09307109dcdadc8a429063e184746d63
+./big9|regular file|644|0|0|40000|1|1792403737|0:0|b892ad0e91dcb7ecbc7c1a3d77e6f25f
+./dir|directory|755|0|0|12|2|1792403737|0:0|
+./dir/s0|regular file|644|0|0|10|1|1792403737|0:0|ce7f640ff83d98c84d3a1ceb6ef77b38
+./dir/s1|regular file|644|0|0|10|1|1792403737|0:0|dc7f7f95ae678a4e7046c046058bd277
+./dir/s2|regular file|644|0|0|10|1|1792403737|0:0|68fa42caa09fdb6ac99071cdfc363f8c
+./dir/s3|regular file|644|0|0|10|1|1792403737|0:0|a08fcf028b0bfb4fc257eceb8c2349c4
+./dir/s4|regular file|644|0|0|10|1|1792403737|0:0|2625ae83d5ed6d0510415ee6564bff60
+./dir/s5|regular file|644|0|0|10|1|1792403737|0:0|9645a149f01b681f3f765143d73bebdc
+./dir/s6|regular file|644|0|0|10|1|1792403737|0:0|0773e37d6e33a75aed302670d7645b20
+./dir/s7|regular file|644|0|0|10|1|1792403737|0:0|008b02bceab0751b1b69a2205993a3bc
+./dir/s8|regular file|644|0|0|10|1|1792403737|0:0|1e4bf161c80fbfd79a98d186fe33df43
+./dir/s9|regular file|644|0|0|10|1|1792403737|0:0|c907799dc2224429429b9f6c229bc215
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.img.gz
new file mode 100644
index 000000000..ee51b01a4
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.manifest b/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.manifest
new file mode 100644
index 000000000..152a1675a
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/lzo1-none-4k.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402700|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402700|7:0|
+./chardev|character special file|644|0|0|0|1|1792402700|1:3|
+./dir|directory|755|0|0|9|3|1792402700|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402700|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402700|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402700|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402700|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402700|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402700|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402700|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402700|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402700|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402700|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402700|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402700|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402700|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402700|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402700|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402700|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402700|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402700|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402701|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402700|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402700|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402700|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402701|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402701|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402701|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402701|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402701|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402701|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402701|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402701|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402701|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402701|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402700|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402701|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402701|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402701|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402701|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402701|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402701|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402701|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402701|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402701|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402701|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402700|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402701|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402701|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402701|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402701|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402701|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402701|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402701|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402701|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402701|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402701|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402700|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402701|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402701|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402701|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402701|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402701|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402701|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402701|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402701|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402701|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402701|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402700|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402701|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402701|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402701|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402701|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402701|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402701|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402701|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402701|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402701|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402701|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402700|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402701|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402701|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402701|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402701|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402701|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402701|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402701|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402701|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402701|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402701|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402700|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402701|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402701|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402701|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402701|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402701|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402701|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402701|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402701|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402701|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402701|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402700|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402701|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402701|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402701|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402701|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402701|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402701|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402701|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402701|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402701|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402701|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402700|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402701|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402701|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402701|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402701|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402701|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402701|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402701|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402701|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402701|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402701|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402700|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402701|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402701|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402701|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402701|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402701|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402701|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402701|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402701|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402701|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402701|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402700|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402700|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402701|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402701|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402701|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402701|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402701|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402701|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402701|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402701|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402701|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402701|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402700|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402701|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402701|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402701|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402701|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402701|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402701|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402701|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402701|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402701|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402701|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402700|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402701|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402701|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402701|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402701|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402701|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402701|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402701|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402701|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402701|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402701|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402700|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402701|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402701|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402701|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402701|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402701|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402701|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402701|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402701|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402701|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402701|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402700|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402701|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402701|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402701|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402701|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402701|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402701|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402701|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402701|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402701|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402701|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402700|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402701|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402701|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402701|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402701|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402701|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402701|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402701|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402701|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402701|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402701|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402700|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402701|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402701|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402701|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402701|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402701|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402701|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402701|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402701|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402701|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402701|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402700|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402701|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402701|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402701|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402701|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402701|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402701|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402701|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402701|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402701|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402701|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402700|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402701|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402701|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402701|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402701|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402701|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402701|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402701|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402701|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402701|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402701|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402700|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402701|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402701|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402701|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402701|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402701|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402701|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402701|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402701|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402701|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402701|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402700|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402700|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402700|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402700|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402700|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402700|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402700|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402700|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402700|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402700|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402700|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402700|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402700|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402700|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402700|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402700|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402700|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402700|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402700|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402700|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402700|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402700|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402700|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402700|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402700|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402700|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402700|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402700|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402700|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402700|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402700|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402700|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402700|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402700|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402700|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402700|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402700|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402700|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402701|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402701|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402701|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402701|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402701|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402701|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402700|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402701|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402701|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402701|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402701|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402701|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402701|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402701|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402701|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402701|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402701|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402700|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402701|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402701|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402701|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402701|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402701|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402701|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402701|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402701|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402701|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402701|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402700|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402701|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402701|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402701|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402701|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402701|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402701|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402701|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402701|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402701|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402701|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402700|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402700|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402700|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/node41.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/node41.img.gz
new file mode 100644
index 000000000..97c5394f3
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/node41.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/node41.manifest b/Compression.Tests/Reiser4/ReferenceVectors/node41.manifest
new file mode 100644
index 000000000..f3e8c13b1
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/node41.manifest
@@ -0,0 +1,325 @@
+.|directory|755|1000|1000|19|6|1792402782|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402782|7:0|
+./chardev|character special file|644|0|0|0|1|1792402782|1:3|
+./dir|directory|755|0|0|9|3|1792402782|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402782|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402782|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402782|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402782|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402782|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402782|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402782|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402782|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402782|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402782|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402782|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402782|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402782|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402782|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402782|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402782|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402782|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402782|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|300|2|1792402783|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402782|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402782|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402782|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402782|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402782|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402782|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402782|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402782|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402782|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402782|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402782|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402782|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402782|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402782|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402782|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402782|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402782|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402782|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402782|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402782|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402782|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402782|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402782|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402782|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402782|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402782|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402782|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402782|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402782|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402782|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402782|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402782|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402782|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402782|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402782|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402782|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402782|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402782|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402782|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402782|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402782|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402782|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402782|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402782|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402782|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402782|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402782|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402782|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402782|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402782|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402782|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402782|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402782|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402782|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402782|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402782|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402782|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402782|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402782|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402782|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402782|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402782|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402782|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402782|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402782|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402782|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402782|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402782|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402782|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402782|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402782|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402782|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402782|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402782|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402782|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402782|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402782|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402782|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402782|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402782|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402782|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402782|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402782|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402782|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402782|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m176|regular file|644|0|0|9|1|1792402782|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402782|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402782|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402782|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402782|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402782|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402782|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402782|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402782|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402782|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402782|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402782|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402782|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402782|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402782|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402782|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402782|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402782|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402782|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402782|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402782|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402782|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402782|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402782|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402782|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402782|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402782|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402782|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402782|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402782|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402782|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402782|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402782|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402782|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402782|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402782|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402782|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402782|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402782|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402782|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402782|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402782|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402782|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402782|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402782|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402783|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402783|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402783|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402783|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402782|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402783|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402783|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402783|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402783|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402783|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402783|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402783|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402783|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402783|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402783|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402782|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402783|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402783|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402783|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402783|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402783|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402783|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402783|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402783|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402783|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402783|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402782|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402783|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402783|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402783|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402783|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402783|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402783|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402783|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402783|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402783|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402783|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402782|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402783|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402783|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402783|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402783|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402783|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402783|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402783|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402783|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402783|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402783|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402782|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402783|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402783|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402783|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402783|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402783|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402783|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402783|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402783|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402783|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402783|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402782|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402783|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m272|regular file|644|0|0|9|1|1792402783|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402783|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402783|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402783|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402783|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402783|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402783|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402783|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402782|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402783|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402783|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402783|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402783|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402783|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402783|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402783|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402783|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402783|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402783|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402782|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402783|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402783|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402783|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402783|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402783|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402783|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402783|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402783|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402783|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402783|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402782|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402782|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402782|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402782|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402782|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402782|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402782|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402782|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402782|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402782|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402782|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402782|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402782|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402782|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402782|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402782|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402782|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402782|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402782|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402782|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402782|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402782|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402782|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402782|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402782|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402782|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402782|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402782|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402782|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402782|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402782|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402782|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402782|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402782|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402782|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402782|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402782|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402782|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402782|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402782|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402782|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402782|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402782|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402782|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402782|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402782|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402782|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402782|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402782|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402782|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402782|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402782|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402782|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402782|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402782|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402782|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402782|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402782|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402782|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402782|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402782|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402782|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402782|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402782|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402782|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402782|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402782|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402782|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402782|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402782|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402782|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402782|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402782|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402782|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402782|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402782|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402782|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402782|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402782|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402782|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/populate.sh b/Compression.Tests/Reiser4/ReferenceVectors/populate.sh
new file mode 100644
index 000000000..d9829bc32
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/populate.sh
@@ -0,0 +1,41 @@
+# Guest script (run inside the Reiser4 kernel by generate.sh): fills a fresh volume through the
+# kernel's own write path, unmounts it, and prints the manifest of what the kernel reads back.
+mount -t reiser4 /dev/vda /mnt || { echo MOUNTFAIL; exit 1; }
+cd /mnt
+P=/payload
+for f in $P/f_*; do cp $f ./$(basename $f); done
+mkdir -p dir/sub/deeper emptydir
+cp $P/f_4097 dir/sub/deeper/text.c
+cp $P/f_4097 dir/foo.o
+cp $P/f_100 dir/x.abc
+cp $P/f_1 "dir/a-name-longer-than-twenty-three-characters.txt"
+cp $P/f_1 "dir/$(printf 'L%.0s' $(seq 1 255))"
+cp $P/f_100 "dir/another-long-name-for-the-hash.abc"
+ln -s f_text sym_short
+ln -s "$(printf 'target/%.0s' $(seq 1 60))end" sym_long
+ln f_100 hard_100
+ln f_100 dir/hard_100_b
+mkfifo fifo
+mknod chardev c 1 3
+mknod blockdev b 7 0
+dd if=$P/f_100 of=sparse bs=1 count=100 2>/dev/null
+dd if=$P/f_4097 of=sparse bs=4096 seek=48 conv=notrunc 2>/dev/null
+mkdir many
+i=0; while [ $i -lt 300 ]; do echo "file $i" > many/m$i; i=$((i+1)); done
+chown 1234:5678 f_100; chmod 0751 f_100
+touch -d "2001-02-03 04:05:06" f_1
+cd /
+sync
+umount /mnt || echo UMOUNTFAIL
+mount -t reiser4 /dev/vda /mnt || { echo MOUNTFAIL; exit 1; }
+cd /mnt
+echo "===MANIFEST==="
+find . | sort | while read p; do
+ t=$(stat -c '%F|%a|%u|%g|%s|%h|%Y|%t:%T' "$p")
+ if [ -L "$p" ]; then echo "$p|$t|$(readlink "$p")"
+ elif [ -f "$p" ]; then echo "$p|$t|$(md5sum < "$p" | cut -d' ' -f1)"
+ else echo "$p|$t|"; fi
+done
+echo "===END-MANIFEST==="
+cd /
+umount /mnt || echo UMOUNTFAIL
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.img.gz
new file mode 100644
index 000000000..5473ede2d
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.manifest b/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.manifest
new file mode 100644
index 000000000..a2811052a
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/reg40-node41.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402758|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402758|7:0|
+./chardev|character special file|644|0|0|0|1|1792402758|1:3|
+./dir|directory|755|0|0|9|3|1792402758|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402758|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402758|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402758|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402758|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402758|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402758|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402758|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402758|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402758|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402758|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402757|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402758|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402758|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402758|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402758|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402758|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402758|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402758|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402758|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402758|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402758|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402758|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402758|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402758|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402758|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402758|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402758|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402758|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402758|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402758|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402758|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402758|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402758|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402758|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402758|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402758|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402758|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402758|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402758|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402758|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402758|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402758|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402758|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402758|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402758|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402758|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402758|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402758|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402758|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402758|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402758|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402758|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402758|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402758|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402758|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402758|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402758|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402758|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402758|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402758|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402758|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402758|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402758|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402758|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402758|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402758|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402758|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402758|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402758|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402758|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402758|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402758|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402758|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402758|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402758|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402758|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402758|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402758|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402758|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402758|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402758|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402758|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402758|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402758|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402758|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402758|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402758|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402758|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402758|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402758|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402758|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402758|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402758|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402758|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402758|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402758|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402758|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402758|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402758|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402758|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402758|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402758|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402758|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402758|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402758|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402758|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402758|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402758|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402758|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402758|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402758|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402758|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402758|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402758|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402758|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402758|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402758|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402758|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402758|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402758|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402758|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402758|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402758|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402758|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402758|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402758|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402758|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402758|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402758|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402758|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402758|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402758|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402758|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402758|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402758|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402758|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402758|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402758|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402758|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402758|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402758|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402758|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402758|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402758|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402758|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402758|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402758|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402758|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402758|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402758|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402758|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402758|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402758|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402758|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402758|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402758|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402758|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402758|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402758|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402758|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402758|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402758|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402758|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402758|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402758|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402758|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402758|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402758|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402758|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402758|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402758|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402758|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402758|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402758|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402758|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402758|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402758|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402758|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402758|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402758|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402758|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402758|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402758|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402758|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402758|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402758|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402758|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402758|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402758|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402758|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402758|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402758|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402758|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402758|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402758|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402758|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402758|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402758|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402758|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402758|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402758|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402758|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402758|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402758|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402758|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402758|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402758|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402758|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402758|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402758|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402758|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402758|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402758|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402758|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402758|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402758|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402758|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402758|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402758|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402758|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402758|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402758|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402758|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402758|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402758|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402758|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402758|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402758|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402758|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402758|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402758|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402758|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402758|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402758|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402758|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402758|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402758|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402758|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402758|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402758|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402758|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402758|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402758|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402758|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402758|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402758|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402758|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402758|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402758|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402758|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402758|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402758|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402758|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402758|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402758|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402758|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402758|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402758|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402758|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402758|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402758|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402758|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402758|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402758|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402758|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402758|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402758|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402758|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402758|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402758|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402758|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402758|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402758|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402758|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402758|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402758|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402758|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402758|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402758|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402758|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402758|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402758|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402758|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402758|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402758|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402758|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402758|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402758|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402758|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402758|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402758|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402758|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402758|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402758|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402758|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402758|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402758|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402758|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402758|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402758|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402758|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402758|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402758|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402758|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402758|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402758|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402758|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402758|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402758|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402758|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402758|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402758|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402758|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402758|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402758|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402758|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402758|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402758|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402758|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402758|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402758|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402758|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.img.gz
new file mode 100644
index 000000000..1e7c533eb
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.manifest b/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.manifest
new file mode 100644
index 000000000..e69e1c40d
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/reg40-smart.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402716|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402716|7:0|
+./chardev|character special file|644|0|0|0|1|1792402716|1:3|
+./dir|directory|755|0|0|9|3|1792402716|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402716|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402716|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402716|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402716|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402716|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402716|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402716|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402716|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402716|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402716|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402716|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402716|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402716|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402716|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402716|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402716|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402716|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402716|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402716|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402716|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402716|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402716|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402716|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402716|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402716|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402716|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402716|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402716|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402716|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402716|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402716|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402716|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402716|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402716|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402716|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402716|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402716|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402716|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402716|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402716|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402716|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402716|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402716|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402716|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402716|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402716|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402716|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402716|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402716|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402716|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402716|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402716|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402716|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402716|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402716|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402716|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402716|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402716|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402716|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402716|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402716|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402716|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402716|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402716|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402716|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402716|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402716|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402716|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402716|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402716|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402716|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402716|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402716|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402716|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402716|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402716|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402716|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402716|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402716|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402716|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402716|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402716|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402716|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402716|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402716|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402716|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402716|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402716|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402716|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402716|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402716|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402716|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402716|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402716|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402716|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402716|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402716|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402716|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402716|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402716|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402716|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402716|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402716|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402716|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402716|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402716|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402716|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402716|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402716|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402716|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402716|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402716|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402716|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402716|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402716|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402716|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402716|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402716|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402716|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402716|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402716|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402716|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402716|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402716|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402716|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402716|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402716|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402716|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402716|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402716|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402716|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402716|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402716|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402716|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402716|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402716|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402716|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402716|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402716|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402716|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402716|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402716|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402716|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402716|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402716|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402716|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402716|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402716|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402716|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402716|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402716|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402716|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402716|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402716|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402716|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402716|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402716|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402716|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402716|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402716|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402716|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402716|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402716|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402716|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402716|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402716|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402716|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402716|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402716|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402716|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402716|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402716|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402716|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402716|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402716|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402716|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402716|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402716|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402716|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402716|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402716|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402716|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402716|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402716|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402716|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402716|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402716|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402716|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402716|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402716|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402716|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402716|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402716|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402716|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402716|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402716|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402716|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402716|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402716|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402716|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402716|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402716|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402716|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402716|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402716|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402716|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402716|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402716|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402716|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402716|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402716|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402716|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402716|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402716|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402716|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402716|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402716|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402716|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402716|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402716|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402716|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402716|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402716|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402716|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402716|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402716|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402716|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402716|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402716|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402716|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402716|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402716|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402716|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402716|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402716|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402716|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402716|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402716|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402716|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402716|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402716|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402716|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402716|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402716|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402716|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402716|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402716|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402716|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402716|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402716|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402716|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402716|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402716|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402716|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402716|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402716|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402716|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402716|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402716|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402716|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402716|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402716|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402716|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402716|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402716|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402716|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402716|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402716|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402716|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402716|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402716|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402716|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402716|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402716|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402716|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402716|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402716|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402716|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402716|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402716|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402716|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402716|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402716|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402716|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402716|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402716|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402716|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402716|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402716|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402716|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402716|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402716|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402716|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402716|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402716|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402716|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402716|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402716|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402716|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402716|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402716|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402716|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402716|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402716|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402716|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402716|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402716|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402716|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402716|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402716|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402716|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402716|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402716|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402716|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402716|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402716|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402716|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402716|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402716|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402716|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402716|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402716|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.img.gz
new file mode 100644
index 000000000..1b977cd8e
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.manifest b/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.manifest
new file mode 100644
index 000000000..0a4b8ac2f
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/reg40-tails.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402735|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402735|7:0|
+./chardev|character special file|644|0|0|0|1|1792402735|1:3|
+./dir|directory|755|0|0|9|3|1792402735|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402735|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402735|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402735|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402735|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402735|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402735|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402735|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402735|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402735|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402735|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402734|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402735|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402735|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402735|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402735|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402735|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402735|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402735|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402735|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402735|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402735|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402735|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402735|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402735|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402735|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402735|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402735|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402735|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402735|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402735|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402735|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402735|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402735|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402735|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402735|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402735|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402735|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402735|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402735|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402735|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402735|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402735|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402735|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402735|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402735|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402735|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402735|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402735|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402735|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402735|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402735|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402735|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402735|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402735|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402735|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402735|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402735|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402735|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402735|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402735|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402735|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402735|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402735|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402735|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402735|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402735|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402735|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402735|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402735|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402735|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402735|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402735|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402735|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402735|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402735|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402735|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402735|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402735|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402735|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402735|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402735|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402735|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402735|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402735|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402735|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402735|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402735|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402735|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402735|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402735|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402735|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402735|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402735|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402735|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402735|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402735|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402735|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402735|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402735|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402735|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402735|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402735|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402735|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402735|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402735|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402735|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402735|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402735|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402735|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402735|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402735|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402735|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402735|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402735|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402735|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402735|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402735|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402735|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402735|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402735|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402735|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402735|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402735|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402735|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402735|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402735|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402735|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402735|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402735|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402735|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402735|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402735|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402735|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402735|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402735|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402735|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402735|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402735|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402735|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402735|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402735|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402735|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402735|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402735|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402735|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402735|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402735|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402735|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402735|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402735|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402735|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402735|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402735|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402735|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402735|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402735|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402735|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402735|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402735|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402735|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402735|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402735|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402735|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402735|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402735|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402735|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402735|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402735|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402735|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402735|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402735|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402735|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402735|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402735|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402735|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402735|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402735|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402735|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402735|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402735|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402735|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402735|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402735|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402735|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402735|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402735|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402735|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402735|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402735|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402735|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402735|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402735|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402735|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402735|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402735|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402735|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402735|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402735|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402735|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402735|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402735|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402735|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402735|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402735|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402735|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402735|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402735|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402735|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402735|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402735|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402735|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402735|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402735|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402735|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402735|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402735|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402735|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402735|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402735|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402735|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402735|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402735|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402735|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402735|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402735|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402735|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402735|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402735|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402735|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402735|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402735|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402735|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402735|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402735|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402735|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402735|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402735|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402735|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402735|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402735|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402735|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402735|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402735|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402735|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402735|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402735|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402735|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402735|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402735|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402735|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402735|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402735|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402735|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402735|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402735|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402735|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402735|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402735|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402735|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402735|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402735|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402735|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402735|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402735|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402735|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402735|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402735|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402735|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402735|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402735|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402735|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402735|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402735|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402735|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402735|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402735|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402735|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402735|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402735|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402735|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402735|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402735|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402735|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402735|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402735|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402735|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402735|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402735|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402735|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402735|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402735|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402735|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402735|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402735|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402735|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402735|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402735|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402735|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402735|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402735|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402735|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402735|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402735|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402735|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402735|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402735|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402735|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402735|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402735|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402735|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402735|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402735|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402735|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402735|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402735|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402735|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402735|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402735|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402735|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402735|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402735|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402735|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/rupasov.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/rupasov.img.gz
new file mode 100644
index 000000000..b17a38ea4
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/rupasov.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/rupasov.manifest b/Compression.Tests/Reiser4/ReferenceVectors/rupasov.manifest
new file mode 100644
index 000000000..635164459
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/rupasov.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402858|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402858|7:0|
+./chardev|character special file|644|0|0|0|1|1792402858|1:3|
+./dir|directory|755|0|0|9|3|1792402858|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402858|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402858|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402858|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402858|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402858|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402858|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402858|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402858|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402858|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402858|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402858|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402858|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402858|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402858|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402858|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402858|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402858|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402858|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402859|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402858|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402858|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402858|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402858|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402858|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402858|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402858|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402858|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402858|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402858|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402858|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402858|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402858|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402858|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402858|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402858|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402858|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402858|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402858|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402858|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402858|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402858|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402858|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402858|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402858|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402858|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402858|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402858|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402858|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402858|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402858|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402858|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402858|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402858|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402858|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402858|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402858|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402858|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402858|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402858|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402858|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402858|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402858|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402858|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402858|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402858|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402858|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402858|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402858|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402858|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402858|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402858|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402858|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402858|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402858|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402858|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402858|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402858|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402858|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402858|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402858|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402858|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402858|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402858|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402858|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402858|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402858|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402858|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402858|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402858|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402858|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402858|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402858|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402858|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402858|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402858|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402858|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402859|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402859|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402858|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402859|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402859|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402859|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402859|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402859|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402859|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402859|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402859|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402859|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402859|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402858|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402859|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402859|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402859|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402859|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402859|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402859|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402859|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402859|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402859|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402859|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402858|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402859|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402859|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402859|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402859|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402859|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402859|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402859|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402859|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402859|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402859|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402858|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402858|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402859|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402859|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402859|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402859|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402859|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402859|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402859|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402859|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402859|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402859|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402858|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402859|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402859|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402859|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402859|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402859|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402859|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402859|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402859|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402859|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402859|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402858|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402859|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402859|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402859|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402859|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402859|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402859|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402859|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402859|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402859|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402859|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402858|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402859|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402859|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402859|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402859|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402859|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402859|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402859|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402859|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402859|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402859|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402858|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402859|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402859|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402859|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402859|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402859|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402859|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402859|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402859|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402859|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402859|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402858|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402859|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402859|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402859|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402859|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402859|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402859|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402859|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402859|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402859|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402859|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402858|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402859|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402859|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402859|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402859|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402859|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402859|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402859|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402859|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402859|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402859|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402858|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402859|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402859|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402859|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402859|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402859|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402859|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402859|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402859|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402859|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402859|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402858|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402859|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402859|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402859|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402859|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402859|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402859|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402859|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402859|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402859|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402859|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402858|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402859|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402859|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402859|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402859|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402859|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402859|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402859|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402859|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402859|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402859|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402858|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402858|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402858|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402858|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402858|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402858|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402858|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402858|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402858|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402858|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402858|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402858|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402858|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402858|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402858|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402858|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402858|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402858|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402858|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402858|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402858|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402858|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402858|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402858|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402858|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402858|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402858|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402858|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402858|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402858|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402858|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402858|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402858|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402858|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402858|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402858|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402858|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402858|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402858|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402858|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402858|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402858|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402858|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402858|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402858|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402858|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402858|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402858|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402858|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402858|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402858|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402858|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402858|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402858|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402858|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402858|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402858|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402858|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402858|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402858|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402858|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402858|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402858|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402858|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402858|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402858|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402858|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402858|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402858|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402858|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402858|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402858|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402858|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402858|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402858|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402858|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402858|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402858|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402858|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402858|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.img.gz
new file mode 100644
index 000000000..3e5ced949
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.manifest b/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.manifest
new file mode 100644
index 000000000..779c4fb1d
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/tea-lexic.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402802|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402802|7:0|
+./chardev|character special file|644|0|0|0|1|1792402802|1:3|
+./dir|directory|755|0|0|9|3|1792402802|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402802|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402801|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402802|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402801|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402801|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402801|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402801|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402801|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402801|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402801|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402801|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402801|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402801|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402801|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402801|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402801|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402802|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402801|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402802|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402802|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402802|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402802|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402802|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402802|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402802|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402802|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402802|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402802|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402802|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402802|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402802|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402802|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402802|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402802|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402802|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402802|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402802|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402802|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402802|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402802|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402802|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402802|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402802|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402802|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402802|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402802|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402802|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402802|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402802|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402802|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402802|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402802|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402802|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402802|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402802|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402802|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402802|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402802|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402802|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402802|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402802|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402802|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402802|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402802|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402802|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402802|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402802|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402802|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402802|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402802|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402802|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402802|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402802|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402802|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402802|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402802|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402802|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402802|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402802|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402802|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402802|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402802|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402802|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402802|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402802|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402802|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402802|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402802|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402802|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402802|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402802|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402802|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402802|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402802|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402802|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402802|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402802|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402802|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402802|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402802|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402802|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402802|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402802|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402802|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402802|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402802|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402802|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402802|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402802|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402802|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402802|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402802|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402802|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402802|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402802|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402802|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402802|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402802|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402802|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402802|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402802|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402802|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402802|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402802|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402802|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402802|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402802|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402802|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402802|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402802|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402802|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402802|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402802|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402802|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402802|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402802|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402802|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402802|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402802|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402802|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402802|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402802|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402802|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402802|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402802|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402802|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402802|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402802|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402802|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402802|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402802|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402802|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402802|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402802|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402802|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402802|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402802|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402802|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402802|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402802|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402802|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402802|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402802|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402802|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402802|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402802|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402802|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402802|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402802|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402802|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402802|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402802|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402802|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402802|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402802|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402802|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402802|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402802|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402802|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402802|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402802|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402802|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402802|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402802|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402802|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402802|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402802|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402802|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402802|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402802|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402802|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402802|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402802|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402802|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402802|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402802|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402802|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402802|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402802|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402802|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402802|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402802|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402802|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402802|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402802|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402802|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402802|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402802|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402802|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402802|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402802|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402802|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402802|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402802|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402802|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402802|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402802|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402802|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402802|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402802|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402802|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402802|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402802|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402802|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402802|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402802|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402802|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402802|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402802|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402802|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402802|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402802|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402802|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402802|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402802|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402802|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402802|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402802|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402802|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402802|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402802|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402802|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402802|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402802|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402802|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402802|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402802|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402802|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402802|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402802|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402802|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402802|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402802|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402802|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402802|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402802|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402802|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402802|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402802|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402802|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402802|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402802|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402802|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402802|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402802|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402802|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402802|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402802|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402802|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402802|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402802|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402802|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402802|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402802|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402802|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402802|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402802|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402802|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402802|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402802|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402802|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402802|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402802|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402802|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402802|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402802|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402802|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402802|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402802|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402802|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402802|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402802|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402802|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402802|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402802|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402802|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402802|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402802|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402802|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402802|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402802|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402802|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402802|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402802|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402802|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402802|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402802|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402802|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402802|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402802|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402802|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402802|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402802|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402802|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402802|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402802|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402802|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402802|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402802|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402802|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402802|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402802|0:0|f_text
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.img.gz b/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.img.gz
new file mode 100644
index 000000000..1e888c439
Binary files /dev/null and b/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.img.gz differ
diff --git a/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.manifest b/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.manifest
new file mode 100644
index 000000000..046b79014
--- /dev/null
+++ b/Compression.Tests/Reiser4/ReferenceVectors/zstd1-latt-16k.manifest
@@ -0,0 +1,327 @@
+.|directory|755|1000|1000|19|6|1792402673|0:0|
+./blockdev|block special file|644|0|0|0|1|1792402673|7:0|
+./chardev|character special file|644|0|0|0|1|1792402673|1:3|
+./dir|directory|755|0|0|9|3|1792402673|0:0|
+./dir/LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL|regular file|644|0|0|1|1|1792402673|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/a-name-longer-than-twenty-three-characters.txt|regular file|644|0|0|1|1|1792402673|0:0|26fc1f29bd4599f5f29200b6ca083531
+./dir/another-long-name-for-the-hash.abc|regular file|644|0|0|100|1|1792402673|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/foo.o|regular file|644|0|0|4097|1|1792402673|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/hard_100_b|regular file|751|1234|5678|100|3|1792402673|0:0|8d46298c51d128bb5dbeff0c63629e62
+./dir/sub|directory|755|0|0|3|3|1792402673|0:0|
+./dir/sub/deeper|directory|755|0|0|3|2|1792402673|0:0|
+./dir/sub/deeper/text.c|regular file|644|0|0|4097|1|1792402673|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./dir/x.abc|regular file|644|0|0|100|1|1792402673|0:0|8d46298c51d128bb5dbeff0c63629e62
+./emptydir|directory|755|0|0|2|2|1792402673|0:0|
+./f_0|regular empty file|644|0|0|0|1|1792402673|0:0|d41d8cd98f00b204e9800998ecf8427e
+./f_1|regular file|644|0|0|1|1|981173106|0:0|26fc1f29bd4599f5f29200b6ca083531
+./f_100|regular file|751|1234|5678|100|3|1792402673|0:0|8d46298c51d128bb5dbeff0c63629e62
+./f_4095|regular file|644|0|0|4095|1|1792402673|0:0|b0fbbf3c1d774e4cde9bbb6c2333240a
+./f_4096|regular file|644|0|0|4096|1|1792402673|0:0|5943c3a697c0247e3660cbef410f7b9b
+./f_4097|regular file|644|0|0|4097|1|1792402673|0:0|222c3621eaa94ed7f006cf65f8ff9dfc
+./f_text|regular file|644|0|0|69559|1|1792402673|0:0|68427bef950fdea83e3a40b7752b5085
+./fifo|fifo|644|0|0|0|1|1792402673|0:0|
+./hard_100|regular file|751|1234|5678|100|3|1792402673|0:0|8d46298c51d128bb5dbeff0c63629e62
+./many|directory|755|0|0|302|2|1792402674|0:0|
+./many/m0|regular file|644|0|0|7|1|1792402673|0:0|30fce81b7f0df29fa90445437e29cbc6
+./many/m1|regular file|644|0|0|7|1|1792402673|0:0|e243bb39c844b3543a7726576c869caf
+./many/m10|regular file|644|0|0|8|1|1792402673|0:0|a9e3737bb4cf960ff521c4ad4c8275e7
+./many/m100|regular file|644|0|0|9|1|1792402673|0:0|5e9c8bfc28eb97f4c9ec7dbcfa349590
+./many/m101|regular file|644|0|0|9|1|1792402673|0:0|71e4a6c5d8d9a5530d2fb44286bc0a5c
+./many/m102|regular file|644|0|0|9|1|1792402673|0:0|451d81b0d1eba9a066a7970d5bd101bf
+./many/m103|regular file|644|0|0|9|1|1792402673|0:0|9b6843356c23c0b1f2ef92c24e2c6618
+./many/m104|regular file|644|0|0|9|1|1792402673|0:0|5d83284f904341bd007a1d2c9170425e
+./many/m105|regular file|644|0|0|9|1|1792402673|0:0|d7b4a549841ef1b3683005470ea5c6a6
+./many/m106|regular file|644|0|0|9|1|1792402673|0:0|053dae9a00020b83119809092b5d32cc
+./many/m107|regular file|644|0|0|9|1|1792402673|0:0|4cad0e71996eee272cbfd0d69eba2f9c
+./many/m108|regular file|644|0|0|9|1|1792402673|0:0|1916f4af4dd7f94f6f29937326c783bf
+./many/m109|regular file|644|0|0|9|1|1792402673|0:0|b06ed943b4aed4a9cc92dc43828c59c9
+./many/m11|regular file|644|0|0|8|1|1792402673|0:0|715081268e5e053a7e89daf6c155244a
+./many/m110|regular file|644|0|0|9|1|1792402673|0:0|6fbb8a796ad4ab374ad8522ad72ab38c
+./many/m111|regular file|644|0|0|9|1|1792402673|0:0|f1e91a40908b17a9d7292ae446d74331
+./many/m112|regular file|644|0|0|9|1|1792402673|0:0|b039c00491cae1372e1bd2bcb95546c9
+./many/m113|regular file|644|0|0|9|1|1792402673|0:0|035fbc5dbfad05e88e7a97037f1d420a
+./many/m114|regular file|644|0|0|9|1|1792402673|0:0|9548ca423f57477900489d56f9943c90
+./many/m115|regular file|644|0|0|9|1|1792402673|0:0|714c9cc478f4ac62c71f684282b3ca9e
+./many/m116|regular file|644|0|0|9|1|1792402673|0:0|0c6969c4a5a366e879dd48fdbd5d8d8b
+./many/m117|regular file|644|0|0|9|1|1792402673|0:0|c6af06da6b1d613c71d9c9b99294b785
+./many/m118|regular file|644|0|0|9|1|1792402673|0:0|cfbfb40f78231026fa8ffa95f210a3f9
+./many/m119|regular file|644|0|0|9|1|1792402673|0:0|bde7fad10ad91d97f69d7261162674ea
+./many/m12|regular file|644|0|0|8|1|1792402673|0:0|1d47b3894c01ea376c576c6cde23c0c3
+./many/m120|regular file|644|0|0|9|1|1792402673|0:0|e3e9d5d360d6b50fc892515632834559
+./many/m121|regular file|644|0|0|9|1|1792402673|0:0|7a9282c2bdfb357dde622d9dcf5d39f8
+./many/m122|regular file|644|0|0|9|1|1792402673|0:0|6bc6a7988fa8f5b28e357044d377eda3
+./many/m123|regular file|644|0|0|9|1|1792402673|0:0|bbc27f45c7863cc62401f4e05ac34cb4
+./many/m124|regular file|644|0|0|9|1|1792402673|0:0|fe6e4959710835d696e00f28212b9884
+./many/m125|regular file|644|0|0|9|1|1792402673|0:0|dd47bd03b176555bc88236c2281f2f52
+./many/m126|regular file|644|0|0|9|1|1792402673|0:0|4fe80d7bb49d5d7009381a8081cac2b6
+./many/m127|regular file|644|0|0|9|1|1792402673|0:0|97ddfd66e065afa494720ae19db3d8f3
+./many/m128|regular file|644|0|0|9|1|1792402673|0:0|60db69f168ed4f56f323c2a4cfe97c95
+./many/m129|regular file|644|0|0|9|1|1792402673|0:0|02055e8d488a51e14354b3353692da3f
+./many/m13|regular file|644|0|0|8|1|1792402673|0:0|8ef8a460853cecc9747ea9c75a54e6c5
+./many/m130|regular file|644|0|0|9|1|1792402673|0:0|21f762bfe54a273420bf0cc9e27beefb
+./many/m131|regular file|644|0|0|9|1|1792402673|0:0|3a555eb9830986c73a016025bf7de464
+./many/m132|regular file|644|0|0|9|1|1792402673|0:0|b536d95e908d91ff249c46a2ce26ce7a
+./many/m133|regular file|644|0|0|9|1|1792402673|0:0|37e65aa7f216c0917982b33bbbdce9c9
+./many/m134|regular file|644|0|0|9|1|1792402673|0:0|0dfb06b520ba85e9850857de67cc537f
+./many/m135|regular file|644|0|0|9|1|1792402673|0:0|4627968ca8beb47883ea2c0af327e865
+./many/m136|regular file|644|0|0|9|1|1792402673|0:0|7cac2f99ad683c23ef35998433bf5e85
+./many/m137|regular file|644|0|0|9|1|1792402673|0:0|f554e9025f214483fdbcec75220b6e47
+./many/m138|regular file|644|0|0|9|1|1792402673|0:0|4de17de2d651b1c4d67d78edf24ffeaf
+./many/m139|regular file|644|0|0|9|1|1792402673|0:0|538d3563e5587014100a844aa72c2e3d
+./many/m14|regular file|644|0|0|8|1|1792402673|0:0|f662b840ccbea565898682c8f8dcd97a
+./many/m140|regular file|644|0|0|9|1|1792402673|0:0|f01f8b6994e8d3290788bf1ad0a3a060
+./many/m141|regular file|644|0|0|9|1|1792402673|0:0|a93d155018fb504d41a4036942c49bd5
+./many/m142|regular file|644|0|0|9|1|1792402674|0:0|f6c5c015993cf74c785b5c0980e71490
+./many/m143|regular file|644|0|0|9|1|1792402674|0:0|61a3937b7d06718a25a1e99b7ea60285
+./many/m144|regular file|644|0|0|9|1|1792402674|0:0|57adad91c24dca84d939caa4c101766b
+./many/m145|regular file|644|0|0|9|1|1792402674|0:0|94f45887532f52fe9332cdac28d99ab3
+./many/m146|regular file|644|0|0|9|1|1792402674|0:0|1e883271c9b323bf0c793c397fd4c2cd
+./many/m147|regular file|644|0|0|9|1|1792402674|0:0|37829b2976e152e803a8bcc5cd9c2717
+./many/m148|regular file|644|0|0|9|1|1792402674|0:0|52057b6b97d5fb47f6171b873edb2bff
+./many/m149|regular file|644|0|0|9|1|1792402674|0:0|f0a3a9c68023185a4fdccb58970da254
+./many/m15|regular file|644|0|0|8|1|1792402673|0:0|c1575e41dabea5854e1500d523916f6a
+./many/m150|regular file|644|0|0|9|1|1792402674|0:0|792c7a51d685072801853560c8b4efd3
+./many/m151|regular file|644|0|0|9|1|1792402674|0:0|dffbd6ebe410ebb2b514d90a0a7f0aa9
+./many/m152|regular file|644|0|0|9|1|1792402674|0:0|44f30f859797ccbc947dd6e7fb163219
+./many/m153|regular file|644|0|0|9|1|1792402674|0:0|4d50d9696eb6682bf3e07a96cd72ec56
+./many/m154|regular file|644|0|0|9|1|1792402674|0:0|a37806f66e52900c01529ea894057a55
+./many/m155|regular file|644|0|0|9|1|1792402674|0:0|1df46e85e2150857ddef01b12144bc49
+./many/m156|regular file|644|0|0|9|1|1792402674|0:0|9e5bf1715fcce57ea772ce19e96c88b2
+./many/m157|regular file|644|0|0|9|1|1792402674|0:0|ff5245e0586c5876ab3e074aac17bb53
+./many/m158|regular file|644|0|0|9|1|1792402674|0:0|77edb145923857b1e13aa652b452717a
+./many/m159|regular file|644|0|0|9|1|1792402674|0:0|ba0e18dc6e493746db14c62cc64dee69
+./many/m16|regular file|644|0|0|8|1|1792402673|0:0|66427cc15376ceaf910e0f1af5c354f4
+./many/m160|regular file|644|0|0|9|1|1792402674|0:0|2d9a4d55c26381f875380909208d2ff3
+./many/m161|regular file|644|0|0|9|1|1792402674|0:0|554b07e145fa922aeb777a0d41b2de80
+./many/m162|regular file|644|0|0|9|1|1792402674|0:0|b4c4f356c33650f638fc911ff7359183
+./many/m163|regular file|644|0|0|9|1|1792402674|0:0|b23ed2f7d446f5af3c60c0cca756bdc7
+./many/m164|regular file|644|0|0|9|1|1792402674|0:0|187fcb21375177e4acc3a93fe58b8c66
+./many/m165|regular file|644|0|0|9|1|1792402674|0:0|f44da39df7b71d2420aa69deecccf81e
+./many/m166|regular file|644|0|0|9|1|1792402674|0:0|2bf2c5e5207431ce1bf3485f97b40a48
+./many/m167|regular file|644|0|0|9|1|1792402674|0:0|87d6752ad6ad8214faffecf9f96a2486
+./many/m168|regular file|644|0|0|9|1|1792402674|0:0|07f462fa142da8ed6f55c0d6c8027b98
+./many/m169|regular file|644|0|0|9|1|1792402674|0:0|43dc5c97caa43158902899da2e43ff72
+./many/m17|regular file|644|0|0|8|1|1792402673|0:0|5678c8e35af7d85b70ea1ff518755309
+./many/m170|regular file|644|0|0|9|1|1792402674|0:0|68dd3dc1225ca5214e2a077963c12244
+./many/m171|regular file|644|0|0|9|1|1792402674|0:0|2b4f877355365d0084ff39c8783030e6
+./many/m172|regular file|644|0|0|9|1|1792402674|0:0|ddc55a8b9afd0fce8eb38c6de6a4a4ba
+./many/m173|regular file|644|0|0|9|1|1792402674|0:0|d2602d917846c1d464a2a35f5fda902b
+./many/m174|regular file|644|0|0|9|1|1792402674|0:0|4640974c5a8df9c1ef346326bbc0e639
+./many/m175|regular file|644|0|0|9|1|1792402674|0:0|cadbbc5c564df97821a77cfd063026de
+./many/m176|regular file|644|0|0|9|1|1792402674|0:0|c20369a3ee03468f578c8c74f34ed844
+./many/m177|regular file|644|0|0|9|1|1792402674|0:0|314361fc1627ba09af6a5c247aa410c4
+./many/m178|regular file|644|0|0|9|1|1792402674|0:0|18b5b3931ac136c6f9844031e2c5e27c
+./many/m179|regular file|644|0|0|9|1|1792402674|0:0|a1354e01ad6137b4fc5cc62f180a8462
+./many/m18|regular file|644|0|0|8|1|1792402673|0:0|f892dd572dd20de347b3b27b1d378c19
+./many/m180|regular file|644|0|0|9|1|1792402674|0:0|7b4f9f59161aaead8ebc6094075d23a1
+./many/m181|regular file|644|0|0|9|1|1792402674|0:0|84803963e2a3b585019db6868f71f14d
+./many/m182|regular file|644|0|0|9|1|1792402674|0:0|e5f69b1224bda5071d64f15caef990eb
+./many/m183|regular file|644|0|0|9|1|1792402674|0:0|b6f0fba8f6e4375b11c060cb188cddb1
+./many/m184|regular file|644|0|0|9|1|1792402674|0:0|c9522bb1a5a30089edc4e66bd5ff522e
+./many/m185|regular file|644|0|0|9|1|1792402674|0:0|77190f2f1e76a9220dba62cd3fa5610a
+./many/m186|regular file|644|0|0|9|1|1792402674|0:0|e840f47e99561ebcbcb029d0672bad48
+./many/m187|regular file|644|0|0|9|1|1792402674|0:0|6737ea174a824ac2718fed9e3f663fd3
+./many/m188|regular file|644|0|0|9|1|1792402674|0:0|58bfd1cb33f6b546eedb0640c509a73d
+./many/m189|regular file|644|0|0|9|1|1792402674|0:0|0cdad90be02c441fb41a6d770dae7d57
+./many/m19|regular file|644|0|0|8|1|1792402673|0:0|a985d5f8c0764f8cdd7bdce73046ad44
+./many/m190|regular file|644|0|0|9|1|1792402674|0:0|4e8c07eb752c075c9453cc9b816e1a0f
+./many/m191|regular file|644|0|0|9|1|1792402674|0:0|7d0924ad195a30a6b2a8ca8addb9c975
+./many/m192|regular file|644|0|0|9|1|1792402674|0:0|4c4b109ce39fe7c53ec65b8210352324
+./many/m193|regular file|644|0|0|9|1|1792402674|0:0|daf7c277f982121ee872422d21f3cea0
+./many/m194|regular file|644|0|0|9|1|1792402674|0:0|04c1462a23779315ff0bdbb99094f74f
+./many/m195|regular file|644|0|0|9|1|1792402674|0:0|d7d1de0936202ba73079a42775c4d615
+./many/m196|regular file|644|0|0|9|1|1792402674|0:0|a6830202fedbaedb83ae586da9d9d14b
+./many/m197|regular file|644|0|0|9|1|1792402674|0:0|7da218966124abd17b6fa5ed56a7b944
+./many/m198|regular file|644|0|0|9|1|1792402674|0:0|8d40c91037dd5a499a63631cbe7d9a94
+./many/m199|regular file|644|0|0|9|1|1792402674|0:0|30dd72ed5a948d80a40b1d7687906145
+./many/m2|regular file|644|0|0|7|1|1792402673|0:0|4349cfeff8e2eb74dffc369bb5fd084e
+./many/m20|regular file|644|0|0|8|1|1792402673|0:0|067f81212cf0fb2e982bd628a8606f97
+./many/m200|regular file|644|0|0|9|1|1792402674|0:0|a4ba2c004cbbc4b1f2922961ea250626
+./many/m201|regular file|644|0|0|9|1|1792402674|0:0|ee1b4d06ef9acb1984715fca56e519e7
+./many/m202|regular file|644|0|0|9|1|1792402674|0:0|3320db42848ba081d007e1dfbe6c7e59
+./many/m203|regular file|644|0|0|9|1|1792402674|0:0|fb29fd3a0da80d1672c321bfe193e8f9
+./many/m204|regular file|644|0|0|9|1|1792402674|0:0|b7d18558fb1e4b3fb1c636d80cf2084c
+./many/m205|regular file|644|0|0|9|1|1792402674|0:0|a02e66f25e04b706131f015a58cb76ad
+./many/m206|regular file|644|0|0|9|1|1792402674|0:0|6abbe7ba05a9074de018aa174fe227b5
+./many/m207|regular file|644|0|0|9|1|1792402674|0:0|a2ba136b96eeb8367e7c5273c466c8f5
+./many/m208|regular file|644|0|0|9|1|1792402674|0:0|70973e242b7ea4ccbcad12d85942c0e0
+./many/m209|regular file|644|0|0|9|1|1792402674|0:0|603673c5215bc406c2600a572038a813
+./many/m21|regular file|644|0|0|8|1|1792402673|0:0|9cfd7afc71338f84647dbacf3f6f6b26
+./many/m210|regular file|644|0|0|9|1|1792402674|0:0|4bf71dba377bf43aa3776e9a551ecb0f
+./many/m211|regular file|644|0|0|9|1|1792402674|0:0|015bc399a474cff7bf5859211eae8c89
+./many/m212|regular file|644|0|0|9|1|1792402674|0:0|3823c1410507af2c3c33b5669ba270fa
+./many/m213|regular file|644|0|0|9|1|1792402674|0:0|c4756d1df6b13a46e55efade51170239
+./many/m214|regular file|644|0|0|9|1|1792402674|0:0|69feabb2da7bc5fad832dfaac32ff1f3
+./many/m215|regular file|644|0|0|9|1|1792402674|0:0|2f49876a5b1cd81a6c681a3279743166
+./many/m216|regular file|644|0|0|9|1|1792402674|0:0|0fba8ffe0203c03dd7929d605e9fe4ca
+./many/m217|regular file|644|0|0|9|1|1792402674|0:0|2f3f14da61b9dd3df33ac539878db78d
+./many/m218|regular file|644|0|0|9|1|1792402674|0:0|fa0c8c205c79dfcb2be989549e4f0580
+./many/m219|regular file|644|0|0|9|1|1792402674|0:0|6b57c36dd6811e8239eab31793417c1b
+./many/m22|regular file|644|0|0|8|1|1792402673|0:0|485c438ed8aa42313e57ecf1bef51e4d
+./many/m220|regular file|644|0|0|9|1|1792402674|0:0|a565450a0967908ababde36cbabaee00
+./many/m221|regular file|644|0|0|9|1|1792402674|0:0|f5be9963266c24b569d03c105628fb62
+./many/m222|regular file|644|0|0|9|1|1792402674|0:0|f310eb13ce84822aeabe2a3e34f5608d
+./many/m223|regular file|644|0|0|9|1|1792402674|0:0|48b026453b394d6bec80401dfb69ac4e
+./many/m224|regular file|644|0|0|9|1|1792402674|0:0|f2b4e319946afadd81756805fe638bd6
+./many/m225|regular file|644|0|0|9|1|1792402674|0:0|ed019ea04f0fe2c790ee5b4748308090
+./many/m226|regular file|644|0|0|9|1|1792402674|0:0|72b70a40d6dd52fdb94eddd8fd3325ea
+./many/m227|regular file|644|0|0|9|1|1792402674|0:0|178a1aa1bc0019534fa15b435b3f3756
+./many/m228|regular file|644|0|0|9|1|1792402674|0:0|cb1a4e4faf4b5fe1f30ea3b6e1884891
+./many/m229|regular file|644|0|0|9|1|1792402674|0:0|6d20673028ed6e907eb0ebcf81f5c105
+./many/m23|regular file|644|0|0|8|1|1792402673|0:0|052933180d7e7bd29f137c4a07fb7066
+./many/m230|regular file|644|0|0|9|1|1792402674|0:0|99d049a2c2e464b31eb7e119e929a66e
+./many/m231|regular file|644|0|0|9|1|1792402674|0:0|e6e371d88bb32c9f7a846b4eb2a9290a
+./many/m232|regular file|644|0|0|9|1|1792402674|0:0|482ef1b309083db205f98ab5159e516e
+./many/m233|regular file|644|0|0|9|1|1792402674|0:0|b614fe6268139a1fe6841febe3b7df77
+./many/m234|regular file|644|0|0|9|1|1792402674|0:0|591f0ee94dcd2759e8926a904d94903d
+./many/m235|regular file|644|0|0|9|1|1792402674|0:0|bfa7a6d92596ca0e104bbf792266d8f2
+./many/m236|regular file|644|0|0|9|1|1792402674|0:0|fd522eb2e58a2788c1ffe58ce1afaec6
+./many/m237|regular file|644|0|0|9|1|1792402674|0:0|1fad87b3d6e7a84cdc1200f0596a1d67
+./many/m238|regular file|644|0|0|9|1|1792402674|0:0|a17a63fc2f5c0fee0995c83e40e09da4
+./many/m239|regular file|644|0|0|9|1|1792402674|0:0|872173419f874262f8c3daf4673e8eff
+./many/m24|regular file|644|0|0|8|1|1792402673|0:0|9cbbd2b55c610f55da23c92ca21fc1ee
+./many/m240|regular file|644|0|0|9|1|1792402674|0:0|3c984e0dd57cac073eb661b0d0f29109
+./many/m241|regular file|644|0|0|9|1|1792402674|0:0|a258c82ce4afef4cca68689c77453826
+./many/m242|regular file|644|0|0|9|1|1792402674|0:0|6b54883641df548fc28508b25c86aa5c
+./many/m243|regular file|644|0|0|9|1|1792402674|0:0|dcf5e125abcc0c2d79c7fac3420a8c18
+./many/m244|regular file|644|0|0|9|1|1792402674|0:0|eae8fbc9bb9e78d145028f7d9c3bc8d0
+./many/m245|regular file|644|0|0|9|1|1792402674|0:0|9407f6a798e5c8f004d5dbaf383f1c74
+./many/m246|regular file|644|0|0|9|1|1792402674|0:0|d68fe80b8e1a1aa20086bd0ca2a11908
+./many/m247|regular file|644|0|0|9|1|1792402674|0:0|85e08221b360aad1f71717187de8de31
+./many/m248|regular file|644|0|0|9|1|1792402674|0:0|f8f29e99cf1a6fa9f1fc39b464a0eefa
+./many/m249|regular file|644|0|0|9|1|1792402674|0:0|d672e07abc4789ead0a03dbf1506fc10
+./many/m25|regular file|644|0|0|8|1|1792402673|0:0|9f3e693a89b092df52fb11b864feaea2
+./many/m250|regular file|644|0|0|9|1|1792402674|0:0|def9e8dcdee098475dcede72a442e269
+./many/m251|regular file|644|0|0|9|1|1792402674|0:0|f8d0e196be420cc42a176f6f209995f5
+./many/m252|regular file|644|0|0|9|1|1792402674|0:0|d99412924a6c1bb54f0ab10a0732ea68
+./many/m253|regular file|644|0|0|9|1|1792402674|0:0|387db4223e750a5d14ef3e50e628267d
+./many/m254|regular file|644|0|0|9|1|1792402674|0:0|5bdde7f2bbce279dcf767e1e34b9e136
+./many/m255|regular file|644|0|0|9|1|1792402674|0:0|e2d5d3a93c37a81e6ad42d458f4dbc57
+./many/m256|regular file|644|0|0|9|1|1792402674|0:0|116877df711114c0ca04aa6573c3cbe0
+./many/m257|regular file|644|0|0|9|1|1792402674|0:0|d80fab7a57a2940191cfdcfc4fd25c20
+./many/m258|regular file|644|0|0|9|1|1792402674|0:0|cfc3ccf0c1e67ee17b66b20e851d32cf
+./many/m259|regular file|644|0|0|9|1|1792402674|0:0|559c87fa5dc5b4169c0e0d5488d777d4
+./many/m26|regular file|644|0|0|8|1|1792402673|0:0|f8d152b9d740b43d2dfb5685af43a48e
+./many/m260|regular file|644|0|0|9|1|1792402674|0:0|d5e639b992b2752650e011c1401efa5d
+./many/m261|regular file|644|0|0|9|1|1792402674|0:0|7507aea9bc33c9c976c2f0b59d341121
+./many/m262|regular file|644|0|0|9|1|1792402674|0:0|fa81f64b113688dc58cde88499f9305f
+./many/m263|regular file|644|0|0|9|1|1792402674|0:0|a214a1ee8dcf140804b126adcbc7d08e
+./many/m264|regular file|644|0|0|9|1|1792402674|0:0|0bdc8921d4ed1613cdef11fb7955bc6f
+./many/m265|regular file|644|0|0|9|1|1792402674|0:0|dd6d021a5de3c50790f1fb02d27d5ddd
+./many/m266|regular file|644|0|0|9|1|1792402674|0:0|ad62fa2cc012b0172c3c3675236db4bb
+./many/m267|regular file|644|0|0|9|1|1792402674|0:0|3fb246e625173634453678b522a7f3fe
+./many/m268|regular file|644|0|0|9|1|1792402674|0:0|ae53335263effc40bd0fc9396e6873cf
+./many/m269|regular file|644|0|0|9|1|1792402674|0:0|ede3d51d87d5214df5ead1b85b3e4cc8
+./many/m27|regular file|644|0|0|8|1|1792402673|0:0|024c2c146a2f83a848ade5d706407328
+./many/m270|regular file|644|0|0|9|1|1792402674|0:0|007ada1f368f7b02f32a54c2da82489f
+./many/m271|regular file|644|0|0|9|1|1792402674|0:0|8051fd0b722ef442d3f46831341d8533
+./many/m272|regular file|644|0|0|9|1|1792402674|0:0|71c34027c99734d5bad2baba86e84e84
+./many/m273|regular file|644|0|0|9|1|1792402674|0:0|b7d34cf0aa38f7ebaecbccb36a09780d
+./many/m274|regular file|644|0|0|9|1|1792402674|0:0|da23114c72d046aba345454980dc13e8
+./many/m275|regular file|644|0|0|9|1|1792402674|0:0|54d707b3701e050cf8b9df18d236f796
+./many/m276|regular file|644|0|0|9|1|1792402674|0:0|334d0893d14cfba5eb3bcd4f18e9d1cc
+./many/m277|regular file|644|0|0|9|1|1792402674|0:0|c0ea39ae9c979278f5bbabe852793291
+./many/m278|regular file|644|0|0|9|1|1792402674|0:0|67792386a500691e513ab78a51ed0d8b
+./many/m279|regular file|644|0|0|9|1|1792402674|0:0|efcec77542ad2ac94b10b120bf19100d
+./many/m28|regular file|644|0|0|8|1|1792402673|0:0|5712274b725e57688a48a769312c7ed6
+./many/m280|regular file|644|0|0|9|1|1792402674|0:0|69ff3fe9c2a4522083daaaf13e4379b3
+./many/m281|regular file|644|0|0|9|1|1792402674|0:0|8732532455011bf125603f98ff251200
+./many/m282|regular file|644|0|0|9|1|1792402674|0:0|93ba143bcd3e6c3c5eec6cacce70cbdd
+./many/m283|regular file|644|0|0|9|1|1792402674|0:0|29ef81bc2e3b9ed567473fd300403cfa
+./many/m284|regular file|644|0|0|9|1|1792402674|0:0|868bd853528a957c194b24209755227c
+./many/m285|regular file|644|0|0|9|1|1792402674|0:0|aaf0b10ef42507eeed10d7cdd1ec8dd7
+./many/m286|regular file|644|0|0|9|1|1792402674|0:0|36bc3bf12e880cb2d1f0b3bab87d90aa
+./many/m287|regular file|644|0|0|9|1|1792402674|0:0|ec4dd1e32e75c8ead1c2545c166030a8
+./many/m288|regular file|644|0|0|9|1|1792402674|0:0|91072a04c92706be3799ff1e7cfa418e
+./many/m289|regular file|644|0|0|9|1|1792402674|0:0|3c55568e2159f1470746b971075f1463
+./many/m29|regular file|644|0|0|8|1|1792402673|0:0|6fb4036efe8048a5a9170260f092f84d
+./many/m290|regular file|644|0|0|9|1|1792402674|0:0|971c75301a3c514d229bb06a26ff788b
+./many/m291|regular file|644|0|0|9|1|1792402674|0:0|2750d16b615bd018b6d4365ab0d3b3cf
+./many/m292|regular file|644|0|0|9|1|1792402674|0:0|bcd598399a115e7eebffa26171c75293
+./many/m293|regular file|644|0|0|9|1|1792402674|0:0|7a765645f034a4c47a19033de0a4a944
+./many/m294|regular file|644|0|0|9|1|1792402674|0:0|e1451f4d8d7a417dfde7b6efa4447653
+./many/m295|regular file|644|0|0|9|1|1792402674|0:0|0fef9d1cf71a2e4b8fc9cde3dd94d70b
+./many/m296|regular file|644|0|0|9|1|1792402674|0:0|e89be74780a41e6dee591be36f30b41a
+./many/m297|regular file|644|0|0|9|1|1792402674|0:0|cbf104c5f2a731482f3669cd84b2dadc
+./many/m298|regular file|644|0|0|9|1|1792402674|0:0|ded58b5321af4738023e4f673a68a972
+./many/m299|regular file|644|0|0|9|1|1792402674|0:0|ddc7b78696b89d6d5c535f70362b5087
+./many/m3|regular file|644|0|0|7|1|1792402673|0:0|9c38e8324dbf031557c89d53a39f0b26
+./many/m30|regular file|644|0|0|8|1|1792402673|0:0|9defc48d530bd462729886fb0faf880c
+./many/m31|regular file|644|0|0|8|1|1792402673|0:0|c5ea05f8d8be61909c1b5b02f560c910
+./many/m32|regular file|644|0|0|8|1|1792402673|0:0|3a4d6240ced04e58f3426f37d8bb01bb
+./many/m33|regular file|644|0|0|8|1|1792402673|0:0|a9a487ecd437d987ba861b2c07efffb9
+./many/m34|regular file|644|0|0|8|1|1792402673|0:0|fc6d15842277346dcf7316b7821529ac
+./many/m35|regular file|644|0|0|8|1|1792402673|0:0|68262abef9fdd7c411159010c719d925
+./many/m36|regular file|644|0|0|8|1|1792402673|0:0|98dd3959a691f9d784c0ab6bd8d58205
+./many/m37|regular file|644|0|0|8|1|1792402673|0:0|092e4b003c31ef3a4d1912b514c6e79a
+./many/m38|regular file|644|0|0|8|1|1792402673|0:0|03107211cf5de1e732f2c7e940150af3
+./many/m39|regular file|644|0|0|8|1|1792402673|0:0|85869f52d139c315c12ffec6a14610c9
+./many/m4|regular file|644|0|0|7|1|1792402673|0:0|fb8b37442ead70d36d54d241a0c7e069
+./many/m40|regular file|644|0|0|8|1|1792402673|0:0|30aba7e5873781a5ae62664efed721b2
+./many/m41|regular file|644|0|0|8|1|1792402673|0:0|e9c7bcd9bc1db300793277157e4f41b4
+./many/m42|regular file|644|0|0|8|1|1792402673|0:0|9cb1389225c46059e110adaab69b81e8
+./many/m43|regular file|644|0|0|8|1|1792402673|0:0|0826b8f8fcb95d4d45a12eb61ca786d1
+./many/m44|regular file|644|0|0|8|1|1792402673|0:0|d1d0e549a5db32880a69049386ff6866
+./many/m45|regular file|644|0|0|8|1|1792402673|0:0|b9973dfba5ffca1c25bbad1ad20a238d
+./many/m46|regular file|644|0|0|8|1|1792402673|0:0|05f6704dab2c9d4395d04d1232a133d9
+./many/m47|regular file|644|0|0|8|1|1792402673|0:0|ef7cbaf29d0dad3b13062156cc56cce4
+./many/m48|regular file|644|0|0|8|1|1792402673|0:0|c283c0e3ef689fa6f1d44c22b4924fff
+./many/m49|regular file|644|0|0|8|1|1792402673|0:0|165cc8d27fdbe30571e39297862f46e4
+./many/m5|regular file|644|0|0|7|1|1792402673|0:0|0998a09014c94a7bdb6bb894495ed335
+./many/m50|regular file|644|0|0|8|1|1792402673|0:0|621e732a99e87995445afc50624e0c9e
+./many/m51|regular file|644|0|0|8|1|1792402673|0:0|f453ece2d7ab4e89a7bc3684cffa3e95
+./many/m52|regular file|644|0|0|8|1|1792402673|0:0|21cc25c9331a621f651e4bb1b3a12c2f
+./many/m53|regular file|644|0|0|8|1|1792402673|0:0|9ff7665cb56590ce5398ece8148eeb7f
+./many/m54|regular file|644|0|0|8|1|1792402673|0:0|9aba7daf532ea4fa81011e470d048a2d
+./many/m55|regular file|644|0|0|8|1|1792402673|0:0|8a6d937ad0c7da63a1c72b61d4f64e2e
+./many/m56|regular file|644|0|0|8|1|1792402673|0:0|58309f1f72eda1b78afd7b95915e7bbd
+./many/m57|regular file|644|0|0|8|1|1792402673|0:0|854d2f35e6eb992aea35c43ae5ff8383
+./many/m58|regular file|644|0|0|8|1|1792402673|0:0|861f23e8bc20e69f063187875204b9a9
+./many/m59|regular file|644|0|0|8|1|1792402673|0:0|5bff7815efc01ce1462568f77c64cdf1
+./many/m6|regular file|644|0|0|7|1|1792402673|0:0|ce5aa0d1c99005cde6aab017fb6307e8
+./many/m60|regular file|644|0|0|8|1|1792402673|0:0|e9e46c67288881002fc69b1a0f21010e
+./many/m61|regular file|644|0|0|8|1|1792402673|0:0|527df91adecb85ce4c2db1b24bbed4fc
+./many/m62|regular file|644|0|0|8|1|1792402673|0:0|c37a6db6720600c4fae00a87a36319dd
+./many/m63|regular file|644|0|0|8|1|1792402673|0:0|bbff5cc47a8f18d86ff8896c9d8403aa
+./many/m64|regular file|644|0|0|8|1|1792402673|0:0|ca0b9c3dc602c59e7f75c2acd68b1cc5
+./many/m65|regular file|644|0|0|8|1|1792402673|0:0|82f7a01e88f5bd8262f86df5332989bc
+./many/m66|regular file|644|0|0|8|1|1792402673|0:0|fd5c2f8ac0299646af81bf20ff386e96
+./many/m67|regular file|644|0|0|8|1|1792402673|0:0|d5b075302eba88ff5981a3ef1c41924a
+./many/m68|regular file|644|0|0|8|1|1792402673|0:0|dbf1249f5b05689a9eecf5011282689d
+./many/m69|regular file|644|0|0|8|1|1792402673|0:0|7fbfefe361ea0a0e7877f82dd48e84c8
+./many/m7|regular file|644|0|0|7|1|1792402673|0:0|f5df0384c964a01d9a01e31e7db512d7
+./many/m70|regular file|644|0|0|8|1|1792402673|0:0|2bad4a950b70855d1f2936ee934dbeb9
+./many/m71|regular file|644|0|0|8|1|1792402673|0:0|662b3f4049eef4f8afb7882958e7ff92
+./many/m72|regular file|644|0|0|8|1|1792402673|0:0|69e587e4d14c16015c08f8b23409a653
+./many/m73|regular file|644|0|0|8|1|1792402673|0:0|46aea6f0d4e272c61ee5bfade2637695
+./many/m74|regular file|644|0|0|8|1|1792402673|0:0|978b7bb8853811c47de913e43dde1051
+./many/m75|regular file|644|0|0|8|1|1792402673|0:0|0cc085bb42463401890025ebeb7aa35e
+./many/m76|regular file|644|0|0|8|1|1792402673|0:0|46b3e8777805e536f33c134aa5ceeb10
+./many/m77|regular file|644|0|0|8|1|1792402673|0:0|c7b78575ac96f1ed111d916941a080a9
+./many/m78|regular file|644|0|0|8|1|1792402673|0:0|198d54d980da418cc29e14f7b25852c6
+./many/m79|regular file|644|0|0|8|1|1792402673|0:0|3d77254be1d635b657d077a883ee63e4
+./many/m8|regular file|644|0|0|7|1|1792402673|0:0|48217eb11e28c1085fe4016fc067de76
+./many/m80|regular file|644|0|0|8|1|1792402673|0:0|4eb244481c13d9f49c33cf971ec52ada
+./many/m81|regular file|644|0|0|8|1|1792402673|0:0|42e04c82e620d1fd68e0f11561e42c84
+./many/m82|regular file|644|0|0|8|1|1792402673|0:0|633503a87cff957d06623e2d2588b032
+./many/m83|regular file|644|0|0|8|1|1792402673|0:0|e4cbadd929638b2607e480bfe2af4ebc
+./many/m84|regular file|644|0|0|8|1|1792402673|0:0|82bb34d3363108ce9ab1cfd91849eb21
+./many/m85|regular file|644|0|0|8|1|1792402673|0:0|68c9ada28f0b1bcad8d890cfdd17ac70
+./many/m86|regular file|644|0|0|8|1|1792402673|0:0|09a0c699e8aa36823d7832459c0f36ed
+./many/m87|regular file|644|0|0|8|1|1792402673|0:0|e1d0c50f92a5d4b993d7e831d01d6db5
+./many/m88|regular file|644|0|0|8|1|1792402673|0:0|d0fc62fc10609116527634f0046b60a0
+./many/m89|regular file|644|0|0|8|1|1792402673|0:0|bc70377b5cb3ac0469e13aff5413f389
+./many/m9|regular file|644|0|0|7|1|1792402673|0:0|61cdf324c2c53b1512c6d867c8deedf3
+./many/m90|regular file|644|0|0|8|1|1792402673|0:0|980649bfecb5eda730757cb11824ffb8
+./many/m91|regular file|644|0|0|8|1|1792402673|0:0|7062493ade7d9fbff23835457dcc2b85
+./many/m92|regular file|644|0|0|8|1|1792402673|0:0|4765be4d8b04b2d36df75d6b651f5de0
+./many/m93|regular file|644|0|0|8|1|1792402673|0:0|43e12b9b4189c8721f0c79264a327ff5
+./many/m94|regular file|644|0|0|8|1|1792402673|0:0|9419149493acdba1887798a89261d131
+./many/m95|regular file|644|0|0|8|1|1792402673|0:0|452ac7567de63f4b42feb2c072c8f93f
+./many/m96|regular file|644|0|0|8|1|1792402673|0:0|04803cac3256b8069e481ba28694ae19
+./many/m97|regular file|644|0|0|8|1|1792402673|0:0|4cbd8087d8038fd0627450310e9558c9
+./many/m98|regular file|644|0|0|8|1|1792402673|0:0|ba172daf8ce182f35ad39a3421a08581
+./many/m99|regular file|644|0|0|8|1|1792402673|0:0|4759b8c629df85d7c5e91be096e11982
+./sparse|regular file|644|0|0|200705|1|1792402673|0:0|f8ac51c4658d3cb55cbfca28b1aed2fc
+./sym_long|symbolic link|777|0|0|423|1|1792402673|0:0|target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/target/end
+./sym_short|symbolic link|777|0|0|6|1|1792402673|0:0|f_text
diff --git a/Compression.Tests/Reiser4/Reiser4FeatureExternalTests.cs b/Compression.Tests/Reiser4/Reiser4FeatureExternalTests.cs
new file mode 100644
index 000000000..2eebc666e
--- /dev/null
+++ b/Compression.Tests/Reiser4/Reiser4FeatureExternalTests.cs
@@ -0,0 +1,174 @@
+using System.Text;
+using System.Text.RegularExpressions;
+using Compression.Registry;
+using FileSystem.Reiser4;
+
+namespace Compression.Tests.Reiser4;
+
+///
+/// reiser4progs judges every plugin profile, body type and object kind the writer handles:
+/// fsck.reiser4 --check must call each volume consistent, debugfs.reiser4 must resolve
+/// the names (keyed with the volume's own hash and fibration) and show the bytes of plain files, and
+/// the volume's plugin profile must survive every edit. Runs in the CI "Reiser4 oracle" gate.
+///
+[TestFixture]
+[Category("ExternalFsInterop")]
+public sealed class Reiser4FeatureExternalTests {
+
+ private string _tmpDir = null!;
+
+ [SetUp]
+ public void SetUp() {
+ this._tmpDir = Path.Combine(Path.GetTempPath(), "cwb_r4feat_" + Guid.NewGuid().ToString("N")[..8]);
+ Directory.CreateDirectory(this._tmpDir);
+ }
+
+ [TearDown]
+ public void TearDown() {
+ try { Directory.Delete(this._tmpDir, recursive: true); } catch { /* best effort */ }
+ }
+
+ private static byte[] Text(int lines, int salt) {
+ var text = new StringBuilder();
+ for (var i = 0; i < lines; ++i) text.Append("line ").Append(i).Append(" of ").Append(salt).Append(": plain words the printf in debugfs cannot misread\n");
+ return Encoding.ASCII.GetBytes(text.ToString());
+ }
+
+ private string Save(string name, byte[] image) {
+ var path = Path.Combine(this._tmpDir, name);
+ File.WriteAllBytes(path, image);
+ return path;
+ }
+
+ private byte[] Mkfs(string name, string options) {
+ var path = Path.Combine(this._tmpDir, name + ".mkfs.img");
+ var wsl = FsInteropToolbox.WinToWsl(path);
+ var run = FsInteropToolbox.RunWsl($"truncate -s 64M {wsl} && mkfs.reiser4 -fffy -L {name} {options} {wsl}");
+ Assert.That(run.ExitCode, Is.EqualTo(0), $"mkfs.reiser4 {options} failed:\n{run.StdOut}\n{run.StdErr}");
+ return File.ReadAllBytes(path);
+ }
+
+ private static void AssertFsckConsistent(string path) {
+ var wsl = FsInteropToolbox.WinToWsl(path);
+ var run = FsInteropToolbox.RunWsl($"cp {wsl} {wsl}.fsck && fsck.reiser4 --check -y {wsl}.fsck; rc=$?; rm -f {wsl}.fsck; exit $rc");
+ var text = run.StdOut + "\n" + run.StdErr;
+ Assert.That(run.ExitCode, Is.EqualTo(0), $"fsck.reiser4 rejected {Path.GetFileName(path)}:\n{text}");
+ Assert.That(text, Does.Contain("FS is consistent"), $"fsck.reiser4 did not call {Path.GetFileName(path)} consistent:\n{text}");
+ }
+
+ ///
+ /// The bytes of a plain-text file as debugfs.reiser4 -k reads them through its own path lookup and
+ /// body plugins. reiser4progs keys a lookup below the root with its own default profile rather
+ /// than the root's plugin set (a kernel-written volume behaves the same way), so the volume's
+ /// mkfs options are handed to it as its profile.
+ ///
+ private static string Cat(string path, string member, string profile = "") {
+ var run = FsInteropToolbox.RunWsl($"debugfs.reiser4 {profile} -k '/{member}' {FsInteropToolbox.WinToWsl(path)} /dev/null");
+ Assert.That(run.ExitCode, Is.EqualTo(0), $"debugfs.reiser4 -k /{member} failed:\n{run.StdOut}\n{run.StdErr}");
+ return run.StdOut;
+ }
+
+ /// What debugfs.reiser4 -i prints about an object (its stat data and every item).
+ private static string Items(string path, string member, string profile = "") {
+ var run = FsInteropToolbox.RunWsl($"debugfs.reiser4 {profile} -i '/{member}' {FsInteropToolbox.WinToWsl(path)} &1");
+ Assert.That(run.ExitCode, Is.EqualTo(0), $"debugfs.reiser4 -i /{member} failed:\n{run.StdOut}\n{run.StdErr}");
+ Assert.That(run.StdOut, Does.Not.Contain("Can't find"), $"debugfs.reiser4 cannot resolve /{member}:\n{run.StdOut}");
+ return run.StdOut;
+ }
+
+ private static string RootProfile(string path) {
+ var info = Items(path, "");
+ return string.Join('\n', info.Split('\n').Select(static l => l.Trim()).Where(static l => Regex.IsMatch(l, @"^\w+ : id = ")));
+ }
+
+ public static readonly string[] Profiles = [
+ "-o hash=tea_hash", "-o hash=fnv1_hash", "-o hash=deg_hash", "-o hash=r5_hash",
+ "-o fibration=lexic_fibre", "-o fibration=dot_o_fibre", "-o fibration=ext_1_fibre", "-o fibration=ext_3_fibre",
+ "-o formatting=tails", "-o formatting=extents", "-o formatting=smart", "-o create=reg40",
+ "-o compress=gzip1", "-o compress=zstd1", "-o compressMode=force", "-o compressMode=none", "-o cluster=4K",
+ "-o node=node41", "-o create=reg40,formatting=tails,hash=tea_hash,fibration=ext_3_fibre",
+ ];
+
+ [TestCaseSource(nameof(Profiles)), Category("HappyPath")]
+ public void GivenAVolumeMkfsMadeWithAPluginProfile_WhenAddingFilesUnderEveryBodyType_ThenFsckPassesTheNamesResolveAndTheProfileStays(string options) {
+ Reiser4Oracle.Require();
+ var original = this.Mkfs("prof", options);
+ var originalPath = this.Save("original.img", original);
+ using var image = new MemoryStream();
+ image.Write(original);
+ var descriptor = new Reiser4FormatDescriptor();
+ var names = new[] { "plain.txt", "a-name-longer-than-twenty-three-characters.txt", "source.c", "object.o", "x.abc", new string('z', 255) };
+ var seed = 0;
+ foreach (var body in new[] { Reiser4FileBody.Extents, Reiser4FileBody.Tails, Reiser4FileBody.Profile })
+ descriptor.Add(image, [.. names.Select(n => ArchiveInputInfo.InMemory($"{body}/{n}", Text(300, ++seed)))], body);
+ descriptor.AddSymlink(image, "links/to-plain", "../Extents/plain.txt");
+ descriptor.AddHardLink(image, "links/hard", "Tails/source.c");
+ descriptor.AddSpecialFile(image, "links/fifo", 0x11A4);
+ var edited = this.Save("edited.img", image.ToArray());
+
+ AssertFsckConsistent(edited);
+ Assert.Multiple(() => {
+ Assert.That(RootProfile(edited), Is.EqualTo(RootProfile(originalPath)).And.Not.Empty, "the root's plugin set");
+ seed = 0;
+ foreach (var body in new[] { Reiser4FileBody.Extents, Reiser4FileBody.Tails, Reiser4FileBody.Profile })
+ foreach (var name in names) {
+ var text = Encoding.ASCII.GetString(Text(300, ++seed));
+ var items = Items(edited, $"{body}/{name}", options);
+ // reiser4progs has no decompressor: a cryptcompress file's bytes are the kernel oracle's to judge.
+ if (!items.Contains("ccreg40", StringComparison.Ordinal))
+ Assert.That(Cat(edited, $"{body}/{name}", options), Does.Contain(text), $"{options}: {body}/{name}");
+ }
+ Assert.That(Items(edited, "links/to-plain", options), Does.Contain("../Extents/plain.txt"));
+ Assert.That(Items(edited, "links/hard", options), Does.Contain("nlink:\t\t2"));
+ });
+ }
+
+ [Test, Category("HappyPath")]
+ public void GivenTheRupasovHash_WhenAddingNames_ThenShortNamesAreAddedAndLongOnesRefusedWithTheImageUntouched() {
+ Reiser4Oracle.Require();
+ var original = this.Mkfs("rupasov", "-o hash=rupasov_hash");
+ using var image = new MemoryStream();
+ image.Write(original);
+ var descriptor = new Reiser4FormatDescriptor();
+ descriptor.Add(image, [ArchiveInputInfo.InMemory("short-name.txt", Text(10, 1))]);
+ var afterShort = image.ToArray();
+ var error = Assert.Throws(() => descriptor.Add(image,
+ [ArchiveInputInfo.InMemory("a-name-longer-than-twenty-three-characters.txt", Text(10, 2))]));
+ var path = this.Save("rupasov.img", image.ToArray());
+ Assert.Multiple(() => {
+ Assert.That(error!.Message, Does.Contain("Rupasov"));
+ Assert.That(image.ToArray(), Is.EqualTo(afterShort), "a refused edit leaves the image byte-identical");
+ });
+ AssertFsckConsistent(path);
+ Assert.That(Cat(path, "short-name.txt"), Does.Contain(Encoding.ASCII.GetString(Text(10, 1))));
+ }
+
+ [TestCaseSource(typeof(Reiser4KernelVolumeTests), nameof(Reiser4KernelVolumeTests.EditableVolumes)), Category("HappyPath")]
+ public void GivenAVolumeTheKernelWrote_WhenEditing_ThenFsckCallsItConsistent(string volume) {
+ Reiser4Oracle.Require();
+ using var image = new MemoryStream();
+ image.Write(Reiser4KernelVolumeTests.Image(volume));
+ var descriptor = new Reiser4FormatDescriptor();
+ descriptor.Add(image, [ArchiveInputInfo.InMemory("added/a-new-name-longer-than-twenty-three.txt", Text(500, 3))], Reiser4FileBody.Profile);
+ descriptor.AddSymlink(image, "added/link", "../f_100");
+ descriptor.Remove(image, ["dir/foo.o"]);
+ AssertFsckConsistent(this.Save($"{volume}.img", image.ToArray()));
+ }
+
+ [Test, Category("HappyPath")]
+ public void GivenATallTree_WhenScatteringAndDefragmentingInPlace_ThenFsckCallsEveryStepConsistentAndNoNodeMoves() {
+ Reiser4Oracle.Require();
+ var writer = new Reiser4Writer { BlockCount = 16_384 };
+ for (var i = 0; i < 1_500; ++i) writer.AddFile($"t/f{i:D5}", Text(1 + i % 60, i));
+ using var image = new MemoryStream(writer.Build());
+ var nodes = Reiser4TestLayouts.NodeBlocks(image);
+ Assert.That(Reiser4TestLayouts.NodeBlocks(image).Length, Is.GreaterThan(20), "a tree of several twigs");
+ Reiser4TestLayouts.ScatterInPlace(image);
+ AssertFsckConsistent(this.Save("scattered.img", image.ToArray()));
+ new Reiser4FormatDescriptor().Defragment(image);
+ var path = this.Save("defragmented.img", image.ToArray());
+ AssertFsckConsistent(path);
+ Assert.That(Reiser4TestLayouts.NodeBlocks(image), Is.EqualTo(nodes), "the in-place pass moved data, not nodes");
+ Assert.That(Cat(path, "t/f01499"), Does.Contain(Encoding.ASCII.GetString(Text(1 + 1_499 % 60, 1_499))));
+ }
+}
diff --git a/Compression.Tests/Reiser4/Reiser4KernelOracle.cs b/Compression.Tests/Reiser4/Reiser4KernelOracle.cs
new file mode 100644
index 000000000..d338e2097
--- /dev/null
+++ b/Compression.Tests/Reiser4/Reiser4KernelOracle.cs
@@ -0,0 +1,58 @@
+namespace Compression.Tests.Reiser4;
+
+///
+/// A Reiser4 kernel under QEMU as the oracle: it mounts an image, resolves every path and reads
+/// every file whole, and reports what it found as a manifest (see KernelOracle/). Nothing a
+/// test does with it is taken on our reader's word.
+///
+///
+/// The kernel package is fetched once by kernel-run.sh --prepare; tests do that only when
+/// CWB_REISER4_KERNEL_DOWNLOAD=1, and otherwise skip unless it is already in place.
+///
+internal static class Reiser4KernelOracle {
+
+ private static readonly string ScriptDirectory = Path.Combine(AppContext.BaseDirectory, "Reiser4", "KernelOracle");
+ private static bool? _available;
+
+ internal static void Require() {
+ if (!FsInteropToolbox.WslAvailable && OperatingSystem.IsWindows())
+ Assert.Ignore("WSL is not available on this machine.");
+ _available ??= Prepare();
+ if (_available != true)
+ Assert.Ignore("The Reiser4 kernel oracle is not prepared (set CWB_REISER4_KERNEL_DOWNLOAD=1 to fetch it; needs qemu-system-x86_64).");
+ }
+
+ private static bool Prepare() {
+ var script = FsInteropToolbox.WinToWsl(Path.Combine(ScriptDirectory, "kernel-run.sh"));
+ var mode = Environment.GetEnvironmentVariable("CWB_REISER4_KERNEL_DOWNLOAD") == "1" ? "--prepare" : "--check";
+ return FsInteropToolbox.RunWsl($"bash {script} {mode}").ExitCode == 0;
+ }
+
+ /// What the kernel made of an image: its manifest and any complaints it logged.
+ internal sealed record Mount(IReadOnlyDictionary Manifest, string[] Complaints, string Log);
+
+ /// Mounts a copy of and reads everything in it.
+ internal static Mount Read(string imagePath) {
+ var copy = imagePath + ".kernel";
+ File.Copy(imagePath, copy, overwrite: true);
+ try {
+ var script = FsInteropToolbox.WinToWsl(Path.Combine(ScriptDirectory, "kernel-run.sh"));
+ var guest = FsInteropToolbox.WinToWsl(Path.Combine(ScriptDirectory, "manifest.sh"));
+ var run = FsInteropToolbox.RunWsl($"bash {script} {FsInteropToolbox.WinToWsl(copy)} {guest}");
+ var log = run.StdOut + "\n" + run.StdErr;
+ Assert.That(run.ExitCode, Is.EqualTo(0), $"the kernel run did not finish:\n{log}");
+ Assert.That(log, Does.Not.Contain("MOUNTFAIL"), $"the kernel refused to mount the volume:\n{log}");
+ var complaints = log.Split('\n').Where(static l => l.StartsWith("dmesg:", StringComparison.Ordinal))
+ .Where(static l => l.Contains("WARNING", StringComparison.OrdinalIgnoreCase) || l.Contains("error", StringComparison.OrdinalIgnoreCase) ||
+ l.Contains("bad", StringComparison.OrdinalIgnoreCase) || l.Contains("fsck", StringComparison.OrdinalIgnoreCase) ||
+ l.Contains("BUG", StringComparison.Ordinal) || l.Contains("Oops", StringComparison.Ordinal))
+ .ToArray();
+ var start = log.IndexOf("===MANIFEST===", StringComparison.Ordinal);
+ var end = log.IndexOf("===END-MANIFEST===", StringComparison.Ordinal);
+ Assert.That(start >= 0 && end > start, Is.True, $"the kernel printed no manifest:\n{log}");
+ return new Mount(Reiser4KernelVolumeTests.ParseManifest(log[start..end]), complaints, log);
+ } finally {
+ try { File.Delete(copy); } catch { /* best effort */ }
+ }
+ }
+}
diff --git a/Compression.Tests/Reiser4/Reiser4KernelOracleTests.cs b/Compression.Tests/Reiser4/Reiser4KernelOracleTests.cs
new file mode 100644
index 000000000..5d10dcaed
--- /dev/null
+++ b/Compression.Tests/Reiser4/Reiser4KernelOracleTests.cs
@@ -0,0 +1,197 @@
+using System.Security.Cryptography;
+using System.Text;
+using Compression.Registry;
+using FileSystem.Reiser4;
+
+namespace Compression.Tests.Reiser4;
+
+///
+/// The Reiser4 kernel judges what the writer produces: it mounts each volume, resolves every path
+/// and reads every byte, and its manifest must be what was written. Volumes it wrote itself are
+/// edited and handed back to it, so carried objects, new names keyed under every hash and
+/// fibration plugin, and compressed clusters written with lzo1, gzip1 and zstd1 are all read by the
+/// implementation that owns the format. Wherever reiser4progs is installed, fsck.reiser4 checks the
+/// same volumes.
+///
+[TestFixture]
+[Category("ExternalFsInterop")]
+public sealed class Reiser4KernelOracleTests {
+
+ private string _tmpDir = null!;
+
+ [SetUp]
+ public void SetUp() {
+ this._tmpDir = Path.Combine(Path.GetTempPath(), "cwb_r4kernel_" + Guid.NewGuid().ToString("N")[..8]);
+ Directory.CreateDirectory(this._tmpDir);
+ }
+
+ [TearDown]
+ public void TearDown() {
+ try { Directory.Delete(this._tmpDir, recursive: true); } catch { /* best effort */ }
+ }
+
+ private static byte[] Random(int length, int seed) {
+ var bytes = new byte[length];
+ new Random(seed).NextBytes(bytes);
+ return bytes;
+ }
+
+ private static byte[] Text(int lines) {
+ var text = new StringBuilder();
+ for (var i = 0; i < lines; ++i) text.Append("line ").Append(i).Append(": compressible text for the cluster codecs\n");
+ return Encoding.ASCII.GetBytes(text.ToString());
+ }
+
+ private static string Md5(byte[] data) => Convert.ToHexString(MD5.HashData(data)).ToLowerInvariant();
+
+ private string Save(string name, byte[] image) {
+ var path = Path.Combine(this._tmpDir, name);
+ File.WriteAllBytes(path, image);
+ return path;
+ }
+
+ /// fsck.reiser4 --check on a copy, when reiser4progs is reachable.
+ private static void FsckIfAvailable(string path) {
+ if (!FsInteropToolbox.WslHasTool("fsck.reiser4")) return;
+ var wsl = FsInteropToolbox.WinToWsl(path);
+ var run = FsInteropToolbox.RunWsl($"cp {wsl} {wsl}.fsck && fsck.reiser4 --check -y {wsl}.fsck; rc=$?; rm -f {wsl}.fsck; exit $rc");
+ var text = run.StdOut + "\n" + run.StdErr;
+ Assert.That(run.ExitCode == 0 && text.Contains("FS is consistent"), Is.True, $"fsck.reiser4 rejected {Path.GetFileName(path)}:\n{text}");
+ }
+
+ /// What a test expects the kernel to find at a path.
+ private sealed record Expected(string Type, long Size, string Value, uint Links = 0, int Mode = -1, ulong Device = 0);
+
+ private static void AssertKernelReads(string path, IReadOnlyDictionary expected, IReadOnlySet? unchecked_ = null) {
+ var mount = Reiser4KernelOracle.Read(path);
+ Assert.That(mount.Complaints, Is.Empty, "the kernel logged complaints:\n" + string.Join('\n', mount.Complaints));
+ var seen = mount.Manifest.Keys.Where(static k => k != ".").Order(StringComparer.Ordinal).ToArray();
+ Assert.That(seen, Is.EqualTo(expected.Keys.Order(StringComparer.Ordinal)), "the namespace the kernel resolves");
+ Assert.Multiple(() => {
+ foreach (var (name, want) in expected) {
+ if (unchecked_?.Contains(name) == true) continue;
+ var got = mount.Manifest[name];
+ Assert.That(got.Type, Is.EqualTo(want.Type), name + " type");
+ if (want.Type != "directory") Assert.That(got.Size, Is.EqualTo(want.Size), name + " size");
+ if (want.Value.Length > 0) Assert.That(got.Value, Is.EqualTo(want.Value), name + " bytes or target");
+ if (want.Links != 0) Assert.That(got.Links, Is.EqualTo(want.Links), name + " links");
+ if (want.Mode >= 0) Assert.That(got.Mode, Is.EqualTo(want.Mode), name + " mode");
+ if (want.Device != 0) Assert.That(got.Device, Is.EqualTo(want.Device), name + " device");
+ }
+ });
+ }
+
+ private static Dictionary FromManifest(IReadOnlyDictionary manifest)
+ => manifest.Where(static p => p.Key != ".").ToDictionary(static p => p.Key,
+ static p => new Expected(p.Value.Type, p.Value.Size, p.Value.Value, p.Value.Links, p.Value.Mode, p.Value.Device), StringComparer.Ordinal);
+
+ [TestCase(Reiser4FileBody.Extents)]
+ [TestCase(Reiser4FileBody.Tails)]
+ [TestCase(Reiser4FileBody.Smart)]
+ [TestCase(Reiser4FileBody.Compressed)]
+ [Category("HappyPath")]
+ public void GivenEveryObjectKindTheWriterMakes_WhenTheKernelMountsTheVolume_ThenItReadsBackExactlyWhatWasWritten(Reiser4FileBody body) {
+ Reiser4KernelOracle.Require();
+ var writer = new Reiser4Writer { FileBody = body, BlockCount = 8192 };
+ var expected = new Dictionary(StringComparer.Ordinal);
+ void File(string name, byte[] data) {
+ writer.AddFile(name, data);
+ expected[name] = new Expected(data.Length == 0 ? "regular empty file" : "regular file", data.Length, Md5(data));
+ }
+ void Directory(string name) => expected[name] = new Expected("directory", 0, "");
+ var seed = 0;
+ foreach (var size in new[] { 0, 1, 4_095, 4_096, 4_097, 16_384, 16_385, 70_000 }) File($"sizes/f{size}", Random(size, ++seed));
+ File("sizes/text.c", Text(6_000));
+ File("names/" + new string('n', 23), Random(10, ++seed));
+ File("names/" + new string('n', 24), Random(10, ++seed));
+ File("names/a-name-longer-than-twenty-three.txt", Random(10, ++seed));
+ File("names/" + new string('x', 255), Random(10, ++seed));
+ File("names/x.c", Random(10, ++seed));
+ File("names/x.o", Random(10, ++seed));
+ writer.AddDirectory("empty/inner");
+ writer.AddSymlink("links/short", "../sizes/f1");
+ var longTarget = string.Concat(Enumerable.Repeat("target/", 60)) + "end";
+ writer.AddSymlink("links/long", longTarget);
+ writer.AddHardLink("links/hard", "sizes/f4097");
+ writer.AddSpecialFile("special/fifo", 0x11A4);
+ writer.AddSpecialFile("special/char", 0x21A4, 1UL << 20 | 3);
+ writer.AddSpecialFile("special/block", 0x61A4, 7UL << 20);
+ writer.AddSpecialFile("special/socket", 0xC1ED);
+ expected["sizes/f4097"] = expected["sizes/f4097"] with { Links = 2 };
+ expected["links/hard"] = expected["sizes/f4097"];
+ expected["links/short"] = new Expected("symbolic link", 11, "../sizes/f1");
+ expected["links/long"] = new Expected("symbolic link", longTarget.Length, longTarget);
+ expected["special/fifo"] = new Expected("fifo", 0, "", Mode: 0x1A4);
+ expected["special/char"] = new Expected("character special file", 0, "", Device: 1UL << 20 | 3);
+ expected["special/block"] = new Expected("block special file", 0, "", Device: 7UL << 20);
+ expected["special/socket"] = new Expected("socket", 0, "", Mode: 0x1ED);
+ foreach (var dir in new[] { "sizes", "names", "empty", "empty/inner", "links", "special" }) Directory(dir);
+
+ var path = this.Save($"kinds-{body}.img", writer.Build());
+ FsckIfAvailable(path);
+ AssertKernelReads(path, expected);
+ }
+
+ [TestCaseSource(typeof(Reiser4KernelVolumeTests), nameof(Reiser4KernelVolumeTests.EditableVolumes)), Category("HappyPath")]
+ public void GivenAVolumeTheKernelWrote_WhenAddingLinkingAndRemoving_ThenTheKernelReadsEveryCarriedAndAddedObject(string volume) {
+ Reiser4KernelOracle.Require();
+ var manifest = Reiser4KernelVolumeTests.Manifest(volume);
+ var expected = FromManifest(manifest);
+ using var image = new MemoryStream();
+ image.Write(Reiser4KernelVolumeTests.Image(volume));
+ var descriptor = new Reiser4FormatDescriptor();
+
+ var text = Text(4_000);
+ var noise = Random(30_000, 11);
+ // Profile: on a cryptcompress volume the new files are compressed clusters made with the
+ // volume's own compression plugin and cluster size.
+ descriptor.Add(image, [
+ ArchiveInputInfo.InMemory("added/compressible-text-with-a-long-name.txt", text),
+ ArchiveInputInfo.InMemory("added/noise.bin", noise),
+ new ArchiveInputInfo("", "added/empty", IsDirectory: true),
+ ], Reiser4FileBody.Profile);
+ descriptor.AddSymlink(image, "added/link", "../f_100");
+ descriptor.AddHardLink(image, "added/hard", "f_4097");
+ var removed = manifest.Keys.First(static k => k.StartsWith("many/", StringComparison.Ordinal));
+ descriptor.Remove(image, [removed, "dir/foo.o"]);
+
+ expected.Remove(removed);
+ expected.Remove("dir/foo.o");
+ expected["added"] = new Expected("directory", 0, "");
+ expected["added/empty"] = new Expected("directory", 0, "");
+ expected["added/compressible-text-with-a-long-name.txt"] = new Expected("regular file", text.Length, Md5(text));
+ expected["added/noise.bin"] = new Expected("regular file", noise.Length, Md5(noise));
+ expected["added/link"] = new Expected("symbolic link", 8, "../f_100");
+ expected["f_4097"] = expected["f_4097"] with { Links = expected["f_4097"].Links + 1 };
+ expected["added/hard"] = expected["f_4097"];
+
+ var path = this.Save($"{volume}-edited.img", image.ToArray());
+ FsckIfAvailable(path);
+ AssertKernelReads(path, expected, new HashSet(StringComparer.Ordinal) { "many", "dir" });
+ }
+
+ [Test, Category("HappyPath")]
+ public void GivenATallTree_WhenDefragmentingInPlace_ThenTheKernelReadsEveryFileFromItsNewBlocks() {
+ Reiser4KernelOracle.Require();
+ var writer = new Reiser4Writer { BlockCount = 16_384 };
+ var expected = new Dictionary(StringComparer.Ordinal) { ["t"] = new("directory", 0, "") };
+ for (var i = 0; i < 1_500; ++i) {
+ var data = Random(1 + i % 9_000, i);
+ writer.AddFile($"t/f{i:D5}", data);
+ expected[$"t/f{i:D5}"] = new Expected("regular file", data.Length, Md5(data));
+ }
+ using var image = new MemoryStream(writer.Build());
+ var descriptor = new Reiser4FormatDescriptor();
+ descriptor.Remove(image, [.. Enumerable.Range(0, 1_500).Where(static i => i % 3 == 0).Select(static i => $"t/f{i:D5}")]);
+ foreach (var i in Enumerable.Range(0, 1_500).Where(static i => i % 3 == 0)) expected.Remove($"t/f{i:D5}");
+ // Removal by rebuild leaves the volume compact; scatter it again so the in-place pass has work.
+ Reiser4TestLayouts.ScatterInPlace(image);
+ byte[] before = image.ToArray();
+ descriptor.Defragment(image);
+ Assert.That(Reiser4TestLayouts.NodeBlocks(image), Is.EqualTo(Reiser4TestLayouts.NodeBlocks(new MemoryStream(before))),
+ "an in-place pass leaves every tree node where it was");
+ var path = this.Save("tall-defragmented.img", image.ToArray());
+ FsckIfAvailable(path);
+ AssertKernelReads(path, expected);
+ }
+}
diff --git a/Compression.Tests/Reiser4/Reiser4KernelVolumeTests.cs b/Compression.Tests/Reiser4/Reiser4KernelVolumeTests.cs
new file mode 100644
index 000000000..342b81ed4
--- /dev/null
+++ b/Compression.Tests/Reiser4/Reiser4KernelVolumeTests.cs
@@ -0,0 +1,185 @@
+using System.Globalization;
+using System.IO.Compression;
+using System.Security.Cryptography;
+using Compression.Registry;
+using FileSystem.Reiser4;
+
+namespace Compression.Tests.Reiser4;
+
+///
+/// Volumes a Reiser4 kernel wrote (see ReferenceVectors/README.md): each was formatted by
+/// mkfs.reiser4 with a plugin profile and filled through the kernel's own write path, and the
+/// manifest beside it is what the kernel read back. The reader must agree with it entry for entry,
+/// byte for byte, and the editor must carry every object across an edit unchanged.
+///
+[TestFixture]
+public sealed class Reiser4KernelVolumeTests {
+
+ internal static readonly string[] Volumes = [
+ "default", "gzip1-force-8k", "zstd1-latt-16k", "lzo1-none-4k", "reg40-smart", "reg40-tails", "reg40-node41",
+ "node41", "tea-lexic", "fnv1-dot-o", "deg-ext-3", "rupasov", "journal-replay",
+ ];
+
+ /// Volumes populate.sh filled whose names the writer may key: every hash but Rupasov.
+ internal static readonly string[] EditableVolumes = [.. Volumes.Where(static v => v is not ("rupasov" or "journal-replay"))];
+
+ internal static byte[] Image(string name) {
+ using var resource = typeof(Reiser4KernelVolumeTests).Assembly.GetManifestResourceStream($"Reiser4Vectors.{name}.img.gz")
+ ?? throw new InvalidOperationException($"reference volume {name} is not embedded");
+ using var gzip = new GZipStream(resource, CompressionMode.Decompress);
+ using var bytes = new MemoryStream();
+ gzip.CopyTo(bytes);
+ return bytes.ToArray();
+ }
+
+ /// One line of a kernel manifest.
+ internal sealed record ManifestEntry(string Path, string Type, int Mode, uint Uid, uint Gid, long Size, uint Links,
+ long ModifiedTime, ulong Device, string Value);
+
+ internal static Dictionary Manifest(string name) {
+ using var resource = typeof(Reiser4KernelVolumeTests).Assembly.GetManifestResourceStream($"Reiser4Vectors.{name}.manifest")
+ ?? throw new InvalidOperationException($"manifest {name} is not embedded");
+ using var reader = new StreamReader(resource);
+ return ParseManifest(reader.ReadToEnd());
+ }
+
+ internal static Dictionary ParseManifest(string text) {
+ var result = new Dictionary(StringComparer.Ordinal);
+ foreach (var raw in text.Split('\n')) {
+ var line = raw.TrimEnd('\r');
+ if (!line.StartsWith("./", StringComparison.Ordinal)) continue;
+ var f = line.Split('|');
+ var device = f[8].Split(':');
+ var major = Convert.ToUInt64(device[0], 16);
+ var minor = Convert.ToUInt64(device[1], 16);
+ result[f[0][2..]] = new ManifestEntry(f[0][2..], f[1], Convert.ToInt32(f[2], 8), uint.Parse(f[3], CultureInfo.InvariantCulture),
+ uint.Parse(f[4], CultureInfo.InvariantCulture), long.Parse(f[5], CultureInfo.InvariantCulture), uint.Parse(f[6], CultureInfo.InvariantCulture),
+ long.Parse(f[7], CultureInfo.InvariantCulture), major << 20 | minor, string.Join('|', f[9..]));
+ }
+ return result;
+ }
+
+ private static string Md5(byte[] data) => Convert.ToHexString(MD5.HashData(data)).ToLowerInvariant();
+
+ /// Asserts the reader sees exactly what the kernel manifest lists.
+ internal static void AssertMatches(Reiser4Reader reader, IReadOnlyDictionary manifest, string label,
+ IReadOnlySet? skip = null) {
+ Assert.That(reader.NativeTreeValid, Is.True, $"{label}: {reader.NativeProblem}");
+ var entries = reader.Entries.ToDictionary(static e => e.Name, StringComparer.Ordinal);
+ var expected = manifest.Where(p => p.Key != "." && skip?.Contains(p.Key) != true).ToDictionary(StringComparer.Ordinal);
+ Assert.That(entries.Keys.Where(k => skip?.Contains(k) != true).Order(StringComparer.Ordinal),
+ Is.EqualTo(expected.Keys.Order(StringComparer.Ordinal)), $"{label}: the namespace");
+ foreach (var (path, want) in expected) {
+ var entry = entries[path];
+ var metadata = entry.Metadata!;
+ var where = $"{label}: {path}";
+ Assert.That(metadata.Mode & 0xFFF, Is.EqualTo(want.Mode), where + " mode");
+ Assert.That(metadata.UserId, Is.EqualTo(want.Uid), where + " uid");
+ Assert.That(metadata.GroupId, Is.EqualTo(want.Gid), where + " gid");
+ Assert.That(metadata.ModifiedTime, Is.EqualTo((uint)want.ModifiedTime), where + " mtime");
+ Assert.That(metadata.LinkCount, Is.EqualTo(want.Links), where + " links");
+ switch (want.Type) {
+ case "directory":
+ Assert.That(entry.IsDirectory, Is.True, where);
+ Assert.That(metadata.Size, Is.EqualTo(want.Size), where + " size");
+ break;
+ case "regular file" or "regular empty file":
+ Assert.That(entry.Kind, Is.EqualTo(Reiser4Reader.EntryKind.File), where);
+ Assert.That(entry.Size, Is.EqualTo(want.Size), where + " size");
+ Assert.That(Md5(reader.Extract(entry)), Is.EqualTo(want.Value), where + " bytes");
+ break;
+ case "symbolic link":
+ Assert.That(entry.Kind, Is.EqualTo(Reiser4Reader.EntryKind.Symlink), where);
+ Assert.That(entry.LinkTarget, Is.EqualTo(want.Value), where + " target");
+ break;
+ case "fifo":
+ Assert.That(entry.Kind, Is.EqualTo(Reiser4Reader.EntryKind.Fifo), where);
+ break;
+ case "character special file":
+ Assert.That(entry.Kind, Is.EqualTo(Reiser4Reader.EntryKind.CharacterDevice), where);
+ Assert.That(entry.Device, Is.EqualTo(want.Device), where + " device");
+ break;
+ case "block special file":
+ Assert.That(entry.Kind, Is.EqualTo(Reiser4Reader.EntryKind.BlockDevice), where);
+ Assert.That(entry.Device, Is.EqualTo(want.Device), where + " device");
+ break;
+ default:
+ Assert.Fail($"{where}: unexpected manifest type {want.Type}");
+ break;
+ }
+ }
+ }
+
+ [TestCaseSource(nameof(Volumes)), Category("HappyPath")]
+ public void GivenAVolumeTheKernelWrote_WhenReading_ThenEveryEntryMatchesWhatTheKernelReadBack(string volume) {
+ using var reader = new Reiser4Reader(new MemoryStream(Image(volume)));
+ Assert.Multiple(() => AssertMatches(reader, Manifest(volume), volume));
+ }
+
+ [Test, Category("HappyPath")]
+ public void GivenAVolumeWithACommittedButUnflushedTransaction_WhenReading_ThenTheReplayedViewIsWhatTheKernelMounted() {
+ var image = Image("journal-replay");
+ using var reader = new Reiser4Reader(new MemoryStream(image));
+ Assert.That(reader.ReplayedTransactions, Is.GreaterThan(0), "the reference volume must need a replay to be meaningful");
+ var unreplayed = image.ToArray();
+ Array.Clear(unreplayed, 19 * 4096, 2 * 4096);
+ using var stale = new Reiser4Reader(new MemoryStream(unreplayed));
+ var manifest = Manifest("journal-replay");
+ Assert.That(stale.Entries.Select(static e => e.Name).Order(), Is.Not.EqualTo(manifest.Keys.Where(static k => k != ".").Order()),
+ "without the replay the namespace is the one before the last commit");
+ }
+
+ [TestCaseSource(nameof(EditableVolumes)), Category("HappyPath")]
+ public void GivenAVolumeTheKernelWrote_WhenAddingAndRemoving_ThenEveryOtherObjectIsCarriedUnchanged(string volume) {
+ var image = new MemoryStream();
+ image.Write(Image(volume));
+ var manifest = Manifest(volume);
+ var payload = new byte[9_000];
+ new Random(7).NextBytes(payload);
+ var removed = manifest.Keys.First(static k => k.StartsWith("many/", StringComparison.Ordinal));
+ var descriptor = new Reiser4FormatDescriptor();
+ descriptor.Add(image, [ArchiveInputInfo.InMemory("added/a-new-name-longer-than-twenty-three.bin", payload)]);
+ descriptor.Remove(image, [removed]);
+
+ using var reader = new Reiser4Reader(image);
+ Assert.Multiple(() => {
+ AssertMatches(reader, manifest, volume, new HashSet(StringComparer.Ordinal) { removed, "many", "added", "added/a-new-name-longer-than-twenty-three.bin" });
+ Assert.That(reader.ReplayedTransactions, Is.Zero, "a rebuilt volume has its journal folded in");
+ Assert.That(reader.Entries.Any(e => e.Name == removed), Is.False);
+ Assert.That(reader.Extract(reader.Entries.Single(static e => e.Name == "added/a-new-name-longer-than-twenty-three.bin")), Is.EqualTo(payload));
+ });
+ }
+
+ [Test, Category("HappyPath")]
+ public void GivenAVolumeWithAPendingTransaction_WhenEditing_ThenTheReplayedStateIsWhatIsCarried() {
+ var image = new MemoryStream();
+ image.Write(Image("journal-replay"));
+ var manifest = Manifest("journal-replay");
+ new Reiser4FormatDescriptor().Add(image, [ArchiveInputInfo.InMemory("added.bin", [1, 2, 3])]);
+ using var reader = new Reiser4Reader(image);
+ Assert.Multiple(() => {
+ Assert.That(reader.ReplayedTransactions, Is.Zero, "the rebuilt journal is blank");
+ Assert.That(image.ToArray().AsSpan(19 * 4096, 2 * 4096).ToArray(), Is.All.Zero);
+ AssertMatches(reader, manifest, "journal-replay", new HashSet(StringComparer.Ordinal) { "added.bin" });
+ });
+ }
+
+ [TestCaseSource(nameof(EditableVolumes)), TestCase("rupasov"), Category("Spec")]
+ public void GivenTheEntriesTheKernelKeyed_WhenKeyingTheirNamesAgain_ThenTheKeysAreIdentical(string volume) {
+ using var reader = new Reiser4Reader(new MemoryStream(Image(volume)));
+ var vol = reader.Volume!;
+ var checkedNames = 0;
+ foreach (var directory in vol.Objects.Values.Where(static o => o.IsDirectory)) {
+ var hash = (Reiser4HashId)vol.Plugin(directory, 4);
+ var fibration = (Reiser4FibrationId)vol.Plugin(directory, 5);
+ foreach (var entry in directory.Entries.Where(static e => !e.IsDot)) {
+ if (entry.Hashed && !Reiser4NameKeys.CanHash(hash)) continue;
+ var (ordering, objectId, offset, _) = Reiser4NameKeys.Make(entry.Name, hash, fibration);
+ Assert.That((ordering, objectId, offset), Is.EqualTo((entry.Ordering, entry.ObjectId, entry.Offset)),
+ $"{volume}: {Reiser4Volume.DecodeName(entry.Name)} under {hash}/{fibration}");
+ ++checkedNames;
+ }
+ }
+ Assert.That(checkedNames, Is.GreaterThan(300));
+ }
+}
diff --git a/Compression.Tests/Reiser4/Reiser4NativeTreeTests.cs b/Compression.Tests/Reiser4/Reiser4NativeTreeTests.cs
index 957765405..b2ac04d69 100644
--- a/Compression.Tests/Reiser4/Reiser4NativeTreeTests.cs
+++ b/Compression.Tests/Reiser4/Reiser4NativeTreeTests.cs
@@ -422,13 +422,10 @@ public void GivenAVolume_WhenEditingAndDefragmentingByRebuild_ThenTheMkfsIdSurvi
});
}
- // Offsets inside the fixed blocks that carry the profile rather than the identity:
- // the format40 tail policy (block 17, byte 70), the backup of the root directory's
- // plugin set (block 22, from byte 127 on), the status block (21) and the journal (19, 20).
- [TestCase(17, 70, (byte)1, TestName = "GivenATailsOnlyPolicy_WhenEditing_ThenTheEditIsRefusedAndTheImageIsUntouched")]
- [TestCase(22, 131, (byte)2, TestName = "GivenANonDefaultHashInTheBackedUpPluginSet_WhenEditing_ThenTheEditIsRefusedAndTheImageIsUntouched")]
+ // A status block not marked consistent belongs to a volume the tools found damaged, and a journal
+ // header naming a transaction that is not there cannot be replayed: neither is rewritten.
[TestCase(21, 16, (byte)2, TestName = "GivenAStatusBlockNotMarkedConsistent_WhenEditing_ThenTheEditIsRefusedAndTheImageIsUntouched")]
- [TestCase(19, 0, (byte)1, TestName = "GivenAJournalHeaderThatIsNotBlank_WhenEditing_ThenTheEditIsRefusedAndTheImageIsUntouched")]
+ [TestCase(19, 0, (byte)1, TestName = "GivenAJournalHeaderNamingNoTransaction_WhenEditing_ThenTheEditIsRefusedAndTheImageIsUntouched")]
public void VolumeOutsideTheWriterProfile_IsRefusedForEveryRebuild(int block, int offset, byte value) {
var writer = new Reiser4Writer();
writer.AddFile("d/f.bin", Payload(3_000, 32));
@@ -453,6 +450,28 @@ public void VolumeOutsideTheWriterProfile_IsRefusedForEveryRebuild(int block, in
});
}
+ // The format40 tail policy (block 17, byte 70) and the backed-up plugin set (block 22) are the
+ // volume's profile: an edit carries them byte for byte.
+ [TestCase(17, 70, (byte)1, TestName = "GivenATailsOnlyPolicy_WhenEditing_ThenThePolicyIsCarried")]
+ [TestCase(22, 131, (byte)2, TestName = "GivenANonDefaultHashInTheBackedUpPluginSet_WhenEditing_ThenTheBackupIsCarried")]
+ public void ProfileBytesOfTheFixedBlocks_AreCarriedAcrossEdits(int block, int offset, byte value) {
+ var writer = new Reiser4Writer();
+ writer.AddFile("d/f.bin", Payload(3_000, 32));
+ var original = writer.Build();
+ original[block * Reiser4Writer.BlockSize + offset] = value;
+ using var image = new MemoryStream(original.ToArray());
+ var descriptor = new Reiser4FormatDescriptor();
+ descriptor.Add(image, [ArchiveInputInfo.InMemory("x.bin", Payload(10, 33))]);
+ descriptor.Remove(image, ["d/f.bin"]);
+ descriptor.Defragment(image);
+ using var reader = new Reiser4Reader(image);
+ Assert.Multiple(() => {
+ Assert.That(image.ToArray()[block * Reiser4Writer.BlockSize + offset], Is.EqualTo(value));
+ Assert.That(reader.Entries.Select(static e => e.Name), Is.EquivalentTo(new[] { "d", "x.bin" }));
+ Assert.That(reader.Extract(reader.Entries.Single(static e => e.Name == "x.bin")), Is.EqualTo(Payload(10, 33)));
+ });
+ }
+
private static Reiser4Reader.FileMetadata MetadataOfOneFile() {
var writer = new Reiser4Writer();
writer.AddFile("f.bin", Payload(100, 39));
@@ -468,7 +487,7 @@ public void GivenStatDataBytesItsMaskDoesNotDeclare_WhenWriting_ThenTheyAreRefus
Assert.Throws(() => writer.Build());
}
- [TestCase(3, TestName = "GivenASymlinkStatExtension_WhenWriting_ThenItIsRefused")]
+ [TestCase(6, TestName = "GivenAnUnassignedStatExtension_WhenWriting_ThenItIsRefused")]
[TestCase(7, TestName = "GivenACryptoStatExtension_WhenWriting_ThenItIsRefused")]
[TestCase(15, TestName = "GivenAChainedExtensionMask_WhenWriting_ThenItIsRefused")]
public void UnsupportedStatExtension_IsRefused(int bit) {
diff --git a/Compression.Tests/Reiser4/Reiser4ProfileExternalTests.cs b/Compression.Tests/Reiser4/Reiser4ProfileExternalTests.cs
index d6e850b63..503857a04 100644
--- a/Compression.Tests/Reiser4/Reiser4ProfileExternalTests.cs
+++ b/Compression.Tests/Reiser4/Reiser4ProfileExternalTests.cs
@@ -143,22 +143,6 @@ public void GivenAVolumeMkfsWrote_WhenAddingNestedFilesLongNamesAndAnEmptyDirect
});
}
- [TestCase("-o hash=tea_hash", TestName = "GivenAVolumeMkfsWroteWithTheTeaHash_WhenAdding_ThenTheEditIsRefusedAndTheImageIsUntouched")]
- [TestCase("-o formatting=tails", TestName = "GivenAVolumeMkfsWroteWithATailsOnlyPolicy_WhenAdding_ThenTheEditIsRefusedAndTheImageIsUntouched")]
- [TestCase("-o fibration=lexic_fibre", TestName = "GivenAVolumeMkfsWroteWithLexicographicFibration_WhenAdding_ThenTheEditIsRefusedAndTheImageIsUntouched")]
- public void VolumeWithAnotherPluginProfile_IsReadButNotRewritten(string options) {
- RequireReiser4Progs();
- var original = this.Mkfs("cwbprof", options);
- using var image = new MemoryStream();
- image.Write(original);
- using (var reader = new Reiser4Reader(image))
- Assert.That(reader.NativeTreeValid, Is.True, "an empty volume of another profile is still read");
- var error = Assert.Throws(() => new Reiser4FormatDescriptor().Add(image,
- [ArchiveInputInfo.InMemory("a-name-longer-than-twenty-three.txt", Payload(100, 5))]));
- Assert.That(error!.Message, Does.Contain("refusing"));
- Assert.That(image.ToArray(), Is.EqualTo(original));
- }
-
[Test, Category("Boundary")]
public void GivenTwelveThousandFiles_WhenWriting_ThenFsckAcceptsAFourLevelTreeAndTheProgsReadTheBoundaryFiles() {
RequireReiser4Progs();
diff --git a/Compression.Tests/Reiser4/Reiser4TestLayouts.cs b/Compression.Tests/Reiser4/Reiser4TestLayouts.cs
new file mode 100644
index 000000000..7108c4841
--- /dev/null
+++ b/Compression.Tests/Reiser4/Reiser4TestLayouts.cs
@@ -0,0 +1,47 @@
+using FileSystem.Reiser4;
+
+namespace Compression.Tests.Reiser4;
+
+/// Layout helpers for the in-place defragmentation tests.
+internal static class Reiser4TestLayouts {
+
+ /// The blocks the tree's nodes occupy, in order.
+ internal static ulong[] NodeBlocks(Stream image) {
+ using var reader = new Reiser4Reader(image);
+ Assert.That(reader.NativeTreeValid, Is.True, reader.NativeProblem);
+ return [.. reader.NativeNodeBlocks.Order()];
+ }
+
+ ///
+ /// Fragments a compact volume through the block mover itself: every other file's runs go to the
+ /// free blocks at the end of the volume, last file highest, and the tree and bitmap are settled.
+ ///
+ internal static void ScatterInPlace(Stream image) {
+ var descriptor = new Reiser4FormatDescriptor();
+ image.Position = 0;
+ var extents = descriptor.EnumerateExtents(image).ToList();
+ var used = extents.Max(static e => e.Offset + e.Length);
+ var mover = new Reiser4BlockMover();
+ mover.Init(image);
+ var top = image.Length;
+ var files = extents.Where(static e => e.Kind == Compression.Registry.DefragBlockKind.Used).GroupBy(static e => e.FileName!).ToList();
+ for (var i = 0; i < files.Count; i += 2)
+ foreach (var run in files[i]) {
+ var blocks = (run.Length + mover.BlockSize - 1) / mover.BlockSize * mover.BlockSize;
+ var target = (top - blocks) / mover.BlockSize * mover.BlockSize;
+ while (IsBitmap(target, blocks, mover.BlockSize)) target -= mover.BlockSize;
+ Assert.That(target, Is.GreaterThan(used), "the volume has room to scatter into");
+ mover.MoveExtent(image, run.Offset, target, run.Length);
+ mover.UpdateAllocationAfterMove(image, run.FileName!, run.Offset, target, run.Length);
+ top = target;
+ }
+ mover.SettleDirectory(image);
+ image.Position = 0;
+ }
+
+ private static bool IsBitmap(long offset, long length, int blockSize) {
+ for (var block = (ulong)(offset / blockSize); block < (ulong)((offset + length) / blockSize); ++block)
+ if (block == 18 || block % Reiser4Writer.BlocksPerBitmap == 0) return true;
+ return false;
+ }
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileFormats/FileFormat.FirmwareHex/FirmwareHexWriter.cs b/Hawkynt.FileFormats.FileSystems/FileFormats/FileFormat.FirmwareHex/FirmwareHexWriter.cs
index 6c7d4b452..1c9e17266 100644
--- a/Hawkynt.FileFormats.FileSystems/FileFormats/FileFormat.FirmwareHex/FirmwareHexWriter.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileFormats/FileFormat.FirmwareHex/FirmwareHexWriter.cs
@@ -33,6 +33,7 @@ public static class FirmwareHexWriter {
/// one the reader rendered. An input list with no payload describes an image
/// with no data, which both formats can write.
///
+ /// More than one non-metadata payload is supplied.
public static FirmwareImage ImageFrom(IReadOnlyList inputs, string sourceFormat) {
ArgumentNullException.ThrowIfNull(inputs);
@@ -53,7 +54,9 @@ public static FirmwareImage ImageFrom(IReadOnlyList inputs, st
}
// Any other single input is the payload, whatever it is called: a caller
// converting a .bin into a .hex should not have to rename it first.
- payload ??= input.ReadContent();
+ if (payload is not null)
+ throw new InvalidDataException($"{sourceFormat} represents one logical firmware payload; multiple payload inputs are ambiguous.");
+ payload = input.ReadContent();
}
List<(uint Address, byte[] Data)> segments;
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4BlockMover.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4BlockMover.cs
index 5209068b1..1b87ea028 100644
--- a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4BlockMover.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4BlockMover.cs
@@ -1,117 +1,92 @@
#pragma warning disable CS1591
using System.Buffers.Binary;
-using System.Text;
using Compression.Registry;
namespace FileSystem.Reiser4;
///
-/// Moves a file's blocks inside a Reiser4 payload area and rewrites the
-/// directory entry that said where it started.
+/// Moves the data blocks of a Reiser4 volume's extent files in place and repoints the extent
+/// units that name them, wherever in the tree their twig nodes sit.
///
///
-/// A file here is the run of blocks that begins at the block its
-/// directory entry names, stepping over the allocator bitmaps that sit at
-/// stride boundaries. Nothing else records the position — there is one field
-/// per file and the rest is implied — so a move is the copy plus those eight
-/// bytes.
-///
-/// Because the position is implied, a file can only be put somewhere its
-/// blocks stay in that order: consecutive, bitmaps stepped over. The directory
-/// is written once the pass is over and checked against that rule; a layout
-/// that breaks it is refused rather than written down.
+/// Every data run a file has is one extent unit: a start block and a width in some twig
+/// node. A move is the copy plus that unit's start, so the planner may move each unit's run on
+/// its own. Units are tracked by where their run currently is; once the pass is over
+/// writes every new start into its twig, re-seals node41 checksums,
+/// and moves the allocator bits: the blocks every unit left are cleared and the blocks it landed on
+/// set, so no other bit of the bitmap changes.
+/// Tails and compressed clusters live inside tree nodes and do not move; nor do the nodes.
+/// A volume whose journal still holds transactions, or a file whose extent covers blocks past its
+/// end, is refused, and the caller falls back to a staged rebuild.
///
public sealed class Reiser4BlockMover : IFilesystemBlockMover {
- private const ulong NativeLeafBlock = 24;
- private const ulong NativeTwigBlock = 23;
- private const int NativeItemHeaderBytes = 38;
- private const ushort NativeExtent40Plugin = 5;
- private const byte NativeFileBodyMinor = 4;
- private const uint NativeNodeMagic = 0x52344653;
- private const ulong RootObjectId = 0x2a;
-
- /// Where each file's runs are now, in the order its bytes are in.
- private readonly Dictionary> _runsOf = new(StringComparer.Ordinal);
-
- /// The byte length represented by each corresponding physical run.
- private readonly Dictionary> _runLengthsOf = new(StringComparer.Ordinal);
-
- /// Where the field naming each file's first block sits.
- private readonly Dictionary _firstBlockFieldOf = new(StringComparer.Ordinal);
-
- /// Native object id assigned to each file by the writer's tree profile.
- private readonly Dictionary _objectIdOf = new(StringComparer.Ordinal);
-
- /// How long each file is, which is what says how many blocks it takes.
- private readonly Dictionary _sizeOf = new(StringComparer.Ordinal);
+ private sealed class Unit {
+ internal required ulong Node { get; init; }
+ internal required int Field { get; init; }
+ internal required long Original { get; init; }
+ internal required long Length { get; init; }
+ internal required ulong Width { get; init; }
+ internal long Current { get; set; }
+ }
+ private readonly Dictionary> _unitsOf = new(StringComparer.Ordinal);
+ private ushort _nodePlugin;
private long _imageLength;
- /// Reads the directory once and notes where every file is.
+ /// Reads the tree once and notes where every extent unit is.
public void Init(Stream image) {
ArgumentNullException.ThrowIfNull(image);
- this._runsOf.Clear();
- this._runLengthsOf.Clear();
- this._firstBlockFieldOf.Clear();
- this._objectIdOf.Clear();
- this._sizeOf.Clear();
+ this._unitsOf.Clear();
this._imageLength = image.Length;
-
image.Position = 0;
- using var reader = new Reiser4Reader(image);
- if (!reader.Valid)
- throw new InvalidDataException("Reiser4: the volume does not carry a payload area this reads.");
-
- foreach (var entry in reader.Entries) {
- if (entry.Size <= 0) continue;
- var runs = reader.EnumerateRuns(entry).ToArray();
- this._runsOf[entry.Name] = runs.Select(static run => run.Offset).ToList();
- this._runLengthsOf[entry.Name] = runs.Select(static run => run.Length).ToList();
- this._sizeOf[entry.Name] = entry.Size;
- }
-
- var objectId = RootObjectId + 1;
- foreach (var (name, at) in DirectoryFields(image)) {
- this._firstBlockFieldOf[name] = at;
- this._objectIdOf[name] = objectId++;
+ using var volume = new Reiser4Volume(image);
+ if (!volume.TreeValid)
+ throw new InvalidDataException($"Reiser4: the volume cannot be moved in place: {volume.Problem}.");
+ if (volume.ReplayedTransactions > 0)
+ throw new NotSupportedException("Reiser4: the journal holds transactions to replay; blocks cannot be moved in place.");
+ this._nodePlugin = volume.NodePlugin;
+ var seen = new HashSet();
+ foreach (var (path, _, obj, _) in volume.Paths) {
+ if (obj.Stat.Kind != Reiser4Stat.Regular || obj.Body.Count == 0 || obj.Body[0].Plugin != Reiser4ItemPlugin.Extent || !seen.Add(obj.StatKey))
+ continue;
+ var remaining = (long)obj.Stat.Size;
+ var units = new List();
+ foreach (var item in obj.Body) {
+ var body = volume.ReadBody(item);
+ for (var at = 0; at < body.Length; at += 16) {
+ var start = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at));
+ var width = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at + 8));
+ var bytes = (long)Math.Min((ulong)Math.Max(0, remaining), width * Reiser4Writer.BlockSize);
+ remaining -= (long)(width * Reiser4Writer.BlockSize);
+ if (start == 0) continue;
+ if ((ulong)((bytes + Reiser4Writer.BlockSize - 1) / Reiser4Writer.BlockSize) != width)
+ throw new NotSupportedException($"Reiser4: '{path}' holds blocks past its end, which cannot be moved in place.");
+ units.Add(new Unit {
+ Node = item.Block, Field = item.BodyOffset + at, Original = checked((long)start * Reiser4Writer.BlockSize),
+ Length = bytes, Width = width, Current = checked((long)start * Reiser4Writer.BlockSize),
+ });
+ }
+ }
+ if (units.Count > 0) this._unitsOf[path] = units;
}
-
- // The reserved blocks and the directory chain come first, and the first
- // file starts where they end.
- this.FirstDataByte = this._runsOf.Count == 0
- ? Math.Min(image.Length, 25L * Reiser4Writer.BlockSize)
- : this._runsOf.Values.Select(r => r[0]).Min();
}
- /// A block, which is what the directory counts in.
+ /// A block, which is what an extent unit counts in.
public int BlockSize => Reiser4Writer.BlockSize;
- ///
- /// First byte a file may occupy: past the reserved blocks and the directory,
- /// which is where the first file already sits.
- ///
- public long FirstDataByte { get; private set; }
+ /// First byte a file may occupy: past the jump area, the superblocks, the journal, the status and backup blocks and the first two nodes.
+ public long FirstDataByte => Math.Min(this._imageLength, 25L * Reiser4Writer.BlockSize);
- ///
- /// Each call notes where one run has got to; a file split by the bitmaps it
- /// steps over is simply several calls.
- ///
+ /// Each call notes where one unit's run has got to.
public bool RepointsRunsIndependently => true;
- ///
- /// A run may be held outside the volume while the rest of the layout moves,
- /// which is what lets a full volume be rearranged at all.
- ///
+ /// A run may be held outside the volume while the rest of the layout moves.
public bool SupportsHeldRuns => true;
///
public void MoveExtent(Stream image, long srcOffset, long dstOffset, long length, bool zeroSource = false) {
if (length <= 0 || srcOffset == dstOffset) return;
-
- // Overlap-safe: a run shifted forward by less than its own length
- // overwrites its own tail, and copying that front to back reads bytes
- // the copy has already replaced.
Compression.Core.DiskImage.ExtentCopy.Move(image, srcOffset, dstOffset, length);
if (zeroSource)
Compression.Core.DiskImage.ExtentCopy.Zero(image, srcOffset, length);
@@ -123,238 +98,70 @@ public void UpdateAllocationAfterMove(Stream image, string fileName, long oldOff
ArgumentNullException.ThrowIfNull(fileName);
if (this._imageLength == 0) this.Init(image);
if (oldOffset == newOffset) return;
-
if (newOffset % Reiser4Writer.BlockSize != 0)
throw new NotSupportedException(
- $"Reiser4: {newOffset} is not on a {Reiser4Writer.BlockSize}-byte block boundary, which is " +
- "all the directory can name.");
-
- if (!this._runsOf.TryGetValue(fileName, out var runs))
- throw new InvalidOperationException(
- $"Reiser4: the directory names no file '{fileName}', so it cannot be repointed.");
-
- // By where the run is now rather than where it began: the planner may put a
- // run down more than once on its way to where it ends up.
- var at = runs.IndexOf(oldOffset);
- if (at < 0)
- throw new InvalidOperationException(
- $"Reiser4: no run of '{fileName}' sits at {oldOffset}, so it cannot be repointed.");
-
- if (!this._runLengthsOf.TryGetValue(fileName, out var lengths) || at >= lengths.Count)
- throw new InvalidOperationException($"Reiser4: run accounting for '{fileName}' is incomplete.");
- if (length != lengths[at])
+ $"Reiser4: {newOffset} is not on a {Reiser4Writer.BlockSize}-byte block boundary, which is all an extent can name.");
+ if (!this._unitsOf.TryGetValue(fileName, out var units))
+ throw new InvalidOperationException($"Reiser4: the tree names no extent file '{fileName}', so it cannot be repointed.");
+ // By where the run is now rather than where it began: the planner may put a run down more
+ // than once on its way to where it ends up.
+ var unit = units.FirstOrDefault(u => u.Current == oldOffset)
+ ?? throw new InvalidOperationException($"Reiser4: no run of '{fileName}' sits at {oldOffset}, so it cannot be repointed.");
+ if (length != unit.Length)
throw new NotSupportedException(
- $"Reiser4: moving only {length} bytes of the {lengths[at]}-byte run of '{fileName}' " +
- "would require splitting its native extent40 item.");
-
- runs[at] = newOffset;
+ $"Reiser4: moving only {length} bytes of the {unit.Length}-byte run of '{fileName}' would require splitting its extent unit.");
+ unit.Current = newOffset;
}
- ///
- /// Writes each file's new physical location into both the native extent40 item
- /// and the legacy workbench directory once the pass is over.
- ///
+ /// Writes every unit's new start into its twig and moves the allocator bits with it.
public void SettleDirectory(Stream image) {
ArgumentNullException.ThrowIfNull(image);
-
- var native = HasNativeTree(image);
- Span value = stackalloc byte[8];
- foreach (var (name, runs) in this._runsOf) {
- if (runs.Count == 0) continue;
-
- if (!native) {
- var expected = ImpliedRuns(runs[0], this._sizeOf[name]);
- if (!expected.SequenceEqual(runs))
- throw new NotSupportedException(
- $"Reiser4: '{name}' would not read back from block {runs[0] / Reiser4Writer.BlockSize} — " +
- "its blocks are where the legacy layout implies no file can be.");
- }
-
- // Keep the old private directory coherent for pre-native Workbench readers.
- if (this._firstBlockFieldOf.TryGetValue(name, out var field)) {
- BinaryPrimitives.WriteUInt64LittleEndian(value, (ulong)(runs[0] / Reiser4Writer.BlockSize));
- image.Position = field;
- image.Write(value);
- } else if (!native) {
- throw new InvalidOperationException(
- $"Reiser4: the directory holds no entry for '{name}' to write back.");
- }
+ var units = this._unitsOf.Values.SelectMany(static u => u).ToList();
+ var nodes = new Dictionary();
+ byte[] Node(ulong block) {
+ if (nodes.TryGetValue(block, out var cached)) return cached;
+ var buffer = new byte[Reiser4Writer.BlockSize];
+ image.Position = checked((long)block * Reiser4Writer.BlockSize);
+ image.ReadExactly(buffer);
+ return nodes[block] = buffer;
}
- if (native)
- this.RepointNativeExtents(image);
-
- image.Flush();
- }
-
- /// True when block 24 is the native leaf written by the tree profile.
- private static bool HasNativeTree(Stream image) {
- var offset = checked((long)NativeLeafBlock * Reiser4Writer.BlockSize);
- if (!image.CanSeek || offset + Reiser4Writer.BlockSize > image.Length) return false;
-
- Span header = stackalloc byte[12];
- image.Position = offset;
- image.ReadExactly(header);
- return BinaryPrimitives.ReadUInt32LittleEndian(header[8..]) == NativeNodeMagic;
- }
-
- ///
- /// Repoints only extent40 start blocks in the native leaf. Widths and every
- /// other tree byte stay untouched, so defrag does not silently rebuild metadata.
- ///
- private void RepointNativeExtents(Stream image) {
- // Extents are twig items (block 23); images from before the writer put them
- // there carry them in the leaf (block 24), so both are searched.
- var nodes = new List<(long Offset, byte[] Bytes, ushort ItemCount, ushort BodiesEnd, ushort[] BodyOffsets)>(2);
- foreach (var block in (ReadOnlySpan)[NativeTwigBlock, NativeLeafBlock]) {
- var nodeOffset = checked((long)block * Reiser4Writer.BlockSize);
- var node = new byte[Reiser4Writer.BlockSize];
- image.Position = nodeOffset;
- image.ReadExactly(node);
- if (BinaryPrimitives.ReadUInt32LittleEndian(node.AsSpan(8, 4)) != NativeNodeMagic) continue;
-
- var count = BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(2, 2));
- var end = BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(6, 2));
- if (count == 0
- || count > (Reiser4Writer.BlockSize - Reiser4Tree.NodeHeaderBytes) / NativeItemHeaderBytes
- || end < Reiser4Tree.NodeHeaderBytes || end > Reiser4Writer.BlockSize)
- throw new InvalidDataException($"Reiser4: malformed native node {block} while settling defragmentation.");
-
- var offsets = new ushort[count];
- for (var i = 0; i < count; ++i)
- offsets[i] = BinaryPrimitives.ReadUInt16LittleEndian(
- node.AsSpan(Reiser4Writer.BlockSize - (i + 1) * NativeItemHeaderBytes + 32, 2));
- nodes.Add((nodeOffset, node, count, end, offsets));
+ var bitmaps = new Dictionary();
+ byte[] Bitmap(ulong index) {
+ if (bitmaps.TryGetValue(index, out var cached)) return cached;
+ var buffer = new byte[Reiser4Writer.BlockSize];
+ image.Position = checked((long)(index == 0 ? 18 : index * Reiser4Writer.BlocksPerBitmap) * Reiser4Writer.BlockSize);
+ image.ReadExactly(buffer);
+ return bitmaps[index] = buffer;
}
-
- foreach (var (name, objectId) in this._objectIdOf) {
- if (!this._runsOf.TryGetValue(name, out var runs) || runs.Count == 0) continue;
- if (!this._runLengthsOf.TryGetValue(name, out var lengths) || lengths.Count != runs.Count)
- throw new InvalidOperationException($"Reiser4: run accounting for '{name}' is incomplete.");
-
- var found = false;
- foreach (var (_, leaf, itemCount, bodiesEnd, bodyOffsets) in nodes) {
- for (var i = 0; i < itemCount; ++i) {
- var header = Reiser4Writer.BlockSize - (i + 1) * NativeItemHeaderBytes;
- var key0 = BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header, 8));
- var itemObjectId = BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header + 16, 8));
- var plugin = BinaryPrimitives.ReadUInt16LittleEndian(leaf.AsSpan(header + 36, 2));
- if ((byte)(key0 & 0xF) != NativeFileBodyMinor
- || plugin != NativeExtent40Plugin || itemObjectId != objectId)
- continue;
-
- var body = bodyOffsets[i];
- var end = bodiesEnd;
- foreach (var candidate in bodyOffsets)
- if (candidate > body && candidate < end) end = candidate;
- var bodyLength = end - body;
- if (bodyLength != runs.Count * 16)
- throw new NotSupportedException(
- $"Reiser4: native extent40 body for '{name}' has {bodyLength / 16} runs, " +
- $"but the mover tracks {runs.Count}.");
-
- for (var r = 0; r < runs.Count; ++r) {
- if ((runs[r] & (Reiser4Writer.BlockSize - 1)) != 0)
- throw new InvalidOperationException($"Reiser4: run of '{name}' is not block aligned.");
- var startBlock = checked((ulong)(runs[r] / Reiser4Writer.BlockSize));
- var width = checked((ulong)((lengths[r] + Reiser4Writer.BlockSize - 1) / Reiser4Writer.BlockSize));
- BinaryPrimitives.WriteUInt64LittleEndian(leaf.AsSpan(body + r * 16, 8), startBlock);
- var existingWidth = BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(body + r * 16 + 8, 8));
- if (existingWidth != width)
- throw new NotSupportedException(
- $"Reiser4: native extent40 width for '{name}' is {existingWidth} blocks; " +
- $"the mover accounts for {width}.");
- }
-
- found = true;
- break;
- }
- if (found) break;
+ void Mark(long offset, ulong width, bool used) {
+ var first = (ulong)(offset / Reiser4Writer.BlockSize);
+ for (var block = first; block < first + width; ++block) {
+ var map = Bitmap(block / Reiser4Writer.BlocksPerBitmap);
+ var bit = block % Reiser4Writer.BlocksPerBitmap;
+ ref var cell = ref map[4 + (int)(bit >> 3)];
+ cell = used ? (byte)(cell | 1 << (int)(bit & 7)) : (byte)(cell & ~(1 << (int)(bit & 7)));
}
-
- if (!found)
- throw new InvalidDataException($"Reiser4: native tree has no extent40 item for '{name}'.");
}
- foreach (var (nodeOffset, node, _, _, _) in nodes) {
- image.Position = nodeOffset;
- image.Write(node);
+ foreach (var unit in units.Where(static u => u.Current != u.Original)) Mark(unit.Original, unit.Width, used: false);
+ foreach (var unit in units.Where(static u => u.Current != u.Original)) {
+ if (unit.Current < 0 || unit.Current % Reiser4Writer.BlockSize != 0)
+ throw new InvalidOperationException("Reiser4: a run did not land on a block boundary inside the volume.");
+ Mark(unit.Current, unit.Width, used: true);
+ BinaryPrimitives.WriteUInt64LittleEndian(Node(unit.Node).AsSpan(unit.Field), (ulong)(unit.Current / Reiser4Writer.BlockSize));
}
- }
-
- ///
- /// The runs a file of this length occupies when it starts at
- /// : consecutive blocks, broken wherever a
- /// bitmap sits.
- ///
- private List ImpliedRuns(long firstOffset, long size) {
- var runs = new List();
- var blockSize = (long)Reiser4Writer.BlockSize;
- var block = (ulong)(firstOffset / blockSize);
- var remaining = size;
-
- while (remaining > 0) {
- while (IsBitmapBlock(block)) ++block;
- var start = (long)block * blockSize;
- if (start < 0 || start >= this._imageLength) break;
-
- long run = 0;
- while (remaining - run > 0 && !IsBitmapBlock(block)) {
- var take = Math.Min(blockSize, remaining - run);
- take = Math.Min(take, this._imageLength - (start + run));
- if (take <= 0) break;
- run += take;
- ++block;
- }
- if (run <= 0) break;
- runs.Add(start);
- remaining -= run;
+ foreach (var (block, node) in nodes) {
+ if (this._nodePlugin == 1) Reiser4Volume.SealNode41(node);
+ image.Position = checked((long)block * Reiser4Writer.BlockSize);
+ image.Write(node);
}
-
- return runs;
- }
-
- /// Bitmap blocks sit at stride boundaries, and one sits at block 18.
- private static bool IsBitmapBlock(ulong block)
- => block == 18 || (block != 0 && block % Reiser4Writer.BlocksPerBitmap == 0);
-
- /// Walks the directory chain and yields where each name's first-block field sits.
- private static IEnumerable<(string Name, long At)> DirectoryFields(Stream image) {
- var master = new byte[Reiser4Writer.BlockSize];
- image.Position = Reiser4Reader.MasterOffset;
- image.ReadExactly(master);
-
- var block = BinaryPrimitives.ReadUInt64LittleEndian(
- master.AsSpan(Reiser4Writer.MasterPayloadDirOff, 8));
-
- var visited = new HashSet();
- var buffer = new byte[Reiser4Writer.BlockSize];
- while (block != 0 && visited.Add(block)) {
- var at = (long)block * Reiser4Writer.BlockSize;
- if (at < 0 || at + Reiser4Writer.BlockSize > image.Length) yield break;
-
- image.Position = at;
- image.ReadExactly(buffer);
- if (!buffer.AsSpan(0, Reiser4Writer.DirMagic.Length).SequenceEqual(Reiser4Writer.DirMagic))
- yield break;
-
- var next = BinaryPrimitives.ReadUInt64LittleEndian(buffer.AsSpan(8, 8));
- var count = BinaryPrimitives.ReadUInt32LittleEndian(buffer.AsSpan(16, 4));
- for (var i = 0; i < count && i < Reiser4Writer.DirEntriesPerBlock; ++i) {
- var entry = Reiser4Writer.DirHeadSize + i * Reiser4Writer.DirEntrySize;
- var name = ReadName(buffer.AsSpan(entry, Reiser4Writer.DirNameLength));
- if (name.Length == 0) continue;
- yield return (name, at + entry + Reiser4Writer.DirNameLength);
- }
-
- block = next;
+ foreach (var (index, map) in bitmaps) {
+ Reiser4Volume.SealBitmap(map);
+ image.Position = checked((long)(index == 0 ? 18 : index * Reiser4Writer.BlocksPerBitmap) * Reiser4Writer.BlockSize);
+ image.Write(map);
}
- }
-
- private static string ReadName(ReadOnlySpan span) {
- var end = span.IndexOf((byte)0);
- if (end < 0) end = span.Length;
- return end == 0 ? "" : Encoding.UTF8.GetString(span[..end]);
+ image.Flush();
}
}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Clusters.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Clusters.cs
new file mode 100644
index 000000000..0408a4bbe
--- /dev/null
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Clusters.cs
@@ -0,0 +1,79 @@
+#pragma warning disable CS1591
+using System.Buffers.Binary;
+using Compression.Core.Checksums;
+using Compression.Core.Deflate;
+using Compression.Core.Dictionary.Lzo;
+using Compression.Core.Streams;
+using FileFormat.Zstd;
+
+namespace FileSystem.Reiser4;
+
+/// Compression transform plugins (plugin type 0xC) a cryptcompress file names.
+internal enum Reiser4CompressionId : ushort { Lzo1 = 0, Gzip1 = 1, Zstd1 = 2 }
+
+/// Compression mode plugins (plugin type 0xD).
+internal enum Reiser4CompressionModeId : ushort { None = 0, Lattice = 1, Ultimate = 2, Force = 3, Convert = 4 }
+
+///
+/// The disk-cluster encoding of a cryptcompress (ccreg40) file: each logical cluster is
+/// stored either as its plain bytes or, when that is shorter, as the compressed stream followed by
+/// the stream's 32-bit Adler checksum, little-endian.
+///
+///
+/// Which of the two a disk cluster holds is not flagged anywhere: it is compressed exactly when
+/// it is shorter than the logical cluster it stands for — the cluster size, or what is left of the
+/// file in the last cluster. The compressors are the workbench's own: raw LZO1X for lzo1, a
+/// raw deflate stream for gzip1, a Zstandard frame for zstd1. A compressed result is
+/// kept only when it and its checksum together are shorter than the input, and inputs below the
+/// plugin's minimum (256 bytes for lzo1 and zstd1, 64 for gzip1) are stored plain.
+/// Verified by a Reiser4 kernel reading clusters this writes and by this reader decoding
+/// clusters the kernel wrote; see docs/REISER4-NATIVE-PROFILE.md.
+///
+internal static class Reiser4Clusters {
+
+ internal const int ChecksumBytes = 4;
+
+ internal static int MinimumToCompress(Reiser4CompressionId id) => id == Reiser4CompressionId.Gzip1 ? 64 : 256;
+
+ /// The logical bytes of one disk cluster.
+ internal static byte[] Decode(ReadOnlySpan disk, int logicalLength, Reiser4CompressionId id) {
+ if (disk.Length == logicalLength) return disk.ToArray();
+ if (disk.Length > logicalLength || disk.Length <= ChecksumBytes)
+ throw new InvalidDataException("Reiser4: a disk cluster is longer than the data it stands for.");
+ var stream = disk[..^ChecksumBytes];
+ if (Adler32.Compute(stream) != BinaryPrimitives.ReadUInt32LittleEndian(disk[^ChecksumBytes..]))
+ throw new InvalidDataException("Reiser4: a compressed disk cluster fails its checksum.");
+ var plain = id switch {
+ Reiser4CompressionId.Lzo1 => Lzo1xDecompressor.Decompress(stream, logicalLength),
+ Reiser4CompressionId.Gzip1 => DeflateDecompressor.Decompress(stream),
+ Reiser4CompressionId.Zstd1 => new ZstdBuildingBlock().Decompress(stream),
+ _ => throw new NotSupportedException($"Reiser4: compression plugin {id} is not supported."),
+ };
+ if (plain.Length != logicalLength)
+ throw new InvalidDataException("Reiser4: a disk cluster decompresses to the wrong length.");
+ return plain;
+ }
+
+ /// The disk form of a logical cluster: compressed with its checksum when that is shorter.
+ internal static byte[] Encode(ReadOnlySpan logical, Reiser4CompressionId id, Reiser4CompressionModeId mode) {
+ if (mode == Reiser4CompressionModeId.None || logical.Length < MinimumToCompress(id)) return logical.ToArray();
+ var stream = id switch {
+ Reiser4CompressionId.Lzo1 => Lzo1xCompressor.Compress(logical),
+ Reiser4CompressionId.Gzip1 => DeflateCompressor.Compress(logical, DeflateCompressionLevel.Fast),
+ Reiser4CompressionId.Zstd1 => CompressZstd(logical),
+ _ => throw new NotSupportedException($"Reiser4: compression plugin {id} is not supported."),
+ };
+ if (stream.Length + ChecksumBytes >= logical.Length) return logical.ToArray();
+ var disk = new byte[stream.Length + ChecksumBytes];
+ stream.CopyTo(disk, 0);
+ BinaryPrimitives.WriteUInt32LittleEndian(disk.AsSpan(stream.Length), Adler32.Compute(stream));
+ return disk;
+ }
+
+ private static byte[] CompressZstd(ReadOnlySpan data) {
+ using var output = new MemoryStream();
+ using (var zstd = new ZstdStream(output, CompressionStreamMode.Compress, ZstdCompressionLevel.Fast, leaveOpen: true))
+ zstd.Write(data);
+ return output.ToArray();
+ }
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4FormatDescriptor.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4FormatDescriptor.cs
index 2f0b0d9d1..477f4c349 100644
--- a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4FormatDescriptor.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4FormatDescriptor.cs
@@ -2,6 +2,7 @@
using System.Buffers.Binary;
using System.Globalization;
using System.Text;
+using Compression.Core.DiskImage;
using Compression.Registry;
using static Compression.Registry.FormatHelpers;
@@ -9,11 +10,12 @@ namespace FileSystem.Reiser4;
///
/// Descriptor for Reiser4 filesystem images (successor to ReiserFS 3.6 — completely
-/// different on-disk layout). Volumes whose node40 tree the reader walks completely list
-/// and extract their files and directories, and are created and edited through staged
-/// rebuilds that carry the volume's identity and every object's metadata across; other
-/// images surface the master superblock at offset 65536, the format40 superblock that
-/// follows it, a structured metadata bundle and the raw image.
+/// different on-disk layout). Volumes whose node40/node41 tree the reader walks completely list
+/// and extract their files, directories, links and special files — after replaying a pending
+/// journal — and are created and edited through staged rebuilds that carry the volume's identity,
+/// plugin profile and every object's keys, metadata and body across; other images surface the
+/// master superblock at offset 65536, the format40 superblock that follows it, a structured
+/// metadata bundle and the raw image.
///
/// Magic:
///
@@ -33,89 +35,51 @@ public sealed class Reiser4FormatDescriptor : IFormatDescriptor, IArchiveFormatO
// ── IFormatOptionsSchema ────────────────────────────────────────────────
///
- /// Knobs the empty-filesystem writer actually honours. VolumeLabel is
- /// written into the master superblock label field (and the backup record) and
- /// surfaces through fsck.reiser4 / our metadata readback;
- /// ImageSize drives (4 KB
- /// blocks, clamped to the writer minimum). The 4 KB block size is fixed —
- /// the embedded mkfs.reiser4 templates are byte-exact 4096-byte captures — so
- /// it is intentionally not exposed.
+ /// Knobs the writer honours. VolumeLabel is written into the master superblock label
+ /// field (and the backup record); ImageSize drives
+ /// (4 KB blocks, clamped to the writer minimum); FileBody picks how regular files are
+ /// stored (). The 4 KB block size is fixed — the embedded
+ /// mkfs.reiser4 templates are byte-exact 4096-byte captures — so it is intentionally not exposed.
///
public IReadOnlyList OptionsSchema { get; } = [
FilesystemSchemaPresets.VolumeLabel(maxChars: 16),
FilesystemSchemaPresets.ImageSize(["16 MB", "32 MB", "64 MB", "128 MB"]),
+ new FormatOptionDescriptor("FileBody", "File body", FormatOptionKind.Enum, nameof(Reiser4FileBody.Extents),
+ AllowedValues: Enum.GetNames(),
+ Description: "How regular files are stored: extents, tails, the kernel's smart policy (tails up to four blocks), " +
+ "compressed cryptcompress clusters, or whatever the volume's plugin profile says.",
+ IsOptimizationAxis: false),
];
- ///
- /// Gets the id.
- ///
public string Id => "Reiser4";
- ///
- /// Gets the display name.
- ///
public string DisplayName => "Reiser4";
- ///
- /// Gets the category.
- ///
public FormatCategory Category => FormatCategory.Archive;
- ///
- /// Gets the capabilities.
- ///
public FormatCapabilities Capabilities =>
FormatCapabilities.CanList | FormatCapabilities.CanExtract | FormatCapabilities.CanTest |
FormatCapabilities.CanCreate | FormatCapabilities.CanModify | FormatCapabilities.SupportsDirectories;
- ///
- /// Gets the default extension.
- ///
public string DefaultExtension => ".reiser4";
- ///
- /// Gets the extensions.
- ///
public IReadOnlyList Extensions => [".reiser4"];
- ///
- /// Gets the compound extensions.
- ///
public IReadOnlyList CompoundExtensions => [];
- ///
- /// Gets the magic signatures.
- ///
public IReadOnlyList MagicSignatures => [
// "ReIsEr4" at byte offset 65536 (= 16 * 4096). Confidence 0.9: the 7-byte
// magic is highly unlikely to land at exactly this offset by chance, but
// it shares the "ReIsEr" prefix with the older ReiserFS 3.6 magic
// ("ReIsErFs", "ReIsEr2Fs", "ReIsEr3Fs") which lives at offset 65536+52.
- // The disambiguation is unambiguous (different offsets, different suffixes)
- // so 0.9 is appropriate — slightly below the 0.95 used for unique 4+ byte
- // magics that live at position 0.
new("ReIsEr4"u8.ToArray(), Offset: (int)Reiser4MasterSb.MasterOffset, Confidence: 0.9),
];
- ///
- /// Gets the methods.
- ///
public IReadOnlyList Methods => [new("stored", "Stored")];
- ///
- /// Gets the tar compression format id.
- ///
public string? TarCompressionFormatId => null;
- ///
- /// Gets the family.
- ///
public AlgorithmFamily Family => AlgorithmFamily.Archive;
- ///
- /// Gets the description.
- ///
- public string Description => "Reiser4 filesystem image — native node40 traversal and multi-leaf writing with nested directories and metadata-preserving rebuilds.";
+ public string Description => "Reiser4 filesystem image — every node40/node41 plugin profile, journal replay, " +
+ "extents, tails, compressed clusters, symlinks, special files and hard links, edited through metadata-preserving rebuilds.";
- ///
- /// Lists the entries in the supplied container.
- ///
+ /// Lists the entries in the supplied container.
public List List(Stream stream, string? password) {
var entries = new List();
byte[] image;
try {
image = ReadAllBounded(stream);
} catch {
- // Stream blew up before we got anywhere. Surface the irreducible minimum.
entries.Add(new ArchiveEntryInfo(0, "FULL.reiser4", 0, 0, "stored", false, false, null));
entries.Add(new ArchiveEntryInfo(1, "metadata.ini", 0, 0, "stored", false, false, null));
return entries;
@@ -134,19 +98,19 @@ public List List(Stream stream, string? password) {
// header entries alongside them would make every rebuild (shrink, defrag)
// fold them back in as real files, so they stay on the carver path — empty
// or foreign images, where the header IS all we can offer.
- var payload = ReadPayload(stream);
var idx = 0;
- if (payload.Count > 0) {
- foreach (var e in payload)
- entries.Add(new ArchiveEntryInfo(idx++, e.Name, e.Size, e.Size, "stored", e.IsDirectory, false,
- e.Metadata?.LastModified));
- return entries;
+ try {
+ if (stream.CanSeek) stream.Position = 0;
+ using var reader = new Reiser4Reader(stream);
+ if (reader.NativeTreeValid || reader.Entries.Count > 0) {
+ foreach (var e in reader.Entries)
+ entries.Add(ToInfo(idx++, e));
+ return entries;
+ }
+ } catch {
+ // fall through to the carver view
}
- if (stream.CanSeek) stream.Position = 0;
- using (var native = new Reiser4Reader(stream))
- if (native.NativeTreeValid) return entries;
-
entries.Add(new ArchiveEntryInfo(idx++, "FULL.reiser4", image.LongLength, image.LongLength, "stored", false, false, null));
entries.Add(new ArchiveEntryInfo(idx++, "metadata.ini", 0, 0, "stored", false, false, null));
if (sb.Valid)
@@ -156,20 +120,16 @@ public List List(Stream stream, string? password) {
return entries;
}
- /// Files the workbench-layout payload area holds. Never throws — empty when there are none.
- private static IReadOnlyList ReadPayload(Stream stream) {
- try {
- if (stream.CanSeek) stream.Position = 0;
- using var reader = new Reiser4Reader(stream);
- return reader.Entries;
- } catch {
- return [];
- }
- }
+ private static ArchiveEntryInfo ToInfo(int index, Reiser4Reader.Entry e) => e.Kind switch {
+ Reiser4Reader.EntryKind.Symlink => new ArchiveEntryInfo(index, e.Name, 0, 0, "stored", false, false,
+ e.Metadata?.LastModified, IsSymlink: true, LinkTarget: e.LinkTarget),
+ Reiser4Reader.EntryKind.CharacterDevice or Reiser4Reader.EntryKind.BlockDevice or Reiser4Reader.EntryKind.Fifo or Reiser4Reader.EntryKind.Socket =>
+ new ArchiveEntryInfo(index, e.Name, 0, 0, "stored", false, false, e.Metadata?.LastModified, Kind: e.Kind.ToString()),
+ _ => new ArchiveEntryInfo(index, e.Name, e.Size, e.Size, e.Body is "ctail" ? "compressed" : "stored", e.IsDirectory, false,
+ e.Metadata?.LastModified),
+ };
- ///
- /// Decodes the supplied input.
- ///
+ /// Decodes the supplied input.
public void Extract(Stream stream, string outputDir, string? password, string[]? files) {
byte[] image;
try {
@@ -188,15 +148,16 @@ public void Extract(Stream stream, string outputDir, string? password, string[]?
return;
}
- // A volume that carries files extracts exactly those, mirroring List.
if (stream.CanSeek) stream.Position = 0;
using (var reader = new Reiser4Reader(stream)) {
if (reader.NativeTreeValid || reader.Entries.Count > 0) {
foreach (var e in reader.Entries) {
if (files is { Length: > 0 } && !MatchesFilter(e.Name, files)) continue;
- var target = Path.Combine(outputDir, e.Name.Replace('/', Path.DirectorySeparatorChar));
+ var target = SafeMemberPath(outputDir, e.Name);
Directory.CreateDirectory(Path.GetDirectoryName(target) ?? outputDir);
if (e.IsDirectory) { Directory.CreateDirectory(target); continue; }
+ // Links and special files have no bytes to extract; List names them and their targets.
+ if (e.Kind != Reiser4Reader.EntryKind.File) continue;
using var output = File.Create(target);
reader.ExtractTo(e, output);
}
@@ -240,66 +201,66 @@ private static byte[] BuildMetadata(Reiser4MasterSb sb) {
}
// ── IArchiveCreatable ────────────────────────────────────────────────
- // A captured mkfs prefix supplies the format defaults; native stat40, cde40
- // and extent40 items describe the supported namespace across native nodes.
- ///
- /// Performs the create operation.
- ///
- public void Create(Stream output, IReadOnlyList inputs, FormatCreateOptions options)
- => CreateCore(output, inputs, options);
- private static void CreateCore(Stream output, IReadOnlyList inputs, FormatCreateOptions options,
- RebuildMetadata? saved = null) {
+ /// Creates a volume holding .
+ public void Create(Stream output, IReadOnlyList inputs, FormatCreateOptions options) {
ArgumentNullException.ThrowIfNull(output);
var w = new Reiser4Writer();
- if (saved is not null) {
- w.Label = saved.Label;
- w.Uuid = Convert.FromHexString(saved.UuidHex);
- w.MkfsId = saved.MkfsId;
- w.BlockCount = (ulong)(saved.Length / Reiser4Writer.BlockSize);
- w.AddDirectory("", saved.Root);
- }
-
- // Volume label: prefer the schema knob, falling back to the legacy
- // password-slot mapping (kept for callers that pre-date the schema).
- var label = options?.GetOption("VolumeLabel", "") ?? "";
- if (string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(options?.Password))
- label = options.Password;
- if (!string.IsNullOrEmpty(label))
- w.Label = label;
+ ApplyCreateOptions(w, options);
- // Image size: the writer counts 4 KB blocks. "Auto (fit to files)" and any
- // unset/unparsable value leave the default (and writer minimum) in place.
var sizes = new List();
if (inputs != null)
foreach (var i in inputs) {
var name = i.ArchiveName.Replace('\\', '/').TrimEnd('/');
- var metadata = saved?.Entries.GetValueOrDefault(name)?.Metadata;
- if (i.IsDirectory) { w.AddDirectory(name, metadata); continue; }
+ if (i.IsDirectory) { w.AddDirectory(name, ToFileMetadata(i.Metadata)); continue; }
var length = i.InMemoryContent?.LongLength ?? new FileInfo(i.FullPath).Length;
sizes.Add(length);
if (i.InMemoryContent is { } bytes) {
- w.AddFile(i.ArchiveName, bytes, metadata);
+ w.AddFile(i.ArchiveName, bytes, ToFileMetadata(i.Metadata));
continue;
}
var path = i.FullPath;
- w.AddStreamingFile(i.ArchiveName, length, () => File.OpenRead(path), metadata);
+ w.AddStreamingFile(i.ArchiveName, length, () => File.OpenRead(path), ToFileMetadata(i.Metadata));
}
- // The requested size is a floor: the volume has to be at least large enough
- // for the payload's directory chain, data blocks and bitmaps.
var sizeBytes = FilesystemSchemaPresets.ParseSize(options?.GetOption("ImageSize", ""));
var requested = sizeBytes > 0 ? (ulong)Math.Max(1, sizeBytes / Reiser4Writer.BlockSize) : 0UL;
- w.BlockCount = Math.Max(w.BlockCount, Math.Max(requested, Reiser4Writer.EstimateBlockCount(sizes)));
-
+ w.BlockCount = Math.Max(requested, Reiser4Writer.EstimateBlockCount(sizes));
w.Write(output);
}
+ private static void ApplyCreateOptions(Reiser4Writer writer, FormatCreateOptions? options) {
+ // Volume label: prefer the schema knob, falling back to the legacy
+ // password-slot mapping (kept for callers that pre-date the schema).
+ var label = options?.GetOption("VolumeLabel", "") ?? "";
+ if (string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(options?.Password))
+ label = options.Password;
+ if (!string.IsNullOrEmpty(label)) writer.Label = label;
+ writer.FileBody = ParseFileBody(options?.GetOption("FileBody", ""));
+ }
+
+ private static Reiser4FileBody ParseFileBody(string? value) {
+ if (string.IsNullOrWhiteSpace(value)) return Reiser4FileBody.Extents;
+ return Enum.TryParse(value, ignoreCase: true, out var body)
+ ? body
+ : throw new NotSupportedException($"Reiser4: unknown FileBody '{value}'.");
+ }
+
+ /// Metadata an archive input carries, in the shape the writer applies to a new object.
+ private static Reiser4Reader.FileMetadata? ToFileMetadata(ArchiveEntryMetadata? metadata) {
+ if (metadata is null) return null;
+ var now = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+ static uint Seconds(DateTimeOffset? time, uint fallback) => time is { } t && t.ToUnixTimeSeconds() is >= 0 and <= uint.MaxValue ? (uint)t.ToUnixTimeSeconds() : fallback;
+ var modified = Seconds(metadata.LastWriteTimeUtc, now);
+ return new Reiser4Reader.FileMetadata(0, (ushort)((metadata.UnixMode ?? 0x1A4) & 0xFFF), 1,
+ metadata.UnixUserId ?? 0, metadata.UnixGroupId ?? 0, modified, Seconds(metadata.LastAccessTimeUtc, modified),
+ Seconds(metadata.StatusChangeTimeUtc, modified), []);
+ }
+
///
- /// Creates the supported native node40 profile from input streams. Each source
- /// is consumed once into a temporary file, then copied in bounded chunks by
- /// ; no complete file is staged in memory. Directory
- /// inputs retain empty directories and nested paths.
+ /// Creates the volume from input streams. Each source is consumed once into a temporary file,
+ /// then copied in bounded chunks by ; no complete file is staged in
+ /// memory. Directory inputs retain empty directories and nested paths.
///
public void CreateFromStreams(Stream target,
IEnumerable inputs,
@@ -336,11 +297,7 @@ public void CreateFromStreams(Stream target,
FileOptions.SequentialScan));
}
- var label = options?.GetOption("VolumeLabel", "") ?? "";
- if (string.IsNullOrEmpty(label) && !string.IsNullOrEmpty(options?.Password))
- label = options.Password;
- if (!string.IsNullOrEmpty(label)) writer.Label = label;
-
+ ApplyCreateOptions(writer, options);
var requestedBytes = FilesystemSchemaPresets.ParseSize(options?.GetOption("ImageSize", ""));
var requestedBlocks = requestedBytes > 0
? (ulong)Math.Max(1, requestedBytes / Reiser4Writer.BlockSize)
@@ -354,26 +311,75 @@ public void CreateFromStreams(Stream target,
}
}
+ // ── Rebuilds ─────────────────────────────────────────────────────────
+
///
- /// Performs the defragment operation.
+ /// Reads the volume into a plan, applies , writes the result to scratch,
+ /// reads it back and verifies it, and only then replaces . A volume
+ /// outside the profile — or an edit the profile cannot represent — is refused before anything
+ /// is written.
///
- public void Defragment(Stream archive)
- => this.Defragment(archive, new DefragOptions { Mode = DefragMode.ConsolidateAtStart });
+ private static void EditStaged(Stream archive, Action edit, Func? minimumBlocks = null) {
+ ArgumentNullException.ThrowIfNull(archive);
+ using var staged = RebuildVerb.CreateScratchStream();
+ StageTo(archive, staged, edit, minimumBlocks);
+ archive.Position = 0;
+ archive.SetLength(0);
+ staged.Position = 0;
+ staged.CopyTo(archive);
+ archive.Flush();
+ }
+
+ /// Writes the edited plan of to and verifies it there.
+ private static void StageTo(Stream source, Stream target, Action edit, Func? minimumBlocks) {
+ source.Position = 0;
+ using var volume = new Reiser4Volume(source);
+ var plan = Reiser4Plan.FromVolume(volume);
+ edit(plan);
+ if (minimumBlocks is not null) plan.MinimumBlocks = minimumBlocks(plan);
+ target.Position = 0;
+ target.SetLength(0);
+ plan.Write(target);
+ Verify(plan, target, volume);
+ }
///
- /// Largest volume the in-place pass is offered for. Its guard holds a copy of
- /// the image to compare payloads across the pass.
+ /// The staged volume must read back whole, keep the volume's identity, name exactly what the
+ /// plan names, and hold every object's stat data as the plan wrote it.
///
+ private static void Verify(Reiser4Plan plan, Stream staged, Reiser4Volume source) {
+ staged.Position = 0;
+ using var rebuilt = new Reiser4Volume(staged);
+ if (!rebuilt.TreeValid)
+ throw new InvalidDataException($"Reiser4: the rebuilt tree failed verification: {rebuilt.Problem}.");
+ if (rebuilt.UuidHex != source.UuidHex || rebuilt.Label != source.Label)
+ throw new InvalidDataException("Reiser4: the rebuilt volume lost its identity.");
+ var expected = plan.Paths.ToDictionary(static p => p.Key, static p => p.Value.Entry.Target, StringComparer.Ordinal);
+ if (rebuilt.Paths.Count != expected.Count)
+ throw new InvalidDataException("Reiser4: the rebuilt namespace failed verification.");
+ var objects = plan.Objects.ToDictionary(static o => o.StatKey);
+ foreach (var (path, _, obj, _) in rebuilt.Paths) {
+ if (!expected.TryGetValue(path, out var key) || key != obj.StatKey || !objects.TryGetValue(key, out var planned) ||
+ !planned.Stat.AsSpan().SequenceEqual(obj.Stat.Raw))
+ throw new InvalidDataException($"Reiser4: '{path}' failed verification after the rebuild.");
+ }
+ }
+
+ /// Performs the defragment operation.
+ public void Defragment(Stream archive)
+ => this.Defragment(archive, new DefragOptions { Mode = DefragMode.ConsolidateAtStart });
+
+ /// Largest volume the in-place pass is offered for. Its guard holds a copy of the image to compare payloads across the pass.
private const long MaxBufferedImageBytes = 256L * 1024 * 1024;
/// Every file's bytes, as the guard compares them before and after.
private static IReadOnlyList ReadPayloadsForGuard(Stream stream) {
stream.Position = 0;
using var reader = new Reiser4Reader(stream, leaveOpen: true);
- return reader.Entries.Where(e => !e.IsDirectory && e.Size > 0).Select(reader.Extract).ToList();
+ return reader.Entries.Where(e => e.Kind == Reiser4Reader.EntryKind.File && e.Size > 0).Select(reader.Extract).ToList();
}
- /// Plans the new layout and moves the runs into it, repointing at the end.
+ /// Plans the new layout and moves the runs into it, repointing every extent at the end.
private void DefragmentWithPlanner(Stream archive, DefragOptions options) {
archive.Position = 0;
var mover = new Reiser4BlockMover();
@@ -397,8 +403,8 @@ private void DefragmentWithPlanner(Stream archive, DefragOptions options) {
Compression.Core.Layout.DefragPlannerExecutor.Execute(archive, options, mover, moves,
archive.Length, reinitAfterMove: null);
- // The directory is written once every run has landed: a file's position is
- // one field, and what it means depends on where all of its blocks are.
+ // The tree is written once every run has landed: an extent unit is one field, and what it
+ // means depends on where all of a file's blocks are.
mover.SettleDirectory(archive);
archive.Position = 0;
@@ -408,57 +414,60 @@ private void DefragmentWithPlanner(Stream archive, DefragOptions options) {
}
///
- /// Rewrites the volume with every file laid out contiguously from the start of
- /// the payload area. Each entry is spilled to scratch and the writer pulls it
- /// back, so the rebuild is not bounded by what a byte[] can hold.
+ /// Defragments the volume: in place when the planner's moves can be written back as extent
+ /// repoints (any tree height), otherwise by a staged rebuild that lays every file out
+ /// contiguously at the same volume size.
///
public void Defragment(Stream archive, DefragOptions options) {
ArgumentNullException.ThrowIfNull(archive);
ArgumentNullException.ThrowIfNull(options);
- var saved = CaptureMetadata(archive);
-
- using (var reader = new Reiser4Reader(archive)) {
- var plannerProfile = reader.NativeNodeBlocks.Count == 2 && reader.NativeNodeBlocks.Contains(23UL) &&
- reader.NativeNodeBlocks.Contains(24UL) && reader.Entries.All(static entry => !entry.IsDirectory);
- if (plannerProfile && archive.CanSeek && archive.Length <= MaxBufferedImageBytes) {
- var planned = false;
- DefragContentGuard.RunOrRebuild(archive,
- readContents: ReadPayloadsForGuard,
- inPlace: () => {
- DefragmentWithPlanner(archive, options);
- var moved = CaptureMetadata(archive);
- if (saved.Root is { } root && !MetadataMatches(root, moved.Root) ||
- saved.Entries.Any(pair => !moved.Entries.TryGetValue(pair.Key, out var entry) ||
- pair.Value.Metadata is { } metadata && !MetadataMatches(metadata, entry.Metadata)))
- throw new InvalidDataException("Reiser4: in-place defrag changed native metadata.");
- planned = true;
- },
- rebuild: () => planned = false);
- if (planned) return;
- archive.Position = 0;
- }
+ archive.Position = 0;
+ Dictionary before;
+ bool inPlace;
+ using (var volume = new Reiser4Volume(archive)) {
+ if (!volume.TreeValid) throw new NotSupportedException($"Reiser4: refusing to defragment: {volume.Problem}.");
+ _ = Reiser4Plan.FromVolume(volume);
+ before = volume.Objects.ToDictionary(static pair => pair.Key.ToString(), static pair => pair.Value.Stat.Raw);
+ inPlace = volume.ReplayedTransactions == 0 && archive.CanSeek && archive.Length <= MaxBufferedImageBytes;
+ }
+ if (inPlace) {
+ var planned = false;
+ DefragContentGuard.RunOrRebuild(archive,
+ readContents: ReadPayloadsForGuard,
+ inPlace: () => {
+ this.DefragmentWithPlanner(archive, options);
+ archive.Position = 0;
+ using var moved = new Reiser4Volume(archive);
+ if (!moved.TreeValid || moved.Objects.Count != before.Count ||
+ moved.Objects.Any(pair => !before.TryGetValue(pair.Key.ToString(), out var raw) || !raw.AsSpan().SequenceEqual(pair.Value.Stat.Raw)))
+ throw new InvalidDataException("Reiser4: in-place defrag changed native metadata.");
+ planned = true;
+ },
+ rebuild: () => planned = false);
+ if (planned) return;
+ archive.Position = 0;
}
if (options.Mode is not (DefragMode.ConsolidateAtStart or DefragMode.FillHolesLazy))
throw new NotSupportedException(
$"Reiser4 defragmentation supports ConsolidateAtStart and FillHolesLazy; got {options.Mode}.");
- using var source = new RebuildSource(this, archive);
- RebuildVerb.RebuildInPlace(archive, source, new MetadataCreator(saved),
- onProgress: options.OnProgress, cancellationToken: options.CancellationToken);
+ options.OnProgress?.Invoke(new DefragProgressEvent("rebuilding", 0.1, -1, -1, archive.Length, null, "Rebuilding the volume"));
+ EditStaged(archive, static _ => { });
+ options.OnProgress?.Invoke(new DefragProgressEvent("complete", 1, -1, -1, archive.Length, null, "Rebuild committed successfully"));
}
- /// Rebuilds tightly while retaining native metadata, or copies through on failure.
+ /// Rebuilds tightly while retaining native metadata, or copies through when the volume cannot be rebuilt smaller.
public void Shrink(Stream input, Stream output) {
using var staged = RebuildVerb.CreateScratchStream();
var useStaged = false;
try {
- var saved = CaptureMetadata(input) with { Length = 0 };
- using var source = new RebuildSource(this, input);
- RebuildVerb.RebuildToStream(input, staged, source, new MetadataCreator(saved));
+ StageTo(input, staged, static _ => { }, static _ => Reiser4Writer.MinBlockCount);
useStaged = staged.Length < input.Length;
- } catch { /* retain the original when the supported writer cannot represent it */ }
+ } catch (Exception ex) when (ex is NotSupportedException or InvalidDataException) {
+ // the original is retained when the writer cannot represent it
+ }
input.Position = 0;
output.Position = 0;
output.SetLength(0);
@@ -466,22 +475,20 @@ public void Shrink(Stream input, Stream output) {
else input.CopyTo(output);
}
- /// Rebuilds the supported native profile while carrying existing metadata.
+ /// Rebuilds the volume while carrying existing metadata, at the requested image size or the smallest that holds it.
public void RebuildStreaming(Stream source, Stream target, LayoutRebuildOptions options) {
ArgumentNullException.ThrowIfNull(options);
if (options.UnitSize is not (0 or Reiser4Writer.BlockSize) || options.MakeSparse || options.DeduplicateWithLinks)
throw new NotSupportedException("Reiser4: this writer uses 4096-byte blocks without sparse or shared-file transforms.");
- var parameters = new Dictionary(StringComparer.OrdinalIgnoreCase);
- if (options.ImageSize > 0) parameters["ImageSize"] = options.ImageSize.ToString(CultureInfo.InvariantCulture);
+ var imageSize = options.ImageSize;
if (options.Parameters is not null)
foreach (var pair in options.Parameters) {
if (!pair.Key.Equals("ImageSize", StringComparison.OrdinalIgnoreCase))
throw new NotSupportedException($"Reiser4: unsupported rebuild parameter '{pair.Key}'.");
- parameters[pair.Key] = pair.Value;
+ imageSize = FilesystemSchemaPresets.ParseSize(pair.Value);
}
- var saved = CaptureMetadata(source) with { Length = 0 };
- using var sourceOps = new RebuildSource(this, source);
- RebuildVerb.RebuildToStream(source, target, sourceOps, new MetadataCreator(saved), parameters);
+ var blocks = imageSize > 0 ? (ulong)(imageSize / Reiser4Writer.BlockSize) : Reiser4Writer.MinBlockCount;
+ StageTo(source, target, static _ => { }, _ => Math.Max(Reiser4Writer.MinBlockCount, blocks));
}
private static string SafeMemberPath(string root, string name) {
@@ -492,127 +499,6 @@ private static string SafeMemberPath(string root, string name) {
return Path.Combine(root, Path.Combine(components));
}
- // One native walk for a rebuild; opening every member must not reparse a wide tree.
- private sealed class RebuildSource : IArchiveFormatOperations, IDisposable {
- private readonly Reiser4FormatDescriptor _owner;
- private readonly Stream _source;
- private readonly Reiser4Reader _reader;
- private readonly Dictionary _entries;
-
- internal RebuildSource(Reiser4FormatDescriptor owner, Stream source) {
- this._owner = owner;
- this._source = source;
- this._reader = new Reiser4Reader(source);
- if (!this._reader.NativeTreeValid) throw new NotSupportedException("Reiser4: unsupported rebuild source.");
- this._entries = this._reader.Entries.ToDictionary(static entry => entry.Name, StringComparer.Ordinal);
- }
-
- public List List(Stream stream, string? password)
- => ReferenceEquals(stream, this._source)
- ? this._reader.Entries.Select(static (entry, index) => new ArchiveEntryInfo(index, entry.Name,
- entry.Size, entry.Size, "stored", entry.IsDirectory, false, entry.Metadata?.LastModified)).ToList()
- : this._owner.List(stream, password);
-
- public void Extract(Stream stream, string outputDir, string? password, string[]? files) {
- if (!ReferenceEquals(stream, this._source)) { this._owner.Extract(stream, outputDir, password, files); return; }
- foreach (var entry in this._reader.Entries) {
- if (files is { Length: > 0 } && !MatchesFilter(entry.Name, files)) continue;
- var destination = SafeMemberPath(outputDir, entry.Name);
- if (entry.IsDirectory) { Directory.CreateDirectory(destination); continue; }
- Directory.CreateDirectory(Path.GetDirectoryName(destination)!);
- using var output = File.Create(destination);
- if (this._reader.ExtractTo(entry, output) != entry.Size)
- throw new EndOfStreamException($"Reiser4: truncated source member '{entry.Name}'.");
- }
- }
-
- public Stream OpenEntry(Stream archive, string entryName, string? password) {
- if (!ReferenceEquals(archive, this._source))
- return ((IArchiveFormatOperations)this._owner).OpenEntry(archive, entryName, password);
- if (!this._entries.TryGetValue(entryName, out var entry) || entry.IsDirectory)
- throw new FileNotFoundException("Reiser4: source member was not found.", entryName);
- if (entry.Size == 0) return new MemoryStream([], writable: false);
- var spool = RebuildVerb.CreateScratchStream();
- try {
- if (this._reader.ExtractTo(entry, spool) != entry.Size)
- throw new EndOfStreamException($"Reiser4: truncated source member '{entryName}'.");
- spool.Position = 0;
- return spool;
- } catch { spool.Dispose(); throw; }
- }
-
- public void Dispose() => this._reader.Dispose();
- }
-
- private sealed record RebuildMetadata(string Label, string UuidHex, uint MkfsId, long Length,
- Reiser4Reader.FileMetadata? Root, Dictionary Entries);
-
- ///
- /// Everything a rebuild has to carry across, taken before anything is written. A tree the
- /// reader cannot walk completely, or fixed blocks the writer would not reproduce, are
- /// refused here, so the source is never touched.
- ///
- private static RebuildMetadata CaptureMetadata(Stream archive) {
- using var reader = new Reiser4Reader(archive);
- if (!reader.NativeTreeValid)
- throw new NotSupportedException("Reiser4: refusing to rebuild an incomplete or unsupported native tree.");
- var blocks = new Dictionary();
- byte[] Block(int number) {
- if (blocks.TryGetValue(number, out var cached)) return cached;
- var buffer = new byte[Reiser4Writer.BlockSize];
- archive.Position = (long)number * Reiser4Writer.BlockSize;
- archive.ReadExactly(buffer);
- return blocks[number] = buffer;
- }
- if (Reiser4Writer.ProfileMismatch(Block) is { } reason)
- throw new NotSupportedException($"Reiser4: refusing to rebuild: {reason}.");
- var mkfsId = BinaryPrimitives.ReadUInt32LittleEndian(Block(17).AsSpan(48, 4));
- archive.Position = 0;
- return new(reader.Label, reader.UuidHex, mkfsId, reader.Length, reader.RootMetadata,
- reader.Entries.ToDictionary(static entry => entry.Name, StringComparer.Ordinal));
- }
-
- private sealed class MetadataCreator(RebuildMetadata saved) : IArchiveCreatable {
- public void Create(Stream output, IReadOnlyList inputs, FormatCreateOptions options) {
- var directoryNames = inputs.Where(static input => input.IsDirectory)
- .Select(static input => input.ArchiveName.Replace('\\', '/').TrimEnd('/')).ToArray();
- uint DirectoryLinks(string name) => checked((name.Length == 0 ? 3U : 2U) + (uint)directoryNames.Count(path => {
- var slash = path.LastIndexOf('/');
- return (slash < 0 ? "" : path[..slash]) == name;
- }));
- var entries = saved.Entries.ToDictionary(static pair => pair.Key, pair => pair.Value.IsDirectory && pair.Value.Metadata is { } metadata
- ? pair.Value with { Metadata = metadata with { LinkCount = DirectoryLinks(pair.Key) } } : pair.Value, StringComparer.Ordinal);
- var effective = saved with {
- Entries = entries, Root = saved.Root is { } rootMetadata ? rootMetadata with { LinkCount = DirectoryLinks("") } : null,
- };
- CreateCore(output, inputs, options, effective);
- using var rebuilt = new Reiser4Reader(output);
- if (!rebuilt.NativeTreeValid || rebuilt.Label != saved.Label || rebuilt.UuidHex != saved.UuidHex)
- throw new InvalidDataException("Reiser4: rebuilt native tree or volume identity failed verification.");
- var expectedNames = inputs.Select(static input => input.ArchiveName.Replace('\\', '/').TrimEnd('/'))
- .Order(StringComparer.Ordinal).ToArray();
- if (!rebuilt.Entries.Select(static entry => entry.Name).Order(StringComparer.Ordinal)
- .SequenceEqual(expectedNames, StringComparer.Ordinal))
- throw new InvalidDataException("Reiser4: rebuilt namespace failed verification.");
- if (effective.Root is { } root && !MetadataMatches(root, rebuilt.RootMetadata))
- throw new InvalidDataException("Reiser4: root metadata failed verification.");
- foreach (var entry in rebuilt.Entries) {
- if (effective.Entries.TryGetValue(entry.Name, out var original) && original.Metadata is { } before &&
- !MetadataMatches(before, entry.Metadata))
- throw new InvalidDataException($"Reiser4: metadata was lost for '{entry.Name}'.");
- }
- }
- }
-
- private static bool MetadataMatches(Reiser4Reader.FileMetadata expected, Reiser4Reader.FileMetadata? actual)
- => actual is not null && expected.ObjectId == actual.ObjectId && expected.StatLocality == actual.StatLocality &&
- expected.Mode == actual.Mode && expected.LinkCount == actual.LinkCount &&
- expected.UserId == actual.UserId && expected.GroupId == actual.GroupId &&
- expected.ModifiedTime == actual.ModifiedTime && expected.AccessedTime == actual.AccessedTime &&
- expected.ChangedTime == actual.ChangedTime && expected.RawStatData.Length == actual.RawStatData.Length &&
- expected.RawStatData.AsSpan(0, 2).SequenceEqual(actual.RawStatData.AsSpan(0, 2)) &&
- expected.RawStatData.AsSpan(44).SequenceEqual(actual.RawStatData.AsSpan(44));
-
/// Updates a native object's mode, owner and timestamps through a staged rebuild.
/// The readable, writable, seekable volume to update.
/// The member path, or an empty string for the root directory.
@@ -622,87 +508,80 @@ private static bool MetadataMatches(Reiser4Reader.FileMetadata expected, Reiser4
/// its extension bytes, or the volume is outside the supported profile; the volume is unchanged.
public void UpdateMetadata(Stream archive, string name, Reiser4Reader.FileMetadata metadata) {
ArgumentNullException.ThrowIfNull(metadata);
- var saved = CaptureMetadata(archive);
- var normalized = name.Replace('\\', '/').TrimEnd('/');
- var original = normalized.Length == 0 ? saved.Root : saved.Entries.GetValueOrDefault(normalized)?.Metadata;
- if (original is null) throw new FileNotFoundException("Reiser4: native object was not found.", name);
- if ((metadata.Mode & 0xF000) != (original.Mode & 0xF000))
- throw new NotSupportedException("Reiser4: metadata updates cannot change an object's kind.");
- // The link count follows the namespace: a file has one name, a directory one more than
- // its sub-directories. Any other value is what fsck.reiser4 reports as wrong.
- if (metadata.LinkCount != original.LinkCount)
- throw new NotSupportedException("Reiser4: the link count follows the namespace and cannot be set.");
- // Extension bytes past the Unix fields are carried as found because their meaning is not
- // verified here; accepting new ones would write a stat data nothing has checked.
- if (metadata.RawStatData.Length != original.RawStatData.Length ||
- !metadata.RawStatData.AsSpan(0, 2).SequenceEqual(original.RawStatData.AsSpan(0, 2)) ||
- !metadata.RawStatData.AsSpan(Math.Min(44, metadata.RawStatData.Length)).SequenceEqual(original.RawStatData.AsSpan(Math.Min(44, original.RawStatData.Length))))
- throw new NotSupportedException("Reiser4: stat-data extensions other than the Unix fields cannot be changed.");
- var updated = metadata with {
- Size = original.Size, ObjectId = original.ObjectId, StatLocality = original.StatLocality,
- RawStatData = original.RawStatData.ToArray(),
- };
- if (normalized.Length == 0) saved = saved with { Root = updated };
- else saved.Entries[normalized] = saved.Entries[normalized] with { Metadata = updated };
- using var source = new RebuildSource(this, archive);
- RebuildVerb.EditViaRebuild(archive, source, new MetadataCreator(saved), static _ => { });
+ EditStaged(archive, plan => {
+ var target = plan.Find(name) ?? throw new FileNotFoundException("Reiser4: native object was not found.", name);
+ var original = Reiser4Stat.Parse(target.Stat, out _)!;
+ if ((metadata.Mode & 0xF000) != (original.Mode & 0xF000))
+ throw new NotSupportedException("Reiser4: metadata updates cannot change an object's kind.");
+ // The link count follows the namespace: a file has one name per link, a directory one more
+ // than its sub-directories. Any other value is what fsck.reiser4 reports as wrong.
+ if (metadata.LinkCount != original.Links)
+ throw new NotSupportedException("Reiser4: the link count follows the namespace and cannot be set.");
+ // Extension bytes past the Unix fields are carried as found because their meaning is not
+ // verified here; accepting new ones would write a stat data nothing has checked.
+ if (metadata.RawStatData.Length != original.Raw.Length ||
+ !metadata.RawStatData.AsSpan(0, 2).SequenceEqual(original.Raw.AsSpan(0, 2)) ||
+ !metadata.RawStatData.AsSpan(Math.Min(44, metadata.RawStatData.Length)).SequenceEqual(original.Raw.AsSpan(Math.Min(44, original.Raw.Length))))
+ throw new NotSupportedException("Reiser4: stat-data extensions other than the Unix fields cannot be changed.");
+ plan.ApplyMetadata(target, metadata);
+ });
}
- /// Adds or replaces members while retaining existing stat-data extensions.
- public void Add(Stream archive, IReadOnlyList inputs) {
- var saved = CaptureMetadata(archive);
- using var source = new RebuildSource(this, archive);
- RebuildVerb.EditViaRebuild(archive, source, new MetadataCreator(saved), directory => {
+ /// Adds or replaces members while retaining every existing object; new files are stored as extents.
+ public void Add(Stream archive, IReadOnlyList inputs) => this.Add(archive, inputs, Reiser4FileBody.Extents);
+
+ /// Adds or replaces members, storing new regular files as says.
+ /// A replaced file keeps its identity, metadata and plugin: a cryptcompress file stays one.
+ public void Add(Stream archive, IReadOnlyList inputs, Reiser4FileBody body) {
+ ArgumentNullException.ThrowIfNull(inputs);
+ foreach (var input in inputs)
+ if (!this.CanAccept(input, out var reason)) throw new NotSupportedException("Reiser4: " + reason + ".");
+ EditStaged(archive, plan => {
+ plan.FileBody = body;
foreach (var input in inputs) {
- var destination = SafeMemberPath(directory, input.ArchiveName);
- if (input.IsDirectory) { Directory.CreateDirectory(destination); continue; }
- Directory.CreateDirectory(Path.GetDirectoryName(destination)!);
- if (input.InMemoryContent is { } bytes) File.WriteAllBytes(destination, bytes);
- else File.Copy(input.FullPath, destination, overwrite: true);
+ var name = input.ArchiveName.Replace('\\', '/').TrimEnd('/');
+ if (input.IsDirectory) { plan.AddDirectory(name, ToFileMetadata(input.Metadata)); continue; }
+ var payload = input.InMemoryContent is { } bytes
+ ? FilePayload.FromBytes(bytes)
+ : FilePayload.FromStream(new FileInfo(input.FullPath).Length, () => File.OpenRead(input.FullPath));
+ plan.AddFile(name, payload, ToFileMetadata(input.Metadata));
}
});
}
+ /// Adds a symbolic link at pointing at .
+ public void AddSymlink(Stream archive, string path, string target)
+ => EditStaged(archive, plan => plan.AddSymlink(path, target));
+
+ /// Adds as a further name of the existing file .
+ public void AddHardLink(Stream archive, string path, string existing)
+ => EditStaged(archive, plan => plan.AddHardLink(path, existing));
+
+ /// Adds a device node ( = major << 20 | minor), FIFO or socket.
+ public void AddSpecialFile(Stream archive, string path, ushort mode, ulong device = 0)
+ => EditStaged(archive, plan => plan.AddSpecial(path, mode, device));
+
/// Removes members and directory subtrees through a metadata-preserving rebuild.
public void Remove(Stream archive, string[] entryNames) {
- var saved = CaptureMetadata(archive);
- using var source = new RebuildSource(this, archive);
- RebuildVerb.EditViaRebuild(archive, source, new MetadataCreator(saved), directory => {
- foreach (var name in entryNames) {
- var destination = SafeMemberPath(directory, name);
- if (Directory.Exists(destination)) Directory.Delete(destination, recursive: true);
- else if (File.Exists(destination)) File.Delete(destination);
- }
+ ArgumentNullException.ThrowIfNull(entryNames);
+ EditStaged(archive, plan => {
+ foreach (var name in entryNames) plan.Remove(name);
});
}
// ── IArchiveWriteConstraints ─────────────────────────────────────────
- ///
- /// Performs the can accept operation.
- ///
public bool CanAccept(ArchiveInputInfo input, out string? reason) {
ArgumentNullException.ThrowIfNull(input);
reason = Reiser4Writer.RejectName(input.IsDirectory ? input.ArchiveName.TrimEnd('/', '\\') : input.ArchiveName);
return reason is null;
}
- ///
- /// Gets the max total archive size.
- ///
public long? MaxTotalArchiveSize => null;
- ///
- /// Gets the min total archive size.
- ///
public long? MinTotalArchiveSize => Reiser4Writer.BlockSize * (long)Reiser4Writer.MinBlockCount; // 16 MB
- ///
- /// Gets the accepted inputs description.
- ///
public string AcceptedInputsDescription =>
"Reiser4 image; regular files and nested directories named by the native tree.";
// Bounded read — must NOT pull multi-GB images into memory when the carver
- // runs us speculatively. Master SB is at 65536, format40 SB at 65536+blocksize
- // (4 KB typical). Cap at 96 KB so the format40 block at 69632..70112 always
- // fits even when blocksize is 4 KB.
+ // runs us speculatively. Master SB is at 65536, format40 SB at 65536+blocksize.
private const int HeaderReadCap = 96 * 1024;
private static byte[] ReadAllBounded(Stream stream) {
@@ -717,9 +596,9 @@ private static byte[] ReadAllBounded(Stream stream) {
// ── IFilesystemExtentMap + IWipeEmpty ─────────────────────────────────
///
- /// Reports the volume's layout: the reserved blocks and the payload directory
- /// chain as metadata, then each file's blocks. A file's blocks are consecutive
- /// apart from the block-allocator bitmaps they step over.
+ /// Reports the volume's layout: the reserved blocks, the tree nodes and the allocator bitmaps as
+ /// metadata, then each file's extent runs. A volume whose journal still holds transactions to
+ /// replay reports nothing: its blocks are not yet where the tree says.
///
public IEnumerable EnumerateExtents(Stream image) {
ArgumentNullException.ThrowIfNull(image);
@@ -727,16 +606,14 @@ public IEnumerable EnumerateExtents(Stream image) {
try {
if (image.CanSeek) image.Position = 0;
using var reader = new Reiser4Reader(image);
- if (!reader.NativeTreeValid) return [];
+ if (!reader.NativeTreeValid || reader.ReplayedTransactions > 0) return [];
var blockSize = reader.BlockSize;
- // Everything before the first file's blocks is reserved or directory.
var firstData = reader.Length;
List> files = [];
+ var seen = new HashSet();
foreach (var e in reader.Entries) {
- if (e.Size <= 0) continue;
- // A file is not one run: the allocator bitmaps inside it are stepped
- // over, so its bytes continue past where its length alone would end.
+ if (e.Kind != Reiser4Reader.EntryKind.File || e.Size <= 0 || e.Native is null || !seen.Add(e.Native.StatKey)) continue;
List runs = [];
foreach (var (offset, length) in reader.EnumerateRuns(e)) {
if (offset < firstData) firstData = offset;
@@ -745,16 +622,15 @@ public IEnumerable EnumerateExtents(Stream image) {
if (runs.Count > 0) files.Add(runs);
}
- var metadataEnd = files.Count > 0 ? firstData : Math.Min(reader.Length, 25L * blockSize);
+ var metadataEnd = Math.Min(reader.Length, 25L * blockSize);
result.Add(new DefragBlockInfo(0, metadataEnd, DefragBlockKind.MetadataReserved,
- "Reserved blocks and the payload directory"));
+ "Reserved blocks"));
foreach (var node in reader.NativeNodeBlocks)
if ((long)node * blockSize >= metadataEnd)
result.Add(new DefragBlockInfo((long)node * blockSize, blockSize,
DefragBlockKind.MetadataReserved, "Native tree node"));
- // The bitmaps sit at stride boundaries inside the payload area.
for (var block = Reiser4Writer.BlocksPerBitmap;
(long)block * blockSize + blockSize <= reader.Length;
block += Reiser4Writer.BlocksPerBitmap)
@@ -762,10 +638,7 @@ public IEnumerable EnumerateExtents(Stream image) {
DefragBlockKind.MetadataReserved, "Block-allocator bitmap"));
// A map is read as a walk over the volume: each file keeps its own runs in
- // chain order, but the files themselves follow the bytes, not the
- // directory. The native tree lists names in key order, which is not where
- // their blocks are, and a map in that order makes the defrag planner shuffle
- // an already-consolidated volume.
+ // logical order, but the files themselves follow the bytes, not the tree.
foreach (var runs in files.OrderBy(static runs => runs[0].Offset))
result.AddRange(runs);
} catch {
@@ -783,5 +656,4 @@ public long WipeUnusedSpace(Stream image, bool wipeClusterTips = true, bool wipe
return UnusedSpaceWiper.Wipe(image, extents, image.Length,
wipeClusterTips: false, fileSizeLookup: null);
}
-
}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Journal.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Journal.cs
new file mode 100644
index 000000000..515efd3c1
--- /dev/null
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Journal.cs
@@ -0,0 +1,94 @@
+#pragma warning disable CS1591
+using System.Buffers.Binary;
+
+namespace FileSystem.Reiser4;
+
+///
+/// Replays the format40 journal ("wandered logs") into an in-memory overlay, the way the kernel
+/// and fsck.reiser4 do before they read the tree.
+///
+///
+/// Block 19 (journal header) names the last committed transaction, block 20 (journal footer)
+/// the last one whose blocks were written back to their home locations. Every transaction between
+/// the two, oldest first, is replayed: its head block ("TxMagic4") links to the previous
+/// transaction and to a chain of wander records ("LogMagc4"), each listing
+/// (original, wandered) block pairs; replay copies each wandered block over its original.
+/// The layout is written down in docs/REISER4-NATIVE-PROFILE.md and was confirmed on a
+/// volume captured between a kernel commit and its write-back.
+///
+internal static class Reiser4Journal {
+
+ internal const ulong HeaderBlock = 19;
+ internal const ulong FooterBlock = 20;
+
+ private static readonly byte[] TxMagic = "TxMagic4"u8.ToArray();
+ private static readonly byte[] RecordMagic = "LogMagc4"u8.ToArray();
+
+ /// Outcome of a replay: the replaced blocks and how many transactions they came from.
+ internal sealed record Replay(IReadOnlyDictionary Blocks, int Transactions);
+
+ ///
+ /// Replays every committed but unflushed transaction. Returns an empty replay when the journal
+ /// has nothing pending, and with a reason when the chain does not parse.
+ ///
+ internal static Replay? Read(Func readRaw, ulong blockCount, out string? problem) {
+ problem = null;
+ var header = readRaw(HeaderBlock);
+ var footer = readRaw(FooterBlock);
+ var lastCommitted = BinaryPrimitives.ReadUInt64LittleEndian(header);
+ var lastFlushed = BinaryPrimitives.ReadUInt64LittleEndian(footer);
+ var blocks = new Dictionary();
+ if (lastCommitted == 0 || lastCommitted == lastFlushed) return new(blocks, 0);
+
+ var chain = new List();
+ var seen = new HashSet();
+ for (var tx = lastCommitted; tx != lastFlushed;) {
+ if (tx == 0 || tx >= blockCount || !seen.Add(tx) || chain.Count > 4096) {
+ problem = "the journal's transaction chain does not reach the last flushed transaction";
+ return null;
+ }
+ var head = readRaw(tx);
+ if (!head.AsSpan(0, TxMagic.Length).SequenceEqual(TxMagic)) {
+ problem = $"journal block {tx} is not a transaction head";
+ return null;
+ }
+ chain.Add(head);
+ tx = BinaryPrimitives.ReadUInt64LittleEndian(head.AsSpan(24));
+ }
+
+ byte[] Current(ulong block) => blocks.TryGetValue(block, out var replaced) ? replaced : readRaw(block);
+ for (var i = chain.Count - 1; i >= 0; --i) {
+ var head = chain[i];
+ var total = BinaryPrimitives.ReadUInt32LittleEndian(head.AsSpan(16));
+ var record = BinaryPrimitives.ReadUInt64LittleEndian(head.AsSpan(32));
+ var pending = new List<(ulong Original, ulong Wandered)>();
+ for (var serial = 1U; serial < total; ++serial) {
+ if (record == 0 || record >= blockCount) {
+ problem = "a wander record lies outside the volume";
+ return null;
+ }
+ var log = Current(record);
+ if (!log.AsSpan(0, RecordMagic.Length).SequenceEqual(RecordMagic) ||
+ BinaryPrimitives.ReadUInt32LittleEndian(log.AsSpan(20)) != serial) {
+ problem = $"journal block {record} is not wander record {serial}";
+ return null;
+ }
+ for (var at = 32; at + 16 <= log.Length; at += 16) {
+ var original = BinaryPrimitives.ReadUInt64LittleEndian(log.AsSpan(at));
+ var wandered = BinaryPrimitives.ReadUInt64LittleEndian(log.AsSpan(at + 8));
+ if (original == 0) break;
+ if (original >= blockCount || wandered == 0 || wandered >= blockCount) {
+ problem = "a wander record names a block outside the volume";
+ return null;
+ }
+ pending.Add((original, wandered));
+ }
+ record = BinaryPrimitives.ReadUInt64LittleEndian(log.AsSpan(24));
+ }
+ // Read every wandered copy before writing any home location: a transaction is applied whole.
+ var copies = pending.Select(pair => (pair.Original, Bytes: Current(pair.Wandered).ToArray())).ToList();
+ foreach (var (original, bytes) in copies) blocks[original] = bytes;
+ }
+ return new(blocks, chain.Count);
+ }
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Keys.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Keys.cs
new file mode 100644
index 000000000..b333f5012
--- /dev/null
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Keys.cs
@@ -0,0 +1,214 @@
+#pragma warning disable CS1591
+using System.Buffers.Binary;
+
+namespace FileSystem.Reiser4;
+
+/// A large (four-word) Reiser4 key, compared word by word as unsigned values.
+///
+/// The first word holds the locality in its top sixty bits and the item type ("minor") in its
+/// low four; then come the ordering, the object id and the offset. See
+/// docs/REISER4-NATIVE-PROFILE.md for how each item kind fills them.
+///
+internal readonly record struct Reiser4Key(ulong Word0, ulong Ordering, ulong ObjectId, ulong Offset) : IComparable {
+
+ internal const byte MinorName = 0;
+ internal const byte MinorStatData = 1;
+ internal const byte MinorBody = 4;
+
+ internal ulong Locality => this.Word0 >> 4;
+ internal byte Minor => (byte)(this.Word0 & 0xF);
+
+ internal static Reiser4Key Of(ulong locality, byte minor, ulong ordering, ulong objectId, ulong offset)
+ => new(locality << 4 | minor, ordering, objectId, offset);
+
+ /// The stat-data key of the object this key belongs to.
+ internal Reiser4Key StatKey => Of(this.Locality, MinorStatData, this.Ordering, this.ObjectId, 0);
+
+ public int CompareTo(Reiser4Key other) {
+ var c = this.Word0.CompareTo(other.Word0);
+ if (c != 0) return c;
+ c = this.Ordering.CompareTo(other.Ordering);
+ if (c != 0) return c;
+ c = this.ObjectId.CompareTo(other.ObjectId);
+ return c != 0 ? c : this.Offset.CompareTo(other.Offset);
+ }
+
+ internal static Reiser4Key Read(ReadOnlySpan at) => new(
+ BinaryPrimitives.ReadUInt64LittleEndian(at),
+ BinaryPrimitives.ReadUInt64LittleEndian(at[8..]),
+ BinaryPrimitives.ReadUInt64LittleEndian(at[16..]),
+ BinaryPrimitives.ReadUInt64LittleEndian(at[24..]));
+
+ internal void Write(Span at) {
+ BinaryPrimitives.WriteUInt64LittleEndian(at, this.Word0);
+ BinaryPrimitives.WriteUInt64LittleEndian(at[8..], this.Ordering);
+ BinaryPrimitives.WriteUInt64LittleEndian(at[16..], this.ObjectId);
+ BinaryPrimitives.WriteUInt64LittleEndian(at[24..], this.Offset);
+ }
+}
+
+/// Plugin identifiers of the hash and fibration plugin types (plugin type 3 and 4).
+internal enum Reiser4HashId : ushort { Rupasov = 0, R5 = 1, Tea = 2, Fnv1 = 3, Degenerate = 4 }
+
+internal enum Reiser4FibrationId : ushort { Lexicographic = 0, DotO = 1, Extension1 = 2, Extension3 = 3 }
+
+///
+/// How a directory entry's key is made from its name: the bytes packed into the key where they
+/// fit, a hash of the rest where they do not, and a "fibre" chosen by the fibration plugin in the
+/// ordering's top seven bits.
+///
+///
+/// Derived from the format description in docs/REISER4-NATIVE-PROFILE.md and checked
+/// against directory entries a Reiser4 kernel wrote with every hash and fibration plugin; none of
+/// the reference implementations' code was carried over.
+///
+internal static class Reiser4NameKeys {
+
+ /// Names up to this many bytes are held in the key itself and stored nowhere else.
+ internal const int MaxInlineLength = 23;
+
+ /// The ordering bit that says the name was hashed rather than held.
+ internal const ulong LongNameBit = 0x0100_0000_0000_0000;
+
+ private const int FibreShift = 57;
+
+ /// Up to eight (or seven) bytes of , big-endian, from .
+ private static ulong Pack(ReadOnlySpan name, int from, int skip) {
+ ulong value = 0;
+ var room = 8 - skip;
+ var taken = 0;
+ for (var i = from; i < name.Length && taken < room; ++i, ++taken)
+ value = value << 8 | name[i];
+ return value << (room - taken) * 8;
+ }
+
+ /// Whether can key new long names this writer is asked to add.
+ ///
+ /// The Rupasov hash is computed differently by the kernel and by reiser4progs — a kernel-written
+ /// entry is reported by fsck.reiser4 as carrying the wrong offset — so no long name keyed
+ /// with it can satisfy both. Existing entries are carried with their keys as found.
+ ///
+ internal static bool CanHash(Reiser4HashId hash) => hash is Reiser4HashId.R5 or Reiser4HashId.Tea
+ or Reiser4HashId.Fnv1 or Reiser4HashId.Degenerate;
+
+ /// The three words of the entry key for , and whether it was hashed.
+ internal static (ulong Ordering, ulong ObjectId, ulong Offset, bool Hashed) Make(
+ ReadOnlySpan name, Reiser4HashId hash, Reiser4FibrationId fibration) {
+ if (name.Length == 1 && name[0] == (byte)'.') return (0, 0, 0, false);
+ var ordering = Pack(name, 0, 1);
+ var objectId = name.Length > 7 ? Pack(name, 7, 0) : 0UL;
+ ulong offset = 0;
+ var hashed = name.Length > MaxInlineLength;
+ if (hashed) {
+ ordering |= LongNameBit;
+ offset = Hash(hash, name[15..]);
+ } else if (name.Length > 15)
+ offset = Pack(name, 15, 0);
+ return (ordering | Fibre(fibration, name), objectId, offset, hashed);
+ }
+
+ /// The fibre bits a name sorts under, already shifted into place.
+ internal static ulong Fibre(Reiser4FibrationId fibration, ReadOnlySpan name) {
+ var n = name.Length;
+ ulong fibre = fibration switch {
+ Reiser4FibrationId.Lexicographic => 0,
+ Reiser4FibrationId.DotO => n > 2 && name[n - 1] == (byte)'o' && name[n - 2] == (byte)'.' ? 1UL : 0,
+ Reiser4FibrationId.Extension1 => n > 2 && name[n - 2] == (byte)'.' ? (ulong)(sbyte)name[n - 1] : 0,
+ Reiser4FibrationId.Extension3 => n > 4 && name[n - 4] == (byte)'.'
+ ? (ulong)((sbyte)name[n - 3] + (sbyte)name[n - 2] + (sbyte)name[n - 1]) : 0,
+ _ => throw new NotSupportedException($"Reiser4: fibration plugin {fibration} is not supported."),
+ };
+ // Only seven bits survive the shift: the eighth and above fall off the word.
+ return fibre << FibreShift;
+ }
+
+ internal static ulong Hash(Reiser4HashId hash, ReadOnlySpan tail) => hash switch {
+ Reiser4HashId.R5 => R5(tail),
+ Reiser4HashId.Tea => Tea(tail),
+ Reiser4HashId.Fnv1 => Fnv1(tail),
+ Reiser4HashId.Degenerate => 0xC0C0_C0C0_1010_1010UL,
+ _ => throw new NotSupportedException($"Reiser4: names cannot be hashed with the {hash} hash."),
+ };
+
+ private static ulong R5(ReadOnlySpan data) {
+ ulong a = 0;
+ foreach (var b in data) {
+ a += (ulong)b << 4;
+ a += (ulong)b >> 4;
+ a *= 11;
+ }
+ return a;
+ }
+
+ /// FNV-1 (64-bit): multiply by the prime, then xor the octet.
+ private static ulong Fnv1(ReadOnlySpan data) {
+ var a = 0xCBF2_9CE4_8422_2325UL;
+ foreach (var b in data) {
+ a *= 0x0000_0100_0000_01B3UL;
+ a ^= b;
+ }
+ return a;
+ }
+
+ ///
+ /// The TEA-based Davies–Meyer hash in the 64-bit arithmetic Reiser4 evaluates it in: sixteen-byte
+ /// blocks get six rounds, the padded remainder ten, and the result is the two halves xored.
+ ///
+ private static ulong Tea(ReadOnlySpan name) {
+ ulong h0 = 0x9464A485u, h1 = 0x542E1A94u;
+ var len = name.Length;
+ var pad = (ulong)(uint)len | (ulong)(uint)len << 8;
+ pad |= pad << 16;
+
+ static ulong Word(ReadOnlySpan s) => s[0] | (ulong)s[1] << 8 | (ulong)s[2] << 16 | (ulong)s[3] << 24;
+
+ void Mix(ulong a, ulong b, ulong c, ulong d, int rounds) {
+ ulong sum = 0, b0 = h0, b1 = h1;
+ for (var n = 0; n < rounds; ++n) {
+ sum += 0x9E3779B9u;
+ b0 += ((b1 << 4) + a) ^ (b1 + sum) ^ ((b1 >> 5) + b);
+ b1 += ((b0 << 4) + c) ^ (b0 + sum) ^ ((b0 >> 5) + d);
+ }
+ h0 += b0;
+ h1 += b1;
+ }
+
+ var at = 0;
+ while (len - at >= 16) {
+ var s = name[at..];
+ Mix(Word(s), Word(s[4..]), Word(s[8..]), Word(s[12..]), 6);
+ at += 16;
+ }
+
+ var rest = name[at..];
+ ulong wa, wb, wc, wd;
+ static ulong Tail(ReadOnlySpan rest, int from, ulong pad) {
+ var v = pad;
+ for (var i = from; i < rest.Length; ++i) v = v << 8 | rest[i];
+ return v;
+ }
+ if (rest.Length >= 12) { wa = Word(rest); wb = Word(rest[4..]); wc = Word(rest[8..]); wd = Tail(rest, 12, pad); }
+ else if (rest.Length >= 8) { wa = Word(rest); wb = Word(rest[4..]); wc = Tail(rest, 8, pad); wd = pad; }
+ else if (rest.Length >= 4) { wa = Word(rest); wb = Tail(rest, 4, pad); wc = wd = pad; }
+ else { wa = Tail(rest, 0, pad); wb = wc = wd = pad; }
+ Mix(wa, wb, wc, wd, 10);
+ return h0 ^ h1;
+ }
+
+ /// The name a key holds whole, or when the key hashed it.
+ internal static byte[]? Unpack(ulong ordering, ulong objectId, ulong offset) {
+ if ((ordering & LongNameBit) != 0) return null;
+ if (ordering == 0 && objectId == 0 && offset == 0) return [(byte)'.'];
+ var bytes = new List(23);
+ static bool Take(List into, ulong value, int count) {
+ for (var shift = (count - 1) * 8; shift >= 0; shift -= 8) {
+ var b = (byte)(value >> shift);
+ if (b == 0) return false;
+ into.Add(b);
+ }
+ return true;
+ }
+ if (Take(bytes, ordering & 0x00FF_FFFF_FFFF_FFFFUL, 7) && Take(bytes, objectId, 8)) Take(bytes, offset, 8);
+ return [.. bytes];
+ }
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Plan.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Plan.cs
new file mode 100644
index 000000000..dbbc76e33
--- /dev/null
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Plan.cs
@@ -0,0 +1,481 @@
+#pragma warning disable CS1591
+using System.Buffers.Binary;
+using System.Text;
+using Compression.Core.DiskImage;
+
+namespace FileSystem.Reiser4;
+
+/// How the body of a regular file this writer creates is stored.
+public enum Reiser4FileBody {
+ /// Extent items in twigs pointing at data blocks (reg40, "extents" formatting).
+ Extents,
+ /// Tail (plain40) items in leaves holding the bytes themselves (reg40, "tails" formatting).
+ Tails,
+ /// Tails up to four blocks, extents above that — the kernel's "smart" formatting.
+ Smart,
+ /// A cryptcompress (ccreg40) file: compressed disk clusters in ctail40 items.
+ Compressed,
+ /// Whatever the volume's root plugin set says new files are: its create plugin, then its formatting.
+ Profile,
+}
+
+/// One unit of an extent body: a hole (no payload) or blocks that receive the payload's bytes.
+internal readonly record struct Reiser4PlanUnit(ulong Width, FilePayload? Payload);
+
+/// An object as the writer lays it out.
+internal sealed class Reiser4PlanObject {
+ internal required Reiser4Key StatKey { get; set; }
+ internal required byte[] Stat { get; set; }
+ internal List Entries { get; } = [];
+ internal List<(Reiser4Key Key, ushort Plugin, byte[] Body)> Items { get; set; } = [];
+ internal List Extents { get; set; } = [];
+
+ internal ushort Mode => BinaryPrimitives.ReadUInt16LittleEndian(this.Stat.AsSpan(2));
+ internal int Kind => this.Mode & Reiser4Stat.FileType;
+ internal bool IsDirectory => this.Kind == Reiser4Stat.Directory;
+ internal ulong ObjectId => this.StatKey.ObjectId;
+ internal bool IsCryptcompress {
+ get {
+ var stat = Reiser4Stat.Parse(this.Stat, out _);
+ return stat is not null && stat.PluginSet.TryGetValue(Reiser4PsetMember.File, out var file) && file == 4;
+ }
+ }
+
+ internal void SetLinks(uint links) => BinaryPrimitives.WriteUInt32LittleEndian(this.Stat.AsSpan(4), links);
+ internal void SetSize(ulong size) => BinaryPrimitives.WriteUInt64LittleEndian(this.Stat.AsSpan(8), size);
+ internal void SetBytes(ulong bytes) => BinaryPrimitives.WriteUInt64LittleEndian(this.Stat.AsSpan(36), bytes);
+}
+
+///
+/// A whole volume as the writer will lay it out: the fixed blocks it carries (master, format,
+/// status, backup), the node plugin, and every object with its stat data, body and entries.
+/// Edits — add, replace, remove, metadata updates, links — are made here, and
+/// turns the result into an image.
+///
+///
+/// Objects read from a volume keep their stat data, keys, directory entry keys and file bodies as
+/// found; only the counters the namespace implies (link counts, directory sizes) are recomputed.
+/// New names are keyed with the directory's own hash and fibration plugins.
+///
+internal sealed class Reiser4Plan {
+
+ internal byte[] Master { get; set; } = [];
+ internal byte[] Format { get; set; } = [];
+ internal byte[] Status { get; set; } = [];
+ internal byte[] Backup { get; set; } = [];
+ internal ushort NodePlugin { get; set; }
+ internal uint MkfsId { get; set; }
+ internal ulong MinimumBlocks { get; set; }
+ internal ulong NextObjectId { get; set; }
+
+ /// How new regular files are stored.
+ internal Reiser4FileBody FileBody { get; set; } = Reiser4FileBody.Extents;
+
+ private readonly Dictionary _objects = [];
+ internal IReadOnlyList Objects => [.. this._objects.Values.OrderBy(static o => o.StatKey)];
+ internal Reiser4PlanObject Root => this._objects[Reiser4Volume.RootStatKey];
+
+ private int MaxItemBody => Reiser4Volume.BlockSize - (this.NodePlugin == 1 ? 32 : Reiser4Tree.NodeHeaderBytes) - Reiser4Tree.ItemHeaderBytes;
+
+ // ── Construction ───────────────────────────────────────────────────────
+
+ /// A plan holding everything holds, bodies referencing its blocks.
+ internal static Reiser4Plan FromVolume(Reiser4Volume volume) {
+ if (!volume.TreeValid || volume.Root is null)
+ throw new NotSupportedException($"Reiser4: refusing to rebuild: {volume.Problem ?? "the tree was not read"}.");
+ var status = volume.ReadBlock(21);
+ if (!status.AsSpan(0, 15).SequenceEqual("ReiSeR4StATusBl"u8) || BinaryPrimitives.ReadUInt64LittleEndian(status.AsSpan(16)) != 0)
+ throw new NotSupportedException("Reiser4: refusing to rebuild: the status block does not mark the volume consistent.");
+ var format = volume.ReadBlock(17);
+ var plan = new Reiser4Plan {
+ Master = volume.ReadBlock(16),
+ Format = format,
+ Status = status,
+ Backup = volume.ReadBlock(22),
+ NodePlugin = volume.NodePlugin,
+ MkfsId = BinaryPrimitives.ReadUInt32LittleEndian(format.AsSpan(48)),
+ MinimumBlocks = volume.BlockCount,
+ };
+ var maxId = Reiser4Volume.RootObjectId;
+ foreach (var obj in volume.Objects.Values) {
+ var planned = new Reiser4PlanObject { StatKey = obj.StatKey, Stat = obj.Stat.Raw.ToArray() };
+ planned.Entries.AddRange(obj.Entries);
+ if (obj.Body.Count > 0 && obj.Body[0].Plugin == Reiser4ItemPlugin.Extent) {
+ foreach (var (start, width) in volume.ExtentUnits(obj))
+ planned.Extents.Add(new Reiser4PlanUnit(width, start == 0 ? null : BlockPayload(volume, start, width)));
+ } else {
+ foreach (var item in obj.Body) planned.Items.Add((item.Key, item.Plugin, volume.ReadBody(item)));
+ }
+ plan._objects.Add(obj.StatKey, planned);
+ maxId = Math.Max(maxId, obj.ObjectId);
+ }
+ var next = BinaryPrimitives.ReadUInt64LittleEndian(format.AsSpan(24));
+ plan.NextObjectId = Math.Max(next, Math.Max(0x10000UL, maxId + 1));
+ plan._paths = null;
+ return plan;
+ }
+
+ /// An empty volume made from the captured mkfs blocks: a root directory holding only its dot entries.
+ internal static Reiser4Plan Fresh(byte[] master, byte[] format, byte[] status, byte[] backup, byte[] rootLeaf, uint mkfsId, ulong blocks) {
+ var rootStatOffset = BinaryPrimitives.ReadUInt16LittleEndian(rootLeaf.AsSpan(Reiser4Volume.BlockSize - Reiser4Tree.ItemHeaderBytes + 32));
+ var rootStatEnd = BinaryPrimitives.ReadUInt16LittleEndian(rootLeaf.AsSpan(Reiser4Volume.BlockSize - 2 * Reiser4Tree.ItemHeaderBytes + 32));
+ var plan = new Reiser4Plan {
+ Master = master, Format = format, Status = status, Backup = backup,
+ NodePlugin = 0, MkfsId = mkfsId, MinimumBlocks = blocks, NextObjectId = 0x10000,
+ };
+ var root = new Reiser4PlanObject { StatKey = Reiser4Volume.RootStatKey, Stat = rootLeaf.AsSpan(rootStatOffset, rootStatEnd - rootStatOffset).ToArray() };
+ root.Entries.Add(new Reiser4DirEntry(0, 0, 0, [(byte)'.'], Reiser4Volume.RootStatKey));
+ var (o, i, f, _) = Reiser4NameKeys.Make(".."u8, Reiser4HashId.R5, Reiser4FibrationId.Extension1);
+ root.Entries.Add(new Reiser4DirEntry(o, i, f, ".."u8.ToArray(), Reiser4Volume.RootStatKey));
+ plan._objects.Add(root.StatKey, root);
+ return plan;
+ }
+
+ private static FilePayload BlockPayload(Reiser4Volume volume, ulong start, ulong width)
+ => FilePayload.FromStream(checked((long)width * Reiser4Volume.BlockSize), () => {
+ var buffer = new MemoryStream();
+ volume.CopyBlocks(start, width, buffer, checked((long)width * Reiser4Volume.BlockSize));
+ buffer.Position = 0;
+ return buffer;
+ });
+
+ // ── Profile ────────────────────────────────────────────────────────────
+
+ /// A plugin-set member of : its own, else the root's, else the kernel default.
+ internal ushort Plugin(Reiser4PlanObject owner, ushort member) {
+ if (Reiser4Stat.Parse(owner.Stat, out _) is { } own && own.PluginSet.TryGetValue(member, out var value)) return value;
+ if (Reiser4Stat.Parse(this.Root.Stat, out _) is { } root && root.PluginSet.TryGetValue(member, out var inherited)) return inherited;
+ return member switch {
+ Reiser4PsetMember.Formatting => 2,
+ Reiser4PsetMember.Hash => (ushort)Reiser4HashId.R5,
+ Reiser4PsetMember.Fibration => (ushort)Reiser4FibrationId.Extension1,
+ Reiser4PsetMember.CompressionMode => (ushort)Reiser4CompressionModeId.Convert,
+ _ => 0,
+ };
+ }
+
+ // ── Namespace ──────────────────────────────────────────────────────────
+
+ private Dictionary? _paths;
+
+ /// Every path, with the directory that names it and the entry that does.
+ internal IReadOnlyDictionary Paths {
+ get {
+ if (this._paths is { } cached) return cached;
+ var paths = new Dictionary(StringComparer.Ordinal);
+ void Walk(Reiser4PlanObject directory, string prefix, int depth) {
+ if (depth > 128) throw new InvalidDataException("Reiser4: the namespace is deeper than this writer walks.");
+ foreach (var entry in directory.Entries) {
+ if (entry.IsDot || entry.IsDotDot) continue;
+ var path = prefix.Length == 0 ? Reiser4Volume.DecodeName(entry.Name) : prefix + "/" + Reiser4Volume.DecodeName(entry.Name);
+ paths[path] = (directory, entry);
+ if (this._objects.TryGetValue(entry.Target, out var target) && target.IsDirectory) Walk(target, path, depth + 1);
+ }
+ }
+ Walk(this.Root, "", 0);
+ return this._paths = paths;
+ }
+ }
+
+ internal Reiser4PlanObject? Find(string path) {
+ var normalized = Normalize(path);
+ if (normalized.Length == 0) return this.Root;
+ return this.Paths.TryGetValue(normalized, out var hit) ? this._objects.GetValueOrDefault(hit.Entry.Target) : null;
+ }
+
+ internal static string Normalize(string path) => path.Replace('\\', '/').Trim('/');
+
+ private Reiser4PlanObject EnsureDirectory(string path, Reiser4Reader.FileMetadata? metadata = null) {
+ var normalized = Normalize(path);
+ if (normalized.Length == 0) return this.Root;
+ if (this.Find(normalized) is { } existing) {
+ if (!existing.IsDirectory) throw new InvalidDataException($"Reiser4: file/directory collision at '{normalized}'.");
+ return existing;
+ }
+ var slash = normalized.LastIndexOf('/');
+ var parent = this.EnsureDirectory(slash < 0 ? "" : normalized[..slash]);
+ var name = Encoding.UTF8.GetBytes(slash < 0 ? normalized : normalized[(slash + 1)..]);
+ var stat = this.NewStat(metadata, 0x41ED, 0, 0, symlink: null, pluginSet: null);
+ var directory = this.Link(parent, name, stat, metadata?.ObjectId ?? 0);
+ var (o, i, f, _) = Reiser4NameKeys.Make(".."u8, Reiser4HashId.R5, Reiser4FibrationId.Extension1);
+ directory.Entries.Add(new Reiser4DirEntry(0, 0, 0, [(byte)'.'], directory.StatKey));
+ directory.Entries.Add(new Reiser4DirEntry(o, i, f, ".."u8.ToArray(), parent.StatKey));
+ return directory;
+ }
+
+ /// Creates a new object named in .
+ private Reiser4PlanObject Link(Reiser4PlanObject parent, byte[] name, byte[] stat, ulong requestedId) {
+ var hash = (Reiser4HashId)this.Plugin(parent, Reiser4PsetMember.Hash);
+ var fibration = (Reiser4FibrationId)this.Plugin(parent, Reiser4PsetMember.Fibration);
+ var (ordering, objectId, offset, hashed) = MakeKey(name, hash, fibration);
+ if (parent.Entries.Any(e => e.Ordering == ordering && e.ObjectId == objectId && e.Offset == offset))
+ throw new NotSupportedException($"Reiser4: the name '{Reiser4Volume.DecodeName(name)}' would share its key with an existing entry.");
+ ulong id;
+ if (requestedId > Reiser4Volume.RootObjectId && this._objects.Values.All(o => o.ObjectId != requestedId)) {
+ id = requestedId;
+ this.NextObjectId = Math.Max(this.NextObjectId, id + 1);
+ } else id = this.NextObjectId++;
+ var statKey = Reiser4Key.Of(parent.ObjectId, Reiser4Key.MinorStatData, ordering, id, 0);
+ var obj = new Reiser4PlanObject { StatKey = statKey, Stat = stat };
+ this._objects.Add(statKey, obj);
+ parent.Entries.Add(new Reiser4DirEntry(ordering, objectId, offset, name, statKey));
+ this._paths = null;
+ _ = hashed;
+ return obj;
+ }
+
+ private static (ulong Ordering, ulong ObjectId, ulong Offset, bool Hashed) MakeKey(byte[] name, Reiser4HashId hash, Reiser4FibrationId fibration) {
+ if (name.Length > Reiser4NameKeys.MaxInlineLength && !Reiser4NameKeys.CanHash(hash))
+ throw new NotSupportedException(
+ $"Reiser4: names longer than {Reiser4NameKeys.MaxInlineLength} bytes cannot be added under the {hash} hash, which the kernel and reiser4progs compute differently.");
+ return Reiser4NameKeys.Make(name, hash, fibration);
+ }
+
+ private (Reiser4PlanObject Parent, byte[] Name) ParentOf(string path) {
+ var normalized = Normalize(path);
+ if (Reiser4Writer.RejectName(normalized) is { } reason) throw new NotSupportedException("Reiser4: " + reason + ".");
+ var slash = normalized.LastIndexOf('/');
+ var parent = this.EnsureDirectory(slash < 0 ? "" : normalized[..slash]);
+ return (parent, Encoding.UTF8.GetBytes(slash < 0 ? normalized : normalized[(slash + 1)..]));
+ }
+
+ // ── Edits ──────────────────────────────────────────────────────────────
+
+ internal void AddDirectory(string path, Reiser4Reader.FileMetadata? metadata = null) {
+ var normalized = Normalize(path);
+ if (normalized.Length == 0) {
+ if (metadata is not null) this.ApplyMetadata(this.Root, metadata);
+ return;
+ }
+ if (Reiser4Writer.RejectName(normalized) is { } reason) throw new NotSupportedException("Reiser4: " + reason + ".");
+ var existing = this.Find(normalized);
+ var directory = this.EnsureDirectory(normalized, metadata);
+ if (existing is not null && metadata is not null) this.ApplyMetadata(directory, metadata);
+ }
+
+ /// Adds a regular file, or replaces the body of the one already there (keeping its identity and metadata).
+ internal void AddFile(string path, FilePayload payload, Reiser4Reader.FileMetadata? metadata = null) {
+ var (parent, name) = this.ParentOf(path);
+ var existing = this.Find(path);
+ Reiser4PlanObject file;
+ bool compressed;
+ if (existing is not null) {
+ if (existing.Kind != Reiser4Stat.Regular)
+ throw new InvalidDataException($"Reiser4: '{Normalize(path)}' exists and is not a regular file.");
+ file = existing;
+ compressed = existing.IsCryptcompress;
+ if (metadata is not null) this.ApplyMetadata(file, metadata);
+ } else {
+ compressed = this.ResolveBody(parent, payload.Size) == Reiser4FileBody.Compressed ||
+ metadata is { RawStatData.Length: >= 44 } carried && Reiser4Stat.Parse(carried.RawStatData, out _) is { } carriedStat &&
+ carriedStat.PluginSet.TryGetValue(Reiser4PsetMember.File, out var carriedFile) && carriedFile == 4;
+ var pset = compressed && metadata is not { RawStatData.Length: >= 44 } ? new Dictionary { [Reiser4PsetMember.File] = 4 } : null;
+ file = this.Link(parent, name, this.NewStat(metadata, 0x81A4, 0, 0, null, pset), metadata?.ObjectId ?? 0);
+ }
+ this.SetBody(file, parent, payload, compressed);
+ }
+
+ private Reiser4FileBody ResolveBody(Reiser4PlanObject parent, long size) {
+ var body = this.FileBody;
+ if (body == Reiser4FileBody.Profile) {
+ if (this.Plugin(parent, Reiser4PsetMember.Create) == 4) return Reiser4FileBody.Compressed;
+ body = this.Plugin(parent, Reiser4PsetMember.Formatting) switch { 0 => Reiser4FileBody.Extents, 1 => Reiser4FileBody.Tails, _ => Reiser4FileBody.Smart };
+ }
+ if (body == Reiser4FileBody.Smart) body = size > 4 * Reiser4Volume.BlockSize ? Reiser4FileBody.Extents : Reiser4FileBody.Tails;
+ return body;
+ }
+
+ private void SetBody(Reiser4PlanObject file, Reiser4PlanObject parent, FilePayload payload, bool compressed) {
+ file.Items = [];
+ file.Extents = [];
+ var size = (ulong)payload.Size;
+ file.SetSize(size);
+ var key = file.StatKey;
+ Reiser4Key BodyKey(ulong offset) => Reiser4Key.Of(key.Locality, Reiser4Key.MinorBody, key.Ordering, key.ObjectId, offset);
+ if (compressed) {
+ var clusterId = this.Plugin(file, Reiser4PsetMember.Cluster);
+ if (clusterId > 4) throw new NotSupportedException($"Reiser4: cluster plugin {clusterId} is not supported.");
+ var shift = 16 - clusterId;
+ var clusterSize = 1 << shift;
+ var compression = (Reiser4CompressionId)this.Plugin(file, Reiser4PsetMember.Compression);
+ var mode = (Reiser4CompressionModeId)this.Plugin(file, Reiser4PsetMember.CompressionMode);
+ using var source = payload.Open();
+ var buffer = new byte[clusterSize];
+ ulong clusters = 0;
+ for (ulong start = 0; start < size; start += (ulong)clusterSize) {
+ var length = (int)Math.Min((ulong)clusterSize, size - start);
+ source.ReadExactly(buffer, 0, length);
+ var disk = Reiser4Clusters.Encode(buffer.AsSpan(0, length), compression, mode);
+ for (var at = 0; at < disk.Length;) {
+ var take = Math.Min(this.MaxItemBody - 1, disk.Length - at);
+ var item = new byte[take + 1];
+ item[0] = (byte)shift;
+ disk.AsSpan(at, take).CopyTo(item.AsSpan(1));
+ file.Items.Add((BodyKey(start + (ulong)at), Reiser4ItemPlugin.CompressedTail, item));
+ at += take;
+ }
+ ++clusters;
+ }
+ file.SetBytes(clusters * (ulong)clusterSize);
+ return;
+ }
+ var body = this.ResolveBody(parent, payload.Size);
+ if (body == Reiser4FileBody.Tails) {
+ using var source = payload.Open();
+ for (ulong at = 0; at < size;) {
+ var take = (int)Math.Min((ulong)this.MaxItemBody, size - at);
+ var chunk = new byte[take];
+ source.ReadExactly(chunk);
+ file.Items.Add((BodyKey(at), Reiser4ItemPlugin.Tail, chunk));
+ at += (ulong)take;
+ }
+ file.SetBytes(size);
+ return;
+ }
+ var blocks = (size + Reiser4Volume.BlockSize - 1) / Reiser4Volume.BlockSize;
+ if (blocks > 0) file.Extents.Add(new Reiser4PlanUnit(blocks, payload));
+ file.SetBytes(blocks * Reiser4Volume.BlockSize);
+ }
+
+ /// Adds a symbolic link holding .
+ internal void AddSymlink(string path, string target, Reiser4Reader.FileMetadata? metadata = null) {
+ var bytes = Encoding.UTF8.GetBytes(target);
+ if (bytes.Length is 0 or > 4095 || Array.IndexOf(bytes, (byte)0) >= 0)
+ throw new NotSupportedException("Reiser4: a symlink target must be 1..4095 bytes without NUL.");
+ if (this.Find(path) is not null) throw new InvalidDataException($"Reiser4: '{Normalize(path)}' already exists.");
+ var (parent, name) = this.ParentOf(path);
+ this.Link(parent, name, this.NewStat(metadata, 0xA1FF, (ulong)bytes.Length, 0, bytes, null), metadata?.ObjectId ?? 0);
+ }
+
+ /// Adds a device node, FIFO or socket. is the kernel's (major << 20 | minor).
+ internal void AddSpecial(string path, ushort mode, ulong device, Reiser4Reader.FileMetadata? metadata = null) {
+ var kind = mode & Reiser4Stat.FileType;
+ if (kind is not (Reiser4Stat.CharDevice or Reiser4Stat.BlockDevice or Reiser4Stat.Fifo or Reiser4Stat.Socket))
+ throw new NotSupportedException("Reiser4: special files are character or block devices, FIFOs or sockets.");
+ if (kind is Reiser4Stat.Fifo or Reiser4Stat.Socket && device != 0)
+ throw new NotSupportedException("Reiser4: a FIFO or socket has no device number.");
+ if (this.Find(path) is not null) throw new InvalidDataException($"Reiser4: '{Normalize(path)}' already exists.");
+ var (parent, name) = this.ParentOf(path);
+ this.Link(parent, name, this.NewStat(metadata, mode, 0, device, null, null), metadata?.ObjectId ?? 0);
+ }
+
+ /// Adds a second name for an existing non-directory object.
+ internal void AddHardLink(string path, string existingPath) {
+ var target = this.Find(existingPath) ?? throw new FileNotFoundException("Reiser4: the link target was not found.", existingPath);
+ if (target.IsDirectory) throw new NotSupportedException("Reiser4: directories cannot be hard-linked.");
+ if (this.Find(path) is not null) throw new InvalidDataException($"Reiser4: '{Normalize(path)}' already exists.");
+ var (parent, name) = this.ParentOf(path);
+ var hash = (Reiser4HashId)this.Plugin(parent, Reiser4PsetMember.Hash);
+ var fibration = (Reiser4FibrationId)this.Plugin(parent, Reiser4PsetMember.Fibration);
+ var (ordering, objectId, offset, _) = MakeKey(name, hash, fibration);
+ if (parent.Entries.Any(e => e.Ordering == ordering && e.ObjectId == objectId && e.Offset == offset))
+ throw new NotSupportedException($"Reiser4: the name '{Reiser4Volume.DecodeName(name)}' would share its key with an existing entry.");
+ parent.Entries.Add(new Reiser4DirEntry(ordering, objectId, offset, name, target.StatKey));
+ this._paths = null;
+ }
+
+ /// Removes a name; a directory goes with everything beneath it, an object with its last name.
+ internal bool Remove(string path) {
+ var normalized = Normalize(path);
+ if (normalized.Length == 0 || !this.Paths.TryGetValue(normalized, out var hit)) return false;
+ hit.Parent.Entries.Remove(hit.Entry);
+ this._paths = null;
+ this.CollectUnreachable();
+ return true;
+ }
+
+ private void CollectUnreachable() {
+ var reached = new HashSet { this.Root.StatKey };
+ var stack = new Stack([this.Root]);
+ while (stack.Count > 0)
+ foreach (var entry in stack.Pop().Entries) {
+ if (entry.IsDot || entry.IsDotDot || !reached.Add(entry.Target)) continue;
+ if (this._objects.TryGetValue(entry.Target, out var target) && target.IsDirectory) stack.Push(target);
+ }
+ foreach (var key in this._objects.Keys.Where(k => !reached.Contains(k)).ToList()) this._objects.Remove(key);
+ }
+
+ /// Sets mode permission bits, owner and the three timestamps of an object.
+ internal void ApplyMetadata(Reiser4PlanObject obj, Reiser4Reader.FileMetadata metadata) {
+ var stat = obj.Stat;
+ var kind = obj.Mode & Reiser4Stat.FileType;
+ BinaryPrimitives.WriteUInt16LittleEndian(stat.AsSpan(2), (ushort)(kind | (metadata.Mode & 0x0FFF)));
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(16), metadata.UserId);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(20), metadata.GroupId);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(24), metadata.AccessedTime);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(28), metadata.ModifiedTime);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(32), metadata.ChangedTime);
+ }
+
+ ///
+ /// A stat data for a new object: the light-weight and Unix extensions, plus a symlink target or a
+ /// plugin set where the object needs one. A caller's raw stat data is carried instead when it
+ /// parses, with the fields this writer owns patched in.
+ ///
+ private byte[] NewStat(Reiser4Reader.FileMetadata? metadata, ushort mode, ulong size, ulong bytesOrDevice,
+ byte[]? symlink, Dictionary? pluginSet) {
+ var now = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+ byte[] stat;
+ if (metadata is { RawStatData.Length: >= 44 } carried && symlink is null && pluginSet is null) {
+ if (Reiser4Stat.Parse(carried.RawStatData, out var problem) is null) throw new NotSupportedException($"Reiser4: {problem}.");
+ stat = carried.RawStatData.ToArray();
+ } else {
+ var mask = (ushort)(0x3 | (symlink is null ? 0 : 0x8) | (pluginSet is null ? 0 : 0x10));
+ var length = 44 + (symlink is null ? 0 : symlink.Length + 1) + (pluginSet is null ? 0 : 2 + 4 * pluginSet.Count);
+ stat = new byte[length];
+ BinaryPrimitives.WriteUInt16LittleEndian(stat, mask);
+ var at = 44;
+ if (symlink is not null) { symlink.CopyTo(stat.AsSpan(at)); at += symlink.Length + 1; }
+ if (pluginSet is not null) {
+ BinaryPrimitives.WriteUInt16LittleEndian(stat.AsSpan(at), (ushort)pluginSet.Count);
+ var slot = at + 2;
+ foreach (var (member, id) in pluginSet.OrderBy(static p => p.Key)) {
+ BinaryPrimitives.WriteUInt16LittleEndian(stat.AsSpan(slot), member);
+ BinaryPrimitives.WriteUInt16LittleEndian(stat.AsSpan(slot + 2), id);
+ slot += 4;
+ }
+ }
+ }
+ var kind = mode & Reiser4Stat.FileType;
+ BinaryPrimitives.WriteUInt16LittleEndian(stat.AsSpan(2), (ushort)(kind | ((metadata?.Mode ?? mode) & 0x0FFF)));
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(4), 1);
+ BinaryPrimitives.WriteUInt64LittleEndian(stat.AsSpan(8), size);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(16), metadata?.UserId ?? 0);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(20), metadata?.GroupId ?? 0);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(24), metadata?.AccessedTime ?? now);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(28), metadata?.ModifiedTime ?? now);
+ BinaryPrimitives.WriteUInt32LittleEndian(stat.AsSpan(32), metadata?.ChangedTime ?? now);
+ BinaryPrimitives.WriteUInt64LittleEndian(stat.AsSpan(36), bytesOrDevice);
+ return stat;
+ }
+
+ // ── Finishing ──────────────────────────────────────────────────────────
+
+ /// Recomputes what the namespace implies: link counts, directory sizes and directory bytes.
+ internal void Finish() {
+ var names = new Dictionary();
+ var subdirectories = new Dictionary();
+ foreach (var directory in this._objects.Values.Where(static o => o.IsDirectory))
+ foreach (var entry in directory.Entries) {
+ if (entry.IsDot || entry.IsDotDot) continue;
+ names[entry.Target] = names.GetValueOrDefault(entry.Target) + 1;
+ if (this._objects.TryGetValue(entry.Target, out var target) && target.IsDirectory)
+ subdirectories[directory.StatKey] = subdirectories.GetValueOrDefault(directory.StatKey) + 1;
+ }
+ foreach (var obj in this._objects.Values) {
+ if (obj.IsDirectory) {
+ var isRoot = obj.StatKey == Reiser4Volume.RootStatKey;
+ obj.SetLinks((isRoot ? 3U : 2U) + subdirectories.GetValueOrDefault(obj.StatKey));
+ obj.SetSize((ulong)obj.Entries.Count);
+ obj.SetBytes(Reiser4Tree.DirectoryBytes(obj.Entries));
+ } else {
+ obj.SetLinks(names.GetValueOrDefault(obj.StatKey));
+ }
+ }
+ }
+
+ internal Reiser4Tree.Result Write(Stream output) {
+ this.Finish();
+ return Reiser4Tree.Write(this, output);
+ }
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Reader.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Reader.cs
index 7cf8b8105..3bab1a603 100644
--- a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Reader.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Reader.cs
@@ -6,32 +6,22 @@
namespace FileSystem.Reiser4;
///
-/// Reads a Reiser4 image: the master superblock's label, UUID and block size,
-/// plus regular files represented by the native stat40/cde40/extent40 items
-/// emitted by . The older workbench payload directory
-/// remains a compatibility fallback for images written before native tree items
-/// became authoritative.
+/// Reads a Reiser4 image: the master superblock's label, UUID and block size, and every object of
+/// the node40/node41 tree after the journal is replayed — directories, regular files whose bodies
+/// are extents, tails or compressed clusters (holes included), symbolic links, device nodes, FIFOs,
+/// sockets and hard links. The older workbench payload directory remains a compatibility fallback
+/// for images written before native tree items became authoritative.
///
public sealed class Reiser4Reader : IDisposable {
/// Byte offset of the master superblock: block 16 at a 4 KB block size.
public const long MasterOffset = 65536;
- private const int ItemHeaderBytes = 38;
- private const int DirectoryUnitHeaderBytes = 26;
- private const int TargetKeyBytes = 24;
- private const ushort PluginStat40 = 0;
- private const ushort PluginCde40 = 2;
- private const ushort PluginExtent40 = 5;
- private const byte MinorStatData = 1;
- private const byte MinorFileBody = 4;
- private const ulong HashedNameBit = 0x0100000000000000;
-
private static readonly byte[] MasterMagic = "ReIsEr4"u8.ToArray();
private readonly ImageAccessor _image;
+ private readonly Reiser4Volume? _volume;
private readonly List _entries = [];
- private readonly HashSet _nativeNames = new(StringComparer.Ordinal);
/// True when the image carries a valid Reiser4 master superblock.
public bool Valid { get; }
@@ -45,56 +35,48 @@ public sealed class Reiser4Reader : IDisposable {
/// Volume UUID from the master superblock, as hex.
public string UuidHex { get; } = "";
- /// Files and directories found in the native tree, or files in the legacy payload directory.
+ /// Files, directories, links and special files found in the native tree, or files in the legacy payload directory.
public IReadOnlyList Entries => this._entries;
/// Total size of the backing image in bytes.
public long Length => this._image.Length;
- ///
- /// Initializes a new instance of .
- ///
- public Reiser4Reader(Stream stream, bool leaveOpen = true) {
- ArgumentNullException.ThrowIfNull(stream);
- if (stream.CanSeek) stream.Position = 0;
- this._image = new ImageAccessor(stream, leaveOpen);
- if (this._image.Length < MasterOffset + Reiser4Writer.BlockSize) return;
-
- var master = this._image.Read(MasterOffset, Reiser4Writer.BlockSize);
- if (!master.AsSpan(0, MasterMagic.Length).SequenceEqual(MasterMagic)) return;
- this.Valid = true;
-
- var blockSize = BinaryPrimitives.ReadUInt16LittleEndian(master.AsSpan(18, 2));
- if (blockSize is >= 512 and <= 8192) this.BlockSize = blockSize;
- this.UuidHex = Convert.ToHexString(master.AsSpan(20, 16));
- this.Label = ReadCString(master.AsSpan(36, 16));
-
- // Native metadata is authoritative. The private payload directory is kept
- // only so old workbench images remain readable while they are migrated.
- if (this.TryReadNativeTree()) { this.NativeTreeValid = true; return; }
- this._entries.Clear();
- this._nativeNames.Clear();
- this.RootMetadata = null;
+ /// True when the complete native namespace was decoded.
+ public bool NativeTreeValid { get; }
- if (!master.AsSpan(Reiser4Writer.MasterPayloadMarkerOff, Reiser4Writer.PayloadMarker.Length)
- .SequenceEqual(Reiser4Writer.PayloadMarker))
- return;
+ /// Why the native tree was not decoded, when it was not.
+ public string? NativeProblem { get; }
- var dirBlock = BinaryPrimitives.ReadUInt64LittleEndian(
- master.AsSpan(Reiser4Writer.MasterPayloadDirOff, 8));
- this.ReadLegacyDirectory(dirBlock);
- }
-
- /// True when the complete supported native namespace was decoded.
- public bool NativeTreeValid { get; private set; }
+ /// Journal transactions replayed before the tree was read (0 when the journal was clean).
+ public int ReplayedTransactions { get; }
/// Root stat-data, including inherited plugin settings.
- public FileMetadata? RootMetadata { get; private set; }
+ public FileMetadata? RootMetadata { get; }
+
+ internal IReadOnlyList NativeNodeBlocks { get; } = [];
- internal IReadOnlyList NativeNodeBlocks { get; private set; } = [];
+ internal Reiser4Volume? Volume => this.NativeTreeValid ? this._volume : null;
internal readonly record struct NativeRun(ulong Start, ulong Width);
+ /// What kind of object an entry names.
+ public enum EntryKind {
+ /// A regular file.
+ File,
+ /// A directory.
+ Directory,
+ /// A symbolic link; holds its target.
+ Symlink,
+ /// A character device; holds its number.
+ CharacterDevice,
+ /// A block device; holds its number.
+ BlockDevice,
+ /// A named pipe.
+ Fifo,
+ /// A socket.
+ Socket,
+ }
+
/// Stat-data fields which can be represented by the current writer.
public sealed record FileMetadata(
long Size, ushort Mode, uint LinkCount, uint UserId, uint GroupId,
@@ -104,6 +86,8 @@ public sealed record FileMetadata(
public ulong ObjectId { get; init; }
/// Locality of the object stat key.
public ulong StatLocality { get; init; }
+ /// Ordering word of the object stat key (the kernel derives it from the object's first name).
+ public ulong StatOrdering { get; init; }
/// Last-write timestamp, when the seconds value is representable.
public DateTime? LastModified => ModifiedTime == 0
@@ -114,12 +98,120 @@ public sealed record FileMetadata(
/// One filesystem object and its physical extents.
public sealed record Entry(string Name, ulong FirstBlock, long Size) {
internal IReadOnlyList? NativeRuns { get; init; }
+ internal Reiser4Object? Native { get; init; }
/// True when this entry is a directory.
public bool IsDirectory { get; init; }
+ /// What kind of object this entry names.
+ public EntryKind Kind { get; init; }
+ /// The target of a symbolic link.
+ public string? LinkTarget { get; init; }
+ /// The device number of a device node, as the kernel encodes it (major << 20 | minor).
+ public ulong Device { get; init; }
+ /// The path this entry is a further name of, when the object has more than one name.
+ public string? HardLinkOf { get; init; }
+ /// How the body of a regular file is stored: "extent", "tail", "ctail" or "" for none.
+ public string Body { get; init; } = "";
/// On-disk stat-data fields retained for metadata-preserving rebuilds.
public FileMetadata? Metadata { get; init; }
}
+ /// Initializes a new instance of .
+ public Reiser4Reader(Stream stream, bool leaveOpen = true) {
+ ArgumentNullException.ThrowIfNull(stream);
+ if (stream.CanSeek) stream.Position = 0;
+ this._image = new ImageAccessor(stream, leaveOpen: true);
+ this._leaveOpen = leaveOpen;
+ this._stream = stream;
+ if (this._image.Length < MasterOffset + Reiser4Writer.BlockSize) return;
+
+ var master = this._image.Read(MasterOffset, Reiser4Writer.BlockSize);
+ if (!master.AsSpan(0, MasterMagic.Length).SequenceEqual(MasterMagic)) return;
+ this.Valid = true;
+
+ var blockSize = BinaryPrimitives.ReadUInt16LittleEndian(master.AsSpan(18, 2));
+ if (blockSize is >= 512 and <= 8192) this.BlockSize = blockSize;
+ this.UuidHex = Convert.ToHexString(master.AsSpan(20, 16));
+ this.Label = ReadCString(master.AsSpan(36, 16));
+
+ // Native metadata is authoritative. The private payload directory is kept
+ // only so old workbench images remain readable while they are migrated.
+ this._volume = new Reiser4Volume(stream, leaveOpen: true);
+ if (this._volume.TreeValid) {
+ this.NativeTreeValid = true;
+ this.ReplayedTransactions = this._volume.ReplayedTransactions;
+ this.NativeNodeBlocks = [.. this._volume.NodeBlocks];
+ this.RootMetadata = ToMetadata(this._volume.Root!);
+ this.BuildEntries(this._volume);
+ return;
+ }
+ this.NativeProblem = this._volume.Problem;
+
+ if (!master.AsSpan(Reiser4Writer.MasterPayloadMarkerOff, Reiser4Writer.PayloadMarker.Length)
+ .SequenceEqual(Reiser4Writer.PayloadMarker))
+ return;
+
+ var dirBlock = BinaryPrimitives.ReadUInt64LittleEndian(
+ master.AsSpan(Reiser4Writer.MasterPayloadDirOff, 8));
+ this.ReadLegacyDirectory(dirBlock);
+ }
+
+ private readonly bool _leaveOpen;
+ private readonly Stream _stream;
+
+ private void BuildEntries(Reiser4Volume volume) {
+ var firstName = new Dictionary();
+ foreach (var (path, _, obj, _) in volume.Paths) {
+ var metadata = ToMetadata(obj);
+ var stat = obj.Stat;
+ string? linkOf = null;
+ if (!obj.IsDirectory) {
+ if (firstName.TryGetValue(obj.StatKey, out var first)) linkOf = first;
+ else firstName[obj.StatKey] = path;
+ }
+ var kind = stat.Kind switch {
+ Reiser4Stat.Directory => EntryKind.Directory,
+ Reiser4Stat.Symlink => EntryKind.Symlink,
+ Reiser4Stat.CharDevice => EntryKind.CharacterDevice,
+ Reiser4Stat.BlockDevice => EntryKind.BlockDevice,
+ Reiser4Stat.Fifo => EntryKind.Fifo,
+ Reiser4Stat.Socket => EntryKind.Socket,
+ _ => EntryKind.File,
+ };
+ if (kind == EntryKind.Directory) {
+ this._entries.Add(new Entry(path, 0, 0) { IsDirectory = true, Kind = kind, Metadata = metadata, Native = obj });
+ continue;
+ }
+ if (kind != EntryKind.File) {
+ this._entries.Add(new Entry(path, 0, 0) {
+ Kind = kind, Metadata = metadata, Native = obj, HardLinkOf = linkOf,
+ LinkTarget = stat.SymlinkTarget is { } target ? Reiser4Volume.DecodeName(target) : null,
+ Device = kind is EntryKind.CharacterDevice or EntryKind.BlockDevice ? stat.BytesOrDevice : 0,
+ });
+ continue;
+ }
+ var body = obj.Body.Count == 0 ? "" : obj.Body[0].Plugin switch {
+ Reiser4ItemPlugin.Extent => "extent",
+ Reiser4ItemPlugin.Tail => "tail",
+ _ => "ctail",
+ };
+ var runs = body == "extent"
+ ? volume.ExtentUnits(obj).Where(static u => u.Start != 0).Select(static u => new NativeRun(u.Start, u.Width)).ToArray()
+ : [];
+ this._entries.Add(new Entry(path, runs.Length == 0 ? 0 : runs[0].Start, (long)stat.Size) {
+ Kind = kind, Metadata = metadata, Native = obj, HardLinkOf = linkOf, Body = body,
+ NativeRuns = runs,
+ });
+ }
+ }
+
+ private static FileMetadata ToMetadata(Reiser4Object obj) {
+ var stat = obj.Stat;
+ return new FileMetadata(checked((long)stat.Size), stat.Mode, stat.Links, stat.UserId, stat.GroupId,
+ stat.ModifyTime, stat.AccessTime, stat.ChangeTime, stat.Raw.ToArray()) {
+ ObjectId = obj.ObjectId, StatLocality = obj.StatKey.Locality, StatOrdering = obj.StatKey.Ordering,
+ };
+ }
+
/// Reads a file's contents. Only valid below the array limit.
public byte[] Extract(Entry entry) {
ArgumentNullException.ThrowIfNull(entry);
@@ -135,11 +227,11 @@ public byte[] Extract(Entry entry) {
public long ExtractTo(Entry entry, Stream destination) {
ArgumentNullException.ThrowIfNull(entry);
ArgumentNullException.ThrowIfNull(destination);
- if (entry.IsDirectory) return 0;
+ if (entry.IsDirectory || entry.Kind != EntryKind.File) return 0;
if (entry.Size <= 0) return 0;
- if (entry.NativeRuns is { } runs)
- return this.ExtractNative(runs, entry.Size, destination);
+ if (entry.Native is { } native && this._volume is { } volume)
+ return volume.ExtractTo(native, destination);
var blocksPerBitmap = Reiser4Writer.BlocksPerBitmap;
var block = entry.FirstBlock;
@@ -158,38 +250,13 @@ public long ExtractTo(Entry entry, Stream destination) {
return written;
}
- private long ExtractNative(IReadOnlyList runs, long size, Stream destination) {
- long written = 0;
- foreach (var run in runs) {
- if (written >= size || run.Width == 0) break;
- var offset = checked((long)run.Start * this.BlockSize);
- if (offset < 0 || offset >= this._image.Length) break;
- var runBytes = checked((long)Math.Min(run.Width, (ulong)(long.MaxValue / this.BlockSize)) * this.BlockSize);
- var take = Math.Min(Math.Min(runBytes, size - written), this._image.Length - offset);
- if (take <= 0) break;
- this._image.CopyTo(offset, destination, take);
- written += take;
- }
- return written;
- }
-
- /// Where an entry's bytes live as physical byte runs.
+ /// Where an entry's bytes live as physical byte runs (extent data only; tails and clusters live in tree nodes).
public IEnumerable<(long Offset, long Length)> EnumerateRuns(Entry entry) {
ArgumentNullException.ThrowIfNull(entry);
if (entry.Size <= 0) yield break;
- if (entry.NativeRuns is { } nativeRuns) {
- long remaining = entry.Size;
- foreach (var run in nativeRuns) {
- if (remaining <= 0 || run.Width == 0) yield break;
- var offset = checked((long)run.Start * this.BlockSize);
- if (offset < 0 || offset >= this._image.Length) yield break;
- var capacity = checked((long)Math.Min(run.Width, (ulong)(long.MaxValue / this.BlockSize)) * this.BlockSize);
- var length = Math.Min(Math.Min(capacity, remaining), this._image.Length - offset);
- if (length <= 0) yield break;
- yield return (offset, length);
- remaining -= length;
- }
+ if (entry.Native is { } native && this._volume is { } volume) {
+ foreach (var run in volume.DataRuns(native)) yield return run;
yield break;
}
@@ -215,247 +282,6 @@ private long ExtractNative(IReadOnlyList runs, long size, Stream dest
}
}
- ///
- /// Walks formatted node40 internal pointers from the format40 root, collects
- /// standard leaf1 items, then resolves cde40 names against stat40 keys. Unknown
- /// node and item plugins fail closed so the legacy compatibility path remains
- /// available for images carrying it.
- ///
- private bool TryReadNativeTree() {
- if (this.BlockSize != Reiser4Writer.BlockSize) return false;
- var format = this._image.Read((long)17 * this.BlockSize, this.BlockSize);
- if (format.Length != this.BlockSize || !format.AsSpan(52, Reiser4MasterSb.Format40Magic.Length)
- .SequenceEqual(Reiser4MasterSb.Format40Magic)) return false;
- var root = BinaryPrimitives.ReadUInt64LittleEndian(format.AsSpan(16, 8));
- if (root == 0) return false;
-
- var leafBlocks = new List<(ulong Block, byte[] Data)>();
- var nodeBlocks = new HashSet();
- if (!this.WalkNativeNodes(root, nodeBlocks, leafBlocks, 0) || leafBlocks.Count == 0)
- return false;
-
- var statData = new Dictionary<(ulong Locality, ulong ObjectId), FileMetadata>();
- var extents = new Dictionary<(ulong Locality, ulong ObjectId), List<(ulong Offset, List Runs)>>();
- var directories = new Dictionary>();
- foreach (var (_, leaf) in leafBlocks) {
- if (!TryReadLeafItems(leaf, out var leafItems, out var bodiesEnd)) return false;
- var byBody = leafItems.OrderBy(static item => item.BodyOffset).ToArray();
- for (var i = 0; i < byBody.Length; ++i) {
- var item = byBody[i];
- var end = i + 1 < byBody.Length ? byBody[i + 1].BodyOffset : bodiesEnd;
- if (end < item.BodyOffset) return false;
- var body = leaf.AsSpan(item.BodyOffset, end - item.BodyOffset);
- var objectKey = (item.Locality, item.ObjectId);
- switch (item.Plugin) {
- case PluginStat40 when item.Minor == MinorStatData && item.Ordering == 0 && item.KeyOffset == 0:
- if (body.Length < 44 || (BinaryPrimitives.ReadUInt16LittleEndian(body) & 3) != 3) return false;
- var size = BinaryPrimitives.ReadUInt64LittleEndian(body.Slice(8, 8));
- if (size > long.MaxValue) return false;
- if (statData.ContainsKey(objectKey)) return false;
- statData[objectKey] = new FileMetadata((long)size,
- BinaryPrimitives.ReadUInt16LittleEndian(body.Slice(2, 2)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(4, 4)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(16, 4)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(20, 4)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(24, 4)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(28, 4)),
- BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(32, 4)), body.ToArray()) {
- ObjectId = item.ObjectId, StatLocality = item.Locality,
- };
- break;
- case PluginExtent40 when item.Minor == MinorFileBody && item.Ordering == 0:
- if ((body.Length & 15) != 0) return false;
- var runs = new List(body.Length / 16);
- for (var p = 0; p < body.Length; p += 16) {
- var start = BinaryPrimitives.ReadUInt64LittleEndian(body.Slice(p, 8));
- var width = BinaryPrimitives.ReadUInt64LittleEndian(body.Slice(p + 8, 8));
- if (width != 0) runs.Add(new NativeRun(start, width));
- }
- if (!extents.TryGetValue(objectKey, out var pieces)) extents[objectKey] = pieces = [];
- pieces.Add((item.KeyOffset, runs));
- break;
- case PluginCde40 when item.Minor == 0:
- if (!directories.TryGetValue(item.Locality, out var items)) directories[item.Locality] = items = [];
- items.Add(body.ToArray());
- break;
- case PluginNodePointer when leaf[26] == 2:
- if (body.Length != 8) return false;
- break;
- default: return false;
- }
- }
- }
-
- foreach (var parts in extents.Values) {
- ulong logical = 0;
- foreach (var part in parts.OrderBy(static p => p.Offset)) {
- if (part.Offset != logical) return false;
- foreach (var run in part.Runs) {
- if (run.Start < 25 || nodeBlocks.Any(node => node >= run.Start && node - run.Start < run.Width) || run.Start >= (ulong)(this.Length / this.BlockSize) ||
- run.Width > (ulong)(this.Length / this.BlockSize) - run.Start ||
- run.Width > (ulong)long.MaxValue / (ulong)this.BlockSize - logical / (ulong)this.BlockSize) return false;
- logical += run.Width * (ulong)this.BlockSize;
- }
- }
- }
- var joinedExtents = extents.ToDictionary(static pair => pair.Key,
- static pair => (IReadOnlyList)pair.Value.OrderBy(static part => part.Offset)
- .SelectMany(static part => part.Runs).ToArray());
- var visited = new HashSet();
- if (!WalkNativeDirectory(0x2a, "", statData, joinedExtents, directories, visited))
- return false;
- if (!statData.TryGetValue((0x29, 0x2a), out var rootMetadata) || (rootMetadata.Mode & 0xF000) != 0x4000)
- return false;
- if (statData.Count != this._entries.Count + 1 || directories.Keys.Any(key => !visited.Contains(key)) ||
- extents.Keys.Any(key => !statData.TryGetValue(key, out var metadata) || (metadata.Mode & 0xF000) != 0x8000))
- return false;
- this.RootMetadata = rootMetadata;
- this.NativeNodeBlocks = nodeBlocks.ToArray();
- return true;
- }
-
- private const ushort PluginNodePointer = 3;
-
- private readonly record struct NativeItem(
- ulong Locality, byte Minor, ulong Ordering, ulong ObjectId, ulong KeyOffset, ushort Plugin, ushort BodyOffset);
-
- private bool WalkNativeNodes(ulong block, HashSet visited,
- List<(ulong Block, byte[] Data)> leaves, int depth, int expectedLevel = 0) {
- if (depth > 16 || block >= (ulong)(this._image.Length / this.BlockSize) || !visited.Add(block)) return false;
- var node = this._image.Read(checked((long)block * this.BlockSize), this.BlockSize);
- if (node.Length != this.BlockSize || BinaryPrimitives.ReadUInt16LittleEndian(node) != 0
- || BinaryPrimitives.ReadUInt32LittleEndian(node.AsSpan(8, 4)) != unchecked((uint)Reiser4Tree.NodeMagic))
- return false;
- var level = node[26];
- if (expectedLevel != 0 && level != expectedLevel) return false;
- var count = BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(2, 2));
- if (count > (this.BlockSize - Reiser4Tree.NodeHeaderBytes) / ItemHeaderBytes) return false;
- if (level == 1) {
- leaves.Add((block, node));
- return true;
- }
- if (level < 2 || count == 0) return false;
-
- if (!TryReadLeafItems(node, out var items, out var bodiesEnd)) return false;
- if (level == 2) leaves.Add((block, node));
- var children = new List(count);
- var byBody = items.OrderBy(static item => item.BodyOffset).ToArray();
- for (var i = 0; i < byBody.Length; ++i) {
- var item = byBody[i];
- var end = i + 1 < byBody.Length ? byBody[i + 1].BodyOffset : bodiesEnd;
- if (item.Plugin == PluginExtent40 && level == 2) continue;
- if (item.Plugin != PluginNodePointer || end - item.BodyOffset != sizeof(ulong)) return false;
- children.Add(BinaryPrimitives.ReadUInt64LittleEndian(node.AsSpan(item.BodyOffset, sizeof(ulong))));
- }
- foreach (var child in children)
- if (!this.WalkNativeNodes(child, visited, leaves, depth + 1, level - 1)) return false;
- return true;
- }
-
- private bool TryReadLeafItems(byte[] leaf, out List items, out int bodiesEnd) {
- items = [];
- var count = BinaryPrimitives.ReadUInt16LittleEndian(leaf.AsSpan(2, 2));
- bodiesEnd = BinaryPrimitives.ReadUInt16LittleEndian(leaf.AsSpan(6, 2));
- if (count == 0 || count > (this.BlockSize - Reiser4Tree.NodeHeaderBytes) / ItemHeaderBytes
- || bodiesEnd < Reiser4Tree.NodeHeaderBytes || bodiesEnd > this.BlockSize - count * ItemHeaderBytes)
- return false;
- for (var i = 0; i < count; ++i) {
- var header = this.BlockSize - (i + 1) * ItemHeaderBytes;
- var key0 = BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header, 8));
- var bodyOffset = BinaryPrimitives.ReadUInt16LittleEndian(leaf.AsSpan(header + 32, 2));
- var plugin = BinaryPrimitives.ReadUInt16LittleEndian(leaf.AsSpan(header + 36, 2));
- if (bodyOffset < Reiser4Tree.NodeHeaderBytes || bodyOffset > bodiesEnd) return false;
- items.Add(new NativeItem(key0 >> 4, (byte)(key0 & 0xf),
- BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header + 8, 8)),
- BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header + 16, 8)),
- BinaryPrimitives.ReadUInt64LittleEndian(leaf.AsSpan(header + 24, 8)), plugin, bodyOffset));
- }
- return true;
- }
-
- private bool WalkNativeDirectory(ulong directoryId, string path,
- IReadOnlyDictionary<(ulong Locality, ulong ObjectId), FileMetadata> statData,
- IReadOnlyDictionary<(ulong Locality, ulong ObjectId), IReadOnlyList> extents,
- IReadOnlyDictionary> directories, HashSet visited) {
- if (path.Count(static c => c == '/') > 128 || !visited.Add(directoryId)) return false;
- if (!directories.TryGetValue(directoryId, out var directoryItems)) return false;
-
- foreach (var directory in directoryItems) {
- if (directory.Length < 2) return false;
- var count = BinaryPrimitives.ReadUInt16LittleEndian(directory);
- var unitsStart = 2 + count * DirectoryUnitHeaderBytes;
- if (unitsStart > directory.Length) return false;
-
- for (var i = 0; i < count; ++i) {
- var header = 2 + i * DirectoryUnitHeaderBytes;
- var ordering = BinaryPrimitives.ReadUInt64LittleEndian(directory.AsSpan(header, 8));
- var objectIdPart = BinaryPrimitives.ReadUInt64LittleEndian(directory.AsSpan(header + 8, 8));
- var offsetPart = BinaryPrimitives.ReadUInt64LittleEndian(directory.AsSpan(header + 16, 8));
- var unit = BinaryPrimitives.ReadUInt16LittleEndian(directory.AsSpan(header + 24, 2));
- var unitEnd = i + 1 < count
- ? BinaryPrimitives.ReadUInt16LittleEndian(directory.AsSpan(header + DirectoryUnitHeaderBytes + 24, 2))
- : directory.Length;
- if (unit < unitsStart || unitEnd < unit || unitEnd > directory.Length || unit + TargetKeyBytes > unitEnd)
- return false;
-
- var name = DecodeName(directory.AsSpan(unit, unitEnd - unit), ordering, objectIdPart, offsetPart);
- if (name.Length == 0 || name is "." or "..") continue;
- if (name.Contains('/') || name.Contains('\\') || name.Contains('\0') || name.Contains(':') || name.Any(static c => c > 127)) return false;
- var targetLocality = BinaryPrimitives.ReadUInt64LittleEndian(directory.AsSpan(unit, 8)) >> 4;
- var targetObjectId = BinaryPrimitives.ReadUInt64LittleEndian(directory.AsSpan(unit + 16, 8));
- if (!statData.TryGetValue((targetLocality, targetObjectId), out var metadata)) return false;
-
- var fullName = string.IsNullOrEmpty(path) ? name : $"{path}/{name}";
- if (!this._nativeNames.Add(fullName)) return false;
- var modeType = metadata.Mode & 0xF000;
- if (modeType == 0x4000) {
- this._entries.Add(new Entry(fullName, 0, 0) { IsDirectory = true, Metadata = metadata });
- if (!this.WalkNativeDirectory(targetObjectId, fullName, statData, extents, directories, visited))
- return false;
- continue;
- }
-
- if (modeType != 0x8000) return false;
- extents.TryGetValue((targetLocality, targetObjectId), out var runs);
- runs ??= Array.Empty();
- if (runs.Aggregate(0UL, static (sum, run) => sum + run.Width) * (ulong)this.BlockSize < (ulong)metadata.Size) return false;
- this._entries.Add(new Entry(fullName, runs.Count == 0 ? 0 : runs[0].Start, metadata.Size) {
- NativeRuns = runs,
- Metadata = metadata,
- });
- }
- }
- return true;
- }
-
- private static string DecodeName(
- ReadOnlySpan unit, ulong ordering, ulong objectId, ulong offset) {
- if (ordering == 0 && objectId == 0 && offset == 0) return ".";
- if ((ordering & HashedNameBit) != 0) {
- var stored = unit[TargetKeyBytes..];
- var nul = stored.IndexOf((byte)0);
- if (nul >= 0) stored = stored[..nul];
- return Encoding.Latin1.GetString(stored);
- }
-
- Span name = stackalloc byte[23];
- var length = 0;
- length += Unpack(name[length..], ordering & 0x00FF_FFFF_FFFF_FFFFUL, 7);
- length += Unpack(name[length..], objectId, 8);
- length += Unpack(name[length..], offset, 8);
- return Encoding.Latin1.GetString(name[..length]);
- }
-
- private static int Unpack(Span destination, ulong value, int bytes) {
- var written = 0;
- for (var shift = (bytes - 1) * 8; shift >= 0; shift -= 8) {
- var b = (byte)(value >> shift);
- if (b == 0) break;
- destination[written++] = b;
- }
- return written;
- }
-
private void ReadLegacyDirectory(ulong firstBlock) {
var visited = new HashSet();
var block = firstBlock;
@@ -491,5 +317,9 @@ private static string ReadCString(ReadOnlySpan span) {
}
/// Releases resources held by this instance.
- public void Dispose() => this._image.Dispose();
+ public void Dispose() {
+ this._volume?.Dispose();
+ this._image.Dispose();
+ if (!this._leaveOpen) this._stream.Dispose();
+ }
}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Tree.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Tree.cs
index 3c68a540b..a2f5abb10 100644
--- a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Tree.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Tree.cs
@@ -1,29 +1,22 @@
#pragma warning disable CS1591
using System.Buffers.Binary;
-using System.Text;
+using Compression.Core.Checksums;
+using Compression.Core.DiskImage;
namespace FileSystem.Reiser4;
///
-/// Builds a reiser4 node40 tree containing directory stat data and entries,
-/// plus stat data and extents for regular files.
+/// Lays a out as a volume: data blocks for extents, then a node40 (or
+/// node41) tree of stat data, directory entries and tail items in leaves, extents in twigs, and as
+/// many internal levels above them as it takes — plus the allocator bitmaps and the counters the
+/// format superblock keeps.
///
///
-/// A node is a 28-byte header, item bodies growing up from there, and an
-/// array of 38-byte item headers growing down from the node's end — each a
-/// four-word key, the body's offset, flags, and which plugin reads it. Items sit
-/// in key order.
-///
-/// A key is four little-endian words: the locality in the top sixty bits of
-/// the first with the item's type in its low four, an ordering, an object id, and
-/// an offset. A file's stat data and its body share the first three and differ in
-/// the type and the offset, so every stat data sorts ahead of every body.
-///
-/// A directory entry carries its name in its own key rather than a hash of
-/// it, for any name of twenty-three characters or fewer. The bytes pack
-/// big-endian into the ordering starting one byte in, then the object id, then the
-/// offset; the ordering's top seven bits hold a fibre, which is the last character
-/// when the one before it is a dot. A name held that way is stored nowhere else.
+/// A node is a 28-byte header (32 for node41, whose last four bytes are a CRC-32C of the
+/// rest), item bodies growing up from there, and an array of 38-byte item headers growing down
+/// from the node's end — each a four-word key, the body's offset, flags, and the item plugin.
+/// Items sit in key order. A leaf never straddles a twig extent: the leaf run is ended before an
+/// extent's key and resumed after it.
///
internal static class Reiser4Tree {
@@ -31,216 +24,196 @@ internal static class Reiser4Tree {
internal const int ItemHeaderBytes = 38;
internal const int NodeMagic = 0x52344653;
- private const int PluginStat40 = 0x0;
- private const int PluginCde40 = 0x2;
- private const int PluginExtent40 = 0x5;
+ /// First data block: blocks 0..24 are the jump area, superblocks, journal, status, backup and the first two nodes.
+ internal const ulong FirstDataBlock = 25;
- private const byte MinorFileName = 0;
- private const byte MinorStatData = 1;
- private const byte MinorFileBody = 4;
+ internal const ulong BlocksPerBitmap = (ulong)(Reiser4Volume.BlockSize - 4) * 8;
- /// Characters of a name the ordering holds, its top byte being the fibre.
- private const int OrderingChars = 7;
+ internal static bool IsBitmapBlock(ulong block) => block == 18 || block != 0 && block % BlocksPerBitmap == 0;
- /// And the object id after it.
- private const int ObjectIdChars = 8;
+ private sealed record Item(Reiser4Key Key, ushort Plugin, byte[] Body);
- /// Past this many a name no longer fits its key and is hashed into it.
- internal const int MaxInlineNameLength = OrderingChars + ObjectIdChars + 8;
+ /// What a laid-out volume amounts to.
+ internal sealed record Result(ulong Blocks, ushort Height, ulong ObjectCount, IReadOnlyList NodeBlocks);
- /// The bit in the ordering that says the name was hashed, not held.
- private const ulong HashedNameBit = 0x0100000000000000;
+ /// Lays out and writes the whole volume to .
+ internal static Result Write(Reiser4Plan plan, Stream output) {
+ ArgumentNullException.ThrowIfNull(plan);
+ ArgumentNullException.ThrowIfNull(output);
+ const int blockSize = Reiser4Volume.BlockSize;
+ var headerBytes = plan.NodePlugin == 1 ? 32 : NodeHeaderBytes;
+ var capacity = blockSize - headerBytes;
+ var maxBody = capacity - ItemHeaderBytes;
- /// One run of blocks holding part of a file.
- internal readonly record struct Run(ulong Start, ulong Width);
-
- /// A file to put in the tree.
- internal sealed record Entry {
- internal required string Name { get; init; }
- internal required ulong ParentObjectId { get; init; }
- internal required ulong ObjectId { get; init; }
- internal required long Size { get; init; }
- internal required IReadOnlyList Runs { get; init; }
- internal Reiser4Reader.FileMetadata? Metadata { get; init; }
- }
-
- private sealed record Item(ulong Locality, byte Minor, ulong Ordering, ulong ObjectId, ulong Offset,
- int Plugin, byte[] Body);
-
- internal sealed record Layout(ulong NextObjectId, ulong ObjectCount, byte Height, IReadOnlyDictionary Nodes);
-
- private sealed class DirectoryNode {
- internal required string Path { get; init; }
- internal required string Name { get; init; }
- internal required ulong ObjectId { get; init; }
- internal required ulong ParentObjectId { get; init; }
- internal required ulong StatLocality { get; init; }
- internal required ulong ParentStatLocality { get; init; }
- internal List<(string Name, ulong ObjectId)> Children { get; } = [];
- }
-
- /// The name packed into a word, big-endian, from .
- private static ulong PackName(string name, int from, int skip) {
- ulong value = 0;
- var taken = 0;
- for (var i = from; i < name.Length && taken < 8 - skip; ++i, ++taken)
- value = value << 8 | (byte)name[i];
-
- return value << (8 - taken - skip) * 8;
- }
-
- /// The fibre a name sorts under: its last character after a one-letter suffix.
- private static byte Fibre(string name)
- => name.Length > 2 && name[^2] == '.' ? (byte)name[^1] : (byte)0;
-
- private static void WriteKey(Span at, ulong locality, byte minor,
- ulong ordering, ulong objectId, ulong offset) {
- BinaryPrimitives.WriteUInt64LittleEndian(at, locality << 4 | minor);
- BinaryPrimitives.WriteUInt64LittleEndian(at[8..], ordering);
- BinaryPrimitives.WriteUInt64LittleEndian(at[16..], objectId);
- BinaryPrimitives.WriteUInt64LittleEndian(at[24..], offset);
- }
-
- ///
- /// The r5 hash, which a name too long to be held in its key is reduced to.
- ///
- private static ulong R5Hash(string name, int from) {
- ulong a = 0;
- for (var i = from; i < name.Length; ++i) {
- var b = (byte)name[i];
- a += (ulong)(b << 4);
- a += (ulong)(b >> 4);
- a *= 11;
+ var cursor = FirstDataBlock;
+ ulong Allocate() {
+ while (IsBitmapBlock(cursor)) ++cursor;
+ return cursor++;
}
- return a;
- }
-
- /// The three words a directory entry's key carries a name in.
- ///
- /// A name of twenty-three characters or fewer fits whole; past that only its
- /// first fifteen are held and the rest becomes a hash, with a bit set in the
- /// ordering to say so — and the name itself is then stored beside the entry.
- ///
- private static (ulong Ordering, ulong ObjectId, ulong Offset, bool Hashed) NameKey(string name) {
- if (name == ".") return (0, 0, 0, false);
-
- var ordering = PackName(name, 0, 1);
- var objectId = name.Length > OrderingChars ? PackName(name, OrderingChars, 0) : 0;
-
- ulong offset;
- var hashed = name.Length > MaxInlineNameLength;
- if (hashed) {
- ordering |= HashedNameBit;
- offset = R5Hash(name, OrderingChars + ObjectIdChars);
- } else {
- offset = name.Length > OrderingChars + ObjectIdChars
- ? PackName(name, OrderingChars + ObjectIdChars, 0)
- : 0;
+ // ── Data blocks, in object order ────────────────────────────────────
+ var payloads = new DeferredPayloads();
+ var items = new List- ();
+ foreach (var obj in plan.Objects) {
+ items.Add(new Item(obj.StatKey, Reiser4ItemPlugin.StatData, obj.Stat));
+ if (obj.IsDirectory) {
+ items.AddRange(DirectoryItems(obj, maxBody));
+ continue;
+ }
+ foreach (var (key, plugin, body) in obj.Items) {
+ if (body.Length > maxBody) throw new InvalidDataException("Reiser4: a body item exceeds node capacity.");
+ items.Add(new Item(key, plugin, body));
+ }
+ if (obj.Extents.Count == 0) continue;
+
+ var units = new List<(ulong Start, ulong Width)>();
+ foreach (var unit in obj.Extents) {
+ if (unit.Payload is not { } payload) { units.Add((0, unit.Width)); continue; }
+ // A run of blocks never includes an allocator bitmap; one that would is split around it.
+ ulong done = 0;
+ while (done < unit.Width) {
+ var start = Allocate();
+ ulong width = 1;
+ while (done + width < unit.Width && !IsBitmapBlock(cursor)) { ++cursor; ++width; }
+ var byteOffset = (long)(done * blockSize);
+ var byteLength = Math.Min((long)(width * blockSize), payload.Size - byteOffset);
+ if (byteLength > 0) payloads.Add((long)start * blockSize, Slice(payload, byteOffset, byteLength));
+ if (units.Count > 0 && units[^1].Start != 0 && units[^1].Start + units[^1].Width == start)
+ units[^1] = (units[^1].Start, units[^1].Width + width);
+ else
+ units.Add((start, width));
+ done += width;
+ }
+ }
+ var perItem = maxBody / 16;
+ ulong logical = 0;
+ var bodyKey = obj.StatKey;
+ for (var first = 0; first < units.Count; first += perItem) {
+ var count = Math.Min(perItem, units.Count - first);
+ var body = new byte[count * 16];
+ for (var i = 0; i < count; ++i) {
+ BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(i * 16), units[first + i].Start);
+ BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(i * 16 + 8), units[first + i].Width);
+ }
+ items.Add(new Item(Reiser4Key.Of(bodyKey.Locality, Reiser4Key.MinorBody, bodyKey.Ordering, bodyKey.ObjectId, logical),
+ Reiser4ItemPlugin.Extent, body));
+ for (var i = 0; i < count; ++i) logical = checked(logical + units[first + i].Width * blockSize);
+ }
}
- return (ordering | (ulong)Fibre(name) << 57, objectId, offset, hashed);
- }
+ items.Sort(static (a, b) => a.Key.CompareTo(b.Key));
+ for (var i = 1; i < items.Count; ++i)
+ if (items[i].Key.CompareTo(items[i - 1].Key) == 0 && items[i].Plugin != Reiser4ItemPlugin.DirEntries)
+ throw new InvalidDataException("Reiser4: two items share one key.");
- ///
- /// Why a stat-data body does not hold exactly the extensions its mask declares, or
- /// when it does.
- ///
- ///
- /// Extensions follow the 16-bit mask in bit order: light-weight (bit 0, 14 bytes),
- /// Unix (bit 1, 28), large times (bit 2, three 32-bit nanosecond fields), the plugin
- /// set (bit 4) and heir set (bit 8) — a 16-bit count of 4-byte member/plugin slots —
- /// and flags (bit 5, 32 bits). Anything else, including bit 15, which chains a
- /// further mask, is not carried: a body that does not parse is what
- /// fsck.reiser4 calls a fatal corruption.
- ///
- internal static string? StatDataProblem(ReadOnlySpan body) {
- if (body.Length < 2) return "the stat data has no extension mask";
- var mask = BinaryPrimitives.ReadUInt16LittleEndian(body);
- if ((mask & 3) != 3) return "the stat data lacks the light-weight or Unix extension";
- var at = 2;
- for (var bit = 0; bit < 16; ++bit) {
- if ((mask & 1 << bit) == 0) continue;
- int length;
- switch (bit) {
- case 0: length = 14; break;
- case 1: length = 28; break;
- case 2: length = 12; break;
- case 5: length = 4; break;
- case 4 or 8:
- if (at + 2 > body.Length) return "a plugin-set extension is truncated";
- length = 2 + 4 * BinaryPrimitives.ReadUInt16LittleEndian(body[at..]);
- break;
- default: return $"stat-data extension {bit} is not supported";
+ // ── Leaves and twigs ────────────────────────────────────────────────
+ var nodes = new Dictionary();
+ var twigItems = new List
- ();
+ var pending = new List
- ();
+ var firstLeaf = true;
+ void FlushLeaves() {
+ foreach (var group in Pack(pending, capacity)) {
+ var block = firstLeaf ? 24UL : Allocate();
+ firstLeaf = false;
+ nodes.Add(block, EncodeNode(group, plan, headerBytes, 1));
+ twigItems.Add(new Item(group[0].Key, Reiser4ItemPlugin.NodePointer, PointerBody(block)));
}
- if (at + length > body.Length) return $"stat-data extension {bit} is truncated";
- at += length;
+ pending.Clear();
}
- return at == body.Length ? null : "the stat data holds bytes its extension mask does not declare";
- }
-
- /// A stat data saying what a file is and how long.
- private static byte[] StatData(ushort mode, uint links, ulong size, ulong bytes, uint time,
- Reiser4Reader.FileMetadata? metadata = null) {
- if (metadata is { RawStatData.Length: > 0 } carried && StatDataProblem(carried.RawStatData) is { } problem)
- throw new NotSupportedException($"Reiser4: {problem}.");
- if (metadata is { } saved && saved.RawStatData.Length >= 44) {
- var preserved = saved.RawStatData.ToArray();
- BinaryPrimitives.WriteUInt16LittleEndian(preserved.AsSpan(2), saved.Mode);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(4), saved.LinkCount);
- BinaryPrimitives.WriteUInt64LittleEndian(preserved.AsSpan(8), size);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(16), saved.UserId);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(20), saved.GroupId);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(24), saved.ModifiedTime);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(28), saved.AccessedTime);
- BinaryPrimitives.WriteUInt32LittleEndian(preserved.AsSpan(32), saved.ChangedTime);
- BinaryPrimitives.WriteUInt64LittleEndian(preserved.AsSpan(36), bytes);
- return preserved;
+ foreach (var item in items) {
+ if (item.Plugin == Reiser4ItemPlugin.Extent) {
+ FlushLeaves();
+ twigItems.Add(item);
+ } else pending.Add(item);
}
- var body = new byte[2 + 14 + 28];
- BinaryPrimitives.WriteUInt16LittleEndian(body, 0x3); // light-weight and unix
- BinaryPrimitives.WriteUInt16LittleEndian(body.AsSpan(2), metadata?.Mode ?? mode);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(4), metadata?.LinkCount ?? links);
- BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(8), size);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(16), metadata?.UserId ?? 0);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(20), metadata?.GroupId ?? 0);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(24), metadata?.ModifiedTime ?? time);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(28), metadata?.AccessedTime ?? time);
- BinaryPrimitives.WriteUInt32LittleEndian(body.AsSpan(32), metadata?.ChangedTime ?? time);
- BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(36), bytes);
- return body;
- }
-
- /// The root's entries, its own two and one for each file.
- private static IEnumerable
- Directory(DirectoryNode directory, int blockSize) {
- var names = new List<(string Name, ulong Locality, ulong ObjectId)> {
- (".", directory.StatLocality, directory.ObjectId),
- ("..", directory.ParentStatLocality, directory.ParentObjectId),
- };
- foreach (var child in directory.Children) names.Add((child.Name, directory.ObjectId, child.ObjectId));
+ FlushLeaves();
- var keyed = new List<(ulong Ordering, ulong ObjectId, ulong Offset, bool Hashed,
- string Name, ulong Locality, ulong Target)>();
- foreach (var (name, locality, target) in names) {
- var (ordering, objectId, offset, hashed) = NameKey(name);
- keyed.Add((ordering, objectId, offset, hashed, name, locality, target));
+ ushort level = 2;
+ var parentItems = twigItems;
+ while (true) {
+ var groups = Pack(parentItems, capacity).ToList();
+ if (groups.Count == 1) {
+ nodes.Add(23, EncodeNode(groups[0], plan, headerBytes, (byte)level));
+ break;
+ }
+ parentItems = [];
+ foreach (var group in groups) {
+ var block = Allocate();
+ nodes.Add(block, EncodeNode(group, plan, headerBytes, (byte)level));
+ parentItems.Add(new Item(group[0].Key, Reiser4ItemPlugin.NodePointer, PointerBody(block)));
+ }
+ level = checked((ushort)(level + 1));
}
- keyed.Sort((a, b) => a.Ordering != b.Ordering ? a.Ordering.CompareTo(b.Ordering)
- : a.ObjectId != b.ObjectId ? a.ObjectId.CompareTo(b.ObjectId)
- : a.Offset.CompareTo(b.Offset));
+ // ── Counters, bitmaps and the fixed blocks ──────────────────────────
+ var used = cursor;
+ var blocks = Math.Max(plan.MinimumBlocks, used + 1);
+ var format = plan.Format.ToArray();
+ var backup = plan.Backup.ToArray();
+ var objects = (ulong)plan.Objects.Count;
+ var tailBitmaps = (blocks - 1) / BlocksPerBitmap - (used - 1) / BlocksPerBitmap;
+ BinaryPrimitives.WriteUInt64LittleEndian(format.AsSpan(0), blocks);
+ BinaryPrimitives.WriteUInt64LittleEndian(format.AsSpan(8), blocks - used - tailBitmaps);
+ BinaryPrimitives.WriteUInt64LittleEndian(format.AsSpan(16), 23);
+ BinaryPrimitives.WriteUInt64LittleEndian(format.AsSpan(24), plan.NextObjectId);
+ BinaryPrimitives.WriteUInt64LittleEndian(format.AsSpan(32), objects);
+ BinaryPrimitives.WriteUInt32LittleEndian(format.AsSpan(48), plan.MkfsId);
+ BinaryPrimitives.WriteUInt16LittleEndian(format.AsSpan(68), level);
+ BinaryPrimitives.WriteUInt64LittleEndian(backup.AsSpan(0x4D), blocks);
+ BinaryPrimitives.WriteUInt32LittleEndian(backup.AsSpan(0x55), plan.MkfsId);
+
+ var basePosition = output.Position;
+ var zero = new byte[blockSize];
+ var bitmaps = BuildBitmaps(blocks, used);
+ for (var b = 0UL; b < FirstDataBlock; ++b) {
+ var bytes = b switch {
+ 16 => plan.Master,
+ 17 => format,
+ 18 => bitmaps[0].Bytes,
+ 21 => plan.Status,
+ 22 => backup,
+ 23 => nodes[23],
+ 24 => nodes[24],
+ _ => zero,
+ };
+ output.Write(bytes, 0, blockSize);
+ }
+ output.SetLength(basePosition + checked((long)blocks * blockSize));
+ foreach (var (block, bytes) in bitmaps.Skip(1)) {
+ output.Position = basePosition + (long)block * blockSize;
+ output.Write(bytes);
+ }
+ foreach (var (block, node) in nodes) {
+ if (block is 23 or 24) continue;
+ output.Position = basePosition + checked((long)block * blockSize);
+ output.Write(node);
+ }
+ payloads.FlushTo(output, basePosition);
+ output.Position = basePosition + (long)blocks * blockSize;
+ output.Flush();
+ return new Result(blocks, level, objects, [.. nodes.Keys]);
+ }
+ /// The cde40 items of a directory: its entries in key order, packed into items that fit a node.
+ private static IEnumerable
- DirectoryItems(Reiser4PlanObject directory, int maxBody) {
+ var entries = directory.Entries.Select(static (entry, index) => (entry, index)).ToList();
+ entries.Sort(static (a, b) => {
+ var c = a.entry.Ordering.CompareTo(b.entry.Ordering);
+ if (c != 0) return c;
+ c = a.entry.ObjectId.CompareTo(b.entry.ObjectId);
+ if (c != 0) return c;
+ c = a.entry.Offset.CompareTo(b.entry.Offset);
+ return c != 0 ? c : a.index.CompareTo(b.index);
+ });
const int unitHeaderBytes = 26;
const int targetKeyBytes = 24;
-
var first = 0;
- while (first < keyed.Count) {
+ while (first < entries.Count) {
var last = first;
var bodySize = 2;
- while (last < keyed.Count) {
- var entrySize = unitHeaderBytes + targetKeyBytes +
- (keyed[last].Hashed ? Encoding.ASCII.GetByteCount(keyed[last].Name) + 1 : 0);
- if (bodySize + entrySize > blockSize - NodeHeaderBytes - ItemHeaderBytes) break;
+ while (last < entries.Count) {
+ var entrySize = unitHeaderBytes + targetKeyBytes + (entries[last].entry.Hashed ? entries[last].entry.Name.Length + 1 : 0);
+ if (bodySize + entrySize > maxBody) break;
bodySize += entrySize;
++last;
}
@@ -249,191 +222,53 @@ private static IEnumerable
- Directory(DirectoryNode directory, int blockSiz
BinaryPrimitives.WriteUInt16LittleEndian(body, checked((ushort)(last - first)));
var unit = 2 + (last - first) * unitHeaderBytes;
for (var i = first; i < last; ++i) {
- var entry = keyed[i];
+ var entry = entries[i].entry;
var header = 2 + (i - first) * unitHeaderBytes;
BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(header), entry.Ordering);
BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(header + 8), entry.ObjectId);
BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(header + 16), entry.Offset);
BinaryPrimitives.WriteUInt16LittleEndian(body.AsSpan(header + 24), checked((ushort)unit));
- BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(unit), entry.Locality << 4 | MinorStatData);
- BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(unit + 16), entry.Target);
+ BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(unit), entry.Target.Word0);
+ BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(unit + 8), entry.Target.Ordering);
+ BinaryPrimitives.WriteUInt64LittleEndian(body.AsSpan(unit + 16), entry.Target.ObjectId);
unit += targetKeyBytes;
if (entry.Hashed) {
- var bytes = Encoding.ASCII.GetBytes(entry.Name);
- bytes.CopyTo(body.AsSpan(unit));
- unit += bytes.Length + 1;
+ entry.Name.CopyTo(body.AsSpan(unit));
+ unit += entry.Name.Length + 1;
}
}
- var firstKey = keyed[first];
- yield return new(directory.ObjectId, MinorFileName, firstKey.Ordering, firstKey.ObjectId,
- firstKey.Offset, PluginCde40, body);
+ var key = entries[first].entry;
+ yield return new Item(Reiser4Key.Of(directory.StatKey.ObjectId, Reiser4Key.MinorName, key.Ordering, key.ObjectId, key.Offset),
+ Reiser4ItemPlugin.DirEntries, body);
first = last;
}
}
- ///
- /// Builds leaves, twig extents and pointer levels from the captured root defaults.
- ///
- internal static Layout Build(byte[] leaf, int blockSize, uint mkfsId, uint time,
- ulong rootLocality, ulong rootObjectId, IReadOnlyList sourceFiles,
- IReadOnlyDictionary? savedDirectories, Func allocate) {
- // The root's own stat data, kept as mkfs wrote it — it carries the plugin set
- // every file below it inherits, which this does not attempt to rebuild.
- var rootStatOffset = BinaryPrimitives.ReadUInt16LittleEndian(leaf[(blockSize - ItemHeaderBytes + 32)..]);
- var rootStatLength = BinaryPrimitives.ReadUInt16LittleEndian(leaf[(blockSize - 2 * ItemHeaderBytes + 32)..])
- - rootStatOffset;
- var rootStat = leaf.AsSpan(rootStatOffset, rootStatLength).ToArray();
- if (savedDirectories?.GetValueOrDefault("") is { } rootMetadata)
- rootStat = StatData(rootMetadata.Mode, rootMetadata.LinkCount, (ulong)rootMetadata.Size,
- BinaryPrimitives.ReadUInt64LittleEndian(rootMetadata.RawStatData.AsSpan(36)), time, rootMetadata);
-
- var rootDirectory = new DirectoryNode {
- Path = "", Name = "", ObjectId = rootObjectId, ParentObjectId = rootObjectId,
- StatLocality = rootLocality, ParentStatLocality = rootLocality,
- };
- var directories = new List { rootDirectory };
- var byPath = new Dictionary(StringComparer.Ordinal) { [""] = rootDirectory };
- var knownIds = sourceFiles.Select(static entry => entry.Metadata?.ObjectId ?? 0)
- .Concat(savedDirectories?.Values.Select(static metadata => metadata?.ObjectId ?? 0) ?? []);
- var nextObjectId = checked(Math.Max(0xFFFFUL, Math.Max(rootObjectId, knownIds.DefaultIfEmpty().Max())) + 1);
- var assignedIds = new HashSet { rootObjectId };
- ulong ObjectId(Reiser4Reader.FileMetadata? metadata) {
- var id = metadata?.ObjectId is > 0 ? metadata.ObjectId : nextObjectId;
- if (metadata?.ObjectId is not > 0) nextObjectId = checked(nextObjectId + 1);
- if (id <= rootObjectId || !assignedIds.Add(id))
- throw new InvalidDataException("Reiser4: duplicate or reserved object identity.");
- return id;
- }
- var fileParents = new List<(Entry Source, ulong ParentObjectId, ulong ObjectId)>();
-
- var allSources = (savedDirectories?.Keys.Where(static path => path.Length > 0) ?? [])
- .Select(static path => new Entry { Name = path + "/", ParentObjectId = 0, ObjectId = 0, Size = 0, Runs = [] })
- .Concat(sourceFiles);
- foreach (var source in allSources) {
- var isDirectory = source.Name.EndsWith('/');
- var components = source.Name.Replace('\\', '/').Split('/', StringSplitOptions.RemoveEmptyEntries);
- if (components.Length == 0 || components.Any(static component => component is "." or ".." ||
- component.Contains(':') || component.Contains('\0') || component.Any(static c => c > 127)))
- throw new InvalidDataException($"Reiser4: invalid archive path '{source.Name}'.");
-
- var parentPath = "";
- var parent = rootDirectory;
- for (var i = 0; i < components.Length - (isDirectory ? 0 : 1); ++i) {
- var path = parentPath.Length == 0 ? components[i] : $"{parentPath}/{components[i]}";
- if (!byPath.TryGetValue(path, out var directory)) {
- if (parent.Children.Any(child => child.Name == components[i]))
- throw new InvalidDataException($"Reiser4: file/directory collision at '{path}'.");
- directory = new DirectoryNode {
- Path = path, Name = components[i], ObjectId = ObjectId(savedDirectories?.GetValueOrDefault(path)), ParentObjectId = parent.ObjectId,
- StatLocality = parent.ObjectId, ParentStatLocality = parent.StatLocality,
- };
- byPath.Add(path, directory);
- directories.Add(directory);
- parent.Children.Add((directory.Name, directory.ObjectId));
- }
- parent = directory;
- parentPath = path;
- }
-
- if (isDirectory) continue;
- var leafName = components[^1];
- if (parent.Children.Any(child => string.Equals(child.Name, leafName, StringComparison.Ordinal)))
- throw new InvalidDataException($"Reiser4: duplicate path or file/directory collision at '{source.Name}'.");
- var objectId = ObjectId(source.Metadata);
- parent.Children.Add((leafName, objectId));
- fileParents.Add((source with { Name = leafName }, parent.ObjectId, objectId));
- }
-
- var files = fileParents.Select(static file => new Entry {
- Name = file.Source.Name, ParentObjectId = file.ParentObjectId, ObjectId = file.ObjectId,
- Size = file.Source.Size, Runs = file.Source.Runs, Metadata = file.Source.Metadata,
- }).ToArray();
-
- var rootItems = Directory(rootDirectory, blockSize).ToArray();
- BinaryPrimitives.WriteUInt32LittleEndian(rootStat.AsSpan(4), checked(3U + (uint)directories.Count(directory => directory != rootDirectory && directory.ParentObjectId == rootObjectId)));
- BinaryPrimitives.WriteUInt64LittleEndian(rootStat.AsSpan(8), (ulong)rootDirectory.Children.Count + 2);
- BinaryPrimitives.WriteUInt64LittleEndian(rootStat.AsSpan(36), (ulong)rootItems.Sum(static item => item.Body.Length - 2));
- var bodies = new List
- {
- new(rootLocality, MinorStatData, 0, rootObjectId, 0, PluginStat40, rootStat),
- };
- bodies.AddRange(rootItems);
-
- foreach (var directory in directories.Skip(1)) {
- var directoryItems = Directory(directory, blockSize).ToArray();
- bodies.Add(new(directory.StatLocality, MinorStatData, 0, directory.ObjectId, 0, PluginStat40,
- StatData(0x41ED, checked(2U + (uint)directories.Count(child => child.ParentObjectId == directory.ObjectId)), (ulong)directory.Children.Count + 2, (ulong)directoryItems.Sum(static item => item.Body.Length - 2), time,
- savedDirectories?.GetValueOrDefault(directory.Path))));
- bodies.AddRange(directoryItems);
- }
-
- foreach (var file in files) {
- var held = file.Runs.Aggregate(0UL, static (sum, run) => checked(sum + run.Width));
- bodies.Add(new(file.ParentObjectId, MinorStatData, 0, file.ObjectId, 0, PluginStat40,
- StatData(0x81A4, 1, (ulong)file.Size, held * (ulong)blockSize, time, file.Metadata)));
- if (file.Runs.Count == 0) continue;
- var runsPerItem = (blockSize - NodeHeaderBytes - ItemHeaderBytes) / 16;
- ulong logicalOffset = 0;
- for (var firstRun = 0; firstRun < file.Runs.Count; firstRun += runsPerItem) {
- var count = Math.Min(runsPerItem, file.Runs.Count - firstRun);
- var extents = new byte[count * 16];
- for (var i = 0; i < count; ++i) {
- var run = file.Runs[firstRun + i];
- BinaryPrimitives.WriteUInt64LittleEndian(extents.AsSpan(i * 16), run.Start);
- BinaryPrimitives.WriteUInt64LittleEndian(extents.AsSpan(i * 16 + 8), run.Width);
- }
- bodies.Add(new(file.ParentObjectId, MinorFileBody, 0, file.ObjectId, logicalOffset, PluginExtent40, extents));
- for (var i = 0; i < count; ++i)
- logicalOffset = checked(logicalOffset + file.Runs[firstRun + i].Width * (ulong)blockSize);
- }
- }
+ /// The body bytes of a directory's entries as its stat data's "bytes" counts them.
+ internal static ulong DirectoryBytes(IEnumerable entries)
+ => (ulong)entries.Sum(static e => 26 + 24 + (e.Hashed ? e.Name.Length + 1 : 0));
- bodies.Sort(static (a, b) => {
- var c = (a.Locality << 4 | a.Minor).CompareTo(b.Locality << 4 | b.Minor);
- if (c != 0) return c;
- c = a.Ordering.CompareTo(b.Ordering);
- if (c != 0) return c;
- c = a.ObjectId.CompareTo(b.ObjectId);
- return c != 0 ? c : a.Offset.CompareTo(b.Offset);
- });
+ /// A byte range of , read lazily.
+ internal static FilePayload Slice(FilePayload payload, long offset, long length) {
+ if (offset == 0 && length == payload.Size) return payload;
+ if (payload.Data is { } data) return FilePayload.FromBytes(data.AsSpan(checked((int)offset), checked((int)length)).ToArray());
+ return FilePayload.FromStream(length, () => SkipTo(payload.Open(), offset));
+ }
- var nodes = new Dictionary();
- var twigItems = new List
- ();
- var pending = new List
- ();
- var firstLeaf = true;
- void FlushLeaves() {
- foreach (var group in Pack(pending, blockSize)) {
- var block = firstLeaf ? 24UL : allocate();
- firstLeaf = false;
- nodes.Add(block, EncodeNode(group, blockSize, mkfsId, 1));
- twigItems.Add(group[0] with { Plugin = 3, Body = PointerBody(block) });
- }
- pending.Clear();
+ private static Stream SkipTo(Stream source, long offset) {
+ if (offset <= 0) return source;
+ if (source.CanSeek) {
+ source.Position = offset;
+ return source;
}
- // A leaf cannot straddle a key range occupied by a twig extent item.
- // End the leaf run before that extent, then resume after it.
- foreach (var item in bodies) {
- if (item.Plugin == PluginExtent40) {
- FlushLeaves();
- twigItems.Add(item);
- } else pending.Add(item);
- }
- FlushLeaves();
- byte level = 2;
- var parentItems = twigItems;
- while (true) {
- var groups = Pack(parentItems, blockSize).ToList();
- if (groups.Count == 1) {
- nodes.Add(23, EncodeNode(groups[0], blockSize, mkfsId, level));
- return new(nextObjectId, (ulong)assignedIds.Count, level, nodes);
- }
- parentItems = [];
- foreach (var group in groups) {
- var block = allocate();
- nodes.Add(block, EncodeNode(group, blockSize, mkfsId, level));
- parentItems.Add(group[0] with { Plugin = 3, Body = PointerBody(block) });
- }
- level = checked((byte)(level + 1));
+ var buffer = new byte[64 * 1024];
+ var remaining = offset;
+ while (remaining > 0) {
+ var n = source.Read(buffer, 0, (int)Math.Min(buffer.Length, remaining));
+ if (n <= 0) break;
+ remaining -= n;
}
+ return source;
}
private static byte[] PointerBody(ulong block) {
@@ -442,17 +277,16 @@ private static byte[] PointerBody(ulong block) {
return body;
}
- private static IEnumerable
> Pack(IReadOnlyList- items, int blockSize) {
+ private static IEnumerable
> Pack(IReadOnlyList- items, int capacity) {
var group = new List
- ();
- var bytes = NodeHeaderBytes;
+ var bytes = 0;
foreach (var item in items) {
var need = checked(item.Body.Length + ItemHeaderBytes);
- if (need > blockSize - NodeHeaderBytes)
- throw new InvalidDataException("Reiser4: an indivisible item exceeds node capacity.");
- if (bytes + need > blockSize) {
+ if (need > capacity) throw new InvalidDataException("Reiser4: an indivisible item exceeds node capacity.");
+ if (bytes + need > capacity) {
yield return group;
group = [];
- bytes = NodeHeaderBytes;
+ bytes = 0;
}
group.Add(item);
bytes += need;
@@ -460,24 +294,51 @@ private static IEnumerable
> Pack(IReadOnlyList- items, int block
if (group.Count > 0) yield return group;
}
- private static byte[] EncodeNode(IReadOnlyList
- items, int blockSize, uint mkfsId, byte level) {
+ private static byte[] EncodeNode(IReadOnlyList
- items, Reiser4Plan plan, int headerBytes, byte level) {
+ const int blockSize = Reiser4Volume.BlockSize;
var node = new byte[blockSize];
- var at = NodeHeaderBytes;
+ var at = headerBytes;
for (var i = 0; i < items.Count; ++i) {
var item = items[i];
item.Body.CopyTo(node.AsSpan(at));
var header = blockSize - (i + 1) * ItemHeaderBytes;
- WriteKey(node.AsSpan(header), item.Locality, item.Minor, item.Ordering, item.ObjectId, item.Offset);
+ item.Key.Write(node.AsSpan(header));
BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(header + 32), checked((ushort)at));
- BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(header + 36), checked((ushort)item.Plugin));
+ BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(header + 36), item.Plugin);
at += item.Body.Length;
}
+ BinaryPrimitives.WriteUInt16LittleEndian(node, plan.NodePlugin);
BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(2), checked((ushort)items.Count));
BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(4), checked((ushort)(blockSize - items.Count * ItemHeaderBytes - at)));
BinaryPrimitives.WriteUInt16LittleEndian(node.AsSpan(6), checked((ushort)at));
- BinaryPrimitives.WriteUInt32LittleEndian(node.AsSpan(8), unchecked((uint)NodeMagic));
- BinaryPrimitives.WriteUInt32LittleEndian(node.AsSpan(12), mkfsId);
+ BinaryPrimitives.WriteUInt32LittleEndian(node.AsSpan(8), plan.NodePlugin == 1 ? Reiser4Volume.Node41Magic : unchecked((uint)NodeMagic));
+ BinaryPrimitives.WriteUInt32LittleEndian(node.AsSpan(12), plan.MkfsId);
node[26] = level;
+ if (plan.NodePlugin == 1) Reiser4Volume.SealNode41(node);
return node;
}
+
+ ///
+ /// Every block-allocator bitmap. Bitmap i covers blocks [i × BlocksPerBitmap, (i+1) ×
+ /// BlocksPerBitmap); the first lives at block 18 and the rest at the stride boundaries. Blocks
+ /// below , every bitmap block and everything past the end of the volume
+ /// are marked allocated.
+ ///
+ internal static List<(ulong Block, byte[] Bytes)> BuildBitmaps(ulong blocks, ulong used) {
+ var result = new List<(ulong Block, byte[] Bytes)>();
+ var count = (blocks + BlocksPerBitmap - 1) / BlocksPerBitmap;
+ for (var i = 0UL; i < count; ++i) {
+ var block = i == 0 ? 18UL : i * BlocksPerBitmap;
+ var buffer = new byte[Reiser4Volume.BlockSize];
+ var baseBlock = i * BlocksPerBitmap;
+ for (var bit = 0UL; bit < BlocksPerBitmap; ++bit) {
+ var target = baseBlock + bit;
+ if (target >= used && target < blocks && !IsBitmapBlock(target)) continue;
+ buffer[4 + (int)(bit >> 3)] |= (byte)(1 << (int)(bit & 7));
+ }
+ BinaryPrimitives.WriteUInt32LittleEndian(buffer, Adler32.Compute(buffer.AsSpan(4)));
+ result.Add((block, buffer));
+ }
+ return result;
+ }
}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Volume.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Volume.cs
new file mode 100644
index 000000000..e9b575c75
--- /dev/null
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Volume.cs
@@ -0,0 +1,625 @@
+#pragma warning disable CS1591
+using System.Buffers.Binary;
+using System.Text;
+using Compression.Core.Checksums;
+using Compression.Core.DiskImage;
+
+namespace FileSystem.Reiser4;
+
+/// Item plugin identifiers (plugin type 1).
+internal static class Reiser4ItemPlugin {
+ internal const ushort StatData = 0;
+ internal const ushort DirEntries = 2;
+ internal const ushort NodePointer = 3;
+ internal const ushort Extent = 5;
+ internal const ushort Tail = 6;
+ internal const ushort CompressedTail = 7;
+}
+
+/// Plugin-set member slots (the sdext_plugin_set member numbers).
+internal static class Reiser4PsetMember {
+ internal const ushort File = 0;
+ internal const ushort Directory = 1;
+ internal const ushort Formatting = 3;
+ internal const ushort Hash = 4;
+ internal const ushort Fibration = 5;
+ internal const ushort Cipher = 8;
+ internal const ushort Compression = 10;
+ internal const ushort CompressionMode = 11;
+ internal const ushort Cluster = 12;
+ internal const ushort Create = 13;
+}
+
+/// One item as it sits in a node: its key, plugin and where its body lives.
+internal sealed record Reiser4ItemRef(Reiser4Key Key, ushort Plugin, ushort Flags, ulong Block, int BodyOffset, int BodyLength);
+
+/// One directory entry: the three key words its name produced, the name and its target.
+internal sealed record Reiser4DirEntry(ulong Ordering, ulong ObjectId, ulong Offset, byte[] Name, Reiser4Key Target) {
+ internal bool Hashed => (this.Ordering & Reiser4NameKeys.LongNameBit) != 0;
+ internal bool IsDot => this.Name is [(byte)'.'];
+ internal bool IsDotDot => this.Name is [(byte)'.', (byte)'.'];
+}
+
+///
+/// The stat data of an object, parsed only as far as the writer needs it; the raw body is always
+/// kept so a rebuild can carry every extension byte for byte.
+///
+internal sealed class Reiser4Stat {
+
+ internal byte[] Raw { get; }
+ internal ushort Mask => BinaryPrimitives.ReadUInt16LittleEndian(this.Raw);
+ internal ushort Mode => BinaryPrimitives.ReadUInt16LittleEndian(this.Raw.AsSpan(2));
+ internal uint Links => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(4));
+ internal ulong Size => BinaryPrimitives.ReadUInt64LittleEndian(this.Raw.AsSpan(8));
+ internal uint UserId => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(16));
+ internal uint GroupId => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(20));
+ internal uint AccessTime => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(24));
+ internal uint ModifyTime => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(28));
+ internal uint ChangeTime => BinaryPrimitives.ReadUInt32LittleEndian(this.Raw.AsSpan(32));
+ /// Allocated bytes for files and directories; the device number for special files.
+ internal ulong BytesOrDevice => BinaryPrimitives.ReadUInt64LittleEndian(this.Raw.AsSpan(36));
+
+ /// The object's own plugin-set members, member → plugin id.
+ internal IReadOnlyDictionary PluginSet { get; }
+
+ /// Byte range of the plugin-set extension, or (-1, 0) when there is none.
+ internal (int Start, int Length) PluginSetRange { get; } = (-1, 0);
+
+ /// The symlink target the symlink extension holds.
+ internal byte[]? SymlinkTarget { get; }
+
+ internal const int FileType = 0xF000;
+ internal const int Directory = 0x4000;
+ internal const int Regular = 0x8000;
+ internal const int Symlink = 0xA000;
+ internal const int CharDevice = 0x2000;
+ internal const int BlockDevice = 0x6000;
+ internal const int Fifo = 0x1000;
+ internal const int Socket = 0xC000;
+
+ private Reiser4Stat(byte[] raw, Dictionary pset, (int, int) psetRange, byte[]? symlink) {
+ this.Raw = raw;
+ this.PluginSet = pset;
+ this.PluginSetRange = psetRange;
+ this.SymlinkTarget = symlink;
+ }
+
+ ///
+ /// Parses a stat-data body, or returns why it is outside what this profile carries: an
+ /// extension nobody verified (crypto, a chained mask) or bytes the mask does not declare.
+ ///
+ internal static Reiser4Stat? Parse(ReadOnlySpan body, out string? problem) {
+ problem = null;
+ if (body.Length < 2) { problem = "the stat data has no extension mask"; return null; }
+ var mask = BinaryPrimitives.ReadUInt16LittleEndian(body);
+ if ((mask & 3) != 3) { problem = "the stat data lacks the light-weight or Unix extension"; return null; }
+ var at = 2;
+ var pset = new Dictionary();
+ (int, int) psetRange = (-1, 0);
+ byte[]? symlink = null;
+ for (var bit = 0; bit < 16; ++bit) {
+ if ((mask & 1 << bit) == 0) continue;
+ int length;
+ switch (bit) {
+ case 0: length = 14; break;
+ case 1: length = 28; break;
+ case 2: length = 12; break;
+ case 3: {
+ // Symlink: the target, as long as the light-weight extension's size says, then a NUL.
+ var size = BinaryPrimitives.ReadUInt64LittleEndian(body[8..]);
+ if (size > 4096) { problem = "a symlink target is longer than a page"; return null; }
+ length = (int)size + 1;
+ if (at + length > body.Length) { problem = "the symlink extension is truncated"; return null; }
+ symlink = body.Slice(at, (int)size).ToArray();
+ break;
+ }
+ case 5: length = 4; break;
+ case 4 or 8: {
+ if (at + 2 > body.Length) { problem = "a plugin-set extension is truncated"; return null; }
+ var count = BinaryPrimitives.ReadUInt16LittleEndian(body[at..]);
+ length = 2 + 4 * count;
+ if (at + length > body.Length) { problem = $"stat-data extension {bit} is truncated"; return null; }
+ if (bit == 4) {
+ psetRange = (at, length);
+ for (var i = 0; i < count; ++i)
+ pset[BinaryPrimitives.ReadUInt16LittleEndian(body[(at + 2 + 4 * i)..])] =
+ BinaryPrimitives.ReadUInt16LittleEndian(body[(at + 4 + 4 * i)..]);
+ }
+ break;
+ }
+ default: problem = $"stat-data extension {bit} is not supported"; return null;
+ }
+ if (at + length > body.Length) { problem = $"stat-data extension {bit} is truncated"; return null; }
+ at += length;
+ }
+ if (at != body.Length) { problem = "the stat data holds bytes its extension mask does not declare"; return null; }
+ if (pset.TryGetValue(Reiser4PsetMember.Cipher, out var cipher) && cipher != 0) {
+ problem = "the object is encrypted";
+ return null;
+ }
+ return new Reiser4Stat(body.ToArray(), pset, psetRange, symlink);
+ }
+
+ internal int Kind => this.Mode & FileType;
+}
+
+/// One object of the volume: its stat data, its body items and, for a directory, its entries.
+internal sealed class Reiser4Object {
+ internal required Reiser4Key StatKey { get; init; }
+ internal required Reiser4Stat Stat { get; init; }
+ internal List Body { get; } = [];
+ internal List Entries { get; } = [];
+ internal ulong ObjectId => this.StatKey.ObjectId;
+ internal bool IsDirectory => this.Stat.Kind == Reiser4Stat.Directory;
+}
+
+///
+/// A Reiser4 volume read whole: the fixed blocks after journal replay, the root's plugin profile
+/// and every object the node40/node41 tree holds, resolved into a namespace.
+///
+///
+/// The layout this reads — and the reasons it refuses what it does not — is written down in
+/// docs/REISER4-NATIVE-PROFILE.md.
+///
+internal sealed class Reiser4Volume : IDisposable {
+
+ internal const int BlockSize = 4096;
+ internal const long MasterOffset = 65536;
+ internal const ulong RootLocality = 0x29;
+ internal const ulong RootObjectId = 0x2a;
+ internal static readonly Reiser4Key RootStatKey = Reiser4Key.Of(RootLocality, Reiser4Key.MinorStatData, 0, RootObjectId, 0);
+
+ private static readonly byte[] MasterMagic = "ReIsEr4"u8.ToArray();
+ private static readonly byte[] FormatMagic = "ReIsEr40FoRmAt"u8.ToArray();
+ private const uint NodeMagic = 0x52344653;
+ /// The magic a node41 (checksummed) node carries instead.
+ internal const uint Node41Magic = 0x19051966;
+ private const int ItemHeaderBytes = 38;
+
+ private readonly ImageAccessor _image;
+ private Dictionary _replayed = [];
+
+ internal bool Valid { get; }
+ internal string Label { get; } = "";
+ internal string UuidHex { get; } = "";
+ internal int VolumeBlockSize { get; } = BlockSize;
+ internal long Length => this._image.Length;
+ internal ulong BlockCount => (ulong)(this._image.Length / BlockSize);
+
+ /// True when the whole tree was read and every object is one this profile carries.
+ internal bool TreeValid { get; private set; }
+
+ /// Why the tree was not read, when it was not.
+ internal string? Problem { get; private set; }
+
+ /// Number of journal transactions replayed before the tree was read.
+ internal int ReplayedTransactions { get; private set; }
+
+ /// Node plugin the format superblock names: 0 node40, 1 node41 (checksummed).
+ internal ushort NodePlugin { get; private set; }
+ internal int NodeHeaderBytes => this.NodePlugin == 1 ? 32 : 28;
+
+ internal ushort TreeHeight { get; private set; }
+
+ internal Dictionary Objects { get; } = [];
+ internal Reiser4Object? Root { get; private set; }
+ internal List NodeBlocks { get; } = [];
+
+ /// Every path the namespace resolves, in walk order, with the object each one names.
+ internal List<(string Path, byte[] Name, Reiser4Object Object, Reiser4Object Parent)> Paths { get; } = [];
+
+ internal Reiser4Volume(Stream stream, bool leaveOpen = true) {
+ ArgumentNullException.ThrowIfNull(stream);
+ if (stream.CanSeek) stream.Position = 0;
+ this._image = new ImageAccessor(stream, leaveOpen);
+ if (this._image.Length < MasterOffset + BlockSize) return;
+ var master = this._image.Read(MasterOffset, BlockSize);
+ if (!master.AsSpan(0, MasterMagic.Length).SequenceEqual(MasterMagic)) return;
+ this.Valid = true;
+ var blockSize = BinaryPrimitives.ReadUInt16LittleEndian(master.AsSpan(18, 2));
+ if (blockSize is >= 512 and <= 8192) this.VolumeBlockSize = blockSize;
+ this.UuidHex = Convert.ToHexString(master.AsSpan(20, 16));
+ var label = master.AsSpan(36, 16);
+ var nul = label.IndexOf((byte)0);
+ this.Label = Encoding.UTF8.GetString(nul < 0 ? label : label[..nul]);
+ try {
+ this.Problem = this.Load();
+ } catch (Exception ex) when (ex is InvalidDataException or NotSupportedException or OverflowException or ArgumentException or IndexOutOfRangeException) {
+ this.Problem = ex.Message;
+ }
+ this.TreeValid = this.Problem is null;
+ }
+
+ /// A block as the volume holds it once the journal is replayed.
+ internal byte[] ReadBlock(ulong block) {
+ if (this._replayed.TryGetValue(block, out var replayed)) return replayed.ToArray();
+ return this._image.Read(checked((long)block * BlockSize), BlockSize);
+ }
+
+ /// Bytes of an item body.
+ internal byte[] ReadBody(Reiser4ItemRef item) => this.ReadBlock(item.Block).AsSpan(item.BodyOffset, item.BodyLength).ToArray();
+
+ /// Copies whole blocks from the volume, journal replay included.
+ internal void CopyBlocks(ulong start, ulong count, Stream destination, long byteLimit) {
+ for (ulong i = 0; i < count && byteLimit > 0; ++i) {
+ var block = start + i;
+ var take = (int)Math.Min(BlockSize, byteLimit);
+ if (this._replayed.TryGetValue(block, out var replayed)) destination.Write(replayed, 0, take);
+ else this._image.CopyTo(checked((long)block * BlockSize), destination, take);
+ byteLimit -= take;
+ }
+ }
+
+ private string? Load() {
+ if (this.VolumeBlockSize != BlockSize) return "only 4096-byte blocks are read natively";
+ if (this.BlockCount <= 25) return "the image is too small for a format40 volume";
+ var replay = Reiser4Journal.Read(block => this._image.Read(checked((long)block * BlockSize), BlockSize), this.BlockCount, out var journalProblem);
+ if (replay is null) return journalProblem;
+ this._replayed = replay.Blocks.ToDictionary(static pair => pair.Key, static pair => pair.Value);
+ this.ReplayedTransactions = replay.Transactions;
+
+ var format = this.ReadBlock(17);
+ if (!format.AsSpan(52, FormatMagic.Length).SequenceEqual(FormatMagic)) return "the format40 superblock is missing";
+ var flags = BinaryPrimitives.ReadUInt64LittleEndian(format.AsSpan(72));
+ if ((flags & 1) == 0) return "the volume uses short keys";
+ this.NodePlugin = (ushort)BinaryPrimitives.ReadUInt32LittleEndian(format.AsSpan(84));
+ if (this.NodePlugin > 1) return $"node plugin {this.NodePlugin} is not supported";
+ var root = BinaryPrimitives.ReadUInt64LittleEndian(format.AsSpan(16));
+ this.TreeHeight = BinaryPrimitives.ReadUInt16LittleEndian(format.AsSpan(68));
+ if (root == 0 || root >= this.BlockCount) return "the tree root lies outside the volume";
+
+ var items = new List();
+ var visited = new HashSet();
+ if (this.Walk(root, 0, visited, items) is { } walkProblem) return walkProblem;
+ this.NodeBlocks.AddRange(visited);
+ return this.Assemble(items);
+ }
+
+ private string? Walk(ulong block, int expectedLevel, HashSet visited, List items) {
+ if (block < 23 || block >= this.BlockCount) return $"a tree pointer names block {block}, outside the volume";
+ if (!visited.Add(block)) return $"node {block} is reached twice";
+ if (visited.Count > 16_000_000) return "the tree is larger than this reader walks";
+ var node = this.ReadBlock(block);
+ var plugin = BinaryPrimitives.ReadUInt16LittleEndian(node);
+ if (plugin != this.NodePlugin || BinaryPrimitives.ReadUInt32LittleEndian(node.AsSpan(8)) != (this.NodePlugin == 1 ? Node41Magic : NodeMagic))
+ return $"block {block} is not a formatted node of the volume's node plugin";
+ if (this.NodePlugin == 1 && NodeChecksum(node) != BinaryPrimitives.ReadUInt32LittleEndian(node.AsSpan(28)))
+ return $"node {block} fails its checksum";
+ var level = node[26];
+ if (level == 0 || expectedLevel != 0 && level != expectedLevel) return $"node {block} sits at the wrong tree level";
+ var count = BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(2));
+ var bodiesEnd = BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(6));
+ if (count == 0 || count > (BlockSize - this.NodeHeaderBytes) / ItemHeaderBytes ||
+ bodiesEnd < this.NodeHeaderBytes || bodiesEnd > BlockSize - count * ItemHeaderBytes)
+ return $"node {block} has a malformed header";
+ var headers = new (Reiser4Key Key, ushort Offset, ushort Flags, ushort Plugin)[count];
+ for (var i = 0; i < count; ++i) {
+ var at = BlockSize - (i + 1) * ItemHeaderBytes;
+ headers[i] = (Reiser4Key.Read(node.AsSpan(at)), BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(at + 32)),
+ BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(at + 34)), BinaryPrimitives.ReadUInt16LittleEndian(node.AsSpan(at + 36)));
+ if (headers[i].Offset < this.NodeHeaderBytes || headers[i].Offset > bodiesEnd) return $"node {block} has an item outside its body area";
+ if (i > 0 && headers[i].Key.CompareTo(headers[i - 1].Key) < 0) return $"node {block} holds items out of key order";
+ }
+ var ends = headers.Select(static h => (int)h.Offset).Append(bodiesEnd).Distinct().Order().ToArray();
+ var children = new List();
+ for (var i = 0; i < count; ++i) {
+ var (key, offset, itemFlags, itemPlugin) = headers[i];
+ var end = ends[Array.IndexOf(ends, offset) + 1];
+ var length = end - offset;
+ if (level > 1 && itemPlugin == Reiser4ItemPlugin.NodePointer) {
+ if (length != 8) return $"node {block} holds a malformed node pointer";
+ children.Add(BinaryPrimitives.ReadUInt64LittleEndian(node.AsSpan(offset)));
+ continue;
+ }
+ // Extents live at the twig level (the earliest workbench images also put them in leaves);
+ // every other item lives in a leaf.
+ if (level > 2 || level == 2 && itemPlugin != Reiser4ItemPlugin.Extent)
+ return $"node {block} holds item plugin {itemPlugin} at level {level}";
+ items.Add(new Reiser4ItemRef(key, itemPlugin, itemFlags, block, offset, length));
+ }
+ if (level == 1 && children.Count > 0) return $"leaf {block} holds a node pointer";
+ foreach (var child in children)
+ if (this.Walk(child, level - 1, visited, items) is { } problem) return problem;
+ return null;
+ }
+
+ /// The CRC-32C node41 keeps at byte 28: over the node40 header and everything after the checksum.
+ internal static uint NodeChecksum(ReadOnlySpan node) {
+ var crc = Crc32CUpdate(0xFFFF_FFFFu, node[..28]);
+ return Crc32CUpdate(crc, node[32..]);
+ }
+
+ private static readonly uint[] Crc32CTable = BuildCrc32CTable();
+
+ private static uint[] BuildCrc32CTable() {
+ var table = new uint[256];
+ for (var n = 0u; n < 256; ++n) {
+ var c = n;
+ for (var k = 0; k < 8; ++k) c = (c & 1) != 0 ? 0x82F63B78u ^ (c >> 1) : c >> 1;
+ table[n] = c;
+ }
+ return table;
+ }
+
+ /// The CRC-32C register advanced over , without the final inversion.
+ private static uint Crc32CUpdate(uint crc, ReadOnlySpan data) {
+ foreach (var b in data) crc = Crc32CTable[(crc ^ b) & 0xFF] ^ (crc >> 8);
+ return crc;
+ }
+
+ private string? Assemble(List items) {
+ var directoryItems = new Dictionary>();
+ foreach (var item in items) {
+ var key = item.Key;
+ switch (key.Minor) {
+ case Reiser4Key.MinorStatData when item.Plugin == Reiser4ItemPlugin.StatData && key.Offset == 0: {
+ var stat = Reiser4Stat.Parse(this.ReadBody(item), out var problem);
+ if (stat is null) return problem;
+ if (!this.Objects.TryAdd(key, new Reiser4Object { StatKey = key, Stat = stat })) return "an object has two stat data";
+ break;
+ }
+ case Reiser4Key.MinorName when item.Plugin == Reiser4ItemPlugin.DirEntries:
+ if (!directoryItems.TryGetValue(key.Locality, out var list)) directoryItems[key.Locality] = list = [];
+ list.Add(item);
+ break;
+ case Reiser4Key.MinorBody when item.Plugin is Reiser4ItemPlugin.Extent or Reiser4ItemPlugin.Tail or Reiser4ItemPlugin.CompressedTail:
+ break;
+ default:
+ return $"item plugin {item.Plugin} with key type {key.Minor} is not supported";
+ }
+ }
+ foreach (var item in items.Where(static item => item.Key.Minor == Reiser4Key.MinorBody)) {
+ if (!this.Objects.TryGetValue(item.Key.StatKey, out var owner)) return "a file body has no stat data";
+ if (owner.Stat.Kind != Reiser4Stat.Regular) return "a body item belongs to an object that is not a regular file";
+ owner.Body.Add(item);
+ }
+ foreach (var owner in this.Objects.Values) {
+ owner.Body.Sort(static (a, b) => a.Key.Offset.CompareTo(b.Key.Offset));
+ if (this.BodyProblem(owner) is { } bodyProblem) return bodyProblem;
+ }
+
+ var byObjectId = this.Objects.Values.Where(static o => o.IsDirectory).GroupBy(static o => o.ObjectId)
+ .ToDictionary(static g => g.Key, static g => g.ToList());
+ foreach (var (directoryId, list) in directoryItems) {
+ if (!byObjectId.TryGetValue(directoryId, out var owners) || owners.Count != 1) return "directory entries have no directory";
+ foreach (var item in list) {
+ var body = this.ReadBody(item);
+ if (DecodeEntries(body, item.Key, owners[0].Entries) is { } entryProblem) return entryProblem;
+ }
+ }
+
+ if (!this.Objects.TryGetValue(RootStatKey, out var rootObject) || !rootObject.IsDirectory) return "the root directory is missing";
+ this.Root = rootObject;
+ var reached = new HashSet { RootStatKey };
+ var walked = new HashSet();
+ if (this.WalkNamespace(rootObject, "", 0, reached, walked) is { } nsProblem) return nsProblem;
+ if (reached.Count != this.Objects.Count) return "the tree holds objects no directory names";
+ return null;
+ }
+
+ private string? BodyProblem(Reiser4Object owner) {
+ if (owner.Body.Count == 0) return null;
+ var plugins = owner.Body.Select(static item => item.Plugin).Distinct().ToArray();
+ if (plugins.Contains(Reiser4ItemPlugin.CompressedTail) && plugins.Length > 1)
+ return "a file mixes compressed and plain body items";
+ if (plugins.Contains(Reiser4ItemPlugin.CompressedTail)) {
+ foreach (var item in owner.Body)
+ if (item.BodyLength < 2) return "a compressed body item is empty";
+ return null;
+ }
+ ulong expected = 0;
+ foreach (var item in owner.Body) {
+ if (item.Key.Offset != expected) return "a file body has a gap or an overlap between items";
+ if (item.Plugin == Reiser4ItemPlugin.Tail) { expected += (ulong)item.BodyLength; continue; }
+ if (item.BodyLength == 0 || item.BodyLength % 16 != 0) return "an extent item is malformed";
+ var body = this.ReadBody(item);
+ for (var at = 0; at < body.Length; at += 16) {
+ var start = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at));
+ var width = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at + 8));
+ if (width == 0 || start == 1 || start != 0 && (start < 25 || start >= this.BlockCount || width > this.BlockCount - start))
+ return "an extent unit lies outside the volume or is unallocated";
+ expected = checked(expected + width * BlockSize);
+ }
+ }
+ return null;
+ }
+
+ private static string? DecodeEntries(byte[] body, Reiser4Key itemKey, List into) {
+ if (body.Length < 2) return "a directory item is truncated";
+ var count = BinaryPrimitives.ReadUInt16LittleEndian(body);
+ var unitsStart = 2 + count * 26;
+ if (count == 0 || unitsStart > body.Length) return "a directory item is truncated";
+ for (var i = 0; i < count; ++i) {
+ var header = 2 + i * 26;
+ var ordering = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(header));
+ var objectId = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(header + 8));
+ var offset = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(header + 16));
+ int unit = BinaryPrimitives.ReadUInt16LittleEndian(body.AsSpan(header + 24));
+ int unitEnd = i + 1 < count ? BinaryPrimitives.ReadUInt16LittleEndian(body.AsSpan(header + 26 + 24)) : body.Length;
+ if (unit < unitsStart || unitEnd < unit + 24 || unitEnd > body.Length) return "a directory unit lies outside its item";
+ if (i == 0 && (ordering != itemKey.Ordering || objectId != itemKey.ObjectId || offset != itemKey.Offset))
+ return "a directory item's key is not its first entry's";
+ var targetWord0 = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(unit));
+ var target = Reiser4Key.Of(targetWord0 >> 4, Reiser4Key.MinorStatData,
+ BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(unit + 8)), BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(unit + 16)), 0);
+ byte[] name;
+ if ((ordering & Reiser4NameKeys.LongNameBit) != 0) {
+ var stored = body.AsSpan(unit + 24, unitEnd - unit - 24);
+ var nul = stored.IndexOf((byte)0);
+ if (nul <= 0) return "a long directory entry has no stored name";
+ name = stored[..nul].ToArray();
+ } else {
+ name = Reiser4NameKeys.Unpack(ordering, objectId, offset) ?? [];
+ if (unitEnd != unit + 24) return "a short directory entry carries a stored name";
+ }
+ if (name.Length == 0 || name.AsSpan().IndexOf((byte)'/') >= 0) return "a directory entry has an invalid name";
+ into.Add(new Reiser4DirEntry(ordering, objectId, offset, name, target));
+ }
+ return null;
+ }
+
+ private string? WalkNamespace(Reiser4Object directory, string path, int depth, HashSet reached, HashSet walked) {
+ if (depth > 128) return "the namespace is deeper than this reader walks";
+ if (!walked.Add(directory.StatKey)) return "a directory is reached through two paths";
+ var names = new HashSet(StringComparer.Ordinal);
+ foreach (var entry in directory.Entries) {
+ if (entry.IsDot || entry.IsDotDot) continue;
+ if (!this.Objects.TryGetValue(entry.Target, out var target)) return "a directory entry names a missing object";
+ var name = DecodeName(entry.Name);
+ if (!names.Add(name)) return "a directory holds the same name twice";
+ var full = path.Length == 0 ? name : path + "/" + name;
+ this.Paths.Add((full, entry.Name, target, directory));
+ reached.Add(entry.Target);
+ if (target.IsDirectory && this.WalkNamespace(target, full, depth + 1, reached, walked) is { } problem) return problem;
+ }
+ return null;
+ }
+
+ /// Names are bytes; they are shown as UTF-8 where they are valid UTF-8 and as Latin-1 otherwise.
+ internal static string DecodeName(byte[] name) {
+ try {
+ return new UTF8Encoding(false, true).GetString(name);
+ } catch (DecoderFallbackException) {
+ return Encoding.Latin1.GetString(name);
+ }
+ }
+
+ // ── Profile ────────────────────────────────────────────────────────────
+
+ /// A plugin-set member as an object inherits it: its own, else the root's, else the kernel default.
+ internal ushort Plugin(Reiser4Object? owner, ushort member) {
+ if (owner is not null && owner.Stat.PluginSet.TryGetValue(member, out var own)) return own;
+ if (this.Root is { } root && root.Stat.PluginSet.TryGetValue(member, out var inherited)) return inherited;
+ return member switch {
+ Reiser4PsetMember.Formatting => 2,
+ Reiser4PsetMember.Hash => (ushort)Reiser4HashId.R5,
+ Reiser4PsetMember.Fibration => (ushort)Reiser4FibrationId.Extension1,
+ Reiser4PsetMember.CompressionMode => (ushort)Reiser4CompressionModeId.Convert,
+ _ => 0,
+ };
+ }
+
+ // ── File bodies ────────────────────────────────────────────────────────
+
+ /// The extent units of a file, in logical order: (start, width), start 0 being a hole.
+ internal IEnumerable<(ulong Start, ulong Width)> ExtentUnits(Reiser4Object file) {
+ foreach (var item in file.Body.Where(static i => i.Plugin == Reiser4ItemPlugin.Extent)) {
+ var body = this.ReadBody(item);
+ for (var at = 0; at < body.Length; at += 16)
+ yield return (BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at)), BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at + 8)));
+ }
+ }
+
+ /// Writes a regular file's logical bytes, holes as zeros, into .
+ internal long ExtractTo(Reiser4Object file, Stream destination) {
+ var size = checked((long)file.Stat.Size);
+ if (file.Stat.Kind != Reiser4Stat.Regular || size == 0) return 0;
+ long written = 0;
+ void Zeros(long count) {
+ Span zero = stackalloc byte[4096];
+ zero.Clear();
+ while (count > 0) {
+ var n = (int)Math.Min(zero.Length, count);
+ destination.Write(zero[..n]);
+ count -= n;
+ written += n;
+ }
+ }
+ if (file.Body.Count > 0 && file.Body[0].Plugin == Reiser4ItemPlugin.CompressedTail) {
+ foreach (var (start, bytes) in this.Clusters(file)) {
+ if (start >= size) break;
+ if (start > written) Zeros(start - written);
+ var take = (int)Math.Min(bytes.Length, size - written);
+ destination.Write(bytes, 0, take);
+ written += take;
+ }
+ if (written < size) Zeros(size - written);
+ return written;
+ }
+ foreach (var item in file.Body) {
+ if (written >= size) break;
+ if (item.Plugin == Reiser4ItemPlugin.Tail) {
+ var bytes = this.ReadBody(item);
+ var take = (int)Math.Min(bytes.Length, size - written);
+ destination.Write(bytes, 0, take);
+ written += take;
+ continue;
+ }
+ var body = this.ReadBody(item);
+ for (var at = 0; at < body.Length && written < size; at += 16) {
+ var start = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at));
+ var width = BinaryPrimitives.ReadUInt64LittleEndian(body.AsSpan(at + 8));
+ var bytes = (long)Math.Min((ulong)(size - written), width * BlockSize);
+ if (start == 0) { Zeros(bytes); continue; }
+ this.CopyBlocks(start, width, destination, bytes);
+ written += bytes;
+ }
+ }
+ if (written < size) Zeros(size - written);
+ return written;
+ }
+
+ /// The cluster shift of a cryptcompress file, from its body items.
+ internal int ClusterShift(Reiser4Object file) => this.ReadBlock(file.Body[0].Block)[file.Body[0].BodyOffset];
+
+ ///
+ /// Each present logical cluster of a cryptcompress file: its start and its decoded bytes. Absent
+ /// clusters are holes.
+ ///
+ internal IEnumerable<(long Start, byte[] Bytes)> Clusters(Reiser4Object file) {
+ var size = (long)file.Stat.Size;
+ var compression = (Reiser4CompressionId)this.Plugin(file, Reiser4PsetMember.Compression);
+ foreach (var (index, shift, disk) in this.DiskClusters(file)) {
+ var start = index << shift;
+ if (start >= size) yield break;
+ var logical = (int)Math.Min(1L << shift, size - start);
+ yield return (start, Reiser4Clusters.Decode(disk, logical, compression));
+ }
+ }
+
+ /// Each disk cluster of a cryptcompress file as stored: index, shift and bytes.
+ internal IEnumerable<(long Index, int Shift, byte[] Disk)> DiskClusters(Reiser4Object file) {
+ using var current = new MemoryStream();
+ long index = -1;
+ var shift = 0;
+ ulong expected = 0;
+ foreach (var item in file.Body) {
+ var body = this.ReadBody(item);
+ var itemShift = body[0];
+ if (itemShift is < 12 or > 16) throw new InvalidDataException("Reiser4: a compressed body item names an unsupported cluster size.");
+ var itemIndex = (long)(item.Key.Offset >> itemShift);
+ if (itemIndex != index) {
+ if (index >= 0) yield return (index, shift, current.ToArray());
+ if (item.Key.Offset != (ulong)itemIndex << itemShift)
+ throw new InvalidDataException("Reiser4: a disk cluster does not start at its cluster's offset.");
+ current.SetLength(0);
+ index = itemIndex;
+ shift = itemShift;
+ expected = item.Key.Offset;
+ } else if (itemShift != shift || item.Key.Offset != expected)
+ throw new InvalidDataException("Reiser4: a disk cluster's items are not contiguous.");
+ current.Write(body, 1, body.Length - 1);
+ expected += (ulong)(body.Length - 1);
+ }
+ if (index >= 0) yield return (index, shift, current.ToArray());
+ }
+
+ /// Physical byte runs that hold a regular file's extent data.
+ internal IEnumerable<(long Offset, long Length)> DataRuns(Reiser4Object file) {
+ var remaining = (long)file.Stat.Size;
+ foreach (var (start, width) in this.ExtentUnits(file)) {
+ if (remaining <= 0) yield break;
+ var bytes = (long)Math.Min((ulong)remaining, width * BlockSize);
+ if (start != 0) yield return ((long)start * BlockSize, bytes);
+ remaining -= bytes;
+ }
+ }
+
+ public void Dispose() => this._image.Dispose();
+
+ /// Recomputes a node41 checksum in place.
+ internal static void SealNode41(Span node) => BinaryPrimitives.WriteUInt32LittleEndian(node[28..], NodeChecksum(node));
+
+ /// Recomputes a bitmap block's leading adler32.
+ internal static void SealBitmap(Span bitmap) => BinaryPrimitives.WriteUInt32LittleEndian(bitmap, Adler32.Compute(bitmap[4..]));
+}
diff --git a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Writer.cs b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Writer.cs
index 0e5b8e197..83171c2b7 100644
--- a/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Writer.cs
+++ b/Hawkynt.FileFormats.FileSystems/FileSystems/FileSystem.Reiser4/Reiser4Writer.cs
@@ -1,8 +1,5 @@
#pragma warning disable CS1591
-using System.Buffers.Binary;
-using System.Reflection;
using System.Text;
-using Compression.Core.Checksums;
using Compression.Core.DiskImage;
namespace FileSystem.Reiser4;
@@ -10,10 +7,10 @@ namespace FileSystem.Reiser4;
///
/// Creator for a Reiser4 filesystem image that starts from what
/// mkfs.reiser4 -fffy from reiser4progs 1.2.2 produces and adds
-/// directories and regular files through the native tree — stat data and directory
-/// entries in leaves, extents in twigs, as many internal levels above them as the
-/// tree needs — so that fsck.reiser4 validates the result as
-/// "FS is consistent." with or without files.
+/// directories, regular files, symbolic links, device nodes, FIFOs, sockets and hard links
+/// through the native tree — stat data, directory entries and tails in leaves, extents in twigs,
+/// as many internal levels above them as the tree needs — so that fsck.reiser4 validates
+/// the result as "FS is consistent." and a Reiser4 kernel mounts and reads it.
///
///
/// The image holds 25 reserved blocks at fixed positions (block size = 4 KB):
@@ -22,33 +19,20 @@ namespace FileSystem.Reiser4;
///
- 16 — master superblock ("ReIsEr4" at offset 65536).
/// - 17 — format40 superblock ("ReIsEr40FoRmAt" at offset 52).
/// - 18 — block-allocator bitmap (4-byte adler32 + bit array).
-/// - 19..20 — journal header / footer (zero for an empty FS).
+/// - 19..20 — journal header / footer (zero for an unjournalled volume).
/// - 21 — status block ("ReiSeR4StATusBl").
/// - 22 — superblock backup record.
-/// - 23 — storage-tree root (twig, level 2).
-/// - 24 — leaf containing the root-directory stat-data + ".", "..".
+/// - 23 — storage-tree root (twig, level 2, or higher).
+/// - 24 — first leaf (the root directory's stat data and entries).
///
///
///
///
-/// Implementation strategy: we embed the seven non-zero reference blocks as
-/// resources captured byte-exact from a real mkfs.reiser4 image, then
-/// patch in only the per-image fields:
-///
-///
-/// - UUID (16 bytes, random)
-/// - Label (≤ 16 bytes, optional)
-/// - mkfs_id (4 bytes, random) — appears in 4 places: format40
-/// SB, backup record, twig header, leaf header.
-/// - block_count / free_blocks (in format40 SB and backup).
-/// - Bitmap (block 18) — bits 0..24 set for the 25 reserved
-/// blocks plus filler bits for the unused tail of the bitmap range, then
-/// adler32 of the bitmap data prepended.
-///
-///
-///
-/// Round-trips with fsck.reiser4 -y exit 0 and produces output identical
-/// to the reference image except for the random fields above.
+/// The fixed blocks are byte-exact captures of a real mkfs.reiser4 image with only the
+/// per-image fields patched in: UUID, label, mkfs id, block and free-block counts, the root, the
+/// next object id, the file count and the tree height. Regular files are written as extents by
+/// default; selects tails, the kernel's smart policy or compressed
+/// (cryptcompress) files instead.
///
///
public sealed class Reiser4Writer {
@@ -62,65 +46,12 @@ public sealed class Reiser4Writer {
/// reference capture and avoid bitmap-truncation edge cases.
public const ulong MinBlockCount = 4096;
- /// Number of blocks the empty filesystem permanently occupies
- /// (jump area + master + format40 + bitmap + journal pair + status + backup
- /// + twig root + leaf).
private const ulong ReservedBlockCount = 25;
- // Field offsets — captured by inspecting the reference image with xxd.
- private const int MasterMagicOff = 0; // "ReIsEr4"
- private const int MasterFormatOff = 16; // d16 disk plugin id (= 0)
- private const int MasterBlksizeOff = 18; // d16 = 4096
- private const int MasterUuidOff = 20; // 16 bytes
- private const int MasterLabelOff = 36; // 16 bytes
-
- private const int F40BlockCountOff = 0;
- private const int F40FreeBlocksOff = 8;
- private const int F40RootBlockOff = 16;
- private const int F40OidNextOff = 24;
- private const int F40OidFileCountOff = 32;
- private const int F40FlushesOff = 40;
- private const int F40MkfsIdOff = 48;
- private const int F40MagicOff = 52; // "ReIsEr40FoRmAt"
- private const int F40TreeHeightOff = 68;
- private const int F40PolicyOff = 70;
- private const int F40FlagsOff = 72;
- private const int F40VersionOff = 80;
-
- // Backup record (block 22) — packed format-specific struct (not a direct copy of
- // master + format40 SBs). Reverse-engineered from the reference image:
- // 0x00 pad (1 byte)
- // 0x01-0x10 master ms_magic[16] ("ReIsEr4" + zeros)
- // 0x11-0x12 master ms_format (d16 = 0)
- // 0x13-0x14 master ms_blksize (d16 LE = 4096 → 00 10)
- // 0x15-0x24 master ms_uuid[16]
- // 0x25-0x34 master ms_label[16]
- // 0x35-0x3C reserved zeros
- // 0x3D-0x4C format40 sb_magic[16] ("ReIsEr40FoRmAt" + 2 NUL)
- // 0x4D-0x54 sb_block_count (d64)
- // 0x55-0x58 sb_mkfs_id (d32)
- // 0x59-0x5A sb_policy (d16)
- // 0x5B-0x62 sb_flags (d64)
- // 0x63-0x6F more — including a "PsEt" magic at 0x6F (PSET = plugin-set sentinel)
- // Note: backup struct does NOT carry sb_free_blocks — only block_count.
- private const int BackupUuidOff = 0x15; // 21
- private const int BackupBlkSizeOff = 0x13; // 19 — d16 (was master+18)
- private const int BackupLabelOff = 0x25; // 37
- private const int BackupF40BlockCountOff = 0x4D; // 77 — d64
- private const int BackupF40MkfsIdOff = 0x55; // 85 — d32
-
- // Tree-node header offsets — same for twig (block 23) and leaf (block 24).
- private const int NodeMkfsIdOff = 12; // d32
-
- /// The root directory's own object id, and the locality above it.
- /// Fixed: the tree this writer starts from is a byte-exact mkfs capture.
- private const ulong RootLocality = 0x29;
- private const ulong RootObjectId = 0x2a;
-
- // Bitmap (block 18)
- private const int BitmapAdlerOff = 0; // d32 adler32 over bytes 4..4095
- private const int BitmapDataOff = 4;
- private const int BitmapDataLength = BlockSize - 4; // 4092 bytes = 32736 bits
+ private const int MasterUuidOff = 20;
+ private const int MasterLabelOff = 36;
+ private const int BackupUuidOff = 0x15;
+ private const int BackupLabelOff = 0x25;
/// Customisable label written to the master SB (NUL-padded to 16
/// bytes; longer strings are truncated; null = empty/zero).
@@ -137,13 +68,11 @@ public sealed class Reiser4Writer {
/// .
public ulong BlockCount { get; set; } = MinBlockCount;
- // Native stat40/cde40 items live in leaves; extent40 items live in twigs.
- // Reiser4Tree packs additional nodes as needed, and allocator accounting covers
- // both file data and tree blocks. Derived layout and oracle evidence are in
- // docs/REISER4-NATIVE-PROFILE.md. The legacy constants below are retained only
- // for reading images made by the earlier private-directory writer.
+ /// How regular files are stored. follows the
+ /// captured mkfs profile, whose root names cryptcompress for new files.
+ public Reiser4FileBody FileBody { get; set; } = Reiser4FileBody.Extents;
- /// Marker written at of the master superblock.
+ /// Marker written at of the master superblock by the earliest workbench writer.
/// The value spells nothing: a marker that reads as words names whoever chose them.
internal static readonly byte[] PayloadMarker =
[0x8D, 0x17, 0x0C, 0xE1, 0x93, 0x1A, 0x0F, 0xB6, 0x81];
@@ -154,14 +83,11 @@ public sealed class Reiser4Writer {
/// Offset in the master superblock of the first directory block number (d64).
internal const int MasterPayloadDirOff = MasterPayloadMarkerOff + 12;
- /// Magic at the head of every payload directory block.
+ /// Magic at the head of every legacy payload directory block.
internal static readonly byte[] DirMagic =
[0x9E, 0x0B, 0x14, 0xA7, 0x02, 0xDB, 0x18, 0x8F];
- /// Directory block head: magic, next-block link, entry count.
internal const int DirHeadSize = 8 + 8 + 4;
-
- /// One directory entry: a 224-byte name, then the first data block and the byte length.
internal const int DirNameLength = 224;
internal const int DirEntrySize = DirNameLength + 8 + 8;
internal const int DirEntriesPerBlock = (BlockSize - DirHeadSize) / DirEntrySize;
@@ -172,55 +98,74 @@ public sealed class Reiser4Writer {
///
internal const ulong BlocksPerBitmap = (ulong)(BlockSize - 4) * 8;
- private readonly List<(string Name, FilePayload Payload, Reiser4Reader.FileMetadata? Metadata)> _files = [];
+ private readonly List> _edits = [];
+ private readonly HashSet _names = new(StringComparer.Ordinal);
- /// Adds a regular file to the payload area.
+ /// Adds a regular file.
public void AddFile(string name, byte[] data, Reiser4Reader.FileMetadata? metadata = null) {
- ValidateName(name);
ArgumentNullException.ThrowIfNull(data);
- this._files.Add((name, FilePayload.FromBytes(data), metadata));
+ this.Claim(name);
+ this._edits.Add(plan => plan.AddFile(name, FilePayload.FromBytes(data), metadata));
}
/// Adds a file whose bytes are pulled from as the image is written.
public void AddStreamingFile(string name, long size, Func openStream, Reiser4Reader.FileMetadata? metadata = null) {
- ValidateName(name);
ArgumentNullException.ThrowIfNull(openStream);
- this._files.Add((name, FilePayload.FromStream(size, openStream), metadata));
+ this.Claim(name);
+ this._edits.Add(plan => plan.AddFile(name, FilePayload.FromStream(size, openStream), metadata));
}
- /// Validates the path components supported by the native namespace writer.
- internal static string? RejectName(string? name) {
- if (string.IsNullOrEmpty(name)) return "an entry needs a name";
- var components = name.Replace('\\', '/').Split('/');
- if (components.Length > 129) return "this profile supports at most 129 path components";
- if (components.Any(static component => component.Length == 0 || component is "." or ".."))
- return "path components must be non-empty and cannot be dot entries";
- if (name.Contains('\0') || name.Contains(':') || name.Any(static c => c > 127))
- return "this profile requires ASCII names without NUL or colon";
- return null;
- }
-
- private readonly Dictionary _directories = new(StringComparer.Ordinal);
-
/// Retains an explicit directory, including an empty directory.
public void AddDirectory(string name, Reiser4Reader.FileMetadata? metadata = null) {
var normalized = name.Replace('\\', '/').TrimEnd('/');
if (normalized.Length > 0 && RejectName(normalized) is { } reason)
throw new NotSupportedException("Reiser4: " + reason + ".");
- this._directories[normalized] = metadata;
+ this._edits.Add(plan => plan.AddDirectory(normalized, metadata));
+ }
+
+ /// Adds a symbolic link whose target is .
+ public void AddSymlink(string name, string target, Reiser4Reader.FileMetadata? metadata = null) {
+ ArgumentNullException.ThrowIfNull(target);
+ this.Claim(name);
+ this._edits.Add(plan => plan.AddSymlink(name, target, metadata));
+ }
+
+ /// Adds a device node, FIFO or socket; carries the file type bits.
+ public void AddSpecialFile(string name, ushort mode, ulong device = 0, Reiser4Reader.FileMetadata? metadata = null) {
+ this.Claim(name);
+ this._edits.Add(plan => plan.AddSpecial(name, mode, device, metadata));
+ }
+
+ /// Adds as a further name of the file at .
+ public void AddHardLink(string name, string existing) {
+ ArgumentNullException.ThrowIfNull(existing);
+ this.Claim(name);
+ this._edits.Add(plan => plan.AddHardLink(name, existing));
}
- private void ValidateName(string name) {
+ private void Claim(string name) {
if (RejectName(name) is { } reason)
throw new NotSupportedException("Reiser4: " + reason + ".");
- if (this._files.Any(f => f.Name.Replace('\\', '/').Equals(name.Replace('\\', '/'), StringComparison.Ordinal)))
+ if (!this._names.Add(name.Replace('\\', '/')))
throw new ArgumentException($"Reiser4: '{name}' is already in the root directory.", nameof(name));
}
+ /// Validates the path components supported by the native namespace writer.
+ internal static string? RejectName(string? name) {
+ if (string.IsNullOrEmpty(name)) return "an entry needs a name";
+ var components = name.Replace('\\', '/').Split('/');
+ if (components.Length > 129) return "this profile supports at most 129 path components";
+ if (components.Any(static component => component.Length == 0 || component is "." or ".."))
+ return "path components must be non-empty and cannot be dot entries";
+ if (name.Contains('\0') || name.Contains(':') || name.Any(static c => c > 127))
+ return "this profile requires ASCII names without NUL or colon";
+ if (components.Any(static component => component.Length > 255)) return "a name is longer than 255 bytes";
+ return null;
+ }
+
///
- /// Smallest block count that holds : the reserved
- /// blocks, the directory chain, every file's data blocks, and the bitmap blocks
- /// interleaved among them.
+ /// Smallest block count that holds : the reserved blocks, every
+ /// file's data blocks, the tree, and the bitmap blocks interleaved among them.
///
public static ulong EstimateBlockCount(IEnumerable fileSizes) {
ArgumentNullException.ThrowIfNull(fileSizes);
@@ -229,26 +174,18 @@ public static ulong EstimateBlockCount(IEnumerable fileSizes) {
blocks += (ulong)((sizes.Count + DirEntriesPerBlock - 1) / Math.Max(1, DirEntriesPerBlock));
foreach (var size in sizes)
blocks += (ulong)((size + BlockSize - 1) / BlockSize);
- blocks += blocks / BlocksPerBitmap + 2; // the strided bitmap blocks
+ blocks += blocks / BlocksPerBitmap + 2;
return Math.Max(MinBlockCount, blocks + blocks / 20);
}
- /// True when holds a block-allocator bitmap.
- private static bool IsBitmapBlock(ulong block)
- => block == 18 || (block != 0 && block % BlocksPerBitmap == 0);
-
- /// Builds the image fully in memory and returns the byte array.
- /// For block counts above ~32 K the result will be tens of MB; prefer the
- /// streaming overload when caller-side allocation matters.
+ /// Builds the image fully in memory and returns the byte array.
public byte[] Build() {
using var ms = new MemoryStream();
this.Write(ms);
return ms.ToArray();
}
- /// Streams the full image into . Writes
- /// ×4096 bytes and leaves the stream positioned at
- /// the end.
+ /// Streams the full image into and leaves the stream positioned at the end.
public void Write(Stream output) {
ArgumentNullException.ThrowIfNull(output);
if (!output.CanSeek) {
@@ -259,204 +196,33 @@ public void Write(Stream output) {
output.Flush();
return;
}
- var blocks = Math.Max(this.BlockCount, MinBlockCount);
- var totalBytes = checked((long)blocks * BlockSize);
+ var plan = this.CreatePlan();
+ foreach (var edit in this._edits) edit(plan);
+ plan.Write(output);
+ }
+ /// The empty volume: the captured mkfs blocks with this writer's identity patched in.
+ internal Reiser4Plan CreatePlan() {
var uuid = this.Uuid ?? Guid.NewGuid().ToByteArray(bigEndian: true);
if (uuid.Length != 16)
throw new ArgumentException("UUID must be exactly 16 bytes.", nameof(this.Uuid));
var mkfsId = this.MkfsId ?? unchecked((uint)Random.Shared.Next(int.MinValue, int.MaxValue));
var label = TrimLabel(this.Label);
- // Templates are byte-exact 4 KB captures from `mkfs.reiser4 -fffy` on a 4096-block
- // image, so the patches below are pure overrides of variable fields.
- var blk16 = LoadTemplate(16);
- var blk17 = LoadTemplate(17);
- var blk18 = LoadTemplate(18);
- var blk21 = LoadTemplate(21);
- var blk22 = LoadTemplate(22);
- var blk23 = LoadTemplate(23);
- var blk24 = LoadTemplate(24);
-
- // ── Master superblock (block 16) ─────────────────────────────────────
- uuid.AsSpan().CopyTo(blk16.AsSpan(MasterUuidOff, 16));
- Array.Clear(blk16, MasterLabelOff, 16);
- label.AsSpan().CopyTo(blk16.AsSpan(MasterLabelOff, 16));
-
- // ── Format40 SB (block 17) ───────────────────────────────────────────
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40BlockCountOff, 8), blocks);
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40FreeBlocksOff, 8), blocks - ReservedBlockCount);
- BinaryPrimitives.WriteUInt32LittleEndian(blk17.AsSpan(F40MkfsIdOff, 4), mkfsId);
-
-
- // ── Backup record (block 22) ─────────────────────────────────────────
- uuid.AsSpan().CopyTo(blk22.AsSpan(BackupUuidOff, 16));
- Array.Clear(blk22, BackupLabelOff, 16);
- label.AsSpan().CopyTo(blk22.AsSpan(BackupLabelOff, 16));
- BinaryPrimitives.WriteUInt64LittleEndian(blk22.AsSpan(BackupF40BlockCountOff, 8), blocks);
- BinaryPrimitives.WriteUInt32LittleEndian(blk22.AsSpan(BackupF40MkfsIdOff, 4), mkfsId);
-
- // ── Tree nodes — twig (block 23) and leaf (block 24) ─────────────────
- BinaryPrimitives.WriteUInt32LittleEndian(blk23.AsSpan(NodeMkfsIdOff, 4), mkfsId);
- BinaryPrimitives.WriteUInt32LittleEndian(blk24.AsSpan(NodeMkfsIdOff, 4), mkfsId);
-
- // ── Native file data blocks ─────────────────────────────────────────
- // Allocations step over the strided bitmap blocks, which the bitmap pass below then
- // marks along with everything else in use.
- var cursor = ReservedBlockCount;
- ulong Alloc() {
- while (IsBitmapBlock(cursor)) ++cursor;
- blocks = Math.Max(blocks, checked(cursor + 1));
- return cursor++;
- }
-
- // No private directory chain any more: the native tree names every file, and
- // blocks that the tree does not reach but the bitmap marks used are exactly
- // what fsck.reiser4 reports as a bitmap mismatch. Readers keep understanding
- // the chain in images written before.
- var payloads = new DeferredPayloads();
- // The same runs the payload area is made of become the extents of the file in
- // the tree — one file's bytes, described twice, sitting in one place.
- var treeFiles = new List(this._files.Count);
- var nextObjectId = RootObjectId + 1;
- foreach (var (name, payload, metadata) in this._files) {
- var need = (payload.Size + BlockSize - 1) / BlockSize;
- var first = need > 0 ? Alloc() : 0UL;
- // A file's blocks are consecutive apart from any bitmap they straddle, so
- // the body is recorded as one payload per contiguous stretch.
- var runs = new List();
- var runStart = first;
- var runBlocks = need > 0 ? 1L : 0L;
- var written = 0L;
- for (var i = 1L; i < need; ++i) {
- var next = Alloc();
- if (next == runStart + (ulong)runBlocks) { ++runBlocks; continue; }
- AddRun(payloads, payload, runStart, runBlocks, ref written);
- runs.Add(new Reiser4Tree.Run(runStart, (ulong)runBlocks));
- runStart = next;
- runBlocks = 1;
- }
- if (runBlocks > 0) {
- AddRun(payloads, payload, runStart, runBlocks, ref written);
- runs.Add(new Reiser4Tree.Run(runStart, (ulong)runBlocks));
- }
-
- treeFiles.Add(new Reiser4Tree.Entry {
- Name = name, ParentObjectId = RootObjectId, ObjectId = nextObjectId++, Size = payload.Size, Runs = runs, Metadata = metadata,
- });
- }
-
- // ── The tree itself ──────────────────────────────────────────────────
- // Every file gets a stat data and its extents, and the root directory an entry
- // naming it — so what the volume holds is what a reader of the format finds,
- // not only what our own reader knows to look for.
- var tree = Reiser4Tree.Build(blk24, BlockSize, mkfsId, (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
- RootLocality, RootObjectId, treeFiles, this._directories, Alloc);
- blk23 = tree.Nodes[23];
- blk24 = tree.Nodes[24];
- BinaryPrimitives.WriteUInt16LittleEndian(blk17.AsSpan(F40TreeHeightOff), tree.Height);
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40OidNextOff), tree.NextObjectId);
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40OidFileCountOff), tree.ObjectCount);
- totalBytes = checked((long)blocks * BlockSize);
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40BlockCountOff), blocks);
- BinaryPrimitives.WriteUInt64LittleEndian(blk22.AsSpan(BackupF40BlockCountOff), blocks);
-
- var usedBlocks = cursor; // every block below the cursor is reserved or payload
-
- // ── Free-block accounting and the bitmap blocks ──────────────────────
- var tailBitmapBlocks = (blocks - 1) / BlocksPerBitmap - (usedBlocks - 1) / BlocksPerBitmap;
- BinaryPrimitives.WriteUInt64LittleEndian(blk17.AsSpan(F40FreeBlocksOff, 8), blocks - usedBlocks - tailBitmapBlocks);
- var bitmaps = BuildBitmaps(blocks, usedBlocks, blk18);
-
- // ── Emit the metadata prefix, then the payload ───────────────────────
- var basePosition = output.CanSeek ? output.Position : 0;
- var firstDataBlock = ReservedBlockCount;
- var zero = new byte[BlockSize];
- for (var b = 0UL; b < firstDataBlock; b++) {
- var buf = b switch {
- 16 => blk16,
- 17 => blk17,
- 18 => blk18,
- 21 => blk21,
- 22 => blk22,
- 23 => blk23,
- 24 => blk24,
- _ => zero,
- };
- output.Write(buf, 0, BlockSize);
- }
- output.Flush();
+ var master = LoadTemplate(16);
+ uuid.AsSpan().CopyTo(master.AsSpan(MasterUuidOff, 16));
+ Array.Clear(master, MasterLabelOff, 16);
+ label.AsSpan().CopyTo(master.AsSpan(MasterLabelOff, 16));
- output.SetLength(basePosition + totalBytes);
- foreach (var (block, bytes) in bitmaps) {
- if (block < firstDataBlock) continue; // already emitted in the prefix
- output.Position = basePosition + (long)block * BlockSize;
- output.Write(bytes);
- }
- foreach (var (block, node) in tree.Nodes) {
- if (block is 23 or 24) continue;
- output.Position = basePosition + checked((long)block * BlockSize);
- output.Write(node);
- }
- payloads.FlushTo(output, basePosition);
- output.Position = basePosition + totalBytes;
- output.Flush();
- }
+ var backup = LoadTemplate(22);
+ uuid.AsSpan().CopyTo(backup.AsSpan(BackupUuidOff, 16));
+ Array.Clear(backup, BackupLabelOff, 16);
+ label.AsSpan().CopyTo(backup.AsSpan(BackupLabelOff, 16));
- /// Records one contiguous run of a file's blocks as a payload to copy.
- private static void AddRun(DeferredPayloads payloads, FilePayload payload,
- ulong firstBlock, long blockCount, ref long written) {
- var length = Math.Min(blockCount * BlockSize, payload.Size - written);
- if (length <= 0) return;
- var skip = written;
- payloads.Add((long)firstBlock * BlockSize,
- FilePayload.FromStream(length, () => SkipTo(payload.Open(), skip)));
- written += blockCount * BlockSize;
- }
-
- /// Advances to , reading through when it cannot seek.
- private static Stream SkipTo(Stream source, long offset) {
- if (offset <= 0) return source;
- if (source.CanSeek) {
- source.Position = offset;
- return source;
- }
- var buffer = new byte[64 * 1024];
- var remaining = offset;
- while (remaining > 0) {
- var n = source.Read(buffer, 0, (int)Math.Min(buffer.Length, remaining));
- if (n <= 0) break;
- remaining -= n;
- }
- return source;
- }
-
- ///
- /// Builds every block-allocator bitmap. Bitmap i covers blocks
- /// [i × BlocksPerBitmap, (i+1) × BlocksPerBitmap); the first lives at the
- /// reserved block 18 and the rest at the stride boundaries. Blocks below
- /// are allocated, as is every bitmap block and
- /// everything past the end of the filesystem — an out-of-range bit must read as
- /// 1 or the allocator would hand out a block that is not there.
- ///
- private static List<(ulong Block, byte[] Bytes)> BuildBitmaps(ulong blocks, ulong usedBlocks, byte[] first) {
- var result = new List<(ulong Block, byte[] Bytes)>();
- var count = (blocks + BlocksPerBitmap - 1) / BlocksPerBitmap;
- for (var i = 0UL; i < count; ++i) {
- var block = i == 0 ? 18UL : i * BlocksPerBitmap;
- var buf = i == 0 ? first : new byte[BlockSize];
- Array.Clear(buf, 0, buf.Length);
- var baseBlock = i * BlocksPerBitmap;
- for (var bit = 0UL; bit < BlocksPerBitmap; ++bit) {
- var target = baseBlock + bit;
- if (target >= usedBlocks && target < blocks && !IsBitmapBlock(target)) continue;
- buf[BitmapDataOff + (int)(bit >> 3)] |= (byte)(1 << (int)(bit & 7));
- }
- var adler = Adler32.Compute(buf.AsSpan(BitmapDataOff, BitmapDataLength));
- BinaryPrimitives.WriteUInt32LittleEndian(buf.AsSpan(BitmapAdlerOff, 4), adler);
- result.Add((block, buf));
- }
- return result;
+ var plan = Reiser4Plan.Fresh(master, LoadTemplate(17), LoadTemplate(21), backup, LoadTemplate(24), mkfsId,
+ Math.Max(this.BlockCount, MinBlockCount));
+ plan.FileBody = this.FileBody;
+ return plan;
}
private static byte[] TrimLabel(string? label) {
@@ -465,51 +231,7 @@ private static byte[] TrimLabel(string? label) {
return bytes.Length <= 16 ? bytes : bytes[..16];
}
- ///
- /// Why the fixed blocks of an existing volume describe something this writer would not
- /// write back, or when a rebuild reproduces them.
- ///
- ///
- /// A rebuild writes the captured mkfs prefix again with only the volume's identity
- /// patched in, so every other byte of those blocks has to be what the source already
- /// holds. That is where a volume made with another profile shows: the format40 tail
- /// policy, and the plugin set the backup record keeps of the root directory's — hash,
- /// fibration, formatting. Writing the default profile over them leaves the root's own
- /// plugin set disagreeing with its backup, which fsck.reiser4 reports, and names
- /// keyed with a hash the volume does not use, which nothing can look up.
- /// A status block other than "consistent" marks a volume the tools found damaged,
- /// and a journal header or footer that is not blank belongs to a volume the kernel
- /// wrote, whose transactions this reader does not replay. Both are left alone rather
- /// than silently rewritten.
- ///
- internal static string? ProfileMismatch(Func readBlock) {
- ArgumentNullException.ThrowIfNull(readBlock);
- static bool SameOutside(ReadOnlySpan actual, ReadOnlySpan template, params (int Start, int End)[] volatileRanges) {
- if (actual.Length != template.Length) return false;
- for (var i = 0; i < template.Length; ++i)
- if (actual[i] != template[i] && !volatileRanges.Any(range => i >= range.Start && i < range.End))
- return false;
- return true;
- }
-
- // Master: uuid, label and the legacy payload marker and pointer that follow them.
- if (!SameOutside(readBlock(16), LoadTemplate(16), (MasterUuidOff, MasterPayloadDirOff + 8)))
- return "the master superblock carries fields this writer does not reproduce";
- // Format40: the counters, the root, the mkfs id and the tree height move; magic,
- // tail policy, flags and version are the profile.
- if (!SameOutside(readBlock(17), LoadTemplate(17), (F40BlockCountOff, F40MagicOff), (F40TreeHeightOff, F40PolicyOff)))
- return "the volume uses a tail policy or format40 flags other than the default profile";
- if (readBlock(19).Any(static b => b != 0) || readBlock(20).Any(static b => b != 0))
- return "the journal is not blank, and its transactions are not replayed";
- if (!SameOutside(readBlock(21), LoadTemplate(21)))
- return "the status block does not mark the volume consistent";
- if (!SameOutside(readBlock(22), LoadTemplate(22), (BackupUuidOff, BackupLabelOff + 16),
- (BackupF40BlockCountOff, BackupF40MkfsIdOff + 4)))
- return "the root directory's plugin set (hash, fibration or formatting) is not the default profile";
- return null;
- }
-
- private static byte[] LoadTemplate(int blockNumber) {
+ internal static byte[] LoadTemplate(int blockNumber) {
var resource = $"FileSystem.Reiser4.Templates.block_{blockNumber}.bin";
var asm = typeof(Reiser4Writer).Assembly;
using var stream = asm.GetManifestResourceStream(resource)
diff --git a/Hawkynt.FileFormats.FileSystems/README.md b/Hawkynt.FileFormats.FileSystems/README.md
index 4ee792651..13ef79ca6 100644
--- a/Hawkynt.FileFormats.FileSystems/README.md
+++ b/Hawkynt.FileFormats.FileSystems/README.md
@@ -131,7 +131,7 @@ The `Id`, `State` and verb columns are read off the descriptors by `FilesystemRe
| [OCFS2 (Oracle Cluster Filesystem 2)](https://en.wikipedia.org/wiki/OCFS2) | `Ocfs2` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | Linux kernel `ocfs2` driver (libguestfs appliance) mounts the written volume and reads the tree back byte-identical with modes, owners and times; [`fsck.ocfs2 -fn`](https://github.com/markfasheh/ocfs2-tools) clean before and after a kernel read-write mount, and after in-place add / replace / remove (nested too) / defrag / shrink on our volumes and on `mkfs.ocfs2 -M local` volumes filled by the kernel; kernel-written files with extent trees of depth 1 and 2 extract with the kernel's SHA-256 | Single-node (local) volumes; in-place edits cover files in inline directories (missing directories are made), extent-backed directories are refused; shrink trims the free tail in place; journal at least the kernel's 4 MiB minimum | [OCFS2](https://www.kernel.org/doc/html/latest/filesystems/ocfs2.html) |
| [QNX4 FS](https://en.wikipedia.org/wiki/QNX4FS) | `Qnx4` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | own reader + struct-parity tests | — | [qnx4](https://www.kernel.org/doc/html/latest/filesystems/qnx4.html) |
| [QNX6 Neutrino FS](https://en.wikipedia.org/wiki/QNX6FS) | `Qnx6` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | own reader + struct-parity tests | — | [qnx6](https://www.kernel.org/doc/html/latest/filesystems/qnx6.html) |
-| [Reiser4](https://en.wikipedia.org/wiki/Reiser4) | `Reiser4` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | `fsck.reiser4 --check` + `debugfs.reiser4` (WSL-gated): trees up to height 4, nested/empty directories, bytes read through the tools' own lookup; edits on `mkfs.reiser4` volumes and on trees `fsck.reiser4 --build-fs` rewrote | Multi-level node40 trees with nested and empty directories; edits rebuild the volume keeping UUID, label, mkfs id, object IDs and stat data; volumes of another plugin profile (hash, fibration, tail policy) are read but not rewritten; defrag moves in place only for a two-node tree | [Reiser4](https://reiser4.wiki.kernel.org/) |
+| [Reiser4](https://en.wikipedia.org/wiki/Reiser4) | `Reiser4` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | `fsck.reiser4 --check` + `debugfs.reiser4` (CI gate) on every `mkfs.reiser4 -o` profile; a Reiser4 kernel (Linux 5.4 + SFRN 4.0.2 under QEMU) mounts and reads back every volume the writer makes or edits, and wrote the 13 reference volumes the reader is checked against | Every plugin profile (r5/tea/fnv1/deg/rupasov hashes, all four fibrations, tails/extents/smart, node40/node41, cryptcompress with lzo1/gzip1/zstd1, 4K–64K clusters); extents with holes, tails and compressed clusters; symlinks, device nodes, FIFOs, sockets, hard links; journal replay; edits keep identity, keys and every stat byte; in-place defrag on trees of any height; new long names refused under the Rupasov hash; encrypted files, short keys and other block sizes refused | [Reiser4](https://reiser4.wiki.kernel.org/) |
| [ReiserFS](https://en.wikipedia.org/wiki/ReiserFS) | `ReiserFs` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | [`reiserfsck`](https://git.kernel.org/pub/scm/linux/kernel/git/jeffm/reiserfsprogs.git), also after mutation | ReiserFS 3.6; edits rebuild the tree | [ReiserFS documentation](https://www.kernel.org/doc/html/latest/filesystems/reiserfs.html) |
| [TUX2](https://en.wikipedia.org/wiki/Tux2) | `Tux2` | R/W | ✅ | ✅ moving | — | ✅ | ✅ | — | ✅ | own reader + struct-parity tests | Phase-tree filesystem | [Tux2](https://en.wikipedia.org/wiki/Tux2) |
| [TUX3](https://en.wikipedia.org/wiki/Tux3) | `Tux3` | R | ✅ | — | — | ✅ | ✅ | — | — | own reader + struct-parity tests | — | [Tux3](https://github.com/OGAWAHirofumi/tux3) |
@@ -285,7 +285,7 @@ ops.Remove(image, ["var/log/old.log"]);
-Every public and protected member of all 890 types, generated from the built assembly and its XML documentation, is in [REFERENCE.md](https://github.com/Hawkynt/CompressionWorkbench/blob/main/Hawkynt.FileFormats.FileSystems/REFERENCE.md).
+Every public and protected member of all 892 types, generated from the built assembly and its XML documentation, is in [REFERENCE.md](https://github.com/Hawkynt/CompressionWorkbench/blob/main/Hawkynt.FileFormats.FileSystems/REFERENCE.md).
@@ -336,7 +336,7 @@ cwb recover raw.img --mode files --format Jpeg,Png
- Where **Notes** says a format's edits *rebuild* the volume, an add or remove costs the whole image rather than the bytes that changed, and the block placement of untouched files may move.
- **bcachefs** creation, in-place add/replace, reading and extraction preserve inode timestamps (to 100 ns, before the epoch and past 2038), UID/GID and permission bits when supplied through the archive-input metadata; ordinary file-backed inputs capture available host timestamps and mode automatically. Applying UID/GID on extraction depends on host APIs and is not available through the portable .NET filesystem API. Volumes are written at metadata version 1.3, the newest the distributions' bcachefs-tools open, so their `fsck` can judge them; newer tools upgrade such a volume as they open it. Mutation is profile-gated: the in-place writer owns single-device regular pointer extents as emitted by this package, and re-publishes every tree from what it read, so a volume another implementation wrote (packed keys, appended bsets, a journal with keys in it, another metadata version) is refused for mutation with the reason and left untouched; it is still read, including packed and multi-bset nodes, sparse files and symbolic links. Compressed and encrypted extents are recognised and refused per file, not decoded. Bucket generations are carried through a mutation: emptying a bucket advances its generation, and the alloc key, the `bucket_gens` slot, the extent pointer and its backpointer are written from one source and checked against each other before the commit is published. Foreign volumes with extra live b-trees, non-canonical `bucket_gens` or `alloc_v4` keys, inline / reflink / compressed extent keys, or unsupported inode and dirent types are refused for mutation rather than rewritten speculatively; read support is broader. What a volume carries and how each value was established is written up in [BCACHEFS-ON-DISK.md](https://github.com/Hawkynt/CompressionWorkbench/blob/main/docs/BCACHEFS-ON-DISK.md).
- **ReFS** edits are offline-quiescent: the image must not be mounted, and `RefsMutationMode.NativeCow` stays fail-closed. The reader walks ReFS 3.x containers, MSB+ trees, allocators, Block Refcount rows and MLog framing; the offline editor relocates data and metadata pages, replaces and removes regular files and empty directories through CoW B+ replacement and alternate-checkpoint publication. Block Refcount row creation and whole-file clone semantics are implemented and tested: `RefsOfflineBlockCloner.CloneWholeFile` repoints an existing destination stream at an existing, equal-sized, cluster-aligned source stream, materialises the shared-cluster reference counts — including the first clone of a slot the sparse table does not yet track — and publishes Object Table root #0 and Block Refcount root #6 through one alternate checkpoint, reclaiming the destination's former allocation only once that checkpoint is durable. Writing to a clone afterwards reallocates rather than overwriting the shared clusters. **No public verb reaches this primitive**: it is a library entry point, not something `cwb` can be asked to do, and the profile is deliberately narrower than `FSCTL_DUPLICATE_EXTENTS_TO_FILE` — resident, sparse, integrity, zero-length, already-shared and partial-range clones are all refused. Still open before a mounted driver could use the same core: redo-payload codecs and replay for every opcode, every Schema Table key rule, the allocation-zone policies of the three allocators, container create / delete / move, partial-range and EOF-extending clones, hard links, sparse and integrity-stream mutation beyond 4 KiB clusters, snapshots, ADS, security descriptors, reparse points, USN, rename, truncate, a format path, locking and a Windows `chkdsk` corpus.
-- **Reiser4** R/W writes and reads node40 trees with as many leaves, twigs and internal levels as the namespace needs, nested and empty directories, and extents in twig nodes. Edits, defrag, shrink and relayout are staged rebuilds that keep the volume's UUID, label and mkfs id, every object ID, mode, owner, timestamps and declared stat-data extensions (large times, flags, plugin and heir sets); `UpdateMetadata` sets mode, owner and timestamps the same way and refuses link-count or extension changes. `fsck.reiser4` calls trees of height 3 and 4 consistent before and after those edits, and file bytes agree with where `debugfs.reiser4` finds them. A rebuild is refused, the image untouched, when the volume uses another plugin profile (a hash, fibration or tail policy other than mkfs's default), has a non-blank journal or a status other than consistent, or holds items outside the profile — tails, ctails, xattr items, symlinks, other stat-data extensions, sparse or shared files, non-ASCII names, short keys. No Reiser4-capable kernel was reachable, so nothing was mounted. Older private payload-chain images remain readable. See [native profile notes](https://github.com/Hawkynt/CompressionWorkbench/blob/main/docs/REISER4-NATIVE-PROFILE.md).
+- **Reiser4** R/W reads and writes node40 and node41 (checksummed) trees of any height under every plugin profile `mkfs.reiser4 -o` can set: directory entries are keyed with the directory's own hash (r5, tea, fnv1, deg) and fibration (lexic, dot_o, ext_1, ext_3), and the tail policy, root plugin set and backup block are carried. File bodies are extents (holes kept as holes), tails, or cryptcompress clusters compressed with lzo1, gzip1 or zstd1 at 4–64 KiB; symlinks, device nodes, FIFOs, sockets and hard links are read and written. A journal holding committed but unflushed transactions is replayed before reading, and an edit writes the replayed state. Edits, defrag, shrink and relayout are staged: the volume is read whole, edited as a plan, written to scratch, read back and verified, and only then copied over the source — refusals leave it byte-identical. New regular files are extents unless `FileBody` asks for tails, the smart policy, compressed files or the volume's own profile. Defragmentation moves extent data in place on trees of any height (twig units repointed, allocator bits moved), falling back to a rebuild when the journal is pending. A Reiser4 kernel (Linux 5.4.18 with the SFRN 4.0.2 patch, under QEMU) wrote the 13 reference volumes the reader is checked against and reads back every volume the writer makes or edits; `fsck.reiser4` calls them consistent. Refused: names longer than 23 bytes under the Rupasov hash (the kernel and reiser4progs compute it differently), encrypted files, short keys, block sizes other than 4096, damaged volumes. See [native profile notes](https://github.com/Hawkynt/CompressionWorkbench/blob/main/docs/REISER4-NATIVE-PROFILE.md).
- **GFS2** R/W is the standalone `lock_nolock` profile with regular files in the root directory; small files are stuffed and larger files use the indirect tree. Existing-image edits rebuild the volume while preserving its size floor, lock-table value, UUID and each regular file's mode, owner, timestamps (with nanoseconds) and access-policy flags; layout-changing flags such as JDATA are not carried over because the rebuilt file is laid out plainly. Directory attributes are not preserved. ExHash/nested-directory writing, journal replay, cluster-lock-manager state and extended attributes remain out of scope.
- **NSS** native read support is intentionally narrow and quiescent: the reader reconstructs validated DirH/LEAF namespace relationships and ordinary contiguous file extents using the OES-derived clean-room profile in [NSS-ON-DISK.md](https://github.com/Hawkynt/CompressionWorkbench/blob/main/docs/NSS-ON-DISK.md), while retaining anchor diagnostics for unsupported images. Native allocation trees, journals, trustee metadata, ZLBH history, compressed/sparse/fragmented data profiles and writable NSS pools remain out of scope; the existing writer still emits a private Workbench container rather than a pool NetWare/OES would mount.
- **HFS+** is listed as a POSIX system shows it: a catalog '/' appears as ':' (and a ':' given to the writer is stored as '/'), file hard links carry their indirect node's data under every name, directory hard links (Time Machine snapshots) are directories holding their inode's content wherever they are linked — a link back into a directory being listed is shown but not entered, and the links add at most a million entries — and the metadata directories and journal files are left out. `.HFS+ Private Directory Data` stays visible only while it holds something no link reaches. A journal that holds transactions is replayed into what is listed and extracted, the image untouched, stopping where Apple's replay does: at the first damaged block list, dropping the transaction last opened before it. hfsprogs' `fsck.hfsplus` does not replay journals, so the replay is checked by writing it out and having fsck accept the result; no other independent replay was available. Every decmpfs (HFS+ transparent compression) method is read: 1, 3/4 zlib, 5 (zeros, as libfshfs reads it), 7/8 LZVN, 9/10 raw, 11/12 LZFSE and 13/14 LZBITMAP; a dataless placeholder (0x80000001/0x80000002) has no local content and lists and extracts as empty, with `Kind` `dataless`. The writer's `Compression` option (default `None`) stores files compressed with any of those methods except 5 and the dataless types, which do not encode given content: inline in the attribute when the encoding fits (3802 bytes, files up to 64 KiB), otherwise as 64 KiB resource-fork chunks; a file that would not shrink stays uncompressed. libfshfs reads the zlib, LZVN, LZFSE and raw volumes byte for byte, 7-Zip the zlib and LZVN ones, HFSExplorer the zlib one; none of them, nor hfsfuse or Apple's open-source fsck_hfs, implements method 1 or LZBITMAP, so those two have no independent HFS+ reader here (the LZBITMAP stream itself is checked against dissect.util). The in-place editor repacks the catalog, extents overflow and attributes B-trees after each edit, growing a B-tree file into free space (one more extent at most per growth, up to eight), so an add may split nodes and a removal may empty a leaf. It adds files at any path, creating missing folders, optionally compressed (`HfsPlusModifier.AddFile` with an `HfsPlusCompression`) and with extended attributes (inline when they fit an attributes node, else in an attribute fork); data that no single free run holds is spread over several, the runs past the eighth recorded in the extents overflow file. Removing a file removes its extended attributes, decmpfs attribute, resource fork and overflow records and frees every block they own. On a case-folding volume a name differing only in case replaces the file; on a case-sensitive HFSX volume it is a second file. Refused, the volume untouched: removing or replacing a hard link or directory hard link, anything in the metadata directories, a fork whose extents do not add up to its block count, a special file continued in the extents overflow file, and any in-place write — edit, defragmentation, wipe — on a volume whose journal holds transactions; a journal that is empty stays empty and valid. Defragmentation leaves the journal files where the volume header points. fsck.hfsplus accepts volumes edited each of these ways, including `mkfs.hfsplus -J`, `-s` and `-s -J` volumes and the hdiutil volume, and libfshfs reads every file and extended attribute back. On extraction, characters the host cannot hold in a file name (on Windows `: < > " | ? *`, control characters, trailing dots and blanks) become `_`, as for every format.
diff --git a/Hawkynt.FileFormats.FileSystems/REFERENCE.md b/Hawkynt.FileFormats.FileSystems/REFERENCE.md
index 21439cab7..cb0389988 100644
--- a/Hawkynt.FileFormats.FileSystems/REFERENCE.md
+++ b/Hawkynt.FileFormats.FileSystems/REFERENCE.md
@@ -12531,63 +12531,79 @@ Performs the bounded offline ReFS block-clone operation for two existing, equal-
### Namespace `FileSystem.Reiser4`
-[`Reiser4BlockMover`](#reiser4blockmover) · [`Reiser4FormatDescriptor`](#reiser4formatdescriptor) · [`Reiser4MasterSb`](#reiser4mastersb) · [`Reiser4Reader`](#reiser4reader) · [`Reiser4Reader.Entry`](#reiser4readerentry) · [`Reiser4Reader.FileMetadata`](#reiser4readerfilemetadata) · [`Reiser4Writer`](#reiser4writer)
+[`Reiser4BlockMover`](#reiser4blockmover) · [`Reiser4FileBody`](#reiser4filebody) · [`Reiser4FormatDescriptor`](#reiser4formatdescriptor) · [`Reiser4MasterSb`](#reiser4mastersb) · [`Reiser4Reader`](#reiser4reader) · [`Reiser4Reader.Entry`](#reiser4readerentry) · [`Reiser4Reader.EntryKind`](#reiser4readerentrykind) · [`Reiser4Reader.FileMetadata`](#reiser4readerfilemetadata) · [`Reiser4Writer`](#reiser4writer)
#### `Reiser4BlockMover`
-Moves a file's blocks inside a Reiser4 payload area and rewrites the directory entry that said where it started.
+Moves the data blocks of a Reiser4 volume's extent files in place and repoints the extent units that name them, wherever in the tree their twig nodes sit.
Implements `IFilesystemBlockMover`.
| Member | Signature | Summary |
| --- | --- | --- |
| `Reiser4BlockMover` | `Reiser4BlockMover()` | |
-| `BlockSize` | `int BlockSize { get; }` | A block, which is what the directory counts in. |
-| `FirstDataByte` | `long FirstDataByte { get; }` | First byte a file may occupy: past the reserved blocks and the directory, which is where the first file already sits. |
-| `RepointsRunsIndependently` | `bool RepointsRunsIndependently { get; }` | Each call notes where one run has got to; a file split by the bitmaps it steps over is simply several calls. |
-| `SupportsHeldRuns` | `bool SupportsHeldRuns { get; }` | A run may be held outside the volume while the rest of the layout moves, which is what lets a full volume be rearranged at all. |
-| `Init` | `void Init(Stream image)` | Reads the directory once and notes where every file is. |
+| `BlockSize` | `int BlockSize { get; }` | A block, which is what an extent unit counts in. |
+| `FirstDataByte` | `long FirstDataByte { get; }` | First byte a file may occupy: past the jump area, the superblocks, the journal, the status and backup blocks and the first two nodes. |
+| `RepointsRunsIndependently` | `bool RepointsRunsIndependently { get; }` | Each call notes where one unit's run has got to. |
+| `SupportsHeldRuns` | `bool SupportsHeldRuns { get; }` | A run may be held outside the volume while the rest of the layout moves. |
+| `Init` | `void Init(Stream image)` | Reads the tree once and notes where every extent unit is. |
| `MoveExtent` | `void MoveExtent(Stream image, long srcOffset, long dstOffset, long length, bool zeroSource = false)` | |
-| `SettleDirectory` | `void SettleDirectory(Stream image)` | Writes each file's new physical location into both the native extent40 item and the legacy workbench directory once the pass is over. |
+| `SettleDirectory` | `void SettleDirectory(Stream image)` | Writes every unit's new start into its twig and moves the allocator bits with it. |
| `UpdateAllocationAfterMove` | `void UpdateAllocationAfterMove(Stream image, string fileName, long oldOffset, long newOffset, long length)` | |
+#### `Reiser4FileBody`
+
+How the body of a regular file this writer creates is stored.
+
+| Value | Numeric | Summary |
+| --- | --- | --- |
+| `Extents` | `0` | Extent items in twigs pointing at data blocks (`reg40`, "extents" formatting). |
+| `Tails` | `1` | Tail (`plain40`) items in leaves holding the bytes themselves (`reg40`, "tails" formatting). |
+| `Smart` | `2` | Tails up to four blocks, extents above that — the kernel's "smart" formatting. |
+| `Compressed` | `3` | A cryptcompress (`ccreg40`) file: compressed disk clusters in `ctail40` items. |
+| `Profile` | `4` | Whatever the volume's root plugin set says new files are: its create plugin, then its formatting. |
+
#### `Reiser4FormatDescriptor`
-Descriptor for Reiser4 filesystem images (successor to ReiserFS 3.6 — completely different on-disk layout). Volumes whose node40 tree the reader walks completely list and extract their files and directories, and are created and edited through staged rebuilds that carry the volume's identity and every object's metadata across; other images surface the master superblock at offset 65536, the format40 superblock that follows it, a structured metadata bundle and the raw image. Magic: `"ReIsEr4"` at offset 65536 — master superblock `ms_magic[16]`. References: `https://archive.kernel.org/oldwiki/reiser4.wiki.kernel.org/` — archived Reiser4 wiki (format40 layout, plugin system)reiser4progs (`mkfs.reiser4` / `debugfs.reiser4`) — canonical userspace tooling`https://en.wikipedia.org/wiki/Reiser4` — Wikipedia article
+Descriptor for Reiser4 filesystem images (successor to ReiserFS 3.6 — completely different on-disk layout). Volumes whose node40/node41 tree the reader walks completely list and extract their files, directories, links and special files — after replaying a pending journal — and are created and edited through staged rebuilds that carry the volume's identity, plugin profile and every object's keys, metadata and body across; other images surface the master superblock at offset 65536, the format40 superblock that follows it, a structured metadata bundle and the raw image. Magic: `"ReIsEr4"` at offset 65536 — master superblock `ms_magic[16]`. References: `https://archive.kernel.org/oldwiki/reiser4.wiki.kernel.org/` — archived Reiser4 wiki (format40 layout, plugin system)reiser4progs (`mkfs.reiser4` / `debugfs.reiser4`) — canonical userspace tooling`https://en.wikipedia.org/wiki/Reiser4` — Wikipedia article
Implements `IArchiveCreatable`, `IArchiveDefragmentable`, `IArchiveFormatOperations`, `IArchiveModifiable`, `IArchivePurgeable`, `IArchiveShrinkable`, `IArchiveWriteConstraints`, `IFilesystemExtentMap`, `IFormatDescriptor`, `IFormatOptionsSchema`, `ILayoutOptimizable`, `IWipeEmpty`.
| Member | Signature | Summary |
| --- | --- | --- |
| `Reiser4FormatDescriptor` | `Reiser4FormatDescriptor()` | |
-| `AcceptedInputsDescription` | `string AcceptedInputsDescription { get; }` | Gets the accepted inputs description. |
-| `Capabilities` | `FormatCapabilities Capabilities { get; }` | Gets the capabilities. |
-| `Category` | `FormatCategory Category { get; }` | Gets the category. |
-| `CompoundExtensions` | `IReadOnlyList CompoundExtensions { get; }` | Gets the compound extensions. |
-| `DefaultExtension` | `string DefaultExtension { get; }` | Gets the default extension. |
-| `Description` | `string Description { get; }` | Gets the description. |
-| `DisplayName` | `string DisplayName { get; }` | Gets the display name. |
-| `Extensions` | `IReadOnlyList Extensions { get; }` | Gets the extensions. |
-| `Family` | `AlgorithmFamily Family { get; }` | Gets the family. |
-| `Id` | `string Id { get; }` | Gets the id. |
-| `MagicSignatures` | `IReadOnlyList MagicSignatures { get; }` | Gets the magic signatures. |
-| `MaxTotalArchiveSize` | `long? MaxTotalArchiveSize { get; }` | Gets the max total archive size. |
-| `Methods` | `IReadOnlyList Methods { get; }` | Gets the methods. |
-| `MinTotalArchiveSize` | `long? MinTotalArchiveSize { get; }` | Gets the min total archive size. |
-| `OptionsSchema` | `IReadOnlyList OptionsSchema { get; }` | Knobs the empty-filesystem writer actually honours. `VolumeLabel` is written into the master superblock label field (and the backup record) and surfaces through `fsck.reiser4` / our metadata readback; `ImageSize` drives `BlockCount` (4 KB blocks, clamped to the writer minimum). The 4 KB block size is fixed — the embedded mkfs.reiser4 templates are byte-exact 4096-byte captures — so it is intentionally not exposed. |
-| `TarCompressionFormatId` | `string TarCompressionFormatId { get; }` | Gets the tar compression format id. |
-| `Add` | `void Add(Stream archive, IReadOnlyList inputs)` | Adds or replaces members while retaining existing stat-data extensions. |
-| `CanAccept` | `bool CanAccept(ArchiveInputInfo input, out string reason)` | Performs the can accept operation. |
-| `CreateFromStreams` | `void CreateFromStreams(Stream target, IEnumerable inputs, FormatCreateOptions options)` | Creates the supported native node40 profile from input streams. Each source is consumed once into a temporary file, then copied in bounded chunks by `Reiser4Writer`; no complete file is staged in memory. Directory inputs retain empty directories and nested paths. |
-| `Create` | `void Create(Stream output, IReadOnlyList inputs, FormatCreateOptions options)` | Performs the create operation. |
+| `AcceptedInputsDescription` | `string AcceptedInputsDescription { get; }` | |
+| `Capabilities` | `FormatCapabilities Capabilities { get; }` | |
+| `Category` | `FormatCategory Category { get; }` | |
+| `CompoundExtensions` | `IReadOnlyList CompoundExtensions { get; }` | |
+| `DefaultExtension` | `string DefaultExtension { get; }` | |
+| `Description` | `string Description { get; }` | |
+| `DisplayName` | `string DisplayName { get; }` | |
+| `Extensions` | `IReadOnlyList Extensions { get; }` | |
+| `Family` | `AlgorithmFamily Family { get; }` | |
+| `Id` | `string Id { get; }` | |
+| `MagicSignatures` | `IReadOnlyList MagicSignatures { get; }` | |
+| `MaxTotalArchiveSize` | `long? MaxTotalArchiveSize { get; }` | |
+| `Methods` | `IReadOnlyList Methods { get; }` | |
+| `MinTotalArchiveSize` | `long? MinTotalArchiveSize { get; }` | |
+| `OptionsSchema` | `IReadOnlyList OptionsSchema { get; }` | Knobs the writer honours. `VolumeLabel` is written into the master superblock label field (and the backup record); `ImageSize` drives `BlockCount` (4 KB blocks, clamped to the writer minimum); `FileBody` picks how regular files are stored (`Reiser4FileBody`). The 4 KB block size is fixed — the embedded mkfs.reiser4 templates are byte-exact 4096-byte captures — so it is intentionally not exposed. |
+| `TarCompressionFormatId` | `string TarCompressionFormatId { get; }` | |
+| `AddHardLink` | `void AddHardLink(Stream archive, string path, string existing)` | Adds `path` as a further name of the existing file `existing`. |
+| `AddSpecialFile` | `void AddSpecialFile(Stream archive, string path, ushort mode, ulong device = 0)` | Adds a device node (`device` = major << 20 \| minor), FIFO or socket. |
+| `AddSymlink` | `void AddSymlink(Stream archive, string path, string target)` | Adds a symbolic link at `path` pointing at `target`. |
+| `Add` | `void Add(Stream archive, IReadOnlyList inputs)` | Adds or replaces members while retaining every existing object; new files are stored as extents. |
+| `Add` | `void Add(Stream archive, IReadOnlyList inputs, Reiser4FileBody body)` | Adds or replaces members, storing new regular files as `body` says. |
+| `CanAccept` | `bool CanAccept(ArchiveInputInfo input, out string reason)` | |
+| `CreateFromStreams` | `void CreateFromStreams(Stream target, IEnumerable inputs, FormatCreateOptions options)` | Creates the volume from input streams. Each source is consumed once into a temporary file, then copied in bounded chunks by `Reiser4Writer`; no complete file is staged in memory. Directory inputs retain empty directories and nested paths. |
+| `Create` | `void Create(Stream output, IReadOnlyList inputs, FormatCreateOptions options)` | Creates a volume holding `inputs`. |
| `Defragment` | `void Defragment(Stream archive)` | Performs the defragment operation. |
-| `Defragment` | `void Defragment(Stream archive, DefragOptions options)` | Rewrites the volume with every file laid out contiguously from the start of the payload area. Each entry is spilled to scratch and the writer pulls it back, so the rebuild is not bounded by what a byte[] can hold. |
-| `EnumerateExtents` | `IEnumerable EnumerateExtents(Stream image)` | Reports the volume's layout: the reserved blocks and the payload directory chain as metadata, then each file's blocks. A file's blocks are consecutive apart from the block-allocator bitmaps they step over. |
+| `Defragment` | `void Defragment(Stream archive, DefragOptions options)` | Defragments the volume: in place when the planner's moves can be written back as extent repoints (any tree height), otherwise by a staged rebuild that lays every file out contiguously at the same volume size. |
+| `EnumerateExtents` | `IEnumerable EnumerateExtents(Stream image)` | Reports the volume's layout: the reserved blocks, the tree nodes and the allocator bitmaps as metadata, then each file's extent runs. A volume whose journal still holds transactions to replay reports nothing: its blocks are not yet where the tree says. |
| `Extract` | `void Extract(Stream stream, string outputDir, string password, string[] files)` | Decodes the supplied input. |
| `List` | `List List(Stream stream, string password)` | Lists the entries in the supplied container. |
-| `RebuildStreaming` | `void RebuildStreaming(Stream source, Stream target, LayoutRebuildOptions options)` | Rebuilds the supported native profile while carrying existing metadata. |
+| `RebuildStreaming` | `void RebuildStreaming(Stream source, Stream target, LayoutRebuildOptions options)` | Rebuilds the volume while carrying existing metadata, at the requested image size or the smallest that holds it. |
| `Remove` | `void Remove(Stream archive, string[] entryNames)` | Removes members and directory subtrees through a metadata-preserving rebuild. |
-| `Shrink` | `void Shrink(Stream input, Stream output)` | Rebuilds tightly while retaining native metadata, or copies through on failure. |
+| `Shrink` | `void Shrink(Stream input, Stream output)` | Rebuilds tightly while retaining native metadata, or copies through when the volume cannot be rebuilt smaller. |
| `UpdateMetadata` | `void UpdateMetadata(Stream archive, string name, FileMetadata metadata)` | Updates a native object's mode, owner and timestamps through a staged rebuild. |
| `WipeUnusedSpace` | `long WipeUnusedSpace(Stream image, bool wipeClusterTips = true, bool wipeDeletedEntries = true)` | Zeros every byte no live file and no metadata block occupies. |
@@ -12624,7 +12640,7 @@ Parses the Reiser4 master superblock at byte offset 65536 (16 * 4 KB) and the ad
#### `Reiser4Reader`
-Reads a Reiser4 image: the master superblock's label, UUID and block size, plus regular files represented by the native stat40/cde40/extent40 items emitted by `Reiser4Writer`. The older workbench payload directory remains a compatibility fallback for images written before native tree items became authoritative.
+Reads a Reiser4 image: the master superblock's label, UUID and block size, and every object of the node40/node41 tree after the journal is replayed — directories, regular files whose bodies are extents, tails or compressed clusters (holes included), symbolic links, device nodes, FIFOs, sockets and hard links. The older workbench payload directory remains a compatibility fallback for images written before native tree items became authoritative.
Implements `IDisposable`.
@@ -12633,15 +12649,17 @@ Implements `IDisposable`.
| `Reiser4Reader` | `Reiser4Reader(Stream stream, bool leaveOpen = true)` | Initializes a new instance of `Reiser4Reader`. |
| `MasterOffset` | `const long MasterOffset` | Byte offset of the master superblock: block 16 at a 4 KB block size. |
| `BlockSize` | `int BlockSize { get; }` | Filesystem block size from the master superblock. |
-| `Entries` | `IReadOnlyList Entries { get; }` | Files and directories found in the native tree, or files in the legacy payload directory. |
+| `Entries` | `IReadOnlyList Entries { get; }` | Files, directories, links and special files found in the native tree, or files in the legacy payload directory. |
| `Label` | `string Label { get; }` | Volume label from the master superblock. |
| `Length` | `long Length { get; }` | Total size of the backing image in bytes. |
-| `NativeTreeValid` | `bool NativeTreeValid { get; }` | True when the complete supported native namespace was decoded. |
+| `NativeProblem` | `string NativeProblem { get; }` | Why the native tree was not decoded, when it was not. |
+| `NativeTreeValid` | `bool NativeTreeValid { get; }` | True when the complete native namespace was decoded. |
+| `ReplayedTransactions` | `int ReplayedTransactions { get; }` | Journal transactions replayed before the tree was read (0 when the journal was clean). |
| `RootMetadata` | `FileMetadata RootMetadata { get; }` | Root stat-data, including inherited plugin settings. |
| `UuidHex` | `string UuidHex { get; }` | Volume UUID from the master superblock, as hex. |
| `Valid` | `bool Valid { get; }` | True when the image carries a valid Reiser4 master superblock. |
| `Dispose` | `void Dispose()` | Releases resources held by this instance. |
-| `EnumerateRuns` | `IEnumerable> EnumerateRuns(Entry entry)` | Where an entry's bytes live as physical byte runs. |
+| `EnumerateRuns` | `IEnumerable> EnumerateRuns(Entry entry)` | Where an entry's bytes live as physical byte runs (extent data only; tails and clusters live in tree nodes). |
| `ExtractTo` | `long ExtractTo(Entry entry, Stream destination)` | Writes `entry`'s contents into `destination`. |
| `Extract` | `byte[] Extract(Entry entry)` | Reads a file's contents. Only valid below the array limit. |
@@ -12654,12 +12672,31 @@ Implements `IEquatable`.
| Member | Signature | Summary |
| --- | --- | --- |
| `Entry` | `Entry(string Name, ulong FirstBlock, long Size)` | One filesystem object and its physical extents. |
+| `Body` | `string Body { get; init; }` | How the body of a regular file is stored: "extent", "tail", "ctail" or "" for none. |
+| `Device` | `ulong Device { get; init; }` | The device number of a device node, as the kernel encodes it (major << 20 \| minor). |
| `FirstBlock` | `ulong FirstBlock { get; init; }` | |
+| `HardLinkOf` | `string HardLinkOf { get; init; }` | The path this entry is a further name of, when the object has more than one name. |
| `IsDirectory` | `bool IsDirectory { get; init; }` | True when this entry is a directory. |
+| `Kind` | `EntryKind Kind { get; init; }` | What kind of object this entry names. |
+| `LinkTarget` | `string LinkTarget { get; init; }` | The target of a symbolic link. |
| `Metadata` | `FileMetadata Metadata { get; init; }` | On-disk stat-data fields retained for metadata-preserving rebuilds. |
| `Name` | `string Name { get; init; }` | |
| `Size` | `long Size { get; init; }` | |
+#### `Reiser4Reader.EntryKind`
+
+What kind of object an entry names.
+
+| Value | Numeric | Summary |
+| --- | --- | --- |
+| `File` | `0` | A regular file. |
+| `Directory` | `1` | A directory. |
+| `Symlink` | `2` | A symbolic link; `LinkTarget` holds its target. |
+| `CharacterDevice` | `3` | A character device; `Device` holds its number. |
+| `BlockDevice` | `4` | A block device; `Device` holds its number. |
+| `Fifo` | `5` | A named pipe. |
+| `Socket` | `6` | A socket. |
+
#### `Reiser4Reader.FileMetadata`
Stat-data fields which can be represented by the current writer.
@@ -12680,11 +12717,12 @@ Implements `IEquatable`.
| `RawStatData` | `byte[] RawStatData { get; init; }` | |
| `Size` | `long Size { get; init; }` | |
| `StatLocality` | `ulong StatLocality { get; init; }` | Locality of the object stat key. |
+| `StatOrdering` | `ulong StatOrdering { get; init; }` | Ordering word of the object stat key (the kernel derives it from the object's first name). |
| `UserId` | `uint UserId { get; init; }` | |
#### `Reiser4Writer`
-Creator for a Reiser4 filesystem image that starts from what `mkfs.reiser4 -fffy` from `reiser4progs 1.2.2` produces and adds directories and regular files through the native tree — stat data and directory entries in leaves, extents in twigs, as many internal levels above them as the tree needs — so that `fsck.reiser4` validates the result as `"FS is consistent."` with or without files. The image holds 25 reserved blocks at fixed positions (block size = 4 KB): 0..15 — jump-area / partition data (zero).16 — master superblock (`"ReIsEr4"` at offset 65536).17 — format40 superblock (`"ReIsEr40FoRmAt"` at offset 52).18 — block-allocator bitmap (4-byte adler32 + bit array).19..20 — journal header / footer (zero for an empty FS).21 — status block (`"ReiSeR4StATusBl"`).22 — superblock backup record.23 — storage-tree root (twig, level 2).24 — leaf containing the root-directory stat-data + ".", "..". Implementation strategy: we embed the seven non-zero reference blocks as resources captured byte-exact from a real `mkfs.reiser4` image, then patch in only the per-image fields: UUID (16 bytes, random)Label (≤ 16 bytes, optional)mkfs_id (4 bytes, random) — appears in 4 places: format40 SB, backup record, twig header, leaf header.block_count / free_blocks (in format40 SB and backup).Bitmap (block 18) — bits 0..24 set for the 25 reserved blocks plus filler bits for the unused tail of the bitmap range, then adler32 of the bitmap data prepended. Round-trips with `fsck.reiser4 -y` exit 0 and produces output identical to the reference image except for the random fields above.
+Creator for a Reiser4 filesystem image that starts from what `mkfs.reiser4 -fffy` from `reiser4progs 1.2.2` produces and adds directories, regular files, symbolic links, device nodes, FIFOs, sockets and hard links through the native tree — stat data, directory entries and tails in leaves, extents in twigs, as many internal levels above them as the tree needs — so that `fsck.reiser4` validates the result as `"FS is consistent."` and a Reiser4 kernel mounts and reads it. The image holds 25 reserved blocks at fixed positions (block size = 4 KB): 0..15 — jump-area / partition data (zero).16 — master superblock (`"ReIsEr4"` at offset 65536).17 — format40 superblock (`"ReIsEr40FoRmAt"` at offset 52).18 — block-allocator bitmap (4-byte adler32 + bit array).19..20 — journal header / footer (zero for an unjournalled volume).21 — status block (`"ReiSeR4StATusBl"`).22 — superblock backup record.23 — storage-tree root (twig, level 2, or higher).24 — first leaf (the root directory's stat data and entries). The fixed blocks are byte-exact captures of a real `mkfs.reiser4` image with only the per-image fields patched in: UUID, label, mkfs id, block and free-block counts, the root, the next object id, the file count and the tree height. Regular files are written as extents by default; `FileBody` selects tails, the kernel's smart policy or compressed (cryptcompress) files instead.
| Member | Signature | Summary |
| --- | --- | --- |
@@ -12692,15 +12730,19 @@ Creator for a Reiser4 filesystem image that starts from what `mkfs.reiser4 -fffy
| `BlockSize` | `const int BlockSize` | Filesystem block size — 4 KB is the only supported value. Reiser4 theoretically supports 512 / 1024 / 2048 / 4096 / 8192, but the embedded templates are 4096-byte exact captures. |
| `MinBlockCount` | `const ulong MinBlockCount` | Minimum block count we'll emit. mkfs.reiser4 itself rejects images below ~750 blocks, but we round up to 4096 (= 16 MB) to match the reference capture and avoid bitmap-truncation edge cases. |
| `BlockCount` | `ulong BlockCount { get; set; }` | Total filesystem size in 4 KB blocks. Clamped to `MinBlockCount`. |
+| `FileBody` | `Reiser4FileBody FileBody { get; set; }` | How regular files are stored. `Profile` follows the captured mkfs profile, whose root names cryptcompress for new files. |
| `Label` | `string Label { get; set; }` | Customisable label written to the master SB (NUL-padded to 16 bytes; longer strings are truncated; null = empty/zero). |
| `MkfsId` | `uint? MkfsId { get; set; }` | Optional 32-bit mkfs identifier. When null, a random value is drawn from `Shared`. |
| `Uuid` | `byte[] Uuid { get; set; }` | Optional 16-byte UUID. When null, a random Guid is used. |
| `AddDirectory` | `void AddDirectory(string name, FileMetadata metadata = null)` | Retains an explicit directory, including an empty directory. |
-| `AddFile` | `void AddFile(string name, byte[] data, FileMetadata metadata = null)` | Adds a regular file to the payload area. |
+| `AddFile` | `void AddFile(string name, byte[] data, FileMetadata metadata = null)` | Adds a regular file. |
+| `AddHardLink` | `void AddHardLink(string name, string existing)` | Adds `name` as a further name of the file at `existing`. |
+| `AddSpecialFile` | `void AddSpecialFile(string name, ushort mode, ulong device = 0, FileMetadata metadata = null)` | Adds a device node, FIFO or socket; `mode` carries the file type bits. |
| `AddStreamingFile` | `void AddStreamingFile(string name, long size, Func openStream, FileMetadata metadata = null)` | Adds a file whose bytes are pulled from `openStream` as the image is written. |
-| `Build` | `byte[] Build()` | Builds the image fully in memory and returns the byte array. For block counts above ~32 K the result will be tens of MB; prefer the streaming overload when caller-side allocation matters. |
-| `EstimateBlockCount` | `static ulong EstimateBlockCount(IEnumerable fileSizes)` | Smallest block count that holds `fileSizes`: the reserved blocks, the directory chain, every file's data blocks, and the bitmap blocks interleaved among them. |
-| `Write` | `void Write(Stream output)` | Streams the full image into `output`. Writes `BlockCount`×4096 bytes and leaves the stream positioned at the end. |
+| `AddSymlink` | `void AddSymlink(string name, string target, FileMetadata metadata = null)` | Adds a symbolic link whose target is `target`. |
+| `Build` | `byte[] Build()` | Builds the image fully in memory and returns the byte array. |
+| `EstimateBlockCount` | `static ulong EstimateBlockCount(IEnumerable fileSizes)` | Smallest block count that holds `fileSizes`: the reserved blocks, every file's data blocks, the tree, and the bitmap blocks interleaved among them. |
+| `Write` | `void Write(Stream output)` | Streams the full image into `output` and leaves the stream positioned at the end. |
### Namespace `FileSystem.ReiserFs`
diff --git a/docs/REISER4-NATIVE-PROFILE.md b/docs/REISER4-NATIVE-PROFILE.md
index 21320c49f..6e3d05a72 100644
--- a/docs/REISER4-NATIVE-PROFILE.md
+++ b/docs/REISER4-NATIVE-PROFILE.md
@@ -2,128 +2,189 @@
## Evidence and provenance
-The existing binary templates were captured from `mkfs.reiser4 -fffy` in
-reiser4progs 1.2.2. Their fixed fields are the starting point for this profile.
-The on-disk layout is also described by the Reiser4 node40, stat40, cde40,
-extent40 and format40 plugins in the upstream
-[reiser4progs project](https://github.com/edward6/reiser4progs).
-The upstream GPL implementation is reference material, not copied or converted
-source. This follows sourcing rung 2: no compatible managed implementation was
-identified. The new traversal and rebuild tests use synthetic native nodes;
-reference-tool conformance is covered separately as described below. Mounted
-kernel interoperability has not been tested.
-
-## Derived layout used here
-
-For the captured 4096-byte format40 profile, the master is block 16 and the
-format superblock is block 17. The latter stores the root block at byte 16 and
-the tree height at byte 68. The root object's stat key has locality 41 and object
-ID 42. Names beneath a directory use that directory's object ID as locality.
-
-A node40 block has a 28-byte header, bodies growing upwards and 38-byte item
-headers growing downwards from the end. The header's item count is at byte 2,
-body-end offset at byte 6, magic at byte 8 and level at byte 26. Each item
-header contains four little-endian key words, followed by body offset, flags
-and plugin ID. Internal pointer bodies contain a little-endian block address.
-Traversal follows all pointers, requires descending levels, and rejects cycles
-and out-of-range addresses.
-
-The supported object plugins are stat40 (0), cde40 (2) and extent40 (5).
-Stat-data and directory items occupy level-1 leaves. Extents occupy level-2
-twig nodes alongside child pointers; the reader also accepts the earlier
-workbench placement of extents in leaves. This placement follows upstream
-`libreiser4/tree.c` target-level selection, which assigns extent items to the
-twig level and other object items to the leaf level.
-Stat-data must include the lightweight and Unix extensions. Its first 44 bytes
-carry extension mask, mode, link count, size, UID, GID, three timestamps and
-allocated-byte count. Further extensions follow in mask-bit order; the writer
-carries large times (bit 2, 12 bytes), flags (bit 5, 4 bytes), the plugin set
-(bit 4) and the heir set (bit 8), each a 16-bit count of 4-byte slots, and
-refuses a body holding any other extension or bytes its mask does not declare,
-which `fsck.reiser4` reports as a fatal corruption.
-Extent bodies contain pairs of 64-bit block start and block count. Multiple
-items are joined in logical-offset order only when they describe contiguous
-logical content. Holes and unsupported body plugins are rejected.
-
-Cde40 has a 16-bit entry count, 26-byte unit headers, and units containing a
-24-byte target stat key plus the stored name when its key is hashed. Resolving
-the target's locality and object ID distinguishes files and directories. Dot
-entries are omitted from the archive namespace. Nested and empty directories
-are represented explicitly. Large directories split at unit boundaries; each
-item uses its first unit name key. Extent arrays split at run boundaries with
-logical byte offsets. Leaves end before a twig extent key, so a child pointer does not span an
-extent key range at its parent. Sorted leaf items pack into bounded leaves, and parent nodes
-use the first key of each child as their delimiting key. Parent levels grow until
-one root fits. Format40 height, allocator bitmaps, object counts and allocated
-node blocks follow the resulting layout. Paths have at most 129 components to
-bound directory recursion. This writer restricts names to ASCII; it rejects
-unsupported names rather than truncating them into different names.
-
-## Rebuild contract and limits
-
-Add, remove, defrag, shrink and layout rebuild capture metadata before staging,
-and write nothing to the source until the staged volume has been read back and
-verified. Volume UUID, label and mkfs id survive, as do existing object IDs;
-new IDs are allocated beyond the retained ones rather than renumbering live
-objects. Mode, ownership and timestamps are retained, size, allocated bytes and
-directory link counts follow the rebuilt namespace, and the declared
-stat-data extensions listed above are carried byte for byte. Root stat-data
-(with its plugin set) and empty directories are retained.
-
-`UpdateMetadata` sets mode permission bits, UID, GID and the three timestamps
-through the same staged rebuild, including on the root. It refuses a change of
-object kind, of link count (which follows the namespace) and of extension bytes
-with `NotSupportedException`, the volume unchanged.
-
-A rebuild writes the captured mkfs prefix back with only the identity patched
-in, so it is refused, before anything is written, when the source's fixed
-blocks hold anything else:
-
-| Block | What must match the captured profile | Why |
+The fixed blocks of a fresh volume are byte-exact captures from `mkfs.reiser4 -fffy` in
+reiser4progs 1.2.2. Everything else in this document was derived from the behaviour of two
+implementations and checked against both:
+
+* **reiser4progs 1.2.2** (Ubuntu package 1.2.2-1build2) under WSL: `mkfs.reiser4` makes volumes with
+ every plugin profile, `fsck.reiser4 --check` judges every volume the writer produces, and
+ `debugfs.reiser4` resolves names (`-i` prints an object's stat data and items, `-k` prints a
+ file through reiser4progs' own body plugins — usable as a byte oracle only for text without `%`,
+ because the bytes are handed to `printf` as its format string).
+* **A Reiser4 kernel**: Metztli's Debian build of Linux 5.4.18 with the SFRN 4.0.2 patch
+ (`linux-image-5.4.0-3+reizer4.0.2-cloud-amd64`), booted under QEMU with a busybox initramfs
+ (`Compression.Tests/Reiser4/KernelOracle/kernel-run.sh`). It wrote the reference volumes in
+ `Compression.Tests/Reiser4/ReferenceVectors` through its own write path and reads back every
+ volume the writer produces.
+
+The upstream sources (the GPL [reiser4progs](https://github.com/edward6/reiser4progs) and
+[kernel module](https://github.com/edward6/reiser4)) were read as reference material to write this
+document; no code was copied, converted or transliterated (sourcing rung 2: no licence-compatible
+managed implementation exists). Constants — magic strings, TEA key words and delta, FNV offset
+basis and prime, the degenerate hash value, CRC-32C and Adler-32 — are copied exactly.
+
+## Fixed blocks
+
+Block size is 4096; the master superblock is block 16 and the format40 superblock block 17
+(root block at byte 16, next object id at 24, file count at 32, mkfs id at 48, tree height at 68,
+tail policy at 70, flags at 72 — bit 0 set for large keys — and node plugin id at 84). Block 18 is
+the first allocator bitmap (a 4-byte Adler-32 of the rest, then one bit per block; further bitmaps
+sit at multiples of 32 736 blocks), 19 and 20 the journal header and footer, 21 the status block
+(`"ReiSeR4StATusBl"`, then a 64-bit status that is 0 for a consistent volume), 22 the backup of
+the master, the format fields and the root's plugin set.
+
+An edit carries blocks 16, 17, 21 and 22 of the source and patches only the counters (block and
+free-block counts, root, next object id, file count, height); the journal blocks are written blank
+because the rebuilt volume already holds the replayed state. A volume whose status is not 0 is
+refused, as is one with short keys (`mkfs.reiser4 -o key=key_short` crashes in 1.2.2, so no
+reference exists) or a block size other than 4096.
+
+## Plugin profile
+
+`mkfs.reiser4 -o` changes exactly three things: the format40 tail policy (block 17, byte 70), the
+root directory's `sdext_plugin_set` and its copy in the backup block, and — for `node=node41` — the
+node plugin id (block 17, byte 84) and the node layout. Plugin-set members are 16-bit pairs
+(member, plugin id): 0 file, 1 directory, 2 permission, 3 formatting, 4 hash, 5 fibration,
+6 stat data, 7 directory item, 8 cipher, 9 digest, 10 compression, 11 compression mode, 12 cluster,
+13 create. An object's missing members come from the root's plugin set (the kernel's
+`finish_pset`), and the root's missing ones from the kernel defaults (r5, ext_1, smart, lzo1, conv,
+64K, reg40). The default mkfs profile names **ccreg40** (cryptcompress) as the create plugin, so a
+kernel writes compressed files on a default volume.
+
+### Directory entry keys
+
+A directory entry's key is `(directory oid, type 0, ordering, objectid, offset)`. The name's bytes
+pack big-endian into the ordering from its second byte (seven bytes), then the objectid (eight),
+then the offset (eight). A name longer than 23 bytes sets bit 56 of the ordering, keeps only its
+first 15 bytes in the key, and puts the hash of the remaining bytes in the offset; such a name is
+stored after the entry's 24-byte target key, NUL-terminated. The fibration plugin's fibre occupies
+the ordering's top seven bits:
+
+| Fibration | Fibre |
+| --- | --- |
+| `lexic_fibre` (0) | 0 |
+| `dot_o_fibre` (1) | 1 for names ending in `.o`, else 0 |
+| `ext_1_fibre` (2) | the last byte, when the byte before it is `.` (and the name is longer than 2) |
+| `ext_3_fibre` (3) | the sum of the last three bytes, when the fourth from last is `.` (name longer than 4), modulo 128 |
+
+| Hash | Value of the bytes after the 15th |
+| --- | --- |
+| `r5_hash` (1) | `a = (a + (b << 4) + (b >> 4)) * 11` over the bytes, 64-bit |
+| `tea_hash` (2) | TEA in a Davies–Meyer construction evaluated in 64-bit arithmetic: 16-byte blocks of four little-endian 32-bit words get 6 rounds, the remainder padded with `len | len << 8 | …` gets 10; the result is the two halves xored |
+| `fnv1_hash` (3) | 64-bit FNV-1 |
+| `deg_hash` (4) | the constant `0xC0C0C0C010101010` |
+| `rupasov_hash` (0) | not computed: the kernel and reiser4progs disagree (fsck.reiser4 reports every kernel-keyed long name as carrying the wrong offset), so no long name keyed with it can satisfy both. Existing entries are carried; new names longer than 23 bytes are refused. |
+
+The key of a new object's stat data is `(parent oid, type 1, ordering of its first name, oid, 0)`,
+as the kernel makes it; directory entries carry the target's full stat key. Existing entries and
+stat keys are always carried as found, never recomputed.
+
+## Nodes and items
+
+A node40 node has a 28-byte header (plugin id, item count, free space, free-space start, magic
+`0x52344653`, mkfs id, flush id, flags, level) and 38-byte item headers growing down from the end
+(32-byte key, body offset, flags, item plugin id). node41 adds a 32-bit checksum at byte 28 — the
+CRC-32C register (initial value all ones, no final inversion) over the 28 header bytes and then
+everything after the checksum — and its bodies start at byte 32.
+
+| Item plugin | Level | Body |
| --- | --- | --- |
-| 16 master | everything but UUID and label | other disk-format fields are not reproduced |
-| 17 format40 | magic, tail policy, flags, version | `mkfs.reiser4 -o formatting=tails` changes the policy |
-| 19, 20 journal | blank | a kernel-written journal is not replayed |
-| 21 status | "consistent" | a volume fsck marked damaged is not silently cleared |
-| 22 backup | everything but UUID, label, block count, mkfs id | it backs up the root's plugin set: hash, fibration, formatting |
-
-Writing the default profile over another one was observed to fail:
-`fsck.reiser4` reported the root's plugin set disagreeing with its backup, and
-with `-o hash=tea_hash` a long name keyed with r5 could not be looked up by
-`debugfs.reiser4`. Such volumes are read, not rewritten. Unsupported or
-incomplete native trees are refused the same way. Shrink copies the original
-through when it cannot build a supported smaller result.
-
-Reading supports multiple internal levels. Writing builds multiple leaves and
-additional internal levels as needed. An indivisible stat-data body or
-directory unit larger than a node is refused. This is not full Reiser4
-metadata support: separate xattr items, tail and ctail bodies, arbitrary
-object plugins, symlinks, sparse files, shared objects, non-ASCII names,
-short keys and alternate node plugins are outside the profile. Native tree
-blocks discovered by traversal are reserved in the wipe map.
+| stat40 (0) | leaf | the stat data |
+| cde40 (2) | leaf | 16-bit count, 26-byte unit headers (three key words, body offset), units of a 24-byte target key plus the stored name of a long entry |
+| nodeptr40 (3) | internal | a 64-bit block number |
+| extent40 (5) | twig | 16-byte units: start block and width; start 0 is a hole |
+| plain40 (6) | leaf | tail: the file's bytes from the key's offset |
+| ctail40 (7) | leaf | one byte of cluster shift, then bytes of a disk cluster from the key's offset |
+
+Stat data starts with a 16-bit extension mask; extensions follow in bit order: light-weight (bit 0:
+mode, links, size), Unix (bit 1: uid, gid, atime, mtime, ctime, then 64-bit bytes — or the device
+number `major << 20 | minor` of a device node), large times (bit 2, 12 bytes), symlink (bit 3: the
+target, as long as the light-weight size, then a NUL), plugin set (bit 4) and heir set (bit 8)
+(a count of 4-byte pairs), flags (bit 5, 4 bytes). The crypto extension (bit 7), a cipher in the
+plugin set and a chained mask (bit 15) are refused: no key is available for encrypted files.
+
+### File bodies
+
+* **reg40, extents.** Units in logical order; holes are units with start 0 and are kept as holes.
+ `bytes` counts allocated blocks. A unit never covers an allocator bitmap block.
+* **reg40, tails.** plain40 items covering the file from offset 0; `bytes` equals the size. The
+ kernel's smart policy keeps files of up to four blocks in tails.
+* **ccreg40 (cryptcompress).** The file is cut into logical clusters of 4 KiB to 64 KiB (cluster
+ plugin 4…0, shift 12…16, also stored as each ctail item's first byte). Each present cluster is
+ a disk cluster split across ctail items keyed at the cluster's start plus the byte offset within
+ the disk cluster. A disk cluster is compressed exactly when it is shorter than the logical
+ cluster (the cluster size, or what is left of the file); then its last four bytes are the
+ little-endian Adler-32 of the compressed stream before them. lzo1 is raw LZO1X, gzip1 a raw
+ deflate stream, zstd1 a Zstandard frame. Compression is kept only when stream plus checksum is
+ shorter than the input, and inputs under the plugin's minimum (256 bytes, 64 for gzip1) are
+ stored plain. Missing clusters are holes. `bytes` counts clusters times the cluster size. The
+ kernel's `conv` mode turns an incompressible file into a reg40 extent file and records
+ `compressMode=latt` in the plugin set of one it compressed; both are carried.
+
+### Objects
+
+Directories, regular files, symlinks (target in the stat data), character and block devices,
+FIFOs and sockets (no body), and hard links (several entries naming one stat key; `nlink` counts
+them). A directory's `size` is its number of entries including the dot entries, its `bytes` the sum
+of its units (26 + 24 bytes each, plus a long name and its NUL), its `nlink` 2 plus its
+subdirectories (3 plus them for the root). The writer recomputes these, and a file's `nlink`, from
+the namespace; every other stat-data byte is carried.
+
+## Journal
+
+Block 19 holds the last committed transaction, block 20 the last one written back to its home
+locations (plus the free-block, file and next-oid counters). Every transaction between them is
+replayed, oldest first: its head (`"TxMagic4"`, id, total records, padding, previous transaction,
+first wander record, counters) links back to the previous one, and its wander records
+(`"LogMagc4"`, id, total, serial, next record) list `(original, wandered)` block pairs from byte 32;
+replay copies each wandered block over its original. Reading happens on the replayed view; an edit
+writes the replayed state with a blank journal. A chain that does not parse is refused.
+
+Verified on `journal-replay`, captured between a kernel commit and its write-back (writes throttled
+by QEMU, image copied the moment the header moved past the footer): the replayed namespace is the
+one the kernel shows after mounting, and differs from the unreplayed one.
+
+## Writing
+
+New regular files are extents by default; `FileBody` (`Reiser4Writer`, the `FileBody` create
+option, `Add(…, Reiser4FileBody)`) selects tails, the smart policy, cryptcompress, or whatever the
+volume's root says (`Profile`: its create plugin, then its formatting). A replaced file keeps its
+identity, metadata and plugin. Leaves end before a twig extent key; parent levels grow until one
+root fits at block 23; the first leaf is block 24.
+
+Every edit is staged: the source is read whole (journal replayed), edited as a plan, written to
+scratch, read back and verified — namespace, identity and every object's stat data — and only then
+copied over the source. Refusals leave the source byte-identical.
+
+### Defragmentation
+
+The in-place pass moves extent data on trees of any height: each unit's run moves on its own, the
+new start is written into the unit's twig (node41 checksums re-sealed), and the allocator bits of
+the blocks each unit left are cleared and of the blocks it landed on set. Tree nodes, tails and
+compressed clusters do not move. A volume whose journal holds transactions, or a file whose extent
+covers blocks past its end, falls back to a staged rebuild at the same size.
## Evidence
-Oracle: reiser4progs 1.2.2 (Ubuntu package 1.2.2-1build2) under WSL. The WSL
-kernel (6.6) has no Reiser4 driver, so nothing was mounted; volumes written by
-the tools themselves come from `mkfs.reiser4` and from
-`fsck.reiser4 --build-fs`. File bytes are taken where `debugfs.reiser4 -i`
-says they are (its own path lookup, stat data and extent units); `debugfs -k`
-is not usable as a byte oracle because it hands file contents to `printf` as
-the format string.
-
| Volume | Checked by | Result |
| --- | --- | --- |
+| 13 kernel-written reference volumes: default (lzo1, conv, 64K), gzip1+force+8K, zstd1+latt+16K, lzo1+none+4K, reg40 smart, reg40 tails, reg40+extents+node41, node41, tea+lexic, fnv1+dot_o, deg+ext_3, rupasov, journal replay | our reader against the kernel's read-back manifest | every path, type, mode, owner, mtime, link count, size, device, symlink target and file MD5 equal |
+| the same, edited (add a long-named file under each body, a symlink, a hard link; remove two names) | `fsck.reiser4 --check`; the kernel's manifest | consistent; carried objects identical, new ones read back byte for byte, including clusters we compressed with lzo1, gzip1 and zstd1 |
+| names in every reference directory | re-keyed with the volume's hash and fibration | identical to the kernel's keys (all but Rupasov) |
+| every `mkfs.reiser4 -o` profile (hashes, fibrations, formattings, create, compression, mode, cluster, node41) edited under each body | `fsck.reiser4 --check`; `debugfs.reiser4 -i/-k` | consistent; names resolve; plain bodies read back; root plugin set unchanged |
+| writer volumes with every object kind and body | `fsck.reiser4`; the kernel's manifest | consistent; identical |
+| a tall tree scattered and defragmented in place | `fsck.reiser4`; the kernel's manifest | consistent after both; no node moved; every file identical |
| 3,004 files in 28 nested directories, empty and deep-empty directories, sizes 0/1/4095/4096/4097/2.2 MB, names of 23, 24, 100 and 255 characters | `fsck.reiser4 --check`; `debugfs -s`; `debugfs -i` + block copy for 316 files; `measurefs -S` | consistent; height 3, 38 twigs, 113 leaves, 3,040 objects; 0 byte mismatches |
-| the same after metadata update, add (nested), remove (subtree and a 255-character name), defrag, shrink, relayout | `fsck`; `debugfs -s`, `-i` and `-k` before/after | consistent each time; UUID, label, stat data and stat keys (object IDs) of untouched objects identical; the update applied exactly |
| 12,000 files with extents | `fsck`; `debugfs -s` | consistent; height 4 |
-| our volume after `fsck.reiser4 --build-fs` inserted lost+found (object 0xffff, uid 1000) | our reader; then add into lost+found and `fsck` | read completely, 0 mismatches; consistent, object ID and owner kept |
-| `mkfs.reiser4` volume, then add nested files, long names, an empty directory | `fsck`; `debugfs -s`, `-i` | consistent; UUID, label, mkfs id, policies and root stat unchanged |
-| `mkfs.reiser4 -o hash=tea_hash` / `formatting=tails` / `fibration=lexic_fibre` | our editor | read; edit refused, image byte-identical |
-| a file carrying a large-time extension (mask bit 2) through add and defrag | `fsck`; `debugfs -i` | consistent; `sdext_lt` still present |
-
-`Reiser4ProfileExternalTests` and `Reiser4MutationExternalTests` replay these
-checks wherever reiser4progs is installed. The Linux CI leg installs
-reiser4progs and runs them as the hard "Reiser4 oracle" gate, with
-`CWB_REQUIRE_REISER4PROGS=1` so a missing tool fails the gate instead of
-skipping it.
+| our volume after `fsck.reiser4 --build-fs` inserted lost+found | our reader; then add into lost+found and `fsck` | read completely; consistent, object ID and owner kept |
+
+Known disagreements between the two oracles, recorded rather than resolved: kernel-written Rupasov
+long names fail `fsck.reiser4`; a tails-formatted file the kernel left with a trailing hole is
+reported by `fsck.reiser4` as having the wrong size. `debugfs.reiser4` keys lookups below the root with its own default profile rather than the root's plugin set, so in a non-default profile it finds hashed or fibred names in subdirectories — the kernel's as well as ours — only when given the volume's profile with `-o`.
+
+`Reiser4KernelVolumeTests` runs without any tool. `Reiser4ProfileExternalTests`,
+`Reiser4MutationExternalTests` and `Reiser4FeatureExternalTests` replay the reiser4progs checks
+wherever it is installed; the Linux CI leg installs it and runs them as the hard "Reiser4 oracle"
+gate with `CWB_REQUIRE_REISER4PROGS=1`, so a missing tool fails the gate instead of skipping it.
+`Reiser4KernelOracleTests` need the kernel (`CWB_REISER4_KERNEL_DOWNLOAD=1` fetches it) and skip
+without it.
diff --git a/docs/catalogue/GAPS.md b/docs/catalogue/GAPS.md
index 171540636..b5c645582 100644
--- a/docs/catalogue/GAPS.md
+++ b/docs/catalogue/GAPS.md
@@ -23,8 +23,8 @@ exists. It warns when a capability letter has drifted from the live descriptor.
| Gap type | Rows | Meaning |
| --- | ---: | --- |
-| `MISSING` | 238 | a source lists it; no descriptor or building block covers it |
-| `READ-ONLY-BUT-SOURCES-WRITE` | 20 | we only read it; a source or the format's own tool writes it |
+| `MISSING` | 237 | a source lists it; no descriptor or building block covers it |
+| `READ-ONLY-BUT-SOURCES-WRITE` | 21 | we only read it; a source or the format's own tool writes it |
| `PARTIAL` | 37 | covered, but the reader handles only part of the format (see the table below) |
| `OK` | 230 | covered with no known gap against what the sources list |
| `OURS-ONLY` | 458 | in our registry, listed by none of the seven sources |