Fix several problems with accessing FAT filesystems

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@758 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2008-05-31 22:10:21 +00:00
parent be2a62af5a
commit bdf74c42f2
4 changed files with 141 additions and 111 deletions
+7 -4
View File
@@ -353,11 +353,14 @@
* Add configuration for the ZiLOG z8f64200100kit development kit, Z8F6423 part. * Add configuration for the ZiLOG z8f64200100kit development kit, Z8F6423 part.
* Add configuration for the ZiLOG ez80f0910200kitg development kit, EZ80F091 part. * Add configuration for the ZiLOG ez80f0910200kitg development kit, EZ80F091 part.
* Correct critical list handling errors in task shutdown logic: One in timer * Correct critical list handling errors in task shutdown logic: One in timer
deletion logic (timer_delete.c) and one in stream logic (lib_init.c). deletion logic (timer_delete.c) and one in stream logic (lib_init.c) reported
by kwonsk.
0.3.11 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> 0.3.11 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Add support for recursive mutexes. * FEATURE: Add support for recursive mutexes.
* BUGFIX: Eliminate a memory leak -- contained watchdog instance was not * BUGFIX: Eliminate a memory leak -- contained watchdog instance was not
being deleted with a POSIX timer was deleted. being deleted with a POSIX timer was deleted reported by kwonsk.
* BUGFIX: Eliminate a deadlock condition in opendir(). * BUGFIX: Eliminate a deadlock condition in opendir() reported by kwonsk.
* BUGFIX: Fix several FAT filesystem problems reported by kwonsk (Changes
not yet verified).
+7 -4
View File
@@ -979,7 +979,8 @@ nuttx-0.3.10 2008-05-15 Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Add configuration for the ZiLOG z8f64200100kit development kit, Z8F6423 part. * Add configuration for the ZiLOG z8f64200100kit development kit, Z8F6423 part.
* Add configuration for the ZiLOG ez80f0910200kitg development kit, EZ80F091 part. * Add configuration for the ZiLOG ez80f0910200kitg development kit, EZ80F091 part.
* Correct critical list handling errors in task shutdown logic: One in timer * Correct critical list handling errors in task shutdown logic: One in timer
deletion logic (timer_delete.c) and one in stream logic (lib_init.c). deletion logic (timer_delete.c) and one in stream logic (lib_init.c) reported
by kwonsk.
pascal-0.1.2 2008-02-10 Gregory Nutt <spudmonkey@racsa.co.cr> pascal-0.1.2 2008-02-10 Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -1007,10 +1008,12 @@ buildroot-0.1.0 2007-03-09 &lt;spudmonkey@racsa.co.cr&gt
<pre><ul> <pre><ul>
nuttx-0.3.11 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt; nuttx-0.3.11 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Add support for recursive mutexes. * FEATURE: Add support for recursive mutexes.
* BUGFIX: Eliminate a memory leak -- contained watchdog instance was not * BUGFIX: Eliminate a memory leak -- contained watchdog instance was not
being deleted with a POSIX timer was deleted. being deleted with a POSIX timer was deleted reported by kwonsk.
* BUGFIX: Eliminate a deadlock condition in opendir(). * BUGFIX: Eliminate a deadlock condition in opendir() reported by kwonsk.
* BUGFIX: Fix several FAT filesystem problems reported by kwonsk (Changes
not yet verified).
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;
+60 -37
View File
@@ -1,12 +1,13 @@
/**************************************************************************** /****************************************************************************
* fs_fat32.c * fs_fat32.c
* *
* Copyright (C) 2007 Gregory Nutt. All rights reserved. * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr> * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* *
* References: * References:
* Microsoft FAT documentation * Microsoft FAT documentation
* FAT implementation 'Copyright (C) 2007, ChaN, all right reserved.' * Some good ideas were leveraged from the FAT implementation:
* 'Copyright (C) 2007, ChaN, all right reserved.'
* which has an unrestricted license. * which has an unrestricted license.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -19,7 +20,7 @@
* notice, this list of conditions and the following disclaimer in * notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the * the documentation and/or other materials provided with the
* distribution. * distribution.
* 3. Neither the name Gregory Nutt nor the names of its contributors may be * 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software * used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@@ -262,7 +263,7 @@ static int fat_open(FAR struct file *filp, const char *relpath,
/* Yes.. create the file */ /* Yes.. create the file */
ret = fat_dircreate(fs, &dirinfo); ret = fat_dircreate(fs, &dirinfo);
if ( ret < 0) if (ret < 0)
{ {
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@@ -344,10 +345,10 @@ static int fat_open(FAR struct file *filp, const char *relpath,
* handling a lot simpler. * handling a lot simpler.
*/ */
errout_with_struct: errout_with_struct:
free(ff); free(ff);
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -444,7 +445,7 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
if ((ff->ff_oflags & O_RDOK) == 0) if ((ff->ff_oflags & O_RDOK) == 0)
{ {
ret= -EACCES; ret = -EACCES;
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@@ -466,11 +467,13 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
*/ */
readsize = 0; readsize = 0;
readsector = ff->ff_currentsector;
while (buflen > 0) while (buflen > 0)
{ {
/* Get offset into the sector where we begin the read */ /* Get offset into the sector where we begin the read */
int sectorindex = ff->ff_position & SEC_NDXMASK(fs); int sectorindex = ff->ff_position & SEC_NDXMASK(fs);
bytesread = 0;
/* Check if the current read stream happens to lie on a /* Check if the current read stream happens to lie on a
* sector boundary. * sector boundary.
@@ -523,8 +526,9 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
/* Setup to read the first sector from the new cluster */ /* Setup to read the first sector from the new cluster */
ff->ff_currentcluster = cluster; ff->ff_currentcluster = cluster;
readsector = fat_cluster2sector(fs, cluster);
ff->ff_sectorsincluster = fs->fs_fatsecperclus; ff->ff_sectorsincluster = fs->fs_fatsecperclus;
readsector = fat_cluster2sector(fs, cluster);
}
} }
/* Check if the user has provided a buffer large enough to /* Check if the user has provided a buffer large enough to
@@ -562,6 +566,7 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
} }
ff->ff_sectorsincluster -= nsectors - 1; ff->ff_sectorsincluster -= nsectors - 1;
ff->ff_currentsector = readsector + nsectors - 1;
bytesread = nsectors * fs->fs_hwsectorsize; bytesread = nsectors * fs->fs_hwsectorsize;
} }
else else
@@ -586,6 +591,7 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
} }
memcpy(userbuffer, &ff->ff_buffer[sectorindex], bytesread); memcpy(userbuffer, &ff->ff_buffer[sectorindex], bytesread);
ff->ff_currentsector = readsector;
} }
/* Set up for the next sector read */ /* Set up for the next sector read */
@@ -595,12 +601,11 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
readsize += bytesread; readsize += bytesread;
buflen -= bytesread; buflen -= bytesread;
} }
}
fat_semgive(fs); fat_semgive(fs);
return readsize; return readsize;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -648,7 +653,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
if ((ff->ff_oflags & O_WROK) == 0) if ((ff->ff_oflags & O_WROK) == 0)
{ {
ret= -EACCES; ret = -EACCES;
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@@ -665,6 +670,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
*/ */
byteswritten = 0; byteswritten = 0;
writesector = ff->ff_currentsector;
while (buflen > 0) while (buflen > 0)
{ {
/* Get offset into the sector where we begin the read */ /* Get offset into the sector where we begin the read */
@@ -744,8 +750,8 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
/* Setup to write the first sector from the new cluster */ /* Setup to write the first sector from the new cluster */
ff->ff_currentcluster = cluster; ff->ff_currentcluster = cluster;
writesector = fat_cluster2sector(fs, cluster);
ff->ff_sectorsincluster = fs->fs_fatsecperclus; ff->ff_sectorsincluster = fs->fs_fatsecperclus;
writesector = fat_cluster2sector(fs, cluster);
} }
} }
@@ -792,6 +798,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
} }
ff->ff_sectorsincluster -= nsectors - 1; ff->ff_sectorsincluster -= nsectors - 1;
ff->ff_currentsector = writesector + nsectors - 1;
writesize = nsectors * fs->fs_hwsectorsize; writesize = nsectors * fs->fs_hwsectorsize;
ff->ff_bflags |= FFBUFF_MODIFIED; ff->ff_bflags |= FFBUFF_MODIFIED;
} }
@@ -843,7 +850,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
fat_semgive(fs); fat_semgive(fs);
return byteswritten; return byteswritten;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -1074,7 +1081,7 @@ static off_t fat_seek(FAR struct file *filp, off_t offset, int whence)
fat_semgive(fs); fat_semgive(fs);
return OK; return OK;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -1210,7 +1217,7 @@ static int fat_sync(FAR struct file *filp)
ret = fat_updatefsinfo(fs); ret = fat_updatefsinfo(fs);
} }
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -1257,12 +1264,14 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct intern
if (dirinfo.fd_entry == NULL) if (dirinfo.fd_entry == NULL)
{ {
/* Handler the FAT12/16 root directory */ /* Handle the FAT12/16/32 root directory using the values setup by
* fat_finddirentry() above.
*/
dir->u.fat.fd_startcluster = 0; dir->u.fat.fd_startcluster = dirinfo.dir.fd_startcluster;
dir->u.fat.fd_currcluster = 0; dir->u.fat.fd_currcluster = dirinfo.dir.fd_currcluster;
dir->u.fat.fd_currsector = fs->fs_rootbase; dir->u.fat.fd_currsector = dirinfo.dir.fd_currsector;
dir->u.fat.fd_index = 2; dir->u.fat.fd_index = dirinfo.dir.fd_index;
} }
/* This is not the root directory. Verify that it is some kind of directory */ /* This is not the root directory. Verify that it is some kind of directory */
@@ -1307,7 +1316,7 @@ static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir)
ubyte *direntry; ubyte *direntry;
ubyte ch; ubyte ch;
ubyte attribute; ubyte attribute;
int ret; int ret = OK;
/* Sanity checks */ /* Sanity checks */
@@ -1332,7 +1341,7 @@ static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir)
while (dir->u.fat.fd_currsector && dir->fd_dir.d_name[0] == '\0') while (dir->u.fat.fd_currsector && dir->fd_dir.d_name[0] == '\0')
{ {
ret = fat_fscacheread(fs, dir->u.fat.fd_currsector); ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);
if ( ret < 0) if (ret < 0)
{ {
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@@ -1380,7 +1389,8 @@ static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir)
if (fat_nextdirentry(fs, &dir->u.fat) != OK) if (fat_nextdirentry(fs, &dir->u.fat) != OK)
{ {
dir->u.fat.fd_currsector = 0; ret = -ENOENT;
goto errout_with_semaphore;
} }
} }
@@ -1389,7 +1399,7 @@ static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir)
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ERROR; return ret;
} }
/**************************************************************************** /****************************************************************************
@@ -1423,13 +1433,23 @@ static int fat_rewinddir(struct inode *mountpt, struct internal_dir_s *dir)
/* Check if this is the root directory */ /* Check if this is the root directory */
if (dir->u.fat.fd_startcluster == 0) if (fs->fs_type != FSTYPE_FAT32 &&
dir->u.fat.fd_startcluster == 0)
{ {
/* Handler the FAT12/16 root directory */ /* Handle the FAT12/16 root directory */
dir->u.fat.fd_currcluster = 0; dir->u.fat.fd_currcluster = 0;
dir->u.fat.fd_currsector = fs->fs_rootbase; dir->u.fat.fd_currsector = fs->fs_rootbase;
dir->u.fat.fd_index = 2; dir->u.fat.fd_index = 0;
}
else if (fs->fs_type == FSTYPE_FAT32 &&
dir->u.fat.fd_startcluster == fs->fs_rootbase)
{
/* Handle the FAT32 root directory */
dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster;
dir->u.fat.fd_currsector = fat_cluster2sector(fs, fs->fs_rootbase);
dir->u.fat.fd_index = 0;
} }
/* This is not the root directory */ /* This is not the root directory */
@@ -1473,7 +1493,7 @@ static int fat_bind(FAR struct inode *blkdriver, const void *data,
return -ENODEV; return -ENODEV;
} }
if ( blkdriver->u.i_bops->open && if (blkdriver->u.i_bops->open &&
blkdriver->u.i_bops->open(blkdriver) != OK) blkdriver->u.i_bops->open(blkdriver) != OK)
{ {
return -ENODEV; return -ENODEV;
@@ -1482,7 +1502,7 @@ static int fat_bind(FAR struct inode *blkdriver, const void *data,
/* Create an instance of the mountpt state structure */ /* Create an instance of the mountpt state structure */
fs = (struct fat_mountpt_s *)zalloc(sizeof(struct fat_mountpt_s)); fs = (struct fat_mountpt_s *)zalloc(sizeof(struct fat_mountpt_s));
if ( !fs ) if (!fs)
{ {
return -ENOMEM; return -ENOMEM;
} }
@@ -1500,7 +1520,7 @@ static int fat_bind(FAR struct inode *blkdriver, const void *data,
*/ */
ret = fat_mount(fs, TRUE); ret = fat_mount(fs, TRUE);
if ( ret != 0 ) if (ret != 0)
{ {
sem_destroy(&fs->fs_sem); sem_destroy(&fs->fs_sem);
free(fs); free(fs);
@@ -1525,7 +1545,7 @@ static int fat_unbind(void *handle, FAR struct inode **blkdriver)
struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle; struct fat_mountpt_s *fs = (struct fat_mountpt_s*)handle;
int ret; int ret;
if ( !fs ) if (!fs)
{ {
return -EINVAL; return -EINVAL;
} }
@@ -1881,7 +1901,7 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
fat_semgive(fs); fat_semgive(fs);
return OK; return OK;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -2061,7 +2081,7 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
fat_semgive(fs); fat_semgive(fs);
return OK; return OK;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
@@ -2111,9 +2131,13 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
goto errout_with_semaphore; goto errout_with_semaphore;
} }
if (! dirinfo.fd_entry) memset(buf, 0, sizeof(struct stat));
if (!dirinfo.fd_entry)
{ {
ret = -ENOENT; /* It's directory name of mount point */
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IWOTH|S_IWGRP|S_IWUSR;
ret = OK;
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@@ -2130,7 +2154,6 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
* by everyone but may be writeable by no-one. * by everyone but may be writeable by no-one.
*/ */
memset(buf, 0, sizeof(struct stat));
buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR; buf->st_mode = S_IROTH|S_IRGRP|S_IRUSR;
if ((attribute & FATATTR_READONLY) == 0) if ((attribute & FATATTR_READONLY) == 0)
{ {
@@ -2176,7 +2199,7 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
ret = OK; ret = OK;
errout_with_semaphore: errout_with_semaphore:
fat_semgive(fs); fat_semgive(fs);
return ret; return ret;
} }
+5 -4
View File
@@ -6,7 +6,8 @@
* *
* References: * References:
* Microsoft FAT documentation * Microsoft FAT documentation
* FAT implementation 'Copyright (C) 2007, ChaN, all right reserved.' * Some good ideas were leveraged from the FAT implementation:
* 'Copyright (C) 2007, ChaN, all right reserved.'
* which has an unrestricted license. * which has an unrestricted license.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -1340,7 +1341,7 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
* been examined. * been examined.
*/ */
if (ndx >= DIRSEC_NDIRS(fs)) if ((ndx & (DIRSEC_NDIRS(fs)-1)) == 0)
{ {
/* Yes, then we will have to read the next sector */ /* Yes, then we will have to read the next sector */
@@ -1352,7 +1353,7 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
if (!dir->fd_currcluster) if (!dir->fd_currcluster)
{ {
/* For FAT12/13, the boot record tells us number of 32-bit directories /* For FAT12/16, the boot record tells us number of 32-bit directories
* that are contained in the root directory. This should correspond to * that are contained in the root directory. This should correspond to
* an even number of sectors. * an even number of sectors.
*/ */
@@ -1381,7 +1382,7 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
* has been examined. * has been examined.
*/ */
if (sector >= fs->fs_fatsecperclus) if ((sector & (fs->fs_fatsecperclus-1)) == 0)
{ {
/* Get next cluster */ /* Get next cluster */