📄 dosfsfmtlib.c
字号:
{ pConf->maxRootEnts = DEFAULT_MAX_ROOT_ENTS; } /* one last time, recalculate cluster nClust, knowing reserved */ nClust = (nBlks - pConf->nResrvd - rootSecs - pConf->nHidden - (pConf->secPerFat * pConf->nFats ) ) / pConf->secPerClust; pConf->nClust = nClust; /* see if it all sums up */ if((pConf->nHidden + pConf->nResrvd + rootSecs + (pConf->secPerFat * pConf->nFats ) + (pConf->nClust * pConf->secPerClust)) > nBlks ) goto error; if( (pConf->secPerClust <= 255 ) ) return OK ;error: errno = EINVAL ; return ERROR; }/********************************************************************************* dosFsFmtReadBootBlock - read existing boot block on the disk** Read the existing boot block on the disk, to salvage some fields* that should be preserved, if the volume is already formatted.** RETURNS: results confidence level: 100 is the highest confidence, * a lower value means more probability for bogus values, or ERROR if * could not read block.*/LOCAL int dosFsFmtReadBootBlock ( CBIO_DEV_ID cbioDev, DOS_VOL_CONFIG * pConf ) { int confidence = 100 ; STATUS stat ; u_char bootBlockBuffer [ 512 ] ; /* must be at least 512 bytes */ u_char * pBoot ; u_char c1 ; u_long i, work ; int bytesPerBlk; u_char tmpType [ DOS_BOOT_FSTYPE_LEN + 1] = { 0 }; CBIO_PARAMS cbioParams; /* Below we request the (underlying CBIO) device parameters. */ if (ERROR == cbioParamsGet (cbioDev, &cbioParams)) { return (ERROR); } bytesPerBlk = cbioParams.bytesPerBlk ; if (0 == bytesPerBlk) { return (ERROR); } if( bytesPerBlk > (int) sizeof(bootBlockBuffer) ) { pBoot = KHEAP_ALLOC(bytesPerBlk); } else { pBoot = bootBlockBuffer ; } if (NULL == pBoot) { return (ERROR); } bzero( (char *) pBoot, bytesPerBlk); /* read the boot block */ stat = cbioBlkRW( cbioDev, DOS_BOOT_SEC_NUM, 1, (addr_t)pBoot, CBIO_READ, NULL ); if( stat == ERROR ) return (ERROR); /* * inspect the boot block fields, and decrease confidence value * each time a field seems bogus, by something relative to * level of criticality of an appropriate field */ /* check for either 80x80 JMP instruction opcodes */ if( pBoot[ DOS_BOOT_JMP ] != 0xe9 && pBoot[ DOS_BOOT_JMP ] != 0xeb ) confidence -= 5; /* * Many FAT documents mistakenly state that the 0x55aa signature word * "occupies the last two bytes of the boot sector". That is only true * when the bytes-per-sector value is 512 bytes. Microsoft * defines the signature at offsets 510 and 511 (zero-based) * regardless of the sector size. It is okay, however to have * the signature at the end of the sector. We accept either. */ /* First, check for a signature at the end of the sector. */ if((pBoot[ bytesPerBlk - 2 ] != 0x55 ) || (pBoot[ bytesPerBlk-1] != 0xaa)) { /* Didn't find signature, check the 510 and 511 offsets. */ if ((pBoot[510] != 0x55) || (pBoot[511] != 0xaa)) { confidence -= 5; /* no 0x55aa signature :-( */ } } if( DISK_TO_VX_16(pBoot+DOS_BOOT_BYTES_PER_SEC) != bytesPerBlk ) confidence -= 5 ; if((pConf->secPerClust = pBoot[ DOS_BOOT_SEC_PER_CLUST ]) == 0) confidence -= 5 ; if((pConf->mediaByte = pBoot[ DOS_BOOT_MEDIA_BYTE ]) == 0) confidence -= 2; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NRESRVD_SECS )) == 0 ) confidence -= 5; else pConf->nResrvd = work ; if((pConf->nFats = pBoot[ DOS_BOOT_NFATS ]) == 0) confidence -= 5 ; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_MAX_ROOT_ENTS )) == 0 ) confidence -= 5 ; else pConf->maxRootEnts = work ; if((work = DISK_TO_VX_16( pBoot + DOS_BOOT_NSECTORS )) == 0 ) { if((work = DISK_TO_VX_32( pBoot + DOS_BOOT_LONG_NSECTORS )) == 0) confidence -= 5; } /* a problem here may indicate a problem in cbio layer partitioning */ if( work > cbioParams.nBlocks ) confidence -= 5; /* setup the fat type and sectors per fat */ if((work = DISK_TO_VX_16(pBoot + DOS_BOOT_SEC_PER_FAT)) == 0 ) { /* when 16 bit sectors per FAT field is zero, we presume FAT32 */ if((work = DISK_TO_VX_32( pBoot + DOS32_BOOT_SEC_PER_FAT )) == 0 ) confidence -= 5 ; bcopy((char *) pBoot + DOS32_BOOT_FS_TYPE, (char *) tmpType, DOS_SYS_ID_LEN ); if(strcmp ((char *)tmpType, DOS_BOOT_SYSID_FAT32) != 0 ) confidence -= 5 ; pConf->fatType = _FAT32; pConf->secPerFat = work; } else /* must be using either FAT12 or FAT16 */ { /* * Not using FAT32, determine between FAT12 and FAT16, * and test the cluster count against the string, if present. */ pConf->secPerFat = work; bcopy ( (char *) pBoot + DOS_BOOT_FSTYPE_ID, (char *) tmpType, DOS_BOOT_FSTYPE_LEN); stat = dosFsVolIsFat12 (pBoot); if (ERROR == stat) { confidence -= 5; } if (TRUE == stat) /* calc'd FAT12 */ { /* * Check the FSTYPE field in the BPB to ensure the string * value matches our calculation. If not, the we assume * the formatter knew what they wanted, and we honor * the string value. We look for "FAT12 " or "FAT16 ". */ if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT16)) == 0) { pConf->fatType = _FAT16; printf("dosFsFmtLib: %s indicated by BPB FSTYPE string, " "cluster calculation was FAT12. Returning string.\n", tmpType); } else { pConf->fatType = _FAT12; } } else /* calc'd FAT16 */ { /* * Check the FSTYPE field in the BPB to ensure the string * value matches our calculation. If not, the we assume * the formatter knew what they wanted, and we honor * the string value. We look for "FAT12 " or "FAT16 ". */ if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT12)) == 0) { pConf->fatType = _FAT12; printf("dosFsFmtLib: %s indicated by BPB FSTYPE string, " "cluster calculation was FAT16. Returning string.\n", tmpType); } else { pConf->fatType = _FAT16; } } } /* this is not the CHKDSK, no need to be absolutely perfect. */ if( (pConf->nHeads = DISK_TO_VX_32( pBoot + DOS_BOOT_NHEADS))== 0) confidence -=5 ; if((pConf->secPerTrack = DISK_TO_VX_32(pBoot + DOS_BOOT_SEC_PER_TRACK))==0) confidence -=5 ; /* get volume serial number, this is what its all about, actually */ if( pConf->fatType == _FAT32 ) work = DISK_TO_VX_32( pBoot + DOS32_BOOT_VOL_ID ) ; else work = DISK_TO_VX_32( pBoot + DOS_BOOT_VOL_ID ) ; /* scrutinize the serial number */ if( (work & 0xffff) == ((work >> 16) & 0xffff) || (work & 0xffff0000) == 0) { /* found suspicious serial number, so we mangle it XXX WHY? */ confidence -= 5 ; work |= tickGet() << 16 ; } pConf->volSerial = work; /* get label, should be useful too */ if( pConf->fatType == _FAT32 ) i = DOS32_BOOT_VOL_LABEL; else i = DOS_BOOT_VOL_LABEL; bcopy( (char *)pBoot + i, pConf->volLabel, DOS_VOL_LABEL_LEN ); /* replace any illegal character with a space */ for(i = 0; i< DOS_VOL_LABEL_LEN; i++) { c1 = pConf->volLabel[i] ; if( ! isupper(c1) && ! isdigit(c1) && (c1 != '_') && (c1 != '$')) pConf->volLabel[i] = ' '; } /* preserve hidden sectors */ pConf->nHidden = DISK_TO_VX_32 (pBoot + DOS_BOOT_NHIDDEN_SECS); /* Done */ if( pBoot != bootBlockBuffer ) KHEAP_FREE(pBoot); if( confidence < 0 ) confidence = 0 ; return( confidence ); }/********************************************************************************* dosFsFmtNonFsBootInit - initialize non-fs fields in boot block** Set areas such as JUMP command, boot code, signature* */LOCAL void dosFsFmtNonFsBootInit ( u_char * pBoot, /* comment for this arg */ int bytesPerBlk /* comment for this arg */ ) { /* * 0xEB is a x86, JMP rel8, Jump short, relative, * displacement relative to next instruction, 0x3e * The 0x90 is a NOP instruction and it is an alias * mnemonic for the XCHG (E)AX, (E)AX instruction. */ pBoot[ 0 ] = 0xeb ; /* JUMP */ pBoot[ 1 ] = 0x3e ; /* program offset */ pBoot[ 2 ] = 0x90 ; /* NOP */ /* * Many FAT documents mistakenly say that the 0x55AA signature word * "occupies the last two bytes of the boot sector". That is only true * when the bytes-per-sector value is 512 bytes. Microsoft * defines the signature at offsets 510 and 511 (zero-based) * regardless of the sector size. It is okay, however to have * the signature also at the end of the sector. We write it to * both places to be safe. */ pBoot[ bytesPerBlk-2 ] = 0x55 ; pBoot[ bytesPerBlk-1 ] = 0xaa ; if (bytesPerBlk > 512) { pBoot[ 510 ] = 0x55 ; pBoot[ 511 ] = 0xaa ; } }/******************************************************************************** * dosFsFmtVolInit - perform the actual disk formatting** Initialize all file system control structure on the disk, optionally* preserving the boot block non-file system fields such as boot code* and partition table.**/LOCAL int dosFsFmtVolInit ( CBIO_DEV_ID cbioDev, /* cbio handle */ DOS_VOL_CONFIG * pConf, /* volume parameters */ BOOL preserve, /* =1 - preserve boot blocks fields */ int opt /* VxLong names */ ) { STATUS stat = ERROR ; u_char bootBlockBuffer [512] ; u_char * pBoot ; u_char dirEntrySize = DOS_DIRENT_STD_LEN; int backupBootSec = NONE ; u_long i, work, rootStartSec ; int bytesPerBlk; CBIO_PARAMS cbioParams; /* * Below we request the (underlying CBIO) device parameters. * These parameters will be used to help calculate this dosFs volumes * configuration. The information will be used to help * determine the FAT type, the sectors per cluster, etc. * For example, the number of sectors (aka blocks) on the device returned * by the cbioParamsGet call must reflect the partitions total block * values, which is NOT necessarily the entire disk; else the calculations * may be incorrect. */ if (ERROR == cbioParamsGet (cbioDev, &cbioParams)) { return (ERROR); } bytesPerBlk = cbioParams.bytesPerBlk ; if (0 == bytesPerBlk) { return (ERROR); } if( opt & DOS_OPT_VXLONGNAMES ) dirEntrySize = DOS_VX_DIRENT_LEN; /* Thanks Kent! */ /* * Need enough space for at least a sector, * depending on sector size we may KHEAP_ALLOC it. */ if( bytesPerBlk > (int)sizeof(bootBlockBuffer) ) pBoot = KHEAP_ALLOC(bytesPerBlk);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -