(index<- )        ./libstd/rt/uv/file.rs

   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  use prelude::*;
  12  use ptr::null;
  13  use libc::c_void;
  14  use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
  15               status_to_maybe_uv_error, UvError};
  16  use rt::uv::uvll;
  17  use rt::uv::uvll::*;
  18  use super::super::io::support::PathLike;
  19  use cast::transmute;
  20  use libc;
  21  use libc::{c_int};
  22  use option::{None, Some, Option};
  23  
  24  pub struct FsRequest(*uvll::uv_fs_t);
  25  impl Request for FsRequest {}
  26  
  27  pub struct RequestData {
  28      complete_cb: Option<FsCallback>
  29  }
  30  
  31  impl FsRequest {
  32      pub fn new() -> FsRequest {
  33          let fs_req = unsafe { malloc_req(UV_FS) };
  34          assert!(fs_req.is_not_null());
  35          let fs_reqFsRequest = NativeHandle::from_native_handle(fs_req);
  36          fs_req
  37      }
  38  
  39      pub fn open<P: PathLike>(self, loop_&Loop, path&P, flagsint, modeint,
  40                 cbFsCallback) {
  41          let complete_cb_ptr = {
  42              let mut me = self;
  43              me.req_boilerplate(Some(cb))
  44          };
  45          path.path_as_str(|p| {
  46              p.with_c_str(|p| unsafe {
  47              uvll::fs_open(loop_.native_handle(),
  48                            self.native_handle(), p, flags, mode, complete_cb_ptr)
  49              })
  50          });
  51      }
  52  
  53      pub fn open_sync<P: PathLike>(self, loop_&Loop, path&P,
  54                                    flagsint, modeint) -> Result<c_int, UvError> {
  55          let complete_cb_ptr = {
  56              let mut me = self;
  57              me.req_boilerplate(None)
  58          };
  59          let result = path.path_as_str(|p| {
  60              p.with_c_str(|p| unsafe {
  61              uvll::fs_open(loop_.native_handle(),
  62                      self.native_handle(), p, flags, mode, complete_cb_ptr)
  63              })
  64          });
  65          self.sync_cleanup(result)
  66      }
  67  
  68      pub fn unlink<P: PathLike>(self, loop_&Loop, path&P, cbFsCallback) {
  69          let complete_cb_ptr = {
  70              let mut me = self;
  71              me.req_boilerplate(Some(cb))
  72          };
  73          path.path_as_str(|p| {
  74              p.with_c_str(|p| unsafe {
  75                  uvll::fs_unlink(loop_.native_handle(),
  76                                self.native_handle(), p, complete_cb_ptr)
  77              })
  78          });
  79      }
  80  
  81      pub fn unlink_sync<P: PathLike>(self, loop_&Loop, path&P)
  82        -> Result<c_int, UvError> {
  83          let complete_cb_ptr = {
  84              let mut me = self;
  85              me.req_boilerplate(None)
  86          };
  87          let result = path.path_as_str(|p| {
  88              p.with_c_str(|p| unsafe {
  89                  uvll::fs_unlink(loop_.native_handle(),
  90                                self.native_handle(), p, complete_cb_ptr)
  91              })
  92          });
  93          self.sync_cleanup(result)
  94      }
  95  
  96      pub fn stat<P: PathLike>(self, loop_&Loop, path&P, cbFsCallback) {
  97          let complete_cb_ptr = {
  98              let mut me = self;
  99              me.req_boilerplate(Some(cb))
 100          };
 101          path.path_as_str(|p| {
 102              p.with_c_str(|p| unsafe {
 103                  uvll::fs_stat(loop_.native_handle(),
 104                                self.native_handle(), p, complete_cb_ptr)
 105              })
 106          });
 107      }
 108  
 109      pub fn write(self, loop_&Loop, fdc_int, bufBuf, offseti64, cbFsCallback) {
 110          let complete_cb_ptr = {
 111              let mut me = self;
 112              me.req_boilerplate(Some(cb))
 113          };
 114          let base_ptr = buf.base as *c_void;
 115          let len = buf.len as uint;
 116          unsafe {
 117              uvll::fs_write(loop_.native_handle(), self.native_handle(),
 118                             fd, base_ptr,
 119                             len, offset, complete_cb_ptr)
 120          };
 121      }
 122      pub fn write_sync(self, loop_&Loop, fdc_int, bufBuf, offseti64)
 123            -> Result<c_int, UvError> {
 124          let complete_cb_ptr = {
 125              let mut me = self;
 126              me.req_boilerplate(None)
 127          };
 128          let base_ptr = buf.base as *c_void;
 129          let len = buf.len as uint;
 130          let result = unsafe {
 131              uvll::fs_write(loop_.native_handle(), self.native_handle(),
 132                             fd, base_ptr,
 133                             len, offset, complete_cb_ptr)
 134          };
 135          self.sync_cleanup(result)
 136      }
 137  
 138      pub fn read(self, loop_&Loop, fdc_int, bufBuf, offseti64, cbFsCallback) {
 139          let complete_cb_ptr = {
 140              let mut me = self;
 141              me.req_boilerplate(Some(cb))
 142          };
 143          let buf_ptr = buf.base as *c_void;
 144          let len = buf.len as uint;
 145          unsafe {
 146              uvll::fs_read(loop_.native_handle(), self.native_handle(),
 147                             fd, buf_ptr,
 148                             len, offset, complete_cb_ptr)
 149          };
 150      }
 151      pub fn read_sync(self, loop_&Loop, fdc_int, bufBuf, offseti64)
 152            -> Result<c_int, UvError> {
 153          let complete_cb_ptr = {
 154              let mut me = self;
 155              me.req_boilerplate(None)
 156          };
 157          let buf_ptr = buf.base as *c_void;
 158          let len = buf.len as uint;
 159          let result = unsafe {
 160              uvll::fs_read(loop_.native_handle(), self.native_handle(),
 161                             fd, buf_ptr,
 162                             len, offset, complete_cb_ptr)
 163          };
 164          self.sync_cleanup(result)
 165      }
 166  
 167      pub fn close(self, loop_&Loop, fdc_int, cbFsCallback) {
 168          let complete_cb_ptr = {
 169              let mut me = self;
 170              me.req_boilerplate(Some(cb))
 171          };
 172          unsafe {
 173              uvll::fs_close(loop_.native_handle(), self.native_handle(),
 174                             fd, complete_cb_ptr)
 175          };
 176      }
 177      pub fn close_sync(self, loop_&Loop, fdc_int) -> Result<c_int, UvError> {
 178          let complete_cb_ptr = {
 179              let mut me = self;
 180              me.req_boilerplate(None)
 181          };
 182          let result = unsafe {
 183              uvll::fs_close(loop_.native_handle(), self.native_handle(),
 184                             fd, complete_cb_ptr)
 185          };
 186          self.sync_cleanup(result)
 187      }
 188  
 189      pub fn mkdir<P: PathLike>(self, loop_&Loop, path&P, modeint, cbFsCallback) {
 190          let complete_cb_ptr = {
 191              let mut me = self;
 192              me.req_boilerplate(Some(cb))
 193          };
 194          path.path_as_str(|p| {
 195              p.with_c_str(|p| unsafe {
 196              uvll::fs_mkdir(loop_.native_handle(),
 197                            self.native_handle(), p, mode, complete_cb_ptr)
 198              })
 199          });
 200      }
 201  
 202      pub fn rmdir<P: PathLike>(self, loop_&Loop, path&P, cbFsCallback) {
 203          let complete_cb_ptr = {
 204              let mut me = self;
 205              me.req_boilerplate(Some(cb))
 206          };
 207          path.path_as_str(|p| {
 208              p.with_c_str(|p| unsafe {
 209              uvll::fs_rmdir(loop_.native_handle(),
 210                            self.native_handle(), p, complete_cb_ptr)
 211              })
 212          });
 213      }
 214  
 215      pub fn readdir<P: PathLike>(self, loop_&Loop, path&P,
 216                                  flagsc_int, cbFsCallback) {
 217          let complete_cb_ptr = {
 218              let mut me = self;
 219              me.req_boilerplate(Some(cb))
 220          };
 221          path.path_as_str(|p| {
 222              p.with_c_str(|p| unsafe {
 223              uvll::fs_readdir(loop_.native_handle(),
 224                            self.native_handle(), p, flags, complete_cb_ptr)
 225              })
 226          });
 227      }
 228  
 229      // accessors/utility funcs
 230      fn sync_cleanup(self, resultc_int)
 231            -> Result<c_int, UvError> {
 232          self.cleanup_and_delete();
 233          match status_to_maybe_uv_error(result as i32) {
 234              Some(err) => Err(err),
 235              None => Ok(result)
 236          }
 237      }
 238      fn req_boilerplate(&mut self, cbOption<FsCallback>) -> *u8 {
 239          let result = match cb {
 240              Some(_) => {
 241                  compl_cb as *u8
 242              },
 243              None => 0 as *u8
 244          };
 245          self.install_req_data(cb);
 246          result
 247      }
 248      pub fn install_req_data(&mut self, cbOption<FsCallback>) {
 249          let fs_req = (self.native_handle()) as *uvll::uv_write_t;
 250          let data = ~RequestData {
 251              complete_cb: cb
 252          };
 253          unsafe {
 254              let data = transmute::<~RequestData, *c_void>(data);
 255              uvll::set_data_for_req(fs_req, data);
 256          }
 257      }
 258  
 259      fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData {
 260          unsafe {
 261              let data = uvll::get_data_for_req((self.native_handle()));
 262              let data = transmute::<&*c_void, &mut ~RequestData>(&data);
 263              &mut **data
 264          }
 265      }
 266  
 267      pub fn get_result(&mut self) -> c_int {
 268          unsafe {
 269              uvll::get_result_from_fs_req(self.native_handle())
 270          }
 271      }
 272  
 273      pub fn get_loop(&self) -> Loop {
 274          unsafe { Loop{handle:uvll::get_loop_from_fs_req(self.native_handle())} }
 275      }
 276  
 277      pub fn get_stat(&self) -> uv_stat_t {
 278          let stat = uv_stat_t::new();
 279          unsafe { uvll::populate_stat(self.native_handle(), &stat); }
 280          stat
 281      }
 282  
 283      pub fn get_ptr(&self) -> *libc::c_void {
 284          unsafe {
 285              uvll::get_ptr_from_fs_req(self.native_handle())
 286          }
 287      }
 288  
 289      pub fn get_paths(&mut self) -> ~[~str] {
 290          use str;
 291          let ptr = self.get_ptr();
 292          match self.get_result() {
 293              n if (n <= 0) => {
 294                  ~[]
 295              },
 296              n => {
 297                  let n_len = n as uint;
 298                  // we pass in the len that uv tells us is there
 299                  // for the entries and we don't continue past that..
 300                  // it appears that sometimes the multistring isn't
 301                  // correctly delimited and we stray into garbage memory?
 302                  // in any case, passing Some(n_len) fixes it and ensures
 303                  // good results
 304                  let raw_path_strs = unsafe {
 305                      str::raw::from_c_multistring(ptr as *libc::c_char, Some(n_len)) };
 306                  let raw_len = raw_path_strs.len();
 307                  assert_eq!(raw_len, n_len);
 308                  raw_path_strs
 309              }
 310          }
 311      }
 312  
 313      fn cleanup_and_delete(self) {
 314          unsafe {
 315              let data = uvll::get_data_for_req(self.native_handle());
 316              let _data = transmute::<*c_void, ~RequestData>(data);
 317              uvll::set_data_for_req(self.native_handle(), null::<()>());
 318              uvll::fs_req_cleanup(self.native_handle());
 319              free_req(self.native_handle() as *c_void)
 320          }
 321      }
 322  }
 323  
 324  impl NativeHandle<*uvll::uv_fs_t> for FsRequest {
 325      fn from_native_handle(handle*uvll:: uv_fs_t) -> FsRequest {
 326          FsRequest(handle)
 327      }
 328      fn native_handle(&self) -> *uvll::uv_fs_t {
 329          match self { &FsRequest(ptr) => ptr }
 330      }
 331  }
 332  
 333  fn sync_cleanup(resultint)
 334      -> Result<int, UvError> {
 335      match status_to_maybe_uv_error(result as i32) {
 336          Some(err) => Err(err),
 337          None => Ok(result)
 338      }
 339  }
 340  
 341  extern fn compl_cb(req*uv_fs_t) {
 342      let mut reqFsRequest = NativeHandle::from_native_handle(req);
 343      // pull the user cb out of the req data
 344      let cb = {
 345          let data = req.get_req_data();
 346          assert!(data.complete_cb.is_some());
 347          // option dance, option dance. oooooh yeah.
 348          data.complete_cb.take_unwrap()
 349      };
 350      // in uv_fs_open calls, the result will be the fd in the
 351      // case of success, otherwise it's -1 indicating an error
 352      let result = req.get_result();
 353      let status = status_to_maybe_uv_error(result);
 354      // we have a req and status, call the user cb..
 355      // only giving the user a ref to the FsRequest, as we
 356      // have to clean it up, afterwards (and they aren't really
 357      // reusable, anyways
 358      cb(&mut req, status);
 359      // clean up the req (and its data!) after calling the user cb
 360      req.cleanup_and_delete();
 361  }
 362  
 363  #[cfg(test)]
 364  mod test {
 365      use super::*;
 366      //use rt::test::*;
 367      use libc::{STDOUT_FILENO};
 368      use vec;
 369      use str;
 370      use unstable::run_in_bare_thread;
 371      use path::Path;
 372      use rt::uv::{Loop, Buf, slice_to_uv_buf};
 373      use libc::{O_CREAT, O_RDWR, O_RDONLY, S_IWUSR, S_IRUSR};
 374  
 375      #[test]
 376      fn file_test_full_simple() {
 377          do run_in_bare_thread {
 378              let mut loop_ = Loop::new();
 379              let create_flags = O_RDWR | O_CREAT;
 380              let read_flags = O_RDONLY;
 381              // 0644 BZZT! WRONG! 0600! See below.
 382              let mode = S_IWUSR |S_IRUSR;
 383                  // these aren't defined in std::libc :(
 384                  //map_mode(S_IRGRP) |
 385                  //map_mode(S_IROTH);
 386              let path_str = "./tmp/file_full_simple.txt";
 387              let write_val = "hello".as_bytes().to_owned();
 388              let write_buf  = slice_to_uv_buf(write_val);
 389              let write_buf_ptr: *Buf = &write_buf;
 390              let read_buf_len = 1028;
 391              let read_mem = vec::from_elem(read_buf_len, 0u8);
 392              let read_buf = slice_to_uv_buf(read_mem);
 393              let read_buf_ptr: *Buf = &read_buf;
 394              let p = Path::new(path_str);
 395              let open_req = FsRequest::new();
 396              do open_req.open(&loop_, &p, create_flags as int, mode as int)
 397              |req, uverr| {
 398                  assert!(uverr.is_none());
 399                  let fd = req.get_result();
 400                  let buf = unsafe { *write_buf_ptr };
 401                  let write_req = FsRequest::new();
 402                  do write_req.write(&req.get_loop(), fd, buf, -1) |req, uverr| {
 403                      let close_req = FsRequest::new();
 404                      do close_req.close(&req.get_loop(), fd) |req, _| {
 405                          assert!(uverr.is_none());
 406                          let loop_ = req.get_loop();
 407                          let open_req = FsRequest::new();
 408                          do open_req.open(&loop_, &Path::new(path_str), read_flags as int,0)
 409                              |req, uverr| {
 410                              assert!(uverr.is_none());
 411                              let loop_ = req.get_loop();
 412                              let fd = req.get_result();
 413                              let read_buf = unsafe { *read_buf_ptr };
 414                              let read_req = FsRequest::new();
 415                              do read_req.read(&loop_, fd, read_buf, 0) |req, uverr| {
 416                                  assert!(uverr.is_none());
 417                                  let loop_ = req.get_loop();
 418                                  // we know nread >=0 because uverr is none..
 419                                  let nread = req.get_result() as uint;
 420                                  // nread == 0 would be EOF
 421                                  if nread > 0 {
 422                                      let read_str = unsafe {
 423                                          let read_buf = *read_buf_ptr;
 424                                          str::from_utf8(
 425                                              vec::from_buf(
 426                                                  read_buf.base, nread))
 427                                      };
 428                                      assert!(read_str == ~"hello");
 429                                      let close_req = FsRequest::new();
 430                                      do close_req.close(&loop_, fd) |req,uverr| {
 431                                          assert!(uverr.is_none());
 432                                          let loop_ = &req.get_loop();
 433                                          let unlink_req = FsRequest::new();
 434                                          do unlink_req.unlink(loop_, &Path::new(path_str))
 435                                          |_,uverr| {
 436                                              assert!(uverr.is_none());
 437                                          };
 438                                      };
 439                                  };
 440                              };
 441                          };
 442                      };
 443                  };
 444              };
 445              loop_.run();
 446              loop_.close();
 447          }
 448      }
 449  
 450      #[test]
 451      fn file_test_full_simple_sync() {
 452          do run_in_bare_thread {
 453              // setup
 454              let mut loop_ = Loop::new();
 455              let create_flags = O_RDWR |
 456                  O_CREAT;
 457              let read_flags = O_RDONLY;
 458              // 0644
 459              let mode = S_IWUSR |
 460                  S_IRUSR;
 461                  //S_IRGRP |
 462                  //S_IROTH;
 463              let path_str = "./tmp/file_full_simple_sync.txt";
 464              let write_val = "hello".as_bytes().to_owned();
 465              let write_buf = slice_to_uv_buf(write_val);
 466              // open/create
 467              let open_req = FsRequest::new();
 468              let result = open_req.open_sync(&loop_, &Path::new(path_str),
 469                                                     create_flags as int, mode as int);
 470              assert!(result.is_ok());
 471              let fd = result.unwrap();
 472              // write
 473              let write_req = FsRequest::new();
 474              let result = write_req.write_sync(&loop_, fd, write_buf, -1);
 475              assert!(result.is_ok());
 476              // close
 477              let close_req = FsRequest::new();
 478              let result = close_req.close_sync(&loop_, fd);
 479              assert!(result.is_ok());
 480              // re-open
 481              let open_req = FsRequest::new();
 482              let result = open_req.open_sync(&loop_, &Path::new(path_str),
 483                                                     read_flags as int,0);
 484              assert!(result.is_ok());
 485              let len = 1028;
 486              let fd = result.unwrap();
 487              // read
 488              let read_mem: ~[u8] = vec::from_elem(len, 0u8);
 489              let buf = slice_to_uv_buf(read_mem);
 490              let read_req = FsRequest::new();
 491              let result = read_req.read_sync(&loop_, fd, buf, 0);
 492              assert!(result.is_ok());
 493              let nread = result.unwrap();
 494              // nread == 0 would be EOF.. we know it's >= zero because otherwise
 495              // the above assert would fail
 496              if nread > 0 {
 497                  let read_str = str::from_utf8(
 498                      read_mem.slice(0, nread as uint));
 499                  assert!(read_str == ~"hello");
 500                  // close
 501                  let close_req = FsRequest::new();
 502                  let result = close_req.close_sync(&loop_, fd);
 503                  assert!(result.is_ok());
 504                  // unlink
 505                  let unlink_req = FsRequest::new();
 506                  let result = unlink_req.unlink_sync(&loop_, &Path::new(path_str));
 507                  assert!(result.is_ok());
 508              } else { fail2!("nread was 0.. wudn't expectin' that."); }
 509              loop_.close();
 510          }
 511      }
 512  
 513      fn naive_print(loop_: &Loop, input: &str) {
 514          let write_val = input.as_bytes();
 515          let write_buf = slice_to_uv_buf(write_val);
 516          let write_req = FsRequest::new();
 517          write_req.write_sync(loop_, STDOUT_FILENO, write_buf, -1);
 518      }
 519  
 520      #[test]
 521      fn file_test_write_to_stdout() {
 522          do run_in_bare_thread {
 523              let mut loop_ = Loop::new();
 524              naive_print(&loop_, "zanzibar!\n");
 525              loop_.run();
 526              loop_.close();
 527          };
 528      }
 529      #[test]
 530      fn file_test_stat_simple() {
 531          do run_in_bare_thread {
 532              let mut loop_ = Loop::new();
 533              let path = "./tmp/file_test_stat_simple.txt";
 534              let create_flags = O_RDWR |
 535                  O_CREAT;
 536              let mode = S_IWUSR |
 537                  S_IRUSR;
 538              let write_val = "hello".as_bytes().to_owned();
 539              let write_buf  = slice_to_uv_buf(write_val);
 540              let write_buf_ptr: *Buf = &write_buf;
 541              let open_req = FsRequest::new();
 542              do open_req.open(&loop_, &path, create_flags as int, mode as int)
 543              |req, uverr| {
 544                  assert!(uverr.is_none());
 545                  let fd = req.get_result();
 546                  let buf = unsafe { *write_buf_ptr };
 547                  let write_req = FsRequest::new();
 548                  do write_req.write(&req.get_loop(), fd, buf, 0) |req, uverr| {
 549                      assert!(uverr.is_none());
 550                      let loop_ = req.get_loop();
 551                      let stat_req = FsRequest::new();
 552                      do stat_req.stat(&loop_, &path) |req, uverr| {
 553                          assert!(uverr.is_none());
 554                          let loop_ = req.get_loop();
 555                          let stat = req.get_stat();
 556                          let sz: uint = stat.st_size as uint;
 557                          assert!(sz > 0);
 558                          let close_req = FsRequest::new();
 559                          do close_req.close(&loop_, fd) |req, uverr| {
 560                              assert!(uverr.is_none());
 561                              let loop_ = req.get_loop();
 562                              let unlink_req = FsRequest::new();
 563                              do unlink_req.unlink(&loop_, &path) |req,uverr| {
 564                                  assert!(uverr.is_none());
 565                                  let loop_ = req.get_loop();
 566                                  let stat_req = FsRequest::new();
 567                                  do stat_req.stat(&loop_, &path) |_, uverr| {
 568                                      // should cause an error because the
 569                                      // file doesn't exist anymore
 570                                      assert!(uverr.is_some());
 571                                  };
 572                              };
 573                          };
 574                      };
 575                  };
 576              };
 577              loop_.run();
 578              loop_.close();
 579          }
 580      }
 581  
 582      #[test]
 583      fn file_test_mk_rm_dir() {
 584          do run_in_bare_thread {
 585              let mut loop_ = Loop::new();
 586              let path = "./tmp/mk_rm_dir";
 587              let mode = S_IWUSR |
 588                  S_IRUSR;
 589              let mkdir_req = FsRequest::new();
 590              do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
 591                  assert!(uverr.is_none());
 592                  let loop_ = req.get_loop();
 593                  let stat_req = FsRequest::new();
 594                  do stat_req.stat(&loop_, &path) |req, uverr| {
 595                      assert!(uverr.is_none());
 596                      let loop_ = req.get_loop();
 597                      let stat = req.get_stat();
 598                      naive_print(&loop_, format!("{:?}", stat));
 599                      assert!(stat.is_dir());
 600                      let rmdir_req = FsRequest::new();
 601                      do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
 602                          assert!(uverr.is_none());
 603                          let loop_ = req.get_loop();
 604                          let stat_req = FsRequest::new();
 605                          do stat_req.stat(&loop_, &path) |_req, uverr| {
 606                              assert!(uverr.is_some());
 607                          }
 608                      }
 609                  }
 610              }
 611              loop_.run();
 612              loop_.close();
 613          }
 614      }
 615      #[test]
 616      fn file_test_mkdir_chokes_on_double_create() {
 617          do run_in_bare_thread {
 618              let mut loop_ = Loop::new();
 619              let path = "./tmp/double_create_dir";
 620              let mode = S_IWUSR |
 621                  S_IRUSR;
 622              let mkdir_req = FsRequest::new();
 623              do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
 624                  assert!(uverr.is_none());
 625                  let loop_ = req.get_loop();
 626                  let mkdir_req = FsRequest::new();
 627                  do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
 628                      assert!(uverr.is_some());
 629                      let loop_ = req.get_loop();
 630                      let _stat = req.get_stat();
 631                      let rmdir_req = FsRequest::new();
 632                      do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
 633                          assert!(uverr.is_none());
 634                          let _loop = req.get_loop();
 635                      }
 636                  }
 637              }
 638              loop_.run();
 639              loop_.close();
 640          }
 641      }
 642      #[test]
 643      fn file_test_rmdir_chokes_on_nonexistant_path() {
 644          do run_in_bare_thread {
 645              let mut loop_ = Loop::new();
 646              let path = "./tmp/never_existed_dir";
 647              let rmdir_req = FsRequest::new();
 648              do rmdir_req.rmdir(&loop_, &path) |_req, uverr| {
 649                  assert!(uverr.is_some());
 650              }
 651              loop_.run();
 652              loop_.close();
 653          }
 654      }
 655  }

