summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-10-31 16:09:28 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-10-31 16:09:28 +0000
commita5e77d8f943e602c56036f0f21b60b7f442a3976 (patch)
tree324101cf4060f4f06bd522bd49d4f57469a6dad3
parent3bf2f7858188c222abde85643ce980963dc7e4c9 (diff)
downloadrockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.zip
rockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.tar.gz
rockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.tar.bz2
rockbox-a5e77d8f943e602c56036f0f21b60b7f442a3976.tar.xz
Fat writing update. File creation now works, though still only short filenames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@2790 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/fat.c217
-rw-r--r--firmware/drivers/fat.h19
-rw-r--r--firmware/test/fat/ata-sim.c19
-rw-r--r--firmware/test/fat/main.c21
-rw-r--r--firmware/test/fat/test.sh39
5 files changed, 208 insertions, 107 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index 40f9c47..4c3e410 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -455,11 +455,13 @@ static int update_fat_entry(unsigned int entry, unsigned int val)
LDEBUGF("update_fat_entry(%x,%x)\n",entry,val);
+#ifdef TEST_FAT
if (entry==val)
panicf("Creating FAT loop: %x,%x\n",entry,val);
if ( entry < 2 )
panicf("Updating reserved FAT entry %d.\n",entry);
+#endif
sec = cache_fat_sector(sector);
if (!sec)
@@ -636,6 +638,12 @@ static int add_dir_entry(struct fat_dir* dir,
if (sec_cnt >= fat_bpb.bpb_secperclus)
{
int oldcluster;
+
+ /* we're not adding a whole new sector
+ just for the end-of-dir marker */
+ if ( need_to_update_last_empty_marker )
+ break;
+
if (!currdir)
currdir = sec2cluster(fat_bpb.rootdirsector);
oldcluster = currdir;
@@ -647,17 +655,35 @@ static int add_dir_entry(struct fat_dir* dir,
{
/* end of dir, add new cluster */
LDEBUGF("Adding cluster to dir\n");
- currdir = find_free_cluster(fat_bpb.fsinfo.nextfree);
+ currdir = find_free_cluster(oldcluster+1);
if (!currdir) {
DEBUGF("add_dir_entry(): Disk full!\n");
return -1;
}
update_fat_entry(oldcluster, currdir);
+ update_fat_entry(currdir, FAT_EOF_MARK);
new = true;
memset(buf, 0, sizeof buf);
+
+ /* clear remaining sectors in this cluster */
+ if (fat_bpb.bpb_secperclus > 1) {
+ int i;
+ sec = cluster2sec(currdir);
+ for (i=1; i<fat_bpb.bpb_secperclus; i++ ) {
+ err = ata_write_sectors(sec + fat_bpb.startsector + i,
+ 1, buf);
+ if (err) {
+ DEBUGF( "add_dir_entry() - "
+ " Couldn't write dir"
+ " sector (error code %d)\n", err);
+ return -3;
+ }
+ }
+ }
}
LDEBUGF("new cluster is %x\n", currdir);
sec = cluster2sec(currdir);
+ sec_cnt = 0;
}
if (!new) {
@@ -714,6 +740,7 @@ static int add_dir_entry(struct fat_dir* dir,
/* We must fill in the first entry
in the next sector */
need_to_update_last_empty_marker = true;
+ LDEBUGF("need_to_update_last_empty\n");
}
}
else
@@ -907,13 +934,13 @@ int fat_open(unsigned int startcluster,
{
file->firstcluster = startcluster;
file->lastcluster = startcluster;
- file->lastsector = cluster2sec(startcluster);
+ file->lastsector = 0;
file->sectornum = 0;
/* remember where the file's dir entry is located */
file->dirsector = dir->cached_sec;
file->direntry = (dir->entry % DIR_ENTRIES_PER_SECTOR) - 1;
- LDEBUGF("fat_open: entry %d\n",file->direntry);
+ LDEBUGF("fat_open(%x), entry %d\n",startcluster,file->direntry);
return 0;
}
@@ -952,7 +979,7 @@ int fat_closewrite(struct fat_file *file, int size)
int next, last = file->lastcluster;
int endcluster = last;
- LDEBUGF("fat_closewrite()\n");
+ LDEBUGF("fat_closewrite(%d)\n",size);
last = get_next_cluster(last);
while ( last && last != FAT_EOF_MARK ) {
@@ -961,10 +988,32 @@ int fat_closewrite(struct fat_file *file, int size)
last = next;
}
- update_fat_entry(endcluster, FAT_EOF_MARK);
+ if ( !size ) {
+ /* empty file */
+ update_fat_entry(file->firstcluster, 0);
+ file->firstcluster = 0;
+ }
+ else
+ update_fat_entry(endcluster, FAT_EOF_MARK);
update_dir_entry(file, size);
flush_fat();
+#ifdef TEST_FAT
+ {
+ /* debug */
+ int count = 0;
+ int len;
+ for ( next = file->firstcluster; next;
+ next = get_next_cluster(next) )
+ LDEBUGF("cluster %d: %x\n", count++, next);
+ len = count * fat_bpb.bpb_secperclus * SECTOR_SIZE;
+ LDEBUGF("File is %d clusters (chainlen=%d, size=%d)\n",
+ count, len, size );
+ if ( len > size + fat_bpb.bpb_secperclus * SECTOR_SIZE)
+ panicf("Cluster chain is too long\n");
+ }
+#endif
+
return 0;
}
@@ -999,33 +1048,41 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
if ( sector == -1 )
return 0;
- first = 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 ) {
+ if ( numsec > fat_bpb.bpb_secperclus ) {
cluster = get_next_cluster(cluster);
if (!cluster) {
/* reading past end-of-file */
sector = -1;
}
-
+
if (cluster) {
sector = cluster2sec(cluster);
LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
if (sector<0)
return -1;
- numsec=0;
+ numsec=1;
}
}
- else
- sector++;
-
- if ( (sector != last+1) || /* not sequential any more? */
+ else {
+ if (sector)
+ sector++;
+ else {
+ sector = cluster2sec(file->firstcluster);
+ numsec=1;
+ }
+ }
+
+ if (!first)
+ first = sector;
+
+ if ( ((sector != first) && (sector != last+1)) ||
+ /* not sequential any more? */
(i == sectorcount-1) || /* last sector requested? */
- (last-first+1 == 256) ) { /* max 256 sectors per ata request */
- int count = last - first + 1;
+ (sector-first+1 == 256) ) { /* max 256 sectors per ata request */
+ int count = sector - first + 1;
int start = first + fat_bpb.startsector;
LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i);
err = ata_read_sectors(start, count, buf);
@@ -1035,10 +1092,10 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
return -2;
}
((char*)buf) += count * SECTOR_SIZE;
- first = sector;
+ first = 0;
}
last = sector;
- }
+ }
file->lastcluster = cluster;
file->lastsector = sector;
@@ -1047,7 +1104,41 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
return sectorcount;
}
-int fat_write( struct fat_file *file, int sectorcount, void* buf )
+int next_write_cluster(struct fat_file* file, int oldcluster, int* newsector)
+{
+ int cluster;
+ int sector;
+
+ LDEBUGF("next_write_cluster(%x,%x)\n",file->firstcluster, oldcluster);
+
+ cluster = get_next_cluster(oldcluster);
+ if (!cluster) {
+ if (oldcluster)
+ cluster = find_free_cluster(oldcluster+1);
+ else
+ cluster = find_free_cluster(fat_bpb.fsinfo.nextfree);
+
+ if (cluster) {
+ if (oldcluster)
+ update_fat_entry(oldcluster, cluster);
+ else
+ file->firstcluster = cluster;
+ }
+ else {
+ DEBUGF("next_write_sector(): Disk full!\n");
+ return 0;
+ }
+ }
+ sector = cluster2sec(cluster);
+ if (sector<0)
+ return 0;
+
+ *newsector = sector;
+ return cluster;
+}
+
+int fat_readwrite( struct fat_file *file, int sectorcount,
+ void* buf, bool write )
{
int cluster = file->lastcluster;
int sector = file->lastsector;
@@ -1062,53 +1153,50 @@ int fat_write( struct fat_file *file, int sectorcount, void* buf )
return 0;
/* find sequential sectors and write them all at once */
- for (i=0; i<sectorcount && sector>=0; i++ ) {
+ for (i=0; i<sectorcount; i++ ) {
numsec++;
-
- /* find a new cluster */
- if ( numsec >= fat_bpb.bpb_secperclus || !cluster) {
- int oldcluster = cluster;
- cluster = get_next_cluster(cluster);
- if (!cluster) {
- if (!oldcluster)
- cluster = find_free_cluster(fat_bpb.fsinfo.nextfree);
- else
- cluster = find_free_cluster(oldcluster+1);
-
- if (cluster) {
- if ( !oldcluster )
- file->firstcluster = cluster;
- else
- update_fat_entry(oldcluster, cluster);
- }
- else {
- sector = -1;
- DEBUGF("fat_write(): Disk full!\n");
- }
+ if ( numsec > fat_bpb.bpb_secperclus || !cluster ) {
+ if (write)
+ cluster = next_write_cluster(file, cluster, &sector);
+ else {
+ cluster = get_next_cluster(cluster);
+ sector = cluster2sec(cluster);
+ }
+ if (!cluster)
+ sector = -1;
+ numsec=1;
+ }
+ else {
+ if (sector)
+ sector++;
+ else {
+ sector = cluster2sec(file->firstcluster);
+ numsec=1;
}
+ }
- if (cluster) {
- sector = cluster2sec(cluster);
- LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
- if (sector<0)
- return -1;
- numsec=0;
+ if (!first)
+ first = sector;
- if (!oldcluster)
- first = last = sector;
+ if ( ((sector != first) && (sector != last+1)) || /* not sequential */
+ (i == sectorcount-1) || /* last sector requested */
+ (sector-first+1 == 256) ) { /* max 256 sectors per ata request */
+ int count = sector - first + 1;
+ int start = first + fat_bpb.startsector;
+ LDEBUGF("s=%x, l=%x, f=%x, i=%d\n",sector,last,first,i);
+ if (write)
+ err = ata_write_sectors(start, count, buf);
+ else
+ err = ata_read_sectors(start, count, buf);
+ if (err) {
+ DEBUGF( "fat_readwrite() - Couldn't read sector %d"
+ " (error code %d)\n", sector,err);
+ return -2;
}
+ ((char*)buf) += count * SECTOR_SIZE;
+ first = 0;
}
- else
- sector++;
-
- /* we start simple: one sector at a time */
- err = ata_write_sectors(sector, 1, buf);
- if (err) {
- DEBUGF( "fat_write() - Couldn't write sector %d"
- " (error code %d)\n", sector,err);
- return -2;
- }
- ((char*)buf) += SECTOR_SIZE;
+ last = sector;
}
file->lastcluster = cluster;
@@ -1118,15 +1206,6 @@ int fat_write( struct fat_file *file, int sectorcount, void* buf )
return sectorcount;
}
-int fat_readwrite( struct fat_file *file, int sectorcount,
- void* buf, bool write )
-{
- if (write)
- return fat_write(file, sectorcount, buf);
- else
- return fat_read(file, sectorcount, buf);
-}
-
int fat_seek(struct fat_file *file, int seeksector )
{
int cluster = file->firstcluster;
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h
index 1316202..6ed68ad 100644
--- a/firmware/drivers/fat.h
+++ b/firmware/drivers/fat.h
@@ -46,15 +46,6 @@ struct fat_direntry
#define FAT_ATTR_DIRECTORY 0x10
#define FAT_ATTR_ARCHIVE 0x20
-struct fat_dir
-{
- int entry;
- int cached_sec;
- int num_sec;
- unsigned char cached_buf[SECTOR_SIZE];
- int startcluster;
-};
-
struct fat_file
{
int firstcluster; /* first cluster in file */
@@ -65,6 +56,16 @@ struct fat_file
int direntry; /* dir entry index in sector */
};
+struct fat_dir
+{
+ int entry;
+ int cached_sec;
+ int num_sec;
+ unsigned char cached_buf[SECTOR_SIZE];
+ int startcluster;
+};
+
+
extern int fat_mount(int startsector);
extern int fat_create_dir(unsigned int currdir, char *name);
diff --git a/firmware/test/fat/ata-sim.c b/firmware/test/fat/ata-sim.c
index a64e0a4..661cc79 100644
--- a/firmware/test/fat/ata-sim.c
+++ b/firmware/test/fat/ata-sim.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include "debug.h"
+#include "panic.h"
#define BLOCK_SIZE 512
@@ -9,7 +10,10 @@ static FILE* file;
int ata_read_sectors(unsigned long start, unsigned char count, void* buf)
{
- DEBUGF("[Reading block 0x%lx]\n",start);
+ int i;
+ for (i=0; i<count; i++ )
+ DEBUGF("[Reading block 0x%lx]\n",start+i);
+
if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) {
perror("fseek");
return -1;
@@ -17,6 +21,7 @@ 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");
+ panicf("Disk error\n");
return -2;
}
return 0;
@@ -24,20 +29,22 @@ int ata_read_sectors(unsigned long start, unsigned char count, void* buf)
int ata_write_sectors(unsigned long start, unsigned char count, void* buf)
{
- DEBUGF("[Writing block 0x%lx]\n",start);
+ int i;
+ for (i=0; i<count; i++ )
+ DEBUGF("[Writing block 0x%lx]\n",start+i);
- if (start == 0) {
- DEBUGF("Holy crap! You're writing on sector 0!\n");
- exit(0);
- }
+ if (start == 0)
+ panicf("Writing on sector 0!\n");
if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) {
perror("fseek");
return -1;
+ panicf("Disk error\n");
}
if(!fwrite(buf,BLOCK_SIZE,count,file)) {
perror("fwrite");
return -2;
+ panicf("Disk error\n");
}
return 0;
}
diff --git a/firmware/test/fat/main.c b/firmware/test/fat/main.c
index 708ee45..0259be4 100644
--- a/firmware/test/fat/main.c
+++ b/firmware/test/fat/main.c
@@ -12,7 +12,7 @@ extern int ata_init(char*);
extern void ata_read_sectors(int, int, char*);
void dbg_dump_sector(int sec);
-void dbg_dump_buffer(unsigned char *buf, int len);
+void dbg_dump_buffer(unsigned char *buf, int len, int offset);
void dbg_console(void);
void panicf( char *fmt, ...)
@@ -31,10 +31,10 @@ void dbg_dump_sector(int sec)
ata_read_sectors(sec,1,buf);
DEBUGF("---< Sector %d >-----------------------------------------\n", sec);
- dbg_dump_buffer(buf, 512);
+ dbg_dump_buffer(buf, 512, 0);
}
-void dbg_dump_buffer(unsigned char *buf, int len)
+void dbg_dump_buffer(unsigned char *buf, int len, int offset)
{
int i, j;
unsigned char c;
@@ -42,7 +42,7 @@ void dbg_dump_buffer(unsigned char *buf, int len)
for(i = 0;i < len/16;i++)
{
- DEBUGF("%03x: ", i*16);
+ DEBUGF("%03x: ", i*16 + offset);
for(j = 0;j < 16;j++)
{
c = buf[i*16+j];
@@ -102,7 +102,7 @@ int dbg_mkfile(char* name, int num)
int len = num > sizeof text ? sizeof text : num;
for (i=0; i<len/CHUNKSIZE; i++ )
- sprintf(text+i*CHUNKSIZE,"%07x,",x++);
+ sprintf(text+i*CHUNKSIZE,"%c%06x,",name[1],x++);
if (write(fd, text, len) < 0) {
DEBUGF("Failed writing data\n");
@@ -139,12 +139,15 @@ int dbg_chkfile(char* name)
if (!rc)
break;
for (i=0; i<rc/CHUNKSIZE; i++ ) {
- sprintf(tmp,"%07x,",x++);
+ sprintf(tmp,"%c%06x,",name[1],x++);
if (strncmp(text+i*CHUNKSIZE,tmp,CHUNKSIZE)) {
- DEBUGF("Mismatch in byte %d (%.4s != %.4s)\n",
- block*sizeof(text)+i*CHUNKSIZE, tmp,
+ DEBUGF("Mismatch in byte %x (sector %d). Expected %.8s found %.8s\n",
+ block*sizeof(text)+i*CHUNKSIZE,
+ (block*sizeof(text)+i*CHUNKSIZE) / SECTOR_SIZE,
+ tmp,
text+i*CHUNKSIZE);
- dbg_dump_buffer(text+i*CHUNKSIZE - 0x20, 0x40);
+ dbg_dump_buffer(text+i*CHUNKSIZE - 0x20, 0x40,
+ block*sizeof(text)+i*CHUNKSIZE - 0x20);
return -1;
}
}
diff --git a/firmware/test/fat/test.sh b/firmware/test/fat/test.sh
index 0b00d76..476b0e4 100644
--- a/firmware/test/fat/test.sh
+++ b/firmware/test/fat/test.sh
@@ -2,32 +2,34 @@
IMAGE=disk.img
MOUNT=/mnt/dummy
+RESULT=result.txt
fail() {
- echo "!! Test failed. Look in result.txt for test log."
+ echo "!! Test failed. Look in $RESULT for test logs."
exit
}
check() {
- /sbin/dosfsck -r $IMAGE | tee -a result.txt
+ /sbin/dosfsck -r $IMAGE | tee -a $RESULT
[ $RETVAL -ne 0 ] && fail
}
try() {
- ./fat $1 $2 $3 2> result.txt
+ ./fat $1 $2 $3 2>> $RESULT
RETVAL=$?
[ $RETVAL -ne 0 ] && fail
}
buildimage() {
- umount $MOUNT
- /sbin/mkdosfs -F 32 -s $1 disk.img >/dev/null
+ /sbin/mkdosfs -F 32 -s $1 $IMAGE > /dev/null
mount -o loop $IMAGE $MOUNT
echo "Filling it with /etc files"
find /etc -type f -maxdepth 1 -exec cp {} $MOUNT \;
+ umount $MOUNT
}
runtests() {
+ rm $RESULT
echo ---Test: create a 10K file
try mkfile /apa.txt 10
@@ -53,29 +55,38 @@ runtests() {
try mkfile /cpa.txt 0
check
try chkfile /cpa.txt
+ try chkfile /apa.txt
+ try chkfile /bpa.txt
- echo ---Test: create 20 1k files
+ echo ---Test: create 10 1k files
for i in `seq 1 10`;
do
- echo -n $i
+ echo ---Test: $i/10 ---
try mkfile /rockbox.$i
check
+ try chkfile /bpa.txt
done
}
-echo "Building test image A (2 sectors/cluster)"
-buildimage 2
+echo "Building test image (1 sector/cluster)"
+buildimage 1
runtests
-echo "Building test image B (8 sectors/cluster)"
+echo "Building test image (4 sector/cluster)"
+buildimage 4
+runtests
+
+echo "Building test image (8 sectors/cluster)"
buildimage 8
runtests
-echo "Building test image B (1 sector/cluster)"
-buildimage 1
+echo "Building test image (32 sectors/cluster)"
+buildimage 32
runtests
-umount $MOUNT
+echo "Building test image (128 sectors/cluster)"
+buildimage 128
+runtests
-echo "-- Test complete --"
+echo "== Test completed sucessfully =="