Fix a FAT error when trying to create file in a non-existent directory. Reported by Andrew Tridgell.

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5764 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2013-03-20 15:26:50 +00:00
parent 7f8958d651
commit d5d9fa89ab
3 changed files with 48 additions and 12 deletions

View File

@ -4389,3 +4389,9 @@
build different objects in the first and second pass kernel builds need build different objects in the first and second pass kernel builds need
to keep those objects in separate directories so that they are not to keep those objects in separate directories so that they are not
constantly rebuilt (2013-93-19). constantly rebuilt (2013-93-19).
* fs/fat: Create an error in FAT file creation. The FAT logic was
not making a distinction between directory non-existence and file
non-existence so when it you try to create a file in a non-existent
directory, it would create a file with the nameof the missing
directory. Reported by Andrew Tridgell.

View File

@ -260,6 +260,12 @@ static int fat_open(FAR struct file *filep, const char *relpath,
/* fall through to finish the file open operations */ /* fall through to finish the file open operations */
} }
/* ENOENT would be returned by fat_finddirentry() if the full
* directory path was found, but the file was not found in the
* final directory.
*/
else if (ret == -ENOENT) else if (ret == -ENOENT)
{ {
/* The file does not exist. Were we asked to create it? */ /* The file does not exist. Were we asked to create it? */
@ -284,6 +290,9 @@ static int fat_open(FAR struct file *filep, const char *relpath,
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
} }
/* No other error is handled */
else else
{ {
/* An error occurred while checking for file existence -- /* An error occurred while checking for file existence --
@ -1406,6 +1415,7 @@ static int fat_opendir(struct inode *mountpt, const char *relpath, struct fs_dir
{ {
goto errout_with_semaphore; goto errout_with_semaphore;
} }
direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset];
/* Check if this is the root directory */ /* Check if this is the root directory */
@ -1942,11 +1952,20 @@ static int fat_mkdir(struct inode *mountpt, const char *relpath, mode_t mode)
ret = fat_finddirentry(fs, &dirinfo, relpath); ret = fat_finddirentry(fs, &dirinfo, relpath);
/* Or if any error occurs other -ENOENT, then return the error. For
* example, if one of the earlier directory path segments was not found
* then ENOTDIR will be returned.
*/
if (ret != -ENOENT)
{
/* If anything exists at this location, then we fail with EEXIST */ /* If anything exists at this location, then we fail with EEXIST */
if (ret == OK) if (ret == OK)
{ {
ret = -EEXIST; ret = -EEXIST;
}
goto errout_with_semaphore; goto errout_with_semaphore;
} }
@ -2224,13 +2243,6 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
/* Now find the directory where we should create the newpath object */ /* Now find the directory where we should create the newpath object */
ret = fat_finddirentry(fs, &dirinfo, newrelpath); 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 /* What we expect is -ENOENT mean that the full directory path was
* followed but that the object does not exists in the terminal directory. * followed but that the object does not exists in the terminal directory.
@ -2238,6 +2250,13 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath,
if (ret != -ENOENT) if (ret != -ENOENT)
{ {
if (ret == OK)
{
/* It is an error if the object at newrelpath already exists */
ret = -EEXIST;
}
goto errout_with_semaphore; goto errout_with_semaphore;
} }

View File

@ -2343,6 +2343,17 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
if (ret < 0) if (ret < 0)
{ {
/* A return value of -ENOENT would mean that the path segement
* was not found. Let's distinguish to cases: (1) the final
* file was not found in the directory (-ENOENT), or (2) one
* of the directory path segments does not exist (-ENOTDIR)
*/
if (ret == -ENOENT && terminator != '\0')
{
return -ENOTDIR;
}
return ret; return ret;
} }
@ -2351,7 +2362,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo,
* the path. * the path.
*/ */
if (!terminator) if (terminator == '\0')
{ {
/* Return success meaning that the description the matching /* Return success meaning that the description the matching
* directory entry is in dirinfo. * directory entry is in dirinfo.
@ -2795,7 +2806,7 @@ int fat_remove(struct fat_mountpt_s *fs, const char *relpath, bool directory)
ret = fat_finddirentry(fs, &dirinfo, relpath); ret = fat_finddirentry(fs, &dirinfo, relpath);
if (ret != OK) if (ret != OK)
{ {
/* No such path */ /* Most likely, some element of the path does not exist. */
return -ENOENT; return -ENOENT;
} }