(index<- )        ./libnative/io/file_unix.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  //! Blocking posix-based file I/O
  12  
  13  use libc::{c_int, c_void};
  14  use libc;
  15  use std::c_str::CString;
  16  use std::io::IoError;
  17  use std::io;
  18  use std::mem;
  19  use std::rt::rtio;
  20  use std::sync::arc::UnsafeArc;
  21  
  22  use io::{IoResult, retry, keep_going};
  23  
  24  pub type fd_t = libc::c_int;
  25  
  26  struct Inner {
  27      fd: fd_t,
  28      close_on_drop: bool,
  29  }
  30  
  31  pub struct FileDesc {
  32      inner: UnsafeArc<Inner>
  33  }
  34  
  35  impl FileDesc {
  36      /// Create a `FileDesc` from an open C file descriptor.
  37      ///
  38      /// The `FileDesc` will take ownership of the specified file descriptor and
  39      /// close it upon destruction if the `close_on_drop` flag is true, otherwise
  40      /// it will not close the file descriptor when this `FileDesc` is dropped.
  41      ///
  42      /// Note that all I/O operations done on this object will be *blocking*, but
  43      /// they do not require the runtime to be active.
  44      pub fn new(fdfd_t, close_on_dropbool) -> FileDesc {
  45          FileDesc { inner: UnsafeArc::new(Inner {
  46              fd: fd,
  47              close_on_drop: close_on_drop
  48          }) }
  49      }
  50  
  51      // FIXME(#10465) these functions should not be public, but anything in
  52      //               native::io wanting to use them is forced to have all the
  53      //               rtio traits in scope
  54      pub fn inner_read(&mut self, buf&mut [u8]) -> Result<uint, IoError> {
  55          let ret = retry(|| unsafe {
  56              libc::read(self.fd(),
  57                         buf.as_mut_ptr() as *mut libc::c_void,
  58                         buf.len() as libc::size_t) as libc::c_int
  59          });
  60          if ret == 0 {
  61              Err(io::standard_error(io::EndOfFile))
  62          } else if ret < 0 {
  63              Err(super::last_error())
  64          } else {
  65              Ok(ret as uint)
  66          }
  67      }
  68      pub fn inner_write(&mut self, buf&[u8]) -> Result<(), IoError> {
  69          let ret = keep_going(buf, |buf, len| {
  70              unsafe {
  71                  libc::write(self.fd(), buf as *libc::c_void,
  72                              len as libc::size_t) as i64
  73              }
  74          });
  75          if ret < 0 {
  76              Err(super::last_error())
  77          } else {
  78              Ok(())
  79          }
  80      }
  81  
  82      pub fn fd(&self) -> fd_t {
  83          // This unsafety is fine because we're just reading off the file
  84          // descriptor, no one is modifying this.
  85          unsafe { (*self.inner.get()).fd }
  86      }
  87  }
  88  
  89  impl io::Reader for FileDesc {
  90      fn read(&mut self, buf&mut [u8]) -> io::IoResult<uint> {
  91          self.inner_read(buf)
  92      }
  93  }
  94  
  95  impl io::Writer for FileDesc {
  96      fn write(&mut self, buf&[u8]) -> io::IoResult<()> {
  97          self.inner_write(buf)
  98      }
  99  }
 100  
 101  impl rtio::RtioFileStream for FileDesc {
 102      fn read(&mut self, buf&mut [u8]) -> Result<int, IoError> {
 103          self.inner_read(buf).map(|i| i as int)
 104      }
 105      fn write(&mut self, buf&[u8]) -> Result<(), IoError> {
 106          self.inner_write(buf)
 107      }
 108      fn pread(&mut self, buf&mut [u8], offsetu64) -> Result<int, IoError> {
 109          match retry(|| unsafe {
 110              libc::pread(self.fd(), buf.as_ptr() as *libc::c_void,
 111                          buf.len() as libc::size_t,
 112                          offset as libc::off_t) as libc::c_int
 113          }) {
 114              -1 => Err(super::last_error()),
 115              n => Ok(n as int)
 116          }
 117      }
 118      fn pwrite(&mut self, buf&[u8], offsetu64) -> Result<(), IoError> {
 119          super::mkerr_libc(retry(|| unsafe {
 120              libc::pwrite(self.fd(), buf.as_ptr() as *libc::c_void,
 121                           buf.len() as libc::size_t, offset as libc::off_t)
 122          } as c_int))
 123      }
 124      fn seek(&mut self, posi64, whenceio::SeekStyle) -> Result<u64, IoError> {
 125          let whence = match whence {
 126              io::SeekSet => libc::SEEK_SET,
 127              io::SeekEnd => libc::SEEK_END,
 128              io::SeekCur => libc::SEEK_CUR,
 129          };
 130          let n = unsafe { libc::lseek(self.fd(), pos as libc::off_t, whence) };
 131          if n < 0 {
 132              Err(super::last_error())
 133          } else {
 134              Ok(n as u64)
 135          }
 136      }
 137      fn tell(&self) -> Result<u64, IoError> {
 138          let n = unsafe { libc::lseek(self.fd(), 0, libc::SEEK_CUR) };
 139          if n < 0 {
 140              Err(super::last_error())
 141          } else {
 142              Ok(n as u64)
 143          }
 144      }
 145      fn fsync(&mut self) -> Result<(), IoError> {
 146          super::mkerr_libc(retry(|| unsafe { libc::fsync(self.fd()) }))
 147      }
 148      fn datasync(&mut self) -> Result<(), IoError> {
 149          return super::mkerr_libc(os_datasync(self.fd()));
 150  
 151          #[cfg(target_os = "macos")]
 152          fn os_datasync(fd: c_int) -> c_int {
 153              unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) }
 154          }
 155          #[cfg(target_os = "linux")]
 156          fn os_datasync(fdc_int) -> c_int {
 157              retry(|| unsafe { libc::fdatasync(fd) })
 158          }
 159          #[cfg(not(target_os = "macos"), not(target_os = "linux"))]
 160          fn os_datasync(fd: c_int) -> c_int {
 161              retry(|| unsafe { libc::fsync(fd) })
 162          }
 163      }
 164      fn truncate(&mut self, offseti64) -> Result<(), IoError> {
 165          super::mkerr_libc(retry(|| unsafe {
 166              libc::ftruncate(self.fd(), offset as libc::off_t)
 167          }))
 168      }
 169  }
 170  
 171  impl rtio::RtioPipe for FileDesc {
 172      fn read(&mut self, buf&mut [u8]) -> Result<uint, IoError> {
 173          self.inner_read(buf)
 174      }
 175      fn write(&mut self, buf&[u8]) -> Result<(), IoError> {
 176          self.inner_write(buf)
 177      }
 178      fn clone(&self) -> Box<rtio::RtioPipe:Send> {
 179          box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
 180      }
 181  
 182      // Only supported on named pipes currently. Note that this doesn't have an
 183      // impact on the std::io primitives, this is never called via
 184      // std::io::PipeStream. If the functionality is exposed in the future, then
 185      // these methods will need to be implemented.
 186      fn close_read(&mut self) -> Result<(), IoError> {
 187          Err(io::standard_error(io::InvalidInput))
 188      }
 189      fn close_write(&mut self) -> Result<(), IoError> {
 190          Err(io::standard_error(io::InvalidInput))
 191      }
 192      fn set_timeout(&mut self, _tOption<u64>) {}
 193      fn set_read_timeout(&mut self, _tOption<u64>) {}
 194      fn set_write_timeout(&mut self, _tOption<u64>) {}
 195  }
 196  
 197  impl rtio::RtioTTY for FileDesc {
 198      fn read(&mut self, buf&mut [u8]) -> Result<uint, IoError> {
 199          self.inner_read(buf)
 200      }
 201      fn write(&mut self, buf&[u8]) -> Result<(), IoError> {
 202          self.inner_write(buf)
 203      }
 204      fn set_raw(&mut self, _rawbool) -> Result<(), IoError> {
 205          Err(super::unimpl())
 206      }
 207      fn get_winsize(&mut self) -> Result<(int, int), IoError> {
 208          Err(super::unimpl())
 209      }
 210      fn isatty(&self) -> bool { false }
 211  }
 212  
 213  impl Drop for Inner {
 214      fn drop(&mut self) {
 215          // closing stdio file handles makes no sense, so never do it. Also, note
 216          // that errors are ignored when closing a file descriptor. The reason
 217          // for this is that if an error occurs we don't actually know if the
 218          // file descriptor was closed or not, and if we retried (for something
 219          // like EINTR), we might close another valid file descriptor (opened
 220          // after we closed ours.
 221          if self.close_on_drop && self.fd > libc::STDERR_FILENO {
 222              let n = unsafe { libc::close(self.fd) };
 223              if n != 0 {
 224                  println!("error {} when closing file descriptor {}", n,
 225                           self.fd);
 226              }
 227          }
 228      }
 229  }
 230  
 231  pub struct CFile {
 232      file: *libc::FILE,
 233      fd: FileDesc,
 234  }
 235  
 236  impl CFile {
 237      /// Create a `CFile` from an open `FILE` pointer.
 238      ///
 239      /// The `CFile` takes ownership of the `FILE` pointer and will close it upon
 240      /// destruction.
 241      pub fn new(file*libc::FILE) -> CFile {
 242          CFile {
 243              file: file,
 244              fd: FileDesc::new(unsafe { libc::fileno(file) }, false)
 245          }
 246      }
 247  
 248      pub fn flush(&mut self) -> Result<(), IoError> {
 249          super::mkerr_libc(retry(|| unsafe { libc::fflush(self.file) }))
 250      }
 251  }
 252  
 253  impl rtio::RtioFileStream for CFile {
 254      fn read(&mut self, buf&mut [u8]) -> Result<int, IoError> {
 255          let ret = keep_going(buf, |buf, len| {
 256              unsafe {
 257                  libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
 258                              self.file) as i64
 259              }
 260          });
 261          if ret == 0 {
 262              Err(io::standard_error(io::EndOfFile))
 263          } else if ret < 0 {
 264              Err(super::last_error())
 265          } else {
 266              Ok(ret as int)
 267          }
 268      }
 269  
 270      fn write(&mut self, buf&[u8]) -> Result<(), IoError> {
 271          let ret = keep_going(buf, |buf, len| {
 272              unsafe {
 273                  libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
 274                              self.file) as i64
 275              }
 276          });
 277          if ret < 0 {
 278              Err(super::last_error())
 279          } else {
 280              Ok(())
 281          }
 282      }
 283  
 284      fn pread(&mut self, buf&mut [u8], offsetu64) -> Result<int, IoError> {
 285          self.flush().and_then(|()| self.fd.pread(buf, offset))
 286      }
 287      fn pwrite(&mut self, buf&[u8], offsetu64) -> Result<(), IoError> {
 288          self.flush().and_then(|()| self.fd.pwrite(buf, offset))
 289      }
 290      fn seek(&mut self, posi64, styleio::SeekStyle) -> Result<u64, IoError> {
 291          let whence = match style {
 292              io::SeekSet => libc::SEEK_SET,
 293              io::SeekEnd => libc::SEEK_END,
 294              io::SeekCur => libc::SEEK_CUR,
 295          };
 296          let n = unsafe { libc::fseek(self.file, pos as libc::c_long, whence) };
 297          if n < 0 {
 298              Err(super::last_error())
 299          } else {
 300              Ok(n as u64)
 301          }
 302      }
 303      fn tell(&self) -> Result<u64, IoError> {
 304          let ret = unsafe { libc::ftell(self.file) };
 305          if ret < 0 {
 306              Err(super::last_error())
 307          } else {
 308              Ok(ret as u64)
 309          }
 310      }
 311      fn fsync(&mut self) -> Result<(), IoError> {
 312          self.flush().and_then(|()| self.fd.fsync())
 313      }
 314      fn datasync(&mut self) -> Result<(), IoError> {
 315          self.flush().and_then(|()| self.fd.fsync())
 316      }
 317      fn truncate(&mut self, offseti64) -> Result<(), IoError> {
 318          self.flush().and_then(|()| self.fd.truncate(offset))
 319      }
 320  }
 321  
 322  impl Drop for CFile {
 323      fn drop(&mut self) {
 324          unsafe { let _ = libc::fclose(self.file); }
 325      }
 326  }
 327  
 328  pub fn open(path: &CString, fmio::FileMode, faio::FileAccess)
 329          -> IoResult<FileDesc> {
 330      let flags = match fm {
 331          io::Open => 0,
 332          io::Append => libc::O_APPEND,
 333          io::Truncate => libc::O_TRUNC,
 334      };
 335      // Opening with a write permission must silently create the file.
 336      let (flags, mode) = match fa {
 337          io::Read => (flags | libc::O_RDONLY, 0),
 338          io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
 339                        libc::S_IRUSR | libc::S_IWUSR),
 340          io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
 341                            libc::S_IRUSR | libc::S_IWUSR),
 342      };
 343  
 344      match retry(|| unsafe { libc::open(path.with_ref(|p| p), flags, mode) }) {
 345          -1 => Err(super::last_error()),
 346          fd => Ok(FileDesc::new(fd, true)),
 347      }
 348  }
 349  
 350  pub fn mkdir(p: &CString, modeio::FilePermission) -> IoResult<()> {
 351      super::mkerr_libc(retry(|| unsafe {
 352          libc::mkdir(p.with_ref(|p| p), mode.bits() as libc::mode_t)
 353      }))
 354  }
 355  
 356  pub fn readdir(p: &CString) -> IoResult<Vec<Path>> {
 357      use libc::{dirent_t};
 358      use libc::{opendir, readdir_r, closedir};
 359  
 360      fn prune(root&CString, dirsVec<Path>) -> Vec<Path> {
 361          let root = unsafe { CString::new(root.with_ref(|p| p), false) };
 362          let root = Path::new(root);
 363  
 364          dirs.move_iter().filter(|path| {
 365              path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
 366          }).map(|path| root.join(path)).collect()
 367      }
 368  
 369      extern {
 370          fn rust_dirent_t_size() -> libc::c_int;
 371          fn rust_list_dir_val(ptr*mut dirent_t) -> *libc::c_char;
 372      }
 373  
 374      let size = unsafe { rust_dirent_t_size() };
 375      let mut buf = Vec::<u8>::with_capacity(size as uint);
 376      let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
 377  
 378      let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) });
 379  
 380      if dir_ptr as uint != 0 {
 381          let mut paths = vec!();
 382          let mut entry_ptr = 0 as *mut dirent_t;
 383          while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
 384              if entry_ptr.is_null() { break }
 385              let cstr = unsafe {
 386                  CString::new(rust_list_dir_val(entry_ptr), false)
 387              };
 388              paths.push(Path::new(cstr));
 389          }
 390          assert_eq!(unsafe { closedir(dir_ptr) }, 0);
 391          Ok(prune(p, paths))
 392      } else {
 393          Err(super::last_error())
 394      }
 395  }
 396  
 397  pub fn unlink(p: &CString) -> IoResult<()> {
 398      super::mkerr_libc(retry(|| unsafe { libc::unlink(p.with_ref(|p| p)) }))
 399  }
 400  
 401  pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
 402      super::mkerr_libc(retry(|| unsafe {
 403          libc::rename(old.with_ref(|p| p), new.with_ref(|p| p))
 404      }))
 405  }
 406  
 407  pub fn chmod(p: &CString, modeio::FilePermission) -> IoResult<()> {
 408      super::mkerr_libc(retry(|| unsafe {
 409          libc::chmod(p.with_ref(|p| p), mode.bits() as libc::mode_t)
 410      }))
 411  }
 412  
 413  pub fn rmdir(p: &CString) -> IoResult<()> {
 414      super::mkerr_libc(retry(|| unsafe {
 415          libc::rmdir(p.with_ref(|p| p))
 416      }))
 417  }
 418  
 419  pub fn chown(p: &CString, uid: int, gid: int) -> IoResult<()> {
 420      super::mkerr_libc(retry(|| unsafe {
 421          libc::chown(p.with_ref(|p| p), uid as libc::uid_t,
 422                      gid as libc::gid_t)
 423      }))
 424  }
 425  
 426  pub fn readlink(p: &CString) -> IoResult<Path> {
 427      let p = p.with_ref(|p| p);
 428      let mut len = unsafe { libc::pathconf(p, libc::_PC_NAME_MAX) };
 429      if len == -1 {
 430          len = 1024; // FIXME: read PATH_MAX from C ffi?
 431      }
 432      let mut bufVec<u8> = Vec::with_capacity(len as uint);
 433      match retry(|| unsafe {
 434          libc::readlink(p, buf.as_ptr() as *mut libc::c_char,
 435                         len as libc::size_t) as libc::c_int
 436      }) {
 437          -1 => Err(super::last_error()),
 438          n => {
 439              assert!(n > 0);
 440              unsafe { buf.set_len(n as uint); }
 441              Ok(Path::new(buf))
 442          }
 443      }
 444  }
 445  
 446  pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
 447      super::mkerr_libc(retry(|| unsafe {
 448          libc::symlink(src.with_ref(|p| p), dst.with_ref(|p| p))
 449      }))
 450  }
 451  
 452  pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
 453      super::mkerr_libc(retry(|| unsafe {
 454          libc::link(src.with_ref(|p| p), dst.with_ref(|p| p))
 455      }))
 456  }
 457  
 458  fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
 459      let path = unsafe { CString::new(path.with_ref(|p| p), false) };
 460  
 461      // FileStat times are in milliseconds
 462      fn mktime(secsu64, nsecsu64) -> u64 { secs * 1000 + nsecs / 1000000 }
 463  
 464      let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
 465          libc::S_IFREG => io::TypeFile,
 466          libc::S_IFDIR => io::TypeDirectory,
 467          libc::S_IFIFO => io::TypeNamedPipe,
 468          libc::S_IFBLK => io::TypeBlockSpecial,
 469          libc::S_IFLNK => io::TypeSymlink,
 470          _ => io::TypeUnknown,
 471      };
 472  
 473      #[cfg(not(target_os = "linux"), not(target_os = "android"))]
 474      fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 }
 475      #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
 476      fn flags(_stat&libc::stat) -> u64 { 0 }
 477  
 478      #[cfg(not(target_os = "linux"), not(target_os = "android"))]
 479      fn gen(stat: &libc::stat) -> u64 { stat.st_gen as u64 }
 480      #[cfg(target_os = "linux")] #[cfg(target_os = "android")]
 481      fn gen(_stat&libc::stat) -> u64 { 0 }
 482  
 483      io::FileStat {
 484          path: Path::new(path),
 485          size: stat.st_size as u64,
 486          kind: kind,
 487          perm: unsafe {
 488              io::FilePermission::from_bits(stat.st_mode as u32) & io::AllPermissions
 489          },
 490          created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
 491          modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
 492          accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
 493          unstable: io::UnstableFileStat {
 494              device: stat.st_dev as u64,
 495              inode: stat.st_ino as u64,
 496              rdev: stat.st_rdev as u64,
 497              nlink: stat.st_nlink as u64,
 498              uid: stat.st_uid as u64,
 499              gid: stat.st_gid as u64,
 500              blksize: stat.st_blksize as u64,
 501              blocks: stat.st_blocks as u64,
 502              flags: flags(stat),
 503              gen: gen(stat),
 504          }
 505      }
 506  }
 507  
 508  pub fn stat(p: &CString) -> IoResult<io::FileStat> {
 509      let mut statlibc::stat = unsafe { mem::uninit() };
 510      match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) {
 511          0 => Ok(mkstat(&stat, p)),
 512          _ => Err(super::last_error()),
 513      }
 514  }
 515  
 516  pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
 517      let mut statlibc::stat = unsafe { mem::uninit() };
 518      match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
 519          0 => Ok(mkstat(&stat, p)),
 520          _ => Err(super::last_error()),
 521      }
 522  }
 523  
 524  pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
 525      let buf = libc::utimbuf {
 526          actime: (atime / 1000) as libc::time_t,
 527          modtime: (mtime / 1000) as libc::time_t,
 528      };
 529      super::mkerr_libc(retry(|| unsafe {
 530          libc::utime(p.with_ref(|p| p), &buf)
 531      }))
 532  }
 533  
 534  #[cfg(test)]
 535  mod tests {
 536      use super::{CFile, FileDesc};
 537      use std::io;
 538      use libc;
 539      use std::os;
 540      use std::rt::rtio::RtioFileStream;
 541  
 542      #[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
 543      #[test]
 544      fn test_file_desc() {
 545          // Run this test with some pipes so we don't have to mess around with
 546          // opening or closing files.
 547          let os::Pipe { input, out } = os::pipe();
 548          let mut reader = FileDesc::new(input, true);
 549          let mut writer = FileDesc::new(out, true);
 550  
 551          writer.inner_write(bytes!("test")).unwrap();
 552          let mut buf = [0u8, ..4];
 553          match reader.inner_read(buf) {
 554              Ok(4) => {
 555                  assert_eq!(buf[0], 't' as u8);
 556                  assert_eq!(buf[1], 'e' as u8);
 557                  assert_eq!(buf[2], 's' as u8);
 558                  assert_eq!(buf[3], 't' as u8);
 559              }
 560              r => fail!("invalid read: {:?}", r)
 561          }
 562  
 563          assert!(writer.inner_read(buf).is_err());
 564          assert!(reader.inner_write(buf).is_err());
 565      }
 566  
 567      #[test]
 568      fn test_cfile() {
 569          unsafe {
 570              let f = libc::tmpfile();
 571              assert!(!f.is_null());
 572              let mut file = CFile::new(f);
 573  
 574              file.write(bytes!("test")).unwrap();
 575              let mut buf = [0u8, ..4];
 576              let _ = file.seek(0, io::SeekSet).unwrap();
 577              match file.read(buf) {
 578                  Ok(4) => {
 579                      assert_eq!(buf[0], 't' as u8);
 580                      assert_eq!(buf[1], 'e' as u8);
 581                      assert_eq!(buf[2], 's' as u8);
 582                      assert_eq!(buf[3], 't' as u8);
 583                  }
 584                  r => fail!("invalid read: {:?}", r)
 585              }
 586          }
 587      }
 588  }


