Skip to content

Commit c135cb2

Browse files
committedSep 17, 2013
auto merge of #9235 : olsonjeffery/rust/newrt_file_io_1, r=thestinger
A quick rundown: - added `file::{readdir, stat, mkdir, rmdir}` - Added access-constrained versions of `FileStream`; `FileReader` and `FileWriter` respectively - big rework in `uv::file` .. most actions are by-val-self methods on `FsRequest`; `FileDescriptor` has gone the way of the dinosaurs - playing nice w/ homing IO (I just copied ecr's work, hehe), etc - added `FileInfo` trait, with an impl for `Path` - wrapper for file-specific actions, with the file path always implied by self's value - has the means to create `FileReader` & `FileWriter` (this isn't exposed in the top-level free function API) - has "safe" wrappers for `stat()` that won't throw in the event of non-existence/error (in this case, I mean `is_file` and `exists`) - actions should fail if done on non-regular-files, as appropriate - added `DirectoryInfo` trait, with an impl for `Path` - pretty much ditto above, but for directories - added `readdir` (!!) to iterate over entries in a dir as a `~[Path]` (this was *brutal* to get working) ...<del>and lots of other stuff</del>not really. Do your worst!
·
1.88.00.8
2 parents 9e8fb4a + 70152ff commit c135cb2

File tree

10 files changed

+1444
-231
lines changed

10 files changed

+1444
-231
lines changed
 

‎src/libstd/os.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,16 +196,7 @@ pub fn env() -> ~[(~str,~str)] {
196196
if (ch as uint == 0) {
197197
fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
198198
}
199-
let mut curr_ptr: uint = ch as uint;
200-
let mut result = ~[];
201-
while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
202-
let env_pair = str::raw::from_c_str(
203-
curr_ptr as *libc::c_char);
204-
result.push(env_pair);
205-
curr_ptr +=
206-
libc::strlen(curr_ptr as *libc::c_char) as uint
207-
+ 1;
208-
}
199+
let result = str::raw::from_c_multistring(ch as *libc::c_char, None);
209200
FreeEnvironmentStringsA(ch);
210201
result
211202
}

‎src/libstd/rt/io/file.rs

Lines changed: 659 additions & 20 deletions
Large diffs are not rendered by default.

‎src/libstd/rt/io/mod.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ Out of scope
245245
use prelude::*;
246246
use to_str::ToStr;
247247
use str::{StrSlice, OwnedStr};
248+
use path::Path;
248249

249250
// Reexports
250251
pub use self::stdio::stdin;
@@ -357,7 +358,10 @@ pub enum IoErrorKind {
357358
Closed,
358359
ConnectionRefused,
359360
ConnectionReset,
360-
BrokenPipe
361+
BrokenPipe,
362+
PathAlreadyExists,
363+
PathDoesntExist,
364+
MismatchedFileTypeForOperation
361365
}
362366

363367
// FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -373,7 +377,10 @@ impl ToStr for IoErrorKind {
373377
Closed => ~"Closed",
374378
ConnectionRefused => ~"ConnectionRefused",
375379
ConnectionReset => ~"ConnectionReset",
376-
BrokenPipe => ~"BrokenPipe"
380+
BrokenPipe => ~"BrokenPipe",
381+
PathAlreadyExists => ~"PathAlreadyExists",
382+
PathDoesntExist => ~"PathDoesntExist",
383+
MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation"
377384
}
378385
}
379386
}
@@ -394,6 +401,18 @@ condition! {
394401
pub read_error: super::IoError -> ();
395402
}
396403

