diff --git a/ChangeLog b/ChangeLog index bb4f3ac046..7bfeca0818 100644 --- a/ChangeLog +++ b/ChangeLog @@ -459,4 +459,6 @@ * Fixed several critical bugs with regard to fat reading and writing and FAT12 accesses. Basically the FAT FS only worked with my tiny test files and test cases. A lot of stronger FAT tested is needed!! + * Fixed another FAT bug in implementation of FAT lseek; this prohibit correct + random access to large files. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index b6693b8d56..ad71c555fe 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: September 7, 2008

+

Last Updated: September 8, 2008

@@ -1117,6 +1117,8 @@ nuttx-0.3.14 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * Fixed several critical bugs with regard to fat reading and writing and FAT12 accesses. Basically the FAT FS only worked with my tiny test files and test cases. A lot of stronger FAT tested is needed!! + * Fixed another FAT bug in implementation of FAT lseek; this prohibit correct + random access to large files. pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/fs/fat/fs_fat32.c b/fs/fat/fs_fat32.c index 47290642d8..97ec1fd496 100644 --- a/fs/fat/fs_fat32.c +++ b/fs/fat/fs_fat32.c @@ -44,6 +44,7 @@ ****************************************************************************/ #include + #include #include #include @@ -478,9 +479,11 @@ static ssize_t fat_read(FAR struct file *filep, char *buffer, size_t buflen) * and the file offset. */ - ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) - + (SEC_NSECTORS(fs, filep->f_pos) & CLUS_NDXMASK(fs)); - fdbg("Start with sector: %d\n", ff->ff_currentsector); + ret = fat_currentsector(fs, ff, filep->f_pos); + if (ret < 0) + { + return ret; + } } /* Loop until either (1) all data has been transferred, or (2) an @@ -676,8 +679,11 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, * and the file offset. */ - ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) - + (SEC_NSECTORS(fs, filep->f_pos) & CLUS_NDXMASK(fs)); + ret = fat_currentsector(fs, ff, filep->f_pos); + if (ret < 0) + { + return ret; + } } /* Loop until either (1) all data has been transferred, or (2) an @@ -773,7 +779,9 @@ static ssize_t fat_write(FAR struct file *filep, const char *buffer, } memcpy(&ff->ff_buffer[sectorindex], userbuffer, writesize); - ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED); + + ff->ff_bflags |= (FFBUFF_DIRTY|FFBUFF_VALID|FFBUFF_MODIFIED); + ff->ff_cachesector = ff->ff_currentsector; } /* Set up for the next write */ @@ -844,7 +852,6 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) sint32 cluster; ssize_t position; unsigned int clustersize; - unsigned int sectoroffset; int ret; /* Sanity checks */ @@ -906,6 +913,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) if (position > ff->ff_size && (ff->ff_oflags & O_WROK) == 0) { /* Otherwise, the position is limited to the file size */ + position = ff->ff_size; } @@ -948,7 +956,7 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) */ ff->ff_currentcluster = cluster; - if (position <= clustersize) + if (position < clustersize) { break; } @@ -1015,16 +1023,17 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) /* We get here after we have found the sector containing * the requested position. + * + * Save the new file position */ - sectoroffset = (position - 1) / fs->fs_hwsectorsize; + filep->f_pos += position; - /* And get the current sector from the cluster and - * the sectoroffset into the cluster. + /* Then get the current sector from the cluster and the offset + * into the cluster from the position */ - ff->ff_currentsector = - fat_cluster2sector(fs, cluster) + sectoroffset; + (void)fat_currentsector(fs, ff, filep->f_pos); /* Load the sector corresponding to the position */ @@ -1037,13 +1046,6 @@ static off_t fat_seek(FAR struct file *filep, off_t offset, int whence) } } - /* Save the number of sectors left in the cluster */ - - ff->ff_sectorsincluster = fs->fs_fatsecperclus - sectoroffset; - - /* And save the new file position */ - - filep->f_pos += position; } } @@ -1141,6 +1143,7 @@ static int fat_sync(FAR struct file *filep) } /* Check if the has been modified in any way */ + if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0) { /* Flush any unwritten data in the file buffer */ diff --git a/fs/fat/fs_fat32.h b/fs/fat/fs_fat32.h index 576e7ea84a..55d6fbbb49 100644 --- a/fs/fat/fs_fat32.h +++ b/fs/fat/fs_fat32.h @@ -162,7 +162,7 @@ #define SEC_NDXMASK(f) ((f)->fs_hwsectorsize - 1) #define SEC_NSECTORS(f,n) ((n) / (f)->fs_hwsectorsize) -#define CLUS_NDXMASK(f) ((f)->fs_fatsecperclus -1) +#define CLUS_NDXMASK(f) ((f)->fs_fatsecperclus - 1) /**************************************************************************** * File system types */ @@ -615,8 +615,9 @@ EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s /* FSINFO sector support */ -EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs); -EXTERN int fat_nfreeclusters(struct fat_mountpt_s *fs, size_t *pfreeclusters); +EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs); +EXTERN int fat_nfreeclusters(struct fat_mountpt_s *fs, size_t *pfreeclusters); +EXTERN int fat_currentsector(struct fat_mountpt_s *fs, struct fat_file_s *ff, off_t position); #undef EXTERN #if defined(__cplusplus) diff --git a/fs/fat/fs_fat32util.c b/fs/fat/fs_fat32util.c index c6680b6f03..f38cc3741a 100644 --- a/fs/fat/fs_fat32util.c +++ b/fs/fat/fs_fat32util.c @@ -44,6 +44,7 @@ ****************************************************************************/ #include + #include #include #include @@ -2303,7 +2304,8 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff) /* Then discard the current cache contents */ - ff->ff_bflags &= ~FFBUFF_VALID; + ff->ff_bflags &= ~FFBUFF_VALID; + ff->ff_cachesector = 0; } return OK; } @@ -2461,3 +2463,47 @@ int fat_nfreeclusters(struct fat_mountpt_s *fs, size_t *pfreeclusters) return OK; } +/**************************************************************************** + * Name: fat_nfreeclusters + * + * Desciption: + * Given the file position, set the correct current sector to access. + * + ****************************************************************************/ + +int fat_currentsector(struct fat_mountpt_s *fs, struct fat_file_s *ff, + off_t position) +{ + int sectoroffset; + + if (position <= ff->ff_size ) + { + /* sectoroffset is the sector number offset into the current cluster */ + + sectoroffset = SEC_NSECTORS(fs, position) & CLUS_NDXMASK(fs); + + /* The current cluster is the the first sector of the cluster plus + * the sector offset + */ + + ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) + + sectoroffset; + + /* The remainder is the number of sectors left in the cluster to be + * read/written + */ + + ff->ff_sectorsincluster = fs->fs_fatsecperclus - sectoroffset; + + fvdbg("position=%d currentsector=%d sectorsincluster=%d\n", + position, ff->ff_currentsector, ff->ff_sectorsincluster); + + return OK; + } + + /* The position does not lie within the file */ + + return -ENOSPC; +} + +