Documentation ¶
Overview ¶
Read and write Linux kernel initramfs-style cpio "newc" formatted archives.
This implementation follows the documented kernel buffer format. See also early userspace support for more information about how the kernel uses initramfs during the boot process.
See go.pdmccormick.com/initramfs/examples for demonstrations of how to use this package.
Index ¶
- Constants
- Variables
- func Bzip2Reader(r io.Reader) (io.Reader, error)
- func ComputeChecksum(data []byte) (sum uint32)
- func GzipReader(r io.Reader) (io.Reader, error)
- func GzipWriter(w io.Writer) (io.Writer, error)
- func ReaderChecksum(r io.Reader) (sum uint32, err error)
- type CompressReader
- type CompressReaderMap
- type CompressWriter
- type Flusher
- type Header
- type InvalidByteError
- type Lookahead
- type Magic
- type Mode
- func (m Mode) BlockDevice() bool
- func (m Mode) CharDevice() bool
- func (m *Mode) ClearBits(bits int) Mode
- func (m Mode) Dir() bool
- func (m Mode) FIFO() bool
- func (m Mode) File() bool
- func (m Mode) FileType() Mode
- func (m Mode) Perms() int
- func (m Mode) SGID() bool
- func (m Mode) SUID() bool
- func (m *Mode) SetBits(bits int) Mode
- func (m *Mode) SetFileType(ftype int) Mode
- func (m *Mode) SetPerms(perms int) Mode
- func (m Mode) Socket() bool
- func (m Mode) Sticky() bool
- func (m Mode) String() string
- func (m Mode) Symlink() bool
- func (m Mode) WithPerms(perms int) Mode
- type Reader
- func (r *Reader) All() iter.Seq2[int, Header]
- func (r *Reader) ContinueCompressed(compressReaders CompressReaderMap) (isCompressed bool, compressType Lookahead, err error)
- func (r *Reader) Next() (*Header, error)
- func (r *Reader) Read(buf []byte) (int, error)
- func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
- type Writer
- func (iw *Writer) Close() error
- func (iw *Writer) Flush() error
- func (iw *Writer) MkdirAll(path string, perm Mode) error
- func (iw *Writer) ReadFrom(r io.Reader) (n int64, err error)
- func (iw *Writer) SetDataAlignment(alignTo int) error
- func (iw *Writer) SetHeaderAlignment(alignTo int) error
- func (iw *Writer) StartCompression(c CompressWriter) error
- func (iw *Writer) Write(buf []byte) (n int, err error)
- func (iw *Writer) WriteHeader(hdr *Header) error
- func (iw *Writer) WriteTrailer() error
Constants ¶
const ( MicrocodeX86Path = "kernel/x86/microcode/" MicrocodePath_AuthenticAMD = "kernel/x86/microcode/AuthenticAMD.bin" MicrocodePath_GenuineIntel = "kernel/x86/microcode/GenuineIntel.bin" )
The Linux kernel can load x86 microcode updates from an initramfs very early in the boot process. See The Linux Microcode Loader and the go.pdmccormick.com/initramfs/examples/earlyinitramfs example.
const ( Magic_070701 = `070701` Magic_070702 = `070702` )
Magic identifiers for cpio archive member file headers.
const HeaderSize = 110
The size of a member file header within a cpio archive.
const MicrocodeDataAlignment = 16
Current practise is to align Intel x86 kernel microcode update data to a 16 byte boundary, although this may only be necessary for older kernel versions.
Use with Writer.SetDataAlignment.
const StartCompressionAlignment = 512
Before the start of a compressed stream within an archive, the output will be padded to match this alignment.
const TrailerFilename = "TRAILER!!!"
The sentinel filename that indicates end-of-archive.
Variables ¶
var ( ErrMalformedFilename = errors.New("initramfs: filename field is missing trailing 0") ErrBadHeaderMagic = errors.New("initramfs: header contains a bad magic value") )
Errors related to Header.
var ( ErrBadAlignment = errors.New("initramfs: alignment must itself be a multiple of 4") ErrBadDataAlignment = errors.New("initramfs: unable to align data as requested given the filename") ErrAlreadyCompressed = errors.New("initramfs: writer compression is already being applied") )
var CompressReaders = CompressReaderMap{ Gzip: GzipReader, Bzip2: Bzip2Reader, }
A global map of known compression readers.
The default only includes compressors that exist within the standard library. See go.pdmccormick.com/initramfs/examples for sample implementations of existing packages.
var ErrCompressedContentAhead = errors.New("initramfs: compressed content ahead")
var ErrNoCompressReader = errors.New("initramfs: no suitable CompressReader found")
Functions ¶
func Bzip2Reader ¶
A CompressReader using compress/bzip2.NewReader.
func ComputeChecksum ¶
Compute the 32-bit unsigned sum of all the data bytes.
This is the simple algorithm as used by the kernel for calculating the value of the Header Checksum field, as noted in the buffer format documentation.
func GzipReader ¶
A CompressReader using compress/gzip.NewReader.
func GzipWriter ¶
A CompressWriter using compress/gzip.NewWriter.
func ReaderChecksum ¶
Computes the 32-bit unsigned sum of all the bytes from given reader. See ComputeChecksum for details.
Types ¶
type CompressReader ¶
A CompressReader will decompress the given input.
type CompressReaderMap ¶
type CompressReaderMap map[Lookahead]CompressReader
Use the Lookahead token to select a suitable CompressReader.
type CompressWriter ¶
A CompressWriter will compress anything written to it and write the compressed data to the given output.
When compressing an initramfs archive using Xz, review the XZ compression options to ensure compatibility.
type Flusher ¶
type Flusher interface {
Flush() error
}
Any writer that supports flushing its output.
type Header ¶
type Header struct { HeaderOffset int64 DataOffset int64 // Fixed length fields Magic string // Either `070701` or `070702` Inode uint32 // File inode number Mode Mode // File mode and permission bits Uid uint32 // File owner user id Gid uint32 // File owner group id NumLinks uint32 // Number of hard links Mtime time.Time // Modification time (seconds since Unix epoch) DataSize uint32 // Size of file data following the header Major uint32 // Major part of file device number Minor uint32 // Minor part of file device number RMajor uint32 // Major part of device node reference RMinor uint32 // Minor part of device node reference FilenameSize uint32 // Length of filename field (including trailing 0) Checksum uint32 // Checksum of data field (if magic is `070702`, otherwise 0) // Variable length field Filename string }
Header for a file member within a cpio archive.
func (*Header) ReadFrom ¶
Read and convert the textual form of the header and filename fields.
Returns an InvalidByteError if an invalid hexadecimal byte value is encountered. Returns ErrMalformedFilename if the filename field is missing a trailing 0.
type InvalidByteError ¶
type InvalidByteError int
An invalid hexadecimal character was found at an offset relative to the start of a Header.
func (*InvalidByteError) Error ¶
func (offs *InvalidByteError) Error() string
type Lookahead ¶
type Lookahead int
Identify what kind of data comes next in a stream by looking ahead a few bytes and identifying magic values.
Recognizes the difference between cpio archive member file headers, zero padding and various compression schemes. See the RD_ and INITRAMFS_COMPRESSION_ config options in Linux kernel usr/Kconfig.
const ( UnknownLookahead Lookahead = iota EOF // End of file Padding // Zero padding CpioFile // Start of cpio archive member file header Gzip // Start of Gzip compressed data Bzip2 // Start of Bzip2 compressed data Lzma // Start of LZMA compressed data Xz // Start of XZ compressed data Lzo // Start of LZO compressed data Lz4 // Start of LZ4 compressed data Zstd // Start of Zstd compressed data )
func PeekLookahead ¶
Uses bufio.Reader.Peek to determine what kind of data follows. Does not consume the input. Only returns non-EOF errors.
func (Lookahead) Compression ¶
Returns true if and only if the lookahead indicates the start of compressed data.
type Magic ¶
type Magic uint16
Magic byte values used to identify the start of various types of compressed data streams.
These match what the kernel uses, see Linux kernel lib/decompress.c.
const ( CpioFileMagic Magic = 0x30_37 // A cpio archive member file header starts with "07" (either "070701" or "070702") GzipMagic1 Magic = 0x1F_8B GzipMagic2 Magic = 0x1F_9E Bzip2Magic Magic = 0x42_5A LzmaMagic Magic = 0x5D_00 XzMagic Magic = 0xFD_37 LzoMagic Magic = 0x89_4C Lz4Magic Magic = 0x02_21 ZstdMagic Magic = 0x28_B5 )
func SniffMagic ¶
Determine if the provided bytes are a recognized magic value.
func (Magic) MatchBytes ¶
type Mode ¶
type Mode uint32
File mode and permission bits
const ( Mode_FileTypeMask Mode = 0o170_000 Mode_Socket Mode = 0o140_000 // File type for sockets. Mode_Symlink Mode = 0o120_000 // File type for symbolic links (file data is link target). Mode_File Mode = 0o100_000 // File type for regular files. Mode_BlockDevice Mode = 0o060_000 // File type for block devices. Mode_Dir Mode = 0o040_000 // File type for directories. Mode_CharDevice Mode = 0o020_000 // File type for character devices. Mode_FIFO Mode = 0o010_000 // File type for named pipes or FIFO's. Mode_SUID Mode = 0o004_000 // SUID bit. See https://man7.org/linux/man-pages/man2/setfsuid.2.html#DESCRIPTION Mode_SGID Mode = 0o002_000 // SGID bit. See https://man7.org/linux/man-pages/man2/setfsgid.2.html#DESCRIPTION Mode_Sticky Mode = 0o001_000 // Sticky bit. See https://www.man7.org/linux/man-pages/man1/chmod.1.html#RESTRICTED_DELETION_FLAG_OR_STICKY_BIT Mode_PermsMask Mode = 0o000_777 // Permission bits (read/write/execute for user, group and other). See https://man7.org/linux/man-pages/man1/chmod.1.html#DESCRIPTION UserRead Mode = 0o400 UserWrite Mode = 0o200 UserExecute Mode = 0o100 GroupRead Mode = 0o040 GroupWrite Mode = 0o020 GroupExecute Mode = 0o010 OtherRead Mode = 0o004 OtherWrite Mode = 0o002 OtherExecute Mode = 0o001 )
const DefaultMkdirPerm Mode = 0o700
Default permissions for directory entries
func (Mode) BlockDevice ¶
func (Mode) CharDevice ¶
func (*Mode) SetFileType ¶
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
func (*Reader) All ¶
Provides a sequence iterator that is equivalent to calling Reader.Next until EOF.
func (*Reader) ContinueCompressed ¶
func (r *Reader) ContinueCompressed(compressReaders CompressReaderMap) (isCompressed bool, compressType Lookahead, err error)
Attempt to continue reader into the start of a compressed data stream.
Returns ErrNoCompressReader if the CompressReaderMap does not contain a suitable reader for the encountered compression type.
func (*Reader) Next ¶
Consumes input looking for the next file entry. Returns ErrCompressedContentAhead if the start of compress data has been detected.
Check for compressed data by calling Reader.ContinueCompressed.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer
func (*Writer) Flush ¶
Flush any unwritten buffered output.
The base io.Writer or CompressWriter must implement the Flusher interface for this to be effective.
func (*Writer) MkdirAll ¶
Add a directory named path, along with any necessary parents, to the archive.
The writer tracks which directories have already been added, and will skip any that already exist.
func (*Writer) SetDataAlignment ¶
Attempts to set the alignment of the file data by adjusting the amount of padding before the next header write. Value must itself be a multiple of 4.
If the length of the header (110 bytes, see HeaderSize), plus the length of the NUL-terminated filename, is itself not a multiple of 4, the call to Writer.WriteHeader will return ErrBadDataAlignment. In the case of filename MicrocodePath_GenuineIntel, this will work.
Only one of header or data alignment can be applied, and whichever is called last prior to calling Writer.WriteHeader will be applied. After every call to Writer.WriteHeader alignment is reset.
func (*Writer) SetHeaderAlignment ¶
Sets the output alignment for the start of the next header write. Value must itself be a multiple of 4.
Only one of header or data alignment can be applied, and whichever is called last prior to calling Writer.WriteHeader will be applied. After every call to Writer.WriteHeader alignment is reset.
func (*Writer) StartCompression ¶
func (iw *Writer) StartCompression(c CompressWriter) error
Switch the writer to a compressed output stream, according to the supplied CompressWriter. It is not possible to end a compressed stream other than by reaching the end of the file, so all remaining output from the writer will be compressed.
func (*Writer) WriteHeader ¶
Write the header in textual form, respecting output alignment requirements. The header will first be updated to ensure well-formedness:
- If Magic is blank, it will be given a default value of Magic_070701
- NumLinks will be minimum 1
- If Inode is 0 and this is not a trailer, an inode number will be assigned
- All leading slashes will be removed from the Filename
- FilenameSize will be set to the length of Filename plus 1
func (*Writer) WriteTrailer ¶
Write the end-of-archive sentinel trailer entry.