1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
//! `posish` provides safe wrappers to `libc` functions. The current focus is //! on the functionality needed by [`cap-std`] and [`system-interface`] that //! isn't provided by [`std`] or [`getrandom`]. //! //! The wrappers perform the following tasks: //! - Error values are translated to `Result`s. //! - Out-parameters are translated to return values. //! - Path arguments can by any kind of string type. //! - File descriptors are passed in through arguments implementing //! [`AsRawFd`] instead of as bare integers and returned as //! [`std::fs::File`]s. //! - Constants use `enum`s and [`bitflags`] types. //! - Multiplexed functions (eg. `fcntl`, `ioctl`, etc.) are de-multiplexed. //! - Variadic functions (eg. `openat`, etc.) are presented as non-variadic. //! - Functions and types which need `64` suffixes to enable large-file //! support are used automatically. //! - Behaviors that depend on the sizes of C types like `long` are hidden. //! - File offsets and sizes are presented as `i64` and `u64` rather than //! `off_t`. //! - In some places, more human-friendly and less historical-accident names //! are used. //! //! Things they don't do include: //! - Emulating functions that aren't natively supported on a platform. //! - Detecting whether functions are supported at runtime. //! - Hiding significant differences between platforms. //! - Hiding ambient authorities. //! - Imposing sandboxing features such as filesystem path or network address //! sandboxing. //! //! See [`cap-std`] and [`system-interface`] for libraries which do hide //! ambient authorities and perform sandboxing. //! //! # Safety //! //! This library follows [`std`] in considering dynamic integer values that //! have no meaning outside of OS APIs to be similar to raw pointers, from a //! safety perspective. For example, //! [`std::os::unix::io::FromRawFd::from_raw_fd`] is unsafe since it takes a //! raw file descriptor. In this library, raw file descriptors and raw //! directory seek locations are considered to be similar to raw pointers in //! terms of safety. //! //! [`cap-std`]: https://crates.io/crates/cap-std //! [`system-interface`]: https://crates.io/crates/system-interface //! [`std`]: https://doc.rust-lang.org/std/ //! [`getrandom`]: https://crates.io/crates/getrandom //! [`AsRawFd`]: https://doc.rust-lang.org/std/os/unix/io/trait.AsRawFd.html //! [`std::fs::File`]: https://doc.rust-lang.org/std/fs/struct.File.html //! [`bitflags`]: https://crates.io/crates/bitflags //! [`std::os::unix::io::FromRawFd::from_raw_fd`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.from_raw_fd #![deny(missing_docs)] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #[cfg(not(target_os = "wasi"))] #[macro_use] mod weak; pub mod fs; pub mod io; #[cfg(not(any(target_os = "wasi", target_os = "redox")))] // WASI doesn't support `net` yet. pub mod net; pub mod path; pub mod process; pub mod time; /// Given a `libc` return value, translate `0` into `Ok(())` and any other value /// to an `Err` with the error from `errno`. fn zero_ok<T: LibcResult>(t: T) -> std::io::Result<()> { if t.is_zero() { Ok(()) } else { Err(std::io::Error::last_os_error()) } } /// Given a `libc` return value, translate `-1` into an `Err` with the error /// from `errno`, and any other value to an `Ok` containing the value. fn negone_err<T: LibcResult>(t: T) -> std::io::Result<T> { if t.is_negone() { Err(std::io::Error::last_os_error()) } else { Ok(t) } } /// Given a `libc` return value, translate a negative value into an `Err` with /// the error from `errno`, and any other value to an `Ok` containing the value. #[allow(dead_code)] fn negative_err<T: LibcResult>(t: T) -> std::io::Result<()> { if t.is_negative() { Err(std::io::Error::last_os_error()) } else { Ok(()) } } trait LibcResult { fn is_zero(&self) -> bool; fn is_negone(&self) -> bool; fn is_negative(&self) -> bool; } macro_rules! is_impls { ($($t:ident)*) => ($(impl LibcResult for $t { fn is_zero(&self) -> bool { *self == 0 } fn is_negone(&self) -> bool { *self == -1 } fn is_negative(&self) -> bool { *self < 0 } })*) } is_impls! { i32 i64 isize }