diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-26 22:37:57 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-05-26 22:37:57 +0000 |
commit | 824fcd39cf4947527eafcbfa7c0dcbc4704b4cb3 (patch) | |
tree | 9958b54a89de6282576ddb77bb4192a079ddb316 /nuttx/fs | |
parent | 503ba396598ab1d5ce6f336cd3543d32d6aacbaa (diff) | |
download | px4-nuttx-824fcd39cf4947527eafcbfa7c0dcbc4704b4cb3.tar.gz px4-nuttx-824fcd39cf4947527eafcbfa7c0dcbc4704b4cb3.tar.bz2 px4-nuttx-824fcd39cf4947527eafcbfa7c0dcbc4704b4cb3.zip |
Fat dir operations seem to work
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@254 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs')
-rw-r--r-- | nuttx/fs/fs_fat32.c | 2 | ||||
-rw-r--r-- | nuttx/fs/fs_internal.h | 22 | ||||
-rw-r--r-- | nuttx/fs/fs_opendir.c | 174 | ||||
-rw-r--r-- | nuttx/fs/fs_readdir.c | 28 |
4 files changed, 122 insertions, 104 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c index adb6c47b6..633695fd1 100644 --- a/nuttx/fs/fs_fat32.c +++ b/nuttx/fs/fs_fat32.c @@ -1262,7 +1262,7 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct intern /* This is not the root directory. Verify that it is some kind of directory */ - else if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) + else if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY) == 0) { /* The entry is not a directory */ ret = -ENOTDIR; diff --git a/nuttx/fs/fs_internal.h b/nuttx/fs/fs_internal.h index 432344515..8bfc52f21 100644 --- a/nuttx/fs/fs_internal.h +++ b/nuttx/fs/fs_internal.h @@ -69,6 +69,13 @@ #define INODE_SET_MOUNTPT(i) \ ((i)->i_flags = (((i)->i_flags & ~FSNODEFLAG_TYPE_MASK) | FSNODEFLAG_TYPE_MOUNTPT)) +/* Mountpoint fd_flags values */ + +#define DIRENTFLAGS_PSUEDONODE 1 + +#define DIRENT_SETPSUEDONODE(f) do (f) |= DIRENTFLAGS_PSUEDONODE; while (0) +#define DIRENT_ISPSUEDONODE(f) (((f) & DIRENTFLAGS_PSUEDONODE) != 0) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -87,7 +94,7 @@ struct fs_psuedodir_s struct inode *fd_next; /* The inode for the next call to readdir() */ }; -#ifdef CONFIG_FS_FAT +#if defined(CONFIG_FS_FAT) && !defined(CONFIG_DISABLE_MOUNTPOINT) /* For fat, we need to retun the start cluster, current cluster, current * sector and current directory index. */ @@ -113,6 +120,12 @@ struct internal_dir_s struct inode *fd_root; + /* At present, only mountpoints require special handling flags */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + unsigned int fd_flags; +#endif + /* This keeps track of the current directory position for telldir */ off_t fd_position; @@ -125,10 +138,17 @@ struct internal_dir_s union { + /* Private data used by the built-in psuedo-file system */ + struct fs_psuedodir_s psuedo; + + /* Private data used by other file systems */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT #ifdef CONFIG_FS_FAT struct fs_fatdir_s fat; #endif +#endif } u; /* In any event, this the actual struct dirent that is returned by readdir */ diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c index 6791195a2..58a1f4bb2 100644 --- a/nuttx/fs/fs_opendir.c +++ b/nuttx/fs/fs_opendir.c @@ -51,81 +51,6 @@ ************************************************************/ /************************************************************ - * 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; -} - -/************************************************************ * Public Functions ************************************************************/ @@ -161,22 +86,45 @@ static inline FAR struct inode *fs_finddirnode(const char *path, const char **re FAR DIR *opendir(const char *path) { - FAR struct inode *inode; + FAR struct inode *inode = NULL; FAR struct internal_dir_s *dir; const char *relpath; + boolean isroot = FALSE; int ret; - /* Get an inode corresponding to the path. On successful - * return, we will hold on reference count on the inode. + /* If we are given 'nothing' then we will interpret this as + * request for the root inode. */ - inode = fs_finddirnode(path, &relpath); + if (!path || *path == 0 || strcmp(path, "/") == 0) + { + inode_semgive(); + inode = root_inode; + isroot = TRUE; + } + else + { + /* We don't know what to do with relative pathes */ + + if (*path != '/') + { + return NULL; + } + + /* Find the node matching the path. */ + + inode_semtake(); + inode = inode_search(&path, (FAR void*)NULL, (FAR void*)NULL, &relpath); + } + + /* Did we get an inode? */ + if (!inode) { - /* 'path' is not a directory.*/ + /* 'path' is not a does not exist.*/ ret = ENOTDIR; - goto errout; + goto errout_with_semaphore; } /* Allocate a type DIR -- which is little more than an inode @@ -189,7 +137,7 @@ FAR DIR *opendir(const char *path) /* Insufficient memory to complete the operation.*/ ret = ENOMEM; - goto errout_with_inode; + goto errout_with_semaphore; } /* Populate the DIR structure and return it to the caller. The way that @@ -200,20 +148,29 @@ FAR DIR *opendir(const char *path) dir->fd_root = inode; /* Save the inode where we start */ dir->fd_position = 0; /* This is the position in the read stream */ - /* Is this a not in the psuedo filesystem? */ + /* Is this a node in the psuedo filesystem? Or a mountpoint? */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_MOUNTPT(inode)) + { + /* Yes, then return the inode itself as the 'root' of + * the directory. The actually directory is at relpath into the + * mounted filesystem. + */ -#ifndef CONFIG_DISABLE_MOUNTPOUNT - if (INODE_IS_MOUNTPT(inode)) - { /* The node is a file system mointpoint. Verify that the mountpoint - * supports the opendir() method - */ + * supports the opendir() method + */ if (!inode->u.i_mops || !inode->u.i_mops->opendir) - { + { ret = ENOSYS; goto errout_with_direntry; - } + } + + /* Take reference to the mountpoint inode (fd_root) */ + + inode_addref(inode); /* Perform the opendir() operation */ @@ -221,27 +178,52 @@ FAR DIR *opendir(const char *path) if (ret < 0) { ret = -ret; - goto errout_with_direntry; + goto errout_with_inode; } } else #endif { - /* The node is part of the root psuedo file system */ + /* The node is part of the root psuedo file system. Does the inode have a child? + * If so that the child would be the 'root' of a list of nodes under + * the directory. + */ + + if (!isroot) + { + inode = inode->i_child; + if (!inode) + { + ret = ENOTDIR; + goto errout_with_direntry; + } + } - inode_addref(inode); /* Now we have two references on inode */ + /* It looks we have a valid psuedo-filesystem node. Take two references + * on the inode -- one for the parent (fd_root) and one for the child (fd_next). + */ + + inode_addref(inode); + inode_addref(inode); dir->u.psuedo.fd_next = inode; /* This is the next node to use for readdir() */ + + /* Flag the inode as belonging to the psuedo-filesystem */ +#ifndef CONFIG_DISABLE_MOUNTPOINT + DIRENT_SETPSUEDONODE(dir->fd_flags); +#endif } + inode_semgive(); return ((DIR*)dir); /* Nasty goto's make error handling simpler */ -errout_with_direntry: - free(dir); errout_with_inode: inode_release(inode); -errout: +errout_with_direntry: + free(dir); +errout_with_semaphore: + inode_semgive(); *get_errno_ptr() = ret; return NULL; } diff --git a/nuttx/fs/fs_readdir.c b/nuttx/fs/fs_readdir.c index 6cb3eb099..0c15d04e9 100644 --- a/nuttx/fs/fs_readdir.c +++ b/nuttx/fs/fs_readdir.c @@ -82,7 +82,20 @@ static inline int readpsuedodir(struct internal_dir_s *idir) idir->fd_dir.d_type = 0; if (idir->u.psuedo.fd_next->u.i_ops) { - idir->fd_dir.d_type |= DTYPE_FILE; +#ifndef CONFIG_DISABLE_MOUNTPOINT + if (INODE_IS_BLOCK(idir->u.psuedo.fd_next)) + { + idir->fd_dir.d_type |= DTYPE_BLK; + } + if (INODE_IS_MOUNTPT(idir->u.psuedo.fd_next)) + { + idir->fd_dir.d_type |= DTYPE_DIRECTORY; + } + else +#endif + { + idir->fd_dir.d_type |= DTYPE_CHR; + } } /* If the node has child node(s), then we will say that it @@ -147,7 +160,9 @@ static inline int readpsuedodir(struct internal_dir_s *idir) FAR struct dirent *readdir(DIR *dirp) { FAR struct internal_dir_s *idir = (struct internal_dir_s *)dirp; +#ifndef CONFIG_DISABLE_MOUNTPOINT struct inode *inode; +#endif int ret; /* Sanity checks */ @@ -162,8 +177,9 @@ FAR struct dirent *readdir(DIR *dirp) * that we are dealing with. */ +#ifndef CONFIG_DISABLE_MOUNTPOINT inode = idir->fd_root; - if (INODE_IS_MOUNTPT(inode)) + if (INODE_IS_MOUNTPT(inode) && !DIRENT_ISPSUEDONODE(idir->fd_flags)) { /* The node is a file system mointpoint. Verify that the mountpoint * supports the readdir() method @@ -172,7 +188,7 @@ FAR struct dirent *readdir(DIR *dirp) if (!inode->u.i_mops || !inode->u.i_mops->readdir) { ret = EACCES; - goto errout; + goto errout; } /* Perform the readdir() operation */ @@ -180,10 +196,10 @@ FAR struct dirent *readdir(DIR *dirp) ret = inode->u.i_mops->readdir(inode, idir); } else +#endif { - /* The node is part of the root psuedo file system, release - * our contained reference to the 'next' inode. - */ + /* The node is part of the root psuedo file system */ + ret = readpsuedodir(idir); } |