Home > Back-end >  std::filesystem::recursive_directory_iterator and read permision
std::filesystem::recursive_directory_iterator and read permision

Time:12-22

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!

CodePudding user response:

The directory contains a subdirectory lost found that can only be accessed by root. This is typical for an Ext2-4 filesystem.

You can skip permission errors by constructing the iterator with the skip_permission_denied flag:

recursive_directory_iterator(path,
    std::filesystem::directory_options::skip_permission_denied)

Alternatively, you can check permissions when the iterator returns the directory, then call recursive_directory_iterator::disable_recursion_pending() if you find that the access would fail. I don't see another way to report permission errors without invalidating the iterator.

Also, this workaround has a race condition, because the directory permissions could change between testing and recursing into it.

I guess keeping a copy of the iterator between iterations would also allow recovery, but at a higher cost.

CodePudding user response:

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!!

  • Related