diff options
| author | David LeGare <excaliburhissheath@gmail.com> | 2017-05-05 20:35:41 -0500 |
|---|---|---|
| committer | David LeGare <excaliburhissheath@gmail.com> | 2017-05-05 20:35:41 -0500 |
| commit | d7df6dcd7399e0c49b6008ab3b82c979dba835a6 (patch) | |
| tree | e2054076d05c9f68a99f235717bd95efb72faaf9 /src/libstd/sys | |
| parent | e406cd1ec9abb77236318db30e362e4654411a1a (diff) | |
| parent | f4209651ec4d4455dab4fc3f3a3456a897d9da7f (diff) | |
| download | rust-d7df6dcd7399e0c49b6008ab3b82c979dba835a6.tar.gz rust-d7df6dcd7399e0c49b6008ab3b82c979dba835a6.zip | |
Merge remote-tracking branch 'rust-lang/master' into iss29367-windows-docs
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/redox/process.rs | 21 | ||||
| -rw-r--r-- | src/libstd/sys/redox/syscall/call.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys/redox/syscall/number.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/unix/ext/net.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/unix/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/unix/pipe.rs | 22 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process/magenta.rs | 77 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process/process_common.rs | 16 | ||||
| -rw-r--r-- | src/libstd/sys/unix/process/process_unix.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/unix/time.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext/fs.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/windows/ext/process.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sys/windows/process.rs | 9 | ||||
| -rw-r--r-- | src/libstd/sys/windows/stdio.rs | 92 |
14 files changed, 147 insertions, 118 deletions
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 707b4cbc6ac..95e9438cd71 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -270,19 +270,22 @@ impl Command { } if let Some(fd) = stdio.stderr.fd() { - let _ = syscall::close(2); - t!(cvt(syscall::dup(fd, &[]))); - let _ = syscall::close(fd); + t!(cvt(syscall::dup2(fd, 2, &[]))); + let mut flags = t!(cvt(syscall::fcntl(2, syscall::F_GETFL, 0))); + flags &= ! syscall::O_CLOEXEC; + t!(cvt(syscall::fcntl(2, syscall::F_SETFL, flags))); } if let Some(fd) = stdio.stdout.fd() { - let _ = syscall::close(1); - t!(cvt(syscall::dup(fd, &[]))); - let _ = syscall::close(fd); + t!(cvt(syscall::dup2(fd, 1, &[]))); + let mut flags = t!(cvt(syscall::fcntl(1, syscall::F_GETFL, 0))); + flags &= ! syscall::O_CLOEXEC; + t!(cvt(syscall::fcntl(1, syscall::F_SETFL, flags))); } if let Some(fd) = stdio.stdin.fd() { - let _ = syscall::close(0); - t!(cvt(syscall::dup(fd, &[]))); - let _ = syscall::close(fd); + t!(cvt(syscall::dup2(fd, 0, &[]))); + let mut flags = t!(cvt(syscall::fcntl(0, syscall::F_GETFL, 0))); + flags &= ! syscall::O_CLOEXEC; + t!(cvt(syscall::fcntl(0, syscall::F_SETFL, flags))); } if let Some(g) = self.gid { diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs index f58c240f31e..fadf7325d75 100644 --- a/src/libstd/sys/redox/syscall/call.rs +++ b/src/libstd/sys/redox/syscall/call.rs @@ -71,6 +71,11 @@ pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> { unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) } } +/// Copy and transform a file descriptor +pub fn dup2(fd: usize, newfd: usize, buf: &[u8]) -> Result<usize> { + unsafe { syscall4(SYS_DUP2, fd, newfd, buf.as_ptr() as usize, buf.len()) } +} + /// Replace the current process with a new executable pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> { unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(), diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs index 358746cd20a..98f8b73e4e1 100644 --- a/src/libstd/sys/redox/syscall/number.rs +++ b/src/libstd/sys/redox/syscall/number.rs @@ -28,6 +28,7 @@ pub const SYS_UNLINK: usize = SYS_CLASS_PATH | 10; pub const SYS_CLOSE: usize = SYS_CLASS_FILE | 6; pub const SYS_DUP: usize = SYS_CLASS_FILE | SYS_RET_FILE | 41; +pub const SYS_DUP2: usize = SYS_CLASS_FILE | SYS_RET_FILE | 63; pub const SYS_READ: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 3; pub const SYS_WRITE: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 4; pub const SYS_LSEEK: usize = SYS_CLASS_FILE | 19; diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 55118829eee..d688f2fa504 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -641,7 +641,7 @@ impl UnixListener { let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path)?; - cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len))?; + cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?; cvt(libc::listen(*inner.as_inner(), 128))?; Ok(UnixListener(inner)) @@ -920,7 +920,7 @@ impl UnixDatagram { let socket = UnixDatagram::unbound()?; let (addr, len) = sockaddr_un(path)?; - cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len))?; + cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?; Ok(socket) } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c57751a01d7..854d380d128 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -92,7 +92,7 @@ pub fn init() { #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))] unsafe fn reset_sigpipe() { - assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0); + assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR); } #[cfg(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia"))] unsafe fn reset_sigpipe() {} diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 51e00fc1ab9..706256ff10e 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cmp; use io; use libc::{self, c_int}; use mem; -use ptr; use sys::{cvt, cvt_r}; use sys::fd::FileDesc; @@ -80,16 +78,14 @@ pub fn read2(p1: AnonPipe, p1.set_nonblocking(true)?; p2.set_nonblocking(true)?; - let max = cmp::max(p1.raw(), p2.raw()); + let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; + fds[0].fd = p1.raw(); + fds[0].events = libc::POLLIN; + fds[1].fd = p2.raw(); + fds[1].events = libc::POLLIN; loop { - // wait for either pipe to become readable using `select` - cvt_r(|| unsafe { - let mut read: libc::fd_set = mem::zeroed(); - libc::FD_SET(p1.raw(), &mut read); - libc::FD_SET(p2.raw(), &mut read); - libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(), - ptr::null_mut()) - })?; + // wait for either pipe to become readable using `poll` + cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?; // Read as much as we can from each pipe, ignoring EWOULDBLOCK or // EAGAIN. If we hit EOF, then this will happen because the underlying @@ -109,11 +105,11 @@ pub fn read2(p1: AnonPipe, } } }; - if read(&p1, v1)? { + if fds[0].revents != 0 && read(&p1, v1)? { p2.set_nonblocking(false)?; return p2.read_to_end(v2).map(|_| ()); } - if read(&p2, v2)? { + if fds[1].revents != 0 && read(&p2, v2)? { p1.set_nonblocking(false)?; return p1.read_to_end(v1).map(|_| ()); } diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs index 07f29784df6..5b5e29c0374 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/magenta.rs @@ -202,7 +202,7 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; // ERR_NO_RESOURCES: The system was not able to allocate some resource // needed for the operation. -#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -5; +#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -3; // ERR_NO_MEMORY: The system was not able to allocate memory needed // for the operation. @@ -210,30 +210,34 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; // ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete // successfully. -#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -53; +#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -5; + +// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be +// retried. This should not be seen outside of the VDSO. +#[allow(unused)] pub const ERR_INTERRUPTED_RETRY: mx_status_t = -6; // ======= Parameter errors ======= // ERR_INVALID_ARGS: an argument is invalid, ex. null pointer #[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10; +// ERR_BAD_HANDLE: A specified handle value does not refer to a handle. +#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -11; + // ERR_WRONG_TYPE: The subject of the operation is the wrong type to // perform the operation. // Example: Attempting a message_read on a thread handle. -#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -54; +#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -12; // ERR_BAD_SYSCALL: The specified syscall number is invalid. -#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -11; - -// ERR_BAD_HANDLE: A specified handle value does not refer to a handle. -#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -12; +#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -13; // ERR_OUT_OF_RANGE: An argument is outside the valid range for this // operation. -#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -13; +#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -14; // ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for // this operation. -#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -14; +#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -15; // ======= Precondition or state errors ======= // ERR_BAD_STATE: operation failed because the current state of the @@ -241,47 +245,48 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; // not satisfied #[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20; +// ERR_TIMED_OUT: The time limit for the operation elapsed before +// the operation completed. +#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -21; + +// ERR_SHOULD_WAIT: The operation cannot be performed currently but +// potentially could succeed if the caller waits for a prerequisite +// to be satisfied, for example waiting for a handle to be readable +// or writable. +// Example: Attempting to read from a message pipe that has no +// messages waiting but has an open remote will return ERR_SHOULD_WAIT. +// Attempting to read from a message pipe that has no messages waiting +// and has a closed remote end will return ERR_REMOTE_CLOSED. +#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -22; + +// ERR_CANCELED: The in-progress operation (e.g. a wait) has been +// // canceled. +#[allow(unused)] pub const ERR_CANCELED: mx_status_t = -23; + +// ERR_PEER_CLOSED: The operation failed because the remote end +// of the subject of the operation was closed. +#[allow(unused)] pub const ERR_PEER_CLOSED: mx_status_t = -24; + // ERR_NOT_FOUND: The requested entity is not found. -#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -3; +#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -25; // ERR_ALREADY_EXISTS: An object with the specified identifier // already exists. // Example: Attempting to create a file when a file already exists // with that name. -#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -15; +#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -26; // ERR_ALREADY_BOUND: The operation failed because the named entity // is already owned or controlled by another entity. The operation // could succeed later if the current owner releases the entity. -#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -16; - -// ERR_TIMED_OUT: The time limit for the operation elapsed before -// the operation completed. -#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -23; - -// ERR_HANDLE_CLOSED: a handle being waited on was closed -#[allow(unused)] pub const ERR_HANDLE_CLOSED: mx_status_t = -24; - -// ERR_REMOTE_CLOSED: The operation failed because the remote end -// of the subject of the operation was closed. -#[allow(unused)] pub const ERR_REMOTE_CLOSED: mx_status_t = -25; +#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -27; // ERR_UNAVAILABLE: The subject of the operation is currently unable // to perform the operation. // Note: This is used when there's no direct way for the caller to // observe when the subject will be able to perform the operation // and should thus retry. -#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -26; - -// ERR_SHOULD_WAIT: The operation cannot be performed currently but -// potentially could succeed if the caller waits for a prerequisite -// to be satisfied, for example waiting for a handle to be readable -// or writable. -// Example: Attempting to read from a message pipe that has no -// messages waiting but has an open remote will return ERR_SHOULD_WAIT. -// Attempting to read from a message pipe that has no messages waiting -// and has a closed remote end will return ERR_REMOTE_CLOSED. -#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -27; +#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -28; // ======= Permission check errors ======= // ERR_ACCESS_DENIED: The caller did not have permission to perform @@ -312,3 +317,7 @@ pub const LP_CLONE_MXIO_CWD: u32 = 0x0002; #[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50; #[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51; #[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52; +// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit. +#[allow(unused)] pub const ERR_FILE_BIG: mx_status_t = -53; +// ERR_NO_SPACE: Filesystem or device space is exhausted. +#[allow(unused)] pub const ERR_NO_SPACE: mx_status_t = -54; diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 5f1a6c2f746..e9f41009064 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -417,13 +417,27 @@ mod tests { } } + // Android with api less than 21 define sig* functions inline, so it is not + // available for dynamic link. Implementing sigemptyset and sigaddset allow us + // to support older Android version (independent of libc version). + // The following implementations are based on https://git.io/vSkNf + #[cfg(not(target_os = "android"))] extern { + #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] + fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; + #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; } #[cfg(target_os = "android")] + unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { + libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>()); + return 0; + } + + #[cfg(target_os = "android")] unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { use slice; @@ -450,7 +464,7 @@ mod tests { let mut set: libc::sigset_t = mem::uninitialized(); let mut old_set: libc::sigset_t = mem::uninitialized(); - t!(cvt(libc::sigemptyset(&mut set))); + t!(cvt(sigemptyset(&mut set))); t!(cvt(sigaddset(&mut set, libc::SIGINT))); t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set))); diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index a213273aac8..edd322ca6fa 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -193,7 +193,16 @@ impl Command { // need to clean things up now to avoid confusing the program // we're about to run. let mut set: libc::sigset_t = mem::uninitialized(); - t!(cvt(libc::sigemptyset(&mut set))); + if cfg!(target_os = "android") { + // Implementing sigemptyset allow us to support older Android + // versions. See the comment about Android and sig* functions in + // process_common.rs + libc::memset(&mut set as *mut _ as *mut _, + 0, + mem::size_of::<libc::sigset_t>()); + } else { + t!(cvt(libc::sigemptyset(&mut set))); + } t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, ptr::null_mut()))); let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs index a08cec38f73..a1ad94872de 100644 --- a/src/libstd/sys/unix/time.rs +++ b/src/libstd/sys/unix/time.rs @@ -157,7 +157,7 @@ mod inner { pub fn sub_duration(&self, other: &Duration) -> Instant { Instant { t: self.t.checked_sub(dur2intervals(other)) - .expect("overflow when adding duration to instant"), + .expect("overflow when subtracting duration from instant"), } } } diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs index ea322b9822a..e2e405db276 100644 --- a/src/libstd/sys/windows/ext/fs.rs +++ b/src/libstd/sys/windows/ext/fs.rs @@ -188,7 +188,7 @@ pub trait OpenOptionsExt { /// [`CreateFile`]). /// /// If a _new_ file is created because it does not yet exist and - ///`.create(true)` or `.create_new(true)` are specified, the new file is + /// `.create(true)` or `.create_new(true)` are specified, the new file is /// given the attributes declared with `.attributes()`. /// /// If an _existing_ file is opened with `.create(true).truncate(true)`, its diff --git a/src/libstd/sys/windows/ext/process.rs b/src/libstd/sys/windows/ext/process.rs index 1419a4af427..759f055c4b1 100644 --- a/src/libstd/sys/windows/ext/process.rs +++ b/src/libstd/sys/windows/ext/process.rs @@ -104,6 +104,7 @@ pub trait CommandExt { /// Sets the [process creation flags][1] to be passed to `CreateProcess`. /// /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`. + /// /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx #[stable(feature = "windows_process_extensions", since = "1.16.0")] fn creation_flags(&mut self, flags: u32) -> &mut process::Command; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 1afb3728c9d..dfbc1b581ee 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -257,8 +257,13 @@ impl Stdio { // INVALID_HANDLE_VALUE. Stdio::Inherit => { match stdio::get(stdio_id) { - Ok(io) => io.handle().duplicate(0, true, - c::DUPLICATE_SAME_ACCESS), + Ok(io) => { + let io = Handle::new(io.handle()); + let ret = io.duplicate(0, true, + c::DUPLICATE_SAME_ACCESS); + io.into_raw(); + return ret + } Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)), } } diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b1a57c349fb..d72e4b4438b 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -22,42 +22,43 @@ use sys::cvt; use sys::handle::Handle; use sys_common::io::read_to_end_uninitialized; -pub struct NoClose(Option<Handle>); - pub enum Output { - Console(NoClose), - Pipe(NoClose), + Console(c::HANDLE), + Pipe(c::HANDLE), } pub struct Stdin { - handle: Output, utf8: Mutex<io::Cursor<Vec<u8>>>, } -pub struct Stdout(Output); -pub struct Stderr(Output); +pub struct Stdout; +pub struct Stderr; pub fn get(handle: c::DWORD) -> io::Result<Output> { let handle = unsafe { c::GetStdHandle(handle) }; if handle == c::INVALID_HANDLE_VALUE { Err(io::Error::last_os_error()) } else if handle.is_null() { - Err(io::Error::new(io::ErrorKind::Other, - "no stdio handle available for this process")) + Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32)) } else { - let ret = NoClose::new(handle); let mut out = 0; match unsafe { c::GetConsoleMode(handle, &mut out) } { - 0 => Ok(Output::Pipe(ret)), - _ => Ok(Output::Console(ret)), + 0 => Ok(Output::Pipe(handle)), + _ => Ok(Output::Console(handle)), } } } -fn write(out: &Output, data: &[u8]) -> io::Result<usize> { - let handle = match *out { - Output::Console(ref c) => c.get().raw(), - Output::Pipe(ref p) => return p.get().write(data), +fn write(handle: c::DWORD, data: &[u8]) -> io::Result<usize> { + let handle = match try!(get(handle)) { + Output::Console(c) => c, + Output::Pipe(p) => { + let handle = Handle::new(p); + let ret = handle.write(data); + handle.into_raw(); + return ret + } }; + // As with stdin on windows, stdout often can't handle writes of large // sizes. For an example, see #14940. For this reason, don't try to // write the entire output buffer on windows. @@ -93,18 +94,20 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> { impl Stdin { pub fn new() -> io::Result<Stdin> { - get(c::STD_INPUT_HANDLE).map(|handle| { - Stdin { - handle: handle, - utf8: Mutex::new(Cursor::new(Vec::new())), - } + Ok(Stdin { + utf8: Mutex::new(Cursor::new(Vec::new())), }) } pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let handle = match self.handle { - Output::Console(ref c) => c.get().raw(), - Output::Pipe(ref p) => return p.get().read(buf), + let handle = match try!(get(c::STD_INPUT_HANDLE)) { + Output::Console(c) => c, + Output::Pipe(p) => { + let handle = Handle::new(p); + let ret = handle.read(buf); + handle.into_raw(); + return ret + } }; let mut utf8 = self.utf8.lock().unwrap(); // Read more if the buffer is empty @@ -125,11 +128,9 @@ impl Stdin { Ok(utf8) => utf8.into_bytes(), Err(..) => return Err(invalid_encoding()), }; - if let Output::Console(_) = self.handle { - if let Some(&last_byte) = data.last() { - if last_byte == CTRL_Z { - data.pop(); - } + if let Some(&last_byte) = data.last() { + if last_byte == CTRL_Z { + data.pop(); } } *utf8 = Cursor::new(data); @@ -158,11 +159,11 @@ impl<'a> Read for &'a Stdin { impl Stdout { pub fn new() -> io::Result<Stdout> { - get(c::STD_OUTPUT_HANDLE).map(Stdout) + Ok(Stdout) } pub fn write(&self, data: &[u8]) -> io::Result<usize> { - write(&self.0, data) + write(c::STD_OUTPUT_HANDLE, data) } pub fn flush(&self) -> io::Result<()> { @@ -172,11 +173,11 @@ impl Stdout { impl Stderr { pub fn new() -> io::Result<Stderr> { - get(c::STD_ERROR_HANDLE).map(Stderr) + Ok(Stderr) } pub fn write(&self, data: &[u8]) -> io::Result<usize> { - write(&self.0, data) + write(c::STD_ERROR_HANDLE, data) } pub fn flush(&self) -> io::Result<()> { @@ -197,27 +198,12 @@ impl io::Write for Stderr { } } -impl NoClose { - fn new(handle: c::HANDLE) -> NoClose { - NoClose(Some(Handle::new(handle))) - } - - fn get(&self) -> &Handle { self.0.as_ref().unwrap() } -} - -impl Drop for NoClose { - fn drop(&mut self) { - self.0.take().unwrap().into_raw(); - } -} - impl Output { - pub fn handle(&self) -> &Handle { - let nc = match *self { - Output::Console(ref c) => c, - Output::Pipe(ref c) => c, - }; - nc.0.as_ref().unwrap() + pub fn handle(&self) -> c::HANDLE { + match *self { + Output::Console(c) => c, + Output::Pipe(c) => c, + } } } |
