summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/Makefile5
-rw-r--r--nuttx/fs/fs_closedir.c105
-rw-r--r--nuttx/fs/fs_inode.c419
-rw-r--r--nuttx/fs/fs_inodeaddref.c83
-rw-r--r--nuttx/fs/fs_inodefind.c96
-rw-r--r--nuttx/fs/fs_inodefinddir.c110
-rw-r--r--nuttx/fs/fs_inoderelease.c103
-rw-r--r--nuttx/fs/fs_internal.h36
-rw-r--r--nuttx/fs/fs_open.c5
-rw-r--r--nuttx/fs/fs_opendir.c126
-rw-r--r--nuttx/fs/fs_readdir.c145
-rw-r--r--nuttx/fs/fs_readdirr.c123
-rw-r--r--nuttx/fs/fs_registerinode.c222
-rw-r--r--nuttx/fs/fs_rewinddir.c101
-rw-r--r--nuttx/fs/fs_seekdir.c117
-rw-r--r--nuttx/fs/fs_telldir.c106
-rw-r--r--nuttx/fs/fs_unregisterinode.c155
17 files changed, 1715 insertions, 342 deletions
diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile
index b7d09a4e9..8c57d6129 100644
--- a/nuttx/fs/Makefile
+++ b/nuttx/fs/Makefile
@@ -41,7 +41,10 @@ ASRCS =
AOBJS = $(ASRCS:.S=$(OBJEXT))
CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \
- fs_files.c fs_inode.c
+ fs_opendir.c fs_closedir.c fs_readdir.c fs_readdirr.c \
+ fs_seekdir.c fs_telldir.c fs_rewinddir.c fs_files.c \
+ fs_inode.c fs_inodefind.c fs_inodefinddir.c fs_registerinode.c \
+ fs_unregisterinode.c fs_inodeaddref.c fs_inoderelease.c
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
diff --git a/nuttx/fs/fs_closedir.c b/nuttx/fs/fs_closedir.c
new file mode 100644
index 000000000..cf22902af
--- /dev/null
+++ b/nuttx/fs/fs_closedir.c
@@ -0,0 +1,105 @@
+/************************************************************
+ * fs_closedir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: seekdir
+ *
+ * Description:
+ * The closedir() function closes the directory stream
+ * associated with 'dirp'. The directory stream
+ * descriptor 'dirp' is not available after this call.
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ *
+ * Return:
+ * The closedir() function returns 0 on success. On error,
+ * -1 is returned, and errno is set appropriately.
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+int closedir(FAR DIR *dirp)
+{
+ struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+ off_t i;
+
+ if (!idir)
+ {
+ *get_errno_ptr() = EBADF;
+ return ERROR;
+ }
+
+ /* Release our references on the contained inodes */
+
+ if (idir->root)
+ {
+ inode_release(idir->root);
+ }
+
+ if (idir->next)
+ {
+ inode_release(idir->next);
+ }
+
+ /* Then release the container */
+
+ free(idir);
+ return OK;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_inode.c b/nuttx/fs/fs_inode.c
index c6d673190..10936c8be 100644
--- a/nuttx/fs/fs_inode.c
+++ b/nuttx/fs/fs_inode.c
@@ -34,10 +34,6 @@
************************************************************/
/************************************************************
- * Compilation Switches
- ************************************************************/
-
-/************************************************************
* Included Files
************************************************************/
@@ -56,9 +52,6 @@
* Definitions
************************************************************/
-#define INODE_SEMGIVE() \
- sem_post(&tree_sem)
-
/************************************************************
* Private Variables
************************************************************/
@@ -75,21 +68,9 @@ FAR struct inode *root_inode = NULL;
* Private Functions
************************************************************/
-static void _inode_semtake(void)
-{
- /* Take the semaphore (perhaps waiting) */
-
- while (sem_wait(&tree_sem) != 0)
- {
- /* The only case that an error should occr here is if
- * the wait was awakened by a signal.
- */
-
- ASSERT(*get_errno_ptr() == EINTR);
- }
-}
-
-#define _inode_semgive(void) sem_post(&tree_sem)
+/************************************************************
+ * Name: _inode_compare
+ ************************************************************/
static int _inode_compare(const char *fname,
FAR struct inode *node)
@@ -152,49 +133,79 @@ static int _inode_compare(const char *fname,
}
}
-static int _inode_namelen(const char *name)
-{
- const char *tmp = name;
- while(*tmp && *tmp != '/') tmp++;
- return tmp - name;
-}
+/************************************************************
+ * Public Functions
+ ************************************************************/
-static void _inode_namecpy(char *dest, const char *src)
-{
- while(*src && *src != '/') *dest++ = *src++;
- *dest='\0';
-}
+/************************************************************
+ * Name: fs_initialize
+ *
+ * Description:
+ * This is called from the OS initialization logic to configure
+ * the file system.
+ *
+ ************************************************************/
-static const char *_inode_nextname(const char *name)
+void fs_initialize(void)
{
- while (*name && *name != '/') name++;
- if (*name) name++;
- return name;
+ /* Initialize the semaphore to one (to support one-at-
+ * a-time access to the inode tree).
+ */
+
+ (void)sem_init(&tree_sem, 0, 1);
+
+ /* Initialize files array (if it is used) */
+
+#ifdef CONFIG_HAVE_WEAKFUNCTIONS
+ if (files_initialize != NULL)
+#endif
+ {
+ files_initialize();
+ }
}
-static FAR struct inode *_inode_alloc(const char *name,
- struct file_operations *fops,
- mode_t mode, void *private)
+/************************************************************
+ * Name: inode_semtake
+ ************************************************************/
+
+void inode_semtake(void)
{
- int namelen = _inode_namelen(name);
- FAR struct inode *node = (FAR struct inode*)malloc(FSNODE_SIZE(namelen));
- if (node)
+ /* Take the semaphore (perhaps waiting) */
+
+ while (sem_wait(&tree_sem) != 0)
{
- node->i_peer = NULL;
- node->i_child = NULL;
- node->i_ops = fops;
-#ifdef CONFIG_FILE_MODE
- node->i_mode = mode;
-#endif
- node->i_private = private;
- _inode_namecpy(node->i_name, name);
+ /* The only case that an error should occr here is if
+ * the wait was awakened by a signal.
+ */
+
+ ASSERT(*get_errno_ptr() == EINTR);
}
- return node;
}
-static FAR struct inode *_inode_find(const char **path,
- FAR struct inode **peer,
- FAR struct inode **parent)
+/************************************************************
+ * Name: inode_semgive
+ ************************************************************/
+
+void inode_semgive(void)
+{
+ sem_post(&tree_sem);
+}
+
+/************************************************************
+ * Name: inode_search
+ *
+ * Description:
+ * Find the inode associated with 'path' returning the
+ * inode references and references to its companion nodes.
+ *
+ * Assumptions:
+ * The caller holds the tree_sem
+ *
+ ************************************************************/
+
+FAR struct inode *inode_search(const char **path,
+ FAR struct inode **peer,
+ FAR struct inode **parent)
{
const char *name = *path + 1; /* Skip over leading '/' */
FAR struct inode *node = root_inode;
@@ -237,7 +248,7 @@ static FAR struct inode *_inode_find(const char **path,
* (2) the node we are looking for is "blow" this one.
*/
- name = _inode_nextname(name);
+ name = inode_nextname(name);
if (!*name)
{
/* We are at the end of the path, so this must be
@@ -278,296 +289,32 @@ static FAR struct inode *_inode_find(const char **path,
return node;
}
-static void _inode_insert(FAR struct inode *node,
- FAR struct inode *peer,
- FAR struct inode *parent)
-{
- /* If peer is non-null, then new node simply goes to the right
- * of that peer node.
- */
-
- if (peer)
- {
- node->i_peer = peer->i_peer;
- peer->i_peer = node;
- }
-
- /* If parent is non-null, then it must go at the head of its
- * list of children.
- */
-
- else if (parent)
- {
- node->i_peer = parent->i_child;
- parent->i_child = node;
- }
-
- /* Otherwise, this must be the new root_inode */
-
- else
- {
- node->i_peer = root_inode;
- root_inode = node;
- }
-}
-
-static void _inode_remove(struct inode *node,
- struct inode *peer,
- struct inode *parent)
-{
- /* If peer is non-null, then remove the node from the right of
- * of that peer node.
- */
-
- if (peer)
- {
- peer->i_peer = node->i_peer;
- }
-
- /* If parent is non-null, then remove the node from head of
- * of the list of children.
- */
-
- else if (parent)
- {
- parent->i_child = node->i_peer;
- }
-
- /* Otherwise, we must be removing the root inode. */
-
- else
- {
- root_inode = node->i_peer;
- }
- node->i_peer = NULL;
-}
+/************************************************************
+ * Name: inode_free
+ ************************************************************/
-static void _inode_free(FAR struct inode *node)
+void inode_free(FAR struct inode *node)
{
if (node)
{
- _inode_free(node->i_peer);
- _inode_free(node->i_child);
+ inode_free(node->i_peer);
+ inode_free(node->i_child);
free(node);
}
}
/************************************************************
- * Public Functions
+ * Name: inode_nextname
+ *
+ * Description:
+ * Given a path with node names separated by '/', return
+ * the next node name.
+ *
************************************************************/
-/* This is called from the OS initialization logic to configure
- * the file system.
- */
-
-void fs_initialize(void)
+const char *inode_nextname(const char *name)
{
- /* Initialize the semaphore to one (to support one-at-
- * a-time access to the inode tree).
- */
-
- (void)sem_init(&tree_sem, 0, 1);
-
- /* Initialize files array (if it is used) */
-
-#ifdef CONFIG_HAVE_WEAKFUNCTIONS
- if (files_initialize != NULL)
-#endif
- {
- files_initialize();
- }
-}
-
-/* This is called from the open() logic to get a reference
- * to the inode associatged with a path.
- */
-
-FAR struct inode *inode_find(const char *path)
-{
- FAR struct inode *node;
-
- if (!*path || path[0] != '/')
- {
- return NULL;
- }
-
- /* Find the node matching the path. If found,
- * increment the count of references on the node.
- */
-
- _inode_semtake();
- node = _inode_find(&path, (FAR void*)NULL, (FAR void*)NULL);
- if (node) node->i_crefs++;
- _inode_semgive();
- return node;
-}
-
-/* Increment the reference count on an inode (as when a file
- * descriptor is dup'ed.
- */
-
-void inode_addref(FAR struct inode *inode)
-{
- if (inode)
- {
- _inode_semtake();
- inode->i_crefs++;
- _inode_semgive();
- }
-}
-
-/* This is called from close() logic when it no longer refers
- * to the inode.
- */
-
-void inode_release(FAR struct inode *node)
-{
- if (node)
- {
- /* Decrement the references of the inode */
-
- _inode_semtake();
- if (node->i_crefs)
- {
- node->i_crefs--;
- }
-
- /* If the subtree was previously deleted and the reference
- * count has decrement to zero, then delete the inode
- * now.
- */
-
- if (node->i_crefs <= 0 && (node->i_flags & FSNODEFLAG_DELETED) != 0)
- {
- _inode_semgive();
- _inode_free(node->i_child);
- free(node);
- }
- else
- {
- _inode_semgive();
- }
- }
-}
-
-
-STATUS register_inode(const char *path,
- struct file_operations *fops,
- mode_t mode, void *private)
-{
- const char *name = path;
- FAR struct inode *left;
- FAR struct inode *parent;
-
- if (!*path || path[0] != '/')
- {
- return ERROR;
- }
-
- /* Find the location to insert the new subtree */
-
- _inode_semtake();
- if (_inode_find(&name, &left, &parent) != NULL)
- {
- /* Is is an error if the node already exists in the tree */
-
- _inode_semgive();
- return ERROR;
- }
-
- /* Now we now where to insert the subtree */
-
- for (;;)
- {
- FAR struct inode *node;
-
- /* Create a new node -- we need to know if this is the
- * the leaf node or some intermediary. We can find this
- * by looking at the next name.
- */
-
- const char *next_name = _inode_nextname(name);
- if (*next_name)
- {
- /* Insert an operationless node */
-
- node = _inode_alloc(name, NULL, mode, NULL);
- if (node)
- {
- _inode_insert(node, left, parent);
-
- /* Set up for the next time through the loop */
-
- name = next_name;
- left = NULL;
- parent = node;
- continue;
- }
- }
- else
- {
- node = _inode_alloc(name, fops, mode, private);
- if (node)
- {
- _inode_insert(node, left, parent);
- _inode_semgive();
- return 0;
- }
- }
-
- /* We get here on failures to allocate node memory */
-
- _inode_semgive();
- return ERROR;
- }
-}
-
-STATUS unregister_inode(const char *path)
-{
- const char *name = path;
- FAR struct inode *node;
- FAR struct inode *left;
- FAR struct inode *parent;
-
- if (*path && path[0] == '/')
- {
- return ERROR;
- }
-
- /* Find the node to delete */
-
- _inode_semtake();
- node = _inode_find(&name, &left, &parent);
- if (node)
- {
- /* Found it, now remove it from the tree */
-
- _inode_remove(node, left, parent);
-
- /* We cannot delete it if there reference to the inode */
-
- if (node->i_crefs)
- {
- /* In that case, we will mark it deleted, when the FS
- * releases the inode, we will then, finally delete
- * the subtree.
- */
-
- node->i_flags |= FSNODEFLAG_DELETED;
- _inode_semgive();
- }
- else
- {
- /* And delete it now -- recursively to delete all of its children */
-
- _inode_semgive();
- _inode_free(node->i_child);
- free(node);
- return OK;
- }
- }
-
- /* The node does not exist or it has references */
- _inode_semgive();
- return ERROR;
+ while (*name && *name != '/') name++;
+ if (*name) name++;
+ return name;
}
diff --git a/nuttx/fs/fs_inodeaddref.c b/nuttx/fs/fs_inodeaddref.c
new file mode 100644
index 000000000..278cf08ab
--- /dev/null
+++ b/nuttx/fs/fs_inodeaddref.c
@@ -0,0 +1,83 @@
+/************************************************************
+ * fs_inodeaddref.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_addref
+ *
+ * Description:
+ * Increment the reference count on an inode (as when a file
+ * descriptor is dup'ed.
+ *
+ ************************************************************/
+
+void inode_addref(FAR struct inode *inode)
+{
+ if (inode)
+ {
+ inode_semtake();
+ inode->i_crefs++;
+ inode_semgive();
+ }
+}
diff --git a/nuttx/fs/fs_inodefind.c b/nuttx/fs/fs_inodefind.c
new file mode 100644
index 000000000..8edd19f08
--- /dev/null
+++ b/nuttx/fs/fs_inodefind.c
@@ -0,0 +1,96 @@
+/************************************************************
+ * fs_inodefind.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_find
+ *
+ * Description:
+ * This is called from the open() logic to get a reference
+ * to the inode associated with a path.
+ *
+ ************************************************************/
+
+FAR struct inode *inode_find(const char *path)
+{
+ FAR struct inode *node;
+
+ if (!*path || path[0] != '/')
+ {
+ return NULL;
+ }
+
+ /* Find the node matching the path. If found,
+ * increment the count of references on the node.
+ */
+
+ inode_semtake();
+ node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL);
+ if (node)
+ {
+ node->i_crefs++;
+ }
+ inode_semgive();
+ return node;
+}
diff --git a/nuttx/fs/fs_inodefinddir.c b/nuttx/fs/fs_inodefinddir.c
new file mode 100644
index 000000000..597d81096
--- /dev/null
+++ b/nuttx/fs/fs_inodefinddir.c
@@ -0,0 +1,110 @@
+/************************************************************
+ * fs_inodefinddir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_finddir
+ *
+ * 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.
+ *
+ ************************************************************/
+
+FAR struct inode *inode_finddir(const char *path)
+{
+ FAR struct inode *node;
+ FAR struct inode *child = NULL;
+
+ if (!*path || path[0] != '/')
+ {
+ return NULL;
+ }
+
+ /* Find the node matching the path. */
+
+ inode_semtake();
+ node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL);
+ if (node)
+ {
+ /* Does the inode have a child? If so that the child
+ * would be the 'head' of a list of nodes under the
+ * directory.
+ */
+
+ child = node->i_child;
+ if (child)
+ {
+ /* If found, then increment the count of
+ * references on the child node.
+ */
+
+ child->i_crefs++;
+ }
+ }
+ inode_semgive();
+ return child;
+}
diff --git a/nuttx/fs/fs_inoderelease.c b/nuttx/fs/fs_inoderelease.c
new file mode 100644
index 000000000..3989a4959
--- /dev/null
+++ b/nuttx/fs/fs_inoderelease.c
@@ -0,0 +1,103 @@
+/************************************************************
+ * fs_inoderelease.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_release
+ *
+ * Description:
+ * This is called from close() logic when it no longer refers
+ * to the inode.
+ *
+ ************************************************************/
+
+void inode_release(FAR struct inode *node)
+{
+ if (node)
+ {
+ /* Decrement the references of the inode */
+
+ inode_semtake();
+ if (node->i_crefs)
+ {
+ node->i_crefs--;
+ }
+
+ /* If the subtree was previously deleted and the reference
+ * count has decrement to zero, then delete the inode
+ * now.
+ */
+
+ if (node->i_crefs <= 0 && (node->i_flags & FSNODEFLAG_DELETED) != 0)
+ {
+ inode_semgive();
+ inode_free(node->i_child);
+ free(node);
+ }
+ else
+ {
+ inode_semgive();
+ }
+ }
+} \ No newline at end of file
diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h
index a063335fb..111f56aae 100644
--- a/nuttx/fs/fs_internal.h
+++ b/nuttx/fs/fs_internal.h
@@ -42,6 +42,7 @@
#include <nuttx/config.h>
#include <nuttx/fs.h>
+#include <dirent.h>
#include <nuttx/compiler.h>
/************************************************************
@@ -54,6 +55,20 @@
* Public Types
************************************************************/
+/* The internal representation of type DIR is just a
+ * container for an inode reference and a dirent structure.
+ */
+
+struct internal_dir_s
+{
+ struct inode *root; /* The start inode (in case we
+ * rewind) */
+ struct inode *next; /* The inode to use for the next call
+ * to readdir() */
+ struct dirent dir; /* Populated using inode when readdir
+ * is called */
+};
+
/************************************************************
* Global Variables
************************************************************/
@@ -74,8 +89,29 @@ extern "C" {
/* fs_inode.c ***********************************************/
+EXTERN void inode_semtake(void);
+EXTERN void inode_semgive(void);
+EXTERN FAR struct inode *inode_search(const char **path,
+ FAR struct inode **peer,
+ FAR struct inode **parent);
+EXTERN void inode_free(FAR struct inode *node);
+EXTERN const char *inode_nextname(const char *name);
+
+
+/* fs_inodefind.c ********************************************/
+
EXTERN FAR struct inode *inode_find(const char *path);
+
+/* fs_inodefinddir.c *****************************************/
+
+EXTERN FAR struct inode *inode_finddir(const char *path);
+
+/* fs_inodeaddref.c ******************************************/
+
EXTERN void inode_addref(FAR struct inode *inode);
+
+/* fs_inoderelease.c *****************************************/
+
EXTERN void inode_release(FAR struct inode *inode);
/* fs_files.c ***********************************************/
diff --git a/nuttx/fs/fs_open.c b/nuttx/fs/fs_open.c
index ac6d39e43..53af359fb 100644
--- a/nuttx/fs/fs_open.c
+++ b/nuttx/fs/fs_open.c
@@ -34,10 +34,6 @@
************************************************************/
/************************************************************
- * Compilation Switches
- ************************************************************/
-
-/************************************************************
* Included Files
************************************************************/
@@ -50,7 +46,6 @@
#include <stdarg.h>
#endif
#include <nuttx/fs.h>
-#include <errno.h>
#include "fs_internal.h"
/************************************************************
diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c
new file mode 100644
index 000000000..810b365fe
--- /dev/null
+++ b/nuttx/fs/fs_opendir.c
@@ -0,0 +1,126 @@
+/************************************************************
+ * fs_opendir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: opendir
+ *
+ * Description:
+ * The opendir() function opens a directory stream
+ * corresponding to the directory name, and returns a
+ * pointer to the directory stream. The stream is
+ * positioned at the first entry in the directory.
+ *
+ * Inputs:
+ * path -- the directory to open
+ *
+ * Return:
+ * The opendir() function returns a pointer to the
+ * directory stream. On error, NULL is returned, and
+ * errno is set appropriately.
+ *
+ * EACCES - Permission denied.
+ * EMFILE - Too many file descriptors in use by process.
+ * ENFILE - Too many files are currently open in the
+ * system.
+ * ENOENT - Directory does not exist, or name is an empty
+ * string.
+ * ENOMEM - Insufficient memory to complete the operation.
+ * ENOTDIR - 'path' is not a directory.
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+FAR DIR *opendir(const char *path)
+{
+ FAR struct inode *inode;
+ FAR struct internal_dir_s *dir;
+
+ /* Get an inode corresponding to the path. On successful
+ * return, we will hold on reference count on the inode.
+ */
+
+ inode = inode_finddir(path);
+ if (!inode)
+ {
+ /* 'path' is not a directory.*/
+
+ *get_errno_ptr() = ENOTDIR;
+ return NULL;
+ }
+
+ /* Allocate a type DIR -- which is little more than an inode
+ * container.
+ */
+
+ dir = (FAR struct internal_dir_s *)zmalloc(sizeof(struct internal_dir_s *));
+ if (!dir)
+ {
+ /* Insufficient memory to complete the operation.*/
+
+ *get_errno_ptr() = ENOMEM;
+ inode_release(inode);
+ return NULL;
+ }
+
+ /* Populate the DIR structure and return it to the caller */
+
+ dir->root = inode; /* Save where we started in case we rewind */
+ inode_addref(inode); /* Now we have two references on inode */
+ dir->next = inode; /* This is the next node to use for readdir() */
+ return ((DIR*)dir);
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c
new file mode 100644
index 000000000..40f4f1747
--- /dev/null
+++ b/nuttx/fs/fs_readdir.c
@@ -0,0 +1,145 @@
+/************************************************************
+ * fs_readdir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: readdir
+ *
+ * Description:
+ * The readdir() function returns a pointer to a dirent
+ * structure representing the next directory entry in the
+ * directory stream pointed to by dir. It returns NULL on
+ * reaching the end-of-file or if an error occurred.
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ *
+ * Return:
+ * The readdir() function returns a pointer to a dirent
+ * structure, or NULL if an error occurs or end-of-file
+ * is reached. On error, errno is set appropriately.
+ *
+ * EBADF - Invalid directory stream descriptor dir
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+FAR struct dirent *readdir(DIR *dirp)
+{
+ FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+ FAR struct inode *prev;
+
+ if (!idir)
+ {
+ *get_errno_ptr() = EBADF;
+ return NULL;
+ }
+
+ /* Check if we are at the end of the list */
+
+ if (!idir->next)
+ {
+ return NULL;
+ }
+
+ /* Copy the inode name into the dirent structure */
+
+ strncpy(idir->dir.d_name, idir->next->i_name, NAME_MAX+1);
+
+ /* If the node has file operations, we will say that it is
+ * a file.
+ */
+
+ idir->dir.d_type = 0;
+ if (idir->next->i_ops)
+ {
+ idir->dir.d_type |= DTYPE_FILE;
+ }
+
+ /* If the node has child node(s), then we will say that it
+ * is a directory. NOTE: that the node can be both!
+ */
+
+ if (idir->next->i_child || !idir->next->i_ops)
+ {
+ idir->dir.d_type |= DTYPE_FILE;
+ }
+
+ /* Now get the inode to vist next time that readdir() is called */
+
+ inode_semtake();
+
+ prev = idir->next;
+ idir->next = prev->i_peer; /* The next node to visit */
+
+ if (idir->next)
+ {
+ /* Increment the reference count on this next node */
+
+ idir->next->i_crefs++;
+ }
+
+ inode_semgive();
+
+ if (prev)
+ {
+ inode_release(prev);
+ }
+
+ return &idir->dir;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_readdirr.c b/nuttx/fs/fs_readdirr.c
new file mode 100644
index 000000000..930856041
--- /dev/null
+++ b/nuttx/fs/fs_readdirr.c
@@ -0,0 +1,123 @@
+/************************************************************
+ * fs_readdirr.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: readdir_r
+ *
+ * Description:
+ * The readdir() function returns a pointer to a dirent
+ * structure representing the next directory entry in the
+ * directory stream pointed to by dir. It returns NULL on
+ * reaching the end-of-file or if an error occurred.
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ * entry -- The storage pointed to by entry must be large
+ * enough for a dirent with an array of char d_name
+ * members containing at least {NAME_MAX}+1 elements.
+ * result -- Upon successful return, the pointer returned
+ * at *result shall have the same value as the
+ * argument entry. Upon reaching the end of the directory
+ * stream, this pointer shall have the value NULL.
+ *
+ * Return:
+ * If successful, the readdir_r() function return s zero;
+ * otherwise, an error number is returned to indicate the
+ * error.
+ *
+ * EBADF - Invalid directory stream descriptor dir
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+int readdir_r(FAR DIR *dirp, FAR struct dirent *entry,
+ FAR struct dirent **result)
+{
+ struct dirent *tmp;
+
+ *get_errno_ptr() = 0;
+ tmp = readdir(dirp);
+ if (!tmp)
+ {
+ int error = *get_errno_ptr();
+ if (!error)
+ {
+ if (result)
+ {
+ *result = NULL;
+ }
+ return 0;
+ }
+ else
+ {
+ return error;
+ }
+ }
+
+ if (entry)
+ {
+ memcpy(entry, tmp, sizeof(struct dirent));
+ }
+
+ if (result)
+ {
+ *result = entry;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_registerinode.c b/nuttx/fs/fs_registerinode.c
new file mode 100644
index 000000000..395959422
--- /dev/null
+++ b/nuttx/fs/fs_registerinode.c
@@ -0,0 +1,222 @@
+/************************************************************
+ * fs_registerinode.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_namelen
+ ************************************************************/
+
+static int inode_namelen(const char *name)
+{
+ const char *tmp = name;
+ while(*tmp && *tmp != '/') tmp++;
+ return tmp - name;
+}
+
+/************************************************************
+ * Name: inode_namecpy
+ ************************************************************/
+
+static void inode_namecpy(char *dest, const char *src)
+{
+ while(*src && *src != '/') *dest++ = *src++;
+ *dest='\0';
+}
+
+/************************************************************
+ * Name: inode_alloc
+ ************************************************************/
+
+static FAR struct inode *inode_alloc(const char *name,
+ struct file_operations *fops,
+ mode_t mode, void *private)
+{
+ int namelen = inode_namelen(name);
+ FAR struct inode *node = (FAR struct inode*)malloc(FSNODE_SIZE(namelen));
+ if (node)
+ {
+ node->i_peer = NULL;
+ node->i_child = NULL;
+ node->i_ops = fops;
+#ifdef CONFIG_FILE_MODE
+ node->i_mode = mode;
+#endif
+ node->i_private = private;
+ inode_namecpy(node->i_name, name);
+ }
+ return node;
+}
+
+/************************************************************
+ * Name: inode_insert
+ ************************************************************/
+
+static void inode_insert(FAR struct inode *node,
+ FAR struct inode *peer,
+ FAR struct inode *parent)
+{
+ /* If peer is non-null, then new node simply goes to the right
+ * of that peer node.
+ */
+
+ if (peer)
+ {
+ node->i_peer = peer->i_peer;
+ peer->i_peer = node;
+ }
+
+ /* If parent is non-null, then it must go at the head of its
+ * list of children.
+ */
+
+ else if (parent)
+ {
+ node->i_peer = parent->i_child;
+ parent->i_child = node;
+ }
+
+ /* Otherwise, this must be the new root_inode */
+
+ else
+ {
+ node->i_peer = root_inode;
+ root_inode = node;
+ }
+}
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: register_inode
+ ************************************************************/
+
+STATUS register_inode(const char *path,
+ struct file_operations *fops,
+ mode_t mode, void *private)
+{
+ const char *name = path;
+ FAR struct inode *left;
+ FAR struct inode *parent;
+
+ if (!*path || path[0] != '/')
+ {
+ return ERROR;
+ }
+
+ /* Find the location to insert the new subtree */
+
+ inode_semtake();
+ if (inode_search(&name, &left, &parent) != NULL)
+ {
+ /* Is is an error if the node already exists in the tree */
+
+ inode_semgive();
+ return ERROR;
+ }
+
+ /* Now we now where to insert the subtree */
+
+ for (;;)
+ {
+ FAR struct inode *node;
+
+ /* Create a new node -- we need to know if this is the
+ * the leaf node or some intermediary. We can find this
+ * by looking at the next name.
+ */
+
+ const char *next_name = inode_nextname(name);
+ if (*next_name)
+ {
+ /* Insert an operationless node */
+
+ node = inode_alloc(name, NULL, mode, NULL);
+ if (node)
+ {
+ inode_insert(node, left, parent);
+
+ /* Set up for the next time through the loop */
+
+ name = next_name;
+ left = NULL;
+ parent = node;
+ continue;
+ }
+ }
+ else
+ {
+ node = inode_alloc(name, fops, mode, private);
+ if (node)
+ {
+ inode_insert(node, left, parent);
+ inode_semgive();
+ return 0;
+ }
+ }
+
+ /* We get here on failures to allocate node memory */
+
+ inode_semgive();
+ return ERROR;
+ }
+}
diff --git a/nuttx/fs/fs_rewinddir.c b/nuttx/fs/fs_rewinddir.c
new file mode 100644
index 000000000..a5de2784b
--- /dev/null
+++ b/nuttx/fs/fs_rewinddir.c
@@ -0,0 +1,101 @@
+/************************************************************
+ * fs_rewinddir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: rewinddir
+ *
+ * Description:
+ * The rewinddir() function resets the position of the
+ * directory stream dir to the beginning of the directory.
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ *
+ * Return:
+ * None
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+void rewinddir(FAR DIR *dirp)
+{
+ struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+ struct inode *prev;
+
+ if (idir)
+ {
+ inode_semtake();
+
+ prev = idir->next;
+ idir->next = idir->root; /* The next node to visit */
+
+ if (idir->next)
+ {
+ /* Increment the reference count on this next node */
+
+ idir->next->i_crefs++;
+ }
+
+ inode_semgive();
+
+ if (prev)
+ {
+ inode_release(prev);
+ }
+ }
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_seekdir.c b/nuttx/fs/fs_seekdir.c
new file mode 100644
index 000000000..aa0ee907d
--- /dev/null
+++ b/nuttx/fs/fs_seekdir.c
@@ -0,0 +1,117 @@
+/************************************************************
+ * fs_seekdir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: seekdir
+ *
+ * Description:
+ * The seekdir() function sets the location in the
+ * directory stream from which the next readdir() call will
+ * start. seekdir() should be used with an offset returned
+ * by telldir().
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ * offset -- offset to seek to
+ *
+ * Return:
+ * None
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+void seekdir(FAR DIR *dirp, off_t offset)
+{
+ struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+ struct inode *curr;
+ struct inode *prev;
+ off_t i;
+
+ if (idir)
+ {
+ /* Traverse the peer list starting at the 'root' of the
+ * the list until we find the node at 'offset". If devices
+ * are being registered and unregistered, then this can
+ * be a very unpredictable operation.
+ */
+
+ inode_semtake();
+ for (i = 0, curr = idir->root;
+ curr && i != offset;
+ i++, curr = curr->i_peer);
+
+ /* Now get the inode to vist next time that readdir() is called */
+
+ prev = idir->next;
+ idir->next = curr; /* The next node to visit */
+
+ if (curr)
+ {
+ /* Increment the reference count on this next node */
+
+ curr->i_crefs++;
+ }
+
+ inode_semgive();
+
+ if (prev)
+ {
+ inode_release(prev);
+ }
+ }
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_telldir.c b/nuttx/fs/fs_telldir.c
new file mode 100644
index 000000000..781a46469
--- /dev/null
+++ b/nuttx/fs/fs_telldir.c
@@ -0,0 +1,106 @@
+/************************************************************
+ * fs_telldir.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: telldir
+ *
+ * Description:
+ * The telldir() function returns the current location
+ * associated with the directory stream dirp.
+ *
+ * Inputs:
+ * dirp -- An instance of type DIR created by a previous
+ * call to opendir();
+ *
+ * Return:
+ * On success, the telldir() function returns the current
+ * location in the directory stream. On error, -1 is
+ * returned, and errno is set appropriately.
+ *
+ * EBADF - Invalid directory stream descriptor dir
+ *
+ ************************************************************/
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+
+off_t telldir(FAR DIR *dirp)
+{
+ struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
+ struct inode *curr;
+ off_t offs;
+
+ if (!idir)
+ {
+ *get_errno_ptr() = EBADF;
+ return -1;
+ }
+
+ /* Traverse the peer list starting at the 'root' of the
+ * the list until we find the 'next' node. If devices
+ * are being registered and unregistered, then this can
+ * be a very unpredictable operation.
+ */
+
+ inode_semtake();
+ for (offs = 0, curr = idir->root;
+ curr && curr != idir->next;
+ offs++, curr = curr->i_peer);
+
+ /* We should have an offset now corresponding to idir->next.*/
+
+ inode_semgive();
+ return offs;
+}
+
+#endif /* CONFIG_NFILE_DESCRIPTORS */
diff --git a/nuttx/fs/fs_unregisterinode.c b/nuttx/fs/fs_unregisterinode.c
new file mode 100644
index 000000000..37fd538ce
--- /dev/null
+++ b/nuttx/fs/fs_unregisterinode.c
@@ -0,0 +1,155 @@
+/************************************************************
+ * fs_unregisterinode.c
+ *
+ * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name Gregory Nutt nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <nuttx/fs.h>
+#include "fs_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Public Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: inode_remove
+ ************************************************************/
+
+static void inode_remove(struct inode *node,
+ struct inode *peer,
+ struct inode *parent)
+{
+ /* If peer is non-null, then remove the node from the right of
+ * of that peer node.
+ */
+
+ if (peer)
+ {
+ peer->i_peer = node->i_peer;
+ }
+
+ /* If parent is non-null, then remove the node from head of
+ * of the list of children.
+ */
+
+ else if (parent)
+ {
+ parent->i_child = node->i_peer;
+ }
+
+ /* Otherwise, we must be removing the root inode. */
+
+ else
+ {
+ root_inode = node->i_peer;
+ }
+ node->i_peer = NULL;
+}
+
+/************************************************************
+ * Public Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: unregister_inode
+ ************************************************************/
+
+STATUS unregister_inode(const char *path)
+{
+ const char *name = path;
+ FAR struct inode *node;
+ FAR struct inode *left;
+ FAR struct inode *parent;
+
+ if (*path && path[0] == '/')
+ {
+ return ERROR;
+ }
+
+ /* Find the node to delete */
+
+ inode_semtake();
+ node = inode_search(&name, &left, &parent);
+ if (node)
+ {
+ /* Found it, now remove it from the tree */
+
+ inode_remove(node, left, parent);
+
+ /* We cannot delete it if there reference to the inode */
+
+ if (node->i_crefs)
+ {
+ /* In that case, we will mark it deleted, when the FS
+ * releases the inode, we will then, finally delete
+ * the subtree.
+ */
+
+ node->i_flags |= FSNODEFLAG_DELETED;
+ inode_semgive();
+ }
+ else
+ {
+ /* And delete it now -- recursively to delete all of its children */
+
+ inode_semgive();
+ inode_free(node->i_child);
+ free(node);
+ return OK;
+ }
+ }
+
+ /* The node does not exist or it has references */
+
+ inode_semgive();
+ return ERROR;
+}