404+
/// Helper for wrapper calls where you want to
405+
/// ignore any io_errors that might be raised
406+
pub fn ignore_io_error<T>(cb: &fn() -> T) -> T {
407+
do io_error::cond.trap(|_| {
408+
// just swallow the error.. downstream users
409+
// who can make a decision based on a None result
410+
// won't care
411+
}).inside {
412+
cb()
413+
}
414+
}
415+
397416
pub trait Reader {
398417
/// Read bytes, up to the length of `buf` and place them in `buf`.
399418
/// Returns the number of bytes read. The number of bytes read my
@@ -596,3 +615,22 @@ pub enum FileAccess {
596615
Write,
597616
ReadWrite
598617
}
618+
619+
pub struct FileStat {
620+
/// A `Path` object containing information about the `PathInfo`'s location
621+
path: Path,
622+
/// `true` if the file pointed at by the `PathInfo` is a regular file
623+
is_file: bool,
624+
/// `true` if the file pointed at by the `PathInfo` is a directory
625+
is_dir: bool,
626+
/// The file pointed at by the `PathInfo`'s size in bytes
627+
size: u64,
628+
/// The file pointed at by the `PathInfo`'s creation time
629+
created: u64,
630+
/// The file pointed at by the `PathInfo`'s last-modification time in
631+
/// platform-dependent msecs
632+
modified: u64,
633+
/// The file pointed at by the `PathInfo`'s last-accessd time (e.g. read) in
634+
/// platform-dependent msecs
635+
accessed: u64,
636+
}

‎src/libstd/rt/rtio.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rt::uv::uvio;
1818
use path::Path;
1919
use super::io::support::PathLike;
2020
use super::io::{SeekStyle};
21-
use super::io::{FileMode, FileAccess};
21+
use super::io::{FileMode, FileAccess, FileStat};
2222

2323
// XXX: ~object doesn't work currently so these are some placeholder
2424
// types to use instead
@@ -74,6 +74,11 @@ pub trait IoFactory {
7474
-> Result<~RtioFileStream, IoError>;
7575
fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
7676
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
77+
fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
78+
fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
79+
fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
80+
fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
81+
Result<~[Path], IoError>;
7782
}
7883

7984
pub trait RtioTcpListener : RtioSocket {

‎src/libstd/rt/uv/file.rs

Lines changed: 401 additions & 181 deletions
Large diffs are not rendered by default.

‎src/libstd/rt/uv/uvio.rs

Lines changed: 130 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ use rt::uv::idle::IdleWatcher;
3232
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
3333
use rt::uv::addrinfo::GetAddrInfoRequest;
3434
use unstable::sync::Exclusive;
35+
use path::Path;
3536
use super::super::io::support::PathLike;
3637
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
37-
S_IRUSR, S_IWUSR};
38+
S_IRUSR, S_IWUSR, S_IRWXU};
3839
use rt::io::{FileMode, FileAccess, OpenOrCreate, Open, Create,
39-
CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite};
40+
CreateOrTruncate, Append, Truncate, Read, Write, ReadWrite,
41+
FileStat};
4042
use task;
4143

4244
#[cfg(test)] use container::Container;
@@ -407,6 +409,36 @@ impl UvIoFactory {
407409
}
408410
}
409411

