From 7d268cb34ad562b45103f3c9fd4a67bc2a96019d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 25 Oct 2013 16:48:26 -0700 Subject: [PATCH 1/3] Move rt::io traits into the prelude These traits belong here, and were simply waiting for the std::io traits to get removed. It's time they take their rightful positions! --- src/libstd/prelude.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index a15ef879e322d..0190b02fbc08f 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -67,6 +67,7 @@ pub use num::{Orderable, Signed, Unsigned, Round}; pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive}; pub use path::{GenericPath, Path, PosixPath, WindowsPath}; pub use ptr::RawPtr; +pub use rt::io::{Writer, Reader, Seek}; pub use send_str::{SendStr, SendStrOwned, SendStrStatic, IntoSendStr}; pub use str::{Str, StrVector, StrSlice, OwnedStr}; pub use to_bytes::IterBytes; From 6f7d868c27575a77313edc44709dd40ddd596ba6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 25 Oct 2013 16:50:08 -0700 Subject: [PATCH 2/3] Modify IoFactory's fs_mkdir, and add fs_rename The invocation for making a directory should be able to specify a mode to make the directory with (instead of defaulting to one particular mode). Additionally, libuv and various OSes implement efficient versions of renaming files, so this operation is exposed as an IoFactory call. --- src/libstd/rt/rtio.rs | 3 ++- src/libstd/rt/uv/file.rs | 15 +++++++++++++++ src/libstd/rt/uv/uvio.rs | 16 ++++++++++++---- src/libstd/rt/uv/uvll.rs | 8 ++++++++ src/rt/rust_uv.cpp | 5 +++++ src/rt/rustrt.def.in | 1 + 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 366388063d4ef..928ec1a2318f5 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -102,8 +102,9 @@ 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) -> Result<(), IoError>; + fn fs_mkdir(&mut self, path: &CString, mode: int) -> 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) -> Result<~[Path], IoError>; fn spawn(&mut self, config: ProcessConfig) diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs index d2ca15959b025..976913cb34a81 100644 --- a/src/libstd/rt/uv/file.rs +++ b/src/libstd/rt/uv/file.rs @@ -207,6 +207,21 @@ impl FsRequest { assert_eq!(ret, 0); } + pub fn rename(self, loop_: &Loop, path: &CString, to: &CString, cb: FsCallback) { + let complete_cb_ptr = { + let mut me = self; + me.req_boilerplate(Some(cb)) + }; + let ret = unsafe { + uvll::fs_rename(loop_.native_handle(), + self.native_handle(), + path.with_ref(|p| p), + to.with_ref(|p| p), + complete_cb_ptr) + }; + assert_eq!(ret, 0); + } + pub fn readdir(self, loop_: &Loop, path: &CString, flags: c_int, cb: FsCallback) { let complete_cb_ptr = { diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 2d3ecbbd68907..3d3dbfbaa8b20 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -37,7 +37,7 @@ use rt::uv::addrinfo::{GetAddrInfoRequest, accum_addrinfo}; use unstable::sync::Exclusive; use path::{GenericPath, Path}; use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY, - S_IRUSR, S_IWUSR, S_IRWXU}; + S_IRUSR, S_IWUSR}; use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create, CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite, FileStat}; @@ -697,10 +697,9 @@ impl IoFactory for UvIoFactory { assert!(!result_cell.is_empty()); return result_cell.take(); } - fn fs_mkdir(&mut self, path: &CString) -> Result<(), IoError> { - let mode = S_IRWXU as int; + fn fs_mkdir(&mut self, path: &CString, mode: int) -> Result<(), IoError> { do uv_fs_helper(self.uv_loop(), path) |mkdir_req, l, p, cb| { - do mkdir_req.mkdir(l, p, mode as int) |req, err| { + do mkdir_req.mkdir(l, p, mode) |req, err| { cb(req, err) }; } @@ -712,6 +711,15 @@ impl IoFactory for UvIoFactory { }; } } + fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError> { + let to = to.with_ref(|p| p); + do uv_fs_helper(self.uv_loop(), path) |rename_req, l, p, cb| { + let to = unsafe { CString::new(to, false) }; + do rename_req.rename(l, p, &to) |req, err| { + cb(req, err) + }; + } + } fn fs_readdir(&mut self, path: &CString, flags: c_int) -> Result<~[Path], IoError> { use str::StrSlice; diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index 2964eb9c58be3..723ed82bf14b5 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -809,6 +809,12 @@ pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, rust_uv_fs_rmdir(loop_ptr, req, path, cb) } +pub unsafe fn fs_rename(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, + to: *c_char, cb: *u8) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + + rust_uv_fs_rename(loop_ptr, req, path, to, 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)]; @@ -1107,6 +1113,8 @@ extern { mode: c_int, cb: *u8) -> c_int; fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int; + fn rust_uv_fs_rename(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, + to: *c_char, cb: *u8) -> c_int; fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, flags: c_int, cb: *u8) -> c_int; fn rust_uv_fs_req_cleanup(req: *uv_fs_t); diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index c59dacab88990..70602100f2e0d 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -592,6 +592,11 @@ extern "C" int rust_uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) { return uv_fs_readdir(loop, req, path, flags, cb); } +extern "C" int +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_spawn(uv_loop_t *loop, uv_process_t *p, uv_process_options_t options) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 47c9554daa018..70fdc3fcbd187 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -116,6 +116,7 @@ rust_uv_populate_uv_stat rust_uv_fs_mkdir rust_uv_fs_rmdir rust_uv_fs_readdir +rust_uv_fs_rename rust_dbg_lock_create rust_dbg_lock_destroy rust_dbg_lock_lock From cfb481a0856cc5660bb45f3cef53abc6e370b8c1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 25 Oct 2013 17:04:37 -0700 Subject: [PATCH 3/3] 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. The api of the io::file modules has also been reworked in this commit. The open_reader and open_writer functions have had open and create counterparts created, neither of which take any arguments (allowing for easy usage). The top-level 'file::open' function was renamed to 'file::open_stream', and top-level 'file::create' and 'file::open' functions were added (same as the methods). I also removed the traits that add functionality to the platform's Path structure. It was unfortunate having to import all of these traits, and it was unclear whether they would ever be implemented for anything other than Path. For this reason, they're now just an extra impl block on Path itself. 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. 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/rustdoc.rs | 7 +- src/librustpkg/api.rs | 6 +- src/librustpkg/context.rs | 3 +- src/librustpkg/installed_packages.rs | 8 +- src/librustpkg/package_id.rs | 1 - src/librustpkg/package_source.rs | 17 +- src/librustpkg/path_util.rs | 52 +- src/librustpkg/rustpkg.rs | 31 +- 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 | 35 +- src/librustuv/uvio.rs | 33 +- src/librustuv/uvll.rs | 20 +- 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 | 793 +++++++++--------- 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/rt/uv/file.rs | 22 +- src/libstd/rt/uv/uvio.rs | 14 +- src/libstd/rt/uv/uvll.rs | 12 +- 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/rt/rustrt.def.in | 1 + 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 +- 61 files changed, 1437 insertions(+), 1506 deletions(-) diff --git a/mk/tests.mk b/mk/tests.mk index 6aec4b81d0a49..277f1dfd407c5 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -503,8 +503,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) @@ -659,7 +659,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 7f5a72e8a2c8c..a354bc84e52b5 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 0c94ec8ab8a83..dfadea37cd0d3 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 368c96ffe8542..68e8fd7673542 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 e7e1b11028923..718f1e527f8c3 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() } @@ -628,10 +626,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, @@ -745,7 +741,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 { @@ -901,7 +897,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 @@ -996,7 +992,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 5297b48b0e156..a7742f771da3c 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 d8fa130916a46..4affe7c1cde8a 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 8dff53f14a159..c5509f8aec7d7 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 070108ddf2e8e..83af7b60002fe 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; @@ -934,16 +931,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 @@ -1028,7 +1024,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 b94b74a696cc2..54ce349a0b484 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 507962c0b1a2a..b2be4cf811b32 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 1b9cb10f1dcfd..30147b50ee86d 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 8aba36370d0b8..51cac5afad218 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 94dfc006076f9..44e43bd4ef3a6 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 e92d159b5a15d..48740a1b8c3ca 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; @@ -769,7 +762,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. @@ -791,7 +784,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(); @@ -806,8 +799,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, @@ -824,8 +816,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); } _ => {} @@ -962,7 +953,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)); @@ -971,7 +962,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); @@ -1118,7 +1109,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), @@ -1128,7 +1119,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(": "); @@ -1171,7 +1162,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()); @@ -1229,8 +1220,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, @@ -1259,7 +1250,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);
@@ -1283,7 +1274,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(),
@@ -1360,7 +1351,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],
@@ -1413,7 +1404,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| {
@@ -1448,7 +1439,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) => { @@ -1469,7 +1460,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); @@ -1547,7 +1538,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, @@ -1569,7 +1560,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/rustdoc.rs b/src/librustdoc/rustdoc.rs index 770d535c6ea9e..7a64ca6d6fc2a 100644 --- a/src/librustdoc/rustdoc.rs +++ b/src/librustdoc/rustdoc.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 c67b6f52c7e39..c0ffd66d22e43 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 77fe2ae8f704b..0ae08731546f1 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 767a31ed78563..09b58e6e94cce 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/package_id.rs b/src/librustpkg/package_id.rs index 0fc614d7f3ce8..0da343a27bfca 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 797ea3372ccfd..a52aa68e1e471 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 a48ef23115ccf..75f03533d583c 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/rustpkg.rs b/src/librustpkg/rustpkg.rs index 517d43432eccf..bb6088adee18e 100644 --- a/src/librustpkg/rustpkg.rs +++ b/src/librustpkg/rustpkg.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/source_control.rs b/src/librustpkg/source_control.rs index c3e4205dfc972..a0e50ff0f9ef7 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 8f1b269f1caac..60e99f242ef14 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 016635339a9d9..f5d6317e7a68f 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 f82c585b1d156..e5fb6889ae09b 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 9d835dcc20be7..d0ba5ce368fcd 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 6ca19562724fe..eff16cb99968c 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 2e4894b854d5c..c16224afbf4c8 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 a35500372467c..e65f3ce5bb6ab 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 575226f79028b..15df189edcdd4 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)) @@ -206,6 +206,33 @@ impl FsRequest { assert_eq!(ret, 0); } + pub fn rename(self, loop_: &Loop, path: &CString, to: &CString, cb: FsCallback) { + let complete_cb_ptr = { + let mut me = self; + me.req_boilerplate(Some(cb)) + }; + let ret = unsafe { + uvll::fs_rename(loop_.native_handle(), + self.native_handle(), + path.with_ref(|p| p), + to.with_ref(|p| p), + complete_cb_ptr) + }; + assert_eq!(ret, 0); + } + + 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 = { @@ -578,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(); @@ -611,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 8b80a24a1b48f..d4a332230e3de 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}; @@ -122,10 +123,9 @@ trait HomingIO { a // return the result of the IO } - fn home_for_io_consume(self, io: &fn(Self) -> A) -> A { - let mut this = self; - let home = this.go_to_IO_home(); - let a = io(this); // do IO + fn home_for_io_consume(mut self, io: &fn(Self) -> A) -> A { + let home = self.go_to_IO_home(); + let a = io(self); // do IO HomingIO::restore_original_home(None::, home); a // return the result of the IO } @@ -700,10 +700,10 @@ impl IoFactory for UvIoFactory { assert!(!result_cell.is_empty()); return result_cell.take(); } - fn fs_mkdir(&mut self, path: &CString) -> Result<(), IoError> { - let mode = S_IRWXU as int; + 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 as int) |req, err| { + do mkdir_req.mkdir(l, p, perm as c_int) |req, err| { cb(req, err) }; } @@ -715,6 +715,23 @@ impl IoFactory for UvIoFactory { }; } } + fn fs_rename(&mut self, path: &CString, to: &CString) -> Result<(), IoError> { + let to = to.with_ref(|p| p); + do uv_fs_helper(self.uv_loop(), path) |rename_req, l, p, cb| { + let to = unsafe { CString::new(to, false) }; + do rename_req.rename(l, p, &to) |req, err| { + cb(req, err) + }; + } + } + 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) + }; + } + } 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 f80178cfa4c62..c047b9c9cd102 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) @@ -807,6 +807,18 @@ pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, rust_uv_fs_rmdir(loop_ptr, req, path, cb) } +pub unsafe fn fs_rename(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, + to: *c_char, cb: *u8) -> c_int { + #[fixed_stack_segment]; #[inline(never)]; + + 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)]; @@ -1105,6 +1117,10 @@ extern { mode: c_int, cb: *u8) -> c_int; fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int; + fn rust_uv_fs_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 2eec6ff4cba43..7f91c5e4f9054 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 1f32c6a0a35ef..12281f06005a7 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 d92c2974f7691..f14f100de73c9 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 5ed8d6b10d1be..c9499bb4aa8e6 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 d035e2f457cc2..f38bd5e9cf5ee 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()`. -pub struct FileReader { priv stream: FileStream } +/// # 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 + } + } + }; +} -/// 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) - } +/// 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]; - fn eof(&mut self) -> bool { - self.stream.eof() + 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); } -/// a `std::rt::io::Seek` trait impl for file I/O. -impl Seek for FileReader { - fn tell(&self) -> u64 { - self.stream.tell() - } +// 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 + } + } + }; +} - fn seek(&mut self, pos: i64, style: SeekStyle) { - self.stream.seek(pos, style); +/// 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 } + +impl Reader for FileReader { + fn read(&mut self, buf: &mut [u8]) -> Option { self.stream.read(buf) } + fn eof(&mut self) -> bool { self.stream.eof() } +} + +impl Seek for FileReader { + fn tell(&self) -> u64 { self.stream.tell() } + fn seek(&mut self, p: i64, s: SeekStyle) { self.stream.seek(p, s) } } -/// Constrained version of `FileStream` that only exposes write-specific operations. +/// 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) { @@ -394,7 +506,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(); @@ -421,166 +532,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 - } - } - - /// 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) + pub fn is_file(&self) -> bool { + match io::result(|| self.stat()) { + Ok(s) => s.is_file, + Err(*) => false } } - /// 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 @@ -589,109 +574,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 super::super::{SeekSet, SeekCur, SeekEnd, - io_error, Read, Create, Open, ReadWrite}; - use super::super::super::test::*; + use path::{Path, GenericPath}; + use result::{Ok, Err}; use option::{Some, None}; - use path::Path; - use super::*; 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 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"), @@ -711,7 +637,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); @@ -740,11 +666,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); @@ -771,11 +697,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); @@ -800,13 +726,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); @@ -826,11 +752,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); @@ -856,14 +782,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); } @@ -873,11 +796,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); } @@ -887,7 +807,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); } @@ -897,13 +817,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()); } } @@ -913,10 +829,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()); } } @@ -926,36 +842,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 5eba3b2b801d2..e145a61a2044b 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; @@ -421,6 +424,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 @@ -1136,3 +1151,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 ba819df071a97..ddb1be3d2725b 100644 --- a/src/libstd/rt/io/native/file.rs +++ b/src/libstd/rt/io/native/file.rs @@ -299,3 +299,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 d9bdb73066d3b..6098995af5339 100644 --- a/src/libstd/rt/io/net/unix.rs +++ b/src/libstd/rt/io/net/unix.rs @@ -157,7 +157,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); @@ -291,7 +290,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 4c6c675df0342..1cd0278b014f7 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}; @@ -145,10 +146,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)] @@ -206,7 +207,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 500cd91b3db96..36092dfbe34e6 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 928ec1a2318f5..b56ca3ae7370e 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/rt/uv/file.rs b/src/libstd/rt/uv/file.rs index 976913cb34a81..a8708c948224d 100644 --- a/src/libstd/rt/uv/file.rs +++ b/src/libstd/rt/uv/file.rs @@ -183,7 +183,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)) @@ -222,6 +222,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 = { @@ -369,7 +381,7 @@ extern fn compl_cb(req: *uv_fs_t) { mod test { use super::*; //use rt::test::*; - use libc::{STDOUT_FILENO}; + use libc::{STDOUT_FILENO, c_int}; use vec; use str; use unstable::run_in_bare_thread; @@ -594,7 +606,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(); @@ -627,12 +639,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/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 3d3dbfbaa8b20..81ec445adf416 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -20,6 +20,7 @@ use option::*; use ptr; use str; use result::*; +use rt::io; use rt::io::IoError; use rt::io::net::ip::{SocketAddr, IpAddr}; use rt::io::{standard_error, OtherIoError, SeekStyle, SeekSet, SeekCur, SeekEnd}; @@ -697,9 +698,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) }; } @@ -720,6 +722,14 @@ 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) + }; + } + } fn fs_readdir(&mut self, path: &CString, flags: c_int) -> Result<~[Path], IoError> { use str::StrSlice; diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index 723ed82bf14b5..a43529d55aa3d 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -797,8 +797,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) @@ -815,6 +815,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/run.rs b/src/libstd/run.rs index 9e6fdf2ba4c9a..89784acec8ebb 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 fda6f782af450..876adf401862f 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 003bc006ebec0..cd1be9a3c1615 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 70602100f2e0d..2b63325f931e7 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/rt/rustrt.def.in b/src/rt/rustrt.def.in index 70fdc3fcbd187..615ec902cb077 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -117,6 +117,7 @@ rust_uv_fs_mkdir rust_uv_fs_rmdir rust_uv_fs_readdir rust_uv_fs_rename +rust_uv_fs_chmod rust_dbg_lock_create rust_dbg_lock_destroy rust_dbg_lock_lock diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index dbd1edffe7827..531f01c199562 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 52f068b8b1cdd..7d3fa6104e5c3 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 c39c32753679b..c7c8e3a19a6cd 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 62ce4e7c02c09..2e426c0413e74 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 8cd2d9edbd7c0..56bcd24f1cb4e 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 76a1d32705b2d..2f6de7e4472bd 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 85cf265c2d0e8..d46c8a64f5a4e 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 142186853f526..9ac144f5fb5e5 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()) {