summaryrefslogtreecommitdiff
path: root/nuttx
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-19 09:21:38 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-19 09:21:38 -0600
commita056eba87db4299725e9c64a9869735a1400c1be (patch)
tree3f4abc5bb49579be9f477f818dccbd0bdcfe587f /nuttx
parent5966aacdb7c3fa6f7ecaca6ae08d6ed2e6f7fee9 (diff)
downloadnuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.gz
nuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.bz2
nuttx-a056eba87db4299725e9c64a9869735a1400c1be.zip
FS: directory operations will now work on empty directory nodes in the pseudo-filesystem
Diffstat (limited to 'nuttx')
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/fs/fs_closedir.c73
-rw-r--r--nuttx/fs/fs_opendir.c91
-rw-r--r--nuttx/fs/fs_readdir.c37
-rw-r--r--nuttx/fs/fs_rewinddir.c9
-rw-r--r--nuttx/fs/fs_rmdir.c4
-rw-r--r--nuttx/fs/fs_seekdir.c9
7 files changed, 158 insertions, 68 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 9fb44c59e..69437b887 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -6607,4 +6607,7 @@
kconfig-frontends tools by Alan Carvalho de Assis (2014-2-18).
* configs/mbed: All mbed configurations have been converted to use
the kconfig-frontends tools (unverified) (2014-2-18).
+ * fs/fs_opendir.c, fs_readdir.c, et al: Modified so that errors
+ will not be reported if you attempt to list a empty pseudo-directory
+ (2014-2-18).
diff --git a/nuttx/fs/fs_closedir.c b/nuttx/fs/fs_closedir.c
index 6aeed03a5..f6b6edcf3 100644
--- a/nuttx/fs/fs_closedir.c
+++ b/nuttx/fs/fs_closedir.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_closedir.c
*
- * Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -81,57 +81,68 @@ int closedir(FAR DIR *dirp)
#endif
int ret;
- if (!idir || !idir->fd_root)
+ /* Verify that we were provided with a valid directory structure */
+
+ if (!idir)
{
ret = EBADF;
goto errout;
}
- /* This is the 'root' inode of the directory. This means different
- * things wih different filesystems.
+ /* A special case is when we enumerate an "empty", unused inode. That is
+ * an inode in the pseudo-filesystem that has no operations and no children.
+ * This is a "dangling" directory entry that has lost its childre.
*/
-#ifndef CONFIG_DISABLE_MOUNTPOINT
- inode = idir->fd_root;
+ if (idir->fd_root)
+ {
+ /* This is the 'root' inode of the directory. This means different
+ * things wih different filesystems.
+ */
- /* The way that we handle the close operation depends on what kind of root
- * inode we have open.
- */
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ inode = idir->fd_root;
- if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags))
- {
- /* The node is a file system mointpoint. Verify that the mountpoint
- * supports the closedir() method (not an error if it does not)
+ /* The way that we handle the close operation depends on what kind of
+ * root inode we have open.
*/
- if (inode->u.i_mops && inode->u.i_mops->closedir)
+ if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags))
{
- /* Perform the closedir() operation */
+ /* The node is a file system mointpoint. Verify that the
+ * mountpoint supports the closedir() method (not an error if it
+ * does not)
+ */
- ret = inode->u.i_mops->closedir(inode, idir);
- if (ret < 0)
+ if (inode->u.i_mops && inode->u.i_mops->closedir)
{
- ret = -ret;
- goto errout_with_inode;
+ /* Perform the closedir() operation */
+
+ ret = inode->u.i_mops->closedir(inode, idir);
+ if (ret < 0)
+ {
+ ret = -ret;
+ goto errout_with_inode;
+ }
}
}
- }
- else
+ else
#endif
- {
- /* The node is part of the root pseudo file system, release
- * our contained reference to the 'next' inode.
- */
-
- if (idir->u.pseudo.fd_next)
{
- inode_release(idir->u.pseudo.fd_next);
+ /* The node is part of the root pseudo file system, release
+ * our contained reference to the 'next' inode.
+ */
+
+ if (idir->u.pseudo.fd_next)
+ {
+ inode_release(idir->u.pseudo.fd_next);
+ }
}
- }
- /* Release our references on the contained 'root' inode */
+ /* Release our references on the contained 'root' inode */
- inode_release(idir->fd_root);
+ inode_release(idir->fd_root);
+ }
/* Then release the container */
diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c
index c1f44a9d1..46421c37e 100644
--- a/nuttx/fs/fs_opendir.c
+++ b/nuttx/fs/fs_opendir.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_opendir.c
*
- * Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -89,8 +89,8 @@ static inline int open_mountpoint(FAR struct inode *inode,
return ENOSYS;
}
- /* Take reference to the mountpoint inode (fd_root). Note that we do
- * not use inode_addref() because we already hold the tree semaphore.
+ /* Take reference to the mountpoint inode. Note that we do not use
+ * inode_addref() because we already hold the tree semaphore.
*/
inode->i_crefs++;
@@ -132,7 +132,7 @@ static inline int open_mountpoint(FAR struct inode *inode,
* dir -- the dirent structure to be initialized
*
* Return:
- * On success, OK is returned; Otherwise, a positive errno is returned.
+ * None
*
****************************************************************************/
@@ -144,7 +144,8 @@ static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir)
* semaphore and that would result in deadlock.
*/
- inode->i_crefs += 2;
+ inode->i_crefs += 2;
+ dir->fd_root = inode; /* Save the inode where we start */
dir->u.pseudo.fd_next = inode; /* This is the next node to use for readdir() */
/* Flag the inode as belonging to the pseudo-filesystem */
@@ -155,6 +156,43 @@ static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir)
}
/****************************************************************************
+ * Name: open_emptydir
+ *
+ * Description:
+ * Handle the case where the inode to be opened is an empty, directory node
+ * within the top-level pseudo-file system. That is, it has no operations
+ * and, therefore, it must be a directory node. But is has no children
+ * to be enumerated either.
+ *
+ * Inputs:
+ * dir -- the dirent structure to be initialized
+ *
+ * Return:
+ * None
+ *
+ ****************************************************************************/
+
+static inline void open_emptydir(FAR struct fs_dirent_s *dir)
+{
+ /* We have a valid, but empty pseudo-filesystem node. fd_next is NULL
+ * meaning that we are already at the end of the list of its children.
+ * fd_root is NULL so that if the directory is rewound, it will still be
+ * at the end of the list.
+ */
+
+#if 0 /* Already nullified by kuzalloc */
+ dir->fd_root = NULL; /* Save the inode where we start */
+ dir->u.pseudo.fd_next = NULL; /* We are at the end of the list */
+#endif
+
+ /* Flag the inode as belonging to the pseudo-filesystem */
+
+#ifndef CONFIG_DISABLE_MOUNTPOINT
+ DIRENT_SETPSEUDONODE(dir->fd_flags);
+#endif
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -189,7 +227,7 @@ FAR DIR *opendir(FAR const char *path)
FAR struct inode *inode = NULL;
FAR struct fs_dirent_s *dir;
FAR const char *relpath;
- bool bisroot = false;
+ bool isroot = false;
int ret;
/* If we are given 'nothing' then we will interpret this as
@@ -200,7 +238,7 @@ FAR DIR *opendir(FAR const char *path)
if (!path || *path == 0 || strcmp(path, "/") == 0)
{
inode = root_inode;
- bisroot = true;
+ isroot = true;
relpath = NULL;
}
else
@@ -246,14 +284,13 @@ FAR DIR *opendir(FAR const char *path)
* inode or a file system mountpoint.
*/
- dir->fd_root = inode; /* Save the inode where we start */
dir->fd_position = 0; /* This is the position in the read stream */
/* First, handle the special case of the root inode. This must be
* special-cased here because the root inode might ALSO be a mountpoint.
*/
- if (bisroot)
+ if (isroot)
{
/* Whatever payload the root inode carries, the root inode is always
* a directory inode in the pseudo-file system
@@ -263,13 +300,17 @@ FAR DIR *opendir(FAR const char *path)
}
/* Is this a node in the pseudo filesystem? Or a mountpoint? If the node
- * is the root (bisroot == TRUE), then this is a special case.
+ * is the root (isroot == TRUE), then this is a special case.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
else if (INODE_IS_MOUNTPT(inode))
{
- /* Yes, the node is a file system mointpoint. */
+ /* Yes, the node is a file system mountpoint */
+
+ dir->fd_root = inode; /* Save the inode where we start */
+
+ /* Open the directory at the relative path */
ret = open_mountpoint(inode, relpath, dir);
if (ret != OK)
@@ -280,21 +321,31 @@ FAR DIR *opendir(FAR const char *path)
#endif
else
{
- /* The node is part of the root pseudo 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.
+ /* The node is part of the root pseudo 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.
*/
- inode = inode->i_child;
- if (!inode)
+ FAR struct inode *child = inode->i_child;
+ if (child)
+ {
+ /* It looks we have a valid pseudo-filesystem directory node. */
+
+ open_pseudodir(child, dir);
+ }
+ else if (!inode->u.i_ops)
+ {
+ /* This is a dangling node with no children and no operations. Set
+ * up to enumerate an empty directory.
+ */
+
+ open_emptydir(dir);
+ }
+ else
{
ret = ENOTDIR;
goto errout_with_direntry;
}
-
- /* It looks we have a valid pseudo-filesystem directory node. */
-
- open_pseudodir(inode, dir);
}
inode_semgive();
diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c
index f5b266392..11e23d9b1 100644
--- a/nuttx/fs/fs_readdir.c
+++ b/nuttx/fs/fs_readdir.c
@@ -84,11 +84,11 @@ static inline int readpseudodir(struct fs_dirent_s *idir)
if (idir->u.pseudo.fd_next->u.i_ops)
{
#ifndef CONFIG_DISABLE_MOUNTPOINT
- if (INODE_IS_BLOCK(idir->u.pseudo.fd_next))
+ if (INODE_IS_BLOCK(idir->u.pseudo.fd_next))
{
idir->fd_dir.d_type |= DTYPE_BLK;
}
- if (INODE_IS_MOUNTPT(idir->u.pseudo.fd_next))
+ if (INODE_IS_MOUNTPT(idir->u.pseudo.fd_next))
{
idir->fd_dir.d_type |= DTYPE_DIRECTORY;
}
@@ -99,8 +99,9 @@ static inline int readpseudodir(struct fs_dirent_s *idir)
}
}
- /* If the node has child node(s), then we will say that it
- * is a directory. NOTE: that the node can be both!
+ /* If the node has child node(s) or no operations, then we will say that
+ * it is a directory rather than a special file. NOTE: that the node can
+ * be both!
*/
if (idir->u.pseudo.fd_next->i_child || !idir->u.pseudo.fd_next->u.i_ops)
@@ -160,25 +161,38 @@ static inline int readpseudodir(struct fs_dirent_s *idir)
FAR struct dirent *readdir(DIR *dirp)
{
FAR struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
-#ifndef CONFIG_DISABLE_MOUNTPOINT
struct inode *inode;
-#endif
int ret;
- /* Sanity checks */
+ /* Verify that we were provided with a valid directory structure */
- if (!idir || !idir->fd_root)
+ if (!idir)
{
ret = EBADF;
goto errout;
}
+ /* A special case is when we enumerate an "empty", unused inode. That is
+ * an inode in the pseudo-filesystem that has no operations and no children.
+ * This is a "dangling" directory entry that has lost its children.
+ */
+
+ inode = idir->fd_root;
+ if (!inode)
+ {
+ /* End of file and error conditions are not distinguishable
+ * with readdir. We return NULL to signal either case.
+ */
+
+ ret = OK;
+ goto errout;
+ }
+
/* The way we handle the readdir depends on the type of inode
* that we are dealing with.
*/
#ifndef CONFIG_DISABLE_MOUNTPOINT
- inode = idir->fd_root;
if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSEUDONODE(idir->fd_flags))
{
/* The node is a file system mointpoint. Verify that the mountpoint
@@ -188,7 +202,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 */
@@ -205,7 +219,7 @@ FAR struct dirent *readdir(DIR *dirp)
/* ret < 0 is an error. Special case: ret = -ENOENT is end of file */
- if ( ret < 0)
+ if (ret < 0)
{
if (ret == -ENOENT)
{
@@ -215,6 +229,7 @@ FAR struct dirent *readdir(DIR *dirp)
{
ret = -ret;
}
+
goto errout;
}
diff --git a/nuttx/fs/fs_rewinddir.c b/nuttx/fs/fs_rewinddir.c
index c22c15f18..879b66363 100644
--- a/nuttx/fs/fs_rewinddir.c
+++ b/nuttx/fs/fs_rewinddir.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_rewinddir.c
*
- * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -109,7 +109,12 @@ void rewinddir(FAR DIR *dirp)
struct inode *inode;
#endif
- /* Sanity checks */
+ /* Verify that we were provided with a valid directory structure,
+ * A special case is when we enumerate an "empty", unused inode (fd_root
+ * == 0). That is an inode in the pseudo-filesystem that has no
+ * operations and no children. This is a "dangling" directory entry that
+ * has lost its children.
+ */
if (!idir || !idir->fd_root)
{
diff --git a/nuttx/fs/fs_rmdir.c b/nuttx/fs/fs_rmdir.c
index 6c64de5cf..317d7cc42 100644
--- a/nuttx/fs/fs_rmdir.c
+++ b/nuttx/fs/fs_rmdir.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_rmdir.c
*
- * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -111,7 +111,7 @@ int rmdir(FAR const char *pathname)
}
}
else
- {
+ {
ret = ENOSYS;
goto errout_with_inode;
}
diff --git a/nuttx/fs/fs_seekdir.c b/nuttx/fs/fs_seekdir.c
index 781d35f27..c49acef57 100644
--- a/nuttx/fs/fs_seekdir.c
+++ b/nuttx/fs/fs_seekdir.c
@@ -1,7 +1,7 @@
/****************************************************************************
* fs/fs_seekdir.c
*
- * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008, 2011, 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -202,7 +202,12 @@ void seekdir(FAR DIR *dirp, off_t offset)
{
struct fs_dirent_s *idir = (struct fs_dirent_s *)dirp;
- /* Sanity checks */
+ /* Verify that we were provided with a valid directory structure,
+ * A special case is when we enumerate an "empty", unused inode (fd_root
+ * == 0). That is an inode in the pseudo-filesystem that has no
+ * operations and no children. This is a "dangling" directory entry that
+ * has lost its children.
+ */
if (!idir || !idir->fd_root)
{