diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-10-22 15:06:08 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-10-22 15:06:08 +0000 |
commit | 46ddacf533b2b154373f0ac98c85b4ac172ccfa6 (patch) | |
tree | db40164976c9993e1b12a60bb63320a0aa382390 | |
parent | a901c3a433125a939bef9caf6a8219f97f395fc7 (diff) | |
download | rockbox-46ddacf533b2b154373f0ac98c85b4ac172ccfa6.tar.gz rockbox-46ddacf533b2b154373f0ac98c85b4ac172ccfa6.zip |
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
-rw-r--r-- | firmware/common/file.c | 11 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 159 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 5 | ||||
-rw-r--r-- | firmware/test/fat/ata-sim.c | 8 | ||||
-rw-r--r-- | firmware/test/fat/main.c | 42 |
5 files changed, 120 insertions, 105 deletions
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_bpb.fatsize; i++) { int j; unsigned int* fat = cache_fat_sector(i); @@ -440,15 +437,16 @@ static int find_free_cluster(int startcluster) for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++) if (!(SWAB32(fat[j]) & 0x0fffffff)) { int c = i * CLUSTERS_PER_FAT_SECTOR + j; - LDEBUGF("Found free cluster %x\n",c); + LDEBUGF("find_free_cluster(%x) == %x\n",startcluster,c); fat_bpb.fsinfo.nextfree = c; return c; } } + LDEBUGF("find_free_cluster(%x) == 0\n",startcluster); return 0; /* 0 is an illegal cluster number */ } -static int update_fat_entry(int entry, unsigned int val) +static int update_fat_entry(unsigned int entry, unsigned int val) { int sector = entry / CLUSTERS_PER_FAT_SECTOR; int offset = entry % CLUSTERS_PER_FAT_SECTOR; @@ -456,6 +454,12 @@ static int update_fat_entry(int entry, unsigned int val) LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); + if (entry==val) + panicf("Creating FAT loop: %x,%x\n",entry,val); + + if ( entry < 2 ) + panicf("Updating reserved FAT entry %d.\n",entry); + sec = cache_fat_sector(sector); if (!sec) { @@ -465,14 +469,14 @@ static int update_fat_entry(int entry, unsigned int val) fat_cache[sector & FAT_CACHE_MASK].dirty = true; if ( val ) { - if (!(sec[offset] & 0x0fffffff)) + if (!(SWAB32(sec[offset]) & 0x0fffffff)) fat_bpb.fsinfo.freecount--; } else fat_bpb.fsinfo.freecount++; /* don't change top 4 bits */ - sec[offset] &= SWAB32(0xf000000); + sec[offset] &= SWAB32(0xf0000000); sec[offset] |= SWAB32(val & 0x0fffffff); return 0; @@ -491,7 +495,7 @@ static int read_fat_entry(int entry) return -1; } - return SWAB32(sec[offset]); + return SWAB32(sec[offset]) & 0x0fffffff; } static int get_next_cluster(unsigned int cluster) @@ -499,6 +503,7 @@ static int get_next_cluster(unsigned int cluster) int next_cluster; next_cluster = read_fat_entry(cluster); + LDEBUGF("get_next_cluster(%x) == %x\n",cluster,next_cluster); /* is this last cluster in chain? */ if ( next_cluster >= 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<sectorcount && sector>=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<sizeof(text)/4; i++ ) + sprintf(text+i*4,"%03x,",i); + + for (i=0;i<num;i++) + if (write(fd, text, sizeof(text)) < 0) DEBUGF("Failed writing data\n"); close(fd); @@ -137,27 +141,7 @@ void dbg_tail(char* name) return; DEBUGF("Got file descriptor %d\n",fd); - rc = lseek(fd,512,SEEK_SET); - if ( rc >= 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; } |