about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2014-05-12 02:31:22 -0300
committerAlex Crichton <alex@alexcrichton.com>2014-05-12 19:52:29 -0700
commit8c55fcd1f2ef3674d4bda4e38e2e7cacdd7cd5b8 (patch)
tree26e430f86234c4be047df9369327942a4d0861c7 /src
parentf096516d2b5e0ac1a634742a11520dff4b59014b (diff)
downloadrust-8c55fcd1f2ef3674d4bda4e38e2e7cacdd7cd5b8.tar.gz
rust-8c55fcd1f2ef3674d4bda4e38e2e7cacdd7cd5b8.zip
Add `stat` method to `std::io::fs::File` to stat without a Path.
The `FileStat` struct contained a `path` field, which was filled by the
`stat` and `lstat` function. Since this field isn't in fact returned by
the operating system (it was copied from the paths passed to the
functions) it was removed, as in the `fstat` case we aren't working with
a `Path`, but directly with a fd.

If your code used the `path` field of `FileStat` you will now have to
manually store the path passed to `stat` along with the returned struct.

[breaking-change]
Diffstat (limited to 'src')
-rw-r--r--src/libnative/io/file_unix.rs21
-rw-r--r--src/libnative/io/file_win32.rs14
-rw-r--r--src/librustuv/file.rs18
-rw-r--r--src/libstd/io/fs.rs20
-rw-r--r--src/libstd/io/mod.rs3
-rw-r--r--src/libstd/rt/rtio.rs1
6 files changed, 55 insertions, 22 deletions
diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs
index 87225a10e76..c2b69483fa1 100644
--- a/src/libnative/io/file_unix.rs
+++ b/src/libnative/io/file_unix.rs
@@ -166,6 +166,14 @@ impl rtio::RtioFileStream for FileDesc {
             libc::ftruncate(self.fd(), offset as libc::off_t)
         }))
     }
+
+    fn fstat(&mut self) -> IoResult<io::FileStat> {
+        let mut stat: libc::stat = unsafe { mem::uninit() };
+        match retry(|| unsafe { libc::fstat(self.fd(), &mut stat) }) {
+            0 => Ok(mkstat(&stat)),
+            _ => Err(super::last_error()),
+        }
+    }
 }
 
 impl rtio::RtioPipe for FileDesc {
@@ -317,6 +325,10 @@ impl rtio::RtioFileStream for CFile {
     fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
         self.flush().and_then(|()| self.fd.truncate(offset))
     }
+
+    fn fstat(&mut self) -> IoResult<io::FileStat> {
+        self.flush().and_then(|()| self.fd.fstat())
+    }
 }
 
 impl Drop for CFile {
@@ -455,9 +467,7 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
     }))
 }
 
-fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
-    let path = unsafe { CString::new(path.with_ref(|p| p), false) };
-
+fn mkstat(stat: &libc::stat) -> io::FileStat {
     // FileStat times are in milliseconds
     fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
 
@@ -481,7 +491,6 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
     fn gen(_stat: &libc::stat) -> u64 { 0 }
 
     io::FileStat {
-        path: Path::new(path),
         size: stat.st_size as u64,
         kind: kind,
         perm: unsafe {
@@ -508,7 +517,7 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
 pub fn stat(p: &CString) -> IoResult<io::FileStat> {
     let mut stat: libc::stat = unsafe { mem::uninit() };
     match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) {
-        0 => Ok(mkstat(&stat, p)),
+        0 => Ok(mkstat(&stat)),
         _ => Err(super::last_error()),
     }
 }
@@ -516,7 +525,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
 pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
     let mut stat: libc::stat = unsafe { mem::uninit() };
     match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
-        0 => Ok(mkstat(&stat, p)),
+        0 => Ok(mkstat(&stat)),
         _ => Err(super::last_error()),
     }
 }
diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs
index 707b0c0cf3f..d721e1d67f1 100644
--- a/src/libnative/io/file_win32.rs
+++ b/src/libnative/io/file_win32.rs
@@ -197,6 +197,14 @@ impl rtio::RtioFileStream for FileDesc {
         let _ = self.seek(orig_pos as i64, io::SeekSet);
         return ret;
     }
+
+    fn fstat(&mut self) -> IoResult<io::FileStat> {
+        let mut stat: libc::stat = unsafe { mem::uninit() };
+        match unsafe { libc::fstat(self.fd(), &mut stat) } {
+            0 => Ok(mkstat(&stat)),
+            _ => Err(super::last_error()),
+        }
+    }
 }
 
 impl rtio::RtioPipe for FileDesc {
@@ -471,8 +479,7 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
     }))
 }
 
-fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
-    let path = unsafe { CString::new(path.with_ref(|p| p), false) };
+fn mkstat(stat: &libc::stat) -> io::FileStat {
     let kind = match (stat.st_mode as c_int) & libc::S_IFMT {
         libc::S_IFREG => io::TypeFile,
         libc::S_IFDIR => io::TypeDirectory,
@@ -483,7 +490,6 @@ fn mkstat(stat: &libc::stat, path: &CString) -> io::FileStat {
     };
 
     io::FileStat {
-        path: Path::new(path),
         size: stat.st_size as u64,
         kind: kind,
         perm: unsafe {
@@ -511,7 +517,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
     let mut stat: libc::stat = unsafe { mem::uninit() };
     as_utf16_p(p.as_str().unwrap(), |up| {
         match unsafe { libc::wstat(up, &mut stat) } {
-            0 => Ok(mkstat(&stat, p)),
+            0 => Ok(mkstat(&stat)),
             _ => Err(super::last_error()),
         }
     })
diff --git a/src/librustuv/file.rs b/src/librustuv/file.rs
index cd56e76aff6..06271e61ce7 100644
--- a/src/librustuv/file.rs
+++ b/src/librustuv/file.rs
@@ -70,6 +70,12 @@ impl FsRequest {
         }).map(|req| req.mkstat())
     }
 
+    pub fn fstat(loop_: &Loop, fd: c_int) -> Result<FileStat, UvError> {
+        execute(|req, cb| unsafe {
+            uvll::uv_fs_fstat(loop_.handle, req, fd, cb)
+        }).map(|req| req.mkstat())
+    }
+
     pub fn write(loop_: &Loop, fd: c_int, buf: &[u8], offset: i64)
         -> Result<(), UvError>
     {
@@ -262,8 +268,6 @@ impl FsRequest {
     }
 
     pub fn mkstat(&self) -> FileStat {
-        let path = unsafe { uvll::get_path_from_fs_req(self.req) };
-        let path = unsafe { Path::new(CString::new(path, false)) };
         let stat = self.get_stat();
         fn to_msec(stat: uvll::uv_timespec_t) -> u64 {
             // Be sure to cast to u64 first to prevent overflowing if the tv_sec
@@ -279,7 +283,6 @@ impl FsRequest {
             _ => io::TypeUnknown,
         };
         FileStat {
-            path: path,
             size: stat.st_size as u64,
             kind: kind,
             perm: unsafe {
@@ -463,6 +466,11 @@ impl rtio::RtioFileStream for FileWatcher {
         let r = FsRequest::truncate(&self.loop_, self.fd, offset);
         r.map_err(uv_error_to_io_error)
     }
+
+    fn fstat(&mut self) -> Result<FileStat, IoError> {
+        let _m = self.fire_homing_missile();
+        FsRequest::fstat(&self.loop_, self.fd).map_err(uv_error_to_io_error)
+    }
 }
 
 #[cfg(test)]
@@ -537,6 +545,10 @@ mod test {
         assert!(result.is_ok());
         assert_eq!(result.unwrap().size, 5);
 
+        let result = FsRequest::fstat(l(), file.fd);
+        assert!(result.is_ok());
+        assert_eq!(result.unwrap().size, 5);
+
         fn free<T>(_: T) {}
         free(file);
 
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index 125b4ddad88..a497ffd40a0 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -214,6 +214,11 @@ impl File {
     pub fn eof(&self) -> bool {
         self.last_nread == 0
     }
+
+    /// Queries information about the underlying file.
+    pub fn stat(&mut self) -> IoResult<FileStat> {
+        self.fd.fstat()
+    }
 }
 
 /// Unlink a file from the underlying filesystem.
@@ -887,9 +892,12 @@ mod test {
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
         {
-            let mut fs = File::open_mode(filename, Open, ReadWrite);
+            let mut fs = check!(File::open_mode(filename, Open, ReadWrite));
             let msg = "hw";
             fs.write(msg.as_bytes()).unwrap();
+
+            let fstat_res = check!(fs.stat());
+            assert_eq!(fstat_res.kind, io::TypeFile);
         }
         let stat_res_fn = check!(stat(filename));
         assert_eq!(stat_res_fn.kind, io::TypeFile);
@@ -1228,12 +1236,12 @@ mod test {
         check!(file.fsync());
 
         // Do some simple things with truncation
-        assert_eq!(check!(stat(&path)).size, 3);
+        assert_eq!(check!(file.stat()).size, 3);
         check!(file.truncate(10));
-        assert_eq!(check!(stat(&path)).size, 10);
+        assert_eq!(check!(file.stat()).size, 10);
         check!(file.write(bytes!("bar")));
         check!(file.fsync());
-        assert_eq!(check!(stat(&path)).size, 10);
+        assert_eq!(check!(file.stat()).size, 10);
         assert_eq!(check!(File::open(&path).read_to_end()),
                    (Vec::from_slice(bytes!("foobar", 0, 0, 0, 0))));
 
@@ -1241,10 +1249,10 @@ mod test {
         // Ensure that the intermediate zeroes are all filled in (we're seeked
         // past the end of the file).
         check!(file.truncate(2));
-        assert_eq!(check!(stat(&path)).size, 2);
+        assert_eq!(check!(file.stat()).size, 2);
         check!(file.write(bytes!("wut")));
         check!(file.fsync());
-        assert_eq!(check!(stat(&path)).size, 9);
+        assert_eq!(check!(file.stat()).size, 9);
         assert_eq!(check!(File::open(&path).read_to_end()),
                    (Vec::from_slice(bytes!("fo", 0, 0, 0, 0, "wut"))));
         drop(file);
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 37edab99915..36352542590 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -228,7 +228,6 @@ use ops::{BitOr, BitAnd, Sub};
 use option::{Option, Some, None};
 use os;
 use owned::Box;
-use path::Path;
 use result::{Ok, Err, Result};
 use slice::{Vector, MutableVector, ImmutableVector};
 use str::{StrSlice, StrAllocating};
@@ -1516,8 +1515,6 @@ pub enum FileType {
 /// ```
 #[deriving(Hash)]
 pub struct FileStat {
-    /// The path that this stat structure is describing
-    pub path: Path,
     /// The size of the file, in bytes
     pub size: u64,
     /// The kind of file this path points to (directory, file, pipe, etc.)
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index bc3a483f30d..d23d327d558 100644
--- a/src/libstd/rt/rtio.rs
+++ b/src/libstd/rt/rtio.rs
@@ -269,6 +269,7 @@ pub trait RtioFileStream {
     fn fsync(&mut self) -> IoResult<()>;
     fn datasync(&mut self) -> IoResult<()>;
     fn truncate(&mut self, offset: i64) -> IoResult<()>;
+    fn fstat(&mut self) -> IoResult<FileStat>;
 }
 
 pub trait RtioProcess {