about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-10-16 16:48:30 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-10-24 14:21:57 -0700
commit9110a38cbfd801983a838775c690c83e9189b4c3 (patch)
treed4bdc0b6ee4dae3e40916dab864fcb06b2f10cb7
parent0cad9847652088b35ee4c13c04539ca3a67611f7 (diff)
downloadrust-9110a38cbfd801983a838775c690c83e9189b4c3.tar.gz
rust-9110a38cbfd801983a838775c690c83e9189b4c3.zip
Remove rt::io::support
This removes the PathLike trait associated with this "support module". This is
yet another "container of bytes" trait, so I didn't want to duplicate what
already exists throughout libstd. In actuality, we're going to pass of C strings
to the libuv APIs, so instead the arguments are now bound with the 'ToCStr'
trait instead.

Additionally, a layer of complexity was removed by immediately converting these
type-generic parameters into CStrings to get handed off to libuv apis.
-rw-r--r--src/libstd/c_str.rs43
-rw-r--r--src/libstd/os.rs7
-rw-r--r--src/libstd/rt/io/file.rs45
-rw-r--r--src/libstd/rt/io/mod.rs4
-rw-r--r--src/libstd/rt/io/net/unix.rs6
-rw-r--r--src/libstd/rt/io/support.rs42
-rw-r--r--src/libstd/rt/rtio.rs13
-rw-r--r--src/libstd/rt/uv/file.rs84
-rw-r--r--src/libstd/rt/uv/uvio.rs47
-rw-r--r--src/libstd/str.rs48
10 files changed, 131 insertions, 208 deletions
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index acfa02a4def..ba64a71553f 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -348,6 +348,34 @@ impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
     }
 }
 