412+
/// Helper for a variety of simple uv_fs_* functions that
413+
/// have no ret val
414+
fn uv_fs_helper<P: PathLike>(loop_: &mut Loop, path: &P,
415+
cb: ~fn(&mut FsRequest, &mut Loop, &P,
416+
~fn(&FsRequest, Option<UvError>)))
417+
-> Result<(), IoError> {
418+
let result_cell = Cell::new_empty();
419+
let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
420+
let path_cell = Cell::new(path);
421+
do task::unkillable { // FIXME(#8674)
422+
let scheduler: ~Scheduler = Local::take();
423+
let mut new_req = FsRequest::new();
424+
do scheduler.deschedule_running_task_and_then |_, task| {
425+
let task_cell = Cell::new(task);
426+
let path = path_cell.take();
427+
do cb(&mut new_req, loop_, path) |_, err| {
428+
let res = match err {
429+
None => Ok(()),
430+
Some(err) => Err(uv_error_to_io_error(err))
431+
};
432+
unsafe { (*result_cell_ptr).put_back(res); }
433+
let scheduler: ~Scheduler = Local::take();
434+
scheduler.resume_blocked_task_immediately(task_cell.take());
435+
};
436+
}
437+
}
438+
assert!(!result_cell.is_empty());
439+
return result_cell.take();
440+
}
441+
410442
impl IoFactory for UvIoFactory {
411443
// Connect to an address and return a new stream
412444
// NB: This blocks the task waiting on the connection.
@@ -512,7 +544,6 @@ impl IoFactory for UvIoFactory {
512544

513545
fn fs_from_raw_fd(&mut self, fd: c_int, close_on_drop: bool) -> ~RtioFileStream {
514546
let loop_ = Loop {handle: self.uv_loop().native_handle()};
515-
let fd = file::FileDescriptor(fd);
516547
let home = get_handle_to_current_scheduler!();
517548
~UvFileStream::new(loop_, fd, close_on_drop, home) as ~RtioFileStream
518549
}
@@ -543,15 +574,16 @@ impl IoFactory for UvIoFactory {
543574
let path_cell = Cell::new(path);
544575
do task::unkillable { // FIXME(#8674)
545576
let scheduler: ~Scheduler = Local::take();
577+
let open_req = file::FsRequest::new();
546578
do scheduler.deschedule_running_task_and_then |_, task| {
547579
let task_cell = Cell::new(task);
548580
let path = path_cell.take();
549-
do file::FsRequest::open(self.uv_loop(), path, flags as int, create_mode as int)
581+
do open_req.open(self.uv_loop(), path, flags as int, create_mode as int)
550582
|req,err| {
551583
if err.is_none() {
552584
let loop_ = Loop {handle: req.get_loop().native_handle()};
553585
let home = get_handle_to_current_scheduler!();
554-
let fd = file::FileDescriptor(req.get_result());
586+
let fd = req.get_result() as c_int;
555587
let fs = ~UvFileStream::new(
556588
loop_, fd, true, home) as ~RtioFileStream;
557589
let res = Ok(fs);
@@ -566,31 +598,56 @@ impl IoFactory for UvIoFactory {
566598
}
567599
};
568600
};
569-
}
601+
};
570602
assert!(!result_cell.is_empty());
571603
return result_cell.take();
572604
}
573605

574606
fn fs_unlink<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
607+
do uv_fs_helper(self.uv_loop(), path) |unlink_req, l, p, cb| {
608+
do unlink_req.unlink(l, p) |req, err| {
609+
cb(req, err)
610+
};
611+
}
612+
}
613+
fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError> {
614+
use str::StrSlice;
575615
let result_cell = Cell::new_empty();
576-
let result_cell_ptr: *Cell<Result<(), IoError>> = &result_cell;
616+
let result_cell_ptr: *Cell<Result<FileStat,
617+
IoError>> = &result_cell;
577618
let path_cell = Cell::new(path);
578619
do task::unkillable { // FIXME(#8674)
579620
let scheduler: ~Scheduler = Local::take();
621+
let stat_req = file::FsRequest::new();
580622
do scheduler.deschedule_running_task_and_then |_, task| {
581623
let task_cell = Cell::new(task);
582624
let path = path_cell.take();
583-
do file::FsRequest::unlink(self.uv_loop(), path) |_, err| {
625+
let path_str = path.path_as_str(|p| p.to_owned());
626+
do stat_req.stat(self.uv_loop(), path)
627+
|req,err| {
584628
let res = match err {
585-
None => Ok(()),
586-
Some(err) => Err(uv_error_to_io_error(err))
629+
None => {
630+
let stat = req.get_stat();
631+
Ok(FileStat {
632+
path: Path(path_str),
633+
is_file: stat.is_file(),
634+
is_dir: stat.is_dir(),
635+
size: stat.st_size,
636+
created: stat.st_ctim.tv_sec as u64,
637+
modified: stat.st_mtim.tv_sec as u64,
638+
accessed: stat.st_atim.tv_sec as u64
639+
})
640+
},
641+
Some(e) => {
642+
Err(uv_error_to_io_error(e))
643+
}
587644
};
588645
unsafe { (*result_cell_ptr).put_back(res); }
589646
let scheduler: ~Scheduler = Local::take();
590647
scheduler.resume_blocked_task_immediately(task_cell.take());
591648
};
592649
};
593-
}
650+
};
594651
assert!(!result_cell.is_empty());
595652
return result_cell.take();
596653
}
@@ -625,6 +682,59 @@ impl IoFactory for UvIoFactory {
625682
assert!(!result_cell.is_empty());
626683
return result_cell.take();
627684
}
685+
fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
686+
let mode = S_IRWXU as int;
687+
do uv_fs_helper(self.uv_loop(), path) |mkdir_req, l, p, cb| {
688+
do mkdir_req.mkdir(l, p, mode as int) |req, err| {
689+
cb(req, err)
690+
};
691+
}
692+
}
693+
fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError> {
694+
do uv_fs_helper(self.uv_loop(), path) |rmdir_req, l, p, cb| {
695+
do rmdir_req.rmdir(l, p) |req, err| {
696+
cb(req, err)
697+
};
698+
}
699+
}
700+
fn fs_readdir<P: PathLike>(&mut self, path: &P, flags: c_int) ->
701+
Result<~[Path], IoError> {
702+
use str::StrSlice;
703+
let result_cell = Cell::new_empty();
704+
let result_cell_ptr: *Cell<Result<~[Path],
705+
IoError>> = &result_cell;
706+
let path_cell = Cell::new(path);
707+
do task::unkillable { // FIXME(#8674)
708+
let scheduler: ~Scheduler = Local::take();
709+
let stat_req = file::FsRequest::new();
710+
do scheduler.deschedule_running_task_and_then |_, task| {
711+
let task_cell = Cell::new(task);
712+
let path = path_cell.take();
713+
let path_str = path.path_as_str(|p| p.to_owned());
714+
do stat_req.readdir(self.uv_loop(), path, flags)
715+
|req,err| {
716+
let res = match err {
717+
None => {
718+
let rel_paths = req.get_paths();
719+
let mut paths = ~[];
720+
for r in rel_paths.iter() {
721+
paths.push(Path(path_str+"/"+*r));
722+
}
723+
Ok(paths)
724+
},
725+
Some(e) => {
726+
Err(uv_error_to_io_error(e))
727+
}
728+
};
729+
unsafe { (*result_cell_ptr).put_back(res); }
730+
let scheduler: ~Scheduler = Local::take();
731+
scheduler.resume_blocked_task_immediately(task_cell.take());
732+
};
733+
};
734+
};
735+
assert!(!result_cell.is_empty());
736+
return result_cell.take();
737+
}
628738
}
629739

