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]
This commit is contained in:
parent
f096516d2b
commit
8c55fcd1f2
@ -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()),
|
||||
}
|
||||
}
|
||||
|
@ -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()),
|
||||
}
|
||||
})
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.)
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user