diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-15 22:37:14 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-11-15 22:37:14 +0000 |
commit | 6e1ea39b8e41e8600506bc5325c25969de091ff3 (patch) | |
tree | 0506f37ccd6f7779514ea52f38ab89a75f7f0657 | |
parent | 4bf2eeec797de1c158143d33c572ef38e6ccc015 (diff) | |
download | px4-nuttx-6e1ea39b8e41e8600506bc5325c25969de091ff3.tar.gz px4-nuttx-6e1ea39b8e41e8600506bc5325c25969de091ff3.tar.bz2 px4-nuttx-6e1ea39b8e41e8600506bc5325c25969de091ff3.zip |
Fix an error in FAT needed for interoperability with Windows when access first entry in root directory
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4093 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r-- | nuttx/ChangeLog | 4 | ||||
-rw-r--r-- | nuttx/TODO | 12 | ||||
-rw-r--r-- | nuttx/arch/mips/include/mips32/syscall.h | 4 | ||||
-rw-r--r-- | nuttx/fs/fat/fs_fat32.c | 15 | ||||
-rw-r--r-- | nuttx/fs/fat/fs_fat32dirent.c | 106 |
5 files changed, 111 insertions, 30 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 1873e417b..1563caf3f 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -2210,3 +2210,7 @@ * drivers/mmcsd0/mmcsd_sdio.c: Increase capacity variable from size_t to uin64_t (if available) so that SD cards with capacities greater than 4Gb can be supported. + * fs/fat/fs_fat32dirent.c: The root directory structure is different + from other directories. When formatted by Windows, it is not initialized + at all. Some additional special handling is required to initialize the + root directory entry to interoperate correctly with windows. diff --git a/nuttx/TODO b/nuttx/TODO index 256f67689..a5bf08ace 100644 --- a/nuttx/TODO +++ b/nuttx/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated October 3, 2011) +NuttX TODO List (Last updated November 15, 2011) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -16,7 +16,7 @@ nuttx/ (16) Network (net/, drivers/net) (2) USB (drivers/usbdev, drivers/usbhost) (7) Libraries (lib/) - (9) File system/Generic drivers (fs/, drivers/) + (10) File system/Generic drivers (fs/, drivers/) (2) Graphics subystem (graphics/) (1) Pascal add-on (pcode/) (1) Documentation (Documentation/) @@ -501,6 +501,14 @@ o File system / Generic drivers (fs/, drivers/) Status: Open Priority: Medium + Description: mkfatfs() does not create the "." directory entry (all directories) + or the ".." directory entry (all directories except for the root + directory). NuttX doesn't care about these entries, but this will + probably make a FAT filesystem formatted on NuttX unusable under + Windows. + Status: Open + Priority: High + o Graphics subystem (graphics/) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/nuttx/arch/mips/include/mips32/syscall.h b/nuttx/arch/mips/include/mips32/syscall.h index e571e14b0..b2aac6904 100644 --- a/nuttx/arch/mips/include/mips32/syscall.h +++ b/nuttx/arch/mips/include/mips32/syscall.h @@ -148,7 +148,7 @@ /* Context switching system calls ***************************************************/ -/* SYS call 0: +/* SYS call 1: * * void up_fullcontextrestore(uint32_t *restoreregs) __attribute__ ((noreturn)); */ @@ -157,7 +157,7 @@ #define up_fullcontextrestore(restoreregs) \ (void)sys_call1(SYS_restore_context, (uintptr_t)restoreregs) -/* SYS call 1: +/* SYS call 2: * * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); */ diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c index f7818d551..b0ee57a18 100644 --- a/nuttx/fs/fat/fs_fat32.c +++ b/nuttx/fs/fat/fs_fat32.c @@ -1295,12 +1295,13 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir else if ((DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY) == 0) { /* The entry is not a directory */ + ret = -ENOTDIR; goto errout_with_semaphore; } else { - /* The entry is a directory */ + /* The entry is a directory (but not the root directory) */ dir->u.fat.fd_startcluster = ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | @@ -1492,7 +1493,9 @@ static int fat_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) goto errout_with_semaphore; } - /* Check if this is the root directory */ + /* Check if this is the root directory. If it is the root directory, we + * reset the fd_index to 1, skipping over the initial, unused entry. + */ if (fs->fs_type != FSTYPE_FAT32 && dir->u.fat.fd_startcluster == 0) @@ -1501,7 +1504,7 @@ static int fat_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) dir->u.fat.fd_currcluster = 0; dir->u.fat.fd_currsector = fs->fs_rootbase; - dir->u.fat.fd_index = 0; + dir->u.fat.fd_index = 1; } else if (fs->fs_type == FSTYPE_FAT32 && dir->u.fat.fd_startcluster == fs->fs_rootbase) @@ -1510,10 +1513,12 @@ static int fat_rewinddir(struct inode *mountpt, struct fs_dirent_s *dir) 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; + dir->u.fat.fd_index = 1; } - /* This is not the root directory */ + /* This is not the root directory. Here the fd_index is set to 2, skipping over + * both the "." and ".." entries. + */ else { diff --git a/nuttx/fs/fat/fs_fat32dirent.c b/nuttx/fs/fat/fs_fat32dirent.c index a8c65b8de..54633004f 100644 --- a/nuttx/fs/fat/fs_fat32dirent.c +++ b/nuttx/fs/fat/fs_fat32dirent.c @@ -144,6 +144,8 @@ static inline int fat_getsfname(uint8_t *direntry, char *buffer, static void fat_getlfnchunk(uint8_t *chunk, uint8_t *dest, int nchunk); static inline int fat_getlfname(struct fat_mountpt_s *fs, struct fs_dirent_s *dir); #endif +static int fat_dirverify(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + uint16_t offset); static int fat_putsfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo); #ifdef CONFIG_FAT_LFN static void fat_initlfname(uint8_t *chunk, int nchunk); @@ -792,13 +794,14 @@ static inline int fat_findalias(struct fat_mountpt_s *fs, memcpy(&tmpinfo, dirinfo, sizeof(struct fat_dirinfo_s)); - /* Then re-initialize to the beginning of the current directory (skipping - * '.' and '..'). + /* Then re-initialize to the beginning of the current directory, skipping + * over the first entry (unused in the root directory and '.' entry in other + * directories). */ tmpinfo.dir.fd_startcluster = tmpinfo.dir.fd_currcluster; tmpinfo.dir.fd_currsector = tmpinfo.fd_seq.ds_startsector; - tmpinfo.dir.fd_index = 2; + tmpinfo.dir.fd_index = 1; /* Search for the single short file name directory entry in this directory */ @@ -1909,6 +1912,56 @@ static inline int fat_getlfname(struct fat_mountpt_s *fs, struct fs_dirent_s *di #endif /**************************************************************************** + * Name: fat_dirverify + * + * Desciption: + * Verify that every entry preceding this one is marked with something + * other than DIR0_ALLEMPTY. This is necessary only in the root directory + * of freshly formatted volumes. In that case, all entries are set to + * zero. + * + * This function also assures that the sector containing the entry is in + * the sector cache. + * + ****************************************************************************/ + +static int fat_dirverify(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, + uint16_t offset) +{ + uint8_t *direntry; + uint16_t i; + int ret; + + /* Make sure that the sector containing the directory entry is in the sector + * cache. + */ + + ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); + if (ret < 0) + { + return ret; + } + + /* Check every entry preceding this one */ + + for (i = 0; i < offset; i += DIR_SIZE) + { + /* Is the rest of the directory marked empty? */ + + direntry = &fs->fs_buffer[i]; + if (direntry[DIR_NAME] == DIR0_ALLEMPTY) + { + /* Then mark the just the entry as empty */ + + fs->fs_dirty = true; + direntry[DIR_NAME] = DIR0_EMPTY; + } + } + + return OK; +} + +/**************************************************************************** * Name: fat_putsfname * * Desciption: Write the short directory entry name. @@ -1921,6 +1974,8 @@ static int fat_putsfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo { uint8_t *direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; + /* Write the short directory entry */ + memcpy(&direntry[DIR_NAME], dirinfo->fd_name, DIR_MAXFNAME); #ifdef CONFIG_FAT_LCNAMES DIR_PUTNTRES(direntry, dirinfo->fd_ntflags); @@ -2012,6 +2067,12 @@ static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo int namelen; int ret; + /* Some special handling in case we are writing the first entry of the + * root directory in a freshly formatted volume. + */ + + (void)fat_dirverify(fs, dirinfo, dirinfo->fd_seq.ds_lfnoffset); + /* Get the length of the long file name (size of the fd_lfname array is * LDIR_MAXFNAME+1 we do not have to check the length of the string). * NOTE that remainder is conditionally incremented to include the NUL @@ -2065,18 +2126,11 @@ static int fat_putlfname(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo seqno = LDIR0_LAST | nentries; - /* Make sure that the sector containing the "last" long file name entry - * is in the sector cache (it probably is not). + /* Now loop, writing each long file name entry. We know that the sector + * is in the sector cache because fat_dirverify() assures us that that is + * so. */ - ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); - if (ret < 0) - { - return ret; - } - - /* Now loop, writing each long file name entry */ - for (;;) { /* Get the string offset associated with the directory entry. */ @@ -2201,6 +2255,12 @@ static int fat_putsfdirentry(struct fat_mountpt_s *fs, { uint8_t *direntry; + /* Some special handling in case we are writing the first entry of the + * root directory in a freshly formatted volume. + */ + + (void)fat_dirverify(fs, dirinfo, dirinfo->fd_seq.ds_offset); + /* Initialize the 32-byte directory entry */ direntry = &fs->fs_buffer[dirinfo->fd_seq.ds_offset]; @@ -2276,11 +2336,11 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, dirinfo->dir.fd_currsector = cluster; } - /* fd_index is the index into the current directory table. Skipping over - * the '.' and '..' entries. + /* fd_index is the index into the current directory table. It is set to one + * to skip over the first, unused entry in the root directory. */ - dirinfo->dir.fd_index = 2; + dirinfo->dir.fd_index = 1; /* If no path was provided, then the root directory must be exactly what * the caller is looking for. @@ -2377,7 +2437,10 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, ((uint32_t)DIR_GETFSTCLUSTHI(direntry) << 16) | DIR_GETFSTCLUSTLO(direntry); - /* Then restart scanning at the new directory */ + /* Then restart scanning at the new directory, skipping over both the + * '.' and '..' entries that exist in all directories EXCEPT the root + * directory. + */ dirinfo->dir.fd_startcluster = cluster; dirinfo->dir.fd_currcluster = cluster; @@ -2426,9 +2489,9 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo dirinfo->dir.fd_currsector = fs->fs_rootbase; } - /* Skip over the '.' and '..' entries */ + /* Skip over the first, unused entry in the root directory. */ - dirinfo->dir.fd_index = 2; + dirinfo->dir.fd_index = 1; /* Is this a path segment a long or a short file. Was a long file * name parsed? @@ -2835,8 +2898,9 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory) return -EISDIR; } - /* We are asked to delete a directory. Check if this - * sub-directory is empty + /* We are asked to delete a directory. Check if this sub-directory is + * empty (i.e., that there are no valid entries other than the initial + * '.' and '..' entries). */ dirinfo.dir.fd_currcluster = dircluster; |