]> git.lizzy.rs Git - rust.git/commitdiff
Fill out the remaining functionality in io::file
authorAlex Crichton <alex@alexcrichton.com>
Wed, 30 Oct 2013 06:31:07 +0000 (23:31 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 3 Nov 2013 23:15:42 +0000 (15:15 -0800)
This adds bindings to the remaining functions provided by libuv, all of which
are useful operations on files which need to get exposed somehow.

Some highlights:

* Dropped `FileReader` and `FileWriter` and `FileStream` for one `File` type
* Moved all file-related methods to be static methods under `File`
* All directory related methods are still top-level functions
* Created `io::FilePermission` types (backed by u32) that are what you'd expect
* Created `io::FileType` and refactored `FileStat` to use FileType and
  FilePermission
* Removed the expanding matrix of `FileMode` operations. The mode of reading a
  file will not have the O_CREAT flag, but a write mode will always have the
  O_CREAT flag.

Closes #10130
Closes #10131
Closes #10121

38 files changed:
src/compiletest/errors.rs
src/compiletest/header.rs
src/compiletest/runtest.rs
src/etc/libc.c
src/libextra/terminfo/searcher.rs
src/libextra/test.rs
src/libextra/workcache.rs
src/librustc/back/link.rs
src/librustc/driver/driver.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustpkg/lib.rs
src/librustpkg/package_source.rs
src/librustpkg/path_util.rs
src/librustpkg/source_control.rs
src/librustpkg/tests.rs
src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
src/librustpkg/workcache_support.rs
src/librustuv/file.rs
src/librustuv/uvio.rs
src/librustuv/uvll.rs
src/libstd/libc.rs
src/libstd/os.rs
src/libstd/path/windows.rs
src/libstd/rand/os.rs
src/libstd/rt/io/file.rs
src/libstd/rt/io/mod.rs
src/libstd/rt/io/native/file.rs
src/libstd/rt/io/option.rs
src/libstd/rt/rtio.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/parse/mod.rs
src/rt/rust_uv.cpp
src/test/bench/core-std.rs
src/test/bench/shootout-fasta.rs
src/test/run-pass/glob-std.rs
src/test/run-pass/rename-directory.rs
src/test/run-pass/stat.rs

index dfadea37cd0d34175eb62aa32e806b37acda2ad3..8bfef9da805f25ac270c2efbe706a9faf04aaebd 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::rt::io::buffered::BufferedReader;
-use std::rt::io::file;
+use std::rt::io::File;
 
 pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
 
@@ -17,7 +17,7 @@ pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
 pub fn load_errors(testfile: &Path) -> ~[ExpectedError] {
 
     let mut error_patterns = ~[];
-    let mut rdr = BufferedReader::new(file::open(testfile).unwrap());
+    let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
     let mut line_num = 1u;
     loop {
         let ln = match rdr.read_line() {
index 68e8fd76735424179ad497a039e67fb83b7f2cfe..5571e159ee31dcaa27071508298ede3cea5a3d34 100644 (file)
@@ -104,9 +104,9 @@ fn xfail_target(config: &config) -> ~str {
 
 fn iter_header(testfile: &Path, it: &fn(&str) -> bool) -> bool {
     use std::rt::io::buffered::BufferedReader;
-    use std::rt::io::file;
+    use std::rt::io::File;
 
-    let mut rdr = BufferedReader::new(file::open(testfile).unwrap());
+    let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
     loop {
         let ln = match rdr.read_line() {
             Some(ln) => ln, None => break
index 7fc13467217fba94c60593e56e951a81c4fbc306..d55bdc2370327905b286884c43d519d5ba37ff25 100644 (file)
@@ -23,6 +23,7 @@
 use std::cell::Cell;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 use std::os;
 use std::str;
 use std::task::{spawn_sched, SingleThreaded};
@@ -171,7 +172,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
     let rounds =
         match props.pp_exact { Some(_) => 1, None => 2 };
 
-    let src = file::open(testfile).read_to_end();
+    let src = File::open(testfile).read_to_end();
     let src = str::from_utf8_owned(src);
     let mut srcs = ~[src];
 
@@ -193,7 +194,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
     let mut expected = match props.pp_exact {
         Some(ref file) => {
             let filepath = testfile.dir_path().join(file);
-            let s = file::open(&filepath).read_to_end();
+            let s = File::open(&filepath).read_to_end();
             str::from_utf8_owned(s)
           }
           None => { srcs[srcs.len() - 2u].clone() }
@@ -764,7 +765,7 @@ fn dump_output(config: &config, testfile: &Path, out: &str, err: &str) {
 fn dump_output_file(config: &config, testfile: &Path,
                     out: &str, extension: &str) {
     let outfile = make_out_name(config, testfile, extension);
-    file::create(&outfile).write(out.as_bytes());
+    File::create(&outfile).write(out.as_bytes());
 }
 
 fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path {
@@ -1015,7 +1016,7 @@ fn disassemble_extract(config: &config, _props: &TestProps,
 
 
 fn count_extracted_lines(p: &Path) -> uint {
-    let x = file::open(&p.with_extension("ll")).read_to_end();
+    let x = File::open(&p.with_extension("ll")).read_to_end();
     let x = str::from_utf8_owned(x);
     x.line_iter().len()
 }
index e341f495eebb9fe608e16223ddda9cf4f3a5dcef..d86ed510361cc3fd0a1e048cd8201b46362270be 100644 (file)
@@ -143,6 +143,7 @@ void posix88_consts() {
   put_const(S_IFBLK, int);
   put_const(S_IFDIR, int);
   put_const(S_IFREG, int);
+  put_const(S_IFLNK, int);
   put_const(S_IFMT, int);
 
   put_const(S_IEXEC, int);
index c5509f8aec7d7058b78810e4c6578ca508576fa3..09ceae66bb12d355ee95c0bc02ec874fa96e08ce 100644 (file)
@@ -14,7 +14,7 @@
 use std::{os, str};
 use std::os::getenv;
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 
 /// Return path to database entry for `term`
 pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
@@ -76,7 +76,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
 /// Return open file for `term`
 pub fn open(term: &str) -> Result<@mut io::Reader, ~str> {
     match get_dbpath_for_term(term) {
-        Some(x) => Ok(@mut file::open(x) as @mut io::Reader),
+        Some(x) => Ok(@mut File::open(x) as @mut io::Reader),
         None => Err(format!("could not find terminfo entry for {}", term))
     }
 }
index 497d4206fe327932a20c5a395adf2f403b3b7f2a..4cdb3841acf9b0c91c0c3b67df78d0315e907292 100644 (file)
@@ -31,7 +31,7 @@
 use std::clone::Clone;
 use std::comm::{stream, SharedChan, GenericPort, GenericChan};
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::task;
 use std::to_str::ToStr;
 use std::f64;
@@ -353,7 +353,7 @@ struct ConsoleTestState {
 impl ConsoleTestState {
     pub fn new(opts: &TestOpts) -> ConsoleTestState {
         let log_out = match opts.logfile {
-            Some(ref path) => Some(@mut file::create(path) as @mut io::Writer),
+            Some(ref path) => Some(@mut File::create(path) as @mut io::Writer),
             None => None
         };
         let out = @mut io::stdio::stdout() as @mut io::Writer;
@@ -936,14 +936,14 @@ pub fn new() -> MetricMap {
     /// Load MetricDiff from a file.
     pub fn load(p: &Path) -> MetricMap {
         assert!(p.exists());
-        let f = @mut file::open(p) as @mut io::Reader;
+        let f = @mut File::open(p) as @mut io::Reader;
         let mut decoder = json::Decoder(json::from_reader(f).unwrap());
         MetricMap(Decodable::decode(&mut decoder))
     }
 
     /// Write MetricDiff to a file.
     pub fn save(&self, p: &Path) {
-        self.to_json().to_pretty_writer(@mut file::create(p) as @mut io::Writer);
+        self.to_json().to_pretty_writer(@mut File::create(p) as @mut io::Writer);
     }
 
     /// Compare against another MetricMap. Optionally compare all
index b2be4cf811b3272220af20356c3dcc018f2c5a85..09d9dd828d4e5252c1aa9b8a1764c7dadff7fe47 100644 (file)
@@ -19,7 +19,7 @@
 use std::comm::{PortOne, oneshot};
 use std::{str, task};
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::rt::io::Decorator;
 use std::rt::io::mem::MemWriter;
 
@@ -176,14 +176,14 @@ pub fn cache(&mut self,
 
     // FIXME #4330: This should have &mut self and should set self.db_dirty to false.
     fn save(&self) {
-        let f = @mut file::create(&self.db_filename);
+        let f = @mut File::create(&self.db_filename);
         self.db_cache.to_json().to_pretty_writer(f as @mut io::Writer);
     }
 
     fn load(&mut self) {
         assert!(!self.db_dirty);
         assert!(self.db_filename.exists());
-        match io::result(|| file::open(&self.db_filename)) {
+        match io::result(|| File::open(&self.db_filename)) {
             Err(e) => fail!("Couldn't load workcache database {}: {}",
                             self.db_filename.display(),
                             e.desc),
@@ -480,7 +480,6 @@ pub fn unwrap(self) -> T {
 #[test]
 fn test() {
     use std::{os, run};
-    use std::rt::io::file;
     use std::str::from_utf8_owned;
 
     // Create a path to a new file 'filename' in the directory in which
@@ -488,13 +487,13 @@ fn test() {
     fn make_path(filename: ~str) -> Path {
         let pth = os::self_exe_path().expect("workcache::test failed").with_filename(filename);
         if pth.exists() {
-            file::unlink(&pth);
+            File::unlink(&pth);
         }
         return pth;
     }
 
     let pth = make_path(~"foo.c");
-    file::create(&pth).write(bytes!("int main() { return 0; }"));
+    File::create(&pth).write(bytes!("int main() { return 0; }"));
 
     let db_path = make_path(~"db.json");
 
@@ -507,7 +506,7 @@ fn make_path(filename: ~str) -> Path {
         let subcx = cx.clone();
         let pth = pth.clone();
 
-        let file_content = from_utf8_owned(file::open(&pth).read_to_end());
+        let file_content = from_utf8_owned(File::open(&pth).read_to_end());
 
         // FIXME (#9639): This needs to handle non-utf8 paths
         prep.declare_input("file", pth.as_str().unwrap(), file_content);
index 7d044ba998fdbdaa4d3c97c2e875632432e1f004..81a205228073e15288c547f94650210ef29642c2 100644 (file)
@@ -31,7 +31,7 @@
 use std::run;
 use std::str;
 use std::vec;
-use std::rt::io::file;
+use std::rt::io::File;
 use syntax::ast;
 use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
 use syntax::attr;
@@ -950,18 +950,17 @@ pub fn link_binary(sess: Session,
 
     // Remove the temporary object file if we aren't saving temps
     if !sess.opts.save_temps {
-        file::unlink(obj_filename);
+        File::unlink(obj_filename);
     }
 }
 
 fn is_writeable(p: &Path) -> bool {
     use std::rt::io;
-    use std::libc::consts::os::posix88::S_IWUSR;
 
     !p.exists() ||
         (match io::result(|| p.stat()) {
             Err(*) => false,
-            Ok(m) => (m.mode as uint) & S_IWUSR as uint == S_IWUSR as uint
+            Ok(m) => m.perm & io::UserWrite == io::UserWrite
         })
 }
 
index 1526b5ad9c66a74dddcc08737f4df20a0a26ab80..01035385f97c7cd9a09d793b5e724724325fb0d2 100644 (file)
@@ -27,7 +27,7 @@
 
 use std::hashmap::{HashMap,HashSet};
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::rt::io::mem::MemReader;
 use std::os;
 use std::vec;
@@ -370,7 +370,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
 
         // Remove assembly source unless --save-temps was specified
         if !sess.opts.save_temps {
-            file::unlink(&asm_filename);
+            File::unlink(&asm_filename);
         }
     } else {
         time(sess.time_passes(), "LLVM passes", (), |_|
index fd7ba7c04527719172528786912c74fc4031c9e6..d0e01d1f423227a3421d04e05c4033198f031a65 100644 (file)
@@ -42,6 +42,7 @@
 use std::rt::io::buffered::BufferedWriter;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 use std::os;
 use std::str;
 use std::task;
@@ -263,7 +264,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
     // Publish the search index
     {
         dst.push("search-index.js");
-        let mut w = BufferedWriter::new(file::create(&dst).unwrap());
+        let mut w = BufferedWriter::new(File::create(&dst).unwrap());
         let w = &mut w as &mut Writer;
         write!(w, "var searchIndex = [");
         for (i, item) in cache.search_index.iter().enumerate() {
@@ -313,7 +314,7 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
 /// Writes the entire contents of a string to a destination, not attempting to
 /// catch any errors.
 fn write(dst: Path, contents: &str) {
-    file::create(&dst).write(contents.as_bytes());
+    File::create(&dst).write(contents.as_bytes());
 }
 
 /// Makes a directory on the filesystem, failing the task if an error occurs and
@@ -419,7 +420,7 @@ fn emit_source(&mut self, filename: &str) -> bool {
             // If we couldn't open this file, then just returns because it
             // probably means that it's some standard library macro thing and we
             // can't have the source to it anyway.
-            let mut r = match io::result(|| file::open(&p)) {
+            let mut r = match io::result(|| File::open(&p)) {
                 Ok(r) => r,
                 // eew macro hacks
                 Err(*) => return filename == "<std-macros>"
@@ -445,7 +446,7 @@ fn emit_source(&mut self, filename: &str) -> bool {
         }
 
         cur.push(p.filename().expect("source has no filename") + bytes!(".html"));
-        let mut w = BufferedWriter::new(file::create(&cur).unwrap());
+        let mut w = BufferedWriter::new(File::create(&cur).unwrap());
 
         let title = cur.filename_display().with_str(|s| format!("{} -- source", s));
         let page = layout::Page {
@@ -767,7 +768,7 @@ fn worker(cache: RWArc<Cache>,
     ///
     /// The rendering driver uses this closure to queue up more work.
     fn item(&mut self, item: clean::Item, f: &fn(&mut Context, clean::Item)) {
-        fn render(w: file::FileWriter, cx: &mut Context, it: &clean::Item,
+        fn render(w: io::File, cx: &mut Context, it: &clean::Item,
                   pushname: bool) {
             // A little unfortunate that this is done like this, but it sure
             // does make formatting *a lot* nicer.
@@ -804,7 +805,7 @@ fn render(w: file::FileWriter, cx: &mut Context, it: &clean::Item,
                 do self.recurse(name) |this| {
                     let item = item.take();
                     let dst = this.dst.join("index.html");
-                    render(file::create(&dst).unwrap(), this, &item, false);
+                    render(File::create(&dst).unwrap(), this, &item, false);
 
                     let m = match item.inner {
                         clean::ModuleItem(m) => m,
@@ -821,7 +822,7 @@ fn render(w: file::FileWriter, cx: &mut Context, it: &clean::Item,
             // pages dedicated to them.
             _ if item.name.is_some() => {
                 let dst = self.dst.join(item_path(&item));
-                render(file::create(&dst).unwrap(), self, &item, true);
+                render(File::create(&dst).unwrap(), self, &item, true);
             }
 
             _ => {}
index 7a64ca6d6fc2a0c2cb3f1ab911eb01bc99df0183..c69fd9879ce2f6378c6e406be8ace46036402170 100644 (file)
@@ -26,7 +26,7 @@
 use std::cell::Cell;
 use std::local_data;
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::rt::io::mem::MemWriter;
 use std::rt::io::Decorator;
 use std::str;
@@ -259,7 +259,7 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
 /// This input format purely deserializes the json output file. No passes are
 /// run over the deserialized output.
 fn json_input(input: &str) -> Result<Output, ~str> {
-    let input = match file::open(&Path::new(input)) {
+    let input = match File::open(&Path::new(input)) {
         Some(f) => f,
         None => return Err(format!("couldn't open {} for reading", input)),
     };
@@ -321,7 +321,7 @@ fn json_output(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
     json.insert(~"crate", crate_json);
     json.insert(~"plugins", json::Object(plugins_json));
 
-    let mut file = file::create(&dst).unwrap();
+    let mut file = File::create(&dst).unwrap();
     let output = json::Object(json).to_str();
     file.write(output.as_bytes());
 }
index bb6088adee18e7966074ab399258fc6ef2afefa8..cc10f15ffb1016fb85447730828bf8d5c4f75155 100644 (file)
@@ -28,6 +28,7 @@
 use std::hashmap::HashSet;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 pub use std::path::Path;
 
 use extra::workcache;
@@ -661,7 +662,7 @@ fn install_no_build(&self,
                 for exec in subex.iter() {
                     debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display());
                     file::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX);
-                    file::copy(exec, &sub_target_ex);
+                    File::copy(exec, &sub_target_ex);
                     // FIXME (#9639): This needs to handle non-utf8 paths
                     exe_thing.discover_output("binary",
                         sub_target_ex.as_str().unwrap(),
@@ -674,7 +675,7 @@ fn install_no_build(&self,
                                              didn't install it!", lib.display()));
                     target_lib.set_filename(lib.filename().expect("weird target lib"));
                     file::mkdir_recursive(&target_lib.dir_path(), io::UserRWX);
-                    file::copy(lib, &target_lib);
+                    File::copy(lib, &target_lib);
                     debug!("3. discovering output {}", target_lib.display());
                     exe_thing.discover_output("binary",
                                               target_lib.as_str().unwrap(),
index a52aa68e1e4716448b498f6c6e32165e0fd25ef5..5e3a90bbf58f7905f91da22ff11018ee8bfc19d0 100644 (file)
@@ -14,6 +14,7 @@
 use package_id::PkgId;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 use std::os;
 use context::*;
 use crate::Crate;
@@ -301,7 +302,7 @@ pub fn fetch_git(local: &Path, pkgid: &PkgId) -> Option<Path> {
                 // Move clone_target to local.
                 // First, create all ancestor directories.
                 let moved = make_dir_rwx_recursive(&local.dir_path())
-                    && io::result(|| file::rename(&clone_target, local)).is_ok();
+                    && io::result(|| File::rename(&clone_target, local)).is_ok();
                 if moved { Some(local.clone()) }
                     else { None }
             }
@@ -350,7 +351,7 @@ pub fn find_crates_with_filter(&mut self, filter: &fn(&str) -> bool) {
 
         let prefix = self.start_dir.component_iter().len();
         debug!("Matching against {}", self.id.short_name);
-        do file::walk_dir(&self.start_dir) |pth| {
+        for pth in file::walk_dir(&self.start_dir) {
             let maybe_known_crate_set = match pth.filename_str() {
                 Some(filename) if filter(filename) => match filename {
                     "lib.rs" => Some(&mut self.libs),
@@ -363,11 +364,10 @@ pub fn find_crates_with_filter(&mut self, filter: &fn(&str) -> bool) {
             };
 
             match maybe_known_crate_set {
-                Some(crate_set) => PkgSrc::push_crate(crate_set, prefix, pth),
+                Some(crate_set) => PkgSrc::push_crate(crate_set, prefix, &pth),
                 None => ()
             }
-            true
-        };
+        }
 
         let crate_sets = [&self.libs, &self.mains, &self.tests, &self.benchs];
         if crate_sets.iter().all(|crate_set| crate_set.is_empty()) {
index 75f03533d583c00df70e3ec2edece436361a8693..e8f1b2300c73751e947a8bb418c051c049d8fba1 100644 (file)
@@ -21,6 +21,7 @@
 use std::os;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 use messages::*;
 
 pub fn default_workspace() -> Path {
@@ -72,9 +73,9 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
     if !src_dir.is_dir() { return None }
 
     let mut found = None;
-    do file::walk_dir(&src_dir) |p| {
+    for p in file::walk_dir(&src_dir) {
         if p.is_dir() {
-            if *p == src_dir.join(&pkgid.path) || {
+            if p == src_dir.join(&pkgid.path) || {
                 let pf = p.filename_str();
                 do pf.iter().any |&g| {
                     match split_version_general(g, '-') {
@@ -89,9 +90,8 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
                 found = Some(p.clone());
             }
 
-        };
-        true
-    };
+        }
+    }
 
     if found.is_some() {
         debug!("Found {} in {}", pkgid.to_str(), workspace.display());
@@ -399,12 +399,12 @@ pub fn uninstall_package_from(workspace: &Path, pkgid: &PkgId) {
     let mut did_something = false;
     let installed_bin = target_executable_in_workspace(pkgid, workspace);
     if installed_bin.exists() {
-        file::unlink(&installed_bin);
+        File::unlink(&installed_bin);
         did_something = true;
     }
     let installed_lib = target_library_in_workspace(pkgid, workspace);
     if installed_lib.exists() {
-        file::unlink(&installed_lib);
+        File::unlink(&installed_lib);
         did_something = true;
     }
     if !did_something {
index a0e50ff0f9ef7696b06028aeb7f3eebc8f9ddc75..e5d1c9b597ffc7142d3fb418339f716d698e0219 100644 (file)
@@ -96,12 +96,11 @@ pub enum CloneResult {
 
 pub fn make_read_only(target: &Path) {
     // Now, make all the files in the target dir read-only
-    do file::walk_dir(target) |p| {
+    for p in file::walk_dir(target) {
         if !p.is_dir() {
-            assert!(chmod_read_only(p));
-        };
-        true
-    };
+            assert!(chmod_read_only(&p));
+        }
+    }
 }
 
 /// Source can be either a URL or a local file path.
index 60e99f242ef1422077bd2d6595e491ca348cd1a0..a2ef80db6d6846994ce405639e888467115be964 100644 (file)
@@ -14,6 +14,7 @@
 use std::{os, run, str, task};
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 use extra::arc::Arc;
 use extra::arc::RWArc;
 use extra::tempfile::TempDir;
@@ -83,7 +84,7 @@ fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId {
 }
 
 fn writeFile(file_path: &Path, contents: &str) {
-    let mut out = file::create(file_path);
+    let mut out = File::create(file_path);
     out.write(contents.as_bytes());
     out.write(['\n' as u8]);
 }
@@ -196,23 +197,13 @@ fn add_git_tag(repo: &Path, tag: ~str) {
 }
 
 fn is_rwx(p: &Path) -> bool {
-    use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-
     if !p.exists() { return false }
-    let m = p.stat().mode;
-    (m & S_IRUSR as u64) == S_IRUSR as u64
-     && (m & S_IWUSR as u64) == S_IWUSR as u64
-     && (m & S_IXUSR as u64) == S_IXUSR as u64
+    p.stat().perm & io::UserRWX == io::UserRWX
 }
 
 fn is_read_only(p: &Path) -> bool {
-    use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-
     if !p.exists() { return false }
-    let m = p.stat().mode;
-    (m & S_IRUSR as u64) == S_IRUSR as u64
-     && (m & S_IWUSR as u64) == 0 as u64
-     && (m & S_IXUSR as u64) == 0 as u64
+    p.stat().perm & io::UserRWX == io::UserRead
 }
 
 fn test_sysroot() -> Path {
@@ -398,7 +389,7 @@ fn test_executable_exists(repo: &Path, short_name: &str) -> bool {
 fn remove_executable_file(p: &PkgId, workspace: &Path) {
     let exec = target_executable_in_workspace(&PkgId::new(p.short_name), workspace);
     if exec.exists() {
-        file::unlink(&exec);
+        File::unlink(&exec);
     }
 }
 
@@ -419,7 +410,7 @@ fn built_executable_exists(repo: &Path, short_name: &str) -> bool {
 fn remove_built_executable_file(p: &PkgId, workspace: &Path) {
     let exec = built_executable_in_workspace(&PkgId::new(p.short_name), workspace);
     match exec {
-        Some(r) => file::unlink(&r),
+        Some(r) => File::unlink(&r),
         None    => ()
     }
 }
@@ -553,7 +544,7 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) {
             do io::io_error::cond.trap(|e| {
                 cond.raise((p.clone(), format!("Bad path: {}", e.desc)));
             }).inside {
-                let mut w = file::open_stream(p, io::Append, io::Write);
+                let mut w = File::open_mode(p, io::Append, io::Write);
                 w.write(bytes!("/* hi */\n"));
             }
         }
@@ -902,7 +893,7 @@ fn package_script_with_default_build() {
     let source = Path::new(file!()).dir_path().join_many(
         [~"testsuite", ~"pass", ~"src", ~"fancy-lib", ~"pkg.rs"]);
     debug!("package_script_with_default_build: {}", source.display());
-    file::copy(&source, &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"]));
+    File::copy(&source, &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"]));
     command_line_test([~"install", ~"fancy-lib"], dir);
     assert_lib_exists(dir, &Path::new("fancy-lib"), NoVersion);
     assert!(target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]).exists());
@@ -2288,7 +2279,7 @@ fn test_c_dependency_ok() {
     debug!("dir = {}", dir.display());
     let source = Path::new(file!()).dir_path().join_many(
         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
-    file::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
+    File::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
     command_line_test([~"build", ~"cdep"], dir);
     assert_executable_exists(dir, "cdep");
     let out_dir = target_build_dir(dir).join("cdep");
@@ -2309,7 +2300,7 @@ fn test_c_dependency_no_rebuilding() {
     debug!("dir = {}", dir.display());
     let source = Path::new(file!()).dir_path().join_many(
         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
-    file::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
+    File::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
     command_line_test([~"build", ~"cdep"], dir);
     assert_executable_exists(dir, "cdep");
     let out_dir = target_build_dir(dir).join("cdep");
@@ -2342,7 +2333,7 @@ fn test_c_dependency_yes_rebuilding() {
         [~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
     let target = dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]);
     debug!("Copying {} -> {}", source.display(), target.display());
-    file::copy(&source, &target);
+    File::copy(&source, &target);
     command_line_test([~"build", ~"cdep"], dir);
     assert_executable_exists(dir, "cdep");
     let out_dir = target_build_dir(dir).join("cdep");
@@ -2366,7 +2357,5 @@ fn test_c_dependency_yes_rebuilding() {
 
 /// Returns true if p exists and is executable
 fn is_executable(p: &Path) -> bool {
-    use std::libc::consts::os::posix88::{S_IXUSR};
-
-    p.exists() && p.stat().mode & S_IXUSR as u64 == S_IXUSR as u64
+    p.exists() && p.stat().perm & io::UserExec == io::UserExec
 }
index e5fb6889ae09b83caf95e5d42dab6b5b997a8e68..1c3bf897bec1d437a76641fd8deb353c3cb88a4c 100644 (file)
@@ -12,7 +12,7 @@
 extern mod rustc;
 
 use std::os;
-use std::rt::io::file;
+use std::rt::io::File;
 use rustpkg::api;
 use rustpkg::version::NoVersion;
 
@@ -43,7 +43,7 @@ pub fn main() {
     let out_path = os::self_exe_path().expect("Couldn't get self_exe path");
 
     debug!("Writing file");
-    let mut file = file::create(&out_path.join("generated.rs"));
+    let mut file = File::create(&out_path.join("generated.rs"));
     file.write("pub fn wheeeee() { let xs = [1, 2, 3]; \
                 for _ in xs.iter() { assert!(true); } }".as_bytes());
 
index c16224afbf4c815a0d131c7cff319dd54bdbc3a2..d8b35f2c0332a424e2764b48c98f3022a0862c14 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use extra::workcache;
 use sha1::{Digest, Sha1};
 
@@ -17,7 +17,7 @@
 pub fn digest_file_with_date(path: &Path) -> ~str {
     use conditions::bad_path::cond;
 
-    match io::result(|| file::open(path).read_to_end()) {
+    match io::result(|| File::open(path).read_to_end()) {
         Ok(bytes) => {
             let mut sha = Sha1::new();
             sha.input(bytes);
index 15df189edcdd4f7d211f359bcb9194d0c7a8013b..99060de1d2dd2225434671f9bf6eae58e106d75f 100644 (file)
 use std::ptr::null;
 use std::c_str;
 use std::c_str::CString;
-use std::libc::c_void;
 use std::cast::transmute;
 use std::libc;
-use std::libc::{c_int};
+use std::libc::{c_int, c_char, c_void};
 
 use super::{Request, NativeHandle, Loop, FsCallback, Buf,
             status_to_maybe_uv_error, UvError};
@@ -49,12 +48,9 @@ pub fn open(self, loop_: &Loop, path: &CString, flags: int, mode: int,
         assert_eq!(ret, 0);
     }
 
-    pub fn open_sync(self, loop_: &Loop, path: &CString,
+    pub fn open_sync(mut 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 complete_cb_ptr = self.req_boilerplate(None);
         let result = path.with_ref(|p| unsafe {
             uvll::fs_open(loop_.native_handle(),
                     self.native_handle(), p, flags, mode, complete_cb_ptr)
@@ -62,11 +58,8 @@ pub fn open_sync(self, loop_: &Loop, path: &CString,
         self.sync_cleanup(result)
     }
 
-    pub fn unlink(self, loop_: &Loop, path: &CString, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
+    pub fn unlink(mut self, loop_: &Loop, path: &CString, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
         let ret = path.with_ref(|p| unsafe {
             uvll::fs_unlink(loop_.native_handle(),
                           self.native_handle(), p, complete_cb_ptr)
@@ -74,12 +67,9 @@ pub fn unlink(self, loop_: &Loop, path: &CString, cb: FsCallback) {
         assert_eq!(ret, 0);
     }
 
-    pub fn unlink_sync(self, loop_: &Loop, path: &CString)
+    pub fn unlink_sync(mut self, loop_: &Loop, path: &CString)
       -> Result<c_int, UvError> {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(None)
-        };
+        let complete_cb_ptr = self.req_boilerplate(None);
         let result = path.with_ref(|p| unsafe {
             uvll::fs_unlink(loop_.native_handle(),
                           self.native_handle(), p, complete_cb_ptr)
@@ -87,11 +77,17 @@ pub fn unlink_sync(self, loop_: &Loop, path: &CString)
         self.sync_cleanup(result)
     }
 
-    pub fn stat(self, loop_: &Loop, path: &CString, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
+    pub fn lstat(mut self, loop_: &Loop, path: &CString, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        let ret = path.with_ref(|p| unsafe {
+            uvll::uv_fs_lstat(loop_.native_handle(),
+                              self.native_handle(), p, complete_cb_ptr)
+        });
+        assert_eq!(ret, 0);
+    }
+
+    pub fn stat(mut self, loop_: &Loop, path: &CString, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
         let ret = path.with_ref(|p| unsafe {
             uvll::fs_stat(loop_.native_handle(),
                           self.native_handle(), p, complete_cb_ptr)
@@ -99,11 +95,9 @@ pub fn stat(self, loop_: &Loop, path: &CString, cb: FsCallback) {
         assert_eq!(ret, 0);
     }
 
-    pub fn write(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
+    pub fn write(mut self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64,
+                 cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
         let base_ptr = buf.base as *c_void;
         let len = buf.len as uint;
         let ret = unsafe {
@@ -113,12 +107,9 @@ pub fn write(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallbac
         };
         assert_eq!(ret, 0);
     }
-    pub fn write_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
+    pub fn write_sync(mut self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
           -> Result<c_int, UvError> {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(None)
-        };
+        let complete_cb_ptr = self.req_boilerplate(None);
         let base_ptr = buf.base as *c_void;
         let len = buf.len as uint;
         let result = unsafe {
@@ -129,11 +120,9 @@ pub fn write_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
         self.sync_cleanup(result)
     }
 
-    pub fn read(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
+    pub fn read(mut self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64,
+                cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
         let buf_ptr = buf.base as *c_void;
         let len = buf.len as uint;
         let ret = unsafe {
@@ -143,12 +132,9 @@ pub fn read(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64, cb: FsCallback
         };
         assert_eq!(ret, 0);
     }
-    pub fn read_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
+    pub fn read_sync(mut self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
           -> Result<c_int, UvError> {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(None)
-        };
+        let complete_cb_ptr = self.req_boilerplate(None);
         let buf_ptr = buf.base as *c_void;
         let len = buf.len as uint;
         let result = unsafe {
@@ -159,22 +145,16 @@ pub fn read_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
         self.sync_cleanup(result)
     }
 
-    pub fn close(self, loop_: &Loop, fd: c_int, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = unsafe {
+    pub fn close(mut self, loop_: &Loop, fd: c_int, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
             uvll::fs_close(loop_.native_handle(), self.native_handle(),
                            fd, complete_cb_ptr)
-        };
-        assert_eq!(ret, 0);
+        }, 0);
     }
-    pub fn close_sync(self, loop_: &Loop, fd: c_int) -> Result<c_int, UvError> {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(None)
-        };
+    pub fn close_sync(mut self, loop_: &Loop,
+                      fd: c_int) -> Result<c_int, UvError> {
+        let complete_cb_ptr = self.req_boilerplate(None);
         let result = unsafe {
             uvll::fs_close(loop_.native_handle(), self.native_handle(),
                            fd, complete_cb_ptr)
@@ -182,68 +162,119 @@ pub fn close_sync(self, loop_: &Loop, fd: c_int) -> Result<c_int, UvError> {
         self.sync_cleanup(result)
     }
 
-    pub fn mkdir(self, loop_: &Loop, path: &CString, mode: c_int, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = path.with_ref(|p| unsafe {
+    pub fn mkdir(mut self, loop_: &Loop, path: &CString, mode: c_int,
+                 cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
             uvll::fs_mkdir(loop_.native_handle(),
                            self.native_handle(), p, mode, complete_cb_ptr)
-        });
-        assert_eq!(ret, 0);
+        }), 0);
     }
 
-    pub fn rmdir(self, loop_: &Loop, path: &CString, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = path.with_ref(|p| unsafe {
+    pub fn rmdir(mut self, loop_: &Loop, path: &CString, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
             uvll::fs_rmdir(loop_.native_handle(),
                            self.native_handle(), p, complete_cb_ptr)
-        });
-        assert_eq!(ret, 0);
+        }), 0);
     }
 
-    pub fn rename(self, loop_: &Loop, path: &CString, to: &CString, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = unsafe {
+    pub fn rename(mut self, loop_: &Loop, path: &CString, to: &CString,
+                  cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
             uvll::fs_rename(loop_.native_handle(),
                             self.native_handle(),
                             path.with_ref(|p| p),
                             to.with_ref(|p| p),
                             complete_cb_ptr)
-        };
-        assert_eq!(ret, 0);
+        }, 0);
     }
 
-    pub fn chmod(self, loop_: &Loop, path: &CString, mode: c_int, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = path.with_ref(|p| unsafe {
+    pub fn chmod(mut self, loop_: &Loop, path: &CString, mode: c_int,
+                 cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
             uvll::fs_chmod(loop_.native_handle(), self.native_handle(), p, mode,
                            complete_cb_ptr)
-        });
-        assert_eq!(ret, 0);
+        }), 0);
     }
 
-    pub fn readdir(self, loop_: &Loop, path: &CString,
+    pub fn readdir(mut self, loop_: &Loop, path: &CString,
                    flags: c_int, cb: FsCallback) {
-        let complete_cb_ptr = {
-            let mut me = self;
-            me.req_boilerplate(Some(cb))
-        };
-        let ret = path.with_ref(|p| unsafe {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
             uvll::fs_readdir(loop_.native_handle(),
                              self.native_handle(), p, flags, complete_cb_ptr)
-        });
-        assert_eq!(ret, 0);
+        }), 0);
+    }
+
+    pub fn readlink(mut self, loop_: &Loop, path: &CString, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
+            uvll::uv_fs_readlink(loop_.native_handle(),
+                                 self.native_handle(), p, complete_cb_ptr)
+        }), 0);
+    }
+
+    pub fn chown(mut self, loop_: &Loop, path: &CString, uid: int, gid: int,
+                 cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(path.with_ref(|p| unsafe {
+            uvll::uv_fs_chown(loop_.native_handle(),
+                              self.native_handle(), p,
+                              uid as uvll::uv_uid_t,
+                              gid as uvll::uv_gid_t,
+                              complete_cb_ptr)
+        }), 0);
+    }
+
+    pub fn truncate(mut self, loop_: &Loop, file: c_int, offset: i64,
+                    cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
+            uvll::uv_fs_ftruncate(loop_.native_handle(),
+                                  self.native_handle(), file, offset,
+                                  complete_cb_ptr)
+        }, 0);
+    }
+
+    pub fn link(mut self, loop_: &Loop, src: &CString, dst: &CString,
+                cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
+            uvll::uv_fs_link(loop_.native_handle(), self.native_handle(),
+                             src.with_ref(|p| p),
+                             dst.with_ref(|p| p),
+                             complete_cb_ptr)
+        }, 0);
+    }
+
+    pub fn symlink(mut self, loop_: &Loop, src: &CString, dst: &CString,
+                   cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
+            uvll::uv_fs_symlink(loop_.native_handle(), self.native_handle(),
+                                src.with_ref(|p| p),
+                                dst.with_ref(|p| p),
+                                complete_cb_ptr)
+        }, 0);
+    }
+
+    pub fn fsync(mut self, loop_: &Loop, fd: c_int, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
+            uvll::uv_fs_fsync(loop_.native_handle(), self.native_handle(), fd,
+                              complete_cb_ptr)
+        }, 0);
+    }
+
+    pub fn datasync(mut self, loop_: &Loop, fd: c_int, cb: FsCallback) {
+        let complete_cb_ptr = self.req_boilerplate(Some(cb));
+        assert_eq!(unsafe {
+            uvll::uv_fs_fdatasync(loop_.native_handle(), self.native_handle(), fd,
+                                  complete_cb_ptr)
+        }, 0);
     }
 
     // accessors/utility funcs
@@ -284,10 +315,12 @@ fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData {
         }
     }
 
-    pub fn get_result(&mut self) -> c_int {
-        unsafe {
-            uvll::get_result_from_fs_req(self.native_handle())
-        }
+    pub fn get_path(&self) -> *c_char {
+        unsafe { uvll::get_path_from_fs_req(self.native_handle()) }
+    }
+
+    pub fn get_result(&self) -> c_int {
+        unsafe { uvll::get_result_from_fs_req(self.native_handle()) }
     }
 
     pub fn get_loop(&self) -> Loop {
@@ -380,7 +413,7 @@ fn sync_cleanup(result: int)
 mod test {
     use super::*;
     //use std::rt::test::*;
-    use std::libc::{STDOUT_FILENO};
+    use std::libc::{STDOUT_FILENO, c_int};
     use std::vec;
     use std::str;
     use std::unstable::run_in_bare_thread;
index ae8546af4b40efe8a3da75e0e2c8cea6b66e8969..25839c429da6acf58141bd2b76b1b9ef907d9cdd 100644 (file)
@@ -8,18 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::c_str::{ToCStr, CString};
+use std::c_str::CString;
 use std::cast::transmute;
 use std::cast;
 use std::cell::Cell;
-use std::clone::Clone;
 use std::comm::{SendDeferred, SharedChan, Port, PortOne, GenericChan};
+use std::libc;
 use std::libc::{c_int, c_uint, c_void, pid_t};
-use std::ops::Drop;
-use std::option::*;
 use std::ptr;
 use std::str;
-use std::result::*;
 use std::rt::io;
 use std::rt::io::IoError;
 use std::rt::io::net::ip::{SocketAddr, IpAddr};
 use std::rt::tube::Tube;
 use std::rt::task::Task;
 use std::unstable::sync::Exclusive;
-use std::path::{GenericPath, Path};
-use std::libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY,
-                O_WRONLY, S_IRUSR, S_IWUSR};
-use std::rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
-                  CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite,
-                  FileStat};
+use std::libc::{lseek, off_t};
+use std::rt::io::{FileMode, FileAccess, FileStat};
 use std::rt::io::signal::Signum;
 use std::task;
 use ai = std::rt::io::net::addrinfo;
 
-#[cfg(test)] use std::container::Container;
 #[cfg(test)] use std::unstable::run_in_bare_thread;
 #[cfg(test)] use std::rt::test::{spawntask,
                                  next_test_ip4,
                                  run_in_mt_newsched_task};
-#[cfg(test)] use std::iter::{Iterator, range};
 #[cfg(test)] use std::rt::comm::oneshot;
 
 use super::*;
@@ -418,24 +409,25 @@ pub fn uv_loop<'a>(&'a mut self) -> &'a mut Loop {
     }
 }
 
-/// Helper for a variety of simple uv_fs_* functions that
-/// have no ret val
-fn uv_fs_helper(loop_: &mut Loop, path: &CString,
-                cb: ~fn(&mut FsRequest, &mut Loop, &CString,
-                        ~fn(&FsRequest, Option<UvError>)))
-        -> Result<(), IoError> {
+/// Helper for a variety of simple uv_fs_* functions that have no ret val. This
+/// function takes the loop that it will act on, and then invokes the specified
+/// callback in a situation where the task wil be immediately blocked
+/// afterwards. The `FsCallback` yielded must be invoked to reschedule the task
+/// (once the result of the operation is known).
+fn uv_fs_helper<T>(loop_: &mut Loop,
+                   retfn: extern "Rust" fn(&mut FsRequest) -> T,
+                   cb: &fn(&mut FsRequest, &mut Loop, FsCallback))
+        -> Result<T, IoError> {
     let result_cell = Cell::new_empty();
-    let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
-    let path_cell = Cell::new(path);
+    let result_cell_ptr: *Cell<Result<T, IoError>> = &result_cell;
     do task::unkillable { // FIXME(#8674)
         let scheduler: ~Scheduler = Local::take();
         let mut new_req = FsRequest::new();
         do scheduler.deschedule_running_task_and_then |_, task| {
             let task_cell = Cell::new(task);
-            let path = path_cell.take();
-            do cb(&mut new_req, loop_, path) |_, err| {
+            do cb(&mut new_req, loop_) |req, err| {
                 let res = match err {
-                    None => Ok(()),
+                    None => Ok(retfn(req)),
                     Some(err) => Err(uv_error_to_io_error(err))
                 };
                 unsafe { (*result_cell_ptr).put_back(res); }
@@ -448,6 +440,43 @@ fn uv_fs_helper(loop_: &mut Loop, path: &CString,
     return result_cell.take();
 }
 
+fn unit(_: &mut FsRequest) {}
+
+fn fs_mkstat(f: &mut FsRequest) -> FileStat {
+    let path = unsafe { Path::new(CString::new(f.get_path(), false)) };
+    let stat = f.get_stat();
+    fn to_msec(stat: uvll::uv_timespec_t) -> u64 {
+        (stat.tv_sec * 1000 + stat.tv_nsec / 1000000) as u64
+    }
+    let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
+        libc::S_IFREG => io::TypeFile,
+        libc::S_IFDIR => io::TypeDirectory,
+        libc::S_IFIFO => io::TypeNamedPipe,
+        libc::S_IFBLK => io::TypeBlockSpecial,
+        libc::S_IFLNK => io::TypeSymlink,
+        _ => io::TypeUnknown,
+    };
+    FileStat {
+        path: path,
+        size: stat.st_size as u64,
+        kind: kind,
+        perm: (stat.st_mode as io::FilePermission) & io::AllPermissions,
+        created: to_msec(stat.st_birthtim),
+        modified: to_msec(stat.st_mtim),
+        accessed: to_msec(stat.st_atim),
+        device: stat.st_dev as u64,
+        inode: stat.st_ino as u64,
+        rdev: stat.st_rdev as u64,
+        nlink: stat.st_nlink as u64,
+        uid: stat.st_uid as u64,
+        gid: stat.st_gid as u64,
+        blksize: stat.st_blksize as u64,
+        blocks: stat.st_blocks as u64,
+        flags: stat.st_flags as u64,
+        gen: stat.st_gen as u64,
+    }
+}
+
 impl IoFactory for UvIoFactory {
     // Connect to an address and return a new stream
     // NB: This blocks the task waiting on the connection.
@@ -552,6 +581,41 @@ fn timer_init(&mut self) -> Result<~RtioTimer, IoError> {
         Ok(~UvTimer::new(watcher, home) as ~RtioTimer)
     }
 
+    fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
+                          hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
+        let result_cell = Cell::new_empty();
+        let result_cell_ptr: *Cell<Result<~[ai::Info], IoError>> = &result_cell;
+        let host_ptr: *Option<&str> = &host;
+        let servname_ptr: *Option<&str> = &servname;
+        let hint_ptr: *Option<ai::Hint> = &hint;
+        let addrinfo_req = GetAddrInfoRequest::new();
+        let addrinfo_req_cell = Cell::new(addrinfo_req);
+
+        do task::unkillable { // FIXME(#8674)
+            let scheduler: ~Scheduler = Local::take();
+            do scheduler.deschedule_running_task_and_then |_, task| {
+                let task_cell = Cell::new(task);
+                let mut addrinfo_req = addrinfo_req_cell.take();
+                unsafe {
+                    do addrinfo_req.getaddrinfo(self.uv_loop(),
+                                                *host_ptr, *servname_ptr,
+                                                *hint_ptr) |_, addrinfo, err| {
+                        let res = match err {
+                            None => Ok(accum_addrinfo(addrinfo)),
+                            Some(err) => Err(uv_error_to_io_error(err))
+                        };
+                        (*result_cell_ptr).put_back(res);
+                        let scheduler: ~Scheduler = Local::take();
+                        scheduler.resume_blocked_task_immediately(task_cell.take());
+                    }
+                }
+            }
+        }
+        addrinfo_req.delete();
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+
     fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream {
         let loop_ = Loop {handle: self.uv_loop().native_handle()};
         let home = get_handle_to_current_scheduler!();
@@ -560,35 +624,28 @@ fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream
 
     fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError> {
-        let mut flags = match fm {
-            Open => 0,
-            Create => O_CREAT,
-            OpenOrCreate => O_CREAT,
-            Append => O_APPEND,
-            Truncate => O_TRUNC,
-            CreateOrTruncate => O_TRUNC | O_CREAT
-        };
-        flags = match fa {
-            Read => flags | O_RDONLY,
-            Write => flags | O_WRONLY,
-            ReadWrite => flags | O_RDWR
+        let flags = match fm {
+            io::Open => 0,
+            io::Append => libc::O_APPEND,
+            io::Truncate => libc::O_TRUNC,
         };
-        let create_mode = match fm {
-            Create|OpenOrCreate|CreateOrTruncate =>
-                S_IRUSR | S_IWUSR,
-            _ => 0
+        // Opening with a write permission must silently create the file.
+        let (flags, mode) = match fa {
+            io::Read => (flags | libc::O_RDONLY, 0),
+            io::Write => (flags | libc::O_WRONLY | libc::O_CREAT,
+                          libc::S_IRUSR | libc::S_IWUSR),
+            io::ReadWrite => (flags | libc::O_RDWR | libc::O_CREAT,
+                              libc::S_IRUSR | libc::S_IWUSR),
         };
         let result_cell = Cell::new_empty();
         let result_cell_ptr: *Cell<Result<~RtioFileStream,
                                            IoError>> = &result_cell;
-        let path_cell = Cell::new(path);
         do task::unkillable { // FIXME(#8674)
             let scheduler: ~Scheduler = Local::take();
             let open_req = file::FsRequest::new();
             do scheduler.deschedule_running_task_and_then |_, task| {
                 let task_cell = Cell::new(task);
-                let path = path_cell.take();
-                do open_req.open(self.uv_loop(), path, flags as int, create_mode as int)
+                do open_req.open(self.uv_loop(), path, flags as int, mode as int)
                       |req,err| {
                     if err.is_none() {
                         let loop_ = Loop {handle: req.get_loop().native_handle()};
@@ -614,125 +671,42 @@ fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
     }
 
     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)
-            };
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.unlink(l, path, cb)
         }
     }
-    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,
-                                           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();
-                // Don't pick up the null byte
-                let slice = path.as_bytes().slice(0, path.len());
-                let path_instance = Cell::new(Path::new(slice));
-                do stat_req.stat(self.uv_loop(), path) |req,err| {
-                    let res = match err {
-                        None => {
-                            let stat = req.get_stat();
-                            Ok(FileStat {
-                                path: path_instance.take(),
-                                is_file: stat.is_file(),
-                                is_dir: stat.is_dir(),
-                                device: stat.st_dev,
-                                mode: stat.st_mode,
-                                inode: stat.st_ino,
-                                size: stat.st_size,
-                                created: stat.st_ctim.tv_sec as u64,
-                                modified: stat.st_mtim.tv_sec as u64,
-                                accessed: stat.st_atim.tv_sec as u64
-                            })
-                        },
-                        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();
+    fn fs_lstat(&mut self, path: &CString) -> Result<FileStat, IoError> {
+        do uv_fs_helper(self.uv_loop(), fs_mkstat) |req, l, cb| {
+            req.lstat(l, path, cb)
+        }
     }
-
-    fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
-                          hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
-        let result_cell = Cell::new_empty();
-        let result_cell_ptr: *Cell<Result<~[ai::Info], IoError>> = &result_cell;
-        let host_ptr: *Option<&str> = &host;
-        let servname_ptr: *Option<&str> = &servname;
-        let hint_ptr: *Option<ai::Hint> = &hint;
-        let addrinfo_req = GetAddrInfoRequest::new();
-        let addrinfo_req_cell = Cell::new(addrinfo_req);
-
-        do task::unkillable { // FIXME(#8674)
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let task_cell = Cell::new(task);
-                let mut addrinfo_req = addrinfo_req_cell.take();
-                unsafe {
-                    do addrinfo_req.getaddrinfo(self.uv_loop(),
-                                                *host_ptr, *servname_ptr,
-                                                *hint_ptr) |_, addrinfo, err| {
-                        let res = match err {
-                            None => Ok(accum_addrinfo(addrinfo)),
-                            Some(err) => Err(uv_error_to_io_error(err))
-                        };
-                        (*result_cell_ptr).put_back(res);
-                        let scheduler: ~Scheduler = Local::take();
-                        scheduler.resume_blocked_task_immediately(task_cell.take());
-                    }
-                }
-            }
+    fn fs_stat(&mut self, path: &CString) -> Result<FileStat, IoError> {
+        do uv_fs_helper(self.uv_loop(), fs_mkstat) |req, l, cb| {
+            req.stat(l, path, cb)
         }
-        addrinfo_req.delete();
-        assert!(!result_cell.is_empty());
-        return result_cell.take();
     }
     fn fs_mkdir(&mut self, path: &CString,
                 perm: io::FilePermission) -> Result<(), IoError> {
-        do uv_fs_helper(self.uv_loop(), path) |mkdir_req, l, p, cb| {
-            do mkdir_req.mkdir(l, p, perm as c_int) |req, err| {
-                cb(req, err)
-            };
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.mkdir(l, path, perm as c_int, cb)
         }
     }
     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)
-            };
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.rmdir(l, path, cb)
         }
     }
     fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError> {
-        let to = to.with_ref(|p| p);
-        do uv_fs_helper(self.uv_loop(), path) |rename_req, l, p, cb| {
-            let to = unsafe { CString::new(to, false) };
-            do rename_req.rename(l, p, &to) |req, err| {
-                cb(req, err)
-            };
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.rename(l, path, to, cb)
         }
     }
     fn fs_chmod(&mut self, path: &CString,
                 perm: io::FilePermission) -> Result<(), IoError> {
-        do uv_fs_helper(self.uv_loop(), path) |chmod_req, l, p, cb| {
-            do chmod_req.chmod(l, p, perm as c_int) |req, err| {
-                cb(req, err)
-            };
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.chmod(l, path, perm as c_int, cb)
         }
     }
->>>>>>> Remove all blocking std::os blocking functions
     fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
         Result<~[Path], IoError> {
         use str::StrSlice;
@@ -773,6 +747,29 @@ fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
         assert!(!result_cell.is_empty());
         return result_cell.take();
     }
+    fn fs_link(&mut self, src: &CString, dst: &CString) -> Result<(), IoError> {
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.link(l, src, dst, cb)
+        }
+    }
+    fn fs_symlink(&mut self, src: &CString, dst: &CString) -> Result<(), IoError> {
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.symlink(l, src, dst, cb)
+        }
+    }
+    fn fs_chown(&mut self, path: &CString, uid: int, gid: int) -> Result<(), IoError> {
+        do uv_fs_helper(self.uv_loop(), unit) |req, l, cb| {
+            req.chown(l, path, uid, gid, cb)
+        }
+    }
+    fn fs_readlink(&mut self, path: &CString) -> Result<Path, IoError> {
+        fn getlink(f: &mut FsRequest) -> Path {
+            Path::new(unsafe { CString::new(f.get_path(), false) })
+        }
+        do uv_fs_helper(self.uv_loop(), getlink) |req, l, cb| {
+            req.readlink(l, path, cb)
+        }
+    }
 
     fn spawn(&mut self, config: ProcessConfig)
             -> Result<(~RtioProcess, ~[Option<~RtioPipe>]), IoError>
@@ -1581,26 +1578,9 @@ fn base_read(&mut self, buf: &mut [u8], offset: i64) -> Result<int, IoError> {
         result_cell.take()
     }
     fn base_write(&mut self, buf: &[u8], offset: i64) -> Result<(), IoError> {
-        let result_cell = Cell::new_empty();
-        let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
-        let buf_ptr: *&[u8] = &buf;
-        do self.home_for_io_with_sched |self_, scheduler| {
-            do scheduler.deschedule_running_task_and_then |_, task| {
-                let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
-                let task_cell = Cell::new(task);
-                let write_req = file::FsRequest::new();
-                do write_req.write(&self_.loop_, self_.fd, buf, offset) |_, uverr| {
-                    let res = match uverr  {
-                        None => Ok(()),
-                        Some(err) => Err(uv_error_to_io_error(err))
-                    };
-                    unsafe { (*result_cell_ptr).put_back(res); }
-                    let scheduler: ~Scheduler = Local::take();
-                    scheduler.resume_blocked_task_immediately(task_cell.take());
-                }
-            }
+        do self.nop_req |self_, req, cb| {
+            req.write(&self_.loop_, self_.fd, slice_to_uv_buf(buf), offset, cb)
         }
-        result_cell.take()
     }
     fn seek_common(&mut self, pos: i64, whence: c_int) ->
         Result<u64, IoError>{
@@ -1618,6 +1598,27 @@ fn seek_common(&mut self, pos: i64, whence: c_int) ->
             }
         }
     }
+    fn nop_req(&mut self, f: &fn(&mut UvFileStream, file::FsRequest, FsCallback))
+            -> Result<(), IoError> {
+        let result_cell = Cell::new_empty();
+        let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
+        do self.home_for_io_with_sched |self_, sched| {
+            do sched.deschedule_running_task_and_then |_, task| {
+                let task = Cell::new(task);
+                let req = file::FsRequest::new();
+                do f(self_, req) |_, uverr| {
+                    let res = match uverr  {
+                        None => Ok(()),
+                        Some(err) => Err(uv_error_to_io_error(err))
+                    };
+                    unsafe { (*result_cell_ptr).put_back(res); }
+                    let scheduler: ~Scheduler = Local::take();
+                    scheduler.resume_blocked_task_immediately(task.take());
+                }
+            }
+        }
+        result_cell.take()
+    }
 }
 
 impl Drop for UvFileStream {
@@ -1672,6 +1673,21 @@ fn tell(&self) -> Result<u64, IoError> {
         let self_ = unsafe { cast::transmute::<&UvFileStream, &mut UvFileStream>(self) };
         self_.seek_common(0, SEEK_CUR)
     }
+    fn fsync(&mut self) -> Result<(), IoError> {
+        do self.nop_req |self_, req, cb| {
+            req.fsync(&self_.loop_, self_.fd, cb)
+        }
+    }
+    fn datasync(&mut self) -> Result<(), IoError> {
+        do self.nop_req |self_, req, cb| {
+            req.datasync(&self_.loop_, self_.fd, cb)
+        }
+    }
+    fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
+        do self.nop_req |self_, req, cb| {
+            req.truncate(&self_.loop_, self_.fd, offset, cb)
+        }
+    }
 }
 
 pub struct UvProcess {
@@ -2489,13 +2505,13 @@ fn test_timer_sleep_simple() {
 }
 
 fn file_test_uvio_full_simple_impl() {
-    use std::rt::io::{Open, Create, ReadWrite, Read};
+    use std::rt::io::{Open, ReadWrite, Read};
     unsafe {
         let io = local_io();
         let write_val = "hello uvio!";
         let path = "./tmp/file_test_uvio_full.txt";
         {
-            let create_fm = Create;
+            let create_fm = Open;
             let create_fa = ReadWrite;
             let mut fd = io.fs_open(&path.to_c_str(), create_fm, create_fa).unwrap();
             let write_buf = write_val.as_bytes();
index a2047ef98fa834b9db743710ebd480f4373ac7f5..b8f16db1066dc0b1ad8e58b522d1e10b1f1ff036 100644 (file)
@@ -222,6 +222,7 @@ pub fn is_dir(&self) -> bool {
                                     term_signal: c_int);
 pub type uv_signal_cb = extern "C" fn(handle: *uv_signal_t,
                                       signum: c_int);
+pub type uv_fs_cb = extern "C" fn(req: *uv_fs_t);
 
 pub type sockaddr = c_void;
 pub type sockaddr_in = c_void;
@@ -886,6 +887,11 @@ pub unsafe fn get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void {
 
     rust_uv_get_ptr_from_fs_req(req)
 }
+pub unsafe fn get_path_from_fs_req(req: *uv_fs_t) -> *c_char {
+    #[fixed_stack_segment]; #[inline(never)];
+
+    rust_uv_get_path_from_fs_req(req)
+}
 pub unsafe fn get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t {
     #[fixed_stack_segment]; #[inline(never)];
 
@@ -1129,6 +1135,7 @@ fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
     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_path_from_fs_req(req: *uv_fs_t) -> *c_char;
     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;
 
@@ -1189,7 +1196,24 @@ fn rust_uv_signal_start(handle: *uv_signal_t,
                             signal_cb: uv_signal_cb,
                             signum: c_int) -> c_int;
     fn rust_uv_signal_stop(handle: *uv_signal_t) -> c_int;
+
 }
+externfn!(fn uv_fs_fsync(handle: *uv_loop_t, req: *uv_fs_t, file: c_int,
+                         cb: *u8) -> c_int)
+externfn!(fn uv_fs_fdatasync(handle: *uv_loop_t, req: *uv_fs_t, file: c_int,
+                             cb: *u8) -> c_int)
+externfn!(fn uv_fs_ftruncate(handle: *uv_loop_t, req: *uv_fs_t, file: c_int,
+                             offset: i64, cb: *u8) -> c_int)
+externfn!(fn uv_fs_readlink(handle: *uv_loop_t, req: *uv_fs_t, file: *c_char,
+                            cb: *u8) -> c_int)
+externfn!(fn uv_fs_symlink(handle: *uv_loop_t, req: *uv_fs_t, src: *c_char,
+                           dst: *c_char, cb: *u8) -> c_int)
+externfn!(fn uv_fs_link(handle: *uv_loop_t, req: *uv_fs_t, src: *c_char,
+                        dst: *c_char, cb: *u8) -> c_int)
+externfn!(fn uv_fs_chown(handle: *uv_loop_t, req: *uv_fs_t, src: *c_char,
+                         uid: uv_uid_t, gid: uv_gid_t, cb: *u8) -> c_int)
+externfn!(fn uv_fs_lstat(handle: *uv_loop_t, req: *uv_fs_t, file: *c_char,
+                         cb: *u8) -> c_int)
 
 // libuv requires various system libraries to successfully link on some
 // platforms
index d4df0e826f604b8bc9c5099c068afd371312bb0d..f992b327495b55bef2b752d2bfe99451299f94bf 100644 (file)
 pub use libc::consts::os::posix88::{F_OK, O_APPEND, O_CREAT, O_EXCL};
 pub use libc::consts::os::posix88::{O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
 pub use libc::consts::os::posix88::{R_OK, S_IEXEC, S_IFBLK, S_IFCHR};
-pub use libc::consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG};
+pub use libc::consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IFLNK};
 pub use libc::consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR};
 pub use libc::consts::os::posix88::{STDERR_FILENO, STDIN_FILENO};
 pub use libc::consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK};
@@ -1168,6 +1168,7 @@ pub mod posix88 {
             pub static S_IFBLK : c_int = 12288;
             pub static S_IFDIR : c_int = 16384;
             pub static S_IFREG : c_int = 32768;
+            pub static S_IFLNK : c_int = 40960;
             pub static S_IFMT : c_int = 61440;
             pub static S_IEXEC : c_int = 64;
             pub static S_IWRITE : c_int = 128;
@@ -1345,6 +1346,7 @@ pub mod posix88 {
             pub static S_IFBLK : c_int = 24576;
             pub static S_IFDIR : c_int = 16384;
             pub static S_IFREG : c_int = 32768;
+            pub static S_IFLNK : c_int = 40960;
             pub static S_IFMT : c_int = 61440;
             pub static S_IEXEC : c_int = 64;
             pub static S_IWRITE : c_int = 128;
@@ -1555,6 +1557,7 @@ pub mod posix88 {
             pub static S_IFBLK : c_int = 24576;
             pub static S_IFDIR : c_int = 16384;
             pub static S_IFREG : c_int = 32768;
+            pub static S_IFLNK : c_int = 40960;
             pub static S_IFMT : c_int = 61440;
             pub static S_IEXEC : c_int = 64;
             pub static S_IWRITE : c_int = 128;
@@ -1999,6 +2002,7 @@ pub mod posix88 {
             pub static S_IFBLK : c_int = 24576;
             pub static S_IFDIR : c_int = 16384;
             pub static S_IFREG : c_int = 32768;
+            pub static S_IFLNK : c_int = 40960;
             pub static S_IFMT : c_int = 61440;
             pub static S_IEXEC : c_int = 64;
             pub static S_IWRITE : c_int = 128;
@@ -2341,6 +2345,7 @@ pub mod posix88 {
             pub static S_IFBLK : c_int = 24576;
             pub static S_IFDIR : c_int = 16384;
             pub static S_IFREG : c_int = 32768;
+            pub static S_IFLNK : c_int = 40960;
             pub static S_IFMT : c_int = 61440;
             pub static S_IEXEC : c_int = 64;
             pub static S_IWRITE : c_int = 128;
index 12281f06005a78883f3c54732ad6d0f41aec65eb..f461781e13251af089c6eddce8cc9a06a44e1aeb 100644 (file)
@@ -1495,7 +1495,7 @@ fn memory_map_file() {
         use result::{Ok, Err};
         use os::*;
         use libc::*;
-        use rt::io::file;
+        use rt::io::File;
 
         #[cfg(unix)]
         #[fixed_stack_segment]
@@ -1544,7 +1544,7 @@ fn lseek_(fd: c_int, size: uint) {
             assert!(*chunk.data == 0xbe);
             close(fd);
         }
-        file::unlink(&path);
+        File::unlink(&path);
     }
 
     // More recursive_mkdir tests are in extra::tempfile
index dfd654ac13c73fe2a18d35b06711e357f4bc44ae..8483b504c0137fee61ea1057fb8f30c0caa2c11e 100644 (file)
@@ -23,9 +23,6 @@
 use vec::Vector;
 use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
 
-#[cfg(target_os = "win32")]
-use rt::io::{FileStat, file, io_error};
-
 /// Iterator that yields successive components of a Path as &str
 ///
 /// Each component is yielded as Option<&str> for compatibility with PosixPath, but
@@ -1056,67 +1053,6 @@ fn prefix_is_sep(p: Option<PathPrefix>, c: u8) -> bool {
                     else { is_sep_verbatim(c as char) }
 }
 
-// Stat support
-#[cfg(target_os = "win32")]
-impl Path {
-    /// Calls stat() on the represented file and returns the resulting rt::io::FileStat
-    pub fn stat(&self) -> Option<FileStat> {
-        let mut file_stat: Option<FileStat> = None;
-        do io_error::cond.trap(|_| { /* Ignore error, will return None */ }).inside {
-            file_stat = file::stat(self);
-        }
-        file_stat
-    }
-
-    /// Returns whether the represented file exists
-    pub fn exists(&self) -> bool {
-        match self.stat() {
-            None => false,
-            Some(_) => true
-        }
-    }
-
-    /// Returns the filesize of the represented file
-    pub fn get_size(&self) -> Option<u64> {
-        match self.stat() {
-            None => None,
-            Some(st) => Some(st.size)
-        }
-    }
-
-    /// Returns the mode of the represented file
-    pub fn get_mode(&self) -> Option<uint> {
-        match self.stat() {
-            None => None,
-            Some(st) => Some(st.mode as uint)
-        }
-    }
-
-    /// Returns the atime of the represented file, as msecs
-    pub fn get_atime(&self) -> Option<u64> {
-        match self.stat() {
-            None => None,
-            Some(st) => Some(st.accessed)
-        }
-    }
-
-    /// Returns the mtime of the represented file, as msecs
-    pub fn get_mtime(&self) -> Option<u64> {
-        match self.stat() {
-            None => None,
-            Some(st) => Some(st.modified)
-        }
-    }
-
-    /// Returns the ctime of the represented file, as msecs
-    pub fn get_ctime(&self) -> Option<u64> {
-        match self.stat() {
-            None => None,
-            Some(st) => Some(st.created)
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
index c9499bb4aa8e604f2f5a064cc1d79a30f56e9340..a6d05ea307cdb9bb0351de8b2c14aaf1abc4ea43 100644 (file)
 
 use rand::Rng;
 use ops::Drop;
-use path::Path;
 
 #[cfg(unix)]
 use rand::reader::ReaderRng;
 #[cfg(unix)]
-use rt::io::file;
+use rt::io::File;
 
 #[cfg(windows)]
 use cast;
@@ -41,7 +40,7 @@
 /// This does not block.
 #[cfg(unix)]
 pub struct OSRng {
-    priv inner: ReaderRng<file::FileReader>
+    priv inner: ReaderRng<File>
 }
 /// A random number generator that retrieves randomness straight from
 /// the operating system. Platform sources:
@@ -61,7 +60,8 @@ impl OSRng {
     /// Create a new `OSRng`.
     #[cfg(unix)]
     pub fn new() -> OSRng {
-        let reader = file::open(&Path::new("/dev/urandom"));
+        use path::Path;
+        let reader = File::open(&Path::new("/dev/urandom"));
         let reader = reader.expect("Error opening /dev/urandom");
         let reader_rng = ReaderRng::new(reader);
 
index b6c0b58434f1ab958e5fad102db517f9f7f9443d..c3f5f38721151047365c762867207d817de14e65 100644 (file)
@@ -16,7 +16,7 @@
 At the top-level of the module are a set of freestanding functions, associated
 with various filesystem operations. They all operate on a `Path` object.
 
-All operations in this module, including those as part of `FileStream` et al
+All operations in this module, including those as part of `File` et al
 block the task during execution. Most will raise `std::rt::io::io_error`
 conditions in the event of failure.
 
 */
 
 use c_str::ToCStr;
+use iter::Iterator;
 use super::{Reader, Writer, Seek};
-use super::{SeekStyle, Read, Write, Open, CreateOrTruncate,
+use super::{SeekStyle, Read, Write, Open, IoError, Truncate,
             FileMode, FileAccess, FileStat, io_error, FilePermission};
 use rt::rtio::{RtioFileStream, IoFactory, with_local_io};
 use rt::io;
 use option::{Some, None, Option};
-use result::{Ok, Err};
+use result::{Ok, Err, Result};
 use path;
 use path::{Path, GenericPath};
+use vec::OwnedVector;
 
-/// Open a file for reading/writing, as indicated by `path`.
-///
-/// # Example
-///
-///     use std::rt::{io, file, io_error};
-///
-///     let p = Path::new("/some/file/path.txt");
-///
-///     do io_error::cond.trap(|_| {
-///         // hoo-boy...
-///     }).inside {
-///         let stream = match file::open_stream(&p, io::Create, io::ReadWrite) {
-///             Some(s) => s,
-///             None => fail!("whoops! I'm sure this raised, anyways..")
-///         };
-///         // do some stuff with that stream
-///
-///         // the file stream will be closed at the end of this block
-///     }
-///     // ..
-///
-/// `FileMode` and `FileAccess` provide information about the permissions
-/// context in which a given stream is created. More information about them
-/// can be found in `std::rt::io`'s docs.
+/// Unconstrained file access type that exposes read and write operations
 ///
-/// Note that, with this function, a `FileStream` is returned regardless of
-/// the access-limitations indicated by `FileAccess` (e.g. calling `write` on a
-/// `FileStream` opened as `ReadOnly` will raise an `io_error` condition at
-/// runtime). If you desire a more-correctly-constrained interface to files,
-/// use the `{open_stream, open, create}` methods that are a part of `Path`.
+/// Can be retreived via `File::open()` and `Path.File::open_mode()`.
 ///
 /// # Errors
 ///
-/// This function will raise an `io_error` condition under a number of different
-/// circumstances, to include but not limited to:
+/// This type will raise an io_error condition if operations are attempted against
+/// it for which its underlying file descriptor was not configured at creation
+/// time, via the `FileAccess` parameter to `file::open()`.
 ///
-/// * Opening a file that already exists with `FileMode` of `Create` or vice
-///   versa (e.g.  opening a non-existant file with `FileMode` or `Open`)
-/// * Attempting to open a file with a `FileAccess` that the user lacks
-///   permissions for
-/// * Filesystem-level errors (full disk, etc)
-pub fn open_stream(path: &Path,
-                   mode: FileMode,
-                   access: FileAccess) -> Option<FileStream> {
+/// For this reason, it is best to use the access-constrained wrappers that are
+/// exposed via `Path.open()` and `Path.create()`.
+pub struct File {
+    priv fd: ~RtioFileStream,
+    priv path: Path,
+    priv last_nread: int,
+}
+
+fn io_raise<T>(f: &fn(io: &mut IoFactory) -> Result<T, IoError>) -> Option<T> {
     do with_local_io |io| {
-        match io.fs_open(&path.to_c_str(), mode, access) {
-            Ok(fd) => Some(FileStream {
-                fd: fd,
-                last_nread: -1
-            }),
+        match f(io) {
+            Ok(t) => Some(t),
             Err(ioerr) => {
                 io_error::cond.raise(ioerr);
                 None
@@ -96,54 +70,367 @@ pub fn open_stream(path: &Path,
     }
 }
 
-/// Attempts to open a file in read-only mode. This function is equivalent to
-/// `open_stream(path, Open, Read)`, and will raise all of the same errors that
-/// `open_stream` does.
-///
-/// For more information, see the `open_stream` function.
-pub fn open(path: &Path) -> Option<FileReader> {
-    open_stream(path, Open, Read).map(|s| FileReader { stream: s })
-}
+impl File {
+    /// Open a file at `path` in the mode specified by the `mode` and `access`
+    /// arguments
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::{File, io_error, Open, ReadWrite};
+    ///
+    ///     let p = Path::new("/some/file/path.txt");
+    ///
+    ///     do io_error::cond.trap(|_| {
+    ///         // hoo-boy...
+    ///     }).inside {
+    ///         let file = match File::open_mode(&p, Open, ReadWrite) {
+    ///             Some(s) => s,
+    ///             None => fail!("whoops! I'm sure this raised, anyways..")
+    ///         };
+    ///         // do some stuff with that file
+    ///
+    ///         // the file will be closed at the end of this block
+    ///     }
+    ///     // ..
+    ///
+    /// `FileMode` and `FileAccess` provide information about the permissions
+    /// context in which a given stream is created. More information about them
+    /// can be found in `std::rt::io`'s docs. If a file is opened with `Write`
+    /// or `ReadWrite` access, then it will be created it it does not already
+    /// exist.
+    ///
+    /// Note that, with this function, a `File` is returned regardless of the
+    /// access-limitations indicated by `FileAccess` (e.g. calling `write` on a
+    /// `File` opened as `Read` will raise an `io_error` condition at runtime).
+    ///
+    /// # Errors
+    ///
+    /// This function will raise an `io_error` condition under a number of
+    /// different circumstances, to include but not limited to:
+    ///
+    /// * Opening a file that does not exist with `Read` access.
+    /// * Attempting to open a file with a `FileAccess` that the user lacks
+    ///   permissions for
+    /// * Filesystem-level errors (full disk, etc)
+    pub fn open_mode(path: &Path,
+                     mode: FileMode,
+                     access: FileAccess) -> Option<File> {
+        do with_local_io |io| {
+            match io.fs_open(&path.to_c_str(), mode, access) {
+                Ok(fd) => Some(File {
+                    path: path.clone(),
+                    fd: fd,
+                    last_nread: -1
+                }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
 
-/// Attempts to create a file in write-only mode. This function is equivalent to
-/// `open_stream(path, CreateOrTruncate, Write)`, and will raise all of the
-/// same errors that `open_stream` does.
-///
-/// For more information, see the `open_stream` function.
-pub fn create(path: &Path) -> Option<FileWriter> {
-    open_stream(path, CreateOrTruncate, Write).map(|s| FileWriter { stream: s })
-}
+    /// Attempts to open a file in read-only mode. This function is equivalent to
+    /// `File::open_mode(path, Open, Read)`, and will raise all of the same
+    /// errors that `File::open_mode` does.
+    ///
+    /// For more information, see the `File::open_mode` function.
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::File;
+    ///
+    ///     let contents = File::open("foo.txt").read_to_end();
+    pub fn open(path: &Path) -> Option<File> {
+        File::open_mode(path, Open, Read)
+    }
 
-/// Unlink a file from the underlying filesystem.
-///
-/// # Example
-///
-///     use std::rt::io::file;
-///
-///     let p = Path::new("/some/file/path.txt");
-///     file::unlink(&p);
-///     // if we made it here without failing, then the
-///     // unlink operation was successful
-///
-/// Note that, just because an unlink call was successful, it is not
-/// guaranteed that a file is immediately deleted (e.g. depending on
-/// platform, other open file descriptors may prevent immediate removal)
-///
-/// # Errors
-///
-/// This function will raise an `io_error` condition if the path points to a
-/// directory, the user lacks permissions to remove the file, or if some other
-/// filesystem-level error occurs.
-pub fn unlink(path: &Path) {
-    do with_local_io |io| {
-        match io.fs_unlink(&path.to_c_str()) {
-            Ok(()) => Some(()),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+    /// Attempts to create a file in write-only mode. This function is
+    /// equivalent to `File::open_mode(path, Truncate, Write)`, and will
+    /// raise all of the same errors that `File::open_mode` does.
+    ///
+    /// For more information, see the `File::open_mode` function.
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::File;
+    ///
+    ///     File::create("foo.txt").write(bytes!("This is a sample file"));
+    pub fn create(path: &Path) -> Option<File> {
+        File::open_mode(path, Truncate, Write)
+    }
+
+    /// Unlink a file from the underlying filesystem.
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::File;
+    ///
+    ///     let p = Path::new("/some/file/path.txt");
+    ///     File::unlink(&p);
+    ///     // if we made it here without failing, then the
+    ///     // unlink operation was successful
+    ///
+    /// Note that, just because an unlink call was successful, it is not
+    /// guaranteed that a file is immediately deleted (e.g. depending on
+    /// platform, other open file descriptors may prevent immediate removal)
+    ///
+    /// # Errors
+    ///
+    /// This function will raise an `io_error` condition if the path points to a
+    /// directory, the user lacks permissions to remove the file, or if some
+    /// other filesystem-level error occurs.
+    pub fn unlink(path: &Path) {
+        do io_raise |io| { io.fs_unlink(&path.to_c_str()) };
+    }
+
+    /// Given a path, query the file system to get information about a file,
+    /// directory, etc. This function will traverse symlinks to query
+    /// information about the destination file.
+    ///
+    /// Returns a fully-filled out stat structure on succes, and on failure it
+    /// will return a dummy stat structure (it is expected that the condition
+    /// raised is handled as well).
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::{File, io_error};
+    ///
+    ///     let p = Path::new("/some/file/path.txt");
+    ///
+    ///     do io_error::cond.trap(|_| {
+    ///         // hoo-boy...
+    ///     }).inside {
+    ///         let info = File::stat(p);
+    ///         if info.is_file {
+    ///             // just imagine the possibilities ...
+    ///         }
+    ///     }
+    ///
+    /// # Errors
+    ///
+    /// 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(path: &Path) -> FileStat {
+        do io_raise |io| {
+            io.fs_stat(&path.to_c_str())
+        }.unwrap_or_else(File::dummystat)
+    }
+
+    fn dummystat() -> FileStat {
+        FileStat {
+            path: Path::new(""),
+            size: 0,
+            kind: io::TypeFile,
+            perm: 0,
+            created: 0,
+            modified: 0,
+            accessed: 0,
+            device: 0,
+            inode: 0,
+            rdev: 0,
+            nlink: 0,
+            uid: 0,
+            gid: 0,
+            blksize: 0,
+            blocks: 0,
+            flags: 0,
+            gen: 0,
+        }
+    }
+
+    /// Perform the same operation as the `stat` function, except that this
+    /// function does not traverse through symlinks. This will return
+    /// information about the symlink file instead of the file that it points
+    /// to.
+    ///
+    /// # Errors
+    ///
+    /// See `stat`
+    pub fn lstat(path: &Path) -> FileStat {
+        do io_raise |io| {
+            io.fs_lstat(&path.to_c_str())
+        }.unwrap_or_else(File::dummystat)
+    }
+
+    /// Rename a file or directory to a new name.
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::File;
+    ///
+    ///     File::rename(Path::new("foo"), Path::new("bar"));
+    ///     // Oh boy, nothing was raised!
+    ///
+    /// # Errors
+    ///
+    /// Will raise an `io_error` condition if the provided `path` doesn't exist,
+    /// the process lacks permissions to view the contents, or if some other
+    /// intermittent I/O error occurs.
+    pub fn rename(from: &Path, to: &Path) {
+        do io_raise |io| {
+            io.fs_rename(&from.to_c_str(), &to.to_c_str())
+        };
+    }
+
+    /// Copies the contents of one file to another. This function will also
+    /// copy the permission bits of the original file to the destination file.
+    ///
+    /// Note that if `from` and `to` both point to the same file, then the file
+    /// will likely get truncated by this operation.
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io::File;
+    ///
+    ///     File::copy(Path::new("foo.txt"), Path::new("bar.txt"));
+    ///     // Oh boy, nothing was raised!
+    ///
+    /// # Errors
+    ///
+    /// Will raise an `io_error` condition is the following situtations, but is
+    /// not limited to just these cases:
+    ///
+    /// * The `from` path is not a file
+    /// * The `from` file does not exist
+    /// * The current process does not have the permission rights to access
+    ///   `from` or write `to`
+    ///
+    /// Note that this copy is not atomic in that once the destination is
+    /// ensured to not exist, the is nothing preventing the destination from
+    /// being created and then destroyed by this operation.
+    pub fn copy(from: &Path, to: &Path) {
+        if !from.is_file() {
+            return io_error::cond.raise(IoError {
+                kind: io::MismatchedFileTypeForOperation,
+                desc: "the source path is not an existing file",
+                detail: None,
+            });
+        }
+
+        let mut reader = match File::open(from) { Some(f) => f, None => return };
+        let mut writer = match File::create(to) { Some(f) => f, None => return };
+        let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
+
+        loop {
+            match reader.read(buf) {
+                Some(amt) => writer.write(buf.slice_to(amt)),
+                None => break
             }
         }
-    };
+
+        File::chmod(to, from.stat().perm)
+    }
+
+    /// Changes the permission mode bits found on a file or a directory. This
+    /// function takes a mask from the `io` module
+    ///
+    /// # Example
+    ///
+    ///     use std::rt::io;
+    ///     use std::rt::io::File;
+    ///
+    ///     File::chmod(&Path::new("file.txt"), io::UserFile);
+    ///     File::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite);
+    ///     File::chmod(&Path::new("dir"),      io::UserDir);
+    ///     File::chmod(&Path::new("file.exe"), io::UserExec);
+    ///
+    /// # Errors
+    ///
+    /// If this funciton encounters an I/O error, it will raise on the `io_error`
+    /// condition. Some possible error situations are not having the permission to
+    /// change the attributes of a file or the file not existing.
+    pub fn chmod(path: &Path, mode: io::FilePermission) {
+        do io_raise |io| {
+            io.fs_chmod(&path.to_c_str(), mode)
+        };
+    }
+
+    /// Change the user and group owners of a file at the specified path.
+    ///
+    /// # Errors
+    ///
+    /// This funtion will raise on the `io_error` condition on failure.
+    pub fn chown(path: &Path, uid: int, gid: int) {
+        do io_raise |io| { io.fs_chown(&path.to_c_str(), uid, gid) };
+    }
+
+    /// Creates a new hard link on the filesystem. The `dst` path will be a
+    /// link pointing to the `src` path. Note that systems often require these
+    /// two paths to both be located on the same filesystem.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn link(src: &Path, dst: &Path) {
+        do io_raise |io| { io.fs_link(&src.to_c_str(), &dst.to_c_str()) };
+    }
+
+    /// Creates a new symbolic link on the filesystem. The `dst` path will be a
+    /// symlink pointing to the `src` path.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn symlink(src: &Path, dst: &Path) {
+        do io_raise |io| { io.fs_symlink(&src.to_c_str(), &dst.to_c_str()) };
+    }
+
+    /// Reads a symlink, returning the file that the symlink points to.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    ///
+    /// XXX: does this fail if called on files.
+    pub fn readlink(path: &Path) -> Option<Path> {
+        do io_raise |io| { io.fs_readlink(&path.to_c_str()) }
+    }
+
+    /// Returns the original path which was used to open this file.
+    pub fn path<'a>(&'a self) -> &'a Path {
+        &self.path
+    }
+
+    /// Synchronizes all modifications to this file to its permanent storage
+    /// device. This will flush any internal buffers necessary to perform this
+    /// operation.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn fsync(&mut self) {
+        self.fd.fsync();
+    }
+
+    /// This function is similar to `fsync`, except that it may not synchronize
+    /// file metadata to the filesystem. This is intended for use case which
+    /// must synchronize content, but don't need the metadata on disk. The goal
+    /// of this method is to reduce disk operations.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn datasync(&mut self) {
+        self.fd.datasync();
+    }
+
+    /// Either truncates or extends the underlying file, as extended from the
+    /// file's current position. This is equivalent to the unix `truncate`
+    /// function.
+    ///
+    /// The offset given is added to the file's current position and the result
+    /// is the new size of the file. If the new size is less than the current
+    /// size, then the file is truncated. If the new size is greater than the
+    /// current size, then the file is expanded to be filled with 0s.
+    ///
+    /// # Errors
+    ///
+    /// On error, this function will raise on the `io_error` condition.
+    pub fn truncate(&mut self, offset: i64) {
+        self.fd.truncate(offset);
+    }
 }
 
 /// Create a new, empty directory at the provided path
@@ -163,14 +450,8 @@ pub fn unlink(path: &Path) {
 /// to make a new directory at the provided path, or if the directory already
 /// exists.
 pub fn mkdir(path: &Path, mode: FilePermission) {
-    do with_local_io |io| {
-        match io.fs_mkdir(&path.to_c_str(), mode) {
-            Ok(_) => Some(()),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
+    do io_raise |io| {
+        io.fs_mkdir(&path.to_c_str(), mode)
     };
 }
 
@@ -190,71 +471,11 @@ pub fn mkdir(path: &Path, mode: FilePermission) {
 /// to remove the directory at the provided path, or if the directory isn't
 /// empty.
 pub fn rmdir(path: &Path) {
-    do with_local_io |io| {
-        match io.fs_rmdir(&path.to_c_str()) {
-            Ok(_) => Some(()),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
+    do io_raise |io| {
+        io.fs_rmdir(&path.to_c_str())
     };
 }
 
-/// Get information on the file, directory, etc at the provided path
-///
-/// Given a path, query the file system to get information about a file,
-/// directory, etc.
-///
-/// Returns a fully-filled out stat structure on succes, and on failure it will
-/// return a dummy stat structure (it is expected that the condition raised is
-/// handled as well).
-///
-/// # Example
-///
-///     use std::rt::io::{file, io_error};
-///
-///     let p = Path::new("/some/file/path.txt");
-///
-///     do io_error::cond.trap(|_| {
-///         // hoo-boy...
-///     }).inside {
-///         let info = file::stat(p);
-///         if info.is_file {
-///             // just imagine the possibilities ...
-///         }
-///     }
-///
-/// # Errors
-///
-/// 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(path: &Path) -> FileStat {
-    do with_local_io |io| {
-        match io.fs_stat(&path.to_c_str()) {
-            Ok(p) => Some(p),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }.unwrap_or_else(|| {
-        FileStat {
-            path: Path::new(path.to_c_str()),
-            is_file: false,
-            is_dir: false,
-            device: 0,
-            mode: 0,
-            inode: 0,
-            size: 0,
-            created: 0,
-            modified: 0,
-            accessed: 0,
-        }
-    })
-}
-
 /// Retrieve a vector containing all entries within a provided directory
 ///
 /// # Example
@@ -278,105 +499,41 @@ pub fn stat(path: &Path) -> FileStat {
 /// the process lacks permissions to view the contents or if the `path` points
 /// at a non-directory file
 pub fn readdir(path: &Path) -> ~[Path] {
-    do with_local_io |io| {
-        match io.fs_readdir(&path.to_c_str(), 0) {
-            Ok(p) => Some(p),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
+    do io_raise |io| {
+        io.fs_readdir(&path.to_c_str(), 0)
     }.unwrap_or_else(|| ~[])
 }
 
-/// Rename a file or directory to a new name.
-///
-/// # Example
-///
-///     use std::rt::io::file;
-///
-///     file::rename(Path::new("foo"), Path::new("bar"));
-///     // Oh boy, nothing was raised!
-///
-/// # Errors
-///
-/// Will raise an `io_error` condition if the provided `path` doesn't exist,
-/// the process lacks permissions to view the contents, or if some other
-/// intermittent I/O error occurs.
-pub fn rename(from: &Path, to: &Path) {
-    do with_local_io |io| {
-        match io.fs_rename(&from.to_c_str(), &to.to_c_str()) {
-            Ok(()) => Some(()),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    };
+/// Returns an iterator which will recursively walk the directory structure
+/// rooted at `path`. The path given will not be iterated over, and this will
+/// perform iteration in a top-down order.
+pub fn walk_dir(path: &Path) -> WalkIterator {
+    WalkIterator { stack: readdir(path) }
 }
 
-/// Copies the contents of one file to another.
-///
-/// # Example
-///
-///     use std::rt::io::file;
-///
-///     file::copy(Path::new("foo.txt"), Path::new("bar.txt"));
-///     // Oh boy, nothing was raised!
-///
-/// # Errors
-///
-/// Will raise an `io_error` condition if the provided `from` doesn't exist,
-/// the process lacks permissions to view the contents, or if some other
-/// intermittent I/O error occurs (such as `to` couldn't be created).
-pub fn copy(from: &Path, to: &Path) {
-    let mut reader = match open(from) { Some(f) => f, None => return };
-    let mut writer = match create(to) { Some(f) => f, None => return };
-    let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
-
-    loop {
-        match reader.read(buf) {
-            Some(amt) => writer.write(buf.slice_to(amt)),
-            None => break
-        }
-    }
-
-    // FIXME(#10131) this is an awful way to pull out the permission bits.
-    //               If this comment is removed, then there should be a test
-    //               asserting that permission bits are maintained using the
-    //               permission interface created.
-    chmod(to, (from.stat().mode & 0xfff) as u32);
+/// An iterator which walks over a directory
+pub struct WalkIterator {
+    priv stack: ~[Path],
 }
 
-// This function is not public because it's got a terrible interface for `mode`
-// FIXME(#10131)
-fn chmod(path: &Path, mode: u32) {
-    do with_local_io |io| {
-        match io.fs_chmod(&path.to_c_str(), mode) {
-            Ok(()) => Some(()),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
+impl Iterator<Path> for WalkIterator {
+    fn next(&mut self) -> Option<Path> {
+        match self.stack.shift_opt() {
+            Some(path) => {
+                if path.is_dir() {
+                    self.stack.push_all_move(readdir(&path));
+                }
+                Some(path)
             }
+            None => None
         }
-    };
-}
-
-/// Recursively walk a directory structure. This function will call the
-/// provided closure on all directories and files found inside the path
-/// pointed to by `self`. If the closure returns `false`, then the iteration
-/// will be short-circuited.
-pub fn walk_dir(path: &Path, f: &fn(&Path) -> bool) -> bool {
-    let files = readdir(path);
-    files.iter().advance(|q| {
-        f(q) && (!q.is_dir() || walk_dir(q, |p| f(p)))
-    })
+    }
 }
 
 /// Recursively create a directory and all of its parent components if they
 /// are missing.
 ///
-/// # Failure
+/// # Errors
 ///
 /// This function will raise on the `io_error` condition if an error
 /// happens, see `file::mkdir` for more information about error conditions
@@ -396,74 +553,25 @@ pub fn mkdir_recursive(path: &Path, mode: FilePermission) {
 /// Removes a directory at this path, after removing all its contents. Use
 /// carefully!
 ///
-/// # Failure
+/// # Errors
 ///
 /// This function will raise on the `io_error` condition if an error
 /// happens. See `file::unlink` and `file::readdir` for possible error
 /// conditions.
 pub fn rmdir_recursive(path: &Path) {
-    do walk_dir(path) |inner| {
-        if inner.is_dir() {
-            rmdir_recursive(inner);
+    let children = readdir(path);
+    for child in children.iter() {
+        if child.is_dir() {
+            rmdir_recursive(child);
         } else {
-            unlink(inner);
+            File::unlink(child);
         }
-        true
-    };
+    }
     // Directory should now be empty
     rmdir(path);
 }
 
-/// Constrained version of `FileStream` that only exposes read-specific
-/// operations.
-///
-/// Can be retreived via `Path.open()` or `file::open`.
-pub struct FileReader { priv stream: FileStream }
-
-impl Reader for FileReader {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.stream.read(buf) }
-    fn eof(&mut self) -> bool { self.stream.eof() }
-}
-
-impl Seek for FileReader {
-    fn tell(&self) -> u64 { self.stream.tell() }
-    fn seek(&mut self, p: i64, s: SeekStyle) { self.stream.seek(p, s) }
-}
-
-/// Constrained version of `FileStream` that only exposes write-specific
-/// operations.
-///
-/// Can be retreived via `Path.create()` or `file::create`.
-pub struct FileWriter { priv stream: FileStream }
-
-impl Writer for FileWriter {
-    fn write(&mut self, buf: &[u8]) { self.stream.write(buf); }
-    fn flush(&mut self) { self.stream.flush(); }
-}
-
-impl Seek for FileWriter {
-    fn tell(&self) -> u64 { self.stream.tell() }
-    fn seek(&mut self, p: i64, s: SeekStyle) { self.stream.seek(p, s); }
-}
-
-/// Unconstrained file access type that exposes read and write operations
-///
-/// Can be retreived via `file::open()` and `Path.open_stream()`.
-///
-/// # Errors
-///
-/// This type will raise an io_error condition if operations are attempted against
-/// it for which its underlying file descriptor was not configured at creation
-/// time, via the `FileAccess` parameter to `file::open()`.
-///
-/// For this reason, it is best to use the access-constrained wrappers that are
-/// exposed via `Path.open()` and `Path.create()`.
-pub struct FileStream {
-    priv fd: ~RtioFileStream,
-    priv last_nread: int,
-}
-
-impl Reader for FileStream {
+impl Reader for File {
     fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
         match self.fd.read(buf) {
             Ok(read) => {
@@ -486,10 +594,10 @@ fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
     fn eof(&mut self) -> bool { self.last_nread == 0 }
 }
 
-impl Writer for FileStream {
+impl Writer for File {
     fn write(&mut self, buf: &[u8]) {
         match self.fd.write(buf) {
-            Ok(_) => (),
+            Ok(()) => (),
             Err(ioerr) => {
                 io_error::cond.raise(ioerr);
             }
@@ -497,7 +605,7 @@ fn write(&mut self, buf: &[u8]) {
     }
 }
 
-impl Seek for FileStream {
+impl Seek for File {
     fn tell(&self) -> u64 {
         let res = self.fd.tell();
         match res {
@@ -529,7 +637,7 @@ impl path::Path {
     /// Consult the `file::stat` documentation for more info.
     ///
     /// This call preserves identical runtime/error semantics with `file::stat`.
-    pub fn stat(&self) -> FileStat { stat(self) }
+    pub fn stat(&self) -> FileStat { File::stat(self) }
 
     /// Boolean value indicator whether the underlying file exists on the local
     /// filesystem. This will return true if the path points to either a
@@ -552,7 +660,7 @@ pub fn exists(&self) -> bool {
     /// Will not raise a condition
     pub fn is_file(&self) -> bool {
         match io::result(|| self.stat()) {
-            Ok(s) => s.is_file,
+            Ok(s) => s.kind == io::TypeFile,
             Err(*) => false
         }
     }
@@ -567,7 +675,7 @@ pub fn is_file(&self) -> bool {
     /// Will not raise a condition
     pub fn is_dir(&self) -> bool {
         match io::result(|| self.stat()) {
-            Ok(s) => s.is_dir,
+            Ok(s) => s.kind == io::TypeDirectory,
             Err(*) => false
         }
     }
@@ -575,19 +683,11 @@ pub fn is_dir(&self) -> bool {
 
 #[cfg(test)]
 mod test {
-    use path::{Path, GenericPath};
-    use result::{Ok, Err};
-    use option::{Some, None};
-    use iter::range;
-    use rt::test::run_in_mt_newsched_task;
-    use super::{open_stream, unlink, stat, copy, rmdir, mkdir, readdir,
-                open, create, rmdir_recursive, mkdir_recursive};
-
+    use prelude::*;
+    use rt::io::{SeekSet, SeekCur, SeekEnd, io_error, Read, Open, ReadWrite};
     use rt::io;
-    use rt::io::Reader;
-    use super::super::{SeekSet, SeekCur, SeekEnd,
-                       io_error, Read, Create, Open, ReadWrite};
-    use vec::Vector;
+    use str;
+    use super::{File, rmdir, mkdir, readdir, rmdir_recursive, mkdir_recursive};
 
     fn tmpdir() -> Path {
         use os;
@@ -599,266 +699,236 @@ fn tmpdir() -> Path {
 
     #[test]
     fn file_test_io_smoke_test() {
-        do run_in_mt_newsched_task {
-            let message = "it's alright. have a good time";
-            let filename = &Path::new("./tmp/file_rt_io_file_test.txt");
-            {
-                let mut write_stream = open_stream(filename, Create, ReadWrite);
-                write_stream.write(message.as_bytes());
-            }
-            {
-                use str;
-                let mut read_stream = open_stream(filename, Open, Read);
-                let mut read_buf = [0, .. 1028];
-                let read_str = match read_stream.read(read_buf).unwrap() {
-                    -1|0 => fail!("shouldn't happen"),
-                    n => str::from_utf8(read_buf.slice_to(n))
-                };
-                assert!(read_str == message.to_owned());
-            }
-            unlink(filename);
+        let message = "it's alright. have a good time";
+        let filename = &Path::new("./tmp/file_rt_io_file_test.txt");
+        {
+            let mut write_stream = File::open_mode(filename, Open, ReadWrite);
+            write_stream.write(message.as_bytes());
         }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            let mut read_buf = [0, .. 1028];
+            let read_str = match read_stream.read(read_buf).unwrap() {
+                -1|0 => fail!("shouldn't happen"),
+                n => str::from_utf8(read_buf.slice_to(n))
+            };
+            assert!(read_str == message.to_owned());
+        }
+        File::unlink(filename);
     }
 
     #[test]
     fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
-        do run_in_mt_newsched_task {
-            let filename = &Path::new("./tmp/file_that_does_not_exist.txt");
-            let mut called = false;
-            do io_error::cond.trap(|_| {
-                called = true;
-            }).inside {
-                let result = open_stream(filename, Open, Read);
-                assert!(result.is_none());
-            }
-            assert!(called);
+        let filename = &Path::new("./tmp/file_that_does_not_exist.txt");
+        let mut called = false;
+        do io_error::cond.trap(|_| {
+            called = true;
+        }).inside {
+            let result = File::open_mode(filename, Open, Read);
+            assert!(result.is_none());
         }
+        assert!(called);
     }
 
     #[test]
     fn file_test_iounlinking_invalid_path_should_raise_condition() {
-        do run_in_mt_newsched_task {
-            let filename = &Path::new("./tmp/file_another_file_that_does_not_exist.txt");
-            let mut called = false;
-            do io_error::cond.trap(|_| {
-                called = true;
-            }).inside {
-                unlink(filename);
-            }
-            assert!(called);
+        let filename = &Path::new("./tmp/file_another_file_that_does_not_exist.txt");
+        let mut called = false;
+        do io_error::cond.trap(|_| {
+            called = true;
+        }).inside {
+            File::unlink(filename);
         }
+        assert!(called);
     }
 
     #[test]
     fn file_test_io_non_positional_read() {
-        do run_in_mt_newsched_task {
-            use str;
-            let message = "ten-four";
-            let mut read_mem = [0, .. 8];
-            let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt");
+        let message = "ten-four";
+        let mut read_mem = [0, .. 8];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(message.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
             {
-                let mut rw_stream = open_stream(filename, Create, ReadWrite);
-                rw_stream.write(message.as_bytes());
+                let read_buf = read_mem.mut_slice(0, 4);
+                read_stream.read(read_buf);
             }
             {
-                let mut read_stream = open_stream(filename, Open, Read);
-                {
-                    let read_buf = read_mem.mut_slice(0, 4);
-                    read_stream.read(read_buf);
-                }
-                {
-                    let read_buf = read_mem.mut_slice(4, 8);
-                    read_stream.read(read_buf);
-                }
+                let read_buf = read_mem.mut_slice(4, 8);
+                read_stream.read(read_buf);
             }
-            unlink(filename);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == message.to_owned());
         }
+        File::unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == message.to_owned());
     }
 
     #[test]
     fn file_test_io_seek_and_tell_smoke_test() {
-        do run_in_mt_newsched_task {
-            use str;
-            let message = "ten-four";
-            let mut read_mem = [0, .. 4];
-            let set_cursor = 4 as u64;
-            let mut tell_pos_pre_read;
-            let mut tell_pos_post_read;
-            let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt");
-            {
-                let mut rw_stream = open_stream(filename, Create, ReadWrite);
-                rw_stream.write(message.as_bytes());
-            }
-            {
-                let mut read_stream = open_stream(filename, Open, Read);
-                read_stream.seek(set_cursor as i64, SeekSet);
-                tell_pos_pre_read = read_stream.tell();
-                read_stream.read(read_mem);
-                tell_pos_post_read = read_stream.tell();
-            }
-            unlink(filename);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == message.slice(4, 8).to_owned());
-            assert!(tell_pos_pre_read == set_cursor);
-            assert!(tell_pos_post_read == message.len() as u64);
+        let message = "ten-four";
+        let mut read_mem = [0, .. 4];
+        let set_cursor = 4 as u64;
+        let mut tell_pos_pre_read;
+        let mut tell_pos_post_read;
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(message.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            read_stream.seek(set_cursor as i64, SeekSet);
+            tell_pos_pre_read = read_stream.tell();
+            read_stream.read(read_mem);
+            tell_pos_post_read = read_stream.tell();
         }
+        File::unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == message.slice(4, 8).to_owned());
+        assert!(tell_pos_pre_read == set_cursor);
+        assert!(tell_pos_post_read == message.len() as u64);
     }
 
     #[test]
     fn file_test_io_seek_and_write() {
-        do run_in_mt_newsched_task {
-            use str;
-            let initial_msg =   "food-is-yummy";
-            let overwrite_msg =    "-the-bar!!";
-            let final_msg =     "foo-the-bar!!";
-            let seek_idx = 3;
-            let mut read_mem = [0, .. 13];
-            let filename = &Path::new("./tmp/file_rt_io_file_test_seek_and_write.txt");
-            {
-                let mut rw_stream = open_stream(filename, Create, ReadWrite);
-                rw_stream.write(initial_msg.as_bytes());
-                rw_stream.seek(seek_idx as i64, SeekSet);
-                rw_stream.write(overwrite_msg.as_bytes());
-            }
-            {
-                let mut read_stream = open_stream(filename, Open, Read);
-                read_stream.read(read_mem);
-            }
-            unlink(filename);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == final_msg.to_owned());
+        let initial_msg =   "food-is-yummy";
+        let overwrite_msg =    "-the-bar!!";
+        let final_msg =     "foo-the-bar!!";
+        let seek_idx = 3;
+        let mut read_mem = [0, .. 13];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_and_write.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(initial_msg.as_bytes());
+            rw_stream.seek(seek_idx as i64, SeekSet);
+            rw_stream.write(overwrite_msg.as_bytes());
         }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            read_stream.read(read_mem);
+        }
+        File::unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == final_msg.to_owned());
     }
 
     #[test]
     fn file_test_io_seek_shakedown() {
-        do run_in_mt_newsched_task {
-            use str;          // 01234567890123
-            let initial_msg =   "qwer-asdf-zxcv";
-            let chunk_one = "qwer";
-            let chunk_two = "asdf";
-            let chunk_three = "zxcv";
-            let mut read_mem = [0, .. 4];
-            let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt");
-            {
-                let mut rw_stream = open_stream(filename, Create, ReadWrite);
-                rw_stream.write(initial_msg.as_bytes());
-            }
-            {
-                let mut read_stream = open_stream(filename, Open, Read);
-
-                read_stream.seek(-4, SeekEnd);
-                read_stream.read(read_mem);
-                let read_str = str::from_utf8(read_mem);
-                assert!(read_str == chunk_three.to_owned());
-
-                read_stream.seek(-9, SeekCur);
-                read_stream.read(read_mem);
-                let read_str = str::from_utf8(read_mem);
-                assert!(read_str == chunk_two.to_owned());
-
-                read_stream.seek(0, SeekSet);
-                read_stream.read(read_mem);
-                let read_str = str::from_utf8(read_mem);
-                assert!(read_str == chunk_one.to_owned());
-            }
-            unlink(filename);
+        use std::str;          // 01234567890123
+        let initial_msg =   "qwer-asdf-zxcv";
+        let chunk_one = "qwer";
+        let chunk_two = "asdf";
+        let chunk_three = "zxcv";
+        let mut read_mem = [0, .. 4];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(initial_msg.as_bytes());
         }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+
+            read_stream.seek(-4, SeekEnd);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_three.to_owned());
+
+            read_stream.seek(-9, SeekCur);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_two.to_owned());
+
+            read_stream.seek(0, SeekSet);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_one.to_owned());
+        }
+        File::unlink(filename);
     }
 
     #[test]
     fn file_test_stat_is_correct_on_is_file() {
-        do run_in_mt_newsched_task {
-            let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt");
-            {
-                let mut fs = open_stream(filename, Create, ReadWrite);
-                let msg = "hw";
-                fs.write(msg.as_bytes());
-            }
-            let stat_res = stat(filename);
-            assert!(stat_res.is_file);
-            unlink(filename);
+        let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt");
+        {
+            let mut fs = File::open_mode(filename, Open, ReadWrite);
+            let msg = "hw";
+            fs.write(msg.as_bytes());
         }
+        let stat_res = File::stat(filename);
+        assert_eq!(stat_res.kind, io::TypeFile);
+        File::unlink(filename);
     }
 
     #[test]
     fn file_test_stat_is_correct_on_is_dir() {
-        do run_in_mt_newsched_task {
-            let filename = &Path::new("./tmp/file_stat_correct_on_is_dir");
-            mkdir(filename, io::UserRWX);
-            let stat_res = filename.stat();
-            assert!(stat_res.is_dir);
-            rmdir(filename);
-        }
+        let filename = &Path::new("./tmp/file_stat_correct_on_is_dir");
+        mkdir(filename, io::UserRWX);
+        let stat_res = filename.stat();
+        assert!(stat_res.kind == io::TypeDirectory);
+        rmdir(filename);
     }
 
     #[test]
     fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
-        do run_in_mt_newsched_task {
-            let dir = &Path::new("./tmp/fileinfo_false_on_dir");
-            mkdir(dir, io::UserRWX);
-            assert!(dir.is_file() == false);
-            rmdir(dir);
-        }
+        let dir = &Path::new("./tmp/fileinfo_false_on_dir");
+        mkdir(dir, io::UserRWX);
+        assert!(dir.is_file() == false);
+        rmdir(dir);
     }
 
     #[test]
     fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
-        do run_in_mt_newsched_task {
-            let file = &Path::new("./tmp/fileinfo_check_exists_b_and_a.txt");
-            create(file).write(bytes!("foo"));
-            assert!(file.exists());
-            unlink(file);
-            assert!(!file.exists());
-        }
+        let file = &Path::new("./tmp/fileinfo_check_exists_b_and_a.txt");
+        File::create(file).write(bytes!("foo"));
+        assert!(file.exists());
+        File::unlink(file);
+        assert!(!file.exists());
     }
 
     #[test]
     fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
-        do run_in_mt_newsched_task {
-            let dir = &Path::new("./tmp/before_and_after_dir");
-            assert!(!dir.exists());
-            mkdir(dir, io::UserRWX);
-            assert!(dir.exists());
-            assert!(dir.is_dir());
-            rmdir(dir);
-            assert!(!dir.exists());
-        }
+        let dir = &Path::new("./tmp/before_and_after_dir");
+        assert!(!dir.exists());
+        mkdir(dir, io::UserRWX);
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        rmdir(dir);
+        assert!(!dir.exists());
     }
 
     #[test]
     fn file_test_directoryinfo_readdir() {
-        use str;
-        do run_in_mt_newsched_task {
-            let dir = &Path::new("./tmp/di_readdir");
-            mkdir(dir, io::UserRWX);
-            let prefix = "foo";
-            for n in range(0,3) {
-                let f = dir.join(format!("{}.txt", n));
-                let mut w = create(&f);
-                let msg_str = (prefix + n.to_str().to_owned()).to_owned();
-                let msg = msg_str.as_bytes();
-                w.write(msg);
-            }
-            let files = readdir(dir);
-            let mut mem = [0u8, .. 4];
-            for f in files.iter() {
-                {
-                    let n = f.filestem_str();
-                    open(f).read(mem);
-                    let read_str = str::from_utf8(mem);
-                    let expected = match n {
-                        None|Some("") => fail!("really shouldn't happen.."),
-                        Some(n) => prefix+n
-                    };
-                    assert!(expected == read_str);
-                }
-                unlink(f);
+        use std::str;
+        let dir = &Path::new("./tmp/di_readdir");
+        mkdir(dir, io::UserRWX);
+        let prefix = "foo";
+        for n in range(0,3) {
+            let f = dir.join(format!("{}.txt", n));
+            let mut w = File::create(&f);
+            let msg_str = (prefix + n.to_str().to_owned()).to_owned();
+            let msg = msg_str.as_bytes();
+            w.write(msg);
+        }
+        let files = readdir(dir);
+        let mut mem = [0u8, .. 4];
+        for f in files.iter() {
+            {
+                let n = f.filestem_str();
+                File::open(f).read(mem);
+                let read_str = str::from_utf8(mem);
+                let expected = match n {
+                    None|Some("") => fail!("really shouldn't happen.."),
+                    Some(n) => prefix+n
+                };
+                assert!(expected == read_str);
             }
-            rmdir(dir);
+            File::unlink(f);
         }
+        rmdir(dir);
     }
 
     #[test]
@@ -880,7 +950,7 @@ fn unicode_path_is_dir() {
 
         let mut filepath = dirpath;
         filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
-        create(&filepath); // ignore return; touch only
+        File::create(&filepath); // ignore return; touch only
         assert!(!filepath.is_dir());
         assert!(filepath.exists());
 
@@ -905,7 +975,7 @@ fn unicode_path_exists() {
     fn copy_file_does_not_exist() {
         let from = Path::new("test/nonexistent-bogus-path");
         let to = Path::new("test/other-bogus-path");
-        match io::result(|| copy(&from, &to)) {
+        match io::result(|| File::copy(&from, &to)) {
             Ok(*) => fail!(),
             Err(*) => {
                 assert!(!from.exists());
@@ -920,12 +990,226 @@ fn copy_file_ok() {
         let input = tmpdir.join("in.txt");
         let out = tmpdir.join("out.txt");
 
-        create(&input).write(bytes!("hello"));
-        copy(&input, &out);
-        let contents = open(&out).read_to_end();
+        File::create(&input).write(bytes!("hello"));
+        File::copy(&input, &out);
+        let contents = File::open(&out).read_to_end();
         assert_eq!(contents.as_slice(), bytes!("hello"));
 
-        assert_eq!(input.stat().mode, out.stat().mode);
+        assert_eq!(input.stat().perm, out.stat().perm);
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_dst_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        File::create(&out);
+        match io::result(|| File::copy(&out, &tmpdir)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_dst_exists() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in");
+        let output = tmpdir.join("out");
+
+        File::create(&input).write("foo".as_bytes());
+        File::create(&output).write("bar".as_bytes());
+        File::copy(&input, &output);
+
+        assert_eq!(File::open(&output).read_to_end(),
+                   (bytes!("foo")).to_owned());
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_src_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        match io::result(|| File::copy(&tmpdir, &out)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        assert!(!out.exists());
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_preserves_perm_bits() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input);
+        File::chmod(&input, io::UserExec);
+        File::copy(&input, &out);
+        assert_eq!(out.stat().perm, io::UserExec);
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn symlinks_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input).write("foobar".as_bytes());
+        File::symlink(&input, &out);
+        assert_eq!(File::lstat(&out).kind, io::TypeSymlink);
+        assert_eq!(File::stat(&out).size, File::stat(&input).size);
+        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
+
+        // can't link to yourself
+        match io::result(|| File::symlink(&input, &input)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+        // symlinks can point to things that don't exist
+        File::symlink(&tmpdir.join("foo"), &tmpdir.join("bar"));
+
+        assert!(File::readlink(&tmpdir.join("bar")).unwrap() == tmpdir.join("bar"));
+
+        match io::result(|| File::readlink(&tmpdir)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn links_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input).write("foobar".as_bytes());
+        File::link(&input, &out);
+        assert_eq!(File::lstat(&out).kind, io::TypeFile);
+        assert_eq!(File::stat(&out).size, File::stat(&input).size);
+        assert_eq!(File::stat(&out).nlink, 2);
+        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
+
+        // can't link to yourself
+        match io::result(|| File::link(&input, &input)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+        // can't link to something that doesn't exist
+        match io::result(|| File::link(&tmpdir.join("foo"), &tmpdir.join("bar"))) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn chmod_works() {
+        let tmpdir = tmpdir();
+        let file = tmpdir.join("in.txt");
+
+        File::create(&file);
+        File::chmod(&file, io::UserRWX);
+        assert_eq!(File::stat(&file).perm, io::UserRWX);
+
+        match io::result(|| File::chmod(&tmpdir.join("foo"), io::UserRWX)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn sync_doesnt_kill_anything() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
+        file.fsync();
+        file.datasync();
+        file.write(bytes!("foo"));
+        file.fsync();
+        file.datasync();
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn truncate_works() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
+        file.write(bytes!("foo"));
+
+        // Do some simple things with truncation
+        assert_eq!(File::stat(&path).size, 3);
+        file.truncate(10);
+        assert_eq!(File::stat(&path).size, 10);
+        file.write(bytes!("bar"));
+        assert_eq!(File::stat(&path).size, 10);
+        assert_eq!(File::open(&path).read_to_end(),
+                   (bytes!("foobar", 0, 0, 0, 0)).to_owned());
+
+        // Truncate to a smaller length, don't seek, and then write something.
+        // Ensure that the intermediate zeroes are all filled in (we're seeked
+        // past the end of the file).
+        file.truncate(2);
+        assert_eq!(File::stat(&path).size, 2);
+        file.write(bytes!("wut"));
+        assert_eq!(File::stat(&path).size, 9);
+        assert_eq!(File::open(&path).read_to_end(),
+                   (bytes!("fo", 0, 0, 0, 0, "wut")).to_owned());
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn open_flavors() {
+        let tmpdir = tmpdir();
+
+        match io::result(|| File::open_mode(&tmpdir.join("a"), io::Open,
+                                            io::Read)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        File::open_mode(&tmpdir.join("b"), io::Open, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("c"), io::Open, io::ReadWrite).unwrap();
+        File::open_mode(&tmpdir.join("d"), io::Append, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("e"), io::Append, io::ReadWrite).unwrap();
+        File::open_mode(&tmpdir.join("f"), io::Truncate, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("g"), io::Truncate, io::ReadWrite).unwrap();
+
+        File::create(&tmpdir.join("h")).write("foo".as_bytes());
+        File::open_mode(&tmpdir.join("h"), io::Open, io::Read).unwrap();
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Open,
+                                        io::Read).unwrap();
+            match io::result(|| f.write("wut".as_bytes())) {
+                Ok(*) => fail!(), Err(*) => {}
+            }
+        }
+        assert_eq!(File::stat(&tmpdir.join("h")).size, 3);
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Append,
+                                        io::Write).unwrap();
+            f.write("bar".as_bytes());
+        }
+        assert_eq!(File::stat(&tmpdir.join("h")).size, 6);
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Truncate,
+                                        io::Write).unwrap();
+            f.write("bar".as_bytes());
+        }
+        assert_eq!(File::stat(&tmpdir.join("h")).size, 3);
+
         rmdir_recursive(&tmpdir);
     }
 }
index 51204ca73b94bbe45225d52f00e5f3666ac28af7..510c3470d06ae721e8f8c302b904fc4b889930da 100644 (file)
 * Trait for things that are both readers and writers, Stream?
 * How to handle newline conversion
 * String conversion
-* File vs. FileStream? File is shorter but could also be used for getting file info
-  - maybe File is for general file querying and *also* has a static `open` method
 * open vs. connect for generic stream opening
 * Do we need `close` at all? dtors might be good enough
 * How does I/O relate to the Iterator trait?
 
 use cast;
 use int;
-use libc;
 use path::Path;
 use str::{StrSlice, OwnedStr};
 use option::{Option, Some, None};
 pub use self::stdio::print;
 pub use self::stdio::println;
 
-pub use self::file::FileStream;
+pub use self::file::File;
 pub use self::timer::Timer;
 pub use self::net::ip::IpAddr;
 pub use self::net::tcp::TcpListener;
@@ -465,7 +462,7 @@ pub trait Reader {
     ///
     /// # Example
     ///
-    ///     let reader = FileStream::new()
+    ///     let reader = File::open(&Path::new("foo.txt"))
     ///     while !reader.eof() {
     ///         println(reader.read_line());
     ///     }
@@ -1104,55 +1101,103 @@ pub fn placeholder_error() -> IoError {
     }
 }
 
-/// Instructions on how to open a file and return a `FileStream`.
+/// A mode specifies how a file should be opened or created. These modes are
+/// passed to `File::open_mode` and are used to control where the file is
+/// positioned when it is initially opened.
 pub enum FileMode {
-    /// Opens an existing file. IoError if file does not exist.
+    /// Opens a file positioned at the beginning.
     Open,
-    /// Creates a file. IoError if file exists.
-    Create,
-    /// Opens an existing file or creates a new one.
-    OpenOrCreate,
-    /// Opens an existing file or creates a new one, positioned at EOF.
+    /// Opens a file positioned at EOF.
     Append,
-    /// Opens an existing file, truncating it to 0 bytes.
+    /// Opens a file, truncating it if it already exists.
     Truncate,
-    /// Opens an existing file or creates a new one, truncating it to 0 bytes.
-    CreateOrTruncate,
 }
 
-/// Access permissions with which the file should be opened.
-/// `FileStream`s opened with `Read` will raise an `io_error` condition if written to.
+/// Access permissions with which the file should be opened. `File`s
+/// opened with `Read` will raise an `io_error` condition if written to.
 pub enum FileAccess {
     Read,
     Write,
-    ReadWrite
+    ReadWrite,
+}
+
+/// Different kinds of files which can be identified by a call to stat
+#[deriving(Eq)]
+pub enum FileType {
+    TypeFile,
+    TypeDirectory,
+    TypeNamedPipe,
+    TypeBlockSpecial,
+    TypeSymlink,
+    TypeUnknown,
 }
 
 pub struct FileStat {
-    /// A `Path` object containing information about the `PathInfo`'s location
+    /// The path that this stat structure is describing
     path: Path,
-    /// `true` if the file pointed at by the `PathInfo` is a regular file
-    is_file: bool,
-    /// `true` if the file pointed at by the `PathInfo` is a directory
-    is_dir: bool,
-    /// The file pointed at by the `PathInfo`'s device
-    device: u64,
-    /// The file pointed at by the `PathInfo`'s mode
-    mode: u64,
-    /// The file pointed at by the `PathInfo`'s inode
-    inode: u64,
-    /// The file pointed at by the `PathInfo`'s size in bytes
+    /// The size of the file, in bytes
     size: u64,
-    /// The file pointed at by the `PathInfo`'s creation time
+    /// The kind of file this path points to (directory, file, pipe, etc.)
+    kind: FileType,
+    /// The file permissions currently on the file
+    perm: FilePermission,
+
+    // XXX: These time fields are pretty useless without an actual time
+    //      representation, what are the milliseconds relative to?
+
+    /// The time that the file was created at, in platform-dependent
+    /// milliseconds
     created: u64,
-    /// The file pointed at by the `PathInfo`'s last-modification time in
-    /// platform-dependent msecs
+    /// The time that this file was last modified, in platform-dependent
+    /// milliseconds
     modified: u64,
-    /// The file pointed at by the `PathInfo`'s last-accessd time (e.g. read) in
-    /// platform-dependent msecs
+    /// The time that this file was last accessed, in platform-dependent
+    /// milliseconds
     accessed: u64,
+
+    // Various filesytem info
+    device: u64,
+    inode: u64,
+    rdev: u64,
+    nlink: u64,
+    uid: u64,
+    gid: u64,
+    blksize: u64,
+    blocks: u64,
+    flags: u64,
+    gen: u64,
 }
 
-// FIXME(#10131): this needs to get designed for real
+/// A set of permissions for a file or directory is represented by a set of
+/// flags which are or'd together.
 pub type FilePermission = u32;
-pub static UserRWX: FilePermission = libc::S_IRWXU as FilePermission;
+
+// Each permission bit
+pub static UserRead: FilePermission     = 0x100;
+pub static UserWrite: FilePermission    = 0x080;
+pub static UserExecute: FilePermission  = 0x040;
+pub static GroupRead: FilePermission    = 0x020;
+pub static GroupWrite: FilePermission   = 0x010;
+pub static GroupExecute: FilePermission = 0x008;
+pub static OtherRead: FilePermission    = 0x004;
+pub static OtherWrite: FilePermission   = 0x002;
+pub static OtherExecute: FilePermission = 0x001;
+
+// Common combinations of these bits
+pub static UserRWX: FilePermission  = UserRead | UserWrite | UserExecute;
+pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
+pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
+
+/// A set of permissions for user owned files, this is equivalent to 0644 on
+/// unix-like systems.
+pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
+/// A set of permissions for user owned directories, this is equivalent to 0755
+/// on unix-like systems.
+pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
+                                     OtherRead | OtherExecute;
+/// A set of permissions for user owned executables, this is equivalent to 0755
+/// on unix-like systems.
+pub static UserExec: FilePermission = UserDir;
+
+/// A mask for all possible permission bits
+pub static AllPermissions: FilePermission = 0x1ff;
index e26cc166c8da4c6a070a5558b7ac7a6fec9f27ca..4eb473a73a6a3fbd0db98c1a96347a11ee3dacdd 100644 (file)
@@ -309,14 +309,16 @@ fn test_cfile() {
 //      get bitrotted instantaneously.
 mod old_os {
     use prelude::*;
-    use c_str::CString;
-    use libc::fclose;
     use libc::{size_t, c_void, c_int};
     use libc;
     use vec;
 
-    #[cfg(test)] use os;
+    #[cfg(not(windows))] use c_str::CString;
+    #[cfg(not(windows))] use libc::fclose;
+    #[cfg(test)] #[cfg(windows)] use os;
     #[cfg(test)] use rand;
+    #[cfg(windows)] use str;
+    #[cfg(windows)] use ptr;
 
     // On Windows, wide character version of function must be used to support
     // unicode, so functions should be split into at least two versions,
@@ -651,7 +653,7 @@ fn do_copy_file(from: &Path, to: &Path) -> bool {
                     return false;
                 }
                 // Preserve permissions
-                let from_mode = from.stat().mode;
+                let from_mode = from.stat().perm;
 
                 let ostream = do to.with_c_str |top| {
                     do "w+b".with_c_str |modebuf| {
@@ -735,8 +737,8 @@ fn test_list_dir_root() {
 
     #[test]
     fn test_path_is_dir() {
-        use rt::io::file::{open_stream, mkdir_recursive};
-        use rt::io::{OpenOrCreate, Read, UserRWX};
+        use rt::io::file::{mkdir_recursive};
+        use rt::io::{File, UserRWX};
 
         assert!((path_is_dir(&Path::new("."))));
         assert!((!path_is_dir(&Path::new("test/stdtest/fs.rs"))));
@@ -754,7 +756,7 @@ fn test_path_is_dir() {
         filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
         debug!("path_is_dir filepath: {}", filepath.display());
 
-        open_stream(&filepath, OpenOrCreate, Read); // ignore return; touch only
+        File::create(&filepath); // ignore return; touch only
         assert!((!path_is_dir(&filepath)));
 
         assert!((!path_is_dir(&Path::new(
index 234b46458b458a4d8843498deb93c09a75a03b58..5938252571f515927f18123e335806c7ad93c2c5 100644 (file)
@@ -11,7 +11,7 @@
 //! Implementations of I/O traits for the Option type
 //!
 //! I/O constructors return option types to allow errors to be handled.
-//! These implementations allow e.g. `Option<FileStream>` to be used
+//! These implementations allow e.g. `Option<File>` to be used
 //! as a `Reader` without unwrapping the option first.
 
 use option::*;
index a0db1f1df000ca6c16605c1cd3b4ee2ec27a8f1c..d24de7cbfee51086fa2585e0a8c680a1fd624878 100644 (file)
@@ -91,12 +91,17 @@ pub fn with_local_io<T>(f: &fn(&mut IoFactory) -> Option<T>) -> Option<T> {
 }
 
 pub trait IoFactory {
+    // networking
     fn tcp_connect(&mut self, addr: SocketAddr) -> Result<~RtioTcpStream, IoError>;
     fn tcp_bind(&mut self, addr: SocketAddr) -> Result<~RtioTcpListener, IoError>;
     fn udp_bind(&mut self, addr: SocketAddr) -> Result<~RtioUdpSocket, IoError>;
+    fn unix_bind(&mut self, path: &CString) ->
+        Result<~RtioUnixListener, IoError>;
+    fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError>;
     fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
                           hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError>;
-    fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
+
+    // filesystem operations
     fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior) -> ~RtioFileStream;
     fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
         -> Result<~RtioFileStream, IoError>;
@@ -110,13 +115,18 @@ fn fs_chmod(&mut self, path: &CString,
     fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError>;
     fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
         Result<~[Path], IoError>;
+    fn fs_lstat(&mut self, path: &CString) -> Result<FileStat, IoError>;
+    fn fs_chown(&mut self, path: &CString, uid: int, gid: int) ->
+        Result<(), IoError>;
+    fn fs_readlink(&mut self, path: &CString) -> Result<Path, IoError>;
+    fn fs_symlink(&mut self, src: &CString, dst: &CString) -> Result<(), IoError>;
+    fn fs_link(&mut self, src: &CString, dst: &CString) -> Result<(), IoError>;
+
+    // misc
+    fn timer_init(&mut self) -> Result<~RtioTimer, IoError>;
     fn spawn(&mut self, config: ProcessConfig)
             -> Result<(~RtioProcess, ~[Option<~RtioPipe>]), IoError>;
-
     fn pipe_open(&mut self, fd: c_int) -> Result<~RtioPipe, IoError>;
-    fn unix_bind(&mut self, path: &CString) ->
-        Result<~RtioUnixListener, IoError>;
-    fn unix_connect(&mut self, path: &CString) -> Result<~RtioPipe, IoError>;
     fn tty_open(&mut self, fd: c_int, readable: bool)
             -> Result<~RtioTTY, IoError>;
     fn signal(&mut self, signal: Signum, channel: SharedChan<Signum>)
@@ -177,6 +187,9 @@ pub trait RtioFileStream {
     fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError>;
     fn seek(&mut self, pos: i64, whence: SeekStyle) -> Result<u64, IoError>;
     fn tell(&self) -> Result<u64, IoError>;
+    fn fsync(&mut self) -> Result<(), IoError>;
+    fn datasync(&mut self) -> Result<(), IoError>;
+    fn truncate(&mut self, offset: i64) -> Result<(), IoError>;
 }
 
 pub trait RtioProcess {
index 876adf401862f7b27433b72c8393c4ea56ccd8fd..75b5ab81f9bb3324024c84cc3d9f76f8402b1357 100644 (file)
@@ -20,8 +20,7 @@
 use print::pprust;
 
 use std::rt::io;
-use std::rt::io::Reader;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::str;
 
 // These macros all relate to the file system; they either return
@@ -92,7 +91,7 @@ pub fn expand_include_str(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
     -> base::MacResult {
     let file = get_single_str_from_tts(cx, sp, tts, "include_str!");
     let file = res_rel_file(cx, sp, &Path::new(file));
-    let bytes = match io::result(|| file::open(&file).read_to_end()) {
+    let bytes = match io::result(|| File::open(&file).read_to_end()) {
         Err(e) => {
             cx.span_fatal(sp, format!("couldn't read {}: {}",
                                       file.display(), e.desc));
@@ -114,7 +113,7 @@ pub fn expand_include_bin(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
 
     let file = get_single_str_from_tts(cx, sp, tts, "include_bin!");
     let file = res_rel_file(cx, sp, &Path::new(file));
-    match io::result(|| file::open(&file).read_to_end()) {
+    match io::result(|| File::open(&file).read_to_end()) {
         Err(e) => {
             cx.span_fatal(sp, format!("couldn't read {}: {}",
                                       file.display(), e.desc));
index cd1be9a3c1615ff695fbbb8049020dfb05ab4066..fbe711b5efe9e7cd5f88bf47669cfacf85ba14f5 100644 (file)
@@ -19,9 +19,8 @@
 use parse::lexer::reader;
 use parse::parser::Parser;
 
-use std::path::Path;
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::str;
 
 pub mod lexer;
@@ -268,7 +267,7 @@ pub fn file_to_filemap(sess: @mut ParseSess, path: &Path, spanopt: Option<Span>)
             None => sess.span_diagnostic.handler().fatal(msg),
         }
     };
-    let bytes = match io::result(|| file::open(path).read_to_end()) {
+    let bytes = match io::result(|| File::open(path).read_to_end()) {
         Ok(bytes) => bytes,
         Err(e) => {
             err(format!("couldn't read {}: {}", path.display(), e.desc));
index 2b63325f931e7949eedfa944d2cf2ac6fcebd69f..a4361f14f69b257fe2dfb6cf0898a6deb65ac5c8 100644 (file)
@@ -532,6 +532,10 @@ extern "C" int
 rust_uv_get_result_from_fs_req(uv_fs_t* req) {
   return req->result;
 }
+extern "C" const char*
+rust_uv_get_path_from_fs_req(uv_fs_t* req) {
+  return req->path;
+}
 extern "C" void*
 rust_uv_get_ptr_from_fs_req(uv_fs_t* req) {
   return req->ptr;
index 531f01c199562ce6c1cdd32e17bb25136ae9c484..2c86fdfe6ad722d8c498a801d7ee9ba0b9b9f523 100644 (file)
@@ -21,7 +21,7 @@
 use std::str;
 use std::util;
 use std::vec;
-use std::rt::io::file;
+use std::rt::io::File;
 
 macro_rules! bench (
     ($argv:expr, $id:ident) => (maybe_run_test($argv, stringify!($id).to_owned(), $id))
@@ -76,7 +76,7 @@ fn read_line() {
     path.push("src/test/bench/shootout-k-nucleotide.data");
 
     for _ in range(0, 3) {
-        let mut reader = BufferedReader::new(file::open(&path).unwrap());
+        let mut reader = BufferedReader::new(File::open(&path).unwrap());
         while !reader.eof() {
             reader.read_line();
         }
index 7d3fa6104e5c38e650cd79b9afb85281af89887b..d7d7e9a58f3ca1cce2b10ef18e207a26610ca4b1 100644 (file)
@@ -19,7 +19,7 @@
 
 use std::int;
 use std::rt::io;
-use std::rt::io::file;
+use std::rt::io::File;
 use std::os;
 use std::rand::Rng;
 use std::rand;
@@ -123,7 +123,7 @@ fn main() {
     };
 
     let writer = if os::getenv("RUST_BENCH").is_some() {
-        let file = file::create(&Path::new("./shootout-fasta.data"));
+        let file = File::create(&Path::new("./shootout-fasta.data"));
         @mut file as @mut io::Writer
     } else {
         @mut io::stdout() as @mut io::Writer
index 56bcd24f1cb4e9c0505a8336a15398d2d5d063ad..7f684e41c75a9e1509e58550c40c83e4f97a5df8 100644 (file)
@@ -23,7 +23,7 @@ fn mk_file(path: &str, directory: bool) {
         if directory {
             io::file::mkdir(&Path::new(path), io::UserRWX);
         } else {
-            io::file::create(&Path::new(path));
+            io::File::create(&Path::new(path));
         }
     }
 
index 2f6de7e4472bdaf93ddd6cb566f6e5e6bc8d5245..0aa4ae40f9e5d22f56ce7e1baef88871ed09d0f6 100644 (file)
@@ -19,6 +19,7 @@
 use std::libc;
 use std::rt::io;
 use std::rt::io::file;
+use std::rt::io::File;
 
 fn rename_directory() {
     #[fixed_stack_segment];
@@ -50,7 +51,7 @@ fn rename_directory() {
 
         let new_path = tmpdir.join_many(["quux", "blat"]);
         file::mkdir_recursive(&new_path, io::UserRWX);
-        file::rename(&old_path, &new_path.join("newdir"));
+        File::rename(&old_path, &new_path.join("newdir"));
         assert!(new_path.join("newdir").is_dir());
         assert!(new_path.join_many(["newdir", "temp.txt"]).exists());
     }
index d46c8a64f5a4e3cf595423ea0d1871448aea29f7..9ce3d318064c98274be3da892ceb5af0ee821ebc 100644 (file)
 extern mod extra;
 
 use extra::tempfile;
-use std::rt::io::file;
+use std::rt::io::File;
 
 pub fn main() {
     let dir = tempfile::TempDir::new_in(&Path::new("."), "").unwrap();
     let path = dir.path().join("file");
 
     {
-        match file::create(&path) {
+        match File::create(&path) {
             None => unreachable!(),
             Some(f) => {
                 let mut f = f;