diff --git a/ChangeLog b/ChangeLog
index eaf9de1285..1579ded46a 100644
--- a/ChangeLog
+++ b/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(), mkdir() and rmdir()
+ * Added FAT support for unlink(), mkdir(), rmdir(), and rename
* Started m68322
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index e16071e1ad..50ba2f76a8 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -8,7 +8,7 @@
NuttX RTOS
- Last Updated: May 19, 2007
+ Last Updated: May 21, 2007
|
@@ -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(), mkdir() and rmdir()
+ * Added FAT support for unlink(), mkdir(), rmdir(), and rename()
* Started m68322
diff --git a/examples/mount/mount_main.c b/examples/mount/mount_main.c
index ef12c4bb57..0656951d7d 100644
--- a/examples/mount/mount_main.c
+++ b/examples/mount/mount_main.c
@@ -65,10 +65,13 @@ 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_testdir2[] = "/mnt/fs/NewDir1";
+static const char g_testdir3[] = "/mnt/fs/NewDir2";
+static const char g_testdir4[] = "/mnt/fs/NewDir3";
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_testfile2[] = "/mnt/fs/TestDir/WrTest1.txt";
+static const char g_testfile3[] = "/mnt/fs/NewDir1/WrTest2.txt";
+static const char g_testfile4[] = "/mnt/fs/NewDir3/Renamed.txt";
static const char g_testmsg[] = "This is a write test";
static int g_nerrors = 0;
@@ -315,6 +318,52 @@ static void succeed_unlink(const char *path)
}
}
+/****************************************************************************
+ * Name: fail_rename
+ ****************************************************************************/
+
+static void fail_rename(const char *oldpath, const char *newpath, int expectederror)
+{
+ int ret;
+
+ /* Try rename() against a file or directory. It should fail with expectederror */
+
+ printf("fail_rename: Try rename(%s->%s)\n", oldpath, newpath);
+
+ ret = rename(oldpath, newpath);
+ if (ret == 0)
+ {
+ printf("fail_rename: ERROR rename(%s->%s) succeeded\n",
+ oldpath, newpath);
+ g_nerrors++;
+ }
+ else if (*get_errno_ptr() != expectederror)
+ {
+ printf("fail_rename: ERROR rename(%s->%s) failed with errno=%d (expected %d)\n",
+ oldpath, newpath, *get_errno_ptr(), expectederror);
+ g_nerrors++;
+ }
+}
+
+/****************************************************************************
+ * Name: succeed_rename
+ ****************************************************************************/
+
+static void succeed_rename(const char *oldpath, const char *newpath)
+{
+ int ret;
+
+ printf("succeed_rename: Try rename(%s->%s)\n", oldpath, newpath);
+
+ ret = rename(oldpath, newpath);
+ if (ret != 0)
+ {
+ printf("succeed_rename: ERROR rename(%s->%s) failed with errno=%d\n",
+ oldpath, newpath, *get_errno_ptr());
+ g_nerrors++;
+ }
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -413,6 +462,30 @@ int user_start(int argc, char *argv[])
read_test_file(g_testfile3);
+ /* Use mkdir() to create test dir3. It should succeed */
+
+ succeed_mkdir(g_testdir3);
+
+ /* Try rename() on the root directory. Should fail with EXDEV*/
+
+ fail_rename(g_target, g_testdir4, EXDEV);
+
+ /* Try rename() to an existing directory. Should fail with EEXIST */
+
+ fail_rename(g_testdir2, g_testdir3, EEXIST);
+
+ /* Try rename() to a non-existing directory. Should succeed */
+
+ succeed_rename(g_testdir3, g_testdir4);
+
+ /* Try rename() of file. Should work. */
+
+ succeed_rename(g_testfile3, g_testfile4);
+
+ /* Make sure that we can still read the renamed file */
+
+ read_test_file(g_testfile4);
+
/* Unmount the file system */
printf("user_start: Try unmount(%s)\n", g_target);
diff --git a/fs/fs_fat32.c b/fs/fs_fat32.c
index 1307520b28..3f29741098 100644
--- a/fs/fs_fat32.c
+++ b/fs/fs_fat32.c
@@ -90,8 +90,8 @@ 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 *relpath);
-static int fat_rename(struct inode *mountpt, const char *old_relpath,
- const char *new_relpath);
+static int fat_rename(struct inode *mountpt, const char *oldrelpath,
+ const char *newrelpath);
/****************************************************************************
* Private Variables
@@ -1615,10 +1615,15 @@ int fat_rmdir(struct inode *mountpt, const char *relpath)
*
****************************************************************************/
-int fat_rename(struct inode *mountpt, const char *old_relpath,
- const char *new_relpath)
+int fat_rename(struct inode *mountpt, const char *oldrelpath,
+ const char *newrelpath)
{
struct fat_mountpt_s *fs;
+ struct fat_dirinfo_s dirinfo;
+ size_t oldsector;
+ ubyte *olddirentry;
+ ubyte *newdirentry;
+ ubyte dirstate[32-11];
int ret;
/* Sanity checks */
@@ -1638,8 +1643,103 @@ int fat_rename(struct inode *mountpt, const char *old_relpath,
goto errout_with_semaphore;
}
-#warning "fat_rename is not implemented"
- ret = -ENOSYS;
+ /* Find the directory entry for the oldrelpath */
+
+ ret = fat_finddirentry(fs, &dirinfo, oldrelpath);
+ if (ret != OK)
+ {
+ /* Some error occurred -- probably -ENOENT */
+
+ goto errout_with_semaphore;
+ }
+
+ /* Save the information that will need to recover the
+ * directory sector and directory entry offset to the
+ * old directory.
+ */
+
+ olddirentry = dirinfo.fd_entry;
+
+ /* One more check: Make sure that the oldrelpath does
+ * not refer to the root directory. We can't rename the
+ * root directory.
+ */
+
+ if (!olddirentry)
+ {
+ ret = -EXDEV;
+ goto errout_with_semaphore;
+ }
+
+ oldsector = fs->fs_currentsector;
+ memcpy(dirstate, &olddirentry[DIR_ATTRIBUTES], 32-11);
+
+ /* No find the directory where we should create the newpath object */
+
+ ret = fat_finddirentry(fs, &dirinfo, newrelpath);
+ if (ret == OK)
+ {
+ /* It is an error if the object at newrelpath already exists */
+
+ ret = -EEXIST;
+ goto errout_with_semaphore;
+ }
+
+ /* What we expect is -ENOENT mean that the full directory path was
+ * followed but that the object does not exists in the terminal directory.
+ */
+
+ if (ret != -ENOENT)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Reserve a directory entry */
+
+ ret = fat_allocatedirentry(fs, &dirinfo);
+ if (ret != OK)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Create the new directory entry */
+
+ newdirentry = dirinfo.fd_entry;
+
+ memcpy(&newdirentry[DIR_ATTRIBUTES], dirstate, 32-11);
+ memcpy(&newdirentry[DIR_NAME], dirinfo.fd_name, 8+3);
+#ifdef CONFIG_FLAT_LCNAMES
+ DIR_PUTNTRES(newdirentry, dirinfo.fd_ntflags);
+#else
+ DIR_PUTNTRES(newdirentry, 0);
+#endif
+ fs->fs_dirty = TRUE;
+
+ /* Now flush the new directory entry to disk and read the sector
+ * containing the old directory entry.
+ */
+
+ ret = fat_fscacheread(fs, oldsector);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ /* Remove the old entry */
+
+ olddirentry[DIR_NAME] = DIR0_EMPTY;
+ fs->fs_dirty = TRUE;
+
+ /* Write the old entry to disk and update FSINFO if necessary */
+
+ ret = fat_updatefsinfo(fs);
+ if (ret < 0)
+ {
+ goto errout_with_semaphore;
+ }
+
+ fat_semgive(fs);
+ return OK;
errout_with_semaphore:
fat_semgive(fs);