(index<- )        ./libnative/io/mod.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 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  //! Native thread-blocking I/O implementation
  12  //!
  13  //! This module contains the implementation of native thread-blocking
  14  //! implementations of I/O on all platforms. This module is not intended to be
  15  //! used directly, but rather the rust runtime will fall back to using it if
  16  //! necessary.
  17  //!
  18  //! Rust code normally runs inside of green tasks with a local scheduler using
  19  //! asynchronous I/O to cooperate among tasks. This model is not always
  20  //! available, however, and that's where these native implementations come into
  21  //! play. The only dependencies of these modules are the normal system libraries
  22  //! that you would find on the respective platform.
  23  
  24  use libc::c_int;
  25  use libc;
  26  use std::c_str::CString;
  27  use std::io;
  28  use std::io::IoError;
  29  use std::io::net::ip::SocketAddr;
  30  use std::io::process::ProcessConfig;
  31  use std::io::signal::Signum;
  32  use std::os;
  33  use std::rt::rtio;
  34  use std::rt::rtio::{RtioTcpStream, RtioTcpListener, RtioUdpSocket};
  35  use std::rt::rtio::{RtioUnixListener, RtioPipe, RtioFileStream, RtioProcess};
  36  use std::rt::rtio::{RtioSignal, RtioTTY, CloseBehavior, RtioTimer};
  37  use ai = std::io::net::addrinfo;
  38  
  39  // Local re-exports
  40  pub use self::file::FileDesc;
  41  pub use self::process::Process;
  42  
  43  // Native I/O implementations
  44  pub mod addrinfo;
  45  pub mod net;
  46  pub mod process;
  47  mod util;
  48  
  49  #[cfg(unix)]
  50  #[path = "file_unix.rs"]
  51  pub mod file;
  52  #[cfg(windows)]
  53  #[path = "file_win32.rs"]
  54  pub mod file;
  55  
  56  #[cfg(target_os = "macos")]
  57  #[cfg(target_os = "freebsd")]
  58  #[cfg(target_os = "android")]
  59  #[cfg(target_os = "linux")]
  60  #[path = "timer_unix.rs"]
  61  pub mod timer;
  62  
  63  #[cfg(target_os = "win32")]
  64  #[path = "timer_win32.rs"]
  65  pub mod timer;
  66  
  67  #[cfg(unix)]
  68  #[path = "pipe_unix.rs"]
  69  pub mod pipe;
  70  
  71  #[cfg(windows)]
  72  #[path = "pipe_win32.rs"]
  73  pub mod pipe;
  74  
  75  #[cfg(unix)]    #[path = "c_unix.rs"]  mod c;
  76  #[cfg(windows)] #[path = "c_win32.rs"] mod c;
  77  
  78  mod timer_helper;
  79  
  80  pub type IoResult<T> = Result<T, IoError>;
  81  
  82  fn unimpl() -> IoError {
  83      IoError {
  84          kind: io::IoUnavailable,
  85          desc: "unimplemented I/O interface",
  86          detail: None,
  87      }
  88  }
  89  
  90  fn last_error() -> IoError {
  91      IoError::last_error()
  92  }
  93  
  94  // unix has nonzero values as errors
  95  fn mkerr_libc(retlibc::c_int) -> IoResult<()> {
  96      if ret != 0 {
  97          Err(last_error())
  98      } else {
  99          Ok(())
 100      }
 101  }
 102  
 103  // windows has zero values as errors
 104  #[cfg(windows)]
 105  fn mkerr_winbool(ret: libc::c_int) -> IoResult<(){
 106      if ret == 0 {
 107          Err(last_error())
 108      } else {
 109          Ok(())
 110      }
 111  }
 112  
 113  #[cfg(windows)]
 114  #[inline]
 115  fn retry(f: || -> libc::c_int) -> libc::c_int {
 116      loop {
 117          match f() {
 118              -1 if os::errno() as int == libc::WSAEINTR as int => {}
 119              n => return n,
 120          }
 121      }
 122  }
 123  
 124  #[cfg(unix)]
 125  #[inline]
 126  fn retry(f: || -> libc::c_int) -> libc::c_int {
 127      loop {
 128          match f() {
 129              -1 if os::errno() as int == libc::EINTR as int => {}
 130              n => return n,
 131          }
 132      }
 133  }
 134  
 135  fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
 136      let origamt = data.len();
 137      let mut data = data.as_ptr();
 138      let mut amt = origamt;
 139      while amt > 0 {
 140          let ret = retry(|| f(data, amt) as libc::c_int);
 141          if ret == 0 {
 142              break
 143          } else if ret != -1 {
 144              amt -= ret as uint;
 145              data = unsafe { data.offset(ret as int) };
 146          } else {
 147              return ret as i64;
 148          }
 149      }
 150      return (origamt - amt) as i64;
 151  }
 152  
 153  /// Implementation of rt::rtio's IoFactory trait to generate handles to the
 154  /// native I/O functionality.
 155  pub struct IoFactory {
 156      cannot_construct_outside_of_this_module: ()
 157  }
 158  
 159  impl IoFactory {
 160      pub fn new() -> IoFactory {
 161          net::init();
 162          IoFactory { cannot_construct_outside_of_this_module: () }
 163      }
 164  }
 165  
 166  impl rtio::IoFactory for IoFactory {
 167      // networking
 168      fn tcp_connect(&mut self, addrSocketAddr,
 169                     timeoutOption<u64>) -> IoResult<Box<RtioTcpStream:Send>> {
 170          net::TcpStream::connect(addr, timeout).map(|s| {
 171              box s as Box<RtioTcpStream:Send>
 172          })
 173      }
 174      fn tcp_bind(&mut self, addrSocketAddr)
 175                  -> IoResult<Box<RtioTcpListener:Send>> {
 176          net::TcpListener::bind(addr).map(|s| {
 177              box s as Box<RtioTcpListener:Send>
 178          })
 179      }
 180      fn udp_bind(&mut self, addrSocketAddr)
 181                  -> IoResult<Box<RtioUdpSocket:Send>> {
 182          net::UdpSocket::bind(addr).map(|u| box u as Box<RtioUdpSocket:Send>)
 183      }
 184      fn unix_bind(&mut self, path&CString)
 185                   -> IoResult<Box<RtioUnixListener:Send>> {
 186          pipe::UnixListener::bind(path).map(|s| {
 187              box s as Box<RtioUnixListener:Send>
 188          })
 189      }
 190      fn unix_connect(&mut self, path&CString,
 191                      timeoutOption<u64>) -> IoResult<Box<RtioPipe:Send>> {
 192          pipe::UnixStream::connect(path, timeout).map(|s| {
 193              box s as Box<RtioPipe:Send>
 194          })
 195      }
 196      fn get_host_addresses(&mut self, hostOption<&str>, servnameOption<&str>,
 197                            hintOption<ai::Hint>) -> IoResult<Vec<ai::Info>> {
 198          addrinfo::GetAddrInfoRequest::run(host, servname, hint)
 199      }
 200  
 201      // filesystem operations
 202      fn fs_from_raw_fd(&mut self, fdc_int, closeCloseBehavior)
 203                        -> Box<RtioFileStream:Send> {
 204          let close = match close {
 205              rtio::CloseSynchronously | rtio::CloseAsynchronously => true,
 206              rtio::DontClose => false
 207          };
 208          box file::FileDesc::new(fd, close) as Box<RtioFileStream:Send>
 209      }
 210      fn fs_open(&mut self, path&CString, fmio::FileMode, faio::FileAccess)
 211          -> IoResult<Box<RtioFileStream:Send>> {
 212          file::open(path, fm, fa).map(|fd| box fd as Box<RtioFileStream:Send>)
 213      }
 214      fn fs_unlink(&mut self, path&CString) -> IoResult<()> {
 215          file::unlink(path)
 216      }
 217      fn fs_stat(&mut self, path&CString) -> IoResult<io::FileStat> {
 218          file::stat(path)
 219      }
 220      fn fs_mkdir(&mut self, path&CString,
 221                  modeio::FilePermission) -> IoResult<()> {
 222          file::mkdir(path, mode)
 223      }
 224      fn fs_chmod(&mut self, path&CString,
 225                  modeio::FilePermission) -> IoResult<()> {
 226          file::chmod(path, mode)
 227      }
 228      fn fs_rmdir(&mut self, path&CString) -> IoResult<()> {
 229          file::rmdir(path)
 230      }
 231      fn fs_rename(&mut self, path&CString, to&CString) -> IoResult<()> {
 232          file::rename(path, to)
 233      }
 234      fn fs_readdir(&mut self, path&CString, _flagsc_int) -> IoResult<Vec<Path>> {
 235          file::readdir(path)
 236      }
 237      fn fs_lstat(&mut self, path&CString) -> IoResult<io::FileStat> {
 238          file::lstat(path)
 239      }
 240      fn fs_chown(&mut self, path&CString, uidint, gidint) -> IoResult<()> {
 241          file::chown(path, uid, gid)
 242      }
 243      fn fs_readlink(&mut self, path&CString) -> IoResult<Path> {
 244          file::readlink(path)
 245      }
 246      fn fs_symlink(&mut self, src&CString, dst&CString) -> IoResult<()> {
 247          file::symlink(src, dst)
 248      }
 249      fn fs_link(&mut self, src&CString, dst&CString) -> IoResult<()> {
 250          file::link(src, dst)
 251      }
 252      fn fs_utime(&mut self, src&CString, atimeu64,
 253                  mtimeu64) -> IoResult<()> {
 254          file::utime(src, atime, mtime)
 255      }
 256  
 257      // misc
 258      fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>> {
 259          timer::Timer::new().map(|t| box t as Box<RtioTimer:Send>)
 260      }
 261      fn spawn(&mut self, configProcessConfig)
 262              -> IoResult<(Box<RtioProcess:Send>,
 263                           Vec<Option<Box<RtioPipe:Send>>>)> {
 264          process::Process::spawn(config).map(|(p, io)| {
 265              (box p as Box<RtioProcess:Send>,
 266               io.move_iter().map(|p| p.map(|p| {
 267                   box p as Box<RtioPipe:Send>
 268               })).collect())
 269          })
 270      }
 271      fn kill(&mut self, pidlibc::pid_t, signumint) -> IoResult<()> {
 272          process::Process::kill(pid, signum)
 273      }
 274      fn pipe_open(&mut self, fdc_int) -> IoResult<Box<RtioPipe:Send>> {
 275          Ok(box file::FileDesc::new(fd, true) as Box<RtioPipe:Send>)
 276      }
 277      fn tty_open(&mut self, fdc_int, _readablebool)
 278                  -> IoResult<Box<RtioTTY:Send>> {
 279          if unsafe { libc::isatty(fd) } != 0 {
 280              Ok(box file::FileDesc::new(fd, true) as Box<RtioTTY:Send>)
 281          } else {
 282              Err(IoError {
 283                  kind: io::MismatchedFileTypeForOperation,
 284                  desc: "file descriptor is not a TTY",
 285                  detail: None,
 286              })
 287          }
 288      }
 289      fn signal(&mut self, _signalSignum, _channelSender<Signum>)
 290                -> IoResult<Box<RtioSignal:Send>> {
 291          Err(unimpl())
 292      }
 293  }


