diff options
| author | bors <bors@rust-lang.org> | 2014-12-05 00:22:58 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-12-05 00:22:58 +0000 |
| commit | 361baabb07b2fb921d0f556d0787b3ea7ef86746 (patch) | |
| tree | bc61837ee47ed0611090b199b69e43a89e5c5c7b /src/libstd | |
| parent | d9c7c00b9a3d80fc81fbbb77a9f21e5f71a1d213 (diff) | |
| parent | 3980cdecd073789fb5ff7256e2ca40685a289b01 (diff) | |
| download | rust-361baabb07b2fb921d0f556d0787b3ea7ef86746.tar.gz rust-361baabb07b2fb921d0f556d0787b3ea7ef86746.zip | |
auto merge of #19303 : nodakai/rust/libsyntax-reject-dirs, r=alexcrichton
On *BSD systems, we can `open(2)` a directory and directly `read(2)` from it due to an old tradition. We should avoid doing so by explicitly calling `fstat(2)` to check the type of the opened file. Opening a directory as a module file can't always be avoided. Even when there's no "path" attribute trick involved, there can always be a *directory* named `my_module.rs`. Incidentally, remove unnecessary mutability of `&self` from `io::fs::File::stat()`.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/fs.rs | 32 | ||||
| -rw-r--r-- | src/libstd/sys/windows/fs.rs | 2 |
2 files changed, 24 insertions, 10 deletions
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index fd6b57d096a..e52c00f8247 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -53,7 +53,8 @@ use clone::Clone; use io::standard_error; use io::{FilePermission, Write, Open, FileAccess, FileMode, FileType}; -use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader}; +use io::{IoResult, IoError, InvalidInput}; +use io::{FileStat, SeekStyle, Seek, Writer, Reader}; use io::{Read, Truncate, ReadWrite, Append}; use io::UpdateIoError; use io; @@ -134,13 +135,26 @@ impl File { pub fn open_mode(path: &Path, mode: FileMode, access: FileAccess) -> IoResult<File> { - fs_imp::open(path, mode, access).map(|fd| { - File { - path: path.clone(), - fd: fd, - last_nread: -1 + fs_imp::open(path, mode, access).and_then(|fd| { + // On *BSD systems, we can open a directory as a file and read from it: + // fd=open("/tmp", O_RDONLY); read(fd, buf, N); + // due to an old tradition before the introduction of opendir(3). + // We explicitly reject it because there are few use cases. + if cfg!(not(any(windows, target_os = "linux", target_os = "android"))) && + try!(fd.fstat()).kind == FileType::Directory { + Err(IoError { + kind: InvalidInput, + desc: "is a directory", + detail: None + }) + } else { + Ok(File { + path: path.clone(), + fd: fd, + last_nread: -1 + }) } - }).update_err("couldn't open file", |e| { + }).update_err("couldn't open path as file", |e| { format!("{}; path={}; mode={}; access={}", e, path.display(), mode_string(mode), access_string(access)) }) @@ -237,7 +251,7 @@ impl File { } /// Queries information about the underlying file. - pub fn stat(&mut self) -> IoResult<FileStat> { + pub fn stat(&self) -> IoResult<FileStat> { self.fd.fstat() .update_err("couldn't fstat file", |e| format!("{}; path={}", e, self.path.display())) @@ -886,7 +900,7 @@ mod test { let filename = &tmpdir.join("file_that_does_not_exist.txt"); let result = File::open_mode(filename, Open, Read); - error!(result, "couldn't open file"); + error!(result, "couldn't open path as file"); if cfg!(unix) { error!(result, "no such file or directory"); } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 9c4ffb926b5..9402c63dcf5 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -131,7 +131,7 @@ impl FileDesc { return ret; } - pub fn fstat(&mut self) -> IoResult<io::FileStat> { + pub fn fstat(&self) -> IoResult<io::FileStat> { let mut stat: libc::stat = unsafe { mem::zeroed() }; match unsafe { libc::fstat(self.fd(), &mut stat) } { 0 => Ok(mkstat(&stat)), |