libnative/io/file_unix.rs:462:4-462:4 -fn- definition:
    fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
    let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
        libc::S_IFREG => io::TypeFile,
references:- 3
490:         created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
491:         modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
492:         accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
493:         unstable: io::UnstableFileStat {


libnative/io/file_unix.rs:30:1-30:1 -struct- definition:
pub struct FileDesc {
    inner: UnsafeArc<Inner>
}
references:- 14
44:     pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
45:         FileDesc { inner: UnsafeArc::new(Inner {
46:             fd: fd,
--
178:     fn clone(&self) -> Box<rtio::RtioPipe:Send> {
179:         box FileDesc { inner: self.inner.clone() } as Box<rtio::RtioPipe:Send>
180:     }
--
232:     file: *libc::FILE,
233:     fd: FileDesc,
234: }
--
328: pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
329:         -> IoResult<FileDesc> {
330:     let flags = match fm {
libnative/io/process.rs:
69:     pub fn spawn(config: p::ProcessConfig)
70:         -> Result<(Process, Vec<Option<file::FileDesc>>), io::IoError>
71:     {
--
551:             fn fail(output: &mut file::FileDesc) -> ! {
552:                 let errno = os::errno();
libnative/io/file_unix.rs:
101: impl rtio::RtioFileStream for FileDesc {
102:     fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {


libnative/io/file_unix.rs:25:1-25:1 -struct- definition:
struct Inner {
    fd: fd_t,
    close_on_drop: bool,
references:- 3
213: impl Drop for Inner {
214:     fn drop(&mut self) {


libnative/io/file_unix.rs:230:1-230:1 -struct- definition:
pub struct CFile {
    file: *libc::FILE,
    fd: FileDesc,
references:- 5
241:     pub fn new(file: *libc::FILE) -> CFile {
242:         CFile {
243:             file: file,
--
322: impl Drop for CFile {
323:     fn drop(&mut self) {


libnative/io/file_unix.rs:457:1-457:1 -fn- definition:
fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
    let path = unsafe { CString::new(path.with_ref(|p| p), false) };
    // FileStat times are in milliseconds
references:- 2
518:     match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
519:         0 => Ok(mkstat(&stat, p)),
520:         _ => Err(super::last_error()),


libnative/io/file_unix.rs:23:1-23:1 -NK_AS_STR_TODO- definition:
pub type fd_t = libc::c_int;
struct Inner {
    fd: fd_t,
references:- 10
82:     pub fn fd(&self) -> fd_t {
83:         // This unsafety is fine because we're just reading off the file
libnative/io/pipe_unix.rs:
27: fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
28:     match unsafe { libc::socket(libc::AF_UNIX, ty, 0) } {
--
64: impl Inner {
65:     fn new(fd: fd_t) -> Inner {
66:         Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
--
241: impl UnixAcceptor {
242:     fn fd(&self) -> fd_t { self.listener.fd() }
libnative/io/net.rs:
libnative/io/pipe_unix.rs:
59: struct Inner {
60:     fd: fd_t,
61:     lock: mutex::NativeMutex,