summaryrefslogtreecommitdiff
path: root/nuttx/fs/fat/fs_fat32.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/fs/fat/fs_fat32.c')
-rw-r--r--nuttx/fs/fat/fs_fat32.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c
index 09db4766b..d9e052ed7 100644
--- a/nuttx/fs/fat/fs_fat32.c
+++ b/nuttx/fs/fat/fs_fat32.c
@@ -1314,6 +1314,7 @@ static int fat_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
uint8_t *direntry;
uint8_t ch;
uint8_t attribute;
+ bool found;
int ret = OK;
/* Sanity checks */
@@ -1336,7 +1337,9 @@ static int fat_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
/* Read the next directory entry */
dir->fd_dir.d_name[0] = '\0';
- while (dir->u.fat.fd_currsector && dir->fd_dir.d_name[0] == '\0')
+ found = false;
+
+ while (dir->u.fat.fd_currsector && !found)
{
ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);
if (ret < 0)
@@ -1365,21 +1368,39 @@ static int fat_readdir(struct inode *mountpt, struct fs_dirent_s *dir)
/* No, is the current entry a valid entry? */
attribute = DIR_GETATTRIBUTES(direntry);
+
+#ifdef CONFIG_FAT_LFN
+ if (ch != DIR0_EMPTY &&
+ ((attribute & FATATTR_VOLUMEID) == 0) ||
+ ((ch & LDIR0_LAST) != 0 && attribute == LDDIR_LFNATTR))
+#else
if (ch != DIR0_EMPTY && (attribute & FATATTR_VOLUMEID) == 0)
+#endif
{
- /* Yes.. get the name from the directory info */
+ /* Yes.. get the name from the directory entry. NOTE: For the case
+ * of the long file name entry, this will advance the several
+ * several directory entries.
+ */
- (void)fat_dirname2path(dir->fd_dir.d_name, direntry);
+ ret = fat_dirname2path(dir, direntry);
+ if (ret == OK)
+ {
+ /* The name was successfully extracted. Now save the file type */
+
+ if ((attribute & FATATTR_DIRECTORY) == 0)
+ {
+ dir->fd_dir.d_type = DTYPE_FILE;
+ }
+ else
+ {
+ dir->fd_dir.d_type = DTYPE_DIRECTORY;
+ }
- /* And the file type */
+ /* Mark the entry found. We will set up the next directory index,
+ * and then exit with success.
+ */
- if ((attribute & FATATTR_DIRECTORY) == 0)
- {
- dir->fd_dir.d_type = DTYPE_FILE;
- }
- else
- {
- dir->fd_dir.d_type = DTYPE_DIRECTORY;
+ found = true;
}
}
@@ -1981,7 +2002,9 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
goto errout_with_semaphore;
}
- /* Find the directory entry for the oldrelpath */
+ /* Find the directory entry for the oldrelpath (there may be multiple
+ * directory entries if long file name support is enabled).
+ */
ret = fat_finddirentry(fs, &dirinfo, oldrelpath);
if (ret != OK)
@@ -2003,14 +2026,18 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
/* Save the information that will need to recover the directory sector and
* directory entry offset to the old directory.
+ *
+ * Save the positional information of the old directory entry.
*/
memcpy(&dirseq, &dirinfo.fd_seq, sizeof(struct fat_dirseq_s));
-
+
+ /* Save the non-name-related portion of the directory entry intact */
+
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 */
+ /* Now find the directory where we should create the newpath object */
ret = fat_finddirentry(fs, &dirinfo, newrelpath);
if (ret == OK)
@@ -2030,7 +2057,11 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
goto errout_with_semaphore;
}
- /* Reserve a directory entry */
+ /* Reserve a directory entry. If long file name support is enabled, then
+ * this might, in fact, allocate a sequence of directory entries. A side
+ * effect of fat_allocatedirentry() in either case is that it leaves the
+ * short file name entry in the sector cache.
+ */
ret = fat_allocatedirentry(fs, &dirinfo);
if (ret != OK)
@@ -2038,19 +2069,28 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
goto errout_with_semaphore;
}
- /* Write the new directory entry */
+ /* Then write the new file name into the directory entry. This, of course,
+ * may involve writing multiple directory entries if long file name
+ * support is enabled. A side effect of fat_allocatedirentry() in either
+ * case is that it leaves the short file name entry in the sector cache.
+ */
- 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);
if (ret < 0)
{
goto errout_with_semaphore;
}
- /* Remove the old entry (flushing the new directory entry to disk) */
+ /* Copy the unchanged information into the new short file name entry. */
+
+ direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
+ memcpy(&direntry[DIR_ATTRIBUTES], dirstate, DIR_SIZE-DIR_ATTRIBUTES);
+ fs->fs_dirty = true;
+
+ /* Remove the old entry, flushing the new directory entry to disk. If
+ * the old file name was a long file name, then multiple directory
+ * entries may be freed.
+ */
ret = fat_freedirentry(fs, &dirseq);
if (ret < 0)