c++c++17std-filesystem

std::filesystem::recursive_directory_iterator and read permision


Under Linux:
I am trying to access a folder using 'recursive_directory_iterator' and it is throwing a "Permission denied" exception. Here are the permissions for the given folder:

ls -l /my_folder/
total 4
drwxr-xr-x 8 root root 4096 Nov  2  2021 my_subfolder

This means that "others" have exec and thus should be able to view and enter 'my_subfolder'.
Why then does the iterator throw and exception on it, as viewing is still permitted?

How can I just iterate though a tree as a user with only 'x' permission on the folder?
My file manager run with my regular user (same user that runs my application) can do this with no problem on the same folder...

Thanks!

Some clarification: Both my file manager and with 'ls' I can list the contests of these folders and their sub-folders, as a regular user. This is what I am trying to achieve with my C++ application as well using the std::filesystem::recursive_directory_iterator.

Here is an output of my console:

ls -l /media/my_user/my_folder/
total 36
drwxr-xr-x 4 root root  4096 Jul 10  2020 install-logs-2020-07-10.0
drwxr-xr-x 4 root root  4096 Jul 27  2020 install-logs-2020-07-27.0
drwxr-xr-x 4 root root  4096 Jul 29  2020 install-logs-2020-07-29.0
drwxr-xr-x 4 root root  4096 Nov  2  2021 install-logs-2021-11-02.0
drwxr-xr-x 4 root root  4096 Nov  2  2021 install-logs-2021-11-02.1
drwx------ 2 root root 16384 Jul 10  2020 lost+found
~$ ls -l /media/my_user/
total 4
drwxr-xr-x 8 root root 4096 Nov  2  2021 my_folder
~$ ls /media/my_user/my_folder/
install-logs-2020-07-10.0  install-logs-2020-07-27.0  install-logs-2020-07-29.0  install-logs-2021-11-02.0  install-logs-2021-11-02.1  lost+found
~$ ls /media/my_user/my_folder/install-logs-2020-07-
install-logs-2020-07-10.0/ install-logs-2020-07-27.0/ install-logs-2020-07-29.0/ 
~$ ls /media/my_user/my_folder/install-logs-2020-07-10.0/
crash  log

As I said, I can do the same with my UI file manager too. I just want to do the same using C++.

Based on some comments, and in particular the answer by @Homer512, I made the code even simpler, and I still have trouble figuring this out. Now all I want is to get the permissions of a given directory, but it seems that even that is not possible?? The directory I am giving is NOT the 'lost+found' directory, but its parent. The current code I am trying is this:

void findPackagesRecursivelyIn(const std::filesystem::path &dir) {
    namespace fs = std::filesystem;
    fs::directory_iterator dirIt{dir};
    std::cout<<"getting status"<<std::endl;
    auto permissions = fs::status(dirIt->path()).permissions();
    std::cout<<"got status"<<std::endl;
    if((permissions & fs::perms::others_exec ) != fs::perms::none) {
        std::cout<<dirIt->path()<<std::endl;
    }
    std::cout<<"after loop"<<std::endl;
}

Here is the output for this code:

getting status
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
  what():  filesystem error: directory iterator cannot open directory: Permission denied [/media/my_user/my_folder]

based on this it seems even initializing the iterator with a directory that has drwxr-xr-x permissions is not possible... What am I missing here??

Many thanks for your help!


Solution

  • Ok, I figured what the problem is, though I am not sure yet why it is behaving like that.
    The issue was not with the permissions.
    The folder I was accessing was a mounted folder that is mounted when a USB stick is inserted.
    The issue was, that while I was notified (using Qt's QFileSystemWatcher) that the mounted folder was added, apparently, it is still not available at that time.
    So, if I output the available storage list (in the slot triggered by QFileSystemWatcher):

    for (const auto &storage : QStorageInfo::mountedVolumes()) {
           
                std::cout<<"Storage:"<<storage.displayName().toStdString()<<std::endl;
                
    }
    

    The the very same mounted folder for which QFileSystemWatcher was notifying me was not in the list of the available storage.
    If I restart the application, and list the storage again, it is in the list and I can access it.

    As this is a different problem to the original I posted, I will close this question with this answer.
    If I see that I can't figure out the problem I just explained, I'll open a new question for it.

    Many thanks for all of you who helped!!

    P.S
    For what ever reason QFileSystemWatcher is notifying about a new mount even when that mount is not fully available yet.
    The solution was to build a little "wait and poll" loop in the slot. That did the trick.
    Once the mount is fully "there", the std::filesystem::recursive_directory_iterator code works as expected.