Asan
Asan

Reputation: 357

FatFS: f_findfirst returns a string that does not correspond to the file found

I am using the FatFs library to create and manage a file system on an SD card. The goal is to identify a file containing the firmware for the bootloader to update (or not) the device.

The procedure im following is the follwing:

DIR  directory;
FILINFO filinfo;

f_findfirst(&directory, &filinfo, "", "firmware_");

To my understanding, the first file that starts with "firmware_" should be identified and the information stored in filinfo . This does work, but when I try to extract the name from filinfo.fname the name that has been extracted is the follwing: "\0IRMWA~1.BIN".

I don't know the reason why the naming of the file is extracted in this format. The idea would be to later take the second part of the file: "firmware_01_01_01" and perform a char to int conversion to process the version number, but I cannot extract the full string of the file name.

Upvotes: 0

Views: 2363

Answers (3)

Barmaley
Barmaley

Reputation: 1232

I had a similar problem. Here is my code. Hope you find this helpful

#define FW_FOLDER               "fw"
#define FW_PATH                 "0:/" FW_FOLDER
#define FW_BIN                  "*.bin"

FRESULT res;
DIR dir;
FILINFO fno;
static char fw_path[128];

// Find first item
res = f_findfirst(&dir, &fno, FW_PATH, FW_BIN);

// Create directory (optional)
if (res == FR_NO_PATH)
{
    printf("Creating %s directory!\n", FW_FOLDER);
    f_mkdir(FW_FOLDER);
}

// Repeat until proper item is found
while (res == FR_OK)
{
    // Make sure file name is valid
    if (fno.fname[0] == 0)
        break;
    
    // Debugging
    printf("Scanning: %s\n", fno.fname);

    // Make sure it is not a directory
    if (!(fno.fattrib & AM_DIR))
    {            
        // Success!
        printf("Found: %s\n", fno.fname);
        
        // Construct file path
        sprintf(fw_path, "%s/%s", FW_PATH, fno.fname);
        
        break;
    }
    
    // Move to the next one
    res = f_findnext(&dir, &fno);
}

// Close directory
f_closedir(&dir);

And yes, you need to enable FF_USE_FIND == 1 in fatfs library. And if you decide to use 2 for FF_USE_FIND you have to check altname as part of fno.

Also, I had to update file validation eventually to this snippet

// Make sure file name is alpha numeric
if (!isalnum(fat_fno.fname[0]))
    break;

Upvotes: 2

Asan
Asan

Reputation: 357

I was using Long File Name (LFN) which had been activated in the ffconf.h file (the options file that comes with FatFs). The problem was that I was using filinfo.fname which refers to the 8.3 file name structure (short naming scheme).

If LFN is activated, the fields lfname and lfsize within the FILINFO struct are active. These two fields are a pointer to a char array as well as the size. Both fields must be initialized before using them like follows:

static char lfn[_MAX_LFN + 1] 
//MAX_LFN is defined in ffconf.h and is 255, maximum value for LFN
filinfo.lfname = lfn;
filinfo.lfsize = sizeof lfn;
f_findfirst(&directory, &filinfo, "", "firmware_*.bin");
(...)

The documentation that also shows an example can be read here.

When LFN feature is enabled, lfname and lfsize in the file information structure must be initialized with valid value prior to use the f_readdir function. The lfname is a pointer to the string buffer to return the long file name. The lfsize is the size of the string buffer in unit of TCHAR.

lfname and lfsize would work the same for f_findfirst as with f_readdir.

This is a wrapper function of f_opendir and f_readdir

Upvotes: 1

0___________
0___________

Reputation: 67476

  1. Always read the documentation.

Description

After the directory specified by path could be opened, it starts to search the directory for items with the name specified by pattern. If the first item is found, the information about the object is stored into the file information structure fno.

The matching pattern can contain wildcard characters (? and *). A ? matches an any character and an * matches an any string in length of zero or longer. When support of long file name is enabled, only fname[] is tested at FF_USE_FIND == 1 and also altname[] is tested at FF_USE_FIND == 2. In this revision, there are some differences listed below between FatFs and standard systems in matching condition.

- "*.*" never matches any name without extension while it matches any name with or without extension at the standard systems.
- Any pattern terminated with a period never matches any name while it matches the name without extensiton at the standard systems.
- DBCS extended characters are compared in case-sensitive at LFN with ANSI/OEM API.

>

QuickInfo

This is a wrapper function of f_opendir and f_readdir function. Available when FF_USE_FIND >= 1 and FF_FS_MINIMIZE <= 1. Examples

/* Search a directory for objects and display it */

void find_image_file (void) {
    FRESULT fr;     /* Return value */
    DIR dj;         /* Directory search object */
    FILINFO fno;    /* File information */

    fr = f_findfirst(&dj, &fno, "", "dsc*.jpg");  /* Start to search for photo files */

    while (fr == FR_OK && fno.fname[0]) {         /* Repeat while an item is found */
        printf("%s\n", fno.fname);                /* Display the object name */
        fr = f_findnext(&dj, &fno);               /* Search for next item */
    }

    f_closedir(&dj); 
    } 
  1. Then you will learn that you need to use:
    • wildcards
    • you need to check the function return value
    • if the first char of the filename is zero - it means that the no file was found

Upvotes: 1

Related Questions