From 11a09e632ceb5513aad54aa6b2c6031bb28b4533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Stenberg?= Date: Mon, 11 Nov 2002 10:21:51 +0000 Subject: [PATCH] close() now does not truncate the file. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2821 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/file.c | 42 ++++++++++++++++++++++++++++++++++++++---- firmware/drivers/fat.c | 36 +++++++++++++++++------------------- firmware/drivers/fat.h | 3 ++- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/firmware/common/file.c b/firmware/common/file.c index 1dd71d98ae..b2c2644725 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -38,7 +38,7 @@ struct filedesc { unsigned char cache[SECTOR_SIZE]; int cacheoffset; - int fileoffset; + unsigned int fileoffset; int size; struct fat_file fatfile; bool busy; @@ -178,7 +178,7 @@ int close(int fd) } /* tie up all loose ends */ - fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].fileoffset); + fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size); } openfiles[fd].busy = false; return rc; @@ -191,7 +191,21 @@ int remove(const char* name) if ( fd < 0 ) return fd; + rc = fat_truncate(&(openfiles[fd].fatfile)); + if ( rc < 0 ) { + DEBUGF("Failed truncating file\n"); + errno = EIO; + return -1; + } + rc = fat_remove(&(openfiles[fd].fatfile)); + if ( rc < 0 ) { + DEBUGF("Failed removing file\n"); + errno = EIO; + return -2; + } + + openfiles[fd].size = 0; close(fd); @@ -259,7 +273,7 @@ static int readwrite(int fd, void* buf, int count, bool write) if ( rc < 0 ) { DEBUGF("Failed read/writing %d sectors\n",sectors); errno = EIO; - return -2; + return -3; } else { if ( rc > 0 ) { @@ -278,10 +292,30 @@ static int readwrite(int fd, void* buf, int count, bool write) openfiles[fd].cacheoffset = -1; } } + openfiles[fd].fileoffset += nread; + nread = 0; /* any tail bytes? */ if ( count ) { if (write) { + /* sector is only partially filled. copy-back from disk */ + int rc; + LDEBUGF("Copy-back tail cache\n"); + rc = fat_readwrite(&(openfiles[fd].fatfile), 1, + openfiles[fd].cache, false ); + if ( rc < 0 ) { + DEBUGF("Failed reading\n"); + errno = EIO; + return -4; + } + /* seek back one sector to put file position right */ + rc = fat_seek(&(openfiles[fd].fatfile), + openfiles[fd].fileoffset / SECTOR_SIZE); + if ( rc < 0 ) { + DEBUGF("fat_seek() failed\n"); + errno = EIO; + return -5; + } memcpy( openfiles[fd].cache, buf + nread, count ); } else { @@ -289,7 +323,7 @@ static int readwrite(int fd, void* buf, int count, bool write) &(openfiles[fd].cache),false) < 1 ) { DEBUGF("Failed caching sector\n"); errno = EIO; - return -1; + return -6; } memcpy( buf + nread, openfiles[fd].cache, count ); } diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 47bfd1afef..74bdbd3491 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -167,7 +167,7 @@ static unsigned int getcurrdostime(unsigned short *dosdate, unsigned short *dostime, unsigned char *dostenth); static int create_dos_name(unsigned char *name, unsigned char *newname); -static int find_free_cluster(int start); +static unsigned int find_free_cluster(unsigned int start); #endif #define FAT_CACHE_SIZE 0x20 @@ -438,10 +438,10 @@ static void *cache_fat_sector(int fatsector) return sectorbuf; } -static int find_free_cluster(int startcluster) +static unsigned int find_free_cluster(unsigned int startcluster) { - int sector = startcluster / CLUSTERS_PER_FAT_SECTOR; - int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; + unsigned int sector = startcluster / CLUSTERS_PER_FAT_SECTOR; + unsigned int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; int i; /* don't waste time scanning if the disk is already full */ @@ -511,7 +511,7 @@ static int update_fat_entry(unsigned int entry, unsigned int val) return 0; } -static int read_fat_entry(int entry) +static int read_fat_entry(unsigned int entry) { int sector = entry / CLUSTERS_PER_FAT_SECTOR; int offset = entry % CLUSTERS_PER_FAT_SECTOR; @@ -998,24 +998,23 @@ int fat_create_file(char* name, return err; } -int fat_closewrite(struct fat_file *file, int size) +int fat_truncate(struct fat_file *file) { - int next, last = file->lastcluster; - int endcluster = last; - - LDEBUGF("fat_closewrite(size=%d, last=%x)\n",size, last); - /* truncate trailing clusters */ - last = get_next_cluster(last); + int next; + int last = get_next_cluster(file->lastcluster); while ( last && last != FAT_EOF_MARK ) { next = get_next_cluster(last); update_fat_entry(last,0); last = next; } - /* if no cluster was written, size is 0 */ - if (!endcluster) - size = 0; + return 0; +} + +int fat_closewrite(struct fat_file *file, int size) +{ + LDEBUGF("fat_closewrite(size=%d)\n",size); if (!size) { /* empty file */ @@ -1024,18 +1023,17 @@ int fat_closewrite(struct fat_file *file, int size) file->firstcluster = 0; } } - else - update_fat_entry(endcluster, FAT_EOF_MARK); if (file->dirsector) update_dir_entry(file, size); flush_fat(); #ifdef TEST_FAT - { + if ( file->firstcluster ) { /* debug */ int count = 0; int len; + int next; for ( next = file->firstcluster; next; next = get_next_cluster(next) ) LDEBUGF("cluster %d: %x\n", count++, next); @@ -1213,7 +1211,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, return i; } -int fat_seek(struct fat_file *file, int seeksector ) +int fat_seek(struct fat_file *file, unsigned int seeksector ) { int clusternum=0, sectornum=0, sector=0; int cluster = file->firstcluster; diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index 6ed68ad8d8..b23d8dfa08 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h @@ -79,8 +79,9 @@ extern int fat_create_file(char* name, extern int fat_readwrite(struct fat_file *ent, int sectorcount, void* buf, bool write ); extern int fat_closewrite(struct fat_file *ent, int size); -extern int fat_seek(struct fat_file *ent, int sector ); +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_opendir(struct fat_dir *ent, unsigned int currdir); extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);