-
Notifications
You must be signed in to change notification settings - Fork 31
Description
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 */