| // 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::<auxv>(), 8); |
| assert_eq!(::core::mem::align_of::<auxv>(), 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::<auxv>(), 16); |
| assert_eq!(::core::mem::align_of::<auxv>(), 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::<ciovec>(), 8); |
| assert_eq!(::core::mem::align_of::<ciovec>(), 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::<ciovec>(), 16); |
| assert_eq!(::core::mem::align_of::<ciovec>(), 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::<dirent>(), 24); |
| assert_eq!(::core::mem::align_of::<dirent>(), 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::<event>(), 32); |
| assert_eq!(::core::mem::align_of::<event>(), 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::<fdstat>(), 24); |
| assert_eq!(::core::mem::align_of::<fdstat>(), 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::<filestat>(), 56); |
| assert_eq!(::core::mem::align_of::<filestat>(), 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::<iovec>(), 8); |
| assert_eq!(::core::mem::align_of::<iovec>(), 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::<iovec>(), 16); |
| assert_eq!(::core::mem::align_of::<iovec>(), 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::<lookup>(), 8); |
| assert_eq!(::core::mem::align_of::<lookup>(), 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::<recv_in>(), 20); |
| assert_eq!(::core::mem::align_of::<recv_in>(), 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::<recv_in>(), 40); |
| assert_eq!(::core::mem::align_of::<recv_in>(), 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::<recv_out>(), 52); |
| assert_eq!(::core::mem::align_of::<recv_out>(), 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::<recv_out>(), 64); |
| assert_eq!(::core::mem::align_of::<recv_out>(), 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::<send_in>(), 20); |
| assert_eq!(::core::mem::align_of::<send_in>(), 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::<send_in>(), 40); |
| assert_eq!(::core::mem::align_of::<send_in>(), 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::<send_out>(), 4); |
| assert_eq!(::core::mem::align_of::<send_out>(), 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::<send_out>(), 8); |
| assert_eq!(::core::mem::align_of::<send_out>(), 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::<subscription>(), 56); |
| assert_eq!(::core::mem::align_of::<subscription>(), 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::<subscription>(), 56); |
| assert_eq!(::core::mem::align_of::<subscription>(), 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::<tcb>(), 4); |
| assert_eq!(::core::mem::align_of::<tcb>(), 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::<tcb>(), 8); |
| assert_eq!(::core::mem::align_of::<tcb>(), 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::<threadattr>(), 16); |
| assert_eq!(::core::mem::align_of::<threadattr>(), 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::<threadattr>(), 32); |
| assert_eq!(::core::mem::align_of::<threadattr>(), 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() |
| } |