BurntSushi / walkdir

Rust library for walking directories recursively.
The Unlicense
1.21k stars 106 forks source link

Root symlink to file: metadata does not follow symlink #115

Closed TimNN closed 5 years ago

TimNN commented 5 years ago

If the path passed to WalkDir::new() is a symlink to a file, calling .metadata() on the produced DirEntry returns the metadata of the symlink, rather than its target. This happens irrespective of whether follow_links is set to true or not.

The documentation of WalkDir::new() states that

If root is a file, then it is the first and only item yielded by the iterator. If root is a symlink, then it is always followed.

Given that documentation, I would have assumed that symlinks would always be followed for the metadata. But even if that documentation was not meant to be applied to root files, I would have still assumed that a root symlink would be followed if follow_links is true.

To illustrate the problem use the following demo script:

extern crate walkdir;

use walkdir::WalkDir;
use std::env;

fn main() {
    for e in WalkDir::new(env::args_os().skip(1).next().unwrap()).follow_links(true) {
        let e = e.unwrap();
        println!(
            "is_symlink: {} ({})", 
            e.metadata().unwrap().file_type().is_symlink(), 
            e.path().display())
    }
}

If you pass a symlink to a file as an argument to the script, it will print is_symlink: true.

If you pass a directory containing a symlink to a file as an argument, it will print is_symlink: false for the symlink.

BurntSushi commented 5 years ago

Thanks for the great bug report! This was a bit of a nasty one, I think it was introduced as a regression in https://github.com/BurntSushi/walkdir/commit/6f72fce4315cb13f2ceb6903910a52852a12ba0b. I've committed a fix to master. Once that passes CI, I'll put out a new release.

BurntSushi commented 5 years ago

The fix is now on crates.io in walkdir 2.2.7.

TimNN commented 5 years ago

Thanks for the quick fix!