+/// Parses a C "multistring", eg windows env values or
+/// the req->ptr result in a uv_fs_readdir() call.
+///
+/// Optionally, a `count` can be passed in, limiting the
+/// parsing to only being done `count`-times.
+///
+/// The specified closure is invoked with each string that
+/// is found, and the number of strings found is returned.
+pub unsafe fn from_c_multistring(buf: *libc::c_char,
+                                 count: Option<uint>,
+                                 f: &fn(&CString)) -> uint {
+
+    let mut curr_ptr: uint = buf as uint;
+    let mut ctr = 0;
+    let (limited_count, limit) = match count {
+        Some(limit) => (true, limit),
+        None => (false, 0)
+    };
+    while ((limited_count && ctr < limit) || !limited_count)
+          && *(curr_ptr as *libc::c_char) != 0 as libc::c_char {
+        let cstr = CString::new(curr_ptr as *libc::c_char, false);
+        f(&cstr);
+        curr_ptr += cstr.len() + 1;
+        ctr += 1;
+    }
+    return ctr;
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -356,6 +384,21 @@ mod tests {
     use option::{Some, None};
 
     #[test]
+    fn test_str_multistring_parsing() {
+        unsafe {
+            let input = bytes!("zero", "\x00", "one", "\x00", "\x00");
+            let ptr = vec::raw::to_ptr(input);
+            let expected = ["zero", "one"];
+            let mut it = expected.iter();
+            let result = do from_c_multistring(ptr as *libc::c_char, None) |c| {
+                assert_eq!(c.as_str(), expected.next().unwrap());
+            };
+            assert_eq!(result, 2);
+            assert!(it.next().is_none());
+        }
+    }
+
+    #[test]
     fn test_str_to_c_str() {
         do "".to_c_str().with_ref |buf| {
             unsafe {
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index ba2b42c9b9c..65190c5d8d6 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -62,7 +62,7 @@ pub fn close(fd: c_int) -> c_int {
 // which are for Windows and for non-Windows, if necessary.
 // See https://github.com/mozilla/rust/issues/9822 for more information.
 
-pub mod rustrt {
+mod rustrt {
     use libc::{c_char, c_int};
     use libc;
 
@@ -200,7 +200,10 @@ pub fn env() -> ~[(~str,~str)] {
                 fail!("os::env() failure getting env string from OS: {}",
                        os::last_os_error());
             }
-            let result = str::raw::from_c_multistring(ch as *libc::c_char, None);
+            let mut result = ~[];
+            do c_str::from_c_multistring(ch as *libc::c_char, None) |cstr| {
+                result.push(cstr.as_str().to_owned());
+            };
             FreeEnvironmentStringsA(ch);
             result
         }
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs
index a43bcd8142e..cc39db44431 100644
--- a/src/libstd/rt/io/file.rs
+++ b/src/libstd/rt/io/file.rs
@@ -15,7 +15,8 @@ with regular files & directories on a filesystem.
 
 At the top-level of the module are a set of freestanding functions,
 associated with various filesystem operations. They all operate
-on a `PathLike` object.
+on a `ToCStr` object. This trait is already defined for common
+objects such as strings and `Path` instances.
 
 All operations in this module, including those as part of `FileStream` et al
 block the task during execution. Most will raise `std::rt::io::{io_error,read_error}`
@@ -30,7 +31,7 @@ free function counterparts.
 */
 
 use prelude::*;
-use super::support::PathLike;
+use c_str::ToCStr;
 use super::{Reader, Writer, Seek};
 use super::{SeekStyle, Read, Write};
 use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
@@ -48,7 +49,6 @@ use path::Path;
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::open;
 ///     use std::rt::io::{FileMode, FileAccess};
 ///
@@ -87,13 +87,13 @@ use path::Path;
 /// * Attempting to open a file with a `FileAccess` that the user lacks permissions
 ///   for
 /// * Filesystem-level errors (full disk, etc)
-pub fn open<P: PathLike>(path: &P,
-                         mode: FileMode,
-                         access: FileAccess
-                        ) -> Option<FileStream> {
+pub fn open<P: ToCStr>(path: &P,
+                       mode: FileMode,
+                       access: FileAccess
+                       ) -> Option<FileStream> {
     let open_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_open(path, mode, access)
+        (*io).fs_open(&path.to_c_str(), mode, access)
     };
     match open_result {
         Ok(fd) => Some(FileStream {
@@ -113,7 +113,6 @@ pub fn open<P: PathLike>(path: &P,
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::unlink;
 ///
 ///     let p = &Path("/some/file/path.txt");
@@ -129,10 +128,10 @@ pub fn open<P: PathLike>(path: &P,
 ///
 /// This function will raise an `io_error` condition if the user lacks permissions to
 /// remove the file or if some other filesystem-level error occurs
-pub fn unlink<P: PathLike>(path: &P) {
+pub fn unlink<P: ToCStr>(path: &P) {
     let unlink_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_unlink(path)
+        (*io).fs_unlink(&path.to_c_str())
     };
     match unlink_result {
         Ok(_) => (),
@@ -148,7 +147,6 @@ pub fn unlink<P: PathLike>(path: &P) {
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::mkdir;
 ///
 ///     let p = &Path("/some/dir");
@@ -159,10 +157,10 @@ pub fn unlink<P: PathLike>(path: &P) {
 ///
 /// This call will raise an `io_error` condition if the user lacks permissions to make a
 /// new directory at the provided path, or if the directory already exists
-pub fn mkdir<P: PathLike>(path: &P) {
+pub fn mkdir<P: ToCStr>(path: &P) {
     let mkdir_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_mkdir(path)
+        (*io).fs_mkdir(&path.to_c_str())
     };
     match mkdir_result {
         Ok(_) => (),
@@ -178,7 +176,6 @@ pub fn mkdir<P: PathLike>(path: &P) {
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::rmdir;
 ///
 ///     let p = &Path("/some/dir");
@@ -189,10 +186,10 @@ pub fn mkdir<P: PathLike>(path: &P) {
 ///
 /// This call will raise an `io_error` condition if the user lacks permissions to remove the
 /// directory at the provided path, or if the directory isn't empty
-pub fn rmdir<P: PathLike>(path: &P) {
+pub fn rmdir<P: ToCStr>(path: &P) {
     let rmdir_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_rmdir(path)
+        (*io).fs_rmdir(&path.to_c_str())
     };
     match rmdir_result {
         Ok(_) => (),
@@ -204,8 +201,8 @@ pub fn rmdir<P: PathLike>(path: &P) {
 
 /// Get information on the file, directory, etc at the provided path
 ///
-/// Given a `rt::io::support::PathLike`, query the file system to get
-/// information about a file, directory, etc.
+/// Given a path, query the file system to get information about a file,
+/// directory, etc.
 ///
 /// Returns a `Some(std::rt::io::PathInfo)` on success
 ///
@@ -213,7 +210,6 @@ pub fn rmdir<P: PathLike>(path: &P) {
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::stat;
 ///
 ///     let p = &Path("/some/file/path.txt");
@@ -238,10 +234,10 @@ pub fn rmdir<P: PathLike>(path: &P) {
 /// This call will raise an `io_error` condition if the user lacks the requisite
 /// permissions to perform a `stat` call on the given path or if there is no
 /// entry in the filesystem at the provided path.
-pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
+pub fn stat<P: ToCStr>(path: &P) -> Option<FileStat> {
     let open_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_stat(path)
+        (*io).fs_stat(&path.to_c_str())
     };
     match open_result {
         Ok(p) => {
@@ -260,7 +256,6 @@ pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
 ///
 ///     use std;
 ///     use std::path::Path;
-///     use std::rt::io::support::PathLike;
 ///     use std::rt::io::file::readdir;
 ///
 ///     fn visit_dirs(dir: &Path, cb: &fn(&Path)) {
@@ -279,10 +274,10 @@ pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
 /// Will raise an `io_error` condition if the provided `path` doesn't exist,
 /// the process lacks permissions to view the contents or if the `path` points
 /// at a non-directory file
-pub fn readdir<P: PathLike>(path: &P) -> Option<~[Path]> {
+pub fn readdir<P: ToCStr>(path: &P) -> Option<~[Path]> {
     let readdir_result = unsafe {
         let io: *mut IoFactoryObject = Local::unsafe_borrow();
-        (*io).fs_readdir(path, 0)
+        (*io).fs_readdir(&path.to_c_str(), 0)
     };
     match readdir_result {
         Ok(p) => {
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
index eaff43378f2..cb6361ff4e3 100644
--- a/src/libstd/rt/io/mod.rs
+++ b/src/libstd/rt/io/mod.rs
@@ -298,10 +298,6 @@ pub mod comm_adapters;
 /// Extension traits
 pub mod extensions;
 
-/// Non-I/O things needed by the I/O module
-// XXX: shouldn this really be pub?
-pub mod support;
-
 /// Basic Timer
 pub mod timer;
 
diff --git a/src/libstd/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs
index 1394cdb04a8..fe045bff050 100644
--- a/src/libstd/rt/io/net/unix.rs
+++ b/src/libstd/rt/io/net/unix.rs
@@ -24,7 +24,7 @@ instances as clients.
 
 use prelude::*;
 
-use super::super::support::PathLike;
+use c_str::ToCStr;
 use rt::rtio::{IoFactory, IoFactoryObject, RtioUnixListener};
 use rt::rtio::{RtioUnixAcceptor, RtioPipe, RtioUnixListenerObject};
 use rt::io::pipe::PipeStream;
@@ -59,7 +59,7 @@ impl UnixStream {
     ///     let mut stream = UnixStream::connect(&server);
     ///     stream.write([1, 2, 3]);
     ///
-    pub fn connect<P: PathLike>(path: &P) -> Option<UnixStream> {
+    pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> {
         let pipe = unsafe {
             let io: *mut IoFactoryObject = Local::unsafe_borrow();
             (*io).unix_connect(path)
@@ -112,7 +112,7 @@ impl UnixListener {
     ///         client.write([1, 2, 3, 4]);
     ///     }
     ///
-    pub fn bind<P: PathLike>(path: &P) -> Option<UnixListener> {
+    pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> {
         let listener = unsafe {
             let io: *mut IoFactoryObject = Local::unsafe_borrow();
             (*io).unix_bind(path)
diff --git a/src/libstd/rt/io/support.rs b/src/libstd/rt/io/support.rs
deleted file mode 100644
index 31040bc51a1..00000000000
--- a/src/libstd/rt/io/support.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use path::*;
-
-pub trait PathLike {
-    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T;
-}
-
-impl<'self> PathLike for &'self str {
-    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
-        f(*self)
-    }
-}
-
-impl PathLike for Path {
-    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
-        let s = self.as_str().unwrap();
-        f(s)
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use path::*;
-    use super::PathLike;
-
-    #[test]
-    fn path_like_smoke_test() {
-        let expected = if cfg!(unix) { "/home" } else { "C:\\" };
-        let path = Path::new(expected);
-        path.path_as_str(|p| assert!(p == expected));
-        path.path_as_str(|p| assert!(p == expected));
-    }
-}
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index ef695130e22..c889355f353 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -12,6 +12,7 @@ use libc;
 use option::*;
 use result::*;
 use libc::c_int;
+use c_str::CString;
 
 use ai = rt::io::net::addrinfo;
 use rt::io::IoError;
@@ -19,7 +20,6 @@ use super::io::process::ProcessConfig;
 use super::io::net::ip::{IpAddr, SocketAddr};
 use rt::uv::uvio;
 use path::Path;
-use super::io::support::PathLike;
 use super::io::{SeekStyle};
 use super::io::{FileMode, FileAccess, FileStat};
 
@@ -65,15 +65,14 @@ pub trait IoFactory {
     fn udp_bind(&mut self, addr: SocketAddr) -> Result<~RtioUdpSocket, IoError>;
     fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
     fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream;
-    fn fs_open<P: PathLike>(&mut self, path: &P, fm: FileMode, fa: FileAccess)
+    fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError>;
-    fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
     fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
                           hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
-    fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
-    fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
-    fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
-    fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
+    fn fs_stat(&mut self, path: &CString) -> Result<FileStat, IoError>;
+    fn fs_mkdir(&mut self, path: &CString) -> Result<(), IoError>;
+    fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError>;
+    fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
         Result<~[Path], IoError>;
     fn spawn(&mut self, config: ProcessConfig)
             -> Result<(~RtioProcess, ~[Option<~RtioPipe>]), IoError>;
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
index 5d64ca4d755..07a22bc00e3 100644
--- a/src/libstd/rt/uv/file.rs
+++ b/src/libstd/rt/uv/file.rs
@@ -10,12 +10,13 @@
 
 use prelude::*;
 use ptr::null;
+use c_str;
+use c_str::CString;
 use libc::c_void;
 use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf,
              status_to_maybe_uv_error, UvError};
 use rt::uv::uvll;
 use rt::uv::uvll::*;
-use super::super::io::support::PathLike;
 use cast::transmute;
 use libc;
 use libc::{c_int};
@@ -36,73 +37,63 @@ impl FsRequest {
         fs_req
     }
 
-    pub fn open<P: PathLike>(self, loop_: &Loop, path: &P, flags: int, mode: int,
-               cb: FsCallback) {
+    pub fn open(self, loop_: &Loop, path: &CString, flags: int, mode: int,
+                cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
+        path.with_ref(|p| unsafe {
             uvll::fs_open(loop_.native_handle(),
                           self.native_handle(), p, flags, mode, complete_cb_ptr)
-            })
         });
     }
 
-    pub fn open_sync<P: PathLike>(self, loop_: &Loop, path: &P,
-                                  flags: int, mode: int) -> Result<c_int, UvError> {
+    pub fn open_sync(self, loop_: &Loop, path: &CString,
+                     flags: int, mode: int) -> Result<c_int, UvError> {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(None)
         };
-        let result = path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
+        let result = path.with_ref(|p| unsafe {
             uvll::fs_open(loop_.native_handle(),
                     self.native_handle(), p, flags, mode, complete_cb_ptr)
-            })
         });
         self.sync_cleanup(result)
     }
 
-    pub fn unlink<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+    pub fn unlink(self, loop_: &Loop, path: &CString, cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
-                uvll::fs_unlink(loop_.native_handle(),
-                              self.native_handle(), p, complete_cb_ptr)
-            })
+        path.with_ref(|p| unsafe {
+            uvll::fs_unlink(loop_.native_handle(),
+                          self.native_handle(), p, complete_cb_ptr)
         });
     }
 
-    pub fn unlink_sync<P: PathLike>(self, loop_: &Loop, path: &P)
+    pub fn unlink_sync(self, loop_: &Loop, path: &CString)
       -> Result<c_int, UvError> {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(None)
         };
-        let result = path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
-                uvll::fs_unlink(loop_.native_handle(),
-                              self.native_handle(), p, complete_cb_ptr)
-            })
+        let result = path.with_ref(|p| unsafe {
+            uvll::fs_unlink(loop_.native_handle(),
+                          self.native_handle(), p, complete_cb_ptr)
         });
         self.sync_cleanup(result)
     }
 
-    pub fn stat<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+    pub fn stat(self, loop_: &Loop, path: &CString, cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
-                uvll::fs_stat(loop_.native_handle(),
-                              self.native_handle(), p, complete_cb_ptr)
-            })
+        path.with_ref(|p| unsafe {
+            uvll::fs_stat(loop_.native_handle(),
+                          self.native_handle(), p, complete_cb_ptr)
         });
     }
 
@@ -186,43 +177,37 @@ impl FsRequest {
         self.sync_cleanup(result)
     }
 
-    pub fn mkdir<P: PathLike>(self, loop_: &Loop, path: &P, mode: int, cb: FsCallback) {
+    pub fn mkdir(self, loop_: &Loop, path: &CString, mode: int, cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
+        path.with_ref(|p| unsafe {
             uvll::fs_mkdir(loop_.native_handle(),
                           self.native_handle(), p, mode, complete_cb_ptr)
-            })
         });
     }
 
-    pub fn rmdir<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
+    pub fn rmdir(self, loop_: &Loop, path: &CString, cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
+        path.with_ref(|p| unsafe {
             uvll::fs_rmdir(loop_.native_handle(),
                           self.native_handle(), p, complete_cb_ptr)
-            })
         });
     }
 
-    pub fn readdir<P: PathLike>(self, loop_: &Loop, path: &P,
-                                flags: c_int, cb: FsCallback) {
+    pub fn readdir(self, loop_: &Loop, path: &CString,
+                   flags: c_int, cb: FsCallback) {
         let complete_cb_ptr = {
             let mut me = self;
             me.req_boilerplate(Some(cb))
         };
-        path.path_as_str(|p| {
-            p.with_c_str(|p| unsafe {
+        path.with_ref(|p| unsafe {
             uvll::fs_readdir(loop_.native_handle(),
                           self.native_handle(), p, flags, complete_cb_ptr)
-            })
         });
     }
 
@@ -286,13 +271,11 @@ impl FsRequest {
         }
     }
 
-    pub fn get_paths(&mut self) -> ~[~str] {
+    pub fn each_path(&mut self, f: &fn(&CString)) {
         use str;
         let ptr = self.get_ptr();
         match self.get_result() {
-            n if (n <= 0) => {
-                ~[]
-            },
+            n if (n <= 0) => {}
             n => {
                 let n_len = n as uint;
                 // we pass in the len that uv tells us is there
@@ -301,11 +284,10 @@ impl FsRequest {
                 // 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
+                unsafe {
+                    c_str::from_c_multistring(ptr as *libc::c_char,
+                                              Some(n_len), f);
+                }
             }
         }
     }
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index 00572d66573..b0cdce7dd93 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use c_str::ToCStr;
+use c_str::{ToCStr, CString};
 use cast::transmute;
 use cast;
 use cell::Cell;
@@ -36,7 +36,6 @@ use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
 use rt::uv::addrinfo::{GetAddrInfoRequest, accum_addrinfo};
 use unstable::sync::Exclusive;
 use path::{GenericPath, Path};
-use super::super::io::support::PathLike;
 use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
           S_IRUSR, S_IWUSR, S_IRWXU};
 use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
@@ -415,9 +414,9 @@ impl UvIoFactory {
 
 /// Helper for a variety of simple uv_fs_* functions that
 /// have no ret val
-fn uv_fs_helper<P: PathLike>(loop_: &mut Loop, path: &P,
-                             cb: ~fn(&mut FsRequest, &mut Loop, &P,
-                                     ~fn(&FsRequest, Option<UvError>)))
+fn uv_fs_helper(loop_: &mut Loop, path: &CString,
+                cb: ~fn(&mut FsRequest, &mut Loop, &CString,
+                        ~fn(&FsRequest, Option<UvError>)))
         -> Result<(), IoError> {
     let result_cell = Cell::new_empty();
     let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
@@ -553,7 +552,7 @@ impl IoFactory for UvIoFactory {
         ~UvFileStream::new(loop_, fd, close_on_drop, home) as ~RtioFileStream
     }
 
-    fn fs_open<P: PathLike>(&mut self, path: &P, fm: FileMode, fa: FileAccess)
+    fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError> {
         let mut flags = match fm {
             Open => 0,
@@ -608,14 +607,14 @@ impl IoFactory for UvIoFactory {
         return result_cell.take();
     }
 
-    fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+    fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError> {
         do uv_fs_helper(self.uv_loop(), path) |unlink_req, l, p, cb| {
             do unlink_req.unlink(l, p) |req, err| {
                 cb(req, err)
             };
         }
     }
-    fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError> {
+    fn fs_stat(&mut self, path: &CString) -> Result<FileStat, IoError> {
         use str::StrSlice;
         let result_cell = Cell::new_empty();
         let result_cell_ptr: *Cell<Result<FileStat,
@@ -627,14 +626,13 @@ impl IoFactory for UvIoFactory {
             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.stat(self.uv_loop(), path)
-                      |req,err| {
+                let path_instance = Cell::new(Path::new(path.as_bytes()));
+                do stat_req.stat(self.uv_loop(), path) |req,err| {
                     let res = match err {
                         None => {
                             let stat = req.get_stat();
                             Ok(FileStat {
-                                path: Path::new(path_str.as_slice()),
+                                path: path_instance.take(),
                                 is_file: stat.is_file(),
                                 is_dir: stat.is_dir(),
                                 device: stat.st_dev,
@@ -694,7 +692,7 @@ impl IoFactory for UvIoFactory {
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
-    fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+    fn fs_mkdir(&mut self, path: &CString) -> Result<(), IoError> {
         let mode = S_IRWXU as int;
         do uv_fs_helper(self.uv_loop(), path) |mkdir_req, l, p, cb| {
             do mkdir_req.mkdir(l, p, mode as int) |req, err| {
@@ -702,14 +700,14 @@ impl IoFactory for UvIoFactory {
             };
         }
     }
-    fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
+    fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError> {
         do uv_fs_helper(self.uv_loop(), path) |rmdir_req, l, p, cb| {
             do rmdir_req.rmdir(l, p) |req, err| {
                 cb(req, err)
             };
         }
     }
-    fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
+    fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
         Result<~[Path], IoError> {
         use str::StrSlice;
         let result_cell = Cell::new_empty();
@@ -722,17 +720,14 @@ impl IoFactory for UvIoFactory {
             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 path_parent = Cell::new(Path::new(path.as_bytes()));
+                do stat_req.readdir(self.uv_loop(), path, flags) |req,err| {
+                    let parent = path_parent.take();
                     let res = match err {
                         None => {
-                            let rel_paths = req.get_paths();
                             let mut paths = ~[];
-                            for r in rel_paths.iter() {
-                                let mut p = Path::new(path_str.as_slice());
-                                p.push(r.as_slice());
-                                paths.push(p);
+                            do req.each_path |rel_path| {
+                                paths.push(parent.join(rel_path.as_bytes()));
                             }
                             Ok(paths)
                         },
@@ -2417,20 +2412,20 @@ fn file_test_uvio_full_simple_impl() {
         {
             let create_fm = Create;
             let create_fa = ReadWrite;
-            let mut fd = (*io).fs_open(&Path::new(path), create_fm, create_fa).unwrap();
+            let mut fd = (*io).fs_open(&path.to_c_str(), create_fm, create_fa).unwrap();
             let write_buf = write_val.as_bytes();
             fd.write(write_buf);
         }
         {
             let ro_fm = Open;
             let ro_fa = Read;
-            let mut fd = (*io).fs_open(&Path::new(path), ro_fm, ro_fa).unwrap();
+            let mut fd = (*io).fs_open(&path.to_c_str(), ro_fm, ro_fa).unwrap();
             let mut read_vec = [0, .. 1028];
             let nread = fd.read(read_vec).unwrap();
             let read_val = str::from_utf8(read_vec.slice(0, nread as uint));
             assert!(read_val == write_val.to_owned());
         }
-        (*io).fs_unlink(&Path::new(path));
+        (*io).fs_unlink(&path.to_c_str());
     }
 }
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index f134788942c..3c89c12dbfa 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -1172,34 +1172,6 @@ pub mod raw {
         vec::raw::set_len(as_owned_vec(s), new_len)
     }
 
-    /// Parses a C "multistring", eg windows env values or
-    /// the req->ptr result in a uv_fs_readdir() call.
-    /// Optionally, a `count` can be passed in, limiting the
-    /// parsing to only being done `count`-times.
-    #[inline]
-    pub unsafe fn from_c_multistring(buf: *libc::c_char, count: Option<uint>) -> ~[~str] {
-        #[fixed_stack_segment]; #[inline(never)];
-
-        let mut curr_ptr: uint = buf as uint;
-        let mut result = ~[];
-        let mut ctr = 0;
-        let (limited_count, limit) = match count {
-            Some(limit) => (true, limit),
-            None => (false, 0)
-        };
-        while(((limited_count && ctr < limit) || !limited_count)
-              && *(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
-            let env_pair = from_c_str(
-                curr_ptr as *libc::c_char);
-            result.push(env_pair);
-            curr_ptr +=
-                libc::strlen(curr_ptr as *libc::c_char) as uint
-                + 1;
-            ctr += 1;
-        }
-        result
-    }
-
     /// Sets the length of a string
     ///
     /// This will explicitly set the size of the string, without actually
@@ -1214,26 +1186,6 @@ pub mod raw {
             assert_eq!(c, ~"AAA");
         }
     }
-
-    #[test]
-    fn test_str_multistring_parsing() {
-        use option::None;
-        unsafe {
-            let input = bytes!("zero", "\x00", "one", "\x00", "\x00");
-            let ptr = vec::raw::to_ptr(input);
-            let result = from_c_multistring(ptr as *libc::c_char, None);
-            assert!(result.len() == 2);
-            let mut ctr = 0;
-            for x in result.iter() {
-                match ctr {
-                    0 => assert_eq!(x, &~"zero"),
-                    1 => assert_eq!(x, &~"one"),
-                    _ => fail!("shouldn't happen!")
-                }
-                ctr += 1;
-            }
-        }
-    }
 }
 
 /*