📄 dosfslib.c
字号:
/* check boot sector bottom opcode */ work = DISK_TO_VX_16( &work ); if( work != 0xaa55 && work != 0xface ) { dosFsBadBootMsg( 1, cbioParams.cbio_bytesPerBlk - 2, work, "At the end of boot sector", __LINE__ ); goto error; } /* bytes per sector */ work = DISK_TO_VX_16( bootSec + DOS_BOOT_BYTES_PER_SEC ); pVolDesc->bytesPerSec = work; if( work == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_BYTES_PER_SEC, work, NULL, __LINE__ ); ERR_MSG(10, "bytesPerSec = 0\n", 0,0,0,0,0,0 ); goto error; } if( work != cbioParams.cbio_bytesPerBlk ) { dosFsBadBootMsg( 1, DOS_BOOT_BYTES_PER_SEC, work, NULL, __LINE__ ); ERR_MSG(10, "cbioParams.cbio_bytesPerBlk %u != bytes-per-sec %u\n", cbioParams.cbio_bytesPerBlk, work, 0,0,0,0 ); goto error; } /* * bytes-per-sector must be power of two and * at least 32 bytes, so shift is used instead * of multiplication in operations with this value */ pVolDesc->secSizeShift = 0; for( work = 5; work < 16; work ++ ) { if( (1 << work) == pVolDesc->bytesPerSec ) { pVolDesc->secSizeShift = work; break; } } if( pVolDesc->secSizeShift == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_BYTES_PER_SEC, pVolDesc->bytesPerSec, NULL, __LINE__ ); goto error; } /* total number of sectors */ work = DISK_TO_VX_16( bootSec + DOS_BOOT_NSECTORS ); if( work == 0 ) /* it is a large disk */ { work = DISK_TO_VX_32( bootSec + DOS_BOOT_LONG_NSECTORS ); if( work == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_LONG_NSECTORS, work, NULL, __LINE__ ); goto error; } } pVolDesc->totalSec = work; /* total number of sectors can not outnumber <params.cbio_nBlocks> */ if( work != cbioParams.cbio_nBlocks ) { if( work < cbioParams.cbio_nBlocks ) { ERR_MSG(10, "WARNING: num-sectors %u < cbioParams.cbio_nBlocks %u\n", work, cbioParams.cbio_nBlocks, 0,0,0,0 ); } else { dosFsBadBootMsg( 1, DOS_BOOT_LONG_NSECTORS, 0, NULL, __LINE__ ); ERR_MSG(10, "num-sectors %u > params.cbio_nBlocks %u\n", work, cbioParams.cbio_nBlocks, 0,0,0,0 ); goto error; } } /* sectors per cluster */ pVolDesc->secPerClust = bootSec[ DOS_BOOT_SEC_PER_CLUST ]; if( pVolDesc->secPerClust == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_SEC_PER_CLUST, 0, NULL, __LINE__ ); goto error; } /* number of FAT copies */ pVolDesc->nFats = bootSec[ DOS_BOOT_NFATS ]; if( pVolDesc->nFats == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_NFATS, 0, NULL, __LINE__ ); goto error; } /* check FAT type and extract appropriate parameters */ pVolDesc->secPerFat = DISK_TO_VX_16( bootSec + DOS_BOOT_SEC_PER_FAT ); if( pVolDesc->secPerFat != 0 ) /* using FAT12/FAT16 */ { /* sectors per fat copy */ if( pVolDesc->secPerFat > (ULONG)0x10000*2 / pVolDesc->bytesPerSec) { dosFsBadBootMsg( 1, DOS_BOOT_SEC_PER_FAT, pVolDesc->secPerFat, NULL, __LINE__ ); ERR_MSG(10, "secPerFat 12/16 = %u, while BPS = %u\n", pVolDesc->secPerFat,pVolDesc->bytesPerSec,0,0,0,0 ); goto error; } /* * Attempt to use the new MS FSTYPE (0x36 in the boot sector) * to determine FAT type. jkf */ bcopy ( (char *) bootSec + DOS_BOOT_FSTYPE_ID, (char *) tmpType, DOS_BOOT_FSTYPE_LEN); if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT16)) == 0) { pVolDesc->fatType = FAT16; } else if ((strcmp ((char *)tmpType, DOS_BOOT_FSTYPE_FAT12)) == 0) { pVolDesc->fatType = FAT12; } /* * the only other way to distinct between FAT12 and FAT16 * is based on total number of clusters. * Check, how many 16-bit (2-byte) cluster entries stand in * FAT sectors. */ else if( (pVolDesc->secPerFat << (pVolDesc->secSizeShift - 1)) <= DOS_FAT_12BIT_MAX ) { pVolDesc->fatType = FAT12; } else { pVolDesc->fatType = FAT16; } /* volume Id and label */ pVolDesc->volIdOff = DOS_BOOT_VOL_ID; pVolDesc->volLabOff = DOS_BOOT_VOL_LABEL; } else /* FAT32 (pVolDesc->secPerFat == 0) */ { pVolDesc->fatType = FAT32; /* sectors per fat copy */ pVolDesc->secPerFat = DISK_TO_VX_32( bootSec + DOS32_BOOT_SEC_PER_FAT ); if( pVolDesc->secPerFat == 0 ) { dosFsBadBootMsg( 1, DOS32_BOOT_SEC_PER_FAT, 0, "(FAT32)", __LINE__ ); goto error; } /* volume Id and label */ pVolDesc->volIdOff = DOS32_BOOT_VOL_ID; pVolDesc->volLabOff = DOS32_BOOT_VOL_LABEL; } /* hidden sectors */ pVolDesc->nHiddenSecs = DISK_TO_VX_16( bootSec + DOS_BOOT_NHIDDEN_SECS); /* reserved sectors */ pVolDesc->nReservedSecs = DISK_TO_VX_16( bootSec + DOS_BOOT_NRESRVD_SECS); if( pVolDesc->nReservedSecs == 0 ) { dosFsBadBootMsg( 1, DOS_BOOT_NRESRVD_SECS, 0, NULL, __LINE__ ); goto error; } /* * count sector number of data area start cluster. * This value can be corrected later by directory handler, if * root directory is not stored as regular directory * in clusters (FAT32), but instead resides contiguously * ahead first data cluster (FAT12/FAT16) */ pVolDesc->dataStartSec = pVolDesc->nReservedSecs + pVolDesc->secPerFat * pVolDesc->nFats; /* volume Id and label */ pVolDesc->volId = DISK_TO_VX_32( bootSec + pVolDesc->volIdOff ); bcopy( (char *)bootSec + pVolDesc->volLabOff, (char *)pVolDesc->bootVolLab, DOS_VOL_LABEL_LEN ); *(pVolDesc->bootVolLab + DOS_VOL_LABEL_LEN) = EOS; /* restore base version of boot sector */ if( pVolDesc->bootSecNum != DOS_BOOT_SEC_NUM ) { ERR_MSG( 10, "Try to reclaim original copy of boot sector\n", 0,0,0,0,0,0 ); if( pass == 0 && cbioBlkCopy(pVolDesc->pCbio, pVolDesc->bootSecNum, DOS_BOOT_SEC_NUM, 1 ) == OK && cbioIoctl(pVolDesc->pCbio, CBIO_CACHE_FLUSH, (void *)(-1) ) == OK ) { /* remount again */ pass ++; pVolDesc->bootSecNum = DOS_BOOT_SEC_NUM; goto boot_get; } } /* currently it is enough for starting */ return OK; error: /* some data is inconsistent */ pVolDesc->bootSecNum ++; if( pVolDesc->bootSecNum < (u_int)DOS_BOOT_SEC_NUM + cbioParams.cbio_blksPerTrack ) { /* try to find other boot block copy */ if( pVolDesc->bootSecNum == DOS_BOOT_SEC_NUM + 1 ) { ERR_MSG( 1, "Try to accept other boot block copy...\n", 0,0,0,0,0,0 ); } goto boot_get; } if( errnoGet() == OK ) errnoSet( S_dosFsLib_UNKNOWN_VOLUME_FORMAT ); return ERROR; } /* dosFsBootSecGet() *//********************************************************************************* dosFsVolMount - prepare to use dosFs volume** This routine prepares the library to use the dosFs volume on the * device specified. The first sector, known as the boot sector,* is read from the disk. The required information in the boot sector* is copied to the volume descriptor for this device.* Some other fields in the volume descriptor* are set using values calculated from the boot sector information.** The appropriate File Allocation Table (FAT) handler and directory* handler are chosen from handlers list in accordance with* particular volume format version and user's preferences.** This routine is automatically called via first open() if device not* mounted and every time after a disk is changed.* * RETURNS: OK or ERROR.** ERRNO:* S_dosFsLib_INVALID_PARAMETER**/LOCAL STATUS dosFsVolMount ( DOS_VOLUME_DESC_ID pVolDesc /* pointer to volume descriptor */ ) { DOS_FILE_DESC_ID pFd = (void *)ERROR; u_int errnoBuf = errnoGet(); int i; /* check volume descriptor */ if( (pVolDesc == NULL) || pVolDesc->magic != DOS_FS_MAGIC ) { errnoSet( S_dosFsLib_INVALID_PARAMETER ); return ERROR; } /* prevent mount process from reentrant call */ if( semTake( & pVolDesc->devSem, WAIT_FOREVER ) == ERROR ) return ERROR; /* * before we can mount new volume * we have to unmount previous one */ if( pVolDesc->mounted ) { if( FALSE == cbioRdyChgdGet (pVolDesc->pCbio) ) goto ret; dosFsVolUnmount( pVolDesc ); } pVolDesc->mounted = FALSE; /* update and check base volume information from boot sector */ errnoSet( OK ); if( dosFsBootSecGet( pVolDesc ) == ERROR ) { if( errnoGet() == OK ) errnoSet( S_dosFsLib_UNKNOWN_VOLUME_FORMAT ); goto ret; } /* * init DIRECTORY handler ahead FAT, because * directory handler finally sets "data start sector" field, * that depends for FAT12/FAT16 root directory size in sectors */ /* dir handler mount */ for( i = 0; i < (int)NELEMENTS( dosDirHdlrsList ); i ++ ) { if( ( dosDirHdlrsList[ i ].mountRtn != NULL ) && dosDirHdlrsList[ i ].mountRtn( pVolDesc, dosDirHdlrsList[ i ].arg ) == OK ) { break; } } if( i == NELEMENTS( dosDirHdlrsList ) ) goto ret; /* FAT handler mount */ for( i = 0; i < (int)NELEMENTS( dosFatHdlrsList ); i ++ ) { if( ( dosFatHdlrsList[ i ].mountRtn != NULL ) && dosFatHdlrsList[ i ].mountRtn( pVolDesc, dosFatHdlrsList[ i ].arg ) == OK ) { break; } } if( i == NELEMENTS( dosFatHdlrsList ) ) goto ret; errnoSet( errnoBuf ); pVolDesc->mounted = TRUE; /* execute device integrity check (if not started yet) */ /* * It may seem, that following call to open() while device * semaphore is taken can cause deadlock because during * open() a file handle semaphore possibly is taken. * But don't worry. First, file semaphore is taken only * when open() has been called with O_TRUNC or DOS_O_CONTIG_CHK * flags, second, all opened file handles have been * marked obsolete already and so no one of them will be * actually shared. */ if( dosFsChkRtn != NULL && pVolDesc->autoChk != 0 && pVolDesc->chkLevel == 0 ) { pFd = dosFsOpen( pVolDesc, "", 0, 0 ); if( pFd != (void *) ERROR ) { if( dosFsChkDsk( pFd, pVolDesc->autoChk | (pVolDesc->autoChkVerb << 8) ) == OK || pVolDesc->autoChk == DOS_CHK_ONLY ) { goto ret; } pVolDesc->mounted = FALSE; } } ret: if( pFd != (void *)ERROR ) { pFd->pFileHdl->obsolet = 0; /* avoid errno set */ dosFsClose( pFd ); } semGive( & pVolDesc->devSem );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -