summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-21 17:17:42 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-21 17:17:42 +0000
commit2bb67b254657c5707557082da0b23449b8309c72 (patch)
tree12e921379a6979b29804391ac650ed42c4c12fd1 /nuttx/fs
parentd7d1d7f99d0cd4549f676cf9e450124c9c4170cb (diff)
downloadpx4-nuttx-2bb67b254657c5707557082da0b23449b8309c72.tar.gz
px4-nuttx-2bb67b254657c5707557082da0b23449b8309c72.tar.bz2
px4-nuttx-2bb67b254657c5707557082da0b23449b8309c72.zip
Add FAT rmdir and unlink
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@247 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/fs_fat32.c62
-rw-r--r--nuttx/fs/fs_fat32.h11
-rw-r--r--nuttx/fs/fs_fat32util.c191
3 files changed, 226 insertions, 38 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index 81992e72d..d0561f380 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -73,7 +73,7 @@
* Private Function Prototypes
****************************************************************************/
-static int fat_open(FAR struct file *filp, const char *rel_path,
+static int fat_open(FAR struct file *filp, const char *relpath,
int oflags, mode_t mode);
static int fat_close(FAR struct file *filp);
static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen);
@@ -86,10 +86,10 @@ static int fat_sync(FAR struct file *filp);
static int fat_bind(FAR struct inode *blkdriver, const void *data,
void **handle);
static int fat_unbind(void *handle);
-static int fat_unlink(struct inode *mountpt, const char *rel_path);
-static int fat_mkdir(struct inode *mountpt, const char *rel_path,
+static int fat_unlink(struct inode *mountpt, const char *relpath);
+static int fat_mkdir(struct inode *mountpt, const char *relpath,
mode_t mode);
-static int fat_rmdir(struct inode *mountpt, const char *rel_path);
+static int fat_rmdir(struct inode *mountpt, const char *relpath);
static int fat_rename(struct inode *mountpt, const char *old_relpath,
const char *new_relpath);
@@ -120,6 +120,7 @@ const struct mountpt_operations fat_operations =
fat_unbind,
fat_unlink,
fat_mkdir,
+ fat_rmdir,
fat_rename
};
@@ -131,7 +132,7 @@ const struct mountpt_operations fat_operations =
* Name: fat_open
****************************************************************************/
-static int fat_open(FAR struct file *filp, const char *rel_path,
+static int fat_open(FAR struct file *filp, const char *relpath,
int oflags, mode_t mode)
{
struct fat_dirinfo_s dirinfo;
@@ -165,13 +166,12 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
/* Initialize the directory info structure */
memset(&dirinfo, 0, sizeof(struct fat_dirinfo_s));
- dirinfo.fs = fs;
/* Locate the directory entry for this path */
- ret = fat_finddirentry(&dirinfo, rel_path);
+ ret = fat_finddirentry(fs, &dirinfo, relpath);
- /* Three possibililities: (1) a node exists for the rel_path and
+ /* Three possibililities: (1) a node exists for the relpath and
* dirinfo describes the directory entry of the entity, (2) the
* node does not exist, or (3) some error occurred.
*/
@@ -206,7 +206,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
/* Check if the caller has sufficient privileges to open the file */
readonly = ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0);
- if (((oflags && O_WRONLY) != 0) && readonly)
+ if (((oflags & O_WRONLY) != 0) && readonly)
{
ret = -EACCES;
goto errout_with_semaphore;
@@ -236,7 +236,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
{
/* The file does not exist. Were we asked to create it? */
- if ((oflags && O_CREAT) == 0)
+ if ((oflags & O_CREAT) == 0)
{
/* No.. then we fail with -ENOENT */
ret = -ENOENT;
@@ -303,7 +303,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
/* In write/append mode, we need to set the file pointer to the end of the file */
- if ((oflags && (O_APPEND|O_WRONLY)) == (O_APPEND|O_WRONLY))
+ if ((oflags & (O_APPEND|O_WRONLY)) == (O_APPEND|O_WRONLY))
{
ff->ff_position = ff->ff_size;
}
@@ -1320,7 +1320,7 @@ static int fat_unbind(void *handle)
*
****************************************************************************/
-static int fat_unlink(struct inode *mountpt, const char *rel_path)
+static int fat_unlink(struct inode *mountpt, const char *relpath)
{
struct fat_mountpt_s *fs;
int ret;
@@ -1337,15 +1337,20 @@ static int fat_unlink(struct inode *mountpt, const char *rel_path)
fat_semtake(fs);
ret = fat_checkmount(fs);
- if (ret != OK)
+ if (ret == OK)
{
- goto errout_with_semaphore;
- }
+ /* If the file is open, the correct behavior is to remove the file
+ * name, but to keep the file cluster chain in place until the last
+ * open reference to the file is closed.
+ */
-#warning "fat_unlink is not implemented"
- ret = -ENOSYS;
+#warning "Need to defer deleting cluster chain if the file is open"
+
+ /* Remove the file */
+
+ ret = fat_remove(fs, relpath, FALSE);
+ }
- errout_with_semaphore:
fat_semgive(fs);
return ret;
}
@@ -1357,7 +1362,7 @@ static int fat_unlink(struct inode *mountpt, const char *rel_path)
*
****************************************************************************/
-static int fat_mkdir(struct inode *mountpt, const char *rel_path, mode_t mode)
+static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
{
struct fat_mountpt_s *fs;
int ret;
@@ -1394,7 +1399,7 @@ static int fat_mkdir(struct inode *mountpt, const char *rel_path, mode_t mode)
*
****************************************************************************/
-int fat_rmdir(struct inode *mountpt, const char *rel_path)
+int fat_rmdir(struct inode *mountpt, const char *relpath)
{
struct fat_mountpt_s *fs;
int ret;
@@ -1411,15 +1416,20 @@ int fat_rmdir(struct inode *mountpt, const char *rel_path)
fat_semtake(fs);
ret = fat_checkmount(fs);
- if (ret != OK)
+ if (ret == OK)
{
- goto errout_with_semaphore;
- }
+ /* If the directory is open, the correct behavior is to remove the directory
+ * name, but to keep the directory cluster chain in place until the last
+ * open reference to the directory is closed.
+ */
-#warning "fat_rmdir is not implemented"
- ret = -ENOSYS;
+#warning "Need to defer deleting cluster chain if the directory is open"
+
+ /* Remove the directory */
+
+ ret = fat_remove(fs, relpath, TRUE);
+ }
- errout_with_semaphore:
fat_semgive(fs);
return ret;
}
diff --git a/nuttx/fs/fs_fat32.h b/nuttx/fs/fs_fat32.h
index 9e10cd7d8..e8edd14c7 100644
--- a/nuttx/fs/fs_fat32.h
+++ b/nuttx/fs/fs_fat32.h
@@ -488,7 +488,6 @@ struct fat_file_s
struct fat_dirinfo_s
{
- struct fat_mountpt_s *fs; /* Pointer to the parent mountpoint */
ubyte fd_name[8+3]; /* Filename -- directory format*/
#ifdef CONFIG_FAT_LCNAMES
ubyte fd_ntflags; /* NTRes lower case flags */
@@ -557,15 +556,17 @@ EXTERN sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster);
/* Help for traverseing directory trees */
-EXTERN int fat_nextdirentry(struct fat_dirinfo_s *dirinfo);
-EXTERN int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path);
+EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
+EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
+ const char *path);
-/* File creation helpers */
+/* File creation and removal helpers */
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
+EXTERN int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory);
-/* Mountpoint and fFile buffer cache (for partial sector accesses) */
+/* Mountpoint and file buffer cache (for partial sector accesses) */
EXTERN int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector);
EXTERN int fat_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff);
diff --git a/nuttx/fs/fs_fat32util.c b/nuttx/fs/fs_fat32util.c
index 826d13bec..eb7981a56 100644
--- a/nuttx/fs/fs_fat32util.c
+++ b/nuttx/fs/fs_fat32util.c
@@ -471,7 +471,7 @@ static int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *
return OK;
}
- ret = fat_nextdirentry(dirinfo);
+ ret = fat_nextdirentry(fs, dirinfo);
if (ret < 0)
{
return ret;
@@ -1583,9 +1583,8 @@ sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster)
*
****************************************************************************/
-int fat_nextdirentry(struct fat_dirinfo_s *dirinfo)
+int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
{
- struct fat_mountpt_s *fs = dirinfo->fs;
unsigned int cluster;
unsigned int ndx;
@@ -1674,9 +1673,9 @@ int fat_nextdirentry(struct fat_dirinfo_s *dirinfo)
*
****************************************************************************/
-int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path)
+int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
+ const char *path)
{
- struct fat_mountpt_s *fs = dirinfo->fs;
size_t cluster;
ubyte *direntry = NULL;
char terminator;
@@ -1778,7 +1777,7 @@ int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path)
/* No... get the next directory index and try again */
- if (fat_nextdirentry(dirinfo) != OK)
+ if (fat_nextdirentry(fs, dirinfo) != OK)
{
return -ENOENT;
}
@@ -1936,6 +1935,184 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
}
/****************************************************************************
+ * Name: fat_remove
+ *
+ * Desciption: Remove a directory or file from the file system. This
+ * implements both rmdir() and unlink().
+ *
+ ****************************************************************************/
+
+int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
+{
+ struct fat_dirinfo_s dirinfo;
+ uint32 dircluster;
+ size_t dirsector;
+ int ret;
+
+ /* Find the directory entry referring to the entry to be deleted */
+
+ ret = fat_finddirentry(fs, &dirinfo, relpath);
+ if (ret != OK)
+ {
+ /* No such path */
+
+ return -ENOENT;
+ }
+
+ /* Check if this is a FAT12/16 root directory */
+
+ if (dirinfo.fd_entry == NULL)
+ {
+ /* The root directory cannot be removed */
+
+ return -EPERM;
+ }
+
+ /* The object has to have write access to be deleted */
+
+ if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0)
+ {
+ /* It is a read-only entry */
+
+ return -EACCES;
+ }
+
+ /* Get the directory sector and cluster containing the
+ * entry to be deleted
+ */
+
+ dirsector = fs->fs_currentsector;
+ dircluster =
+ ((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
+ DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
+
+ /* Is this entry a directory? */
+
+ if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY)
+ {
+ /* It is a sub-directory. Check if we are be asked to remove
+ * a directory or a file.
+ */
+
+ if (!directory)
+ {
+ /* We are asked to delete a file */
+
+ return -EISDIR;
+ }
+
+ /* We are asked to delete a directory. Check if this
+ * sub-directory is empty
+ */
+
+ dirinfo.fd_currcluster = dircluster;
+ dirinfo.fd_currsector = fat_cluster2sector(fs, dircluster);
+ dirinfo.fd_index = 2;
+
+ /* Loop until either (1) an entry is found in the directory
+ * (error), (2) the directory is found to be empty, or (3) some
+ * error occurs.
+ */
+
+ for (;;)
+ {
+ unsigned int subdirindex;
+ ubyte *subdirentry;
+
+ /* Make sure that the sector containing the of the
+ * subdirectory sector is in the cache
+ */
+
+ ret = fat_fscacheread(fs, dirinfo.fd_currsector);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Get a reference to the next entry in the directory */
+
+ subdirindex = (dirinfo.fd_index & DIRSEC_NDXMASK(fs)) * 32;
+ subdirentry = &fs->fs_buffer[subdirindex];
+
+ /* Is this the last entry in the direcory? */
+
+ if (subdirentry[DIR_NAME] == DIR0_ALLEMPTY)
+ {
+ /* Yes then the directory is empty. Break out of the
+ * loop and delete the directory.
+ */
+
+ break;
+ }
+
+ /* Check if the next entry refers to a file or directory */
+
+ if (subdirentry[DIR_NAME] != DIR0_EMPTY &&
+ !(DIR_GETATTRIBUTES(subdirentry) & FATATTR_VOLUMEID))
+ {
+ /* The directory is not empty */
+
+ return -ENOTEMPTY;
+ }
+
+ /* Get the next directgory entry */
+
+ ret = fat_nextdirentry(fs, &dirinfo);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ }
+ else
+ {
+ /* It is a file. Check if we are be asked to remove a directory
+ * or a file.
+ */
+
+ if (directory)
+ {
+ /* We are asked to remove a directory */
+
+ return -ENOTDIR;
+ }
+ }
+
+ /* Make sure that the directory containing the entry to be deleted is
+ * in the cache.
+ */
+
+ ret = fat_fscacheread(fs, dirsector);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Mark the directory entry 'deleted' */
+
+ dirinfo.fd_entry[DIR_NAME] = DIR0_EMPTY;
+ fs->fs_dirty = TRUE;
+
+ /* And remove the cluster chain making up the subdirectory */
+
+ ret = fat_removechain(fs, dircluster);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Update the FSINFO sector (FAT32) */
+
+ ret = fat_updatefsinfo(fs);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
* Name: fat_fscacheread
*
* Desciption: Read the specified sector into the sector cache, flushing any
@@ -2092,7 +2269,7 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff)
* Name: fat_updatefsinfo
*
* Desciption: Flush evertyhing buffered for the mountpoint and update
- * the FSINFO sector, if appropriate
+ * the FSINFO sector, if appropriate
*
****************************************************************************/