Build and Verify a Read-Only Cramfs Image

mkfs.cramfs packs a directory into a compressed, read-only image the kernel can page in one block at a time, which is why it caps every file at 16 MB. You will turn a directory tree into an image, inspect the result, and validate it without mounting anything. Allow about fifteen minutes for a small test image.

You need mkfs.cramfs, a source directory that can be read, and a destination on a filesystem with enough free space. The installed command here reports util-linux 2.41.3. The local manual page identifies util-linux 2.39.3, while the distribution package query reports util-linux 2.39.3-9ubuntu6.6. Check your own binary and package before relying on version-specific output. This guide follows the options and limits in the installed manual.

1. Check the command before creating anything

Run these ordinary, read-only checks as your normal user:

$ command -v mkfs.cramfs
/home/linuxbrew/.linuxbrew/sbin/mkfs.cramfs
$ mkfs.cramfs --version
mkfs.cramfs from util-linux 2.41.3
$ mkfs.cramfs --help

Your path and help text may differ. The documented command shape is mkfs.cramfs [options] directory file: the directory is the root of the tree to package, and the file is the image that will later be mounted read-only. Do not confuse the source directory with a device. This command makes an image file; it does not mount it.

2. Prepare a disposable source tree

Use a directory containing only files intended for the image. The command records file metadata and contents, so review the tree before building it:

$ SOURCE_DIR=/path/to/cramfs-source
$ IMAGE_FILE=/path/to/output/test.cramfs
$ find "$SOURCE_DIR" -maxdepth 2 -type f -print
/path/to/cramfs-source/etc/motd
/path/to/cramfs-source/hello.txt

These variables are placeholders. Replace both paths with real locations. A normal image build does not need sudo. Use elevated privileges only if the source or destination permissions genuinely require them, and check the expanded paths first. A typo in the destination can put an image somewhere unexpected.

Checkpoint: make sure the destination is new or disposable. mkfs.cramfs writes the output file, so do not point it at a useful archive or device while experimenting.

3. Create the image with a safe temporary name

Build beside the intended destination, then rename the completed image. The temporary name keeps a failed build separate from an older good image:

$ TEMP_IMAGE="$IMAGE_FILE.new"
$ mkfs.cramfs -v "$SOURCE_DIR" "$TEMP_IMAGE"
  etc
  hello.txt
Directory data: 132 bytes
Everything: 4 kilobytes
$ mv "$TEMP_IMAGE" "$IMAGE_FILE"

Verbose output lists directories and files, then reports image statistics; exact byte counts depend on your tree. The final mv replaces an existing destination of the same name, so run it only after checking that TEMP_IMAGE is the file you meant to create. If the build fails, leave the old image alone and investigate the error. Remove an unwanted temporary file manually after confirming its path.

The source tree remains in place. Cramfs itself is intentionally read-only, and its files are compressed one page at a time so the kernel can read individual pages without decompressing the entire image.

4. Inspect the image and run its filesystem check

Check that the output is a cramfs image, has a plausible size, and passes the separate checker:

$ file "$IMAGE_FILE"
/path/to/output/test.cramfs: Linux Compressed ROM File System data, little endian size 4096 version #2 sorted_dirs CRC 0x80834501, edition 0, 2 blocks, 4 files
$ stat -c 'size=%s bytes mode=%a' "$IMAGE_FILE"
size=4096 bytes mode=644
$ fsck.cramfs "$IMAGE_FILE"
$ printf 'fsck status: %s\n' "$?"
fsck status: 0

A healthy check may produce no diagnostic text, as it did for this small image. The file wording, CRC and counts vary with the contents and tool versions. The useful checks are that the type is Linux Compressed ROM File System data and that fsck.cramfs exits successfully. If the checker reports corruption, keep the source tree, discard only the new image, and rebuild after checking the storage and input files.

5. Handle warnings instead of hiding them

Use -E when a warning must make an automated build fail. This is particularly useful in a release script, but it can reject a small test image. For example, the installed command produced a warning about group IDs being truncated to eight bits and returned status 8 when -E was used:

$ mkfs.cramfs -E "$SOURCE_DIR" "$TEMP_IMAGE"
mkfs.cramfs: warning: gids truncated to 8 bits.  (This may be a security concern.)
$ printf 'exit status: %s\n' "$?"
exit status: 8

Warning: do not treat a warning as harmless simply because an image was written. Review ownership and group IDs in the source tree, decide whether truncation is acceptable for the target, and rebuild to a new temporary name after correcting the input. Exit status 0 means success; the manual documents status 8 for an operation error such as an allocation failure.

6. Choose the options that affect compatibility

7. Check the size limits before packaging large trees

Cramfs is not a general-purpose archive format. Each file must be smaller than 16 MB. The filesystem size is limited to a little under 272 MB, because the last file must begin before the 256 MB block, even though that file can extend beyond it. Check large inputs before a build rather than discovering the limit halfway through a release:

$ find "$SOURCE_DIR" -type f -printf '%s %p\n' | sort -nr | head
5242880 /path/to/cramfs-source/firmware.bin
8192 /path/to/cramfs-source/etc/motd
$ du -sh "$SOURCE_DIR"
5.1M    /path/to/cramfs-source

The size checks are planning aids, not a substitute for a successful build and filesystem check. If the tree is too large, split it or use a filesystem format designed for larger or writable data. Do not delete source files merely to make cramfs accept the tree; retain the original and produce a deliberate reduced input tree.

Done means