aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-01-25 09:56:32 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-01-25 09:56:32 -0800
commit340e78363a8a0754588bc555456771e4d681f3a3 (patch)
tree833f9c86919f35a7322dcc1e911d4138ea198f67
parent5964900d2335a6d84a63e89fb0e7e302aeae4da3 (diff)
downloadsyslinux.git-340e78363a8a0754588bc555456771e4d681f3a3.tar.gz
syslinux.git-340e78363a8a0754588bc555456771e4d681f3a3.tar.xz
syslinux.git-340e78363a8a0754588bc555456771e4d681f3a3.zip
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@zytor.com>
-rw-r--r--core/fs/fat/fat.c42
-rw-r--r--core/fs/fat/fat_fs.h4
2 files changed, 23 insertions, 23 deletions
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index 21dda90f..2ffc303a 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 9453a67f..8d441e34 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 */