Skip to content

Commit 38d2246

Browse files
committed
---
yaml --- r: 80882 b: refs/heads/try c: b49fc4c h: refs/heads/master v: v3
1 parent 4b30bb1 commit 38d2246

File tree

7 files changed

+291
-153
lines changed

7 files changed

+291
-153
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cbd1eefbd350797b783df119fed7956d7e1c74ad
5-
refs/heads/try: 055488df1a6a4500de565ac2531d7bc42dd02f83
5+
refs/heads/try: b49fc4cf4eb7299a08d83ed8880d1002ecef9257
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c

branches/try/src/libstd/rt/io/file.rs

Lines changed: 195 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use prelude::*;
1212
use super::support::PathLike;
1313
use super::{Reader, Writer, Seek};
1414
use super::{SeekStyle,SeekSet, SeekCur, SeekEnd,
15-
Open, Read, Create, ReadWrite};
15+
Open, Read, Write, Create, ReadWrite};
1616
use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
1717
use rt::io::{io_error, read_error, EndOfFile,
1818
FileMode, FileAccess, FileStat};
@@ -57,26 +57,108 @@ pub fn unlink<P: PathLike>(path: &P) {
5757
}
5858
}
5959

60-
/// Abstraction representing *positional* access to a file. In this case,
61-
/// *positional* refers to it keeping an encounter *cursor* of where in the
62-
/// file a subsequent `read` or `write` will begin from. Users of a `FileStream`
63-
/// can `seek` to move the cursor to a given location *within the bounds of the
64-
/// file* and can ask to have the `FileStream` `tell` them the location, in
65-
/// bytes, of the cursor.
66-
///
67-
/// This abstraction is roughly modeled on the access workflow as represented
68-
/// by `open(2)`, `read(2)`, `write(2)` and friends.
60+
/// Create a new directory with default permissions (process user
61+
/// has read/write privs)
62+
pub fn mkdir<P: PathLike>(path: &P) {
63+
let mkdir_result = unsafe {
64+
let io: *mut IoFactoryObject = Local::unsafe_borrow();
65+
(*io).fs_mkdir(path)
66+
};
67+
match mkdir_result {
68+
Ok(_) => (),
69+
Err(ioerr) => {
70+
io_error::cond.raise(ioerr);
71+
}
72+
}
73+
}
74+
/// Removes a directory
75+
pub fn rmdir<P: PathLike>(path: &P) {
76+
let rmdir_result = unsafe {
77+
let io: *mut IoFactoryObject = Local::unsafe_borrow();
78+
(*io).fs_rmdir(path)
79+
};
80+
match rmdir_result {
81+
Ok(_) => (),
82+
Err(ioerr) => {
83+
io_error::cond.raise(ioerr);
84+
}
85+
}
86+
}
87+
88+
/// Given a `rt::io::support::PathLike`, query the file system to get
89+
/// information about a file, directory, etc.
6990
///
70-
/// The `open` and `unlink` static methods are provided to manage creation/removal
71-
/// of files. All other methods operatin on an instance of `FileStream`.
91+
/// Returns a `Some(PathInfo)` on success, and raises a `rt::io::IoError` condition
92+
/// on failure and returns `None`.
93+
pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
94+
let open_result = unsafe {
95+
let io: *mut IoFactoryObject = Local::unsafe_borrow();
96+
(*io).fs_stat(path)
97+
};
98+
match open_result {
99+
Ok(p) => {
100+
Some(p)
101+
},
102+
Err(ioerr) => {
103+
read_error::cond.raise(ioerr);
104+
None
105+
}
106+
}
107+
}
108+
109+
/// Read-only view of file
110+
pub struct FileReader { priv stream: FileStream }
111+
112+
impl Reader for FileReader {
113+
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
114+
self.stream.read(buf)
115+
}
116+
117+
fn eof(&mut self) -> bool {
118+
self.stream.eof()
119+
}
120+
}
121+
122+
impl Seek for FileReader {
123+
fn tell(&self) -> u64 {
124+
self.stream.tell()
125+
}
126+
127+
fn seek(&mut self, pos: i64, style: SeekStyle) {
128+
self.stream.seek(pos, style);
129+
}
130+
}
131+
132+
/// Write-only view of a file
133+
pub struct FileWriter { priv stream: FileStream }
134+
135+
impl Writer for FileWriter {
136+
fn write(&mut self, buf: &[u8]) {
137+
self.stream.write(buf);
138+
}
139+
140+
fn flush(&mut self) {
141+
self.stream.flush();
142+
}
143+
}
144+
145+
impl Seek for FileWriter {
146+
fn tell(&self) -> u64 {
147+
self.stream.tell()
148+
}
149+
150+
fn seek(&mut self, pos: i64, style: SeekStyle) {
151+
self.stream.seek(pos, style);
152+
}
153+
}
154+
155+
/// Internal representation of a FileStream, used to consolidate functionality
156+
/// exposed in the public API
72157
pub struct FileStream {
73158
fd: ~RtioFileStream,
74159
last_nread: int,
75160
}
76161

