1 //! Rust friendly bindings to the various *nix system functions. 2 //! 3 //! Modules are structured according to the C header file that they would be 4 //! defined in. 5 #![crate_name = "nix"] 6 #![cfg(unix)] 7 #![allow(non_camel_case_types)] 8 #![cfg_attr(test, deny(warnings))] 9 #![recursion_limit = "500"] 10 #![deny(unused)] 11 #![deny(unstable_features)] 12 #![deny(missing_copy_implementations)] 13 #![deny(missing_debug_implementations)] 14 #![warn(missing_docs)] 15 16 // Re-exported external crates 17 pub use libc; 18 19 // Private internal modules 20 #[macro_use] mod macros; 21 22 // Public crates 23 #[cfg(not(target_os = "redox"))] 24 #[allow(missing_docs)] 25 pub mod dir; 26 pub mod env; 27 #[allow(missing_docs)] 28 pub mod errno; 29 pub mod features; 30 #[allow(missing_docs)] 31 pub mod fcntl; 32 #[cfg(any(target_os = "android", 33 target_os = "dragonfly", 34 target_os = "freebsd", 35 target_os = "ios", 36 target_os = "linux", 37 target_os = "macos", 38 target_os = "netbsd", 39 target_os = "illumos", 40 target_os = "openbsd"))] 41 pub mod ifaddrs; 42 #[cfg(any(target_os = "android", 43 target_os = "linux"))] 44 #[allow(missing_docs)] 45 pub mod kmod; 46 #[cfg(any(target_os = "android", 47 target_os = "freebsd", 48 target_os = "linux"))] 49 pub mod mount; 50 #[cfg(any(target_os = "dragonfly", 51 target_os = "freebsd", 52 target_os = "fushsia", 53 target_os = "linux", 54 target_os = "netbsd"))] 55 #[allow(missing_docs)] 56 pub mod mqueue; 57 #[cfg(not(target_os = "redox"))] 58 pub mod net; 59 pub mod poll; 60 #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] 61 pub mod pty; 62 pub mod sched; 63 pub mod sys; 64 #[allow(missing_docs)] 65 pub mod time; 66 // This can be implemented for other platforms as soon as libc 67 // provides bindings for them. 68 #[cfg(all(target_os = "linux", 69 any(target_arch = "x86", target_arch = "x86_64")))] 70 #[allow(missing_docs)] 71 pub mod ucontext; 72 #[allow(missing_docs)] 73 pub mod unistd; 74 75 /* 76 * 77 * ===== Result / Error ===== 78 * 79 */ 80 81 use libc::{c_char, PATH_MAX}; 82 83 use std::{ptr, result}; 84 use std::ffi::{CStr, OsStr}; 85 use std::os::unix::ffi::OsStrExt; 86 use std::path::{Path, PathBuf}; 87 88 use errno::Errno; 89 90 /// Nix Result Type 91 pub type Result<T> = result::Result<T, Errno>; 92 93 /// Nix's main error type. 94 /// 95 /// It's a wrapper around Errno. As such, it's very interoperable with 96 /// [`std::io::Error`], but it has the advantages of: 97 /// * `Clone` 98 /// * `Copy` 99 /// * `Eq` 100 /// * Small size 101 /// * Represents all of the system's errnos, instead of just the most common 102 /// ones. 103 pub type Error = Errno; 104 105 /// Common trait used to represent file system paths by many Nix functions. 106 pub trait NixPath { 107 /// Is the path empty? is_empty(&self) -> bool108 fn is_empty(&self) -> bool; 109 110 /// Length of the path in bytes len(&self) -> usize111 fn len(&self) -> usize; 112 113 /// Execute a function with this path as a `CStr`. 114 /// 115 /// Mostly used internally by Nix. with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T116 fn with_nix_path<T, F>(&self, f: F) -> Result<T> 117 where F: FnOnce(&CStr) -> T; 118 } 119 120 impl NixPath for str { is_empty(&self) -> bool121 fn is_empty(&self) -> bool { 122 NixPath::is_empty(OsStr::new(self)) 123 } 124 len(&self) -> usize125 fn len(&self) -> usize { 126 NixPath::len(OsStr::new(self)) 127 } 128 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T129 fn with_nix_path<T, F>(&self, f: F) -> Result<T> 130 where F: FnOnce(&CStr) -> T { 131 OsStr::new(self).with_nix_path(f) 132 } 133 } 134 135 impl NixPath for OsStr { is_empty(&self) -> bool136 fn is_empty(&self) -> bool { 137 self.as_bytes().is_empty() 138 } 139 len(&self) -> usize140 fn len(&self) -> usize { 141 self.as_bytes().len() 142 } 143 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T144 fn with_nix_path<T, F>(&self, f: F) -> Result<T> 145 where F: FnOnce(&CStr) -> T { 146 self.as_bytes().with_nix_path(f) 147 } 148 } 149 150 impl NixPath for CStr { is_empty(&self) -> bool151 fn is_empty(&self) -> bool { 152 self.to_bytes().is_empty() 153 } 154 len(&self) -> usize155 fn len(&self) -> usize { 156 self.to_bytes().len() 157 } 158 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T159 fn with_nix_path<T, F>(&self, f: F) -> Result<T> 160 where F: FnOnce(&CStr) -> T { 161 // Equivalence with the [u8] impl. 162 if self.len() >= PATH_MAX as usize { 163 return Err(Errno::ENAMETOOLONG) 164 } 165 166 Ok(f(self)) 167 } 168 } 169 170 impl NixPath for [u8] { is_empty(&self) -> bool171 fn is_empty(&self) -> bool { 172 self.is_empty() 173 } 174 len(&self) -> usize175 fn len(&self) -> usize { 176 self.len() 177 } 178 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T179 fn with_nix_path<T, F>(&self, f: F) -> Result<T> 180 where F: FnOnce(&CStr) -> T { 181 let mut buf = [0u8; PATH_MAX as usize]; 182 183 if self.len() >= PATH_MAX as usize { 184 return Err(Errno::ENAMETOOLONG) 185 } 186 187 match self.iter().position(|b| *b == 0) { 188 Some(_) => Err(Errno::EINVAL), 189 None => { 190 unsafe { 191 // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028 192 ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len()); 193 Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char))) 194 } 195 196 } 197 } 198 } 199 } 200 201 impl NixPath for Path { is_empty(&self) -> bool202 fn is_empty(&self) -> bool { 203 NixPath::is_empty(self.as_os_str()) 204 } 205 len(&self) -> usize206 fn len(&self) -> usize { 207 NixPath::len(self.as_os_str()) 208 } 209 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T210 fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T { 211 self.as_os_str().with_nix_path(f) 212 } 213 } 214 215 impl NixPath for PathBuf { is_empty(&self) -> bool216 fn is_empty(&self) -> bool { 217 NixPath::is_empty(self.as_os_str()) 218 } 219 len(&self) -> usize220 fn len(&self) -> usize { 221 NixPath::len(self.as_os_str()) 222 } 223 with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T224 fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T { 225 self.as_os_str().with_nix_path(f) 226 } 227 } 228