Finish FAT directory operations; add option to disable mountpoints; fix ARM compile errors
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@252 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
fa9916cac2
commit
587cdd45a1
|
@ -143,5 +143,9 @@
|
|||
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||
* Added FAT support for unlink(), mkdir(), rmdir(), and rename
|
||||
* Added FAT support for opendir(), closedir(), readdir(), seekdir(),
|
||||
telldir(), rewindir().
|
||||
* Fixed ARM compilation errors introduced in 1.2.5 (that is what I get
|
||||
for only testing on the simulation).
|
||||
* Started m68322
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<tr align="center" bgcolor="#e4e4e4">
|
||||
<td>
|
||||
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
||||
<p>Last Updated: May 21, 2007</p>
|
||||
<p>Last Updated: May 26, 2007</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -574,6 +574,10 @@ Other memory:
|
|||
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||
* Added FAT support for unlink(), mkdir(), rmdir(), and rename()
|
||||
* Added FAT support for opendir(), closedir(), readdir(), seekdir(),
|
||||
telldir(), rewindir().
|
||||
* Fixed ARM compilation errors introduced in 1.2.5 (that is what I get
|
||||
for only testing on the simulation).
|
||||
* Started m68322
|
||||
</pre></ul>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</b></big>
|
||||
<p><small>by</small></p>
|
||||
<p>Gregory Nutt</p>
|
||||
<p><small>Last Update: April 30, 2007</small></p>
|
||||
<p><small>Last Update: May 26, 2007</small></p>
|
||||
</center>
|
||||
|
||||
<center><h1>Table of Contents</h1></center>
|
||||
|
@ -1211,8 +1211,9 @@ The system can be re-made subsequently by just typing <code>make</code>.
|
|||
</ul>
|
||||
|
||||
<ul>
|
||||
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFI_DISABLE_POSIX_TIMERS</code>, <code>CONFIG_DISABLE_PTHREAD</code>,
|
||||
<code>CONFIG_DISABLE_SIGNALS</code>, <code>CONFIG_DISABLE_MQUEUE</code>,
|
||||
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFI_DISABLE_POSIX_TIMERS</code>,
|
||||
<code>CONFIG_DISABLE_PTHREAD</code>, <code>CONFIG_DISABLE_SIGNALS</code>,
|
||||
<code>CONFIG_DISABLE_MQUEUE</code>, <code>CONFIG_DISABLE_MOUNTPOUNT</code>
|
||||
</ul>
|
||||
|
||||
<h2>Miscellaneous libc settings</h2>
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <debug.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include "os_internal.h"
|
||||
#include "clock_internal.h"
|
||||
#include "up_internal.h"
|
||||
|
||||
/************************************************************
|
||||
|
|
|
@ -159,7 +159,7 @@ defconfig -- This is a configuration file similar to the Linux
|
|||
up waiting tasks.
|
||||
|
||||
CONFIG_DISABLE_CLOCK, CONFIG_DISABLE_POSIX_TIMERS, CONFIG_DISABLE_PTHREAD.
|
||||
CONFIG_DISABLE_SIGNALS, CONFIG_DISABLE_MQUEUE
|
||||
CONFIG_DISABLE_SIGNALS, CONFIG_DISABLE_MQUEUE, CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
|
||||
Misc libc settings
|
||||
|
|
|
@ -157,6 +157,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||
CONFIG_DISABLE_PTHREAD=n
|
||||
CONFIG_DISABLE_SIGNALS=n
|
||||
CONFIG_DISABLE_MQUEUE=n
|
||||
CONFIG_DISABLE_MOUNTPOINT=y
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -146,6 +146,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||
CONFIG_DISABLE_PTHREAD=n
|
||||
CONFIG_DISABLE_SIGNALS=n
|
||||
CONFIG_DISABLE_MQUEUE=n
|
||||
CONFIG_DISABLE_MOUNTPOINT=y
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -170,6 +170,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||
CONFIG_DISABLE_PTHREAD=n
|
||||
CONFIG_DISABLE_SIGNALS=n
|
||||
CONFIG_DISABLE_MQUEUE=n
|
||||
CONFIG_DISABLE_MOUNTPOINT=y
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -155,6 +155,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||
CONFIG_DISABLE_PTHREAD=n
|
||||
CONFIG_DISABLE_SIGNALS=n
|
||||
CONFIG_DISABLE_MQUEUE=n
|
||||
CONFIG_DISABLE_MOUNTPOINT=y
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -143,6 +143,7 @@ CONFIG_DISABLE_POSIX_TIMERS=y
|
|||
CONFIG_DISABLE_PTHREAD=y
|
||||
CONFIG_DISABLE_SIGNALS=y
|
||||
CONFIG_DISABLE_MQUEUE=y
|
||||
CONFIG_DISABLE_MOUNTPOINT=y
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -111,6 +111,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||
CONFIG_DISABLE_PTHREAD=n
|
||||
CONFIG_DISABLE_SIGNALS=n
|
||||
CONFIG_DISABLE_MQUEUE=n
|
||||
CONFIG_DISABLE_MOUNTPOINT=n
|
||||
|
||||
#
|
||||
# Misc libc settings
|
||||
|
|
|
@ -45,12 +45,15 @@ CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \
|
|||
fs_seekdir.c fs_telldir.c fs_rewinddir.c fs_fsync.c fs_files.c \
|
||||
fs_inode.c fs_inodefind.c fs_inodereserve.c \
|
||||
fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.c \
|
||||
fs_registerblockdriver.c fs_unregisterblockdriver.c \
|
||||
fs_inodeaddref.c fs_inoderelease.c
|
||||
ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y)
|
||||
CSRCS += fs_registerblockdriver.c fs_unregisterblockdriver.c \
|
||||
fs_mount.c fs_umount.c fs_unlink.c fs_mkdir.c fs_rmdir.c \
|
||||
fs_rename.c fs_inodeaddref.c fs_inoderelease.c
|
||||
fs_rename.c
|
||||
ifeq ($(CONFIG_FS_FAT),y)
|
||||
CSRCS += fs_fat32.c fs_fat32util.c
|
||||
endif
|
||||
endif
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
|
||||
SRCS = $(ASRCS) $(CSRCS)
|
||||
|
|
|
@ -76,8 +76,12 @@
|
|||
int closedir(FAR DIR *dirp)
|
||||
{
|
||||
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
struct inode *inode;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if (!idir || !idir->root)
|
||||
if (!idir || !idir->fd_root)
|
||||
{
|
||||
*get_errno_ptr() = EBADF;
|
||||
return ERROR;
|
||||
|
@ -87,31 +91,44 @@ int closedir(FAR DIR *dirp)
|
|||
* inode we have open.
|
||||
*/
|
||||
|
||||
if (IS_MOUNTPT_INODE(idir->root))
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
inode = idir->fd_root;
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the closedir() method (not an error if it does not)
|
||||
*/
|
||||
|
||||
#warning "Mountpoint support not implemented"
|
||||
*get_errno_ptr() = ENOSYS;
|
||||
return ERROR;
|
||||
if (inode->u.i_mops && inode->u.i_mops->closedir)
|
||||
{
|
||||
/* Perform the closedir() operation */
|
||||
|
||||
ret = inode->u.i_mops->closedir(inode, idir);
|
||||
if (ret < 0)
|
||||
{
|
||||
*get_errno_ptr() = -ret;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root psuedo file system, release
|
||||
* our contained reference to the 'next' inode.
|
||||
*/
|
||||
|
||||
if (idir->u.psuedo.next)
|
||||
if (idir->u.psuedo.fd_next)
|
||||
{
|
||||
inode_release(idir->u.psuedo.next);
|
||||
inode_release(idir->u.psuedo.fd_next);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release our references on the contained 'root' inode */
|
||||
|
||||
if (idir->root)
|
||||
if (idir->fd_root)
|
||||
{
|
||||
inode_release(idir->root);
|
||||
inode_release(idir->fd_root);
|
||||
}
|
||||
|
||||
/* Then release the container */
|
||||
|
|
|
@ -59,7 +59,8 @@
|
|||
#include "fs_internal.h"
|
||||
#include "fs_fat32.h"
|
||||
|
||||
#if CONFIG_FS_FAT
|
||||
#ifdef CONFIG_FS_FAT
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -85,6 +86,8 @@ static int fat_sync(FAR struct file *filp);
|
|||
|
||||
static int fat_opendir(struct inode *mountpt, const char *relpath,
|
||||
struct internal_dir_s *dir);
|
||||
static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir);
|
||||
static int fat_rewinddir(struct inode *mountpt, struct internal_dir_s *dir);
|
||||
|
||||
static int fat_bind(FAR struct inode *blkdriver, const void *data,
|
||||
void **handle);
|
||||
|
@ -120,6 +123,9 @@ const struct mountpt_operations fat_operations =
|
|||
fat_sync,
|
||||
|
||||
fat_opendir,
|
||||
NULL,
|
||||
fat_readdir,
|
||||
fat_rewinddir,
|
||||
|
||||
fat_bind,
|
||||
fat_unbind,
|
||||
|
@ -296,7 +302,7 @@ static int fat_open(FAR struct file *filp, const char *relpath,
|
|||
/* Save information that can be used later to recover the directory entry */
|
||||
|
||||
ff->ff_dirsector = fs->fs_currentsector;
|
||||
ff->ff_dirindex = dirinfo.fd_index;
|
||||
ff->ff_dirindex = dirinfo.dir.fd_index;
|
||||
|
||||
/* File cluster/size info */
|
||||
|
||||
|
@ -1248,10 +1254,10 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct intern
|
|||
{
|
||||
/* Handler the FAT12/16 root directory */
|
||||
|
||||
dir->u.fat.startcluster = 0;
|
||||
dir->u.fat.currcluster = 0;
|
||||
dir->u.fat.currsector = fs->fs_rootbase;
|
||||
dir->u.fat.dirindex = 2;
|
||||
dir->u.fat.fd_startcluster = 0;
|
||||
dir->u.fat.fd_currcluster = 0;
|
||||
dir->u.fat.fd_currsector = fs->fs_rootbase;
|
||||
dir->u.fat.fd_index = 2;
|
||||
}
|
||||
|
||||
/* This is not the root directory. Verify that it is some kind of directory */
|
||||
|
@ -1266,12 +1272,168 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct intern
|
|||
{
|
||||
/* The entry is a directory */
|
||||
|
||||
dir->u.fat.startcluster =
|
||||
dir->u.fat.fd_startcluster =
|
||||
((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||
dir->u.fat.currcluster = dir->u.fat.startcluster;
|
||||
dir->u.fat.currsector = fat_cluster2sector(fs, dir->u.fat.currcluster);
|
||||
dir->u.fat.dirindex = 2;
|
||||
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;
|
||||
}
|
||||
|
||||
fat_semgive(fs);
|
||||
return OK;
|
||||
|
||||
errout_with_semaphore:
|
||||
fat_semgive(fs);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_readdir
|
||||
*
|
||||
* Description: Read the next directory entry
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fat_readdir(struct inode *mountpt, struct internal_dir_s *dir)
|
||||
{
|
||||
struct fat_mountpt_s *fs;
|
||||
unsigned int dirindex;
|
||||
ubyte *direntry;
|
||||
ubyte ch;
|
||||
ubyte attribute;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
|
||||
fs = mountpt->i_private;
|
||||
|
||||
/* Make sure that the mount is still healthy */
|
||||
|
||||
fat_semtake(fs);
|
||||
ret = fat_checkmount(fs);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* 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')
|
||||
{
|
||||
ret = fat_fscacheread(fs, dir->u.fat.fd_currsector);
|
||||
if ( ret < 0)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Get a reference to the current directory entry */
|
||||
|
||||
dirindex = (dir->u.fat.fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||
direntry = &fs->fs_buffer[dirindex];
|
||||
|
||||
/* Has it reached to end of the directory */
|
||||
|
||||
ch = *direntry;
|
||||
if (ch == DIR0_ALLEMPTY)
|
||||
{
|
||||
/* We signal the end of the directory by returning the
|
||||
* special error -ENOENT
|
||||
*/
|
||||
|
||||
ret = -ENOENT;
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* No, is the current entry a valid entry? */
|
||||
|
||||
attribute = DIR_GETATTRIBUTES(direntry);
|
||||
if (ch != DIR0_EMPTY && (attribute & FATATTR_VOLUMEID) == 0)
|
||||
{
|
||||
/* Yes.. get the name from the directory info */
|
||||
|
||||
(void)fat_dirname2path(dir->fd_dir.d_name, direntry);
|
||||
|
||||
/* And the file type */
|
||||
|
||||
if ((attribute & FATATTR_DIRECTORY) == 0)
|
||||
{
|
||||
dir->fd_dir.d_type = DTYPE_FILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir->fd_dir.d_type = DTYPE_DIRECTORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the next directory index */
|
||||
|
||||
if (fat_nextdirentry(fs, &dir->u.fat) != OK)
|
||||
{
|
||||
dir->u.fat.fd_currsector = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fat_semgive(fs);
|
||||
return OK;
|
||||
|
||||
errout_with_semaphore:
|
||||
fat_semgive(fs);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_rewindir
|
||||
*
|
||||
* Description: Reset directory read to the first entry
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int fat_rewinddir(struct inode *mountpt, struct internal_dir_s *dir)
|
||||
{
|
||||
struct fat_mountpt_s *fs;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
DEBUGASSERT(mountpt != NULL && mountpt->i_private != NULL);
|
||||
|
||||
/* Recover our private data from the inode instance */
|
||||
|
||||
fs = mountpt->i_private;
|
||||
|
||||
/* Make sure that the mount is still healthy */
|
||||
|
||||
fat_semtake(fs);
|
||||
ret = fat_checkmount(fs);
|
||||
if (ret != OK)
|
||||
{
|
||||
goto errout_with_semaphore;
|
||||
}
|
||||
|
||||
/* Check if this is the root directory */
|
||||
|
||||
if (dir->u.fat.fd_startcluster == 0)
|
||||
{
|
||||
/* Handler the FAT12/16 root directory */
|
||||
|
||||
dir->u.fat.fd_currcluster = 0;
|
||||
dir->u.fat.fd_currsector = fs->fs_rootbase;
|
||||
dir->u.fat.fd_index = 2;
|
||||
}
|
||||
|
||||
/* This is not the root directory */
|
||||
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
fat_semgive(fs);
|
||||
|
@ -1589,7 +1751,7 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
|||
DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16);
|
||||
DIR_PUTFSTCLUSTLO(direntry, dircluster);
|
||||
|
||||
parentcluster = dirinfo.fd_startcluster;
|
||||
parentcluster = dirinfo.dir.fd_startcluster;
|
||||
if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase)
|
||||
{
|
||||
parentcluster = 0;
|
||||
|
@ -1833,4 +1995,5 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_FS_FAT */
|
||||
|
|
|
@ -492,10 +492,7 @@ struct fat_dirinfo_s
|
|||
#ifdef CONFIG_FAT_LCNAMES
|
||||
ubyte fd_ntflags; /* NTRes lower case flags */
|
||||
#endif
|
||||
uint16 fd_index; /* Current index */
|
||||
size_t fd_startcluster; /* Start cluster number */
|
||||
size_t fd_currcluster; /* Current cluster number */
|
||||
size_t fd_currsector; /* Current sector */
|
||||
struct fs_fatdir_s dir; /* Used with opendir, readdir, etc. */
|
||||
ubyte *fd_entry; /* A pointer to the raw 32-byte entry */
|
||||
};
|
||||
|
||||
|
@ -556,11 +553,13 @@ EXTERN sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster);
|
|||
|
||||
/* Help for traverseing directory trees */
|
||||
|
||||
EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||
EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir);
|
||||
EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||
const char *path);
|
||||
EXTERN int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||
|
||||
EXTERN int fat_dirname2path(char *path, ubyte *direntry);
|
||||
|
||||
/* File creation and removal helpers */
|
||||
|
||||
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
#include "fs_internal.h"
|
||||
#include "fs_fat32.h"
|
||||
|
||||
#if CONFIG_FS_FAT
|
||||
#ifdef CONFIG_FS_FAT
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -252,113 +253,6 @@ static inline int fat_path2dirname(const char **path, struct fat_dirinfo_s *diri
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_dirname2path
|
||||
*
|
||||
* Desciption: Convert a filename in a raw directory entry into a user
|
||||
* filename. This is essentially the inverse operation of that performed
|
||||
* by fat_path2dirname. See that function for more details.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline int fat_dirname2path(char *path, struct fat_dirinfo_s *dirinfo)
|
||||
{
|
||||
const unsigned char *direntry = dirinfo->fd_entry;
|
||||
int ch;
|
||||
int ndx;
|
||||
|
||||
/* Check if we will be doing upper to lower case conversions */
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
dirinfo->fd_ntflags = DIR_GETNTRES(direntry);
|
||||
#endif
|
||||
|
||||
/* Get the 8-byte filename */
|
||||
|
||||
for (ndx = 0; ndx < 8; ndx++)
|
||||
{
|
||||
/* Get the next filename character from the directory entry */
|
||||
|
||||
ch = direntry[ndx];
|
||||
|
||||
/* Any space (or ndx==8) terminates the filename */
|
||||
|
||||
if (ch == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* In this version, we never write 0xe5 in the directoryfilenames
|
||||
* (because we do not handle any character sets where 0xe5 is valid
|
||||
* in a filaname), but we could encounted this in a filesystem
|
||||
* written by some other system
|
||||
*/
|
||||
|
||||
if (ndx == 0 && ch == DIR0_E5)
|
||||
{
|
||||
ch = 0xe5;
|
||||
}
|
||||
|
||||
/* Check if we should perform upper to lower case conversion
|
||||
* of the (whole) filename.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
if (dirinfo->fd_ntflags & FATNTRES_LCNAME && isupper(ch))
|
||||
{
|
||||
ch = tolower(ch);
|
||||
}
|
||||
#endif
|
||||
/* Copy the next character into the filename */
|
||||
|
||||
*path++ = ch;
|
||||
}
|
||||
|
||||
/* Check if there is an extension */
|
||||
|
||||
if (direntry[8] != ' ')
|
||||
{
|
||||
/* Yes, output the dot before the extension */
|
||||
|
||||
*path++ = '.';
|
||||
|
||||
/* Then output the (up to) 3 character extension */
|
||||
|
||||
for (ndx = 8; ndx < 11; ndx++)
|
||||
{
|
||||
/* Get the next extensions character from the directory entry */
|
||||
|
||||
ch = dirinfo->fd_name[ndx];
|
||||
|
||||
/* Any space (or ndx==11) terminates the extension */
|
||||
|
||||
if (ch == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we should perform upper to lower case conversion
|
||||
* of the (whole) filename.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
if (ntflags & FATNTRES_LCEXT && isupper(ch))
|
||||
{
|
||||
ch = tolower(ch);
|
||||
}
|
||||
#endif
|
||||
/* Copy the next character into the filename */
|
||||
|
||||
*path++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put a null terminator at the end of the filename */
|
||||
|
||||
*path = '\0';
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_checkfsinfo
|
||||
*
|
||||
|
@ -1412,14 +1306,14 @@ sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
||||
int fat_nextdirentry(struct fat_mountpt_s *fs, struct fs_fatdir_s *dir)
|
||||
{
|
||||
unsigned int cluster;
|
||||
unsigned int ndx;
|
||||
|
||||
/* Increment the index to the next 32-byte directory entry */
|
||||
|
||||
ndx = dirinfo->fd_index + 1;
|
||||
ndx = dir->fd_index + 1;
|
||||
|
||||
/* Check if all of the directory entries in this sectory have
|
||||
* been examined.
|
||||
|
@ -1429,13 +1323,13 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
{
|
||||
/* Yes, then we will have to read the next sector */
|
||||
|
||||
dirinfo->fd_currsector++;
|
||||
dir->fd_currsector++;
|
||||
|
||||
/* For FAT12/16, the root directory is a group of sectors relative
|
||||
* to the first sector of the fat volume.
|
||||
*/
|
||||
|
||||
if (!dirinfo->fd_currcluster)
|
||||
if (!dir->fd_currcluster)
|
||||
{
|
||||
/* For FAT12/13, the boot record tells us number of 32-bit directories
|
||||
* that are contained in the root directory. This should correspond to
|
||||
|
@ -1470,7 +1364,7 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
{
|
||||
/* Get next cluster */
|
||||
|
||||
cluster = fat_getcluster(fs, dirinfo->fd_currcluster);
|
||||
cluster = fat_getcluster(fs, dir->fd_currcluster);
|
||||
|
||||
/* Check if a valid cluster was obtained. */
|
||||
|
||||
|
@ -1482,15 +1376,15 @@ int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
|
||||
/* Initialize for new cluster */
|
||||
|
||||
dirinfo->fd_currcluster = cluster;
|
||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
dir->fd_currcluster = cluster;
|
||||
dir->fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the new index into dirinfo->fd_currsector */
|
||||
/* Save the new index into dir->fd_currsector */
|
||||
|
||||
dirinfo->fd_index = ndx;
|
||||
dir->fd_index = ndx;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -1522,9 +1416,9 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
* the first cluster of the root directory.
|
||||
*/
|
||||
|
||||
dirinfo->fd_startcluster = cluster;
|
||||
dirinfo->fd_currcluster = cluster;
|
||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
dirinfo->dir.fd_startcluster = cluster;
|
||||
dirinfo->dir.fd_currcluster = cluster;
|
||||
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1532,14 +1426,14 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
* relative to the first sector of the fat volume.
|
||||
*/
|
||||
|
||||
dirinfo->fd_startcluster = 0;
|
||||
dirinfo->fd_currcluster = 0;
|
||||
dirinfo->fd_currsector = cluster;
|
||||
dirinfo->dir.fd_startcluster = 0;
|
||||
dirinfo->dir.fd_currcluster = 0;
|
||||
dirinfo->dir.fd_currsector = cluster;
|
||||
}
|
||||
|
||||
/* fd_index is the index into the current directory table */
|
||||
|
||||
dirinfo->fd_index = 0;
|
||||
dirinfo->dir.fd_index = 0;
|
||||
|
||||
/* If no path was provided, then the root directory must be exactly
|
||||
* what the caller is looking for.
|
||||
|
@ -1577,7 +1471,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
{
|
||||
/* Read the next sector into memory */
|
||||
|
||||
ret = fat_fscacheread(fs, dirinfo->fd_currsector);
|
||||
ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1585,7 +1479,7 @@ 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->fd_index)];
|
||||
direntry = &fs->fs_buffer[DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index)];
|
||||
|
||||
/* Check if we are at the end of the directory */
|
||||
|
||||
|
@ -1606,7 +1500,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
/* No... get the next directory index and try again */
|
||||
|
||||
if (fat_nextdirentry(fs, dirinfo) != OK)
|
||||
if (fat_nextdirentry(fs, &dirinfo->dir) != OK)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -1646,9 +1540,9 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
|||
|
||||
/* The restart scanning at the new directory */
|
||||
|
||||
dirinfo->fd_currcluster = dirinfo->fd_startcluster = cluster;
|
||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
dirinfo->fd_index = 2;
|
||||
dirinfo->dir.fd_currcluster = dirinfo->dir.fd_startcluster = cluster;
|
||||
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
dirinfo->dir.fd_index = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1670,21 +1564,21 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
/* Re-initialize directory object */
|
||||
|
||||
cluster = dirinfo->fd_startcluster;
|
||||
cluster = dirinfo->dir.fd_startcluster;
|
||||
if (cluster)
|
||||
{
|
||||
/* Cluster chain can be extended */
|
||||
|
||||
dirinfo->fd_currcluster = cluster;
|
||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
dirinfo->dir.fd_currcluster = cluster;
|
||||
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fixed size FAT12/16 root directory is at fixxed offset/size */
|
||||
|
||||
dirinfo->fd_currsector = fs->fs_rootbase;
|
||||
dirinfo->dir.fd_currsector = fs->fs_rootbase;
|
||||
}
|
||||
dirinfo->fd_index = 0;
|
||||
dirinfo->dir.fd_index = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -1692,7 +1586,7 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
/* Read the directory sector into fs_buffer */
|
||||
|
||||
ret = fat_fscacheread(fs, dirinfo->fd_currsector);
|
||||
ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1700,7 +1594,7 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
/* Get a pointer to the entry at fd_index */
|
||||
|
||||
dirindex = (dirinfo->fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||
dirindex = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||
direntry = &fs->fs_buffer[dirindex];
|
||||
|
||||
/* Check if this directory entry is empty */
|
||||
|
@ -1714,7 +1608,7 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
return OK;
|
||||
}
|
||||
|
||||
ret = fat_nextdirentry(fs, dirinfo);
|
||||
ret = fat_nextdirentry(fs, &dirinfo->dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1737,7 +1631,7 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
|
||||
/* Try to extend the cluster chain for this directory */
|
||||
|
||||
cluster = fat_extendchain(fs, dirinfo->fd_currcluster);
|
||||
cluster = fat_extendchain(fs, dirinfo->dir.fd_currcluster);
|
||||
if (cluster < 0)
|
||||
{
|
||||
return cluster;
|
||||
|
@ -1773,6 +1667,115 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_dirname2path
|
||||
*
|
||||
* Desciption: Convert a filename in a raw directory entry into a user
|
||||
* filename. This is essentially the inverse operation of that performed
|
||||
* by fat_path2dirname. See that function for more details.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int fat_dirname2path(char *path, ubyte *direntry)
|
||||
{
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
ubyte ntflags;
|
||||
#endif
|
||||
int ch;
|
||||
int ndx;
|
||||
|
||||
/* Check if we will be doing upper to lower case conversions */
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
ntflags = DIR_GETNTRES(direntry);
|
||||
#endif
|
||||
|
||||
/* Get the 8-byte filename */
|
||||
|
||||
for (ndx = 0; ndx < 8; ndx++)
|
||||
{
|
||||
/* Get the next filename character from the directory entry */
|
||||
|
||||
ch = direntry[ndx];
|
||||
|
||||
/* Any space (or ndx==8) terminates the filename */
|
||||
|
||||
if (ch == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* In this version, we never write 0xe5 in the directoryfilenames
|
||||
* (because we do not handle any character sets where 0xe5 is valid
|
||||
* in a filaname), but we could encounted this in a filesystem
|
||||
* written by some other system
|
||||
*/
|
||||
|
||||
if (ndx == 0 && ch == DIR0_E5)
|
||||
{
|
||||
ch = 0xe5;
|
||||
}
|
||||
|
||||
/* Check if we should perform upper to lower case conversion
|
||||
* of the (whole) filename.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
if (ntflags & FATNTRES_LCNAME && isupper(ch))
|
||||
{
|
||||
ch = tolower(ch);
|
||||
}
|
||||
#endif
|
||||
/* Copy the next character into the filename */
|
||||
|
||||
*path++ = ch;
|
||||
}
|
||||
|
||||
/* Check if there is an extension */
|
||||
|
||||
if (direntry[8] != ' ')
|
||||
{
|
||||
/* Yes, output the dot before the extension */
|
||||
|
||||
*path++ = '.';
|
||||
|
||||
/* Then output the (up to) 3 character extension */
|
||||
|
||||
for (ndx = 8; ndx < 11; ndx++)
|
||||
{
|
||||
/* Get the next extensions character from the directory entry */
|
||||
|
||||
ch = direntry[DIR_NAME + ndx];
|
||||
|
||||
/* Any space (or ndx==11) terminates the extension */
|
||||
|
||||
if (ch == ' ')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we should perform upper to lower case conversion
|
||||
* of the (whole) filename.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
if (ntflags & FATNTRES_LCEXT && isupper(ch))
|
||||
{
|
||||
ch = tolower(ch);
|
||||
}
|
||||
#endif
|
||||
/* Copy the next character into the filename */
|
||||
|
||||
*path++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
/* Put a null terminator at the end of the filename */
|
||||
|
||||
*path = '\0';
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fat_dirtruncate
|
||||
*
|
||||
|
@ -1955,9 +1958,9 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
|||
* sub-directory is empty
|
||||
*/
|
||||
|
||||
dirinfo.fd_currcluster = dircluster;
|
||||
dirinfo.fd_currsector = fat_cluster2sector(fs, dircluster);
|
||||
dirinfo.fd_index = 2;
|
||||
dirinfo.dir.fd_currcluster = dircluster;
|
||||
dirinfo.dir.fd_currsector = fat_cluster2sector(fs, dircluster);
|
||||
dirinfo.dir.fd_index = 2;
|
||||
|
||||
/* Loop until either (1) an entry is found in the directory
|
||||
* (error), (2) the directory is found to be empty, or (3) some
|
||||
|
@ -1973,7 +1976,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
|||
* subdirectory sector is in the cache
|
||||
*/
|
||||
|
||||
ret = fat_fscacheread(fs, dirinfo.fd_currsector);
|
||||
ret = fat_fscacheread(fs, dirinfo.dir.fd_currsector);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1981,7 +1984,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
|||
|
||||
/* Get a reference to the next entry in the directory */
|
||||
|
||||
subdirindex = (dirinfo.fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||
subdirindex = (dirinfo.dir.fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||
subdirentry = &fs->fs_buffer[subdirindex];
|
||||
|
||||
/* Is this the last entry in the direcory? */
|
||||
|
@ -2007,7 +2010,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
|||
|
||||
/* Get the next directgory entry */
|
||||
|
||||
ret = fat_nextdirentry(fs, &dirinfo);
|
||||
ret = fat_nextdirentry(fs, &dirinfo.dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
|
@ -2298,7 +2301,7 @@ int fat_updatefsinfo(struct fat_mountpt_s *fs)
|
|||
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;
|
||||
|
@ -2313,4 +2316,5 @@ int fat_updatefsinfo(struct fat_mountpt_s *fs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_FS_FAT */
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -137,4 +138,5 @@ int fsync(int fd)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOINT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -73,10 +73,34 @@
|
|||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* The internal representation of type DIR is just a
|
||||
* container for an inode reference and a dirent structure.
|
||||
/* The internal representation of type DIR is just a container for an inode
|
||||
* reference, a position, a dirent structure, and file-system-specific
|
||||
* information.
|
||||
*
|
||||
* For the root psuedo-file system, we need retain only the 'next' inode
|
||||
* need for the next readdir() operation. We hold a reference on this
|
||||
* inode so we know that it will persist until closedir is called.
|
||||
*/
|
||||
|
||||
struct fs_psuedodir_s
|
||||
{
|
||||
struct inode *fd_next; /* The inode for the next call to readdir() */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_FS_FAT
|
||||
/* For fat, we need to retun the start cluster, current cluster, current
|
||||
* sector and current directory index.
|
||||
*/
|
||||
|
||||
struct fs_fatdir_s
|
||||
{
|
||||
uint32 fd_startcluster; /* Start cluster number of the directory*/
|
||||
uint32 fd_currcluster; /* Current cluster number being read*/
|
||||
size_t fd_currsector; /* Current sector being read*/
|
||||
unsigned int fd_index; /* Current index of the directory entry to read */
|
||||
};
|
||||
#endif
|
||||
|
||||
struct internal_dir_s
|
||||
{
|
||||
/* This is the node that was opened by opendir. The type of the inode
|
||||
|
@ -87,11 +111,11 @@ struct internal_dir_s
|
|||
* closedir() is called (although inodes linked to this inode may change).
|
||||
*/
|
||||
|
||||
struct inode *root;
|
||||
struct inode *fd_root;
|
||||
|
||||
/* This keeps track of the current directory position for telldir */
|
||||
|
||||
off_t position;
|
||||
off_t fd_position;
|
||||
|
||||
/* Retained control information depends on the type of file system that
|
||||
* provides is provides the mountpoint. Ideally this information should
|
||||
|
@ -101,34 +125,15 @@ struct internal_dir_s
|
|||
|
||||
union
|
||||
{
|
||||
/* For the root psuedo-file system, we need retain only the 'next' inode
|
||||
* need for the next readdir() operation. We hold a reference on this
|
||||
* inode so we know that it will persist until closedir is called.
|
||||
*/
|
||||
|
||||
struct
|
||||
{
|
||||
struct inode *next; /* The inode for the next call to readdir() */
|
||||
} psuedo;
|
||||
|
||||
struct fs_psuedodir_s psuedo;
|
||||
#ifdef CONFIG_FS_FAT
|
||||
/* For fat, we need to retun the start cluster, current cluster, current
|
||||
* sector and current directory index.
|
||||
*/
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 startcluster; /* Starting cluster of directory */
|
||||
uint32 currcluster; /* The current cluster being read */
|
||||
size_t currsector; /* The current sector being read */
|
||||
unsigned int dirindex; /* The next directory entry to read */
|
||||
} fat;
|
||||
struct fs_fatdir_s fat;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
/* In any event, this the actual struct dirent that is returned by readdir */
|
||||
|
||||
struct dirent dir; /* Populated when readdir is called */
|
||||
struct dirent fd_dir; /* Populated when readdir is called */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -130,4 +131,5 @@ int mkdir(const char *pathname, mode_t mode)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/* At least one filesystem must be defined, or this file will not compile.
|
||||
* It may be desire-able to make filesystems dynamically registered at
|
||||
|
@ -272,4 +273,5 @@ int mount(const char *source, const char *target,
|
|||
}
|
||||
|
||||
#endif /* Need at least filesystem */
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* Need file descriptor support */
|
||||
|
|
|
@ -153,12 +153,14 @@ int open(const char *path, int oflags, ...)
|
|||
ret = OK;
|
||||
if (inode->u.i_ops->open)
|
||||
{
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
|
||||
relpath, oflags, mode);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
|
||||
}
|
||||
|
|
|
@ -197,11 +197,12 @@ FAR DIR *opendir(const char *path)
|
|||
* inode or a file system mountpoint.
|
||||
*/
|
||||
|
||||
dir->root = inode; /* Save the inode where we start */
|
||||
dir->position = 0; /* This is the position in the read stream */
|
||||
dir->fd_root = inode; /* Save the inode where we start */
|
||||
dir->fd_position = 0; /* This is the position in the read stream */
|
||||
|
||||
/* Is this a not in the psuedo filesystem? */
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
|
@ -224,11 +225,12 @@ FAR DIR *opendir(const char *path)
|
|||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root psuedo file system */
|
||||
|
||||
inode_addref(inode); /* Now we have two references on inode */
|
||||
dir->u.psuedo.next = inode; /* This is the next node to use for readdir() */
|
||||
inode_addref(inode); /* Now we have two references on inode */
|
||||
dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */
|
||||
}
|
||||
|
||||
return ((DIR*)dir);
|
||||
|
|
|
@ -53,52 +53,59 @@
|
|||
* Name: readpsuedodir
|
||||
************************************************************/
|
||||
|
||||
static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
static inline int readpsuedodir(struct internal_dir_s *idir)
|
||||
{
|
||||
FAR struct inode *prev;
|
||||
|
||||
/* Check if we are at the end of the list */
|
||||
|
||||
if (!idir->u.psuedo.next)
|
||||
if (!idir->u.psuedo.fd_next)
|
||||
{
|
||||
return NULL;
|
||||
/* End of file and error conditions are not distinguishable
|
||||
* with readdir. Here we return -ENOENT to signal the end
|
||||
* of the directory.
|
||||
*/
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* Copy the inode name into the dirent structure */
|
||||
|
||||
strncpy(idir->dir.d_name, idir->u.psuedo.next->i_name, NAME_MAX+1);
|
||||
strncpy(idir->fd_dir.d_name, idir->u.psuedo.fd_next->i_name, NAME_MAX+1);
|
||||
|
||||
/* If the node has file operations, we will say that it is
|
||||
* a file.
|
||||
*/
|
||||
|
||||
idir->dir.d_type = 0;
|
||||
if (idir->u.psuedo.next->u.i_ops)
|
||||
idir->fd_dir.d_type = 0;
|
||||
if (idir->u.psuedo.fd_next->u.i_ops)
|
||||
{
|
||||
idir->dir.d_type |= DTYPE_FILE;
|
||||
idir->fd_dir.d_type |= DTYPE_FILE;
|
||||
}
|
||||
|
||||
/* If the node has child node(s), then we will say that it
|
||||
* is a directory. NOTE: that the node can be both!
|
||||
*/
|
||||
|
||||
if (idir->u.psuedo.next->i_child || !idir->u.psuedo.next->u.i_ops)
|
||||
if (idir->u.psuedo.fd_next->i_child || !idir->u.psuedo.fd_next->u.i_ops)
|
||||
{
|
||||
idir->dir.d_type |= DTYPE_DIRECTORY;
|
||||
idir->fd_dir.d_type |= DTYPE_DIRECTORY;
|
||||
}
|
||||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
|
||||
inode_semtake();
|
||||
|
||||
prev = idir->u.psuedo.next;
|
||||
idir->u.psuedo.next = prev->i_peer; /* The next node to visit */
|
||||
prev = idir->u.psuedo.fd_next;
|
||||
idir->u.psuedo.fd_next = prev->i_peer; /* The next node to visit */
|
||||
|
||||
if (idir->u.psuedo.next)
|
||||
if (idir->u.psuedo.fd_next)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
|
||||
idir->u.psuedo.next->i_crefs++;
|
||||
idir->u.psuedo.fd_next->i_crefs++;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
|
@ -108,7 +115,7 @@ static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
|
|||
inode_release(prev);
|
||||
}
|
||||
|
||||
return &idir->dir;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
|
@ -137,39 +144,72 @@ static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
|
|||
*
|
||||
************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
FAR struct dirent *readdir(DIR *dirp)
|
||||
{
|
||||
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
if (!idir || !idir->fd_root)
|
||||
{
|
||||
*get_errno_ptr() = EBADF;
|
||||
return NULL;
|
||||
ret = EBADF;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
inode = idir->fd_root;
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the readdir() method
|
||||
*/
|
||||
|
||||
#warning "Mountpoint support not implemented"
|
||||
*get_errno_ptr() = ENOSYS;
|
||||
return NULL;
|
||||
if (!inode->u.i_mops || !inode->u.i_mops->readdir)
|
||||
{
|
||||
ret = EACCES;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Perform the readdir() operation */
|
||||
|
||||
ret = inode->u.i_mops->readdir(inode, idir);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The node is part of the root psuedo file system, release
|
||||
* our contained reference to the 'next' inode.
|
||||
*/
|
||||
return readpsuedodir(idir);
|
||||
ret = readpsuedodir(idir);
|
||||
}
|
||||
|
||||
/* ret < 0 is an error. Special case: ret = -ENOENT is end of file */
|
||||
|
||||
if ( ret < 0)
|
||||
{
|
||||
if (ret == -ENOENT)
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ret;
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
|
||||
idir->fd_position++;
|
||||
return &idir->fd_dir;
|
||||
|
||||
errout:
|
||||
*get_errno_ptr() = ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <nuttx/fs.h>
|
||||
#include "fs_internal.h"
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/************************************************************
|
||||
* Definitions
|
||||
************************************************************/
|
||||
|
@ -98,3 +100,5 @@ STATUS register_blockdriver(const char *path,
|
|||
inode_semgive();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -154,4 +155,5 @@ int rename(const char *oldpath, const char *newpath)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
* Private Functions
|
||||
************************************************************/
|
||||
|
||||
/************************************************************
|
||||
* Name: rewindpsuedodir
|
||||
************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
static inline void rewindpsuedodir(struct internal_dir_s *idir)
|
||||
|
@ -58,15 +62,15 @@ static inline void rewindpsuedodir(struct internal_dir_s *idir)
|
|||
|
||||
/* Reset the position to the beginning */
|
||||
|
||||
prev = idir->u.psuedo.next; /* (Save to delete later) */
|
||||
idir->u.psuedo.next = idir->root; /* The next node to visit */
|
||||
idir->position = 0; /* Reset position */
|
||||
prev = idir->u.psuedo.fd_next; /* (Save to delete later) */
|
||||
idir->u.psuedo.fd_next = idir->fd_root; /* The next node to visit */
|
||||
idir->fd_position = 0; /* Reset position */
|
||||
|
||||
/* Increment the reference count on the root=next node. We
|
||||
* should now have two references on the inode.
|
||||
*/
|
||||
|
||||
idir->root->i_crefs++;
|
||||
idir->fd_root->i_crefs++;
|
||||
inode_semgive();
|
||||
|
||||
/* Then release the reference to the old next inode */
|
||||
|
@ -100,10 +104,13 @@ static inline void rewindpsuedodir(struct internal_dir_s *idir)
|
|||
void rewinddir(FAR DIR *dirp)
|
||||
{
|
||||
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
struct inode *inode;
|
||||
#endif
|
||||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
if (!idir || !idir->fd_root)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -112,13 +119,23 @@ void rewinddir(FAR DIR *dirp)
|
|||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
inode = idir->fd_root;
|
||||
if (INODE_IS_MOUNTPT(inode))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||
* supports the rewinddir() method
|
||||
*/
|
||||
|
||||
#warning "Mountpoint support not implemented"
|
||||
if (inode->u.i_mops && inode->u.i_mops->rewinddir)
|
||||
{
|
||||
/* Perform the rewinddir() operation */
|
||||
|
||||
inode->u.i_mops->rewinddir(inode, idir);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root psuedo file system */
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -130,4 +131,5 @@ int rmdir(const char *pathname)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
|
||||
/************************************************************
|
||||
* Name: seekpsuedodir
|
||||
************************************************************/
|
||||
|
||||
static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
||||
{
|
||||
struct inode *curr;
|
||||
|
@ -62,15 +66,15 @@ static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
|||
* "rewind" to the root dir.
|
||||
*/
|
||||
|
||||
if ( offset < idir->position )
|
||||
if ( offset < idir->fd_position )
|
||||
{
|
||||
pos = 0;
|
||||
curr = idir->root;
|
||||
curr = idir->fd_root;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = idir->position;
|
||||
curr = idir->u.psuedo.next;
|
||||
pos = idir->fd_position;
|
||||
curr = idir->u.psuedo.fd_next;
|
||||
}
|
||||
|
||||
/* Traverse the peer list starting at the 'root' of the
|
||||
|
@ -84,9 +88,9 @@ static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
|||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
|
||||
prev = idir->u.psuedo.next;
|
||||
idir->u.psuedo.next = curr; /* The next node to visit (might be null) */
|
||||
idir->position = pos; /* Might be beyond the last dirent */
|
||||
prev = idir->u.psuedo.fd_next;
|
||||
idir->u.psuedo.fd_next = curr; /* The next node to visit (might be null) */
|
||||
idir->fd_position = pos; /* Might be beyond the last dirent */
|
||||
|
||||
if (curr)
|
||||
{
|
||||
|
@ -103,6 +107,73 @@ static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
|||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Name: seekmountptdir
|
||||
************************************************************/
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
static inline void seekmountptdir(struct internal_dir_s *idir, off_t offset)
|
||||
{
|
||||
struct inode *inode;
|
||||
off_t pos;
|
||||
|
||||
/* Determine a starting point for the seek. If the seek
|
||||
* is "forward" from the current position, then we will
|
||||
* start at the current poisition. Otherwise, we will
|
||||
* "rewind" to the root dir.
|
||||
*/
|
||||
|
||||
inode = idir->fd_root;
|
||||
if ( offset < idir->fd_position )
|
||||
{
|
||||
if (inode->u.i_mops && inode->u.i_mops->rewinddir)
|
||||
{
|
||||
/* Perform the rewinddir() operation */
|
||||
|
||||
inode->u.i_mops->rewinddir(inode, idir);
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can't do the seek and there is no way to return
|
||||
* an error indication.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = idir->fd_position;
|
||||
}
|
||||
|
||||
/* This is a brute force approach... we will just read
|
||||
* directory entries until we are at the desired position.
|
||||
*/
|
||||
|
||||
while (pos < offset)
|
||||
{
|
||||
if (!inode->u.i_mops || !inode->u.i_mops->readdir ||
|
||||
inode->u.i_mops->readdir(inode, idir) < 0)
|
||||
{
|
||||
/* We can't read the next entry and there is no way to return
|
||||
* an error indication.
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Increment the position on each successful read */
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
/* If we get here the the directory position has been successfully set */
|
||||
|
||||
idir->fd_position = pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************
|
||||
* Public Functions
|
||||
************************************************************/
|
||||
|
@ -132,7 +203,7 @@ void seekdir(FAR DIR *dirp, off_t offset)
|
|||
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
if (!idir || !idir->fd_root)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -141,13 +212,15 @@ void seekdir(FAR DIR *dirp, off_t offset)
|
|||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
if (INODE_IS_MOUNTPT(idir->fd_root))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
|
||||
#warning "Mountpoint support not implemented"
|
||||
seekmountptdir(idir, offset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* The node is part of the root psuedo file system */
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ off_t telldir(FAR DIR *dirp)
|
|||
{
|
||||
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||
|
||||
if (!idir || !idir->root)
|
||||
if (!idir || !idir->fd_root)
|
||||
{
|
||||
*get_errno_ptr() = EBADF;
|
||||
return (off_t)-1;
|
||||
|
@ -86,7 +86,7 @@ off_t telldir(FAR DIR *dirp)
|
|||
|
||||
/* Just return the current position */
|
||||
|
||||
return idir->position;
|
||||
return idir->fd_position;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -176,4 +177,5 @@ int umount(const char *target)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -130,4 +131,5 @@ int unlink(const char *pathname)
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "fs_internal.h"
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
|
@ -82,4 +83,5 @@ STATUS unregister_blockdriver(const char *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
#endif
|
||||
|
|
|
@ -79,6 +79,7 @@ struct file_operations
|
|||
|
||||
/* This structure provides information about the state of a block driver */
|
||||
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
struct geometry
|
||||
{
|
||||
boolean geo_available; /* TRUE: The device is vailable */
|
||||
|
@ -114,6 +115,7 @@ struct block_operations
|
|||
*/
|
||||
|
||||
struct inode;
|
||||
struct internal_dir_s;
|
||||
struct mountpt_operations
|
||||
{
|
||||
/* The mountpoint open method differs from the driver open method
|
||||
|
@ -148,6 +150,9 @@ struct mountpt_operations
|
|||
/* Directory operations */
|
||||
|
||||
int (*opendir)(struct inode *mountpt, const char *relpath, struct internal_dir_s *dir);
|
||||
int (*closedir)(struct inode *mountpt, struct internal_dir_s *dir);
|
||||
int (*readdir)(struct inode *mountpt, struct internal_dir_s *dir);
|
||||
int (*rewinddir)(struct inode *mountpt, struct internal_dir_s *dir);
|
||||
|
||||
/* General volume-related mountpoint operations: */
|
||||
|
||||
|
@ -163,6 +168,7 @@ struct mountpt_operations
|
|||
* file stat(), file attributes, file truncation, etc.
|
||||
*/
|
||||
};
|
||||
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||
|
||||
/* This structure represents one inode in the Nuttx psuedo-file system */
|
||||
|
||||
|
@ -175,8 +181,10 @@ struct inode
|
|||
union
|
||||
{
|
||||
const struct file_operations *i_ops; /* Driver operations for inode */
|
||||
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||
const struct block_operations *i_bops; /* Block driver operations */
|
||||
const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
|
||||
#endif
|
||||
} u;
|
||||
#ifdef CONFIG_FILE_MODE
|
||||
mode_t i_mode; /* Access mode flags */
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include "os_internal.h"
|
||||
#include "clock_internal.h"
|
||||
#include "pthread_internal.h"
|
||||
|
||||
/************************************************************
|
||||
|
|
|
@ -236,6 +236,12 @@ int main(int argc, char **argv, char **envp)
|
|||
printf("# undef CONFIG_STDIO_BUFFER_SIZE\n");
|
||||
printf("# define CONFIG_STDIO_BUFFER_SIZE 0\n");
|
||||
printf("#endif\n\n");
|
||||
printf("/* If mountpoint support in not included, then no filesystem can\n");
|
||||
printf(" * be supported.\n");
|
||||
printf(" */\n\n");
|
||||
printf("#ifdef CONFIG_DISABLE_MOUNTPOINT\n");
|
||||
printf("# undef CONFIG_FS_FAT\n");
|
||||
printf("#endif\n\n");
|
||||
printf("/* Verbose debug only makes sense if debug is enabled */\n\n");
|
||||
printf("#ifndef CONFIG_DEBUG\n");
|
||||
printf("# undef CONFIG_DEBUG_VERBOSE\n");
|
||||
|
|
Loading…
Reference in New Issue