c++filesystemsfile-permissionspermission-denied

"filesystem error: cannot increment recursive directory iterator: Permission denied" on 0777 directory


My code looks like this:

auto const dir = std::filesystem::path(...);
std::error_code ec (0, std::generic_category());
try {
    for (auto const& inner_entry : std::filesystem::recursive_directory_iterator(dir, std::filesystem::directory_options::follow_directory_symlink, ec)) {
        std::cout << "Trying to set " << inner_entry.path().c_str() << "to 0666\n";
        try {
            // Code setting permissions on file to 0666
        }
        catch (std::exception const& e) {
            std::cout << "Cannot set " << inner_entry.path().c_str() << "to 0666\n";
        }
    }
} catch (std::exception const& e) {
    std::cout << "Cannot for loop with: " << e.what() << ", " << ec.message();
}

My files look like:

dir/tmp/data1/
    dir1/
    dir2/
    file1
    file2

With the following stat outputs:

  File: /dir
  Size: 1024            Blocks: 2          IO Block: 1024   directory
Device: 706h/1798d      Inode: 1897        Links: 3
Access: (0777/drwxrwxrwx)  Uid: (  default)   Gid: (  default)

  File: /dir/tmp/
  Size: 1024            Blocks: 2          IO Block: 1024   directory
Device: 706h/1798d      Inode: 1899        Links: 3
Access: (0666/drw-rw-rw-)  Uid: (  default)   Gid: (  default)

  File: /dir/tmp/data1
  Size: 1024            Blocks: 2          IO Block: 1024   directory
Device: 706h/1798d      Inode: 1900        Links: 6
Access: (0777/drwxrwxrwx)  Uid: (  default)   Gid: (  default)

My output looks like:

Trying to set dir/ to 0666
Trying to set dir/tmp/ to 0666
Cannot for loop with: filesystem error: cannot increment recursive directory iterator: Permission denied, Success

Issue:

Notes:


Solution

  • A directory with mode 0666 is an unusual thing. It has the read and write bits set, but not the execute bit. On a directory, the execute bit actually means "search permission", which basically allows you to access files and subdirectories inside it by name.

    Try it:

    $ mkdir foo
    $ touch foo/bar
    $ chmod 0666 foo
    $ ls -l foo
    ls: cannot access 'foo/bar': Permission denied
    total 0
    -????????? ? ? ? ?            ? bar
    $ cat foo/bar
    cat: foo/bar: Permission denied
    

    I'm not sure this fully explains the behaviour you're seeing, because changing permissions during recursive_directory_iterator execution probably does not have well defined behaviour.

    TL;DR: On directories, use mode 0777 for full, unrestricted access. (And unless you're in a Docker container or other kind of sandbox, you'll probably want 0755 or 0700 instead, otherwise any other user has full access too.)