Skip to content

File::open() on directories does not return Err(), leads to breakage with BufReader #64144

Open
@kentfredric

Description

@kentfredric

I tripped onto some odd behaviour.

I was under the assumption calling File::open() on a directory would Err(), and that I could use that to handle a user specifying a path that was not a file, ( instead of falling prey to race conditions by stat-ing first and then opening second ).

However, ... bad things happened instead.

use std::path::PathBuf;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;

fn main() {
    let file = File::open(PathBuf::from("/tmp")).unwrap();
    let buf  = BufReader::with_capacity(100, file);
    let _lines: Vec<std::io::Result<String>> = buf.lines().collect();
}

The last of these lines will run forever, with strace reporting:

read(3, 0x564803253b80, 100)            = -1 EISDIR (Is a directory)

Over and over again ad-infinitum with no end in sight.

Somehow I had a variation of this go crazy and eat 200% of my ram, but I'm having a hard time reproducing that exact case (Though it may have been related to the target-directory in question also being massive in my case).

Digging shows related bug #43504

The profound question that remains unanswered is: "Why is calling File::open on a directory fine?"

And the residual question is "How does one invoke File::open in such a way that it refuses to work on directories".

And importantly, how do I achieve that portably?

And if none of these concerns can be mitigated, the very least that could be done is have this giant foot-gun documented somewhere in File::open.

( As far as I can divine, there's no useful behaviour to be found by allowing File::open to work on directories, as standard read() semantics simply don't work on directory filehandles, you have to use readdir() )

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsA-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions