3cpio(1)
========
Benjamin Drung
:doctype: manpage
:manmanual: 3cpio
:mansource: 3cpio 0.5.1
:manversion: 0.5.1

== Name

3cpio - manage initrd cpio archives

== Synopsis

*3cpio* *--count* _ARCHIVE_

*3cpio* {*-c*|*--create*} [*-v*|*--debug*] [*-C* _DIR_] [*--data-align* _ALIGNMENT_]
[_ARCHIVE_] < _manifest_

*3cpio* {*-e*|*--examine*} _ARCHIVE_

*3cpio* {*-t*|*--list*} [*-v*|*--debug*] [*-P* _LIST_] _ARCHIVE_ [_pattern_...]

*3cpio* {*-x*|*--extract*} [*-v*|*--debug*] [*-C* _DIR_] [*-P* _LIST_] [*-p*] [*-s* _NAME_]
[*--to-stdout*] [*--force*] _ARCHIVE_ [_pattern_...]

*3cpio* {*-V*|*--version*}

*3cpio* {*-h*|*--help*}

== Description

*3cpio* is a tool to manage initramfs cpio files for the Linux kernel. The Linux
kernel's
https://www.kernel.org/doc/html/latest/driver-api/early-userspace/buffer-format.html[initramfs buffer format]
is based around the `newc` or `crc` cpio formats. Multiple cpio archives can be
concatenated and the last archive can be compressed. Different compression
algorithms can be used depending on what support was compiled into the Linux
kernel. *3cpio* is tailored to initramfs cpio files and will not gain support for
other cpio formats.

Following compression formats are supported: bzip2, gzip, lz4, lzma, lzop, xz, zstd.

== Modes

*--count* _ARCHIVE_::
  Print the number of concatenated cpio archives.

*-c*, *--create* [_ARCHIVE_]::
  Create a new cpio archive. Read the manifest from the standard input.
  See the MANIFEST section for the description of the manifest format.
  Write the cpio archive to standard output or to the specified _ARCHIVE_ file if provided.
  The permission of the _ARCHIVE_ file will be determined by the permission of the input files
  (to avoid leaking sensitive information).

*-e*, *--examine* _ARCHIVE_::
  List the offsets of the cpio archives and their compression.

*-t*, *--list* _ARCHIVE_ [_pattern_...]::
  List the contents of the cpio archives. By default only the file names are printed.
  If *--verbose* is specified, the long listing format is used (similar to ls --long).
  If *--debug* is specified, the inode is printed in addition to the long format.
  If one or more __pattern__s are supplied, list only file names
  matching at least one of those __pattern__s.
  These __pattern__s are shell wildcard patterns (see *glob*(7)).

*-x*, *--extract* _ARCHIVE_ [_pattern_...]::
  Extract cpio archives.
  If one or more __pattern__s are supplied, extract only files
  matching at least one of those __pattern__s.
  These __pattern__s are shell wildcard patterns (see *glob*(7)).

*-V*, *--version*::
  Print version number.

*-h*, *--help*::
   Print help message.

== Options

*--data-align* _ALIGNMENT_::
When creating a cpio archive, pad the cpio metadata to align the file data on
_ALIGNMENT_ in bytes. This option is useful to reflink cpio file data on file
systems that support reflinks.
This padding/alignment will be skipped for files that are smaller than
_ALIGNMENT_, files where the padded namesize field would exceed `PATH_MAX`,
and for cpio archives that are compressed.
_ALIGNMENT_ must be a multiple of 4 bytes.
This option is only taken into account in the *--create* mode.
+
The resulting cpio archive may be highly fragmented, which can lead to performance
degradation when reading/extracting the image from devices with slow random IO
(e.g. spinning disk).
+
**Note**: Using this option will "bend" the cpio newc spec a bit to inject
zeros after the filename to provide data segment alignment. These zeros are
accounted for in the namesize, but some applications may only expect a single
zero-terminator (and 4 byte alignment). GNU cpio and Linux initramfs handle
this fine as long as `PATH_MAX` is not exceeded.
+
The following command can be used to determine the optimal tranfer size of the
file system (where _$path_ is the path the cpio archive will be written to):
+
  stat --file-system -c "%s" -- "$path"

*-C* _DIR_, *--directory*=_DIR_::
  Change directory before performing any operation, but after opening the _ARCHIVE_.
  This option is only taken into account in the *--extract* mode.

