1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Björn Stenberg 2002-10-31 16:09:28 +00:00
parent 3bf2f78581
commit a5e77d8f94
5 changed files with 212 additions and 111 deletions

View file

@ -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,12 +1048,10 @@ 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 */
@ -1016,16 +1063,26 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
if (sector<0)
return -1;
numsec=0;
numsec=1;
}
}
else {
if (sector)
sector++;
else {
sector = cluster2sec(file->firstcluster);
numsec=1;
}
}
else
sector++;
if ( (sector != last+1) || /* not sequential any more? */
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 (cluster) {
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);
LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
if (sector<0)
return -1;
numsec=0;
if (!oldcluster)
first = last = sector;
}
if (!cluster)
sector = -1;
numsec=1;
}
else {
if (sector)
sector++;
else {
sector = cluster2sec(file->firstcluster);
numsec=1;
}
}
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;
if (!first)
first = 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;
}
((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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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
runtests
echo "Building test image B (8 sectors/cluster)"
buildimage 8
runtests
echo "Building test image B (1 sector/cluster)"
echo "Building test image (1 sector/cluster)"
buildimage 1
runtests
umount $MOUNT
echo "Building test image (4 sector/cluster)"
buildimage 4
runtests
echo "-- Test complete --"
echo "Building test image (8 sectors/cluster)"
buildimage 8
runtests
echo "Building test image (32 sectors/cluster)"
buildimage 32
runtests
echo "Building test image (128 sectors/cluster)"
buildimage 128
runtests
echo "== Test completed sucessfully =="