Main Site Documentation

File.Exists returns true for unexisting file


#1

I have checked this on USBizi100/144. When i run this program

using System.IO;
using System.Threading;
using GHIElectronics.NETMF.IO;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;

namespace MFConsoleApplication1
{
    public class Program
    {
        public static void Main()
        {
            if (PersistentStorage.DetectSDCard())
            {
                var storage = new PersistentStorage("SD");
                storage.MountFileSystem();

                if (!VolumeInfo.GetVolumes()[0].IsFormatted)
                {
                    Debug.Print("Storage not formatted!");
                }
                else
                {
                    var rootDir = VolumeInfo.GetVolumes()[0].RootDirectory;

                    CheckFile(rootDir + @ "\index.html");
                    CheckFile(rootDir + @ "\index.html.gz");
                    CheckFile(rootDir + @ "\test.jpg");
                    CheckFile(rootDir + @ "\test.jpg.gz");
                }
            }
            else
            {
                Debug.Print("No SD card detected!");
            }

            Thread.Sleep(Timeout.Infinite);
        }

        private static void CheckFile(string filePath)
        {
            Debug.Print("File exists - " + filePath + "? " + File.Exists(filePath));
        }
    }
}

I get this result

[quote]
File exists - \SD\index.html? True
File exists - \SD\index.html.gz? False
File exists - \SD\test.jpg? True
File exists - \SD\test.jpg.gz? True[/quote]

The problem is there are only index.html and test.jpg files on the card. Funny is that it occurs for jpg but not for html. The card has been formated before the test. Can anyone confirm this?


#2

maybe there is a bug in handling ‘.’ in the file name. html is 4 letters and this is why it worked maybe!

This should go on NETMF codeplex to cover in 4.3


#3

Did you try it Gus? I wanted to make sure it’s not only me before posting this on codeplex. Can anyone test this on som other board not USBizi based?


#4

We also found this issue on other device so it is a bug in NETMF.


#5

Ok, i have reported this bug here - please vote.

http://netmf.codeplex.com/workitem/1636

Meanwhile i have found a reported issue that can be associated with this one:

http://netmf.codeplex.com/workitem/1109


#6

Well actually this happens for any file named test with any extension…

if you rename your files to anything but test they will work fine…

so it looks like some test code made it to the release of the NETMF.

tested on a Spider… please retest and report back…

thanks.


#7

Funny. I saw this bug for the first time when i was. using name image.jpg. I renamed it to test to be sure there was never such file on the card (and the gz version). I have my boards at work, can you check image.jpg Jay Jay?


#8

hi Gralin,
it looks like it affects those two so far…
a file named image or test…


#9

Now who can find a pattern :wink:


#10

LOL …


#11

I routinely use File.Exists to check for a file called “Application.hex” and the method returns the correct value each time.


#12

Retested on Spider: if a file named “filename.xxx” exist on SD card already, File.Exist will return “TRUE” if file need to check that has pattern like: “filename.xxxyyyy…”.
Only happen on files have extension 3 characters


#13

I think i found there reason for this problem. I have browsed .NET MF source code starting from File.Exists method and came across this file

\client_v4_1\DeviceCode\Drivers\FS\FAT\FAT_FS.cpp

Inside there is a method that essentialy is responsible for deciding whether the file exists or not. Here is the code:

BOOL FAT_Directory::IsName( LPCWSTR name, UINT32 nameLen )
{
    char c;
    int j;


    // Compare the base name
    for(j = 0; j < SHORTNAME_SIZE && nameLen > 0; j++)
    {
        c = (char)(*name);
        name++;
        nameLen--;


        // stop if we see the "."
        if(c == '.') break;
        
        if(c >= 'a' && c <= 'z') c -= 'a' - 'A';
        else if(j == 0 && c == 0xE5) c = 0x05;

        if(DIR_Name[j] != c) return FALSE;
        
    }

    // the rest of the base name has to be blanks
    for(; j < 8; j++)
    {
        if(DIR_Name[j] != WHITESPACE_CHAR) return FALSE;
    }

    // Only compare the extension if there is one
    if(nameLen > 0)
    {
        // skip the '.' if we haven't already
        
        if(*name == '.')
        {
            name++;
            nameLen--;
        }

        // Compare the extension
        for(; j < SHORTNAME_FULL_SIZE && nameLen > 0; j++)
        {
        
            c = (char)(*name);
            name++;
            nameLen--;

            if(c >= 'a' && c <= 'z') c -= 'a' - 'A';
            
            if(DIR_Name[j] != c) return FALSE;
            
        }
    }

    // the rest of the extension has to be blanks
    for(; j < 11; j++)
    {
    
        if(DIR_Name[j] != WHITESPACE_CHAR) return FALSE;
    }

    return TRUE;
}

Correct me if I’m wrong. In FAT when a filename is <= 11 characters (1-8 for name and 1-3 for extension) it will be stored as short entry. Let’s use this filename as an example:

index.htm

. The problem is that when we call

File.Exists("index.html")

we will get true. This is because the file we are trying to find has <= 11 characters and when we run the above method it will compare only first three characters of the extension. This problem should only occure for files that have 3 letter extensions and qualify for short entry in FAT. I think a simple fix at the end of that method could work to fix this problem:

return nameLen  == 0;

Could GHI or anyone compile NET MF with this fix and check it ?


#14

Please vote for this issue so that Microsoft checks if my fix works. Maybe someone can check it before they do?

http://netmf.codeplex.com/workitem/1636