diff --git a/ChangeLog b/ChangeLog index a14dc11e23..402a824b37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,3 +31,7 @@ when the timer interrupt is enabled. Seems to be an issue when SP enters indirect address space. * Documentation updates + +0.1.2 2007-xx-xx Gregory Nutt + + * Add dirent.h, opendir(), readdir(), closedir(), etc. diff --git a/arch/README.txt b/arch/README.txt index 07d11b9b38..4b03a020e8 100644 --- a/arch/README.txt +++ b/arch/README.txt @@ -137,6 +137,7 @@ defconfig -- This is a configuration file similar to the Linux descriptors (one for each open) CONFIG_NFILE_STREAMS - The maximum number of streams that can be fopen'ed + CONFIG_NAME_MAX - The maximum size of a file name. CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate on fopen. (Only if CONFIG_NFILE_STREAMS > 0) CONFIG_NUNGET_CHARS - Number of characters that can be diff --git a/arch/c5471/defconfig b/arch/c5471/defconfig index 641f1ca548..7ebb81587d 100644 --- a/arch/c5471/defconfig +++ b/arch/c5471/defconfig @@ -191,6 +191,7 @@ CONFIG_RRLOAD_BINARY=y # descriptors (one for each open) # CONFIG_NFILE_STREAMS - The maximum number of streams that # can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. # CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate # on fopen. (Only if CONFIG_NFILE_STREAMS > 0) # CONFIG_NUNGET_CHARS - Number of characters that can be @@ -212,6 +213,7 @@ CONFIG_MAX_TASK_ARGS=4 CONFIG_NPTHREAD_KEYS=4 CONFIG_NFILE_DESCRIPTORS=32 CONFIG_NFILE_STREAMS=16 +CONFIG_NAME_MAX=32 CONFIG_STDIO_BUFFER_SIZE=1024 CONFIG_NUNGET_CHARS=2 CONFIG_PREALLOC_MQ_MSGS=32 diff --git a/arch/pjrc-8051/defconfig b/arch/pjrc-8051/defconfig index 789bd79c95..28925eec54 100644 --- a/arch/pjrc-8051/defconfig +++ b/arch/pjrc-8051/defconfig @@ -185,6 +185,7 @@ CONFIG_RRLOAD_BINARY=n # descriptors (one for each open) # CONFIG_NFILE_STREAMS - The maximum number of streams that # can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. # CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate # on fopen. (Only if CONFIG_NFILE_STREAMS > 0) # CONFIG_NUNGET_CHARS - Number of characters that can be @@ -206,6 +207,7 @@ CONFIG_MAX_TASK_ARGS=4 CONFIG_NPTHREAD_KEYS=0 CONFIG_NFILE_DESCRIPTORS=0 CONFIG_NFILE_STREAMS=0 +CONFIG_NAME_MAX=32 CONFIG_STDIO_BUFFER_SIZE=0 CONFIG_NUNGET_CHARS=0 CONFIG_PREALLOC_MQ_MSGS=0 diff --git a/arch/sim/defconfig b/arch/sim/defconfig index 7ec6f01d35..bff4ac404c 100644 --- a/arch/sim/defconfig +++ b/arch/sim/defconfig @@ -151,6 +151,7 @@ CONFIG_RRLOAD_BINARY=n # descriptors (one for each open) # CONFIG_NFILE_STREAMS - The maximum number of streams that # can be fopen'ed +# CONFIG_NAME_MAX - The maximum size of a file name. # CONFIG_STDIO_BUFFER_SIZE - Size of the buffer to allocate # on fopen. (Only if CONFIG_NFILE_STREAMS > 0) # CONFIG_NUNGET_CHARS - Number of characters that can be @@ -172,6 +173,7 @@ CONFIG_MAX_TASK_ARGS=4 CONFIG_NPTHREAD_KEYS=4 CONFIG_NFILE_DESCRIPTORS=32 CONFIG_NFILE_STREAMS=16 +CONFIG_NAME_MAX=32 CONFIG_STDIO_BUFFER_SIZE=1024 CONFIG_NUNGET_CHARS=2 CONFIG_PREALLOC_MQ_MSGS=32 diff --git a/fs/Makefile b/fs/Makefile index b7d09a4e9f..8c57d6129b 100644 --- a/fs/Makefile +++ b/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/fs/fs_closedir.c b/fs/fs_closedir.c new file mode 100644 index 0000000000..cf22902aff --- /dev/null +++ b/fs/fs_closedir.c @@ -0,0 +1,105 @@ +/************************************************************ + * fs_closedir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include +#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/fs/fs_inode.c b/fs/fs_inode.c index c6d6731903..10936c8be9 100644 --- a/fs/fs_inode.c +++ b/fs/fs_inode.c @@ -33,10 +33,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). + */ -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; + (void)sem_init(&tree_sem, 0, 1); + + /* Initialize files array (if it is used) */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (files_initialize != NULL) #endif - node->i_private = private; - _inode_namecpy(node->i_name, name); + { + files_initialize(); } - return node; } -static FAR struct inode *_inode_find(const char **path, - FAR struct inode **peer, - FAR struct inode **parent) +/************************************************************ + * Name: inode_semtake + ************************************************************/ + +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); + } +} + +/************************************************************ + * 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. - */ +/************************************************************ + * Name: inode_free + ************************************************************/ - 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; -} - -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/fs/fs_inodeaddref.c b/fs/fs_inodeaddref.c new file mode 100644 index 0000000000..278cf08aba --- /dev/null +++ b/fs/fs_inodeaddref.c @@ -0,0 +1,83 @@ +/************************************************************ + * fs_inodeaddref.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#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/fs/fs_inodefind.c b/fs/fs_inodefind.c new file mode 100644 index 0000000000..8edd19f087 --- /dev/null +++ b/fs/fs_inodefind.c @@ -0,0 +1,96 @@ +/************************************************************ + * fs_inodefind.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#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/fs/fs_inodefinddir.c b/fs/fs_inodefinddir.c new file mode 100644 index 0000000000..597d810966 --- /dev/null +++ b/fs/fs_inodefinddir.c @@ -0,0 +1,110 @@ +/************************************************************ + * fs_inodefinddir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#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/fs/fs_inoderelease.c b/fs/fs_inoderelease.c new file mode 100644 index 0000000000..3989a4959a --- /dev/null +++ b/fs/fs_inoderelease.c @@ -0,0 +1,103 @@ +/************************************************************ + * fs_inoderelease.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#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/fs/fs_internal.h b/fs/fs_internal.h index a063335fb7..111f56aae9 100644 --- a/fs/fs_internal.h +++ b/fs/fs_internal.h @@ -42,6 +42,7 @@ #include #include +#include #include /************************************************************ @@ -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/fs/fs_open.c b/fs/fs_open.c index ac6d39e439..53af359fb3 100644 --- a/fs/fs_open.c +++ b/fs/fs_open.c @@ -33,10 +33,6 @@ * ************************************************************/ -/************************************************************ - * Compilation Switches - ************************************************************/ - /************************************************************ * Included Files ************************************************************/ @@ -50,7 +46,6 @@ #include #endif #include -#include #include "fs_internal.h" /************************************************************ diff --git a/fs/fs_opendir.c b/fs/fs_opendir.c new file mode 100644 index 0000000000..810b365fe2 --- /dev/null +++ b/fs/fs_opendir.c @@ -0,0 +1,126 @@ +/************************************************************ + * fs_opendir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include +#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/fs/fs_readdir.c b/fs/fs_readdir.c new file mode 100644 index 0000000000..40f4f1747b --- /dev/null +++ b/fs/fs_readdir.c @@ -0,0 +1,145 @@ +/************************************************************ + * fs_readdir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include +#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/fs/fs_readdirr.c b/fs/fs_readdirr.c new file mode 100644 index 0000000000..9308560418 --- /dev/null +++ b/fs/fs_readdirr.c @@ -0,0 +1,123 @@ +/************************************************************ + * fs_readdirr.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#include +#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/fs/fs_registerinode.c b/fs/fs_registerinode.c new file mode 100644 index 0000000000..3959594228 --- /dev/null +++ b/fs/fs_registerinode.c @@ -0,0 +1,222 @@ +/************************************************************ + * fs_registerinode.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#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/fs/fs_rewinddir.c b/fs/fs_rewinddir.c new file mode 100644 index 0000000000..a5de2784b2 --- /dev/null +++ b/fs/fs_rewinddir.c @@ -0,0 +1,101 @@ +/************************************************************ + * fs_rewinddir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#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/fs/fs_seekdir.c b/fs/fs_seekdir.c new file mode 100644 index 0000000000..aa0ee907d2 --- /dev/null +++ b/fs/fs_seekdir.c @@ -0,0 +1,117 @@ +/************************************************************ + * fs_seekdir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#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/fs/fs_telldir.c b/fs/fs_telldir.c new file mode 100644 index 0000000000..781a464696 --- /dev/null +++ b/fs/fs_telldir.c @@ -0,0 +1,106 @@ +/************************************************************ + * fs_telldir.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#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/fs/fs_unregisterinode.c b/fs/fs_unregisterinode.c new file mode 100644 index 0000000000..37fd538cef --- /dev/null +++ b/fs/fs_unregisterinode.c @@ -0,0 +1,155 @@ +/************************************************************ + * fs_unregisterinode.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 +#include +#include +#include +#include +#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; +} diff --git a/include/dirent.h b/include/dirent.h new file mode 100644 index 0000000000..160dd04ead --- /dev/null +++ b/include/dirent.h @@ -0,0 +1,112 @@ +/************************************************************ + * dirent.h + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ************************************************************/ + +#ifndef __DIRENT_H +#define __DIRENT_H + +/************************************************************ + * Included Files + ************************************************************/ + +#include +#include +#include + +/************************************************************ + * Definitions + ************************************************************/ + +/* File type code for the d_type field in dirent struct. + * Note that because of the simplified filesystem organization + * of NuttX, an inode can be BOTH a file and a directory + */ + +#define DTYPE_FILE 0x01 +#define DTYPE_DIRECTORY 0x02 + +#define DIRENT_ISFILE(dtype) (((dtype) & DTYPE_FILE) != ) +#define DIRENT_ISDIRECTORY(dtype) (((dtype) & DTYPE_DIRECTORY) != ) + +/************************************************************ + * Public Type Definitions + ************************************************************/ + +/* The POSIX specification requires that the caller of readdir_r + * provide storage "large enough for a dirent with the d_name + * member and an array of char containing at least {NAME_MAX} + * plus one elements. + */ + +struct dirent +{ + ubyte d_type; /* type of file */ + char d_name[NAME_MAX+1]; /* filename */ +}; + +typedef void DIR; + +/************************************************************ + * Public Variables + ************************************************************/ + +/************************************************************ + * Public Function Prototypes + ************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/* POSIX-like File System Interfaces */ + +EXTERN int closedir(DIR *dirp); +EXTERN FAR DIR *opendir(const char *path); +EXTERN FAR struct dirent *readdir(FAR DIR *dirp); +EXTERN int readdir_r(FAR DIR *dirp, FAR struct dirent *entry, + FAR struct dirent **result); +EXTERN void rewinddir(FAR DIR *dirp); +EXTERN void seekdir(FAR DIR *dirp, int loc); +EXTERN int telldir(FAR DIR *dirp); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __DIRENT_H */ diff --git a/include/limits.h b/include/limits.h index bb043c442e..da3cebaf93 100644 --- a/include/limits.h +++ b/include/limits.h @@ -40,10 +40,19 @@ * Included Files ************************************************************/ +#include + +/* Architecture specific limits */ + #include /************************************************************ * Definitions ************************************************************/ +/* Configurable limits */ + +#define NAME_MAX CONFIG_NAME_MAX +#define MAXNAMELEN CONFIG_NAME_MAX + #endif /* __LIMITS_H */ diff --git a/include/stdio.h b/include/stdio.h index 58f398b46a..12f3c086dd 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -92,11 +92,6 @@ #define FILE_BUF_SIZE (4 * SECTOR_ALIGN_BYTES) #define FILE_BUF_ALIGN_BYTES 16 -/* File type code for the EntryType field in dirent struct */ - -#define FS_FILE_TYPE 0 -#define FS_DIRECTORY_TYPE 1 - /* The first three _iob entries are reserved for standard I/O */ #define stdin (&sched_getstreams()->sl_streams[0]) @@ -119,38 +114,6 @@ * Public Type Definitions ************************************************************/ -/* The POSIX specification requires that the caller of readdir_r - * provide storage "large enough for a dirent with the d_name - * member and an array of char containing at least {NAME_MAX} - * plus one elements. The legacy dirent structure does not - * contain such an array. The legacy dirent structure is - * renamed _dirent below. - */ - -struct _dirent -{ - FAR char *d_name; /* name of directory entry */ -}; - -struct dirent -{ - FAR char *d_name; /* A pointer to d_szname */ - char d_szname[NAME_MAX+1]; /* name of the directory entry */ -}; - -typedef struct -{ - unsigned char EntryType; /* FS_FILE_TYPE or FS_DIRECTORY_TYPE */ - char szName[NAME_MAX]; /* name of the directory entry */ -} fsdirent; - -typedef struct -{ - unsigned long inode; - int generation; - FAR char *filename; -} HANDLE_TO_NAME_IOCTL; - struct stat { dev_t st_dev; /* ID of device containing a */ @@ -189,8 +152,6 @@ struct statfs typedef FAR struct file_struct FILE; -typedef void DIR; - /************************************************************ * Public Variables ************************************************************/ @@ -239,7 +200,6 @@ EXTERN int vsprintf(char *buf, const char *s, va_list ap); EXTERN int chdir(const char *path); EXTERN int close(int fd); -EXTERN int closedir(DIR *dirp); EXTERN int creat(const char *path, mode_t mode); EXTERN FILE *fdopen(int fd, const char *type); EXTERN int fstat(int fd, FAR struct stat *buf); @@ -248,16 +208,10 @@ EXTERN int ioctl(int fd, int req, unsigned long arg); EXTERN off_t lseek(int fd, off_t offset, int whence); EXTERN int mkdir(const char *path, mode_t mode); EXTERN int open(const char *path, int oflag, ...); -EXTERN DIR *opendir(const char *path); EXTERN int read(int fd, void *buf, unsigned int nbytes); -EXTERN struct _dirent *readdir(FAR DIR *dirp); -EXTERN int readdir_r(FAR DIR *dirp, struct dirent *entry, FAR struct dirent **result); -EXTERN void rewinddir(FAR DIR *dirp); EXTERN int rmdir(const char *path); -EXTERN void seekdir(FAR DIR *dirp, int loc); EXTERN int stat(const char *path, FAR struct stat *buf); EXTERN int statfs(const char *path, FAR struct statfs *buf); -EXTERN int telldir(FAR DIR *dirp); EXTERN int unlink(const char *path); EXTERN int write(int fd, const void *buf, unsigned int nbytes);