Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
joel-jetcharge opened this issue Sep 29, 2022 · 1 comment

Comments

@joel-jetcharge
Copy link

joel-jetcharge commented Sep 29, 2022

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 */
@gaelbourreau
Copy link

Hi,
thank you for the workaround. It works for me.

Also, it seems that the issue is related to the SEARCH_CACHE feature.
When the macro FX_MEDIA_DISABLE_SEARCH_CACHE is defined, there is no problem.
But the reopening process will be more expensive.

@eclipsewebmaster eclipsewebmaster transferred this issue from another repository Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants