diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-02-19 09:21:38 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-02-19 09:21:38 -0600 |
commit | a056eba87db4299725e9c64a9869735a1400c1be (patch) | |
tree | 3f4abc5bb49579be9f477f818dccbd0bdcfe587f /nuttx/fs/fs_opendir.c | |
parent | 5966aacdb7c3fa6f7ecaca6ae08d6ed2e6f7fee9 (diff) | |
download | px4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.gz px4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.tar.bz2 px4-nuttx-a056eba87db4299725e9c64a9869735a1400c1be.zip |
FS: directory operations will now work on empty directory nodes in the pseudo-filesystem
Diffstat (limited to 'nuttx/fs/fs_opendir.c')
-rw-r--r-- | nuttx/fs/fs_opendir.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/nuttx/fs/fs_opendir.c b/nuttx/fs/fs_opendir.c index c1f44a9d1..46421c37e 100644 --- a/nuttx/fs/fs_opendir.c +++ b/nuttx/fs/fs_opendir.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/fs_opendir.c * - * Copyright (C) 2007-2009, 2011, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> * * Redistribution and use in source and binary forms, with or without @@ -89,8 +89,8 @@ static inline int open_mountpoint(FAR struct inode *inode, return ENOSYS; } - /* Take reference to the mountpoint inode (fd_root). Note that we do - * not use inode_addref() because we already hold the tree semaphore. + /* Take reference to the mountpoint inode. Note that we do not use + * inode_addref() because we already hold the tree semaphore. */ inode->i_crefs++; @@ -132,7 +132,7 @@ static inline int open_mountpoint(FAR struct inode *inode, * dir -- the dirent structure to be initialized * * Return: - * On success, OK is returned; Otherwise, a positive errno is returned. + * None * ****************************************************************************/ @@ -144,7 +144,8 @@ static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir) * semaphore and that would result in deadlock. */ - inode->i_crefs += 2; + inode->i_crefs += 2; + dir->fd_root = inode; /* Save the inode where we start */ dir->u.pseudo.fd_next = inode; /* This is the next node to use for readdir() */ /* Flag the inode as belonging to the pseudo-filesystem */ @@ -155,6 +156,43 @@ static void open_pseudodir(FAR struct inode *inode, FAR struct fs_dirent_s *dir) } /**************************************************************************** + * Name: open_emptydir + * + * Description: + * Handle the case where the inode to be opened is an empty, directory node + * within the top-level pseudo-file system. That is, it has no operations + * and, therefore, it must be a directory node. But is has no children + * to be enumerated either. + * + * Inputs: + * dir -- the dirent structure to be initialized + * + * Return: + * None + * + ****************************************************************************/ + +static inline void open_emptydir(FAR struct fs_dirent_s *dir) +{ + /* We have a valid, but empty pseudo-filesystem node. fd_next is NULL + * meaning that we are already at the end of the list of its children. + * fd_root is NULL so that if the directory is rewound, it will still be + * at the end of the list. + */ + +#if 0 /* Already nullified by kuzalloc */ + dir->fd_root = NULL; /* Save the inode where we start */ + dir->u.pseudo.fd_next = NULL; /* We are at the end of the list */ +#endif + + /* Flag the inode as belonging to the pseudo-filesystem */ + +#ifndef CONFIG_DISABLE_MOUNTPOINT + DIRENT_SETPSEUDONODE(dir->fd_flags); +#endif +} + +/**************************************************************************** * Public Functions ****************************************************************************/ @@ -189,7 +227,7 @@ FAR DIR *opendir(FAR const char *path) FAR struct inode *inode = NULL; FAR struct fs_dirent_s *dir; FAR const char *relpath; - bool bisroot = false; + bool isroot = false; int ret; /* If we are given 'nothing' then we will interpret this as @@ -200,7 +238,7 @@ FAR DIR *opendir(FAR const char *path) if (!path || *path == 0 || strcmp(path, "/") == 0) { inode = root_inode; - bisroot = true; + isroot = true; relpath = NULL; } else @@ -246,14 +284,13 @@ FAR DIR *opendir(FAR const char *path) * inode or a file system mountpoint. */ - dir->fd_root = inode; /* Save the inode where we start */ dir->fd_position = 0; /* This is the position in the read stream */ /* First, handle the special case of the root inode. This must be * special-cased here because the root inode might ALSO be a mountpoint. */ - if (bisroot) + if (isroot) { /* Whatever payload the root inode carries, the root inode is always * a directory inode in the pseudo-file system @@ -263,13 +300,17 @@ FAR DIR *opendir(FAR const char *path) } /* Is this a node in the pseudo filesystem? Or a mountpoint? If the node - * is the root (bisroot == TRUE), then this is a special case. + * is the root (isroot == TRUE), then this is a special case. */ #ifndef CONFIG_DISABLE_MOUNTPOINT else if (INODE_IS_MOUNTPT(inode)) { - /* Yes, the node is a file system mointpoint. */ + /* Yes, the node is a file system mountpoint */ + + dir->fd_root = inode; /* Save the inode where we start */ + + /* Open the directory at the relative path */ ret = open_mountpoint(inode, relpath, dir); if (ret != OK) @@ -280,21 +321,31 @@ FAR DIR *opendir(FAR const char *path) #endif else { - /* The node is part of the root pseudo 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. + /* The node is part of the root pseudo 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. */ - inode = inode->i_child; - if (!inode) + FAR struct inode *child = inode->i_child; + if (child) + { + /* It looks we have a valid pseudo-filesystem directory node. */ + + open_pseudodir(child, dir); + } + else if (!inode->u.i_ops) + { + /* This is a dangling node with no children and no operations. Set + * up to enumerate an empty directory. + */ + + open_emptydir(dir); + } + else { ret = ENOTDIR; goto errout_with_direntry; } - - /* It looks we have a valid pseudo-filesystem directory node. */ - - open_pseudodir(inode, dir); } inode_semgive(); |