1 use std::fs::{File, OpenOptions}; 2 use std::io; 3 use std::os::unix::fs::MetadataExt; 4 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; 5 use std::path::Path; 6 7 #[derive(Debug)] 8 pub struct Handle { 9 file: Option<File>, 10 // If is_std is true, then we don't drop the corresponding File since it 11 // will close the handle. 12 is_std: bool, 13 dev: u64, 14 ino: u64, 15 } 16 17 impl Drop for Handle { drop(&mut self)18 fn drop(&mut self) { 19 if self.is_std { 20 self.file.take().unwrap().into_raw_fd(); 21 } 22 } 23 } 24 25 impl Eq for Handle {} 26 27 impl PartialEq for Handle { eq(&self, other: &Handle) -> bool28 fn eq(&self, other: &Handle) -> bool { 29 (self.dev, self.ino) == (other.dev, other.ino) 30 } 31 } 32 33 impl AsRawFd for ::Handle { as_raw_fd(&self) -> RawFd34 fn as_raw_fd(&self) -> RawFd { 35 self.0.file.as_ref().take().unwrap().as_raw_fd() 36 } 37 } 38 39 impl IntoRawFd for ::Handle { into_raw_fd(mut self) -> RawFd40 fn into_raw_fd(mut self) -> RawFd { 41 self.0.file.take().unwrap().into_raw_fd() 42 } 43 } 44 45 impl Handle { from_path<P: AsRef<Path>>(p: P) -> io::Result<Handle>46 pub fn from_path<P: AsRef<Path>>(p: P) -> io::Result<Handle> { 47 Handle::from_file(try!(OpenOptions::new().read(true).open(p))) 48 } 49 from_file(file: File) -> io::Result<Handle>50 pub fn from_file(file: File) -> io::Result<Handle> { 51 let md = try!(file.metadata()); 52 Ok(Handle { 53 file: Some(file), 54 is_std: false, 55 dev: md.dev(), 56 ino: md.ino(), 57 }) 58 } 59 from_std(file: File) -> io::Result<Handle>60 pub fn from_std(file: File) -> io::Result<Handle> { 61 Handle::from_file(file).map(|mut h| { 62 h.is_std = true; 63 h 64 }) 65 } 66 stdin() -> io::Result<Handle>67 pub fn stdin() -> io::Result<Handle> { 68 Handle::from_std(unsafe { File::from_raw_fd(0) }) 69 } 70 stdout() -> io::Result<Handle>71 pub fn stdout() -> io::Result<Handle> { 72 Handle::from_std(unsafe { File::from_raw_fd(1) }) 73 } 74 stderr() -> io::Result<Handle>75 pub fn stderr() -> io::Result<Handle> { 76 Handle::from_std(unsafe { File::from_raw_fd(2) }) 77 } 78 as_file(&self) -> &File79 pub fn as_file(&self) -> &File { 80 self.file.as_ref().take().unwrap() 81 } 82 as_file_mut(&mut self) -> &mut File83 pub fn as_file_mut(&mut self) -> &mut File { 84 self.file.as_mut().take().unwrap() 85 } 86 dev(&self) -> u6487 pub fn dev(&self) -> u64 { 88 self.dev 89 } 90 ino(&self) -> u6491 pub fn ino(&self) -> u64 { 92 self.ino 93 } 94 } 95