CPIOArchiveKit

一个简单、零依赖的 Swift 包,用于读取和写入 cpio 归档文件。灵感来源于 go-cpio

Swift 5.3 SPM Compatible Build and Test

目录

gh-md-toc 创建

文档在此处 查阅

安装

Swift 包管理器

将此添加到 Package.swift 文件中的 dependencies 数组

.package(url: "https://github.com/LebJe/CPIOArchiveKit.git", from: "0.0.2")

也将其添加到上述文件中的 targets 数组

.product(name: "CPIOArchiveKit", package: "CPIOArchiveKit")

用法

写入归档文件

要写入归档文件,你需要一个 CPIOArchiveWriter

var writer = CPIOArchiveWriter()

一旦你有了 writer,你必须创建一个 Header,来描述你想要添加到归档文件中的文件

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
)

校验和

如果你想为上面创建的 Header 提供一个 cpio 校验和,有两种方法可以做到。

计算校验和
// Compute the checksum.
let fileContents: [UInt8] = ...
let checksum = Checksum(bytes: fileContents)
预计算校验和
let preComputedChecksum = 123
let checksum = Checksum(sum: preComputedChecksum)
l

一旦你有了 checksum,将其添加到你的 Header 的 checksum 参数中

Header(..., checksum: checksum, ...)

一旦你有了你的 Header,你可以将其连同你的文件内容一起写入归档文件

// 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)

如果你有一个文本文件,请使用 addFile 的重载版本

writer.addFile(header: header, contents: "Hello")

对于目录,省略 addFile 中的 contents 参数。对于符号链接,将 contents 参数设置为链接指向的文件或目录。

一旦你添加了你的文件,你必须调用 finalize() 来创建归档文件并返回数据

// 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"))

如果你想重用 writer,请调用 finalize(clear: true),这将清除 writer 内部的状态。

读取归档文件

要读取归档文件,你需要一个 CPIOArchiveReader

// myData is the bytes of the archive.
let myData: Data = ...

let reader = CPIOArchiveReader(archive: Array<UInt8>(myData))

一旦你有了 reader,你可以通过几种方式检索数据

迭代

你可以像这样迭代归档文件中的所有文件

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 访问数据非常有用

// The subscript provides you with random access to any file in the archive:
let firstFile = reader[0]
let fifthFile = reader[6]

你也可以使用接受 Header 的 subscript 版本 - 当你有一个 Header,但没有该 header 的索引时非常有用。

let header = reader.headers.first(where: { $0.name.contains(".swift") })!
let data = reader[header: header]

FileMode

一旦你从 CPIOArchiveReader 中的 Header 中检索到 FileMode,你就可以访问文件的类型和 UNIX 权限。

文件类型

let type = header.mode.type

switch type {
	case .regular: // Regular file.
	case .directory: // Directory.
	case .symlink: // Symbolic link.
	...
}

权限

要访问 UNIX 权限,请使用 FileMode 中的 permissions 变量。

示例

其他平台

CPIOArchiveKit 不依赖于任何库、FoundationDarwin/Glibc/ucrt - 仅依赖于 Swift 标准库。它应该可以在标准库编译的任何平台上编译。

Windows

CPIOArchiveKit 目前正在 Windows 上构建,但未经过测试,因为 Swift Package Manager Resources 似乎在 Windows 上不起作用(或不可用)。

贡献

在提交之前,请安装 pre-commitswift-formatPrettier,然后安装 pre-commit 钩子

$ brew bundle # install the packages specified in Brewfile
$ pre-commit install

# Commit your changes.

要在其他平台上安装 pre-commit,请参阅文档