Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DirectoryNotFoundException after Directory.Exists

Tags:

c#

io

How can the following statement:

if (Directory.Exists(outputDestination) 
    && new DirectoryInfo(outputDestination).GetFiles().Count() > 0)

throw a DirectoryNotFoundException: Could not find a part of the path given I check directory exists before calling GetFiles()

like image 840
Stuart Brant Avatar asked Aug 07 '26 00:08

Stuart Brant


2 Answers

How can the following statement:

if (Directory.Exists(outputDestination) 
   && new DirectoryInfo(outputDestination).GetFiles().Count() > 0)

throw a DirectoryNotFoundException?

Your code can throw a DirectoryNotFoundException because you've created a TOCTOU bug:

In software development, time of check to time of use (TOCTTOU or TOCTOU, pronounced "tock too") is a class of software bugs caused by changes in a system between the checking of a condition (such as a security credential) and the use of the results of that check. This is one example of a race condition.

Just because the directory exists for the call to Directory.Exists(), that does not mean that it still exists for the call to DirectoryInfo().

like image 191
Andrew Henle Avatar answered Aug 08 '26 13:08

Andrew Henle


For a move operation across drive volumes, I encountered this. Even though the OP said that their answer was a race condition. There are other reasons that the exception can be thrown, such as too long of a file name. As per the docs:

The exception that is thrown when part of a file or directory cannot be found.

when part of a file is key. A check within a catch, will show that a long file name will give the DirectoryNotFoundException

try
{
    fromFile.CopyTo(toFile.FullName, toFile.Exists);
}
catch (DirectoryNotFoundException)
{
    // can occur for really long file names
    if (Math.Max(fromFile.FullName.Length, toFile.FullName.Length) >= 260)
    {
        try
        {
            // in 4.6.1 they added handling for long file names, but its weird
            string from = $"\\\\?\\{fromFile.FullName}";
            string to = $"\\\\?\\{toFile.FullName}";
            File.Copy(from, to, File.Exists(to));
            if (File.Exists(to))
            {
                File.Delete(from);
                Log("Success\n");
                continue;
            }
        }
        catch (DirectoryNotFoundException)
        {
            Log("Failed\n");
            continue;
        }
    }
    throw;
}
like image 24
Chuck Savage Avatar answered Aug 08 '26 15:08

Chuck Savage



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!