libstd/rt/uv/file.rs:23:1-23:1 -struct- definition:

pub struct FsRequest(*uvll::uv_fs_t);
references:-
35:         let fs_req: FsRequest = NativeHandle::from_native_handle(fs_req);
25: impl Request for FsRequest {}
324: impl NativeHandle<*uvll::uv_fs_t> for FsRequest {
31: impl FsRequest {
342:     let mut req: FsRequest = NativeHandle::from_native_handle(req);
32:     pub fn new() -> FsRequest {
325:     fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest {
libstd/rt/uv/mod.rs:
133: pub type FsCallback = ~fn(&mut FsRequest, Option<UvError>);
libstd/rt/uv/uvio.rs:
419:                                      ~fn(&FsRequest, Option<UvError>)))
418:                              cb: ~fn(&mut FsRequest, &mut Loop, &P,


libstd/rt/uv/file.rs:26:1-26:1 -struct- definition:

pub struct RequestData {
references:-
259:     fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData {
262:             let data = transmute::<&*c_void, &mut ~RequestData>(&data);
316:             let _data = transmute::<*c_void, ~RequestData>(data);
250:         let data = ~RequestData {
254:             let data = transmute::<~RequestData, *c_void>(data);


libstd/rt/uv/file.rs:340:1-340:1 -fn- definition:

extern fn compl_cb(req: *uv_fs_t) {
references:-
241:                 compl_cb as *u8