From 2a3e5f6cd969f93fbb56d7ba2b63d7d8da11e756 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 26 May 2007 16:05:59 +0000 Subject: Setting up for mountpoint support git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@250 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/fs/Makefile | 2 +- nuttx/fs/fs_closedir.c | 31 ++++++++-- nuttx/fs/fs_inodefinddir.c | 129 ---------------------------------------- nuttx/fs/fs_internal.h | 60 +++++++++++++++---- nuttx/fs/fs_opendir.c | 142 +++++++++++++++++++++++++++++++++++++++++---- nuttx/fs/fs_readdir.c | 112 ++++++++++++++++++++++------------- nuttx/fs/fs_rewinddir.c | 64 ++++++++++++++------ nuttx/fs/fs_seekdir.c | 103 ++++++++++++++++++++++---------- nuttx/fs/fs_telldir.c | 22 ++----- 9 files changed, 401 insertions(+), 264 deletions(-) delete mode 100644 nuttx/fs/fs_inodefinddir.c diff --git a/nuttx/fs/Makefile b/nuttx/fs/Makefile index 69ffce62d..468e4e803 100644 --- a/nuttx/fs/Makefile +++ b/nuttx/fs/Makefile @@ -43,7 +43,7 @@ AOBJS = $(ASRCS:.S=$(OBJEXT)) CSRCS = fs_open.c fs_close.c fs_read.c fs_write.c fs_ioctl.c fs_dup.c \ fs_opendir.c fs_closedir.c fs_readdir.c fs_readdirr.c \ fs_seekdir.c fs_telldir.c fs_rewinddir.c fs_fsync.c fs_files.c \ - fs_inode.c fs_inodefind.c fs_inodefinddir.c fs_inodereserve.c \ + fs_inode.c fs_inodefind.c fs_inodereserve.c \ fs_inoderemove.c fs_registerdriver.c fs_unregisterdriver.c \ fs_registerblockdriver.c fs_unregisterblockdriver.c \ fs_mount.c fs_umount.c fs_unlink.c fs_mkdir.c fs_rmdir.c \ diff --git a/nuttx/fs/fs_closedir.c b/nuttx/fs/fs_closedir.c index fd2d79d05..a8104b4d2 100644 --- a/nuttx/fs/fs_closedir.c +++ b/nuttx/fs/fs_closedir.c @@ -77,22 +77,41 @@ int closedir(FAR DIR *dirp) { struct internal_dir_s *idir = (struct internal_dir_s *)dirp; - if (!idir) + if (!idir || !idir->root) { *get_errno_ptr() = EBADF; return ERROR; } - /* Release our references on the contained inodes */ + /* The way that we handle the close operation depends on what kind of root + * inode we have open. + */ - if (idir->root) + if (IS_MOUNTPT_INODE(idir->root)) { - inode_release(idir->root); + /* The node is a file system mointpoint */ + +#warning "Mountpoint support not implemented" + *get_errno_ptr() = ENOSYS; + return ERROR; + } + else + { + /* The node is part of the root psuedo file system, release + * our contained reference to the 'next' inode. + */ + + if (idir->u.psuedo.next) + { + inode_release(idir->u.psuedo.next); + } } - if (idir->next) + /* Release our references on the contained 'root' inode */ + + if (idir->root) { - inode_release(idir->next); + inode_release(idir->root); } /* Then release the container */ diff --git a/nuttx/fs/fs_inodefinddir.c b/nuttx/fs/fs_inodefinddir.c deleted file mode 100644 index dcd6f4f30..000000000 --- a/nuttx/fs/fs_inodefinddir.c +++ /dev/null @@ -1,129 +0,0 @@ -/************************************************************ - * 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 -#include "fs_internal.h" - -#if CONFIG_NFILE_DESCRIPTORS >0 - -/************************************************************ - * 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 we are given 'nothing' then we will interpret this as - * request for the root inode. - */ - - if (!path || *path == 0 || strcmp(path, "/") == 0) - { - return root_inode; - } - - /* We don't know what to do with relative pathes */ - - if (*path != '/') - { - return NULL; - } - - /* Find the node matching the path. */ - - inode_semtake(); - - /* Handle some special cases */ - - node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, (FAR const char**)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; -} - -#endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h index 2912ff2b7..c20ab2176 100644 --- a/nuttx/fs/fs_internal.h +++ b/nuttx/fs/fs_internal.h @@ -79,12 +79,56 @@ 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 */ + /* This is the node that was opened by opendir. The type of the inode + * determines the way that the readdir() operations are performed. For the + * psuedo root psuedo-file system, it is also used to support rewind. + * + * We hold a reference on this inode so we know that it will persist until + * closedir() is called (although inodes linked to this inode may change). + */ + + struct inode *root; + + /* This keeps track of the current directory position for telldir */ + + off_t position; + + /* Retained control information depends on the type of file system that + * provides is provides the mountpoint. Ideally this information should + * be hidden behind an opaque, file-system-dependent void *, but we put + * the private definitions in line here for now to reduce allocations. + */ + + union + { + /* For the root psuedo-file system, we need retain only the 'next' inode + * need for the next readdir() operation. We hold a reference on this + * inode so we know that it will persist until closedir is called. + */ + + struct + { + struct inode *next; /* The inode for the next call to readdir() */ + } psuedo; + +#ifdef CONFIG_FS_FAT + /* For fat, we need to retun the start cluster, current cluster, current + * sector and current directory index. + */ + + struct + { + uint32 startcluster; /* Starting cluster of directory */ + uint32 currcluster; /* The current cluster being read */ + size_t currsector; /* The current sector being read */ + unsigned int dirindex; /* The next directory entry to read */ + } fat; +#endif + } u; + + /* In any event, this the actual struct dirent that is returned by readdir */ + + struct dirent dir; /* Populated when readdir is called */ }; /**************************************************************************** @@ -128,10 +172,6 @@ EXTERN STATUS inode_remove(const char *path); EXTERN FAR struct inode *inode_find(const char *path, const char **relpath); -/* fs_inodefinddir.c *********************************************************/ - -EXTERN FAR struct inode *inode_finddir(const char *path); - /* fs_inodeaddref.c **********************************************************/ EXTERN void inode_addref(FAR struct inode *inode); diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c index b02d97bf7..24462d53b 100644 --- a/nuttx/fs/fs_opendir.c +++ b/nuttx/fs/fs_opendir.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "fs_internal.h" @@ -49,6 +50,92 @@ * Private Functions ************************************************************/ +/************************************************************ + * Name: fs_finddirnode + * + * 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 or one + * that is a mountpoint for a "real" file system + * + ************************************************************/ + +static inline FAR struct inode *fs_finddirnode(const char *path, const char **relpath) +{ + FAR struct inode *node; + FAR struct inode *root = NULL; + + /* If we are given 'nothing' then we will interpret this as + * request for the root inode. + */ + + if (!path || *path == 0 || strcmp(path, "/") == 0) + { + return root_inode; + } + + /* We don't know what to do with relative pathes */ + + if (*path != '/') + { + return NULL; + } + + /* Find the node matching the path. */ + + inode_semtake(); + node = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, relpath); + if (node) + { + + /* Is this a not in the psuedo filesystem? */ + + if (INODE_IS_MOUNTPT(node)) + { + /* Yes, then return the inode itself as the 'root' of + * the directory. The actually directory is at relpath into the + * mounted filesystem. Increment the count of references + * on the inode. + */ + + root = node; + root->i_crefs++; + } + else + { + /* It is a node in the psuedo filesystem. Does the inode have a child? + * If so that the child would be the 'root' of a list of nodes under + * the directory. + */ + + root = node->i_child; + if (root) + { + /* If found, then increment the count of + * references on the child node. + */ + + root->i_crefs++; + } + } + } + inode_semgive(); + return root; +} + +/************************************************************ + * Name: fs_openmountptdir + ************************************************************/ + +static inline int fs_openmountptdir(struct inode *inode, const char *relpath, + struct internal_dir_s *dir) +{ +#warning "Mountpoint support not implemented" + return -ENOSYS; +} + /************************************************************ * Public Functions ************************************************************/ @@ -87,18 +174,20 @@ FAR DIR *opendir(const char *path) { FAR struct inode *inode; FAR struct internal_dir_s *dir; + const char *relpath; + int ret; /* Get an inode corresponding to the path. On successful * return, we will hold on reference count on the inode. */ - inode = inode_finddir(path); + inode = fs_finddirnode(path, &relpath); if (!inode) { /* 'path' is not a directory.*/ - *get_errno_ptr() = ENOTDIR; - return NULL; + ret = ENOTDIR; + goto errout; } /* Allocate a type DIR -- which is little more than an inode @@ -110,17 +199,50 @@ FAR DIR *opendir(const char *path) { /* Insufficient memory to complete the operation.*/ - *get_errno_ptr() = ENOMEM; - inode_release(inode); - return NULL; + ret = ENOMEM; + goto errout_with_inode; } - /* Populate the DIR structure and return it to the caller */ + /* Populate the DIR structure and return it to the caller. The way that + * we do this depends on whenever this is a "normal" psuedo-file-system + * inode or a file system mountpoint. + */ + + dir->root = inode; /* Save the inode where we start */ + dir->position = 0; /* This is the position in the read stream */ + + /* Is this a not in the psuedo filesystem? */ + + if (INODE_IS_MOUNTPT(inode)) + { + /* The node is a file system mointpoint */ + + ret = fs_openmountptdir(inode, relpath, dir); + if (ret < 0) + { + ret = -ret; + goto errout_with_direntry; + } + } + else + { + /* The node is part of the root psuedo file system */ + + inode_addref(inode); /* Now we have two references on inode */ + dir->u.psuedo.next = inode; /* This is the next node to use for readdir() */ + } - 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); + + /* Nasty goto's make error handling simpler */ + +errout_with_direntry: + free(dir); +errout_with_inode: + inode_release(inode); +errout: + *get_errno_ptr() = ret; + return NULL; } #endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c index 54a880328..4c2d79227 100644 --- a/nuttx/fs/fs_readdir.c +++ b/nuttx/fs/fs_readdir.c @@ -50,61 +50,30 @@ ************************************************************/ /************************************************************ - * 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 - * + * Name: readpsuedodir ************************************************************/ -#if CONFIG_NFILE_DESCRIPTORS > 0 - -FAR struct dirent *readdir(DIR *dirp) +static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir) { - 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) + if (!idir->u.psuedo.next) { return NULL; } /* Copy the inode name into the dirent structure */ - strncpy(idir->dir.d_name, idir->next->i_name, NAME_MAX+1); + strncpy(idir->dir.d_name, idir->u.psuedo.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->u.i_ops) + if (idir->u.psuedo.next->u.i_ops) { idir->dir.d_type |= DTYPE_FILE; } @@ -113,7 +82,7 @@ FAR struct dirent *readdir(DIR *dirp) * is a directory. NOTE: that the node can be both! */ - if (idir->next->i_child || !idir->next->u.i_ops) + if (idir->u.psuedo.next->i_child || !idir->u.psuedo.next->u.i_ops) { idir->dir.d_type |= DTYPE_DIRECTORY; } @@ -122,14 +91,14 @@ FAR struct dirent *readdir(DIR *dirp) inode_semtake(); - prev = idir->next; - idir->next = prev->i_peer; /* The next node to visit */ + prev = idir->u.psuedo.next; + idir->u.psuedo.next = prev->i_peer; /* The next node to visit */ - if (idir->next) + if (idir->u.psuedo.next) { /* Increment the reference count on this next node */ - idir->next->i_crefs++; + idir->u.psuedo.next->i_crefs++; } inode_semgive(); @@ -142,4 +111,65 @@ FAR struct dirent *readdir(DIR *dirp) return &idir->dir; } +/************************************************************ + * 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; + + /* Sanity checks */ + + if (!idir || !idir->root) + { + *get_errno_ptr() = EBADF; + return NULL; + } + + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ + + if (INODE_IS_MOUNTPT(idir->root)) + { + /* The node is a file system mointpoint */ + +#warning "Mountpoint support not implemented" + *get_errno_ptr() = ENOSYS; + return NULL; + } + else + { + /* The node is part of the root psuedo file system, release + * our contained reference to the 'next' inode. + */ + return readpsuedodir(idir); + } +} + #endif /* CONFIG_NFILE_DESCRIPTORS */ diff --git a/nuttx/fs/fs_rewinddir.c b/nuttx/fs/fs_rewinddir.c index a5de2784b..0f08da250 100644 --- a/nuttx/fs/fs_rewinddir.c +++ b/nuttx/fs/fs_rewinddir.c @@ -48,6 +48,35 @@ * Private Functions ************************************************************/ +#if CONFIG_NFILE_DESCRIPTORS > 0 + +static inline void rewindpsuedodir(struct internal_dir_s *idir) +{ + struct inode *prev; + + inode_semtake(); + + /* Reset the position to the beginning */ + + prev = idir->u.psuedo.next; /* (Save to delete later) */ + idir->u.psuedo.next = idir->root; /* The next node to visit */ + idir->position = 0; /* Reset position */ + + /* Increment the reference count on the root=next node. We + * should now have two references on the inode. + */ + + idir->root->i_crefs++; + inode_semgive(); + + /* Then release the reference to the old next inode */ + + if (prev) + { + inode_release(prev); + } +} + /************************************************************ * Public Functions ************************************************************/ @@ -68,33 +97,32 @@ * ************************************************************/ -#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(); + /* Sanity checks */ - prev = idir->next; - idir->next = idir->root; /* The next node to visit */ + if (!idir || !idir->root) + { + return; + } - if (idir->next) - { - /* Increment the reference count on this next node */ + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ - idir->next->i_crefs++; - } + if (INODE_IS_MOUNTPT(idir->root)) + { + /* The node is a file system mointpoint */ - inode_semgive(); +#warning "Mountpoint support not implemented" + } + else + { + /* The node is part of the root psuedo file system */ - if (prev) - { - inode_release(prev); - } + rewindpsuedodir(idir); } } diff --git a/nuttx/fs/fs_seekdir.c b/nuttx/fs/fs_seekdir.c index aa0ee907d..bdc03d88c 100644 --- a/nuttx/fs/fs_seekdir.c +++ b/nuttx/fs/fs_seekdir.c @@ -48,6 +48,61 @@ * Private Functions ************************************************************/ +#if CONFIG_NFILE_DESCRIPTORS > 0 + +static inline void seekpsuedodir(struct internal_dir_s *idir, off_t offset) +{ + struct inode *curr; + struct inode *prev; + off_t pos; + + /* Determine a starting point for the seek. If the seek + * is "forward" from the current position, then we will + * start at the current poisition. Otherwise, we will + * "rewind" to the root dir. + */ + + if ( offset < idir->position ) + { + pos = 0; + curr = idir->root; + } + else + { + pos = idir->position; + curr = idir->u.psuedo.next; + } + + /* 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 (; curr && pos != offset; pos++, curr = curr->i_peer); + + /* Now get the inode to vist next time that readdir() is called */ + + prev = idir->u.psuedo.next; + idir->u.psuedo.next = curr; /* The next node to visit (might be null) */ + idir->position = pos; /* Might be beyond the last dirent */ + + if (curr) + { + /* Increment the reference count on this next node */ + + curr->i_crefs++; + } + + inode_semgive(); + + if (prev) + { + inode_release(prev); + } +} + /************************************************************ * Public Functions ************************************************************/ @@ -71,46 +126,32 @@ * ************************************************************/ -#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); + /* Sanity checks */ - /* Now get the inode to vist next time that readdir() is called */ - - prev = idir->next; - idir->next = curr; /* The next node to visit */ + if (!idir || !idir->root) + { + return; + } - if (curr) - { - /* Increment the reference count on this next node */ + /* The way we handle the readdir depends on the type of inode + * that we are dealing with. + */ - curr->i_crefs++; - } + if (INODE_IS_MOUNTPT(idir->root)) + { + /* The node is a file system mointpoint */ - inode_semgive(); +#warning "Mountpoint support not implemented" + } + else + { + /* The node is part of the root psuedo file system */ - if (prev) - { - inode_release(prev); - } + seekpsuedodir(idir, offset); } } diff --git a/nuttx/fs/fs_telldir.c b/nuttx/fs/fs_telldir.c index 781a46469..31103d777 100644 --- a/nuttx/fs/fs_telldir.c +++ b/nuttx/fs/fs_telldir.c @@ -77,30 +77,16 @@ off_t telldir(FAR DIR *dirp) { struct internal_dir_s *idir = (struct internal_dir_s *)dirp; - struct inode *curr; - off_t offs; - if (!idir) + if (!idir || !idir->root) { *get_errno_ptr() = EBADF; - return -1; + return (off_t)-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. - */ + /* Just return the current position */ - 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; + return idir->position; } #endif /* CONFIG_NFILE_DESCRIPTORS */ -- cgit v1.2.3