summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorJeff Olson <olson.jeffery@gmail.com>2013-09-15 12:23:53 -0700
committerJeff Olson <olson.jeffery@gmail.com>2013-09-16 23:17:47 -0700
commit71c7798d66953e9f53192d54985a6a46736f5ca5 (patch)
treeb2d7ba35e62d7322e9e70d7a0af84b6915aad2f4 /src/libstd/rt
parentdaf497462844a55678e12545114bcc75d5ce8ebc (diff)
downloadrust-71c7798d66953e9f53192d54985a6a46736f5ca5.tar.gz
rust-71c7798d66953e9f53192d54985a6a46736f5ca5.zip
std: clean up Dir/FileInfo inheritence and flesh out Dir Info
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/io/file.rs178
-rw-r--r--src/libstd/rt/io/mod.rs10
2 files changed, 129 insertions, 59 deletions
diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs
index 4968f327602..af202a729e3 100644
--- a/src/libstd/rt/io/file.rs
+++ b/src/libstd/rt/io/file.rs
@@ -15,7 +15,9 @@ use super::{SeekStyle,SeekSet, SeekCur, SeekEnd,
             Open, Read, Write, Create, ReadWrite};
 use rt::rtio::{RtioFileStream, IoFactory, IoFactoryObject};
 use rt::io::{io_error, read_error, EndOfFile,
-            FileMode, FileAccess, FileStat};
+            FileMode, FileAccess, FileStat, IoError,
+            PathAlreadyExists, PathDoesntExist,
+            MismatchedFileTypeForOperation};
 use rt::local::Local;
 use option::{Some, None};
 use path::Path;
@@ -100,7 +102,7 @@ pub fn stat<P: PathLike>(path: &P) -> Option<FileStat> {
             Some(p)
         },
         Err(ioerr) => {
-            read_error::cond.raise(ioerr);
+            io_error::cond.raise(ioerr);
             None
         }
     }
@@ -230,41 +232,53 @@ impl Seek for FileStream {
     }
 }
 