77-
impl FileStream {
78-
}
79-
80162
impl Reader for FileStream {
81163
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
82164
match self.fd.read(buf) {
@@ -148,69 +230,85 @@ impl Seek for FileStream {
148230
}
149231
}
150232

151-
pub struct FileInfo(Path);
152-
153-
/// FIXME: DOCS
154-
impl<'self> FileInfo {
155-
pub fn new<P: PathLike>(path: &P) -> FileInfo {
156-
do path.path_as_str |p| {
157-
FileInfo(Path(p))
158-
}
159-
}
160-
// FIXME #8873 can't put this in FileSystemInfo
161-
pub fn get_path(&'self self) -> &'self Path {
162-
&(**self)
163-
}
164-
pub fn stat(&self) -> Option<FileStat> {
165-
do io_error::cond.trap(|_| {
233+
/// Represents passive information about a file (primarily exposed
234+
/// via the `stat()` method. Also provides methods for opening
235+
/// a file in various modes/permissions.
236+
pub trait FileInfo<'self> {
237+
/// Get the filesystem path that this `FileInfo` points at,
238+
/// whether it is valid or not. This way, it can be used to
239+
/// to specify a file path of a non-existent file which it
240+
/// later create
241+
fn get_file_path(&'self self) -> &'self Path;
242+
243+
/// Ask the operating system for information about the file
244+
fn stat(&self) -> Option<FileStat> {
245+
use mod_stat = super::file::stat;
246+
do read_error::cond.trap(|_| {
166247
// FIXME: can we do something more useful here?
167248
}).inside {
168-
stat(self.get_path())
249+
mod_stat(self.get_file_path())
169250
}
170251
}
171-
pub fn exists(&self) -> bool {
252+
253+
/// returns `true` if the location pointed at by the enclosing
254+
/// exists on the filesystem
255+
fn file_exists(&self) -> bool {
172256
match self.stat() {
173-
Some(s) => {
174-
match s.is_file {
175-
true => {
176-
true
177-
},
178-
false => {
179-
// FIXME: raise condition?
180-
false
181-
}
182-
}
183-
},
257+
Some(_) => true,
184258
None => false
185259
}
186260
}
187-
pub fn is_file(&self) -> bool {
261+
262+
/// Whether the underlying implemention (be it a file path
263+
/// or active file descriptor) is a "regular file". Will return
264+
/// false for paths to non-existent locations or directories or
265+
/// other non-regular files (named pipes, etc).
266+
fn is_file(&self) -> bool {
188267
match self.stat() {
189268
Some(s) => s.is_file,
190-
None => {
191-
// FIXME: raise condition
192-
false
193-
}
269+
None => false
194270
}
195271
}
196-
pub fn open(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
197-
match self.is_file() {
198-
true => {
199-
open(self.get_path(), mode, access)
272+
273+
/// Attempts to open a regular file for reading/writing based
274+
/// on provided inputs
275+
fn open_stream(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
276+
match self.stat() {
277+
Some(s) => match s.is_file {
278+
true => open(self.get_file_path(), mode, access),
279+
false => None // FIXME: raise condition, not a regular file..
200280
},
201-
false => {
202-
// FIXME: raise condition
203-
None
204-
}
281+
None => open(self.get_file_path(), mode, access)
282+
}
283+
}
284+
/// Attempts to open a regular file for reading-only based
285+
/// on provided inputs
286+
fn open_reader(&self, mode: FileMode) -> Option<FileReader> {
287+
match self.open_stream(mode, Read) {
288+
Some(s) => Some(FileReader { stream: s}),
289+
None => None
290+
}
291+
}
292+
293+
/// Attempts to open a regular file for writing-only based
294+
/// on provided inputs
295+
fn open_writer(&self, mode: FileMode) -> Option<FileWriter> {
296+
match self.open_stream(mode, Write) {
297+
Some(s) => Some(FileWriter { stream: s}),
298+
None => None
205299
}
206300
}
207-
//fn open_read(&self) -> FileStream;
208-
//fn open_write(&self) -> FileStream;
209-
//fn create(&self) -> FileStream;
210-
//fn truncate(&self) -> FileStream;
211-
//fn open_or_create(&self) -> FileStream;
212-
//fn create_or_truncate(&self) -> FileStream;
213-
//fn unlink(&self);
301+
302+
/// Attempt to remove a file from the filesystem, pending the closing
303+
/// of any open file descriptors pointing to the file
304+
fn unlink(&self) {
305+
unlink(self.get_file_path());
306+
}
307+
}
308+
309+
/// `FileInfo` implementation for `Path`s
310+
impl<'self> FileInfo<'self> for Path {
311+
fn get_file_path(&'self self) -> &'self Path { self }
214312
}
215313

216314
/*
@@ -244,27 +342,6 @@ impl DirectoryInfo<'self> {
244342
}
245343
*/
246344

247-
/// Given a `rt::io::support::PathLike`, query the file system to get
248-
/// information about a file, directory, etc.
249-
///
250-
/// Returns a `Some(PathInfo)` on success, and raises a `rt::io::IoError` condition
251-
/// on failure and returns `None`.
252-
pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
253-
let open_result = unsafe {
254-
let io: *mut IoFactoryObject = Local::unsafe_borrow();
255-
(*io).fs_stat(path)
256-
};
257-
match open_result {
258-
Ok(p) => {
259-
Some(p)
260-
},
261-
Err(ioerr) => {
262-
read_error::cond.raise(ioerr);
263-
None
264-
}
265-
}
266-
}
267-
268345
fn file_test_smoke_test_impl() {
269346
do run_in_mt_newsched_task {
270347
let message = "it's alright. have a good time";
@@ -412,7 +489,7 @@ fn file_test_io_seek_and_write_impl() {
412489
read_stream.read(read_mem);
413490
}
414491
unlink(filename);
415-
let read_str = str::from_bytes(read_mem);
492+
let read_str = str::from_utf8(read_mem);
416493
assert!(read_str == final_msg.to_owned());
417494
}
418495
}
@@ -463,8 +540,9 @@ fn file_test_io_seek_shakedown() {
463540
}
464541

465542
#[test]
543+
#[ignore(cfg(windows))] // FIXME #8810
466544
fn file_test_stat_is_correct_on_is_file() {
467-
do run_in_newsched_task {
545+
do run_in_mt_newsched_task {
468546
let filename = &Path("./tmp/file_stat_correct_on_is_file.txt");
469547
{
470548
let mut fs = open(filename, Create, ReadWrite).unwrap();
@@ -476,20 +554,48 @@ fn file_test_stat_is_correct_on_is_file() {
476554
None => fail!("shouldn't happen")
477555
};
478556
assert!(stat_res.is_file);
557+
unlink(filename);
479558
}
480559
}
481560

482561
#[test]
562+
#[ignore(cfg(windows))] // FIXME #8810
483563
fn file_test_stat_is_correct_on_is_dir() {
484-
//assert!(false);
564+
do run_in_mt_newsched_task {
565+
let filename = &Path("./tmp/file_stat_correct_on_is_dir");
566+
mkdir(filename);
567+
let stat_res = match stat(filename) {
568+
Some(s) => s,
569+
None => fail!("shouldn't happen")
570+
};
571+
assert!(stat_res.is_dir);
572+
rmdir(filename);
573+
}
485574
}
486575

487576
#[test]
577+
#[ignore(cfg(windows))] // FIXME #8810
488578
fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
489-
//assert!(false);
579+
do run_in_mt_newsched_task {
580+
let dir = &Path("./tmp/fileinfo_false_on_dir");
581+
mkdir(dir);
582+
assert!(dir.is_file() == false);
583+
rmdir(dir);
584+
}
490585
}
491586

492587
#[test]
588+
#[ignore(cfg(windows))] // FIXME #8810
493589
fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
494-
//assert!(false);
590+
do run_in_mt_newsched_task {
591+
let file = &Path("./tmp/fileinfo_check_exists_b_and_a.txt");
592+
{
593+
let msg = "foo".as_bytes();
594+
let mut w = file.open_writer(Create);
595+
w.write(msg);
596+
}
597+
assert!(file.file_exists());
598+
file.unlink();
599+
assert!(!file.file_exists());
600+
}
495601
}

branches/try/src/libstd/rt/rtio.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ pub trait IoFactory {
7676
fn get_host_addresses(&mut self, host: &str) -> Result<~[IpAddr], IoError>;
7777
fn fs_stat<P: PathLike>(&mut self, path: &P) -> Result<FileStat, IoError>;
7878
//fn fs_fstat(&mut self, fd: c_int) -> Result<FileStat, IoError>;
79+
fn fs_mkdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
80+
fn fs_rmdir<P: PathLike>(&mut self, path: &P) -> Result<(), IoError>;
7981
}
8082

8183
pub trait RtioStream {

0 commit comments

Comments
 (0)