From ed45e813aff84f5646ea7ad1d7ab50f597bdebb9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Mar 2014 08:34:11 +1100 Subject: FAT: move cluster expansion checks to start of IO loops this fixes a filesystem corruption bug at cluster boundaries. Thanks to tkloss for reporting the issue. Fixes issue #12 --- nuttx/fs/fat/fs_fat32.c | 104 +++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c index 2fbb0cba2..1ef2b23e2 100644 --- a/nuttx/fs/fat/fs_fat32.c +++ b/nuttx/fs/fat/fs_fat32.c @@ -518,6 +518,28 @@ static ssize_t fat_read(FAR struct file *filep, char *buffer, size_t buflen) { bytesread = 0; + /* Check if the current read stream has incremented to the next + * cluster boundary + */ + + if (ff->ff_sectorsincluster < 1) + { + /* Find the next cluster in the FAT. */ + + cluster = fat_getcluster(fs, ff->ff_currentcluster); + if (cluster < 2 || cluster >= fs->fs_nclusters) + { + ret = -EINVAL; /* Not the right error */ + goto errout_with_semaphore; + } + + /* Setup to read the first sector from the new cluster */ + + ff->ff_currentcluster = cluster; + ff->ff_currentsector = fat_cluster2sector(fs, cluster); + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + } + fat_read_restart: /* Check if the user has provided a buffer large enough to @@ -616,28 +638,6 @@ fat_read_restart: readsize += bytesread; buflen -= bytesread; sectorindex = filep->f_pos & SEC_NDXMASK(fs); - - /* Check if the current read stream has incremented to the next - * cluster boundary - */ - - if (buflen != 0 && ff->ff_sectorsincluster < 1) - { - /* Find the next cluster in the FAT. */ - - cluster = fat_getcluster(fs, ff->ff_currentcluster); - if (cluster < 2 || cluster >= fs->fs_nclusters) - { - ret = -EINVAL; /* Not the right error */ - goto errout_with_semaphore; - } - - /* Setup to read the first sector from the new cluster */ - - ff->ff_currentcluster = cluster; - ff->ff_currentsector = fat_cluster2sector(fs, cluster); - ff->ff_sectorsincluster = fs->fs_fatsecperclus; - } } fat_semgive(fs); @@ -756,6 +756,34 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, * hold one or more complete sectors. */ + if (ff->ff_sectorsincluster < 1) + { + /* Extend the current cluster by one (unless lseek was used to + * move the file position back from the end of the file) + */ + + cluster = fat_extendchain(fs, ff->ff_currentcluster); + + /* Verify the cluster number */ + + if (cluster < 0) + { + ret = cluster; + goto errout_with_semaphore; + } + else if (cluster < 2 || cluster >= fs->fs_nclusters) + { + ret = -ENOSPC; + goto errout_with_semaphore; + } + + /* Setup to write the first sector from the new cluster */ + + ff->ff_currentcluster = cluster; + ff->ff_sectorsincluster = fs->fs_fatsecperclus; + ff->ff_currentsector = fat_cluster2sector(fs, cluster); + } + fat_write_restart: nsectors = buflen / fs->fs_hwsectorsize; @@ -891,38 +919,6 @@ fat_write_restart: byteswritten += writesize; buflen -= writesize; sectorindex = filep->f_pos & SEC_NDXMASK(fs); - - /* Check if the current read stream has incremented to the next - * cluster boundary - */ - - if (buflen != 0 && ff->ff_sectorsincluster < 1) - { - /* Extend the current cluster by one (unless lseek was used to - * move the file position back from the end of the file) - */ - - cluster = fat_extendchain(fs, ff->ff_currentcluster); - - /* Verify the cluster number */ - - if (cluster < 0) - { - ret = cluster; - goto errout_with_semaphore; - } - else if (cluster < 2 || cluster >= fs->fs_nclusters) - { - ret = -ENOSPC; - goto errout_with_semaphore; - } - - /* Setup to write the first sector from the new cluster */ - - ff->ff_currentcluster = cluster; - ff->ff_sectorsincluster = fs->fs_fatsecperclus; - ff->ff_currentsector = fat_cluster2sector(fs, cluster); - } } /* The transfer has completed without error. Update the file size */ -- cgit v1.2.3