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
+85 -338
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;
}