From 340e78363a8a0754588bc555456771e4d681f3a3 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 25 Jan 2010 09:56:32 -0800 Subject: [PATCH] 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 --- 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 */ -- 2.7.4