summaryrefslogtreecommitdiff
path: root/nuttx/fs/fs_opendir.c
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/fs/fs_opendir.c
parent5966aacdb7c3fa6f7ecaca6ae08d6ed2e6f7fee9 (diff)
downloadpx4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.gz
px4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.bz2
px4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.zip
FS: directory operations will now work on empty directory nodes in the pseudo-filesystem
Diffstat (limited to 'nuttx/fs/fs_opendir.c')
-rw-r--r--nuttx/fs/fs_opendir.c91
1 files changed, 71 insertions, 20 deletions
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();