diff --git a/src/cstr.rs b/src/cstr.rs new file mode 100644 index 0000000000..a863cca14d --- /dev/null +++ b/src/cstr.rs @@ -0,0 +1,80 @@ +use std::ffi::{OsStr, OsString, CString, NulError}; +use std::path::{Path, PathBuf}; +use std::os::unix::ffi::{OsStrExt, OsStringExt}; + +pub trait ToCString { + fn to_cstring(&self) -> Result; + fn into_cstring(self) -> Result where Self: Sized { unimplemented!() } +} + +impl ToCString for [u8] { + fn to_cstring(&self) -> Result { + CString::new(self) + } +} + +impl ToCString for Vec { + fn to_cstring(&self) -> Result { + ToCString::to_cstring(&**self) + } + + fn into_cstring(self) -> Result { + CString::new(self) + } +} + +impl ToCString for str { + fn to_cstring(&self) -> Result { + CString::new(self.as_bytes()) + } +} + +impl ToCString for String { + fn to_cstring(&self) -> Result { + ToCString::to_cstring(&**self) + } + + fn into_cstring(self) -> Result { + CString::new(self.into_bytes()) + } +} + +impl ToCString for OsStr { + fn to_cstring(&self) -> Result { + CString::new(self.as_bytes()) + } +} + +impl ToCString for OsString { + fn to_cstring(&self) -> Result { + ToCString::to_cstring(&**self) + } + + fn into_cstring(self) -> Result { + CString::new(self.into_vec()) + } +} + +impl ToCString for Path { + fn to_cstring(&self) -> Result { + ToCString::to_cstring(self.as_os_str()) + } +} + +impl ToCString for PathBuf { + fn to_cstring(&self) -> Result { + ToCString::to_cstring(self.as_os_str()) + } + + fn into_cstring(self) -> Result { + ToCString::into_cstring(self.into_os_string()) + } +} + +// TODO: allow this in consts/statics +#[macro_export] +macro_rules! cstr { + ($s:expr) => { + unsafe { ::std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _) } + } +} diff --git a/src/errno.rs b/src/errno.rs index 4218bf9cd3..1e219f13cc 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -1,6 +1,5 @@ use libc::c_int; -use std::{fmt, io, error}; -use {Error, Result}; +use std::{fmt, io, error, result}; pub use self::consts::*; pub use self::consts::Errno::*; @@ -74,7 +73,7 @@ impl Errno { /// should not be used when `-1` is not the errno sentinel value. pub fn result>(value: S) -> Result { if value == S::sentinel() { - Err(Error::Sys(Self::last())) + Err(Self::last()) } else { Ok(value) } @@ -117,6 +116,8 @@ impl From for io::Error { } } +pub type Result = result::Result; + fn last() -> Errno { Errno::from_i32(errno()) } diff --git a/src/fcntl.rs b/src/fcntl.rs index 2b1c7b8959..c1d2f81ef6 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1,4 +1,4 @@ -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; use libc::{c_int, c_uint}; use sys::stat::Mode; use std::os::unix::io::RawFd; @@ -96,10 +96,10 @@ mod ffi { } } -pub fn open(path: &P, oflag: OFlag, mode: Mode) -> Result { - let fd = try!(path.with_nix_path(|cstr| { - unsafe { ffi::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } - })); +pub fn open(path: P, oflag: OFlag, mode: Mode) -> Result { + let fd = unsafe { + ffi::open(path.as_ref().as_ptr(), oflag.bits(), mode.bits() as c_uint) + }; Errno::result(fd) } diff --git a/src/lib.rs b/src/lib.rs index 66a9281681..050c92eff2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,13 @@ extern crate nix_test as nixtest; // Re-exports pub use libc::{c_int, c_void}; -pub use errno::Errno; +pub use errno::{Errno, Result}; +pub use nix_string::NixString; + +mod nix_string; + +#[macro_use] +pub mod cstr; pub mod errno; pub mod features; @@ -42,186 +48,3 @@ pub mod sched; pub mod sys; pub mod unistd; - -/* - * - * ===== Result / Error ===== - * - */ - -use libc::c_char; -use std::{ptr, result}; -use std::ffi::{CStr, OsStr}; -use std::path::{Path, PathBuf}; -use std::os::unix::ffi::OsStrExt; -use std::io; -use std::fmt; -use std::error; -use libc::PATH_MAX; - -pub type Result = result::Result; - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Error { - Sys(errno::Errno), - InvalidPath, -} - -impl Error { - pub fn from_errno(errno: errno::Errno) -> Error { - Error::Sys(errno) - } - - pub fn last() -> Error { - Error::Sys(errno::Errno::last()) - } - - pub fn invalid_argument() -> Error { - Error::Sys(errno::EINVAL) - } - - pub fn errno(&self) -> errno::Errno { - match *self { - Error::Sys(errno) => errno, - Error::InvalidPath => errno::Errno::EINVAL, - } - } -} - -impl From for Error { - fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) } -} - -impl error::Error for Error { - fn description(&self) -> &str { - match self { - &Error::InvalidPath => "Invalid path", - &Error::Sys(ref errno) => errno.desc(), - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &Error::InvalidPath => write!(f, "Invalid path"), - &Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()), - } - } -} - -impl From for io::Error { - fn from(err: Error) -> Self { - match err { - Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err), - Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32), - } - } -} - -pub trait NixPath { - fn len(&self) -> usize; - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T; -} - -impl NixPath for str { - fn len(&self) -> usize { - NixPath::len(OsStr::new(self)) - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - OsStr::new(self).with_nix_path(f) - } -} - -impl NixPath for OsStr { - fn len(&self) -> usize { - self.as_bytes().len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - self.as_bytes().with_nix_path(f) - } -} - -impl NixPath for CStr { - fn len(&self) -> usize { - self.to_bytes().len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - // Equivalence with the [u8] impl. - if self.len() >= PATH_MAX as usize { - return Err(Error::InvalidPath); - } - - Ok(f(self)) - } -} - -impl NixPath for [u8] { - fn len(&self) -> usize { - self.len() - } - - fn with_nix_path(&self, f: F) -> Result - where F: FnOnce(&CStr) -> T { - let mut buf = [0u8; PATH_MAX as usize]; - - if self.len() >= PATH_MAX as usize { - return Err(Error::InvalidPath); - } - - match self.iter().position(|b| *b == 0) { - Some(_) => Err(Error::InvalidPath), - None => { - unsafe { - // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028 - ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len()); - Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char))) - } - - } - } - } -} - -impl NixPath for Path { - fn len(&self) -> usize { - NixPath::len(self.as_os_str()) - } - - fn with_nix_path(&self, f: F) -> Result where F: FnOnce(&CStr) -> T { - self.as_os_str().with_nix_path(f) - } -} - -impl NixPath for PathBuf { - fn len(&self) -> usize { - NixPath::len(self.as_os_str()) - } - - fn with_nix_path(&self, f: F) -> Result where F: FnOnce(&CStr) -> T { - self.as_os_str().with_nix_path(f) - } -} - -/// Treats `None` as an empty string. -impl<'a, NP: ?Sized + NixPath> NixPath for Option<&'a NP> { - fn len(&self) -> usize { - self.map_or(0, NixPath::len) - } - - fn with_nix_path(&self, f: F) -> Result where F: FnOnce(&CStr) -> T { - if let Some(nix_path) = *self { - nix_path.with_nix_path(f) - } else { - unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) } - } - } -} diff --git a/src/mount.rs b/src/mount.rs index 13b11e5fe1..6bbf9194c6 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -1,5 +1,5 @@ use libc::{c_ulong, c_int}; -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; bitflags!( flags MsFlags: c_ulong { @@ -65,46 +65,42 @@ mod ffi { } } -pub fn mount( - source: Option<&P1>, - target: &P2, - fstype: Option<&P3>, +pub fn mount( + source: Option, + target: P2, + fstype: Option, flags: MsFlags, - data: Option<&P4>) -> Result<()> { + data: Option) -> Result<()> { + use std::ffi::CStr; + use std::ptr; use libc; - let res = try!(try!(try!(try!( - source.with_nix_path(|source| { - target.with_nix_path(|target| { - fstype.with_nix_path(|fstype| { - data.with_nix_path(|data| { - unsafe { - ffi::mount(source.as_ptr(), - target.as_ptr(), - fstype.as_ptr(), - flags.bits, - data.as_ptr() as *const libc::c_void) - } - }) - }) - }) - }))))); + let source = source.as_ref().map(NixString::as_ref); + let fstype = fstype.as_ref().map(NixString::as_ref); + let data = data.as_ref().map(NixString::as_ref); + let res = unsafe { + ffi::mount(source.map(CStr::as_ptr).unwrap_or(ptr::null()), + target.as_ref().as_ptr(), + fstype.map(CStr::as_ptr).unwrap_or(ptr::null()), + flags.bits, + data.map(CStr::as_ptr).unwrap_or(ptr::null()) as *const libc::c_void) + }; Errno::result(res).map(drop) } -pub fn umount(target: &P) -> Result<()> { - let res = try!(target.with_nix_path(|cstr| { - unsafe { ffi::umount(cstr.as_ptr()) } - })); +pub fn umount(target: P) -> Result<()> { + let res = unsafe { + ffi::umount(target.as_ref().as_ptr()) + }; Errno::result(res).map(drop) } -pub fn umount2(target: &P, flags: MntFlags) -> Result<()> { - let res = try!(target.with_nix_path(|cstr| { - unsafe { ffi::umount2(cstr.as_ptr(), flags.bits) } - })); +pub fn umount2(target: P, flags: MntFlags) -> Result<()> { + let res = unsafe { + ffi::umount2(target.as_ref().as_ptr(), flags.bits) + }; Errno::result(res).map(drop) } diff --git a/src/mqueue.rs b/src/mqueue.rs index bc3eca2cc1..e3cd6d3bba 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -2,10 +2,9 @@ //! //! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html) -use {Errno, Result}; +use {Errno, Result, NixString}; -use libc::{c_int, c_long, c_char, size_t, mode_t, strlen}; -use std::ffi::CString; +use libc::{c_int, c_long, c_char, size_t, mode_t}; use sys::stat::Mode; pub use self::consts::*; @@ -76,14 +75,14 @@ impl MqAttr { #[inline] -pub fn mq_open(name: &CString, oflag: MQ_OFlag, mode: Mode, attr: &MqAttr) -> Result { - let res = unsafe { ffi::mq_open(name.as_ptr(), oflag.bits(), mode.bits() as mode_t, attr as *const MqAttr) }; +pub fn mq_open(name: S, oflag: MQ_OFlag, mode: Mode, attr: &MqAttr) -> Result { + let res = unsafe { ffi::mq_open(name.as_ref().as_ptr(), oflag.bits(), mode.bits() as mode_t, attr as *const MqAttr) }; Errno::result(res) } -pub fn mq_unlink(name: &CString) -> Result<()> { - let res = unsafe { ffi::mq_unlink(name.as_ptr()) }; +pub fn mq_unlink(name: S) -> Result<()> { + let res = unsafe { ffi::mq_unlink(name.as_ref().as_ptr()) }; Errno::result(res).map(drop) } @@ -100,9 +99,8 @@ pub fn mq_receive(mqdes: MQd, message: &mut [u8], msq_prio: u32) -> Result Result { - let len = unsafe { strlen(message.as_ptr()) as size_t }; - let res = unsafe { ffi::mq_send(mqdes, message.as_ptr(), len, msq_prio) }; +pub fn mq_send(mqdes: MQd, message: &[u8], msq_prio: u32) -> Result { + let res = unsafe { ffi::mq_send(mqdes, message.as_ptr() as *const _, message.len(), msq_prio) }; Errno::result(res).map(|r| r as usize) } diff --git a/src/net/if_.rs b/src/net/if_.rs index 7edfc998c6..fe6105ed14 100644 --- a/src/net/if_.rs +++ b/src/net/if_.rs @@ -5,14 +5,14 @@ use libc; use libc::c_uint; -use {Result, Error, NixPath}; +use {Errno, Result, NixString}; /// Resolve an interface into a interface number. -pub fn if_nametoindex(name: &P) -> Result { - let if_index = try!(name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })); +pub fn if_nametoindex(name: P) -> Result { + let if_index = unsafe { libc::if_nametoindex(name.as_ref().as_ptr()) }; if if_index == 0 { - Err(Error::last()) + Err(Errno::last()) } else { Ok(if_index) } diff --git a/src/nix_string.rs b/src/nix_string.rs new file mode 100644 index 0000000000..d1e6473697 --- /dev/null +++ b/src/nix_string.rs @@ -0,0 +1,33 @@ +use std::ffi::{CStr, CString}; + +/// Represents a type that can be converted to a `&CStr` without fail. +/// +/// Note: this trait exists in place of `AsRef` because is not +/// implemented until Rust 1.7.0 +pub trait NixString { + fn as_ref(&self) -> &CStr; +} + +impl NixString for CStr { + fn as_ref(&self) -> &CStr { + self + } +} + +impl NixString for CString { + fn as_ref(&self) -> &CStr { + self + } +} + +impl<'a, T: ?Sized + NixString> NixString for &'a T { + fn as_ref(&self) -> &CStr { + NixString::as_ref(*self) + } +} + +impl<'a, T: ?Sized + NixString> NixString for &'a mut T { + fn as_ref(&self) -> &CStr { + NixString::as_ref(*self) + } +} diff --git a/src/sys/mman.rs b/src/sys/mman.rs index 7537c272e7..a16da3cdfb 100644 --- a/src/sys/mman.rs +++ b/src/sys/mman.rs @@ -1,4 +1,4 @@ -use {Errno, Error, Result, NixPath}; +use {Errno, Result, NixString}; use fcntl::OFlag; use libc::{c_void, size_t, off_t, mode_t}; use sys::stat::Mode; @@ -203,7 +203,7 @@ pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag, let ret = unsafe { ffi::mmap(addr, length, prot, flags, fd, offset) }; if ret as isize == MAP_FAILED { - Err(Error::Sys(Errno::last())) + Err(Errno::last()) } else { Ok(ret) } @@ -221,20 +221,14 @@ pub fn msync(addr: *const c_void, length: size_t, flags: MmapSync) -> Result<()> Errno::result(unsafe { ffi::msync(addr, length, flags) }).map(drop) } -pub fn shm_open(name: &P, flag: OFlag, mode: Mode) -> Result { - let ret = try!(name.with_nix_path(|cstr| { - unsafe { - ffi::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as mode_t) - } - })); - - Errno::result(ret) +pub fn shm_open(name: P, flag: OFlag, mode: Mode) -> Result { + unsafe { + Errno::result(ffi::shm_open(name.as_ref().as_ptr(), flag.bits(), mode.bits() as mode_t)) + } } -pub fn shm_unlink(name: &P) -> Result<()> { - let ret = try!(name.with_nix_path(|cstr| { - unsafe { ffi::shm_unlink(cstr.as_ptr()) } - })); - - Errno::result(ret).map(drop) +pub fn shm_unlink(name: P) -> Result<()> { + unsafe { + Errno::result(ffi::shm_unlink(name.as_ref().as_ptr())).map(drop) + } } diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index 63c7482ddd..99ba2b8762 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -1,4 +1,4 @@ -use {Errno, Error, Result}; +use {Errno, Result}; use libc::{pid_t, c_void, c_long}; #[cfg(all(target_os = "linux", @@ -86,7 +86,7 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da ffi::ptrace(request, pid, addr, data) }; match Errno::result(ret) { - Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret), + Ok(..) | Err(Errno::UnknownErrno) => Ok(ret), err @ Err(..) => err, } } diff --git a/src/sys/quota.rs b/src/sys/quota.rs index a6a1b9b0bb..0b6d5e77ae 100644 --- a/src/sys/quota.rs +++ b/src/sys/quota.rs @@ -1,4 +1,4 @@ -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; use libc::{c_int, c_char}; #[cfg(all(target_os = "linux", @@ -79,45 +79,40 @@ mod ffi { } use std::ptr; +use std::ffi::CStr; -fn quotactl(cmd: quota::QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> { +fn quotactl(cmd: quota::QuotaCmd, special: Option

, id: c_int, addr: *mut c_char) -> Result<()> { unsafe { Errno::clear(); - let res = try!( - match special { - Some(dev) => dev.with_nix_path(|path| ffi::quotactl(cmd.as_int(), path.as_ptr(), id, addr)), - None => Ok(ffi::quotactl(cmd.as_int(), ptr::null(), id, addr)), - } - ); + let special = special.as_ref().map(NixString::as_ref); + let res = ffi::quotactl(cmd.as_int(), special.map(CStr::as_ptr).unwrap_or(ptr::null()), id, addr); Errno::result(res).map(drop) } } -pub fn quotactl_on(which: quota::QuotaType, special: &P, format: quota::QuotaFmt, quota_file: &P) -> Result<()> { - try!(quota_file.with_nix_path(|path| { - let mut path_copy = path.to_bytes_with_nul().to_owned(); - let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char; - quotactl(quota::QuotaCmd(quota::Q_QUOTAON, which), Some(special), format as c_int, p) - })) +pub fn quotactl_on(which: quota::QuotaType, special: P0, format: quota::QuotaFmt, quota_file: P1) -> Result<()> { + let mut path_copy = quota_file.as_ref().to_bytes_with_nul().to_owned(); + let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char; + quotactl(quota::QuotaCmd(quota::Q_QUOTAON, which), Some(special), format as c_int, p) } -pub fn quotactl_off(which: quota::QuotaType, special: &P) -> Result<()> { +pub fn quotactl_off(which: quota::QuotaType, special: P) -> Result<()> { quotactl(quota::QuotaCmd(quota::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut()) } -pub fn quotactl_sync(which: quota::QuotaType, special: Option<&P>) -> Result<()> { +pub fn quotactl_sync(which: quota::QuotaType, special: Option

) -> Result<()> { quotactl(quota::QuotaCmd(quota::Q_SYNC, which), special, 0, ptr::null_mut()) } -pub fn quotactl_get(which: quota::QuotaType, special: &P, id: c_int, dqblk: &mut quota::Dqblk) -> Result<()> { +pub fn quotactl_get(which: quota::QuotaType, special: P, id: c_int, dqblk: &mut quota::Dqblk) -> Result<()> { use std::mem; unsafe { quotactl(quota::QuotaCmd(quota::Q_GETQUOTA, which), Some(special), id, mem::transmute(dqblk)) } } -pub fn quotactl_set(which: quota::QuotaType, special: &P, id: c_int, dqblk: "a::Dqblk) -> Result<()> { +pub fn quotactl_set(which: quota::QuotaType, special: P, id: c_int, dqblk: "a::Dqblk) -> Result<()> { use std::mem; let mut dqblk_copy = *dqblk; unsafe { diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index 01ea66b930..fc7b9772b4 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -113,7 +113,7 @@ impl SignalFd { match unistd::read(self.0, &mut buffer) { Ok(SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute_copy(&buffer) })), Ok(_) => unreachable!("partial read on signalfd"), - Err(Error::Sys(Errno::EAGAIN)) => Ok(None), + Err(Errno::EAGAIN) => Ok(None), Err(error) => Err(error) } } diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index 90bea068e3..ca94fe8de0 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -1,5 +1,5 @@ use super::{consts, sa_family_t}; -use {Errno, Error, Result, NixPath}; +use {Errno, Result, NixString}; use libc; use std::{fmt, hash, mem, net, ptr}; use std::ffi::OsStr; @@ -345,27 +345,26 @@ pub struct UnixAddr(pub libc::sockaddr_un, pub usize); impl UnixAddr { /// Create a new sockaddr_un representing a filesystem path. - pub fn new(path: &P) -> Result { - try!(path.with_nix_path(|cstr| { - unsafe { - let mut ret = libc::sockaddr_un { - sun_family: AddressFamily::Unix as sa_family_t, - .. mem::zeroed() - }; + pub fn new(path: P) -> Result { + let cstr = path.as_ref(); + unsafe { + let mut ret = libc::sockaddr_un { + sun_family: AddressFamily::Unix as sa_family_t, + .. mem::zeroed() + }; - let bytes = cstr.to_bytes_with_nul(); + let bytes = cstr.to_bytes_with_nul(); - if bytes.len() > ret.sun_path.len() { - return Err(Error::Sys(Errno::ENAMETOOLONG)); - } + if bytes.len() > ret.sun_path.len() { + return Err(Errno::ENAMETOOLONG); + } - ptr::copy_nonoverlapping(bytes.as_ptr(), - ret.sun_path.as_mut_ptr() as *mut u8, - bytes.len()); + ptr::copy_nonoverlapping(bytes.as_ptr(), + ret.sun_path.as_mut_ptr() as *mut u8, + bytes.len()); - Ok(UnixAddr(ret, bytes.len())) - } - })) + Ok(UnixAddr(ret, bytes.len())) + } } /// Create a new sockaddr_un representing an address in the @@ -380,7 +379,7 @@ impl UnixAddr { }; if path.len() > ret.sun_path.len() { - return Err(Error::Sys(Errno::ENAMETOOLONG)); + return Err(Errno::ENAMETOOLONG); } // Abstract addresses are represented by sun_path[0] == @@ -463,7 +462,7 @@ impl SockAddr { SockAddr::Inet(addr) } - pub fn new_unix(path: &P) -> Result { + pub fn new_unix(path: P) -> Result { Ok(SockAddr::Unix(try!(UnixAddr::new(path)))) } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index bd87bbf1f9..1daaa434ea 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1,7 +1,7 @@ //! Socket interface functions //! //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html) -use {Error, Errno, Result}; +use {Errno, Result}; use features; use fcntl::{fcntl, FD_CLOEXEC, O_NONBLOCK}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; @@ -614,7 +614,7 @@ pub unsafe fn sockaddr_storage_to_addr( len: usize) -> Result { if len < mem::size_of_val(&addr.ss_family) { - return Err(Error::Sys(Errno::ENOTCONN)); + return Err(Errno::ENOTCONN); } match addr.ss_family as c_int { diff --git a/src/sys/stat.rs b/src/sys/stat.rs index cd142a9600..0c8c1cdb6f 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -1,7 +1,7 @@ pub use libc::dev_t; pub use libc::stat as FileStat; -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; use libc::mode_t; use std::mem; use std::os::unix::io::RawFd; @@ -49,12 +49,10 @@ bitflags! { } } -pub fn mknod(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { - unsafe { - ffi::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev) - } - })); +pub fn mknod(path: P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> { + let res = unsafe { + ffi::mknod(path.as_ref().as_ptr(), kind.bits | perm.bits() as mode_t, dev) + }; Errno::result(res).map(drop) } @@ -72,26 +70,22 @@ pub fn umask(mode: Mode) -> Mode { Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode") } -pub fn stat(path: &P) -> Result { +pub fn stat(path: P) -> Result { let mut dst = unsafe { mem::uninitialized() }; - let res = try!(path.with_nix_path(|cstr| { - unsafe { - ffi::stat(cstr.as_ptr(), &mut dst as *mut FileStat) - } - })); + let res = unsafe { + ffi::stat(path.as_ref().as_ptr(), &mut dst as *mut FileStat) + }; try!(Errno::result(res)); Ok(dst) } -pub fn lstat(path: &P) -> Result { +pub fn lstat(path: P) -> Result { let mut dst = unsafe { mem::uninitialized() }; - let res = try!(path.with_nix_path(|cstr| { - unsafe { - ffi::lstat(cstr.as_ptr(), &mut dst as *mut FileStat) - } - })); + let res = unsafe { + ffi::lstat(path.as_ref().as_ptr(), &mut dst as *mut FileStat) + }; try!(Errno::result(res)); diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index 7c61a3ab31..209dcd42b3 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -1,4 +1,4 @@ -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; use std::os::unix::io::AsRawFd; pub mod vfs { @@ -97,14 +97,10 @@ mod ffi { } } -pub fn statfs(path: &P, stat: &mut vfs::Statfs) -> Result<()> { +pub fn statfs(path: P, stat: &mut vfs::Statfs) -> Result<()> { unsafe { Errno::clear(); - let res = try!( - path.with_nix_path(|path| ffi::statfs(path.as_ptr(), stat)) - ); - - Errno::result(res).map(drop) + Errno::result(ffi::statfs(path.as_ref().as_ptr(), stat)).map(drop) } } diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index 5b72a16bd8..029f90f64a 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -2,7 +2,7 @@ //! //! See the `vfs::Statvfs` struct for some rusty wrappers -use {Errno, Result, NixPath}; +use {Errno, Result, NixString}; use std::os::unix::io::AsRawFd; pub mod vfs { @@ -13,7 +13,7 @@ pub mod vfs { use libc::{c_ulong,c_int}; use std::os::unix::io::AsRawFd; - use {Result, NixPath}; + use {Result, NixString}; use super::{statvfs, fstatvfs}; @@ -84,14 +84,14 @@ pub mod vfs { impl Statvfs { /// Create a new `Statvfs` object and fill it with information about /// the mount that contains `path` - pub fn for_path(path: &P) -> Result { + pub fn for_path(path: P) -> Result { let mut stat = Statvfs::default(); let res = statvfs(path, &mut stat); res.map(|_| stat) } /// Replace information in this struct with information about `path` - pub fn update_with_path(&mut self, path: &P) -> Result<()> { + pub fn update_with_path(&mut self, path: P) -> Result<()> { statvfs(path, self) } @@ -140,13 +140,10 @@ mod ffi { } /// Fill an existing `Statvfs` object with information about the `path` -pub fn statvfs(path: &P, stat: &mut vfs::Statvfs) -> Result<()> { +pub fn statvfs(path: P, stat: &mut vfs::Statvfs) -> Result<()> { unsafe { Errno::clear(); - let res = try!( - path.with_nix_path(|path| ffi::statvfs(path.as_ptr(), stat)) - ); - + let res = ffi::statvfs(path.as_ref().as_ptr(), stat); Errno::result(res).map(drop) } } @@ -167,7 +164,7 @@ mod test { #[test] fn statvfs_call() { let mut stat = vfs::Statvfs::default(); - statvfs("/".as_bytes(), &mut stat).unwrap() + statvfs(cstr!("/"), &mut stat).unwrap() } #[test] diff --git a/src/unistd.rs b/src/unistd.rs index a4e666180c..4c2d6d38e3 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1,6 +1,6 @@ //! Standard symbolic constants and types //! -use {Errno, Error, Result, NixPath}; +use {Errno, Result, NixString}; use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; use libc::{c_char, c_void, c_int, size_t, pid_t, off_t, uid_t, gid_t}; @@ -133,7 +133,7 @@ pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { #[inline] fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { if oldfd == newfd { - return Err(Error::Sys(Errno::EINVAL)); + return Err(Errno::EINVAL); } let fd = try!(dup2(oldfd, newfd)); @@ -149,14 +149,15 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { } #[inline] -pub fn chdir(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { - unsafe { ffi::chdir(cstr.as_ptr()) } - })); +pub fn chdir(path: P) -> Result<()> { + let res = unsafe { + ffi::chdir(path.as_ref().as_ptr()) + }; Errno::result(res).map(drop) } +// TODO: do this without allocations fn to_exec_array(args: &[CString]) -> Vec<*const c_char> { use std::ptr; use libc::c_char; @@ -167,26 +168,26 @@ fn to_exec_array(args: &[CString]) -> Vec<*const c_char> { } #[inline] -pub fn execv(path: &CString, argv: &[CString]) -> Result<()> { +pub fn execv(path: P, argv: &[CString]) -> Result<()> { let args_p = to_exec_array(argv); unsafe { - ffi::execv(path.as_ptr(), args_p.as_ptr()) + ffi::execv(path.as_ref().as_ptr(), args_p.as_ptr()) }; - Err(Error::Sys(Errno::last())) + Err(Errno::last()) } #[inline] -pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<()> { +pub fn execve(path: P, args: &[CString], env: &[CString]) -> Result<()> { let args_p = to_exec_array(args); let env_p = to_exec_array(env); unsafe { - ffi::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) + ffi::execve(path.as_ref().as_ptr(), args_p.as_ptr(), env_p.as_ptr()) }; - Err(Error::Sys(Errno::last())) + Err(Errno::last()) } #[inline] @@ -197,7 +198,7 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<()> { ffi::execvp(filename.as_ptr(), args_p.as_ptr()) }; - Err(Error::Sys(Errno::last())) + Err(Errno::last()) } pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> { @@ -304,27 +305,25 @@ pub fn isatty(fd: RawFd) -> Result { } else { match Errno::last() { Errno::ENOTTY => Ok(false), - err => Err(Error::Sys(err)), + err => Err(err), } } } } -pub fn unlink(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { - unsafe { - ffi::unlink(cstr.as_ptr()) - } - })); +pub fn unlink(path: P) -> Result<()> { + let res = unsafe { + ffi::unlink(path.as_ref().as_ptr()) + }; Errno::result(res).map(drop) } #[inline] -pub fn chroot(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { - unsafe { ffi::chroot(cstr.as_ptr()) } - })); +pub fn chroot(path: P) -> Result<()> { + let res = unsafe { + ffi::chroot(path.as_ref().as_ptr()) + }; Errno::result(res).map(drop) } @@ -372,27 +371,23 @@ pub fn getegid() -> gid_t { #[cfg(any(target_os = "linux", target_os = "android"))] mod linux { use sys::syscall::{syscall, SYSPIVOTROOT}; - use {Errno, Result, NixPath}; + use {Errno, Result, NixString}; #[cfg(feature = "execvpe")] use std::ffi::CString; - pub fn pivot_root( - new_root: &P1, put_old: &P2) -> Result<()> { - let res = try!(try!(new_root.with_nix_path(|new_root| { - put_old.with_nix_path(|put_old| { - unsafe { - syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr()) - } - }) - }))); + pub fn pivot_root( + new_root: P1, put_old: P2) -> Result<()> { + let res = unsafe { + syscall(SYSPIVOTROOT, new_root.as_ref().as_ptr(), put_old.as_ref().as_ptr()) + }; Errno::result(res).map(drop) } #[inline] #[cfg(feature = "execvpe")] - pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> { + pub fn execvpe(filename: F, args: &[CString], env: &[CString]) -> Result<()> { use std::ptr; use libc::c_char; @@ -403,9 +398,9 @@ mod linux { env_p.push(ptr::null()); unsafe { - super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) + super::ffi::execvpe(filename.as_ref().as_ptr(), args_p.as_ptr(), env_p.as_ptr()) }; - Err(Error::Sys(Errno::last())) + Err(Errno::last()) } } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 258cde07dd..7dc4b07baa 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -1,7 +1,7 @@ use nix::sys::socket::{InetAddr, UnixAddr, getsockname}; -use std::{mem, net}; use std::path::Path; -use std::str::FromStr; +use std::{mem, net}; +use std::str::{self, FromStr}; use std::os::unix::io::{AsRawFd, RawFd}; use ports::localhost; use libc::c_char; @@ -30,13 +30,14 @@ pub fn test_inetv4_addr_to_sock_addr() { #[test] pub fn test_path_to_sock_addr() { - let actual = Path::new("/foo/bar"); + let actual = cstr!("/foo/bar"); let addr = UnixAddr::new(actual).unwrap(); let expect: &'static [c_char] = unsafe { mem::transmute(&b"/foo/bar"[..]) }; assert_eq!(&addr.0.sun_path[..8], expect); - assert_eq!(addr.path(), Some(actual)); + let actual = str::from_utf8(actual.to_bytes()).unwrap(); + assert_eq!(addr.path(), Some(Path::new(actual))); } #[test] diff --git a/test/sys/test_termios.rs b/test/sys/test_termios.rs index a41304d73f..ce82282b3f 100644 --- a/test/sys/test_termios.rs +++ b/test/sys/test_termios.rs @@ -1,6 +1,6 @@ use nix::errno::Errno; use nix::sys::termios; -use nix::{Error, unistd}; +use nix::unistd; #[test] fn test_tcgetattr() { @@ -11,8 +11,8 @@ fn test_tcgetattr() { Ok(true) => assert!(termios.is_ok()), // If it's an invalid file descriptor, tcgetattr should also return // the same error - Err(Error::Sys(Errno::EBADF)) => { - assert_eq!(termios.err(), Some(Error::Sys(Errno::EBADF))); + Err(Errno::EBADF) => { + assert_eq!(termios.err(), Some(Errno::EBADF)); }, // Otherwise it should return any error _ => assert!(termios.is_err()) diff --git a/test/test_mount.rs b/test/test_mount.rs index f2c2454fd0..bbdbf9a297 100644 --- a/test/test_mount.rs +++ b/test/test_mount.rs @@ -3,20 +3,23 @@ // namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run // without root. -extern crate libc; +#[macro_use] extern crate nix; +extern crate libc; extern crate tempdir; #[cfg(target_os = "linux")] mod test_mount { use std::fs::{self, File}; use std::io::{Read, Write}; + use std::ffi::CStr; use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::PermissionsExt; use std::process::Command; use libc::{self, EACCES, EROFS}; + use nix::cstr::ToCString; use nix::mount::{mount, umount, MsFlags, MS_BIND, MS_RDONLY, MS_NOEXEC}; use nix::sched::{unshare, CLONE_NEWNS, CLONE_NEWUSER}; use nix::sys::stat::{self, S_IRWXU, S_IRWXG, S_IRWXO, S_IXUSR, S_IXGRP, S_IXOTH}; @@ -28,14 +31,16 @@ exit 23"; const EXPECTED_STATUS: i32 = 23; - const NONE: Option<&'static [u8]> = None; + const NONE: Option<&'static CStr> = None; + pub fn test_mount_tmpfs_without_flags_allows_rwx() { let tempdir = TempDir::new("nix-test_mount") .unwrap_or_else(|e| panic!("tempdir failed: {}", e)); + let temppath = tempdir.path().to_cstring().unwrap(); mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), + &temppath, + Some(cstr!("tmpfs")), MsFlags::empty(), NONE) .unwrap_or_else(|e| panic!("mount failed: {}", e)); @@ -66,16 +71,17 @@ exit 23"; .code() .unwrap_or_else(|| panic!("child killed by signal"))); - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); + umount(&temppath).unwrap_or_else(|e| panic!("umount failed: {}", e)); } pub fn test_mount_rdonly_disallows_write() { let tempdir = TempDir::new("nix-test_mount") .unwrap_or_else(|e| panic!("tempdir failed: {}", e)); + let temppath = tempdir.path().to_cstring().unwrap(); mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), + &temppath, + Some(cstr!("tmpfs")), MS_RDONLY, NONE) .unwrap_or_else(|e| panic!("mount failed: {}", e)); @@ -84,16 +90,17 @@ exit 23"; assert_eq!(EROFS as i32, File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap()); - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); + umount(&temppath).unwrap_or_else(|e| panic!("umount failed: {}", e)); } pub fn test_mount_noexec_disallows_exec() { let tempdir = TempDir::new("nix-test_mount") .unwrap_or_else(|e| panic!("tempdir failed: {}", e)); + let temppath = tempdir.path().to_cstring().unwrap(); mount(NONE, - tempdir.path(), - Some(b"tmpfs".as_ref()), + &temppath, + Some(cstr!("tmpfs")), MS_NOEXEC, NONE) .unwrap_or_else(|e| panic!("mount failed: {}", e)); @@ -123,7 +130,7 @@ exit 23"; assert_eq!(EACCES as i32, Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap()); - umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); + umount(&temppath).unwrap_or_else(|e| panic!("umount failed: {}", e)); } pub fn test_mount_bind() { @@ -135,14 +142,16 @@ exit 23"; let tempdir = TempDir::new("nix-test_mount") .unwrap_or_else(|e| panic!("tempdir failed: {}", e)); + let temppath = tempdir.path().to_cstring().unwrap(); let file_name = "test"; { let mount_point = TempDir::new("nix-test_mount") .unwrap_or_else(|e| panic!("tempdir failed: {}", e)); + let mount_path = mount_point.path().to_cstring().unwrap(); - mount(Some(tempdir.path()), - mount_point.path(), + mount(Some(&temppath), + &mount_path, NONE, MS_BIND, NONE) @@ -156,7 +165,7 @@ exit 23"; .and_then(|mut f| f.write(SCRIPT_CONTENTS)) .unwrap_or_else(|e| panic!("write failed: {}", e)); - umount(mount_point.path()).unwrap_or_else(|e| panic!("umount failed: {}", e)); + umount(&mount_path).unwrap_or_else(|e| panic!("umount failed: {}", e)); } // Verify the file written in the mount shows up in source directory, even diff --git a/test/test_mq.rs b/test/test_mq.rs index 2d7a895594..97fd9e6a4c 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -4,7 +4,6 @@ use nix::mqueue::{O_CREAT, O_WRONLY, O_RDONLY, O_NONBLOCK}; use nix::mqueue::MqAttr; use nix::sys::stat::{S_IWUSR, S_IRUSR, S_IRGRP, S_IROTH}; -use std::ffi::CString; use std::str; use libc::c_long; @@ -12,16 +11,15 @@ use nix::unistd::{fork, read, write, pipe}; use nix::unistd::Fork::{Child, Parent}; use nix::sys::wait::*; use nix::errno::Errno::*; -use nix::Error::Sys; #[test] fn test_mq_send_and_receive() { const MSG_SIZE: c_long = 32; let attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name_in_parent = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); + let mq_name_in_parent = cstr!("/a_nix_test_queue"); let mqd_in_parent = mq_open(mq_name_in_parent, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap(); - let msg_to_send = &CString::new("msg_1").unwrap(); + let msg_to_send = b"msg_1"; mq_send(mqd_in_parent, msg_to_send, 1).unwrap(); @@ -30,7 +28,7 @@ fn test_mq_send_and_receive() { let pid = fork(); match pid { Ok(Child) => { - let mq_name_in_child = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap(); + let mq_name_in_child = cstr!("/a_nix_test_queue"); let mqd_in_child = mq_open(mq_name_in_child, O_CREAT | O_RDONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap(); let mut buf = [0u8; 32]; mq_receive(mqd_in_child, &mut buf, 1).unwrap(); @@ -58,7 +56,7 @@ fn test_mq_send_and_receive() { fn test_mq_getattr() { const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new("/attr_test_get_attr".as_bytes().as_ref()).unwrap(); + let mq_name = cstr!("/attr_test_get_attr"); let mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &initial_attr).unwrap(); let read_attr = mq_getattr(mqd); assert!(read_attr.unwrap() == initial_attr); @@ -69,7 +67,7 @@ fn test_mq_getattr() { fn test_mq_setattr() { const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new("/attr_test_get_attr".as_bytes().as_ref()).unwrap(); + let mq_name = cstr!("/attr_test_get_attr"); let mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &initial_attr).unwrap(); let new_attr = MqAttr::new(0, 20, MSG_SIZE * 2, 100); @@ -95,7 +93,7 @@ fn test_mq_setattr() { fn test_mq_set_nonblocking() { const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name = &CString::new("/attr_test_get_attr".as_bytes().as_ref()).unwrap(); + let mq_name = cstr!("/attr_test_get_attr"); let mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &initial_attr).unwrap(); mq_set_nonblock(mqd).unwrap(); let new_attr = mq_getattr(mqd); @@ -110,18 +108,18 @@ fn test_mq_set_nonblocking() { fn test_mq_unlink() { const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); - let mq_name_opened = &CString::new("/mq_unlink_test".as_bytes().as_ref()).unwrap(); - let mq_name_not_opened = &CString::new("/mq_unlink_test".as_bytes().as_ref()).unwrap(); + let mq_name_opened = cstr!("/mq_unlink_test"); + let mq_name_not_opened = cstr!("/mq_unlink_test"); let mqd = mq_open(mq_name_opened, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &initial_attr).unwrap(); let res_unlink = mq_unlink(mq_name_opened); assert!(res_unlink == Ok(()) ); let res_unlink_not_opened = mq_unlink(mq_name_not_opened); - assert!(res_unlink_not_opened == Err(Sys(ENOENT)) ); + assert!(res_unlink_not_opened == Err(ENOENT) ); mq_close(mqd).unwrap(); let res_unlink_after_close = mq_unlink(mq_name_opened); - assert!(res_unlink_after_close == Err(Sys(ENOENT)) ); + assert!(res_unlink_after_close == Err(ENOENT) ); } diff --git a/test/test_net.rs b/test/test_net.rs index acdaf47a86..8671866731 100644 --- a/test/test_net.rs +++ b/test/test_net.rs @@ -1,12 +1,13 @@ use nix::net::if_::*; - -#[cfg(target_os = "linux")] -const LOOPBACK: &'static [u8] = b"lo"; - -#[cfg(not(target_os = "linux"))] -const LOOPBACK: &'static [u8] = b"lo0"; +use std::ffi::CStr; #[test] fn test_if_nametoindex() { - assert!(if_nametoindex(&LOOPBACK[..]).is_ok()); + #[cfg(target_os = "linux")] + fn loopback_name() -> &'static CStr { cstr!("lo") } + + #[cfg(not(target_os = "linux"))] + fn loopback_name() -> &'static CStr { cstr!("lo0") } + + assert!(if_nametoindex(loopback_name()).is_ok()); } diff --git a/test/test_stat.rs b/test/test_stat.rs index 4b22c29640..23fcdb33fc 100644 --- a/test/test_stat.rs +++ b/test/test_stat.rs @@ -1,12 +1,12 @@ use std::fs::File; use std::os::unix::fs::symlink; use std::os::unix::prelude::AsRawFd; - use libc::{S_IFMT, S_IFLNK}; use nix::sys::stat::{stat, fstat, lstat}; use nix::sys::stat::FileStat; +use nix::cstr::ToCString; use nix::Result; use tempdir::TempDir; @@ -67,7 +67,7 @@ fn test_stat_and_fstat() { let filename = tempdir.path().join("foo.txt"); let file = File::create(&filename).unwrap(); - let stat_result = stat(&filename); + let stat_result = stat(filename.to_cstring().unwrap()); assert_stat_results(stat_result); let fstat_result = fstat(file.as_raw_fd()); @@ -86,10 +86,10 @@ fn test_stat_fstat_lstat() { // should be the same result as calling stat, // since it's a regular file - let stat_result = lstat(&filename); + let stat_result = lstat(filename.to_cstring().unwrap()); assert_stat_results(stat_result); - let lstat_result = lstat(&linkname); + let lstat_result = lstat(linkname.to_cstring().unwrap()); assert_lstat_results(lstat_result); let fstat_result = fstat(link.as_raw_fd()); diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 510f8f6c3b..f0de782fde 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -55,7 +55,7 @@ fn test_getpid() { } macro_rules! execve_test_factory( - ($test_name:ident, $syscall:ident, $unix_sh:expr, $android_sh:expr) => ( + ($test_name:ident, $syscall:ident, $sh:expr) => ( #[test] fn $test_name() { // The `exec`d process will write to `writer`, and we'll read that @@ -64,25 +64,18 @@ macro_rules! execve_test_factory( match fork().unwrap() { Child => { - #[cfg(not(target_os = "android"))] - const SH_PATH: &'static [u8] = $unix_sh; - - #[cfg(target_os = "android")] - const SH_PATH: &'static [u8] = $android_sh; - // Close stdout. close(1).unwrap(); // Make `writer` be the stdout of the new process. dup(writer).unwrap(); // exec! $syscall( - &CString::new(SH_PATH).unwrap(), - &[CString::new(b"".as_ref()).unwrap(), - CString::new(b"-c".as_ref()).unwrap(), - CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz" - .as_ref()).unwrap()], - &[CString::new(b"foo=bar".as_ref()).unwrap(), - CString::new(b"baz=quux".as_ref()).unwrap()]).unwrap(); + cstr!($sh), + &[CString::new(&""[..]).unwrap(), + CString::new(&"-c"[..]).unwrap(), + CString::new(&"echo nix!!! && echo foo=$foo && echo baz=$baz"[..]).unwrap()], + &[CString::new(&"foo=bar"[..]).unwrap(), + CString::new(&"baz=quux"[..]).unwrap()]).unwrap(); }, Parent(child_pid) => { // Wait for the child to exit. @@ -101,8 +94,11 @@ macro_rules! execve_test_factory( ) ); -execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh"); +#[cfg(not(target_os = "android"))] +execve_test_factory!(test_execve, execve, "/bin/sh"); +#[cfg(target_os = "android")] +execve_test_factory!(test_execve, execve, "/system/bin/sh"); #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(feature = "execvpe")] -execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh"); +execve_test_factory!(test_execvpe, execvpe, "sh");