Skip to content

exFAT: fx_dir_entry_available_file_size is not updated when writing to a file #11

@joel-jetcharge

Description

@joel-jetcharge

When calling fx_file_write on a file the fx_file_dir_entry.fx_dir_entry_available_file_size field is not being updated before saving the directory entry. This causes issues when a file is re-opened as the fx_file_current_available_size field will be set to 0 even though disk space has been allocated.

Example code to demonstrate issue:

FX_FILE test_file = { 0U };
const char test_data[] = "ABCD1234";

// Create a new file and open
fx_file_create(media_ptr, "test_file.txt");
fx_file_open(media_ptr, &test_file, "test_file.txt", FX_OPEN_FOR_WRITE);

// Write some data to the file
fx_file_write(&test_file, (void*)test_data, sizeof(test_data));

// Observe the fx_file_current_available_size value. This will be non-zero, 
// in my case 8192 (the size of my cluster).
uint64_t previous_available_size = test_file.fx_file_current_available_size;

// Close the file. It would be expected that the available_size would have been saved.
fx_file_close(&test_file);

memset(&test_file, 0U, sizeof(test_file));

// Re-open the file.
fx_file_open(media_ptr, &test_file, "test_file.txt", FX_OPEN_FOR_WRITE);

// Observe that the fx_file_current_available_size is 0!
uint64_t current_available_size = test_file.fx_file_current_available_size;

Continuing to write to a file in this state causes unexpected behaviour. As fx_file_current_file_offset is non-zero we get an underflow on fx_file_write.c:292:

    /* Next, determine if there is enough room to write the specified number of
       bytes to the clusters already allocated to this file.  */
    if (((file_ptr -> fx_file_current_available_size - file_ptr -> fx_file_current_file_offset) < size)

The driver will continue to think there is enough space allocated even when there is not. Clusters will be written to even though they were not properly allocated.

I tested with both Fault Tolerant module on and off, with same results for exFAT.
I also tested with FAT16 which does not have the issue as fx_file_current_available_size is calculated differently.

Workaround:
As a temporary fix I've added the following code to fx_file_write.c:1603 and fx_file_write.c:1698 (i.e. below where fx_file_dir_entry.fx_dir_entry_file_size is updated):

#ifdef FX_ENABLE_EXFAT
        file_ptr -> fx_file_dir_entry.fx_dir_entry_available_file_size = 
            file_ptr -> fx_file_current_available_size;  
#endif /* FX_ENABLE_EXFAT */

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions