]> git.proxmox.com Git - rustc.git/blob - src/vendor/nix/src/lib.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / nix / src / lib.rs
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 // latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
9 // warnings even though the macro expands into something with allow(dead_code)
10 #![allow(dead_code)]
11 #![cfg_attr(test, deny(warnings))]
12 #![recursion_limit = "500"]
13
14 #[macro_use]
15 extern crate bitflags;
16
17 #[macro_use]
18 extern crate cfg_if;
19 extern crate void;
20
21 #[cfg(test)]
22 extern crate nix_test as nixtest;
23
24 #[macro_use] mod macros;
25
26 // In rust 1.8+ this should be `pub extern crate libc` but prior
27 // to https://github.com/rust-lang/rust/issues/26775 being resolved
28 // it is necessary to get a little creative.
29 pub mod libc {
30 extern crate libc;
31 pub use self::libc::*;
32 }
33
34 pub use libc::{c_int, c_void};
35 pub use errno::Errno;
36
37 pub mod errno;
38 pub mod features;
39 pub mod fcntl;
40
41 #[cfg(any(target_os = "linux", target_os = "android"))]
42 pub mod mount;
43
44 #[cfg(target_os = "linux")]
45 pub mod mqueue;
46
47 #[cfg(any(target_os = "linux", target_os = "macos"))]
48 pub mod poll;
49
50 pub mod net;
51
52 #[cfg(any(target_os = "linux", target_os = "android"))]
53 pub mod sched;
54
55 pub mod sys;
56
57 // This can be implemented for other platforms as soon as libc
58 // provides bindings for them.
59 #[cfg(all(target_os = "linux",
60 any(target_arch = "x86", target_arch = "x86_64")))]
61 pub mod ucontext;
62
63 pub mod unistd;
64
65 /*
66 *
67 * ===== Result / Error =====
68 *
69 */
70
71 use libc::c_char;
72 use std::{ptr, result};
73 use std::ffi::{CStr, OsStr};
74 use std::path::{Path, PathBuf};
75 use std::os::unix::ffi::OsStrExt;
76 use std::io;
77 use std::fmt;
78 use std::error;
79 use libc::PATH_MAX;
80
81 /// Nix Result Type
82 pub type Result<T> = result::Result<T, Error>;
83
84 /// Nix Error Type
85 ///
86 /// The nix error type provides a common way of dealing with
87 /// various system system/libc calls that might fail. Each
88 /// error has a corresponding errno (usually the one from the
89 /// underlying OS) to which it can be mapped in addition to
90 /// implementing other common traits.
91 #[derive(Clone, Copy, Debug, PartialEq)]
92 pub enum Error {
93 Sys(errno::Errno),
94 InvalidPath,
95 }
96
97 impl Error {
98
99 /// Create a nix Error from a given errno
100 pub fn from_errno(errno: errno::Errno) -> Error {
101 Error::Sys(errno)
102 }
103
104 /// Get the current errno and convert it to a nix Error
105 pub fn last() -> Error {
106 Error::Sys(errno::Errno::last())
107 }
108
109 /// Create a new invalid argument error (`EINVAL`)
110 pub fn invalid_argument() -> Error {
111 Error::Sys(errno::EINVAL)
112 }
113
114 /// Get the errno associated with this error
115 pub fn errno(&self) -> errno::Errno {
116 match *self {
117 Error::Sys(errno) => errno,
118 Error::InvalidPath => errno::Errno::EINVAL,
119 }
120 }
121 }
122
123 impl From<errno::Errno> for Error {
124 fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) }
125 }
126
127 impl error::Error for Error {
128 fn description(&self) -> &str {
129 match self {
130 &Error::InvalidPath => "Invalid path",
131 &Error::Sys(ref errno) => errno.desc(),
132 }
133 }
134 }
135
136 impl fmt::Display for Error {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 match self {
139 &Error::InvalidPath => write!(f, "Invalid path"),
140 &Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
141 }
142 }
143 }
144
145 impl From<Error> for io::Error {
146 fn from(err: Error) -> Self {
147 match err {
148 Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
149 Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
150 }
151 }
152 }
153
154 pub trait NixPath {
155 fn len(&self) -> usize;
156
157 fn with_nix_path<T, F>(&self, f: F) -> Result<T>
158 where F: FnOnce(&CStr) -> T;
159 }
160
161 impl NixPath for str {
162 fn len(&self) -> usize {
163 NixPath::len(OsStr::new(self))
164 }
165
166 fn with_nix_path<T, F>(&self, f: F) -> Result<T>
167 where F: FnOnce(&CStr) -> T {
168 OsStr::new(self).with_nix_path(f)
169 }
170 }
171
172 impl NixPath for OsStr {
173 fn len(&self) -> usize {
174 self.as_bytes().len()
175 }
176
177 fn with_nix_path<T, F>(&self, f: F) -> Result<T>
178 where F: FnOnce(&CStr) -> T {
179 self.as_bytes().with_nix_path(f)
180 }
181 }
182
183 impl NixPath for CStr {
184 fn len(&self) -> usize {
185 self.to_bytes().len()
186 }
187
188 fn with_nix_path<T, F>(&self, f: F) -> Result<T>
189 where F: FnOnce(&CStr) -> T {
190 // Equivalence with the [u8] impl.
191 if self.len() >= PATH_MAX as usize {
192 return Err(Error::InvalidPath);
193 }
194
195 Ok(f(self))
196 }
197 }
198
199 impl NixPath for [u8] {
200 fn len(&self) -> usize {
201 self.len()
202 }
203
204 fn with_nix_path<T, F>(&self, f: F) -> Result<T>
205 where F: FnOnce(&CStr) -> T {
206 let mut buf = [0u8; PATH_MAX as usize];
207
208 if self.len() >= PATH_MAX as usize {
209 return Err(Error::InvalidPath);
210 }
211
212 match self.iter().position(|b| *b == 0) {
213 Some(_) => Err(Error::InvalidPath),
214 None => {
215 unsafe {
216 // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
217 ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
218 Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
219 }
220
221 }
222 }
223 }
224 }
225
226 impl NixPath for Path {
227 fn len(&self) -> usize {
228 NixPath::len(self.as_os_str())
229 }
230
231 fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
232 self.as_os_str().with_nix_path(f)
233 }
234 }
235
236 impl NixPath for PathBuf {
237 fn len(&self) -> usize {
238 NixPath::len(self.as_os_str())
239 }
240
241 fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
242 self.as_os_str().with_nix_path(f)
243 }
244 }
245
246 /// Treats `None` as an empty string.
247 impl<'a, NP: ?Sized + NixPath> NixPath for Option<&'a NP> {
248 fn len(&self) -> usize {
249 self.map_or(0, NixPath::len)
250 }
251
252 fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
253 if let Some(nix_path) = *self {
254 nix_path.with_nix_path(f)
255 } else {
256 unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
257 }
258 }
259 }