Setting up for mountpoint support
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@250 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
2a7e55b1fc
commit
0528705d81
@ -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 \
|
||||
|
@ -77,24 +77,43 @@ 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 (IS_MOUNTPT_INODE(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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release our references on the contained 'root' inode */
|
||||
|
||||
if (idir->root)
|
||||
{
|
||||
inode_release(idir->root);
|
||||
}
|
||||
|
||||
if (idir->next)
|
||||
{
|
||||
inode_release(idir->next);
|
||||
}
|
||||
|
||||
/* Then release the container */
|
||||
|
||||
free(idir);
|
||||
|
@ -1,129 +0,0 @@
|
||||
/************************************************************
|
||||
* 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 <string.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/fs.h>
|
||||
#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 */
|
@ -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);
|
||||
|
142
fs/fs_opendir.c
142
fs/fs_opendir.c
@ -41,6 +41,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/fs.h>
|
||||
#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 */
|
||||
|
126
fs/fs_readdir.c
126
fs/fs_readdir.c
@ -49,6 +49,68 @@
|
||||
* Private Functions
|
||||
************************************************************/
|
||||
|
||||
/************************************************************
|
||||
* Name: readpsuedodir
|
||||
************************************************************/
|
||||
|
||||
static inline FAR struct dirent *readpsuedodir(struct internal_dir_s *idir)
|
||||
{
|
||||
FAR struct inode *prev;
|
||||
|
||||
/* Check if we are at the end of the list */
|
||||
|
||||
if (!idir->u.psuedo.next)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy the inode name into the dirent structure */
|
||||
|
||||
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->u.psuedo.next->u.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->u.psuedo.next->i_child || !idir->u.psuedo.next->u.i_ops)
|
||||
{
|
||||
idir->dir.d_type |= DTYPE_DIRECTORY;
|
||||
}
|
||||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
|
||||
inode_semtake();
|
||||
|
||||
prev = idir->u.psuedo.next;
|
||||
idir->u.psuedo.next = prev->i_peer; /* The next node to visit */
|
||||
|
||||
if (idir->u.psuedo.next)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
|
||||
idir->u.psuedo.next->i_crefs++;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
|
||||
if (prev)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
|
||||
return &idir->dir;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Public Functions
|
||||
************************************************************/
|
||||
@ -80,66 +142,34 @@
|
||||
FAR struct dirent *readdir(DIR *dirp)
|
||||
{
|
||||
FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp;
|
||||
FAR struct inode *prev;
|
||||
|
||||
if (!idir)
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
{
|
||||
*get_errno_ptr() = EBADF;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if we are at the end of the list */
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
if (!idir->next)
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
|
||||
#warning "Mountpoint support not implemented"
|
||||
*get_errno_ptr() = ENOSYS;
|
||||
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->u.i_ops)
|
||||
else
|
||||
{
|
||||
idir->dir.d_type |= DTYPE_FILE;
|
||||
/* The node is part of the root psuedo file system, release
|
||||
* our contained reference to the 'next' inode.
|
||||
*/
|
||||
return readpsuedodir(idir);
|
||||
}
|
||||
|
||||
/* 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->u.i_ops)
|
||||
{
|
||||
idir->dir.d_type |= DTYPE_DIRECTORY;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
@ -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)
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
{
|
||||
inode_semtake();
|
||||
return;
|
||||
}
|
||||
|
||||
prev = idir->next;
|
||||
idir->next = idir->root; /* The next node to visit */
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
if (idir->next)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
|
||||
idir->next->i_crefs++;
|
||||
}
|
||||
#warning "Mountpoint support not implemented"
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The node is part of the root psuedo file system */
|
||||
|
||||
inode_semgive();
|
||||
|
||||
if (prev)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
rewindpsuedodir(idir);
|
||||
}
|
||||
}
|
||||
|
||||
|
103
fs/fs_seekdir.c
103
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)
|
||||
/* Sanity checks */
|
||||
|
||||
if (!idir || !idir->root)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
inode_semtake();
|
||||
for (i = 0, curr = idir->root;
|
||||
curr && i != offset;
|
||||
i++, curr = curr->i_peer);
|
||||
/* The way we handle the readdir depends on the type of inode
|
||||
* that we are dealing with.
|
||||
*/
|
||||
|
||||
/* Now get the inode to vist next time that readdir() is called */
|
||||
if (INODE_IS_MOUNTPT(idir->root))
|
||||
{
|
||||
/* The node is a file system mointpoint */
|
||||
|
||||
prev = idir->next;
|
||||
idir->next = curr; /* The next node to visit */
|
||||
#warning "Mountpoint support not implemented"
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The node is part of the root psuedo file system */
|
||||
|
||||
if (curr)
|
||||
{
|
||||
/* Increment the reference count on this next node */
|
||||
|
||||
curr->i_crefs++;
|
||||
}
|
||||
|
||||
inode_semgive();
|
||||
|
||||
if (prev)
|
||||
{
|
||||
inode_release(prev);
|
||||
}
|
||||
seekpsuedodir(idir, offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user