about summary refs log tree commit diff
path: root/src/libstd/rt/uv
diff options
context:
space:
mode:
authorJeff Olson <olson.jeffery@gmail.com>2013-09-16 13:25:10 -0700
committerJeff Olson <olson.jeffery@gmail.com>2013-09-16 23:19:24 -0700
commitbf399d558e755b5964666892e9f95440ad6f8ef2 (patch)
tree60bba6e534cf70e65b84058dfeb8a4433579d165 /src/libstd/rt/uv
parent25b4d8c1d7de70bab8eca8a57fdfb703e5e281c9 (diff)
downloadrust-bf399d558e755b5964666892e9f95440ad6f8ef2.tar.gz
rust-bf399d558e755b5964666892e9f95440ad6f8ef2.zip
std: bind uv_fs_readdir(), flesh out DirectoryInfo and docs/cleanup
Diffstat (limited to 'src/libstd/rt/uv')
-rw-r--r--src/libstd/rt/uv/file.rs50
-rw-r--r--src/libstd/rt/uv/uvio.rs38
-rw-r--r--src/libstd/rt/uv/uvll.rs14
3 files changed, 94 insertions, 8 deletions
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
index 34f87e3601e..cd0a217cc45 100644
--- a/src/libstd/rt/uv/file.rs
+++ b/src/libstd/rt/uv/file.rs
@@ -17,6 +17,7 @@ use rt::uv::uvll;
 use rt::uv::uvll::*;
 use super::super::io::support::PathLike;
 use cast::transmute;
+use libc;
 use libc::{c_int};
 use option::{None, Some, Option};
 
@@ -28,14 +29,6 @@ pub struct RequestData {
 }
 
 impl FsRequest {
-    pub fn new_REFACTOR_ME(cb: Option<FsCallback>) -> FsRequest {
-        let fs_req = unsafe { malloc_req(UV_FS) };
-        assert!(fs_req.is_not_null());
-        let fs_req: FsRequest = NativeHandle::from_native_handle(fs_req);
-        fs_req.install_req_data(cb);
-        fs_req
-    }
-
     pub fn new() -> FsRequest {
         let fs_req = unsafe { malloc_req(UV_FS) };
         assert!(fs_req.is_not_null());
@@ -180,6 +173,17 @@ impl FsRequest {
         });
     }
 
+    pub fn readdir<P: PathLike>(self, loop_: &Loop, path: &P,
+                                flags: c_int, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        path.path_as_str(|p| {
+            p.to_c_str().with_ref(|p| unsafe {
+            uvll::fs_readdir(loop_.native_handle(),
+                          self.native_handle(), p, flags, complete_cb_ptr)
+            })
+        });
+    }
+
     // accessors/utility funcs
     fn sync_cleanup(self, result: c_int)
           -> Result<c_int, UvError> {
@@ -235,6 +239,36 @@ impl FsRequest {
         stat
     }
 
+    pub fn get_ptr(&self) -> *libc::c_void {
+        unsafe {
+            uvll::get_ptr_from_fs_req(self.native_handle())
+        }
+    }
+
+    pub fn get_paths(&mut self) -> ~[~str] {
+        use str;
+        let ptr = self.get_ptr();
+        match self.get_result() {
+            n if (n <= 0) => {
+                ~[]
+            },
+            n => {
+                let n_len = n as uint;
+                // we pass in the len that uv tells us is there
+                // for the entries and we don't continue past that..
+                // it appears that sometimes the multistring isn't
+                // correctly delimited and we stray into garbage memory?
+                // in any case, passing Some(n_len) fixes it and ensures
+                // good results
+                let raw_path_strs = unsafe {
+                    str::raw::from_c_multistring(ptr as *libc::c_char, Some(n_len)) };
+                let raw_len = raw_path_strs.len();
+                assert_eq!(raw_len, n_len);
+                raw_path_strs
+            }
+        }
+    }
+
     fn cleanup_and_delete(self) {
         unsafe {
             let data = uvll::get_data_for_req(self.native_handle());
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index d701a87004c..2d024f04e1d 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -704,6 +704,44 @@ impl IoFactory for UvIoFactory {
             };
         }
     }
+    fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
+        Result<~[Path], IoError> {
+        use str::StrSlice;
+        let result_cell = Cell::new_empty();
+        let result_cell_ptr: *Cell<Result<~[Path],
+                                           IoError>> = &result_cell;
+        let path_cell = Cell::new(path);
+        do task::unkillable { // FIXME(#8674)
+            let scheduler: ~Scheduler = Local::take();
+            let stat_req = file::FsRequest::new();
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task_cell = Cell::new(task);
+                let path = path_cell.take();
+                let path_str = path.path_as_str(|p| p.to_owned());
+                do stat_req.readdir(self.uv_loop(), path, flags)
+                      |req,err| {
+                    let res = match err {
+                        None => {
+                            let rel_paths = req.get_paths();
+                            let mut paths = ~[];
+                            for r in rel_paths.iter() {
+                                paths.push(Path(path_str+"/"+*r));
+                            }
+                            Ok(paths)
+                        },
+                        Some(e) => {
+                            Err(uv_error_to_io_error(e))
+                        }
+                    };
+                    unsafe { (*result_cell_ptr).put_back(res); }
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task_cell.take());
+                };
+            };
+        };
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
 }
 
 pub struct UvTcpListener {
diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs
index a2d1c48c3e1..42102a52e2e 100644
--- a/src/libstd/rt/uv/uvll.rs
+++ b/src/libstd/rt/uv/uvll.rs
@@ -811,6 +811,12 @@ pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
 
     rust_uv_fs_rmdir(loop_ptr, req, path, cb)
 }
+pub unsafe fn fs_readdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
+                flags: c_int, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_fs_readdir(loop_ptr, req, path, flags, cb)
+}
 pub unsafe fn populate_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t) {
     #[fixed_stack_segment]; #[inline(never)];
 
@@ -828,6 +834,11 @@ pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
 
     rust_uv_get_result_from_fs_req(req)
 }
+pub unsafe fn get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_get_ptr_from_fs_req(req)
+}
 pub unsafe fn get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t {
     #[fixed_stack_segment]; #[inline(never)];
 
@@ -1014,9 +1025,12 @@ extern {
                         mode: c_int, cb: *u8) -> c_int;
     fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
                         cb: *u8) -> c_int;
+    fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
+                        flags: c_int, cb: *u8) -> c_int;
     fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
     fn rust_uv_populate_uv_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t);
     fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
+    fn rust_uv_get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void;
     fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
     fn rust_uv_get_loop_from_getaddrinfo_req(req: *uv_fs_t) -> *uv_loop_t;