summaryrefslogtreecommitdiff
path: root/nuttx/fs
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-21 19:24:30 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-05-21 19:24:30 +0000
commit3306f330105dafeb0423943fe21fc4a4a30eedc2 (patch)
tree82550739be4e98f5e6ccd3a850204602e0467242 /nuttx/fs
parent2bb67b254657c5707557082da0b23449b8309c72 (diff)
downloadpx4-nuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.tar.gz
px4-nuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.tar.bz2
px4-nuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.zip
Add FAT mkdir()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@248 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/fs')
-rw-r--r--nuttx/fs/fs_fat32.c180
-rw-r--r--nuttx/fs/fs_fat32.h2
-rw-r--r--nuttx/fs/fs_fat32util.c342
3 files changed, 350 insertions, 174 deletions
diff --git a/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c
index d0561f380..1307520b2 100644
--- a/nuttx/fs/fs_fat32.c
+++ b/nuttx/fs/fs_fat32.c
@@ -1365,7 +1365,16 @@ static int fat_unlink(struct inode *mountpt, const char *relpath)
static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
{
struct fat_mountpt_s *fs;
- int ret;
+ struct fat_dirinfo_s dirinfo;
+ ubyte *direntry;
+ ubyte *direntry2;
+ size_t parentsector;
+ ssize_t dirsector;
+ sint32 dircluster;
+ uint32 parentcluster;
+ uint32 crtime;
+ unsigned int i;
+ int ret;
/* Sanity checks */
@@ -1384,8 +1393,173 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
goto errout_with_semaphore;
}
-#warning "fat_mkdir is not implemented"
- ret = -ENOSYS;
+ /* Find the directory where the new directory should be created. */
+
+ ret = fat_finddirentry(fs, &dirinfo, relpath);
+
+ /* If anything exists at this location, then we fail with EEXIST */
+
+ if (ret == OK)
+ {
+ ret = -EEXIST;
+ goto errout_with_semaphore;
+ }
+
+ /* What we want to see is for fat_finddirentry to fail with -ENOENT.
+ * This error means that no failure occurred but that nothing exists
+ * with this name.
+ */
+
+ if (ret != -ENOENT)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* NOTE: There is no check that dirinfo.fd_name contains the final
+ * directory name. We could be creating an intermediate directory
+ * in the full relpath.
+ */
+
+ /* Allocate a directory entry for the new directory in this directory */
+
+ ret = fat_allocatedirentry(fs, &dirinfo);
+ if (ret != OK)
+ {
+ goto errout_with_semaphore;
+ }
+ parentsector = fs->fs_currentsector;
+
+ /* Allocate a cluster for new directory */
+
+ dircluster = fat_createchain(fs);
+ if (dircluster < 0)
+ {
+ ret = dircluster;
+ goto errout_with_semaphore;
+ }
+ else if (dircluster < 2)
+ {
+ ret = -ENOSPC;
+ goto errout_with_semaphore;
+ }
+
+ dirsector = fat_cluster2sector(fs, dircluster);
+ if (dirsector < 0)
+ {
+ ret = dirsector;
+ goto errout_with_semaphore;
+ }
+
+ /* Flush any existing, dirty data in fs_buffer (because we need
+ * it to create the directory entries.
+ */
+
+ ret = fat_fscacheflush(fs);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Get a pointer to the first directory entry in the sector */
+
+ direntry = fs->fs_buffer;
+
+ /* Now erase the contents of fs_buffer */
+
+ fs->fs_currentsector = dirsector;
+ memset(direntry, 0, fs->fs_hwsectorsize);
+
+ /* Now clear all sectors in the new directory cluster (except for the first) */
+
+ for (i = 1; i < fs->fs_fatsecperclus; i++)
+ {
+ ret = fat_hwwrite(fs, direntry, ++dirsector, 1);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+ }
+
+ /* Now create the "." directory entry in the first directory slot */
+
+ memset(&direntry[DIR_NAME], ' ', 8+3);
+ direntry[DIR_NAME] = '.';
+ DIR_PUTATTRIBUTES(direntry, FATATTR_DIRECTORY);
+
+ crtime = fat_gettime();
+ DIR_PUTCRTIME(direntry, crtime & 0xffff);
+ DIR_PUTWRTTIME(direntry, crtime & 0xffff);
+ DIR_PUTCRDATE(direntry, crtime >> 16);
+ DIR_PUTWRTDATE(direntry, crtime >> 16);
+
+ /* Create ".." directory entry in the second directory slot */
+
+ direntry2 = direntry + 32;
+
+ /* So far, the two entries are nearly the same */
+
+ memcpy(direntry2, direntry, 32);
+ direntry2[DIR_NAME+1] = '.';
+
+ /* Now add the cluster information to both directory entries */
+
+ DIR_PUTFSTCLUSTHI(direntry, dircluster >> 16);
+ DIR_PUTFSTCLUSTLO(direntry, dircluster);
+
+ parentcluster = dirinfo.fd_startcluster;
+ if (fs->fs_type != FSTYPE_FAT32 && parentcluster == fs->fs_rootbase)
+ {
+ parentcluster = 0;
+ }
+
+ DIR_PUTFSTCLUSTHI(direntry2, parentcluster >> 16);
+ DIR_PUTFSTCLUSTLO(direntry2, parentcluster);
+
+ /* Save the first sector of the directory cluster and re-read
+ * the parentsector
+ */
+
+ fs->fs_dirty = TRUE;
+ ret = fat_fscacheread(fs, parentsector);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Initialize the new entry directory entry in the parent directory */
+
+ direntry = dirinfo.fd_entry;
+ memset(direntry, 0, 32);
+
+ memcpy(direntry, dirinfo.fd_name, 8+3);
+#ifdef CONFIG_FLAT_LCNAMES
+ DIR_PUTNTRES(direntry, dirinfo.fd_ntflags);
+#endif
+ DIR_PUTATTRIBUTES(dirinfo.fd_entry, FATATTR_DIRECTORY);
+
+ /* Same creation time as for . and .. */
+
+ DIR_PUTCRTIME(dirinfo.fd_entry, crtime & 0xffff);
+ DIR_PUTWRTTIME(dirinfo.fd_entry, crtime & 0xffff);
+ DIR_PUTCRDATE(dirinfo.fd_entry, crtime >> 16);
+ DIR_PUTWRTDATE(dirinfo.fd_entry, crtime >> 16);
+
+ /* Set subdirectory start cluster */
+
+ DIR_PUTFSTCLUSTLO(dirinfo.fd_entry, dircluster);
+ DIR_PUTFSTCLUSTHI(dirinfo.fd_entry, dircluster >> 16);
+
+ /* Now update the FAT32 FSINFO sector */
+
+ fs->fs_dirty = TRUE;
+ ret = fat_updatefsinfo(fs);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ fat_semgive(fs);
+ return OK;
errout_with_semaphore:
fat_semgive(fs);
diff --git a/nuttx/fs/fs_fat32.h b/nuttx/fs/fs_fat32.h
index e8edd14c7..dd86b3fa2 100644
--- a/nuttx/fs/fs_fat32.h
+++ b/nuttx/fs/fs_fat32.h
@@ -559,6 +559,7 @@ EXTERN sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster);
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);
+EXTERN int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
/* File creation and removal helpers */
@@ -568,6 +569,7 @@ EXTERN int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean
/* Mountpoint and file buffer cache (for partial sector accesses) */
+EXTERN int fat_fscacheflush(struct fat_mountpt_s *fs);
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);
EXTERN int fat_ffcacheread(struct fat_mountpt_s *fs, struct fat_file_s *ff, size_t sector);
diff --git a/nuttx/fs/fs_fat32util.c b/nuttx/fs/fs_fat32util.c
index eb7981a56..d6d3da0cd 100644
--- a/nuttx/fs/fs_fat32util.c
+++ b/nuttx/fs/fs_fat32util.c
@@ -84,56 +84,6 @@
****************************************************************************/
/****************************************************************************
- * Name: fat_fscacheflush
- *
- * Desciption: Flush any dirty sectors as necessary
- *
- ****************************************************************************/
-
-static int fat_fscacheflush(struct fat_mountpt_s *fs)
-{
- int ret;
-
- /* Check if the fs_buffer is dirty. In this case, we will write back the
- * contents of fs_buffer.
- */
-
- if (fs->fs_dirty)
- {
- /* Write the dirty sector */
-
- ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1);
- if (ret < 0)
- {
- return ret;
- }
-
- /* Does the sector lie in the FAT region? */
-
- if (fs->fs_currentsector < fs->fs_fatbase + fs->fs_fatsize)
- {
- /* Yes, then make the change in the FAT copy as well */
- int i;
-
- for (i = fs->fs_fatnumfats; i >= 2; i--)
- {
- fs->fs_currentsector += fs->fs_fatsize;
- ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1);
- if (ret < 0)
- {
- return ret;
- }
- }
- }
-
- /* No longer dirty */
-
- fs->fs_dirty = FALSE;
- }
- return OK;
-}
-
-/****************************************************************************
* Name: fat_path2dirname
*
* Desciption: Convert a user filename into a properly formatted FAT
@@ -410,127 +360,6 @@ static inline int fat_dirname2path(char *path, struct fat_dirinfo_s *dirinfo)
}
/****************************************************************************
- * Name: fat_allocatedirentry
- *
- * Desciption: Find a free directory entry
- *
- ****************************************************************************/
-
-static int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
-{
- sint32 cluster;
- size_t sector;
- ubyte *direntry;
- ubyte ch;
- int ret;
- int i;
-
- /* Re-initialize directory object */
-
- cluster = dirinfo->fd_startcluster;
- if (cluster)
- {
- /* Cluster chain can be extended */
-
- dirinfo->fd_currcluster = cluster;
- dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
- }
- else
- {
- /* Fixed size FAT12/16 root directory is at fixxed offset/size */
-
- dirinfo->fd_currsector = fs->fs_rootbase;
- }
- dirinfo->fd_index = 0;
-
- for (;;)
- {
- unsigned int dirindex;
-
- /* Read the directory sector into fs_buffer */
-
- ret = fat_fscacheread(fs, dirinfo->fd_currsector);
- if (ret < 0)
- {
- return ret;
- }
-
- /* Get a pointer to the entry at fd_index */
-
- dirindex = (dirinfo->fd_index & DIRSEC_NDXMASK(fs)) * 32;
- direntry = &fs->fs_buffer[dirindex];
-
- /* Check if this directory entry is empty */
-
- ch = direntry[DIR_NAME];
- if (ch == DIR0_ALLEMPTY || ch == DIR0_EMPTY)
- {
- /* It is empty -- we have found a directory entry */
-
- dirinfo->fd_entry = direntry;
- return OK;
- }
-
- ret = fat_nextdirentry(fs, dirinfo);
- if (ret < 0)
- {
- return ret;
- }
- }
-
- /* If we get here, then we have reached the end of the directory table
- * in this sector without finding a free directory enty.
- *
- * It this is a fixed size dirctory entry, then this is an error.
- * Otherwise, we can try to extend the directory cluster chain to
- * make space for the new directory entry.
- */
-
- if (!cluster)
- {
- /* The size is fixed */
- return -ENOSPC;
- }
-
- /* Try to extend the cluster chain for this directory */
-
- cluster = fat_extendchain(fs, dirinfo->fd_currcluster);
- if (cluster < 0)
- {
- return cluster;
- }
-
- /* Flush out any cached date in fs_buffer.. we are going to use
- * it to initialize the new directory cluster.
- */
-
- ret = fat_fscacheflush(fs);
- if (ret < 0)
- {
- return ret;
- }
-
- /* Clear all sectors comprising the new directory cluster */
-
- fs->fs_currentsector = fat_cluster2sector(fs, cluster);
- memset(fs->fs_buffer, 0, fs->fs_hwsectorsize);
-
- sector = sector;
- for (i = fs->fs_fatsecperclus; i; i--)
- {
- ret = fat_hwwrite(fs, fs->fs_buffer, sector, 1);
- if ( ret < 0)
- {
- return ret;
- }
- sector++;
- }
-
- dirinfo->fd_entry = fs->fs_buffer;
- return OK;
-}
-
-/****************************************************************************
* Name: fat_checkfsinfo
*
* Desciption: Read the FAT32 FSINFO sector
@@ -1824,6 +1653,127 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
}
/****************************************************************************
+ * Name: fat_allocatedirentry
+ *
+ * Desciption: Find a free directory entry
+ *
+ ****************************************************************************/
+
+int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
+{
+ sint32 cluster;
+ size_t sector;
+ ubyte *direntry;
+ ubyte ch;
+ int ret;
+ int i;
+
+ /* Re-initialize directory object */
+
+ cluster = dirinfo->fd_startcluster;
+ if (cluster)
+ {
+ /* Cluster chain can be extended */
+
+ dirinfo->fd_currcluster = cluster;
+ dirinfo->fd_currsector = fat_cluster2sector(fs, cluster);
+ }
+ else
+ {
+ /* Fixed size FAT12/16 root directory is at fixxed offset/size */
+
+ dirinfo->fd_currsector = fs->fs_rootbase;
+ }
+ dirinfo->fd_index = 0;
+
+ for (;;)
+ {
+ unsigned int dirindex;
+
+ /* Read the directory sector into fs_buffer */
+
+ ret = fat_fscacheread(fs, dirinfo->fd_currsector);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Get a pointer to the entry at fd_index */
+
+ dirindex = (dirinfo->fd_index & DIRSEC_NDXMASK(fs)) * 32;
+ direntry = &fs->fs_buffer[dirindex];
+
+ /* Check if this directory entry is empty */
+
+ ch = direntry[DIR_NAME];
+ if (ch == DIR0_ALLEMPTY || ch == DIR0_EMPTY)
+ {
+ /* It is empty -- we have found a directory entry */
+
+ dirinfo->fd_entry = direntry;
+ return OK;
+ }
+
+ ret = fat_nextdirentry(fs, dirinfo);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+
+ /* If we get here, then we have reached the end of the directory table
+ * in this sector without finding a free directory enty.
+ *
+ * It this is a fixed size dirctory entry, then this is an error.
+ * Otherwise, we can try to extend the directory cluster chain to
+ * make space for the new directory entry.
+ */
+
+ if (!cluster)
+ {
+ /* The size is fixed */
+ return -ENOSPC;
+ }
+
+ /* Try to extend the cluster chain for this directory */
+
+ cluster = fat_extendchain(fs, dirinfo->fd_currcluster);
+ if (cluster < 0)
+ {
+ return cluster;
+ }
+
+ /* Flush out any cached date in fs_buffer.. we are going to use
+ * it to initialize the new directory cluster.
+ */
+
+ ret = fat_fscacheflush(fs);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Clear all sectors comprising the new directory cluster */
+
+ fs->fs_currentsector = fat_cluster2sector(fs, cluster);
+ memset(fs->fs_buffer, 0, fs->fs_hwsectorsize);
+
+ sector = sector;
+ for (i = fs->fs_fatsecperclus; i; i--)
+ {
+ ret = fat_hwwrite(fs, fs->fs_buffer, sector, 1);
+ if ( ret < 0)
+ {
+ return ret;
+ }
+ sector++;
+ }
+
+ dirinfo->fd_entry = fs->fs_buffer;
+ return OK;
+}
+
+/****************************************************************************
* Name: fat_dirtruncate
*
* Desciption: Truncate an existing file to zero length
@@ -2113,6 +2063,56 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
}
/****************************************************************************
+ * Name: fat_fscacheflush
+ *
+ * Desciption: Flush any dirty sector if fs_buffer as necessary
+ *
+ ****************************************************************************/
+
+int fat_fscacheflush(struct fat_mountpt_s *fs)
+{
+ int ret;
+
+ /* Check if the fs_buffer is dirty. In this case, we will write back the
+ * contents of fs_buffer.
+ */
+
+ if (fs->fs_dirty)
+ {
+ /* Write the dirty sector */
+
+ ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Does the sector lie in the FAT region? */
+
+ if (fs->fs_currentsector < fs->fs_fatbase + fs->fs_fatsize)
+ {
+ /* Yes, then make the change in the FAT copy as well */
+ int i;
+
+ for (i = fs->fs_fatnumfats; i >= 2; i--)
+ {
+ fs->fs_currentsector += fs->fs_fatsize;
+ ret = fat_hwwrite(fs, fs->fs_buffer, fs->fs_currentsector, 1);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+ }
+
+ /* No longer dirty */
+
+ fs->fs_dirty = FALSE;
+ }
+ return OK;
+}
+
+/****************************************************************************
* Name: fat_fscacheread
*
* Desciption: Read the specified sector into the sector cache, flushing any