1 //! Rust friendly bindings to the various *nix system functions.
3 //! Modules are structured according to the C header file that they would be
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)
11 #![cfg_attr(test, deny(warnings))]
12 #![recursion_limit = "500"]
15 extern crate bitflags
;
22 extern crate nix_test
as nixtest
;
24 #[macro_use] mod macros;
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.
31 pub use self::libc
::*;
34 pub use libc
::{c_int, c_void}
;
41 #[cfg(any(target_os = "linux", target_os = "android"))]
44 #[cfg(target_os = "linux")]
47 #[cfg(any(target_os = "linux", target_os = "macos"))]
52 #[cfg(any(target_os = "linux", target_os = "android"))]
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")))]
67 * ===== Result / Error =====
72 use std
::{ptr, result}
;
73 use std
::ffi
::{CStr, OsStr}
;
74 use std
::path
::{Path, PathBuf}
;
75 use std
::os
::unix
::ffi
::OsStrExt
;
82 pub type Result
<T
> = result
::Result
<T
, Error
>;
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)]
99 /// Create a nix Error from a given errno
100 pub fn from_errno(errno
: errno
::Errno
) -> Error
{
104 /// Get the current errno and convert it to a nix Error
105 pub fn last() -> Error
{
106 Error
::Sys(errno
::Errno
::last())
109 /// Create a new invalid argument error (`EINVAL`)
110 pub fn invalid_argument() -> Error
{
111 Error
::Sys(errno
::EINVAL
)
114 /// Get the errno associated with this error
115 pub fn errno(&self) -> errno
::Errno
{
117 Error
::Sys(errno
) => errno
,
118 Error
::InvalidPath
=> errno
::Errno
::EINVAL
,
123 impl From
<errno
::Errno
> for Error
{
124 fn from(errno
: errno
::Errno
) -> Error { Error::from_errno(errno) }
127 impl error
::Error
for Error
{
128 fn description(&self) -> &str {
130 &Error
::InvalidPath
=> "Invalid path",
131 &Error
::Sys(ref errno
) => errno
.desc(),
136 impl fmt
::Display
for Error
{
137 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
139 &Error
::InvalidPath
=> write
!(f
, "Invalid path"),
140 &Error
::Sys(errno
) => write
!(f
, "{:?}: {}", errno
, errno
.desc()),
145 impl From
<Error
> for io
::Error
{
146 fn from(err
: Error
) -> Self {
148 Error
::InvalidPath
=> io
::Error
::new(io
::ErrorKind
::InvalidInput
, err
),
149 Error
::Sys(errno
) => io
::Error
::from_raw_os_error(errno
as i32),
155 fn len(&self) -> usize;
157 fn with_nix_path
<T
, F
>(&self, f
: F
) -> Result
<T
>
158 where F
: FnOnce(&CStr
) -> T
;
161 impl NixPath
for str {
162 fn len(&self) -> usize {
163 NixPath
::len(OsStr
::new(self))
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
)
172 impl NixPath
for OsStr
{
173 fn len(&self) -> usize {
174 self.as_bytes().len()
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
)
183 impl NixPath
for CStr
{
184 fn len(&self) -> usize {
185 self.to_bytes().len()
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
);
199 impl NixPath
for [u8] {
200 fn len(&self) -> usize {
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];
208 if self.len() >= PATH_MAX
as usize {
209 return Err(Error
::InvalidPath
);
212 match self.iter().position(|b
| *b
== 0) {
213 Some(_
) => Err(Error
::InvalidPath
),
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
)))
226 impl NixPath
for Path
{
227 fn len(&self) -> usize {
228 NixPath
::len(self.as_os_str())
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
)
236 impl NixPath
for PathBuf
{
237 fn len(&self) -> usize {
238 NixPath
::len(self.as_os_str())
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
)
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
)
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
)
256 unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }