Documentation ¶
Overview ¶
Package cpio providers readers and writers for CPIO archives. Currently, only the SVR4 (New ASCII) format is supported, both with and without checksums.
This package aims to be feel like Go's archive/tar package.
See the CPIO man page: https://www.freebsd.org/cgi/man.cgi?query=cpio&sektion=5
Example ¶
package main import ( "bytes" "fmt" "io" "log" "os" "kraftkit.sh/cpio" ) func main() { // Create a buffer to write our archive to. buf := new(bytes.Buffer) // Create a new cpio archive. w := cpio.NewWriter(buf) // Add some files to the archive. files := []struct { Name, Body string }{ {"readme.txt", "This archive contains some text files."}, {"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"}, {"todo.txt", "Get animal handling license."}, } for _, file := range files { hdr := &cpio.Header{ Name: file.Name, Mode: 0o600, Size: int64(len(file.Body)), } if err := w.WriteHeader(hdr); err != nil { log.Fatalln(err) } if _, err := w.Write([]byte(file.Body)); err != nil { log.Fatalln(err) } } // Make sure to check the error on Close. if err := w.Close(); err != nil { log.Fatalln(err) } // Open the cpio archive for reading. r := cpio.NewReader(buf) // Iterate through the files in the archive. for { hdr, _, err := r.Next() if err == io.EOF { // end of cpio archive break } if err != nil { log.Fatalln(err) } fmt.Printf("Contents of %s:\n", hdr.Name) if _, err := io.Copy(os.Stdout, r); err != nil { log.Fatalln(err) } fmt.Println() } }
Output: Contents of readme.txt: This archive contains some text files. Contents of gopher.txt: Gopher names: George Geoffrey Gonzo Contents of todo.txt: Get animal handling license.
Index ¶
Examples ¶
Constants ¶
const ( // TypeReg indicates a regular file TypeReg = 0o100000 // The following are header-only flags and may not have a data body. TypeSocket = 0o140000 // Socket TypeSymlink = 0o120000 // Symbolic link TypeBlock = 0o60000 // Block device node TypeDir = 0o40000 // Directory TypeChar = 0o20000 // Character device node TypeFifo = 0o10000 // FIFO node )
const ( ModeSetuid = 0o4000 // Set uid ModeSetgid = 0o2000 // Set gid ModeSticky = 0o1000 // Save text (sticky bit) ModeType = 0o170000 // Mask for the type bits ModePerm = 0o777 // Unix permission bits )
Variables ¶
var ( // ErrWriteTooLong indicates that an attempt was made to write more than // Header.Size bytes to the current file. ErrWriteTooLong = errors.New("cpio: write too long") // ErrWriteAfterClose indicates that an attempt was made to write to the // CPIO archive after it was closed. ErrWriteAfterClose = errors.New("cpio: write after close") )
var ErrHeader = errors.New("cpio: invalid cpio header")
ErrHeader indicates there was an error decoding a CPIO header entry.
Functions ¶
func NewHash ¶
NewHash returns a new hash.Hash32 for computing SVR4 checksums.
Example ¶
// Open the cpio archive for reading. f, err := os.Open("testdata/test_svr4_crc.cpio") if err != nil { log.Fatal(err) } defer f.Close() r := NewReader(f) // Iterate through the files in the archive. for { hdr, _, err := r.Next() if err == io.EOF { // end of cpio archive return } if err != nil { log.Fatal(err) } // skip symlinks, directories, etc. if !hdr.Mode.IsRegular() { continue } // read file into hash h := NewHash() _, err = io.CopyN(h, r, hdr.Size) if err != nil { log.Fatal(err) } // check hash matches header checksum sum := h.Sum32() if sum == hdr.Checksum { fmt.Printf("Checksum OK: %s (%08X)\n", hdr.Name, hdr.Checksum) } else { fmt.Printf("Checksum FAIL: %s - expected %08X, got %08X\n", hdr.Name, hdr.Checksum, sum) } }
Output: Checksum OK: gophers.txt (00000C98) Checksum OK: readme.txt (00000E3D) Checksum OK: todo.txt (00000A52)
Types ¶
type FileMode ¶
type FileMode uint32
A FileMode represents a file's mode and permission bits.
func (FileMode) IsDir ¶
IsDir reports whether m describes a directory. That is, it tests for the TypeDir bit being set in m.
func (FileMode) IsRegular ¶
IsRegular reports whether m describes a regular file. That is, it tests for the TypeReg bit being set in m.
type Header ¶
type Header struct { Name string // Name of the file entry NameSize int64 // Real size of the name field Linkname string // Target name of link (valid for TypeLink or TypeSymlink) Links int // Number of inbound links Size int64 // Size in bytes Mode FileMode // Permission and mode bits Uid int // User id of the owner Guid int // Group id of the owner ModTime time.Time // Modification time Checksum uint32 // Computed checksum DeviceID int Inode int64 // Inode number EntryPad int64 // Bytes to pad before next header NamePad int64 // Name bytes of padding }
A Header represents a single header in a CPIO archive. Some fields may not be populated.
For forward compatibility, users that retrieve a Header from Reader.Next, mutate it in some ways, and then pass it back to Writer.WriteHeader should do so by creating a new Header and copying the fields that they are interested in preserving.
func FileInfoHeader ¶
FileInfoHeader creates a partially-populated Header from fi. If fi describes a symlink, FileInfoHeader records link as the link target. If fi describes a directory, a slash is appended to the name.
Since fs.FileInfo's Name method returns only the base name of the file it describes, it may be necessary to modify Header.Name to provide the full path name of the file.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader provides sequential access to the contents of a CPIO archive. Reader.Next advances to the next file in the archive (including the first), and then Reader can be treated as an io.Reader to access the file's data.
func (*Reader) Next ¶
Next advances to the next entry in the CPIO archive. The Header.Size determines how many bytes can be read for the next file. Any remaining data in the current file is automatically discarded.
io.EOF is returned at the end of the input.
func (*Reader) Read ¶
Read reads from the current file in the CPIO archive. It returns (0, io.EOF) when it reaches the end of that file, until Next is called to advance to the next file.
Calling Read on special types like TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, and TypeFifo returns (0, io.EOF) regardless of what the Header.Size claims.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer provides sequential writing of a CPIO archive. Write.WriteHeader begins a new file with the provided Header, and then Writer can be treated as an io.Writer to supply that file's data.
func (*Writer) Close ¶
Close closes the CPIO archive by flushing the padding, and writing the footer. If the current file (from a prior call to WriteHeader) is not fully written, then this returns an error.
func (*Writer) Flush ¶
Flush finishes writing the current file's block padding. The current file must be fully written before Flush can be called.
This is unnecessary as the next call to WriteHeader or Close will implicitly flush out the file's padding.
func (*Writer) Write ¶
Write writes to the current file in the CPIO archive. Write returns the error ErrWriteTooLong if more than Header.Size bytes are written after WriteHeader.
Calling Write on special types like TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, and TypeFifo returns (0, ErrWriteTooLong) regardless of what the Header.Size claims.
func (*Writer) WriteHeader ¶
WriteHeader writes hdr and prepares to accept the file's contents. The Header.Size determines how many bytes can be written for the next file. If the current file is not fully written, then this returns an error. This implicitly flushes any padding necessary before writing the header.