From 26d4a9f99308fa7fb3f97d92c98cbe914bd7f2d9 Mon Sep 17 00:00:00 2001 From: patacongo Date: Mon, 21 May 2007 21:04:03 +0000 Subject: [PATCH] Add FAT rename() git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@249 7fd9a85b-ad96-42d3-883c-3090e2eb8679 --- nuttx/ChangeLog | 2 +- nuttx/Documentation/NuttX.html | 4 +- nuttx/examples/mount/mount_main.c | 79 ++++++++++++++++++++- nuttx/fs/fs_fat32.c | 112 ++++++++++++++++++++++++++++-- 4 files changed, 185 insertions(+), 12 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index eaf9de128..1579ded46 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(), mkdir() and rmdir() + * Added FAT support for unlink(), mkdir(), rmdir(), and rename * Started m68322 diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html index e16071e1a..50ba2f76a 100644 --- a/nuttx/Documentation/NuttX.html +++ b/nuttx/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/nuttx/examples/mount/mount_main.c b/nuttx/examples/mount/mount_main.c index ef12c4bb5..0656951d7 100644 --- a/nuttx/examples/mount/mount_main.c +++ b/nuttx/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/nuttx/fs/fs_fat32.c b/nuttx/fs/fs_fat32.c index 1307520b2..3f2974109 100644 --- a/nuttx/fs/fs_fat32.c +++ b/nuttx/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);