From e0e0140f4e63b451a110840dc5ef5c22c3ed9f7c Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Sun, 22 Aug 2004 11:28:24 +0000 Subject: Bug fix: renaming a directory could cause a name clash. New feature: rename() can now move files/directories as well. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5008 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/file.c | 42 ++++++++++++++++++++++++++++++++++++------ firmware/drivers/fat.c | 13 +++++++------ firmware/export/fat.h | 1 + 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/firmware/common/file.c b/firmware/common/file.c index e875d43f2e..546a927037 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -277,12 +277,16 @@ int remove(const char* name) int rename(const char* path, const char* newpath) { int rc, fd; + DIR* dir; char* nameptr; + char* dirptr; struct filedesc* file; + char newpath2[MAX_PATH]; /* verify new path does not already exist */ + /* If it is a directory, errno == EISDIR if the name exists */ fd = open(newpath, O_RDONLY); - if ( fd >= 0 ) { + if ( fd >= 0 || errno == EISDIR) { close(fd); errno = EBUSY; return -1; @@ -295,25 +299,51 @@ int rename(const char* path, const char* newpath) return fd * 10 - 2; } - /* strip path */ + /* extract new file name */ nameptr = strrchr(newpath,'/'); if (nameptr) nameptr++; else - nameptr = (char*)newpath; + return - 3; + + /* Extract new path */ + strcpy(newpath2, newpath); + + dirptr = strrchr(newpath2,'/'); + if(dirptr) + *dirptr = 0; + else + return - 4; + dirptr = newpath2; + + if(strlen(dirptr) == 0) { + dirptr = "/"; + } + + dir = opendir(dirptr); + if(!dir) + return - 5; + file = &openfiles[fd]; - rc = fat_rename(&file->fatfile, nameptr, file->size, file->attr); + rc = fat_rename(&file->fatfile, &dir->fatdir, nameptr, + file->size, file->attr); if ( rc < 0 ) { DEBUGF("Failed renaming file: %d\n", rc); errno = EIO; - return rc * 10 - 3; + return rc * 10 - 6; } rc = close(fd); if (rc<0) { errno = EIO; - return rc * 10 - 4; + return rc * 10 - 7; + } + + rc = closedir(dir); + if (rc<0) { + errno = EIO; + return rc * 10 - 8; } return 0; diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 1b530153a5..e41bbaca41 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -1551,12 +1551,13 @@ int fat_remove(struct fat_file* file) } int fat_rename(struct fat_file* file, - const unsigned char* newname, - int size, - int attr) + struct fat_dir* dir, + const unsigned char* newname, + int size, + int attr) { int rc; - struct fat_dir dir; + struct fat_dir olddir; struct fat_file newfile = *file; if ( !file->dircluster ) { @@ -1565,12 +1566,12 @@ int fat_rename(struct fat_file* file, } /* create a temporary file handle */ - rc = fat_opendir(&dir, file->dircluster, NULL); + rc = fat_opendir(&olddir, file->dircluster, NULL); if (rc < 0) return rc * 10 - 2; /* create new name */ - rc = add_dir_entry(&dir, &newfile, newname, false, false); + rc = add_dir_entry(dir, &newfile, newname, false, false); if (rc < 0) return rc * 10 - 3; diff --git a/firmware/export/fat.h b/firmware/export/fat.h index f4f09a2d19..6f9c9c5d11 100644 --- a/firmware/export/fat.h +++ b/firmware/export/fat.h @@ -89,6 +89,7 @@ extern int fat_seek(struct fat_file *ent, unsigned int sector ); extern int fat_remove(struct fat_file *ent); extern int fat_truncate(const struct fat_file *ent); extern int fat_rename(struct fat_file* file, + struct fat_dir* dir, const unsigned char* newname, int size, int attr); -- cgit v1.2.3