Continue documenting public surface (#25)

Signed-off-by: Danny Canter <danny_canter@apple.com>
This commit is contained in:
Danny Canter
2025-06-06 10:34:19 -04:00
committed by GitHub
parent 46260fd6a6
commit fc4a124173
32 changed files with 215 additions and 33 deletions
@@ -18,10 +18,10 @@
import Foundation
import Synchronization
/// Async friendly wrapper around DispatchSourceSignal. Provides an AsyncStream
/// Async friendly wrapper around `DispatchSourceSignal`. Provides an `AsyncStream`
/// interface to get notified of received signals.
public final class AsyncSignalHandler: Sendable {
/// An async stream that returns the signal that was caught, if ever
/// An async stream that returns the signal that was caught, if ever.
public var signals: AsyncStream<Int32> {
let (stream, cont) = AsyncStream.makeStream(of: Int32.self)
self.state.withLock {
+24
View File
@@ -19,6 +19,7 @@ import Foundation
/// Trivial type to discover information about a given file (uid, gid, mode...).
public struct File: Sendable {
/// `File` errors.
public enum Error: Swift.Error, CustomStringConvertible {
case errno(_ e: Int32)
@@ -29,10 +30,17 @@ public struct File: Sendable {
}
}
}
/// Returns a `FileInfo` struct with information about the file.
/// - Parameters:
/// - url: The path to the file.
public static func info(_ url: URL) throws -> FileInfo {
try info(url.path)
}
/// Returns a `FileInfo` struct with information about the file.
/// - Parameters:
/// - path: The path to the file as a string.
public static func info(_ path: String) throws -> FileInfo {
var st = stat()
guard stat(path, &st) == 0 else {
@@ -42,6 +50,8 @@ public struct File: Sendable {
}
}
/// `FileInfo` holds and provides easy access to stat(2) data
/// for a file.
public struct FileInfo: Sendable {
private let _stat_t: Foundation.stat
private let _path: String
@@ -51,58 +61,72 @@ public struct FileInfo: Sendable {
self._stat_t = stat
}
/// mode_t for the file.
public var mode: mode_t {
self._stat_t.st_mode
}
/// The files uid.
public var uid: Int {
Int(self._stat_t.st_uid)
}
/// The files gid.
public var gid: Int {
Int(self._stat_t.st_gid)
}
/// The filesystem ID the file belongs to.
public var dev: Int {
Int(self._stat_t.st_dev)
}
/// The files inode number.
public var ino: Int {
Int(self._stat_t.st_ino)
}
/// The size of the file.
public var size: Int {
Int(self._stat_t.st_size)
}
/// The path to the file.
public var path: String {
self._path
}
/// Returns if the file is a directory.
public var isDirectory: Bool {
mode & S_IFMT == S_IFDIR
}
/// Returns if the file is a pipe.
public var isPipe: Bool {
mode & S_IFMT == S_IFIFO
}
/// Returns if the file is a socket.
public var isSocket: Bool {
mode & S_IFMT == S_IFSOCK
}
/// Returns if the file is a link.
public var isLink: Bool {
mode & S_IFMT == S_IFLNK
}
/// Returns if the file is a regular file.
public var isRegularFile: Bool {
mode & S_IFMT == S_IFREG
}
/// Returns if the file is a block device.
public var isBlock: Bool {
mode & S_IFMT == S_IFBLK
}
/// Returns if the file is a character device.
public var isChar: Bool {
mode & S_IFMT == S_IFCHR
}
+10 -2
View File
@@ -25,10 +25,14 @@ import Glibc
private let _mount = Glibc.mount
#endif
/// Small utility to mount or create new binfmt_misc entries.
/// `Binfmt` is a utlity type that contains static helpers and types for
/// mounting the Linux binfmt_misc filesystem, and creating new binfmt entries.
public struct Binfmt: Sendable {
/// Default mount path for binfmt_misc.
public static let path = "/proc/sys/fs/binfmt_misc"
/// Entry models a binfmt_misc entry.
/// https://docs.kernel.org/admin-guide/binfmt-misc.html
public struct Entry {
public var name: String
public var type: String
@@ -53,6 +57,7 @@ public struct Binfmt: Sendable {
self.flags = flags
}
/// Returns a binfmt `Entry` for amd64 ELF binaries.
public static func amd64() -> Self {
Binfmt.Entry(
name: "x86_64",
@@ -62,6 +67,7 @@ public struct Binfmt: Sendable {
}
#if os(Linux)
/// Register the passed in `binaryPath` as the interpreter for a new binfmt_misc entry.
public func register(binaryPath: String) throws {
let registration = ":\(self.name):\(self.type):\(self.offset):\(self.magic):\(self.mask):\(binaryPath):\(self.flags)"
@@ -72,7 +78,8 @@ public struct Binfmt: Sendable {
)
}
public func unregister() throws {
/// Deregister the binfmt_misc entry described by the current object.
public func deregister() throws {
let data = "-1"
try data.write(
to: URL(fileURLWithPath: Binfmt.path).appendingPathComponent(self.name),
@@ -89,6 +96,7 @@ public struct Binfmt: Sendable {
FileManager.default.fileExists(atPath: "\(Self.path)/register")
}
/// Mount the binfmt_misc filesystem.
public static func mount() throws {
guard _mount("binfmt_misc", Self.path, "binfmt_misc", 0, "") == 0 else {
throw POSIXError.fromErrno()
@@ -197,6 +197,7 @@ extension Mount {
return mountOpts
}
/// `Mount` errors
public enum Error: Swift.Error, CustomStringConvertible {
case errno(Int32, String)
case validation(String)
+9 -2
View File
@@ -19,10 +19,13 @@ import Foundation
/// Helper type with utilities to parse and manipulate unix signals.
public struct Signals {
/// Returns the numeric values of all known signals.
public static func allNumeric() -> [Int32] {
Array(Signals.all.values)
}
/// Parses a string representation of a signal (SIGKILL) and returns
// the 32 bit integer representation (9).
public static func parseSignal(_ signal: String) throws -> Int32 {
if let sig = Int32(signal) {
if !Signals.all.values.contains(sig) {
@@ -38,6 +41,7 @@ public struct Signals {
return sig
}
/// Errors that can be encountered for converting signals.
public enum Error: Swift.Error, CustomStringConvertible {
case invalidSignal(String)
@@ -53,7 +57,7 @@ public struct Signals {
#if os(macOS)
extension Signals {
/// all returns all signals for the current platform.
/// `all` returns all signals for the current platform.
public static let all: [String: Int32] = [
"ABRT": SIGABRT,
"ALRM": SIGALRM,
@@ -95,7 +99,10 @@ extension Signals {
#if os(Linux)
extension Signals {
/// all returns all signals for the current platform.
/// `all` returns all signals for the current platform.
///
/// For Linux this isn't actually exhaustive as it excludes
/// rtmin/rtmax entries.
public static let all: [String: Int32] = [
"ABRT": SIGABRT,
"ALRM": SIGALRM,
@@ -27,17 +27,19 @@ import Darwin
/// Protocol used to describe the family of socket to be created with `Socket`.
public protocol SocketType: Sendable, CustomStringConvertible {
/// The domain for the socket (AF_UNIX, AF_VSOCK etc.)
var domain: Int32 { get }
/// The type of socket (SOCK_STREAM).
var type: Int32 { get }
// Different socket types may want to expose things to do
// before bind and listen. UDS for example may want to change
// the permissions of the socket prior to bind/listen and also
// possibly unlink an existing socket before bind.
/// Actions to perform before calling bind(2).
func beforeBind(fd: Int32) throws
/// Actions to perform before calling listen(2).
func beforeListen(fd: Int32) throws
/// Handle accept(2) for an implementation of a socket type.
func accept(fd: Int32) throws -> (Int32, SocketType)
/// Provide a sockaddr pointer (by casting a socket specific type like sockaddr_un for example).
func withSockAddr(_ closure: (_ ptr: UnsafePointer<sockaddr>, _ len: UInt32) throws -> Void) throws
}
@@ -147,6 +147,7 @@ public struct UnixType: SocketType, Sendable, CustomStringConvertible {
}
extension UnixType {
/// `UnixType` errors.
public enum Error: Swift.Error, CustomStringConvertible {
case nameTooLong(_: String)