diff --git a/src/libstd/sys/cloudabi/abi/bitflags.rs b/src/libstd/sys/cloudabi/abi/bitflags.rs new file mode 100644 index 00000000000..f764cc1df5a --- /dev/null +++ b/src/libstd/sys/cloudabi/abi/bitflags.rs @@ -0,0 +1,51 @@ +// Copyright (c) 2018 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. + +// Appease Rust's tidy. +// ignore-license + +#[cfg(feature = "bitflags")] +#[macro_use] +extern crate bitflags; + +// Minimal implementation of bitflags! in case we can't depend on the bitflags +// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't +// actually truncate. +#[cfg(not(feature = "bitflags"))] +macro_rules! bitflags { + ( + $(#[$attr:meta])* + pub struct $name:ident: $type:ty { + $($(#[$const_attr:meta])* const $const:ident = $val:expr;)* + } + ) => { + $(#[$attr])* + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] + pub struct $name { bits: $type } + impl $name { + $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)* + pub fn bits(&self) -> $type { self.bits } + pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } } + } + } +} diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs new file mode 100644 index 00000000000..2909db5098e --- /dev/null +++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs @@ -0,0 +1,2847 @@ +// 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() +}