diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-28 12:17:20 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-28 12:17:20 +0000 |
commit | 781b672b372ade5c1903adbdc4de8dcb16a29a37 (patch) | |
tree | 5c8a1ee82fbd33e2eb99ca431f2c6a0d1bf3efde | |
parent | 70a2c8d5316a74d0d716495170a075df486b2cd9 (diff) |
mkfs.vfat: fix a problem with over-estimating FAT size
-rw-r--r-- | util-linux/mkfs_vfat.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/util-linux/mkfs_vfat.c b/util-linux/mkfs_vfat.c index 30996b267..705c75c20 100644 --- a/util-linux/mkfs_vfat.c +++ b/util-linux/mkfs_vfat.c @@ -327,6 +327,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) volume_size_bytes >= ((off_t)8)*1024*1024*1024 ? 16 : volume_size_bytes >= 260*1024*1024 ? 8 : 1; } else { + // floppy, loop, or regular file int not_floppy = ioctl(dev, FDGETPRM, ¶m); if (not_floppy == 0) { // floppy disk @@ -367,12 +368,14 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) // Calculate number of clusters, sectors/cluster, sectors/FAT // (an initial guess for sect_per_clust should already be set) // - if ((off_t)(volume_size_sect - reserved_sect) < 16) // arbitrary limit + // "mkdosfs -v -F 32 image5k 5" is the minimum: + // 2 sectors for FATs and 2 data sectors + if ((off_t)(volume_size_sect - reserved_sect) < 4) bb_error_msg_and_die("the image is too small for FAT32"); sect_per_fat = 1; while (1) { while (1) { - unsigned spf; + int spf_adj; off_t tcl = (volume_size_sect - reserved_sect - NUM_FATS * sect_per_fat) / sect_per_clust; // tcl may be > MAX_CLUST_32 here, but it may be // because sect_per_fat is underestimated, @@ -382,8 +385,13 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) if (tcl > 0x7fffffff) goto next; total_clust = tcl; // fits in uint32_t - spf = ((total_clust + 2) * 4 + bytes_per_sect - 1) / bytes_per_sect; - if (spf <= sect_per_fat) { + spf_adj = ((total_clust + 2) * 4 + bytes_per_sect - 1) / bytes_per_sect - sect_per_fat; +#if 0 + bb_error_msg("sect_per_clust:%u sect_per_fat:%u total_clust:%u", + sect_per_clust, sect_per_fat, (int)tcl); + bb_error_msg("adjust to sect_per_fat:%d", spf_adj); +#endif + if (spf_adj <= 0) { // do not need to adjust sect_per_fat. // so, was total_clust too big after all? if (total_clust <= MAX_CLUST_32) @@ -392,7 +400,8 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) goto next; } // adjust sect_per_fat, go back and recalc total_clust - sect_per_fat = spf; + // (note: just "sect_per_fat += spf_adj" isn't ok) + sect_per_fat += ((unsigned)spf_adj / 2) | 1; } next: if (sect_per_clust == 128) @@ -409,7 +418,7 @@ int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv) fprintf(stderr, "Device '%s':\n" "heads:%u, sectors/track:%u, bytes/sector:%u\n" - "media descriptor:0x%02x\n" + "media descriptor:%02x\n" "total sectors:%"OFF_FMT"u, clusters:%u, sectors/cluster:%u\n" "FATs:2, sectors/FAT:%u\n" "volumeID:%08x, label:'%s'\n", |