FAT fixes for extending directory entries with long file names. From RonenV

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5802 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-03-31 13:06:22 +00:00
parent 49de19ed4b
commit bc247a45a0
4 changed files with 112 additions and 61 deletions

View File

@ -4473,3 +4473,8 @@
driver (2013-3-29).
* arch/arm/src/lpc17xx/lpc17_gdma.c: LPC17 DMA is code complete and
under test. Does not yet work (2013-3-30).
* fs/fat/fs_fat32dirent.c and fs_fat32util.c: Several fixes to the
FAT file system from Ronen Vainish. These fixes mostly involve the
logic to extend directory clusters for the case of long file names
but also include a few important general fixes (such as for storing
32 bit FAT values) (2013-03-31).

View File

@ -1,7 +1,7 @@
/****************************************************************************
* fs/fat/fs_fat32dirent.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -2011,6 +2011,7 @@ static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
uint8_t offset;
uint8_t seqno;
uint8_t checksum;
off_t startsector;
int namelen;
int ret;
@ -2051,6 +2052,13 @@ static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
dirinfo->dir.fd_currsector = dirinfo->fd_seq.ds_lfnsector;
dirinfo->dir.fd_index = dirinfo->fd_seq.ds_lfnoffset / DIR_SIZE;
/* ds_lfnoffset is the offset in the sector. However fd_index is used as
* index for the entire cluster. We need to add that offset
*/
startsector = fat_cluster2sector(fs, dirinfo->dir.fd_currcluster);
dirinfo->dir.fd_index += (dirinfo->dir.fd_currsector - startsector) * DIRSEC_NDIRS(fs);
/* Make sure that the alias is unique in this directory*/
ret = fat_uniquealias(fs, dirinfo);
@ -2405,13 +2413,15 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
/****************************************************************************
* Name: fat_allocatedirentry
*
* Desciption: Find a free directory entry
* Desciption:
* Find (or allocate) all needed directory entries to contain the file name
*
****************************************************************************/
int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
{
int32_t cluster;
int32_t prevcluster;
off_t sector;
int ret;
int i;
@ -2495,7 +2505,9 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
/* Try to extend the cluster chain for this directory */
prevcluster = cluster;
cluster = fat_extendchain(fs, dirinfo->dir.fd_currcluster);
if (cluster < 0)
{
return cluster;
@ -2524,8 +2536,13 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
{
return ret;
}
sector++;
}
/* Start the search again */
cluster = prevcluster;
}
}
@ -2545,6 +2562,7 @@ int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq)
struct fs_fatdir_s dir;
uint16_t diroffset;
uint8_t *direntry;
off_t startsector;
int ret;
/* Set it to the cluster containing the "last" LFN entry (that appears
@ -2555,6 +2573,13 @@ int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq)
dir.fd_currsector = seq->ds_lfnsector;
dir.fd_index = seq->ds_lfnoffset / DIR_SIZE;
/* Remember that ds_lfnoffset is the offset in the sector and not the
* cluster.
*/
startsector = fat_cluster2sector(fs, dir.fd_currcluster);
dir.fd_index += (dir.fd_currsector - startsector) * DIRSEC_NDIRS(fs);
/* Free all of the directory entries used for the sequence of long file name
* and for the single short file name entry.
*/

View File

