9
0
Fork 0

Add support for close and fsync

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@242 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-05-20 19:25:58 +00:00
parent 1c163ff0b5
commit cc98a856a8
6 changed files with 296 additions and 68 deletions

View File

@ -77,7 +77,7 @@ int close(int fd)
* may have been opened numerous times (for different file
* descriptors) and must also handle being closed numerous times.
* (3) for the case of the mountpoint, we depend on the close
* methods bing identical in signal and position in the operations
* methods bing identical in signature and position in the operations
* vtable.
*/

View File

@ -75,6 +75,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
size_t buflen);
static off_t fat_seek(FAR struct file *filp, off_t offset, int whence);
static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg);
static int fat_sync(FAR struct file *filp);
static int fat_bind(FAR struct inode *blkdriver, const void *data,
void **handle);
static int fat_unbind(void *handle);
@ -100,6 +101,7 @@ const struct mountpt_operations fat_operations =
fat_write,
fat_seek,
fat_ioctl,
fat_sync,
fat_bind,
fat_unbind
};
@ -326,12 +328,13 @@ static int fat_close(FAR struct file *filp)
struct inode *inode;
struct fat_mountpt_s *fs;
struct fat_file_s *ff;
int ret = OK;
/* Sanity checks */
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from struct file instance */
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
@ -343,7 +346,26 @@ static int fat_close(FAR struct file *filp)
* the file even when there is healthy mount.
*/
return -ENOSYS;
/* Synchronize the file buffers and disk content; update times */
ret = fat_sync(filp);
/* Then deallocate the memory structures created when the open method
* was called.
*
* Free the sector buffer that was used to manage partial sector accesses.
*/
if (ff->ff_buffer)
{
free(ff->ff_buffer);
}
/* Then free the file structure itself. */
free(ff);
filp->f_priv = NULL;
return ret;
}
/****************************************************************************
@ -361,14 +383,14 @@ static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen)
unsigned int nsectors;
size_t readsector;
size_t bytesleft;
char *userbuffer = buffer;
ubyte *userbuffer = (ubyte*)buffer;
int ret;
/* Sanity checks */
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from struct file instance */
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
@ -564,7 +586,7 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from struct file instance */
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
@ -578,8 +600,11 @@ static ssize_t fat_write(FAR struct file *filp, const char *buffer,
ret = fat_checkmount(fs);
if (ret != OK)
{
fat_semgive(fs);
return ret;
}
fat_semgive(fs);
return -ENOSYS;
}
@ -598,7 +623,7 @@ static off_t fat_seek(FAR struct file *filp, off_t offset, int whence)
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from struct file instance */
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
@ -612,8 +637,11 @@ static off_t fat_seek(FAR struct file *filp, off_t offset, int whence)
ret = fat_checkmount(fs);
if (ret != OK)
{
fat_semgive(fs);
return ret;
}
fat_semgive(fs);
return -ENOSYS;
}
@ -632,7 +660,7 @@ static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg)
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from struct file instance */
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
@ -646,13 +674,112 @@ static int fat_ioctl(FAR struct file *filp, int cmd, unsigned long arg)
ret = fat_checkmount(fs);
if (ret != OK)
{
fat_semgive(fs);
return ret;
}
/* ioctl calls are just passed through to the contained block driver */
fat_semgive(fs);
return -ENOSYS;
}
/****************************************************************************
* Name: fat_sync
*
* Description: Synchronize the file state on disk to match internal, in-
* memory state.
*
****************************************************************************/
static int fat_sync(FAR struct file *filp)
{
struct inode *inode;
struct fat_mountpt_s *fs;
struct fat_file_s *ff;
uint32 wrttime;
ubyte *direntry;
int ret;
/* Sanity checks */
DEBUGASSERT(filp->f_priv != NULL && filp->f_inode != NULL);
/* Recover our private data from the struct file instance */
ff = filp->f_priv;
inode = filp->f_inode;
fs = inode->i_private;
DEBUGASSERT(fs != NULL);
/* Make sure that the mount is still healthy */
fat_semtake(fs);
ret = fat_checkmount(fs);
if (ret != OK)
{
goto errout_with_semaphore;
}
/* Check if the has been modified in any way */
if ((ff->ff_bflags & FFBUFF_MODIFIED) != 0)
{
/* Flush any unwritten data in the file buffer */
ret = fat_ffcacheflush(fs, ff);
if (ret < 0)
{
goto errout_with_semaphore;
}
/* Update the directory entry. First read the directory
* entry into the fs_buffer (preserving the ff_buffer)
*/
ret = fat_fscacheread(fs, ff->ff_dirsector);
if (ret < 0)
{
goto errout_with_semaphore;
}
/* Recover a pointer to the specific directory entry
* in the sector using the saved directory index.
*/
direntry = &fs->fs_buffer[ff->ff_dirindex];
/* Set the archive bit, set the write time, and update
* anything that may have* changed in the directory
* entry: the file size, and the start cluster
*/
direntry[DIR_ATTRIBUTES] |= FATATTR_ARCHIVE;
DIR_PUTFILESIZE(direntry, ff->ff_size);
DIR_PUTFSTCLUSTLO(direntry, ff->ff_startcluster);
DIR_PUTFSTCLUSTHI(direntry, ff->ff_startcluster >> 16);
wrttime = fat_gettime();
DIR_PUTWRTTIME(direntry, wrttime);
/* Clear the modified bit in the flags */
ff->ff_bflags &= ~FFBUFF_MODIFIED;
/* Flush these change to disk and update FSINFO (if
* appropriate.
*/
fs->fs_dirty = TRUE;
ret = fat_updatefsinfo(fs);
}
errout_with_semaphore:
fat_semgive(fs);
return ret;
}
/****************************************************************************
* Name: fat_bind
*

View File

@ -289,6 +289,12 @@
# define DIR_GETFSTCLUSTLO(p) fat_getuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO))
# define DIR_GETFILESIZE(p) fat_getuint32(UBYTE_PTR(p,DIR_FILESIZE))
# define FSI_GETLEADSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_LEADSIG))
# define FSI_GETSTRUCTSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_STRUCTSIG))
# define FSI_GETFREECOUNT(p) fat_getuint32(UBYTE_PTR(p,FSI_FREECOUNT))
# define FSI_GETNXTFREE(p) fat_getuint32(UBYTE_PTR(p,FSI_NXTFREE))
# define FSI_GETTRAILSIG(p) fat_getuint32(UBYTE_PTR(p,FSI_TRAILSIG))
# define FAT_GETFAT16(p,i) fat_getuint16(UBYTE_PTR(p,i))
# define FAT_GETFAT32(p,i) fat_getuint32(UBYTE_PTR(p,i))
@ -321,6 +327,12 @@
# define DIR_PUTFSTCLUSTLO(p,v) fat_putuint16(UBYTE_PTR(p,DIR_FSTCLUSTLO),v)
# define DIR_PUTFILESIZE(p,v) fat_putuint32(UBYTE_PTR(p,DIR_FILESIZE),v)
# define FSI_PUTLEADSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_LEADSIG),v)
# define FSI_PUTSTRUCTSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_STRUCTSIG),v)
# define FSI_PUTFREECOUNT(p,v) fat_putuint32(UBYTE_PTR(p,FSI_FREECOUNT),v)
# define FSI_PUTNXTFREE(p,v) fat_putuint32(UBYTE_PTR(p,FSI_NXTFREE),v)
# define FSI_PUTTRAILSIG(p,v) fat_putuint32(UBYTE_PTR(p,FSI_TRAILSIG),v)
# define FAT_PUTFAT16(p,i,v) fat_putuint16(UBYTE_PTR(p,i),v)
# define FAT_PUTFAT32(p,i,v) fat_putuint32(UBYTE_PTR(p,i),v)
@ -361,6 +373,12 @@
# define DIR_GETFSTCLUSTLO(p) UINT16_VAL(p,DIR_FSTCLUSTLO)
# define DIR_GETFILESIZE(p) UINT32_VAL(p,DIR_FILESIZE)
# define FSI_GETLEADSIG(p) UINT32_VAL(p,FSI_LEADSIG)
# define FSI_GETSTRUCTSIG(p) UINT32_VAL(p,FSI_STRUCTSIG)
# define FSI_GETFREECOUNT(p) UINT32_VAL(p,FSI_FREECOUNT)
# define FSI_GETNXTFREE(p) UINT32_VAL(p,FSI_NXTFREE)
# define FSI_GETTRAILSIG(p) UINT32_VAL(p,FSI_TRAILSIG)
# define FAT_GETFAT16(p,i) UINT16_VAL(p,i)
# define FAT_GETFAT32(p,i) UINT32_VAL(p,i)
@ -393,6 +411,12 @@
# define DIR_PUTFSTCLUSTLO(p,v) UINT16_PUT(p,DIR_FSTCLUSTLO,v)
# define DIR_PUTFILESIZE(p,v) UINT32_PUT(p,DIR_FILESIZE,v)
# define FSI_PUTLEADSIG(p,v) UINT32_PUT(p,FSI_LEADSIG,v)
# define FSI_PUTSTRUCTSIG(p,v) UINT32_PUT(p,FSI_STRUCTSIG,v)
# define FSI_PUTFREECOUNT(p,v) UINT32_PUT(p,FSI_FREECOUNT,v)
# define FSI_PUTNXTFREE(p,v) UINT32_PUT(p,FSI_NXTFREE,v)
# define FSI_PUTTRAILSIG(p,v) UINT32_PUT(p,FSI_TRAILSIG,v)
# define FAT_PUTFAT16(p,i,v) UINT16_PUT(p,i,v)
# define FAT_PUTFAT32(p,i,v) UINT32_PUT(p,i,v)
@ -430,6 +454,7 @@ struct fat_mountpt_s
uint16 fs_rootentcnt; /* MBR: Count of 32-bit root directory entries */
boolean fs_mounted; /* TRUE: The file system is ready */
boolean fs_dirty; /* TRUE: fs_buffer is dirty */
boolean fs_fsidirty; /* TRUE: FSINFO sector must be written to disk */
ubyte fs_type; /* FSTYPE_FAT12, FSTYPE_FAT16, or FSTYPE_FAT32 */
ubyte fs_fatnumfats; /* MBR: Number of FATs (probably 2) */
ubyte fs_fatsecperclus; /* MBR: Sectors per allocation unit: 2**n, n=0..7 */
@ -446,7 +471,7 @@ struct fat_file_s
{
struct fat_file_s *ff_next; /* Retained in a singly linked list */
boolean ff_open; /* TRUE: The file is (still) open */
boolean ff_bflags; /* The file buffer flags */
ubyte ff_bflags; /* The file buffer flags */
ubyte ff_oflags; /* Flags provided when file was opened */
ubyte ff_sectorsincluster; /* Sectors remaining in cluster */
uint16 ff_dirindex; /* Index into ff_dirsector to directory entry */
@ -503,6 +528,10 @@ EXTERN void fat_putuint32(ubyte *ptr, uint32 value32);
EXTERN void fat_semtake(struct fat_mountpt_s *fs);
EXTERN void fat_semgive(struct fat_mountpt_s *fs);
/* Get the current time for FAT creation and write times */
EXTERN uint32 fat_gettime(void);
/* Handle hardware interactions for mounting */
EXTERN int fat_mount(struct fat_mountpt_s *fs, boolean writeable);
@ -510,16 +539,17 @@ EXTERN int fat_checkmount(struct fat_mountpt_s *fs);
/* low-level hardware access */
EXTERN int fat_hwread(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector,
unsigned int nsectors);
EXTERN int fat_hwwrite(struct fat_mountpt_s *fs, ubyte *buffer, size_t sector,
unsigned int nsectors);
EXTERN int fat_hwread(struct fat_mountpt_s *fs, ubyte *buffer,
size_t sector, unsigned int nsectors);
EXTERN int fat_hwwrite(struct fat_mountpt_s *fs, ubyte *buffer,
size_t sector, unsigned int nsectors);
/* Cluster access helpers */
EXTERN ssize_t fat_cluster2sector(struct fat_mountpt_s *fs, uint32 cluster );
EXTERN ssize_t fat_getcluster(struct fat_mountpt_s *fs, unsigned int clusterno);
EXTERN int fat_putcluster(struct fat_mountpt_s *fs, unsigned int clusterno, size_t startsector);
EXTERN int fat_putcluster(struct fat_mountpt_s *fs, unsigned int clusterno,
size_t startsector);
/* Help for traverseing directory trees */
@ -531,11 +561,16 @@ EXTERN int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path);
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
/* File buffer cache (for partial sector accesses) */
/* Mountpoint and fFile buffer cache (for partial sector accesses) */
EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff);
EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector);
EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff);
EXTERN int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector);
EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff);
EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector);
EXTERN int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff);
/* FSINFO sector support */
EXTERN int fat_updatefsinfo(struct fat_mountpt_s *fs);
#undef EXTERN
#if defined(__cplusplus)

