From 9c1851019f1ef9511fa8731b8f1acb0796d1e97f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 25 Oct 2013 17:04:37 -0700 Subject: [PATCH] Remove all blocking std::os blocking functions This commit moves all thread-blocking I/O functions from the std::os module. Their replacements can be found in either std::rt::io::file or in a hidden "old_os" module inside of native::file. I didn't want to outright delete these functions because they have a lot of special casing learned over time for each OS/platform, and I imagine that these will someday get integrated into a blocking implementation of IoFactory. For now, they're moved to a private module to prevent bitrot and still have tests to ensure that they work. I've also expanded the extensions to a few more methods defined on Path, most of which were previously defined in std::os but now have non-thread-blocking implementations as part of using the current IoFactory. The api of io::file is in flux, but I plan on changing it in the next commit as well. Closes #10057 --- mk/tests.mk | 6 +- src/compiletest/compiletest.rs | 3 +- src/compiletest/errors.rs | 8 +- src/compiletest/header.rs | 5 +- src/compiletest/runtest.rs | 20 +- src/libextra/glob.rs | 13 +- src/libextra/tempfile.rs | 11 +- src/libextra/terminfo/searcher.rs | 10 +- src/libextra/test.rs | 16 +- src/libextra/uuid.rs | 1 - src/libextra/workcache.rs | 36 +- src/librustc/back/link.rs | 17 +- src/librustc/driver/driver.rs | 3 +- src/librustc/metadata/filesearch.rs | 36 +- src/librustdoc/html/render.rs | 67 +- src/librustdoc/lib.rs | 7 +- src/librustpkg/api.rs | 6 +- src/librustpkg/context.rs | 3 +- src/librustpkg/installed_packages.rs | 8 +- src/librustpkg/lib.rs | 31 +- src/librustpkg/package_id.rs | 1 - src/librustpkg/package_source.rs | 17 +- src/librustpkg/path_util.rs | 52 +- src/librustpkg/source_control.rs | 15 +- src/librustpkg/tests.rs | 231 +++-- .../testsuite/pass/src/c-dependencies/pkg.rs | 2 +- .../testsuite/pass/src/fancy-lib/pkg.rs | 8 +- src/librustpkg/util.rs | 27 +- src/librustpkg/version.rs | 4 +- src/librustpkg/workcache_support.rs | 26 +- src/librustpkg/workspace.rs | 2 +- src/librustuv/file.rs | 20 +- src/librustuv/uvio.rs | 17 +- src/librustuv/uvll.rs | 12 +- src/libstd/bool.rs | 7 +- src/libstd/os.rs | 549 +----------- src/libstd/path/posix.rs | 69 -- src/libstd/rand/os.rs | 8 +- src/libstd/rt/io/file.rs | 795 +++++++++--------- src/libstd/rt/io/mod.rs | 21 +- src/libstd/rt/io/native/file.rs | 483 +++++++++++ src/libstd/rt/io/net/unix.rs | 3 +- src/libstd/rt/io/signal.rs | 7 +- src/libstd/rt/io/timer.rs | 1 + src/libstd/rt/rtio.rs | 7 +- src/libstd/run.rs | 8 +- src/libsyntax/ext/source_util.rs | 25 +- src/libsyntax/parse/mod.rs | 16 +- src/rt/rust_uv.cpp | 4 + src/test/bench/core-std.rs | 5 +- src/test/bench/shootout-fasta.rs | 4 +- src/test/run-pass-fulldeps/qquote.rs | 1 + src/test/run-pass-fulldeps/quote-tokens.rs | 12 +- src/test/run-pass/glob-std.rs | 5 +- src/test/run-pass/rename-directory.rs | 12 +- src/test/run-pass/stat.rs | 9 +- src/test/run-pass/tempfile.rs | 65 +- 57 files changed, 1364 insertions(+), 1493 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index eabb5f535e6..a24791d76af 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -517,8 +517,8 @@ CTEST_BUILD_BASE_rpass = run-pass CTEST_MODE_rpass = run-pass CTEST_RUNTOOL_rpass = $(CTEST_RUNTOOL) -CTEST_SRC_BASE_rpass-full = run-pass-full -CTEST_BUILD_BASE_rpass-full = run-pass-full +CTEST_SRC_BASE_rpass-full = run-pass-fulldeps +CTEST_BUILD_BASE_rpass-full = run-pass-fulldeps CTEST_MODE_rpass-full = run-pass CTEST_RUNTOOL_rpass-full = $(CTEST_RUNTOOL) @@ -673,7 +673,7 @@ PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS) PRETTY_DEPS_pretty-bench = $(BENCH_TESTS) PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS) PRETTY_DIRNAME_pretty-rpass = run-pass -PRETTY_DIRNAME_pretty-rpass-full = run-pass-full +PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps PRETTY_DIRNAME_pretty-rfail = run-fail PRETTY_DIRNAME_pretty-bench = bench PRETTY_DIRNAME_pretty-pretty = pretty diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 7f5a72e8a2c..a354bc84e52 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -17,6 +17,7 @@ extern mod extra; use std::os; use std::rt; +use std::rt::io::file; use extra::getopts; use extra::getopts::groups::{optopt, optflag, reqopt}; @@ -247,7 +248,7 @@ pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] { debug!("making tests from {}", config.src_base.display()); let mut tests = ~[]; - let dirs = os::list_dir_path(&config.src_base); + let dirs = file::readdir(&config.src_base); for file in dirs.iter() { let file = file.clone(); debug!("inspecting file {}", file.display()); diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 0c94ec8ab8a..dfadea37cd0 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -8,16 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::rt::io::buffered::BufferedReader; +use std::rt::io::file; + pub struct ExpectedError { line: uint, kind: ~str, msg: ~str } // Load any test directives embedded in the file pub fn load_errors(testfile: &Path) -> ~[ExpectedError] { - use std::rt::io::Open; - use std::rt::io::file::FileInfo; - use std::rt::io::buffered::BufferedReader; let mut error_patterns = ~[]; - let mut rdr = BufferedReader::new(testfile.open_reader(Open).unwrap()); + let mut rdr = BufferedReader::new(file::open(testfile).unwrap()); let mut line_num = 1u; loop { let ln = match rdr.read_line() { diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 368c96ffe85..68e8fd76735 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -103,11 +103,10 @@ pub fn is_test_ignored(config: &config, testfile: &Path) -> bool { } fn iter_header(testfile: &Path, it: &fn(&str) -> bool) -> bool { - use std::rt::io::Open; - use std::rt::io::file::FileInfo; use std::rt::io::buffered::BufferedReader; + use std::rt::io::file; - let mut rdr = BufferedReader::new(testfile.open_reader(Open).unwrap()); + let mut rdr = BufferedReader::new(file::open(testfile).unwrap()); loop { let ln = match rdr.read_line() { Some(ln) => ln, None => break diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 13c4c7948b8..7fc13467217 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -22,9 +22,7 @@ use util::logv; use std::cell::Cell; use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::Reader; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use std::os; use std::str; use std::task::{spawn_sched, SingleThreaded}; @@ -173,7 +171,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) { let rounds = match props.pp_exact { Some(_) => 1, None => 2 }; - let src = testfile.open_reader(io::Open).read_to_end(); + let src = file::open(testfile).read_to_end(); let src = str::from_utf8_owned(src); let mut srcs = ~[src]; @@ -195,7 +193,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 = filepath.open_reader(io::Open).read_to_end(); + let s = file::open(&filepath).read_to_end(); str::from_utf8_owned(s) } None => { srcs[srcs.len() - 2u].clone() } @@ -651,10 +649,8 @@ fn compose_and_run_compiler( } fn ensure_dir(path: &Path) { - if os::path_is_dir(path) { return; } - if !os::make_dir(path, 0x1c0i32) { - fail!("can't make dir {}", path.display()); - } + if path.is_dir() { return; } + file::mkdir(path, io::UserRWX); } fn compose_and_run(config: &config, testfile: &Path, @@ -768,7 +764,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); - outfile.open_writer(io::CreateOrTruncate).write(out.as_bytes()); + file::create(&outfile).write(out.as_bytes()); } fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path { @@ -924,7 +920,7 @@ fn _dummy_exec_compiled_test(config: &config, props: &TestProps, fn _arm_push_aux_shared_library(config: &config, testfile: &Path) { let tdir = aux_output_dir_name(config, testfile); - let dirs = os::list_dir_path(&tdir); + let dirs = file::readdir(&tdir); for file in dirs.iter() { if file.extension_str() == Some("so") { // FIXME (#9639): This needs to handle non-utf8 paths @@ -1019,7 +1015,7 @@ fn disassemble_extract(config: &config, _props: &TestProps, fn count_extracted_lines(p: &Path) -> uint { - let x = p.with_extension("ll").open_reader(io::Open).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() } diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs index 5297b48b0e1..a7742f771da 100644 --- a/src/libextra/glob.rs +++ b/src/libextra/glob.rs @@ -24,6 +24,8 @@ */ use std::{os, path}; +use std::rt::io; +use std::rt::io::file; use std::path::is_sep; use sort; @@ -146,9 +148,14 @@ impl Iterator for GlobIterator { } fn list_dir_sorted(path: &Path) -> ~[Path] { - let mut children = os::list_dir_path(path); - sort::quick_sort(children, |p1, p2| p2.filename().unwrap() <= p1.filename().unwrap()); - children + match io::result(|| file::readdir(path)) { + Ok(children) => { + let mut children = children; + sort::quick_sort(children, |p1, p2| p2.filename() <= p1.filename()); + children + } + Err(*) => ~[] + } } /** diff --git a/src/libextra/tempfile.rs b/src/libextra/tempfile.rs index d8fa130916a..4affe7c1cde 100644 --- a/src/libextra/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -14,6 +14,8 @@ use std::os; use std::rand::Rng; use std::rand; +use std::rt::io; +use std::rt::io::file; /// A wrapper for a path to temporary directory implementing automatic /// scope-pased deletion. @@ -36,8 +38,9 @@ impl TempDir { let mut r = rand::rng(); for _ in range(0u, 1000) { let p = tmpdir.join(r.gen_ascii_str(16) + suffix); - if os::make_dir(&p, 0x1c0) { // 700 - return Some(TempDir { path: Some(p) }); + match io::result(|| file::mkdir(&p, io::UserRWX)) { + Err(*) => {} + Ok(()) => return Some(TempDir { path: Some(p) }) } } None @@ -69,7 +72,9 @@ impl TempDir { impl Drop for TempDir { fn drop(&mut self) { for path in self.path.iter() { - os::remove_dir_recursive(path); + if path.exists() { + file::rmdir_recursive(path); + } } } } diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs index 8dff53f14a1..c5509f8aec7 100644 --- a/src/libextra/terminfo/searcher.rs +++ b/src/libextra/terminfo/searcher.rs @@ -14,7 +14,7 @@ use std::{os, str}; use std::os::getenv; use std::rt::io; -use std::rt::io::file::FileInfo; +use std::rt::io::file; /// Return path to database entry for `term` pub fn get_dbpath_for_term(term: &str) -> Option<~Path> { @@ -56,16 +56,16 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~Path> { // Look for the terminal in all of the search directories for p in dirs_to_search.iter() { - if os::path_exists(p) { + if p.exists() { let f = str::from_char(first_char); let newp = p.join_many([f.as_slice(), term]); - if os::path_exists(&newp) { + if newp.exists() { return Some(~newp); } // on some installations the dir is named after the hex of the char (e.g. OS X) let f = format!("{:x}", first_char as uint); let newp = p.join_many([f.as_slice(), term]); - if os::path_exists(&newp) { + if newp.exists() { return Some(~newp); } } @@ -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 x.open_reader(io::Open).unwrap() 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)) } } diff --git a/src/libextra/test.rs b/src/libextra/test.rs index f262e6c60fb..497d4206fe3 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -31,7 +31,7 @@ use treemap::TreeMap; use std::clone::Clone; use std::comm::{stream, SharedChan, GenericPort, GenericChan}; use std::rt::io; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use std::task; use std::to_str::ToStr; use std::f64; @@ -353,10 +353,7 @@ struct ConsoleTestState { impl ConsoleTestState { pub fn new(opts: &TestOpts) -> ConsoleTestState { let log_out = match opts.logfile { - Some(ref path) => { - let out = path.open_writer(io::CreateOrTruncate); - Some(@mut out 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; @@ -938,16 +935,15 @@ impl MetricMap { /// Load MetricDiff from a file. pub fn load(p: &Path) -> MetricMap { - assert!(os::path_exists(p)); - let f = @mut p.open_reader(io::Open) as @mut io::Reader; + assert!(p.exists()); + 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) { - let f = @mut p.open_writer(io::CreateOrTruncate); - self.to_json().to_pretty_writer(f 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 @@ -1032,7 +1028,7 @@ impl MetricMap { /// `MetricChange`s are `Regression`. Returns the diff as well /// as a boolean indicating whether the ratchet succeeded. pub fn ratchet(&self, p: &Path, pct: Option) -> (MetricDiff, bool) { - let old = if os::path_exists(p) { + let old = if p.exists() { MetricMap::load(p) } else { MetricMap::new() diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs index b94b74a696c..54ce349a0b4 100644 --- a/src/libextra/uuid.rs +++ b/src/libextra/uuid.rs @@ -792,7 +792,6 @@ mod test { #[test] fn test_serialize_round_trip() { - use std; use ebml; use serialize::{Encodable, Decodable}; diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs index 507962c0b1a..b2be4cf811b 100644 --- a/src/libextra/workcache.rs +++ b/src/libextra/workcache.rs @@ -17,13 +17,11 @@ use arc::{Arc,RWArc}; use treemap::TreeMap; use std::cell::Cell; use std::comm::{PortOne, oneshot}; -use std::{os, str, task}; +use std::{str, task}; use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::Reader; +use std::rt::io::file; use std::rt::io::Decorator; use std::rt::io::mem::MemWriter; -use std::rt::io::file::FileInfo; /** * @@ -145,7 +143,7 @@ impl Database { db_cache: TreeMap::new(), db_dirty: false }; - if os::path_exists(&rslt.db_filename) { + if rslt.db_filename.exists() { rslt.load(); } rslt @@ -178,19 +176,19 @@ impl Database { // FIXME #4330: This should have &mut self and should set self.db_dirty to false. fn save(&self) { - let f = @mut self.db_filename.open_writer(io::CreateOrTruncate); + 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!(os::path_exists(&self.db_filename)); - let f = self.db_filename.open_reader(io::Open); - match f { - None => fail!("Couldn't load workcache database {}", - self.db_filename.display()), - Some(r) => - match json::from_reader(@mut r as @mut io::Reader) { + assert!(self.db_filename.exists()); + match io::result(|| file::open(&self.db_filename)) { + Err(e) => fail!("Couldn't load workcache database {}: {}", + self.db_filename.display(), + e.desc), + Ok(r) => + match json::from_reader(@mut r.unwrap() as @mut io::Reader) { Err(e) => fail!("Couldn't parse workcache database (from file {}): {}", self.db_filename.display(), e.to_str()), Ok(r) => { @@ -482,23 +480,21 @@ impl<'self, T:Send + #[test] fn test() { use std::{os, run}; - use std::rt::io::Reader; + use std::rt::io::file; use std::str::from_utf8_owned; // Create a path to a new file 'filename' in the directory in which // this test is running. fn make_path(filename: ~str) -> Path { let pth = os::self_exe_path().expect("workcache::test failed").with_filename(filename); - if os::path_exists(&pth) { - os::remove_file(&pth); + if pth.exists() { + file::unlink(&pth); } return pth; } let pth = make_path(~"foo.c"); - { - pth.open_writer(io::Create).write(bytes!("int main() { return 0; }")); - } + file::create(&pth).write(bytes!("int main() { return 0; }")); let db_path = make_path(~"db.json"); @@ -511,7 +507,7 @@ fn test() { let subcx = cx.clone(); let pth = pth.clone(); - let file_content = from_utf8_owned(pth.open_reader(io::Open).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); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 815ec943c49..7d044ba998f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -27,12 +27,11 @@ use std::char; use std::hash::Streaming; use std::hash; use std::os::consts::{macos, freebsd, linux, android, win32}; -use std::os; use std::ptr; -use std::rt::io::Writer; use std::run; use std::str; use std::vec; +use std::rt::io::file; use syntax::ast; use syntax::ast_map::{path, path_mod, path_name, path_pretty_name}; use syntax::attr; @@ -951,20 +950,18 @@ pub fn link_binary(sess: Session, // Remove the temporary object file if we aren't saving temps if !sess.opts.save_temps { - if ! os::remove_file(obj_filename) { - sess.warn(format!("failed to delete object file `{}`", - obj_filename.display())); - } + file::unlink(obj_filename); } } fn is_writeable(p: &Path) -> bool { + use std::rt::io; use std::libc::consts::os::posix88::S_IWUSR; - !os::path_exists(p) || - (match p.get_mode() { - None => false, - Some(m) => m & S_IWUSR as uint == S_IWUSR as uint + !p.exists() || + (match io::result(|| p.stat()) { + Err(*) => false, + Ok(m) => (m.mode as uint) & S_IWUSR as uint == S_IWUSR as uint }) } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index fb593b56e15..1526b5ad9c6 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -27,6 +27,7 @@ use util::ppaux; use std::hashmap::{HashMap,HashSet}; use std::rt::io; +use std::rt::io::file; use std::rt::io::mem::MemReader; use std::os; use std::vec; @@ -369,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 { - os::remove_file(&asm_filename); + file::unlink(&asm_filename); } } else { time(sess.time_passes(), "LLVM passes", (), |_| diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 94dfc006076..44e43bd4ef3 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -11,6 +11,8 @@ use std::option; use std::os; +use std::rt::io; +use std::rt::io::file; use std::hashmap::HashSet; pub enum FileMatch { FileMatches, FileDoesntMatch } @@ -117,22 +119,26 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>, pub fn search(filesearch: @FileSearch, pick: pick) { do filesearch.for_each_lib_search_path() |lib_search_path| { debug!("searching {}", lib_search_path.display()); - let r = os::list_dir_path(lib_search_path); - let mut rslt = FileDoesntMatch; - for path in r.iter() { - debug!("testing {}", path.display()); - let maybe_picked = pick(path); - match maybe_picked { - FileMatches => { - debug!("picked {}", path.display()); - rslt = FileMatches; - } - FileDoesntMatch => { - debug!("rejected {}", path.display()); + match io::result(|| file::readdir(lib_search_path)) { + Ok(files) => { + let mut rslt = FileDoesntMatch; + for path in files.iter() { + debug!("testing {}", path.display()); + let maybe_picked = pick(path); + match maybe_picked { + FileMatches => { + debug!("picked {}", path.display()); + rslt = FileMatches; + } + FileDoesntMatch => { + debug!("rejected {}", path.display()); + } + } } + rslt } + Err(*) => FileDoesntMatch, } - rslt }; } @@ -210,7 +216,7 @@ pub fn rust_path() -> ~[Path] { break } cwd.set_filename(".rust"); - if !env_rust_path.contains(&cwd) && os::path_exists(&cwd) { + if !env_rust_path.contains(&cwd) && cwd.exists() { env_rust_path.push(cwd.clone()); } cwd.pop(); @@ -218,7 +224,7 @@ pub fn rust_path() -> ~[Path] { let h = os::homedir(); for h in h.iter() { let p = h.join(".rust"); - if !env_rust_path.contains(&p) && os::path_exists(&p) { + if !env_rust_path.contains(&p) && p.exists() { env_rust_path.push(p); } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 7bfe0910252..fd7ba7c0452 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -40,10 +40,8 @@ use std::fmt; use std::hashmap::{HashMap, HashSet}; use std::local_data; use std::rt::io::buffered::BufferedWriter; -use std::rt::io::file::{FileInfo, DirectoryInfo}; -use std::rt::io::file; use std::rt::io; -use std::rt::io::Reader; +use std::rt::io::file; use std::os; use std::str; use std::task; @@ -265,8 +263,8 @@ pub fn run(mut crate: clean::Crate, dst: Path) { // Publish the search index { dst.push("search-index.js"); - let mut w = BufferedWriter::new(dst.open_writer(io::CreateOrTruncate)); - let w = &mut w as &mut io::Writer; + 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() { if i > 0 { write!(w, ","); } @@ -315,8 +313,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) { - let mut w = dst.open_writer(io::CreateOrTruncate); - w.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 @@ -328,7 +325,7 @@ fn mkdir(path: &Path) { fail!() }).inside { if !path.is_dir() { - file::mkdir(path); + file::mkdir(path, io::UserRWX); } } } @@ -419,16 +416,13 @@ impl<'self> SourceCollector<'self> { let mut contents = ~[]; { let mut buf = [0, ..1024]; - let r = do io::io_error::cond.trap(|_| {}).inside { - p.open_reader(io::Open) - }; // 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 r { - Some(r) => r, + let mut r = match io::result(|| file::open(&p)) { + Ok(r) => r, // eew macro hacks - None => return filename == "" + Err(*) => return filename == "" }; // read everything @@ -451,8 +445,7 @@ impl<'self> SourceCollector<'self> { } cur.push(p.filename().expect("source has no filename") + bytes!(".html")); - let w = cur.open_writer(io::CreateOrTruncate); - let mut w = BufferedWriter::new(w); + let mut w = BufferedWriter::new(file::create(&cur).unwrap()); let title = cur.filename_display().with_str(|s| format!("{} -- source", s)); let page = layout::Page { @@ -460,7 +453,7 @@ impl<'self> SourceCollector<'self> { ty: "source", root_path: root_path, }; - layout::render(&mut w as &mut io::Writer, &self.cx.layout, + layout::render(&mut w as &mut Writer, &self.cx.layout, &page, &(""), &Source(contents.as_slice())); w.flush(); return true; @@ -774,7 +767,7 @@ impl Context { /// /// 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: io::file::FileWriter, cx: &mut Context, it: &clean::Item, + fn render(w: file::FileWriter, 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. @@ -796,7 +789,7 @@ impl Context { // of the pain by using a buffered writer instead of invoking the // write sycall all the time. let mut writer = BufferedWriter::new(w); - layout::render(&mut writer as &mut io::Writer, &cx.layout, &page, + layout::render(&mut writer as &mut Writer, &cx.layout, &page, &Sidebar{ cx: cx, item: it }, &Item{ cx: cx, item: it }); writer.flush(); @@ -811,8 +804,7 @@ impl Context { do self.recurse(name) |this| { let item = item.take(); let dst = this.dst.join("index.html"); - let writer = dst.open_writer(io::CreateOrTruncate); - render(writer.unwrap(), this, &item, false); + render(file::create(&dst).unwrap(), this, &item, false); let m = match item.inner { clean::ModuleItem(m) => m, @@ -829,8 +821,7 @@ impl Context { // pages dedicated to them. _ if item.name.is_some() => { let dst = self.dst.join(item_path(&item)); - let writer = dst.open_writer(io::CreateOrTruncate); - render(writer.unwrap(), self, &item, true); + render(file::create(&dst).unwrap(), self, &item, true); } _ => {} @@ -967,7 +958,7 @@ fn shorter<'a>(s: Option<&'a str>) -> &'a str { } } -fn document(w: &mut io::Writer, item: &clean::Item) { +fn document(w: &mut Writer, item: &clean::Item) { match item.doc_value() { Some(s) => { write!(w, "
{}
", Markdown(s)); @@ -976,7 +967,7 @@ fn document(w: &mut io::Writer, item: &clean::Item) { } } -fn item_module(w: &mut io::Writer, cx: &Context, +fn item_module(w: &mut Writer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { document(w, item); debug!("{:?}", items); @@ -1123,7 +1114,7 @@ fn item_module(w: &mut io::Writer, cx: &Context, write!(w, ""); } -fn item_function(w: &mut io::Writer, it: &clean::Item, f: &clean::Function) { +fn item_function(w: &mut Writer, it: &clean::Item, f: &clean::Function) { write!(w, "
{vis}{purity}fn {name}{generics}{decl}
", vis = VisSpace(it.visibility), purity = PuritySpace(f.purity), @@ -1133,7 +1124,7 @@ fn item_function(w: &mut io::Writer, it: &clean::Item, f: &clean::Function) { document(w, it); } -fn item_trait(w: &mut io::Writer, it: &clean::Item, t: &clean::Trait) { +fn item_trait(w: &mut Writer, it: &clean::Item, t: &clean::Trait) { let mut parents = ~""; if t.parents.len() > 0 { parents.push_str(": "); @@ -1176,7 +1167,7 @@ fn item_trait(w: &mut io::Writer, it: &clean::Item, t: &clean::Trait) { // Trait documentation document(w, it); - fn meth(w: &mut io::Writer, m: &clean::TraitMethod) { + fn meth(w: &mut Writer, m: &clean::TraitMethod) { write!(w, "

