Add FAT rmdir and unlink
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@247 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
0cb1595215
commit
d7b254d2e6
@ -141,5 +141,7 @@
|
|||||||
0.2.6 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
0.2.6 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||||
|
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||||
|
* Added FAT support for unlink() and rmdir()
|
||||||
* Started m68322
|
* Started m68322
|
||||||
|
|
||||||
|
@ -186,6 +186,9 @@
|
|||||||
The 8th release of NuttX (nuttx-0.2.5) is available for download
|
The 8th release of NuttX (nuttx-0.2.5) is available for download
|
||||||
from the <a href="http://sourceforge.net/project/showfiles.php?group_id=189573">SourceForge</a>
|
from the <a href="http://sourceforge.net/project/showfiles.php?group_id=189573">SourceForge</a>
|
||||||
website.
|
website.
|
||||||
|
The change log associated with the release is available <a href="#currentrelease">here</a>.
|
||||||
|
Unreleased changes after this release are avalable in CVS.
|
||||||
|
These unreleased changes are listed <a href="#pendingchanges">here</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<table width ="100%">
|
<table width ="100%">
|
||||||
@ -376,6 +379,35 @@ Other memory:
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<center><table width ="80%">
|
||||||
|
<tr>
|
||||||
|
<td><img src="favicon.ico"></td>
|
||||||
|
<td>
|
||||||
|
<a href="#olderreleases">Change Logs for Older Releases</a><br>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="favicon.ico"></td>
|
||||||
|
<td>
|
||||||
|
<a href="#currentrelease">ChangeLog for Current Release</a><br>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><img src="favicon.ico"></td>
|
||||||
|
<td>
|
||||||
|
<a href="#pendingchanges">Unreleased Changes</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table></center>
|
||||||
|
|
||||||
|
<table width ="100%">
|
||||||
|
<tr bgcolor="#e4e4e4">
|
||||||
|
<td>
|
||||||
|
<a name="olderreleases>Change Logs for Older Releases</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<ul><pre>
|
<ul><pre>
|
||||||
0.1.0 2007-03-09 Gregory Nutt <spudmonkey@racsa.co.cr>
|
0.1.0 2007-03-09 Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
@ -499,7 +531,17 @@ Other memory:
|
|||||||
* Logic from arch/c5471 and arch/dm320 combined into arch/arm.
|
* Logic from arch/c5471 and arch/dm320 combined into arch/arm.
|
||||||
arch/c5471 and arch/dm320 are deprecated and will be removed
|
arch/c5471 and arch/dm320 are deprecated and will be removed
|
||||||
when the new c5471 and dm320 logic is verified.
|
when the new c5471 and dm320 logic is verified.
|
||||||
|
</pre></ul>
|
||||||
|
|
||||||
|
<table width ="100%">
|
||||||
|
<tr bgcolor="#e4e4e4">
|
||||||
|
<td>
|
||||||
|
<a name="currentrelease">ChangeLog for Current Release</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<pre><ul>
|
||||||
0.2.5 2007-05-19 Gregory Nutt <spudmonkey@racsa.co.cr>
|
0.2.5 2007-05-19 Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
* Corrected some build/configuration issues introduced with the
|
* Corrected some build/configuration issues introduced with the
|
||||||
@ -516,10 +558,22 @@ Other memory:
|
|||||||
* close() was not closing the underlying device.
|
* close() was not closing the underlying device.
|
||||||
* Added fsync()
|
* Added fsync()
|
||||||
* Added strspn() and strcspn()
|
* Added strspn() and strcspn()
|
||||||
|
</pre></ul>
|
||||||
|
|
||||||
|
<table width ="100%">
|
||||||
|
<tr bgcolor="#e4e4e4">
|
||||||
|
<td>
|
||||||
|
<a name="pendingchanges">Unreleased Changes</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<pre><ul>
|
||||||
0.2.6 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
0.2.6 2007-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||||
|
|
||||||
* Added unlink(), mkdir(), rmdir(), and rename()
|
* Added unlink(), mkdir(), rmdir(), and rename()
|
||||||
|
* Fixed several serious FAT errors with oflags handling (&& instead of &)
|
||||||
|
* Added FAT support for unlink() and rmdir()
|
||||||
* Started m68322
|
* Started m68322
|
||||||
</pre></ul>
|
</pre></ul>
|
||||||
|
|
||||||
|
@ -82,7 +82,11 @@
|
|||||||
* xxd -g 1 nuttx-test.vfat.gz >some-file
|
* xxd -g 1 nuttx-test.vfat.gz >some-file
|
||||||
*
|
*
|
||||||
* Then manually massaged from the gzip xxd output to zlib format. See
|
* Then manually massaged from the gzip xxd output to zlib format. See
|
||||||
* http://www.faqs.org/rfcs/rfc1952.html
|
* http://www.faqs.org/rfcs/rfc1952.html. This amounts to:
|
||||||
|
*
|
||||||
|
* Remove all of the leading bytes through the null terminator of the file name
|
||||||
|
* Remove the last 8 bytes
|
||||||
|
* Add 0x08, 0x1d to the beginning.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const unsigned char g_vfatdata[] =
|
static const unsigned char g_vfatdata[] =
|
||||||
|
@ -63,6 +63,7 @@ static const char g_source[] = "/dev/blkdev";
|
|||||||
static const char g_target[] = "/mnt/fs";
|
static const char g_target[] = "/mnt/fs";
|
||||||
static const char g_filesystemtype[] = "vfat";
|
static const char g_filesystemtype[] = "vfat";
|
||||||
|
|
||||||
|
static const char g_testdir1[] = "/mnt/fs/TestDir";
|
||||||
static const char g_testfile1[] = "/mnt/fs/TestDir/TestFile.txt";
|
static const char g_testfile1[] = "/mnt/fs/TestDir/TestFile.txt";
|
||||||
static const char g_testfile2[] = "/mnt/fs/TestDir/WritTest.txt";
|
static const char g_testfile2[] = "/mnt/fs/TestDir/WritTest.txt";
|
||||||
static const char g_testmsg[] = "This is a write test";
|
static const char g_testmsg[] = "This is a write test";
|
||||||
@ -93,6 +94,8 @@ int user_start(int argc, char *argv[])
|
|||||||
int nbytes;
|
int nbytes;
|
||||||
int ret;
|
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("main: mounting %s filesystem at target=%s with source=%s\n",
|
||||||
g_filesystemtype, g_target, g_source);
|
g_filesystemtype, g_target, g_source);
|
||||||
|
|
||||||
@ -101,12 +104,15 @@ int user_start(int argc, char *argv[])
|
|||||||
|
|
||||||
if (ret == 0)
|
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);
|
printf("main: opening %s for reading\n", g_testfile1);
|
||||||
|
|
||||||
int fd = open(g_testfile1, O_RDONLY);
|
int fd = open(g_testfile1, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to open %s, errno=%d\n", g_testfile1, *get_errno_ptr());
|
printf("main: ERROR failed to open %s, errno=%d\n",
|
||||||
|
g_testfile1, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -114,7 +120,8 @@ int user_start(int argc, char *argv[])
|
|||||||
nbytes = read(fd, buffer, 128);
|
nbytes = read(fd, buffer, 128);
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to read from %s, errno=%d\n", g_testfile1, *get_errno_ptr());
|
printf("main: ERROR failed to read from %s, errno=%d\n",
|
||||||
|
g_testfile1, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -124,19 +131,23 @@ int user_start(int argc, char *argv[])
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write a test file into a pre-existing file on the test file system */
|
||||||
|
|
||||||
printf("main: opening %s for writing\n", g_testfile2);
|
printf("main: opening %s for writing\n", g_testfile2);
|
||||||
|
|
||||||
fd = open(g_testfile2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
fd = open(g_testfile2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to open %s for writing, errno=%d\n", g_testfile2, *get_errno_ptr());
|
printf("main: ERROR failed to open %s for writing, errno=%d\n",
|
||||||
|
g_testfile2, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int nbytes = write(fd, g_testmsg, strlen(g_testmsg));
|
int nbytes = write(fd, g_testmsg, strlen(g_testmsg));
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to write to %s, errno=%d\n", g_testfile2, *get_errno_ptr());
|
printf("main: ERROR failed to write to %s, errno=%d\n",
|
||||||
|
g_testfile2, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -145,12 +156,15 @@ int user_start(int argc, char *argv[])
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the file that we just wrote */
|
||||||
|
|
||||||
printf("main: opening %s for reading\n", g_testfile2);
|
printf("main: opening %s for reading\n", g_testfile2);
|
||||||
|
|
||||||
fd = open(g_testfile2, O_RDONLY);
|
fd = open(g_testfile2, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to open %s for reading, errno=%d\n", g_testfile2, *get_errno_ptr());
|
printf("main: ERRORfailed to open %s for reading, errno=%d\n",
|
||||||
|
g_testfile2, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -158,7 +172,8 @@ int user_start(int argc, char *argv[])
|
|||||||
nbytes = read(fd, buffer, 128);
|
nbytes = read(fd, buffer, 128);
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
printf("main: failed to read from %s, errno=%d\n", g_testfile2, *get_errno_ptr());
|
printf("main: ERROR failed to read from %s, errno=%d\n",
|
||||||
|
g_testfile2, *get_errno_ptr());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -168,8 +183,124 @@ int user_start(int argc, char *argv[])
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try rmdir() against the test directory. It should still 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try unlink() against the test file2. It should succeed. */
|
||||||
|
|
||||||
|
printf("main: Try unlink(%s)\n", 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 rmdir() against the test directory. It should now succeed. */
|
||||||
|
|
||||||
|
printf("main: Try rmdir(%s)\n", g_testdir1);
|
||||||
|
|
||||||
|
ret = rmdir(g_testdir1);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf("main: ERROR rmdir(%s) failed with errno=%d\n",
|
||||||
|
g_testdir1, *get_errno_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unmount the file system */
|
||||||
|
|
||||||
|
printf("main: Try unmount(%s)\n", g_target);
|
||||||
|
|
||||||
ret = umount(g_target);
|
ret = umount(g_target);
|
||||||
printf("main: umount() returned %d\n", ret);
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf("main: ERROR umount() failed, errno %d\n", *get_errno_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int fat_open(FAR struct file *filp, const char *rel_path,
|
static int fat_open(FAR struct file *filp, const char *relpath,
|
||||||
int oflags, mode_t mode);
|
int oflags, mode_t mode);
|
||||||
static int fat_close(FAR struct file *filp);
|
static int fat_close(FAR struct file *filp);
|
||||||
static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen);
|
static ssize_t fat_read(FAR struct file *filp, char *buffer, size_t buflen);
|
||||||
@ -86,10 +86,10 @@ static int fat_sync(FAR struct file *filp);
|
|||||||
static int fat_bind(FAR struct inode *blkdriver, const void *data,
|
static int fat_bind(FAR struct inode *blkdriver, const void *data,
|
||||||
void **handle);
|
void **handle);
|
||||||
static int fat_unbind(void *handle);
|
static int fat_unbind(void *handle);
|
||||||
static int fat_unlink(struct inode *mountpt, const char *rel_path);
|
static int fat_unlink(struct inode *mountpt, const char *relpath);
|
||||||
static int fat_mkdir(struct inode *mountpt, const char *rel_path,
|
static int fat_mkdir(struct inode *mountpt, const char *relpath,
|
||||||
mode_t mode);
|
mode_t mode);
|
||||||
static int fat_rmdir(struct inode *mountpt, const char *rel_path);
|
static int fat_rmdir(struct inode *mountpt, const char *relpath);
|
||||||
static int fat_rename(struct inode *mountpt, const char *old_relpath,
|
static int fat_rename(struct inode *mountpt, const char *old_relpath,
|
||||||
const char *new_relpath);
|
const char *new_relpath);
|
||||||
|
|
||||||
@ -120,6 +120,7 @@ const struct mountpt_operations fat_operations =
|
|||||||
fat_unbind,
|
fat_unbind,
|
||||||
fat_unlink,
|
fat_unlink,
|
||||||
fat_mkdir,
|
fat_mkdir,
|
||||||
|
fat_rmdir,
|
||||||
fat_rename
|
fat_rename
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ const struct mountpt_operations fat_operations =
|
|||||||
* Name: fat_open
|
* Name: fat_open
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int fat_open(FAR struct file *filp, const char *rel_path,
|
static int fat_open(FAR struct file *filp, const char *relpath,
|
||||||
int oflags, mode_t mode)
|
int oflags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fat_dirinfo_s dirinfo;
|
struct fat_dirinfo_s dirinfo;
|
||||||
@ -165,13 +166,12 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
|
|||||||
/* Initialize the directory info structure */
|
/* Initialize the directory info structure */
|
||||||
|
|
||||||
memset(&dirinfo, 0, sizeof(struct fat_dirinfo_s));
|
memset(&dirinfo, 0, sizeof(struct fat_dirinfo_s));
|
||||||
dirinfo.fs = fs;
|
|
||||||
|
|
||||||
/* Locate the directory entry for this path */
|
/* Locate the directory entry for this path */
|
||||||
|
|
||||||
ret = fat_finddirentry(&dirinfo, rel_path);
|
ret = fat_finddirentry(fs, &dirinfo, relpath);
|
||||||
|
|
||||||
/* Three possibililities: (1) a node exists for the rel_path and
|
/* Three possibililities: (1) a node exists for the relpath and
|
||||||
* dirinfo describes the directory entry of the entity, (2) the
|
* dirinfo describes the directory entry of the entity, (2) the
|
||||||
* node does not exist, or (3) some error occurred.
|
* node does not exist, or (3) some error occurred.
|
||||||
*/
|
*/
|
||||||
@ -206,7 +206,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
|
|||||||
/* Check if the caller has sufficient privileges to open the file */
|
/* Check if the caller has sufficient privileges to open the file */
|
||||||
|
|
||||||
readonly = ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0);
|
readonly = ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0);
|
||||||
if (((oflags && O_WRONLY) != 0) && readonly)
|
if (((oflags & O_WRONLY) != 0) && readonly)
|
||||||
{
|
{
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
goto errout_with_semaphore;
|
goto errout_with_semaphore;
|
||||||
@ -236,7 +236,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
|
|||||||
{
|
{
|
||||||
/* The file does not exist. Were we asked to create it? */
|
/* The file does not exist. Were we asked to create it? */
|
||||||
|
|
||||||
if ((oflags && O_CREAT) == 0)
|
if ((oflags & O_CREAT) == 0)
|
||||||
{
|
{
|
||||||
/* No.. then we fail with -ENOENT */
|
/* No.. then we fail with -ENOENT */
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
@ -303,7 +303,7 @@ static int fat_open(FAR struct file *filp, const char *rel_path,
|
|||||||
|
|
||||||
/* In write/append mode, we need to set the file pointer to the end of the file */
|
/* In write/append mode, we need to set the file pointer to the end of the file */
|
||||||
|
|
||||||
if ((oflags && (O_APPEND|O_WRONLY)) == (O_APPEND|O_WRONLY))
|
if ((oflags & (O_APPEND|O_WRONLY)) == (O_APPEND|O_WRONLY))
|
||||||
{
|
{
|
||||||
ff->ff_position = ff->ff_size;
|
ff->ff_position = ff->ff_size;
|
||||||
}
|
}
|
||||||
@ -1320,7 +1320,7 @@ static int fat_unbind(void *handle)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int fat_unlink(struct inode *mountpt, const char *rel_path)
|
static int fat_unlink(struct inode *mountpt, const char *relpath)
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs;
|
struct fat_mountpt_s *fs;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1337,15 +1337,20 @@ static int fat_unlink(struct inode *mountpt, const char *rel_path)
|
|||||||
|
|
||||||
fat_semtake(fs);
|
fat_semtake(fs);
|
||||||
ret = fat_checkmount(fs);
|
ret = fat_checkmount(fs);
|
||||||
if (ret != OK)
|
if (ret == OK)
|
||||||
{
|
{
|
||||||
goto errout_with_semaphore;
|
/* If the file is open, the correct behavior is to remove the file
|
||||||
|
* name, but to keep the file cluster chain in place until the last
|
||||||
|
* open reference to the file is closed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#warning "Need to defer deleting cluster chain if the file is open"
|
||||||
|
|
||||||
|
/* Remove the file */
|
||||||
|
|
||||||
|
ret = fat_remove(fs, relpath, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning "fat_unlink is not implemented"
|
|
||||||
ret = -ENOSYS;
|
|
||||||
|
|
||||||
errout_with_semaphore:
|
|
||||||
fat_semgive(fs);
|
fat_semgive(fs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1357,7 +1362,7 @@ static int fat_unlink(struct inode *mountpt, const char *rel_path)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int fat_mkdir(struct inode *mountpt, const char *rel_path, mode_t mode)
|
static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs;
|
struct fat_mountpt_s *fs;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1394,7 +1399,7 @@ static int fat_mkdir(struct inode *mountpt, const char *rel_path, mode_t mode)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int fat_rmdir(struct inode *mountpt, const char *rel_path)
|
int fat_rmdir(struct inode *mountpt, const char *relpath)
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs;
|
struct fat_mountpt_s *fs;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1411,15 +1416,20 @@ int fat_rmdir(struct inode *mountpt, const char *rel_path)
|
|||||||
|
|
||||||
fat_semtake(fs);
|
fat_semtake(fs);
|
||||||
ret = fat_checkmount(fs);
|
ret = fat_checkmount(fs);
|
||||||
if (ret != OK)
|
if (ret == OK)
|
||||||
{
|
{
|
||||||
goto errout_with_semaphore;
|
/* If the directory is open, the correct behavior is to remove the directory
|
||||||
|
* name, but to keep the directory cluster chain in place until the last
|
||||||
|
* open reference to the directory is closed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#warning "Need to defer deleting cluster chain if the directory is open"
|
||||||
|
|
||||||
|
/* Remove the directory */
|
||||||
|
|
||||||
|
ret = fat_remove(fs, relpath, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning "fat_rmdir is not implemented"
|
|
||||||
ret = -ENOSYS;
|
|
||||||
|
|
||||||
errout_with_semaphore:
|
|
||||||
fat_semgive(fs);
|
fat_semgive(fs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,6 @@ struct fat_file_s
|
|||||||
|
|
||||||
struct fat_dirinfo_s
|
struct fat_dirinfo_s
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs; /* Pointer to the parent mountpoint */
|
|
||||||
ubyte fd_name[8+3]; /* Filename -- directory format*/
|
ubyte fd_name[8+3]; /* Filename -- directory format*/
|
||||||
#ifdef CONFIG_FAT_LCNAMES
|
#ifdef CONFIG_FAT_LCNAMES
|
||||||
ubyte fd_ntflags; /* NTRes lower case flags */
|
ubyte fd_ntflags; /* NTRes lower case flags */
|
||||||
@ -557,15 +556,17 @@ EXTERN sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster);
|
|||||||
|
|
||||||
/* Help for traverseing directory trees */
|
/* Help for traverseing directory trees */
|
||||||
|
|
||||||
EXTERN int fat_nextdirentry(struct fat_dirinfo_s *dirinfo);
|
EXTERN int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||||
EXTERN int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path);
|
EXTERN int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
/* File creation helpers */
|
/* File creation and removal helpers */
|
||||||
|
|
||||||
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
EXTERN int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||||
EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
EXTERN int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo);
|
||||||
|
EXTERN int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory);
|
||||||
|
|
||||||
/* Mountpoint and fFile buffer cache (for partial sector accesses) */
|
/* Mountpoint and file buffer cache (for partial sector accesses) */
|
||||||
|
|
||||||
EXTERN int fat_fscacheread(struct fat_mountpt_s *fs, size_t sector);
|
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_ffcacheflush(struct fat_mountpt_s *fs, struct fat_file_s *ff);
|
||||||
|
@ -471,7 +471,7 @@ static int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = fat_nextdirentry(dirinfo);
|
ret = fat_nextdirentry(fs, dirinfo);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
@ -1583,9 +1583,8 @@ sint32 fat_extendchain(struct fat_mountpt_s *fs, uint32 cluster)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int fat_nextdirentry(struct fat_dirinfo_s *dirinfo)
|
int fat_nextdirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs = dirinfo->fs;
|
|
||||||
unsigned int cluster;
|
unsigned int cluster;
|
||||||
unsigned int ndx;
|
unsigned int ndx;
|
||||||
|
|
||||||
@ -1674,9 +1673,9 @@ int fat_nextdirentry(struct fat_dirinfo_s *dirinfo)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path)
|
int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
|
||||||
|
const char *path)
|
||||||
{
|
{
|
||||||
struct fat_mountpt_s *fs = dirinfo->fs;
|
|
||||||
size_t cluster;
|
size_t cluster;
|
||||||
ubyte *direntry = NULL;
|
ubyte *direntry = NULL;
|
||||||
char terminator;
|
char terminator;
|
||||||
@ -1778,7 +1777,7 @@ int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path)
|
|||||||
|
|
||||||
/* No... get the next directory index and try again */
|
/* No... get the next directory index and try again */
|
||||||
|
|
||||||
if (fat_nextdirentry(dirinfo) != OK)
|
if (fat_nextdirentry(fs, dirinfo) != OK)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
@ -1935,6 +1934,184 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: fat_remove
|
||||||
|
*
|
||||||
|
* Desciption: Remove a directory or file from the file system. This
|
||||||
|
* implements both rmdir() and unlink().
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int fat_remove(struct fat_mountpt_s *fs, const char *relpath, boolean directory)
|
||||||
|
{
|
||||||
|
struct fat_dirinfo_s dirinfo;
|
||||||
|
uint32 dircluster;
|
||||||
|
size_t dirsector;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Find the directory entry referring to the entry to be deleted */
|
||||||
|
|
||||||
|
ret = fat_finddirentry(fs, &dirinfo, relpath);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
/* No such path */
|
||||||
|
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if this is a FAT12/16 root directory */
|
||||||
|
|
||||||
|
if (dirinfo.fd_entry == NULL)
|
||||||
|
{
|
||||||
|
/* The root directory cannot be removed */
|
||||||
|
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The object has to have write access to be deleted */
|
||||||
|
|
||||||
|
if ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0)
|
||||||
|
{
|
||||||
|
/* It is a read-only entry */
|
||||||
|
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the directory sector and cluster containing the
|
||||||
|
* entry to be deleted
|
||||||
|
*/
|
||||||
|
|
||||||
|
dirsector = fs->fs_currentsector;
|
||||||
|
dircluster =
|
||||||
|
((uint32)DIR_GETFSTCLUSTHI(dirinfo.fd_entry) << 16) |
|
||||||
|
DIR_GETFSTCLUSTLO(dirinfo.fd_entry);
|
||||||
|
|
||||||
|
/* Is this entry a directory? */
|
||||||
|
|
||||||
|
if (DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_DIRECTORY)
|
||||||
|
{
|
||||||
|
/* It is a sub-directory. Check if we are be asked to remove
|
||||||
|
* a directory or a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!directory)
|
||||||
|
{
|
||||||
|
/* We are asked to delete a file */
|
||||||
|
|
||||||
|
return -EISDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are asked to delete a directory. Check if this
|
||||||
|
* sub-directory is empty
|
||||||
|
*/
|
||||||
|
|
||||||
|
dirinfo.fd_currcluster = dircluster;
|
||||||
|
dirinfo.fd_currsector = fat_cluster2sector(fs, dircluster);
|
||||||
|
dirinfo.fd_index = 2;
|
||||||
|
|
||||||
|
/* Loop until either (1) an entry is found in the directory
|
||||||
|
* (error), (2) the directory is found to be empty, or (3) some
|
||||||
|
* error occurs.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned int subdirindex;
|
||||||
|
ubyte *subdirentry;
|
||||||
|
|
||||||
|
/* Make sure that the sector containing the of the
|
||||||
|
* subdirectory sector is in the cache
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = fat_fscacheread(fs, dirinfo.fd_currsector);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a reference to the next entry in the directory */
|
||||||
|
|
||||||
|
subdirindex = (dirinfo.fd_index & DIRSEC_NDXMASK(fs)) * 32;
|
||||||
|
subdirentry = &fs->fs_buffer[subdirindex];
|
||||||
|
|
||||||
|
/* Is this the last entry in the direcory? */
|
||||||
|
|
||||||
|
if (subdirentry[DIR_NAME] == DIR0_ALLEMPTY)
|
||||||
|
{
|
||||||
|
/* Yes then the directory is empty. Break out of the
|
||||||
|
* loop and delete the directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the next entry refers to a file or directory */
|
||||||
|
|
||||||
|
if (subdirentry[DIR_NAME] != DIR0_EMPTY &&
|
||||||
|
!(DIR_GETATTRIBUTES(subdirentry) & FATATTR_VOLUMEID))
|
||||||
|
{
|
||||||
|
/* The directory is not empty */
|
||||||
|
|
||||||
|
return -ENOTEMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the next directgory entry */
|
||||||
|
|
||||||
|
ret = fat_nextdirentry(fs, &dirinfo);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* It is a file. Check if we are be asked to remove a directory
|
||||||
|
* or a file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (directory)
|
||||||
|
{
|
||||||
|
/* We are asked to remove a directory */
|
||||||
|
|
||||||
|
return -ENOTDIR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure that the directory containing the entry to be deleted is
|
||||||
|
* in the cache.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = fat_fscacheread(fs, dirsector);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark the directory entry 'deleted' */
|
||||||
|
|
||||||
|
dirinfo.fd_entry[DIR_NAME] = DIR0_EMPTY;
|
||||||
|
fs->fs_dirty = TRUE;
|
||||||
|
|
||||||
|
/* And remove the cluster chain making up the subdirectory */
|
||||||
|
|
||||||
|
ret = fat_removechain(fs, dircluster);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the FSINFO sector (FAT32) */
|
||||||
|
|
||||||
|
ret = fat_updatefsinfo(fs);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: fat_fscacheread
|
* Name: fat_fscacheread
|
||||||
*
|
*
|
||||||
|
@ -122,7 +122,7 @@ struct mountpt_operations
|
|||||||
* information to manage privileges.
|
* information to manage privileges.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int (*open)(FAR struct file *filp, const char *rel_path,
|
int (*open)(FAR struct file *filp, const char *relpath,
|
||||||
int oflags, mode_t mode);
|
int oflags, mode_t mode);
|
||||||
|
|
||||||
/* The following methods must be identical in signature and position because
|
/* The following methods must be identical in signature and position because
|
||||||
@ -150,10 +150,10 @@ struct mountpt_operations
|
|||||||
int (*bind)(FAR struct inode *blkdriver, const void *data, void **handle);
|
int (*bind)(FAR struct inode *blkdriver, const void *data, void **handle);
|
||||||
int (*unbind)(void *handle);
|
int (*unbind)(void *handle);
|
||||||
|
|
||||||
int (*unlink)(struct inode *mountpt, const char *rel_path);
|
int (*unlink)(struct inode *mountpt, const char *relpath);
|
||||||
int (*mkdir)(struct inode *mountpt, const char *rel_path, mode_t mode);
|
int (*mkdir)(struct inode *mountpt, const char *relpath, mode_t mode);
|
||||||
int (*rmdir)(struct inode *mountpt, const char *rel_path);
|
int (*rmdir)(struct inode *mountpt, const char *relpath);
|
||||||
int (*rename)(struct inode *mountpt, const char *old_relpath, const char *new_relpath);
|
int (*rename)(struct inode *mountpt, const char *oldrelpath, const char *newrelpath);
|
||||||
|
|
||||||
/* NOTE: More operations will be needed here to support: disk usage stats
|
/* NOTE: More operations will be needed here to support: disk usage stats
|
||||||
* file stat(), file attributes, file truncation, etc.
|
* file stat(), file attributes, file truncation, etc.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user