View File

@ -128,51 +128,6 @@ static int fat_fscacheflush(struct fat_mountpt_s *fs)
return OK;
}
/****************************************************************************
* Name: fat_fscacheread
*
* Desciption: Read the specified sector into the sector cache, flushing any
* existing dirty sectors as necessary.
*
****************************************************************************/
static int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector)
{
int ret;
/* fs->fs_currentsector holds the current sector that is buffered in
* fs->fs_buffer. If the requested sector is the same as this sector, then
* we do nothing. Otherwise, we will have to read the new sector.
*/
if (fs->fs_currentsector != sector)
{
/* We will need to read the new sector. First, flush the cached
* sector if it is dirty.
*/
ret = fat_fscacheflush(fs);
if (ret < 0)
{
return ret;
}
/* Then read the specified sector into the cache */
ret = fat_hwread(fs, fs->fs_buffer, sector, 1);
if (ret < 0)
{
return ret;
}
/* Update the cached sector number */
fs->fs_currentsector = sector;
}
return OK;
}
/****************************************************************************
* Name: fat_path2dirname
*
@ -726,6 +681,28 @@ void fat_semgive(struct fat_mountpt_s *fs)
sem_post(&fs->fs_sem);
}
/****************************************************************************
* Name: fat_gettime
*
* Desciption: Get the time and date suitble for writing into the FAT FS.
* TIME in LS 16-bits:
* Bits 0:4 = 2 second count (0-29 representing 0-58 seconds)
* Bits 5-10 = minutes (0-59)
* Bits 11-15 = hours (0-23)
* DATE in MS 16-bits
* Bits 0:4 = Day of month (0-31)
* Bits 5:8 = Month of year (1-12)
* Bits 9:15 = Year from 1980 (0-127 representing 1980-2107)
*
*
****************************************************************************/
uint32 fat_gettime(void)
{
#warning "Time not implemented"
return 0;
}
/****************************************************************************
* Name: fat_mount
*
@ -1541,6 +1518,51 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
return -ENOSYS;
}
/****************************************************************************
* Name: fat_fscacheread
*
* Desciption: Read the specified sector into the sector cache, flushing any
* existing dirty sectors as necessary.
*
****************************************************************************/
int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector)
{
int ret;
/* fs->fs_currentsector holds the current sector that is buffered in
* fs->fs_buffer. If the requested sector is the same as this sector, then
* we do nothing. Otherwise, we will have to read the new sector.
*/
if (fs->fs_currentsector != sector)
{
/* We will need to read the new sector. First, flush the cached
* sector if it is dirty.
*/
ret = fat_fscacheflush(fs);
if (ret < 0)
{
return ret;
}
/* Then read the specified sector into the cache */
ret = fat_hwread(fs, fs->fs_buffer, sector, 1);
if (ret < 0)
{
return ret;
}
/* Update the cached sector number */
fs->fs_currentsector = sector;
}
return OK;
}
/****************************************************************************
* Name: fat_ffcacheflush
*
@ -1649,4 +1671,52 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff)
return OK;
}
/****************************************************************************
* Name: fat_updatefsinfo
*
* Desciption: Flush evertyhing buffered for the mountpoint and update
* the FSINFO sector, if appropriate
*
****************************************************************************/
int fat_updatefsinfo(struct fat_mountpt_s *fs)
{
int ret;
/* Flush the fs_buffer if it is dirty */
ret = fat_fscacheflush(fs);
if (ret == OK)
{
/* The FSINFO sector only has to be update for the case of a FAT32 file
* system. Check if the file system type.. If this is a FAT32 file
* system then the fs_fsidirty flag will indicate if the FSINFO sector
* needs to be re-written.
*/
if (fs->fs_type == FSTYPE_FAT32 && fs->fs_fsidirty)
{
/* Create an image of the FSINFO sector in the fs_buffer */
memset(fs->fs_buffer, 0, fs->fs_hwsectorsize);
FSI_PUTLEADSIG(fs->fs_buffer, 0x41615252);
FSI_PUTSTRUCTSIG(fs->fs_buffer, 0x61417272);
FSI_PUTFREECOUNT(fs->fs_buffer, fs->fs_fsifreecount);
FSI_PUTNXTFREE(fs->fs_buffer, fs->fs_fsinextfree);
FSI_PUTTRAILSIG(fs->fs_buffer, 0xaa550000);
/* Then flush this to disk */
fs->fs_currentsector = fs->fs_fsinfo;
fs->fs_dirty = TRUE;
ret = fat_fscacheflush(fs);
/* No longer dirty */
fs->fs_fsidirty = FALSE;
}
}
return ret;
}
#endif /* CONFIG_FS_FAT */

View File

@ -119,7 +119,6 @@ STATUS inode_remove(const char *path)
/* Find the node to delete */
inode_semtake();
node = inode_search(&name, &left, &parent, NULL);
if (node)
{
@ -137,13 +136,11 @@ STATUS inode_remove(const char *path)
*/
node->i_flags |= FSNODEFLAG_DELETED;
inode_semgive();
}
else
{
/* And delete it now -- recursively to delete all of its children */
inode_semgive();
inode_free(node->i_child);
free(node);
return OK;
@ -152,6 +149,5 @@ STATUS inode_remove(const char *path)
/* The node does not exist or it has references */
inode_semgive();
return ERROR;
}

View File

@ -89,7 +89,7 @@ int read(int fd, void *buf, unsigned int nbytes)
{
/* Yes, then let it perform the read. NOTE that for the case
* of the mountpoint, we depend on the read methods bing
* identical in signal and position in the operations vtable.
* identical in signature and position in the operations vtable.
*/
ret = (int)inode->u.i_ops->read(this_file, (char*)buf, (size_t)nbytes);