[syslinux:fsc] FAT: Compare cluster count to total number of clusters

syslinux-bot for H. Peter Anvin hpa at zytor.com
Mon Jan 25 10:00:15 PST 2010


Commit-ID:  340e78363a8a0754588bc555456771e4d681f3a3
Gitweb:     http://syslinux.zytor.com/commit/340e78363a8a0754588bc555456771e4d681f3a3
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Mon, 25 Jan 2010 09:56:32 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Mon, 25 Jan 2010 09:56:32 -0800

FAT: Compare cluster count to total number of clusters

We have to know the total number of clusters, so we might as well make
use of that knowledge.  Treat any impossible cluster number as EOF.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 core/fs/fat/fat.c    |   42 ++++++++++++++++++++----------------------
 core/fs/fat/fat_fs.h |    4 +++-
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index 21dda90..2ffc303 100644
--- a/core/fs/fat/fat.c
+++ b/core/fs/fat/fat.c
@@ -58,7 +58,7 @@ static uint32_t get_next_cluster(struct fs_info *fs, uint32_t clust_num)
 	fat_sector = offset >> SECTOR_SHIFT;
 	offset &= (1 << SECTOR_SHIFT) - 1;
 	cs = get_fat_sector(fs, fat_sector);
-	if (offset == SECTOR_SIZE-1) {
+	if (offset == (1 << SECTOR_SHIFT)-1) {
 	    /* 
 	     * we got the end of the one fat sector, 
 	     * but we have just one byte and we need two,
@@ -77,8 +77,6 @@ static uint32_t get_next_cluster(struct fs_info *fs, uint32_t clust_num)
 	    next_cluster >>= 4;         /* cluster number is ODD */
 	else
 	    next_cluster &= 0x0fff;     /* cluster number is EVEN */
-	if (next_cluster > 0x0ff6)
-	    goto fail;
 	break;
 	
     case FAT16:
@@ -86,8 +84,6 @@ static uint32_t get_next_cluster(struct fs_info *fs, uint32_t clust_num)
 	offset = clust_num & ((1 << (SECTOR_SHIFT-1)) -1);
 	cs = get_fat_sector(fs, fat_sector);
 	next_cluster = ((uint16_t *)cs->data)[offset];
-	if (next_cluster > 0xfff6)
-	    goto fail;
 	break;
 	
     case FAT32:
@@ -95,24 +91,20 @@ static uint32_t get_next_cluster(struct fs_info *fs, uint32_t clust_num)
 	offset = clust_num & ((1 << (SECTOR_SHIFT-2)) -1);
 	cs = get_fat_sector(fs, fat_sector);
 	next_cluster = ((uint32_t *)cs->data)[offset] & 0x0fffffff;
-	if (next_cluster > 0x0ffffff6)
-	    goto fail;
 	break;
     }
     
     return next_cluster;
-    
-fail:  
-    /* got an unexcepted cluster number, so return ZERO */
-    return 0;
 }
 
 
 static sector_t get_next_sector(struct fs_info* fs, uint32_t sector)
 {
-    sector_t data_area = FAT_SB(fs)->data;
+    struct fat_sb_info *sbi = FAT_SB(fs);
+    sector_t data_area = sbi->data;
     sector_t data_sector;
     uint32_t cluster;
+    int clust_shift = sbi->clust_shift;
     
     if (sector < data_area) {
 	sector++;
@@ -123,16 +115,18 @@ static sector_t get_next_sector(struct fs_info* fs, uint32_t sector)
     }
     
     data_sector = sector - data_area;
-    if ((data_sector + 1) & FAT_SB(fs)->clust_mask)  /* in a cluster */
-	return ++sector;
+    if ((data_sector + 1) & sbi->clust_mask)  /* in a cluster */
+	return sector++;
     
     /* get a new cluster */
-    cluster = get_next_cluster(fs, (data_sector >> FAT_SB(fs)->clust_shift) + 2);
-    if (cluster < 2) 
+    cluster = data_sector >> clust_shift;
+    cluster = get_next_cluster(fs, cluster + 2) - 2;
+
+    if (cluster >= sbi->clusters)
 	return 0;
     
     /* return the start of the new cluster */
-    sector = ((cluster - 2) << FAT_SB(fs)->clust_shift) + data_area;
+    sector = (cluster << sbi->clust_shift) + data_area;
     return sector;
 }
 
@@ -711,7 +705,7 @@ static int vfat_fs_init(struct fs_info *fs)
     struct fat_sb_info *sbi;
     struct disk *disk = fs->fs_dev->disk;
     int sectors_per_fat;
-    uint32_t clust_num;
+    uint32_t clusters;
     sector_t total_sectors;
     
     fs->sector_shift = fs->block_shift = disk->sector_shift;
@@ -736,13 +730,17 @@ static int vfat_fs_init(struct fs_info *fs)
     sbi->clust_mask       = fat.bxSecPerClust - 1;
     sbi->clust_size       = fat.bxSecPerClust << fs->sector_shift;
     
-    clust_num = (total_sectors - sbi->data) >> sbi->clust_shift;
-    if (clust_num < 4085)
+    clusters = (total_sectors - sbi->data) >> sbi->clust_shift;
+    if (clusters <= 0xff4) {
 	sbi->fat_type = FAT12;
-    else if (clust_num < 65525)
+    } else if (clusters <= 0xfff4) {
 	sbi->fat_type = FAT16;
-    else
+    } else {
 	sbi->fat_type = FAT32;
+	if (clusters > 0x0ffffff4)
+	    clusters = 0x0ffffff4; /* Maximum possible */
+    }
+    sbi->clusters = clusters;
     
     /* for SYSLINUX, the cache is based on sector size */
     return fs->sector_shift;
diff --git a/core/fs/fat/fat_fs.h b/core/fs/fat/fat_fs.h
index 9453a67..8d441e3 100644
--- a/core/fs/fat/fat_fs.h
+++ b/core/fs/fat/fat_fs.h
@@ -86,8 +86,10 @@ struct fat_bpb {
 struct fat_sb_info {
 	sector_t fat;             /* The FAT region */
 	sector_t root;            /* The root dir region */
-	int      root_size;       /* The root dir size in sectores */
 	sector_t data;            /* The data region */
+
+	uint32_t clusters;	  /* Total number of clusters */
+	int      root_size;       /* The root dir size in sectores */
 	
 	int      clust_shift;      /* based on sectors */
 	int      clust_byte_shift; /* based on bytes   */



More information about the Syslinux-commits mailing list