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;
+}
+
+