std/rt: in-progress file io work
std: remove unneeded field from RequestData struct std: rt::uv::file - map us_fs_stat & start refactoring calls into FsRequest std: stubbing out stat calls from the top-down into uvio std: us_fs_* operations are now by-val self methods on FsRequest std: post-rebase cleanup std: add uv_fs_mkdir|rmdir + tests & minor test cleanup in rt::uv::file WORKING: fleshing out FileStat and FileInfo + tests std: reverting test files.. refactoring back and cleanup...
This commit is contained in:
parent
b75e07501b
commit
af650572e0
@ -11,12 +11,15 @@
|
||||
use prelude::*;
|
||||
use super::support::PathLike;
|
||||
use super::{Reader, Writer, Seek};
|
||||
use super::{SeekSet, SeekCur, SeekEnd, SeekStyle};
|
||||
use super::{SeekStyle,SeekSet, SeekCur, SeekEnd,
|
||||
Open, Read, Create, ReadWrite};
|
||||
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
|
||||
use rt::io::{io_error, read_error, EndOfFile,
|
||||
FileMode, FileAccess, Open, Read, Create, ReadWrite};
|
||||
FileMode, FileAccess, FileStat};
|
||||
use rt::local::Local;
|
||||
use rt::test::*;
|
||||
use option::{Some, None};
|
||||
use path::Path;
|
||||
use super::super::test::*;
|
||||
|
||||
/// Open a file for reading/writing, as indicated by `path`.
|
||||
pub fn open<P: PathLike>(path: &P,
|
||||
@ -145,6 +148,123 @@ impl Seek for FileStream {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileInfo(Path);
|
||||
|
||||
/// FIXME: DOCS
|
||||
impl<'self> FileInfo {
|
||||
pub fn new<P: PathLike>(path: &P) -> FileInfo {
|
||||
do path.path_as_str |p| {
|
||||
FileInfo(Path(p))
|
||||
}
|
||||
}
|
||||
// FIXME #8873 can't put this in FileSystemInfo
|
||||
pub fn get_path(&'self self) -> &'self Path {
|
||||
&(**self)
|
||||
}
|
||||
pub fn stat(&self) -> Option<FileStat> {
|
||||
do io_error::cond.trap(|_| {
|
||||
// FIXME: can we do something more useful here?
|
||||
}).inside {
|
||||
stat(self.get_path())
|
||||
}
|
||||
}
|
||||
pub fn exists(&self) -> bool {
|
||||
match self.stat() {
|
||||
Some(s) => {
|
||||
match s.is_file {
|
||||
true => {
|
||||
true
|
||||
},
|
||||
false => {
|
||||
// FIXME: raise condition?
|
||||
false
|
||||
}
|
||||
}
|
||||
},
|
||||
None => false
|
||||
}
|
||||
}
|
||||
pub fn is_file(&self) -> bool {
|
||||
match self.stat() {
|
||||
Some(s) => s.is_file,
|
||||
None => {
|
||||
// FIXME: raise condition
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn open(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
|
||||
match self.is_file() {
|
||||
true => {
|
||||
open(self.get_path(), mode, access)
|
||||
},
|
||||
false => {
|
||||
// FIXME: raise condition
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
//fn open_read(&self) -> FileStream;
|
||||
//fn open_write(&self) -> FileStream;
|
||||
//fn create(&self) -> FileStream;
|
||||
//fn truncate(&self) -> FileStream;
|
||||
//fn open_or_create(&self) -> FileStream;
|
||||
//fn create_or_truncate(&self) -> FileStream;
|
||||
//fn unlink(&self);
|
||||
}
|
||||
|
||||
/*
|
||||
/// FIXME: DOCS
|
||||
impl DirectoryInfo<'self> {
|
||||
fn new<P: PathLike>(path: &P) -> FileInfo {
|
||||
FileInfo(Path(path.path_as_str()))
|
||||
}
|
||||
// FIXME #8873 can't put this in FileSystemInfo
|
||||
fn get_path(&'self self) -> &'self Path {
|
||||
&*self
|
||||
}
|
||||
fn stat(&self) -> Option<FileStat> {
|
||||
file::stat(self.get_path())
|
||||
}
|
||||
fn exists(&self) -> bool {
|
||||
do io_error::cond.trap(|_| {
|
||||
}).inside {
|
||||
match self.stat() {
|
||||
Some(_) => true,
|
||||
None => false
|
||||
}
|
||||
}
|
||||
}
|
||||
fn is_dir(&self) -> bool {
|
||||
|
||||
}
|
||||
fn create(&self);
|
||||
fn get_subdirs(&self, filter: &str) -> ~[Path];
|
||||
fn get_files(&self, filter: &str) -> ~[Path];
|
||||
}
|
||||
*/
|
||||
|
||||
/// Given a `rt::io::support::PathLike`, query the file system to get
|
||||
/// information about a file, directory, etc.
|
||||
///
|
||||
/// Returns a `Some(PathInfo)` on success, and raises a `rt::io::IoError` condition
|
||||
/// on failure and returns `None`.
|
||||
pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
|
||||
let open_result = unsafe {
|
||||
let io: *mut IoFactoryObject = Local::unsafe_borrow();
|
||||
(*io).fs_stat(path)
|
||||
};
|
||||
match open_result {
|
||||
Ok(p) => {
|
||||
Some(p)
|
||||
},
|
||||
Err(ioerr) => {
|
||||
read_error::cond.raise(ioerr);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn file_test_smoke_test_impl() {
|
||||
do run_in_mt_newsched_task {
|
||||
let message = "it's alright. have a good time";
|
||||
@ -273,7 +393,6 @@ fn file_test_io_seek_and_tell_smoke_test() {
|
||||
}
|
||||
|
||||
fn file_test_io_seek_and_write_impl() {
|
||||
use io;
|
||||
do run_in_mt_newsched_task {
|
||||
use str;
|
||||
let initial_msg = "food-is-yummy";
|
||||
@ -293,8 +412,7 @@ fn file_test_io_seek_and_write_impl() {
|
||||
read_stream.read(read_mem);
|
||||
}
|
||||
unlink(filename);
|
||||
let read_str = str::from_utf8(read_mem);
|
||||
io::println(fmt!("read_str: '%?' final_msg: '%?'", read_str, final_msg));
|
||||
let read_str = str::from_bytes(read_mem);
|
||||
assert!(read_str == final_msg.to_owned());
|
||||
}
|
||||
}
|
||||
@ -343,3 +461,35 @@ fn file_test_io_seek_shakedown_impl() {
|
||||
fn file_test_io_seek_shakedown() {
|
||||
file_test_io_seek_shakedown_impl();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_stat_is_correct_on_is_file() {
|
||||
do run_in_newsched_task {
|
||||
let filename = &Path("./tmp/file_stat_correct_on_is_file.txt");
|
||||
{
|
||||
let mut fs = open(filename, Create, ReadWrite).unwrap();
|
||||
let msg = "hw";
|
||||
fs.write(msg.as_bytes());
|
||||
}
|
||||
let stat_res = match stat(filename) {
|
||||
Some(s) => s,
|
||||
None => fail!("shouldn't happen")
|
||||
};
|
||||
assert!(stat_res.is_file);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_stat_is_correct_on_is_dir() {
|
||||
//assert!(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
|
||||
//assert!(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
|
||||
//assert!(false);
|
||||
}
|
||||
|
@ -245,6 +245,7 @@ Out of scope
|
||||
use prelude::*;
|
||||
use to_str::ToStr;
|
||||
use str::{StrSlice, OwnedStr};
|
||||
use path::Path;
|
||||
|
||||
// Reexports
|
||||
pub use self::stdio::stdin;
|
||||
@ -596,3 +597,26 @@ pub enum FileAccess {
|
||||
Write,
|
||||
ReadWrite
|
||||
}
|
||||
|
||||
pub struct FileStat {
|
||||
/// A `Path` object containing information about the `PathInfo`'s location
|
||||
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
|
||||
// `true` if the file pointed at by the `PathInfo` is a link (what this means
|
||||
// is platform dependant)
|
||||
/*
|
||||
/// The file pointed at by the `PathInfo`'s size in bytes
|
||||
size: u64,
|
||||
/// The file pointed at by the `PathInfo`'s time date in platform-dependent msecs
|
||||
created: u64,
|
||||
/// The file pointed at by the `PathInfo`'s last-modification time in
|
||||
/// platform-dependent msecs
|
||||
modified: u64,
|
||||
/// The file pointed at by the `PathInfo`'s last-accessd time (e.g. read) in
|
||||
/// platform-dependent msecs
|
||||
accessed: u64,
|
||||
*/
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use rt::uv::uvio;
|
||||
use path::Path;
|
||||
use super::io::support::PathLike;
|
||||
use super::io::{SeekStyle};
|
||||
use super::io::{FileMode, FileAccess};
|
||||
use super::io::{FileMode, FileAccess, FileStat};
|
||||
|
||||
// XXX: ~object doesn't work currently so these are some placeholder
|
||||
// types to use instead
|
||||
@ -74,6 +74,13 @@ pub trait IoFactory {
|
||||
-> Result<~RtioFileStream, IoError>;
|
||||
fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
|
||||
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
|
||||
fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
|
||||
//fn fs_fstat(&mut self, fd: c_int) -> Result<FileStat, IoError>;
|
||||
}
|
||||
|
||||
pub trait RtioStream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
|
||||
fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
|
||||
}
|
||||
|
||||
pub trait RtioTcpListener : RtioSocket {
|
||||
|
@ -24,12 +24,11 @@ pub struct FsRequest(*uvll::uv_fs_t);
|
||||
impl Request for FsRequest;
|
||||
|
||||
pub struct RequestData {
|
||||
complete_cb: Option<FsCallback>,
|
||||
raw_fd: Option<c_int>
|
||||
complete_cb: Option<FsCallback>
|
||||
}
|
||||
|
||||
impl FsRequest {
|
||||
pub fn new(cb: Option<FsCallback>) -> FsRequest {
|
||||
pub fn new_REFACTOR_ME(cb: Option<FsCallback>) -> FsRequest {
|
||||
let fs_req = unsafe { malloc_req(UV_FS) };
|
||||
assert!(fs_req.is_not_null());
|
||||
let fs_req: FsRequest = NativeHandle::from_native_handle(fs_req);
|
||||
@ -37,64 +36,174 @@ impl FsRequest {
|
||||
fs_req
|
||||
}
|
||||
|
||||
fn open_common<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int,
|
||||
cb: Option<FsCallback>) -> int {
|
||||
let complete_cb_ptr = match cb {
|
||||
Some(_) => compl_cb as *u8,
|
||||
None => 0 as *u8
|
||||
};
|
||||
let is_sync = cb.is_none();
|
||||
let req = FsRequest::new(cb);
|
||||
pub fn new() -> FsRequest {
|
||||
let fs_req = unsafe { malloc_req(UV_FS) };
|
||||
assert!(fs_req.is_not_null());
|
||||
let fs_req: FsRequest = NativeHandle::from_native_handle(fs_req);
|
||||
fs_req
|
||||
}
|
||||
|
||||
pub fn open<P: PathLike>(self, loop_: &Loop, path: &P, flags: int, mode: int,
|
||||
cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_open(loop_.native_handle(),
|
||||
self.native_handle(), p, flags, mode, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn open_sync<P: PathLike>(self, loop_: &Loop, path: &P,
|
||||
flags: int, mode: int) -> Result<c_int, UvError> {
|
||||
let complete_cb_ptr = self.req_boilerplate(None);
|
||||
let result = path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_open(loop_.native_handle(),
|
||||
req.native_handle(), p, flags, mode, complete_cb_ptr) as int
|
||||
self.native_handle(), p, flags, mode, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
if is_sync { req.cleanup_and_delete(); }
|
||||
result
|
||||
}
|
||||
pub fn open<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int,
|
||||
cb: FsCallback) {
|
||||
FsRequest::open_common(loop_, path, flags, mode, Some(cb));
|
||||
self.sync_cleanup(result)
|
||||
}
|
||||
|
||||
pub fn open_sync<P: PathLike>(loop_: &Loop, path: &P, flags: int, mode: int)
|
||||
-> Result<int, UvError> {
|
||||
let result = FsRequest::open_common(loop_, path, flags, mode, None);
|
||||
sync_cleanup(result)
|
||||
pub fn unlink<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_unlink(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn unlink_common<P: PathLike>(loop_: &Loop, path: &P, cb: Option<FsCallback>) -> int {
|
||||
let complete_cb_ptr = match cb {
|
||||
Some(_) => compl_cb as *u8,
|
||||
None => 0 as *u8
|
||||
};
|
||||
let is_sync = cb.is_none();
|
||||
let req = FsRequest::new(cb);
|
||||
pub fn unlink_sync<P: PathLike>(self, loop_: &Loop, path: &P)
|
||||
-> Result<c_int, UvError> {
|
||||
let complete_cb_ptr = self.req_boilerplate(None);
|
||||
let result = path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_unlink(loop_.native_handle(),
|
||||
req.native_handle(), p, complete_cb_ptr) as int
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
if is_sync { req.cleanup_and_delete(); }
|
||||
result
|
||||
}
|
||||
pub fn unlink<P: PathLike>(loop_: &Loop, path: &P, cb: FsCallback) {
|
||||
let result = FsRequest::unlink_common(loop_, path, Some(cb));
|
||||
sync_cleanup(result);
|
||||
}
|
||||
pub fn unlink_sync<P: PathLike>(loop_: &Loop, path: &P) -> Result<int, UvError> {
|
||||
let result = FsRequest::unlink_common(loop_, path, None);
|
||||
sync_cleanup(result)
|
||||
self.sync_cleanup(result)
|
||||
}
|
||||
|
||||
pub fn stat<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_stat(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn write(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;
|
||||
unsafe {
|
||||
uvll::fs_write(loop_.native_handle(), self.native_handle(),
|
||||
fd, base_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
}
|
||||
pub fn write_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
|
||||
-> Result<c_int, UvError> {
|
||||
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 {
|
||||
uvll::fs_write(loop_.native_handle(), self.native_handle(),
|
||||
fd, base_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
self.sync_cleanup(result)
|
||||
}
|
||||
|
||||
pub fn read(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;
|
||||
unsafe {
|
||||
uvll::fs_read(loop_.native_handle(), self.native_handle(),
|
||||
fd, buf_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
}
|
||||
pub fn read_sync(self, loop_: &Loop, fd: c_int, buf: Buf, offset: i64)
|
||||
-> Result<c_int, UvError> {
|
||||
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 {
|
||||
uvll::fs_read(loop_.native_handle(), self.native_handle(),
|
||||
fd, buf_ptr,
|
||||
len, offset, complete_cb_ptr)
|
||||
};
|
||||
self.sync_cleanup(result)
|
||||
}
|
||||
|
||||
pub fn close(self, loop_: &Loop, fd: c_int, cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
unsafe {
|
||||
uvll::fs_close(loop_.native_handle(), self.native_handle(),
|
||||
fd, complete_cb_ptr)
|
||||
};
|
||||
}
|
||||
pub fn close_sync(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<P: PathLike>(self, loop_: &Loop, path: &P, mode: int, cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_mkdir(loop_.native_handle(),
|
||||
self.native_handle(), p, mode, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub fn rmdir<P: PathLike>(self, loop_: &Loop, path: &P, cb: FsCallback) {
|
||||
let complete_cb_ptr = self.req_boilerplate(Some(cb));
|
||||
path.path_as_str(|p| {
|
||||
p.to_c_str().with_ref(|p| unsafe {
|
||||
uvll::fs_rmdir(loop_.native_handle(),
|
||||
self.native_handle(), p, complete_cb_ptr)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// accessors/utility funcs
|
||||
fn sync_cleanup(self, result: c_int)
|
||||
-> Result<c_int, UvError> {
|
||||
self.cleanup_and_delete();
|
||||
match status_to_maybe_uv_error(result as i32) {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(result)
|
||||
}
|
||||
}
|
||||
fn req_boilerplate(&self, cb: Option<FsCallback>) -> *u8 {
|
||||
// XXX: this is unsafe/mutable
|
||||
let result = match cb {
|
||||
Some(_) => {
|
||||
compl_cb as *u8
|
||||
},
|
||||
None => 0 as *u8
|
||||
};
|
||||
self.install_req_data(cb);
|
||||
result
|
||||
}
|
||||
pub fn install_req_data(&self, cb: Option<FsCallback>) {
|
||||
let fs_req = (self.native_handle()) as *uvll::uv_write_t;
|
||||
let data = ~RequestData {
|
||||
complete_cb: cb,
|
||||
raw_fd: None
|
||||
complete_cb: cb
|
||||
};
|
||||
unsafe {
|
||||
let data = transmute::<~RequestData, *c_void>(data);
|
||||
@ -106,7 +215,7 @@ impl FsRequest {
|
||||
unsafe {
|
||||
let data = uvll::get_data_for_req((self.native_handle()));
|
||||
let data = transmute::<&*c_void, &mut ~RequestData>(&data);
|
||||
return &mut **data;
|
||||
&mut **data
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +229,12 @@ impl FsRequest {
|
||||
unsafe { Loop{handle:uvll::get_loop_from_fs_req(self.native_handle())} }
|
||||
}
|
||||
|
||||
pub fn get_stat(&self) -> uv_stat_t {
|
||||
let stat = uv_stat_t::new();
|
||||
unsafe { uvll::populate_stat(self.native_handle(), &stat); }
|
||||
stat
|
||||
}
|
||||
|
||||
fn cleanup_and_delete(self) {
|
||||
unsafe {
|
||||
let data = uvll::get_data_for_req(self.native_handle());
|
||||
@ -145,100 +260,7 @@ fn sync_cleanup(result: int)
|
||||
match status_to_maybe_uv_error(result as i32) {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FileDescriptor(c_int);
|
||||
|
||||
impl FileDescriptor {
|
||||
fn new(fd: c_int) -> FileDescriptor {
|
||||
FileDescriptor(fd)
|
||||
}
|
||||
|
||||
|
||||
pub fn from_open_req(req: &mut FsRequest) -> FileDescriptor {
|
||||
FileDescriptor::new(req.get_result())
|
||||
}
|
||||
|
||||
// as per bnoordhuis in #libuv: offset >= 0 uses prwrite instead of write
|
||||
fn write_common(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: Option<FsCallback>)
|
||||
-> int {
|
||||
let complete_cb_ptr = match cb {
|
||||
Some(_) => compl_cb as *u8,
|
||||
None => 0 as *u8
|
||||
};
|
||||
let is_sync = cb.is_none();
|
||||
let mut req = FsRequest::new(cb);
|
||||
let base_ptr = buf.base as *c_void;
|
||||
let len = buf.len as uint;
|
||||
req.get_req_data().raw_fd = Some(self.native_handle());
|
||||
let result = unsafe {
|
||||
uvll::fs_write(loop_.native_handle(), req.native_handle(),
|
||||
self.native_handle(), base_ptr,
|
||||
len, offset, complete_cb_ptr) as int
|
||||
};
|
||||
if is_sync { req.cleanup_and_delete(); }
|
||||
result
|
||||
}
|
||||
pub fn write(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
|
||||
self.write_common(loop_, buf, offset, Some(cb));
|
||||
}
|
||||
pub fn write_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
|
||||
-> Result<int, UvError> {
|
||||
let result = self.write_common(loop_, buf, offset, None);
|
||||
sync_cleanup(result)
|
||||
}
|
||||
|
||||
fn read_common(&mut self, loop_: &Loop, buf: Buf,
|
||||
offset: i64, cb: Option<FsCallback>)
|
||||
-> int {
|
||||
let complete_cb_ptr = match cb {
|
||||
Some(_) => compl_cb as *u8,
|
||||
None => 0 as *u8
|
||||
};
|
||||
let is_sync = cb.is_none();
|
||||
let mut req = FsRequest::new(cb);
|
||||
req.get_req_data().raw_fd = Some(self.native_handle());
|
||||
let buf_ptr = buf.base as *c_void;
|
||||
let result = unsafe {
|
||||
uvll::fs_read(loop_.native_handle(), req.native_handle(),
|
||||
self.native_handle(), buf_ptr,
|
||||
buf.len as uint, offset, complete_cb_ptr) as int
|
||||
};
|
||||
if is_sync { req.cleanup_and_delete(); }
|
||||
result
|
||||
}
|
||||
pub fn read(&mut self, loop_: &Loop, buf: Buf, offset: i64, cb: FsCallback) {
|
||||
self.read_common(loop_, buf, offset, Some(cb));
|
||||
}
|
||||
pub fn read_sync(&mut self, loop_: &Loop, buf: Buf, offset: i64)
|
||||
-> Result<int, UvError> {
|
||||
let result = self.read_common(loop_, buf, offset, None);
|
||||
sync_cleanup(result)
|
||||
}
|
||||
|
||||
fn close_common(self, loop_: &Loop, cb: Option<FsCallback>) -> int {
|
||||
let complete_cb_ptr = match cb {
|
||||
Some(_) => compl_cb as *u8,
|
||||
None => 0 as *u8
|
||||
};
|
||||
let is_sync = cb.is_none();
|
||||
let req = FsRequest::new(cb);
|
||||
let result = unsafe {
|
||||
uvll::fs_close(loop_.native_handle(), req.native_handle(),
|
||||
self.native_handle(), complete_cb_ptr) as int
|
||||
};
|
||||
if is_sync { req.cleanup_and_delete(); }
|
||||
result
|
||||
}
|
||||
pub fn close(self, loop_: &Loop, cb: FsCallback) {
|
||||
self.close_common(loop_, Some(cb));
|
||||
}
|
||||
pub fn close_sync(self, loop_: &Loop) -> Result<int, UvError> {
|
||||
let result = self.close_common(loop_, None);
|
||||
sync_cleanup(result)
|
||||
}
|
||||
}
|
||||
extern fn compl_cb(req: *uv_fs_t) {
|
||||
let mut req: FsRequest = NativeHandle::from_native_handle(req);
|
||||
// pull the user cb out of the req data
|
||||
@ -261,15 +283,7 @@ extern fn compl_cb(req: *uv_fs_t) {
|
||||
req.cleanup_and_delete();
|
||||
}
|
||||
|
||||
impl NativeHandle<c_int> for FileDescriptor {
|
||||
fn from_native_handle(handle: c_int) -> FileDescriptor {
|
||||
FileDescriptor(handle)
|
||||
}
|
||||
fn native_handle(&self) -> c_int {
|
||||
match self { &FileDescriptor(ptr) => ptr }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
//use rt::test::*;
|
||||
@ -279,11 +293,12 @@ mod test {
|
||||
use unstable::run_in_bare_thread;
|
||||
use path::Path;
|
||||
use rt::uv::{Loop, Buf, slice_to_uv_buf};
|
||||
use libc::{O_CREAT, O_RDWR, O_RDONLY,
|
||||
S_IWUSR, S_IRUSR}; //NOTE: need defs for S_**GRP|S_**OTH in libc:: ...
|
||||
//S_IRGRP, S_IROTH};
|
||||
use libc::{c_int, O_CREAT, O_RDWR, O_RDONLY,
|
||||
S_IWUSR, S_IRUSR};
|
||||
|
||||
fn file_test_full_simple_impl() {
|
||||
#[test]
|
||||
#[ignore(cfg(windows))] // FIXME #8814
|
||||
fn file_test_full_simple() {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let create_flags = O_RDWR | O_CREAT;
|
||||
@ -302,25 +317,27 @@ mod test {
|
||||
let read_buf = slice_to_uv_buf(read_mem);
|
||||
let read_buf_ptr: *Buf = &read_buf;
|
||||
let p = Path(path_str);
|
||||
do FsRequest::open(&loop_, &p, create_flags as int, mode as int)
|
||||
let open_req = FsRequest::new();
|
||||
do open_req.open(&loop_, &p, create_flags as int, mode as int)
|
||||
|req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let mut fd = FileDescriptor::from_open_req(req);
|
||||
let raw_fd = fd.native_handle();
|
||||
let fd = req.get_result();
|
||||
let buf = unsafe { *write_buf_ptr };
|
||||
do fd.write(&req.get_loop(), buf, -1) |req, uverr| {
|
||||
let fd = FileDescriptor(raw_fd);
|
||||
do fd.close(&req.get_loop()) |req, _| {
|
||||
let loop_ = req.get_loop();
|
||||
let write_req = FsRequest::new();
|
||||
do write_req.write(&req.get_loop(), fd, buf, -1) |req, uverr| {
|
||||
let close_req = FsRequest::new();
|
||||
do close_req.close(&req.get_loop(), fd) |req, _| {
|
||||
assert!(uverr.is_none());
|
||||
do FsRequest::open(&loop_, &Path(path_str), read_flags as int,0)
|
||||
let loop_ = req.get_loop();
|
||||
let open_req = FsRequest::new();
|
||||
do open_req.open(&loop_, &Path(path_str), read_flags as int,0)
|
||||
|req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let mut fd = FileDescriptor::from_open_req(req);
|
||||
let raw_fd = fd.native_handle();
|
||||
let fd = req.get_result();
|
||||
let read_buf = unsafe { *read_buf_ptr };
|
||||
do fd.read(&loop_, read_buf, 0) |req, uverr| {
|
||||
let read_req = FsRequest::new();
|
||||
do read_req.read(&loop_, fd, read_buf, 0) |req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
// we know nread >=0 because uverr is none..
|
||||
@ -334,15 +351,17 @@ mod test {
|
||||
read_buf.base, nread))
|
||||
};
|
||||
assert!(read_str == ~"hello");
|
||||
do FileDescriptor(raw_fd).close(&loop_) |req,uverr| {
|
||||
let close_req = FsRequest::new();
|
||||
do close_req.close(&loop_, fd) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = &req.get_loop();
|
||||
do FsRequest::unlink(loop_, &Path(path_str))
|
||||
let unlink_req = FsRequest::new();
|
||||
do unlink_req.unlink(loop_, &Path(path_str))
|
||||
|_,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -352,7 +371,10 @@ mod test {
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
fn file_test_full_simple_impl_sync() {
|
||||
|
||||
#[test]
|
||||
#[ignore(cfg(windows))] // FIXME #8814
|
||||
fn file_test_full_simple_sync() {
|
||||
do run_in_bare_thread {
|
||||
// setup
|
||||
let mut loop_ = Loop::new();
|
||||
@ -368,26 +390,31 @@ mod test {
|
||||
let write_val = "hello".as_bytes().to_owned();
|
||||
let write_buf = slice_to_uv_buf(write_val);
|
||||
// open/create
|
||||
let result = FsRequest::open_sync(&loop_, &Path(path_str),
|
||||
let open_req = FsRequest::new();
|
||||
let result = open_req.open_sync(&loop_, &Path(path_str),
|
||||
create_flags as int, mode as int);
|
||||
assert!(result.is_ok());
|
||||
let mut fd = FileDescriptor(result.unwrap() as i32);
|
||||
let fd = result.unwrap();
|
||||
// write
|
||||
let result = fd.write_sync(&loop_, write_buf, -1);
|
||||
let write_req = FsRequest::new();
|
||||
let result = write_req.write_sync(&loop_, fd, write_buf, -1);
|
||||
assert!(result.is_ok());
|
||||
// close
|
||||
let result = fd.close_sync(&loop_);
|
||||
let close_req = FsRequest::new();
|
||||
let result = close_req.close_sync(&loop_, fd);
|
||||
assert!(result.is_ok());
|
||||
// re-open
|
||||
let result = FsRequest::open_sync(&loop_, &Path(path_str),
|
||||
let open_req = FsRequest::new();
|
||||
let result = open_req.open_sync(&loop_, &Path(path_str),
|
||||
read_flags as int,0);
|
||||
assert!(result.is_ok());
|
||||
let len = 1028;
|
||||
let mut fd = FileDescriptor(result.unwrap() as i32);
|
||||
let fd = result.unwrap();
|
||||
// read
|
||||
let read_mem: ~[u8] = vec::from_elem(len, 0u8);
|
||||
let buf = slice_to_uv_buf(read_mem);
|
||||
let result = fd.read_sync(&loop_, buf, 0);
|
||||
let read_req = FsRequest::new();
|
||||
let result = read_req.read_sync(&loop_, fd, buf, 0);
|
||||
assert!(result.is_ok());
|
||||
let nread = result.unwrap();
|
||||
// nread == 0 would be EOF.. we know it's >= zero because otherwise
|
||||
@ -397,31 +424,23 @@ mod test {
|
||||
read_mem.slice(0, nread as uint));
|
||||
assert!(read_str == ~"hello");
|
||||
// close
|
||||
let result = fd.close_sync(&loop_);
|
||||
let close_req = FsRequest::new();
|
||||
let result = close_req.close_sync(&loop_, fd);
|
||||
assert!(result.is_ok());
|
||||
// unlink
|
||||
let result = FsRequest::unlink_sync(&loop_, &Path(path_str));
|
||||
let unlink_req = FsRequest::new();
|
||||
let result = unlink_req.unlink_sync(&loop_, &Path(path_str));
|
||||
assert!(result.is_ok());
|
||||
} else { fail!("nread was 0.. wudn't expectin' that."); }
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_full_simple() {
|
||||
file_test_full_simple_impl();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_full_simple_sync() {
|
||||
file_test_full_simple_impl_sync();
|
||||
}
|
||||
|
||||
fn naive_print(loop_: &Loop, input: &str) {
|
||||
let mut stdout = FileDescriptor(STDOUT_FILENO);
|
||||
let write_val = input.as_bytes();
|
||||
let write_buf = slice_to_uv_buf(write_val);
|
||||
stdout.write_sync(loop_, write_buf, -1);
|
||||
let write_req = FsRequest::new();
|
||||
write_req.write_sync(loop_, stdout, write_buf, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -433,4 +452,129 @@ mod test {
|
||||
loop_.close();
|
||||
};
|
||||
}
|
||||
#[test]
|
||||
fn file_test_stat_simple() {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let path = "./tmp/file_test_stat_simple.txt";
|
||||
let create_flags = O_RDWR |
|
||||
O_CREAT;
|
||||
let mode = S_IWUSR |
|
||||
S_IRUSR;
|
||||
let write_val = "hello".as_bytes().to_owned();
|
||||
let write_buf = slice_to_uv_buf(write_val);
|
||||
let write_buf_ptr: *Buf = &write_buf;
|
||||
let open_req = FsRequest::new();
|
||||
do open_req.open(&loop_, &path, create_flags as int, mode as int)
|
||||
|req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let fd = req.get_result();
|
||||
let buf = unsafe { *write_buf_ptr };
|
||||
let write_req = FsRequest::new();
|
||||
do write_req.write(&req.get_loop(), fd, buf, 0) |req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat_req = FsRequest::new();
|
||||
do stat_req.stat(&loop_, &path) |req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat = req.get_stat();
|
||||
let sz: uint = stat.st_size as uint;
|
||||
assert!(sz > 0);
|
||||
let close_req = FsRequest::new();
|
||||
do close_req.close(&loop_, fd) |req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let unlink_req = FsRequest::new();
|
||||
do unlink_req.unlink(&loop_, &path) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat_req = FsRequest::new();
|
||||
do stat_req.stat(&loop_, &path) |_, uverr| {
|
||||
// should cause an error because the
|
||||
// file doesn't exist anymore
|
||||
assert!(uverr.is_some());
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
loop_.run();
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_test_mk_rm_dir() {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let path = "./tmp/mk_rm_dir";
|
||||
let mode = S_IWUSR |
|
||||
S_IRUSR;
|
||||
let mkdir_req = FsRequest::new();
|
||||
do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat_req = FsRequest::new();
|
||||
do stat_req.stat(&loop_, &path) |req, uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat = req.get_stat();
|
||||
assert!(stat.is_dir());
|
||||
let rmdir_req = FsRequest::new();
|
||||
do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let stat_req = FsRequest::new();
|
||||
do stat_req.stat(&loop_, &path) |req, uverr| {
|
||||
assert!(uverr.is_some());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
loop_.run();
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn file_test_mkdir_chokes_on_double_create() {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let path = "./tmp/double_create_dir";
|
||||
let mode = S_IWUSR |
|
||||
S_IRUSR;
|
||||
let mkdir_req = FsRequest::new();
|
||||
do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
let mkdir_req = FsRequest::new();
|
||||
do mkdir_req.mkdir(&loop_, &path, mode as int) |req,uverr| {
|
||||
assert!(uverr.is_some());
|
||||
let loop_ = req.get_loop();
|
||||
let stat = req.get_stat();
|
||||
let rmdir_req = FsRequest::new();
|
||||
do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
|
||||
assert!(uverr.is_none());
|
||||
let loop_ = req.get_loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
loop_.run();
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn file_test_rmdir_chokes_on_nonexistant_path() {
|
||||
do run_in_bare_thread {
|
||||
let mut loop_ = Loop::new();
|
||||
let path = "./tmp/never_existed_dir";
|
||||
let rmdir_req = FsRequest::new();
|
||||
do rmdir_req.rmdir(&loop_, &path) |req,uverr| {
|
||||
assert!(uverr.is_some());
|
||||
}
|
||||
loop_.run();
|
||||
loop_.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,11 +32,13 @@ use rt::uv::idle::IdleWatcher;
|
||||
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
|
||||
use rt::uv::addrinfo::GetAddrInfoRequest;
|
||||
use unstable::sync::Exclusive;
|
||||
use path::Path;
|
||||
use super::super::io::support::PathLike;
|
||||
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
|
||||
S_IRUSR, S_IWUSR};
|
||||
use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
|
||||
CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite};
|
||||
CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite,
|
||||
FileStat};
|
||||
use task;
|
||||
|
||||
#[cfg(test)] use container::Container;
|
||||
@ -516,7 +518,6 @@ impl IoFactory for UvIoFactory {
|
||||
|
||||
fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream {
|
||||
let loop_ = Loop {handle: self.uv_loop().native_handle()};
|
||||
let fd = file::FileDescriptor(fd);
|
||||
let home = get_handle_to_current_scheduler!();
|
||||
~UvFileStream::new(loop_, fd, close_on_drop, home) as ~RtioFileStream
|
||||
}
|
||||
@ -547,15 +548,16 @@ impl IoFactory for UvIoFactory {
|
||||
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 file::FsRequest::open(self.uv_loop(), path, flags as int, create_mode as int)
|
||||
do open_req.open(self.uv_loop(), path, flags as int, create_mode as int)
|
||||
|req,err| {
|
||||
if err.is_none() {
|
||||
let loop_ = Loop {handle: req.get_loop().native_handle()};
|
||||
let home = get_handle_to_current_scheduler!();
|
||||
let fd = file::FileDescriptor(req.get_result());
|
||||
let fd = req.get_result() as c_int;
|
||||
let fs = ~UvFileStream::new(
|
||||
loop_, fd, true, home) as ~RtioFileStream;
|
||||
let res = Ok(fs);
|
||||
@ -570,7 +572,7 @@ impl IoFactory for UvIoFactory {
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
};
|
||||
assert!(!result_cell.is_empty());
|
||||
return result_cell.take();
|
||||
}
|
||||
@ -581,10 +583,11 @@ impl IoFactory for UvIoFactory {
|
||||
let path_cell = Cell::new(path);
|
||||
do task::unkillable { // FIXME(#8674)
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
let unlink_req = FsRequest::new();
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
let path = path_cell.take();
|
||||
do file::FsRequest::unlink(self.uv_loop(), path) |_, err| {
|
||||
do unlink_req.unlink(self.uv_loop(), path) |_, err| {
|
||||
let res = match err {
|
||||
None => Ok(()),
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
@ -593,11 +596,48 @@ impl IoFactory for UvIoFactory {
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
assert!(!result_cell.is_empty());
|
||||
return result_cell.take();
|
||||
}
|
||||
fn fs_stat<P: PathLike>(&mut self, path: &P) -> 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();
|
||||
let path_str = path.path_as_str(|p| p.to_owned());
|
||||
do stat_req.stat(self.uv_loop(), path)
|
||||
|req,err| {
|
||||
if err.is_none() {
|
||||
let stat = req.get_stat();
|
||||
let res = Ok(FileStat {
|
||||
path: Path(path_str),
|
||||
is_file: stat.is_file(),
|
||||
is_dir: stat.is_dir()
|
||||
});
|
||||
unsafe { (*result_cell_ptr).put_back(res); }
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
} else {
|
||||
let res = Err(uv_error_to_io_error(err.unwrap()));
|
||||
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 get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError> {
|
||||
let result_cell = Cell::new_empty();
|
||||
@ -629,6 +669,9 @@ impl IoFactory for UvIoFactory {
|
||||
assert!(!result_cell.is_empty());
|
||||
return result_cell.take();
|
||||
}
|
||||
//fn fs_fstat(&mut self, _fd: c_int) -> Result<FileStat, IoError> {
|
||||
// Ok(FileStat)
|
||||
//}
|
||||
}
|
||||
|
||||
pub struct UvTcpListener {
|
||||
@ -1173,7 +1216,7 @@ impl RtioTimer for UvTimer {
|
||||
|
||||
pub struct UvFileStream {
|
||||
loop_: Loop,
|
||||
fd: file::FileDescriptor,
|
||||
fd: c_int,
|
||||
close_on_drop: bool,
|
||||
home: SchedHandle
|
||||
}
|
||||
@ -1183,7 +1226,7 @@ impl HomingIO for UvFileStream {
|
||||
}
|
||||
|
||||
impl UvFileStream {
|
||||
fn new(loop_: Loop, fd: file::FileDescriptor, close_on_drop: bool,
|
||||
fn new(loop_: Loop, fd: c_int, close_on_drop: bool,
|
||||
home: SchedHandle) -> UvFileStream {
|
||||
UvFileStream {
|
||||
loop_: loop_,
|
||||
@ -1200,7 +1243,8 @@ impl UvFileStream {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.fd.read(&self_.loop_, buf, offset) |req, uverr| {
|
||||
let read_req = file::FsRequest::new();
|
||||
do read_req.read(&self_.loop_, self_.fd, buf, offset) |req, uverr| {
|
||||
let res = match uverr {
|
||||
None => Ok(req.get_result() as int),
|
||||
Some(err) => Err(uv_error_to_io_error(err))
|
||||
@ -1221,7 +1265,8 @@ impl UvFileStream {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.fd.write(&self_.loop_, buf, offset) |_, uverr| {
|
||||
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))
|
||||
@ -1238,7 +1283,7 @@ impl UvFileStream {
|
||||
Result<u64, IoError>{
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
unsafe {
|
||||
match lseek((*self.fd), pos as off_t, whence) {
|
||||
match lseek(self.fd, pos as off_t, whence) {
|
||||
-1 => {
|
||||
Err(IoError {
|
||||
kind: OtherIoError,
|
||||
@ -1259,7 +1304,8 @@ impl Drop for UvFileStream {
|
||||
do self_.home_for_io_with_sched |self_, scheduler| {
|
||||
do scheduler.deschedule_running_task_and_then |_, task| {
|
||||
let task_cell = Cell::new(task);
|
||||
do self_.fd.close(&self.loop_) |_,_| {
|
||||
let close_req = file::FsRequest::new();
|
||||
do close_req.close(&self.loop_, self_.fd) |_,_| {
|
||||
let scheduler: ~Scheduler = Local::take();
|
||||
scheduler.resume_blocked_task_immediately(task_cell.take());
|
||||
};
|
||||
|
@ -96,6 +96,59 @@ pub type uv_fs_t = c_void;
|
||||
pub type uv_udp_send_t = c_void;
|
||||
pub type uv_getaddrinfo_t = c_void;
|
||||
|
||||
pub struct uv_timespec_t {
|
||||
tv_sec: libc::c_long,
|
||||
tv_nsec: libc::c_long
|
||||
}
|
||||
|
||||
pub struct uv_stat_t {
|
||||
st_dev: libc::uint64_t,
|
||||
st_mode: libc::uint64_t,
|
||||
st_nlink: libc::uint64_t,
|
||||
st_uid: libc::uint64_t,
|
||||
st_gid: libc::uint64_t,
|
||||
st_rdev: libc::uint64_t,
|
||||
st_ino: libc::uint64_t,
|
||||
st_size: libc::uint64_t,
|
||||
st_blksize: libc::uint64_t,
|
||||
st_blocks: libc::uint64_t,
|
||||
st_flags: libc::uint64_t,
|
||||
st_gen: libc::uint64_t,
|
||||
st_atim: uv_timespec_t,
|
||||
st_mtim: uv_timespec_t,
|
||||
st_ctim: uv_timespec_t,
|
||||
st_birthtim: uv_timespec_t
|
||||
}
|
||||
|
||||
impl uv_stat_t {
|
||||
pub fn new() -> uv_stat_t {
|
||||
uv_stat_t {
|
||||
st_dev: 0,
|
||||
st_mode: 0,
|
||||
st_nlink: 0,
|
||||
st_uid: 0,
|
||||
st_gid: 0,
|
||||
st_rdev: 0,
|
||||
st_ino: 0,
|
||||
st_size: 0,
|
||||
st_blksize: 0,
|
||||
st_blocks: 0,
|
||||
st_flags: 0,
|
||||
st_gen: 0,
|
||||
st_atim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
|
||||
st_mtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
|
||||
st_ctim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
|
||||
st_birthtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 }
|
||||
}
|
||||
}
|
||||
pub fn is_file(&self) -> bool {
|
||||
((self.st_mode as c_int) & libc::S_IFMT) == libc::S_IFREG
|
||||
}
|
||||
pub fn is_dir(&self) -> bool {
|
||||
((self.st_mode as c_int) & libc::S_IFMT) == libc::S_IFDIR
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
pub type uv_idle_cb = *u8;
|
||||
#[cfg(stage0)]
|
||||
@ -736,6 +789,33 @@ pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int,
|
||||
|
||||
rust_uv_fs_close(loop_ptr, req, fd, cb)
|
||||
}
|
||||
pub unsafe fn fs_stat(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_fs_stat(loop_ptr, req, path, cb)
|
||||
}
|
||||
pub unsafe fn fs_fstat(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_fs_fstat(loop_ptr, req, fd, cb)
|
||||
}
|
||||
pub unsafe fn fs_mkdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, mode: int,
|
||||
cb: *u8) -> c_int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_fs_mkdir(loop_ptr, req, path, mode as c_int, cb)
|
||||
}
|
||||
pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
|
||||
cb: *u8) -> c_int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_fs_rmdir(loop_ptr, req, path, cb)
|
||||
}
|
||||
pub unsafe fn populate_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
rust_uv_populate_uv_stat(req_in, stat_out)
|
||||
}
|
||||
pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
@ -928,7 +1008,14 @@ extern {
|
||||
buf: *c_void, len: c_uint, offset: i64, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
|
||||
cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_stat(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_fstat(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_mkdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
|
||||
mode: c_int, cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
|
||||
cb: *u8) -> c_int;
|
||||
fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
|
||||
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_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;
|
||||
|
@ -551,3 +551,45 @@ extern "C" uv_loop_t*
|
||||
rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) {
|
||||
return req->loop;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
rust_uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
return uv_fs_stat(loop, req, path, cb);
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
|
||||
return uv_fs_fstat(loop, req, file, cb);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) {
|
||||
stat_out->st_dev = req_in->statbuf.st_dev;
|
||||
stat_out->st_mode = req_in->statbuf.st_mode;
|
||||
stat_out->st_nlink = req_in->statbuf.st_nlink;
|
||||
stat_out->st_uid = req_in->statbuf.st_uid;
|
||||
stat_out->st_gid = req_in->statbuf.st_gid;
|
||||
stat_out->st_rdev = req_in->statbuf.st_rdev;
|
||||
stat_out->st_ino = req_in->statbuf.st_ino;
|
||||
stat_out->st_size = req_in->statbuf.st_size;
|
||||
stat_out->st_blksize = req_in->statbuf.st_blksize;
|
||||
stat_out->st_blocks = req_in->statbuf.st_blocks;
|
||||
stat_out->st_flags = req_in->statbuf.st_flags;
|
||||
stat_out->st_gen = req_in->statbuf.st_gen;
|
||||
stat_out->st_atim.tv_sec = req_in->statbuf.st_atim.tv_sec;
|
||||
stat_out->st_atim.tv_nsec = req_in->statbuf.st_atim.tv_nsec;
|
||||
stat_out->st_mtim.tv_sec = req_in->statbuf.st_mtim.tv_sec;
|
||||
stat_out->st_mtim.tv_nsec = req_in->statbuf.st_mtim.tv_nsec;
|
||||
stat_out->st_ctim.tv_sec = req_in->statbuf.st_ctim.tv_sec;
|
||||
stat_out->st_ctim.tv_nsec = req_in->statbuf.st_ctim.tv_nsec;
|
||||
stat_out->st_birthtim.tv_sec = req_in->statbuf.st_birthtim.tv_sec;
|
||||
stat_out->st_birthtim.tv_nsec = req_in->statbuf.st_birthtim.tv_nsec;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
rust_uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) {
|
||||
return uv_fs_mkdir(loop, req, path, mode, cb);
|
||||
}
|
||||
extern "C" int
|
||||
rust_uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
|
||||
return uv_fs_rmdir(loop, req, path, cb);
|
||||
}
|
||||
|
@ -114,7 +114,12 @@ rust_uv_fs_read
|
||||
rust_uv_fs_close
|
||||
rust_uv_get_result_from_fs_req
|
||||
rust_uv_get_loop_from_fs_req
|
||||
rust_uv_fs_stat
|
||||
rust_uv_fs_fstat
|
||||
rust_uv_fs_req_cleanup
|
||||
rust_uv_populate_uv_stat
|
||||
rust_uv_fs_mkdir
|
||||
rust_uv_fs_rmdir
|
||||
rust_dbg_lock_create
|
||||
rust_dbg_lock_destroy
|
||||
rust_dbg_lock_lock
|
||||
|
Loading…
Reference in New Issue
Block a user