mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 01:05:54 +08:00
Add FAT mkdir()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@248 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -142,6 +142,6 @@
|
||||
|
||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||
* Added FAT support for unlink() and rmdir()
|
||||
* Added FAT support for unlink(), mkdir() and rmdir()
|
||||
* Started m68322
|
||||
|
||||
|
||||
@@ -573,7 +573,7 @@ Other memory:
|
||||
|
||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||
* Added FAT support for unlink() and rmdir()
|
||||
* Added FAT support for unlink(), mkdir() and rmdir()
|
||||
* Started m68322
|
||||
</pre></ul>
|
||||
|
||||
|
||||
+283
-159
File diff suppressed because it is too large
Load Diff
+177
-3
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
+171
-171
@@ -83,56 +83,6 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
*
|
||||
@@ -409,127 +359,6 @@ static inline int fat_dirname2path(char *path, struct fat_dirinfo_s *dirinfo)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
*
|
||||
@@ -1823,6 +1652,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
|
||||
*
|
||||
@@ -2112,6 +2062,56 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user