summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/fs_fat32.c2
-rw-r--r--nuttx/fs/fs_internal.h22
-rw-r--r--nuttx/fs/fs_opendir.c174
-rw-r--r--nuttx/fs/fs_readdir.c28
4 files changed, 122 insertions, 104 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index adb6c47b6..633695fd1 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -1262,7 +1262,7 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct intern
/* This is not the root directory. Verify that it is some kind of directory */
- else if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY)
+ else if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) == 0)
{
/* The entry is not a directory */
ret = -ENOTDIR;
diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h
index 432344515..8bfc52f21 100644
--- a/nuttx/fs/fs_internal.h
+++ b/nuttx/fs/fs_internal.h
@@ -69,6 +69,13 @@
#define INODE_SET_MOUNTPT(i) \
((i)->i_flags = (((i)->i_flags & ~FSNODEFLAG_TYPE_MASK) | FSNODEFLAG_TYPE_MOUNTPT))
+/* Mountpoint fd_flags values */
+
+#define DIRENTFLAGS_PSUEDONODE 1
+
+#define DIRENT_SETPSUEDONODE(f) do (f) |= DIRENTFLAGS_PSUEDONODE; while (0)
+#define DIRENT_ISPSUEDONODE(f) (((f) & DIRENTFLAGS_PSUEDONODE) != 0)
+
/****************************************************************************
* Public Types
****************************************************************************/
@@ -87,7 +94,7 @@ struct fs_psuedodir_s
struct inode *fd_next; /* The inode for the next call to readdir() */
};
-#ifdef CONFIG_FS_FAT
+#if defined(CONFIG_FS_FAT) && !defined(CONFIG_DISABLE_MOUNTPOINT)
/* For fat, we need to retun the start cluster, current cluster, current
* sector and current directory index.
*/
@@ -113,6 +120,12 @@ struct internal_dir_s
struct inode *fd_root;
+ /* At present, only mountpoints require special handling flags */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ unsigned int fd_flags;
+#endif
+
/* This keeps track of the current directory position for telldir */
off_t fd_position;
@@ -125,10 +138,17 @@ struct internal_dir_s
union
{
+ /* Private data used by the built-in psuedo-file system */
+
struct fs_psuedodir_s psuedo;
+
+ /* Private data used by other file systems */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
#ifdef CONFIG_FS_FAT
struct fs_fatdir_s fat;
#endif
+#endif
} u;
/* In any event, this the actual struct dirent that is returned by readdir */
diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c
index 6791195a2..58a1f4bb2 100644
--- a/nuttx/fs/fs_opendir.c
+++ b/nuttx/fs/fs_opendir.c
@@ -51,81 +51,6 @@
************************************************************/
/************************************************************
- * Name: fs_finddirnode
- *
- * Description:
- * This is called from the opendir() logic to get a reference
- * to the inode associated with a directory. There are no
- * real directories in this design; For our purposes, a
- * directory inode is simply one that has children or one
- * that is a mountpoint for a "real" file system
- *
- ************************************************************/
-
-static inline FAR struct inode *fs_finddirnode(const char *path, const char **relpath)
-{
- FAR struct inode *node;
- FAR struct inode *root = NULL;
-
- /* If we are given 'nothing' then we will interpret this as
- * request for the root inode.
- */
-
- if (!path || *path == 0 || strcmp(path, "/") == 0)
- {
- return root_inode;
- }
-
- /* We don't know what to do with relative pathes */
-
- if (*path != '/')
- {
- return NULL;
- }
-
- /* Find the node matching the path. */
-
- inode_semtake();
- node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, relpath);
- if (node)
- {
-
- /* Is this a not in the psuedo filesystem? */
-
- if (INODE_IS_MOUNTPT(node))
- {
- /* Yes, then return the inode itself as the 'root' of
- * the directory. The actually directory is at relpath into the
- * mounted filesystem. Increment the count of references
- * on the inode.
- */
-
- root = node;
- root->i_crefs++;
- }
- else
- {
- /* It is a node in the psuedo filesystem. Does the inode have a child?
- * If so that the child would be the 'root' of a list of nodes under
- * the directory.
- */
-
- root = node->i_child;
- if (root)
- {
- /* If found, then increment the count of
- * references on the child node.
- */
-
- root->i_crefs++;
- }
- }
- }
- inode_semgive();
- return root;
-}
-
-/************************************************************
* Public Functions
************************************************************/
@@ -161,22 +86,45 @@ static inline FAR struct inode *fs_finddirnode(const char *path, const char **re
FAR DIR *opendir(const char *path)
{
- FAR struct inode *inode;
+ FAR struct inode *inode = NULL;
FAR struct internal_dir_s *dir;
const char *relpath;
+ boolean isroot = FALSE;
int ret;
- /* Get an inode corresponding to the path. On successful
- * return, we will hold on reference count on the inode.
+ /* If we are given 'nothing' then we will interpret this as
+ * request for the root inode.
*/
- inode = fs_finddirnode(path, &relpath);
+ if (!path || *path == 0 || strcmp(path, "/") == 0)
+ {
+ inode_semgive();
+ inode = root_inode;
+ isroot = TRUE;
+ }
+ else
+ {
+ /* We don't know what to do with relative pathes */
+
+ if (*path != '/')
+ {
+ return NULL;
+ }
+
+ /* Find the node matching the path. */
+
+ inode_semtake();
+ inode = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, &relpath);
+ }
+
+ /* Did we get an inode? */
+
if (!inode)
{
- /* 'path' is not a directory.*/
+ /* 'path' is not a does not exist.*/
ret = ENOTDIR;
- goto errout;
+ goto errout_with_semaphore;
}
/* Allocate a type DIR -- which is little more than an inode
@@ -189,7 +137,7 @@ FAR DIR *opendir(const char *path)
/* Insufficient memory to complete the operation.*/
ret = ENOMEM;
- goto errout_with_inode;
+ goto errout_with_semaphore;
}
/* Populate the DIR structure and return it to the caller. The way that
@@ -200,20 +148,29 @@ FAR DIR *opendir(const char *path)
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? */
+ /* Is this a node in the psuedo filesystem? Or a mountpoint? */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ if (INODE_IS_MOUNTPT(inode))
+ {
+ /* Yes, then return the inode itself as the 'root' of
+ * the directory. The actually directory is at relpath into the
+ * mounted filesystem.
+ */
-#ifndef CONFIG_DISABLE_MOUNTPOUNT
- if (INODE_IS_MOUNTPT(inode))
- {
/* The node is a file system mointpoint. Verify that the mountpoint
- * supports the opendir() method
- */
+ * supports the opendir() method
+ */
if (!inode->u.i_mops || !inode->u.i_mops->opendir)
- {
+ {
ret = ENOSYS;
goto errout_with_direntry;
- }
+ }
+
+ /* Take reference to the mountpoint inode (fd_root) */
+
+ inode_addref(inode);
/* Perform the opendir() operation */
@@ -221,27 +178,52 @@ FAR DIR *opendir(const char *path)
if (ret < 0)
{
ret = -ret;
- goto errout_with_direntry;
+ goto errout_with_inode;
}
}
else
#endif
{
- /* The node is part of the root psuedo file system */
+ /* The node is part of the root psuedo file system. Does the inode have a child?
+ * If so that the child would be the 'root' of a list of nodes under
+ * the directory.
+ */
+
+ if (!isroot)
+ {
+ inode = inode->i_child;
+ if (!inode)
+ {
+ ret = ENOTDIR;
+ goto errout_with_direntry;
+ }
+ }
- inode_addref(inode); /* Now we have two references on inode */
+ /* It looks we have a valid psuedo-filesystem node. Take two references
+ * on the inode -- one for the parent (fd_root) and one for the child (fd_next).
+ */
+
+ inode_addref(inode);
+ inode_addref(inode);
dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */
+
+ /* Flag the inode as belonging to the psuedo-filesystem */
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ DIRENT_SETPSUEDONODE(dir->fd_flags);
+#endif
}
+ inode_semgive();
return ((DIR*)dir);
/* Nasty goto's make error handling simpler */
-errout_with_direntry:
- free(dir);
errout_with_inode:
inode_release(inode);
-errout:
+errout_with_direntry:
+ free(dir);
+errout_with_semaphore:
+ inode_semgive();
*get_errno_ptr() = ret;
return NULL;
}
diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c
index 6cb3eb099..0c15d04e9 100644
--- a/nuttx/fs/fs_readdir.c
+++ b/nuttx/fs/fs_readdir.c
@@ -82,7 +82,20 @@ static inline int readpsuedodir(struct internal_dir_s *idir)
idir->fd_dir.d_type = 0;
if (idir->u.psuedo.fd_next->u.i_ops)
{
- idir->fd_dir.d_type |= DTYPE_FILE;
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ if (INODE_IS_BLOCK(idir->u.psuedo.fd_next))
+ {
+ idir->fd_dir.d_type |= DTYPE_BLK;
+ }
+ if (INODE_IS_MOUNTPT(idir->u.psuedo.fd_next))
+ {
+ idir->fd_dir.d_type |= DTYPE_DIRECTORY;
+ }
+ else
+#endif
+ {
+ idir->fd_dir.d_type |= DTYPE_CHR;
+ }
}
/* If the node has child node(s), then we will say that it
@@ -147,7 +160,9 @@ static inline int readpsuedodir(struct internal_dir_s *idir)
FAR struct dirent *readdir(DIR *dirp)
{
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+#ifndef CONFIG_DISABLE_MOUNTPOINT
struct inode *inode;
+#endif
int ret;
/* Sanity checks */
@@ -162,8 +177,9 @@ FAR struct dirent *readdir(DIR *dirp)
* that we are dealing with.
*/
+#ifndef CONFIG_DISABLE_MOUNTPOINT
inode = idir->fd_root;
- if (INODE_IS_MOUNTPT(inode))
+ if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSUEDONODE(idir->fd_flags))
{
/* The node is a file system mointpoint. Verify that the mountpoint
* supports the readdir() method
@@ -172,7 +188,7 @@ FAR struct dirent *readdir(DIR *dirp)
if (!inode->u.i_mops || !inode->u.i_mops->readdir)
{
ret = EACCES;
- goto errout;
+ goto errout;
}
/* Perform the readdir() operation */
@@ -180,10 +196,10 @@ FAR struct dirent *readdir(DIR *dirp)
ret = inode->u.i_mops->readdir(inode, idir);
}
else
+#endif
{
- /* The node is part of the root psuedo file system, release
- * our contained reference to the 'next' inode.
- */
+ /* The node is part of the root psuedo file system */
+
ret = readpsuedodir(idir);
}