1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Defines interfaces and methods for doing OS agnostic file IO operations.

mod file_desc_wrapper;
mod permissions;
mod pipe;

use IntoInner;
use sys;
use std::io::{Read, Result, Seek, SeekFrom, Write};
use std::process::Stdio;

pub use self::file_desc_wrapper::FileDescWrapper;
pub use self::permissions::Permissions;
pub use self::pipe::Pipe;
pub use sys::io::getpid;

/// A wrapper around an owned OS file primitive. The wrapper
/// allows reading from or writing to the OS file primitive, and
/// will close it once it goes out of scope.
#[derive(Debug, PartialEq, Eq)]
pub struct FileDesc(sys::io::RawIo);

impl FileDesc {
    #[cfg(unix)]
    /// Takes ownership of and wraps an OS file primitive.
    pub unsafe fn new(fd: ::std::os::unix::io::RawFd) -> Self {
        Self::from_inner(sys::io::RawIo::new(fd))
    }

    #[cfg(windows)]
    /// Takes ownership of and wraps an OS file primitive.
    pub unsafe fn new(handle: ::std::os::windows::io::RawHandle) -> Self {
        Self::from_inner(sys::io::RawIo::new(handle))
    }

    /// Duplicates the underlying OS file primitive.
    pub fn duplicate(&self) -> Result<Self> {
        Ok(Self::from_inner(try!(self.inner().duplicate())))
    }

    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        self.inner().read_inner(buf)
    }

    fn write(&self, buf: &[u8]) -> Result<usize> {
        self.inner().write_inner(buf)
    }

    fn flush(&self) -> Result<()> {
        self.inner().flush_inner()
    }

    fn seek(&self, pos: SeekFrom) -> Result<u64> {
        self.inner().seek(pos)
    }
}

impl IntoInner for FileDesc {
    type Inner = sys::io::RawIo;

    fn inner(&self) -> &Self::Inner {
        &self.0
    }

    fn into_inner(self) -> Self::Inner {
        self.0
    }

    fn from_inner(inner: Self::Inner) -> Self {
        FileDesc(inner)
    }
}

impl Into<Stdio> for FileDesc {
    fn into(self) -> Stdio { self.into_inner().into() }
}

impl Read for FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        FileDesc::read(self, buf)
    }
}

impl<'a> Read for &'a FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        FileDesc::read(self, buf)
    }
}

impl Write for FileDesc {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        FileDesc::write(self, buf)
    }

    fn flush(&mut self) -> Result<()> {
        FileDesc::flush(self)
    }
}

impl<'a> Write for &'a FileDesc {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        FileDesc::write(self, buf)
    }

    fn flush(&mut self) -> Result<()> {
        FileDesc::flush(self)
    }
}

impl Seek for FileDesc {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        FileDesc::seek(self, pos)
    }
}

impl<'a> Seek for &'a FileDesc {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
        FileDesc::seek(self, pos)
    }
}

/// Duplicates handles for (stdin, stdout, stderr) and returns them in that order.
pub(crate) fn dup_stdio() -> Result<(FileDesc, FileDesc, FileDesc)> {
    let (stdin, stdout, stderr) = try!(sys::io::dup_stdio());
    Ok((
        FileDesc::from_inner(stdin),
        FileDesc::from_inner(stdout),
        FileDesc::from_inner(stderr)
    ))
}