From 16d9259cc980c7f3a3778431349dcbbf97a7ec82 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 13 Nov 2010 18:57:35 +0000 Subject: [PATCH] Fix reading FAT32 root dirs that span >1 cluster Unlike FAT12/16, FAT32 does not guarantee that root directories will occupy consecutive clusters. To get each cluster after the first you must access the FAT as with any other directory. This patch implements this and bumps up the largest valid cluster number to support large e.g. 64MB partitions. --- fs/fat/fat.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/fs/fat/fat.c b/fs/fat/fat.c index c6bdb13..44ecb4a 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -384,7 +384,7 @@ get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, newclust = get_fatent(mydata, endclust); if((newclust -1)!=endclust) goto getit; - if (newclust <= 0x0001 || newclust >= 0xfff0) { + if (newclust <= 0x0001 || newclust >= 0xfffff0) { FAT_DPRINT("curclust: 0x%x\n", newclust); FAT_DPRINT("Invalid FAT entry\n"); return gotsize; @@ -419,7 +419,7 @@ getit: filesize -= actsize; buffer += actsize; curclust = get_fatent(mydata, endclust); - if (curclust <= 0x0001 || curclust >= 0xfff0) { + if (curclust <= 0x0001 || curclust >= 0xfffff0) { FAT_DPRINT("curclust: 0x%x\n", curclust); FAT_ERROR("Invalid FAT entry\n"); return gotsize; @@ -580,7 +580,7 @@ static dir_entry *get_dentfromdir (fsdata * mydata, int startsect, return retdent; } curclust = get_fatent (mydata, curclust); - if (curclust <= 0x0001 || curclust >= 0xfff0) { + if (curclust <= 0x0001 || curclust >= 0xfffff0) { FAT_DPRINT ("curclust: 0x%x\n", curclust); FAT_ERROR ("Invalid FAT entry\n"); return NULL; @@ -679,7 +679,7 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, dir_entry *dentptr; __u16 prevcksum = 0xffff; char *subname = ""; - int rootdir_size, cursect; + int rootdir_size, cursect, curclus; int idx, isdir = 0; int files = 0, dirs = 0; long ret = 0; @@ -697,6 +697,7 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, mydata->fat_sect = bs.reserved; cursect = mydata->rootdir_sect = mydata->fat_sect + mydata->fatlength * bs.fats; + curclus = bs.root_cluster; // For FAT32 only mydata->clust_size = bs.cluster_size; if (mydata->fatsize == 32) { rootdir_size = mydata->clust_size; @@ -818,7 +819,16 @@ do_fat_read(const char *filename, void *buffer, unsigned long maxsize, goto rootdir_done; /* We got a match */ } - cursect++; + + if (mydata->fatsize != 32) + cursect++; + else { + // FAT32 does not guarantee contiguous root directory + curclus = get_fatent (mydata, curclus); + cursect = (curclus * mydata->clust_size) + mydata->data_begin; + + FAT_DPRINT ("root clus %d sector %d\n", curclus, cursect); + } } rootdir_done: -- 2.47.2