@ -1,7 +1,7 @@
/****************************************************************************
* fs/fat/fs_fat32util.c
*
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@ -349,16 +349,17 @@ void fat_putuint16(uint8_t *ptr, uint16_t value16)
void fat_putuint32(uint8_t *ptr, uint32_t value32)
{
uint16_t *val = (uint16_t*)&value32;
#ifdef CONFIG_ENDIAN_BIG
/* The bytes always have to be swapped if the target is big-endian */
fat_putuint16(&ptr[0], val[2]);
fat_putuint16(&ptr[0], val[1]);
fat_putuint16(&ptr[2], val[0]);
#else
/* Byte-by-byte transfer is still necessary if the address is un-aligned */
fat_putuint16(&ptr[0], val[0]);
fat_putuint16(&ptr[2], val[2]);
fat_putuint16(&ptr[2], val[1]);
#endif
}
@ -670,6 +671,7 @@ int fat_mount(struct fat_mountpt_s *fs, bool writeable)
errout_with_buffer:
fat_io_free(fs->fs_buffer, fs->fs_hwsectorsize);
fs->fs_buffer = 0;
errout:
fs->fs_mounted = false;
return ret;
@ -886,6 +888,7 @@ off_t fat_getcluster(struct fat_mountpt_s *fs, uint32_t clusterno)
cluster &= 0x0fff;
}
return cluster;
}
@ -898,8 +901,10 @@ off_t fat_getcluster(struct fat_mountpt_s *fs, uint32_t clusterno)
if (fat_fscacheread(fs, fatsector) < 0)
{
/* Read error */
break;
}
return FAT_GETFAT16(fs->fs_buffer, fatindex);
}
@ -912,10 +917,13 @@ off_t fat_getcluster(struct fat_mountpt_s *fs, uint32_t clusterno)
if (fat_fscacheread(fs, fatsector) < 0)
{
/* Read error */
break;
}
return FAT_GETFAT32(fs->fs_buffer, fatindex) & 0x0fffffff;
}
default:
break;
}
@ -1046,6 +1054,7 @@ int fat_putcluster(struct fat_mountpt_s *fs, uint32_t clusterno, off_t nextclust
break;
}
FAT_PUTFAT16(fs->fs_buffer, fatindex, nextcluster & 0xffff);
}
break;
@ -1055,6 +1064,7 @@ int fat_putcluster(struct fat_mountpt_s *fs, uint32_t clusterno, off_t nextclust
unsigned int fatoffset = 4 * clusterno;
off_t fatsector = fs->fs_fatbase + SEC_NSECTORS(fs, fatoffset);
unsigned int fatindex = fatoffset & SEC_NDXMASK(fs);
uint32_t val;
if (fat_fscacheread(fs, fatsector) < 0)
{
@ -1062,7 +1072,11 @@ int fat_putcluster(struct fat_mountpt_s *fs, uint32_t clusterno, off_t nextclust
break;
}
FAT_PUTFAT32(fs->fs_buffer, fatindex, nextcluster & 0x0fffffff);
/* Keep the top 4 bits */
val = FAT_GETFAT32(fs->fs_buffer, fatindex) & 0xf0000000;
FAT_PUTFAT32(fs->fs_buffer, fatindex, val | (nextcluster & 0x0fffffff));
}
break;
@ -1228,12 +1242,14 @@ int32_t fat_extendchain(struct fat_mountpt_s *fs, uint32_t cluster)
startsector = fat_getcluster(fs, newcluster);
if (startsector == 0)
{
/* Found have found a free cluster break out*/
/* Found have found a free cluster break out */
break;
}
else if (startsector < 0)
{
/* Some error occurred, return the error number */
return startsector;
}
@ -1255,6 +1271,7 @@ int32_t fat_extendchain(struct fat_mountpt_s *fs, uint32_t cluster)
if (ret < 0)
{
/* An error occurred */
return ret;
}
@ -1290,7 +1307,7 @@ int32_t fat_extendchain(struct fat_mountpt_s *fs, uint32_t cluster)
*
* Desciption: Read the next directory entry from the sector in cache,
* reading the next sector(s) in the cluster as necessary. This function
* must return -ENOSPC if if fails because there are no further entries
* must return -ENOSPC if it fails because there are no further entries
* available in the directory.
*
****************************************************************************/
@ -1368,6 +1385,7 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
dir->fd_currcluster = cluster;
dir->fd_currsector = fat_cluster2sector(fs, cluster);
ndx = 0;
}
}
}
@ -1615,6 +1633,7 @@ int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, off_t secto
ff->ff_cachesector = sector;
ff->ff_bflags |= FFBUFF_VALID;
}
return OK;
}
@ -1646,6 +1665,7 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff)
ff->ff_bflags &= ~FFBUFF_VALID;
ff->ff_cachesector = 0;
}
return OK;
}
@ -1694,6 +1714,7 @@ int fat_updatefsinfo(struct fat_mountpt_s *fs)
fs->fs_fsidirty = false;
}
}
return ret;
}