Date: Sun, 8 Jul 2007 08:29:30 GMT From: Brian Chu <chub@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123099 for review Message-ID: <200707080829.l688TUHi051794@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123099 Change 123099 by chub@chub-msdosfs on 2007/07/08 08:28:50 fsck_msdosfs's loading of the bootsector now uses the unified headers in fs/sys/msdosfs instead of hard coding offsets to variables. Affected files ... .. //depot/projects/soc2007/chub-msdosfs2/sbin/fsck_msdosfs/boot.c#2 edit Differences ... ==== //depot/projects/soc2007/chub-msdosfs2/sbin/fsck_msdosfs/boot.c#2 (text+ko) ==== @@ -30,8 +30,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/cdefs.h> -#include <sys/cdefs.h> #ifndef lint __RCSID("$NetBSD: boot.c,v 1.9 2003/07/24 19:25:46 ws Exp $"); static const char rcsid[] = @@ -44,131 +44,164 @@ #include <stdio.h> #include <unistd.h> +#include <fs/msdosfs/bootsect.h> +#include <fs/msdosfs/bpb.h> #include "ext.h" #include "fsutil.h" int -readboot(dosfs, boot) - int dosfs; - struct bootblock *boot; +readboot(int dosfs, struct bootblock *boot) { - u_char block[DOSBOOTBLOCKSIZE]; - u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; - u_char backup[DOSBOOTBLOCKSIZE]; + union bootsector buffer; + union bootsector backup; + struct byte_bpb50 *pfat50; + struct byte_bpb710 *pfat710; + struct byte_Extboot *pfatext; + struct fsinfo fsstruct; int ret = FSOK; - if (read(dosfs, block, sizeof block) < sizeof block) { + if (read(dosfs, &buffer, sizeof(union bootsector)) + < sizeof(union bootsector)) { perror("could not read boot block"); return FSFATAL; } - if (block[510] != 0x55 || block[511] != 0xaa) { - pfatal("Invalid signature in boot block: %02x%02x", block[511], block[510]); + if (buffer.bs50.bsBootSectSig0 != BOOTSIG0 || + buffer.bs50.bsBootSectSig1 != BOOTSIG1) { + pfatal("Invalid signature in boot block: %02x%02x", + buffer.bs50.bsBootSectSig1, + buffer.bs50.bsBootSectSig0); return FSFATAL; } + + /* set the bpb structs to the boot sector's bpb */ + pfat50 = (struct byte_bpb50 *)&buffer.bs50.bsBPB; + pfat710 = (struct byte_bpb710 *)&buffer.bs710.bsBPB; - memset(boot, 0, sizeof *boot); + memset(boot, 0, sizeof(struct bootblock)); boot->ValidFat = -1; - /* decode bios parameter block */ - boot->BytesPerSec = block[11] + (block[12] << 8); - boot->SecPerClust = block[13]; - boot->ResSectors = block[14] + (block[15] << 8); - boot->FATs = block[16]; - boot->RootDirEnts = block[17] + (block[18] << 8); - boot->Sectors = block[19] + (block[20] << 8); - boot->Media = block[21]; - boot->FATsmall = block[22] + (block[23] << 8); - boot->SecPerTrack = block[24] + (block[25] << 8); - boot->Heads = block[26] + (block[27] << 8); - boot->HiddenSecs = block[28] + (block[29] << 8) + (block[30] << 16) + (block[31] << 24); - boot->HugeSectors = block[32] + (block[33] << 8) + (block[34] << 16) + (block[35] << 24); + /* decode bios parameter block and store in a compacted + * architecture independent data structure for future use + */ + boot->BytesPerSec = getushort(pfat50->bpbBytesPerSec); + boot->SecPerClust = pfat50->bpbSecPerClust; + boot->ResSectors = getushort(pfat50->bpbResSectors); + boot->FATs = pfat50->bpbFATs; + boot->RootDirEnts = getushort(pfat50->bpbRootDirEnts); + boot->Sectors = getushort(pfat50->bpbSectors); + boot->Media = pfat50->bpbMedia; + boot->SecPerTrack = getushort(pfat50->bpbSecPerTrack); + boot->Heads = getushort(pfat50->bpbHeads); + boot->HiddenSecs = getulong(pfat50->bpbHiddenSecs); + boot->HugeSectors = getulong(pfat50->bpbHugeSectors); - boot->FATsecs = boot->FATsmall; + /* first defaulting to FAT12/FAT16 for number of FAT sectors */ + boot->FATsecs = getushort(pfat50->bpbFATsecs); - if (!boot->RootDirEnts) + if (boot->RootDirEnts == 0) { + /* FAT32 parsing */ boot->flags |= FAT32; - if (boot->flags & FAT32) { - boot->FATsecs = block[36] + (block[37] << 8) - + (block[38] << 16) + (block[39] << 24); - if (block[40] & 0x80) - boot->ValidFat = block[40] & 0x0f; + boot->FATsecs = getulong(pfat710->bpbBigFATsecs); + if (pfat710->bpbExtFlags[0] & 0x80) { + boot->ValidFat = pfat710->bpbExtFlags[0] & 0x0f; + } /* check version number: */ - if (block[42] || block[43]) { - /* Correct? XXX */ + if (pfat710->bpbFSVers[0] != 0 || + pfat710->bpbFSVers[1] != 0) { pfatal("Unknown file system version: %x.%x", - block[43], block[42]); + pfat710->bpbFSVers[1], + pfat710->bpbFSVers[0]); return FSFATAL; } - boot->RootCl = block[44] + (block[45] << 8) - + (block[46] << 16) + (block[47] << 24); - boot->FSInfo = block[48] + (block[49] << 8); - boot->Backup = block[50] + (block[51] << 8); + + boot->RootCl = getulong(pfat710->bpbRootClust); + boot->FSInfo = getushort(pfat710->bpbFSInfo); + boot->Backup = getushort(pfat710->bpbBackup); if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) - != boot->FSInfo * boot->BytesPerSec - || read(dosfs, fsinfo, sizeof fsinfo) - != sizeof fsinfo) { + != boot->FSInfo * boot->BytesPerSec) { + perror("could not seek to fsinfo block to read"); + return FSFATAL; + } + + if (read(dosfs, &fsstruct, sizeof(struct fsinfo)) + != sizeof(struct fsinfo)) { perror("could not read fsinfo block"); return FSFATAL; } - if (memcmp(fsinfo, "RRaA", 4) - || memcmp(fsinfo + 0x1e4, "rrAa", 4) - || fsinfo[0x1fc] - || fsinfo[0x1fd] - || fsinfo[0x1fe] != 0x55 - || fsinfo[0x1ff] != 0xaa - || fsinfo[0x3fc] - || fsinfo[0x3fd] - || fsinfo[0x3fe] != 0x55 - || fsinfo[0x3ff] != 0xaa) { + + if (memcmp(fsstruct.fsisig1, "RRaA", 4) || + memcmp(fsstruct.fsisig2, "rrAa", 4) || + memcmp(fsstruct.fsisig3, "\0\0\125\252", 4) || + memcmp(fsstruct.fsisig4, "\0\0\125\252", 4)) { pwarn("Invalid signature in fsinfo block"); + if (ask(0, "fix")) { - memcpy(fsinfo, "RRaA", 4); - memcpy(fsinfo + 0x1e4, "rrAa", 4); - fsinfo[0x1fc] = fsinfo[0x1fd] = 0; - fsinfo[0x1fe] = 0x55; - fsinfo[0x1ff] = 0xaa; - fsinfo[0x3fc] = fsinfo[0x3fd] = 0; - fsinfo[0x3fe] = 0x55; - fsinfo[0x3ff] = 0xaa; + memcpy(fsstruct.fsisig1, "RRaA", 4); + memcpy(fsstruct.fsisig2, "rrAa", 4); + memcpy(fsstruct.fsisig3, "\0\0\125\252", 4); + memcpy(fsstruct.fsisig4, "\0\0\125\252", 4); + if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) - != boot->FSInfo * boot->BytesPerSec - || write(dosfs, fsinfo, sizeof fsinfo) - != sizeof fsinfo) { - perror("Unable to write FSInfo"); + != boot->FSInfo * boot->BytesPerSec) { + perror("could not seek to fsinfo block to fix/write"); + return FSFATAL; + } + + if (write(dosfs, &fsstruct, sizeof(struct fsinfo)) + != sizeof(struct fsinfo)) { + perror("could not write fixed fsinfo"); return FSFATAL; } + ret = FSBOOTMOD; - } else + } + else { + /* we didn't fix the corrupted FSInfo block */ boot->FSInfo = 0; + } } - if (boot->FSInfo) { - boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8) - + (fsinfo[0x1ea] << 16) - + (fsinfo[0x1eb] << 24); - boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8) - + (fsinfo[0x1ee] << 16) - + (fsinfo[0x1ef] << 24); + + if (boot->FSInfo != 0) { + boot->FSFree = getulong(fsstruct.fsinfree); + boot->FSNext = getulong(fsstruct.fsinxtfree); } if (lseek(dosfs, boot->Backup * boot->BytesPerSec, SEEK_SET) - != boot->Backup * boot->BytesPerSec - || read(dosfs, backup, sizeof backup) != sizeof backup) { + != boot->Backup * boot->BytesPerSec) { + perror("could not seek to read backup bootblock"); + return FSFATAL; + } + + if (read(dosfs, &backup, sizeof(union bootsector)) + != sizeof(union bootsector)) { perror("could not read backup bootblock"); return FSFATAL; } - backup[65] = block[65]; /* XXX */ - if (memcmp(block + 11, backup + 11, 79)) { - /* Correct? XXX */ + + // never written back to disk + //backup.bs710.bsExt.exReserved1 = buffer.bs710.bsExt.exReserved1; + + if (memcmp(buffer.bs710.bsBPB, + backup.bs710.bsBPB, + sizeof(struct bpb710)) || + memcmp(buffer.bs710.bsExt, + backup.bs710.bsExt, + sizeof(struct extboot))) { + pfatal("backup doesn't compare to primary bootblock"); if (alwaysno) pfatal("\n"); else return FSFATAL; } - /* Check backup FSInfo? XXX */ + + /* Unnecessary to check the backup FSInfo because there isn't + * an physical backup copy of the FSInfo block. There's only a + * backup of the FSInfo block number, which was checked (bsBPB) above. + */ } boot->ClusterOffset = (boot->RootDirEnts * 32 + boot->BytesPerSec - 1) @@ -190,13 +223,14 @@ boot->NumSectors = boot->Sectors; } else boot->NumSectors = boot->HugeSectors; - boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->SecPerClust; + boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) + / boot->SecPerClust; - if (boot->flags&FAT32) + if (boot->flags & FAT32) boot->ClustMask = CLUST32_MASK; - else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) + else if (boot->NumClusters < (CLUST_RSRVD & CLUST12_MASK)) boot->ClustMask = CLUST12_MASK; - else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK)) + else if (boot->NumClusters < (CLUST_RSRVD & CLUST16_MASK)) boot->ClustMask = CLUST16_MASK; else { pfatal("Filesystem too big (%u clusters) for non-FAT32 partition", @@ -230,33 +264,38 @@ } int -writefsinfo(dosfs, boot) - int dosfs; - struct bootblock *boot; +writefsinfo(int dosfs, struct bootblock *boot) { + struct fsinfo fsstruct; u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; - if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) - != boot->FSInfo * boot->BytesPerSec - || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { - perror("could not read fsinfo block"); + if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) + != boot->FSInfo * boot->BytesPerSec) { + perror("could not seek to fsinfo block to read"); + return FSFATAL; + } + + if (read(dosfs, &fsstruct, sizeof(struct fsinfo)) + != sizeof(struct fsinfo)) { + perror("could not read fsinfo block"); + return FSFATAL; + } + + putulong(&fsstruct.fsinfree, boot->FSFree); + putulong(&fsstruct.fsinxtfree, boot->FSNext); + + if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) + != boot->FSInfo * boot->BytesPerSec) { + perror("could not seek to fsinfo block to write new block"); + return FSFATAL; + } + + if (write(dosfs, &fsstruct, sizeof(struct fsinfo)) + != sizeof(struct fsinfo)) { + perror("could not write fixed fsinfo"); return FSFATAL; } - fsinfo[0x1e8] = (u_char)boot->FSFree; - fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); - fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); - fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24); - fsinfo[0x1ec] = (u_char)boot->FSNext; - fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); - fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); - fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); - if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) - != boot->FSInfo * boot->BytesPerSec - || write(dosfs, fsinfo, sizeof fsinfo) - != sizeof fsinfo) { - perror("Unable to write FSInfo"); - return FSFATAL; - } + /* * Technically, we should return FSBOOTMOD here. * @@ -264,7 +303,7 @@ * support for FAT32) doesn't maintain the FSINFO block * correctly, it has to be fixed pretty often. * - * Therefor, we handle the FSINFO block only informally, + * Therefore, we handle the FSINFO block only informally, * fixing it if necessary, but otherwise ignoring the * fact that it was incorrect. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707080829.l688TUHi051794>