|  | @@ -1,4 +1,5 @@
 | 
											
												
													
														|  |  use c_str::CStr;
 |  |  use c_str::CStr;
 | 
											
												
													
														|  | 
 |  | +use core::ops::Deref;
 | 
											
												
													
														|  |  use header::fcntl::O_CREAT;
 |  |  use header::fcntl::O_CREAT;
 | 
											
												
													
														|  |  use header::unistd::{SEEK_SET, SEEK_CUR, SEEK_END};
 |  |  use header::unistd::{SEEK_SET, SEEK_CUR, SEEK_END};
 | 
											
												
													
														|  |  use io;
 |  |  use io;
 | 
											
										
											
												
													
														|  | @@ -11,48 +12,70 @@ fn last_os_error() -> io::Error {
 | 
											
												
													
														|  |      io::Error::from_raw_os_error(errno)
 |  |      io::Error::from_raw_os_error(errno)
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -pub struct File(c_int);
 |  | 
 | 
											
												
													
														|  | 
 |  | +pub struct File {
 | 
											
												
													
														|  | 
 |  | +    pub fd: c_int,
 | 
											
												
													
														|  | 
 |  | +    /// To avoid self referential FILE struct that needs both a reader and a writer,
 | 
											
												
													
														|  | 
 |  | +    /// make "reference" files that share fd but don't close on drop.
 | 
											
												
													
														|  | 
 |  | +    pub reference: bool
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl File {
 |  |  impl File {
 | 
											
												
													
														|  | 
 |  | +    pub fn new(fd: c_int) -> Self {
 | 
											
												
													
														|  | 
 |  | +        Self {
 | 
											
												
													
														|  | 
 |  | +            fd,
 | 
											
												
													
														|  | 
 |  | +            reference: false
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
 |  |      pub fn open(path: &CStr, oflag: c_int) -> io::Result<Self> {
 | 
											
												
													
														|  |          match Sys::open(path, oflag, 0) {
 |  |          match Sys::open(path, oflag, 0) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  | -            ok => Ok(File(ok)),
 |  | 
 | 
											
												
													
														|  | 
 |  | +            ok => Ok(Self::new(ok)),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
 |  |      pub fn create(path: &CStr, oflag: c_int, mode: mode_t) -> io::Result<Self> {
 | 
											
												
													
														|  |          match Sys::open(path, oflag | O_CREAT, mode) {
 |  |          match Sys::open(path, oflag | O_CREAT, mode) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  | -            ok => Ok(File(ok)),
 |  | 
 | 
											
												
													
														|  | 
 |  | +            ok => Ok(Self::new(ok)),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn sync_all(&self) -> io::Result<()> {
 |  |      pub fn sync_all(&self) -> io::Result<()> {
 | 
											
												
													
														|  | -        match Sys::fsync(self.0) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::fsync(self.fd) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  |              _ok => Ok(()),
 |  |              _ok => Ok(()),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn set_len(&self, size: u64) -> io::Result<()> {
 |  |      pub fn set_len(&self, size: u64) -> io::Result<()> {
 | 
											
												
													
														|  | -        match Sys::ftruncate(self.0, size as off_t) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::ftruncate(self.fd, size as off_t) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  |              _ok => Ok(()),
 |  |              _ok => Ok(()),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      pub fn try_clone(&self) -> io::Result<Self> {
 |  |      pub fn try_clone(&self) -> io::Result<Self> {
 | 
											
												
													
														|  | -        match Sys::dup(self.0) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::dup(self.fd) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  | -            ok => Ok(File(ok)),
 |  | 
 | 
											
												
													
														|  | 
 |  | +            ok => Ok(Self::new(ok)),
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    /// Create a new file pointing to the same underlying descriptor. This file
 | 
											
												
													
														|  | 
 |  | +    /// will know it's a "reference" and won't close the fd. It will, however,
 | 
											
												
													
														|  | 
 |  | +    /// not prevent the original file from closing the fd.
 | 
											
												
													
														|  | 
 |  | +    pub unsafe fn get_ref(&self) -> Self {
 | 
											
												
													
														|  | 
 |  | +        Self {
 | 
											
												
													
														|  | 
 |  | +            fd: self.fd,
 | 
											
												
													
														|  | 
 |  | +            reference: false
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl io::Read for File {
 |  |  impl io::Read for File {
 | 
											
												
													
														|  |      fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 |  |      fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 | 
											
												
													
														|  | -        match Sys::read(self.0, buf) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::read(self.fd, buf) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  |              ok => Ok(ok as usize),
 |  |              ok => Ok(ok as usize),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -61,7 +84,7 @@ impl io::Read for File {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl io::Write for File {
 |  |  impl io::Write for File {
 | 
											
												
													
														|  |      fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
 |  |      fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
 | 
											
												
													
														|  | -        match Sys::write(self.0, buf) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::write(self.fd, buf) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  |              ok => Ok(ok as usize),
 |  |              ok => Ok(ok as usize),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
										
											
												
													
														|  | @@ -80,9 +103,25 @@ impl io::Seek for File {
 | 
											
												
													
														|  |              io::SeekFrom::End(end) => (end as off_t, SEEK_END),
 |  |              io::SeekFrom::End(end) => (end as off_t, SEEK_END),
 | 
											
												
													
														|  |          };
 |  |          };
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -        match Sys::lseek(self.0, offset, whence) {
 |  | 
 | 
											
												
													
														|  | 
 |  | +        match Sys::lseek(self.fd, offset, whence) {
 | 
											
												
													
														|  |              -1 => Err(last_os_error()),
 |  |              -1 => Err(last_os_error()),
 | 
											
												
													
														|  |              ok => Ok(ok as u64),
 |  |              ok => Ok(ok as u64),
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +impl Deref for File {
 | 
											
												
													
														|  | 
 |  | +    type Target = c_int;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    fn deref(&self) -> &Self::Target {
 | 
											
												
													
														|  | 
 |  | +        &self.fd
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +impl Drop for File {
 | 
											
												
													
														|  | 
 |  | +    fn drop(&mut self) {
 | 
											
												
													
														|  | 
 |  | +        if !self.reference {
 | 
											
												
													
														|  | 
 |  | +            let _ = Sys::close(self.fd);
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 |