diff options
-rw-r--r-- | src/errno.rs | 626 | ||||
-rw-r--r-- | src/fcntl.rs | 19 | ||||
-rw-r--r-- | src/lib.rs | 8 | ||||
-rw-r--r-- | src/mount.rs | 68 | ||||
-rw-r--r-- | src/nix.rs | 57 | ||||
-rw-r--r-- | src/sched.rs | 15 | ||||
-rw-r--r-- | src/sys/epoll.rs | 13 | ||||
-rw-r--r-- | src/sys/event.rs | 11 | ||||
-rw-r--r-- | src/sys/eventfd.rs | 7 | ||||
-rw-r--r-- | src/sys/ioctl.rs | 4 | ||||
-rw-r--r-- | src/sys/mman.rs | 46 | ||||
-rw-r--r-- | src/sys/signal.rs | 19 | ||||
-rw-r--r-- | src/sys/socket.rs | 53 | ||||
-rw-r--r-- | src/sys/stat.rs | 27 | ||||
-rw-r--r-- | src/sys/termios.rs | 21 | ||||
-rw-r--r-- | src/sys/wait.rs | 7 | ||||
-rw-r--r-- | src/unistd.rs | 120 | ||||
-rw-r--r-- | src/utils.rs | 25 | ||||
-rw-r--r-- | tests/nix.rs | 26 |
19 files changed, 618 insertions, 554 deletions
diff --git a/src/errno.rs b/src/errno.rs index 6c72d605..973ece04 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -1,423 +1,399 @@ -use std::fmt; use std::os::errno; use std::num::from_uint; -use libc::c_int; pub use self::consts::*; pub use self::consts::Errno::*; -pub type SysResult<T> = Result<T, SysError>; +macro_rules! impl_errno { + ($errno:ty) => { + impl $errno { + pub fn last() -> Errno { + super::last() + } -#[derive(Clone, PartialEq, Copy)] -pub struct SysError { - pub kind: Errno, -} - -impl SysError { - pub fn last() -> SysError { - match from_uint(errno()) { - Some(no) => SysError::new(no), - _ => SysError::new(UnknownErrno) + pub fn desc(self) -> &'static str { + super::desc(self) + } } } +} - pub fn new(kind: Errno) -> SysError { - SysError { kind: kind } - } - - pub fn errno(&self) -> usize { - self.kind as usize - } - - pub fn desc(&self) -> &'static str { - match self.kind { - UnknownErrno => "Unknown errno", - EPERM => "Operation not permitted", - ENOENT => "No such file or directory", - ESRCH => "No such process", - EINTR => "Interrupted system call", - EIO => "I/O error", - ENXIO => "No such device or address", - E2BIG => "Argument list too long", - ENOEXEC => "Exec format error", - EBADF => "Bad file number", - ECHILD => "No child processes", - EAGAIN => "Try again", - ENOMEM => "Out of memory", - EACCES => "Permission denied", - EFAULT => "Bad address", - ENOTBLK => "Block device required", - EBUSY => "Device or resource busy", - EEXIST => "File exists", - EXDEV => "Cross-device link", - ENODEV => "No such device", - ENOTDIR => "Not a directory", - EISDIR => "Is a directory", - EINVAL => "Invalid argument", - ENFILE => "File table overflow", - EMFILE => "Too many open files", - ENOTTY => "Not a typewriter", - ETXTBSY => "Text file busy", - EFBIG => "File too large", - ENOSPC => "No space left on device", - ESPIPE => "Illegal seek", - EROFS => "Read-only file system", - EMLINK => "Too many links", - EPIPE => "Broken pipe", - EDOM => "Math argument out of domain of func", - ERANGE => "Math result not representable", - EDEADLK => "Resource deadlock would occur", - ENAMETOOLONG => "File name too long", - ENOLCK => "No record locks available", - ENOSYS => "Function not implemented", - ENOTEMPTY => "Directory not empty", - ELOOP => "Too many symbolic links encountered", - ENOMSG => "No message of desired type", - EIDRM => "Identifier removed", - EINPROGRESS => "Operation now in progress", - EALREADY => "Operation already in progress", - ENOTSOCK => "Socket operation on non-socket", - EDESTADDRREQ => "Destination address required", - EMSGSIZE => "Message too long", - EPROTOTYPE => "Protocol wrong type for socket", - ENOPROTOOPT => "Protocol not available", - EPROTONOSUPPORT => "Protocol not supported", - ESOCKTNOSUPPORT => "Socket type not supported", - EPFNOSUPPORT => "Protocol family not supported", - EAFNOSUPPORT => "Address family not supported by protocol", - EADDRINUSE => "Address already in use", - EADDRNOTAVAIL => "Cannot assign requested address", - ENETDOWN => "Network is down", - ENETUNREACH => "Network is unreachable", - ENETRESET => "Network dropped connection because of reset", - ECONNABORTED => "Software caused connection abort", - ECONNRESET => "Connection reset by peer", - ENOBUFS => "No buffer space available", - EISCONN => "Transport endpoint is already connected", - ENOTCONN => "Transport endpoint is not connected", - ESHUTDOWN => "Cannot send after transport endpoint shutdown", - ETOOMANYREFS => "Too many references: cannot splice", - ETIMEDOUT => "Connection timed out", - ECONNREFUSED => "Connection refused", - EHOSTDOWN => "Host is down", - EHOSTUNREACH => "No route to host", - - #[cfg(target_os = "linux")] - ECHRNG => "Channel number out of range", - - #[cfg(target_os = "linux")] - EL2NSYNC => "Level 2 not synchronized", - - #[cfg(target_os = "linux")] - EL3HLT => "Level 3 halted", - - #[cfg(target_os = "linux")] - EL3RST => "Level 3 reset", - - #[cfg(target_os = "linux")] - ELNRNG => "Link number out of range", - - #[cfg(target_os = "linux")] - EUNATCH => "Protocol driver not attached", - - #[cfg(target_os = "linux")] - ENOCSI => "No CSI structure available", - - #[cfg(target_os = "linux")] - EL2HLT => "Level 2 halted", - - #[cfg(target_os = "linux")] - EBADE => "Invalid exchange", - - #[cfg(target_os = "linux")] - EBADR => "Invalid request descriptor", - - #[cfg(target_os = "linux")] - EXFULL => "Exchange full", - - #[cfg(target_os = "linux")] - ENOANO => "No anode", - - #[cfg(target_os = "linux")] - EBADRQC => "Invalid request code", - - #[cfg(target_os = "linux")] - EBADSLT => "Invalid slot", - - #[cfg(target_os = "linux")] - EBFONT => "Bad font file format", - - #[cfg(target_os = "linux")] - ENOSTR => "Device not a stream", - - #[cfg(target_os = "linux")] - ENODATA => "No data available", +fn last() -> Errno { + from_uint(errno()).unwrap_or(UnknownErrno) +} - #[cfg(target_os = "linux")] - ETIME => "Timer expired", +fn desc(errno: Errno) -> &'static str { + match errno { + UnknownErrno => "Unknown errno", + EPERM => "Operation not permitted", + ENOENT => "No such file or directory", + ESRCH => "No such process", + EINTR => "Interrupted system call", + EIO => "I/O error", + ENXIO => "No such device or address", + E2BIG => "Argument list too long", + ENOEXEC => "Exec format error", + EBADF => "Bad file number", + ECHILD => "No child processes", + EAGAIN => "Try again", + ENOMEM => "Out of memory", + EACCES => "Permission denied", + EFAULT => "Bad address", + ENOTBLK => "Block device required", + EBUSY => "Device or resource busy", + EEXIST => "File exists", + EXDEV => "Cross-device link", + ENODEV => "No such device", + ENOTDIR => "Not a directory", + EISDIR => "Is a directory", + EINVAL => "Invalid argument", + ENFILE => "File table overflow", + EMFILE => "Too many open files", + ENOTTY => "Not a typewriter", + ETXTBSY => "Text file busy", + EFBIG => "File too large", + ENOSPC => "No space left on device", + ESPIPE => "Illegal seek", + EROFS => "Read-only file system", + EMLINK => "Too many links", + EPIPE => "Broken pipe", + EDOM => "Math argument out of domain of func", + ERANGE => "Math result not representable", + EDEADLK => "Resource deadlock would occur", + ENAMETOOLONG => "File name too long", + ENOLCK => "No record locks available", + ENOSYS => "Function not implemented", + ENOTEMPTY => "Directory not empty", + ELOOP => "Too many symbolic links encountered", + ENOMSG => "No message of desired type", + EIDRM => "Identifier removed", + EINPROGRESS => "Operation now in progress", + EALREADY => "Operation already in progress", + ENOTSOCK => "Socket operation on non-socket", + EDESTADDRREQ => "Destination address required", + EMSGSIZE => "Message too long", + EPROTOTYPE => "Protocol wrong type for socket", + ENOPROTOOPT => "Protocol not available", + EPROTONOSUPPORT => "Protocol not supported", + ESOCKTNOSUPPORT => "Socket type not supported", + EPFNOSUPPORT => "Protocol family not supported", + EAFNOSUPPORT => "Address family not supported by protocol", + EADDRINUSE => "Address already in use", + EADDRNOTAVAIL => "Cannot assign requested address", + ENETDOWN => "Network is down", + ENETUNREACH => "Network is unreachable", + ENETRESET => "Network dropped connection because of reset", + ECONNABORTED => "Software caused connection abort", + ECONNRESET => "Connection reset by peer", + ENOBUFS => "No buffer space available", + EISCONN => "Transport endpoint is already connected", + ENOTCONN => "Transport endpoint is not connected", + ESHUTDOWN => "Cannot send after transport endpoint shutdown", + ETOOMANYREFS => "Too many references: cannot splice", + ETIMEDOUT => "Connection timed out", + ECONNREFUSED => "Connection refused", + EHOSTDOWN => "Host is down", + EHOSTUNREACH => "No route to host", + + #[cfg(target_os = "linux")] + ECHRNG => "Channel number out of range", + + #[cfg(target_os = "linux")] + EL2NSYNC => "Level 2 not synchronized", + + #[cfg(target_os = "linux")] + EL3HLT => "Level 3 halted", + + #[cfg(target_os = "linux")] + EL3RST => "Level 3 reset", + + #[cfg(target_os = "linux")] + ELNRNG => "Link number out of range", + + #[cfg(target_os = "linux")] + EUNATCH => "Protocol driver not attached", + + #[cfg(target_os = "linux")] + ENOCSI => "No CSI structure available", + + #[cfg(target_os = "linux")] + EL2HLT => "Level 2 halted", + + #[cfg(target_os = "linux")] + EBADE => "Invalid exchange", + + #[cfg(target_os = "linux")] + EBADR => "Invalid request descriptor", + + #[cfg(target_os = "linux")] + EXFULL => "Exchange full", + + #[cfg(target_os = "linux")] + ENOANO => "No anode", + + #[cfg(target_os = "linux")] + EBADRQC => "Invalid request code", + + #[cfg(target_os = "linux")] + EBADSLT => "Invalid slot", + + #[cfg(target_os = "linux")] + EBFONT => "Bad font file format", + + #[cfg(target_os = "linux")] + ENOSTR => "Device not a stream", - #[cfg(target_os = "linux")] - ENOSR => "Out of streams resources", + #[cfg(target_os = "linux")] + ENODATA => "No data available", - #[cfg(target_os = "linux")] - ENONET => "Machine is not on the network", + #[cfg(target_os = "linux")] + ETIME => "Timer expired", - #[cfg(target_os = "linux")] - ENOPKG => "Package not installed", + #[cfg(target_os = "linux")] + ENOSR => "Out of streams resources", - #[cfg(target_os = "linux")] - EREMOTE => "Object is remote", + #[cfg(target_os = "linux")] + ENONET => "Machine is not on the network", - #[cfg(target_os = "linux")] - ENOLINK => "Link has been severed", + #[cfg(target_os = "linux")] + ENOPKG => "Package not installed", - #[cfg(target_os = "linux")] - EADV => "Advertise error", + #[cfg(target_os = "linux")] + EREMOTE => "Object is remote", - #[cfg(target_os = "linux")] - ESRMNT => "Srmount error", + #[cfg(target_os = "linux")] + ENOLINK => "Link has been severed", - #[cfg(target_os = "linux")] - ECOMM => "Communication error on send", + #[cfg(target_os = "linux")] + EADV => "Advertise error", - #[cfg(target_os = "linux")] - EPROTO => "Protocol error", + #[cfg(target_os = "linux")] + ESRMNT => "Srmount error", - #[cfg(target_os = "linux")] - EMULTIHOP => "Multihop attempted", + #[cfg(target_os = "linux")] + ECOMM => "Communication error on send", - #[cfg(target_os = "linux")] - EDOTDOT => "RFS specific error", + #[cfg(target_os = "linux")] + EPROTO => "Protocol error", - #[cfg(target_os = "linux")] - EBADMSG => "Not a data message", + #[cfg(target_os = "linux")] + EMULTIHOP => "Multihop attempted", - #[cfg(target_os = "linux")] - EOVERFLOW => "Value too large for defined data type", + #[cfg(target_os = "linux")] + EDOTDOT => "RFS specific error", - #[cfg(target_os = "linux")] - ENOTUNIQ => "Name not unique on network", + #[cfg(target_os = "linux")] + EBADMSG => "Not a data message", - #[cfg(target_os = "linux")] - EBADFD => "File descriptor in bad state", + #[cfg(target_os = "linux")] + EOVERFLOW => "Value too large for defined data type", - #[cfg(target_os = "linux")] - EREMCHG => "Remote address changed", + #[cfg(target_os = "linux")] + ENOTUNIQ => "Name not unique on network", - #[cfg(target_os = "linux")] - ELIBACC => "Can not acces a needed shared library", + #[cfg(target_os = "linux")] + EBADFD => "File descriptor in bad state", - #[cfg(target_os = "linux")] - ELIBBAD => "Accessing a corrupted shared library", + #[cfg(target_os = "linux")] + EREMCHG => "Remote address changed", - #[cfg(target_os = "linux")] - ELIBSCN => ".lib section in a.out corrupted", + #[cfg(target_os = "linux")] + ELIBACC => "Can not acces a needed shared library", - #[cfg(target_os = "linux")] - ELIBMAX => "Attempting to link in too many shared libraries", + #[cfg(target_os = "linux")] + ELIBBAD => "Accessing a corrupted shared library", - #[cfg(target_os = "linux")] - ELIBEXEC => "Cannot exec a shared library directly", + #[cfg(target_os = "linux")] + ELIBSCN => ".lib section in a.out corrupted", - #[cfg(target_os = "linux")] - EILSEQ => "Illegal byte sequence", + #[cfg(target_os = "linux")] + ELIBMAX => "Attempting to link in too many shared libraries", - #[cfg(target_os = "linux")] - ERESTART => "Interrupted system call should be restarted", + #[cfg(target_os = "linux")] + ELIBEXEC => "Cannot exec a shared library directly", - #[cfg(target_os = "linux")] - ESTRPIPE => "Streams pipe error", + #[cfg(target_os = "linux")] + EILSEQ => "Illegal byte sequence", - #[cfg(target_os = "linux")] - EUSERS => "Too many users", + #[cfg(target_os = "linux")] + ERESTART => "Interrupted system call should be restarted", - #[cfg(target_os = "linux")] - EOPNOTSUPP => "Operation not supported on transport endpoint", + #[cfg(target_os = "linux")] + ESTRPIPE => "Streams pipe error", - #[cfg(target_os = "linux")] - ESTALE => "Stale file handle", + #[cfg(target_os = "linux")] + EUSERS => "Too many users", - #[cfg(target_os = "linux")] - EUCLEAN => "Structure needs cleaning", + #[cfg(target_os = "linux")] + EOPNOTSUPP => "Operation not supported on transport endpoint", - #[cfg(target_os = "linux")] - ENOTNAM => "Not a XENIX named type file", + #[cfg(target_os = "linux")] + ESTALE => "Stale file handle", - #[cfg(target_os = "linux")] - ENAVAIL => "No XENIX semaphores available", + #[cfg(target_os = "linux")] + EUCLEAN => "Structure needs cleaning", - #[cfg(target_os = "linux")] - EISNAM => "Is a named type file", + #[cfg(target_os = "linux")] + ENOTNAM => "Not a XENIX named type file", - #[cfg(target_os = "linux")] - EREMOTEIO => "Remote I/O error", + #[cfg(target_os = "linux")] + ENAVAIL => "No XENIX semaphores available", - #[cfg(target_os = "linux")] - EDQUOT => "Quota exceeded", + #[cfg(target_os = "linux")] + EISNAM => "Is a named type file", - #[cfg(target_os = "linux")] - ENOMEDIUM => "No medium found", + #[cfg(target_os = "linux")] + EREMOTEIO => "Remote I/O error", - #[cfg(target_os = "linux")] - EMEDIUMTYPE => "Wrong medium type", + #[cfg(target_os = "linux")] + EDQUOT => "Quota exceeded", - #[cfg(target_os = "linux")] - ECANCELED => "Operation canceled", + #[cfg(target_os = "linux")] + ENOMEDIUM => "No medium found", - #[cfg(target_os = "linux")] - ENOKEY => "Required key not available", + #[cfg(target_os = "linux")] + EMEDIUMTYPE => "Wrong medium type", - #[cfg(target_os = "linux")] - EKEYEXPIRED => "Key has expired", + #[cfg(target_os = "linux")] + ECANCELED => "Operation canceled", - #[cfg(target_os = "linux")] - EKEYREVOKED => "Key has been revoked", + #[cfg(target_os = "linux")] + ENOKEY => "Required key not available", - #[cfg(target_os = "linux")] - EKEYREJECTED => "Key was rejected by service", + #[cfg(target_os = "linux")] + EKEYEXPIRED => "Key has expired", - #[cfg(target_os = "linux")] - EOWNERDEAD => "Owner died", + #[cfg(target_os = "linux")] + EKEYREVOKED => "Key has been revoked", - #[cfg(target_os = "linux")] - ENOTRECOVERABLE => "State not recoverable", + #[cfg(target_os = "linux")] + EKEYREJECTED => "Key was rejected by service", - #[cfg(target_os = "linux")] - ERFKILL => "Operation not possible due to RF-kill", + #[cfg(target_os = "linux")] + EOWNERDEAD => "Owner died", - #[cfg(target_os = "linux")] - EHWPOISON => "Memory page has hardware error", + #[cfg(target_os = "linux")] + ENOTRECOVERABLE => "State not recoverable", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOTSUP => "Operation not supported", + #[cfg(target_os = "linux")] + ERFKILL => "Operation not possible due to RF-kill", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPROCLIM => "Too many processes", + #[cfg(target_os = "linux")] + EHWPOISON => "Memory page has hardware error", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EUSERS => "Too many users", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOTSUP => "Operation not supported", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EDQUOT => "Disc quota exceeded", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPROCLIM => "Too many processes", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ESTALE => "Stale NFS file handle", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EUSERS => "Too many users", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EREMOTE => "Stale NFS file handle", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EDQUOT => "Disc quota exceeded", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADRPC => "RPC struct is bad", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ESTALE => "Stale NFS file handle", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ERPCMISMATCH => "RPC version wrong", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EREMOTE => "Stale NFS file handle", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPROGUNAVAIL => "RPC prog. not avail", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EBADRPC => "RPC struct is bad", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPROGMISMATCH => "Program version wrong", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ERPCMISMATCH => "RPC version wrong", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPROCUNAVAIL => "Bad procedure for program", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPROGUNAVAIL => "RPC prog. not avail", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EFTYPE => "Inappropriate file type or format", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPROGMISMATCH => "Program version wrong", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EAUTH => "Authentication error", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPROCUNAVAIL => "Bad procedure for program", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENEEDAUTH => "Need authenticator", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EFTYPE => "Inappropriate file type or format", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPWROFF => "Device power is off", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EAUTH => "Authentication error", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EDEVERR => "Device error, e.g. paper out", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENEEDAUTH => "Need authenticator", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EOVERFLOW => "Value too large to be stored in data type", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPWROFF => "Device power is off", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADEXEC => "Bad executable", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EDEVERR => "Device error, e.g. paper out", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADARCH => "Bad CPU type in executable", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EOVERFLOW => "Value too large to be stored in data type", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ESHLIBVERS => "Shared library version mismatch", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EBADEXEC => "Bad executable", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADMACHO => "Malformed Macho file", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EBADARCH => "Bad CPU type in executable", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ECANCELED => "Operation canceled", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ESHLIBVERS => "Shared library version mismatch", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EILSEQ => "Illegal byte sequence", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EBADMACHO => "Malformed Macho file", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOATTR => "Attribute not found", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ECANCELED => "Operation canceled", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EBADMSG => "Bad message", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EILSEQ => "Illegal byte sequence", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EMULTIHOP => "Reserved", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOATTR => "Attribute not found", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENODATA => "No message available on STREAM", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EBADMSG => "Bad message", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOLINK => "Reserved", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EMULTIHOP => "Reserved", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOSR => "No STREAM resources", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENODATA => "No message available on STREAM", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOSTR => "Not a STREAM", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOLINK => "Reserved", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EPROTO => "Protocol error", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOSR => "No STREAM resources", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ETIME => "STREAM ioctl timeout", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOSTR => "Not a STREAM", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EOPNOTSUPP => "Operation not supported on socket", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EPROTO => "Protocol error", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOPOLICY => "No such policy registered", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ETIME => "STREAM ioctl timeout", - #[cfg(any(target_os = "macos", target_os = "ios"))] - ENOTRECOVERABLE => "State not recoverable", + #[cfg(any(target_os = "macos", target_os = "ios"))] + EOPNOTSUPP => "Operation not supported on socket", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EOWNERDEAD => "Previous owner died", + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOPOLICY => "No such policy registered", - #[cfg(any(target_os = "macos", target_os = "ios"))] - EQFULL => "Interface output queue is full", - } - } -} + #[cfg(any(target_os = "macos", target_os = "ios"))] + ENOTRECOVERABLE => "State not recoverable", -impl fmt::Debug for SysError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{:?} - {:?}", self.kind, self.desc()) - } -} + #[cfg(any(target_os = "macos", target_os = "ios"))] + EOWNERDEAD => "Previous owner died", -#[inline] -pub fn from_ffi(res: c_int) -> SysResult<()> { - if res != 0 { - return Err(SysError::last()); + #[cfg(any(target_os = "macos", target_os = "ios"))] + EQFULL => "Interface output queue is full", } - - Ok(()) } - #[cfg(target_os = "linux")] mod consts { #[derive(Debug, Clone, PartialEq, FromPrimitive, Copy)] @@ -556,6 +532,8 @@ mod consts { EHWPOISON = 133, } + impl_errno!(Errno); + pub const EWOULDBLOCK: Errno = Errno::EAGAIN; pub const EDEADLOCK: Errno = Errno::EDEADLK; } @@ -673,6 +651,8 @@ mod consts { EQFULL = 106, } + impl_errno!(Errno); + pub const ELAST: Errno = Errno::EQFULL; pub const EWOULDBLOCK: Errno = Errno::EAGAIN; pub const EDEADLOCK: Errno = Errno::EDEADLK; diff --git a/src/fcntl.rs b/src/fcntl.rs index 471a04d3..ac0e99c2 100644 --- a/src/fcntl.rs +++ b/src/fcntl.rs @@ -1,8 +1,7 @@ -use std::old_path::Path; use libc::{c_int, mode_t}; -use errno::{SysResult, SysError}; +use errno::Errno; +use {NixError, NixResult, NixPath}; use sys::stat::Mode; -use utils::ToCStr; pub use self::consts::*; pub use self::ffi::flock; @@ -71,11 +70,15 @@ mod ffi { } } -pub fn open(path: &Path, oflag: OFlag, mode: Mode) -> SysResult<Fd> { - let fd = unsafe { ffi::open(path.to_c_str().as_ptr(), oflag.bits(), mode.bits() as mode_t) }; +pub fn open<P: NixPath>(path: P, oflag: OFlag, mode: Mode) -> NixResult<Fd> { + let fd = try!(path.with_nix_path(|ptr| { + unsafe { + ffi::open(ptr, oflag.bits(), mode.bits() as mode_t) + } + })); if fd < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(fd) @@ -102,7 +105,7 @@ pub enum FcntlArg<'a> { } // TODO: Figure out how to handle value fcntl returns -pub fn fcntl(fd: Fd, arg: FcntlArg) -> SysResult<()> { +pub fn fcntl(fd: Fd, arg: FcntlArg) -> NixResult<()> { use self::FcntlArg::*; let res = unsafe { @@ -114,7 +117,7 @@ pub fn fcntl(fd: Fd, arg: FcntlArg) -> SysResult<()> { }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) @@ -1,6 +1,6 @@ #![crate_name = "nix"] -#![feature(core, linkage, libc, hash, os, path, std_misc)] +#![feature(collections, core, linkage, libc, hash, os)] #![allow(non_camel_case_types)] #[macro_use] @@ -12,8 +12,8 @@ extern crate core; // Re-export some libc constants pub use libc::{c_int, c_void}; -#[cfg(unix)] -pub use errno::{SysResult, SysError}; +mod nix; +pub use nix::{NixResult, NixError, NixPath, from_ffi}; #[cfg(unix)] pub mod errno; @@ -38,5 +38,3 @@ pub mod syscall; #[cfg(unix)] pub mod unistd; - -mod utils; diff --git a/src/mount.rs b/src/mount.rs index c2774ae2..af3e3495 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -1,8 +1,5 @@ -use std::ptr; -use std::old_path::Path; use libc::{c_ulong, c_int, c_void}; -use errno::{SysResult, from_ffi}; -use utils::ToCStr; +use {NixResult, NixPath, from_ffi}; bitflags!( flags MsFlags: c_ulong { @@ -68,42 +65,47 @@ mod ffi { } } -pub fn mount( - source: Option<&Path>, - target: &Path, - fstype: Option<&str>, +// XXX: Should `data` be a `NixPath` here? +pub fn mount<P1: NixPath, P2: NixPath, P3: NixPath, P4: NixPath>( + source: Option<P1>, + target: P2, + fstype: Option<P3>, flags: MsFlags, - data: Option<&str>) -> SysResult<()> { - - let source = source.map(|s| s.to_c_str()); - let target = target.to_c_str(); - let fstype = fstype.map(|s| s.to_c_str()); - let data = data.map(|s| s.to_c_str()); - - let res = unsafe { - ffi::mount( - source.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), - target.as_ptr(), - fstype.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()), - flags.bits, - data.map(|s| s.as_ptr() as *const c_void).unwrap_or(ptr::null())) - }; - - from_ffi(res) + data: Option<P4>) -> NixResult<()> { + 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, + target, + fstype, + flags.bits, + data as *const libc::c_void) + } + }) + }) + }) + }))))); + + return from_ffi(res); } -pub fn umount(target: &Path) -> SysResult<()> { - let target = target.to_c_str(); - - let res = unsafe { ffi::umount(target.as_ptr()) }; +pub fn umount<P: NixPath>(target: P) -> NixResult<()> { + let res = try!(target.with_nix_path(|ptr| { + unsafe { ffi::umount(ptr) } + })); from_ffi(res) } -pub fn umount2(target: &Path, flags: MntFlags) -> SysResult<()> { - let target = target.to_c_str(); - - let res = unsafe { ffi::umount2(target.as_ptr(), flags.bits) }; +pub fn umount2<P: NixPath>(target: P, flags: MntFlags) -> NixResult<()> { + let res = try!(target.with_nix_path(|ptr| { + unsafe { ffi::umount2(ptr, flags.bits) } + })); from_ffi(res) } diff --git a/src/nix.rs b/src/nix.rs new file mode 100644 index 00000000..e59ceaed --- /dev/null +++ b/src/nix.rs @@ -0,0 +1,57 @@ +use libc; +use std; + +use errno::Errno; + +pub type NixResult<T> = Result<T, NixError>; + +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum NixError { + Sys(Errno), + InvalidPath +} + +pub trait NixPath { + fn with_nix_path<T, F>(&self, f: F) -> Result<T, NixError> + where F: FnOnce(*const libc::c_char) -> T; +} + +impl<'a> NixPath for &'a [u8] { + fn with_nix_path<T, F>(&self, f: F) -> Result<T, NixError> + where F: FnOnce(*const libc::c_char) -> T + { + // TODO: Extract this size as a const + let mut buf = [0u8; 4096]; + + if self.len() >= 4096 { + return Err(NixError::InvalidPath); + } + + match self.position_elem(&0) { + Some(_) => Err(NixError::InvalidPath), + None => { + std::slice::bytes::copy_memory(&mut buf, self); + Ok(f(buf.as_ptr() as *const libc::c_char)) + } + } + } +} + +impl<P: NixPath> NixPath for Option<P> { + fn with_nix_path<T, F>(&self, f: F) -> Result<T, NixError> + where F: FnOnce(*const libc::c_char) -> T + { + match *self { + Some(ref some) => some.with_nix_path(f), + None => b"".with_nix_path(f) + } + } +} + +#[inline] +pub fn from_ffi(res: libc::c_int) -> NixResult<()> { + if res != 0 { + return Err(NixError::Sys(Errno::last())); + } + Ok(()) +} diff --git a/src/sched.rs b/src/sched.rs index 842c662e..a25d859f 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -1,6 +1,7 @@ use std::mem; use libc::{c_int, c_uint, c_void, c_ulong}; -use super::{SysResult, SysError}; +use errno::Errno; +use {NixResult, NixError}; pub type CloneFlags = c_uint; @@ -123,7 +124,7 @@ mod ffi { } } -pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> SysResult<()> { +pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> NixResult<()> { use libc::{pid_t, size_t}; let res = unsafe { @@ -131,13 +132,13 @@ pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> SysResult<()> { }; if res != 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(()) } } -pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags) -> SysResult<()> { +pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags) -> NixResult<()> { extern "C" fn callback(data: *mut CloneCb) -> c_int { let cb: &mut CloneCb = unsafe { &mut *data }; (*cb)() as c_int @@ -149,17 +150,17 @@ pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags) -> SysResult< }; if res != 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) } -pub fn unshare(flags: CloneFlags) -> SysResult<()> { +pub fn unshare(flags: CloneFlags) -> NixResult<()> { let res = unsafe { ffi::unshare(flags) }; if res != 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 31a46836..b9b31c9a 100644 --- a/src/sys/epoll.rs +++ b/src/sys/epoll.rs @@ -1,7 +1,8 @@ use std::fmt; use libc::c_int; +use errno::Errno; +use {NixError, NixResult, from_ffi}; use fcntl::Fd; -use errno::{SysResult, SysError, from_ffi}; mod ffi { use libc::{c_int}; @@ -85,30 +86,30 @@ pub struct EpollEvent { } #[inline] -pub fn epoll_create() -> SysResult<Fd> { +pub fn epoll_create() -> NixResult<Fd> { let res = unsafe { ffi::epoll_create(1024) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) } #[inline] -pub fn epoll_ctl(epfd: Fd, op: EpollOp, fd: Fd, event: &EpollEvent) -> SysResult<()> { +pub fn epoll_ctl(epfd: Fd, op: EpollOp, fd: Fd, event: &EpollEvent) -> NixResult<()> { let res = unsafe { ffi::epoll_ctl(epfd, op as c_int, fd, event as *const EpollEvent) }; from_ffi(res) } #[inline] -pub fn epoll_wait(epfd: Fd, events: &mut [EpollEvent], timeout_ms: usize) -> SysResult<usize> { +pub fn epoll_wait(epfd: Fd, events: &mut [EpollEvent], timeout_ms: usize) -> NixResult<usize> { let res = unsafe { ffi::epoll_wait(epfd, events.as_mut_ptr(), events.len() as c_int, timeout_ms as c_int) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res as usize) diff --git a/src/sys/event.rs b/src/sys/event.rs index fa85d84e..efe54b19 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -2,9 +2,10 @@ */ use libc::{timespec, time_t, c_int, c_long, uintptr_t}; -use errno::{SysResult, SysError}; +use errno::Errno; use fcntl::Fd; use std::fmt; +use {NixError, NixResult}; pub use self::ffi::kevent as KEvent; @@ -158,11 +159,11 @@ bitflags!( pub const EV_POLL: EventFlag = EV_FLAG0; pub const EV_OOBAND: EventFlag = EV_FLAG1; -pub fn kqueue() -> SysResult<Fd> { +pub fn kqueue() -> NixResult<Fd> { let res = unsafe { ffi::kqueue() }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) @@ -171,7 +172,7 @@ pub fn kqueue() -> SysResult<Fd> { pub fn kevent(kq: Fd, changelist: &[KEvent], eventlist: &mut [KEvent], - timeout_ms: usize) -> SysResult<usize> { + timeout_ms: usize) -> NixResult<usize> { // Convert ms to timespec let timeout = timespec { @@ -190,7 +191,7 @@ pub fn kevent(kq: Fd, }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(res as usize) diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs index fa6389a4..07162f85 100644 --- a/src/sys/eventfd.rs +++ b/src/sys/eventfd.rs @@ -1,7 +1,8 @@ use std::mem; use libc::{c_int, c_uint}; +use errno::Errno; use fcntl::Fd; -use errno::{SysResult, SysError}; +use {NixError, NixResult}; bitflags!( flags EventFdFlag: c_int { @@ -11,7 +12,7 @@ bitflags!( } ); -pub fn eventfd(initval: usize, flags: EventFdFlag) -> SysResult<Fd> { +pub fn eventfd(initval: usize, flags: EventFdFlag) -> NixResult<Fd> { type F = unsafe extern "C" fn(initval: c_uint, flags: c_int) -> c_int; extern { @@ -29,7 +30,7 @@ pub fn eventfd(initval: usize, flags: EventFdFlag) -> SysResult<Fd> { }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) diff --git a/src/sys/ioctl.rs b/src/sys/ioctl.rs index 4b2370c1..847733f2 100644 --- a/src/sys/ioctl.rs +++ b/src/sys/ioctl.rs @@ -1,6 +1,6 @@ use libc; -use errno::{SysResult, from_ffi}; use fcntl::Fd; +use {NixResult, from_ffi}; pub use self::ffi::Winsize; pub use self::IoctlArg::*; @@ -33,7 +33,7 @@ pub enum IoctlArg<'a> { TIOCGWINSZ(&'a mut Winsize) } -pub fn ioctl(fd: Fd, arg: IoctlArg) -> SysResult<()> { +pub fn ioctl(fd: Fd, arg: IoctlArg) -> NixResult<()> { match arg { TIOCGWINSZ(&mut ref winsize) => { from_ffi(unsafe { diff --git a/src/sys/mman.rs b/src/sys/mman.rs index b301b967..9129aa6e 100644 --- a/src/sys/mman.rs +++ b/src/sys/mman.rs @@ -1,8 +1,8 @@ -use errno::{SysResult, SysError}; +use errno::Errno; use fcntl::{Fd, OFlag}; use libc::{c_void, size_t, off_t, mode_t}; use sys::stat::Mode; -use utils::ToCStr; +use {NixError, NixResult, NixPath}; pub use self::consts::*; @@ -128,68 +128,74 @@ mod ffi { } } -pub unsafe fn mlock(addr: *const c_void, length: size_t) -> SysResult<()> { +pub unsafe fn mlock(addr: *const c_void, length: size_t) -> NixResult<()> { match ffi::mlock(addr, length) { 0 => Ok(()), - _ => Err(SysError::last()) + _ => Err(NixError::Sys(Errno::last())) } } -pub fn munlock(addr: *const c_void, length: size_t) -> SysResult<()> { +pub fn munlock(addr: *const c_void, length: size_t) -> NixResult<()> { match unsafe { ffi::munlock(addr, length) } { 0 => Ok(()), - _ => Err(SysError::last()) + _ => Err(NixError::Sys(Errno::last())) } } /// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically /// a higher-level abstraction will hide the unsafe interactions with the mmap'd region. -pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag, fd: Fd, offset: off_t) -> SysResult<*mut c_void> { +pub fn mmap(addr: *mut c_void, length: size_t, prot: MmapProt, flags: MmapFlag, fd: Fd, offset: off_t) -> NixResult<*mut c_void> { let ret = unsafe { ffi::mmap(addr, length, prot, flags, fd, offset) }; if ret as isize == MAP_FAILED { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(ret) } } -pub fn munmap(addr: *mut c_void, len: size_t) -> SysResult<()> { +pub fn munmap(addr: *mut c_void, len: size_t) -> NixResult<()> { match unsafe { ffi::munmap(addr, len) } { 0 => Ok(()), - _ => Err(SysError::last()) + _ => Err(NixError::Sys(Errno::last())) } } -pub fn madvise(addr: *const c_void, length: size_t, advise: MmapAdvise) -> SysResult<()> { +pub fn madvise(addr: *const c_void, length: size_t, advise: MmapAdvise) -> NixResult<()> { match unsafe { ffi::madvise(addr, length, advise) } { 0 => Ok(()), - _ => Err(SysError::last()) + _ => Err(NixError::Sys(Errno::last())) } } -pub fn msync(addr: *const c_void, length: size_t, flags: MmapSync) -> SysResult<()> { +pub fn msync(addr: *const c_void, length: size_t, flags: MmapSync) -> NixResult<()> { match unsafe { ffi::msync(addr, length, flags) } { 0 => Ok(()), - _ => Err(SysError::last()) + _ => Err(NixError::Sys(Errno::last())) } } -pub fn shm_open(name: &String, flag: OFlag, mode: Mode) -> SysResult<Fd> { - let ret = unsafe { ffi::shm_open(name.to_c_str().as_ptr(), flag.bits(), mode.bits() as mode_t) }; +pub fn shm_open<P: NixPath>(name: P, flag: OFlag, mode: Mode) -> NixResult<Fd> { + let ret = try!(name.with_nix_path(|ptr| { + unsafe { + ffi::shm_open(ptr, flag.bits(), mode.bits() as mode_t) + } + })); if ret < 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(ret) } } -pub fn shm_unlink(name: &String) -> SysResult<()> { - let ret = unsafe { ffi::shm_unlink(name.to_c_str().as_ptr()) }; +pub fn shm_unlink<P: NixPath>(name: P) -> NixResult<()> { + let ret = try!(name.with_nix_path(|ptr| { + unsafe { ffi::shm_unlink(ptr) } + })); if ret < 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(()) } diff --git a/src/sys/signal.rs b/src/sys/signal.rs index bead902f..e63cff13 100644 --- a/src/sys/signal.rs +++ b/src/sys/signal.rs @@ -2,8 +2,9 @@ // See http://rust-lang.org/COPYRIGHT. use libc; +use errno::Errno; use core::mem; -use errno::{SysError, SysResult}; +use {NixError, NixResult}; pub use libc::consts::os::posix88::{ SIGHUP, // 1 @@ -311,21 +312,21 @@ impl SigSet { SigSet { sigset: sigset } } - pub fn add(&mut self, signum: SigNum) -> SysResult<()> { + pub fn add(&mut self, signum: SigNum) -> NixResult<()> { let res = unsafe { ffi::sigaddset(&mut self.sigset as *mut sigset_t, signum) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) } - pub fn remove(&mut self, signum: SigNum) -> SysResult<()> { + pub fn remove(&mut self, signum: SigNum) -> NixResult<()> { let res = unsafe { ffi::sigdelset(&mut self.sigset as *mut sigset_t, signum) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) @@ -349,7 +350,7 @@ impl SigAction { } } -pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> SysResult<SigAction> { +pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> NixResult<SigAction> { let mut oldact = unsafe { mem::uninitialized::<sigaction_t>() }; let res = unsafe { @@ -357,17 +358,17 @@ pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> SysResult<SigAction> }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(SigAction { sigaction: oldact }) } -pub fn kill(pid: libc::pid_t, signum: SigNum) -> SysResult<()> { +pub fn kill(pid: libc::pid_t, signum: SigNum) -> NixResult<()> { let res = unsafe { ffi::kill(pid, signum) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) diff --git a/src/sys/socket.rs b/src/sys/socket.rs index b26f909c..b462570d 100644 --- a/src/sys/socket.rs +++ b/src/sys/socket.rs @@ -1,9 +1,10 @@ use std::{mem, ptr, fmt}; use libc::{c_void, c_int, socklen_t, size_t, ssize_t}; +use errno::Errno; use fcntl::{Fd, fcntl, FD_CLOEXEC, O_NONBLOCK}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; -use errno::{SysResult, SysError, from_ffi}; use features; +use {NixError, NixResult, from_ffi}; pub use libc::{in_addr, sockaddr, sockaddr_storage, sockaddr_in, sockaddr_in6, sockaddr_un, sa_family_t, ip_mreq}; @@ -225,7 +226,7 @@ mod consts { pub const MSG_DONTWAIT: SockMessageFlags = 0x80; } -pub fn socket(domain: AddressFamily, mut ty: SockType, flags: SockFlag) -> SysResult<Fd> { +pub fn socket(domain: AddressFamily, mut ty: SockType, flags: SockFlag) -> NixResult<Fd> { let feat_atomic = features::socket_atomic_cloexec(); if feat_atomic { @@ -236,7 +237,7 @@ pub fn socket(domain: AddressFamily, mut ty: SockType, flags: SockFlag) -> SysRe let res = unsafe { ffi::socket(domain, ty, 0) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } if !feat_atomic { @@ -252,12 +253,12 @@ pub fn socket(domain: AddressFamily, mut ty: SockType, flags: SockFlag) -> SysRe Ok(res) } -pub fn listen(sockfd: Fd, backlog: usize) -> SysResult<()> { +pub fn listen(sockfd: Fd, backlog: usize) -> NixResult<()> { let res = unsafe { ffi::listen(sockfd, backlog as c_int) }; from_ffi(res) } -pub fn bind(sockfd: Fd, addr: &SockAddr) -> SysResult<()> { +pub fn bind(sockfd: Fd, addr: &SockAddr) -> NixResult<()> { use self::SockAddr::*; let res = unsafe { @@ -271,18 +272,18 @@ pub fn bind(sockfd: Fd, addr: &SockAddr) -> SysResult<()> { from_ffi(res) } -pub fn accept(sockfd: Fd) -> SysResult<Fd> { +pub fn accept(sockfd: Fd) -> NixResult<Fd> { let res = unsafe { ffi::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { +pub fn accept4(sockfd: Fd, flags: SockFlag) -> NixResult<Fd> { use libc::sockaddr; type F = unsafe extern "C" fn(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int; @@ -299,7 +300,7 @@ pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) @@ -309,16 +310,16 @@ pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn accept4(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { +pub fn accept4(sockfd: Fd, flags: SockFlag) -> NixResult<Fd> { accept4_polyfill(sockfd, flags) } #[inline] -fn accept4_polyfill(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { +fn accept4_polyfill(sockfd: Fd, flags: SockFlag) -> NixResult<Fd> { let res = unsafe { ffi::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } if flags.contains(SOCK_CLOEXEC) { @@ -332,7 +333,7 @@ fn accept4_polyfill(sockfd: Fd, flags: SockFlag) -> SysResult<Fd> { Ok(res) } -pub fn connect(sockfd: Fd, addr: &SockAddr) -> SysResult<()> { +pub fn connect(sockfd: Fd, addr: &SockAddr) -> NixResult<()> { use self::SockAddr::*; let res = unsafe { @@ -368,7 +369,7 @@ mod sa_helpers { } } -pub fn recvfrom(sockfd: Fd, buf: &mut [u8]) -> SysResult<(usize, SockAddr)> { +pub fn recvfrom(sockfd: Fd, buf: &mut [u8]) -> NixResult<(usize, SockAddr)> { let saddr : sockaddr_storage = unsafe { mem::zeroed() }; let mut len = mem::size_of::<sockaddr_storage>() as socklen_t; @@ -377,7 +378,7 @@ pub fn recvfrom(sockfd: Fd, buf: &mut [u8]) -> SysResult<(usize, SockAddr)> { }; if ret < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok((ret as usize, @@ -427,7 +428,7 @@ fn sendto_sockaddr<T>(sockfd: Fd, buf: &[u8], flags: SockMessageFlags, addr: &T) } } -pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr, flags: SockMessageFlags) -> SysResult<usize> { +pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr, flags: SockMessageFlags) -> NixResult<usize> { use self::SockAddr::*; let ret = match *addr { @@ -437,7 +438,7 @@ pub fn sendto(sockfd: Fd, buf: &[u8], addr: &SockAddr, flags: SockMessageFlags) }; if ret < 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(ret as usize) } @@ -450,7 +451,7 @@ pub struct linger { pub l_linger: c_int } -pub fn getsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &mut T) -> SysResult<usize> { +pub fn getsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &mut T) -> NixResult<usize> { let mut len = mem::size_of::<T>() as socklen_t; let res = unsafe { @@ -461,13 +462,13 @@ pub fn getsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &mut T) -> Sys }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(len as usize) } -pub fn setsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &T) -> SysResult<()> { +pub fn setsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &T) -> NixResult<()> { let len = mem::size_of::<T>() as socklen_t; let res = unsafe { @@ -480,19 +481,19 @@ pub fn setsockopt<T>(fd: Fd, level: SockLevel, opt: SockOpt, val: &T) -> SysResu from_ffi(res) } -fn getpeername_sockaddr<T>(sockfd: Fd, addr: &T) -> SysResult<bool> { +fn getpeername_sockaddr<T>(sockfd: Fd, addr: &T) -> NixResult<bool> { let addrlen_expected = mem::size_of::<T>() as socklen_t; let mut addrlen = addrlen_expected; let ret = unsafe { ffi::getpeername(sockfd, mem::transmute(addr), &mut addrlen) }; if ret < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(addrlen == addrlen_expected) } -pub fn getpeername(sockfd: Fd, addr: &mut SockAddr) -> SysResult<bool> { +pub fn getpeername(sockfd: Fd, addr: &mut SockAddr) -> NixResult<bool> { use self::SockAddr::*; match *addr { @@ -502,19 +503,19 @@ pub fn getpeername(sockfd: Fd, addr: &mut SockAddr) -> SysResult<bool> { } } -fn getsockname_sockaddr<T>(sockfd: Fd, addr: &T) -> SysResult<bool> { +fn getsockname_sockaddr<T>(sockfd: Fd, addr: &T) -> NixResult<bool> { let addrlen_expected = mem::size_of::<T>() as socklen_t; let mut addrlen = addrlen_expected; let ret = unsafe { ffi::getsockname(sockfd, mem::transmute(addr), &mut addrlen) }; if ret < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(addrlen == addrlen_expected) } -pub fn getsockname(sockfd: Fd, addr: &mut SockAddr) -> SysResult<bool> { +pub fn getsockname(sockfd: Fd, addr: &mut SockAddr) -> NixResult<bool> { use self::SockAddr::*; match *addr { diff --git a/src/sys/stat.rs b/src/sys/stat.rs index ca17039c..1397ad24 100644 --- a/src/sys/stat.rs +++ b/src/sys/stat.rs @@ -3,11 +3,10 @@ pub use libc::stat as FileStat; use std::fmt; use std::mem; -use std::old_path::Path; +use errno::Errno; use libc::mode_t; -use errno::{SysResult, SysError, from_ffi}; use fcntl::Fd; -use utils::ToCStr; +use {NixError, NixResult, NixPath, from_ffi}; mod ffi { use libc::{c_char, c_int, mode_t, dev_t}; @@ -58,8 +57,12 @@ impl fmt::Debug for SFlag { } } -pub fn mknod(path: &Path, kind: SFlag, perm: Mode, dev: dev_t) -> SysResult<()> { - let res = unsafe { ffi::mknod(path.to_c_str().as_ptr(), kind.bits | perm.bits() as mode_t, dev) }; +pub fn mknod<P: NixPath>(path: P, kind: SFlag, perm: Mode, dev: dev_t) -> NixResult<()> { + let res = try!(path.with_nix_path(|ptr| { + unsafe { + ffi::mknod(ptr, kind.bits | perm.bits() as mode_t, dev) + } + })); from_ffi(res) } @@ -76,23 +79,27 @@ pub fn umask(mode: Mode) -> Mode { Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode") } -pub fn stat(path: &Path) -> SysResult<FileStat> { +pub fn stat<P: NixPath>(path: P) -> NixResult<FileStat> { let mut dst = unsafe { mem::uninitialized() }; - let res = unsafe { ffi::stat(path.to_c_str().as_ptr(), &mut dst as *mut FileStat) }; + let res = try!(path.with_nix_path(|ptr| { + unsafe { + ffi::stat(ptr, &mut dst as *mut FileStat) + } + })); if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(dst) } -pub fn fstat(fd: Fd) -> SysResult<FileStat> { +pub fn fstat(fd: Fd) -> NixResult<FileStat> { let mut dst = unsafe { mem::uninitialized() }; let res = unsafe { ffi::fstat(fd, &mut dst as *mut FileStat) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(dst) diff --git a/src/sys/termios.rs b/src/sys/termios.rs index 525a13ff..56beca2e 100644 --- a/src/sys/termios.rs +++ b/src/sys/termios.rs @@ -1,7 +1,8 @@ -use errno::{SysError, SysResult, from_ffi}; +use errno::Errno; use fcntl::Fd; use libc::c_int; use std::mem; +use {NixError, NixResult, from_ffi}; pub use self::ffi::consts::*; pub use self::ffi::consts::SetArg::*; @@ -361,19 +362,19 @@ pub fn cfgetospeed(termios: &Termios) -> speed_t { } } -pub fn cfsetispeed(termios: &mut Termios, speed: speed_t) -> SysResult<()> { +pub fn cfsetispeed(termios: &mut Termios, speed: speed_t) -> NixResult<()> { from_ffi(unsafe { ffi::cfsetispeed(termios, speed) }) } -pub fn cfsetospeed(termios: &mut Termios, speed: speed_t) -> SysResult<()> { +pub fn cfsetospeed(termios: &mut Termios, speed: speed_t) -> NixResult<()> { from_ffi(unsafe { ffi::cfsetospeed(termios, speed) }) } -pub fn tcgetattr(fd: Fd) -> SysResult<Termios> { +pub fn tcgetattr(fd: Fd) -> NixResult<Termios> { let mut termios = unsafe { mem::uninitialized() }; let res = unsafe { @@ -381,7 +382,7 @@ pub fn tcgetattr(fd: Fd) -> SysResult<Termios> { }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(termios) @@ -389,31 +390,31 @@ pub fn tcgetattr(fd: Fd) -> SysResult<Termios> { pub fn tcsetattr(fd: Fd, actions: SetArg, - termios: &Termios) -> SysResult<()> { + termios: &Termios) -> NixResult<()> { from_ffi(unsafe { ffi::tcsetattr(fd, actions as c_int, termios) }) } -pub fn tcdrain(fd: Fd) -> SysResult<()> { +pub fn tcdrain(fd: Fd) -> NixResult<()> { from_ffi(unsafe { ffi::tcdrain(fd) }) } -pub fn tcflow(fd: Fd, action: FlowArg) -> SysResult<()> { +pub fn tcflow(fd: Fd, action: FlowArg) -> NixResult<()> { from_ffi(unsafe { ffi::tcflow(fd, action as c_int) }) } -pub fn tcflush(fd: Fd, action: FlushArg) -> SysResult<()> { +pub fn tcflush(fd: Fd, action: FlushArg) -> NixResult<()> { from_ffi(unsafe { ffi::tcflush(fd, action as c_int) }) } -pub fn tcsendbreak(fd: Fd, action: c_int) -> SysResult<()> { +pub fn tcsendbreak(fd: Fd, action: c_int) -> NixResult<()> { from_ffi(unsafe { ffi::tcsendbreak(fd, action) }) diff --git a/src/sys/wait.rs b/src/sys/wait.rs index e2273d2f..b07c68b5 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -1,5 +1,6 @@ use libc::{pid_t, c_int}; -use errno::{SysResult, SysError}; +use errno::Errno; +use {NixError, NixResult}; mod ffi { use libc::{pid_t, c_int}; @@ -21,7 +22,7 @@ pub enum WaitStatus { StillAlive } -pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> SysResult<WaitStatus> { +pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> NixResult<WaitStatus> { use self::WaitStatus::*; let mut status: i32 = 0; @@ -34,7 +35,7 @@ pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> SysResult<WaitStatus let res = unsafe { ffi::waitpid(pid as pid_t, &mut status as *mut c_int, option_bits) }; if res < 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else if res == 0 { Ok(StillAlive) } else { diff --git a/src/unistd.rs b/src/unistd.rs index 2a476015..d3838e9f 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1,12 +1,12 @@ use std::{mem, ptr}; use libc::{c_char, c_void, c_int, size_t, pid_t, off_t}; +use errno::Errno; use fcntl::{fcntl, Fd, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC}; use fcntl::FcntlArg::{F_SETFD, F_SETFL}; +use {NixError, NixResult, NixPath, from_ffi}; -use errno::{SysResult, SysError, from_ffi}; use core::raw::Slice as RawSlice; -use utils::ToCStr; -use std::ffi::CString; +use std::ffi::CString; #[cfg(target_os = "linux")] pub use self::linux::*; @@ -76,13 +76,13 @@ impl Fork { } } -pub fn fork() -> SysResult<Fork> { +pub fn fork() -> NixResult<Fork> { use self::Fork::*; let res = unsafe { ffi::fork() }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } else if res == 0 { Ok(Child) } else { @@ -97,7 +97,7 @@ pub fn fork() -> SysResult<Fork> { // let mut v = Vec::new(); // let iov = Iovec::from_slice(immutable_vec.as_slice()); // v.push(iov); -// let _:SysResult<usize> = readv(fd, v.as_slice()); +// let _:NixResult<usize> = readv(fd, v.as_slice()); // We do not want <T> to appear in ffi functions, so we provide this aliases. type IovecR = Iovec<ToRead>; @@ -143,29 +143,29 @@ impl Iovec<ToRead> { #[inline] -pub fn dup(oldfd: Fd) -> SysResult<Fd> { +pub fn dup(oldfd: Fd) -> NixResult<Fd> { let res = unsafe { ffi::dup(oldfd) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) } #[inline] -pub fn dup2(oldfd: Fd, newfd: Fd) -> SysResult<Fd> { +pub fn dup2(oldfd: Fd, newfd: Fd) -> NixResult<Fd> { let res = unsafe { ffi::dup2(oldfd, newfd) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) } #[cfg(not(any(target_os = "macos", target_os = "ios")))] -pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { +pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> NixResult<Fd> { type F = unsafe extern "C" fn(c_int, c_int, c_int) -> c_int; extern { @@ -180,7 +180,7 @@ pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(res) @@ -190,16 +190,16 @@ pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { +pub fn dup3(oldfd: Fd, newfd: Fd, flags: OFlag) -> NixResult<Fd> { dup3_polyfill(oldfd, newfd, flags) } #[inline] -fn dup3_polyfill(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { +fn dup3_polyfill(oldfd: Fd, newfd: Fd, flags: OFlag) -> NixResult<Fd> { use errno::EINVAL; if oldfd == newfd { - return Err(SysError { kind: EINVAL }); + return Err(NixError::Sys(Errno::EINVAL)); } let fd = try!(dup2(oldfd, newfd)); @@ -215,19 +215,20 @@ fn dup3_polyfill(oldfd: Fd, newfd: Fd, flags: OFlag) -> SysResult<Fd> { } #[inline] -pub fn chdir<S: ToCStr>(path: S) -> SysResult<()> { - let path = path.to_c_str(); - let res = unsafe { ffi::chdir(path.as_ptr()) }; +pub fn chdir<P: NixPath>(path: P) -> NixResult<()> { + let res = try!(path.with_nix_path(|ptr| { + unsafe { ffi::chdir(ptr) } + })); if res != 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(()) } #[inline] -pub fn execve(filename: &CString, args: &[CString], env: &[CString]) -> SysResult<()> { +pub fn execve(filename: &CString, args: &[CString], env: &[CString]) -> NixResult<()> { let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect(); args_p.push(ptr::null()); @@ -239,18 +240,18 @@ pub fn execve(filename: &CString, args: &[CString], env: &[CString]) -> SysResul }; if res != 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } unreachable!() } -pub fn daemon(nochdir: bool, noclose: bool) -> SysResult<()> { +pub fn daemon(nochdir: bool, noclose: bool) -> NixResult<()> { let res = unsafe { ffi::daemon(nochdir as c_int, noclose as c_int) }; from_ffi(res) } -pub fn sethostname(name: &[u8]) -> SysResult<()> { +pub fn sethostname(name: &[u8]) -> NixResult<()> { let ptr = name.as_ptr() as *const c_char; let len = name.len() as size_t; @@ -258,7 +259,7 @@ pub fn sethostname(name: &[u8]) -> SysResult<()> { from_ffi(res) } -pub fn gethostname(name: &mut [u8]) -> SysResult<()> { +pub fn gethostname(name: &mut [u8]) -> NixResult<()> { let ptr = name.as_mut_ptr() as *mut c_char; let len = name.len() as size_t; @@ -266,50 +267,50 @@ pub fn gethostname(name: &mut [u8]) -> SysResult<()> { from_ffi(res) } -pub fn close(fd: Fd) -> SysResult<()> { +pub fn close(fd: Fd) -> NixResult<()> { let res = unsafe { ffi::close(fd) }; from_ffi(res) } -pub fn read(fd: Fd, buf: &mut [u8]) -> SysResult<usize> { +pub fn read(fd: Fd, buf: &mut [u8]) -> NixResult<usize> { let res = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(res as usize) } -pub fn write(fd: Fd, buf: &[u8]) -> SysResult<usize> { +pub fn write(fd: Fd, buf: &[u8]) -> NixResult<usize> { let res = unsafe { ffi::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(res as usize) } -pub fn writev(fd: Fd, iov: &[Iovec<ToWrite>]) -> SysResult<usize> { +pub fn writev(fd: Fd, iov: &[Iovec<ToWrite>]) -> NixResult<usize> { let res = unsafe { ffi::writev(fd, iov.as_ptr(), iov.len() as c_int) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(res as usize) } -pub fn readv(fd: Fd, iov: &mut [Iovec<ToRead>]) -> SysResult<usize> { +pub fn readv(fd: Fd, iov: &mut [Iovec<ToRead>]) -> NixResult<usize> { let res = unsafe { ffi::readv(fd, iov.as_ptr(), iov.len() as c_int) }; if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } return Ok(res as usize) } -pub fn pipe() -> SysResult<(Fd, Fd)> { +pub fn pipe() -> NixResult<(Fd, Fd)> { unsafe { let mut res; let mut fds: [c_int; 2] = mem::uninitialized(); @@ -317,7 +318,7 @@ pub fn pipe() -> SysResult<(Fd, Fd)> { res = ffi::pipe(fds.as_mut_ptr()); if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok((fds[0], fds[1])) @@ -325,7 +326,7 @@ pub fn pipe() -> SysResult<(Fd, Fd)> { } #[cfg(target_os = "linux")] -pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { +pub fn pipe2(flags: OFlag) -> NixResult<(Fd, Fd)> { type F = unsafe extern "C" fn(fds: *mut c_int, flags: c_int) -> c_int; extern { @@ -347,7 +348,7 @@ pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { } if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } if !feat_atomic { @@ -359,7 +360,7 @@ pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { } #[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { +pub fn pipe2(flags: OFlag) -> NixResult<(Fd, Fd)> { unsafe { let mut res; let mut fds: [c_int; 2] = mem::uninitialized(); @@ -367,7 +368,7 @@ pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { res = ffi::pipe(fds.as_mut_ptr()); if res < 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } try!(pipe2_setflags(fds[0], fds[1], flags)); @@ -376,7 +377,7 @@ pub fn pipe2(flags: OFlag) -> SysResult<(Fd, Fd)> { } } -fn pipe2_setflags(fd1: Fd, fd2: Fd, flags: OFlag) -> SysResult<()> { +fn pipe2_setflags(fd1: Fd, fd2: Fd, flags: OFlag) -> NixResult<()> { let mut res = Ok(()); if flags.contains(O_CLOEXEC) { @@ -401,46 +402,47 @@ fn pipe2_setflags(fd1: Fd, fd2: Fd, flags: OFlag) -> SysResult<()> { } } -pub fn ftruncate(fd: Fd, len: off_t) -> SysResult<()> { +pub fn ftruncate(fd: Fd, len: off_t) -> NixResult<()> { if unsafe { ffi::ftruncate(fd, len) } < 0 { - Err(SysError::last()) + Err(NixError::Sys(Errno::last())) } else { Ok(()) } } -pub fn isatty(fd: Fd) -> SysResult<bool> { - use {errno, libc}; +pub fn isatty(fd: Fd) -> NixResult<bool> { + use libc; if unsafe { libc::isatty(fd) } == 1 { Ok(true) } else { - match SysError::last() { + match Errno::last() { // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so // we return `Ok(false)` - SysError { kind: errno::ENOTTY } => Ok(false), - err => Err(err) + Errno::ENOTTY => Ok(false), + err => Err(NixError::Sys(err)) } } } #[cfg(target_os = "linux")] mod linux { - use std::old_path::Path; use syscall::{syscall, SYSPIVOTROOT}; - use errno::{SysResult, SysError}; - use utils::ToCStr; - - pub fn pivot_root(new_root: &Path, put_old: &Path) -> SysResult<()> { - let new_root = new_root.to_c_str(); - let put_old = put_old.to_c_str(); - - let res = unsafe { - syscall(SYSPIVOTROOT, new_root.as_ptr(), put_old.as_ptr()) - }; + use errno::Errno; + use {NixError, NixResult, NixPath}; + + pub fn pivot_root<P1: NixPath, P2: NixPath>(new_root: P1, + put_old: P2) -> NixResult<()> { + let res = try!(try!(new_root.with_nix_path(|new_root| { + put_old.with_nix_path(|put_old| { + unsafe { + syscall(SYSPIVOTROOT, new_root, put_old) + } + }) + }))); if res != 0 { - return Err(SysError::last()); + return Err(NixError::Sys(Errno::last())); } Ok(()) diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 53521eae..00000000 --- a/src/utils.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::ffi::CString; -use std::old_path::{Path}; - -pub trait ToCStr { - fn to_c_str(&self) -> CString; -} - -impl ToCStr for Path { - fn to_c_str(&self) -> CString { - CString::from_slice(self.as_vec()) - } -} - -impl<'a> ToCStr for &'a str { - fn to_c_str(&self) -> CString { - CString::from_slice(self.as_bytes()) - } -} - - -impl ToCStr for String { - fn to_c_str(&self) -> CString { - CString::from_slice(self.as_bytes()) - } -} diff --git a/tests/nix.rs b/tests/nix.rs new file mode 100644 index 00000000..675f357f --- /dev/null +++ b/tests/nix.rs @@ -0,0 +1,26 @@ +#![feature(core, libc)] + +extern crate nix; +extern crate libc; + +use nix::NixPath; + +#[test] +fn test_nix_path() { + fn cstr_to_bytes(cstr: &*const libc::c_char, len: usize) -> &[u8] { + unsafe { + let cstr = cstr as *const _ as *const *const u8; + std::slice::from_raw_parts(*cstr, len) + } + } + + let bytes = b"abcd"; + let ok = bytes.with_nix_path(|cstr| { + assert_eq!(b"abcd\0", cstr_to_bytes(&cstr, 5)); + }); + assert!(ok.is_ok()); + + let bytes = b"ab\0cd"; + let err = bytes.with_nix_path(|_| {}); + assert!(err.is_err()); +} |