macOS v0.1.0
Installation
Add macOS to the [Dependencies] table of your package's Rux.toml:
[Dependencies]
macOS = { Namespace = "Rux", Version = "0.1.0" }
Standard packages are declared by hand: the registry does not serve them, so rux add Rux/macOS cannot add them.
Dependencies
Core0.1.0
Guide
macOS platform bindings: the Darwin ABI as libSystem publishes it, which on this system is the only interface Apple supports.
What it provides
| Module | Covers |
|---|---|
Types | the Darwin ABI's own types: ProcessId, FileDescriptor, FileMode, UserId, Timespec, Timeval |
Errors | the errno numbers, CurrentErrno, and the Normalize / IsError / Errno fold |
LibSystem | every libSystem entry point this package binds, under the symbol it exports, including _NSGetArgc, _NSGetArgv and _NSGetEnviron |
File | Read, Write, Close, OpenAt, Lseek, Fsync, Ftruncate, UnlinkAt, MkdirAt, RenameAt, Dup2, Pipe, the open flags, and the three standard descriptors |
Memory | Mmap, Munmap, Mprotect, Madvise, QueryPageSize, and the protection, mapping and advice flags |
Clock | ClockGetTime, ClockGetResolution, GetTimeOfDay, Nanosleep, and the clock identifiers |
Entropy | GetRandom, which cannot fail and has no short count |
Process | Exit and GetPid |
Dynamic | the RTLD_* flags; dlopen, dlsym, dlclose and dlerror are in LibSystem |
Thread | pthread_create, pthread_join, pthread_detach, the pthread_attr_* stack-size calls, sched_yield, sysconf and SC_NPROCESSORS_ONLN, and pthread_threadid_np, linked from libSystem |
Ulock | __ulock_wait, __ulock_wake and their flags, the word operations every lock in Rux/Sync sleeps on |
Spawn | posix_spawnp, the posix_spawn_file_actions_* calls, waitpid, kill and fcntl |
Socket | the BSD socket calls behind the same wrappers as Linux and FreeBSD, SO_NOSIGPIPE, and getaddrinfo, freeaddrinfo and AddressInfo |
Poll | Kqueue and KeventCall over libSystem's kqueue and kevent, Kevent, the EVFILT_* and EV_* flags, and FcntlInt with F_GETFL, F_SETFL and O_NONBLOCK |
The module names describe where each declaration comes from; they are not part of an import path.
Apple does not support calling the kernel directly. The trap numbers are private, they have changed between releases, and on Apple Silicon the trap interface is not reachable from ordinary code at all. libSystem is the ABI, and this package binds it — which is what makes it different in kind from Rux/Linux and Rux/FreeBSD, whose kernels publish a stable numbering.
libSystem reports failure the way C does, with -1 and a positive errno reached through an accessor. Normalize folds those two into the one negative-error convention the other platform packages use, so IsError and Errno read the same on all three.
Nothing here is interchangeable with the other platform packages. AT_FDCWD is -2 on Darwin and -100 elsewhere; monotonic is clock 6 here, 1 on Linux, 4 on FreeBSD; RTLD_LOCAL is 4 and RTLD_GLOBAL is 8, where both other systems use 0 and 256. A value carried across compiles and means something else.
There is no Brk: Darwin's brk and sbrk have been unavailable to 64-bit code from the start. There is no Pipe2: Darwin has only pipe, so close-on-exec must be set afterwards. And Fsync is weaker here than elsewhere — it does not wait for the device to commit, which F_FULLFSYNC through fcntl is what does.
What is tested
Tests/Packages/macOS/Descriptors covers descriptor numbering, short reads and writes, end of file, size boundaries and the native error for each way of misusing a descriptor or a name. Tests/Packages/macOS/Mapping covers anonymous mappings, protection changes, advice, the requests the kernel refuses, and both edges of the reserved error-result window. Tests/Packages/macOS/Syscall covers the wrapper surface and the shared POSIX contract.
All of it compiles for both architectures, and none of it has ever run on a host that is not macOS. Until it does, the syscall numbers, flag values and errno constants here rest on published documentation rather than on a passing test.
The shared POSIX contract
Nothing here is interchangeable with Rux/Linux or Rux/FreeBSD, but the three are spelled the same, which is a different claim and a deliberate one. An equivalent call has the same wrapper name, the same parameter names and the same parameter shapes on all three systems, so a consumer such as Rux/FileSystem or Rux/Time writes one call site instead of a when #target.os ladder around three names for one idea. Tests/Unit/PlatformBindingContractTests.cpp compares the three packages' parsed sources and fails when they drift apart.
The values are the opposite: every constant is this system's own, and the same file asserts that the ones a reader might carry across really do differ.
Values and pointers
Darwin records such as Timespec and Timeval are structural values and copy by value, and every call that reads or fills one takes its address: GetTimeOfDay(@time), ClockGetTime(ClockMonotonic, @time). That is the convention on all three POSIX packages. It is not the prettiest form available here — libSystem's C declarations would accept a reference, and this package used them until the divergence showed up as target branches in Rux/Time — but one shape across three systems is worth more than a borrow on one of them.
libSystem declarations retain raw pointers for nullable parameters, byte buffers, loader handles, and OS-owned storage. These pointers do not express ownership; use the documented close or unmap operation, or prefer Rux/Io and Rux/Memory for managed interfaces.
Platform
macOS only. Guard use behind a compile-time check, so a build for another target never resolves these declarations:
import Core::{ #target };
when #target.os == .macOS {
import macOS::{ StdOut, Write };
}
Index
Types
| Name | Summary |
|---|---|
Kevent | One struct kevent as 64-bit macOS lays it out: a change to register or an event to report. |
AddressInfo | The C library's addrinfo: one result of getaddrinfo, linked to the next. |
SpawnFileActions | Room for a posix_spawn_file_actions_t, which each C library sizes its own way and none larger than this. |
PThread | A thread as the C library names it, pthread_t. |
PThreadAttributes | Room for a pthread_attr_t, which each C library sizes its own way and none larger than this. |
ProcessId | A process identifier, as getpid reports one. |
FileDescriptor | A file descriptor, as the kernel numbers one. |
FileOffset | A byte offset within a file, 64 bits on every supported Apple target. |
FileMode | A file's type and permission bits. |
UserId | A user identifier. |
GroupId | A group identifier. |
Timespec | A duration or an instant, as seconds and nanoseconds. |
Timeval | A duration or an instant, as seconds and microseconds. |
Functions
| Name | Summary |
|---|---|
ClockGetTime | Reads clockId into time. |
ClockGetResolution | Reads the resolution of clockId into resolution. |
GetTimeOfDay | Reads the wall clock into time, to microsecond resolution. |
Nanosleep | Suspends the caller for the requested duration. |
GetRandom | Fills length bytes of buffer with unpredictable bytes. |
CurrentErrno | The calling thread's current errno value. |
Normalize | Folds a libSystem result and the thread's errno into one value. |
IsError | Whether a normalized result is one of the reserved error values. |
Errno | The error number a normalized result carries, or zero when it carries none. |
Read | Reads up to count bytes from fd into buffer. |
Write | Writes up to count bytes from buffer to fd. |
Close | Closes fd and releases what the kernel held for it. |
OpenAt | Opens path relative to directoryFd and returns a descriptor, or a negative error number. |
Lseek | Moves the file offset of fd and returns where it ended up, or a negative error number. |
Getcwd | Writes the current working directory's absolute path into buffer, NUL-terminated. |
Chdir | Makes path the process's working directory. |
ReadlinkAt | Reads the text a symbolic link holds into buffer. |
Fstat | Fills statBuffer with what the kernel knows about the file behind fd. |
FstatAt | Fills statBuffer with what the kernel knows about the file path names. |
FchmodAt | Sets the permission bits of the file path names. |
UtimensAt | Sets the access and modification times of the file path names. |
LinkAt | Creates a hard link: newPath becomes a second name for the file oldPath names. |
SymlinkAt | Creates a symbolic link at linkPath holding target as its text. |
Getdirentries64 | Reads directory entries from fd into buffer, and returns the bytes filled, zero at the end, or a negative error number. |
Fsync | Flushes everything written to fd toward the storage device. |
Ftruncate | Sets the length of the file behind fd to length. |
UnlinkAt | Removes the name path from its directory. |
MkdirAt | Creates a directory named path with permission bits mode. |
RenameAt | Renames oldPath to newPath, each resolved against its own directory descriptor. |
Dup2 | Makes newFd a copy of oldFd, closing whatever newFd was. |
Pipe | Creates a pipe and writes its two descriptors into descriptors. |
getpagesize | Reports the system page size, in bytes. |
_NSGetArgc | The address of the process's argument count. |
_NSGetArgv | The address of the process's argument vector. |
_NSGetExecutablePath | Copies the path of the process's executable into buffer, NUL-terminated. |
_NSGetEnviron | The address of the process's environment vector. |
dlopen | Loads a shared object and returns a handle to it, or null on failure. |
dlsym | Finds a symbol in a loaded object and returns its address, or null. |
dlclose | Drops one reference to a loaded object, unloading it when the last one goes. |
dlerror | Reports the most recent loader error and clears it, or returns null when there is none. |
Mmap | Creates a mapping and returns its address, or a negative error number. |
Munmap | Releases the mapping that begins at address and spans length bytes. |
Mprotect | Changes what may be done with the pages covering a range. |
Madvise | Tells the kernel how the pages covering a range are about to be used. |
QueryPageSize | The size of a page, asked of libSystem. |
FcntlInt | Performs command on a descriptor with an integer argument. |
Kqueue | Opens a kqueue. |
KeventCall | Applies changeCount changes, then waits until an event is ready or timeout passes, filling events. |
Exit | Ends the calling process with code. |
GetPid | The calling process's own identifier. |
Socket | Opens a socket. |
Connect | Connects a socket to address, waiting for a stream connection to be made. |
Bind | Gives a socket its local address. |
Listen | Makes a bound stream socket accept connections. |
Accept4 | Accepts a waiting connection as a new socket. |
SendTo | Sends bytes on a socket, to address when it is not connected. |
ReceiveFrom | Receives bytes from a socket, and where they came from. |
Shutdown | Ends one or both directions of a connection. |
SetSocketOption | Sets a socket option. |
GetSocketName | Reads a socket's local address. |
GetPeerName | Reads the address of a connected socket's peer. |
getaddrinfo | Looks up the addresses of a host and service. |
freeaddrinfo | Frees the results of getaddrinfo. |
posix_spawnp | Starts file, found through PATH when it has no slash, as a child process. |
posix_spawn_file_actions_init | Initializes an empty list of file actions. |
posix_spawn_file_actions_destroy | Releases what posix_spawn_file_actions_init and the actions added since set up. |
posix_spawn_file_actions_adddup2 | Adds an action duplicating fd onto newFd in the child. |
posix_spawn_file_actions_addopen | Adds an action opening path as fd in the child. |
posix_spawn_file_actions_addchdir_np | Adds an action changing the child's working directory to path. |
waitpid | Waits for a child to change state, and reports how it finished. |
kill | Sends a signal to a process. |
fcntl | Performs a control operation on a descriptor, such as setting its flags with F_SETFD. |
pthread_create | Starts a thread running start(argument). |
pthread_join | Waits for a thread to finish and releases it. |
pthread_detach | Lets a thread release itself when it finishes, so nothing has to join it. |
pthread_attr_init | Initializes thread attributes to the defaults. |
pthread_attr_setstacksize | Sets the stack size a thread started with these attributes gets. |
pthread_attr_destroy | Releases what pthread_attr_init set up. |
pthread_threadid_np | Reads the system-wide identifier of a thread, or of the calling thread when thread is zero. |
sched_yield | Gives up the processor so another ready thread can run. |
sysconf | Reads a system configuration value. |
__ulock_wait | Sleeps while *address equals value, until a wake, a signal or the timeout. |
__ulock_wake | Wakes a thread, or all of them with ULF_WAKE_ALL, sleeping on address. |
Constants
| Name | Summary |
|---|---|
ClockRealtime | CLOCK_REALTIME: wall-clock time, which can jump when the system clock is set. |
ClockMonotonic | CLOCK_MONOTONIC: time since boot, which never goes backwards. |
ClockMonotonicRaw | CLOCK_MONOTONIC_RAW: like ClockMonotonic, but not adjusted by time synchronization. |
RTLD_LAZY | RTLD_LAZY: resolve a function symbol the first time it is called rather than at load. |
RTLD_NOW | RTLD_NOW: resolve every symbol before dlopen returns. |
RTLD_LOCAL | RTLD_LOCAL: keep this object's symbols to itself, which is Darwin's default. |
RTLD_GLOBAL | RTLD_GLOBAL: make this object's symbols available to objects loaded afterwards. |
EPERM | EPERM: the operation is not permitted to this caller. |
ENOENT | ENOENT: no such file or directory. |
ESRCH | ESRCH: no process has that identifier. |
EINTR | EINTR: the call was interrupted by a signal before it did anything. |
EIO | EIO: a low-level input or output error. |
ENXIO | ENXIO: no such device or address. |
EBADF | EBADF: the file descriptor is not open, or is not open for what was asked. |
ENOMEM | ENOMEM: not enough memory to satisfy the request. |
EACCES | EACCES: permission denied. |
EFAULT | EFAULT: an address the call was given is outside the caller's address space. |
EBUSY | EBUSY: the resource is in use by something else. |
EEXIST | EEXIST: the file already exists. |
EXDEV | EXDEV: the two paths are on different file systems. |
ENOTDIR | ENOTDIR: a path component that had to be a directory is not one. |
EISDIR | EISDIR: the target is a directory and the operation is not one a directory accepts. |
EINVAL | EINVAL: an argument is not valid. |
EMFILE | EMFILE: this process has too many descriptors open. |
ENOSPC | ENOSPC: the device has no room left. |
ESPIPE | ESPIPE: the descriptor is a pipe or socket and cannot be seeked. |
EROFS | EROFS: the file system is mounted read-only. |
EPIPE | EPIPE: the reading end of the pipe is closed. |
EAGAIN | EAGAIN: the operation would block, and the descriptor was set not to. |
ELOOP | ELOOP: too many symbolic links were followed resolving the path. |
ENAMETOOLONG | ENAMETOOLONG: the path or a component of it is too long. |
ENOSYS | ENOSYS: the system does not implement this call. |
EOVERFLOW | EOVERFLOW: a value is too large for the type the call reports it in. |
ETIMEDOUT | ETIMEDOUT: the operation timed out. |
MaximumErrno | The largest error number the normalized error range holds. |
StdIn | The descriptor a process reads its input from, unless something reassigned it. |
StdOut | The descriptor a process writes its output to. |
StdErr | The descriptor a process writes its diagnostics to. |
AtFdCwd | AT_FDCWD: resolve a relative path against the current directory rather than a descriptor. |
OpenReadOnly | O_RDONLY: open for reading only. |
OpenWriteOnly | O_WRONLY: open for writing only. |
OpenReadWrite | O_RDWR: open for both reading and writing. |
OpenCreate | O_CREAT: create the file when it does not exist, which is when the mode argument is read. |
OpenExclusive | O_EXCL: with OpenCreate, fail rather than open a file that already exists. |
OpenTruncate | O_TRUNC: truncate the file to nothing when opening it for writing. |
OpenAppend | O_APPEND: every write goes to the end. |
OpenNonBlocking | O_NONBLOCK: reads and writes report EAGAIN rather than waiting. |
OpenCloseOnExec | O_CLOEXEC: close this descriptor automatically when the process executes a new program. |
OpenDirectory | O_DIRECTORY: fail unless the target is a directory. |
SeekSet | SEEK_SET: measure the new offset from the start of the file. |
SeekCurrent | SEEK_CUR: measure the new offset from the current one. |
SeekEnd | SEEK_END: measure the new offset from the end of the file. |
RemoveDirectory | AT_REMOVEDIR: make UnlinkAt remove a directory rather than a file. |
SymlinkNoFollow | AT_SYMLINK_NOFOLLOW: act on a symbolic link itself rather than on what it points at. |
FollowSymlinks | AT_SYMLINK_FOLLOW: make LinkAt link a symbolic link's target rather than the link. |
SystemLib | The library every Darwin interface is reached through. |
ProtectionNone | PROT_NONE: the pages may not be touched at all. |
ProtectionRead | PROT_READ: the pages may be read. |
ProtectionWrite | PROT_WRITE: the pages may be written. |
ProtectionExecute | PROT_EXEC: the pages may be executed. |
MapShared | MAP_SHARED: writes are visible to other mappings of the same object and reach it. |
MapPrivate | MAP_PRIVATE: writes are private to this mapping and never reach the object. |
MapFixed | MAP_FIXED: place the mapping exactly at the requested address, replacing whatever was there. |
MapAnonymous | MAP_ANON: the mapping is backed by zeroed pages rather than by a file. |
AdviseFree | MADV_FREE: the pages may be reclaimed, and read back as zero if they are. |
AdviseDontNeed | MADV_DONTNEED: the pages are not needed soon. |
AdviseWillNeed | MADV_WILLNEED: the pages will be read soon. |
F_GETFL | F_GETFL: the fcntl command that reads a descriptor's status flags. |
F_SETFL | F_SETFL: the fcntl command that sets a descriptor's status flags. |
O_NONBLOCK | O_NONBLOCK: the status flag that makes a call fail with EAGAIN rather than wait. |
EVFILT_READ | EVFILT_READ: the filter that reports a descriptor with something to read, or a connection to accept. |
EVFILT_WRITE | EVFILT_WRITE: the filter that reports a descriptor a write would not wait on. |
EV_ADD | EV_ADD: add the change's filter, or update it. |
EV_DELETE | EV_DELETE: remove the change's filter. |
EV_RECEIPT | EV_RECEIPT: report each change as an event, with its outcome in data, rather than waiting. |
EV_ERROR | EV_ERROR: set on an event that reports a failed change, with the error number in data. |
EV_EOF | EV_EOF: the peer has closed its side. |
AF_INET | AF_INET: the IPv4 address family. |
AF_INET6 | AF_INET6: the IPv6 address family. |
SOCK_STREAM | SOCK_STREAM: a connected byte stream. |
SOCK_DGRAM | SOCK_DGRAM: individual datagrams. |
SOL_SOCKET | SOL_SOCKET: the level of the options every socket has. |
SO_REUSEADDR | SO_REUSEADDR: let a listening address be bound again while old connections to it wind down. |
SO_RCVTIMEO | SO_RCVTIMEO: how long a receive waits. |
SO_SNDTIMEO | SO_SNDTIMEO: how long a send waits. |
IPPROTO_TCP | IPPROTO_TCP: the level of TCP's options. |
TCP_NODELAY | TCP_NODELAY: send small writes at once rather than gathering them. |
IPPROTO_IPV6 | IPPROTO_IPV6: the level of IPv6's options. |
IPV6_V6ONLY | IPV6_V6ONLY: accept only IPv6 on an IPv6 socket. |
SO_NOSIGPIPE | SO_NOSIGPIPE: report a closed peer as an error rather than with SIGPIPE. |
F_SETFD | F_SETFD: the fcntl command that sets a descriptor's flags. |
FD_CLOEXEC | FD_CLOEXEC: close the descriptor when the process starts another program. |
WNOHANG | WNOHANG: have waitpid return at once when the child has not finished. |
SIGKILL | SIGKILL: the signal that ends a process at once and cannot be caught. |
SC_NPROCESSORS_ONLN | _SC_NPROCESSORS_ONLN: the sysconf name for the number of processors currently online. |
UL_COMPARE_AND_WAIT | UL_COMPARE_AND_WAIT: wait on a 32-bit word that holds the expected value. |
ULF_WAKE_ALL | ULF_WAKE_ALL: wake every thread waiting on the word rather than one. |
ULF_NO_ERRNO | ULF_NO_ERRNO: report failure as a negative error number rather than through errno. |