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()`.
This commit is contained in:
commit
361baabb07
@ -53,7 +53,8 @@
|
|||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use io::standard_error;
|
use io::standard_error;
|
||||||
use io::{FilePermission, Write, Open, FileAccess, FileMode, FileType};
|
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::{Read, Truncate, ReadWrite, Append};
|
||||||
use io::UpdateIoError;
|
use io::UpdateIoError;
|
||||||
use io;
|
use io;
|
||||||
@ -134,13 +135,26 @@ impl File {
|
|||||||
pub fn open_mode(path: &Path,
|
pub fn open_mode(path: &Path,
|
||||||
mode: FileMode,
|
mode: FileMode,
|
||||||
access: FileAccess) -> IoResult<File> {
|
access: FileAccess) -> IoResult<File> {
|
||||||
fs_imp::open(path, mode, access).map(|fd| {
|
fs_imp::open(path, mode, access).and_then(|fd| {
|
||||||
File {
|
// 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(),
|
path: path.clone(),
|
||||||
fd: fd,
|
fd: fd,
|
||||||
last_nread: -1
|
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(),
|
format!("{}; path={}; mode={}; access={}", e, path.display(),
|
||||||
mode_string(mode), access_string(access))
|
mode_string(mode), access_string(access))
|
||||||
})
|
})
|
||||||
@ -237,7 +251,7 @@ impl File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Queries information about the underlying file.
|
/// Queries information about the underlying file.
|
||||||
pub fn stat(&mut self) -> IoResult<FileStat> {
|
pub fn stat(&self) -> IoResult<FileStat> {
|
||||||
self.fd.fstat()
|
self.fd.fstat()
|
||||||
.update_err("couldn't fstat file", |e|
|
.update_err("couldn't fstat file", |e|
|
||||||
format!("{}; path={}", e, self.path.display()))
|
format!("{}; path={}", e, self.path.display()))
|
||||||
@ -886,7 +900,7 @@ mod test {
|
|||||||
let filename = &tmpdir.join("file_that_does_not_exist.txt");
|
let filename = &tmpdir.join("file_that_does_not_exist.txt");
|
||||||
let result = File::open_mode(filename, Open, Read);
|
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) {
|
if cfg!(unix) {
|
||||||
error!(result, "no such file or directory");
|
error!(result, "no such file or directory");
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ impl FileDesc {
|
|||||||
return ret;
|
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() };
|
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||||
match unsafe { libc::fstat(self.fd(), &mut stat) } {
|
match unsafe { libc::fstat(self.fd(), &mut stat) } {
|
||||||
0 => Ok(mkstat(&stat)),
|
0 => Ok(mkstat(&stat)),
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// ignore-freebsd FIXME #12460
|
|
||||||
|
|
||||||
#[path = "../compile-fail"]
|
#[path = "../compile-fail"]
|
||||||
mod foo; //~ ERROR: illegal operation on a directory
|
mod foo; //~ ERROR: a directory
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user