I've run into a bit of an odd circumstance while using boost::filesystem::exists. If you attempt to check for the existance of a file on a drive that isn't ready or has no media in it, it throws a basic_filesystem_error. As far as I'm concerned for most all uses of bfs::exists, if a drive isn't ready it means the file doesn't exist.
I can wrap my calls with a try-catch to properly handle this condition, however it becomes a bit cumbersome and makes the code a bit clunky. And worse, it means I'm using a special case of basic_filesystem_error for flow control, which means if a different reason for that exception were to arrise, I wouldn't be handling it properly anymore.
The general case where this comes up is if I attempt to check if a file exists on a CD or DVD drive. My code which used to be:
if( bfs::exists( myFilePath ) )
{
...
}
Becomes:
bool fileExists( false );
try
{
fileExists = bfs::exists( myFilePath );
}
catch( bfs::basic_filesystem_error<bfs::path> e )
{
fileExists = false;
}
if( fileExists )
{
...
}
I'm not overly enamored with the thought of making this change all over the place in my existing code base.
I'm considering making a seperate function somewhere that wrapps up the try-catch and replacing my bfs::exist calls with that, but I'm still not satisfied that using the try-catch in that manner is a good idea. It seems like I'm opening the door for missing more important and relevant exceptional conditions.
I'm aware that you can recompile boost for a non-throwing version of the function, but I don't think that really avoids my exception handling concerns.
Has anyone run into this problem with removable media drives before, and if so how did you overcome it?
According to the documentation, exists(file_status s)
returns "status_known(s) && s.type() != file_not_found
".
The documentation also states that:
If the underlying file system reports an error during [
file_status
] attribute determination:
- If the error indicating that
p
could not be resolved, as if by POSIX errorsENOENT
[i.e., not found] ... returnfile_status(not_found_flag)
.
It seems to me that throwing an exception is not the intended behavior. (when you create the status
object its status is known, and that status is not_found
).
However, the documentation continues by saying:
[Note: The effect of this behavior is to distinguish between knowing that
p
does not exist, and not being able to determine the status ofp
. This distinction is important to users. --end note]
Which implies that the library does intend to make a distinction between "file does not exist" and "I can't determine that file does not exist." You may wish to contact the library's authors for a clearer statement.
However, testing for the existence of a file is a race condition: the file may have existed when the OS looked, but there is no guarantee that it will continue to exist; likewise, the file may not have existed when the OS looked, but there is no guarantee that it will continue not existing. The race condition can have security implications.
Instead, open the file and then see what its attributes are. Once the file is open, the OS makes certain guarantees about what will change and what won't.