From 3d7ed16eabcbea16723b66df2cd2a7d10ba22474 Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 20 Mar 2013 15:26:50 +0000 Subject: 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 --- nuttx/ChangeLog | 6 ++++++ nuttx/fs/fat/fs_fat32.c | 39 +++++++++++++++++++++++++++++---------- nuttx/fs/fat/fs_fat32dirent.c | 15 +++++++++++++-- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index b6b225c65..6baf9f235 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4389,3 +4389,9 @@ build different objects in the first and second pass kernel builds need to keep those objects in separate directories so that they are not 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. + diff --git a/nuttx/fs/fat/fs_fat32.c b/nuttx/fs/fat/fs_fat32.c index 7202bb63d..c9167b3b4 100644 --- a/nuttx/fs/fat/fs_fat32.c +++ b/nuttx/fs/fat/fs_fat32.c @@ -260,6 +260,12 @@ static int fat_open(FAR struct file *filep, const char *relpath, /* 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) { /* 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]; } + + /* No other error is handled */ + else { /* 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; } + direntry = &fs->fs_buffer[dirinfo.fd_seq.ds_offset]; /* 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); - /* If anything exists at this location, then we fail with EEXIST */ + /* 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 == OK) + if (ret != -ENOENT) { - ret = -EEXIST; + /* If anything exists at this location, then we fail with EEXIST */ + + if (ret == OK) + { + ret = -EEXIST; + } + 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 */ 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. @@ -2238,6 +2250,13 @@ int fat_rename(struct inode *mountpt, const char *oldrelpath, if (ret != -ENOENT) { + if (ret == OK) + { + /* It is an error if the object at newrelpath already exists */ + + ret = -EEXIST; + } + goto errout_with_semaphore; } diff --git a/nuttx/fs/fat/fs_fat32dirent.c b/nuttx/fs/fat/fs_fat32dirent.c index 18cf67847..39bdb5371 100644 --- a/nuttx/fs/fat/fs_fat32dirent.c +++ b/nuttx/fs/fat/fs_fat32dirent.c @@ -2343,6 +2343,17 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, 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; } @@ -2351,7 +2362,7 @@ int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, * the path. */ - if (!terminator) + if (terminator == '\0') { /* Return success meaning that the description the matching * 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); if (ret != OK) { - /* No such path */ + /* Most likely, some element of the path does not exist. */ return -ENOENT; } -- cgit v1.2.3