*--make-directories*:
  Create leading directories where needed.
  This option is only taken into account in the *--extract* mode.

*-P* _LIST_, *--parts* _LIST_::
  Only operate on the cpio archives that matches _LIST_.
  This option is only taken into account in the *--list* and *--extract* modes.
  _LIST_ is made up of one range, or many ranges separated by commas.
  Each range is one of:

  N::: N'th cpio archive, counted from 1
  N-::: from N'th (included) to last cpio archive
  N-M::: from N'th to M'th (included) cpio archive
  -M::: from first to M'th (included) cpio archive

*-p*, *--preserve-permissions*::
  Set permissions of extracted files to those recorded in the archive (default
  for superuser). This option is only taken into account in the *--extract*
  mode.

*-s* _NAME_, *--subdir*=_NAME_::
  Extract the cpio archives into separate sub-directories (using the given
  _NAME_ plus an incrementing number). This option is only taken into account
  in the *--extract* mode.

*--to-stdout*::
  Extract files to standard output. Only the content of the files will be written
  to stdout.
  Directories and symlinks will be ignored.
  This option is only taken into account in the *--extract* mode.

*-v*, *--verbose*::
  Verbose output. This option is only taken into account in the *--extract* and
  *--list* modes.

*--debug*::
  Debug output. This option is only taken into account in the *--extract* and
  *--list* modes.

*--force*::
  Force overwriting existing files. This option is only taken into account in
  the *--extract* mode.

== Manifest

When generating initrd cpio archives, following manifest format will be used.
The manifest is a text format that is parsed line by line.

If the line starts with _#cpio_ it is interpreted as section marker to start
a new cpio. A compression may be specified by adding a colon followed by the
compression format and an optional compression level.
Example for a Zstandard-compressed cpio with compression level 9:

----
#cpio: zstd -9
----

All lines starting with _#_ excluding _#cpio_ (see above) will be
treated as comments and will be ignored.

Each element in the line is separated by a tab and is expected to be one
of the following file types:

----
<location> <name> file <mode> <uid> <gid> <mtime> <filesize>
<location> <name> dir <mode> <uid> <gid> <mtime>
<location> <name> block <mode> <uid> <gid> <mtime> <major> <minor>
<location> <name> char <mode> <uid> <gid> <mtime> <major> <minor>
<location> <name> link <mode> <uid> <gid> <mtime> <target>
<location> <name> fifo <mode> <uid> <gid> <mtime>
<location> <name> sock <mode> <uid> <gid> <mtime>
----

fifo is also known as named pipe (see fifo(7)).

In case an element is empty or equal to - it is treated as not specified
and it is derived from the input file.

<location>::
  Path of the input file. It can be left unspecified in case all other
  needed fields are specified (and the file is otherwise empty).
  *Limitation*: The path must not start with #, be equal to -,
  or contain tabs.

<name>::
  Path of the file inside the cpio. If the name is left unspecified it
  will be derived from <location>. *Limitation*: The path must not be
  equal to - or contain tabs.

<mode>::
  File mode specified in octal.

<uid>::
  User ID (owner) of the file specified in decimal.

<gid>::
  Group ID of the file specified in decimal.

<mtime>::
  Modification time of the file specified as seconds since the Epoch
  (1970-01-01 00:00 UTC). The specified time might be clamped by the
  time set in the SOURCE_DATE_EPOCH environment variable.

<filesize>::
  Size of the input file in bytes. 3cpio will fail in case the input
  file is smaller than the provided file size.

<major>::
  Major block/character device number in decimal.

<minor>::
  Minor block/character device number in decimal.

<target>::
  Target of the symbolic link. *Limitation*: The target path must not be
  equal to - or contain tabs.

*Limitations*: Files cannot start with # (will be treated as comment),
be equal to - (will be treated as not specified), or contain tabs (will
be split by tabs). These limitations of the manifest file are not
expected to cause problems in practice.

== Environment variables

SOURCE_DATE_EPOCH::
  This environment variable will be taken into account when creating
  cpio archive.
  All modification times that are newer than the time specified in
  "SOURCE_DATE_EPOCH" will be clamped.
  Compressors will run with only one thread in case their multithreading
  implementation is not reproducible.
  The created cpio archive will be reproducible across multiple runs.

== Exit status

*0*::
  Success.

*1*::
  Failure.

*2*::
  Failure during command line argument parsing.

== Examples

List the number of cpio archives that an initramfs file contains:

