I am running into an error while trying to enumerate a directory using boost::filesystem.
The error appears when I try to enumerate a directory for which I have no permissions on an SMB shared directory - ie, I have RW on the share but a subdirectory on the share is access denied.
Platform etc:
Windows 10.
C++ 17 code.
Visual Studio 2019.
Unicode VS project (thus the use of std::wstring).
Shared folders from a Samba server running on Linux.
Sample code below, then details of the fail.
int enumerate(const std::wstring dir_to_enumerate) {
if (directory.size() == 0)
return -1;
boost::filesystem::path dir_to_enumerate(dir_to_enumerate);
boost::system::error_code ec;
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
if (ec.value())
return -4;
if ( ! boost::filesystem::is_directory(dir_to_enumerate))
return -3;
boost::filesystem::directory_iterator it{ dir_to_enumerate };
while (it != boost::filesystem::directory_iterator{}) {
// ... do stuff
}
return 0;
}
Consider a folder C:\temp2 with permissions removed for my account. The test
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
reliably detects C:\temp2 is not accessible.
Consider a folder "temp2" located on a Samba share T:. This folder on the Linux box is /data/temp2. So the directory passed into the function is L"T:\temp2", and that corresponds to location /data/temp2 on the Linux filesystem.
Samba itself shares the location R/W.
If on the Linux server the EXT4 permissions of the directory /data/temp2 are R/W (mode 700, or 750, or 755 you get the idea) for my account then everything works as expected, I can enumerate the contents of T:\temp2
The problem shows up detecting the following case reliably:
If I set the EXT4 permissions on the directory /data/temp2 to denied (mode 000) then the above code behaves unpredictably...
Sometimes, most of the time, the test
if ( ! boost::filesystem::exists(dir_to_enumerate, ec))
return -2;
detects T:\temp2 is not accessible.
But occasionally exists() returns true, and we fall thru to testing the boost::filesystem::error_code value.
However the error_code never indicates an error.
In this case the line
boost::filesystem::directory_iterator it{ dir_to_enumerate };
always throws. I can't figure out exactly what it is throwing.
I'm pulling my hair out. Can anyone tell me what I am missing, or even just what the directory_iterator initializer is throwing?
(And... if I may be so forward: please do not tell me to just use std::filesystem. On Visual Studio 2019, and AFAIK C++17 itself, std::filesystem is incomplete. Boost::filesystem works better.)