diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs index cab27ee29c1c..2a16a34070d2 100644 --- a/src/libstd/rt/uv/file.rs +++ b/src/libstd/rt/uv/file.rs @@ -11,8 +11,9 @@ use prelude::*; use ptr::null; use libc::c_void; -use rt::uv::{Request, NativeHandle, Loop, FsCallback, - status_to_maybe_uv_error_with_loop}; +use rt::uv::{Request, NativeHandle, Loop, FsCallback, Buf, + status_to_maybe_uv_error_with_loop, + vec_to_uv_buf};//, vec_from_uv_buf}; use rt::uv::uvll; use rt::uv::uvll::*; use path::Path; @@ -30,6 +31,14 @@ pub enum UvFileFlag { O_CREAT, O_TRUNC } +// just want enough to get 0644 +#[allow(non_camel_case_types)] +pub enum UvFileMode { + S_IWUSR, + S_IRUSR, + S_IRGRP, + S_IROTH +} pub fn map_flag(v: UvFileFlag) -> int { unsafe { match v { @@ -41,9 +50,21 @@ pub fn map_flag(v: UvFileFlag) -> int { } } } +pub fn map_mode(v: UvFileMode) -> int { + unsafe { + match v { + S_IWUSR => uvll::get_S_IWUSR() as int, + S_IRUSR => uvll::get_S_IRUSR() as int, + S_IRGRP => uvll::get_S_IRGRP() as int, + S_IROTH => uvll::get_S_IROTH() as int + } + } +} pub struct RequestData { - complete_cb: Option + complete_cb: Option, + buf: Option, + raw_fd: Option } impl FsRequest { @@ -58,7 +79,9 @@ impl FsRequest { pub fn install_req_data(&self, cb: Option) { let fs_req = (self.native_handle()) as *uvll::uv_write_t; let data = ~RequestData { - complete_cb: cb + complete_cb: cb, + buf: None, + raw_fd: None }; unsafe { let data = transmute::<~RequestData, *c_void>(data); @@ -86,10 +109,10 @@ impl FsRequest { fn cleanup_and_delete(self) { unsafe { - uvll::fs_req_cleanup(self.native_handle()); - let data = uvll::get_data_for_uv_handle(self.native_handle()); + let data = uvll::get_data_for_req(self.native_handle()); let _data = transmute::<*c_void, ~RequestData>(data); - uvll::set_data_for_uv_handle(self.native_handle(), null::<()>()); + uvll::set_data_for_req(self.native_handle(), null::<()>()); + uvll::fs_req_cleanup(self.native_handle()); free_req(self.native_handle() as *c_void) } } @@ -121,10 +144,24 @@ impl FileDescriptor { uvll::fs_open(loop_.native_handle(), req.native_handle(), p, flags, mode, complete_cb) as int }) - } - fn close(self, loop_: Loop, cb: FsCallback) -> int { + pub fn write(&self, loop_: Loop, buf: ~[u8], offset: i64, cb: FsCallback) + -> int { + let mut req = FsRequest::new(Some(cb)); + let len = buf.len(); + let buf = vec_to_uv_buf(buf); + let base_ptr = buf.base as *c_void; + req.get_req_data().buf = Some(buf); + req.get_req_data().raw_fd = Some(self.native_handle()); + unsafe { + uvll::fs_write(loop_.native_handle(), req.native_handle(), + self.native_handle(), base_ptr, + len, offset, complete_cb) as int + } + } + + pub fn close(self, loop_: Loop, cb: FsCallback) -> int { let req = FsRequest::new(Some(cb)); unsafe { uvll::fs_close(loop_.native_handle(), req.native_handle(), @@ -170,17 +207,22 @@ mod test { //use rt::test::*; use unstable::run_in_bare_thread; use path::Path; - use rt::uv::Loop; + use rt::uv::{Loop};//, slice_to_uv_buf}; // this is equiv to touch, i guess? fn file_test_touch_impl() { debug!("hello?") do run_in_bare_thread { debug!("In bare thread") - let loop_ = Loop::new(); + let mut loop_ = Loop::new(); let flags = map_flag(O_RDWR) | - map_flag(O_CREAT) | map_flag(O_TRUNC); - do FileDescriptor::open(loop_, Path("./foo.txt"), flags, 0644) + map_flag(O_CREAT); + // 0644 + let mode = map_mode(S_IWUSR) | + map_mode(S_IRUSR) | + map_mode(S_IRGRP) | + map_mode(S_IROTH); + do FileDescriptor::open(loop_, Path("./foo.txt"), flags, mode) |req, uverr| { let loop_ = req.get_loop(); assert!(uverr.is_none()); @@ -189,6 +231,7 @@ mod test { assert!(uverr.is_none()); }; }; + loop_.run(); } } @@ -196,4 +239,56 @@ mod test { fn file_test_touch() { file_test_touch_impl(); } + + fn file_test_tee_impl() { + debug!("hello?") + do run_in_bare_thread { + debug!("In bare thread") + let mut loop_ = Loop::new(); + let flags = map_flag(O_RDWR) | + map_flag(O_CREAT); + // 0644 + let mode = map_mode(S_IWUSR) | + map_mode(S_IRUSR) | + map_mode(S_IRGRP) | + map_mode(S_IROTH); + do FileDescriptor::open(loop_, Path("./file_tee_test.txt"), flags, mode) + |req, uverr| { + let loop_ = req.get_loop(); + assert!(uverr.is_none()); + let fd = FileDescriptor::from_open_req(req); + let msg: ~[u8] = "hello world".as_bytes().to_owned(); + let raw_fd = fd.native_handle(); + do fd.write(loop_, msg, -1) |_, uverr| { + let fd = FileDescriptor(raw_fd); + do fd.close(loop_) |_, _| { + assert!(uverr.is_none()); + }; + }; + }; + loop_.run(); + } + } + + #[test] + fn file_test_tee() { + file_test_tee_impl(); + } + + fn naive_print(input: ~str) { + do run_in_bare_thread { + let mut loop_ = Loop::new(); + let stdout = FileDescriptor(1); + let msg = input.as_bytes().to_owned(); + do stdout.write(loop_, msg, -1) |_, uverr| { + assert!(uverr.is_none()); + }; + loop_.run(); + } + } + + #[test] + fn file_test_println() { + naive_print(~"oh yeah.\n"); + } } diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs index b6cffa754c14..0fbf45fca970 100644 --- a/src/libstd/rt/uv/uvll.rs +++ b/src/libstd/rt/uv/uvll.rs @@ -621,6 +621,10 @@ pub unsafe fn fs_open(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, flags: cb: *u8) -> c_int { rust_uv_fs_open(loop_ptr, req, path, flags as c_int, mode as c_int, cb) } +pub unsafe fn fs_write(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, buf: *c_void, + len: uint, offset: i64, cb: *u8) -> c_int { + rust_uv_fs_write(loop_ptr, req, fd, buf, len as c_uint, offset, cb) +} pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int { rust_uv_fs_close(loop_ptr, req, fd, cb) @@ -630,21 +634,15 @@ pub unsafe fn fs_req_cleanup(req: *uv_fs_t) { } // data access helpers -pub unsafe fn get_O_RDONLY() -> c_int { - rust_uv_get_O_RDONLY() -} -pub unsafe fn get_O_WRONLY() -> c_int { - rust_uv_get_O_WRONLY() -} -pub unsafe fn get_O_RDWR() -> c_int { - rust_uv_get_O_RDWR() -} -pub unsafe fn get_O_CREAT() -> c_int { - rust_uv_get_O_CREAT() -} -pub unsafe fn get_O_TRUNC() -> c_int { - rust_uv_get_O_TRUNC() -} +pub unsafe fn get_O_RDONLY() -> c_int { rust_uv_get_O_RDONLY() } +pub unsafe fn get_O_WRONLY() -> c_int { rust_uv_get_O_WRONLY() } +pub unsafe fn get_O_RDWR() -> c_int { rust_uv_get_O_RDWR() } +pub unsafe fn get_O_CREAT() -> c_int { rust_uv_get_O_CREAT() } +pub unsafe fn get_O_TRUNC() -> c_int { rust_uv_get_O_TRUNC() } +pub unsafe fn get_S_IWUSR() -> c_int { rust_uv_get_S_IWUSR() } +pub unsafe fn get_S_IRUSR() -> c_int { rust_uv_get_S_IRUSR() } +pub unsafe fn get_S_IRGRP() -> c_int { rust_uv_get_S_IRGRP() } +pub unsafe fn get_S_IROTH() -> c_int { rust_uv_get_S_IROTH() } pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int { rust_uv_get_result_from_fs_req(req) } @@ -819,6 +817,8 @@ extern { fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int; fn rust_uv_fs_open(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, flags: c_int, mode: c_int, cb: *u8) -> c_int; + fn rust_uv_fs_write(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int, + 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_req_cleanup(req: *uv_fs_t); @@ -827,6 +827,10 @@ extern { fn rust_uv_get_O_RDWR() -> c_int; fn rust_uv_get_O_CREAT() -> c_int; fn rust_uv_get_O_TRUNC() -> c_int; + fn rust_uv_get_S_IWUSR() -> c_int; + fn rust_uv_get_S_IRUSR() -> c_int; + fn rust_uv_get_S_IRGRP() -> c_int; + fn rust_uv_get_S_IROTH() -> c_int; 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; diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index b5d6e02b46a4..a788b0f71a4a 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -18,16 +18,13 @@ #include #endif +#include #include "uv.h" #include "rust_globals.h" extern "C" void* rust_uv_loop_new() { -// XXX libuv doesn't always ignore SIGPIPE even though we don't need it. -#ifndef __WIN32__ - signal(SIGPIPE, SIG_IGN); -#endif return (void*)uv_loop_new(); } @@ -517,3 +514,45 @@ extern "C" uintptr_t rust_uv_req_type_max() { return UV_REQ_TYPE_MAX; } + +extern "C" int +rust_uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, + int mode, uv_fs_cb cb) { + return uv_fs_open(loop, req, path, flags, mode, cb); +} +extern "C" int +rust_uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) { + return uv_fs_close(loop, req, fd, cb); +} +extern "C" void +rust_uv_fs_req_cleanup(uv_fs_t* req) { + uv_fs_req_cleanup(req); +} +extern "C" int +rust_uv_get_O_RDONLY() { + return O_RDONLY; +} +extern "C" int +rust_uv_get_O_WRONLY() { + return O_WRONLY; +} +extern "C" int +rust_uv_get_O_RDWR() { + return O_RDWR; +} +extern "C" int +rust_uv_get_O_CREAT() { + return O_CREAT; +} +extern "C" int +rust_uv_get_O_TRUNC() { + return O_TRUNC; +} +extern "C" int +rust_uv_get_result_from_fs_req(uv_fs_t* req) { + return req->result; +} +extern "C" uv_loop_t* +rust_uv_get_loop_from_fs_req(uv_fs_t* req) { + return req->loop; +} diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 0e9eefd3018c..d342ffa194ae 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -109,12 +109,17 @@ rust_uv_idle_init rust_uv_idle_start rust_uv_idle_stop rust_uv_fs_open +rust_uv_fs_write rust_uv_fs_close rust_uv_get_O_RDONLY rust_uv_get_O_WRONLY rust_uv_get_O_RDWR rust_uv_get_O_CREAT rust_uv_get_O_TRUNC +rust_uv_get_S_IRUSR +rust_uv_get_S_IWUSR +rust_uv_get_S_IROTH +rust_uv_get_S_IRGRP rust_uv_get_result_from_fs_req rust_uv_get_loop_from_fs_req rust_uv_fs_req_cleanup