mirror of
https://github.com/apache/nuttx.git
synced 2026-06-01 07:45:16 +08:00
Finish FAT directory operations; add option to disable mountpoints; fix ARM compile errors
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@252 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -143,5 +143,9 @@
|
|||||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||||
* Added FAT support for unlink(), mkdir(), rmdir(), and rename
|
* 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
|
* Started m68322
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<tr align="center" bgcolor="#e4e4e4">
|
<tr align="center" bgcolor="#e4e4e4">
|
||||||
<td>
|
<td>
|
||||||
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -574,6 +574,10 @@ Other memory:
|
|||||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||||
* Added FAT support for unlink(), mkdir(), rmdir(), and rename()
|
* 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
|
* Started m68322
|
||||||
</pre></ul>
|
</pre></ul>
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</b></big>
|
</b></big>
|
||||||
<p><small>by</small></p>
|
<p><small>by</small></p>
|
||||||
<p>Gregory Nutt</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>
|
||||||
|
|
||||||
<center><h1>Table of Contents</h1></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>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFI_DISABLE_POSIX_TIMERS</code>, <code>CONFIG_DISABLE_PTHREAD</code>,
|
<code>CONFIG_DISABLE_CLOCK</code>, <code>CONFI_DISABLE_POSIX_TIMERS</code>,
|
||||||
<code>CONFIG_DISABLE_SIGNALS</code>, <code>CONFIG_DISABLE_MQUEUE</code>,
|
<code>CONFIG_DISABLE_PTHREAD</code>, <code>CONFIG_DISABLE_SIGNALS</code>,
|
||||||
|
<code>CONFIG_DISABLE_MQUEUE</code>, <code>CONFIG_DISABLE_MOUNTPOUNT</code>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Miscellaneous libc settings</h2>
|
<h2>Miscellaneous libc settings</h2>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
|
#include "clock_internal.h"
|
||||||
#include "up_internal.h"
|
#include "up_internal.h"
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
|
|||||||
+1
-1
@@ -159,7 +159,7 @@ defconfig -- This is a configuration file similar to the Linux
|
|||||||
up waiting tasks.
|
up waiting tasks.
|
||||||
|
|
||||||
CONFIG_DISABLE_CLOCK, CONFIG_DISABLE_POSIX_TIMERS, CONFIG_DISABLE_PTHREAD.
|
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
|
Misc libc settings
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||||||
CONFIG_DISABLE_PTHREAD=n
|
CONFIG_DISABLE_PTHREAD=n
|
||||||
CONFIG_DISABLE_SIGNALS=n
|
CONFIG_DISABLE_SIGNALS=n
|
||||||
CONFIG_DISABLE_MQUEUE=n
|
CONFIG_DISABLE_MQUEUE=n
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||||||
CONFIG_DISABLE_PTHREAD=n
|
CONFIG_DISABLE_PTHREAD=n
|
||||||
CONFIG_DISABLE_SIGNALS=n
|
CONFIG_DISABLE_SIGNALS=n
|
||||||
CONFIG_DISABLE_MQUEUE=n
|
CONFIG_DISABLE_MQUEUE=n
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||||||
CONFIG_DISABLE_PTHREAD=n
|
CONFIG_DISABLE_PTHREAD=n
|
||||||
CONFIG_DISABLE_SIGNALS=n
|
CONFIG_DISABLE_SIGNALS=n
|
||||||
CONFIG_DISABLE_MQUEUE=n
|
CONFIG_DISABLE_MQUEUE=n
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||||||
CONFIG_DISABLE_PTHREAD=n
|
CONFIG_DISABLE_PTHREAD=n
|
||||||
CONFIG_DISABLE_SIGNALS=n
|
CONFIG_DISABLE_SIGNALS=n
|
||||||
CONFIG_DISABLE_MQUEUE=n
|
CONFIG_DISABLE_MQUEUE=n
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
@@ -143,6 +143,7 @@ CONFIG_DISABLE_POSIX_TIMERS=y
|
|||||||
CONFIG_DISABLE_PTHREAD=y
|
CONFIG_DISABLE_PTHREAD=y
|
||||||
CONFIG_DISABLE_SIGNALS=y
|
CONFIG_DISABLE_SIGNALS=y
|
||||||
CONFIG_DISABLE_MQUEUE=y
|
CONFIG_DISABLE_MQUEUE=y
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ CONFIG_DISABLE_POSIX_TIMERS=n
|
|||||||
CONFIG_DISABLE_PTHREAD=n
|
CONFIG_DISABLE_PTHREAD=n
|
||||||
CONFIG_DISABLE_SIGNALS=n
|
CONFIG_DISABLE_SIGNALS=n
|
||||||
CONFIG_DISABLE_MQUEUE=n
|
CONFIG_DISABLE_MQUEUE=n
|
||||||
|
CONFIG_DISABLE_MOUNTPOINT=n
|
||||||
|
|
||||||
#
|
#
|
||||||
# Misc libc settings
|
# Misc libc settings
|
||||||
|
|||||||
+5
-2
@@ -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_seekdir.c fs_telldir.c fs_rewinddir.c fs_fsync.c fs_files.c \
|
||||||
fs_inode.c fs_inodefind.c fs_inodereserve.c \
|
fs_inode.c fs_inodefind.c fs_inodereserve.c \
|
||||||
fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.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_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)
|
ifeq ($(CONFIG_FS_FAT),y)
|
||||||
CSRCS += fs_fat32.c fs_fat32util.c
|
CSRCS += fs_fat32.c fs_fat32util.c
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||||
|
|
||||||
SRCS = $(ASRCS) $(CSRCS)
|
SRCS = $(ASRCS) $(CSRCS)
|
||||||
|
|||||||
+27
-10
@@ -76,8 +76,12 @@
|
|||||||
int closedir(FAR DIR *dirp)
|
int closedir(FAR DIR *dirp)
|
||||||
{
|
{
|
||||||
struct internal_dir_s *idir = (struct internal_dir_s *)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;
|
*get_errno_ptr() = EBADF;
|
||||||
return ERROR;
|
return ERROR;
|
||||||
@@ -87,31 +91,44 @@ int closedir(FAR DIR *dirp)
|
|||||||
* inode we have open.
|
* 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"
|
if (inode->u.i_mops && inode->u.i_mops->closedir)
|
||||||
*get_errno_ptr() = ENOSYS;
|
{
|
||||||
return ERROR;
|
/* Perform the closedir() operation */
|
||||||
|
|
||||||
|
ret = inode->u.i_mops->closedir(inode, idir);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
*get_errno_ptr() = -ret;
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* The node is part of the root psuedo file system, release
|
/* The node is part of the root psuedo file system, release
|
||||||
* our contained reference to the 'next' inode.
|
* 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 */
|
/* 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 */
|
/* Then release the container */
|
||||||
|
|||||||
+174
-11
@@ -59,7 +59,8 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
#include "fs_fat32.h"
|
#include "fs_fat32.h"
|
||||||
|
|
||||||
#if CONFIG_FS_FAT
|
#ifdef CONFIG_FS_FAT
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -85,6 +86,8 @@ static int fat_sync(FAR struct file *filp);
|
|||||||
|
|
||||||
static int fat_opendir(struct inode *mountpt, const char *relpath,
|
static int fat_opendir(struct inode *mountpt, const char *relpath,
|
||||||
struct internal_dir_s *dir);
|
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,
|
static int fat_bind(FAR struct inode *blkdriver, const void *data,
|
||||||
void **handle);
|
void **handle);
|
||||||
@@ -120,6 +123,9 @@ const struct mountpt_operations fat_operations =
|
|||||||
fat_sync,
|
fat_sync,
|
||||||
|
|
||||||
fat_opendir,
|
fat_opendir,
|
||||||
|
NULL,
|
||||||
|
fat_readdir,
|
||||||
|
fat_rewinddir,
|
||||||
|
|
||||||
fat_bind,
|
fat_bind,
|
||||||
fat_unbind,
|
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 */
|
/* Save information that can be used later to recover the directory entry */
|
||||||
|
|
||||||
ff->ff_dirsector = fs->fs_currentsector;
|
ff->ff_dirsector = fs->fs_currentsector;
|
||||||
ff->ff_dirindex = dirinfo.fd_index;
|
ff->ff_dirindex = dirinfo.dir.fd_index;
|
||||||
|
|
||||||
/* File cluster/size info */
|
/* 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 */
|
/* Handler the FAT12/16 root directory */
|
||||||
|
|
||||||
dir->u.fat.startcluster = 0;
|
dir->u.fat.fd_startcluster = 0;
|
||||||
dir->u.fat.currcluster = 0;
|
dir->u.fat.fd_currcluster = 0;
|
||||||
dir->u.fat.currsector = fs->fs_rootbase;
|
dir->u.fat.fd_currsector = fs->fs_rootbase;
|
||||||
dir->u.fat.dirindex = 2;
|
dir->u.fat.fd_index = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is not the root directory. Verify that it is some kind of directory */
|
/* 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 */
|
/* The entry is a directory */
|
||||||
|
|
||||||
dir->u.fat.startcluster =
|
dir->u.fat.fd_startcluster =
|
||||||
((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||||
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||||
dir->u.fat.currcluster = dir->u.fat.startcluster;
|
dir->u.fat.fd_currcluster = dir->u.fat.fd_startcluster;
|
||||||
dir->u.fat.currsector = fat_cluster2sector(fs, dir->u.fat.currcluster);
|
dir->u.fat.fd_currsector = fat_cluster2sector(fs, dir->u.fat.fd_currcluster);
|
||||||
dir->u.fat.dirindex = 2;
|
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);
|
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_PUTFSTCLUSTHI(direntry, dircluster >> 16);
|
||||||
DIR_PUTFSTCLUSTLO(direntry, dircluster);
|
DIR_PUTFSTCLUSTLO(direntry, dircluster);
|
||||||
|
|
||||||
parentcluster = dirinfo.fd_startcluster;
|
parentcluster = dirinfo.dir.fd_startcluster;
|
||||||
if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase)
|
if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase)
|
||||||
{
|
{
|
||||||
parentcluster = 0;
|
parentcluster = 0;
|
||||||
@@ -1833,4 +1995,5 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_FS_FAT */
|
#endif /* CONFIG_FS_FAT */
|
||||||
|
|||||||
+4
-5
@@ -492,10 +492,7 @@ struct fat_dirinfo_s
|
|||||||
#ifdef CONFIG_FAT_LCNAMES
|
#ifdef CONFIG_FAT_LCNAMES
|
||||||
ubyte fd_ntflags; /* NTRes lower case flags */
|
ubyte fd_ntflags; /* NTRes lower case flags */
|
||||||
#endif
|
#endif
|
||||||
uint16 fd_index; /* Current index */
|
struct fs_fatdir_s dir; /* Used with opendir, readdir, etc. */
|
||||||
size_t fd_startcluster; /* Start cluster number */
|
|
||||||
size_t fd_currcluster; /* Current cluster number */
|
|
||||||
size_t fd_currsector; /* Current sector */
|
|
||||||
ubyte *fd_entry; /* A pointer to the raw 32-byte entry */
|
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 */
|
/* 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,
|
EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||||
const char *path);
|
const char *path);
|
||||||
EXTERN int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
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 */
|
/* File creation and removal helpers */
|
||||||
|
|
||||||
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||||
|
|||||||
+149
-145
@@ -57,7 +57,8 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
#include "fs_fat32.h"
|
#include "fs_fat32.h"
|
||||||
|
|
||||||
#if CONFIG_FS_FAT
|
#ifdef CONFIG_FS_FAT
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -252,113 +253,6 @@ static inline int fat_path2dirname(const char **path, struct fat_dirinfo_s *diri
|
|||||||
return -EINVAL;
|
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
|
* 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 cluster;
|
||||||
unsigned int ndx;
|
unsigned int ndx;
|
||||||
|
|
||||||
/* Increment the index to the next 32-byte directory entry */
|
/* 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
|
/* Check if all of the directory entries in this sectory have
|
||||||
* been examined.
|
* 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 */
|
/* 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
|
/* For FAT12/16, the root directory is a group of sectors relative
|
||||||
* to the first sector of the fat volume.
|
* 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
|
/* For FAT12/13, the boot record tells us number of 32-bit directories
|
||||||
* that are contained in the root directory. This should correspond to
|
* 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 */
|
/* Get next cluster */
|
||||||
|
|
||||||
cluster = fat_getcluster(fs, dirinfo->fd_currcluster);
|
cluster = fat_getcluster(fs, dir->fd_currcluster);
|
||||||
|
|
||||||
/* Check if a valid cluster was obtained. */
|
/* 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 */
|
/* Initialize for new cluster */
|
||||||
|
|
||||||
dirinfo->fd_currcluster = cluster;
|
dir->fd_currcluster = cluster;
|
||||||
dirinfo->fd_currsector = fat_cluster2sector(fs, 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;
|
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.
|
* the first cluster of the root directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dirinfo->fd_startcluster = cluster;
|
dirinfo->dir.fd_startcluster = cluster;
|
||||||
dirinfo->fd_currcluster = cluster;
|
dirinfo->dir.fd_currcluster = cluster;
|
||||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||||
}
|
}
|
||||||
else
|
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.
|
* relative to the first sector of the fat volume.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dirinfo->fd_startcluster = 0;
|
dirinfo->dir.fd_startcluster = 0;
|
||||||
dirinfo->fd_currcluster = 0;
|
dirinfo->dir.fd_currcluster = 0;
|
||||||
dirinfo->fd_currsector = cluster;
|
dirinfo->dir.fd_currsector = cluster;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fd_index is the index into the current directory table */
|
/* 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
|
/* If no path was provided, then the root directory must be exactly
|
||||||
* what the caller is looking for.
|
* 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 */
|
/* Read the next sector into memory */
|
||||||
|
|
||||||
ret = fat_fscacheread(fs, dirinfo->fd_currsector);
|
ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
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 */
|
/* 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 */
|
/* 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 */
|
/* No... get the next directory index and try again */
|
||||||
|
|
||||||
if (fat_nextdirentry(fs, dirinfo) != OK)
|
if (fat_nextdirentry(fs, &dirinfo->dir) != OK)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
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 */
|
/* The restart scanning at the new directory */
|
||||||
|
|
||||||
dirinfo->fd_currcluster = dirinfo->fd_startcluster = cluster;
|
dirinfo->dir.fd_currcluster = dirinfo->dir.fd_startcluster = cluster;
|
||||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||||
dirinfo->fd_index = 2;
|
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 */
|
/* Re-initialize directory object */
|
||||||
|
|
||||||
cluster = dirinfo->fd_startcluster;
|
cluster = dirinfo->dir.fd_startcluster;
|
||||||
if (cluster)
|
if (cluster)
|
||||||
{
|
{
|
||||||
/* Cluster chain can be extended */
|
/* Cluster chain can be extended */
|
||||||
|
|
||||||
dirinfo->fd_currcluster = cluster;
|
dirinfo->dir.fd_currcluster = cluster;
|
||||||
dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
|
dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Fixed size FAT12/16 root directory is at fixxed offset/size */
|
/* 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 (;;)
|
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 */
|
/* 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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
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 */
|
/* 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];
|
direntry = &fs->fs_buffer[dirindex];
|
||||||
|
|
||||||
/* Check if this directory entry is empty */
|
/* 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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fat_nextdirentry(fs, dirinfo);
|
ret = fat_nextdirentry(fs, &dirinfo->dir);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
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 */
|
/* 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)
|
if (cluster < 0)
|
||||||
{
|
{
|
||||||
return cluster;
|
return cluster;
|
||||||
@@ -1773,6 +1667,115 @@ int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo
|
|||||||
return OK;
|
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
|
* Name: fat_dirtruncate
|
||||||
*
|
*
|
||||||
@@ -1955,9 +1958,9 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
|||||||
* sub-directory is empty
|
* sub-directory is empty
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dirinfo.fd_currcluster = dircluster;
|
dirinfo.dir.fd_currcluster = dircluster;
|
||||||
dirinfo.fd_currsector = fat_cluster2sector(fs, dircluster);
|
dirinfo.dir.fd_currsector = fat_cluster2sector(fs, dircluster);
|
||||||
dirinfo.fd_index = 2;
|
dirinfo.dir.fd_index = 2;
|
||||||
|
|
||||||
/* Loop until either (1) an entry is found in the directory
|
/* Loop until either (1) an entry is found in the directory
|
||||||
* (error), (2) the directory is found to be empty, or (3) some
|
* (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
|
* subdirectory sector is in the cache
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ret = fat_fscacheread(fs, dirinfo.fd_currsector);
|
ret = fat_fscacheread(fs, dirinfo.dir.fd_currsector);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
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 */
|
/* 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];
|
subdirentry = &fs->fs_buffer[subdirindex];
|
||||||
|
|
||||||
/* Is this the last entry in the direcory? */
|
/* 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 */
|
/* Get the next directgory entry */
|
||||||
|
|
||||||
ret = fat_nextdirentry(fs, &dirinfo);
|
ret = fat_nextdirentry(fs, &dirinfo.dir);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2313,4 +2316,5 @@ int fat_updatefsinfo(struct fat_mountpt_s *fs)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_FS_FAT */
|
#endif /* CONFIG_FS_FAT */
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -137,4 +138,5 @@ int fsync(int fd)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOINT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
+31
-26
@@ -73,10 +73,34 @@
|
|||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* The internal representation of type DIR is just a
|
/* The internal representation of type DIR is just a container for an inode
|
||||||
* container for an inode reference and a dirent structure.
|
* 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
|
struct internal_dir_s
|
||||||
{
|
{
|
||||||
/* This is the node that was opened by opendir. The type of the inode
|
/* 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).
|
* 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 */
|
/* 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
|
/* Retained control information depends on the type of file system that
|
||||||
* provides is provides the mountpoint. Ideally this information should
|
* provides is provides the mountpoint. Ideally this information should
|
||||||
@@ -101,34 +125,15 @@ struct internal_dir_s
|
|||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
/* For the root psuedo-file system, we need retain only the 'next' inode
|
struct fs_psuedodir_s psuedo;
|
||||||
* 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;
|
|
||||||
|
|
||||||
#ifdef CONFIG_FS_FAT
|
#ifdef CONFIG_FS_FAT
|
||||||
/* For fat, we need to retun the start cluster, current cluster, current
|
struct fs_fatdir_s fat;
|
||||||
* 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;
|
|
||||||
#endif
|
#endif
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
/* In any event, this the actual struct dirent that is returned by readdir */
|
/* 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"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -130,4 +131,5 @@ int mkdir(const char *pathname, mode_t mode)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/* At least one filesystem must be defined, or this file will not compile.
|
/* At least one filesystem must be defined, or this file will not compile.
|
||||||
* It may be desire-able to make filesystems dynamically registered at
|
* 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 /* Need at least filesystem */
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* Need file descriptor support */
|
#endif /* Need file descriptor support */
|
||||||
|
|||||||
@@ -153,12 +153,14 @@ int open(const char *path, int oflags, ...)
|
|||||||
ret = OK;
|
ret = OK;
|
||||||
if (inode->u.i_ops->open)
|
if (inode->u.i_ops->open)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
if (INODE_IS_MOUNTPT(inode))
|
if (INODE_IS_MOUNTPT(inode))
|
||||||
{
|
{
|
||||||
ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
|
ret = inode->u.i_mops->open((FAR struct file*)&list->fl_files[fd],
|
||||||
relpath, oflags, mode);
|
relpath, oflags, mode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
|
ret = inode->u.i_ops->open((FAR struct file*)&list->fl_files[fd]);
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-4
@@ -197,11 +197,12 @@ FAR DIR *opendir(const char *path)
|
|||||||
* inode or a file system mountpoint.
|
* inode or a file system mountpoint.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dir->root = inode; /* Save the inode where we start */
|
dir->fd_root = inode; /* Save the inode where we start */
|
||||||
dir->position = 0; /* This is the position in the read stream */
|
dir->fd_position = 0; /* This is the position in the read stream */
|
||||||
|
|
||||||
/* Is this a not in the psuedo filesystem? */
|
/* Is this a not in the psuedo filesystem? */
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
if (INODE_IS_MOUNTPT(inode))
|
if (INODE_IS_MOUNTPT(inode))
|
||||||
{
|
{
|
||||||
/* The node is a file system mointpoint. Verify that the mountpoint
|
/* The node is a file system mointpoint. Verify that the mountpoint
|
||||||
@@ -224,11 +225,12 @@ FAR DIR *opendir(const char *path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* The node is part of the root psuedo file system */
|
/* The node is part of the root psuedo file system */
|
||||||
|
|
||||||
inode_addref(inode); /* Now we have two references on inode */
|
inode_addref(inode); /* Now we have two references on inode */
|
||||||
dir->u.psuedo.next = inode; /* This is the next node to use for readdir() */
|
dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((DIR*)dir);
|
return ((DIR*)dir);
|
||||||
|
|||||||
+65
-25
@@ -53,52 +53,59 @@
|
|||||||
* Name: readpsuedodir
|
* 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;
|
FAR struct inode *prev;
|
||||||
|
|
||||||
/* Check if we are at the end of the list */
|
/* 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 */
|
/* 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
|
/* If the node has file operations, we will say that it is
|
||||||
* a file.
|
* a file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
idir->dir.d_type = 0;
|
idir->fd_dir.d_type = 0;
|
||||||
if (idir->u.psuedo.next->u.i_ops)
|
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
|
/* If the node has child node(s), then we will say that it
|
||||||
* is a directory. NOTE: that the node can be both!
|
* 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 */
|
/* Now get the inode to vist next time that readdir() is called */
|
||||||
|
|
||||||
inode_semtake();
|
inode_semtake();
|
||||||
|
|
||||||
prev = idir->u.psuedo.next;
|
prev = idir->u.psuedo.fd_next;
|
||||||
idir->u.psuedo.next = prev->i_peer; /* The next node to visit */
|
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 */
|
/* Increment the reference count on this next node */
|
||||||
|
|
||||||
idir->u.psuedo.next->i_crefs++;
|
idir->u.psuedo.fd_next->i_crefs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_semgive();
|
inode_semgive();
|
||||||
@@ -108,7 +115,7 @@ static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
|
|||||||
inode_release(prev);
|
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 dirent *readdir(DIR *dirp)
|
||||||
{
|
{
|
||||||
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||||
|
struct inode *inode;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
if (!idir || !idir->root)
|
if (!idir || !idir->fd_root)
|
||||||
{
|
{
|
||||||
*get_errno_ptr() = EBADF;
|
ret = EBADF;
|
||||||
return NULL;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The way we handle the readdir depends on the type of inode
|
/* The way we handle the readdir depends on the type of inode
|
||||||
* that we are dealing with.
|
* 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"
|
if (!inode->u.i_mops || !inode->u.i_mops->readdir)
|
||||||
*get_errno_ptr() = ENOSYS;
|
{
|
||||||
return NULL;
|
ret = EACCES;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform the readdir() operation */
|
||||||
|
|
||||||
|
ret = inode->u.i_mops->readdir(inode, idir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The node is part of the root psuedo file system, release
|
/* The node is part of the root psuedo file system, release
|
||||||
* our contained reference to the 'next' inode.
|
* 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 */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
#include <nuttx/fs.h>
|
#include <nuttx/fs.h>
|
||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/************************************************************
|
/************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
@@ -98,3 +100,5 @@ STATUS register_blockdriver(const char *path,
|
|||||||
inode_semgive();
|
inode_semgive();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -154,4 +155,5 @@ int rename(const char *oldpath, const char *newpath)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
+25
-8
@@ -48,6 +48,10 @@
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* Name: rewindpsuedodir
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
|
||||||
static inline void rewindpsuedodir(struct internal_dir_s *idir)
|
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 */
|
/* Reset the position to the beginning */
|
||||||
|
|
||||||
prev = idir->u.psuedo.next; /* (Save to delete later) */
|
prev = idir->u.psuedo.fd_next; /* (Save to delete later) */
|
||||||
idir->u.psuedo.next = idir->root; /* The next node to visit */
|
idir->u.psuedo.fd_next = idir->fd_root; /* The next node to visit */
|
||||||
idir->position = 0; /* Reset position */
|
idir->fd_position = 0; /* Reset position */
|
||||||
|
|
||||||
/* Increment the reference count on the root=next node. We
|
/* Increment the reference count on the root=next node. We
|
||||||
* should now have two references on the inode.
|
* should now have two references on the inode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
idir->root->i_crefs++;
|
idir->fd_root->i_crefs++;
|
||||||
inode_semgive();
|
inode_semgive();
|
||||||
|
|
||||||
/* Then release the reference to the old next inode */
|
/* 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)
|
void rewinddir(FAR DIR *dirp)
|
||||||
{
|
{
|
||||||
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
struct inode *inode;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
if (!idir || !idir->root)
|
if (!idir || !idir->fd_root)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -112,13 +119,23 @@ void rewinddir(FAR DIR *dirp)
|
|||||||
* that we are dealing with.
|
* 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
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* The node is part of the root psuedo file system */
|
/* The node is part of the root psuedo file system */
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -130,4 +131,5 @@ int rmdir(const char *pathname)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
+83
-10
@@ -50,6 +50,10 @@
|
|||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
* Name: seekpsuedodir
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
||||||
{
|
{
|
||||||
struct inode *curr;
|
struct inode *curr;
|
||||||
@@ -62,15 +66,15 @@ static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset)
|
|||||||
* "rewind" to the root dir.
|
* "rewind" to the root dir.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( offset < idir->position )
|
if ( offset < idir->fd_position )
|
||||||
{
|
{
|
||||||
pos = 0;
|
pos = 0;
|
||||||
curr = idir->root;
|
curr = idir->fd_root;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pos = idir->position;
|
pos = idir->fd_position;
|
||||||
curr = idir->u.psuedo.next;
|
curr = idir->u.psuedo.fd_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Traverse the peer list starting at the 'root' of the
|
/* 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 */
|
/* Now get the inode to vist next time that readdir() is called */
|
||||||
|
|
||||||
prev = idir->u.psuedo.next;
|
prev = idir->u.psuedo.fd_next;
|
||||||
idir->u.psuedo.next = curr; /* The next node to visit (might be null) */
|
idir->u.psuedo.fd_next = curr; /* The next node to visit (might be null) */
|
||||||
idir->position = pos; /* Might be beyond the last dirent */
|
idir->fd_position = pos; /* Might be beyond the last dirent */
|
||||||
|
|
||||||
if (curr)
|
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
|
* Public Functions
|
||||||
************************************************************/
|
************************************************************/
|
||||||
@@ -132,7 +203,7 @@ void seekdir(FAR DIR *dirp, off_t offset)
|
|||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
|
|
||||||
if (!idir || !idir->root)
|
if (!idir || !idir->fd_root)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -141,13 +212,15 @@ void seekdir(FAR DIR *dirp, off_t offset)
|
|||||||
* that we are dealing with.
|
* 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 */
|
/* The node is a file system mointpoint */
|
||||||
|
|
||||||
#warning "Mountpoint support not implemented"
|
seekmountptdir(idir, offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* The node is part of the root psuedo file system */
|
/* The node is part of the root psuedo file system */
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -78,7 +78,7 @@ off_t telldir(FAR DIR *dirp)
|
|||||||
{
|
{
|
||||||
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||||
|
|
||||||
if (!idir || !idir->root)
|
if (!idir || !idir->fd_root)
|
||||||
{
|
{
|
||||||
*get_errno_ptr() = EBADF;
|
*get_errno_ptr() = EBADF;
|
||||||
return (off_t)-1;
|
return (off_t)-1;
|
||||||
@@ -86,7 +86,7 @@ off_t telldir(FAR DIR *dirp)
|
|||||||
|
|
||||||
/* Just return the current position */
|
/* Just return the current position */
|
||||||
|
|
||||||
return idir->position;
|
return idir->fd_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -176,4 +177,5 @@ int umount(const char *target)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -130,4 +131,5 @@ int unlink(const char *pathname)
|
|||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
#endif /* CONFIG_NFILE_DESCRIPTORS */
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "fs_internal.h"
|
#include "fs_internal.h"
|
||||||
|
|
||||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
@@ -82,4 +83,5 @@ STATUS unregister_blockdriver(const char *path)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ struct file_operations
|
|||||||
|
|
||||||
/* This structure provides information about the state of a block driver */
|
/* This structure provides information about the state of a block driver */
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_MOUNTPOUNT
|
||||||
struct geometry
|
struct geometry
|
||||||
{
|
{
|
||||||
boolean geo_available; /* TRUE: The device is vailable */
|
boolean geo_available; /* TRUE: The device is vailable */
|
||||||
@@ -114,6 +115,7 @@ struct block_operations
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct inode;
|
struct inode;
|
||||||
|
struct internal_dir_s;
|
||||||
struct mountpt_operations
|
struct mountpt_operations
|
||||||
{
|
{
|
||||||
/* The mountpoint open method differs from the driver open method
|
/* The mountpoint open method differs from the driver open method
|
||||||
@@ -148,6 +150,9 @@ struct mountpt_operations
|
|||||||
/* Directory operations */
|
/* Directory operations */
|
||||||
|
|
||||||
int (*opendir)(struct inode *mountpt, const char *relpath, struct internal_dir_s *dir);
|
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: */
|
/* General volume-related mountpoint operations: */
|
||||||
|
|
||||||
@@ -163,6 +168,7 @@ struct mountpt_operations
|
|||||||
* file stat(), file attributes, file truncation, etc.
|
* file stat(), file attributes, file truncation, etc.
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
#endif /* CONFIG_DISABLE_MOUNTPOUNT */
|
||||||
|
|
||||||
/* This structure represents one inode in the Nuttx psuedo-file system */
|
/* This structure represents one inode in the Nuttx psuedo-file system */
|
||||||
|
|
||||||
@@ -175,8 +181,10 @@ struct inode
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
const struct file_operations *i_ops; /* Driver operations for inode */
|
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 block_operations *i_bops; /* Block driver operations */
|
||||||
const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
|
const struct mountpt_operations *i_mops; /* Operations on a mountpoint */
|
||||||
|
#endif
|
||||||
} u;
|
} u;
|
||||||
#ifdef CONFIG_FILE_MODE
|
#ifdef CONFIG_FILE_MODE
|
||||||
mode_t i_mode; /* Access mode flags */
|
mode_t i_mode; /* Access mode flags */
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include <nuttx/kmalloc.h>
|
#include <nuttx/kmalloc.h>
|
||||||
#include <nuttx/arch.h>
|
#include <nuttx/arch.h>
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
|
#include "clock_internal.h"
|
||||||
#include "pthread_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("# undef CONFIG_STDIO_BUFFER_SIZE\n");
|
||||||
printf("# define CONFIG_STDIO_BUFFER_SIZE 0\n");
|
printf("# define CONFIG_STDIO_BUFFER_SIZE 0\n");
|
||||||
printf("#endif\n\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("/* Verbose debug only makes sense if debug is enabled */\n\n");
|
||||||
printf("#ifndef CONFIG_DEBUG\n");
|
printf("#ifndef CONFIG_DEBUG\n");
|
||||||
printf("# undef CONFIG_DEBUG_VERBOSE\n");
|
printf("# undef CONFIG_DEBUG_VERBOSE\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user