-/// Represents passive information about a file (primarily exposed
-/// via the `stat()` method. Also provides methods for opening
-/// a file in various modes/permissions.
-pub trait FileInfo<'self> {
-    /// Get the filesystem path that this `FileInfo` points at,
-    /// whether it is valid or not. This way, it can be used to
-    /// to specify a file path of a non-existent file which it
-    /// later create
-    fn get_file_path(&'self self) -> &'self Path;
-
-    /// Ask the operating system for information about the file
+// helper for grabbing a stat and ignoring any
+// error.. used in Info wrappers
+fn suppressed_stat(cb: &fn() -> Option<FileStat>) -> Option<FileStat> {
+    do io_error::cond.trap(|_| {
+        // just swallow the error.. downstream users
+        // who can make a decision based on a None result
+        // won't care
+    }).inside {
+        cb()
+    }
+}
+
+/// Shared functionality between `FileInfo` and `DirectoryInfo`
+pub trait FileSystemInfo {
+    /// Get the filesystem path that this instance points at,
+    /// whether it is valid or not. In this way, it can be used to
+    /// to specify a path of a non-existent file which it
+    /// later creates
+    fn get_path<'a>(&'a self) -> &'a Path;
+
+    /// Ask the operating system for information about the path,
+    /// will raise a condition if an error occurs during the process
     fn stat(&self) -> Option<FileStat> {
-        use mod_stat = super::file::stat;
-        do read_error::cond.trap(|_| {
-            // FIXME: can we do something more useful here?
-        }).inside {
-            mod_stat(self.get_file_path())
-        }
+        stat(self.get_path())
     }
 
     /// returns `true` if the location pointed at by the enclosing
     /// exists on the filesystem
-    fn file_exists(&self) -> bool {
-        match self.stat() {
+    fn exists(&self) -> bool {
+        match suppressed_stat(|| self.stat()) {
             Some(_) => true,
             None => false
         }
     }
 
-    /// Whether the underlying implemention (be it a file path
-    /// or active file descriptor) is a "regular file". Will return
+}
+
+/// Represents passive information about a file (primarily exposed
+/// via the `stat()` method. Also provides methods for opening
+/// a file in various modes/permissions.
+pub trait FileInfo : FileSystemInfo {
+    /// Whether the underlying implemention (be it a file path,
+    /// or something else) points at a "regular file" on the FS. Will return
     /// false for paths to non-existent locations or directories or
     /// other non-regular files (named pipes, etc).
     fn is_file(&self) -> bool {
-        match self.stat() {
+        match suppressed_stat(|| self.stat()) {
             Some(s) => s.is_file,
             None => false
         }
@@ -273,12 +287,12 @@ pub trait FileInfo<'self> {
     /// Attempts to open a regular file for reading/writing based
     /// on provided inputs
     fn open_stream(&self, mode: FileMode, access: FileAccess) -> Option<FileStream> {
-        match self.stat() {
+        match suppressed_stat(|| self.stat()) {
             Some(s) => match s.is_file {
-                true => open(self.get_file_path(), mode, access),
+                true => open(self.get_path(), mode, access),
                 false => None // FIXME: raise condition, not a regular file..
             },
-            None => open(self.get_file_path(), mode, access)
+            None => open(self.get_path(), mode, access)
         }
     }
     /// Attempts to open a regular file for reading-only based
@@ -302,45 +316,82 @@ pub trait FileInfo<'self> {
     /// Attempt to remove a file from the filesystem, pending the closing
     /// of any open file descriptors pointing to the file
     fn unlink(&self) {
-        unlink(self.get_file_path());
+        unlink(self.get_path());
     }
 }
 
-/// `FileInfo` implementation for `Path`s 
-impl<'self> FileInfo<'self> for Path {
-    fn get_file_path(&'self self) -> &'self Path { self }
+/// `FileSystemInfo` implementation for `Path`s 
+impl FileSystemInfo for Path {
+    fn get_path<'a>(&'a self) -> &'a Path { self }
 }
+/// `FileInfo` implementation for `Path`s 
+impl FileInfo for Path { }
 
-/*
-/// 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
+trait DirectoryInfo : FileSystemInfo {
+    /// Whether the underlying implemention (be it a file path,
+    /// or something else) points at a directory file" on the FS. Will return
+    /// false for paths to non-existent locations or if the item is
+    /// not a directory (eg files, named pipes, links, etc)
+    fn is_dir(&self) -> bool {
+        match suppressed_stat(|| self.stat()) {
+            Some(s) => s.is_dir,
+            None => false
+        }
     }
-    fn stat(&self) -> Option<FileStat> {
-        file::stat(self.get_path())
+    /// Create a directory at the location pointed to by the
+    /// type underlying the given `DirectoryInfo`. Raises a
+    /// condition if a file, directory, etc already exists
+    /// at that location or if some other error occurs during
+    /// the mkdir operation
+    fn mkdir(&self) {
+        match suppressed_stat(|| self.stat()) {
+            Some(_) => {
+                io_error::cond.raise(IoError {
+                    kind: PathAlreadyExists,
+                    desc: "path already exists",
+                    detail:
+                        Some(fmt!("%s already exists; can't mkdir it", self.get_path().to_str()))
+                })
+            },
+            None => mkdir(self.get_path())
+        }
     }
-    fn exists(&self) -> bool {
-        do io_error::cond.trap(|_| {
-        }).inside {
-            match self.stat() {
-                Some(_) => true,
-                None => false
-            }
+    /// Remove a directory at the given location pointed to by
+    /// the type underlying the given `DirectoryInfo`. Will fail
+    /// if there is no directory at the given location or if
+    fn rmdir(&self) {
+        match suppressed_stat(|| self.stat()) {
+            Some(s) => {
+                match s.is_dir {
+                    true => rmdir(self.get_path()),
+                    false => {
+                        let ioerr = IoError {
+                            kind: MismatchedFileTypeForOperation,
+                            desc: "Cannot do rmdir() on a non-directory",
+                            detail:
+                                Some(fmt!("%s is a non-directory; can't rmdir it", self.get_path().to_str()))
+                        };
+                        io_error::cond.raise(ioerr);
+                    }
+                }
+            },
+            None =>
+                io_error::cond.raise(IoError {
+                    kind: PathDoesntExist,
+                    desc: "path doesn't exist",
+                    detail: Some(fmt!("%s doesn't exist; can't rmdir it", self.get_path().to_str()))
+                })
         }
     }
-    fn is_dir(&self) -> bool {
-        
+    fn readdir(&self) -> ~[~str] {
+        ~[]
     }
-    fn create(&self);
-    fn get_subdirs(&self, filter: &str) -> ~[Path];
-    fn get_files(&self, filter: &str) -> ~[Path];
+    //fn get_subdirs(&self, filter: &str) -> ~[Path];
+    //fn get_files(&self, filter: &str) -> ~[Path];
 }
-*/
+
+/// FIXME: DOCS
+impl DirectoryInfo for Path { }
 
 fn file_test_smoke_test_impl() {
     do run_in_mt_newsched_task {
@@ -594,8 +645,21 @@ fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
             let mut w = file.open_writer(Create);
             w.write(msg);
         }
-        assert!(file.file_exists());
+        assert!(file.exists());
         file.unlink();
-        assert!(!file.file_exists());
+        assert!(!file.exists());
+    }
+}
+
+#[test]
+fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
+    do run_in_mt_newsched_task {
+        let dir = &Path("./tmp/before_and_after_dir");
+        assert!(!dir.exists());
+        dir.mkdir();
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        dir.rmdir();
+        assert!(!dir.exists());
     }
 }
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
index 55c7cfd8285..16c8a9deea0 100644
--- a/src/libstd/rt/io/mod.rs
+++ b/src/libstd/rt/io/mod.rs
@@ -358,7 +358,10 @@ pub enum IoErrorKind {
     Closed,
     ConnectionRefused,
     ConnectionReset,
-    BrokenPipe
+    BrokenPipe,
+    PathAlreadyExists,
+    PathDoesntExist,
+    MismatchedFileTypeForOperation
 }
 
 // FIXME: #8242 implementing manually because deriving doesn't work for some reason
@@ -374,7 +377,10 @@ impl ToStr for IoErrorKind {
             Closed => ~"Closed",
             ConnectionRefused => ~"ConnectionRefused",
             ConnectionReset => ~"ConnectionReset",
-            BrokenPipe => ~"BrokenPipe"
+            BrokenPipe => ~"BrokenPipe",
+            PathAlreadyExists => ~"PathAlreadyExists",
+            PathDoesntExist => ~"PathDoesntExist",
+            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation"
         }
     }
 }