Added opendir, readdir, closedir, etc.

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@62 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-03-14 22:41:09 +00:00
parent 08199e1216
commit 599f8b4682
25 changed files with 1849 additions and 390 deletions

View file

@ -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 <spudmonkey@racsa.co.cr>
* Add dirent.h, opendir(), readdir(), closedir(), etc.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

105
fs/fs_closedir.c Normal file
View file

@ -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 */

View file

@ -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;
}

83
fs/fs_inodeaddref.c Normal file
View file

@ -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();
}
}

96
fs/fs_inodefind.c Normal file
View file

@ -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;
}

110
fs/fs_inodefinddir.c Normal file
View file

@ -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;
}

103
fs/fs_inoderelease.c Normal file
View file

@ -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();
}
}
}

View file

@ -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 ***********************************************/

View file

@ -33,10 +33,6 @@
*
************************************************************/
/************************************************************
* Compilation Switches
************************************************************/
/************************************************************
* Included Files
************************************************************/
@ -50,7 +46,6 @@
#include <stdarg.h>
#endif
#include <nuttx/fs.h>
#include <errno.h>
#include "fs_internal.h"
/************************************************************

126
fs/fs_opendir.c Normal file
View file

@ -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 */

145
fs/fs_readdir.c Normal file
View file

@ -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 */

123
fs/fs_readdirr.c Normal file
View file

@ -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 */

222
fs/fs_registerinode.c Normal file
View file

@ -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;
}
}

101
fs/fs_rewinddir.c Normal file
View file

@ -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 */

117
fs/fs_seekdir.c Normal file
View file

@ -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 */

106
fs/fs_telldir.c Normal file
View file

@ -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 */

155
fs/fs_unregisterinode.c Normal file
View file

@ -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;
}

112
include/dirent.h Normal file
View file

@ -0,0 +1,112 @@
/************************************************************
* dirent.h
*
* 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.
*
************************************************************/
#ifndef __DIRENT_H
#define __DIRENT_H
/************************************************************
* Included Files
************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <limits.h>
/************************************************************
* 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 */

View file

@ -40,10 +40,19 @@
* Included Files
************************************************************/
#include <nuttx/config.h>
/* Architecture specific limits */
#include <arch/limits.h>
/************************************************************
* Definitions
************************************************************/
/* Configurable limits */
#define NAME_MAX CONFIG_NAME_MAX
#define MAXNAMELEN CONFIG_NAME_MAX
#endif /* __LIMITS_H */

View file

@ -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);