Re-architect FAT data structures to support long file names
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3780 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
ed3ae5b173
commit
2d10e7c352
|
@ -148,10 +148,12 @@ static ssize_t rd_read(FAR struct inode *inode, unsigned char *buffer,
|
|||
{
|
||||
struct rd_struct_s *dev;
|
||||
|
||||
fvdbg("sector: %d nsectors: %d sectorsize: %d\n");
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
dev = (struct rd_struct_s *)inode->i_private;
|
||||
|
||||
fvdbg("sector: %d nsectors: %d sectorsize: %d\n",
|
||||
start_sector, dev->rd_sectsize, nsectors);
|
||||
|
||||
if (start_sector < dev->rd_nsectors &&
|
||||
start_sector + nsectors <= dev->rd_nsectors)
|
||||
{
|
||||
|
@ -180,10 +182,12 @@ static ssize_t rd_write(FAR struct inode *inode, const unsigned char *buffer,
|
|||
{
|
||||
struct rd_struct_s *dev;
|
||||
|
||||
fvdbg("sector: %d nsectors: %d sectorsize: %d\n");
|
||||
|
||||
DEBUGASSERT(inode && inode->i_private);
|
||||
dev = (struct rd_struct_s *)inode->i_private;
|
||||
|
||||
fvdbg("sector: %d nsectors: %d sectorsize: %d\n",
|
||||
start_sector, dev->rd_sectsize, nsectors);
|
||||
|
||||
if (!dev->rd_writeenabled)
|
||||
{
|
||||
return -EACCES;
|
||||
|
|
|
@ -163,12 +163,21 @@ static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
|
|||
|
||||
static void uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
||||
{
|
||||
int nexthead = dev->xmit.head + 1;
|
||||
irqstate_t flags;
|
||||
int nexthead;
|
||||
|
||||
/* Increment to see what the next head pointer will be. We need to use the "next"
|
||||
* head pointer to determine when the circular buffer would overrun
|
||||
*/
|
||||
|
||||
nexthead = dev->xmit.head + 1;
|
||||
if (nexthead >= dev->xmit.size)
|
||||
{
|
||||
nexthead = 0;
|
||||
}
|
||||
|
||||
/* Loop until we are able to add the character to the TX buffer */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (nexthead != dev->xmit.tail)
|
||||
|
@ -179,8 +188,11 @@ static void uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Inform the interrupt level logic that we are waiting */
|
||||
/* Inform the interrupt level logic that we are waiting.
|
||||
* This and the following steps must be atomic.
|
||||
*/
|
||||
|
||||
flags = irqsave();
|
||||
dev->xmitwaiting = true;
|
||||
|
||||
/* Wait for some characters to be sent from the buffer
|
||||
|
@ -192,6 +204,7 @@ static void uart_putxmitchar(FAR uart_dev_t *dev, int ch)
|
|||
uart_enabletxint(dev);
|
||||
uart_takesem(&dev->xmitsem);
|
||||
uart_disabletxint(dev);
|
||||
irqrestore(flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,7 @@ static int fat_open(FAR struct file *filep, const char *relpath,
|
|||
struct inode *inode;
|
||||
struct fat_mountpt_s *fs;
|
||||
struct fat_file_s *ff;
|
||||
uint8_t *direntry;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
@ -203,10 +204,12 @@ static int fat_open(FAR struct file *filep, const char *relpath,
|
|||
|
||||
/* The name exists -- but is it a file or a directory? */
|
||||
|
||||
if (dirinfo.fd_entry == NULL ||
|
||||
(DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY))
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
if (dirinfo.fd_root ||
|
||||
(DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY))
|
||||
{
|
||||
/* It is a directory */
|
||||
|
||||
ret = -EISDIR;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
@ -227,7 +230,7 @@ static int fat_open(FAR struct file *filep, const char *relpath,
|
|||
|
||||
/* Check if the caller has sufficient privileges to open the file */
|
||||
|
||||
readonly = ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0);
|
||||
readonly = ((DIR_GETATTRIBUTES(direntry) & FATATTR_READONLY) != 0);
|
||||
if (((oflags & O_WRONLY) != 0) && readonly)
|
||||
{
|
||||
ret = -EACCES;
|
||||
|
@ -273,6 +276,8 @@ static int fat_open(FAR struct file *filep, const char *relpath,
|
|||
}
|
||||
|
||||
/* Fall through to finish the file open operation */
|
||||
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -316,12 +321,12 @@ static int fat_open(FAR struct file *filep, const char *relpath,
|
|||
/* File cluster/size info */
|
||||
|
||||
ff->ff_startcluster =
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(direntry);
|
||||
|
||||
ff->ff_currentcluster = ff->ff_startcluster;
|
||||
ff->ff_sectorsincluster = fs->fs_fatsecperclus;
|
||||
ff->ff_size = DIR_GETFILESIZE(dirinfo.fd_entry);
|
||||
ff->ff_size = DIR_GETFILESIZE(direntry);
|
||||
|
||||
/* Attach the private date to the struct file instance */
|
||||
|
||||
|
@ -1224,7 +1229,8 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir
|
|||
{
|
||||
struct fat_mountpt_s *fs;
|
||||
struct fat_dirinfo_s dirinfo;
|
||||
int ret;
|
||||
uint8_t *direntry;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
|
@ -1250,10 +1256,11 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir
|
|||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
|
||||
/* Check if this is the root directory */
|
||||
|
||||
if (dirinfo.fd_entry == NULL)
|
||||
if (dirinfo.fd_root)
|
||||
{
|
||||
/* Handle the FAT12/16/32 root directory using the values setup by
|
||||
* fat_finddirentry() above.
|
||||
|
@ -1267,7 +1274,7 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir
|
|||
|
||||
/* This is not the root directory. Verify that it is some kind of directory */
|
||||
|
||||
else if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) == 0)
|
||||
else if ((DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY) == 0)
|
||||
{
|
||||
/* The entry is not a directory */
|
||||
ret = -ENOTDIR;
|
||||
|
@ -1278,8 +1285,8 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir
|
|||
/* The entry is a directory */
|
||||
|
||||
dir->u.fat.fd_startcluster =
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(direntry);
|
||||
dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster;
|
||||
dir->u.fat.fd_currsector = fat_cluster2sector(fs, dir->u.fat.fd_currcluster);
|
||||
dir->u.fat.fd_index = 2;
|
||||
|
@ -1819,7 +1826,7 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
|||
* management routines.
|
||||
*/
|
||||
|
||||
memset(&direntry[DIR_NAME], ' ', 8+3);
|
||||
memset(&direntry[DIR_NAME], ' ', DIR_MAXFNAME);
|
||||
direntry[DIR_NAME] = '.';
|
||||
DIR_PUTATTRIBUTES(direntry, FATATTR_DIRECTORY);
|
||||
|
||||
|
@ -1875,8 +1882,9 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
|||
* change the sector in the cache.
|
||||
*/
|
||||
|
||||
DIR_PUTFSTCLUSTLO(dirinfo.fd_entry, dircluster);
|
||||
DIR_PUTFSTCLUSTHI(dirinfo.fd_entry, dircluster >> 16);
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
DIR_PUTFSTCLUSTLO(direntry, dircluster);
|
||||
DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16);
|
||||
fs->fs_dirty = true;
|
||||
|
||||
/* Now update the FAT32 FSINFO sector */
|
||||
|
@ -1951,9 +1959,8 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
{
|
||||
struct fat_mountpt_s *fs;
|
||||
struct fat_dirinfo_s dirinfo;
|
||||
off_t oldsector;
|
||||
uint8_t *olddirentry;
|
||||
uint8_t *newdirentry;
|
||||
struct fat_dirseq_s dirseq;
|
||||
uint8_t *direntry;
|
||||
uint8_t dirstate[DIR_SIZE-DIR_ATTRIBUTES];
|
||||
int ret;
|
||||
|
||||
|
@ -1988,7 +1995,7 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
* root directory. We can't rename the root directory.
|
||||
*/
|
||||
|
||||
if (!dirinfo.fd_entry)
|
||||
if (dirinfo.fd_root)
|
||||
{
|
||||
ret = -EXDEV;
|
||||
goto errout_with_semaphore;
|
||||
|
@ -1998,9 +2005,10 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
* directory entry offset to the old directory.
|
||||
*/
|
||||
|
||||
olddirentry = dirinfo.fd_entry;
|
||||
oldsector = fs->fs_currentsector;
|
||||
memcpy(dirstate, &olddirentry[DIR_ATTRIBUTES], DIR_SIZE-DIR_ATTRIBUTES);
|
||||
memcpy(&dirseq, &dirinfo.fd_seq, sizeof(struct fat_dirseq_s));
|
||||
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
memcpy(dirstate, &direntry[DIR_ATTRIBUTES], DIR_SIZE-DIR_ATTRIBUTES);
|
||||
|
||||
/* No find the directory where we should create the newpath object */
|
||||
|
||||
|
@ -2032,8 +2040,8 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
|
||||
/* Write the new directory entry */
|
||||
|
||||
newdirentry = dirinfo.fd_entry;
|
||||
memcpy(&newdirentry[DIR_ATTRIBUTES], dirstate, DIR_SIZE-DIR_ATTRIBUTES);
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
memcpy(&direntry[DIR_ATTRIBUTES], dirstate, DIR_SIZE-DIR_ATTRIBUTES);
|
||||
fs->fs_dirty = true;
|
||||
|
||||
ret = fat_dirnamewrite(fs, &dirinfo);
|
||||
|
@ -2042,19 +2050,9 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Now flush the new directory entry to disk and read the sector
|
||||
* containing the old directory entry.
|
||||
*/
|
||||
/* Remove the old entry (flushing the new directory entry to disk) */
|
||||
|
||||
ret = fat_fscacheread(fs, oldsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Remove the old entry */
|
||||
|
||||
ret = fat_freedirentry(fs, olddirentry);
|
||||
ret = fat_freedirentry(fs, &dirseq);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
|
@ -2090,6 +2088,7 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
|
|||
uint16_t fatdate;
|
||||
uint16_t date2;
|
||||
uint16_t fattime;
|
||||
uint8_t *direntry;
|
||||
uint8_t attribute;
|
||||
int ret;
|
||||
|
||||
|
@ -2122,9 +2121,9 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
|
|||
}
|
||||
|
||||
memset(buf, 0, sizeof(struct stat));
|
||||
if (!dirinfo.fd_entry)
|
||||
if (dirinfo.fd_root)
|
||||
{
|
||||
/* It's directory name of mount point */
|
||||
/* It's directory name of the mount point */
|
||||
|
||||
buf->st_mode = S_IFDIR|S_IROTH|S_IRGRP|S_IRUSR|S_IWOTH|S_IWGRP|S_IWUSR;
|
||||
ret = OK;
|
||||
|
@ -2133,7 +2132,8 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
|
|||
|
||||
/* Get the FAT attribute and map it so some meaningful mode_t values */
|
||||
|
||||
attribute = DIR_GETATTRIBUTES(dirinfo.fd_entry);
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
attribute = DIR_GETATTRIBUTES(direntry);
|
||||
if ((attribute & FATATTR_VOLUMEID) != 0)
|
||||
{
|
||||
ret = -ENOENT;
|
||||
|
@ -2163,17 +2163,17 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
|
|||
|
||||
/* File/directory size, access block size */
|
||||
|
||||
buf->st_size = DIR_GETFILESIZE(dirinfo.fd_entry);
|
||||
buf->st_size = DIR_GETFILESIZE(direntry);
|
||||
buf->st_blksize = fs->fs_fatsecperclus * fs->fs_hwsectorsize;
|
||||
buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
|
||||
|
||||
/* Times */
|
||||
|
||||
fatdate = DIR_GETWRTDATE(dirinfo.fd_entry);
|
||||
fattime = DIR_GETWRTTIME(dirinfo.fd_entry);
|
||||
fatdate = DIR_GETWRTDATE(direntry);
|
||||
fattime = DIR_GETWRTTIME(direntry);
|
||||
buf->st_mtime = fat_fattime2systime(fattime, fatdate);
|
||||
|
||||
date2 = DIR_GETLASTACCDATE(dirinfo.fd_entry);
|
||||
date2 = DIR_GETLASTACCDATE(direntry);
|
||||
if (fatdate == date2)
|
||||
{
|
||||
buf->st_atime = buf->st_mtime;
|
||||
|
@ -2183,8 +2183,8 @@ static int fat_stat(struct inode *mountpt, const char *relpath, struct stat *buf
|
|||
buf->st_atime = fat_fattime2systime(0, date2);
|
||||
}
|
||||
|
||||
fatdate = DIR_GETCRDATE(dirinfo.fd_entry);
|
||||
fattime = DIR_GETCRTIME(dirinfo.fd_entry);
|
||||
fatdate = DIR_GETCRDATE(direntry);
|
||||
fattime = DIR_GETCRTIME(direntry);
|
||||
buf->st_ctime = fat_fattime2systime(fattime, fatdate);
|
||||
|
||||
ret = OK;
|
||||
|
|
|
@ -148,8 +148,15 @@
|
|||
#define PART_SIZE 12 /* 4@12: Partition size (in sectors) */
|
||||
|
||||
/****************************************************************************
|
||||
* Each FAT "short" 8.3 file name directory entry is 32-bytes long. The
|
||||
* following define offsets relative to the beginning of a directory entry.
|
||||
* Each FAT "short" 8.3 file name directory entry is 32-bytes long.
|
||||
*
|
||||
* Sizes and limits
|
||||
*/
|
||||
|
||||
#define DIR_MAXFNAME 11 /* Max short name size is 8+3 = 11 */
|
||||
|
||||
/* The following define offsets relative to the beginning of a directory
|
||||
* entry.
|
||||
*/
|
||||
|
||||
#define DIR_NAME 0 /* 11@ 0: NAME: 8 bytes + 3 byte extension */
|
||||
|
@ -687,6 +694,37 @@ struct fat_file_s
|
|||
uint8_t *ff_buffer; /* File buffer (for partial sector accesses) */
|
||||
};
|
||||
|
||||
/* This structure holds the sequency of directory entries used by one
|
||||
* file element (directory or file). For short file names, this is
|
||||
* single diretory entry. But for long file names, the is a sequence
|
||||
* of directory entries. Long directory name entries appear in reverse
|
||||
* order: Last, next-to-last, ..., first. The "first" long file name
|
||||
* directory is then following by the short directory name entry. The
|
||||
* short file name entry contains the real meat of the file data.
|
||||
*
|
||||
* So it takes the sector number and entry offset of the last long
|
||||
* file name entry and of the short file name entry to define the
|
||||
* sequence. In the case of short file names, the sector number and
|
||||
* offset will be the same.
|
||||
*/
|
||||
|
||||
struct fat_dirseq_s
|
||||
{
|
||||
/* Sector offsets */
|
||||
|
||||
uint16_t ds_offset; /* Sector offset to short file name entry */
|
||||
#ifdef CONFIG_FAT_LFN
|
||||
uint16_t ds_lfnoffset; /* Sector offset to last long file name entry */
|
||||
#endif
|
||||
|
||||
/* Sector numbers */
|
||||
|
||||
off_t ds_sector; /* Sector of the short file name entry */
|
||||
#ifdef CONFIG_FAT_LFN
|
||||
off_t ds_lfnsector; /* Sector of the last long name entry */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure is used internally for describing directory entries */
|
||||
|
||||
struct fat_dirinfo_s
|
||||
|
@ -694,10 +732,9 @@ struct fat_dirinfo_s
|
|||
/* The file/directory name */
|
||||
|
||||
#ifdef CONFIG_FAT_LFN
|
||||
uint8_t fd_name[LDIR_MAXFNAME]; /* Filename -- directory format */
|
||||
#else
|
||||
uint8_t fd_name[8+3]; /* Filename -- directory format */
|
||||
uint8_t fd_lfname[LDIR_MAXFNAME]; /* Long filename */
|
||||
#endif
|
||||
uint8_t fd_name[DIR_MAXFNAME]; /* Short 8.3 alias filename */
|
||||
|
||||
/* NT flags are not used */
|
||||
|
||||
|
@ -705,16 +742,19 @@ struct fat_dirinfo_s
|
|||
uint8_t fd_ntflags; /* NTRes lower case flags */
|
||||
#endif
|
||||
|
||||
/* TRUE if this is the root directory */
|
||||
|
||||
bool fd_root;
|
||||
|
||||
/* The following provides the sequence of directory entries used by the
|
||||
* file or directory.
|
||||
*/
|
||||
|
||||
struct fat_dirseq_s fd_seq; /* Directory sequence */
|
||||
|
||||
/* This is part of the opendir, readdir, ... logic */
|
||||
|
||||
struct fs_fatdir_s dir; /* Used with opendir, readdir, etc. */
|
||||
|
||||
/* The following points the standard, short file name directory
|
||||
* entry that contains the real meat of the file data. Several
|
||||
* 32-byte long fine name records may have preceded this.
|
||||
*/
|
||||
|
||||
uint8_t *fd_entry; /* A pointer to the raw 32-byte entry */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -782,7 +822,7 @@ EXTERN int fat_dirnamewrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *d
|
|||
EXTERN int fat_dirwrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||
uint8_t attributes, uint32_t fattime);
|
||||
EXTERN int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||
EXTERN int fat_freedirentry(struct fat_mountpt_s *fs, FAR uint8_t *direntry);
|
||||
EXTERN int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq);
|
||||
EXTERN int fat_dirname2path(char *path, uint8_t *direntry);
|
||||
|
||||
/* File creation and removal helpers */
|
||||
|
|
|
@ -63,6 +63,7 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
|
|||
struct fat_dirinfo_s dirinfo;
|
||||
FAR struct inode *inode;
|
||||
const char *relpath = NULL;
|
||||
uint8_t *direntry;
|
||||
uint8_t oldattributes;
|
||||
uint8_t newattributes;
|
||||
int ret;
|
||||
|
@ -111,7 +112,7 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
|
|||
|
||||
/* Make sure that we found some valid file or directory */
|
||||
|
||||
if (!dirinfo.fd_entry)
|
||||
if (dirinfo.fd_root)
|
||||
{
|
||||
/* Ooops.. we found the root directory */
|
||||
|
||||
|
@ -121,7 +122,8 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
|
|||
|
||||
/* Get the current attributes */
|
||||
|
||||
oldattributes = DIR_GETATTRIBUTES(dirinfo.fd_entry);
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
oldattributes = DIR_GETATTRIBUTES(direntry);
|
||||
newattributes = oldattributes;
|
||||
|
||||
/* Set or clear any bits as requested */
|
||||
|
@ -133,7 +135,7 @@ static int fat_attrib(const char *path, fat_attrib_t *retattrib,
|
|||
|
||||
if (newattributes != oldattributes)
|
||||
{
|
||||
DIR_PUTATTRIBUTES(dirinfo.fd_entry, newattributes);
|
||||
DIR_PUTATTRIBUTES(direntry, newattributes);
|
||||
fs->fs_dirty = true;
|
||||
ret = fat_updatefsinfo(fs);
|
||||
if (ret != OK)
|
||||
|
|
|
@ -154,7 +154,7 @@ static inline int fat_path2dirname(const char **path, struct fat_dirinfo_s *diri
|
|||
|
||||
/* Initialized the name with all spaces */
|
||||
|
||||
memset(dirinfo->fd_name, ' ', 8+3);
|
||||
memset(dirinfo->fd_name, ' ', DIR_MAXFNAME);
|
||||
|
||||
/* Loop until the name is successfully parsed or an error occurs */
|
||||
|
||||
|
@ -294,10 +294,11 @@ static inline int fat_path2dirname(const char **path, struct fat_dirinfo_s *diri
|
|||
int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||
const char *path)
|
||||
{
|
||||
off_t cluster;
|
||||
off_t cluster;
|
||||
uint16_t diroffset;
|
||||
uint8_t *direntry = NULL;
|
||||
char terminator;
|
||||
int ret;
|
||||
char terminator;
|
||||
int ret;
|
||||
|
||||
/* Initialize to traverse the chain. Set it to the cluster of
|
||||
* the root directory
|
||||
|
@ -336,7 +337,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
if (*path == '\0')
|
||||
{
|
||||
dirinfo->fd_entry = NULL;
|
||||
dirinfo->fd_root = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -374,7 +375,8 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
/* Get a pointer to the directory entry */
|
||||
|
||||
direntry = &fs->fs_buffer[DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index)];
|
||||
diroffset = DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index);
|
||||
direntry = &fs->fs_buffer[diroffset];
|
||||
|
||||
/* Check if we are at the end of the directory */
|
||||
|
||||
|
@ -387,7 +389,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
if (direntry[DIR_NAME] != DIR0_EMPTY &&
|
||||
!(DIR_GETATTRIBUTES(direntry) & FATATTR_VOLUMEID) &&
|
||||
!memcmp(&direntry[DIR_NAME], dirinfo->fd_name, 8+3) )
|
||||
!memcmp(&direntry[DIR_NAME], dirinfo->fd_name, DIR_MAXFNAME) )
|
||||
{
|
||||
/* Yes.. break out of the loop */
|
||||
|
||||
|
@ -412,9 +414,10 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
if (!terminator)
|
||||
{
|
||||
/* Return the pointer to the matching directory entry */
|
||||
/* Return the sector and offset to the matching directory entry */
|
||||
|
||||
dirinfo->fd_entry = direntry;
|
||||
dirinfo->fd_seq.ds_sector = fs->fs_currentsector;
|
||||
dirinfo->fd_seq.ds_offset = diroffset;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -453,12 +456,13 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
||||
{
|
||||
int32_t cluster;
|
||||
off_t sector;
|
||||
int32_t cluster;
|
||||
off_t sector;
|
||||
uint16_t diroffset;
|
||||
uint8_t *direntry;
|
||||
uint8_t ch;
|
||||
int ret;
|
||||
int i;
|
||||
uint8_t ch;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Re-initialize directory object */
|
||||
|
||||
|
@ -480,8 +484,6 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
for (;;)
|
||||
{
|
||||
unsigned int dirindex;
|
||||
|
||||
/* Read the directory sector into fs_buffer */
|
||||
|
||||
ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector);
|
||||
|
@ -492,8 +494,8 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
/* Get a pointer to the entry at fd_index */
|
||||
|
||||
dirindex = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
|
||||
direntry = &fs->fs_buffer[dirindex];
|
||||
diroffset = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * DIR_SIZE;
|
||||
direntry = &fs->fs_buffer[diroffset];
|
||||
|
||||
/* Check if this directory entry is empty */
|
||||
|
||||
|
@ -502,7 +504,8 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
{
|
||||
/* It is empty -- we have found a directory entry */
|
||||
|
||||
dirinfo->fd_entry = direntry;
|
||||
dirinfo->fd_seq.ds_sector = fs->fs_currentsector;
|
||||
dirinfo->fd_seq.ds_offset = diroffset;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -535,7 +538,7 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
return cluster;
|
||||
}
|
||||
|
||||
/* Flush out any cached date in fs_buffer.. we are going to use
|
||||
/* Flush out any cached data in fs_buffer.. we are going to use
|
||||
* it to initialize the new directory cluster.
|
||||
*/
|
||||
|
||||
|
@ -561,7 +564,8 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
sector++;
|
||||
}
|
||||
|
||||
dirinfo->fd_entry = fs->fs_buffer;
|
||||
dirinfo->fd_seq.ds_sector = fs->fs_currentsector;
|
||||
dirinfo->fd_seq.ds_offset = 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -570,17 +574,28 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
*
|
||||
* Desciption: Free the directory entry.
|
||||
*
|
||||
* Assumptions: (1) the directory enty is in the cache and (2) direntry
|
||||
* points to the directory entry to be deleted. This obvioulsy needs
|
||||
* to be re-designed to support long file names!
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fat_freedirentry(struct fat_mountpt_s *fs, FAR uint8_t *direntry)
|
||||
int fat_freedirentry(struct fat_mountpt_s *fs, struct fat_dirseq_s *seq)
|
||||
{
|
||||
direntry[DIR_NAME] = DIR0_EMPTY;
|
||||
fs->fs_dirty = true;
|
||||
return OK;
|
||||
uint8_t *direntry;
|
||||
int ret;
|
||||
|
||||
/* Make sure that the sector containing the directory entry is in the
|
||||
* cache.
|
||||
*/
|
||||
|
||||
ret = fat_fscacheread(fs, seq->ds_sector);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Then mark the entry as deleted */
|
||||
|
||||
direntry = &fs->fs_buffer[seq->ds_offset];
|
||||
direntry[DIR_NAME] = DIR0_EMPTY;
|
||||
fs->fs_dirty = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -703,9 +718,9 @@ int fat_dirname2path(char *path, uint8_t *direntry)
|
|||
|
||||
int fat_dirnamewrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
||||
{
|
||||
uint8_t *direntry = dirinfo->fd_entry;
|
||||
uint8_t *direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset];
|
||||
|
||||
memcpy(&direntry[DIR_NAME], dirinfo->fd_name, 8+3);
|
||||
memcpy(&direntry[DIR_NAME], dirinfo->fd_name, DIR_MAXFNAME);
|
||||
#ifdef CONFIG_FLAT_LCNAMES
|
||||
DIR_PUTNTRES(direntry, dirinfo->fd_ntflags);
|
||||
#else
|
||||
|
@ -732,7 +747,7 @@ int fat_dirwrite(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
/* Initialize the 32-byte directory entry */
|
||||
|
||||
direntry = dirinfo->fd_entry;
|
||||
direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset];
|
||||
memset(direntry, 0, DIR_SIZE);
|
||||
|
||||
/* Directory name info */
|
||||
|
@ -793,9 +808,9 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
||||
{
|
||||
struct fat_dirinfo_s dirinfo;
|
||||
uint32_t dircluster;
|
||||
off_t dirsector;
|
||||
int ret;
|
||||
uint32_t dircluster;
|
||||
uint8_t *direntry;
|
||||
int ret;
|
||||
|
||||
/* Find the directory entry referring to the entry to be deleted */
|
||||
|
||||
|
@ -809,7 +824,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
|||
|
||||
/* Check if this is a FAT12/16 root directory */
|
||||
|
||||
if (dirinfo.fd_entry == NULL)
|
||||
if (dirinfo.fd_root)
|
||||
{
|
||||
/* The root directory cannot be removed */
|
||||
|
||||
|
@ -818,7 +833,8 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
|||
|
||||
/* The object has to have write access to be deleted */
|
||||
|
||||
if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0)
|
||||
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
|
||||
if ((DIR_GETATTRIBUTES(direntry) & FATATTR_READONLY) != 0)
|
||||
{
|
||||
/* It is a read-only entry */
|
||||
|
||||
|
@ -829,14 +845,13 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
|||
* entry to be deleted
|
||||
*/
|
||||
|
||||
dirsector = fs->fs_currentsector;
|
||||
dircluster =
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(direntry);
|
||||
|
||||
/* Is this entry a directory? */
|
||||
|
||||
if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY)
|
||||
if (DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY)
|
||||
{
|
||||
/* It is a sub-directory. Check if we are be asked to remove
|
||||
* a directory or a file.
|
||||
|
@ -903,7 +918,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
|||
return -ENOTEMPTY;
|
||||
}
|
||||
|
||||
/* Get the next directgory entry */
|
||||
/* Get the next directory entry */
|
||||
|
||||
ret = fat_nextdirentry(fs, &dirinfo.dir);
|
||||
if (ret < 0)
|
||||
|
@ -926,19 +941,9 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
|
|||
}
|
||||
}
|
||||
|
||||
/* Make sure that the directory containing the entry to be deleted is
|
||||
* in the cache.
|
||||
*/
|
||||
|
||||
ret = fat_fscacheread(fs, dirsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Mark the directory entry 'deleted' */
|
||||
|
||||
ret = fat_freedirentry(fs, dirinfo.fd_entry);
|
||||
ret = fat_freedirentry(fs, &dirinfo.fd_seq);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
|
|
@ -1273,7 +1273,8 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
|
|||
* Desciption: Truncate an existing file to zero length
|
||||
*
|
||||
* Assumptions: The caller holds mountpoint semaphore, fs_buffer holds
|
||||
* the directory entry, dirinfo refers to the current fs_buffer content.
|
||||
* the directory entry, the directory entry sector (fd_sector) is
|
||||
* currently in the sector cache.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -1281,31 +1282,33 @@ int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
{
|
||||
unsigned int startcluster;
|
||||
uint32_t writetime;
|
||||
uint8_t *direntry;
|
||||
off_t savesector;
|
||||
int ret;
|
||||
|
||||
/* Get start cluster of the file to truncate */
|
||||
|
||||
direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset];
|
||||
startcluster =
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(dirinfo->fd_entry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(dirinfo->fd_entry);
|
||||
((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(direntry);
|
||||
|
||||
/* Clear the cluster start value in the directory and set the file size
|
||||
* to zero. This makes the file look empty but also have to dispose of
|
||||
* all of the clusters in the chain.
|
||||
*/
|
||||
|
||||
DIR_PUTFSTCLUSTHI(dirinfo->fd_entry, 0);
|
||||
DIR_PUTFSTCLUSTLO(dirinfo->fd_entry, 0);
|
||||
DIR_PUTFILESIZE(dirinfo->fd_entry, 0);
|
||||
DIR_PUTFSTCLUSTHI(direntry, 0);
|
||||
DIR_PUTFSTCLUSTLO(direntry, 0);
|
||||
DIR_PUTFILESIZE(direntry, 0);
|
||||
|
||||
/* Set the ARCHIVE attribute and update the write time */
|
||||
|
||||
DIR_PUTATTRIBUTES(dirinfo->fd_entry, FATATTR_ARCHIVE);
|
||||
DIR_PUTATTRIBUTES(direntry, FATATTR_ARCHIVE);
|
||||
|
||||
writetime = fat_systime2fattime();
|
||||
DIR_PUTWRTTIME(dirinfo->fd_entry, writetime & 0xffff);
|
||||
DIR_PUTWRTDATE(dirinfo->fd_entry, writetime > 16);
|
||||
DIR_PUTWRTTIME(direntry, writetime & 0xffff);
|
||||
DIR_PUTWRTDATE(direntry, writetime > 16);
|
||||
|
||||
/* This sector needs to be written back to disk eventually */
|
||||
|
||||
|
|
Loading…
Reference in New Issue