Skip to content

Commit

Permalink
auto merge of #19303 : nodakai/rust/libsyntax-reject-dirs, r=alexcric…
Browse files Browse the repository at this point in the history
…hton

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()`.
  • Loading branch information
bors committed Dec 5, 2014
2 parents d9c7c00 + 3980cde commit 361baab
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 13 deletions.
32 changes: 23 additions & 9 deletions src/libstd/io/fs.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
})
Expand Down Expand Up @@ -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()))
Expand Down Expand Up @@ -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");
}
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/sys/windows/fs.rs
Expand Up @@ -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)),
Expand Down
4 changes: 1 addition & 3 deletions src/test/compile-fail/issue-5806.rs
Expand Up @@ -18,9 +18,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-freebsd FIXME #12460

#[path = "../compile-fail"]
mod foo; //~ ERROR: illegal operation on a directory
mod foo; //~ ERROR: a directory

fn main() {}

0 comments on commit 361baab

Please sign in to comment.