630740
pub struct UvTcpListener {
@@ -1163,7 +1273,7 @@ impl RtioTimer for UvTimer {
11631273

11641274
pub struct UvFileStream {
11651275
loop_: Loop,
1166-
fd: file::FileDescriptor,
1276+
fd: c_int,
11671277
close_on_drop: bool,
11681278
home: SchedHandle
11691279
}
@@ -1173,7 +1283,7 @@ impl HomingIO for UvFileStream {
11731283
}
11741284

11751285
impl UvFileStream {
1176-
fn new(loop_: Loop, fd: file::FileDescriptor, close_on_drop: bool,
1286+
fn new(loop_: Loop, fd: c_int, close_on_drop: bool,
11771287
home: SchedHandle) -> UvFileStream {
11781288
UvFileStream {
11791289
loop_: loop_,
@@ -1190,7 +1300,8 @@ impl UvFileStream {
11901300
do scheduler.deschedule_running_task_and_then |_, task| {
11911301
let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
11921302
let task_cell = Cell::new(task);
1193-
do self_.fd.read(&self_.loop_, buf, offset) |req, uverr| {
1303+
let read_req = file::FsRequest::new();
1304+
do read_req.read(&self_.loop_, self_.fd, buf, offset) |req, uverr| {
11941305
let res = match uverr {
11951306
None => Ok(req.get_result() as int),
11961307
Some(err) => Err(uv_error_to_io_error(err))
@@ -1211,7 +1322,8 @@ impl UvFileStream {
12111322
do scheduler.deschedule_running_task_and_then |_, task| {
12121323
let buf = unsafe { slice_to_uv_buf(*buf_ptr) };
12131324
let task_cell = Cell::new(task);
1214-
do self_.fd.write(&self_.loop_, buf, offset) |_, uverr| {
1325+
let write_req = file::FsRequest::new();
1326+
do write_req.write(&self_.loop_, self_.fd, buf, offset) |_, uverr| {
12151327
let res = match uverr {
12161328
None => Ok(()),
12171329
Some(err) => Err(uv_error_to_io_error(err))
@@ -1228,7 +1340,7 @@ impl UvFileStream {
12281340
Result<u64, IoError>{
12291341
#[fixed_stack_segment]; #[inline(never)];
12301342
unsafe {
1231-
match lseek((*self.fd), pos as off_t, whence) {
1343+
match lseek(self.fd, pos as off_t, whence) {
12321344
-1 => {
12331345
Err(IoError {
12341346
kind: OtherIoError,
@@ -1249,7 +1361,8 @@ impl Drop for UvFileStream {
12491361
do self_.home_for_io_with_sched |self_, scheduler| {
12501362
do scheduler.deschedule_running_task_and_then |_, task| {
12511363
let task_cell = Cell::new(task);
1252-
do self_.fd.close(&self.loop_) |_,_| {
1364+
let close_req = file::FsRequest::new();
1365+
do close_req.close(&self.loop_, self_.fd) |_,_| {
12531366
let scheduler: ~Scheduler = Local::take();
12541367
scheduler.resume_blocked_task_immediately(task_cell.take());
12551368
};

‎src/libstd/rt/uv/uvll.rs

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,59 @@ pub type uv_fs_t = c_void;
9696
pub type uv_udp_send_t = c_void;
9797
pub type uv_getaddrinfo_t = c_void;
9898

99+
pub struct uv_timespec_t {
100+
tv_sec: libc::c_long,
101+
tv_nsec: libc::c_long
102+
}
103+
104+
pub struct uv_stat_t {
105+
st_dev: libc::uint64_t,
106+
st_mode: libc::uint64_t,
107+
st_nlink: libc::uint64_t,
108+
st_uid: libc::uint64_t,
109+
st_gid: libc::uint64_t,
110+
st_rdev: libc::uint64_t,
111+
st_ino: libc::uint64_t,
112+
st_size: libc::uint64_t,
113+
st_blksize: libc::uint64_t,
114+
st_blocks: libc::uint64_t,
115+
st_flags: libc::uint64_t,
116+
st_gen: libc::uint64_t,
117+
st_atim: uv_timespec_t,
118+
st_mtim: uv_timespec_t,
119+
st_ctim: uv_timespec_t,
120+
st_birthtim: uv_timespec_t
121+
}
122+
123+
impl uv_stat_t {
124+
pub fn new() -> uv_stat_t {
125+
uv_stat_t {
126+
st_dev: 0,
127+
st_mode: 0,
128+
st_nlink: 0,
129+
st_uid: 0,
130+
st_gid: 0,
131+
st_rdev: 0,
132+
st_ino: 0,
133+
st_size: 0,
134+
st_blksize: 0,
135+
st_blocks: 0,
136+
st_flags: 0,
137+
st_gen: 0,
138+
st_atim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
139+
st_mtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
140+
st_ctim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 },
141+
st_birthtim: uv_timespec_t { tv_sec: 0, tv_nsec: 0 }
142+
}
143+
}
144+
pub fn is_file(&self) -> bool {
145+
((self.st_mode) & libc::S_IFMT as libc::uint64_t) == libc::S_IFREG as libc::uint64_t
146+
}
147+
pub fn is_dir(&self) -> bool {
148+
((self.st_mode) & libc::S_IFMT as libc::uint64_t) == libc::S_IFDIR as libc::uint64_t
149+
}
150+
}
151+
99152
#[cfg(stage0)]
100153
pub type uv_idle_cb = *u8;
101154
#[cfg(stage0)]
@@ -736,6 +789,39 @@ pub unsafe fn fs_close(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int,
736789

737790
rust_uv_fs_close(loop_ptr, req, fd, cb)
738791
}
792+
pub unsafe fn fs_stat(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int {
793+
#[fixed_stack_segment]; #[inline(never)];
794+
795+
rust_uv_fs_stat(loop_ptr, req, path, cb)
796+
}
797+
pub unsafe fn fs_fstat(loop_ptr: *uv_loop_t, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int {
798+
#[fixed_stack_segment]; #[inline(never)];
799+
800+
rust_uv_fs_fstat(loop_ptr, req, fd, cb)
801+
}
802+
pub unsafe fn fs_mkdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char, mode: int,
803+
cb: *u8) -> c_int {
804+
#[fixed_stack_segment]; #[inline(never)];
805+
806+
rust_uv_fs_mkdir(loop_ptr, req, path, mode as c_int, cb)
807+
}
808+
pub unsafe fn fs_rmdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
809+
cb: *u8) -> c_int {
810+
#[fixed_stack_segment]; #[inline(never)];
811+
812+
rust_uv_fs_rmdir(loop_ptr, req, path, cb)
813+
}
814+
pub unsafe fn fs_readdir(loop_ptr: *uv_loop_t, req: *uv_fs_t, path: *c_char,
815+
flags: c_int, cb: *u8) -> c_int {
816+
#[fixed_stack_segment]; #[inline(never)];
817+
818+
rust_uv_fs_readdir(loop_ptr, req, path, flags, cb)
819+
}
820+
pub unsafe fn populate_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t) {
821+
#[fixed_stack_segment]; #[inline(never)];
822+
823+
rust_uv_populate_uv_stat(req_in, stat_out)
824+
}
739825
pub unsafe fn fs_req_cleanup(req: *uv_fs_t) {
740826
#[fixed_stack_segment]; #[inline(never)];
741827

@@ -748,6 +834,11 @@ pub unsafe fn get_result_from_fs_req(req: *uv_fs_t) -> c_int {
748834

749835
rust_uv_get_result_from_fs_req(req)
750836
}
837+
pub unsafe fn get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void {
838+
#[fixed_stack_segment]; #[inline(never)];
839+
840+
rust_uv_get_ptr_from_fs_req(req)
841+
}
751842
pub unsafe fn get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t {
752843
#[fixed_stack_segment]; #[inline(never)];
753844

@@ -928,8 +1019,18 @@ extern {
9281019
buf: *c_void, len: c_uint, offset: i64, cb: *u8) -> c_int;
9291020
fn rust_uv_fs_close(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int,
9301021
cb: *u8) -> c_int;
1022+
fn rust_uv_fs_stat(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char, cb: *u8) -> c_int;
1023+
fn rust_uv_fs_fstat(loop_ptr: *c_void, req: *uv_fs_t, fd: c_int, cb: *u8) -> c_int;
1024+
fn rust_uv_fs_mkdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
1025+
mode: c_int, cb: *u8) -> c_int;
1026+
fn rust_uv_fs_rmdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
1027+
cb: *u8) -> c_int;
1028+
fn rust_uv_fs_readdir(loop_ptr: *c_void, req: *uv_fs_t, path: *c_char,
1029+
flags: c_int, cb: *u8) -> c_int;
9311030
fn rust_uv_fs_req_cleanup(req: *uv_fs_t);
1031+
fn rust_uv_populate_uv_stat(req_in: *uv_fs_t, stat_out: *uv_stat_t);
9321032
fn rust_uv_get_result_from_fs_req(req: *uv_fs_t) -> c_int;
1033+
fn rust_uv_get_ptr_from_fs_req(req: *uv_fs_t) -> *libc::c_void;
9331034
fn rust_uv_get_loop_from_fs_req(req: *uv_fs_t) -> *uv_loop_t;
9341035
fn rust_uv_get_loop_from_getaddrinfo_req(req: *uv_fs_t) -> *uv_loop_t;
9351036

‎src/libstd/str.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ static TAG_CONT_U8: u8 = 128u8;
938938

939939
/// Unsafe operations
940940
pub mod raw {
941+
use option::{Option, Some};
941942
use cast;
942943
use libc;
943944
use ptr;
@@ -1091,6 +1092,34 @@ pub mod raw {
10911092
vec::raw::set_len(as_owned_vec(s), new_len)
10921093
}
10931094

1095+
/// Parses a C "multistring", eg windows env values or
1096+
/// the req->ptr result in a uv_fs_readdir() call.
1097+
/// Optionally, a `count` can be passed in, limiting the
1098+
/// parsing to only being done `count`-times.
1099+
#[inline]
1100+
pub unsafe fn from_c_multistring(buf: *libc::c_char, count: Option<uint>) -> ~[~str] {
1101+
#[fixed_stack_segment]; #[inline(never)];
1102+
1103+
let mut curr_ptr: uint = buf as uint;
1104+
let mut result = ~[];
1105+
let mut ctr = 0;
1106+
let (limited_count, limit) = match count {
1107+
Some(limit) => (true, limit),
1108+
None => (false, 0)
1109+
};
1110+
while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char
1111+
&& ((limited_count && ctr < limit) || !limited_count)) {
1112+
let env_pair = from_c_str(
1113+
curr_ptr as *libc::c_char);
1114+
result.push(env_pair);
1115+
curr_ptr +=
1116+
libc::strlen(curr_ptr as *libc::c_char) as uint
1117+
+ 1;
1118+
ctr += 1;
1119+
}
1120+
result
1121+
}
1122+
10941123
/// Sets the length of a string
10951124
///
10961125
/// This will explicitly set the size of the string, without actually
@@ -1106,6 +1135,25 @@ pub mod raw {
11061135
}
11071136
}
11081137
1138+
#[test]
1139+
fn test_str_multistring_parsing() {
1140+
use option::None;
1141+
unsafe {
1142+
let input = bytes!("zero", "\x00", "one", "\x00", "\x00");
1143+
let ptr = vec::raw::to_ptr(input);
1144+
let mut result = from_c_multistring(ptr as *libc::c_char, None);
1145+
assert!(result.len() == 2);
1146+
let mut ctr = 0;
1147+
for x in result.iter() {
1148+
match ctr {
1149+
0 => assert_eq!(x, &~"zero"),
1150+
1 => assert_eq!(x, &~"one"),
1151+
_ => fail!("shouldn't happen!")
1152+
}
1153+
ctr += 1;
1154+
}
1155+
}
1156+
}
11091157
}
11101158
11111159
/*

‎src/rt/rust_uv.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,10 @@ extern "C" int
542542
rust_uv_get_result_from_fs_req(uv_fs_t* req) {
543543
return req->result;
544544
}
545+
extern "C" void*
546+
rust_uv_get_ptr_from_fs_req(uv_fs_t* req) {
547+
return req->ptr;
548+
}
545549
extern "C" uv_loop_t*
546550
rust_uv_get_loop_from_fs_req(uv_fs_t* req) {
547551
return req->loop;
@@ -551,3 +555,50 @@ extern "C" uv_loop_t*
551555
rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) {
552556
return req->loop;
553557
}
558+
559+
extern "C" int
560+
rust_uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
561+
return uv_fs_stat(loop, req, path, cb);
562+
}
563+
extern "C" int
564+
rust_uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
565+
return uv_fs_fstat(loop, req, file, cb);
566+
}
567+
568+
extern "C" void
569+
rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) {
570+
stat_out->st_dev = req_in->statbuf.st_dev;
571+
stat_out->st_mode = req_in->statbuf.st_mode;
572+
stat_out->st_nlink = req_in->statbuf.st_nlink;
573+
stat_out->st_uid = req_in->statbuf.st_uid;
574+
stat_out->st_gid = req_in->statbuf.st_gid;
575+
stat_out->st_rdev = req_in->statbuf.st_rdev;
576+
stat_out->st_ino = req_in->statbuf.st_ino;
577+
stat_out->st_size = req_in->statbuf.st_size;
578+
stat_out->st_blksize = req_in->statbuf.st_blksize;
579+
stat_out->st_blocks = req_in->statbuf.st_blocks;
580+
stat_out->st_flags = req_in->statbuf.st_flags;
581+
stat_out->st_gen = req_in->statbuf.st_gen;
582+
stat_out->st_atim.tv_sec = req_in->statbuf.st_atim.tv_sec;
583+
stat_out->st_atim.tv_nsec = req_in->statbuf.st_atim.tv_nsec;
584+
stat_out->st_mtim.tv_sec = req_in->statbuf.st_mtim.tv_sec;
585+
stat_out->st_mtim.tv_nsec = req_in->statbuf.st_mtim.tv_nsec;
586+
stat_out->st_ctim.tv_sec = req_in->statbuf.st_ctim.tv_sec;
587+
stat_out->st_ctim.tv_nsec = req_in->statbuf.st_ctim.tv_nsec;
588+
stat_out->st_birthtim.tv_sec = req_in->statbuf.st_birthtim.tv_sec;
589+
stat_out->st_birthtim.tv_nsec = req_in->statbuf.st_birthtim.tv_nsec;
590+
}
591+
592+
extern "C" int
593+
rust_uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb) {
594+
return uv_fs_mkdir(loop, req, path, mode, cb);
595+
}
596+
extern "C" int
597+
rust_uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
598+
return uv_fs_rmdir(loop, req, path, cb);
599+
}
600+
601+
extern "C" int
602+
rust_uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb) {
603+
return uv_fs_readdir(loop, req, path, flags, cb);
604+
}

‎src/rt/rustrt.def.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,15 @@ rust_uv_fs_write
113113
rust_uv_fs_read
114114
rust_uv_fs_close
115115
rust_uv_get_result_from_fs_req
116+
rust_uv_get_ptr_from_fs_req
116117
rust_uv_get_loop_from_fs_req
118+
rust_uv_fs_stat
119+
rust_uv_fs_fstat
117120
rust_uv_fs_req_cleanup
121+
rust_uv_populate_uv_stat
122+
rust_uv_fs_mkdir
123+
rust_uv_fs_rmdir
124+
rust_uv_fs_readdir
118125
rust_dbg_lock_create
119126
rust_dbg_lock_destroy
120127
rust_dbg_lock_lock

0 commit comments

Comments
 (0)
Please sign in to comment.