summaryrefslogtreecommitdiff
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
parent2bb67b254657c5707557082da0b23449b8309c72 (diff)
downloadnuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.tar.gz
nuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.tar.bz2
nuttx-3306f330105dafeb0423943fe21fc4a4a30eedc2.zip
Add FAT mkdir()
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@248 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html2
-rw-r--r--nuttx/examples/mount/mount_main.c442
-rw-r--r--nuttx/fs/fs_fat32.c180
-rw-r--r--nuttx/fs/fs_fat32.h2
-rw-r--r--nuttx/fs/fs_fat32util.c342
6 files changed, 635 insertions, 335 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 060eb3f01..eaf9de128 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -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
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 49db96df2..e16071e1a 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -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>
diff --git a/nuttx/examples/mount/mount_main.c b/nuttx/examples/mount/mount_main.c
index 75cc3c2ce..ef12c4bb5 100644
--- a/nuttx/examples/mount/mount_main.c
+++ b/nuttx/examples/mount/mount_main.c
@@ -39,6 +39,7 @@
#include <sys/mount.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
@@ -64,15 +65,257 @@ static const char g_target[] = "/mnt/fs";
static const char g_filesystemtype[] = "vfat";
static const char g_testdir1[] = "/mnt/fs/TestDir";
+static const char g_testdir2[] = "/mnt/fs/NewDir";
static const char g_testfile1[] = "/mnt/fs/TestDir/TestFile.txt";
static const char g_testfile2[] = "/mnt/fs/TestDir/WritTest.txt";
+static const char g_testfile3[] = "/mnt/fs/NewDir/WritTest.txt";
static const char g_testmsg[] = "This is a write test";
+static int g_nerrors = 0;
+
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
+ * Name: fail_read_open
+ ****************************************************************************/
+
+static void fail_read_open(const char *path, int expectederror)
+{
+ int fd;
+
+ printf("fail_read_open: Try open(%s) for reading\n", path);
+
+ fd = open(path, O_RDONLY);
+ if (fd >= 0)
+ {
+ printf("fail_read_open: ERROR open(%s) succeeded\n", path);
+ g_nerrors++;
+ close(fd);
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_read_open: ERROR open(%s) failed with errno=%d (expected %d)\n",
+ path, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: read_test_file
+ ****************************************************************************/
+
+static void read_test_file(const char *path)
+{
+ char buffer[128];
+ int nbytes;
+ int fd;
+
+ /* Read a test file that is already on the test file system image */
+
+ printf("read_test_file: opening %s for reading\n", path);
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ {
+ printf("read_test_file: ERROR failed to open %s, errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+ else
+ {
+ memset(buffer, 0, 128);
+ nbytes = read(fd, buffer, 128);
+ if (nbytes < 0)
+ {
+ printf("read_test_file: ERROR failed to read from %s, errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+ else
+ {
+ buffer[127]='\0';
+ printf("read_test_file: Read \"%s\" from %s\n", buffer, path);
+ }
+ close(fd);
+ }
+}
+
+/****************************************************************************
+ * Name: write_test_file
+ ****************************************************************************/
+
+static void write_test_file(const char *path)
+{
+ int fd;
+
+ /* Write a test file into a pre-existing file on the test file system */
+
+ printf("write_test_file: opening %s for writing\n", path);
+
+ fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ printf("write_test_file: ERROR failed to open %s for writing, errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+ else
+ {
+ int nbytes = write(fd, g_testmsg, strlen(g_testmsg));
+ if (nbytes < 0)
+ {
+ printf("write_test_file: ERROR failed to write to %s, errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+ else
+ {
+ printf("write_test_file: wrote %d bytes to %s\n", nbytes, path);
+ }
+ close(fd);
+ }
+}
+
+/****************************************************************************
+ * Name: fail_mkdir
+ ****************************************************************************/
+
+static void fail_mkdir(const char *path, int expectederror)
+{
+ int ret;
+
+ /* Try mkdir() against a file or directory. It should fail with expectederror */
+
+ printf("fail_mkdir: Try mkdir(%s)\n", path);
+
+ ret = mkdir(path, 0666);
+ if (ret == 0)
+ {
+ printf("fail_mkdir: ERROR mkdir(%s) succeeded\n", path);
+ g_nerrors++;
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_mkdir: ERROR mkdir(%s) failed with errno=%d (expected %d)\n",
+ path, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: succeed_mkdir
+ ****************************************************************************/
+
+static void succeed_mkdir(const char *path)
+{
+ int ret;
+
+ printf("succeed_mkdir: Try mkdir(%s)\n", path);
+
+ ret = mkdir(path, 0666);
+ if (ret != 0)
+ {
+ printf("succeed_mkdir: ERROR mkdir(%s) failed with errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: fail_rmdir
+ ****************************************************************************/
+
+static void fail_rmdir(const char *path, int expectederror)
+{
+ int ret;
+
+ /* Try rmdir() against a file or directory. It should fail with expectederror */
+
+ printf("fail_rmdir: Try rmdir(%s)\n", path);
+
+ ret = rmdir(path);
+ if (ret == 0)
+ {
+ printf("fail_rmdir: ERROR rmdir(%s) succeeded\n", path);
+ g_nerrors++;
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_rmdir: ERROR rmdir(%s) failed with errno=%d (expected %d)\n",
+ path, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: succeed_rmdir
+ ****************************************************************************/
+
+static void succeed_rmdir(const char *path)
+{
+ int ret;
+
+ printf("succeed_rmdir: Try rmdir(%s)\n", path);
+
+ ret = rmdir(path);
+ if (ret != 0)
+ {
+ printf("succeed_rmdir: ERROR rmdir(%s) failed with errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: fail_unlink
+ ****************************************************************************/
+
+static void fail_unlink(const char *path, int expectederror)
+{
+ int ret;
+
+ /* Try unlink() against a file or directory. It should fail with expectederror */
+
+ printf("fail_unlink: Try unlink(%s)\n", path);
+
+ ret = unlink(path);
+ if (ret == 0)
+ {
+ printf("fail_unlink: ERROR unlink(%s) succeeded\n", path);
+ g_nerrors++;
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_unlink: ERROR unlink(%s) failed with errno=%d (expected %d)\n",
+ path, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: succeed_unlink
+ ****************************************************************************/
+
+static void succeed_unlink(const char *path)
+{
+ int ret;
+
+ /* Try unlink() against the test file. It should succeed. */
+
+ printf("succeed_unlink: Try unlink(%s)\n", path);
+
+ ret = unlink(path);
+ if (ret != 0)
+ {
+ printf("succeed_unlink: ERROR unlink(%s) failed with errno=%d\n",
+ path, *get_errno_ptr());
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -90,217 +333,98 @@ void user_initialize(void)
int user_start(int argc, char *argv[])
{
- char buffer[128];
- int nbytes;
int ret;
/* Mount the test file system (see arch/sim/src/up_deviceimage.c */
- printf("main: mounting %s filesystem at target=%s with source=%s\n",
+ printf("user_start: mounting %s filesystem at target=%s with source=%s\n",
g_filesystemtype, g_target, g_source);
ret = mount(g_source, g_target, g_filesystemtype, 0, NULL);
- printf("main: mount() returned %d\n", ret);
+ printf("user_start: mount() returned %d\n", ret);
if (ret == 0)
{
/* Read a test file that is already on the test file system image */
- printf("main: opening %s for reading\n", g_testfile1);
+ read_test_file(g_testfile1);
- int fd = open(g_testfile1, O_RDONLY);
- if (fd < 0)
- {
- printf("main: ERROR failed to open %s, errno=%d\n",
- g_testfile1, *get_errno_ptr());
- }
- else
- {
- memset(buffer, 0, 128);
- nbytes = read(fd, buffer, 128);
- if (nbytes < 0)
- {
- printf("main: ERROR failed to read from %s, errno=%d\n",
- g_testfile1, *get_errno_ptr());
- }
- else
- {
- buffer[127]='\0';
- printf("main: Read \"%s\" from %s\n", buffer, g_testfile1);
- }
- close(fd);
- }
-
- /* Write a test file into a pre-existing file on the test file system */
+ /* Write a test file into a pre-existing directory on the test file system */
- printf("main: opening %s for writing\n", g_testfile2);
-
- fd = open(g_testfile2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (fd < 0)
- {
- printf("main: ERROR failed to open %s for writing, errno=%d\n",
- g_testfile2, *get_errno_ptr());
- }
- else
- {
- int nbytes = write(fd, g_testmsg, strlen(g_testmsg));
- if (nbytes < 0)
- {
- printf("main: ERROR failed to write to %s, errno=%d\n",
- g_testfile2, *get_errno_ptr());
- }
- else
- {
- printf("main: wrote %d bytes to %s\n", nbytes, g_testfile2);
- }
- close(fd);
- }
+ write_test_file(g_testfile2);
/* Read the file that we just wrote */
- printf("main: opening %s for reading\n", g_testfile2);
-
- fd = open(g_testfile2, O_RDONLY);
- if (fd < 0)
- {
- printf("main: ERRORfailed to open %s for reading, errno=%d\n",
- g_testfile2, *get_errno_ptr());
- }
- else
- {
- memset(buffer, 0, 128);
- nbytes = read(fd, buffer, 128);
- if (nbytes < 0)
- {
- printf("main: ERROR failed to read from %s, errno=%d\n",
- g_testfile2, *get_errno_ptr());
- }
- else
- {
- buffer[127]='\0';
- printf("main: Read \"%s\" from %s\n", buffer, g_testfile2);
- }
- close(fd);
- }
+ read_test_file(g_testfile2);
/* Try rmdir() against a file on the directory. It should fail with ENOTDIR */
- printf("main: Try rmdir(%s)\n", g_testfile1);
-
- ret = rmdir(g_testfile1);
- if (ret == 0)
- {
- printf("main: ERROR rmdir(%s) succeeded\n", g_testfile1);
- }
- else if (*get_errno_ptr() != ENOTDIR)
- {
- printf("main: ERROR rmdir(%s) failed with errno=%d\n",
- g_testfile1, *get_errno_ptr());
- }
+ fail_rmdir(g_testfile1, ENOTDIR);
/* Try rmdir() against the test directory. It should fail with ENOTEMPTY */
- printf("main: Try rmdir(%s)\n", g_testdir1);
-
- ret = rmdir(g_testdir1);
- if (ret == 0)
- {
- printf("main: ERROR rmdir(%s) succeeded\n", g_testdir1);
- }
- else if (*get_errno_ptr() != ENOTEMPTY)
- {
- printf("main: ERROR rmdir(%s) failed with errno=%d\n",
- g_testdir1, *get_errno_ptr());
- }
+ fail_rmdir(g_testdir1, ENOTEMPTY);
/* Try unlink() against the test directory. It should fail with EISDIR */
- printf("main: Try unlink(%s)\n", g_testdir1);
-
- ret = unlink(g_testdir1);
- if (ret == 0)
- {
- printf("main: ERROR unlink(%s) succeeded\n", g_testdir1);
- }
- else if (*get_errno_ptr() != EISDIR)
- {
- printf("main: ERROR unlink(%s) failed with errno=%d\n",
- g_testdir1, *get_errno_ptr());
- }
+ fail_unlink(g_testdir1, EISDIR);
/* Try unlink() against the test file1. It should succeed. */
- printf("main: Try unlink(%s)\n", g_testfile1);
-
- ret = unlink(g_testfile1);
- if (ret != 0)
- {
- printf("main: ERROR unlink(%s) failed with errno=%d\n",
- g_testfile1, *get_errno_ptr());
- }
+ succeed_unlink(g_testfile1);
/* Attempt to open testfile1 should fail with ENOENT */
- printf("main: Try open(%s) for reading\n", g_testfile1);
-
- fd = open(g_testfile1, O_RDONLY);
- if (fd >= 0)
- {
- printf("main: ERROR open(%s) succeeded\n", g_testfile1);
- close(fd);
- }
- else if (*get_errno_ptr() != ENOENT)
- {
- printf("main: ERROR open(%s) failed with errno=%d\n",
- g_testfile1, *get_errno_ptr());
- }
+ fail_read_open(g_testfile1, ENOENT);
/* Try rmdir() against the test directory. It should still fail with ENOTEMPTY */
- printf("main: Try rmdir(%s)\n", g_testdir1);
+ fail_rmdir(g_testdir1, ENOTEMPTY);
- ret = rmdir(g_testdir1);
- if (ret == 0)
- {
- printf("main: ERROR rmdir(%s) succeeded\n", g_testdir1);
- }
- else if (*get_errno_ptr() != ENOTEMPTY)
- {
- printf("main: ERROR rmdir(%s) failed with errno=%d\n",
- g_testdir1, *get_errno_ptr());
- }
+ /* Try mkdir() against the test file2. It should fail with EEXIST. */
+
+ fail_mkdir(g_testfile2, EEXIST);
/* Try unlink() against the test file2. It should succeed. */
- printf("main: Try unlink(%s)\n", g_testfile2);
+ succeed_unlink(g_testfile2);
- ret = unlink(g_testfile2);
- if (ret != 0)
- {
- printf("main: ERROR unlink(%s) failed with errno=%d\n",
- g_testfile2, *get_errno_ptr());
- }
+ /* Try mkdir() against the test dir1. It should fail with EEXIST. */
+
+ fail_mkdir(g_testdir1, EEXIST);
/* Try rmdir() against the test directory. It should now succeed. */
- printf("main: Try rmdir(%s)\n", g_testdir1);
+ succeed_rmdir(g_testdir1);
- ret = rmdir(g_testdir1);
- if (ret != 0)
- {
- printf("main: ERROR rmdir(%s) failed with errno=%d\n",
- g_testdir1, *get_errno_ptr());
- }
+ /* Try mkdir() against the test dir2. It should succeed */
+
+ succeed_mkdir(g_testdir2);
+
+ /* Try mkdir() against the test dir2. It should fail with EXIST */
+
+ fail_mkdir(g_testdir2, EEXIST);
+
+ /* Write a test file into a new directory on the test file system */
+
+ write_test_file(g_testfile3);
+
+ /* Read the file that we just wrote */
+
+ read_test_file(g_testfile3);
/* Unmount the file system */
- printf("main: Try unmount(%s)\n", g_target);
+ printf("user_start: Try unmount(%s)\n", g_target);
ret = umount(g_target);
if (ret != 0)
{
- printf("main: ERROR umount() failed, errno %d\n", *get_errno_ptr());
+ printf("user_start: ERROR umount() failed, errno %d\n", *get_errno_ptr());
+ g_nerrors++;
}
+
+ printf("user_start: %d errors reported\n", g_nerrors);
}
fflush(stdout);
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