c++c++17filesystemsfile-searchstd-system-error

File search starts with C:\\$Recycle.Bin\\S-1-5-18 and causes filesystem_error


I'm writing a program that searches a file in Windows directory by it's name, starting from C:\. I use recursive_directory_iterator and path from std::filesystem. The problem is, while user input is read correctly and core logic seems fine, the program starts it's search directrly like this: C:\ -> C:\$Recycle.Bin -> C:\$Recycle.Bin\S-1-5-18 and then crushes.

My code:

#include <string>
#include <filesystem>
#include <iostream>

std::string start_path = "C:\\";
std::filesystem::path find_file_path(const std::string& file_name, std::filesystem::path file_path)
{
    for (const auto& entry : std::filesystem::recursive_directory_iterator(file_path))
        if (entry.is_directory())
        {
            auto new_path = entry.path();
            if (!new_path.empty()) {
                if (new_path.filename() == file_name) {
                    return new_path;
                }
            }
        }
    return std::filesystem::path();
}

int main()
{
    std::string input_file{};
    std::cout << "hello! enter file name here: ";
    std::cin >> input_file;
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::filesystem::path file_path = find_file_path(input_file, start_path);
    std::cout << file_path;
}

I've tried using iterators, paths, strings, everything, but the code crushes in std::filesystem::filesystem_error, system_error or stack overflow.

I need to know why my code goes straight to C:\$Recycle.Bin and how to prevent that. Or if there is other errors I can't see because I'm a beginner in C++, the help would really be appreciated.

Thank you in advance.


Solution

  • If you want to avoid permissions exceptions the simplest way is to specify the skip_permission_denied option when you construct the iterator.

    Adding that plus exception handling I believe the code you're looking for is something like...

    std::filesystem::path find_file_path(const std::string& file_name,
                       std::filesystem::path file_path)
    {
        for (const auto& entry : std::filesystem::recursive_directory_iterator(file_path, std::filesystem::directory_options::skip_permission_denied)) {
            try {
    
                /*
                 * Checking to see if it's the one we're searching for.
                 */
                if (entry.path().filename() == file_name) {
                    return entry.path();
                }
            }
            catch (std::exception &ex) {
    
                /*
                 * Handle exception...
                 */
            }
        }
        return {};
    }
    

    The above works for me (Linux, g++ 12.2.0, libstdc++ 6.0.20).