// Copyright (c) 2016-2017 Nuxi (https://nuxi.nl/) and contributors. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. // // This file is automatically generated. Do not edit. // // Source: https://github.com/NuxiNL/cloudabi // Appease Rust's tidy. // ignore-license // ignore-tidy-linelength //! **PLEASE NOTE: This entire crate including this //! documentation is automatically generated from //! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)** //! //! # Nuxi CloudABI //! //! CloudABI is what you get if you take POSIX, add capability-based //! security, and remove everything that's incompatible with that. The //! result is a minimal ABI consisting of only 49 syscalls. //! //! CloudABI doesn't have its own kernel, but instead is implemented in existing //! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set //! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for //! Linux](https://github.com/NuxiNL/linux) are available as well. This means that //! CloudABI binaries can be executed on different operating systems, without any //! modification. //! //! ## Capability-Based Security //! //! Capability-based security means that processes can only perform //! actions that have no global impact. Processes cannot open files by //! their absolute path, cannot open network connections, and cannot //! observe global system state such as the process table. //! //! The capabilities of a process are fully determined by its set of open //! file descriptors (fds). For example, files can only be opened if the //! process already has a file descriptor to a directory the file is in. //! //! Unlike in POSIX, where processes are normally started with file //! descriptors 0, 1, and 2 reserved for standard input, output, and //! error, CloudABI does not reserve any file descriptor numbers for //! specific purposes. //! //! In CloudABI, a process depends on its parent process to launch it with //! the right set of resources, since the process will not be able to open //! any new resources. For example, a simple static web server would need //! to be started with a file descriptor to a [TCP //! listener](https://github.com/NuxiNL/flower), and a file descriptor to //! the directory for which to serve files. The web server will then be //! unable to do anything other than reading files in that directory, and //! process incoming network connections. //! //! So, unknown CloudABI binaries can safely be executed without the need //! for containers, virtual machines, or other sandboxing technologies. //! //! Watch [Ed Schouten's Talk at //! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more //! information about what capability-based security for UNIX means. //! //! ## Cloudlibc //! //! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation //! of the C standard library, without all CloudABI-incompatible //! functions. For example, Cloudlibc does not have `printf`, but does //! have `fprintf`. It does not have `open`, but does have `openat`. //! //! ## CloudABI-Ports //! //! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a //! collection of ports of commonly used libraries and applications to //! CloudABI. It contains software such as `zlib`, `libpng`, `boost`, //! `memcached`, and much more. The software is patched to not depend on //! any global state, such as files in `/etc` or `/dev`, using `open()`, //! etc. //! //! ## Using CloudABI //! //! Instructions for using CloudABI (including kernel modules/patches, //! toolchain, and ports) are available for several operating systems: //! //! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/) //! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/) //! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/) //! - [Mac OS X](https://nuxi.nl/cloudabi/mac/) //! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/) //! //! ## Specification of the ABI //! //! The entire ABI is specified in a a file called //! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt), //! from which all //! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers) //! and documentation (including the one you're reading now) is generated. #![no_std] #![allow(non_camel_case_types)] include!("bitflags.rs"); /// File or memory access pattern advisory information. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum advice { /// The application expects that it will not access the /// specified data in the near future. DONTNEED = 1, /// The application expects to access the specified data /// once and then not reuse it thereafter. NOREUSE = 2, /// The application has no advice to give on its behavior /// with respect to the specified data. NORMAL = 3, /// The application expects to access the specified data /// in a random order. RANDOM = 4, /// The application expects to access the specified data /// sequentially from lower offsets to higher offsets. SEQUENTIAL = 5, /// The application expects to access the specified data /// in the near future. WILLNEED = 6, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } /// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html). #[repr(u32)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum auxtype { /// Base address of the binary argument data provided to /// [`proc_exec()`](fn.proc_exec.html). ARGDATA = 256, /// Length of the binary argument data provided to /// [`proc_exec()`](fn.proc_exec.html). ARGDATALEN = 257, /// Base address at which the executable is placed in /// memory. BASE = 7, /// Base address of a buffer of random data that may be /// used for non-cryptographic purposes, for example as a /// canary for stack smashing protection. CANARY = 258, /// Length of a buffer of random data that may be used /// for non-cryptographic purposes, for example as a /// canary for stack smashing protection. CANARYLEN = 259, /// Number of CPUs that the system this process is running /// on has. NCPUS = 260, /// Terminator of the auxiliary vector. NULL = 0, /// Smallest memory object size for which individual /// memory protection controls can be configured. PAGESZ = 6, /// Address of the first ELF program header of the /// executable. PHDR = 3, /// Number of ELF program headers of the executable. PHNUM = 4, /// Identifier of the process. /// /// This environment does not provide any simple numerical /// process identifiers, for the reason that these are not /// useful in distributed contexts. Instead, processes are /// identified by a UUID. /// /// This record should point to sixteen bytes of binary /// data, containing a version 4 UUID (fully random). PID = 263, /// Address of the ELF header of the vDSO. /// /// The vDSO is a shared library that is mapped in the /// address space of the process. It provides entry points /// for every system call supported by the environment, /// all having a corresponding symbol that is prefixed /// with `cloudabi_sys_`. System calls should be invoked /// through these entry points. /// /// The first advantage of letting processes call into a /// vDSO to perform system calls instead of raising /// hardware traps is that it allows for easy emulation of /// executables on top of existing operating systems. The /// second advantage is that in cases where an operating /// system provides native support for CloudABI executables, /// it may still implement partial userspace /// implementations of these system calls to improve /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides /// a more dynamic way of adding, removing or replacing /// system calls. SYSINFO_EHDR = 262, /// Thread ID of the initial thread of the process. TID = 261, #[doc(hidden)] _NonExhaustive = -1 as isize as u32, } /// Identifiers for clocks. #[repr(u32)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum clockid { /// The system-wide monotonic clock, which is defined as a /// clock measuring real time, whose value cannot be /// adjusted and which cannot have negative clock jumps. /// /// The epoch of this clock is undefined. The absolute /// time value of this clock therefore has no meaning. MONOTONIC = 1, /// The CPU-time clock associated with the current /// process. PROCESS_CPUTIME_ID = 2, /// The system-wide clock measuring real time. Time value /// zero corresponds with 1970-01-01T00:00:00Z. REALTIME = 3, /// The CPU-time clock associated with the current thread. THREAD_CPUTIME_ID = 4, #[doc(hidden)] _NonExhaustive = -1 as isize as u32, } /// A userspace condition variable. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct condvar(pub u32); /// The condition variable is in its initial state. There /// are no threads waiting to be woken up. If the /// condition variable has any other value, the kernel /// must be called to wake up any sleeping threads. pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0); /// Identifier for a device containing a file system. Can be used /// in combination with [`inode`](struct.inode.html) to uniquely identify a file on the /// local system. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct device(pub u64); /// A reference to the offset of a directory entry. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct dircookie(pub u64); /// Permanent reference to the first directory entry /// within a directory. pub const DIRCOOKIE_START: dircookie = dircookie(0); /// Error codes returned by system calls. /// /// Not all of these error codes are returned by the system calls /// provided by this environment, but are either used in userspace /// exclusively or merely provided for alignment with POSIX. #[repr(u16)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum errno { /// No error occurred. System call completed successfully. SUCCESS = 0, /// Argument list too long. TOOBIG = 1, /// Permission denied. ACCES = 2, /// Address in use. ADDRINUSE = 3, /// Address not available. ADDRNOTAVAIL = 4, /// Address family not supported. AFNOSUPPORT = 5, /// Resource unavailable, or operation would block. AGAIN = 6, /// Connection already in progress. ALREADY = 7, /// Bad file descriptor. BADF = 8, /// Bad message. BADMSG = 9, /// Device or resource busy. BUSY = 10, /// Operation canceled. CANCELED = 11, /// No child processes. CHILD = 12, /// Connection aborted. CONNABORTED = 13, /// Connection refused. CONNREFUSED = 14, /// Connection reset. CONNRESET = 15, /// Resource deadlock would occur. DEADLK = 16, /// Destination address required. DESTADDRREQ = 17, /// Mathematics argument out of domain of function. DOM = 18, /// Reserved. DQUOT = 19, /// File exists. EXIST = 20, /// Bad address. FAULT = 21, /// File too large. FBIG = 22, /// Host is unreachable. HOSTUNREACH = 23, /// Identifier removed. IDRM = 24, /// Illegal byte sequence. ILSEQ = 25, /// Operation in progress. INPROGRESS = 26, /// Interrupted function. INTR = 27, /// Invalid argument. INVAL = 28, /// I/O error. IO = 29, /// Socket is connected. ISCONN = 30, /// Is a directory. ISDIR = 31, /// Too many levels of symbolic links. LOOP = 32, /// File descriptor value too large. MFILE = 33, /// Too many links. MLINK = 34, /// Message too large. MSGSIZE = 35, /// Reserved. MULTIHOP = 36, /// Filename too long. NAMETOOLONG = 37, /// Network is down. NETDOWN = 38, /// Connection aborted by network. NETRESET = 39, /// Network unreachable. NETUNREACH = 40, /// Too many files open in system. NFILE = 41, /// No buffer space available. NOBUFS = 42, /// No such device. NODEV = 43, /// No such file or directory. NOENT = 44, /// Executable file format error. NOEXEC = 45, /// No locks available. NOLCK = 46, /// Reserved. NOLINK = 47, /// Not enough space. NOMEM = 48, /// No message of the desired type. NOMSG = 49, /// Protocol not available. NOPROTOOPT = 50, /// No space left on device. NOSPC = 51, /// Function not supported. NOSYS = 52, /// The socket is not connected. NOTCONN = 53, /// Not a directory or a symbolic link to a directory. NOTDIR = 54, /// Directory not empty. NOTEMPTY = 55, /// State not recoverable. NOTRECOVERABLE = 56, /// Not a socket. NOTSOCK = 57, /// Not supported, or operation not supported on socket. NOTSUP = 58, /// Inappropriate I/O control operation. NOTTY = 59, /// No such device or address. NXIO = 60, /// Value too large to be stored in data type. OVERFLOW = 61, /// Previous owner died. OWNERDEAD = 62, /// Operation not permitted. PERM = 63, /// Broken pipe. PIPE = 64, /// Protocol error. PROTO = 65, /// Protocol not supported. PROTONOSUPPORT = 66, /// Protocol wrong type for socket. PROTOTYPE = 67, /// Result too large. RANGE = 68, /// Read-only file system. ROFS = 69, /// Invalid seek. SPIPE = 70, /// No such process. SRCH = 71, /// Reserved. STALE = 72, /// Connection timed out. TIMEDOUT = 73, /// Text file busy. TXTBSY = 74, /// Cross-device link. XDEV = 75, /// Extension: Capabilities insufficient. NOTCAPABLE = 76, #[doc(hidden)] _NonExhaustive = -1 as isize as u16, } bitflags! { /// The state of the file descriptor subscribed to with /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE). #[repr(C)] pub struct eventrwflags: u16 { /// The peer of this socket has closed or disconnected. const HANGUP = 0x0001; } } /// Type of a subscription to an event or its occurrence. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum eventtype { /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id) /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout). CLOCK = 1, /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been /// acquired for writing. CONDVAR = 2, /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has /// data available for reading. This event always triggers /// for regular files. FD_READ = 3, /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has /// capacity available for writing. This event always /// triggers for regular files. FD_WRITE = 4, /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for /// reading. LOCK_RDLOCK = 5, /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for /// writing. LOCK_WRLOCK = 6, /// The process associated with process descriptor /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated. PROC_TERMINATE = 7, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } /// Exit code generated by a process when exiting. pub type exitcode = u32; /// A file descriptor number. /// /// Unlike on POSIX-compliant systems, none of the file descriptor /// numbers are reserved for a purpose (e.g., stdin, stdout, /// stderr). Operating systems are not required to allocate new /// file descriptors in ascending order. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct fd(pub u32); /// Returned to the child process by [`proc_fork()`](fn.proc_fork.html). pub const PROCESS_CHILD: fd = fd(0xffffffff); /// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to /// anonymous memory. pub const MAP_ANON_FD : fd = fd(0xffffffff); bitflags! { /// File descriptor flags. #[repr(C)] pub struct fdflags: u16 { /// Append mode: Data written to the file is always /// appended to the file's end. const APPEND = 0x0001; /// Write according to synchronized I/O data integrity /// completion. Only the data stored in the file is /// synchronized. const DSYNC = 0x0002; /// Non-blocking mode. const NONBLOCK = 0x0004; /// Synchronized read I/O operations. const RSYNC = 0x0008; /// Write according to synchronized I/O file integrity /// completion. In addition to synchronizing the data /// stored in the file, the system may also synchronously /// update the file's metadata. const SYNC = 0x0010; } } bitflags! { /// Which file descriptor attributes to adjust. #[repr(C)] pub struct fdsflags: u16 { /// Adjust the file descriptor flags stored in /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags). const FLAGS = 0x0001; /// Restrict the rights of the file descriptor to the /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting). const RIGHTS = 0x0002; } } /// Relative offset within a file. pub type filedelta = i64; /// Non-negative file size or length of a region within a file. pub type filesize = u64; /// The type of a file descriptor or file. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum filetype { /// The type of the file descriptor or file is unknown or /// is different from any of the other types specified. UNKNOWN = 0, /// The file descriptor or file refers to a block device /// inode. BLOCK_DEVICE = 16, /// The file descriptor or file refers to a character /// device inode. CHARACTER_DEVICE = 17, /// The file descriptor or file refers to a directory /// inode. DIRECTORY = 32, /// The file descriptor refers to a process handle. PROCESS = 80, /// The file descriptor or file refers to a regular file /// inode. REGULAR_FILE = 96, /// The file descriptor refers to a shared memory object. SHARED_MEMORY = 112, /// The file descriptor or file refers to a datagram /// socket. SOCKET_DGRAM = 128, /// The file descriptor or file refers to a byte-stream /// socket. SOCKET_STREAM = 130, /// The file refers to a symbolic link inode. SYMBOLIC_LINK = 144, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } bitflags! { /// Which file attributes to adjust. #[repr(C)] pub struct fsflags: u16 { /// Adjust the last data access timestamp to the value /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim). const ATIM = 0x0001; /// Adjust the last data access timestamp to the time /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME). const ATIM_NOW = 0x0002; /// Adjust the last data modification timestamp to the /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim). const MTIM = 0x0004; /// Adjust the last data modification timestamp to the /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME). const MTIM_NOW = 0x0008; /// Truncate or extend the file to the size stored in /// [`filestat.st_size`](struct.filestat.html#structfield.st_size). const SIZE = 0x0010; } } /// File serial number that is unique within its file system. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct inode(pub u64); /// Number of hard links to an inode. pub type linkcount = u32; /// A userspace read-recursive readers-writer lock, similar to a /// Linux futex or a FreeBSD umtx. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct lock(pub u32); /// Value indicating that the lock is in its initial /// unlocked state. pub const LOCK_UNLOCKED : lock = lock(0x00000000); /// Bitmask indicating that the lock is write-locked. If /// set, the lower 30 bits of the lock contain the /// identifier of the thread that owns the write lock. /// Otherwise, the lower 30 bits of the lock contain the /// number of acquired read locks. pub const LOCK_WRLOCKED : lock = lock(0x40000000); /// Bitmask indicating that the lock is either read locked /// or write locked, and that one or more threads have /// their execution suspended, waiting to acquire the /// lock. The last owner of the lock must call the /// kernel to unlock. /// /// When the lock is acquired for reading and this bit is /// set, it means that one or more threads are attempting /// to acquire this lock for writing. In that case, other /// threads should only acquire additional read locks if /// suspending execution would cause a deadlock. It is /// preferred to suspend execution, as this prevents /// starvation of writers. pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000); /// Value indicating that the lock is in an incorrect /// state. A lock cannot be in its initial unlocked state, /// while also managed by the kernel. pub const LOCK_BOGUS : lock = lock(0x80000000); bitflags! { /// Flags determining the method of how paths are resolved. #[repr(C)] pub struct lookupflags: u32 { /// As long as the resolved path corresponds to a symbolic /// link, it is expanded. const SYMLINK_FOLLOW = 0x00000001; } } bitflags! { /// Memory mapping flags. #[repr(C)] pub struct mflags: u8 { /// Instead of mapping the contents of the file provided, /// create a mapping to anonymous memory. The file /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html), /// and the offset must be set to zero. const ANON = 0x01; /// Require that the mapping is performed at the base /// address provided. const FIXED = 0x02; /// Changes are private. const PRIVATE = 0x04; /// Changes are shared. const SHARED = 0x08; } } bitflags! { /// Memory page protection options. /// /// This implementation enforces the `W^X` property: Pages cannot be /// mapped for execution while also mapped for writing. #[repr(C)] pub struct mprot: u8 { /// Page can be executed. const EXEC = 0x01; /// Page can be written. const WRITE = 0x02; /// Page can be read. const READ = 0x04; } } bitflags! { /// Methods of synchronizing memory with physical storage. #[repr(C)] pub struct msflags: u8 { /// Perform asynchronous writes. const ASYNC = 0x01; /// Invalidate cached data. const INVALIDATE = 0x02; /// Perform synchronous writes. const SYNC = 0x04; } } /// Specifies the number of threads sleeping on a condition /// variable that should be woken up. pub type nthreads = u32; bitflags! { /// Open flags used by [`file_open()`](fn.file_open.html). #[repr(C)] pub struct oflags: u16 { /// Create file if it does not exist. const CREAT = 0x0001; /// Fail if not a directory. const DIRECTORY = 0x0002; /// Fail if file already exists. const EXCL = 0x0004; /// Truncate file to size 0. const TRUNC = 0x0008; } } bitflags! { /// Flags provided to [`sock_recv()`](fn.sock_recv.html). #[repr(C)] pub struct riflags: u16 { /// Returns the message without removing it from the /// socket's receive queue. const PEEK = 0x0004; /// On byte-stream sockets, block until the full amount /// of data can be returned. const WAITALL = 0x0010; } } bitflags! { /// File descriptor rights, determining which actions may be /// performed. #[repr(C)] pub struct rights: u64 { /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html). /// /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC). const FD_DATASYNC = 0x0000000000000001; /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html). /// /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option /// [`READ`](struct.mprot.html#associatedconstant.READ). /// /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke /// [`fd_pread()`](fn.fd_pread.html). const FD_READ = 0x0000000000000002; /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL). const FD_SEEK = 0x0000000000000004; /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS). const FD_STAT_PUT_FLAGS = 0x0000000000000008; /// The right to invoke [`fd_sync()`](fn.fd_sync.html). /// /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC). const FD_SYNC = 0x0000000000000010; /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with /// offset zero). const FD_TELL = 0x0000000000000020; /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html). /// /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE). /// /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to /// invoke [`fd_pwrite()`](fn.fd_pwrite.html). const FD_WRITE = 0x0000000000000040; /// The right to invoke [`file_advise()`](fn.file_advise.html). const FILE_ADVISE = 0x0000000000000080; /// The right to invoke [`file_allocate()`](fn.file_allocate.html). const FILE_ALLOCATE = 0x0000000000000100; /// The right to invoke [`file_create()`](fn.file_create.html) with /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY). const FILE_CREATE_DIRECTORY = 0x0000000000000200; /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT). const FILE_CREATE_FILE = 0x0000000000000400; /// The right to invoke [`file_link()`](fn.file_link.html) with the file /// descriptor as the source directory. const FILE_LINK_SOURCE = 0x0000000000001000; /// The right to invoke [`file_link()`](fn.file_link.html) with the file /// descriptor as the target directory. const FILE_LINK_TARGET = 0x0000000000002000; /// The right to invoke [`file_open()`](fn.file_open.html). const FILE_OPEN = 0x0000000000004000; /// The right to invoke [`file_readdir()`](fn.file_readdir.html). const FILE_READDIR = 0x0000000000008000; /// The right to invoke [`file_readlink()`](fn.file_readlink.html). const FILE_READLINK = 0x0000000000010000; /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file /// descriptor as the source directory. const FILE_RENAME_SOURCE = 0x0000000000020000; /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file /// descriptor as the target directory. const FILE_RENAME_TARGET = 0x0000000000040000; /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html). const FILE_STAT_FGET = 0x0000000000080000; /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE). /// /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC). const FILE_STAT_FPUT_SIZE = 0x0000000000100000; /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM), /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW). const FILE_STAT_FPUT_TIMES = 0x0000000000200000; /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html). const FILE_STAT_GET = 0x0000000000400000; /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM), /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW). const FILE_STAT_PUT_TIMES = 0x0000000000800000; /// The right to invoke [`file_symlink()`](fn.file_symlink.html). const FILE_SYMLINK = 0x0000000001000000; /// The right to invoke [`file_unlink()`](fn.file_unlink.html). const FILE_UNLINK = 0x0000000002000000; /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`](struct.mprot.html) set to /// zero. const MEM_MAP = 0x0000000004000000; /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC). const MEM_MAP_EXEC = 0x0000000008000000; /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ). /// /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE). const POLL_FD_READWRITE = 0x0000000010000000; /// The right to invoke [`poll()`](fn.poll.html) to subscribe to /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE). const POLL_PROC_TERMINATE = 0x0000000040000000; /// The right to invoke [`proc_exec()`](fn.proc_exec.html). const PROC_EXEC = 0x0000000100000000; /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html). const SOCK_SHUTDOWN = 0x0000008000000000; } } bitflags! { /// Flags returned by [`sock_recv()`](fn.sock_recv.html). #[repr(C)] pub struct roflags: u16 { /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors /// has been truncated. const FDS_TRUNCATED = 0x0001; /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been /// truncated. const DATA_TRUNCATED = 0x0008; } } /// Indicates whether an object is stored in private or shared /// memory. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum scope { /// The object is stored in private memory. PRIVATE = 4, /// The object is stored in shared memory. SHARED = 8, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } bitflags! { /// Which channels on a socket need to be shut down. #[repr(C)] pub struct sdflags: u8 { /// Disables further receive operations. const RD = 0x01; /// Disables further send operations. const WR = 0x02; } } bitflags! { /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags /// defined, it must be set to zero. #[repr(C)] pub struct siflags: u16 { const DEFAULT = 0; } } /// Signal condition. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum signal { /// Process abort signal. /// /// Action: Terminates the process. ABRT = 1, /// Alarm clock. /// /// Action: Terminates the process. ALRM = 2, /// Access to an undefined portion of a memory object. /// /// Action: Terminates the process. BUS = 3, /// Child process terminated, stopped, or continued. /// /// Action: Ignored. CHLD = 4, /// Continue executing, if stopped. /// /// Action: Continues executing, if stopped. CONT = 5, /// Erroneous arithmetic operation. /// /// Action: Terminates the process. FPE = 6, /// Hangup. /// /// Action: Terminates the process. HUP = 7, /// Illegal instruction. /// /// Action: Terminates the process. ILL = 8, /// Terminate interrupt signal. /// /// Action: Terminates the process. INT = 9, /// Kill. /// /// Action: Terminates the process. KILL = 10, /// Write on a pipe with no one to read it. /// /// Action: Ignored. PIPE = 11, /// Terminal quit signal. /// /// Action: Terminates the process. QUIT = 12, /// Invalid memory reference. /// /// Action: Terminates the process. SEGV = 13, /// Stop executing. /// /// Action: Stops executing. STOP = 14, /// Bad system call. /// /// Action: Terminates the process. SYS = 15, /// Termination signal. /// /// Action: Terminates the process. TERM = 16, /// Trace/breakpoint trap. /// /// Action: Terminates the process. TRAP = 17, /// Terminal stop signal. /// /// Action: Stops executing. TSTP = 18, /// Background process attempting read. /// /// Action: Stops executing. TTIN = 19, /// Background process attempting write. /// /// Action: Stops executing. TTOU = 20, /// High bandwidth data is available at a socket. /// /// Action: Ignored. URG = 21, /// User-defined signal 1. /// /// Action: Terminates the process. USR1 = 22, /// User-defined signal 2. /// /// Action: Terminates the process. USR2 = 23, /// Virtual timer expired. /// /// Action: Terminates the process. VTALRM = 24, /// CPU time limit exceeded. /// /// Action: Terminates the process. XCPU = 25, /// File size limit exceeded. /// /// Action: Terminates the process. XFSZ = 26, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } bitflags! { /// Flags determining how the timestamp provided in /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted. #[repr(C)] pub struct subclockflags: u16 { /// If set, treat the timestamp provided in /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id). /// /// If clear, treat the timestamp provided in /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id). const ABSTIME = 0x0001; } } bitflags! { /// Flags influencing the method of polling for read or writing on /// a file descriptor. #[repr(C)] pub struct subrwflags: u16 { /// Deprecated. Must be set by callers and ignored by /// implementations. const POLL = 0x0001; } } /// Unique system-local identifier of a thread. This identifier is /// only valid during the lifetime of the thread. /// /// Threads must be aware of their thread identifier, as it is /// written it into locks when acquiring them for writing. It is /// not advised to use these identifiers for any other purpose. /// /// As the thread identifier is also stored in [`lock`](struct.lock.html) when /// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread /// must always be set to zero. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct tid(pub u32); /// Timestamp in nanoseconds. pub type timestamp = u64; bitflags! { /// Specifies whether files are unlinked or directories are /// removed. #[repr(C)] pub struct ulflags: u8 { /// If set, removes a directory. Otherwise, unlinks any /// non-directory file. const REMOVEDIR = 0x01; } } /// User-provided value that can be attached to objects that is /// retained when extracted from the kernel. pub type userdata = u64; /// Relative to which position the offset of the file descriptor /// should be set. #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum whence { /// Seek relative to current position. CUR = 1, /// Seek relative to end-of-file. END = 2, /// Seek relative to start-of-file. SET = 3, #[doc(hidden)] _NonExhaustive = -1 as isize as u8, } /// Auxiliary vector entry. /// /// The auxiliary vector is a list of key-value pairs that is /// provided to the process on startup. Unlike structures, it is /// extensible, as it is possible to add new records later on. /// The auxiliary vector is always terminated by an entry having /// type [`NULL`](enum.auxtype.html#variant.NULL). /// /// The auxiliary vector is part of the x86-64 ABI, but is used by /// this environment on all architectures. #[repr(C)] #[derive(Copy, Clone)] pub struct auxv { /// The type of the auxiliary vector entry. pub a_type: auxtype, pub union: auxv_union } /// A union inside `auxv`. #[repr(C)] #[derive(Copy, Clone)] pub union auxv_union { /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID). /// A numerical value. pub a_val: usize, /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR). /// A pointer value. pub a_ptr: *mut (), } #[test] #[cfg(target_pointer_width = "32")] fn auxv_layout_test_32() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: auxv = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.a_type as *const _ as usize - base, 0); assert_eq!(&obj.union.a_val as *const _ as usize - base, 4); assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4); } } #[test] #[cfg(target_pointer_width = "64")] fn auxv_layout_test_64() { assert_eq!(::core::mem::size_of::(), 16); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: auxv = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.a_type as *const _ as usize - base, 0); assert_eq!(&obj.union.a_val as *const _ as usize - base, 8); assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8); } } /// A region of memory for scatter/gather writes. #[repr(C)] #[derive(Copy, Clone)] pub struct ciovec { /// The address and length of the buffer to be written. pub buf: (*const (), usize), } #[test] #[cfg(target_pointer_width = "32")] fn ciovec_layout_test_32() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: ciovec = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.buf.0 as *const _ as usize - base, 0); assert_eq!(&obj.buf.1 as *const _ as usize - base, 4); } } #[test] #[cfg(target_pointer_width = "64")] fn ciovec_layout_test_64() { assert_eq!(::core::mem::size_of::(), 16); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: ciovec = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.buf.0 as *const _ as usize - base, 0); assert_eq!(&obj.buf.1 as *const _ as usize - base, 8); } } /// A directory entry. #[repr(C)] #[derive(Copy, Clone)] pub struct dirent { /// The offset of the next directory entry stored in this /// directory. pub d_next: dircookie, /// The serial number of the file referred to by this /// directory entry. pub d_ino: inode, /// The length of the name of the directory entry. pub d_namlen: u32, /// The type of the file referred to by this directory /// entry. pub d_type: filetype, } #[test] fn dirent_layout_test() { assert_eq!(::core::mem::size_of::(), 24); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: dirent = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.d_next as *const _ as usize - base, 0); assert_eq!(&obj.d_ino as *const _ as usize - base, 8); assert_eq!(&obj.d_namlen as *const _ as usize - base, 16); assert_eq!(&obj.d_type as *const _ as usize - base, 20); } } /// An event that occurred. #[repr(C)] #[derive(Copy, Clone)] pub struct event { /// User-provided value that got attached to /// [`subscription.userdata`](struct.subscription.html#structfield.userdata). pub userdata: userdata, /// If non-zero, an error that occurred while processing /// the subscription request. pub error: errno, /// The type of the event that occurred. pub type_: eventtype, pub union: event_union } /// A union inside `event`. #[repr(C)] #[derive(Copy, Clone)] pub union event_union { /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE). pub fd_readwrite: event_fd_readwrite, /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE). pub proc_terminate: event_proc_terminate, } #[repr(C)] #[derive(Copy, Clone)] pub struct event_fd_readwrite { /// The number of bytes available /// for reading or writing. pub nbytes: filesize, /// Obsolete. pub unused: [u8; 4], /// The state of the file /// descriptor. pub flags: eventrwflags, } #[repr(C)] #[derive(Copy, Clone)] pub struct event_proc_terminate { /// Obsolete. pub unused: [u8; 4], /// If zero, the process has /// exited. /// Otherwise, the signal /// condition causing it to /// terminated. pub signal: signal, /// If exited, the exit code of /// the process. pub exitcode: exitcode, } #[test] fn event_layout_test() { assert_eq!(::core::mem::size_of::(), 32); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: event = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.userdata as *const _ as usize - base, 0); assert_eq!(&obj.error as *const _ as usize - base, 8); assert_eq!(&obj.type_ as *const _ as usize - base, 10); assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16); assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24); assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28); assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16); assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20); assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24); } } /// File descriptor attributes. #[repr(C)] #[derive(Copy, Clone)] pub struct fdstat { /// File type. pub fs_filetype: filetype, /// File descriptor flags. pub fs_flags: fdflags, /// Rights that apply to this file descriptor. pub fs_rights_base: rights, /// Maximum set of rights that can be installed on new /// file descriptors that are created through this file /// descriptor, e.g., through [`file_open()`](fn.file_open.html). pub fs_rights_inheriting: rights, } #[test] fn fdstat_layout_test() { assert_eq!(::core::mem::size_of::(), 24); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: fdstat = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0); assert_eq!(&obj.fs_flags as *const _ as usize - base, 2); assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8); assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16); } } /// File attributes. #[repr(C)] #[derive(Copy, Clone)] pub struct filestat { /// Device ID of device containing the file. pub st_dev: device, /// File serial number. pub st_ino: inode, /// File type. pub st_filetype: filetype, /// Number of hard links to the file. pub st_nlink: linkcount, /// For regular files, the file size in bytes. For /// symbolic links, the length in bytes of the pathname /// contained in the symbolic link. pub st_size: filesize, /// Last data access timestamp. pub st_atim: timestamp, /// Last data modification timestamp. pub st_mtim: timestamp, /// Last file status change timestamp. pub st_ctim: timestamp, } #[test] fn filestat_layout_test() { assert_eq!(::core::mem::size_of::(), 56); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: filestat = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.st_dev as *const _ as usize - base, 0); assert_eq!(&obj.st_ino as *const _ as usize - base, 8); assert_eq!(&obj.st_filetype as *const _ as usize - base, 16); assert_eq!(&obj.st_nlink as *const _ as usize - base, 20); assert_eq!(&obj.st_size as *const _ as usize - base, 24); assert_eq!(&obj.st_atim as *const _ as usize - base, 32); assert_eq!(&obj.st_mtim as *const _ as usize - base, 40); assert_eq!(&obj.st_ctim as *const _ as usize - base, 48); } } /// A region of memory for scatter/gather reads. #[repr(C)] #[derive(Copy, Clone)] pub struct iovec { /// The address and length of the buffer to be filled. pub buf: (*mut (), usize), } #[test] #[cfg(target_pointer_width = "32")] fn iovec_layout_test_32() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: iovec = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.buf.0 as *const _ as usize - base, 0); assert_eq!(&obj.buf.1 as *const _ as usize - base, 4); } } #[test] #[cfg(target_pointer_width = "64")] fn iovec_layout_test_64() { assert_eq!(::core::mem::size_of::(), 16); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: iovec = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.buf.0 as *const _ as usize - base, 0); assert_eq!(&obj.buf.1 as *const _ as usize - base, 8); } } /// Path lookup properties. #[repr(C)] #[derive(Copy, Clone)] pub struct lookup { /// The working directory at which the resolution of the /// path starts. pub fd: fd, /// Flags determining the method of how the path is /// resolved. pub flags: lookupflags, } #[test] fn lookup_layout_test() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: lookup = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.fd as *const _ as usize - base, 0); assert_eq!(&obj.flags as *const _ as usize - base, 4); } } /// Entry point for a process (`_start`). /// /// **auxv**: /// The auxiliary vector. See [`auxv`](struct.auxv.html). pub type processentry = unsafe extern "C" fn( auxv: *const auxv, ) -> (); /// Arguments of [`sock_recv()`](fn.sock_recv.html). #[repr(C)] #[derive(Copy, Clone)] pub struct recv_in { /// List of scatter/gather vectors where message data /// should be stored. pub ri_data: (*const iovec, usize), /// Buffer where numbers of incoming file descriptors /// should be stored. pub ri_fds: (*mut fd, usize), /// Message flags. pub ri_flags: riflags, } #[test] #[cfg(target_pointer_width = "32")] fn recv_in_layout_test_32() { assert_eq!(::core::mem::size_of::(), 20); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: recv_in = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0); assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4); assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8); assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12); assert_eq!(&obj.ri_flags as *const _ as usize - base, 16); } } #[test] #[cfg(target_pointer_width = "64")] fn recv_in_layout_test_64() { assert_eq!(::core::mem::size_of::(), 40); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: recv_in = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0); assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8); assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16); assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24); assert_eq!(&obj.ri_flags as *const _ as usize - base, 32); } } /// Results of [`sock_recv()`](fn.sock_recv.html). #[repr(C)] #[derive(Copy, Clone)] pub struct recv_out { /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data). pub ro_datalen: usize, /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds). pub ro_fdslen: usize, /// Fields that were used by previous implementations. pub ro_unused: [u8; 40], /// Message flags. pub ro_flags: roflags, } #[test] #[cfg(target_pointer_width = "32")] fn recv_out_layout_test_32() { assert_eq!(::core::mem::size_of::(), 52); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: recv_out = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0); assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4); assert_eq!(&obj.ro_unused as *const _ as usize - base, 8); assert_eq!(&obj.ro_flags as *const _ as usize - base, 48); } } #[test] #[cfg(target_pointer_width = "64")] fn recv_out_layout_test_64() { assert_eq!(::core::mem::size_of::(), 64); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: recv_out = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0); assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8); assert_eq!(&obj.ro_unused as *const _ as usize - base, 16); assert_eq!(&obj.ro_flags as *const _ as usize - base, 56); } } /// Arguments of [`sock_send()`](fn.sock_send.html). #[repr(C)] #[derive(Copy, Clone)] pub struct send_in { /// List of scatter/gather vectors where message data /// should be retrieved. pub si_data: (*const ciovec, usize), /// File descriptors that need to be attached to the /// message. pub si_fds: (*const fd, usize), /// Message flags. pub si_flags: siflags, } #[test] #[cfg(target_pointer_width = "32")] fn send_in_layout_test_32() { assert_eq!(::core::mem::size_of::(), 20); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: send_in = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0); assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4); assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8); assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12); assert_eq!(&obj.si_flags as *const _ as usize - base, 16); } } #[test] #[cfg(target_pointer_width = "64")] fn send_in_layout_test_64() { assert_eq!(::core::mem::size_of::(), 40); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: send_in = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0); assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8); assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16); assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24); assert_eq!(&obj.si_flags as *const _ as usize - base, 32); } } /// Results of [`sock_send()`](fn.sock_send.html). #[repr(C)] #[derive(Copy, Clone)] pub struct send_out { /// Number of bytes transmitted. pub so_datalen: usize, } #[test] #[cfg(target_pointer_width = "32")] fn send_out_layout_test_32() { assert_eq!(::core::mem::size_of::(), 4); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: send_out = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.so_datalen as *const _ as usize - base, 0); } } #[test] #[cfg(target_pointer_width = "64")] fn send_out_layout_test_64() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: send_out = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.so_datalen as *const _ as usize - base, 0); } } /// Subscription to an event. #[repr(C)] #[derive(Copy, Clone)] pub struct subscription { /// User-provided value that is attached to the /// subscription in the kernel and returned through /// [`event.userdata`](struct.event.html#structfield.userdata). pub userdata: userdata, /// Used by previous implementations. Ignored. pub unused: u16, /// The type of the event to which to subscribe. /// /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR), /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK) /// must be provided as the first subscription and may /// only be followed by up to one other subscription, /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK). pub type_: eventtype, pub union: subscription_union } /// A union inside `subscription`. #[repr(C)] #[derive(Copy, Clone)] pub union subscription_union { /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK). pub clock: subscription_clock, /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR). pub condvar: subscription_condvar, /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE). pub fd_readwrite: subscription_fd_readwrite, /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK). pub lock: subscription_lock, /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE). pub proc_terminate: subscription_proc_terminate, } #[repr(C)] #[derive(Copy, Clone)] pub struct subscription_clock { /// The user-defined unique /// identifier of the clock. pub identifier: userdata, /// The clock against which the /// timestamp should be compared. pub clock_id: clockid, /// The absolute or relative /// timestamp. pub timeout: timestamp, /// The amount of time that the /// kernel may wait additionally /// to coalesce with other events. pub precision: timestamp, /// Flags specifying whether the /// timeout is absolute or /// relative. pub flags: subclockflags, } #[repr(C)] #[derive(Copy, Clone)] pub struct subscription_condvar { /// The condition variable on /// which to wait to be woken up. pub condvar: *mut condvar, /// The lock that will be /// released while waiting. /// /// The lock will be reacquired /// for writing when the condition /// variable triggers. pub lock: *mut lock, /// Whether the condition variable /// is stored in private or shared /// memory. pub condvar_scope: scope, /// Whether the lock is stored in /// private or shared memory. pub lock_scope: scope, } #[repr(C)] #[derive(Copy, Clone)] pub struct subscription_fd_readwrite { /// The file descriptor on which /// to wait for it to become ready /// for reading or writing. pub fd: fd, /// Under which conditions to /// trigger. pub flags: subrwflags, } #[repr(C)] #[derive(Copy, Clone)] pub struct subscription_lock { /// The lock that will be acquired /// for reading or writing. pub lock: *mut lock, /// Whether the lock is stored in /// private or shared memory. pub lock_scope: scope, } #[repr(C)] #[derive(Copy, Clone)] pub struct subscription_proc_terminate { /// The process descriptor on /// which to wait for process /// termination. pub fd: fd, } #[test] #[cfg(target_pointer_width = "32")] fn subscription_layout_test_32() { assert_eq!(::core::mem::size_of::(), 56); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: subscription = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.userdata as *const _ as usize - base, 0); assert_eq!(&obj.unused as *const _ as usize - base, 8); assert_eq!(&obj.type_ as *const _ as usize - base, 10); assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16); assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24); assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32); assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40); assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48); assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16); assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20); assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24); assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25); assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16); assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20); assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16); assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20); assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16); } } #[test] #[cfg(target_pointer_width = "64")] fn subscription_layout_test_64() { assert_eq!(::core::mem::size_of::(), 56); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: subscription = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.userdata as *const _ as usize - base, 0); assert_eq!(&obj.unused as *const _ as usize - base, 8); assert_eq!(&obj.type_ as *const _ as usize - base, 10); assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16); assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24); assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32); assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40); assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48); assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16); assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24); assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32); assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33); assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16); assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20); assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16); assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24); assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16); } } /// The Thread Control Block (TCB). /// /// After a thread begins execution (at program startup or when /// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers /// controlling Thread-Local Storage (TLS) will already be /// initialized. They will point to an area only containing the /// TCB. /// /// If the thread needs space for storing thread-specific /// variables, the thread may allocate a larger area and adjust /// the CPU's registers to point to that area instead. However, it /// does need to make sure that the TCB is copied over to the new /// TLS area. /// /// The purpose of the TCB is that it allows light-weight /// emulators to store information related to individual threads. /// For example, it may be used to store a copy of the CPU /// registers prior emulation, so that TLS for the host system /// can be restored if needed. #[repr(C)] #[derive(Copy, Clone)] pub struct tcb { /// Pointer that may be freely assigned by the system. Its /// value cannot be interpreted by the application. pub parent: *mut (), } #[test] #[cfg(target_pointer_width = "32")] fn tcb_layout_test_32() { assert_eq!(::core::mem::size_of::(), 4); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: tcb = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.parent as *const _ as usize - base, 0); } } #[test] #[cfg(target_pointer_width = "64")] fn tcb_layout_test_64() { assert_eq!(::core::mem::size_of::(), 8); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: tcb = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.parent as *const _ as usize - base, 0); } } /// Entry point for additionally created threads. /// /// **tid**: /// Thread ID of the current thread. /// /// **aux**: /// Copy of the value stored in /// [`threadattr.argument`](struct.threadattr.html#structfield.argument). pub type threadentry = unsafe extern "C" fn( tid: tid, aux: *mut (), ) -> (); /// Attributes for thread creation. #[repr(C)] #[derive(Copy, Clone)] pub struct threadattr { /// Initial program counter value. pub entry_point: threadentry, /// Region allocated to serve as stack space. pub stack: (*mut (), usize), /// Argument to be forwarded to the entry point function. pub argument: *mut (), } #[test] #[cfg(target_pointer_width = "32")] fn threadattr_layout_test_32() { assert_eq!(::core::mem::size_of::(), 16); assert_eq!(::core::mem::align_of::(), 4); unsafe { let obj: threadattr = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.entry_point as *const _ as usize - base, 0); assert_eq!(&obj.stack.0 as *const _ as usize - base, 4); assert_eq!(&obj.stack.1 as *const _ as usize - base, 8); assert_eq!(&obj.argument as *const _ as usize - base, 12); } } #[test] #[cfg(target_pointer_width = "64")] fn threadattr_layout_test_64() { assert_eq!(::core::mem::size_of::(), 32); assert_eq!(::core::mem::align_of::(), 8); unsafe { let obj: threadattr = ::core::mem::uninitialized(); let base = &obj as *const _ as usize; assert_eq!(&obj.entry_point as *const _ as usize - base, 0); assert_eq!(&obj.stack.0 as *const _ as usize - base, 8); assert_eq!(&obj.stack.1 as *const _ as usize - base, 16); assert_eq!(&obj.argument as *const _ as usize - base, 24); } } /// The table with pointers to all syscall implementations. #[allow(improper_ctypes)] extern "C" { fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno; fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno; fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno; fn cloudabi_sys_fd_close(_: fd) -> errno; fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno; fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno; fn cloudabi_sys_fd_datasync(_: fd) -> errno; fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno; fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize) -> errno; fn cloudabi_sys_fd_pwrite(_: fd, _: *const ciovec, _: usize, _: filesize, _: *mut usize) -> errno; fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno; fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno; fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno; fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno; fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno; fn cloudabi_sys_fd_sync(_: fd) -> errno; fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno; fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno; fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno; fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno; fn cloudabi_sys_file_link(_: lookup, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno; fn cloudabi_sys_file_open(_: lookup, _: *const u8, _: usize, _: oflags, _: *const fdstat, _: *mut fd) -> errno; fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize) -> errno; fn cloudabi_sys_file_readlink(_: fd, _: *const u8, _: usize, _: *mut u8, _: usize, _: *mut usize) -> errno; fn cloudabi_sys_file_rename(_: fd, _: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno; fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno; fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno; fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno; fn cloudabi_sys_file_stat_put(_: lookup, _: *const u8, _: usize, _: *const filestat, _: fsflags) -> errno; fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno; fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno; fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno; fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno; fn cloudabi_sys_mem_map(_: *mut (), _: usize, _: mprot, _: mflags, _: fd, _: filesize, _: *mut *mut ()) -> errno; fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno; fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno; fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno; fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno; fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno; fn cloudabi_sys_proc_exit(_: exitcode) -> !; fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno; fn cloudabi_sys_proc_raise(_: signal) -> errno; fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno; fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno; fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno; fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno; fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno; fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !; fn cloudabi_sys_thread_yield() -> errno; } /// Obtains the resolution of a clock. /// /// ## Parameters /// /// **clock_id**: /// The clock for which the resolution needs to be /// returned. /// /// **resolution**: /// The resolution of the clock. #[inline] pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno { cloudabi_sys_clock_res_get(clock_id_, resolution_) } /// Obtains the time value of a clock. /// /// ## Parameters /// /// **clock_id**: /// The clock for which the time needs to be /// returned. /// /// **precision**: /// The maximum lag (exclusive) that the returned /// time value may have, compared to its actual /// value. /// /// **time**: /// The time value of the clock. #[inline] pub unsafe fn clock_time_get(clock_id_: clockid, precision_: timestamp, time_: &mut timestamp) -> errno { cloudabi_sys_clock_time_get(clock_id_, precision_, time_) } /// Wakes up threads waiting on a userspace condition variable. /// /// If an invocation of this system call causes all waiting /// threads to be woken up, the value of the condition variable /// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition /// variable is set to this value, it is not needed to invoke this /// system call. /// /// ## Parameters /// /// **condvar**: /// The userspace condition variable that has /// waiting threads. /// /// **scope**: /// Whether the condition variable is stored in /// private or shared memory. /// /// **nwaiters**: /// The number of threads that need to be woken /// up. If it exceeds the number of waiting /// threads, all threads are woken up. #[inline] pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno { cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_) } /// Closes a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor that needs to be closed. #[inline] pub unsafe fn fd_close(fd_: fd) -> errno { cloudabi_sys_fd_close(fd_) } /// Creates a file descriptor. /// /// ## Parameters /// /// **type**: /// Possible values: /// /// - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY): /// Creates an anonymous shared memory /// object. /// /// **fd**: /// The file descriptor that has been created. #[inline] pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno { cloudabi_sys_fd_create1(type_, fd_) } /// Creates a pair of file descriptors. /// /// ## Parameters /// /// **type**: /// Possible values: /// /// - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM): /// Creates a UNIX datagram socket pair. /// - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM): /// Creates a UNIX byte-stream socket /// pair. /// /// **fd1**: /// The first file descriptor of the pair. /// /// **fd2**: /// The second file descriptor of the pair. #[inline] pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno { cloudabi_sys_fd_create2(type_, fd1_, fd2_) } /// Synchronizes the data of a file to disk. /// /// ## Parameters /// /// **fd**: /// The file descriptor of the file whose data /// needs to be synchronized to disk. #[inline] pub unsafe fn fd_datasync(fd_: fd) -> errno { cloudabi_sys_fd_datasync(fd_) } /// Duplicates a file descriptor. /// /// ## Parameters /// /// **from**: /// The file descriptor that needs to be /// duplicated. /// /// **fd**: /// The new file descriptor. #[inline] pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno { cloudabi_sys_fd_dup(from_, fd_) } /// Reads from a file descriptor, without using and updating the /// file descriptor's offset. /// /// ## Parameters /// /// **fd**: /// The file descriptor from which data should be /// read. /// /// **iovs**: /// List of scatter/gather vectors where data /// should be stored. /// /// **offset**: /// The offset within the file at which reading /// should start. /// /// **nread**: /// The number of bytes read. #[inline] pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno { cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_) } /// Writes to a file descriptor, without using and updating the /// file descriptor's offset. /// /// ## Parameters /// /// **fd**: /// The file descriptor to which data should be /// written. /// /// **iovs**: /// List of scatter/gather vectors where data /// should be retrieved. /// /// **offset**: /// The offset within the file at which writing /// should start. /// /// **nwritten**: /// The number of bytes written. #[inline] pub unsafe fn fd_pwrite(fd_: fd, iovs_: &[ciovec], offset_: filesize, nwritten_: &mut usize) -> errno { cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_) } /// Reads from a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor from which data should be /// read. /// /// **iovs**: /// List of scatter/gather vectors where data /// should be stored. /// /// **nread**: /// The number of bytes read. #[inline] pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno { cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_) } /// Atomically replaces a file descriptor by a copy of another /// file descriptor. /// /// Due to the strong focus on thread safety, this environment /// does not provide a mechanism to duplicate a file descriptor to /// an arbitrary number, like dup2(). This would be prone to race /// conditions, as an actual file descriptor with the same number /// could be allocated by a different thread at the same time. /// /// This system call provides a way to atomically replace file /// descriptors, which would disappear if dup2() were to be /// removed entirely. /// /// ## Parameters /// /// **from**: /// The file descriptor that needs to be copied. /// /// **to**: /// The file descriptor that needs to be /// overwritten. #[inline] pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno { cloudabi_sys_fd_replace(from_, to_) } /// Moves the offset of the file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor whose offset has to be /// moved. /// /// **offset**: /// The number of bytes to move. /// /// **whence**: /// Relative to which position the move should /// take place. /// /// **newoffset**: /// The new offset of the file descriptor, /// relative to the start of the file. #[inline] pub unsafe fn fd_seek(fd_: fd, offset_: filedelta, whence_: whence, newoffset_: &mut filesize) -> errno { cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_) } /// Gets attributes of a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor whose attributes have to /// be obtained. /// /// **buf**: /// The buffer where the file descriptor's /// attributes are stored. #[inline] pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno { cloudabi_sys_fd_stat_get(fd_, buf_) } /// Adjusts attributes of a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor whose attributes have to /// be adjusted. /// /// **buf**: /// The desired values of the file descriptor /// attributes that are adjusted. /// /// **flags**: /// A bitmask indicating which attributes have to /// be adjusted. #[inline] pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno { cloudabi_sys_fd_stat_put(fd_, buf_, flags_) } /// Synchronizes the data and metadata of a file to disk. /// /// ## Parameters /// /// **fd**: /// The file descriptor of the file whose data /// and metadata needs to be synchronized to disk. #[inline] pub unsafe fn fd_sync(fd_: fd) -> errno { cloudabi_sys_fd_sync(fd_) } /// Writes to a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor to which data should be /// written. /// /// **iovs**: /// List of scatter/gather vectors where data /// should be retrieved. /// /// **nwritten**: /// The number of bytes written. #[inline] pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno { cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_) } /// Provides file advisory information on a file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor for which to provide file /// advisory information. /// /// **offset**: /// The offset within the file to which the /// advisory applies. /// /// **len**: /// The length of the region to which the advisory /// applies. /// /// **advice**: /// The advice. #[inline] pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno { cloudabi_sys_file_advise(fd_, offset_, len_, advice_) } /// Forces the allocation of space in a file. /// /// ## Parameters /// /// **fd**: /// The file in which the space should be /// allocated. /// /// **offset**: /// The offset at which the allocation should /// start. /// /// **len**: /// The length of the area that is allocated. #[inline] pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno { cloudabi_sys_file_allocate(fd_, offset_, len_) } /// Creates a file of a specified type. /// /// ## Parameters /// /// **fd**: /// The working directory at which the resolution /// of the file to be created starts. /// /// **path**: /// The path at which the file should be created. /// /// **type**: /// Possible values: /// /// - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY): /// Creates a directory. #[inline] pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno { cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_) } /// Creates a hard link. /// /// ## Parameters /// /// **fd1**: /// The working directory at which the resolution /// of the source path starts. /// /// **path1**: /// The source path of the file that should be /// hard linked. /// /// **fd2**: /// The working directory at which the resolution /// of the destination path starts. /// /// **path2**: /// The destination path at which the hard link /// should be created. #[inline] pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno { cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len()) } /// Opens a file. /// /// ## Parameters /// /// **dirfd**: /// The working directory at which the resolution /// of the file to be opened starts. /// /// **path**: /// The path of the file that should be opened. /// /// **oflags**: /// The method at which the file should be opened. /// /// **fds**: /// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the /// initial rights of the newly created file /// descriptor. The operating system is allowed to /// return a file descriptor with fewer rights /// than specified, if and only if those rights do /// not apply to the type of file being opened. /// /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags /// of the file descriptor. /// /// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored. /// /// **fd**: /// The file descriptor of the file that has been /// opened. #[inline] pub unsafe fn file_open(dirfd_: lookup, path_: &[u8], oflags_: oflags, fds_: *const fdstat, fd_: &mut fd) -> errno { cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_) } /// Reads directory entries from a directory. /// /// When successful, the contents of the output buffer consist of /// a sequence of directory entries. Each directory entry consists /// of a [`dirent`](struct.dirent.html) object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes /// holding the name of the directory entry. /// /// This system call fills the output buffer as much as possible, /// potentially truncating the last directory entry. This allows /// the caller to grow its read buffer size in case it's too small /// to fit a single large directory entry, or skip the oversized /// directory entry. /// /// ## Parameters /// /// **fd**: /// The directory from which to read the directory /// entries. /// /// **buf**: /// The buffer where directory entries are stored. /// /// **cookie**: /// The location within the directory to start /// reading. /// /// **bufused**: /// The number of bytes stored in the read buffer. /// If less than the size of the read buffer, the /// end of the directory has been reached. #[inline] pub unsafe fn file_readdir(fd_: fd, buf_: &mut [u8], cookie_: dircookie, bufused_: &mut usize) -> errno { cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_) } /// Reads the contents of a symbolic link. /// /// ## Parameters /// /// **fd**: /// The working directory at which the resolution /// of the path of the symbolic starts. /// /// **path**: /// The path of the symbolic link whose contents /// should be read. /// /// **buf**: /// The buffer where the contents of the symbolic /// link should be stored. /// /// **bufused**: /// The number of bytes placed in the buffer. #[inline] pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno { cloudabi_sys_file_readlink(fd_, path_.as_ptr(), path_.len(), buf_.as_mut_ptr(), buf_.len(), bufused_) } /// Renames a file. /// /// ## Parameters /// /// **fd1**: /// The working directory at which the resolution /// of the source path starts. /// /// **path1**: /// The source path of the file that should be /// renamed. /// /// **fd2**: /// The working directory at which the resolution /// of the destination path starts. /// /// **path2**: /// The destination path to which the file should /// be renamed. #[inline] pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno { cloudabi_sys_file_rename(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len()) } /// Gets attributes of a file by file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor whose attributes have to /// be obtained. /// /// **buf**: /// The buffer where the file's attributes are /// stored. #[inline] pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno { cloudabi_sys_file_stat_fget(fd_, buf_) } /// Adjusts attributes of a file by file descriptor. /// /// ## Parameters /// /// **fd**: /// The file descriptor whose attributes have to /// be adjusted. /// /// **buf**: /// The desired values of the file attributes that /// are adjusted. /// /// **flags**: /// A bitmask indicating which attributes have to /// be adjusted. #[inline] pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno { cloudabi_sys_file_stat_fput(fd_, buf_, flags_) } /// Gets attributes of a file by path. /// /// ## Parameters /// /// **fd**: /// The working directory at which the resolution /// of the path whose attributes have to be /// obtained starts. /// /// **path**: /// The path of the file whose attributes have to /// be obtained. /// /// **buf**: /// The buffer where the file's attributes are /// stored. #[inline] pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno { cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_) } /// Adjusts attributes of a file by path. /// /// ## Parameters /// /// **fd**: /// The working directory at which the resolution /// of the path whose attributes have to be /// adjusted starts. /// /// **path**: /// The path of the file whose attributes have to /// be adjusted. /// /// **buf**: /// The desired values of the file attributes that /// are adjusted. /// /// **flags**: /// A bitmask indicating which attributes have to /// be adjusted. #[inline] pub unsafe fn file_stat_put(fd_: lookup, path_: &[u8], buf_: *const filestat, flags_: fsflags) -> errno { cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_) } /// Creates a symbolic link. /// /// ## Parameters /// /// **path1**: /// The contents of the symbolic link. /// /// **fd**: /// The working directory at which the resolution /// of the destination path starts. /// /// **path2**: /// The destination path at which the symbolic /// link should be created. #[inline] pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno { cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len()) } /// Unlinks a file, or removes a directory. /// /// ## Parameters /// /// **fd**: /// The working directory at which the resolution /// of the path starts. /// /// **path**: /// The path that needs to be unlinked or removed. /// /// **flags**: /// Possible values: /// /// - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR): /// If set, attempt to remove a directory. /// Otherwise, unlink a file. #[inline] pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno { cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_) } /// Unlocks a write-locked userspace lock. /// /// If a userspace lock is unlocked while having its /// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in /// userspace directly. This system call needs to be performed /// instead, so that any waiting threads can be woken up. /// /// To prevent spurious invocations of this system call, the lock /// must be locked for writing. This prevents other threads from /// acquiring additional read locks while the system call is in /// progress. If the lock is acquired for reading, it must first /// be upgraded to a write lock. /// /// ## Parameters /// /// **lock**: /// The userspace lock that is locked for writing /// by the calling thread. /// /// **scope**: /// Whether the lock is stored in private or /// shared memory. #[inline] pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno { cloudabi_sys_lock_unlock(lock_, scope_) } /// Provides memory advisory information on a region of memory. /// /// ## Parameters /// /// **mapping**: /// The pages for which to provide memory advisory /// information. /// /// **advice**: /// The advice. #[inline] pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno { cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_) } /// Creates a memory mapping, making the contents of a file /// accessible through memory. /// /// ## Parameters /// /// **addr**: /// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which /// address the file region is mapped. Otherwise, /// the mapping is performed at an unused /// location. /// /// **len**: /// The length of the memory mapping to be /// created. /// /// **prot**: /// Initial memory protection options for the /// memory mapping. /// /// **flags**: /// Memory mapping flags. /// /// **fd**: /// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be /// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument /// specifies the file whose contents need to be /// mapped. /// /// **off**: /// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be /// zero. Otherwise, this argument specifies the /// offset within the file at which the mapping /// starts. /// /// **mem**: /// The starting address of the memory mapping. #[inline] pub unsafe fn mem_map(addr_: *mut (), len_: usize, prot_: mprot, flags_: mflags, fd_: fd, off_: filesize, mem_: &mut *mut ()) -> errno { cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_) } /// Change the protection of a memory mapping. /// /// ## Parameters /// /// **mapping**: /// The pages that need their protection changed. /// /// **prot**: /// New protection options. #[inline] pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno { cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_) } /// Synchronize a region of memory with its physical storage. /// /// ## Parameters /// /// **mapping**: /// The pages that need to be synchronized. /// /// **flags**: /// The method of synchronization. #[inline] pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno { cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_) } /// Unmaps a region of memory. /// /// ## Parameters /// /// **mapping**: /// The pages that needs to be unmapped. #[inline] pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno { cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len()) } /// Concurrently polls for the occurrence of a set of events. /// /// ## Parameters /// /// **in**: /// The events to which to subscribe. /// /// **out**: /// The events that have occurred. /// /// **nsubscriptions**: /// Both the number of subscriptions and events. /// /// **nevents**: /// The number of events stored. #[inline] pub unsafe fn poll(in_: *const subscription, out_: *mut event, nsubscriptions_: usize, nevents_: &mut usize) -> errno { cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_) } /// Replaces the process by a new executable. /// /// Process execution in CloudABI differs from POSIX in two ways: /// handling of arguments and inheritance of file descriptors. /// /// CloudABI does not use string command line arguments. Instead, /// a buffer with binary data is copied into the address space of /// the new executable. The kernel does not enforce any specific /// structure to this data, although CloudABI's C library uses it /// to store a tree structure that is semantically identical to /// YAML. /// /// Due to the strong focus on thread safety, file descriptors /// aren't inherited through close-on-exec flags. An explicit /// list of file descriptors that need to be retained needs to be /// provided. After execution, file descriptors are placed in the /// order in which they are stored in the array. This not only /// makes the execution process deterministic. It also prevents /// potential information disclosures about the layout of the /// original process. /// /// ## Parameters /// /// **fd**: /// A file descriptor of the new executable. /// /// **data**: /// Binary argument data that is passed on to the /// new executable. /// /// **fds**: /// The layout of the file descriptor table after /// execution. #[inline] pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno { cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len()) } /// Terminates the process normally. /// /// ## Parameters /// /// **rval**: /// The exit code returned by the process. The /// exit code can be obtained by other processes /// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode). #[inline] pub unsafe fn proc_exit(rval_: exitcode) -> ! { cloudabi_sys_proc_exit(rval_) } /// Forks the process of the calling thread. /// /// After forking, a new process shall be created, having only a /// copy of the calling thread. The parent process will obtain a /// process descriptor. When closed, the child process is /// automatically signaled with [`KILL`](enum.signal.html#variant.KILL). /// /// ## Parameters /// /// **fd**: /// In the parent process: the file descriptor /// number of the process descriptor. /// /// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html). /// /// **tid**: /// In the parent process: undefined. /// /// In the child process: the thread ID of the /// initial thread of the child process. #[inline] pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno { cloudabi_sys_proc_fork(fd_, tid_) } /// Sends a signal to the process of the calling thread. /// /// ## Parameters /// /// **sig**: /// The signal condition that should be triggered. /// If the signal causes the process to terminate, /// its condition can be obtained by other /// processes through /// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal). #[inline] pub unsafe fn proc_raise(sig_: signal) -> errno { cloudabi_sys_proc_raise(sig_) } /// Obtains random data from the kernel random number generator. /// /// As this interface is not guaranteed to be fast, it is advised /// that the random data obtained through this system call is used /// as the seed for a userspace pseudo-random number generator. /// /// ## Parameters /// /// **buf**: /// The buffer that needs to be filled with random /// data. #[inline] pub unsafe fn random_get(buf_: &mut [u8]) -> errno { cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len()) } /// Receives a message on a socket. /// /// ## Parameters /// /// **sock**: /// The socket on which a message should be /// received. /// /// **in**: /// Input parameters. /// /// **out**: /// Output parameters. #[inline] pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno { cloudabi_sys_sock_recv(sock_, in_, out_) } /// Sends a message on a socket. /// /// ## Parameters /// /// **sock**: /// The socket on which a message should be sent. /// /// **in**: /// Input parameters. /// /// **out**: /// Output parameters. #[inline] pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno { cloudabi_sys_sock_send(sock_, in_, out_) } /// Shuts down socket send and receive channels. /// /// ## Parameters /// /// **sock**: /// The socket that needs its channels shut down. /// /// **how**: /// Which channels on the socket need to be shut /// down. #[inline] pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno { cloudabi_sys_sock_shutdown(sock_, how_) } /// Creates a new thread within the current process. /// /// ## Parameters /// /// **attr**: /// The desired attributes of the new thread. /// /// **tid**: /// The thread ID of the new thread. #[inline] pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno { cloudabi_sys_thread_create(attr_, tid_) } /// Terminates the calling thread. /// /// This system call can also unlock a single userspace lock /// after termination, which can be used to implement thread /// joining. /// /// ## Parameters /// /// **lock**: /// Userspace lock that is locked for writing by /// the calling thread. /// /// **scope**: /// Whether the lock is stored in private or /// shared memory. #[inline] pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! { cloudabi_sys_thread_exit(lock_, scope_) } /// Temporarily yields execution of the calling thread. #[inline] pub unsafe fn thread_yield() -> errno { cloudabi_sys_thread_yield() }