Fix FAT seek bug

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@896 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2008-09-08 17:04:14 +00:00
parent 7f85f96228
commit d57cb4fc90
5 changed files with 79 additions and 25 deletions

View File

@ -459,4 +459,6 @@
* Fixed several critical bugs with regard to fat reading and writing and FAT12 * 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 accesses. Basically the FAT FS only worked with my tiny test files and test
cases. A lot of stronger FAT tested is needed!! 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.

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4"> <tr align="center" bgcolor="#e4e4e4">
<td> <td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1> <h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: September 7, 2008</p> <p>Last Updated: September 8, 2008</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -1117,6 +1117,8 @@ nuttx-0.3.14 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Fixed several critical bugs with regard to fat reading and writing and FAT12 * 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 accesses. Basically the FAT FS only worked with my tiny test files and test
cases. A lot of stronger FAT tested is needed!! 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 &lt;spudmonkey@racsa.co.cr&gt; pascal-0.1.3 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;

View File

@ -44,6 +44,7 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statfs.h> #include <sys/statfs.h>
@ -478,9 +479,11 @@ static ssize_t fat_read(FAR struct file *filep, char *buffer, size_t buflen)
* and the file offset. * and the file offset.
*/ */
ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) ret = fat_currentsector(fs, ff, filep->f_pos);
+ (SEC_NSECTORS(fs, filep->f_pos) & CLUS_NDXMASK(fs)); if (ret < 0)
fdbg("Start with sector: %d\n", ff->ff_currentsector); {
return ret;
}
} }
/* Loop until either (1) all data has been transferred, or (2) an /* 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. * and the file offset.
*/ */
ff->ff_currentsector = fat_cluster2sector(fs, ff->ff_currentcluster) ret = fat_currentsector(fs, ff, filep->f_pos);
+ (SEC_NSECTORS(fs, filep->f_pos) & CLUS_NDXMASK(fs)); if (ret < 0)
{
return ret;
}
} }
/* Loop until either (1) all data has been transferred, or (2) an /* 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); 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 */ /* 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; sint32 cluster;
ssize_t position; ssize_t position;
unsigned int clustersize; unsigned int clustersize;
unsigned int sectoroffset;
int ret; int ret;
/* Sanity checks */ /* 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) if (position > ff->ff_size && (ff->ff_oflags & O_WROK) == 0)
{ {
/* Otherwise, the position is limited to the file size */ /* Otherwise, the position is limited to the file size */
position = ff->ff_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; ff->ff_currentcluster = cluster;
if (position <= clustersize) if (position < clustersize)
{ {
break; 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 /* We get here after we have found the sector containing
* the requested position. * 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 /* Then get the current sector from the cluster and the offset
* the sectoroffset into the cluster. * into the cluster from the position
*/ */
ff->ff_currentsector = (void)fat_currentsector(fs, ff, filep->f_pos);
fat_cluster2sector(fs, cluster) + sectoroffset;
/* Load the sector corresponding to the position */ /* 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 */ /* Check if the has been modified in any way */
if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0) if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0)
{ {
/* Flush any unwritten data in the file buffer */ /* Flush any unwritten data in the file buffer */

View File

@ -162,7 +162,7 @@
#define SEC_NDXMASK(f) ((f)->fs_hwsectorsize - 1) #define SEC_NDXMASK(f) ((f)->fs_hwsectorsize - 1)
#define SEC_NSECTORS(f,n) ((n) / (f)->fs_hwsectorsize) #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 */ * File system types */
@ -615,8 +615,9 @@ EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s
/* FSINFO sector support */ /* FSINFO sector support */
EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs); EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs);
EXTERN int fat_nfreeclusters(struct fat_mountpt_s *fs, size_t *pfreeclusters); 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 #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)

View File

@ -44,6 +44,7 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -2303,7 +2304,8 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff)
/* Then discard the current cache contents */ /* Then discard the current cache contents */
ff->ff_bflags &= ~FFBUFF_VALID; ff->ff_bflags &= ~FFBUFF_VALID;
ff->ff_cachesector = 0;
} }
return OK; return OK;
} }
@ -2461,3 +2463,47 @@ int fat_nfreeclusters(struct fat_mountpt_s *fs, size_t *pfreeclusters)
return OK; 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;
}