2677. directory_entry::status is not allowed to be cached as a quality-of-implementation issue

Section: 30.11.11.3 [fs.dir.entry.obs] Status: Resolved Submitter: Billy O'Neal Opened: 2016-03-03 Last modified: 2017-03-19

Priority: 2

View all other issues in [fs.dir.entry.obs].

View all issues with Resolved status.

Discussion:

To fix multi-threading problems in directory_entry, caching behavior was removed from the type. This is bad for performance reasons, because the values can no longer be cached from the result of readdir on POSIX platforms, or from FindFirstFile/FindNextFile on Windows.

It appears that the intent was to allow implementers to fill in the values for directory_entry::status inside directory_iterator, but as currently specified:

Returns: status(path()[, ec]).

This is not allowed to be cached, because the target of the path can change. For example, consider the following program:

#include <stdio.h>
#include <stdlib.h>
#include <filesystem>
#include <fstream>

using namespace std;
namespace fs = ::std::filesystem;

void verify(const bool b, const char * const msg) {
    if (!b) {
        printf("fail: %s\n", msg);
        exit(1);
    }
}

void touch_file(const char * const filename) {
    ofstream f(filename);
    f << '\n' << endl;
    verify(f.good(), "File write failed");
}

int main() {
    fs::remove_all("subDir");
    fs::create_directory("subDir");
    fs::create_directory("subDir/child");
    touch_file("subDir/child/child");
    fs::current_path("./subDir");
    fs::directory_iterator dir(".");
    ++dir;
    fs::directory_entry entry = *dir;

    verify(entry == "./child",
      "unexpected subdirectory"); //enumerating "subDir" returned the directory "child"

    fs::file_status status = entry.status();
    verify(status.type() == fs::file_type::directory,
        "subDir/child was not a directory");
    fs::current_path("./child");
    status = entry.status(); // REQUIRED to re-stat() on POSIX,
                             // GetFileAttributes() on Windows
    verify(status.type() == fs::file_type::regular,
        "subDir/child/child was not a regular file");
    return 0;
}

directory_entry should be re-specified to allow implementers to cache the value of status(path) at the time irectory_iterator was incremented to avoid repeated stat() / GetFileAttributes calls. (This may mean additional constructors are necessary for directory_entry as well)

[2016-04, Issues Telecon]

Beman is working on a paper to address this.

[2016-08, Beman comments]

This will be resolved by P0317R1, Directory Entry Caching for Filesystem.

Fri AM: Moved to Tentatively Resolved

Proposed resolution: