Как я могу перебрать каталог и определить или пропустить NTFS-переходы (symlink-ish) - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть код для перечисления файлов в каталоге.Для систем Windows я надеюсь получить список файлов и папок, который соответствует тому, что вы увидите в проводнике Windows.Например, когда я перечисляю C: \ на Server 2016, я хочу иметь папку Users, но не соединение Documents and Settings.В настоящее время я получаю и то и другое, без видимого способа их различения.

Мой текущий код выглядит так:

boost::filesystem::directory_iterator itr(dir);
boost::filesystem::directory_iterator end;
Poco::SharedPtr<Poco::JSON::Array> fileList(new Poco::JSON::Array);
for (; itr != end; ++itr) {
    boost::filesystem::path entryPath = itr->path();
    Poco::File file(entryPath.string());
    // ...

Я пробовал метод Poco isLink(), но он возвращаетложно для переходов.

Я также попробовал Poco::DirectoryIterator, который дает то же поведение, что и Boost, и Poco::SortedDirectoryIterator, который всегда выдает File access error: sharing violation: \pagefile.sys при чтении C:\.

В идеале этот код должен включатьсимволические ссылки в системах Linux и MacOS, игнорируя при этом соединения в Windows.

1 Ответ

0 голосов
/ 13 февраля 2019

Вот что я в итоге придумал.Это не идеальное решение - это скорее эвристика, чем правильный идентификатор - но, похоже, оно работает достаточно хорошо для моего варианта использования:

#ifdef _WIN32
    #include <windows.h>
#endif

bool FileController::isNtfsJunction(const std::string& dirPath) const {
    #ifdef _WIN32
        DWORD attrs = GetFileAttributesA(dirPath.c_str());
        if (INVALID_FILE_ATTRIBUTES == attrs) {
            DWORD err = GetLastError();
            logger.error("Could not determine if path is NTFS Junction: %s. Error: %s", dirPath, err);
            return false;
        }
        return attrs & FILE_ATTRIBUTE_DIRECTORY &&
            attrs & FILE_ATTRIBUTE_REPARSE_POINT &&
            attrs & FILE_ATTRIBUTE_HIDDEN &&
            attrs & FILE_ATTRIBUTE_SYSTEM;
    #else
        return false;
    #endif
}
...