gulrak / filesystem

An implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD.
MIT License
1.31k stars 168 forks source link

directory_entry::refresh() throws on broken symlinks #151

Closed ilyapopov closed 1 year ago

ilyapopov commented 2 years ago

Describe the bug In presence of a broken symlink, directory_entry::refresh() throws, while both status() and symlink_status() succeed. Under the same circumstances, libstdc++ succeeds.

To Reproduce

#ifndef USE_GHC_FILESYSTEM
#    include <filesystem>
namespace fs = std::filesystem;
#else
#    include "ghc/filesystem.hpp"
namespace fs = ghc::filesystem;
#endif

#include <iostream>

int main() {
    // create a broken symlink
    if (fs::is_symlink("broken")) {
        fs::remove("broken");
    }
    fs::create_symlink("nonexistent", "broken");

    for (auto entry: fs::directory_iterator(".")) {
        std::cout << entry.path() << '\n';
        // this works
        entry.symlink_status();
        //this works
        entry.status();
        //this throws
        entry.refresh();
    }

    // non-iterating version behaves the same:
    fs::directory_entry entry("broken");
    entry.refresh();
}
$ g++ test1.cpp -DUSE_GHC_FILESYSTEM -I path/to/ghc_filesystem/include/ -o ghc
$ g++ test1.cpp -o gcc
./gcc
./ghc

Clang with libc++ behaves the same as GCC.

Expected behavior

I expect refresh() succeed and save file_status(file_type::not_found) into directory_entry instead.

Additional context

OS: Ubuntu 22.04 gcc: gcc version 11.2.0 (Ubuntu 11.2.0-19ubuntu1) ghc_filesystem: cd6805e94dd5d6346be1b75a54cdc27787319dd2 clang++: Ubuntu clang version 14.0.0-1ubuntu1

https://en.cppreference.com/w/cpp/filesystem/status https://en.cppreference.com/w/cpp/filesystem/directory_entry/refresh

ilyapopov commented 2 years ago

Maybe related: #107 #122

https://github.com/gulrak/filesystem/wiki/Differences-to-Standard-Filesystem-Implementations#3010122-directory_entry-modifiers-fsdirentrymods

gulrak commented 1 year ago

I decided to fix the exception for broken symlinks as that is driven by external factors, but keep the behavior for initializing a directory_entry with an empty or non existing file as that is more often a usage error I keep wanting to assert. The specs are not clear to me there, and I try to not change behavior not explicitly defined as it is surprising for users of ghc::fs, but I think this change is for the better and more consistent.

gulrak commented 1 year ago

Released with v1.5.14.