From 46ddacf533b2b154373f0ac98c85b4ac172ccfa6 Mon Sep 17 00:00:00 2001 From: Björn Stenberg Date: Tue, 22 Oct 2002 15:06:08 +0000 Subject: Fat32 write updates: Nixed some bugs. Basic file creation now works. Todo: Long filenames and extensive test cases. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2742 a1c6a512-1295-4272-9138-f99709370657 --- firmware/common/file.c | 11 ++- firmware/drivers/fat.c | 159 +++++++++++++++++++++++++------------------- firmware/drivers/fat.h | 5 +- firmware/test/fat/ata-sim.c | 8 +-- firmware/test/fat/main.c | 42 +++++------- 5 files changed, 120 insertions(+), 105 deletions(-) (limited to 'firmware') diff --git a/firmware/common/file.c b/firmware/common/file.c index 3e402bde2b..0cde938a70 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c @@ -178,7 +178,7 @@ int close(int fd) } /* tie up all loose ends */ - fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size); + fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].fileoffset); } openfiles[fd].busy = false; return rc; @@ -239,8 +239,6 @@ static int readwrite(int fd, void* buf, int count, bool write) nread = headbytes; count -= headbytes; - - LDEBUGF("readwrite incache: offs=%d\n",openfiles[fd].cacheoffset); } /* read whole sectors right into the supplied buffer */ @@ -316,6 +314,13 @@ int lseek(int fd, int offset, int whence) return -1; } + if ( openfiles[fd].write ) { + DEBUGF("lseek() is not supported when writing\n"); + errno = EROFS; + return -2; + } + + switch ( whence ) { case SEEK_SET: pos = offset; diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 322ae76a2d..a60a017d3e 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c @@ -241,8 +241,7 @@ int fat_mount(int startsector) err = ata_read_sectors(startsector,1,buf); if(err) { - DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", - err); + DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", err); return -1; } @@ -325,7 +324,7 @@ int fat_mount(int startsector) if (err) { DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", err); - return -1; + return -4; } fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); @@ -430,8 +429,6 @@ static int find_free_cluster(int startcluster) int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; int i; - LDEBUGF("find_free_cluster(%x)\n",startcluster); - for (i = sector; i= FAT_EOF_MARK ) @@ -608,34 +613,37 @@ static int add_dir_entry(struct fat_dir* dir, int i; int err; int sec; - int sec_cnt; + int sec_cnt = 0; bool need_to_update_last_empty_marker = false; bool done = false; unsigned char firstbyte; int currdir = dir->startcluster; bool is_rootdir = (currdir == 0); - LDEBUGF( "add_dir_entry()\n"); + LDEBUGF( "add_dir_entry(%x,%s,%x)\n", + dir->startcluster, de->name, file->firstcluster); if (is_rootdir) sec = fat_bpb.rootdirsector; else sec = first_sector_of_cluster(currdir); - sec_cnt = 0; - while(!done) { if (sec_cnt >= fat_bpb.bpb_secperclus) { - int oldcluster = currdir; + int oldcluster; + if (!currdir) + currdir = sec2cluster(fat_bpb.rootdirsector); + oldcluster = currdir; + /* We have reached the end of this cluster */ - LDEBUGF("Moving to the next cluster..."); + LDEBUGF("Moving to the next cluster...\n"); currdir = get_next_cluster(currdir); - LDEBUGF("new cluster is %d\n", currdir); - if (!currdir) { + /* end of dir, add new cluster */ + LDEBUGF("Adding cluster to dir\n"); currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); if (!currdir) { currdir = find_free_cluster(0); @@ -646,9 +654,11 @@ static int add_dir_entry(struct fat_dir* dir, } update_fat_entry(oldcluster, currdir); } + LDEBUGF("new cluster is %x\n", currdir); + sec = cluster2sec(currdir); } - LDEBUGF("Reading sector %d...\n", sec); + LDEBUGF("Reading sector %x...\n", sec); /* Read the next sector in the current dir */ err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); if (err) @@ -673,7 +683,7 @@ static int add_dir_entry(struct fat_dir* dir, firstbyte = buf[i]; if (firstbyte == 0xe5 || firstbyte == 0) { - LDEBUGF("Found free slot at entry %d in sector %x\n", + LDEBUGF("Found free entry %d in sector %x\n", i/DIR_ENTRY_SIZE, sec); eptr = &buf[i]; memset(eptr, 0, DIR_ENTRY_SIZE); @@ -681,22 +691,6 @@ static int add_dir_entry(struct fat_dir* dir, eptr[FATDIR_ATTR] = de->attr; eptr[FATDIR_NTRES] = 0; - eptr[FATDIR_CRTTIMETENTH] = de->crttimetenth; - eptr[FATDIR_CRTDATE] = de->crtdate & 0xff; - eptr[FATDIR_CRTDATE+1] = de->crtdate >> 8; - eptr[FATDIR_CRTTIME] = de->crttime & 0xff; - eptr[FATDIR_CRTTIME+1] = de->crttime >> 8; - - eptr[FATDIR_WRTDATE] = de->wrtdate & 0xff; - eptr[FATDIR_WRTDATE+1] = de->wrtdate >> 8; - eptr[FATDIR_WRTTIME] = de->wrttime & 0xff; - eptr[FATDIR_WRTTIME+1] = de->wrttime >> 8; - - eptr[FATDIR_FILESIZE] = de->filesize & 0xff; - eptr[FATDIR_FILESIZE+1] = (de->filesize >> 8) & 0xff; - eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; - eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; - /* remember where the dir entry is located */ file->dirsector = sec; file->direntry = i/DIR_ENTRY_SIZE; @@ -853,15 +847,21 @@ static void update_dir_entry( struct fat_file* file, int size ) " (error code %d)\n", sector, err); return; } - - clusptr = (short*)(entry + FATDIR_FSTCLUSHI); - *clusptr = SWAB16(file->firstcluster >> 16); - clusptr = (short*)(entry + FATDIR_FSTCLUSLO); - *clusptr = SWAB16(file->firstcluster & 0xffff); + if ( size == -1 ) { + /* mark entry deleted */ + entry[0] = 0xe5; + } + else { + clusptr = (short*)(entry + FATDIR_FSTCLUSHI); + *clusptr = SWAB16(file->firstcluster >> 16); + + clusptr = (short*)(entry + FATDIR_FSTCLUSLO); + *clusptr = SWAB16(file->firstcluster & 0xffff); - sizeptr = (int*)(entry + FATDIR_FILESIZE); - *sizeptr = SWAB32(size); + sizeptr = (int*)(entry + FATDIR_FILESIZE); + *sizeptr = SWAB32(size); + } err = ata_write_sectors(sector, 1, buf); if (err) @@ -902,8 +902,8 @@ int fat_open(unsigned int startcluster, struct fat_dir* dir) { file->firstcluster = startcluster; - file->nextcluster = startcluster; - file->nextsector = cluster2sec(startcluster); + file->lastcluster = startcluster; + file->lastsector = cluster2sec(startcluster); file->sectornum = 0; /* remember where the file's dir entry is located */ @@ -935,8 +935,8 @@ int fat_create_file(char* name, err = add_dir_entry(dir, &de, file); if (!err) { file->firstcluster = 0; - file->nextcluster = 0; - file->nextsector = 0; + file->lastcluster = 0; + file->lastsector = 0; file->sectornum = 0; } @@ -945,21 +945,38 @@ int fat_create_file(char* name, int fat_closewrite(struct fat_file *file, int size) { - int endcluster = file->nextcluster; - int next, last = endcluster; + int next, last = file->lastcluster; + int endcluster = last; - /* free unused clusters, if any */ - for ( next = get_next_cluster(last); next; last = next ) { - LDEBUGF("Clearing cluster %x\n",last); + LDEBUGF("fat_closewrite()\n"); + + last = get_next_cluster(last); + while ( last && last != FAT_EOF_MARK ) { + next = get_next_cluster(last); update_fat_entry(last,0); + last = next; } - /* mark last used cluster as last in chain */ update_fat_entry(endcluster, FAT_EOF_MARK); - + update_dir_entry(file, size); flush_fat(); - update_dir_entry(file, size); + return 0; +} + +int fat_remove(struct fat_file* file) +{ + int next, last = file->firstcluster; + + LDEBUGF("fat_remove(%x)\n",last); + + while ( last != FAT_EOF_MARK ) { + LDEBUGF("Freeing cluster %x\n",last); + next = get_next_cluster(last); + update_fat_entry(last,0); + last = next; + } + update_dir_entry(file, -1); return 0; } @@ -967,15 +984,15 @@ int fat_closewrite(struct fat_file *file, int size) int fat_readwrite( struct fat_file *file, int sectorcount, void* buf, bool write ) { - int cluster = file->nextcluster; - int sector = file->nextsector; + int cluster = file->lastcluster; + int sector = file->lastsector; int numsec = file->sectornum; - int first, last; + int first=0, last=0; int err, i; LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n", cluster,sectorcount,buf,write?"write":"read"); - + LDEBUGF( "fat_readwrite: c=%x s=%x n=%d\n", cluster,sector,numsec); if ( sector == -1 ) return 0; @@ -995,12 +1012,8 @@ int fat_readwrite( struct fat_file *file, int sectorcount, return -1; } - first = sector; - last = sector; - /* find sequential sectors and read/write them all at once */ for (i=0; i=0; i++ ) { - numsec++; if ( numsec >= fat_bpb.bpb_secperclus ) { int oldcluster = cluster; cluster = get_next_cluster(cluster); @@ -1008,9 +1021,9 @@ int fat_readwrite( struct fat_file *file, int sectorcount, if ( write ) { /* writing past end-of-file, find a new free cluster to use. */ - cluster = find_free_cluster(cluster); + cluster = find_free_cluster(oldcluster+1); if (!cluster) { - /* no cluster found after last, + /* no free cluster found after last, search from beginning */ cluster = find_free_cluster(0); if (!cluster) { @@ -1030,6 +1043,7 @@ int fat_readwrite( struct fat_file *file, int sectorcount, if (cluster) { sector = cluster2sec(cluster); + LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector); if (sector<0) return -1; numsec=0; @@ -1037,7 +1051,13 @@ int fat_readwrite( struct fat_file *file, int sectorcount, } else sector++; + numsec++; + if (!first) + first = sector; + if (!last) + last = sector; + if ( (sector != last+1) || /* not sequential any more? */ (i == sectorcount-1) || /* last sector requested? */ (last-first+1 == 256) ) { /* max 256 sectors per ata request */ @@ -1056,8 +1076,9 @@ int fat_readwrite( struct fat_file *file, int sectorcount, } last = sector; } - file->nextcluster = cluster; - file->nextsector = sector; + + file->lastcluster = cluster; + file->lastsector = sector; file->sectornum = numsec; return sectorcount; @@ -1099,8 +1120,8 @@ int fat_seek(struct fat_file *file, int seeksector ) } } - file->nextcluster = cluster; - file->nextsector = sector; + file->lastcluster = cluster; + file->lastsector = sector; file->sectornum = numsec; return 0; } diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index 3052488c5a..1316202a6c 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h @@ -58,8 +58,8 @@ struct fat_dir struct fat_file { int firstcluster; /* first cluster in file */ - int nextcluster; /* cluster of last access */ - int nextsector; /* sector of last access */ + int lastcluster; /* cluster of last access */ + int lastsector; /* sector of last access */ int sectornum; /* sector number in this cluster */ int dirsector; /* sector where the dir entry is located */ int direntry; /* dir entry index in sector */ @@ -79,6 +79,7 @@ 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_remove(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); diff --git a/firmware/test/fat/ata-sim.c b/firmware/test/fat/ata-sim.c index a37fabcfc0..a64e0a4d4d 100644 --- a/firmware/test/fat/ata-sim.c +++ b/firmware/test/fat/ata-sim.c @@ -9,7 +9,7 @@ static FILE* file; int ata_read_sectors(unsigned long start, unsigned char count, void* buf) { - DEBUGF("Reading block 0x%lx\n",start); + DEBUGF("[Reading block 0x%lx]\n",start); if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) { perror("fseek"); return -1; @@ -17,14 +17,14 @@ int ata_read_sectors(unsigned long start, unsigned char count, void* buf) if(!fread(buf,BLOCK_SIZE,count,file)) { printf("Failed reading %d blocks starting at block 0x%lx\n",count,start); perror("fread"); - return -1; + return -2; } return 0; } int ata_write_sectors(unsigned long start, unsigned char count, void* buf) { - DEBUGF("Writing block 0x%lx\n",start); + DEBUGF("[Writing block 0x%lx]\n",start); if (start == 0) { DEBUGF("Holy crap! You're writing on sector 0!\n"); @@ -37,7 +37,7 @@ int ata_write_sectors(unsigned long start, unsigned char count, void* buf) } if(!fwrite(buf,BLOCK_SIZE,count,file)) { perror("fwrite"); - return -1; + return -2; } return 0; } diff --git a/firmware/test/fat/main.c b/firmware/test/fat/main.c index 1b9fd22183..91e7444999 100644 --- a/firmware/test/fat/main.c +++ b/firmware/test/fat/main.c @@ -19,6 +19,7 @@ void panicf( char *fmt, ...) { va_list ap; va_start( ap, fmt ); + printf("***PANIC*** "); vprintf( fmt, ap ); va_end( ap ); exit(0); @@ -82,17 +83,20 @@ void dbg_dir(char* currdir) } } -void dbg_mkfile(char* name) +void dbg_mkfile(char* name, int num) { - char* text = "Detta är en dummy-text\n"; + char text[800]; int i; int fd = open(name,O_WRONLY); if (fd<0) { DEBUGF("Failed creating file\n"); return; } - for (i=0;i<200;i++) - if (write(fd, text, strlen(text)) < 0) + for (i=0; i= 0 ) { - rc = read(fd, buf, SECTOR_SIZE); - if( rc > 0 ) - { - buf[rc]=0; - printf("%d: %s\n", strlen(buf), buf); - } - else if ( rc == 0 ) { - DEBUGF("EOF\n"); - } - else - { - DEBUGF("Failed reading file: %d\n",rc); - } - } - else { - perror("lseek"); - } - - rc = lseek(fd,-100,SEEK_CUR); + rc = lseek(fd,-512,SEEK_END); if ( rc >= 0 ) { rc = read(fd, buf, SECTOR_SIZE); if( rc > 0 ) @@ -284,6 +268,8 @@ void dbg_console(void) } } +extern void ata_exit(void); + int main(int argc, char *argv[]) { int rc,i; @@ -325,12 +311,14 @@ int main(int argc, char *argv[]) //dbg_console(); //dbg_dir("/"); #if 1 - dbg_head("/bepa.txt"); + dbg_tail("/depa.txt"); #else - dbg_mkfile("/bepa.txt"); + dbg_mkfile("/depa.txt", 10); #endif dbg_dir("/"); + ata_exit(); + return 0; } -- cgit v1.2.3