diff options
-rw-r--r-- | nuttx/ChangeLog | 5 | ||||
-rw-r--r-- | nuttx/fs/fat/fs_fat32.c | 45 |
2 files changed, 41 insertions, 9 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index c916d8cf9..a5aaa89a2 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2085,4 +2085,7 @@ used. There are other issues with the "a+" modes (see the top-level TODO list). * drivers/usbdev/cdc_serial.c and include/nuttx/usb/cdc.h and cdc_serial.h: - Add support for the CDC ACM serial device class.
\ No newline at end of file + Add support for the CDC ACM serial device class. + * fs/fat/fs_fat32.c: Fix a critical bug in the write logic: It a tiny write + cross a sector boundary, then two sector writes will occur. The first part + in the first sector may be written to the wrong sector number. diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c index d41df88d5..c7157b091 100644 --- a/nuttx/fs/fat/fs_fat32.c +++ b/nuttx/fs/fat/fs_fat32.c @@ -630,6 +630,7 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, int32_t cluster; unsigned int byteswritten; unsigned int writesize; + unsigned int bufsize; unsigned int nsectors; uint8_t *userbuffer = (uint8_t*)buffer; int sectorindex; @@ -776,28 +777,56 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, goto errout_with_semaphore; } } + else + { + /* But in this rare case, we do have to mark the unused cached + * buffer as the current buffer. + */ + + ff->ff_cachesector = ff->ff_currentsector; + } /* Copy the partial sector from the user buffer */ - writesize = fs->fs_hwsectorsize - sectorindex; - if (writesize > buflen) + bufsize = fs->fs_hwsectorsize - sectorindex; + if (bufsize > buflen) { - /* We will not write to the end of the buffer */ + /* We will not write to the end of the buffer. Set + * write size to the size of the user buffer. + */ writesize = buflen; } else { - /* We will write to the end of the buffer (or beyond) */ + /* We will write to the end of the cached sector and + * perhaps beyond. Set writesize to the number of + * bytes still available in the cached sector. + */ - ff->ff_sectorsincluster--; - ff->ff_currentsector++; + writesize = bufsize; } + /* Copy the data into the cached sector and make sure that the + * cached sector is marked "dirty" + */ + memcpy(&ff->ff_buffer[sectorindex], userbuffer, writesize); + ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED); + + /* Do we need to write more in the next sector? We may need + * to this if we wrote to the end of the cached sector. + */ - ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED); - ff->ff_cachesector = ff->ff_currentsector; + if (writesize >= bufsize) + { + /* We will write to the end of the buffer (or beyond). Bump + * up the current sector number. + */ + + ff->ff_sectorsincluster--; + ff->ff_currentsector++; + } } /* Set up for the next write */ |