From ca035734df2e3dfeb866cbfee51de7b582be83f5 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Sat, 8 Dec 2018 13:47:33 -0700 Subject: [PATCH 1/4] Replace try! with ? try! is not available in Rust 2018 --- src/fcntl.rs | 16 ++++++------ src/mount.rs | 12 ++++----- src/mqueue.rs | 4 +-- src/net/if_.rs | 2 +- src/sys/mman.rs | 8 +++--- src/sys/quota.rs | 14 +++++----- src/sys/signal.rs | 4 +-- src/sys/signalfd.rs | 2 +- src/sys/socket/addr.rs | 8 +++--- src/sys/socket/mod.rs | 10 ++++---- src/sys/socket/sockopt.rs | 2 +- src/sys/stat.rs | 24 ++++++++--------- src/sys/statfs.rs | 4 +-- src/sys/statvfs.rs | 6 ++--- src/sys/termios.rs | 2 +- src/sys/time.rs | 22 ++++++++-------- src/sys/wait.rs | 11 ++++---- src/unistd.rs | 54 +++++++++++++++++++-------------------- 18 files changed, 101 insertions(+), 104 deletions(-) diff --git a/src/fcntl.rs b/src/fcntl.rs index 5942506be4..a763c10f9a 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -139,17 +139,17 @@ libc_bitflags!( ); pub fn open(path: &P, oflag: OFlag, mode: Mode) -> Result { - let fd = try!(path.with_nix_path(|cstr| { + let fd = path.with_nix_path(|cstr| { unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } - })); + })?; Errno::result(fd) } pub fn openat(dirfd: RawFd, path: &P, oflag: OFlag, mode: Mode) -> Result { - let fd = try!(path.with_nix_path(|cstr| { + let fd = path.with_nix_path(|cstr| { unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) } - })); + })?; Errno::result(fd) } @@ -167,18 +167,18 @@ fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> { } pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) } - })); + })?; wrap_readlink_result(buffer, res) } pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) } - })); + })?; wrap_readlink_result(buffer, res) } diff --git a/src/mount.rs b/src/mount.rs index 8fe995135c..72b719d7a4 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -63,7 +63,7 @@ pub fn mount) -> Result<()> { use libc; - let res = try!(try!(try!(try!( + let res = source.with_nix_path(|source| { target.with_nix_path(|target| { fstype.with_nix_path(|fstype| { @@ -78,23 +78,23 @@ pub fn mount(target: &P) -> Result<()> { - let res = try!(target.with_nix_path(|cstr| { + let res = target.with_nix_path(|cstr| { unsafe { libc::umount(cstr.as_ptr()) } - })); + })?; Errno::result(res).map(drop) } pub fn umount2(target: &P, flags: MntFlags) -> Result<()> { - let res = try!(target.with_nix_path(|cstr| { + let res = target.with_nix_path(|cstr| { unsafe { libc::umount2(cstr.as_ptr(), flags.bits) } - })); + })?; Errno::result(res).map(drop) } diff --git a/src/mqueue.rs b/src/mqueue.rs index 0c6990f663..87be65321b 100644 --- a/src/mqueue.rs +++ b/src/mqueue.rs @@ -152,7 +152,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result { /// Sets the `O_NONBLOCK` attribute for a given message queue descriptor /// Returns the old attributes pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> { - let oldattr = try!(mq_getattr(mqd)); + let oldattr = mq_getattr(mqd)?; let newattr = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, oldattr.mq_attr.mq_maxmsg, oldattr.mq_attr.mq_msgsize, @@ -164,7 +164,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> { /// Removes `O_NONBLOCK` attribute for a given message queue descriptor /// Returns the old attributes pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> { - let oldattr = try!(mq_getattr(mqd)); + let oldattr = mq_getattr(mqd)?; let newattr = MqAttr::new(0, oldattr.mq_attr.mq_maxmsg, oldattr.mq_attr.mq_msgsize, diff --git a/src/net/if_.rs b/src/net/if_.rs index 714eac7750..58d677ae34 100644 --- a/src/net/if_.rs +++ b/src/net/if_.rs @@ -9,7 +9,7 @@ use {Result, Error, NixPath}; /// 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()) })); + let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?; if if_index == 0 { Err(Error::last()) diff --git a/src/sys/mman.rs b/src/sys/mman.rs index 48b5767e95..a30629db5f 100644 --- a/src/sys/mman.rs +++ b/src/sys/mman.rs @@ -264,7 +264,7 @@ pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result #[cfg(not(target_os = "android"))] pub fn shm_open(name: &P, flag: OFlag, mode: Mode) -> Result { - let ret = try!(name.with_nix_path(|cstr| { + let ret = name.with_nix_path(|cstr| { #[cfg(any(target_os = "macos", target_os = "ios"))] unsafe { libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint) @@ -273,16 +273,16 @@ pub fn shm_open(name: &P, flag: OFlag, mode: Mode) -> Resul unsafe { libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t) } - })); + })?; Errno::result(ret) } #[cfg(not(target_os = "android"))] pub fn shm_unlink(name: &P) -> Result<()> { - let ret = try!(name.with_nix_path(|cstr| { + let ret = name.with_nix_path(|cstr| { unsafe { libc::shm_unlink(cstr.as_ptr()) } - })); + })?; Errno::result(ret).map(drop) } diff --git a/src/sys/quota.rs b/src/sys/quota.rs index b4cac1dc9b..14c0462929 100644 --- a/src/sys/quota.rs +++ b/src/sys/quota.rs @@ -231,12 +231,10 @@ impl Dqblk { fn quotactl(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> { unsafe { Errno::clear(); - let res = try!( - match special { - Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)), - None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)), - } - ); + let res = match special { + Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)), + None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)), + }?; Errno::result(res).map(drop) } @@ -244,11 +242,11 @@ fn quotactl(cmd: QuotaCmd, special: Option<&P>, id: c_int, /// Turn on disk quotas for a block device. pub fn quotactl_on(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> { - try!(quota_file.with_nix_path(|path| { + 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(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p) - })) + })? } /// Disable disk quotas for a block device. diff --git a/src/sys/signal.rs b/src/sys/signal.rs index c9826d7276..7135b7334f 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -413,7 +413,7 @@ impl SigSet { /// Gets the currently blocked (masked) set of signals for the calling thread. pub fn thread_get_mask() -> Result { let mut oldmask: SigSet = unsafe { mem::uninitialized() }; - try!(pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))); + pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?; Ok(oldmask) } @@ -435,7 +435,7 @@ impl SigSet { /// Sets the set of signals as the signal mask, and returns the old mask. pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result { let mut oldmask: SigSet = unsafe { mem::uninitialized() }; - try!(pthread_sigmask(how, Some(self), Some(&mut oldmask))); + pthread_sigmask(how, Some(self), Some(&mut oldmask))?; Ok(oldmask) } diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index 65c09ea4cf..5425a27be9 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -88,7 +88,7 @@ impl SignalFd { } pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result { - let fd = try!(signalfd(SIGNALFD_NEW, mask, flags)); + let fd = signalfd(SIGNALFD_NEW, mask, flags)?; Ok(SignalFd(fd)) } diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index ebd32c1f5d..b2cafe3c1f 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -600,7 +600,7 @@ 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| { + path.with_nix_path(|cstr| { unsafe { let mut ret = libc::sockaddr_un { sun_family: AddressFamily::Unix as sa_family_t, @@ -619,7 +619,7 @@ impl UnixAddr { Ok(UnixAddr(ret, bytes.len())) } - })) + })? } /// Create a new `sockaddr_un` representing an address in the "abstract namespace". @@ -759,7 +759,7 @@ impl SockAddr { } pub fn new_unix(path: &P) -> Result { - Ok(SockAddr::Unix(try!(UnixAddr::new(path)))) + Ok(SockAddr::Unix(UnixAddr::new(path)?)) } #[cfg(any(target_os = "android", target_os = "linux"))] @@ -1079,7 +1079,7 @@ pub mod sys_control { ctl_name[..name.len()].clone_from_slice(name.as_bytes()); let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name }; - unsafe { try!(ctl_info(sockfd, &mut info)); } + unsafe { ctl_info(sockfd, &mut info)?; } Ok(SysControlAddr::new(info.ctl_id, unit)) } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 85acaf4cfb..2ac0e24a41 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -750,7 +750,7 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<& }; Ok(unsafe { RecvMsg { - bytes: try!(Errno::result(ret)) as usize, + bytes: Errno::result(ret)? as usize, cmsg_buffer, address: sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok(), @@ -890,13 +890,13 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> { let addr: sockaddr_storage = mem::zeroed(); let mut len = mem::size_of::() as socklen_t; - let ret = try!(Errno::result(libc::recvfrom( + let ret = Errno::result(libc::recvfrom( sockfd, buf.as_ptr() as *mut c_void, buf.len() as size_t, 0, mem::transmute(&addr), - &mut len as *mut socklen_t))); + &mut len as *mut socklen_t))?; sockaddr_storage_to_addr(&addr, len as usize) .map(|addr| (ret as usize, addr)) @@ -1004,7 +1004,7 @@ pub fn getpeername(fd: RawFd) -> Result { let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len); - try!(Errno::result(ret)); + Errno::result(ret)?; sockaddr_storage_to_addr(&addr, len as usize) } @@ -1020,7 +1020,7 @@ pub fn getsockname(fd: RawFd) -> Result { let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len); - try!(Errno::result(ret)); + Errno::result(ret)?; sockaddr_storage_to_addr(&addr, len as usize) } diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 17119384d4..f166d997f0 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -89,7 +89,7 @@ macro_rules! getsockopt_impl { let res = libc::getsockopt(fd, $level, $flag, getter.ffi_ptr(), getter.ffi_len()); - try!(Errno::result(res)); + Errno::result(res)?; Ok(getter.unwrap()) } diff --git a/src/sys/stat.rs b/src/sys/stat.rs index f3a2e7e38d..e03678599e 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -43,11 +43,11 @@ libc_bitflags! { } pub fn mknod(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev) } - })); + })?; Errno::result(res).map(drop) } @@ -79,26 +79,26 @@ pub fn umask(mode: Mode) -> Mode { pub fn stat(path: &P) -> Result { let mut dst = unsafe { mem::uninitialized() }; - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat) } - })); + })?; - try!(Errno::result(res)); + Errno::result(res)?; Ok(dst) } pub fn lstat(path: &P) -> Result { let mut dst = unsafe { mem::uninitialized() }; - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat) } - })); + })?; - try!(Errno::result(res)); + Errno::result(res)?; Ok(dst) } @@ -107,18 +107,18 @@ pub fn fstat(fd: RawFd) -> Result { let mut dst = unsafe { mem::uninitialized() }; let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) }; - try!(Errno::result(res)); + Errno::result(res)?; Ok(dst) } pub fn fstatat(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result { let mut dst = unsafe { mem::uninitialized() }; - let res = try!(pathname.with_nix_path(|cstr| { + let res = pathname.with_nix_path(|cstr| { unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) } - })); + })?; - try!(Errno::result(res)); + Errno::result(res)?; Ok(dst) } diff --git a/src/sys/statfs.rs b/src/sys/statfs.rs index 6d4fafe968..e7ffae5e4e 100644 --- a/src/sys/statfs.rs +++ b/src/sys/statfs.rs @@ -6,9 +6,7 @@ use libc; pub fn statfs(path: &P, stat: &mut libc::statfs) -> Result<()> { unsafe { Errno::clear(); - let res = try!( - path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat)) - ); + let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat))?; Errno::result(res).map(drop) } diff --git a/src/sys/statvfs.rs b/src/sys/statvfs.rs index 845ae0dbd5..de69ae51f8 100644 --- a/src/sys/statvfs.rs +++ b/src/sys/statvfs.rs @@ -126,9 +126,9 @@ pub fn statvfs(path: &P) -> Result { unsafe { Errno::clear(); let mut stat: Statvfs = mem::uninitialized(); - let res = try!( - path.with_nix_path(|path| libc::statvfs(path.as_ptr(), &mut stat.0)) - ); + let res = path.with_nix_path(|path| + libc::statvfs(path.as_ptr(), &mut stat.0) + )?; Errno::result(res).map(|_| stat) } diff --git a/src/sys/termios.rs b/src/sys/termios.rs index 8a99c1ab47..d8815baa00 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -1050,7 +1050,7 @@ pub fn tcgetattr(fd: RawFd) -> Result { let res = unsafe { libc::tcgetattr(fd, &mut termios) }; - try!(Errno::result(res)); + Errno::result(res)?; Ok(termios.into()) } diff --git a/src/sys/time.rs b/src/sys/time.rs index e300cfe7d5..9671f5310a 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -235,20 +235,20 @@ impl fmt::Display for TimeSpec { let sec = abs.tv_sec(); - try!(write!(f, "{}", sign)); + write!(f, "{}", sign)?; if abs.tv_nsec() == 0 { if abs.tv_sec() == 1 { - try!(write!(f, "{} second", sec)); + write!(f, "{} second", sec)?; } else { - try!(write!(f, "{} seconds", sec)); + write!(f, "{} seconds", sec)?; } } else if abs.tv_nsec() % 1_000_000 == 0 { - try!(write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)); + write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?; } else if abs.tv_nsec() % 1_000 == 0 { - try!(write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)); + write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?; } else { - try!(write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())); + write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?; } Ok(()) @@ -449,18 +449,18 @@ impl fmt::Display for TimeVal { let sec = abs.tv_sec(); - try!(write!(f, "{}", sign)); + write!(f, "{}", sign)?; if abs.tv_usec() == 0 { if abs.tv_sec() == 1 { - try!(write!(f, "{} second", sec)); + write!(f, "{} second", sec)?; } else { - try!(write!(f, "{} seconds", sec)); + write!(f, "{} seconds", sec)?; } } else if abs.tv_usec() % 1000 == 0 { - try!(write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)); + write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?; } else { - try!(write!(f, "{}.{:06} seconds", sec, abs.tv_usec())); + write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?; } Ok(()) diff --git a/src/sys/wait.rs b/src/sys/wait.rs index 038354b107..3f99757daf 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -181,7 +181,7 @@ impl WaitStatus { Ok(if exited(status) { WaitStatus::Exited(pid, exit_status(status)) } else if signaled(status) { - WaitStatus::Signaled(pid, try!(term_signal(status)), dumped_core(status)) + WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status)) } else if stopped(status) { cfg_if! { if #[cfg(any(target_os = "android", target_os = "linux"))] { @@ -190,14 +190,15 @@ impl WaitStatus { Ok(if syscall_stop(status) { WaitStatus::PtraceSyscall(pid) } else if status_additional == 0 { - WaitStatus::Stopped(pid, try!(stop_signal(status))) + WaitStatus::Stopped(pid, stop_signal(status)?) } else { - WaitStatus::PtraceEvent(pid, try!(stop_signal(status)), stop_additional(status)) + WaitStatus::PtraceEvent(pid, stop_signal(status)?, + stop_additional(status)) }) } } else { fn decode_stopped(pid: Pid, status: i32) -> Result { - Ok(WaitStatus::Stopped(pid, try!(stop_signal(status)))) + Ok(WaitStatus::Stopped(pid, stop_signal(status)?)) } } } @@ -227,7 +228,7 @@ pub fn waitpid>>(pid: P, options: Option) -> Re ) }; - match try!(Errno::result(res)) { + match Errno::result(res)? { 0 => Ok(StillAlive), res => WaitStatus::from_raw(Pid::from_raw(res), status), } diff --git a/src/unistd.rs b/src/unistd.rs index 07f1e6fdb5..f2ad55b2f1 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -384,7 +384,7 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { return Err(Error::Sys(Errno::EINVAL)); } - let fd = try!(dup2(oldfd, newfd)); + let fd = dup2(oldfd, newfd)?; if flags.contains(OFlag::O_CLOEXEC) { if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) { @@ -403,9 +403,9 @@ fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result { /// pages for additional details on possible failure cases. #[inline] pub fn chdir(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::chdir(cstr.as_ptr()) } - })); + })?; Errno::result(res).map(drop) } @@ -456,9 +456,9 @@ pub fn fchdir(dirfd: RawFd) -> Result<()> { /// ``` #[inline] pub fn mkdir(path: &P, mode: Mode) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) } - })); + })?; Errno::result(res).map(drop) } @@ -499,9 +499,9 @@ pub fn mkdir(path: &P, mode: Mode) -> Result<()> { /// ``` #[inline] pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) } - })); + })?; Errno::result(res).map(drop) } @@ -576,10 +576,10 @@ fn chown_raw_ids(owner: Option, group: Option) -> (libc::uid_t, libc:: /// only if `Some` owner/group is provided. #[inline] pub fn chown(path: &P, owner: Option, group: Option) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { let (uid, gid) = chown_raw_ids(owner, group); unsafe { libc::chown(cstr.as_ptr(), uid, gid) } - })); + })?; Errno::result(res).map(drop) } @@ -977,7 +977,7 @@ pub fn pipe() -> Result<(RawFd, RawFd)> { let res = libc::pipe(fds.as_mut_ptr()); - try!(Errno::result(res)); + Errno::result(res)?; Ok((fds[0], fds[1])) } @@ -1004,7 +1004,7 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) }; - try!(Errno::result(res)); + Errno::result(res)?; Ok((fds[0], fds[1])) } @@ -1026,9 +1026,9 @@ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> { let res = unsafe { libc::pipe(fds.as_mut_ptr()) }; - try!(Errno::result(res)); + Errno::result(res)?; - try!(pipe2_setflags(fds[0], fds[1], flags)); + pipe2_setflags(fds[0], fds[1], flags)?; Ok((fds[0], fds[1])) } @@ -1067,11 +1067,11 @@ fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> { /// See also /// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html) pub fn truncate(path: &P, len: off_t) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::truncate(cstr.as_ptr(), len) } - })); + })?; Errno::result(res).map(drop) } @@ -1105,19 +1105,19 @@ pub fn isatty(fd: RawFd) -> Result { /// /// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html) pub fn unlink(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::unlink(cstr.as_ptr()) } - })); + })?; Errno::result(res).map(drop) } #[inline] pub fn chroot(path: &P) -> Result<()> { - let res = try!(path.with_nix_path(|cstr| { + let res = path.with_nix_path(|cstr| { unsafe { libc::chroot(cstr.as_ptr()) } - })); + })?; Errno::result(res).map(drop) } @@ -1553,9 +1553,9 @@ pub mod acct { /// /// See also [acct(2)](https://linux.die.net/man/2/acct) pub fn enable(filename: &P) -> Result<()> { - let res = try!(filename.with_nix_path(|cstr| { + let res = filename.with_nix_path(|cstr| { unsafe { libc::acct(cstr.as_ptr()) } - })); + })?; Errno::result(res).map(drop) } @@ -1594,13 +1594,13 @@ pub mod acct { /// ``` #[inline] pub fn mkstemp(template: &P) -> Result<(RawFd, PathBuf)> { - let mut path = try!(template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})); + let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?; let p = path.as_mut_ptr() as *mut _; let fd = unsafe { libc::mkstemp(p) }; let last = path.pop(); // drop the trailing nul debug_assert!(last == Some(b'\0')); let pathname = OsString::from_vec(path); - try!(Errno::result(fd)); + Errno::result(fd)?; Ok((fd, PathBuf::from(pathname))) } @@ -1761,12 +1761,12 @@ pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result> { /// unsupported (for option variables) /// - `Err(x)`: an error occurred pub fn pathconf(path: &P, var: PathconfVar) -> Result> { - let raw = try!(path.with_nix_path(|cstr| { + let raw = path.with_nix_path(|cstr| { unsafe { Errno::clear(); libc::pathconf(cstr.as_ptr(), var as c_int) } - })); + })?; if raw == -1 { if errno::errno() == 0 { Ok(None) @@ -2228,13 +2228,13 @@ mod pivot_root { pub fn pivot_root( new_root: &P1, put_old: &P2) -> Result<()> { - let res = try!(try!(new_root.with_nix_path(|new_root| { + let res = new_root.with_nix_path(|new_root| { put_old.with_nix_path(|put_old| { unsafe { libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr()) } }) - }))); + })??; Errno::result(res).map(drop) } From 98ac44103601cdf0578f868e12f3090051dabe5f Mon Sep 17 00:00:00 2001 From: oblique Date: Tue, 11 Dec 2018 23:32:09 +0200 Subject: [PATCH 2/4] Implement symlinkat --- CHANGELOG.md | 2 ++ src/unistd.rs | 28 ++++++++++++++++++++++++++++ test/test_unistd.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f89e499876..8e8135b580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ([#972](https://github.com/nix-rust/nix/pull/972)) - Added option `TCP_CONGESTION` in `setsockopt`. ([#972](https://github.com/nix-rust/nix/pull/972)) +- Added `symlinkat` wrapper. + ([#997](https://github.com/nix-rust/nix/pull/997)) ### Changed ### Fixed diff --git a/src/unistd.rs b/src/unistd.rs index f2ad55b2f1..2c00f7f036 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -506,6 +506,34 @@ pub fn mkfifo(path: &P, mode: Mode) -> Result<()> { Errno::result(res).map(drop) } +/// Creates a symbolic link at `path2` which points to `path1`. +/// +/// If `dirfd` has a value, then `path2` is relative to directory associated +/// with the file descriptor. +/// +/// If `dirfd` is `None`, then `path2` is relative to the current working +/// directory. This is identical to `libc::symlink(path1, path2)`. +/// +/// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html). +pub fn symlinkat( + path1: &P1, + dirfd: Option, + path2: &P2) -> Result<()> { + let res = + path1.with_nix_path(|path1| { + path2.with_nix_path(|path2| { + unsafe { + libc::symlinkat( + path1.as_ptr(), + dirfd.unwrap_or(libc::AT_FDCWD), + path2.as_ptr() + ) + } + }) + })??; + Errno::result(res).map(drop) +} + /// Returns the current directory as a `PathBuf` /// /// Err is returned if the current user doesn't have the permission to read or search a component diff --git a/test/test_unistd.rs b/test/test_unistd.rs index a4bb92eb52..8b3732787f 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -1,4 +1,4 @@ -use nix::fcntl::{fcntl, FcntlArg, FdFlag, open, OFlag}; +use nix::fcntl::{fcntl, FcntlArg, FdFlag, open, OFlag, readlink}; use nix::unistd::*; use nix::unistd::ForkResult::*; use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction}; @@ -543,3 +543,29 @@ fn test_canceling_alarm() { assert_eq!(alarm::set(60), None); assert_eq!(alarm::cancel(), Some(60)); } + +#[test] +fn test_symlinkat() { + let mut buf = [0; 1024]; + let tempdir = tempfile::tempdir().unwrap(); + + let target = tempdir.path().join("a"); + let linkpath = tempdir.path().join("b"); + symlinkat(&target, None, &linkpath).unwrap(); + assert_eq!( + readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(), + target.to_str().unwrap() + ); + + let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap(); + let target = "c"; + let linkpath = "d"; + symlinkat(target, Some(dirfd), linkpath).unwrap(); + assert_eq!( + readlink(&tempdir.path().join(linkpath), &mut buf) + .unwrap() + .to_str() + .unwrap(), + target + ); +} From 940a8de7b986bf67a4cdc2eb18062104f7af26ab Mon Sep 17 00:00:00 2001 From: Tom Pusateri Date: Tue, 4 Dec 2018 00:58:47 -0500 Subject: [PATCH 3/4] Add cmsg PKTINFO for IPv4 and IPv6. ignore pktinfo tests on qemu mips,mips64,powerpc64 Original work by @mcginty. --- CHANGELOG.md | 2 + src/sys/socket/mod.rs | 128 ++++++++++++++++++++- src/sys/socket/sockopt.rs | 16 +++ test/sys/test_socket.rs | 235 +++++++++++++++++++++++++++++++++++++- 4 files changed, 374 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f89e499876..88e41a5290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS. + ([#990](https://github.com/nix-rust/nix/pull/990)) ### Added - Added support of CString type in `setsockopt`. ([#972](https://github.com/nix-rust/nix/pull/972)) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 85acaf4cfb..ab5c18d7fc 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -28,7 +28,7 @@ pub use self::addr::{ Ipv6Addr, LinkAddr, }; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "android", target_os = "linux"))] pub use ::sys::socket::addr::netlink::NetlinkAddr; pub use libc::{ @@ -153,7 +153,7 @@ libc_bitflags!{ /// This flag specifies that queued errors should be received from /// the socket error queue. (For more details, see /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom)) - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] MSG_ERRQUEUE; /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain /// file descriptor using the `SCM_RIGHTS` operation (described in @@ -526,6 +526,23 @@ pub enum ControlMessage<'a> { /// nix::unistd::close(in_socket).unwrap(); /// ``` ScmTimestamp(&'a TimeVal), + + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + Ipv4PacketInfo(&'a libc::in_pktinfo), + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + Ipv6PacketInfo(&'a libc::in6_pktinfo), + /// Catch-all variant for unimplemented cmsg types. #[doc(hidden)] Unknown(UnknownCmsg<'a>), @@ -565,12 +582,57 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmTimestamp(t) => { mem::size_of_val(t) }, + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv4PacketInfo(pktinfo) => { + mem::size_of_val(pktinfo) + }, + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv6PacketInfo(pktinfo) => { + mem::size_of_val(pktinfo) + }, ControlMessage::Unknown(UnknownCmsg(_, bytes)) => { mem::size_of_val(bytes) } } } + /// Returns the value to put into the `cmsg_level` field of the header. + fn cmsg_level(&self) -> libc::c_int { + match *self { + ControlMessage::ScmRights(_) => libc::SOL_SOCKET, + #[cfg(any(target_os = "android", target_os = "linux"))] + ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET, + ControlMessage::ScmTimestamp(_) => libc::SOL_SOCKET, + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP, + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6, + ControlMessage::Unknown(ref cmsg) => cmsg.0.cmsg_level, + } + } + /// Returns the value to put into the `cmsg_type` field of the header. fn cmsg_type(&self) -> libc::c_int { match *self { @@ -578,6 +640,21 @@ impl<'a> ControlMessage<'a> { #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS, ControlMessage::ScmTimestamp(_) => libc::SCM_TIMESTAMP, + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO, + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO, ControlMessage::Unknown(ref cmsg) => cmsg.0.cmsg_type, } } @@ -598,7 +675,7 @@ impl<'a> ControlMessage<'a> { } else { let cmsg = cmsghdr { cmsg_len: self.len() as _, - cmsg_level: libc::SOL_SOCKET, + cmsg_level: self.cmsg_level(), cmsg_type: self.cmsg_type(), ..mem::zeroed() // zero out platform-dependent padding fields }; @@ -615,10 +692,29 @@ impl<'a> ControlMessage<'a> { #[cfg(any(target_os = "android", target_os = "linux"))] ControlMessage::ScmCredentials(creds) => { copy_bytes(creds, buf) - } + }, ControlMessage::ScmTimestamp(t) => { copy_bytes(t, buf) }, + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv4PacketInfo(pktinfo) => { + copy_bytes(pktinfo, buf) + }, + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + ControlMessage::Ipv6PacketInfo(pktinfo) => { + copy_bytes(pktinfo, buf) + } ControlMessage::Unknown(_) => unreachable!(), } }; @@ -650,6 +746,28 @@ impl<'a> ControlMessage<'a> { ControlMessage::ScmTimestamp( &*(data.as_ptr() as *const _)) }, + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { + ControlMessage::Ipv6PacketInfo( + &*(data.as_ptr() as *const _)) + } + #[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" + ))] + (libc::IPPROTO_IP, libc::IP_PKTINFO) => { + ControlMessage::Ipv4PacketInfo( + &*(data.as_ptr() as *const _)) + } + (_, _) => { ControlMessage::Unknown(UnknownCmsg(header, data)) } @@ -1055,7 +1173,7 @@ pub unsafe fn sockaddr_storage_to_addr( let pathlen = len - offset_of!(sockaddr_un, sun_path); Ok(SockAddr::Unix(UnixAddr(sun, pathlen))) } - #[cfg(any(target_os = "linux", target_os = "android"))] + #[cfg(any(target_os = "android", target_os = "linux"))] libc::AF_NETLINK => { use libc::sockaddr_nl; Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl)))) diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 17119384d4..96055a9023 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -271,6 +271,22 @@ sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32); sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool); #[cfg(any(target_os = "freebsd", target_os = "linux"))] sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>); +#[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" +))] +sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool); +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" +))] +sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool); + /* * diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 3329417d08..5730fb86d3 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -201,10 +201,10 @@ fn test_scm_rights_single_cmsg_multiple_fds() { } assert!(cmsgs.next().is_none(), "unexpected control msg"); - assert_eq!(iovec[0].as_slice(), [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8]); + assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]); }); - let slice = [1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8]; + let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; let iov = [IoVec::from_slice(&slice)]; let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout let cmsg = [ControlMessage::ScmRights(&fds)]; @@ -451,3 +451,234 @@ pub fn test_syscontrol() { // requires root privileges // connect(fd, &sockaddr).expect("connect failed"); } + +#[cfg(any( + target_os = "android", + target_os = "ios", + target_os = "linux", + target_os = "macos" +))] +// qemu doesn't seem to be emulating this correctly in these architectures +#[cfg_attr(any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "powerpc64", +), ignore)] +#[test] +pub fn test_recv_ipv4pktinfo() { + use libc; + use nix::ifaddrs::{getifaddrs, InterfaceAddress}; + use nix::net::if_::*; + use nix::sys::socket::sockopt::Ipv4PacketInfo; + use nix::sys::socket::{bind, AddressFamily, SockFlag, SockType}; + use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr}; + use nix::sys::socket::{recvmsg, sendmsg, CmsgSpace, ControlMessage, MsgFlags}; + use nix::sys::uio::IoVec; + use std::io; + use std::io::Write; + use std::thread; + + fn loopback_v4addr() -> Option { + let addrs = match getifaddrs() { + Ok(iter) => iter, + Err(e) => { + let stdioerr = io::stderr(); + let mut handle = stdioerr.lock(); + writeln!(handle, "getifaddrs: {:?}", e).unwrap(); + return None; + }, + }; + for ifaddr in addrs { + if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) { + match ifaddr.address { + Some(SockAddr::Inet(InetAddr::V4(..))) => { + return Some(ifaddr); + } + _ => continue, + } + } + } + None + } + + let lo_ifaddr = loopback_v4addr(); + let (lo_name, lo) = match lo_ifaddr { + Some(ifaddr) => (ifaddr.interface_name, + ifaddr.address.expect("Expect IPv4 address on interface")), + None => return, + }; + let receive = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None, + ).expect("receive socket failed"); + bind(receive, &lo).expect("bind failed"); + let sa = getsockname(receive).expect("getsockname failed"); + setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed"); + + let thread = thread::spawn(move || { + let mut buf = [0u8; 8]; + let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut space = CmsgSpace::::new(); + let msg = recvmsg( + receive, + &iovec, + Some(&mut space), + MsgFlags::empty(), + ).expect("recvmsg failed"); + assert!( + !msg.flags + .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC) + ); + + let mut cmsgs = msg.cmsgs(); + match cmsgs.next() { + Some(ControlMessage::Ipv4PacketInfo(pktinfo)) => { + let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); + assert_eq!( + pktinfo.ipi_ifindex as libc::c_uint, + i, + "unexpected ifindex (expected {}, got {})", + i, + pktinfo.ipi_ifindex + ); + } + _ => (), + } + assert!(cmsgs.next().is_none(), "unexpected additional control msg"); + assert_eq!( + iovec[0].as_slice(), + [1u8, 2, 3, 4, 5, 6, 7, 8] + ); + }); + + let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; + let iov = [IoVec::from_slice(&slice)]; + + let send = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + None, + ).expect("send socket failed"); + sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed"); + + thread.join().unwrap(); +} + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "ios", + target_os = "linux", + target_os = "macos" +))] +// qemu doesn't seem to be emulating this correctly in these architectures +#[cfg_attr(any( + target_arch = "mips", + target_arch = "mips64", + target_arch = "powerpc64", +), ignore)] +#[test] +pub fn test_recv_ipv6pktinfo() { + use libc; + use nix::ifaddrs::{getifaddrs, InterfaceAddress}; + use nix::net::if_::*; + use nix::sys::socket::sockopt::Ipv6RecvPacketInfo; + use nix::sys::socket::{bind, AddressFamily, SockFlag, SockType}; + use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr}; + use nix::sys::socket::{recvmsg, sendmsg, CmsgSpace, ControlMessage, MsgFlags}; + use nix::sys::uio::IoVec; + use std::io; + use std::io::Write; + use std::thread; + + fn loopback_v6addr() -> Option { + let addrs = match getifaddrs() { + Ok(iter) => iter, + Err(e) => { + let stdioerr = io::stderr(); + let mut handle = stdioerr.lock(); + writeln!(handle, "getifaddrs: {:?}", e).unwrap(); + return None; + }, + }; + for ifaddr in addrs { + if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) { + match ifaddr.address { + Some(SockAddr::Inet(InetAddr::V6(..))) => { + return Some(ifaddr); + } + _ => continue, + } + } + } + None + } + + let lo_ifaddr = loopback_v6addr(); + let (lo_name, lo) = match lo_ifaddr { + Some(ifaddr) => (ifaddr.interface_name, + ifaddr.address.expect("Expect IPv4 address on interface")), + None => return, + }; + let receive = socket( + AddressFamily::Inet6, + SockType::Datagram, + SockFlag::empty(), + None, + ).expect("receive socket failed"); + bind(receive, &lo).expect("bind failed"); + let sa = getsockname(receive).expect("getsockname failed"); + setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed"); + + let thread = thread::spawn(move || { + let mut buf = [0u8; 8]; + let iovec = [IoVec::from_mut_slice(&mut buf)]; + let mut space = CmsgSpace::::new(); + let msg = recvmsg( + receive, + &iovec, + Some(&mut space), + MsgFlags::empty(), + ).expect("recvmsg failed"); + assert!( + !msg.flags + .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC) + ); + + let mut cmsgs = msg.cmsgs(); + match cmsgs.next() { + Some(ControlMessage::Ipv6PacketInfo(pktinfo)) => { + let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex"); + assert_eq!( + pktinfo.ipi6_ifindex, + i, + "unexpected ifindex (expected {}, got {})", + i, + pktinfo.ipi6_ifindex + ); + } + _ => (), + } + assert!(cmsgs.next().is_none(), "unexpected additional control msg"); + assert_eq!( + iovec[0].as_slice(), + [1u8, 2, 3, 4, 5, 6, 7, 8] + ); + }); + + let slice = [1u8, 2, 3, 4, 5, 6, 7, 8]; + let iov = [IoVec::from_slice(&slice)]; + + let send = socket( + AddressFamily::Inet6, + SockType::Datagram, + SockFlag::empty(), + None, + ).expect("send socket failed"); + sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed"); + + thread.join().unwrap(); +} From d1395511a653f216f3223c9a64673291ab1a9045 Mon Sep 17 00:00:00 2001 From: Tom Pusateri Date: Wed, 5 Dec 2018 14:26:01 -0500 Subject: [PATCH 4/4] Allow 'cargo test' to complete successfully on NetBSD 8.0. Some tests have been disabled and will need further review. --- src/sys/socket/addr.rs | 3 ++- src/sys/socket/mod.rs | 8 ++++++-- test/sys/test_socket.rs | 3 ++- test/test_mq.rs | 10 +++++++++- test/test_poll.rs | 5 +++-- test/test_stat.rs | 21 +++++++++++++++++++-- test/test_unistd.rs | 7 ++++--- 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs index b2cafe3c1f..db62b00172 100644 --- a/src/sys/socket/addr.rs +++ b/src/sys/socket/addr.rs @@ -497,7 +497,8 @@ impl Eq for Ipv4Addr { impl hash::Hash for Ipv4Addr { fn hash(&self, s: &mut H) { - self.0.s_addr.hash(s) + let saddr = self.0.s_addr; + saddr.hash(s) } } diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 2ac0e24a41..c633512dca 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -258,9 +258,13 @@ impl Eq for IpMembershipRequest {} impl fmt::Debug for IpMembershipRequest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mref = &self.0.imr_multiaddr; + let maddr = mref.s_addr; + let iref = &self.0.imr_interface; + let ifaddr = iref.s_addr; f.debug_struct("IpMembershipRequest") - .field("imr_multiaddr", &self.0.imr_multiaddr.s_addr) - .field("imr_interface", &self.0.imr_interface.s_addr) + .field("imr_multiaddr", &maddr) + .field("imr_interface", &ifaddr) .finish() } } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 3329417d08..08ca653f0e 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -16,8 +16,9 @@ pub fn test_inetv4_addr_to_sock_addr() { InetAddr::V4(addr) => { let ip: u32 = 0x7f00_0001; let port: u16 = 3000; + let saddr = addr.sin_addr.s_addr; - assert_eq!(addr.sin_addr.s_addr, ip.to_be()); + assert_eq!(saddr, ip.to_be()); assert_eq!(addr.sin_port, port.to_be()); } _ => panic!("nope"), diff --git a/test/test_mq.rs b/test/test_mq.rs index 26fd587f92..41ab358b33 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -5,7 +5,7 @@ use std::str; use nix::errno::Errno::*; use nix::Error::Sys; -use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_getattr, mq_setattr, mq_unlink, mq_set_nonblock, mq_remove_nonblock}; +use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive}; use nix::mqueue::{MqAttr, MQ_OFlag}; use nix::sys::stat::Mode; @@ -40,7 +40,9 @@ fn test_mq_send_and_receive() { #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_mq_getattr() { + use nix::mqueue::mq_getattr; const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); @@ -60,8 +62,10 @@ fn test_mq_getattr() { // FIXME: Fix failures for mips in QEMU #[test] +#[cfg(not(any(target_os = "netbsd")))] #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)] fn test_mq_setattr() { + use nix::mqueue::{mq_getattr, mq_setattr}; const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); @@ -95,8 +99,10 @@ fn test_mq_setattr() { // FIXME: Fix failures for mips in QEMU #[test] +#[cfg(not(any(target_os = "netbsd")))] #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)] fn test_mq_set_nonblocking() { + use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock}; const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap(); @@ -118,7 +124,9 @@ fn test_mq_set_nonblocking() { } #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_mq_unlink() { + use nix::mqueue::mq_unlink; const MSG_SIZE: c_long = 32; let initial_attr = MqAttr::new(0, 10, MSG_SIZE, 0); let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap(); diff --git a/test/test_poll.rs b/test/test_poll.rs index a9831ed4ce..23df151790 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -1,6 +1,4 @@ use nix::poll::{EventFlags, poll, PollFd}; -use nix::sys::signal::SigSet; -use nix::sys::time::{TimeSpec, TimeValLike}; use nix::unistd::{write, pipe, close}; #[test] @@ -49,6 +47,9 @@ fn test_poll_debug() { #[test] fn test_ppoll() { use nix::poll::ppoll; + use nix::sys::signal::SigSet; + use nix::sys::time::{TimeSpec, TimeValLike}; + let timeout = TimeSpec::milliseconds(1); let (r, w) = pipe().unwrap(); let mut fds = [PollFd::new(r, EventFlags::POLLIN)]; diff --git a/test/test_stat.rs b/test/test_stat.rs index bd16e635dd..9d27ce7944 100644 --- a/test/test_stat.rs +++ b/test/test_stat.rs @@ -3,13 +3,20 @@ use std::os::unix::fs::symlink; use std::os::unix::prelude::AsRawFd; use std::time::{Duration, UNIX_EPOCH}; +#[cfg(not(any(target_os = "netbsd")))] use libc::{S_IFMT, S_IFLNK}; use nix::fcntl; -use nix::sys::stat::{self, fchmod, fchmodat, fstat, futimens, lstat, lutimes, stat, utimes, utimensat}; -use nix::sys::stat::{FileStat, Mode, FchmodatFlags, UtimensatFlags}; +use nix::sys::stat::{self, fchmod, fchmodat, futimens, lutimes, stat, utimes, utimensat}; +use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags}; + +#[cfg(not(any(target_os = "netbsd")))] +use nix::sys::stat::FileStat; + use nix::sys::time::{TimeSpec, TimeVal, TimeValLike}; use nix::unistd::chdir; + +#[cfg(not(any(target_os = "netbsd")))] use nix::Result; use tempfile; @@ -17,12 +24,14 @@ use tempfile; // uid and gid are signed on Windows, but not on other platforms. This function // allows warning free compiles on all platforms, and can be removed when // expression-level #[allow] is available. +#[cfg(not(any(target_os = "netbsd")))] fn valid_uid_gid(stat: FileStat) -> bool { // uid could be 0 for the `root` user. This quite possible when // the tests are being run on a rooted Android device. stat.st_uid >= 0 && stat.st_gid >= 0 } +#[cfg(not(any(target_os = "netbsd")))] fn assert_stat_results(stat_result: Result) { let stats = stat_result.expect("stat call failed"); assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent @@ -35,6 +44,7 @@ fn assert_stat_results(stat_result: Result) { assert!(stats.st_blocks <= 16); // Up to 16 blocks can be allocated for a blank file } +#[cfg(not(any(target_os = "netbsd")))] fn assert_lstat_results(stat_result: Result) { let stats = stat_result.expect("stat call failed"); assert!(stats.st_dev > 0); // must be positive integer, exact number machine dependent @@ -57,7 +67,10 @@ fn assert_lstat_results(stat_result: Result) { } #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_stat_and_fstat() { + use nix::sys::stat::fstat; + let tempdir = tempfile::tempdir().unwrap(); let filename = tempdir.path().join("foo.txt"); let file = File::create(&filename).unwrap(); @@ -70,6 +83,7 @@ fn test_stat_and_fstat() { } #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_fstatat() { let tempdir = tempfile::tempdir().unwrap(); let filename = tempdir.path().join("foo.txt"); @@ -85,7 +99,10 @@ fn test_fstatat() { } #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_stat_fstat_lstat() { + use nix::sys::stat::{fstat, lstat}; + let tempdir = tempfile::tempdir().unwrap(); let filename = tempdir.path().join("bar.txt"); let linkname = tempdir.path().join("barlink"); diff --git a/test/test_unistd.rs b/test/test_unistd.rs index 8b3732787f..ead4b4874e 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -13,6 +13,7 @@ use tempfile::{self, tempfile}; use libc::{self, _exit, off_t}; #[test] +#[cfg(not(any(target_os = "netbsd")))] fn test_fork_and_waitpid() { let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test"); @@ -230,15 +231,15 @@ cfg_if!{ execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd()); } else if #[cfg(any(target_os = "freebsd", target_os = "linux", - target_os = "netbsd", target_os = "openbsd"))] { execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap()); execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd()); } else if #[cfg(any(target_os = "dragonfly", target_os = "ios", - target_os = "macos"))] { + target_os = "macos", + target_os = "netbsd"))] { execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap()); - // No fexecve() on macos/ios and DragonFly. + // No fexecve() on DragonFly, ios, macos, and NetBSD. } }