[example,shell]
----
$ 3cpio --count /boot/initrd.img
4
----

Examine the content of the initramfs cpio on an Ubuntu 24.04 system:

[example,shell]
----
$ 3cpio --examine /boot/initrd.img
0	cpio
77312	cpio
7286272	cpio
85523968	zstd
----

This initramfs cpio consists of three uncompressed cpio archives followed by a
Zstandard-compressed cpio archive.

List the content of the initramfs cpio on an Ubuntu 24.04 system:

[example,shell]
----
$ 3cpio --list /boot/initrd.img
.
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/AuthenticAMD.bin
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/.enuineIntel.align.0123456789abc
kernel/x86/microcode/GenuineIntel.bin
.
usr
usr/lib
usr/lib/firmware
usr/lib/firmware/3com
usr/lib/firmware/3com/typhoon.bin.zst
[...]
----

The first cpio contains only the AMD microcode. The second cpio contains only
the Intel microcode. The third cpio contains firmware files and kernel modules.

Extract the content of the initramfs cpio to the initrd subdirectory on an
Ubuntu 24.04 system:

[example,shell]
----
$ 3cpio --extract -C initrd /boot/initrd.img
$ ls initrd
bin   cryptroot  init    lib    lib.usr-is-merged  run   scripts  var
conf  etc        kernel  lib64  libx32             sbin  usr
----

Create a cpio archive similar to the other cpio tools using the `find` command:

[example,shell]
----
$ cd inputdir && find . | sort | 3cpio --create ../example.cpio
----

Due to its manifest file format support, 3cpio can create cpio archives without
the need of copying files into a temporary directory first. Example for creating
an early microcode cpio image directly using the system installed files:

[example,shell]
----
$ cat manifest
-	kernel	dir	755	0	0	1751654557
-	kernel/x86	dir	755	0	0	1752011622
/usr/lib/firmware/amd-ucode	kernel/x86/microcode
/usr/lib/firmware/amd-ucode/microcode_amd_fam19h.bin	kernel/x86/microcode/AuthenticAMD.bin
$ 3cpio --create amd-ucode.img < manifest
$ 3cpio --list --verbose amd-ucode.img
drwxr-xr-x   2 root     root            0 Jul  4 20:42 kernel
drwxr-xr-x   2 root     root            0 Jul  8 23:53 kernel/x86
drwxr-xr-x   2 root     root            0 Jun 10 10:51 kernel/x86/microcode
-rw-r--r--   1 root     root       100684 Mar 23 22:42 kernel/x86/microcode/AuthenticAMD.bin
----

Example for creating an initrd image containing of an uncompressed early
microcode cpio followed by a Zstandard-compressed cpio:

[example,shell]
----
$ cat manifest
#cpio
-	kernel	dir	755	0	0	1751654557
-	kernel/x86	dir	755	0	0	1752011622
/usr/lib/firmware/amd-ucode	kernel/x86/microcode
/usr/lib/firmware/amd-ucode/microcode_amd_fam19h.bin	kernel/x86/microcode/AuthenticAMD.bin
#cpio: zstd -9
/
/bin
/usr
/usr/bin
/usr/bin/bash
# This is a comment. Leaving the remaining files as task for the reader.
$ 3cpio --create initrd.img < manifest
$ 3cpio --examine initrd.img
0	cpio
101332	zstd
$ 3cpio --list --verbose initrd.img
drwxr-xr-x   2 root     root            0 Jul  4 20:42 kernel
drwxr-xr-x   2 root     root            0 Jul  8 23:53 kernel/x86
drwxr-xr-x   2 root     root            0 Jun 10 10:51 kernel/x86/microcode
-rw-r--r--   1 root     root       100684 Mar 23 22:42 kernel/x86/microcode/AuthenticAMD.bin
drwxr-xr-x   2 root     root            0 Jun  5 14:11 .
lrwxrwxrwx   1 root     root            7 Mar 20  2022 bin -> usr/bin
drwxr-xr-x   2 root     root            0 Apr 20  2023 usr
drwxr-xr-x   2 root     root            0 Jul  9 09:56 usr/bin
-rwxr-xr-x   1 root     root      1740896 Mar  5 03:35 usr/bin/bash
----

== See also

bsdcpio(1), cpio(1), lsinitramfs(8), lsinitrd(1)

== Copying

Copyright (C) 2024-2025 Benjamin Drung.
Free use of this software is granted under the terms of the ISC License.