", shortty(m.item()), *m.item().name.get_ref()); @@ -1234,8 +1225,8 @@ fn item_trait(w: &mut io::Writer, it: &clean::Item, t: &clean::Trait) { } } -fn render_method(w: &mut io::Writer, meth: &clean::Item, withlink: bool) { - fn fun(w: &mut io::Writer, it: &clean::Item, purity: ast::purity, +fn render_method(w: &mut Writer, meth: &clean::Item, withlink: bool) { + fn fun(w: &mut Writer, it: &clean::Item, purity: ast::purity, g: &clean::Generics, selfty: &clean::SelfTy, d: &clean::FnDecl, withlink: bool) { write!(w, "{}fn {withlink, select, @@ -1264,7 +1255,7 @@ fn render_method(w: &mut io::Writer, meth: &clean::Item, withlink: bool) { } } -fn item_struct(w: &mut io::Writer, it: &clean::Item, s: &clean::Struct) { +fn item_struct(w: &mut Writer, it: &clean::Item, s: &clean::Struct) { write!(w, "
");
     render_struct(w, it, Some(&s.generics), s.struct_type, s.fields,
                   s.fields_stripped, "", true);
@@ -1288,7 +1279,7 @@ fn item_struct(w: &mut io::Writer, it: &clean::Item, s: &clean::Struct) {
     render_methods(w, it);
 }
 
-fn item_enum(w: &mut io::Writer, it: &clean::Item, e: &clean::Enum) {
+fn item_enum(w: &mut Writer, it: &clean::Item, e: &clean::Enum) {
     write!(w, "
{}enum {}{}",
            VisSpace(it.visibility),
            it.name.get_ref().as_slice(),
@@ -1365,7 +1356,7 @@ fn item_enum(w: &mut io::Writer, it: &clean::Item, e: &clean::Enum) {
     render_methods(w, it);
 }
 
-fn render_struct(w: &mut io::Writer, it: &clean::Item,
+fn render_struct(w: &mut Writer, it: &clean::Item,
                  g: Option<&clean::Generics>,
                  ty: doctree::StructType,
                  fields: &[clean::Item],
@@ -1418,7 +1409,7 @@ fn render_struct(w: &mut io::Writer, it: &clean::Item,
     }
 }
 
-fn render_methods(w: &mut io::Writer, it: &clean::Item) {
+fn render_methods(w: &mut Writer, it: &clean::Item) {
     do local_data::get(cache_key) |cache| {
         let cache = cache.unwrap();
         do cache.read |c| {
@@ -1453,7 +1444,7 @@ fn render_methods(w: &mut io::Writer, it: &clean::Item) {
     }
 }
 
-fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) {
+fn render_impl(w: &mut Writer, i: &clean::Impl, dox: &Option<~str>) {
     write!(w, "

impl{} ", i.generics); let trait_id = match i.trait_ { Some(ref ty) => { @@ -1474,7 +1465,7 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) { None => {} } - fn docmeth(w: &mut io::Writer, item: &clean::Item) -> bool { + fn docmeth(w: &mut Writer, item: &clean::Item) -> bool { write!(w, "

", *item.name.get_ref()); render_method(w, item, false); @@ -1552,7 +1543,7 @@ fn render_impl(w: &mut io::Writer, i: &clean::Impl, dox: &Option<~str>) { write!(w, ""); } -fn item_typedef(w: &mut io::Writer, it: &clean::Item, t: &clean::Typedef) { +fn item_typedef(w: &mut Writer, it: &clean::Item, t: &clean::Typedef) { write!(w, "
type {}{} = {};
", it.name.get_ref().as_slice(), t.generics, @@ -1574,7 +1565,7 @@ impl<'self> fmt::Default for Sidebar<'self> { } write!(fmt.buf, "

"); - fn block(w: &mut io::Writer, short: &str, longty: &str, + fn block(w: &mut Writer, short: &str, longty: &str, cur: &clean::Item, cx: &Context) { let items = match cx.sidebar.find_equiv(&short) { Some(items) => items.as_slice(), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 770d535c6ea..7a64ca6d6fc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -25,9 +25,8 @@ extern mod extra; use std::cell::Cell; use std::local_data; -use std::rt::io::Writer; -use std::rt::io::file::FileInfo; use std::rt::io; +use std::rt::io::file; use std::rt::io::mem::MemWriter; use std::rt::io::Decorator; use std::str; @@ -260,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 { - let input = match Path::new(input).open_reader(io::Open) { + let input = match file::open(&Path::new(input)) { Some(f) => f, None => return Err(format!("couldn't open {} for reading", input)), }; @@ -322,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 = dst.open_writer(io::Create).unwrap(); + let mut file = file::create(&dst).unwrap(); let output = json::Object(json).to_str(); file.write(output.as_bytes()); } diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index c67b6f52c7e..c0ffd66d22e 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -21,7 +21,7 @@ pub use path_util::default_workspace; pub use source_control::{safe_git_clone, git_clone_url}; -use std::{os, run}; +use std::run; use extra::arc::{Arc,RWArc}; use extra::workcache; use extra::workcache::{Database, Logger, FreshnessMap}; @@ -57,12 +57,12 @@ pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext { fn file_is_fresh(path: &str, in_hash: &str) -> bool { let path = Path::new(path); - os::path_exists(&path) && in_hash == digest_file_with_date(&path) + path.exists() && in_hash == digest_file_with_date(&path) } fn binary_is_fresh(path: &str, in_hash: &str) -> bool { let path = Path::new(path); - os::path_exists(&path) && in_hash == digest_only_date(&path) + path.exists() && in_hash == digest_only_date(&path) } pub fn new_workcache_context(p: &Path) -> workcache::Context { diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index 77fe2ae8f70..0ae08731546 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -14,7 +14,6 @@ use extra::workcache; use rustc::driver::session::{OptLevel, No}; use std::hashmap::HashSet; -use std::os; #[deriving(Clone)] pub struct Context { @@ -176,7 +175,7 @@ pub fn in_target(sysroot: &Path) -> bool { debug!("Checking whether {} is in target", sysroot.display()); let mut p = sysroot.dir_path(); p.set_filename("rustc"); - os::path_is_dir(&p) + p.is_dir() } impl RustcFlags { diff --git a/src/librustpkg/installed_packages.rs b/src/librustpkg/installed_packages.rs index 767a31ed785..09b58e6e94c 100644 --- a/src/librustpkg/installed_packages.rs +++ b/src/librustpkg/installed_packages.rs @@ -13,11 +13,13 @@ use rustc::metadata::filesearch::rust_path; use path_util::*; use std::os; +use std::rt::io; +use std::rt::io::file; pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool { let workspaces = rust_path(); for p in workspaces.iter() { - let binfiles = os::list_dir(&p.join("bin")); + let binfiles = do io::ignore_io_error { file::readdir(&p.join("bin")) }; for exec in binfiles.iter() { // FIXME (#9639): This needs to handle non-utf8 paths match exec.filestem_str() { @@ -29,7 +31,7 @@ pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool { } } } - let libfiles = os::list_dir(&p.join("lib")); + let libfiles = do io::ignore_io_error { file::readdir(&p.join("lib")) }; for lib in libfiles.iter() { debug!("Full name: {}", lib.display()); match has_library(lib) { @@ -53,7 +55,7 @@ pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool { } pub fn has_library(p: &Path) -> Option<~str> { - let files = os::list_dir(p); + let files = do io::ignore_io_error { file::readdir(p) }; for path in files.iter() { if path.extension_str() == Some(os::consts::DLL_EXTENSION) { let stuff : &str = path.filestem_str().expect("has_library: weird path"); diff --git a/src/librustpkg/lib.rs b/src/librustpkg/lib.rs index 517d43432ec..bb6088adee1 100644 --- a/src/librustpkg/lib.rs +++ b/src/librustpkg/lib.rs @@ -26,6 +26,8 @@ extern mod syntax; use std::{os, result, run, str, task}; use std::hashmap::HashSet; +use std::rt::io; +use std::rt::io::file; pub use std::path::Path; use extra::workcache; @@ -36,7 +38,7 @@ use extra::{getopts}; use syntax::{ast, diagnostic}; use messages::{error, warn, note}; use path_util::{build_pkg_id_in_workspace, built_test_in_workspace}; -use path_util::{U_RWX, in_rust_path}; +use path_util::in_rust_path; use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace}; use path_util::{target_executable_in_workspace, target_library_in_workspace, dir_has_crate_file}; use source_control::{CheckedOutSources, is_git_dir, make_read_only}; @@ -513,7 +515,7 @@ impl CtxMethods for BuildContext { // We expect that p is relative to the package source's start directory, // so check that assumption debug!("JustOne: p = {}", p.display()); - assert!(os::path_exists(&pkg_src.start_dir.join(p))); + assert!(pkg_src.start_dir.join(p).exists()); if is_lib(p) { PkgSrc::push_crate(&mut pkg_src.libs, 0, p); } else if is_main(p) { @@ -541,8 +543,8 @@ impl CtxMethods for BuildContext { let dir = build_pkg_id_in_workspace(id, workspace); note(format!("Cleaning package {} (removing directory {})", id.to_str(), dir.display())); - if os::path_exists(&dir) { - os::remove_dir_recursive(&dir); + if dir.exists() { + file::rmdir_recursive(&dir); note(format!("Removed directory {}", dir.display())); } @@ -600,7 +602,6 @@ impl CtxMethods for BuildContext { build_inputs: &[Path], target_workspace: &Path, id: &PkgId) -> ~[~str] { - use conditions::copy_failed::cond; debug!("install_no_build: assuming {} comes from {} with target {}", id.to_str(), build_workspace.display(), target_workspace.display()); @@ -659,10 +660,8 @@ impl CtxMethods for BuildContext { for exec in subex.iter() { debug!("Copying: {} -> {}", exec.display(), sub_target_ex.display()); - if !(os::mkdir_recursive(&sub_target_ex.dir_path(), U_RWX) && - os::copy_file(exec, &sub_target_ex)) { - cond.raise(((*exec).clone(), sub_target_ex.clone())); - } + file::mkdir_recursive(&sub_target_ex.dir_path(), io::UserRWX); + 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,10 +673,8 @@ impl CtxMethods for BuildContext { .clone().expect(format!("I built {} but apparently \ didn't install it!", lib.display())); target_lib.set_filename(lib.filename().expect("weird target lib")); - if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) && - os::copy_file(lib, &target_lib)) { - cond.raise(((*lib).clone(), target_lib.clone())); - } + file::mkdir_recursive(&target_lib.dir_path(), io::UserRWX); + file::copy(lib, &target_lib); debug!("3. discovering output {}", target_lib.display()); exe_thing.discover_output("binary", target_lib.as_str().unwrap(), @@ -710,10 +707,10 @@ impl CtxMethods for BuildContext { } fn init(&self) { - os::mkdir_recursive(&Path::new("src"), U_RWX); - os::mkdir_recursive(&Path::new("lib"), U_RWX); - os::mkdir_recursive(&Path::new("bin"), U_RWX); - os::mkdir_recursive(&Path::new("build"), U_RWX); + file::mkdir_recursive(&Path::new("src"), io::UserRWX); + file::mkdir_recursive(&Path::new("bin"), io::UserRWX); + file::mkdir_recursive(&Path::new("lib"), io::UserRWX); + file::mkdir_recursive(&Path::new("build"), io::UserRWX); } fn uninstall(&self, _id: &str, _vers: Option<~str>) { diff --git a/src/librustpkg/package_id.rs b/src/librustpkg/package_id.rs index 0fc614d7f3c..0da343a27bf 100644 --- a/src/librustpkg/package_id.rs +++ b/src/librustpkg/package_id.rs @@ -10,7 +10,6 @@ use version::{try_getting_version, try_getting_local_version, Version, NoVersion, split_version}; -use std::rt::io::Writer; use std::hash::Streaming; use std::hash; diff --git a/src/librustpkg/package_source.rs b/src/librustpkg/package_source.rs index 797ea3372cc..a52aa68e1e4 100644 --- a/src/librustpkg/package_source.rs +++ b/src/librustpkg/package_source.rs @@ -12,7 +12,8 @@ extern mod extra; use target::*; use package_id::PkgId; -use std::path::Path; +use std::rt::io; +use std::rt::io::file; use std::os; use context::*; use crate::Crate; @@ -117,7 +118,7 @@ impl PkgSrc { debug!("Checking dirs: {:?}", to_try.map(|p| p.display().to_str()).connect(":")); - let path = to_try.iter().find(|&d| os::path_exists(d)); + let path = to_try.iter().find(|&d| d.exists()); // See the comments on the definition of PkgSrc let mut build_in_destination = use_rust_path_hack; @@ -132,7 +133,7 @@ impl PkgSrc { let package_id = PkgId::new(prefix.as_str().unwrap()); let path = build_dir.join(&package_id.path); debug!("in loop: checking if {} is a directory", path.display()); - if os::path_is_dir(&path) { + if path.is_dir() { let ps = PkgSrc::new(source_workspace, destination_workspace, use_rust_path_hack, @@ -237,7 +238,7 @@ impl PkgSrc { debug!("For package id {}, returning {}", id.to_str(), dir.display()); - if !os::path_is_dir(&dir) { + if !dir.is_dir() { cond.raise((id.clone(), ~"supplied path for package dir is a \ non-directory")); } @@ -267,7 +268,7 @@ impl PkgSrc { debug!("Checking whether {} (path = {}) exists locally. Cwd = {}, does it? {:?}", pkgid.to_str(), pkgid.path.display(), cwd.display(), - os::path_exists(&pkgid.path)); + pkgid.path.exists()); match safe_git_clone(&pkgid.path, &pkgid.version, local) { CheckedOutSources => { @@ -300,7 +301,7 @@ impl PkgSrc { // Move clone_target to local. // First, create all ancestor directories. let moved = make_dir_rwx_recursive(&local.dir_path()) - && os::rename_file(&clone_target, local); + && io::result(|| file::rename(&clone_target, local)).is_ok(); if moved { Some(local.clone()) } else { None } } @@ -312,7 +313,7 @@ impl PkgSrc { pub fn package_script_option(&self) -> Option { let maybe_path = self.start_dir.join("pkg.rs"); debug!("package_script_option: checking whether {} exists", maybe_path.display()); - if os::path_exists(&maybe_path) { + if maybe_path.exists() { Some(maybe_path) } else { None @@ -349,7 +350,7 @@ impl PkgSrc { let prefix = self.start_dir.component_iter().len(); debug!("Matching against {}", self.id.short_name); - do os::walk_dir(&self.start_dir) |pth| { + do file::walk_dir(&self.start_dir) |pth| { let maybe_known_crate_set = match pth.filename_str() { Some(filename) if filter(filename) => match filename { "lib.rs" => Some(&mut self.libs), diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index a48ef23115c..75f03533d58 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -18,8 +18,9 @@ use rustc::driver::driver::host_triple; use std::libc; use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; -use std::os::mkdir_recursive; use std::os; +use std::rt::io; +use std::rt::io::file; use messages::*; pub fn default_workspace() -> Path { @@ -28,8 +29,8 @@ pub fn default_workspace() -> Path { fail!("Empty RUST_PATH"); } let result = p[0]; - if !os::path_is_dir(&result) { - os::mkdir_recursive(&result, U_RWX); + if !result.is_dir() { + file::mkdir_recursive(&result, io::UserRWX); } result } @@ -43,9 +44,13 @@ pub static U_RWX: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32; /// Creates a directory that is readable, writeable, /// and executable by the user. Returns true iff creation /// succeeded. -pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, U_RWX) } +pub fn make_dir_rwx(p: &Path) -> bool { + io::result(|| file::mkdir(p, io::UserRWX)).is_ok() +} -pub fn make_dir_rwx_recursive(p: &Path) -> bool { os::mkdir_recursive(p, U_RWX) } +pub fn make_dir_rwx_recursive(p: &Path) -> bool { + io::result(|| file::mkdir_recursive(p, io::UserRWX)).is_ok() +} // n.b. The next three functions ignore the package version right // now. Should fix that. @@ -59,15 +64,16 @@ pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool { pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path, // Returns the directory it was actually found in workspace_to_src_dir: &fn(&Path) -> Path) -> Option { - if !os::path_is_dir(workspace) { + if !workspace.is_dir() { return None; } let src_dir = workspace_to_src_dir(workspace); + if !src_dir.is_dir() { return None } let mut found = None; - do os::walk_dir(&src_dir) |p| { - if os::path_is_dir(p) { + do file::walk_dir(&src_dir) |p| { + if p.is_dir() { if *p == src_dir.join(&pkgid.path) || { let pf = p.filename_str(); do pf.iter().any |&g| { @@ -125,7 +131,7 @@ pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option< result = mk_output_path(Main, Build, pkgid, result); debug!("built_executable_in_workspace: checking whether {} exists", result.display()); - if os::path_exists(&result) { + if result.exists() { Some(result) } else { @@ -152,7 +158,7 @@ fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Opt result = mk_output_path(what, Build, pkgid, result); debug!("output_in_workspace: checking whether {} exists", result.display()); - if os::path_exists(&result) { + if result.exists() { Some(result) } else { @@ -210,7 +216,7 @@ pub fn system_library(sysroot: &Path, lib_name: &str) -> Option { fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Option { debug!("Listing directory {}", dir_to_search.display()); - let dir_contents = os::list_dir(dir_to_search); + let dir_contents = do io::ignore_io_error { file::readdir(dir_to_search) }; debug!("dir has {:?} entries", dir_contents.len()); let lib_prefix = format!("{}{}", os::consts::DLL_PREFIX, short_name); @@ -294,7 +300,7 @@ pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { /// As a side effect, creates the lib-dir if it doesn't exist pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { use conditions::bad_path::cond; - if !os::path_is_dir(workspace) { + if !workspace.is_dir() { cond.raise(((*workspace).clone(), format!("Workspace supplied to target_library_in_workspace \ is not a directory! {}", workspace.display()))); @@ -333,7 +339,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path, (Install, Lib) => target_lib_dir(workspace), (Install, _) => target_bin_dir(workspace) }; - if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) { + if io::result(|| file::mkdir_recursive(&result, io::UserRWX)).is_err() { cond.raise((result.clone(), format!("target_file_in_workspace couldn't \ create the {} dir (pkgid={}, workspace={}, what={:?}, where={:?}", subdir, pkgid.to_str(), workspace.display(), what, where))); @@ -344,18 +350,12 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path, /// Return the directory for 's build artifacts in . /// Creates it if it doesn't exist. pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - use conditions::bad_path::cond; - let mut result = target_build_dir(workspace); result.push(&pkgid.path); debug!("Creating build dir {} for package id {}", result.display(), pkgid.to_str()); - if os::path_exists(&result) || os::mkdir_recursive(&result, U_RWX) { - result - } - else { - cond.raise((result, format!("Could not create directory for package {}", pkgid.to_str()))) - } + file::mkdir_recursive(&result, io::UserRWX); + return result; } /// Return the output file for a given directory name, @@ -398,13 +398,13 @@ pub fn mk_output_path(what: OutputType, where: Target, pub fn uninstall_package_from(workspace: &Path, pkgid: &PkgId) { let mut did_something = false; let installed_bin = target_executable_in_workspace(pkgid, workspace); - if os::path_exists(&installed_bin) { - os::remove_file(&installed_bin); + if installed_bin.exists() { + file::unlink(&installed_bin); did_something = true; } let installed_lib = target_library_in_workspace(pkgid, workspace); - if os::path_exists(&installed_lib) { - os::remove_file(&installed_lib); + if installed_lib.exists() { + file::unlink(&installed_lib); did_something = true; } if !did_something { @@ -421,7 +421,7 @@ pub fn dir_has_crate_file(dir: &Path) -> bool { fn dir_has_file(dir: &Path, file: &str) -> bool { assert!(dir.is_absolute()); - os::path_exists(&dir.join(file)) + dir.join(file).exists() } pub fn find_dir_using_rust_path_hack(p: &PkgId) -> Option { diff --git a/src/librustpkg/source_control.rs b/src/librustpkg/source_control.rs index c3e4205dfc9..a0e50ff0f9e 100644 --- a/src/librustpkg/source_control.rs +++ b/src/librustpkg/source_control.rs @@ -10,8 +10,9 @@ // Utils for working with version control repositories. Just git right now. -use std::{os, run, str}; +use std::{run, str}; use std::run::{ProcessOutput, ProcessOptions, Process}; +use std::rt::io::file; use extra::tempfile::TempDir; use version::*; use path_util::chmod_read_only; @@ -22,14 +23,14 @@ use path_util::chmod_read_only; /// directory (that the callee may use, for example, to check out remote sources into). /// Returns `CheckedOutSources` if the clone succeeded. pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult { - if os::path_exists(source) { + if source.exists() { debug!("{} exists locally! Cloning it into {}", source.display(), target.display()); // Ok to use target here; we know it will succeed - assert!(os::path_is_dir(source)); + assert!(source.is_dir()); assert!(is_git_dir(source)); - if !os::path_exists(target) { + if !target.exists() { debug!("Running: git clone {} {}", source.display(), target.display()); // FIXME (#9639): This needs to handle non-utf8 paths let outp = run::process_output("git", [~"clone", @@ -95,8 +96,8 @@ pub enum CloneResult { pub fn make_read_only(target: &Path) { // Now, make all the files in the target dir read-only - do os::walk_dir(target) |p| { - if !os::path_is_dir(p) { + do file::walk_dir(target) |p| { + if !p.is_dir() { assert!(chmod_read_only(p)); }; true @@ -138,5 +139,5 @@ fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> ProcessOutput } pub fn is_git_dir(p: &Path) -> bool { - os::path_is_dir(&p.join(".git")) + p.join(".git").is_dir() } diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 8f1b269f1ca..60e99f242ef 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -13,8 +13,7 @@ use context::{BuildContext, Context, RustcFlags}; use std::{os, run, str, task}; use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use extra::arc::Arc; use extra::arc::RWArc; use extra::tempfile::TempDir; @@ -27,7 +26,7 @@ use installed_packages::list_installed_packages; use package_id::{PkgId}; use version::{ExactRevision, NoVersion, Version, Tagged}; use path_util::{target_executable_in_workspace, target_test_in_workspace, - target_bench_in_workspace, make_dir_rwx, U_RWX, + target_bench_in_workspace, make_dir_rwx, library_in_workspace, installed_library_in_workspace, built_bench_in_workspace, built_test_in_workspace, built_library_in_workspace, built_executable_in_workspace, target_build_dir, @@ -84,7 +83,7 @@ fn git_repo_pkg_with_tag(a_tag: ~str) -> PkgId { } fn writeFile(file_path: &Path, contents: &str) { - let mut out = file_path.open_writer(io::CreateOrTruncate); + let mut out = file::create(file_path); out.write(contents.as_bytes()); out.write(['\n' as u8]); } @@ -92,7 +91,7 @@ fn writeFile(file_path: &Path, contents: &str) { fn mk_emptier_workspace(tag: &str) -> TempDir { let workspace = TempDir::new(tag).expect("couldn't create temp dir"); let package_dir = workspace.path().join("src"); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); workspace } @@ -107,7 +106,7 @@ fn mk_workspace(workspace: &Path, short_name: &Path, version: &Version) -> Path // FIXME (#9639): This needs to handle non-utf8 paths let package_dir = workspace.join_many([~"src", format!("{}-{}", short_name.as_str().unwrap(), version.to_str())]); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); package_dir } @@ -120,12 +119,12 @@ fn mk_temp_workspace(short_name: &Path, version: &Version) -> (TempDir, Path) { version.to_str())]); debug!("Created {} and does it exist? {:?}", package_dir.display(), - os::path_is_dir(&package_dir)); + package_dir.is_dir()); // Create main, lib, test, and bench files debug!("mk_workspace: creating {}", package_dir.display()); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); debug!("Created {} and does it exist? {:?}", package_dir.display(), - os::path_is_dir(&package_dir)); + package_dir.is_dir()); // Create main, lib, test, and bench files writeFile(&package_dir.join("main.rs"), @@ -162,7 +161,7 @@ fn init_git_repo(p: &Path) -> TempDir { let tmp = TempDir::new("git_local").expect("couldn't create temp dir"); let work_dir = tmp.path().join(p); let work_dir_for_opts = work_dir.clone(); - assert!(os::mkdir_recursive(&work_dir, U_RWX)); + file::mkdir_recursive(&work_dir, io::UserRWX); debug!("Running: git init in {}", work_dir.display()); run_git([~"init"], None, &work_dir_for_opts, format!("Couldn't initialize git repository in {}", work_dir.display())); @@ -199,25 +198,21 @@ 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}; - match p.get_mode() { - None => return false, - Some(m) => - ((m & S_IRUSR as uint) == S_IRUSR as uint - && (m & S_IWUSR as uint) == S_IWUSR as uint - && (m & S_IXUSR as uint) == S_IXUSR as uint) - } + 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 } fn is_read_only(p: &Path) -> bool { use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; - match p.get_mode() { - None => return false, - Some(m) => - ((m & S_IRUSR as uint) == S_IRUSR as uint - && (m & S_IWUSR as uint) == 0 as uint - && (m & S_IXUSR as uint) == 0 as uint) - } + 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 } fn test_sysroot() -> Path { @@ -289,7 +284,7 @@ fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~s None => ~"" }; debug!("{} cd {}; {} {}", env_str, cwd.display(), cmd, args.connect(" ")); - assert!(os::path_is_dir(&*cwd)); + assert!(cwd.is_dir()); let cwd = (*cwd).clone(); let mut prog = run::Process::new(cmd, args, run::ProcessOptions { env: env.map(|e| e + os::env()), @@ -325,9 +320,9 @@ fn create_local_package_in(pkgid: &PkgId, pkgdir: &Path) -> Path { let package_dir = pkgdir.join_many([~"src", pkgid.to_str()]); // Create main, lib, test, and bench files - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); debug!("Created {} and does it exist? {:?}", package_dir.display(), - os::path_is_dir(&package_dir)); + package_dir.is_dir()); // Create main, lib, test, and bench files writeFile(&package_dir.join("main.rs"), @@ -378,7 +373,7 @@ fn lib_exists(repo: &Path, pkg_path: &Path, _v: Version) -> bool { // ??? versio debug!("assert_lib_exists: checking whether {:?} exists", lib); lib.is_some() && { let libname = lib.get_ref(); - os::path_exists(libname) && is_rwx(libname) + libname.exists() && is_rwx(libname) } } @@ -389,21 +384,21 @@ fn assert_executable_exists(repo: &Path, short_name: &str) { fn executable_exists(repo: &Path, short_name: &str) -> bool { debug!("executable_exists: repo = {}, short_name = {}", repo.display(), short_name); let exec = target_executable_in_workspace(&PkgId::new(short_name), repo); - os::path_exists(&exec) && is_rwx(&exec) + exec.exists() && is_rwx(&exec) } fn test_executable_exists(repo: &Path, short_name: &str) -> bool { debug!("test_executable_exists: repo = {}, short_name = {}", repo.display(), short_name); let exec = built_test_in_workspace(&PkgId::new(short_name), repo); do exec.map_default(false) |exec| { - os::path_exists(&exec) && is_rwx(&exec) + exec.exists() && is_rwx(&exec) } } fn remove_executable_file(p: &PkgId, workspace: &Path) { let exec = target_executable_in_workspace(&PkgId::new(p.short_name), workspace); - if os::path_exists(&exec) { - assert!(os::remove_file(&exec)); + if exec.exists() { + file::unlink(&exec); } } @@ -417,14 +412,14 @@ fn built_executable_exists(repo: &Path, short_name: &str) -> bool { let exec = built_executable_in_workspace(&PkgId::new(short_name), repo); exec.is_some() && { let execname = exec.get_ref(); - os::path_exists(execname) && is_rwx(execname) + execname.exists() && is_rwx(execname) } } 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) => assert!(os::remove_file(&r)), + Some(r) => file::unlink(&r), None => () } } @@ -446,8 +441,9 @@ fn llvm_bitcode_file_exists(repo: &Path, short_name: &str) -> bool { } fn file_exists(repo: &Path, short_name: &str, extension: &str) -> bool { - os::path_exists(&target_build_dir(repo).join_many([short_name.to_owned(), - format!("{}.{}", short_name, extension)])) + target_build_dir(repo).join_many([short_name.to_owned(), + format!("{}.{}", short_name, extension)]) + .exists() } fn assert_built_library_exists(repo: &Path, short_name: &str) { @@ -459,7 +455,7 @@ fn built_library_exists(repo: &Path, short_name: &str) -> bool { let lib = built_library_in_workspace(&PkgId::new(short_name), repo); lib.is_some() && { let libname = lib.get_ref(); - os::path_exists(libname) && is_rwx(libname) + libname.exists() && is_rwx(libname) } } @@ -508,7 +504,7 @@ fn output_file_name(workspace: &Path, short_name: ~str) -> Path { fn touch_source_file(workspace: &Path, pkgid: &PkgId) { use conditions::bad_path::cond; let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]); - let contents = os::list_dir_path(&pkg_src_dir); + let contents = file::readdir(&pkg_src_dir); for p in contents.iter() { if p.extension_str() == Some("rs") { // should be able to do this w/o a process @@ -527,7 +523,7 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) { fn touch_source_file(workspace: &Path, pkgid: &PkgId) { use conditions::bad_path::cond; let pkg_src_dir = workspace.join_many([~"src", pkgid.to_str()]); - let contents = os::list_dir_path(&pkg_src_dir); + let contents = file::readdir(&pkg_src_dir); for p in contents.iter() { if p.extension_str() == Some("rs") { // should be able to do this w/o a process @@ -548,7 +544,7 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) { let mut maybe_p = None; let maybe_file = pkg_src_dir.join(filename); debug!("Trying to frob {} -- {}", pkg_src_dir.display(), filename); - if os::path_exists(&maybe_file) { + if maybe_file.exists() { maybe_p = Some(maybe_file); } debug!("Frobbed? {:?}", maybe_p); @@ -557,7 +553,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 = p.open_writer(io::Append); + let mut w = file::open_stream(p, io::Append, io::Write); w.write(bytes!("/* hi */\n")); } } @@ -570,13 +566,14 @@ fn frob_source_file(workspace: &Path, pkgid: &PkgId, filename: &str) { fn test_make_dir_rwx() { let temp = &os::tmpdir(); let dir = temp.join("quux"); - assert!(!os::path_exists(&dir) || - os::remove_dir_recursive(&dir)); + if dir.exists() { + file::rmdir_recursive(&dir); + } debug!("Trying to make {}", dir.display()); assert!(make_dir_rwx(&dir)); - assert!(os::path_is_dir(&dir)); + assert!(dir.is_dir()); assert!(is_rwx(&dir)); - assert!(os::remove_dir_recursive(&dir)); + file::rmdir_recursive(&dir); } // n.b. I ignored the next two tests for now because something funny happens on linux @@ -603,19 +600,19 @@ fn test_install_valid() { // Check that all files exist let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace); debug!("exec = {}", exec.display()); - assert!(os::path_exists(&exec)); + assert!(exec.exists()); assert!(is_rwx(&exec)); let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace); debug!("lib = {:?}", lib); - assert!(lib.as_ref().map_default(false, |l| os::path_exists(l))); + assert!(lib.as_ref().map_default(false, |l| l.exists())); assert!(lib.as_ref().map_default(false, |l| is_rwx(l))); // And that the test and bench executables aren't installed - assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, temp_workspace))); + assert!(!target_test_in_workspace(&temp_pkg_id, temp_workspace).exists()); let bench = target_bench_in_workspace(&temp_pkg_id, temp_workspace); debug!("bench = {}", bench.display()); - assert!(!os::path_exists(&bench)); + assert!(!bench.exists()); // Make sure the db isn't dirty, so that it doesn't try to save() // asynchronously after the temporary directory that it wants to save @@ -655,19 +652,19 @@ fn test_install_valid_external() { // Check that all files exist let exec = target_executable_in_workspace(&temp_pkg_id, temp_workspace); debug!("exec = {}", exec.display()); - assert!(os::path_exists(&exec)); + assert!(exec.exists()); assert!(is_rwx(&exec)); let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace); debug!("lib = {:?}", lib); - assert!(lib.as_ref().map_default(false, |l| os::path_exists(l))); + assert!(lib.as_ref().map_default(false, |l| l.exists())); assert!(lib.as_ref().map_default(false, |l| is_rwx(l))); // And that the test and bench executables aren't installed - assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, temp_workspace))); + assert!(!target_test_in_workspace(&temp_pkg_id, temp_workspace).exists()); let bench = target_bench_in_workspace(&temp_pkg_id, temp_workspace); debug!("bench = {}", bench.display()); - assert!(!os::path_exists(&bench)); + assert!(!bench.exists()); } @@ -711,7 +708,7 @@ fn test_install_git() { debug!("Checking for files in {}", ws.display()); let exec = target_executable_in_workspace(&temp_pkg_id, &ws); debug!("exec = {}", exec.display()); - assert!(os::path_exists(&exec)); + assert!(exec.exists()); assert!(is_rwx(&exec)); let _built_lib = built_library_in_workspace(&temp_pkg_id, @@ -719,17 +716,17 @@ fn test_install_git() { assert_lib_exists(&ws, &temp_pkg_id.path, temp_pkg_id.version.clone()); let built_test = built_test_in_workspace(&temp_pkg_id, &ws).expect("test_install_git: built test should exist"); - assert!(os::path_exists(&built_test)); + assert!(built_test.exists()); let built_bench = built_bench_in_workspace(&temp_pkg_id, &ws).expect("test_install_git: built bench should exist"); - assert!(os::path_exists(&built_bench)); + assert!(built_bench.exists()); // And that the test and bench executables aren't installed let test = target_test_in_workspace(&temp_pkg_id, &ws); - assert!(!os::path_exists(&test)); + assert!(!test.exists()); debug!("test = {}", test.display()); let bench = target_bench_in_workspace(&temp_pkg_id, &ws); debug!("bench = {}", bench.display()); - assert!(!os::path_exists(&bench)); + assert!(!bench.exists()); } #[test] @@ -783,6 +780,7 @@ fn test_package_version() { let repo = repo.path(); let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test_pkg_version"]); debug!("Writing files in: {}", repo_subdir.display()); + file::mkdir_recursive(&repo_subdir, io::UserRWX); writeFile(&repo_subdir.join("main.rs"), "fn main() { let _x = (); }"); writeFile(&repo_subdir.join("lib.rs"), @@ -853,9 +851,9 @@ fn test_package_request_version() { let mut dir = target_build_dir(&repo.join(".rust")); dir.push(&Path::new("src/mockgithub.com/catamorphism/test_pkg_version-0.3")); debug!("dir = {}", dir.display()); - assert!(os::path_is_dir(&dir)); - assert!(os::path_exists(&dir.join("version-0.3-file.txt"))); - assert!(!os::path_exists(&dir.join("version-0.4-file.txt"))); + assert!(dir.is_dir()); + assert!(dir.join("version-0.3-file.txt").exists()); + assert!(!dir.join("version-0.4-file.txt").exists()); } #[test] @@ -904,16 +902,13 @@ 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()); - if !os::copy_file(&source, - &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"])) { - fail!("Couldn't copy file"); - } + 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!(os::path_exists(&target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]))); + assert!(target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]).exists()); let generated_path = target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]); debug!("generated path = {}", generated_path.display()); - assert!(os::path_exists(&generated_path)); + assert!(generated_path.exists()); } #[test] @@ -921,7 +916,7 @@ fn rustpkg_build_no_arg() { let tmp = TempDir::new("rustpkg_build_no_arg").expect("rustpkg_build_no_arg failed"); let tmp = tmp.path().join(".rust"); let package_dir = tmp.join_many(["src", "foo"]); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); writeFile(&package_dir.join("main.rs"), "fn main() { let _x = (); }"); @@ -935,7 +930,7 @@ fn rustpkg_install_no_arg() { let tmp = TempDir::new("rustpkg_install_no_arg").expect("rustpkg_install_no_arg failed"); let tmp = tmp.path().join(".rust"); let package_dir = tmp.join_many(["src", "foo"]); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); writeFile(&package_dir.join("lib.rs"), "fn main() { let _x = (); }"); debug!("install_no_arg: dir = {}", package_dir.display()); @@ -948,7 +943,7 @@ fn rustpkg_clean_no_arg() { let tmp = TempDir::new("rustpkg_clean_no_arg").expect("rustpkg_clean_no_arg failed"); let tmp = tmp.path().join(".rust"); let package_dir = tmp.join_many(["src", "foo"]); - assert!(os::mkdir_recursive(&package_dir, U_RWX)); + file::mkdir_recursive(&package_dir, io::UserRWX); writeFile(&package_dir.join("main.rs"), "fn main() { let _x = (); }"); @@ -957,7 +952,7 @@ fn rustpkg_clean_no_arg() { assert_built_executable_exists(&tmp, "foo"); command_line_test([~"clean"], &package_dir); let res = built_executable_in_workspace(&PkgId::new("foo"), &tmp); - assert!(!res.as_ref().map_default(false, |m| { os::path_exists(m) })); + assert!(!res.as_ref().map_default(false, |m| m.exists())); } #[test] @@ -983,9 +978,9 @@ fn rust_path_test() { fn rust_path_contents() { let dir = TempDir::new("rust_path").expect("rust_path_contents failed"); let abc = &dir.path().join_many(["A", "B", "C"]); - assert!(os::mkdir_recursive(&abc.join(".rust"), U_RWX)); - assert!(os::mkdir_recursive(&abc.with_filename(".rust"), U_RWX)); - assert!(os::mkdir_recursive(&abc.dir_path().with_filename(".rust"), U_RWX)); + file::mkdir_recursive(&abc.join(".rust"), io::UserRWX); + file::mkdir_recursive(&abc.with_filename(".rust"), io::UserRWX); + file::mkdir_recursive(&abc.dir_path().with_filename(".rust"), io::UserRWX); assert!(os::change_dir(abc)); let p = rust_path(); @@ -1225,8 +1220,8 @@ fn test_non_numeric_tag() { temp_pkg_id.path.as_str().unwrap())], repo); let file1 = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg", "testbranch_only"]); let file2 = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg", "master_only"]); - assert!(os::path_exists(&file1)); - assert!(!os::path_exists(&file2)); + assert!(file1.exists()); + assert!(!file2.exists()); } #[test] @@ -1237,11 +1232,11 @@ fn test_extern_mod() { let lib_depend_dir = TempDir::new("foo").expect("test_extern_mod"); let lib_depend_dir = lib_depend_dir.path(); let aux_dir = lib_depend_dir.join_many(["src", "mockgithub.com", "catamorphism", "test_pkg"]); - assert!(os::mkdir_recursive(&aux_dir, U_RWX)); + file::mkdir_recursive(&aux_dir, io::UserRWX); let aux_pkg_file = aux_dir.join("lib.rs"); writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() { assert!(true); } }\n"); - assert!(os::path_exists(&aux_pkg_file)); + assert!(aux_pkg_file.exists()); writeFile(&main_file, "extern mod test = \"mockgithub.com/catamorphism/test_pkg\";\nuse test::bar;\ @@ -1275,7 +1270,7 @@ fn test_extern_mod() { str::from_utf8(outp.output), str::from_utf8(outp.error)); } - assert!(os::path_exists(&exec_file) && is_executable(&exec_file)); + assert!(exec_file.exists() && is_executable(&exec_file)); } #[test] @@ -1286,11 +1281,11 @@ fn test_extern_mod_simpler() { let lib_depend_dir = TempDir::new("foo").expect("test_extern_mod_simpler"); let lib_depend_dir = lib_depend_dir.path(); let aux_dir = lib_depend_dir.join_many(["src", "rust-awesomeness"]); - assert!(os::mkdir_recursive(&aux_dir, U_RWX)); + file::mkdir_recursive(&aux_dir, io::UserRWX); let aux_pkg_file = aux_dir.join("lib.rs"); writeFile(&aux_pkg_file, "pub mod bar { pub fn assert_true() { assert!(true); } }\n"); - assert!(os::path_exists(&aux_pkg_file)); + assert!(aux_pkg_file.exists()); writeFile(&main_file, "extern mod test = \"rust-awesomeness\";\nuse test::bar;\ @@ -1330,7 +1325,7 @@ fn test_extern_mod_simpler() { str::from_utf8(outp.output), str::from_utf8(outp.error)); } - assert!(os::path_exists(&exec_file) && is_executable(&exec_file)); + assert!(exec_file.exists() && is_executable(&exec_file)); } #[test] @@ -1342,8 +1337,8 @@ fn test_import_rustpkg() { "extern mod rustpkg; fn main() {}"); command_line_test([~"build", ~"foo"], workspace); debug!("workspace = {}", workspace.display()); - assert!(os::path_exists(&target_build_dir(workspace).join("foo").join(format!("pkg{}", - os::EXE_SUFFIX)))); + assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}", + os::EXE_SUFFIX)).exists()); } #[test] @@ -1355,8 +1350,8 @@ fn test_macro_pkg_script() { "extern mod rustpkg; fn main() { debug!(\"Hi\"); }"); command_line_test([~"build", ~"foo"], workspace); debug!("workspace = {}", workspace.display()); - assert!(os::path_exists(&target_build_dir(workspace).join("foo").join(format!("pkg{}", - os::EXE_SUFFIX)))); + assert!(target_build_dir(workspace).join("foo").join(format!("pkg{}", + os::EXE_SUFFIX)).exists()); } #[test] @@ -1436,7 +1431,7 @@ fn rust_path_hack_cwd() { // Same as rust_path_hack_test, but the CWD is the dir to build out of let cwd = TempDir::new("foo").expect("rust_path_hack_cwd"); let cwd = cwd.path().join("foo"); - assert!(os::mkdir_recursive(&cwd, U_RWX)); + file::mkdir_recursive(&cwd, io::UserRWX); writeFile(&cwd.join("lib.rs"), "pub fn f() { }"); let dest_workspace = mk_empty_workspace(&Path::new("bar"), &NoVersion, "dest_workspace"); @@ -1456,7 +1451,7 @@ fn rust_path_hack_multi_path() { // Same as rust_path_hack_test, but with a more complex package ID let cwd = TempDir::new("pkg_files").expect("rust_path_hack_cwd"); let subdir = cwd.path().join_many(["foo", "bar", "quux"]); - assert!(os::mkdir_recursive(&subdir, U_RWX)); + file::mkdir_recursive(&subdir, io::UserRWX); writeFile(&subdir.join("lib.rs"), "pub fn f() { }"); let name = ~"foo/bar/quux"; @@ -1870,21 +1865,22 @@ fn pkgid_pointing_to_subdir() { // rustpkg should recognize that and treat the part after some_repo/ as a subdir let workspace = TempDir::new("parent_repo").expect("Couldn't create temp dir"); let workspace = workspace.path(); - assert!(os::mkdir_recursive(&workspace.join_many(["src", "mockgithub.com", - "mozilla", "some_repo"]), U_RWX)); + file::mkdir_recursive(&workspace.join_many(["src", "mockgithub.com", + "mozilla", "some_repo"]), + io::UserRWX); let foo_dir = workspace.join_many(["src", "mockgithub.com", "mozilla", "some_repo", "extras", "foo"]); let bar_dir = workspace.join_many(["src", "mockgithub.com", "mozilla", "some_repo", "extras", "bar"]); - assert!(os::mkdir_recursive(&foo_dir, U_RWX)); - assert!(os::mkdir_recursive(&bar_dir, U_RWX)); + file::mkdir_recursive(&foo_dir, io::UserRWX); + file::mkdir_recursive(&bar_dir, io::UserRWX); writeFile(&foo_dir.join("lib.rs"), "pub fn f() {}"); writeFile(&bar_dir.join("lib.rs"), "pub fn g() {}"); debug!("Creating a file in {}", workspace.display()); let testpkg_dir = workspace.join_many(["src", "testpkg-0.1"]); - assert!(os::mkdir_recursive(&testpkg_dir, U_RWX)); + file::mkdir_recursive(&testpkg_dir, io::UserRWX); writeFile(&testpkg_dir.join("main.rs"), "extern mod foo = \"mockgithub.com/mozilla/some_repo/extras/foo\";\n @@ -1957,9 +1953,9 @@ fn test_target_specific_build_dir() { ~"build", ~"foo"], workspace); - assert!(os::path_is_dir(&target_build_dir(workspace))); + assert!(target_build_dir(workspace).is_dir()); assert!(built_executable_exists(workspace, "foo")); - assert!(os::list_dir(&workspace.join("build")).len() == 1); + assert!(file::readdir(&workspace.join("build")).len() == 1); } #[test] @@ -1973,10 +1969,10 @@ fn test_target_specific_install_dir() { ~"install", ~"foo"], workspace); - assert!(os::path_is_dir(&workspace.join_many([~"lib", host_triple()]))); + assert!(workspace.join_many([~"lib", host_triple()]).is_dir()); assert_lib_exists(workspace, &Path::new("foo"), NoVersion); - assert!(os::list_dir(&workspace.join("lib")).len() == 1); - assert!(os::path_is_dir(&workspace.join("bin"))); + assert!(file::readdir(&workspace.join("lib")).len() == 1); + assert!(workspace.join("bin").is_dir()); assert_executable_exists(workspace, "foo"); } @@ -1988,7 +1984,7 @@ fn test_dependencies_terminate() { let workspace = workspace.path(); let b_dir = workspace.join_many(["src", "b-0.1"]); let b_subdir = b_dir.join("test"); - assert!(os::mkdir_recursive(&b_subdir, U_RWX)); + file::mkdir_recursive(&b_subdir, io::UserRWX); writeFile(&b_subdir.join("test.rs"), "extern mod b; use b::f; #[test] fn g() { f() }"); command_line_test([~"install", ~"b"], workspace); @@ -2161,19 +2157,19 @@ fn test_installed_read_only() { debug!("Checking for files in {}", ws.display()); let exec = target_executable_in_workspace(&temp_pkg_id, &ws); debug!("exec = {}", exec.display()); - assert!(os::path_exists(&exec)); + assert!(exec.exists()); assert!(is_rwx(&exec)); let built_lib = built_library_in_workspace(&temp_pkg_id, &ws).expect("test_install_git: built lib should exist"); - assert!(os::path_exists(&built_lib)); + assert!(built_lib.exists()); assert!(is_rwx(&built_lib)); // Make sure sources are (a) under "build" and (b) read-only let src1 = target_build_dir(&ws).join_many([~"src", temp_pkg_id.to_str(), ~"main.rs"]); let src2 = target_build_dir(&ws).join_many([~"src", temp_pkg_id.to_str(), ~"lib.rs"]); - assert!(os::path_exists(&src1)); - assert!(os::path_exists(&src2)); + assert!(src1.exists()); + assert!(src2.exists()); assert!(is_read_only(&src1)); assert!(is_read_only(&src2)); } @@ -2186,7 +2182,7 @@ fn test_installed_local_changes() { debug!("repo = {}", repo.display()); let repo_subdir = repo.join_many(["mockgithub.com", "catamorphism", "test-pkg"]); debug!("repo_subdir = {}", repo_subdir.display()); - assert!(os::mkdir_recursive(&repo.join_many([".rust", "src"]), U_RWX)); + file::mkdir_recursive(&repo.join_many([".rust", "src"]), io::UserRWX); writeFile(&repo_subdir.join("main.rs"), "fn main() { let _x = (); }"); @@ -2269,7 +2265,7 @@ fn find_sources_in_cwd() { let temp_dir = TempDir::new("sources").expect("find_sources_in_cwd failed"); let temp_dir = temp_dir.path(); let source_dir = temp_dir.join("foo"); - os::mkdir_recursive(&source_dir, U_RWX); + file::mkdir_recursive(&source_dir, io::UserRWX); writeFile(&source_dir.join("main.rs"), "fn main() { let _x = (); }"); command_line_test([~"install", ~"foo"], &source_dir); @@ -2292,16 +2288,13 @@ 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"]); - if !os::copy_file(&source, - &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"])) { - fail!("Couldn't copy file"); - } + 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"); let c_library_path = out_dir.join(platform_library_name("foo")); debug!("c library path: {}", c_library_path.display()); - assert!(os::path_exists(&c_library_path)); + assert!(c_library_path.exists()); } #[test] @@ -2316,16 +2309,13 @@ 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"]); - if !os::copy_file(&source, - &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"])) { - fail!("Couldn't copy file"); - } + 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"); let c_library_path = out_dir.join(platform_library_name("foo")); debug!("c library path: {}", c_library_path.display()); - assert!(os::path_exists(&c_library_path)); + assert!(c_library_path.exists()); // Now, make it read-only so rebuilding will fail assert!(chmod_read_only(&c_library_path)); @@ -2352,15 +2342,13 @@ 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()); - if !os::copy_file(&source, &target) { - fail!("Couldn't copy file"); - } + file::copy(&source, &target); command_line_test([~"build", ~"cdep"], dir); assert_executable_exists(dir, "cdep"); let out_dir = target_build_dir(dir).join("cdep"); let c_library_path = out_dir.join(platform_library_name("foo")); debug!("c library path: {}", c_library_path.display()); - assert!(os::path_exists(&c_library_path)); + assert!(c_library_path.exists()); // Now, make the Rust library read-only so rebuilding will fail match built_library_in_workspace(&PkgId::new("cdep"), dir) { @@ -2380,8 +2368,5 @@ fn test_c_dependency_yes_rebuilding() { fn is_executable(p: &Path) -> bool { use std::libc::consts::os::posix88::{S_IXUSR}; - match p.get_mode() { - None => false, - Some(mode) => mode & S_IXUSR as uint == S_IXUSR as uint - } + p.exists() && p.stat().mode & S_IXUSR as u64 == S_IXUSR as u64 } diff --git a/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs index 016635339a9..f5d6317e7a6 100644 --- a/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/c-dependencies/pkg.rs @@ -31,7 +31,7 @@ pub fn main() { let sysroot_arg = args[1].clone(); let sysroot = Path::new(sysroot_arg); - if !os::path_exists(&sysroot) { + if !sysroot.exists() { fail!("Package script requires a sysroot that exists; {} doesn't", sysroot.display()); } diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs index f82c585b1d1..e5fb6889ae0 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs @@ -12,9 +12,7 @@ extern mod rustpkg; extern mod rustc; use std::os; -use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use rustpkg::api; use rustpkg::version::NoVersion; @@ -30,7 +28,7 @@ pub fn main() { let sysroot_arg = args[1].clone(); let sysroot = Path::new(sysroot_arg); - if !os::path_exists(&sysroot) { + if !sysroot.exists() { debug!("Failing, sysroot"); fail!("Package script requires a sysroot that exists;{} doesn't", sysroot.display()); } @@ -45,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 = out_path.join("generated.rs").open_writer(io::Create); + 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()); diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 9d835dcc20b..d0ba5ce368f 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -10,6 +10,8 @@ use std::libc; use std::os; +use std::rt::io; +use std::rt::io::file; use extra::workcache; use rustc::driver::{driver, session}; use extra::getopts::groups::getopts; @@ -32,7 +34,6 @@ use path_util::{default_workspace, built_library_in_workspace}; pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename}; pub use target::{Target, Build, Install}; use extra::treemap::TreeMap; -use path_util::U_RWX; pub use target::{lib_name_of, lib_crate_filename, WhatToBuild, MaybeCustom, Inferred}; use workcache_support::{digest_file_with_date, digest_only_date}; @@ -184,7 +185,7 @@ pub fn compile_input(context: &BuildContext, let mut out_dir = target_build_dir(workspace); out_dir.push(&pkg_id.path); // Make the output directory if it doesn't exist already - assert!(os::mkdir_recursive(&out_dir, U_RWX)); + file::mkdir_recursive(&out_dir, io::UserRWX); let binary = os::args()[0].to_managed(); @@ -256,11 +257,11 @@ pub fn compile_input(context: &BuildContext, // Make sure all the library directories actually exist, since the linker will complain // otherwise for p in addl_lib_search_paths.iter() { - if os::path_exists(p) { - assert!(os::path_is_dir(p)); + if p.exists() { + assert!(p.is_dir()) } else { - assert!(os::mkdir_recursive(p, U_RWX)); + file::mkdir_recursive(p, io::UserRWX); } } @@ -324,7 +325,7 @@ pub fn compile_input(context: &BuildContext, }; for p in discovered_output.iter() { debug!("About to discover output {}", p.display()); - if os::path_exists(p) { + if p.exists() { debug!("4. discovering output {}", p.display()); // FIXME (#9639): This needs to handle non-utf8 paths exec.discover_output("binary", p.as_str().unwrap(), digest_only_date(p)); @@ -629,10 +630,16 @@ fn debug_flags() -> ~[~str] { ~[] } /// Returns the last-modified date as an Option pub fn datestamp(p: &Path) -> Option { - debug!("Scrutinizing datestamp for {} - does it exist? {:?}", p.display(), os::path_exists(p)); - let out = p.stat().map(|stat| stat.modified); - debug!("Date = {:?}", out); - out.map(|t| { t as libc::time_t }) + debug!("Scrutinizing datestamp for {} - does it exist? {:?}", p.display(), + p.exists()); + match io::result(|| p.stat()) { + Ok(s) => { + let out = s.modified; + debug!("Date = {:?}", out); + Some(out as libc::time_t) + } + Err(*) => None, + } } pub type DepMap = TreeMap<~str, ~[(~str, ~str)]>; diff --git a/src/librustpkg/version.rs b/src/librustpkg/version.rs index 6ca19562724..eff16cb9996 100644 --- a/src/librustpkg/version.rs +++ b/src/librustpkg/version.rs @@ -14,7 +14,7 @@ extern mod std; use extra::semver; -use std::{char, os, result, run, str}; +use std::{char, result, run, str}; use extra::tempfile::TempDir; use path_util::rust_path; @@ -100,7 +100,7 @@ pub fn try_getting_local_version(local_path: &Path) -> Option { for rp in rustpath.iter() { let local_path = rp.join(local_path); let git_dir = local_path.join(".git"); - if !os::path_is_dir(&git_dir) { + if !git_dir.is_dir() { continue; } // FIXME (#9639): This needs to handle non-utf8 paths diff --git a/src/librustpkg/workcache_support.rs b/src/librustpkg/workcache_support.rs index 2e4894b854d..c16224afbf4 100644 --- a/src/librustpkg/workcache_support.rs +++ b/src/librustpkg/workcache_support.rs @@ -9,32 +9,23 @@ // except according to those terms. use std::rt::io; -use std::rt::io::Reader; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use extra::workcache; use sha1::{Digest, Sha1}; /// Hashes the file contents along with the last-modified time pub fn digest_file_with_date(path: &Path) -> ~str { use conditions::bad_path::cond; - use cond1 = conditions::bad_stat::cond; - let mut err = None; - let bytes = do io::io_error::cond.trap(|e| err = Some(e)).inside { - path.open_reader(io::Open).read_to_end() - }; - match err { - None => { + match io::result(|| file::open(path).read_to_end()) { + Ok(bytes) => { let mut sha = Sha1::new(); sha.input(bytes); - let st = match path.stat() { - Some(st) => st, - None => cond1.raise((path.clone(), format!("Couldn't get file access time"))) - }; + let st = path.stat(); sha.input_str(st.modified.to_str()); sha.result_str() } - Some(e) => { + Err(e) => { cond.raise((path.clone(), format!("Couldn't read file: {}", e.desc))); ~"" } @@ -43,13 +34,8 @@ pub fn digest_file_with_date(path: &Path) -> ~str { /// Hashes only the last-modified time pub fn digest_only_date(path: &Path) -> ~str { - use cond = conditions::bad_stat::cond; - let mut sha = Sha1::new(); - let st = match path.stat() { - Some(st) => st, - None => cond.raise((path.clone(), format!("Couldn't get file access time"))) - }; + let st = path.stat(); sha.input_str(st.modified.to_str()); sha.result_str() } diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs index a3550037246..e65f3ce5bb6 100644 --- a/src/librustpkg/workspace.rs +++ b/src/librustpkg/workspace.rs @@ -52,7 +52,7 @@ pub fn pkg_parent_workspaces(cx: &Context, pkgid: &PkgId) -> ~[Path] { } pub fn is_workspace(p: &Path) -> bool { - os::path_is_dir(&p.join("src")) + p.join("src").is_dir() } /// Construct a workspace and package-ID name based on the current directory. diff --git a/src/librustuv/file.rs b/src/librustuv/file.rs index 2303721986c..15df189edcd 100644 --- a/src/librustuv/file.rs +++ b/src/librustuv/file.rs @@ -182,7 +182,7 @@ impl FsRequest { self.sync_cleanup(result) } - pub fn mkdir(self, loop_: &Loop, path: &CString, mode: int, cb: FsCallback) { + 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)) @@ -221,6 +221,18 @@ impl FsRequest { assert_eq!(ret, 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 { + uvll::fs_chmod(loop_.native_handle(), self.native_handle(), p, mode, + complete_cb_ptr) + }); + assert_eq!(ret, 0); + } + pub fn readdir(self, loop_: &Loop, path: &CString, flags: c_int, cb: FsCallback) { let complete_cb_ptr = { @@ -593,7 +605,7 @@ mod test { S_IRUSR; let mkdir_req = FsRequest::new(); do mkdir_req.mkdir(&loop_, &path.to_c_str(), - mode as int) |req,uverr| { + mode as c_int) |req,uverr| { assert!(uverr.is_none()); let loop_ = req.get_loop(); let stat_req = FsRequest::new(); @@ -626,12 +638,12 @@ mod test { let mode = S_IWUSR | S_IRUSR; let mkdir_req = FsRequest::new(); - do mkdir_req.mkdir(&loop_, &path.to_c_str(), mode as int) |req,uverr| { + do mkdir_req.mkdir(&loop_, &path.to_c_str(), mode as c_int) |req,uverr| { assert!(uverr.is_none()); let loop_ = req.get_loop(); let mkdir_req = FsRequest::new(); do mkdir_req.mkdir(&loop_, &path.to_c_str(), - mode as int) |req,uverr| { + mode as c_int) |req,uverr| { assert!(uverr.is_some()); let loop_ = req.get_loop(); let _stat = req.get_stat(); diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index 7ecb51bb0d6..ae8546af4b4 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -20,6 +20,7 @@ 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::io::{standard_error, OtherIoError, SeekStyle, SeekSet, SeekCur, @@ -34,7 +35,7 @@ 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, S_IRWXU}; + O_WRONLY, S_IRUSR, S_IWUSR}; use std::rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create, CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite, FileStat}; @@ -699,9 +700,10 @@ impl IoFactory for UvIoFactory { assert!(!result_cell.is_empty()); return result_cell.take(); } - fn fs_mkdir(&mut self, path: &CString, mode: int) -> Result<(), IoError> { + 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, mode) |req, err| { + do mkdir_req.mkdir(l, p, perm as c_int) |req, err| { cb(req, err) }; } @@ -722,6 +724,15 @@ impl IoFactory for UvIoFactory { }; } } + 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) + }; + } + } +>>>>>>> Remove all blocking std::os blocking functions fn fs_readdir(&mut self, path: &CString, flags: c_int) -> Result<~[Path], IoError> { use str::StrSlice; diff --git a/src/librustuv/uvll.rs b/src/librustuv/uvll.rs index 9f26f9506a0..a2047ef98fa 100644 --- a/src/librustuv/uvll.rs +++ b/src/librustuv/uvll.rs @@ -795,8 +795,8 @@ pub unsafe fn fs_fstat(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, cb: *u8) rust_uv_fs_fstat(loop_ptr, req, fd, cb) } -pub unsafe fn fs_mkdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, mode: int, - cb: *u8) -> c_int { +pub unsafe fn fs_mkdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, + mode: c_int, cb: *u8) -> c_int { #[fixed_stack_segment]; #[inline(never)]; rust_uv_fs_mkdir(loop_ptr, req, path, mode as c_int, cb) @@ -813,6 +813,12 @@ pub unsafe fn fs_rename(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, rust_uv_fs_rename(loop_ptr, req, path, to, cb) } +pub unsafe fn fs_chmod(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, + mode: c_int, cb: *u8) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + + rust_uv_fs_chmod(loop_ptr, req, path, mode as c_int, cb) +} pub unsafe fn fs_readdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, flags: c_int, cb: *u8) -> c_int { #[fixed_stack_segment]; #[inline(never)]; @@ -1115,6 +1121,8 @@ extern { cb: *u8) -> c_int; fn rust_uv_fs_rename(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, to: *c_char, cb: *u8) -> c_int; + fn rust_uv_fs_chmod(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, + mode: c_int, cb: *u8) -> c_int; fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, flags: c_int, cb: *u8) -> c_int; fn rust_uv_fs_req_cleanup(req: *uv_fs_t); diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs index 2eec6ff4cba..7f91c5e4f90 100644 --- a/src/libstd/bool.rs +++ b/src/libstd/bool.rs @@ -317,8 +317,11 @@ impl Zero for bool { #[cfg(test)] mod tests { - use super::*; - use prelude::*; + use cmp::{Equal, Greater, Less, Eq, TotalOrd}; + use ops::{BitAnd, BitXor, BitOr}; + use from_str::{FromStr, from_str}; + use option::{Some, None}; + use super::all_values; #[test] fn test_bool() { diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 1f32c6a0a35..12281f06005 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -35,7 +35,6 @@ use container::Container; use iter::range; use libc; use libc::{c_char, c_void, c_int, size_t}; -use libc::FILE; use option::{Some, None}; use os; use prelude::*; @@ -45,7 +44,6 @@ use to_str; use unstable::finally::Finally; use vec; -pub use libc::fclose; pub use os::consts::*; /// Delegates to the libc close() function, returning the same return value. @@ -56,28 +54,6 @@ pub fn close(fd: c_int) -> c_int { } } -// On Windows, wide character version of function must be used to support -// unicode, so functions should be split into at least two versions, -// which are for Windows and for non-Windows, if necessary. -// See https://github.com/mozilla/rust/issues/9822 for more information. - -mod rustrt { - use libc::{c_char, c_int}; - use libc; - - extern { - pub fn rust_path_is_dir(path: *libc::c_char) -> c_int; - pub fn rust_path_exists(path: *libc::c_char) -> c_int; - } - - // Uses _wstat instead of stat. - #[cfg(windows)] - extern { - pub fn rust_path_is_dir_u16(path: *u16) -> c_int; - pub fn rust_path_exists_u16(path: *u16) -> c_int; - } -} - pub static TMPBUF_SZ : uint = 1000u; static BUF_BYTES : uint = 2048u; @@ -348,15 +324,6 @@ pub fn unsetenv(n: &str) { _unsetenv(n); } -pub fn fdopen(fd: c_int) -> *FILE { - #[fixed_stack_segment]; #[inline(never)]; - do "r".with_c_str |modebuf| { - unsafe { - libc::fdopen(fd, modebuf) - } - } -} - pub struct Pipe { input: c_int, out: c_int @@ -373,8 +340,6 @@ pub fn pipe() -> Pipe { } } - - #[cfg(windows)] pub fn pipe() -> Pipe { #[fixed_stack_segment]; #[inline(never)]; @@ -574,58 +539,6 @@ pub fn tmpdir() -> Path { } } -/// Recursively walk a directory structure -pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool { - let r = list_dir(p); - r.iter().advance(|q| { - let path = &p.join(q); - f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p))) - }) -} - -#[cfg(unix)] -/// Indicates whether a path represents a directory -pub fn path_is_dir(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do p.with_c_str |buf| { - rustrt::rust_path_is_dir(buf) != 0 as c_int - } - } -} - - -#[cfg(windows)] -pub fn path_is_dir(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| { - rustrt::rust_path_is_dir_u16(buf) != 0 as c_int - } - } -} - -#[cfg(unix)] -/// Indicates whether a path exists -pub fn path_exists(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do p.with_c_str |buf| { - rustrt::rust_path_exists(buf) != 0 as c_int - } - } -} - -#[cfg(windows)] -pub fn path_exists(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| { - rustrt::rust_path_exists_u16(buf) != 0 as c_int - } - } -} - /** * Convert a relative path to an absolute path * @@ -646,206 +559,6 @@ pub fn make_absolute(p: &Path) -> Path { } } - -/// Creates a directory at the specified path -pub fn make_dir(p: &Path, mode: c_int) -> bool { - return mkdir(p, mode); - - #[cfg(windows)] - fn mkdir(p: &Path, _mode: c_int) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - use os::win32::as_utf16_p; - // FIXME: turn mode into something useful? #2623 - do as_utf16_p(p.as_str().unwrap()) |buf| { - libc::CreateDirectoryW(buf, ptr::mut_null()) - != (0 as libc::BOOL) - } - } - } - - #[cfg(unix)] - fn mkdir(p: &Path, mode: c_int) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - do p.with_c_str |buf| { - unsafe { - libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int) - } - } - } -} - -/// Creates a directory with a given mode. -/// Returns true iff creation -/// succeeded. Also creates all intermediate subdirectories -/// if they don't already exist, giving all of them the same mode. - -// tjc: if directory exists but with different permissions, -// should we return false? -pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool { - if path_is_dir(p) { - return true; - } - if p.filename().is_some() { - let mut p_ = p.clone(); - p_.pop(); - if !mkdir_recursive(&p_, mode) { - return false; - } - } - return make_dir(p, mode); -} - -/// Lists the contents of a directory -/// -/// Each resulting Path is a relative path with no directory component. -pub fn list_dir(p: &Path) -> ~[Path] { - unsafe { - #[cfg(target_os = "linux")] - #[cfg(target_os = "android")] - #[cfg(target_os = "freebsd")] - #[cfg(target_os = "macos")] - unsafe fn get_list(p: &Path) -> ~[Path] { - #[fixed_stack_segment]; #[inline(never)]; - use libc::{dirent_t}; - use libc::{opendir, readdir, closedir}; - extern { - fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char; - } - let mut paths = ~[]; - debug!("os::list_dir -- BEFORE OPENDIR"); - - let dir_ptr = do p.with_c_str |buf| { - opendir(buf) - }; - - if (dir_ptr as uint != 0) { - debug!("os::list_dir -- opendir() SUCCESS"); - let mut entry_ptr = readdir(dir_ptr); - while (entry_ptr as uint != 0) { - let cstr = CString::new(rust_list_dir_val(entry_ptr), false); - paths.push(Path::new(cstr)); - entry_ptr = readdir(dir_ptr); - } - closedir(dir_ptr); - } - else { - debug!("os::list_dir -- opendir() FAILURE"); - } - debug!("os::list_dir -- AFTER -- \\#: {}", paths.len()); - paths - } - #[cfg(windows)] - unsafe fn get_list(p: &Path) -> ~[Path] { - #[fixed_stack_segment]; #[inline(never)]; - use libc::consts::os::extra::INVALID_HANDLE_VALUE; - use libc::{wcslen, free}; - use libc::funcs::extra::kernel32::{ - FindFirstFileW, - FindNextFileW, - FindClose, - }; - use libc::types::os::arch::extra::HANDLE; - use os::win32::{ - as_utf16_p - }; - use rt::global_heap::malloc_raw; - - #[nolink] - extern { - fn rust_list_dir_wfd_size() -> libc::size_t; - fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16; - } - let star = p.join("*"); - do as_utf16_p(star.as_str().unwrap()) |path_ptr| { - let mut paths = ~[]; - let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint); - let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE); - if find_handle as libc::c_int != INVALID_HANDLE_VALUE { - let mut more_files = 1 as libc::c_int; - while more_files != 0 { - let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr); - if fp_buf as uint == 0 { - fail!("os::list_dir() failure: got null ptr from wfd"); - } - else { - let fp_vec = vec::from_buf( - fp_buf, wcslen(fp_buf) as uint); - let fp_str = str::from_utf16(fp_vec); - paths.push(Path::new(fp_str)); - } - more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE); - } - FindClose(find_handle); - free(wfd_ptr) - } - paths - } - } - do get_list(p).move_iter().filter |path| { - path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..") - }.collect() - } -} - -/** - * Lists the contents of a directory - * - * This version prepends each entry with the directory. - */ -pub fn list_dir_path(p: &Path) -> ~[Path] { - list_dir(p).map(|f| p.join(f)) -} - -/// Removes a directory at the specified path, after removing -/// all its contents. Use carefully! -pub fn remove_dir_recursive(p: &Path) -> bool { - let mut error_happened = false; - do walk_dir(p) |inner| { - if !error_happened { - if path_is_dir(inner) { - if !remove_dir_recursive(inner) { - error_happened = true; - } - } - else { - if !remove_file(inner) { - error_happened = true; - } - } - } - true - }; - // Directory should now be empty - !error_happened && remove_dir(p) -} - -/// Removes a directory at the specified path -pub fn remove_dir(p: &Path) -> bool { - return rmdir(p); - - #[cfg(windows)] - fn rmdir(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - use os::win32::as_utf16_p; - return do as_utf16_p(p.as_str().unwrap()) |buf| { - libc::RemoveDirectoryW(buf) != (0 as libc::BOOL) - }; - } - } - - #[cfg(unix)] - fn rmdir(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - do p.with_c_str |buf| { - unsafe { - libc::rmdir(buf) == (0 as c_int) - } - } - } -} - /// Changes the current working directory to the specified path, returning /// whether the change was completed successfully or not. pub fn change_dir(p: &Path) -> bool { @@ -873,121 +586,6 @@ pub fn change_dir(p: &Path) -> bool { } } -/// Copies a file from one location to another -pub fn copy_file(from: &Path, to: &Path) -> bool { - return do_copy_file(from, to); - - #[cfg(windows)] - fn do_copy_file(from: &Path, to: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - use os::win32::as_utf16_p; - return do as_utf16_p(from.as_str().unwrap()) |fromp| { - do as_utf16_p(to.as_str().unwrap()) |top| { - libc::CopyFileW(fromp, top, (0 as libc::BOOL)) != - (0 as libc::BOOL) - } - } - } - } - - #[cfg(unix)] - fn do_copy_file(from: &Path, to: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - let istream = do from.with_c_str |fromp| { - do "rb".with_c_str |modebuf| { - libc::fopen(fromp, modebuf) - } - }; - if istream as uint == 0u { - return false; - } - // Preserve permissions - let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \ - for source file"); - - let ostream = do to.with_c_str |top| { - do "w+b".with_c_str |modebuf| { - libc::fopen(top, modebuf) - } - }; - if ostream as uint == 0u { - fclose(istream); - return false; - } - let bufsize = 8192u; - let mut buf = vec::with_capacity::(bufsize); - let mut done = false; - let mut ok = true; - while !done { - do buf.as_mut_buf |b, _sz| { - let nread = libc::fread(b as *mut c_void, 1u as size_t, - bufsize as size_t, - istream); - if nread > 0 as size_t { - if libc::fwrite(b as *c_void, 1u as size_t, nread, - ostream) != nread { - ok = false; - done = true; - } - } else { - done = true; - } - } - } - fclose(istream); - fclose(ostream); - - // Give the new file the old file's permissions - if do to.with_c_str |to_buf| { - libc::chmod(to_buf, from_mode as libc::mode_t) - } != 0 { - return false; // should be a condition... - } - return ok; - } - } -} - -/// Deletes an existing file -pub fn remove_file(p: &Path) -> bool { - return unlink(p); - - #[cfg(windows)] - fn unlink(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - use os::win32::as_utf16_p; - return do as_utf16_p(p.as_str().unwrap()) |buf| { - libc::DeleteFileW(buf) != (0 as libc::BOOL) - }; - } - } - - #[cfg(unix)] - fn unlink(p: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do p.with_c_str |buf| { - libc::unlink(buf) == (0 as c_int) - } - } - } -} - -/// Renames an existing file or directory -pub fn rename_file(old: &Path, new: &Path) -> bool { - #[fixed_stack_segment]; #[inline(never)]; - unsafe { - do old.with_c_str |old_buf| { - do new.with_c_str |new_buf| { - libc::rename(old_buf, new_buf) == (0 as c_int) - } - } - } -} - #[cfg(unix)] /// Returns the platform-specific value of errno pub fn errno() -> int { @@ -1707,19 +1305,15 @@ pub mod consts { #[cfg(test)] mod tests { use c_str::ToCStr; - use libc::{c_int, c_void, size_t}; - use libc; use option::Some; use option; use os::{env, getcwd, getenv, make_absolute, args}; - use os::{remove_file, setenv, unsetenv}; + use os::{setenv, unsetenv}; use os; use path::Path; use rand::Rng; use rand; - use run; use str::StrSlice; - use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; #[test] @@ -1875,144 +1469,6 @@ mod tests { for s in olduserprofile.iter() { setenv("USERPROFILE", *s) } } - #[test] - fn tmpdir() { - let p = os::tmpdir(); - let s = p.as_str(); - assert!(s.is_some() && s.unwrap() != "."); - } - - // Issue #712 - #[test] - fn test_list_dir_no_invalid_memory_access() { - os::list_dir(&Path::new(".")); - } - - #[test] - fn list_dir() { - let dirs = os::list_dir(&Path::new(".")); - // Just assuming that we've got some contents in the current directory - assert!(dirs.len() > 0u); - - for dir in dirs.iter() { - debug!("{:?}", (*dir).clone()); - } - } - - #[test] - #[cfg(not(windows))] - fn list_dir_root() { - let dirs = os::list_dir(&Path::new("/")); - assert!(dirs.len() > 1); - } - #[test] - #[cfg(windows)] - fn list_dir_root() { - let dirs = os::list_dir(&Path::new("C:\\")); - assert!(dirs.len() > 1); - } - - - #[test] - fn path_is_dir() { - use rt::io::file::open; - use rt::io::{OpenOrCreate, Read}; - - assert!((os::path_is_dir(&Path::new(".")))); - assert!((!os::path_is_dir(&Path::new("test/stdtest/fs.rs")))); - - let mut dirpath = os::tmpdir(); - dirpath.push(format!("rust-test-{}/test-\uac00\u4e00\u30fc\u4f60\u597d", - rand::random::())); // 가一ー你好 - debug!("path_is_dir dirpath: {}", dirpath.display()); - - let mkdir_result = os::mkdir_recursive(&dirpath, (S_IRUSR | S_IWUSR | S_IXUSR) as i32); - debug!("path_is_dir mkdir_result: {}", mkdir_result); - - assert!((os::path_is_dir(&dirpath))); - - let mut filepath = dirpath; - filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs"); - debug!("path_is_dir filepath: {}", filepath.display()); - - open(&filepath, OpenOrCreate, Read); // ignore return; touch only - assert!((!os::path_is_dir(&filepath))); - - assert!((!os::path_is_dir(&Path::new( - "test/unicode-bogus-dir-\uac00\u4e00\u30fc\u4f60\u597d")))); - } - - #[test] - fn path_exists() { - assert!((os::path_exists(&Path::new(".")))); - assert!((!os::path_exists(&Path::new( - "test/nonexistent-bogus-path")))); - - let mut dirpath = os::tmpdir(); - dirpath.push(format!("rust-test-{}/test-\uac01\u4e01\u30fc\u518d\u89c1", - rand::random::())); // 각丁ー再见 - - os::mkdir_recursive(&dirpath, (S_IRUSR | S_IWUSR | S_IXUSR) as i32); - assert!((os::path_exists(&dirpath))); - assert!((!os::path_exists(&Path::new( - "test/unicode-bogus-path-\uac01\u4e01\u30fc\u518d\u89c1")))); - } - - #[test] - fn copy_file_does_not_exist() { - assert!(!os::copy_file(&Path::new("test/nonexistent-bogus-path"), - &Path::new("test/other-bogus-path"))); - assert!(!os::path_exists(&Path::new("test/other-bogus-path"))); - } - - #[test] - fn copy_file_ok() { - #[fixed_stack_segment]; #[inline(never)]; - - unsafe { - let tempdir = getcwd(); // would like to use $TMPDIR, - // doesn't seem to work on Linux - let input = tempdir.join("in.txt"); - let out = tempdir.join("out.txt"); - - /* Write the temp input file */ - let ostream = do input.with_c_str |fromp| { - do "w+b".with_c_str |modebuf| { - libc::fopen(fromp, modebuf) - } - }; - assert!((ostream as uint != 0u)); - let s = ~"hello"; - do "hello".with_c_str |buf| { - let write_len = libc::fwrite(buf as *c_void, - 1u as size_t, - (s.len() + 1u) as size_t, - ostream); - assert_eq!(write_len, (s.len() + 1) as size_t) - } - assert_eq!(libc::fclose(ostream), (0u as c_int)); - let in_mode = input.get_mode(); - let rs = os::copy_file(&input, &out); - if (!os::path_exists(&input)) { - fail!("{} doesn't exist", input.display()); - } - assert!((rs)); - // FIXME (#9639): This needs to handle non-utf8 paths - let rslt = run::process_status("diff", [input.as_str().unwrap().to_owned(), - out.as_str().unwrap().to_owned()]); - assert_eq!(rslt, 0); - assert_eq!(out.get_mode(), in_mode); - assert!((remove_file(&input))); - assert!((remove_file(&out))); - } - } - - #[test] - fn recursive_mkdir_slash() { - let path = Path::new("/"); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - } - #[test] fn memory_map_rw() { use result::{Ok, Err}; @@ -2039,6 +1495,7 @@ mod tests { use result::{Ok, Err}; use os::*; use libc::*; + use rt::io::file; #[cfg(unix)] #[fixed_stack_segment] @@ -2060,7 +1517,6 @@ mod tests { let mut path = tmpdir(); path.push("mmap_file.tmp"); let size = MemoryMap::granularity() * 2; - remove_file(&path); let fd = unsafe { let fd = do path.with_c_str |path| { @@ -2088,6 +1544,7 @@ mod tests { assert!(*chunk.data == 0xbe); close(fd); } + file::unlink(&path); } // More recursive_mkdir tests are in extra::tempfile diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index d92c2974f76..f14f100de73 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -24,9 +24,6 @@ use vec; use vec::{CopyableVector, RSplitIterator, SplitIterator, Vector, VectorVector}; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; -#[cfg(not(target_os = "win32"))] -use rt::io::{FileStat, file, io_error}; - /// Iterator that yields successive components of a Path as &[u8] pub type ComponentIter<'self> = SplitIterator<'self, u8>; /// Iterator that yields components of a Path in reverse as &[u8] @@ -442,72 +439,6 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<~[&'a [u8]]> { static dot_static: &'static [u8] = bytes!("."); static dot_dot_static: &'static [u8] = bytes!(".."); -// Stat support -#[cfg(not(target_os = "win32"))] -impl Path { - /// Calls stat() on the represented file and returns the resulting rt::io::FileStat - pub fn stat(&self) -> Option { - let mut file_stat: Option = 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 { - match self.stat() { - None => None, - Some(st) => Some(st.size) - } - } - - /// Returns the mode of the represented file - pub fn get_mode(&self) -> Option { - match self.stat() { - None => None, - Some(st) => Some(st.mode as uint) - } - } -} - -#[cfg(target_os = "freebsd")] -#[cfg(target_os = "linux")] -#[cfg(target_os = "macos")] -impl Path { - /// Returns the atime of the represented file, as msecs - pub fn get_atime(&self) -> Option { - 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 { - 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 { - match self.stat() { - None => None, - Some(st) => Some(st.created) - } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 5ed8d6b10d1..c9499bb4aa8 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -13,11 +13,12 @@ use rand::Rng; use ops::Drop; +use path::Path; #[cfg(unix)] use rand::reader::ReaderRng; #[cfg(unix)] -use rt::io::{file, Open, Read}; +use rt::io::file; #[cfg(windows)] use cast; @@ -40,7 +41,7 @@ type HCRYPTPROV = c_long; /// This does not block. #[cfg(unix)] pub struct OSRng { - priv inner: ReaderRng + priv inner: ReaderRng } /// A random number generator that retrieves randomness straight from /// the operating system. Platform sources: @@ -60,7 +61,8 @@ impl OSRng { /// Create a new `OSRng`. #[cfg(unix)] pub fn new() -> OSRng { - let reader = file::open(& &"/dev/urandom", Open, Read).expect("Error opening /dev/urandom"); + let reader = file::open(&Path::new("/dev/urandom")); + let reader = reader.expect("Error opening /dev/urandom"); let reader_rng = ReaderRng::new(reader); OSRng { inner: reader_rng } diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs index 99a4a709504..b6c0b58434f 100644 --- a/src/libstd/rt/io/file.rs +++ b/src/libstd/rt/io/file.rs @@ -13,50 +13,43 @@ This module provides a set of functions and traits for working with regular files & directories on a filesystem. -At the top-level of the module are a set of freestanding functions, -associated with various filesystem operations. They all operate -on a `ToCStr` object. This trait is already defined for common -objects such as strings and `Path` instances. +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 block the task during execution. Most will raise `std::rt::io::io_error` conditions in the event of failure. -Also included in this module are the `FileInfo` and `DirectoryInfo` traits. When -`use`'d alongside a value whose type implements them (A `std::path::Path` impl is -a part of this module), they expose a set of functions for operations against -a given file location, depending on whether the path already exists. Whenever -possible, the `{FileInfo, DirectoryInfo}` preserve the same semantics as their -free function counterparts. +Also included in this module is an implementation block on the `Path` object +defined in `std::path::Path`. The impl adds useful methods about inspecting the +metadata of a file. This includes getting the `stat` information, reading off +particular bits of it, etc. + */ -use prelude::*; use c_str::ToCStr; use super::{Reader, Writer, Seek}; -use super::{SeekStyle, Read, Write}; +use super::{SeekStyle, Read, Write, Open, CreateOrTruncate, + FileMode, FileAccess, FileStat, io_error, FilePermission}; use rt::rtio::{RtioFileStream, IoFactory, with_local_io}; -use rt::io::{io_error, EndOfFile, - FileMode, FileAccess, FileStat, IoError, - PathAlreadyExists, PathDoesntExist, - MismatchedFileTypeForOperation, ignore_io_error}; -use option::{Some, None}; -use path::Path; +use rt::io; +use option::{Some, None, Option}; +use result::{Ok, Err}; +use path; +use path::{Path, GenericPath}; /// Open a file for reading/writing, as indicated by `path`. /// /// # Example /// -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::open; -/// use std::rt::io::{FileMode, FileAccess}; +/// use std::rt::{io, file, io_error}; /// -/// let p = &Path("/some/file/path.txt"); +/// let p = Path::new("/some/file/path.txt"); /// /// do io_error::cond.trap(|_| { /// // hoo-boy... /// }).inside { -/// let stream = match open(p, Create, ReadWrite) { +/// let stream = match file::open_stream(&p, io::Create, io::ReadWrite) { /// Some(s) => s, /// None => fail!("whoops! I'm sure this raised, anyways..") /// }; @@ -72,24 +65,23 @@ use path::Path; /// /// 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_reader, open_writer}` methods that are a part of `FileInfo` +/// `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`. /// /// # Errors /// -/// This function will raise an `io_error` condition under a number of different circumstances, -/// to include but not limited to: +/// This function will raise an `io_error` condition under a number of different +/// circumstances, to include but not limited to: /// -/// * 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 +/// * 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(path: &P, - mode: FileMode, - access: FileAccess - ) -> Option { +pub fn open_stream(path: &Path, + mode: FileMode, + access: FileAccess) -> Option { do with_local_io |io| { match io.fs_open(&path.to_c_str(), mode, access) { Ok(fd) => Some(FileStream { @@ -104,16 +96,32 @@ pub fn open(path: &P, } } +/// 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 { + open_stream(path, Open, Read).map(|s| FileReader { stream: s }) +} + +/// 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 { + open_stream(path, CreateOrTruncate, Write).map(|s| FileWriter { stream: s }) +} + /// Unlink a file from the underlying filesystem. /// /// # Example /// -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::unlink; +/// use std::rt::io::file; /// -/// let p = &Path("/some/file/path.txt"); -/// unlink(p); +/// let p = Path::new("/some/file/path.txt"); +/// file::unlink(&p); /// // if we made it here without failing, then the /// // unlink operation was successful /// @@ -123,12 +131,13 @@ pub fn open(path: &P, /// /// # Errors /// -/// This function will raise an `io_error` condition if the user lacks permissions to -/// remove the file or if some other filesystem-level error occurs -pub fn unlink(path: &P) { +/// 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(()), + Ok(()) => Some(()), Err(ioerr) => { io_error::cond.raise(ioerr); None @@ -141,21 +150,21 @@ pub fn unlink(path: &P) { /// /// # Example /// -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::mkdir; +/// use std::libc::S_IRWXU; +/// use std::rt::io::file; /// -/// let p = &Path("/some/dir"); -/// mkdir(p); +/// let p = Path::new("/some/dir"); +/// file::mkdir(&p, S_IRWXU as int); /// // If we got here, our directory exists! Horray! /// /// # Errors /// -/// This call will raise an `io_error` condition if the user lacks permissions to make a -/// new directory at the provided path, or if the directory already exists -pub fn mkdir(path: &P) { +/// This call will raise an `io_error` condition if the user lacks permissions +/// to make a new directory at the provided path, or if the directory already +/// exists. +pub fn mkdir(path: &Path, mode: FilePermission) { do with_local_io |io| { - match io.fs_mkdir(&path.to_c_str()) { + match io.fs_mkdir(&path.to_c_str(), mode) { Ok(_) => Some(()), Err(ioerr) => { io_error::cond.raise(ioerr); @@ -169,19 +178,18 @@ pub fn mkdir(path: &P) { /// /// # Example /// -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::rmdir; +/// use std::rt::io::file; /// -/// let p = &Path("/some/dir"); -/// rmdir(p); +/// let p = Path::new("/some/dir"); +/// file::rmdir(&p); /// // good riddance, you mean ol' directory /// /// # Errors /// -/// This call will raise an `io_error` condition if the user lacks permissions to remove the -/// directory at the provided path, or if the directory isn't empty -pub fn rmdir(path: &P) { +/// This call will raise an `io_error` condition if the user lacks permissions +/// to remove the directory at the provided path, or if the directory isn't +/// empty. +pub fn rmdir(path: &Path) { do with_local_io |io| { match io.fs_rmdir(&path.to_c_str()) { Ok(_) => Some(()), @@ -198,37 +206,31 @@ pub fn rmdir(path: &P) { /// Given a path, query the file system to get information about a file, /// directory, etc. /// -/// Returns a `Some(std::rt::io::PathInfo)` on success +/// 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; -/// use std::path::Path; -/// use std::rt::io::file::stat; +/// use std::rt::io::{file, io_error}; /// -/// let p = &Path("/some/file/path.txt"); +/// let p = Path::new("/some/file/path.txt"); /// /// do io_error::cond.trap(|_| { /// // hoo-boy... /// }).inside { -/// let info = match stat(p) { -/// Some(s) => s, -/// None => fail!("whoops! I'm sure this raised, anyways.."); -/// } -/// if stat.is_file { +/// let info = file::stat(p); +/// if info.is_file { /// // just imagine the possibilities ... /// } -/// -/// // the file stream will be closed at the end of this block /// } -/// // .. /// /// # 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: &P) -> Option { +pub fn stat(path: &Path) -> FileStat { do with_local_io |io| { match io.fs_stat(&path.to_c_str()) { Ok(p) => Some(p), @@ -237,20 +239,31 @@ pub fn stat(path: &P) -> Option { 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 /// -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::readdir; +/// use std::rt::io::file; /// /// fn visit_dirs(dir: &Path, cb: &fn(&Path)) { /// if dir.is_dir() { -/// let contents = dir.readdir(); +/// let contents = file::readdir(dir).unwrap(); /// for entry in contents.iter() { /// if entry.is_dir() { visit_dirs(entry, cb); } /// else { cb(entry); } @@ -261,10 +274,10 @@ pub fn stat(path: &P) -> Option { /// /// # Errors /// -/// Will raise an `io_error` condition if the provided `path` doesn't exist, +/// Will raise an `io_error` condition if the provided `from` doesn't exist, /// the process lacks permissions to view the contents or if the `path` points /// at a non-directory file -pub fn readdir(path: &P) -> Option<~[Path]> { +pub fn readdir(path: &Path) -> ~[Path] { do with_local_io |io| { match io.fs_readdir(&path.to_c_str(), 0) { Ok(p) => Some(p), @@ -273,66 +286,169 @@ pub fn readdir(path: &P) -> Option<~[Path]> { None } } - } + }.unwrap_or_else(|| ~[]) } -/// Constrained version of `FileStream` that only exposes read-specific operations. +/// Rename a file or directory to a new name. /// -/// Can be retreived via `FileInfo.open_reader()`. +/// # 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 + } + } + }; +} + +/// 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); +} + +// 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 + } + } + }; +} + +/// 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 +/// +/// This function will raise on the `io_error` condition if an error +/// happens, see `file::mkdir` for more information about error conditions +/// and performance. +pub fn mkdir_recursive(path: &Path, mode: FilePermission) { + // tjc: if directory exists but with different permissions, + // should we return false? + if path.is_dir() { + return + } + if path.filename().is_some() { + mkdir_recursive(&path.dir_path(), mode); + } + mkdir(path, mode) +} + +/// Removes a directory at this path, after removing all its contents. Use +/// carefully! +/// +/// # Failure +/// +/// 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); + } else { + unlink(inner); + } + 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 } -/// a `std::rt::io::Reader` trait impl for file I/O. impl Reader for FileReader { - fn read(&mut self, buf: &mut [u8]) -> Option { - self.stream.read(buf) - } - - fn eof(&mut self) -> bool { - self.stream.eof() - } + fn read(&mut self, buf: &mut [u8]) -> Option { self.stream.read(buf) } + fn eof(&mut self) -> bool { self.stream.eof() } } -/// a `std::rt::io::Seek` trait impl for file I/O. impl Seek for FileReader { - fn tell(&self) -> u64 { - self.stream.tell() - } - - fn seek(&mut self, pos: i64, style: SeekStyle) { - self.stream.seek(pos, style); - } + 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. +/// Constrained version of `FileStream` that only exposes write-specific +/// operations. /// -/// Can be retreived via `FileInfo.open_writer()`. +/// Can be retreived via `Path.create()` or `file::create`. pub struct FileWriter { priv stream: FileStream } -/// a `std::rt::io::Writer` trait impl for file I/O. impl Writer for FileWriter { - fn write(&mut self, buf: &[u8]) { - self.stream.write(buf); - } - - fn flush(&mut self) { - self.stream.flush(); - } + fn write(&mut self, buf: &[u8]) { self.stream.write(buf); } + fn flush(&mut self) { self.stream.flush(); } } -/// a `std::rt::io::Seek` trait impl for file I/O. impl Seek for FileWriter { - fn tell(&self) -> u64 { - self.stream.tell() - } - - fn seek(&mut self, pos: i64, style: SeekStyle) { - self.stream.seek(pos, style); - } + 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 `FileInfo.open_stream()`. +/// Can be retreived via `file::open()` and `Path.open_stream()`. /// /// # Errors /// @@ -341,13 +457,12 @@ impl Seek for FileWriter { /// time, via the `FileAccess` parameter to `file::open()`. /// /// For this reason, it is best to use the access-constrained wrappers that are -/// exposed via `FileInfo.open_reader()` and `FileInfo.open_writer()`. +/// exposed via `Path.open()` and `Path.create()`. pub struct FileStream { priv fd: ~RtioFileStream, priv last_nread: int, } -/// a `std::rt::io::Reader` trait impl for file I/O. impl Reader for FileStream { fn read(&mut self, buf: &mut [u8]) -> Option { match self.fd.read(buf) { @@ -360,7 +475,7 @@ impl Reader for FileStream { }, Err(ioerr) => { // EOF is indicated by returning None - if ioerr.kind != EndOfFile { + if ioerr.kind != io::EndOfFile { io_error::cond.raise(ioerr); } return None; @@ -368,12 +483,9 @@ impl Reader for FileStream { } } - fn eof(&mut self) -> bool { - self.last_nread == 0 - } + fn eof(&mut self) -> bool { self.last_nread == 0 } } -/// a `std::rt::io::Writer` trait impl for file I/O. impl Writer for FileStream { fn write(&mut self, buf: &[u8]) { match self.fd.write(buf) { @@ -385,7 +497,6 @@ impl Writer for FileStream { } } -/// a `std::rt::io:Seek` trait impl for file I/O. impl Seek for FileStream { fn tell(&self) -> u64 { let res = self.fd.tell(); @@ -412,166 +523,40 @@ impl Seek for FileStream { } } -/// Shared functionality between `FileInfo` and `DirectoryInfo` -pub trait FileSystemInfo { - /// Get the filesystem path that this instance points at, - /// whether it is valid or not. In this way, it can be used to - /// to specify a path of a non-existent file which it - /// later creates - fn get_path<'a>(&'a self) -> &'a Path; - - /// Get information on the file, directory, etc at the provided path +impl path::Path { + /// Get information on the file, directory, etc at this path. /// /// Consult the `file::stat` documentation for more info. /// - /// This call preserves identical runtime/error semantics with `file::stat` - fn stat(&self) -> Option { - stat(self.get_path()) - } + /// This call preserves identical runtime/error semantics with `file::stat`. + pub fn stat(&self) -> FileStat { stat(self) } - /// Boolean value indicator whether the underlying file exists on the filesystem + /// Boolean value indicator whether the underlying file exists on the local + /// filesystem. This will return true if the path points to either a + /// directory or a file. /// /// # Errors /// /// Will not raise a condition - fn exists(&self) -> bool { - match ignore_io_error(|| self.stat()) { - Some(_) => true, - None => false - } + pub fn exists(&self) -> bool { + io::result(|| self.stat()).is_ok() } -} - -/// Represents a file, whose underlying path may or may not be valid -/// -/// # Example -/// -/// * Check if a file exists, reading from it if so -/// -/// ```rust -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::{FileInfo, FileReader}; -/// -/// let f = &Path("/some/file/path.txt"); -/// if f.exists() { -/// let reader = f.open_reader(Open); -/// let mut mem = [0u8, 8*64000]; -/// reader.read(mem); -/// // ... -/// } -/// ``` -/// -/// * Is the given path a file? -/// -/// ```rust -/// let f = get_file_path_from_wherever(); -/// match f.is_file() { -/// true => doing_something_with_a_file(f), -/// _ => {} -/// } -/// ``` -pub trait FileInfo : FileSystemInfo { - /// Whether the underlying implemention (be it a file path, - /// or something else) points at a "regular file" on the FS. Will return - /// false for paths to non-existent locations or directories or - /// other non-regular files (named pipes, etc). + /// Whether the underlying implemention (be it a file path, or something + /// else) points at a "regular file" on the FS. Will return false for paths + /// to non-existent locations or directories or other non-regular files + /// (named pipes, etc). /// /// # Errors /// /// Will not raise a condition - fn is_file(&self) -> bool { - match ignore_io_error(|| self.stat()) { - Some(s) => s.is_file, - None => false + pub fn is_file(&self) -> bool { + match io::result(|| self.stat()) { + Ok(s) => s.is_file, + Err(*) => false } } - /// Attempts to open a regular file for reading/writing based - /// on provided inputs - /// - /// See `file::open` for more information on runtime semantics and error conditions - fn open_stream(&self, mode: FileMode, access: FileAccess) -> Option { - match ignore_io_error(|| self.stat()) { - Some(s) => match s.is_file { - true => open(self.get_path(), mode, access), - false => None - }, - None => open(self.get_path(), mode, access) - } - } - - /// Attempts to open a regular file in read-only mode, based - /// on provided inputs - /// - /// See `file::open` for more information on runtime semantics and error conditions - fn open_reader(&self, mode: FileMode) -> Option { - match self.open_stream(mode, Read) { - Some(s) => Some(FileReader { stream: s}), - None => None - } - } - - /// Attempts to open a regular file in write-only mode, based - /// on provided inputs - /// - /// See `file::open` for more information on runtime semantics and error conditions - fn open_writer(&self, mode: FileMode) -> Option { - match self.open_stream(mode, Write) { - Some(s) => Some(FileWriter { stream: s}), - None => None - } - } - - /// Attempt to remove a file from the filesystem - /// - /// See `file::unlink` for more information on runtime semantics and error conditions - fn unlink(&self) { - unlink(self.get_path()); - } -} - -/// `FileSystemInfo` implementation for `Path`s -impl FileSystemInfo for Path { - fn get_path<'a>(&'a self) -> &'a Path { self } -} - -/// `FileInfo` implementation for `Path`s -impl FileInfo for Path { } - -/// Represents a directory, whose underlying path may or may not be valid -/// -/// # Example -/// -/// * Check if a directory exists, `mkdir`'ing it if not -/// -/// ```rust -/// use std; -/// use std::path::Path; -/// use std::rt::io::file::{DirectoryInfo}; -/// -/// let dir = &Path("/some/dir"); -/// if !dir.exists() { -/// dir.mkdir(); -/// } -/// ``` -/// -/// * Is the given path a directory? If so, iterate on its contents -/// -/// ```rust -/// fn visit_dirs(dir: &Path, cb: &fn(&Path)) { -/// if dir.is_dir() { -/// let contents = dir.readdir(); -/// for entry in contents.iter() { -/// if entry.is_dir() { visit_dirs(entry, cb); } -/// else { cb(entry); } -/// } -/// } -/// else { fail!("nope"); } -/// } -/// ``` -pub trait DirectoryInfo : FileSystemInfo { /// Whether the underlying implemention (be it a file path, /// or something else) is pointing at a directory in the underlying FS. /// Will return false for paths to non-existent locations or if the item is @@ -580,109 +565,50 @@ pub trait DirectoryInfo : FileSystemInfo { /// # Errors /// /// Will not raise a condition - fn is_dir(&self) -> bool { - match ignore_io_error(|| self.stat()) { - Some(s) => s.is_dir, - None => false + pub fn is_dir(&self) -> bool { + match io::result(|| self.stat()) { + Ok(s) => s.is_dir, + Err(*) => false } } - - /// Create a directory at the location pointed to by the - /// type underlying the given `DirectoryInfo`. - /// - /// # Errors - /// - /// This method will raise a `PathAlreadyExists` kind of `io_error` condition - /// if the provided path exists - /// - /// See `file::mkdir` for more information on runtime semantics and error conditions - fn mkdir(&self) { - match ignore_io_error(|| self.stat()) { - Some(_) => { - let path = self.get_path(); - io_error::cond.raise(IoError { - kind: PathAlreadyExists, - desc: "Path already exists", - detail: - Some(format!("{} already exists; can't mkdir it", - path.display())) - }) - }, - None => mkdir(self.get_path()) - } - } - - /// Remove a directory at the given location. - /// - /// # Errors - /// - /// This method will raise a `PathDoesntExist` kind of `io_error` condition - /// if the provided path exists. It will raise a `MismatchedFileTypeForOperation` - /// kind of `io_error` condition if the provided path points at any - /// non-directory file type - /// - /// See `file::rmdir` for more information on runtime semantics and error conditions - fn rmdir(&self) { - match ignore_io_error(|| self.stat()) { - Some(s) => { - match s.is_dir { - true => rmdir(self.get_path()), - false => { - let path = self.get_path(); - let ioerr = IoError { - kind: MismatchedFileTypeForOperation, - desc: "Cannot do rmdir() on a non-directory", - detail: Some(format!( - "{} is a non-directory; can't rmdir it", - path.display())) - }; - io_error::cond.raise(ioerr); - } - } - }, - None => { - let path = self.get_path(); - io_error::cond.raise(IoError { - kind: PathDoesntExist, - desc: "Path doesn't exist", - detail: Some(format!("{} doesn't exist; can't rmdir it", - path.display())) - }) - } - } - } - - // Get a collection of all entries at the given - // directory - fn readdir(&self) -> Option<~[Path]> { - readdir(self.get_path()) - } } -/// `DirectoryInfo` impl for `path::Path` -impl DirectoryInfo for Path { } - #[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 rt::io; + use rt::io::Reader; use super::super::{SeekSet, SeekCur, SeekEnd, io_error, Read, Create, Open, ReadWrite}; - use super::super::super::test::*; - use option::{Some, None}; - use path::Path; - use super::*; - use iter::range; + use vec::Vector; + + fn tmpdir() -> Path { + use os; + use rand; + let ret = os::tmpdir().join(format!("rust-{}", rand::random::())); + mkdir(&ret, io::UserRWX); + ret + } + #[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(filename, Create, ReadWrite).unwrap(); + let mut write_stream = open_stream(filename, Create, ReadWrite); write_stream.write(message.as_bytes()); } { use str; - let mut read_stream = open(filename, Open, Read).unwrap(); + 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"), @@ -702,7 +628,7 @@ mod test { do io_error::cond.trap(|_| { called = true; }).inside { - let result = open(filename, Open, Read); + let result = open_stream(filename, Open, Read); assert!(result.is_none()); } assert!(called); @@ -731,11 +657,11 @@ mod test { let mut read_mem = [0, .. 8]; let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt"); { - let mut rw_stream = open(filename, Create, ReadWrite).unwrap(); + let mut rw_stream = open_stream(filename, Create, ReadWrite); rw_stream.write(message.as_bytes()); } { - let mut read_stream = open(filename, Open, Read).unwrap(); + let mut read_stream = open_stream(filename, Open, Read); { let read_buf = read_mem.mut_slice(0, 4); read_stream.read(read_buf); @@ -762,11 +688,11 @@ mod test { let mut tell_pos_post_read; let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt"); { - let mut rw_stream = open(filename, Create, ReadWrite).unwrap(); + let mut rw_stream = open_stream(filename, Create, ReadWrite); rw_stream.write(message.as_bytes()); } { - let mut read_stream = open(filename, Open, Read).unwrap(); + 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); @@ -791,13 +717,13 @@ mod test { 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(filename, Create, ReadWrite).unwrap(); + 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(filename, Open, Read).unwrap(); + let mut read_stream = open_stream(filename, Open, Read); read_stream.read(read_mem); } unlink(filename); @@ -817,11 +743,11 @@ mod test { let mut read_mem = [0, .. 4]; let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt"); { - let mut rw_stream = open(filename, Create, ReadWrite).unwrap(); + let mut rw_stream = open_stream(filename, Create, ReadWrite); rw_stream.write(initial_msg.as_bytes()); } { - let mut read_stream = open(filename, Open, Read).unwrap(); + let mut read_stream = open_stream(filename, Open, Read); read_stream.seek(-4, SeekEnd); read_stream.read(read_mem); @@ -847,14 +773,11 @@ mod test { do run_in_mt_newsched_task { let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt"); { - let mut fs = open(filename, Create, ReadWrite).unwrap(); + let mut fs = open_stream(filename, Create, ReadWrite); let msg = "hw"; fs.write(msg.as_bytes()); } - let stat_res = match stat(filename) { - Some(s) => s, - None => fail!("shouldn't happen") - }; + let stat_res = stat(filename); assert!(stat_res.is_file); unlink(filename); } @@ -864,11 +787,8 @@ mod 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); - let stat_res = match stat(filename) { - Some(s) => s, - None => fail!("shouldn't happen") - }; + mkdir(filename, io::UserRWX); + let stat_res = filename.stat(); assert!(stat_res.is_dir); rmdir(filename); } @@ -878,7 +798,7 @@ mod 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); + mkdir(dir, io::UserRWX); assert!(dir.is_file() == false); rmdir(dir); } @@ -888,13 +808,9 @@ mod 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"); - { - let msg = "foo".as_bytes(); - let mut w = file.open_writer(Create); - w.write(msg); - } + create(file).write(bytes!("foo")); assert!(file.exists()); - file.unlink(); + unlink(file); assert!(!file.exists()); } } @@ -904,10 +820,10 @@ mod test { do run_in_mt_newsched_task { let dir = &Path::new("./tmp/before_and_after_dir"); assert!(!dir.exists()); - dir.mkdir(); + mkdir(dir, io::UserRWX); assert!(dir.exists()); assert!(dir.is_dir()); - dir.rmdir(); + rmdir(dir); assert!(!dir.exists()); } } @@ -917,36 +833,99 @@ mod test { use str; do run_in_mt_newsched_task { let dir = &Path::new("./tmp/di_readdir"); - dir.mkdir(); + mkdir(dir, io::UserRWX); let prefix = "foo"; for n in range(0,3) { let f = dir.join(format!("{}.txt", n)); - let mut w = f.open_writer(Create); + 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); } - match dir.readdir() { - Some(files) => { - let mut mem = [0u8, .. 4]; - for f in files.iter() { - { - let n = f.filestem_str(); - let mut r = f.open_reader(Open); - r.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); - } - f.unlink(); - } - }, - None => fail!("shouldn't happen") + 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); } - dir.rmdir(); + rmdir(dir); } } + + #[test] + fn recursive_mkdir_slash() { + mkdir_recursive(&Path::new("/"), io::UserRWX); + } + + #[test] + fn unicode_path_is_dir() { + assert!(Path::new(".").is_dir()); + assert!(!Path::new("test/stdtest/fs.rs").is_dir()); + + let tmpdir = tmpdir(); + + let mut dirpath = tmpdir.clone(); + dirpath.push(format!("test-가一ー你好")); + mkdir(&dirpath, io::UserRWX); + assert!(dirpath.is_dir()); + + let mut filepath = dirpath; + filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs"); + create(&filepath); // ignore return; touch only + assert!(!filepath.is_dir()); + assert!(filepath.exists()); + + rmdir_recursive(&tmpdir); + } + + #[test] + fn unicode_path_exists() { + assert!(Path::new(".").exists()); + assert!(!Path::new("test/nonexistent-bogus-path").exists()); + + let tmpdir = tmpdir(); + let unicode = tmpdir.clone(); + let unicode = unicode.join(format!("test-각丁ー再见")); + mkdir(&unicode, io::UserRWX); + assert!(unicode.exists()); + assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists()); + rmdir_recursive(&tmpdir); + } + + #[test] + 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)) { + Ok(*) => fail!(), + Err(*) => { + assert!(!from.exists()); + assert!(!to.exists()); + } + } + } + + #[test] + fn copy_file_ok() { + let tmpdir = tmpdir(); + 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(); + assert_eq!(contents.as_slice(), bytes!("hello")); + + assert_eq!(input.stat().mode, out.stat().mode); + rmdir_recursive(&tmpdir); + } } diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs index be205749186..51204ca73b9 100644 --- a/src/libstd/rt/io/mod.rs +++ b/src/libstd/rt/io/mod.rs @@ -244,9 +244,12 @@ Out of scope use cast; use int; +use libc; use path::Path; -use prelude::*; use str::{StrSlice, OwnedStr}; +use option::{Option, Some, None}; +use result::{Ok, Err, Result}; +use iter::Iterator; use to_str::ToStr; use uint; use unstable::finally::Finally; @@ -418,6 +421,18 @@ pub fn ignore_io_error(cb: &fn() -> T) -> T { } } +/// Helper for catching an I/O error and wrapping it in a Result object. The +/// return result will be the last I/O error that happened or the result of the +/// closure if no error occurred. +pub fn result(cb: &fn() -> T) -> Result { + let mut err = None; + let ret = io_error::cond.trap(|e| err = Some(e)).inside(cb); + match err { + Some(e) => Err(e), + None => Ok(ret), + } +} + pub trait Reader { // Only two methods which need to get implemented for this trait @@ -1137,3 +1152,7 @@ pub struct FileStat { /// platform-dependent msecs accessed: u64, } + +// FIXME(#10131): this needs to get designed for real +pub type FilePermission = u32; +pub static UserRWX: FilePermission = libc::S_IRWXU as FilePermission; diff --git a/src/libstd/rt/io/native/file.rs b/src/libstd/rt/io/native/file.rs index 9f9e7dcee9f..e26cc166c8d 100644 --- a/src/libstd/rt/io/native/file.rs +++ b/src/libstd/rt/io/native/file.rs @@ -297,3 +297,486 @@ mod tests { } } } + +// n.b. these functions were all part of the old `std::os` module. There's lots +// of fun little nuances that were taken care of by these functions, but +// they are all thread-blocking versions that are no longer desired (we now +// use a non-blocking event loop implementation backed by libuv). +// +// In theory we will have a thread-blocking version of the event loop (if +// desired), so these functions may just need to get adapted to work in +// those situtations. For now, I'm leaving the code around so it doesn't +// 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(test)] use rand; + + // On Windows, wide character version of function must be used to support + // unicode, so functions should be split into at least two versions, + // which are for Windows and for non-Windows, if necessary. + // See https://github.com/mozilla/rust/issues/9822 for more information. + + mod rustrt { + use libc::{c_char, c_int}; + use libc; + + extern { + pub fn rust_path_is_dir(path: *libc::c_char) -> c_int; + pub fn rust_path_exists(path: *libc::c_char) -> c_int; + } + + // Uses _wstat instead of stat. + #[cfg(windows)] + extern { + pub fn rust_path_is_dir_u16(path: *u16) -> c_int; + pub fn rust_path_exists_u16(path: *u16) -> c_int; + } + } + + /// Recursively walk a directory structure + pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool { + let r = list_dir(p); + r.iter().advance(|q| { + let path = &p.join(q); + f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p))) + }) + } + + #[cfg(unix)] + /// Indicates whether a path represents a directory + pub fn path_is_dir(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do p.with_c_str |buf| { + rustrt::rust_path_is_dir(buf) != 0 as c_int + } + } + } + + + #[cfg(windows)] + pub fn path_is_dir(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| { + rustrt::rust_path_is_dir_u16(buf) != 0 as c_int + } + } + } + + #[cfg(unix)] + /// Indicates whether a path exists + pub fn path_exists(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do p.with_c_str |buf| { + rustrt::rust_path_exists(buf) != 0 as c_int + } + } + } + + #[cfg(windows)] + pub fn path_exists(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| { + rustrt::rust_path_exists_u16(buf) != 0 as c_int + } + } + } + + /// Creates a directory at the specified path + pub fn make_dir(p: &Path, mode: c_int) -> bool { + return mkdir(p, mode); + + #[cfg(windows)] + fn mkdir(p: &Path, _mode: c_int) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + use os::win32::as_utf16_p; + // FIXME: turn mode into something useful? #2623 + do as_utf16_p(p.as_str().unwrap()) |buf| { + libc::CreateDirectoryW(buf, ptr::mut_null()) + != (0 as libc::BOOL) + } + } + } + + #[cfg(unix)] + fn mkdir(p: &Path, mode: c_int) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + do p.with_c_str |buf| { + unsafe { + libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int) + } + } + } + } + + /// Creates a directory with a given mode. + /// Returns true iff creation + /// succeeded. Also creates all intermediate subdirectories + /// if they don't already exist, giving all of them the same mode. + + // tjc: if directory exists but with different permissions, + // should we return false? + pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool { + if path_is_dir(p) { + return true; + } + if p.filename().is_some() { + let mut p_ = p.clone(); + p_.pop(); + if !mkdir_recursive(&p_, mode) { + return false; + } + } + return make_dir(p, mode); + } + + /// Lists the contents of a directory + /// + /// Each resulting Path is a relative path with no directory component. + pub fn list_dir(p: &Path) -> ~[Path] { + unsafe { + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] + #[cfg(target_os = "macos")] + unsafe fn get_list(p: &Path) -> ~[Path] { + #[fixed_stack_segment]; #[inline(never)]; + use libc::{dirent_t}; + use libc::{opendir, readdir, closedir}; + extern { + fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char; + } + let mut paths = ~[]; + debug!("os::list_dir -- BEFORE OPENDIR"); + + let dir_ptr = do p.with_c_str |buf| { + opendir(buf) + }; + + if (dir_ptr as uint != 0) { + debug!("os::list_dir -- opendir() SUCCESS"); + let mut entry_ptr = readdir(dir_ptr); + while (entry_ptr as uint != 0) { + let cstr = CString::new(rust_list_dir_val(entry_ptr), false); + paths.push(Path::new(cstr)); + entry_ptr = readdir(dir_ptr); + } + closedir(dir_ptr); + } + else { + debug!("os::list_dir -- opendir() FAILURE"); + } + debug!("os::list_dir -- AFTER -- \\#: {}", paths.len()); + paths + } + #[cfg(windows)] + unsafe fn get_list(p: &Path) -> ~[Path] { + #[fixed_stack_segment]; #[inline(never)]; + use libc::consts::os::extra::INVALID_HANDLE_VALUE; + use libc::{wcslen, free}; + use libc::funcs::extra::kernel32::{ + FindFirstFileW, + FindNextFileW, + FindClose, + }; + use libc::types::os::arch::extra::HANDLE; + use os::win32::{ + as_utf16_p + }; + use rt::global_heap::malloc_raw; + + #[nolink] + extern { + fn rust_list_dir_wfd_size() -> libc::size_t; + fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16; + } + let star = p.join("*"); + do as_utf16_p(star.as_str().unwrap()) |path_ptr| { + let mut paths = ~[]; + let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint); + let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE); + if find_handle as libc::c_int != INVALID_HANDLE_VALUE { + let mut more_files = 1 as libc::c_int; + while more_files != 0 { + let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr); + if fp_buf as uint == 0 { + fail!("os::list_dir() failure: got null ptr from wfd"); + } + else { + let fp_vec = vec::from_buf( + fp_buf, wcslen(fp_buf) as uint); + let fp_str = str::from_utf16(fp_vec); + paths.push(Path::new(fp_str)); + } + more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE); + } + FindClose(find_handle); + free(wfd_ptr) + } + paths + } + } + do get_list(p).move_iter().filter |path| { + path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..") + }.collect() + } + } + + /// Removes a directory at the specified path, after removing + /// all its contents. Use carefully! + pub fn remove_dir_recursive(p: &Path) -> bool { + let mut error_happened = false; + do walk_dir(p) |inner| { + if !error_happened { + if path_is_dir(inner) { + if !remove_dir_recursive(inner) { + error_happened = true; + } + } + else { + if !remove_file(inner) { + error_happened = true; + } + } + } + true + }; + // Directory should now be empty + !error_happened && remove_dir(p) + } + + /// Removes a directory at the specified path + pub fn remove_dir(p: &Path) -> bool { + return rmdir(p); + + #[cfg(windows)] + fn rmdir(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + use os::win32::as_utf16_p; + return do as_utf16_p(p.as_str().unwrap()) |buf| { + libc::RemoveDirectoryW(buf) != (0 as libc::BOOL) + }; + } + } + + #[cfg(unix)] + fn rmdir(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + do p.with_c_str |buf| { + unsafe { + libc::rmdir(buf) == (0 as c_int) + } + } + } + } + + /// Deletes an existing file + pub fn remove_file(p: &Path) -> bool { + return unlink(p); + + #[cfg(windows)] + fn unlink(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + use os::win32::as_utf16_p; + return do as_utf16_p(p.as_str().unwrap()) |buf| { + libc::DeleteFileW(buf) != (0 as libc::BOOL) + }; + } + } + + #[cfg(unix)] + fn unlink(p: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do p.with_c_str |buf| { + libc::unlink(buf) == (0 as c_int) + } + } + } + } + + /// Renames an existing file or directory + pub fn rename_file(old: &Path, new: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + do old.with_c_str |old_buf| { + do new.with_c_str |new_buf| { + libc::rename(old_buf, new_buf) == (0 as c_int) + } + } + } + } + + /// Copies a file from one location to another + pub fn copy_file(from: &Path, to: &Path) -> bool { + return do_copy_file(from, to); + + #[cfg(windows)] + fn do_copy_file(from: &Path, to: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + use os::win32::as_utf16_p; + return do as_utf16_p(from.as_str().unwrap()) |fromp| { + do as_utf16_p(to.as_str().unwrap()) |top| { + libc::CopyFileW(fromp, top, (0 as libc::BOOL)) != + (0 as libc::BOOL) + } + } + } + } + + #[cfg(unix)] + fn do_copy_file(from: &Path, to: &Path) -> bool { + #[fixed_stack_segment]; #[inline(never)]; + unsafe { + let istream = do from.with_c_str |fromp| { + do "rb".with_c_str |modebuf| { + libc::fopen(fromp, modebuf) + } + }; + if istream as uint == 0u { + return false; + } + // Preserve permissions + let from_mode = from.stat().mode; + + let ostream = do to.with_c_str |top| { + do "w+b".with_c_str |modebuf| { + libc::fopen(top, modebuf) + } + }; + if ostream as uint == 0u { + fclose(istream); + return false; + } + let bufsize = 8192u; + let mut buf = vec::with_capacity::(bufsize); + let mut done = false; + let mut ok = true; + while !done { + do buf.as_mut_buf |b, _sz| { + let nread = libc::fread(b as *mut c_void, 1u as size_t, + bufsize as size_t, + istream); + if nread > 0 as size_t { + if libc::fwrite(b as *c_void, 1u as size_t, nread, + ostream) != nread { + ok = false; + done = true; + } + } else { + done = true; + } + } + } + fclose(istream); + fclose(ostream); + + // Give the new file the old file's permissions + if do to.with_c_str |to_buf| { + libc::chmod(to_buf, from_mode as libc::mode_t) + } != 0 { + return false; // should be a condition... + } + return ok; + } + } + } + + #[test] + fn tmpdir() { + let p = os::tmpdir(); + let s = p.as_str(); + assert!(s.is_some() && s.unwrap() != "."); + } + + // Issue #712 + #[test] + fn test_list_dir_no_invalid_memory_access() { + list_dir(&Path::new(".")); + } + + #[test] + fn test_list_dir() { + let dirs = list_dir(&Path::new(".")); + // Just assuming that we've got some contents in the current directory + assert!(dirs.len() > 0u); + + for dir in dirs.iter() { + debug!("{:?}", (*dir).clone()); + } + } + + #[test] + #[cfg(not(windows))] + fn test_list_dir_root() { + let dirs = list_dir(&Path::new("/")); + assert!(dirs.len() > 1); + } + #[test] + #[cfg(windows)] + fn test_list_dir_root() { + let dirs = list_dir(&Path::new("C:\\")); + assert!(dirs.len() > 1); + } + + #[test] + fn test_path_is_dir() { + use rt::io::file::{open_stream, mkdir_recursive}; + use rt::io::{OpenOrCreate, Read, UserRWX}; + + assert!((path_is_dir(&Path::new(".")))); + assert!((!path_is_dir(&Path::new("test/stdtest/fs.rs")))); + + let mut dirpath = os::tmpdir(); + dirpath.push(format!("rust-test-{}/test-\uac00\u4e00\u30fc\u4f60\u597d", + rand::random::())); // 가一ー你好 + debug!("path_is_dir dirpath: {}", dirpath.display()); + + mkdir_recursive(&dirpath, UserRWX); + + assert!((path_is_dir(&dirpath))); + + let mut filepath = dirpath; + 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 + assert!((!path_is_dir(&filepath))); + + assert!((!path_is_dir(&Path::new( + "test/unicode-bogus-dir-\uac00\u4e00\u30fc\u4f60\u597d")))); + } + + #[test] + fn test_path_exists() { + use rt::io::file::mkdir_recursive; + use rt::io::UserRWX; + + assert!((path_exists(&Path::new(".")))); + assert!((!path_exists(&Path::new( + "test/nonexistent-bogus-path")))); + + let mut dirpath = os::tmpdir(); + dirpath.push(format!("rust-test-{}/test-\uac01\u4e01\u30fc\u518d\u89c1", + rand::random::())); // 각丁ー再见 + + mkdir_recursive(&dirpath, UserRWX); + assert!((path_exists(&dirpath))); + assert!((!path_exists(&Path::new( + "test/unicode-bogus-path-\uac01\u4e01\u30fc\u518d\u89c1")))); + } +} diff --git a/src/libstd/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs index f30423812ba..dd8a999c6de 100644 --- a/src/libstd/rt/io/net/unix.rs +++ b/src/libstd/rt/io/net/unix.rs @@ -156,7 +156,6 @@ mod tests { use rt::test::*; use rt::io::*; use rt::comm::oneshot; - use os; fn smalltest(server: ~fn(UnixStream), client: ~fn(UnixStream)) { let server = Cell::new(server); @@ -290,7 +289,7 @@ mod tests { do run_in_mt_newsched_task { let path = next_test_unix(); let _acceptor = UnixListener::bind(&path).listen(); - assert!(os::path_exists(&path)); + assert!(path.exists()); } } } diff --git a/src/libstd/rt/io/signal.rs b/src/libstd/rt/io/signal.rs index b782d713950..1b856ab0755 100644 --- a/src/libstd/rt/io/signal.rs +++ b/src/libstd/rt/io/signal.rs @@ -19,6 +19,7 @@ definitions for a number of signals. */ +use container::{Map, MutableMap}; use comm::{Port, SharedChan, stream}; use hashmap; use option::{Some, None}; @@ -146,10 +147,10 @@ impl Listener { #[cfg(test)] mod test { - use super::*; - use libc; use rt::io::timer; + use super::{Listener, Interrupt}; + use comm::{GenericPort, Peekable}; // kill is only available on Unixes #[cfg(unix)] @@ -207,7 +208,7 @@ mod test { #[cfg(windows)] #[test] fn test_io_signal_invalid_signum() { - use rt::io; + use super::User1; let mut s = Listener::new(); let mut called = false; do io::io_error::cond.trap(|_| { diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs index 500cd91b3db..36092dfbe34 100644 --- a/src/libstd/rt/io/timer.rs +++ b/src/libstd/rt/io/timer.rs @@ -108,6 +108,7 @@ impl Timer { #[cfg(test)] mod test { + use prelude::*; use super::*; use rt::test::*; use cell::Cell; diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 44d9f59c410..a0db1f1df00 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -22,7 +22,7 @@ use super::io::process::ProcessConfig; use super::io::net::ip::{IpAddr, SocketAddr}; use path::Path; use super::io::{SeekStyle}; -use super::io::{FileMode, FileAccess, FileStat}; +use super::io::{FileMode, FileAccess, FileStat, FilePermission}; pub trait EventLoop { fn run(&mut self); @@ -102,7 +102,10 @@ pub trait IoFactory { -> Result<~RtioFileStream, IoError>; fn fs_unlink(&mut self, path: &CString) -> Result<(), IoError>; fn fs_stat(&mut self, path: &CString) -> Result; - fn fs_mkdir(&mut self, path: &CString, mode: int) -> Result<(), IoError>; + fn fs_mkdir(&mut self, path: &CString, + mode: FilePermission) -> Result<(), IoError>; + fn fs_chmod(&mut self, path: &CString, + mode: FilePermission) -> Result<(), IoError>; fn fs_rmdir(&mut self, path: &CString) -> Result<(), IoError>; fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError>; fn fs_readdir(&mut self, path: &CString, flags: c_int) -> diff --git a/src/libstd/run.rs b/src/libstd/run.rs index 9e6fdf2ba4c..89784acec8e 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -604,8 +604,8 @@ mod tests { let parent_dir = os::getcwd(); let child_dir = Path::new(output.trim()); - let parent_stat = parent_dir.stat().unwrap(); - let child_stat = child_dir.stat().unwrap(); + let parent_stat = parent_dir.stat(); + let child_stat = child_dir.stat(); assert_eq!(parent_stat.device, child_stat.device); assert_eq!(parent_stat.inode, child_stat.inode); @@ -621,8 +621,8 @@ mod tests { let output = str::from_utf8(prog.finish_with_output().output); let child_dir = Path::new(output.trim()); - let parent_stat = parent_dir.stat().unwrap(); - let child_stat = child_dir.stat().unwrap(); + let parent_stat = parent_dir.stat(); + let child_stat = child_dir.stat(); assert_eq!(parent_stat.device, child_stat.device); assert_eq!(parent_stat.inode, child_stat.inode); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index fda6f782af4..876adf40186 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -21,7 +21,7 @@ use print::pprust; use std::rt::io; use std::rt::io::Reader; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use std::str; // These macros all relate to the file system; they either return @@ -92,17 +92,13 @@ 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 mut error = None; - let bytes = do io::io_error::cond.trap(|e| error = Some(e)).inside { - file.open_reader(io::Open).read_to_end() - }; - match error { - Some(e) => { + 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)); } - None => {} - } + Ok(bytes) => bytes, + }; match str::from_utf8_owned_opt(bytes) { Some(s) => base::MRExpr(cx.expr_str(sp, s.to_managed())), None => { @@ -118,17 +114,12 @@ 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)); - - let mut error = None; - let bytes = do io::io_error::cond.trap(|e| error = Some(e)).inside { - file.open_reader(io::Open).read_to_end() - }; - match error { - Some(e) => { + match io::result(|| file::open(&file).read_to_end()) { + Err(e) => { cx.span_fatal(sp, format!("couldn't read {}: {}", file.display(), e.desc)); } - None => { + Ok(bytes) => { let bytes = at_vec::to_managed_move(bytes); base::MRExpr(cx.expr_lit(sp, ast::lit_binary(bytes))) } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 003bc006ebe..cd1be9a3c16 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -21,8 +21,7 @@ use parse::parser::Parser; use std::path::Path; use std::rt::io; -use std::rt::io::Reader; -use std::rt::io::file::FileInfo; +use std::rt::io::file; use std::str; pub mod lexer; @@ -269,16 +268,13 @@ pub fn file_to_filemap(sess: @mut ParseSess, path: &Path, spanopt: Option) None => sess.span_diagnostic.handler().fatal(msg), } }; - let mut error = None; - let bytes = do io::io_error::cond.trap(|e| error = Some(e)).inside { - path.open_reader(io::Open).read_to_end() - }; - match error { - Some(e) => { + 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)); + unreachable!() } - None => {} - } + }; match str::from_utf8_owned_opt(bytes) { Some(s) => { return string_to_filemap(sess, s.to_managed(), diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 70602100f2e..2b63325f931 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -597,6 +597,10 @@ rust_uv_fs_rename(uv_loop_t *loop, uv_fs_t* req, const char *path, const char *to, uv_fs_cb cb) { return uv_fs_rename(loop, req, path, to, cb); } +extern "C" int +rust_uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) { + return uv_fs_chmod(loop, req, path, mode, cb); +} extern "C" int rust_uv_spawn(uv_loop_t *loop, uv_process_t *p, uv_process_options_t options) { diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index dbd1edffe78..531f01c1995 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -21,6 +21,7 @@ use std::rand; use std::str; use std::util; use std::vec; +use std::rt::io::file; macro_rules! bench ( ($argv:expr, $id:ident) => (maybe_run_test($argv, stringify!($id).to_owned(), $id)) @@ -69,15 +70,13 @@ fn shift_push() { } fn read_line() { - use std::rt::io::{Reader, Open}; - use std::rt::io::file::FileInfo; use std::rt::io::buffered::BufferedReader; let mut path = Path::new(env!("CFG_SRC_DIR")); path.push("src/test/bench/shootout-k-nucleotide.data"); for _ in range(0, 3) { - let mut reader = BufferedReader::new(path.open_reader(Open).unwrap()); + let mut reader = BufferedReader::new(file::open(&path).unwrap()); while !reader.eof() { reader.read_line(); } diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 52f068b8b1c..7d3fa6104e5 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -19,6 +19,7 @@ extern mod extra; use std::int; use std::rt::io; +use std::rt::io::file; use std::os; use std::rand::Rng; use std::rand; @@ -111,7 +112,6 @@ fn acid(ch: char, prob: u32) -> AminoAcids { } fn main() { - use std::rt::io::file::FileInfo; let args = os::args(); let args = if os::getenv("RUST_BENCH").is_some() { // alioth tests k-nucleotide with this data at 25,000,000 @@ -123,7 +123,7 @@ fn main() { }; let writer = if os::getenv("RUST_BENCH").is_some() { - let file = Path::new("./shootout-fasta.data").open_writer(io::CreateOrTruncate); + let file = file::create(&Path::new("./shootout-fasta.data")); @mut file as @mut io::Writer } else { @mut io::stdout() as @mut io::Writer diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index c39c3275367..c7c8e3a19a6 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -9,6 +9,7 @@ // except according to those terms. // xfail-pretty +// xfail-test extern mod extra; extern mod syntax; diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 62ce4e7c02c..2e426c0413e 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test + +#[feature(managed_boxes)]; + extern mod syntax; use syntax::ext::base::ExtCtxt; @@ -16,11 +20,11 @@ fn syntax_extension(cx: @ExtCtxt) { let e_toks : ~[syntax::ast::token_tree] = quote_tokens!(cx, 1 + 2); let p_toks : ~[syntax::ast::token_tree] = quote_tokens!(cx, (x, 1 .. 4, *)); - let a: @syntax::ast::expr = quote_expr!(cx, 1 + 2); + let a: @syntax::ast::Expr = quote_expr!(cx, 1 + 2); let _b: Option<@syntax::ast::item> = quote_item!(cx, static foo : int = $e_toks; ); - let _c: @syntax::ast::pat = quote_pat!(cx, (x, 1 .. 4, *) ); - let _d: @syntax::ast::stmt = quote_stmt!(cx, let x = $a; ); - let _e: @syntax::ast::expr = quote_expr!(cx, match foo { $p_toks => 10 } ); + let _c: @syntax::ast::Pat = quote_pat!(cx, (x, 1 .. 4, *) ); + let _d: @syntax::ast::Stmt = quote_stmt!(cx, let x = $a; ); + let _e: @syntax::ast::Expr = quote_expr!(cx, match foo { $p_toks => 10 } ); } fn main() { diff --git a/src/test/run-pass/glob-std.rs b/src/test/run-pass/glob-std.rs index 8cd2d9edbd7..56bcd24f1cb 100644 --- a/src/test/run-pass/glob-std.rs +++ b/src/test/run-pass/glob-std.rs @@ -17,14 +17,13 @@ use extra::tempfile::TempDir; use std::unstable::finally::Finally; use std::{os, unstable}; use std::rt::io; -use std::rt::io::file::FileInfo; pub fn main() { fn mk_file(path: &str, directory: bool) { if directory { - os::make_dir(&Path::new(path), 0xFFFF); + io::file::mkdir(&Path::new(path), io::UserRWX); } else { - Path::new(path).open_writer(io::Create); + io::file::create(&Path::new(path)); } } diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs index 76a1d32705b..2f6de7e4472 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass/rename-directory.rs @@ -17,6 +17,8 @@ extern mod extra; use extra::tempfile::TempDir; use std::os; use std::libc; +use std::rt::io; +use std::rt::io::file; fn rename_directory() { #[fixed_stack_segment]; @@ -26,7 +28,7 @@ fn rename_directory() { let tmpdir = TempDir::new("rename_directory").expect("rename_directory failed"); let tmpdir = tmpdir.path(); let old_path = tmpdir.join_many(["foo", "bar", "baz"]); - assert!(os::mkdir_recursive(&old_path, U_RWX)); + file::mkdir_recursive(&old_path, io::UserRWX); let test_file = &old_path.join("temp.txt"); /* Write the temp input file */ @@ -47,10 +49,10 @@ fn rename_directory() { assert_eq!(libc::fclose(ostream), (0u as libc::c_int)); let new_path = tmpdir.join_many(["quux", "blat"]); - assert!(os::mkdir_recursive(&new_path, U_RWX)); - assert!(os::rename_file(&old_path, &new_path.join("newdir"))); - assert!(os::path_is_dir(&new_path.join("newdir"))); - assert!(os::path_exists(&new_path.join_many(["newdir", "temp.txt"]))); + file::mkdir_recursive(&new_path, io::UserRWX); + file::rename(&old_path, &new_path.join("newdir")); + assert!(new_path.join("newdir").is_dir()); + assert!(new_path.join_many(["newdir", "temp.txt"]).exists()); } } diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs index 85cf265c2d0..d46c8a64f5a 100644 --- a/src/test/run-pass/stat.rs +++ b/src/test/run-pass/stat.rs @@ -13,17 +13,14 @@ extern mod extra; use extra::tempfile; -use std::rt::io; -use std::rt::io::Writer; -use std::rt::io::file::FileInfo; -use std::os; +use std::rt::io::file; pub fn main() { let dir = tempfile::TempDir::new_in(&Path::new("."), "").unwrap(); let path = dir.path().join("file"); { - match path.open_writer(io::CreateOrTruncate) { + match file::create(&path) { None => unreachable!(), Some(f) => { let mut f = f; @@ -35,5 +32,5 @@ pub fn main() { } assert!(path.exists()); - assert_eq!(path.get_size(), Some(1000)); + assert_eq!(path.stat().size, 1000); } diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 142186853f5..9ac144f5fb5 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -22,9 +22,10 @@ extern mod extra; use extra::tempfile::TempDir; use std::os; -use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; use std::task; use std::cell::Cell; +use std::rt::io; +use std::rt::io::file; fn test_tempdir() { let path = { @@ -33,7 +34,7 @@ fn test_tempdir() { assert!(p.as_vec().ends_with(bytes!("foobar"))); p.clone() }; - assert!(!os::path_exists(&path)); + assert!(!path.exists()); } fn test_rm_tempdir() { @@ -45,7 +46,7 @@ fn test_rm_tempdir() { }; task::try(f); let path = rd.recv(); - assert!(!os::path_exists(&path)); + assert!(!path.exists()); let tmp = TempDir::new("test_rm_tempdir").unwrap(); let path = tmp.path().clone(); @@ -55,7 +56,7 @@ fn test_rm_tempdir() { fail!("fail to unwind past `tmp`"); }; task::try(f); - assert!(!os::path_exists(&path)); + assert!(!path.exists()); let path; { @@ -64,18 +65,18 @@ fn test_rm_tempdir() { }; let tmp = task::try(f).expect("test_rm_tmdir"); path = tmp.path().clone(); - assert!(os::path_exists(&path)); + assert!(path.exists()); } - assert!(!os::path_exists(&path)); + assert!(!path.exists()); let path; { let tmp = TempDir::new("test_rm_tempdir").unwrap(); path = tmp.unwrap(); } - assert!(os::path_exists(&path)); - os::remove_dir_recursive(&path); - assert!(!os::path_exists(&path)); + assert!(path.exists()); + file::rmdir_recursive(&path); + assert!(!path.exists()); } // Ideally these would be in std::os but then core would need @@ -84,39 +85,39 @@ fn recursive_mkdir_rel() { let path = Path::new("frob"); let cwd = os::getcwd(); debug!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.display(), - cwd.display(), os::path_exists(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); + cwd.display(), path.exists()); + file::mkdir_recursive(&path, io::UserRWX); + assert!(path.is_dir()); + file::mkdir_recursive(&path, io::UserRWX); + assert!(path.is_dir()); } fn recursive_mkdir_dot() { let dot = Path::new("."); - assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); + file::mkdir_recursive(&dot, io::UserRWX); let dotdot = Path::new(".."); - assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); + file::mkdir_recursive(&dotdot, io::UserRWX); } fn recursive_mkdir_rel_2() { let path = Path::new("./frob/baz"); let cwd = os::getcwd(); debug!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.display(), - cwd.display(), os::path_exists(&path)); - assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path)); - assert!(os::path_is_dir(&path.dir_path())); + cwd.display(), path.exists()); + file::mkdir_recursive(&path, io::UserRWX); + assert!(path.is_dir()); + assert!(path.dir_path().is_dir()); let path2 = Path::new("quux/blat"); debug!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(), cwd.display()); - assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32)); - assert!(os::path_is_dir(&path2)); - assert!(os::path_is_dir(&path2.dir_path())); + file::mkdir_recursive(&path2, io::UserRWX); + assert!(path2.is_dir()); + assert!(path2.dir_path().is_dir()); } // Ideally this would be in core, but needs TempFile pub fn test_rmdir_recursive_ok() { - let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32; + let rwx = io::UserRWX; let tmpdir = TempDir::new("test").expect("test_rmdir_recursive_ok: \ couldn't create temp dir"); @@ -124,14 +125,14 @@ pub fn test_rmdir_recursive_ok() { let root = tmpdir.join("foo"); debug!("making {}", root.display()); - assert!(os::make_dir(&root, rwx)); - assert!(os::make_dir(&root.join("foo"), rwx)); - assert!(os::make_dir(&root.join("foo").join("bar"), rwx)); - assert!(os::make_dir(&root.join("foo").join("bar").join("blat"), rwx)); - assert!(os::remove_dir_recursive(&root)); - assert!(!os::path_exists(&root)); - assert!(!os::path_exists(&root.join("bar"))); - assert!(!os::path_exists(&root.join("bar").join("blat"))); + file::mkdir(&root, rwx); + file::mkdir(&root.join("foo"), rwx); + file::mkdir(&root.join("foo").join("bar"), rwx); + file::mkdir(&root.join("foo").join("bar").join("blat"), rwx); + file::rmdir_recursive(&root); + assert!(!root.exists()); + assert!(!root.join("bar").exists()); + assert!(!root.join("bar").join("blat").exists()); } fn in_tmpdir(f: &fn()) {