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