libnative/io/mod.rs:154:30-154:30 -struct- definition:
/// native I/O functionality.
pub struct IoFactory {
    cannot_construct_outside_of_this_module: ()
references:- 5
166: impl rtio::IoFactory for IoFactory {
167:     // networking
libnative/task.rs:
112:     awoken: bool,      // used to prevent spurious wakeups
113:     io: io::IoFactory, // local I/O factory
libnative/io/mod.rs:
161:         net::init();
162:         IoFactory { cannot_construct_outside_of_this_module: () }
163:     }


libnative/io/mod.rs:134:1-134:1 -fn- definition:
fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 {
    let origamt = data.len();
    let mut data = data.as_ptr();
references:- 4
libnative/io/net.rs:
845:         if write_everything {
846:             ret = keep_going(buf, |inner, len| {
847:                 written = buf.len() - len;
libnative/io/file_unix.rs:
270:     fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
271:         let ret = keep_going(buf, |buf, len| {
272:             unsafe {


libnative/io/mod.rs:89:1-89:1 -fn- definition:
fn last_error() -> IoError {
    IoError::last_error()
}
references:- 27
96:     if ret != 0 {
97:         Err(last_error())
98:     } else {
libnative/io/net.rs:
144: fn last_error() -> io::IoError {
145:     super::last_error()
146: }
libnative/io/process.rs:
835:             0 => None,
836:             n => fail!("unknown waitpid error `{}`: {}", n, super::last_error()),
837:         }
libnative/io/util.rs:
109:         -1 => Err(last_error()),
110:         _ => Ok(()),
libnative/io/file_unix.rs:
113:         }) {
114:             -1 => Err(super::last_error()),
115:             n => Ok(n as int)
--
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)),
--
392:     } else {
393:         Err(super::last_error())
394:     }
--
519:         0 => Ok(mkstat(&stat, p)),
520:         _ => Err(super::last_error()),
521:     }
libnative/io/pipe_unix.rs:
83:             match retry(|| unsafe { libc::connect(inner.fd, addrp, len) }) {
84:                 -1 => Err(super::last_error()),
85:                 _  => Ok(inner)
--
221:         match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } {
222:             -1 => Err(super::last_error()),
223:             _ => Ok(UnixAcceptor { listener: self, deadline: 0 })
--
256:         }) {
257:             -1 => Err(super::last_error()),
258:             fd => Ok(UnixStream::new(UnsafeArc::new(Inner::new(fd))))
libnative/io/util.rs:
163:     }) {
164:         -1 => Err(last_error()),
165:         0 => Err(timeout("timed out")),


libnative/io/mod.rs:79:1-79:1 -NK_AS_STR_TODO- definition:
pub type IoResult<T> = Result<T, IoError>;
fn unimpl() -> IoError {
    IoError {
references:- 103
libnative/io/net.rs:
libnative/io/process.rs:
libnative/io/file_unix.rs:
libnative/io/timer_unix.rs:
libnative/io/pipe_unix.rs:
libnative/io/net.rs:


libnative/io/mod.rs:81:1-81:1 -fn- definition:
fn unimpl() -> IoError {
    IoError {
        kind: io::IoUnavailable,
references:- 4
290:               -> IoResult<Box<RtioSignal:Send>> {
291:         Err(unimpl())
292:     }
libnative/io/process.rs:
73:         if config.extra_io.len() > 0 {
74:             return Err(super::unimpl());
75:         }
libnative/io/file_unix.rs:
204:     fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
205:         Err(super::unimpl())
206:     }
207:     fn get_winsize(&mut self) -> Result<(int, int), IoError> {
208:         Err(super::unimpl())
209:     }


libnative/io/mod.rs:94:37-94:37 -fn- definition:
// unix has nonzero values as errors
fn mkerr_libc(ret: libc::c_int) -> IoResult<()> {
    if ret != 0 {
references:- 20
libnative/io/net.rs:
396:     fn close_write(&mut self) -> IoResult<()> {
397:         super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
398:     }
399:     fn close_read(&mut self) -> IoResult<()> {
400:         super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
401:     }
libnative/io/process.rs:
235:     let r = libc::funcs::posix88::signal::kill(pid, signal as c_int);
236:     super::mkerr_libc(r)
237: }
libnative/io/util.rs:
57:     let set = nb as libc::c_int;
58:     super::mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
59: }
libnative/io/file_unix.rs:
164:     fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
165:         super::mkerr_libc(retry(|| unsafe {
166:             libc::ftruncate(self.fd(), offset as libc::off_t)
--
413: pub fn rmdir(p: &CString) -> IoResult<()> {
414:     super::mkerr_libc(retry(|| unsafe {
415:         libc::rmdir(p.with_ref(|p| p))
--
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,
--
528:     };
529:     super::mkerr_libc(retry(|| unsafe {
530:         libc::utime(p.with_ref(|p| p), &buf)
libnative/io/pipe_unix.rs:
183:     fn close_write(&mut self) -> IoResult<()> {
184:         super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
185:     }
186:     fn close_read(&mut self) -> IoResult<()> {
187:         super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
188:     }
libnative/io/file_unix.rs:
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))


libnative/io/mod.rs:125:10-125:10 -fn- definition:
fn retry(f: || -> libc::c_int) -> libc::c_int {
    loop {
        match f() {
references:- 37
libnative/io/net.rs:
libnative/io/process.rs:
libnative/io/util.rs:
libnative/io/file_unix.rs:
libnative/io/pipe_unix.rs:
libnative/io/process.rs: