From c5f5be565ea5488b3c6ba18b4af7696ef0cd92b8 Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Tue, 19 Nov 2002 12:48:50 +0000 Subject: Added rename() git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2857 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/file.c | 57 ++++++++++++++++-- firmware/common/file.h | 2 +- firmware/drivers/fat.c | 159 ++++++++++++++++++++++++++++++++----------------- firmware/drivers/fat.h | 3 + 4 files changed, 163 insertions(+), 58 deletions(-) (limited to 'firmware') diff --git a/firmware/common/file.c b/firmware/common/file.c index 01a0ebf890..1d78dcb456 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -125,7 +125,7 @@ int open(const char* pathname, int flags) break; } } - closedir(dir); + if ( !entry ) { LDEBUGF("Didn't find file %s\n",name); if ( file->write && (flags & O_CREAT) ) { @@ -135,6 +135,7 @@ int open(const char* pathname, int flags) DEBUGF("Couldn't create %s in %s\n",name,pathname); errno = EIO; file->busy = false; + closedir(dir); return -5; } file->size = 0; @@ -143,9 +144,11 @@ int open(const char* pathname, int flags) DEBUGF("Couldn't find %s in %s\n",name,pathname); errno = ENOENT; file->busy = false; + closedir(dir); return -6; } } + closedir(dir); file->cacheoffset = -1; file->fileoffset = 0; @@ -205,23 +208,69 @@ int remove(const char* name) file = &openfiles[fd]; rc = fat_truncate(&(file->fatfile)); if ( rc < 0 ) { - DEBUGF("Failed truncating file\n"); + DEBUGF("Failed truncating file: %d\n", rc); errno = EIO; return -1; } rc = fat_remove(&(file->fatfile)); if ( rc < 0 ) { - DEBUGF("Failed removing file\n"); + DEBUGF("Failed removing file: %d\n", rc); errno = EIO; return -2; } file->size = 0; + rc = close(fd); + if (rc<0) + return -3; + + return 0; +} + +int rename(const char* path, const char* newpath) +{ + int rc, fd; + char* nameptr; + struct filedesc* file; + + /* verify new path does not already exist */ + fd = open(newpath, O_RDONLY); + if ( fd >= 0 ) { + errno = EBUSY; + return fd; + } close(fd); - return rc; + fd = open(path, O_RDONLY); + if ( fd < 0 ) { + errno = EIO; + return fd; + } + + /* strip path */ + nameptr = strrchr(newpath,'/'); + if (nameptr) + nameptr++; + else + nameptr = (char*)newpath; + + file = &openfiles[fd]; + rc = fat_rename(&file->fatfile, nameptr, file->size); + if ( rc < 0 ) { + DEBUGF("Failed renaming file: %d\n", rc); + errno = EIO; + return -1; + } + + rc = close(fd); + if (rc<0) { + errno = EIO; + return -2; + } + + return 0; } int ftruncate(int fd, unsigned int size) diff --git a/firmware/common/file.h b/firmware/common/file.h index bf7ad82ff7..bf8dc38ae9 100644 --- a/firmware/common/file.h +++ b/firmware/common/file.h @@ -58,7 +58,7 @@ extern int lseek(int fd, int offset, int whence); extern int creat(const char *pathname, int mode); extern int write(int fd, void* buf, int count); extern int remove(const char* pathname); -extern int rename(const char* oldname, const char* newname); +extern int rename(const char* path, const char* newname); extern int ftruncate(int fd, unsigned int size); #else diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 2ff36e2595..b6bedc1d26 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -1175,6 +1175,68 @@ int fat_closewrite(struct fat_file *file, int size) return 0; } +static int free_direntries(int dircluster, int startentry, int numentries) +{ + unsigned char buf[SECTOR_SIZE]; + struct fat_file dir; + unsigned int entry = startentry - numentries + 1; + unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; + int i; + int err; + + /* create a temporary file handle for the dir holding this file */ + err = fat_open(dircluster, &dir, NULL); + if (err<0) + return -1; + + err = fat_seek( &dir, sector ); + if (err<0) + return -2; + + err = fat_readwrite(&dir, 1, buf, false); + if (err<1) + return -3; + + for (i=0; i < numentries; i++) { + LDEBUGF("Clearing dir entry %d (%d/%d)\n", + entry, i+1, numentries); + buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; + entry++; + + if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { + /* flush this sector */ + err = fat_seek(&dir, sector); + if (err<0) + return -4; + + err = fat_readwrite(&dir, 1, buf, true); + if (err<1) + return -5; + + if ( i+1 < numentries ) { + /* read next sector */ + err = fat_readwrite(&dir, 1, buf, false); + if (err<1) + return -6; + } + sector++; + } + } + + if ( entry % DIR_ENTRIES_PER_SECTOR ) { + /* flush this sector */ + err = fat_seek(&dir, sector); + if (err<0) + return -7; + + err = fat_readwrite(&dir, 1, buf, true); + if (err<1) + return -8; + } + + return 0; +} + int fat_remove(struct fat_file* file) { int next, last = file->firstcluster; @@ -1187,68 +1249,59 @@ int fat_remove(struct fat_file* file) last = next; } - /* free all dir entries */ - if ( file->dircluster ) { - unsigned char buf[SECTOR_SIZE]; - struct fat_file dir; - unsigned int entry = file->direntry - file->direntries + 1; - unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; - unsigned int i; - int err; - - /* create a temporary file handle for the dir holding this file */ - err = fat_open(file->dircluster, &dir, NULL); - if (err<0) + if ( file->dircluster ) + if ( free_direntries(file->dircluster, + file->direntry, + file->direntries) < 0 ) return -1; - err = fat_seek( &dir, sector ); - if (err<0) - return -2; + file->firstcluster = 0; + file->dircluster = 0; - err = fat_readwrite(&dir, 1, buf, false); - if (err<1) - return -3; + return 0; +} - for (i=0; i < file->direntries; i++) { - LDEBUGF("Clearing dir entry %d (%d/%d)\n", - entry, i+1, file->direntries); - buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; - entry++; +int fat_rename(struct fat_file* file, + unsigned char* newname, + int size) +{ + int err; + struct fat_dir dir; + struct fat_file newfile = *file; - if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { - /* flush this sector */ - err = fat_seek(&dir, sector); - if (err<0) - return -4; + if ( !file->dircluster ) { + LDEBUGF("File has no dir cluster!\n"); + return -1; + } - err = fat_readwrite(&dir, 1, buf, true); - if (err<1) - return -5; + /* create a temporary file handle */ + LDEBUGF("create a temporary file handle: fat_opendir(%x,%x)\n", + &dir, file->dircluster); + err = fat_opendir(&dir, file->dircluster); + if (err<0) + return -2; - if ( i+1 < file->direntries ) { - /* read next sector */ - err = fat_readwrite(&dir, 1, buf, false); - if (err<1) - return -6; - } - sector++; - } - } + /* create new name */ + LDEBUGF("create new name\n"); + err = add_dir_entry(&dir, &newfile, newname); + if (err<0) + return -3; - if ( entry % DIR_ENTRIES_PER_SECTOR ) { - /* flush this sector */ - err = fat_seek(&dir, sector); - if (err<0) - return -7; - - err = fat_readwrite(&dir, 1, buf, true); - if (err<1) - return -8; - } - } + /* write size and cluster link */ + LDEBUGF("write size and cluster link\n"); + err = update_file_size(&newfile, size); + if (err<0) + return -4; - file->firstcluster = 0; - file->dircluster = 0; + /* remove old name */ + LDEBUGF("remove old name\n"); + err = free_direntries(file->dircluster, file->direntry, file->direntries); + if (err<0) + return -5; + + err = flush_fat(); + if (err<0) + return -6; return 0; } diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index a5abfd5214..d81ec65363 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h @@ -84,6 +84,9 @@ extern int fat_closewrite(struct fat_file *ent, int size); extern int fat_seek(struct fat_file *ent, unsigned int sector ); extern int fat_remove(struct fat_file *ent); extern int fat_truncate(struct fat_file *ent); +extern int fat_rename(struct fat_file* file, + unsigned char* newname, + int size); extern int fat_opendir(struct fat_dir *ent, unsigned int currdir); extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); -- cgit v1.2.3