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>
|
||||
|
||||
* 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
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@
|
|||
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>
|
||||
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>
|
||||
|
||||
<table width ="100%">
|
||||
|
@ -376,6 +379,35 @@ Other memory:
|
|||
</tr>
|
||||
</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>
|
||||
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.
|
||||
arch/c5471 and arch/dm320 are deprecated and will be removed
|
||||
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>
|
||||
|
||||
* Corrected some build/configuration issues introduced with the
|
||||
|
@ -516,10 +558,22 @@ Other memory:
|
|||
* close() was not closing the underlying device.
|
||||
* Added fsync()
|
||||
* 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>
|
||||
|
||||
* 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
|
||||
</pre></ul>
|
||||
|
||||
|
|
|
@ -82,7 +82,11 @@
|
|||
* xxd -g 1 nuttx-test.vfat.gz >some-file
|
||||
*
|
||||
* 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[] =
|
||||
|
|
|
@ -63,6 +63,7 @@ static const char g_source[] = "/dev/blkdev";
|
|||
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_testfile1[] = "/mnt/fs/TestDir/TestFile.txt";
|
||||
static const char g_testfile2[] = "/mnt/fs/TestDir/WritTest.txt";
|
||||
static const char g_testmsg[] = "This is a write test";
|
||||
|
@ -93,6 +94,8 @@ int user_start(int argc, char *argv[])
|
|||
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",
|
||||
g_filesystemtype, g_target, g_source);
|
||||
|
||||
|
@ -101,12 +104,15 @@ int user_start(int argc, char *argv[])
|
|||
|
||||
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);
|
||||
|
||||
int fd = open(g_testfile1, O_RDONLY);
|
||||
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
|
||||
{
|
||||
|
@ -114,7 +120,8 @@ int user_start(int argc, char *argv[])
|
|||
nbytes = read(fd, buffer, 128);
|
||||
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
|
||||
{
|
||||
|
@ -124,19 +131,23 @@ int user_start(int argc, char *argv[])
|
|||
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);
|
||||
|
||||
fd = open(g_testfile2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
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
|
||||
{
|
||||
int nbytes = write(fd, g_testmsg, strlen(g_testmsg));
|
||||
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
|
||||
{
|
||||
|
@ -145,12 +156,15 @@ int user_start(int argc, char *argv[])
|
|||
close(fd);
|
||||
}
|
||||
|
||||
/* 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: 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
|
||||
{
|
||||
|
@ -158,7 +172,8 @@ int user_start(int argc, char *argv[])
|
|||
nbytes = read(fd, buffer, 128);
|
||||
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
|
||||
{
|
||||
|
@ -168,8 +183,124 @@ int user_start(int argc, char *argv[])
|
|||
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);
|
||||
printf("main: umount() returned %d\n", ret);
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("main: ERROR umount() failed, errno %d\n", *get_errno_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
* 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);
|
||||
static int fat_close(FAR struct file *filp);
|
||||
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,
|
||||
void **handle);
|
||||
static int fat_unbind(void *handle);
|
||||
static int fat_unlink(struct inode *mountpt, const char *rel_path);
|
||||
static int fat_mkdir(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 *relpath,
|
||||
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,
|
||||
const char *new_relpath);
|
||||
|
||||
|
@ -120,6 +120,7 @@ const struct mountpt_operations fat_operations =
|
|||
fat_unbind,
|
||||
fat_unlink,
|
||||
fat_mkdir,
|
||||
fat_rmdir,
|
||||
fat_rename
|
||||
};
|
||||
|
||||
|
@ -131,7 +132,7 @@ const struct mountpt_operations fat_operations =
|
|||
* 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)
|
||||
{
|
||||
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 */
|
||||
|
||||
memset(&dirinfo, 0, sizeof(struct fat_dirinfo_s));
|
||||
dirinfo.fs = fs;
|
||||
|
||||
/* 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
|
||||
* 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 */
|
||||
|
||||
readonly = ((DIR_GETATTRIBUTES(dirinfo.fd_entry) & FATATTR_READONLY) != 0);
|
||||
if (((oflags && O_WRONLY) != 0) && readonly)
|
||||
if (((oflags & O_WRONLY) != 0) && readonly)
|
||||
{
|
||||
ret = -EACCES;
|
||||
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? */
|
||||
|
||||
if ((oflags && O_CREAT) == 0)
|
||||
if ((oflags & O_CREAT) == 0)
|
||||
{
|
||||
/* No.. then we fail with -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 */
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
int ret;
|
||||
|
@ -1337,15 +1337,20 @@ static int fat_unlink(struct inode *mountpt, const char *rel_path)
|
|||
|
||||
fat_semtake(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);
|
||||
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;
|
||||
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;
|
||||
int ret;
|
||||
|
@ -1411,15 +1416,20 @@ int fat_rmdir(struct inode *mountpt, const char *rel_path)
|
|||
|
||||
fat_semtake(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);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -488,7 +488,6 @@ struct fat_file_s
|
|||
|
||||
struct fat_dirinfo_s
|
||||
{
|
||||
struct fat_mountpt_s *fs; /* Pointer to the parent mountpoint */
|
||||
ubyte fd_name[8+3]; /* Filename -- directory format*/
|
||||
#ifdef CONFIG_FAT_LCNAMES
|
||||
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 */
|
||||
|
||||
EXTERN int fat_nextdirentry(struct fat_dirinfo_s *dirinfo);
|
||||
EXTERN int fat_finddirentry(struct fat_dirinfo_s *dirinfo, const char *path);
|
||||
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);
|
||||
|
||||
/* 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_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_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;
|
||||
}
|
||||
|
||||
ret = fat_nextdirentry(dirinfo);
|
||||
ret = fat_nextdirentry(fs, dirinfo);
|
||||
if (ret < 0)
|
||||
{
|
||||
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 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;
|
||||
ubyte *direntry = NULL;
|
||||
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 */
|
||||
|
||||
if (fat_nextdirentry(dirinfo) != OK)
|
||||
if (fat_nextdirentry(fs, dirinfo) != OK)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -1935,6 +1934,184 @@ int fat_dircreate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo)
|
|||
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
|
||||
*
|
||||
|
@ -2092,7 +2269,7 @@ int fat_ffcacheinvalidate(struct fat_mountpt_s *fs, struct fat_file_s *ff)
|
|||
* Name: fat_updatefsinfo
|
||||
*
|
||||
* Desciption: Flush evertyhing buffered for the mountpoint and update
|
||||
* the FSINFO sector, if appropriate
|
||||
* the FSINFO sector, if appropriate
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ struct mountpt_operations
|
|||
* 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);
|
||||
|
||||
/* 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 (*unbind)(void *handle);
|
||||
|
||||
int (*unlink)(struct inode *mountpt, const char *rel_path);
|
||||
int (*mkdir)(struct inode *mountpt, const char *rel_path, mode_t mode);
|
||||
int (*rmdir)(struct inode *mountpt, const char *rel_path);
|
||||
int (*rename)(struct inode *mountpt, const char *old_relpath, const char *new_relpath);
|
||||
int (*unlink)(struct inode *mountpt, const char *relpath);
|
||||
int (*mkdir)(struct inode *mountpt, const char *relpath, mode_t mode);
|
||||
int (*rmdir)(struct inode *mountpt, const char *relpath);
|
||||
int (*rename)(struct inode *mountpt, const char *oldrelpath, const char *newrelpath);
|
||||
|
||||
/* NOTE: More operations will be needed here to support: disk usage stats
|
||||
* file stat(), file attributes, file truncation, etc.
|
||||
|
|
Loading…
Reference in New Issue