mirror of
https://github.com/apache/nuttx.git
synced 2026-05-19 20:06:24 +08:00
Fat dir operations seem to work
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@254 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
/****************************************************************************
|
||||
@@ -76,10 +77,54 @@ static const char g_testmsg[] = "This is a write test";
|
||||
|
||||
static int g_nerrors = 0;
|
||||
|
||||
static char g_namebuffer[256];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fail_read_open
|
||||
****************************************************************************/
|
||||
|
||||
static void show_directories( const char *path, int indent )
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *direntry;
|
||||
int i;
|
||||
|
||||
dirp = opendir(path);
|
||||
if ( !dirp )
|
||||
{
|
||||
printf("show_directories: ERROR opendir(\"%s\") failed with errno=%d\n", path, *get_errno_ptr());
|
||||
g_nerrors++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (direntry = readdir(dirp); direntry; direntry = readdir(dirp))
|
||||
{
|
||||
for (i = 0; i < 2*indent; i++)
|
||||
{
|
||||
putchar(' ');
|
||||
}
|
||||
if (DIRENT_ISDIRECTORY(direntry->d_type))
|
||||
{
|
||||
char *subdir;
|
||||
printf("%s/\n", direntry->d_name);
|
||||
sprintf(g_namebuffer, "%s/%s", path, direntry->d_name);
|
||||
subdir = strdup(g_namebuffer);
|
||||
show_directories( subdir, indent + 1);
|
||||
free(subdir);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s\n", direntry->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fail_read_open
|
||||
****************************************************************************/
|
||||
@@ -396,11 +441,13 @@ int user_start(int argc, char *argv[])
|
||||
{
|
||||
/* Read a test file that is already on the test file system image */
|
||||
|
||||
show_directories("", 0);
|
||||
read_test_file(g_testfile1);
|
||||
|
||||
/* Write a test file into a pre-existing directory on the test file system */
|
||||
|
||||
write_test_file(g_testfile2);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Read the file that we just wrote */
|
||||
|
||||
@@ -421,6 +468,7 @@ int user_start(int argc, char *argv[])
|
||||
/* Try unlink() against the test file1. It should succeed. */
|
||||
|
||||
succeed_unlink(g_testfile1);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Attempt to open testfile1 should fail with ENOENT */
|
||||
|
||||
@@ -437,6 +485,7 @@ int user_start(int argc, char *argv[])
|
||||
/* Try unlink() against the test file2. It should succeed. */
|
||||
|
||||
succeed_unlink(g_testfile2);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Try mkdir() against the test dir1. It should fail with EEXIST. */
|
||||
|
||||
@@ -445,10 +494,12 @@ int user_start(int argc, char *argv[])
|
||||
/* Try rmdir() against the test directory. It should now succeed. */
|
||||
|
||||
succeed_rmdir(g_testdir1);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Try mkdir() against the test dir2. It should succeed */
|
||||
|
||||
succeed_mkdir(g_testdir2);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Try mkdir() against the test dir2. It should fail with EXIST */
|
||||
|
||||
@@ -457,6 +508,7 @@ int user_start(int argc, char *argv[])
|
||||
/* Write a test file into a new directory on the test file system */
|
||||
|
||||
write_test_file(g_testfile3);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Read the file that we just wrote */
|
||||
|
||||
@@ -465,6 +517,7 @@ int user_start(int argc, char *argv[])
|
||||
/* Use mkdir() to create test dir3. It should succeed */
|
||||
|
||||
succeed_mkdir(g_testdir3);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Try rename() on the root directory. Should fail with EXDEV*/
|
||||
|
||||
@@ -477,10 +530,12 @@ int user_start(int argc, char *argv[])
|
||||
/* Try rename() to a non-existing directory. Should succeed */
|
||||
|
||||
succeed_rename(g_testdir3, g_testdir4);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Try rename() of file. Should work. */
|
||||
|
||||
succeed_rename(g_testfile3, g_testfile4);
|
||||
show_directories("", 0);
|
||||
|
||||
/* Make sure that we can still read the renamed file */
|
||||
|
||||
|
||||
@@ -254,15 +254,6 @@ static void cmd_ls(const char *cmd, char *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
if (DIRENT_ISFILE(entryp->d_type))
|
||||
{
|
||||
#ifdef CONFIG_FULL_PATH
|
||||
printf(" %s/%s\n", arg, entryp->d_name);
|
||||
#else
|
||||
printf(" %s\n", entryp->d_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (DIRENT_ISDIRECTORY(entryp->d_type))
|
||||
{
|
||||
#ifdef CONFIG_FULL_PATH
|
||||
@@ -271,6 +262,15 @@ static void cmd_ls(const char *cmd, char *arg)
|
||||
printf(" %s/\n", entryp->d_name);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_FULL_PATH
|
||||
printf(" %s/%s\n", arg, entryp->d_name);
|
||||
#else
|
||||
printf(" %s\n", entryp->d_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
closedir(dirp);
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+21
-1
@@ -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,9 +138,16 @@ 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;
|
||||
|
||||
|
||||
+78
-96
@@ -50,81 +50,6 @@
|
||||
* 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;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* 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.
|
||||
*/
|
||||
|
||||
inode_addref(inode); /* Now we have two references on inode */
|
||||
if (!isroot)
|
||||
{
|
||||
inode = inode->i_child;
|
||||
if (!inode)
|
||||
{
|
||||
ret = ENOTDIR;
|
||||
goto errout_with_direntry;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
+22
-6
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -54,9 +54,13 @@
|
||||
*/
|
||||
|
||||
#define DTYPE_FILE 0x01
|
||||
#define DTYPE_DIRECTORY 0x02
|
||||
#define DTYPE_CHR 0x02
|
||||
#define DTYPE_BLK 0x04
|
||||
#define DTYPE_DIRECTORY 0x08
|
||||
|
||||
#define DIRENT_ISFILE(dtype) (((dtype) & DTYPE_FILE) != 0 )
|
||||
#define DIRENT_ISCHR(dtype) (((dtype) & DTYPE_CHR) != 0 )
|
||||
#define DIRENT_ISBLK(dtype) (((dtype) & DTYPE_BLK) != 0 )
|
||||
#define DIRENT_ISDIRECTORY(dtype) (((dtype) & DTYPE_DIRECTORY) != 0 )
|
||||
|
||||
/************************************************************
|
||||
|
||||
@@ -209,8 +209,6 @@ int pthread_completejoin(pid_t pid, FAR void *exit_value)
|
||||
|
||||
void pthread_destroyjoin(FAR join_t *pjoin)
|
||||
{
|
||||
int status;
|
||||
|
||||
dbg("pjoin=0x%p\n", pjoin);
|
||||
|
||||
/* Remove the join info from the set of joins */
|
||||
|
||||
Reference in New Issue
Block a user