9
0
Fork 0

Fix a critical bug in FAT sector management

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3955 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2011-09-15 20:05:00 +00:00
parent 0f59e002d8
commit f43f971898
2 changed files with 42 additions and 10 deletions

View File

@ -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.
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.

View File

@ -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.
*/
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.
*/
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++;
}
memcpy(&ff->ff_buffer[sectorindex], userbuffer, writesize);
ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED);
ff->ff_cachesector = ff->ff_currentsector;
}
/* Set up for the next write */