cpio#
Pure OCaml implementation of the CPIO archive format (newc/SVR4) for reading and writing archives, primarily for Linux initramfs creation.
Features#
- Read and write CPIO archives in newc (SVR4) format
- Support for regular files, directories, symlinks, and device nodes
- No external dependencies on
cpiocommand-line tools - Suitable for embedding in unikernels and cross-compilation scenarios
Installation#
opam install cpio
Usage#
Creating an archive#
let entries = [
Cpio.directory "root";
Cpio.directory "root/bin";
Cpio.regular ~name:"root/bin/init" ~perm:0o755 "#!/bin/sh\nexec /bin/sh";
Cpio.symlink ~name:"root/bin/sh" ~target:"/bin/busybox";
]
let archive = Cpio.to_string entries
Reading an archive#
match Cpio.read_all archive_data with
| Ok entries ->
List.iter (fun e ->
Printf.printf "%s (%d bytes)\n" e.Cpio.header.name (String.length e.Cpio.data)
) entries
| Error msg ->
Printf.eprintf "Error: %s\n" msg
Creating an initramfs#
let initramfs = Cpio.to_string [
Cpio.directory "dev";
Cpio.device ~char:true ~major:1 ~minor:3 "dev/null";
Cpio.device ~char:true ~major:1 ~minor:5 "dev/zero";
Cpio.device ~char:true ~major:5 ~minor:1 "dev/console";
Cpio.directory "proc";
Cpio.directory "sys";
Cpio.regular ~name:"init" ~perm:0o755 init_script;
]
Format#
This library implements the "newc" (new ASCII) CPIO format as defined in SVR4. Each entry consists of:
- 110-byte ASCII header with hex-encoded fields
- Variable-length pathname (NUL-terminated, padded to 4-byte boundary)
- File data (padded to 4-byte boundary)
Archives are terminated with an entry named "TRAILER!!!".
Related Work#
- cpio-rs - Rust CPIO library (write-focused)
- cpio_reader - Rust CPIO reader (no_std)
- rcore-os/cpio - Rust freestanding CPIO reader
- GNU cpio - Reference implementation
References#
Licence#
MIT License. See LICENSE.md for details.