FAT32: fix broken root directory handling.
On FAT32, instead of fetching the cluster numbers from the FAT, the code assumed (incorrectly) that the clusters for the root directory were allocated contiguously. In the result, only the first cluster could be accessed. At the typical cluster size of 8 sectors this caused all accesses to files after the first 128 entries to fail - "fatls" would terminate after 128 files (usually displaying a bogus file name, occasionally even crashing the system), and "fatload" would fail to find any files that were not in the first directory cluster. Signed-off-by: Wolfgang Denk <wd@denx.de>
This commit is contained in:
parent
66c2d73cfc
commit
2aa98c6612
60
fs/fat/fat.c
60
fs/fat/fat.c
@ -201,6 +201,9 @@ get_fatent(fsdata *mydata, __u32 entry)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FAT_DPRINT("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
|
||||||
|
mydata->fatsize, entry, entry, offset, offset);
|
||||||
|
|
||||||
/* Read a new block of FAT entries into the cache. */
|
/* Read a new block of FAT entries into the cache. */
|
||||||
if (bufnum != mydata->fatbufnum) {
|
if (bufnum != mydata->fatbufnum) {
|
||||||
int getsize = FATBUFSIZE/FS_BLOCK_SIZE;
|
int getsize = FATBUFSIZE/FS_BLOCK_SIZE;
|
||||||
@ -260,7 +263,8 @@ get_fatent(fsdata *mydata, __u32 entry)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FAT_DPRINT("ret: %d, offset: %d\n", ret, offset);
|
FAT_DPRINT("FAT%d: ret: %08x, offset: %04x\n",
|
||||||
|
mydata->fatsize, ret, offset);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -323,7 +327,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
|
|||||||
|
|
||||||
if (maxsize > 0 && filesize > maxsize) filesize = maxsize;
|
if (maxsize > 0 && filesize > maxsize) filesize = maxsize;
|
||||||
|
|
||||||
FAT_DPRINT("Reading: %ld bytes\n", filesize);
|
FAT_DPRINT("%ld bytes\n", filesize);
|
||||||
|
|
||||||
actsize=bytesperclust;
|
actsize=bytesperclust;
|
||||||
endclust=curclust;
|
endclust=curclust;
|
||||||
@ -719,16 +723,19 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
|
|||||||
dir_entry *dentptr;
|
dir_entry *dentptr;
|
||||||
__u16 prevcksum = 0xffff;
|
__u16 prevcksum = 0xffff;
|
||||||
char *subname = "";
|
char *subname = "";
|
||||||
int rootdir_size, cursect;
|
int cursect;
|
||||||
int idx, isdir = 0;
|
int idx, isdir = 0;
|
||||||
int files = 0, dirs = 0;
|
int files = 0, dirs = 0;
|
||||||
long ret = 0;
|
long ret = 0;
|
||||||
int firsttime;
|
int firsttime;
|
||||||
|
int root_cluster;
|
||||||
|
int j;
|
||||||
|
|
||||||
if (read_bootsectandvi (&bs, &volinfo, &mydata->fatsize)) {
|
if (read_bootsectandvi (&bs, &volinfo, &mydata->fatsize)) {
|
||||||
FAT_DPRINT ("Error: reading boot sector\n");
|
FAT_DPRINT ("Error: reading boot sector\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
root_cluster = bs.root_cluster;
|
||||||
if (mydata->fatsize == 32) {
|
if (mydata->fatsize == 32) {
|
||||||
mydata->fatlength = bs.fat32_length;
|
mydata->fatlength = bs.fat32_length;
|
||||||
} else {
|
} else {
|
||||||
@ -739,10 +746,11 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
|
|||||||
= mydata->fat_sect + mydata->fatlength * bs.fats;
|
= mydata->fat_sect + mydata->fatlength * bs.fats;
|
||||||
mydata->clust_size = bs.cluster_size;
|
mydata->clust_size = bs.cluster_size;
|
||||||
if (mydata->fatsize == 32) {
|
if (mydata->fatsize == 32) {
|
||||||
rootdir_size = mydata->clust_size;
|
mydata->data_begin = mydata->rootdir_sect
|
||||||
mydata->data_begin = mydata->rootdir_sect /* + rootdir_size */
|
|
||||||
- (mydata->clust_size * 2);
|
- (mydata->clust_size * 2);
|
||||||
} else {
|
} else {
|
||||||
|
int rootdir_size;
|
||||||
|
|
||||||
rootdir_size = ((bs.dir_entries[1] * (int) 256 + bs.dir_entries[0])
|
rootdir_size = ((bs.dir_entries[1] * (int) 256 + bs.dir_entries[0])
|
||||||
* sizeof (dir_entry)) / SECTOR_SIZE;
|
* sizeof (dir_entry)) / SECTOR_SIZE;
|
||||||
mydata->data_begin = mydata->rootdir_sect + rootdir_size
|
mydata->data_begin = mydata->rootdir_sect + rootdir_size
|
||||||
@ -750,12 +758,19 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
|
|||||||
}
|
}
|
||||||
mydata->fatbufnum = -1;
|
mydata->fatbufnum = -1;
|
||||||
|
|
||||||
FAT_DPRINT ("FAT%d, fatlength: %d\n", mydata->fatsize,
|
#ifdef CONFIG_SUPPORT_VFAT
|
||||||
|
FAT_DPRINT ("VFAT Support enabled\n");
|
||||||
|
#endif
|
||||||
|
FAT_DPRINT ("FAT%d, fat_sect: %d, fatlength: %d\n",
|
||||||
|
mydata->fatsize,
|
||||||
|
mydata->fat_sect,
|
||||||
mydata->fatlength);
|
mydata->fatlength);
|
||||||
FAT_DPRINT ("Rootdir begins at sector: %d, offset: %x, size: %d\n"
|
FAT_DPRINT ("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
|
||||||
"Data begins at: %d\n",
|
"Data begins at: %d\n",
|
||||||
mydata->rootdir_sect, mydata->rootdir_sect * SECTOR_SIZE,
|
root_cluster,
|
||||||
rootdir_size, mydata->data_begin);
|
mydata->rootdir_sect,
|
||||||
|
mydata->rootdir_sect * SECTOR_SIZE,
|
||||||
|
mydata->data_begin);
|
||||||
FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);
|
FAT_DPRINT ("Cluster size: %d\n", mydata->clust_size);
|
||||||
|
|
||||||
/* "cwd" is always the root... */
|
/* "cwd" is always the root... */
|
||||||
@ -779,9 +794,12 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
|
|||||||
isdir = 1;
|
isdir = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j=0;
|
||||||
while (1) {
|
while (1) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
FAT_DPRINT ("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%d\n",
|
||||||
|
cursect, mydata->clust_size, DIRENTSPERBLOCK);
|
||||||
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) {
|
if (disk_read (cursect, mydata->clust_size, do_fat_read_block) < 0) {
|
||||||
FAT_DPRINT ("Error: reading rootdir block\n");
|
FAT_DPRINT ("Error: reading rootdir block\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -894,7 +912,29 @@ do_fat_read (const char *filename, void *buffer, unsigned long maxsize,
|
|||||||
|
|
||||||
goto rootdir_done; /* We got a match */
|
goto rootdir_done; /* We got a match */
|
||||||
}
|
}
|
||||||
cursect++;
|
FAT_DPRINT ("END LOOP: j=%d clust_size=%d\n", j, mydata->clust_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On FAT32 we must fetch the FAT entries for the next
|
||||||
|
* root directory clusters when a cluster has been
|
||||||
|
* completely processed.
|
||||||
|
*/
|
||||||
|
if ((mydata->fatsize == 32) && (++j == mydata->clust_size)) {
|
||||||
|
int nxtsect;
|
||||||
|
int cur_clust, nxt_clust;
|
||||||
|
|
||||||
|
cur_clust = (cursect - mydata->data_begin) / mydata->clust_size;
|
||||||
|
nxt_clust = get_fatent(mydata, root_cluster);
|
||||||
|
nxtsect = mydata->data_begin + (nxt_clust * mydata->clust_size);
|
||||||
|
FAT_DPRINT ("END LOOP: sect=%d, clust=%d, root_clust=%d, n_sect=%d, n_clust=%d\n",
|
||||||
|
cursect, cur_clust, root_cluster, nxtsect, nxt_clust);
|
||||||
|
root_cluster = nxt_clust;
|
||||||
|
|
||||||
|
cursect = nxtsect;
|
||||||
|
j = 0;
|
||||||
|
} else {
|
||||||
|
cursect++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rootdir_done:
|
rootdir_done:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user