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:
parent
3bf2f78581
commit
a5e77d8f94
5 changed files with 212 additions and 111 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
else {
|
||||
if (sector)
|
||||
sector++;
|
||||
else {
|
||||
sector = cluster2sec(file->firstcluster);
|
||||
numsec=1;
|
||||
}
|
||||
}
|
||||
|
||||
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,7 +1092,7 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf )
|
|||
return -2;
|
||||
}
|
||||
((char*)buf) += count * SECTOR_SIZE;
|
||||
first = sector;
|
||||
first = 0;
|
||||
}
|
||||
last = 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;
|
||||
if ( numsec > fat_bpb.bpb_secperclus || !cluster ) {
|
||||
if (write)
|
||||
cluster = next_write_cluster(file, cluster, §or);
|
||||
else {
|
||||
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);
|
||||
sector = cluster2sec(cluster);
|
||||
}
|
||||
if (!cluster)
|
||||
sector = -1;
|
||||
numsec=1;
|
||||
}
|
||||
else {
|
||||
sector = -1;
|
||||
DEBUGF("fat_write(): Disk full!\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster) {
|
||||
sector = cluster2sec(cluster);
|
||||
LDEBUGF("cluster2sec(%x) == %x\n",cluster,sector);
|
||||
if (sector<0)
|
||||
return -1;
|
||||
numsec=0;
|
||||
|
||||
if (!oldcluster)
|
||||
first = last = sector;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (sector)
|
||||
sector++;
|
||||
else {
|
||||
sector = cluster2sec(file->firstcluster);
|
||||
numsec=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we start simple: one sector at a time */
|
||||
err = ata_write_sectors(sector, 1, buf);
|
||||
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_write() - Couldn't write sector %d"
|
||||
DEBUGF( "fat_readwrite() - Couldn't read sector %d"
|
||||
" (error code %d)\n", sector,err);
|
||||
return -2;
|
||||
}
|
||||
((char*)buf) += SECTOR_SIZE;
|
||||
((char*)buf) += count * SECTOR_SIZE;
|
||||
first = 0;
|
||||
}
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 =="
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue