To write archives, you’ll need a CPIOArchiveWriter:
var writer = CPIOArchiveWriter()
Once you have your writer, you must create a Header, that describes the file you wish to add to your archive:
var time: Int = 1615929568
// You can also use date
let date: Date = ...
time = Int(date.timeIntervalSince1970)
// File
let header = Header(
name: "hello.txt",
mode: FileMode(0o644, modes: [.regular]),
modificationTime: time
)
// Directory
let header = Header(
name: "dir/",
mode: FileMode(0o644, modes: [.directory]),
modificationTime: time
)
Checksums
If you would like to provide a cpio checksum with the Header you created above, there are two ways to do so.
Computed Checksum
// Compute the checksum.
let fileContents: [UInt8] = ...
let checksum = Checksum(bytes: fileContents)
Pre-computed Checksum
let preComputedChecksum = 123
let checksum = Checksum(sum: preComputedChecksum)
l
Once you have a checksum, add it to the checksum parameter of your Header:
Header(..., checksum: checksum, ...)
Once you have your Header, you can write it, along with the contents of your file, to the archive:
// Without Foundation
var contents = Array("Hello".utf8)
// With Foundation
let myData: Data = "Hello".data(using .utf8)!
contents = Array<UInt8>(myData)
writer.addFile(header: header, contents: contents)
If you have a text file, use the overloaded version of addFile:
writer.addFile(header: header, contents: "Hello")
For directories, omit the contents parameter in addFile. For symlinks, set the contents parameter to the file or directory the link points to.
Once you have added your files, you must call finalize() to create the archive and return the data:
// The binary representation (Array<UInt8>) of the created archive.
let bytes = writer.finalize()
// You convert it to `Data` like this:
let data = Data(bytes)
// And write it:
try data.write(to: URL(fileURLWithPath: "myArchive.cpio"))
if you want to reuse writer, call finalize(clear: true) instead, which will clear the state inside writer.
Reading Archives
To read archives, you need an CPIOArchiveReader:
// myData is the bytes of the archive.
let myData: Data = ...
let reader = CPIOArchiveReader(archive: Array<UInt8>(myData))
Once you have your reader, there are several ways you can retrieve the data:
Iteration
You can iterate though all the files in the archive like this:
for (header, data) in reader {
// `data` is `Array<UInt8>` that contains the raw bytes of the file in the archive.
// `header` is the `Header` that describes the `data`.
// if you know `data` is a `String`, then you can use this initializer:
let str = String(data)
}
Subscript
Accessing data through the subscript is useful when you only need to access a few items in a large archive:
// The subscript provides you with random access to any file in the archive:
let firstFile = reader[0]
let fifthFile = reader[6]
You can also use the version of the subscript that takes a Header - useful for when you have a Header, but not the index of that header.
let header = reader.headers.first(where: { $0.name.contains(".swift") })!
let data = reader[header: header]
FileMode
Once you have retrived a FileMode from a Header in a CPIOArchiveReader, you can access the file’s type and UNIX permissions.
File Type
let type = header.mode.type
switch type {
case .regular: // Regular file.
case .directory: // Directory.
case .symlink: // Symbolic link.
...
}
Permissions
To access the UNIX permissions, use the permissions variable in FileMode.
Examples
Examples/CreateReadWrite: This example shows how to use CPIOArchiveKit to read, create, or extract an archive; or compute a checksum for an archive using only Darwin.C (macOS), Glibc (Linux) or ucrt (Windows (not tested)).
Other Platforms
CPIOArchiveKit doesn’t depend on any library, Foundation, or Darwin/Glibc/ucrt - only the Swift standard library. It should compile on any platform where the standard library compiles.
Windows
CPIOArchiveKit is currently being built on Windows, but not tested, as the Swift Package Manager Resources doesn’t seem to work (or isn’t available) on Windows.
CPIOArchiveKit
A simple, 0-dependency Swift package for reading and writing
cpio
archives. Inspired by go-cpio.Table of Contents
Created by gh-md-toc
Documentation is available here.
Installation
Swift Package Manager
Add this to the
dependencies
array inPackage.swift
:Also add this to the
targets
array in the aforementioned file:Usage
Writing Archives
To write archives, you’ll need a
CPIOArchiveWriter
:Once you have your writer, you must create a
Header
, that describes the file you wish to add to your archive:Checksums
If you would like to provide a cpio checksum with the
Header
you created above, there are two ways to do so.Computed Checksum
Pre-computed Checksum
Once you have a
checksum
, add it to the checksum parameter of yourHeader
:Once you have your
Header
, you can write it, along with the contents of your file, to the archive:If you have a text file, use the overloaded version of
addFile
:Once you have added your files, you must call
finalize()
to create the archive and return the data:if you want to reuse
writer
, callfinalize(clear: true)
instead, which will clear the state insidewriter
.Reading Archives
To read archives, you need an
CPIOArchiveReader
:Once you have your reader, there are several ways you can retrieve the data:
Iteration
You can iterate though all the files in the archive like this:
Subscript
Accessing data through the
subscript
is useful when you only need to access a few items in a large archive:You can also use the version of the subscript that takes a
Header
- useful for when you have aHeader
, but not the index of that header.FileMode
Once you have retrived a
FileMode
from aHeader
in aCPIOArchiveReader
, you can access the file’s type and UNIX permissions.File Type
Permissions
To access the UNIX permissions, use the
permissions
variable inFileMode
.Examples
Examples/CreateReadWrite
: This example shows how to use CPIOArchiveKit to read, create, or extract an archive; or compute a checksum for an archive using onlyDarwin.C
(macOS),Glibc
(Linux) orucrt
(Windows (not tested)).Other Platforms
CPIOArchiveKit doesn’t depend on any library,
Foundation
, orDarwin
/Glibc
/ucrt
- only the Swift standard library. It should compile on any platform where the standard library compiles.Windows
CPIOArchiveKit is currently being built on Windows, but not tested, as the Swift Package Manager Resources doesn’t seem to work (or isn’t available) on Windows.
Contributing
Before committing, please install pre-commit, swift-format, and Prettier, then install the pre-commit hook:
To install pre-commit on other platforms, refer to the documentation.