📄 dosfslib.c
字号:
** RETURNS: STATUS as result of semGive.*/LOCAL STATUS dosFsFSemGive ( DOS_FILE_DESC_ID pFd ) { STATUS retStat; assert( pFd - pFd->pVolDesc->pFdList < pFd->pVolDesc->maxFiles ); assert( pFd->pFileHdl - pFd->pVolDesc->pFhdlList < pFd->pVolDesc->maxFiles ); retStat = semGive( *(pFd->pVolDesc->pFsemList + (pFd->pFileHdl - pFd->pVolDesc->pFhdlList))); assert( retStat == OK ); return retStat; } /* dosFsFSemGive() */ /********************************************************************************* dosFsVolUnmount - unmount a dosFs volume** This routine is called when I/O operations on a volume are to be* discontinued. This is the preferred action prior to changing a* removable disk.** All buffered data for the volume is written to the device* (if possible, with no error returned if data cannot be written),* any open file descriptors are marked as obsolete,* and the volume is marked as not currently mounted.** When a subsequent open() operation is initiated on the device,* new volume will be mounted automatically.** Once file descriptors have been marked as obsolete, any attempt to* use them for file operations will return an error. (An obsolete file* descriptor may be freed by using close(). The call to close() will* return an error, but the descriptor will in fact be freed).** This routine may also be invoked by calling ioctl() with the* FIOUNMOUNT function code.** This routine must not be called from interrupt level.** RETURNS: OK, or ERROR if the volume was not mounted.** NOMANUAL*/STATUS dosFsVolUnmount ( void * pDevNameOrPVolDesc /* device name or ptr to */ /* volume descriptor */ ) { DOS_VOLUME_DESC_ID pVolDesc; /* pointer to volume descriptor */ int i; /* get volume descriptor */ pVolDesc = dosFsVolDescGet( pDevNameOrPVolDesc, NULL ); if( pVolDesc == NULL ) return ERROR; if( ! pVolDesc->mounted ) return ERROR; /* acquire semaphore */ if( semTake( pVolDesc->devSem, WAIT_FOREVER ) == ERROR ) return ERROR; /* mark all opened file descriptors as obsolete */ /* also synchronize the FAT and do not hold the */ /* file semaphore, in certain operations like */ /* rename-file the file semaphore is locked */ /* before devSem. Trying to hold file semaphore */ /* , after holding devSem, will cause dead-lock */ for( i = 0; i < pVolDesc->maxFiles; i ++ ) { if( pVolDesc->pFdList[ i ].busy ) { /* Synchronize the FAT */ pVolDesc->pFatDesc->flush(&pVolDesc->pFdList[i]); pVolDesc->pFdList[ i ].pFileHdl->obsolet = 1; } } pVolDesc->nBusyFd = 0; /* flush buffers */ cbioIoctl( pVolDesc->pCbio, CBIO_CACHE_FLUSH, (void*)(-1) ); cbioIoctl( pVolDesc->pCbio, CBIO_CACHE_INVAL, 0 ); pVolDesc->mounted = FALSE; /* volume unmounted */ semGive( pVolDesc->devSem ); return OK; } /* dosFsVolUnmount() */ /********************************************************************************* dosFsChkDsk - make volume integrity checking.** This library does not makes integrity check process itself, but* instead uses routine provided by dosChkLib. * This routine prepares parameters and invokes checking routine* via preinitialized function pointer. If dosChkLib does not configured* into vxWorks, this routine returns ERROR.** Ownership on device should be taken by an upper level routine.** RETURNS: STATUS as returned by volume checking routine or* ERROR, if such routine does not installed.** ERRNO:* S_dosFsLib_UNSUPPORTED.*/STATUS dosFsChkDsk ( FAST DOS_FILE_DESC_ID pFd, /* file descriptor of root dir */ u_int params /* check level and verbosity */ ) { DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; CBIO_DEV_ID cbio = pFd->pVolDesc->pCbio; STATUS retVal = ERROR; if( dosFsChkRtn == NULL ) { errnoSet( S_dosFsLib_UNSUPPORTED ); ERR_MSG(1,"Check disk utility not installed\n", 0,0,0,0,0,0 ); return ERROR; } /* prepare check disk parameters */ if( (params & 0xff) == 0 ) params |= DOS_CHK_ONLY; /* prevent attempts to write on read only volume */ cbioIoctl(cbio, CBIO_STATUS_CHK, 0 ); if( cbioModeGet(cbio) == O_RDONLY ) { /* avoid writing to O_RDONLY devices */ params = (params & ~0xff) | DOS_CHK_ONLY; } pVolDesc->chkLevel = min( params & 0xff, DOS_CHK_REPAIR ); pVolDesc->chkVerbLevel = ( (params & 0xff00) == DOS_CHK_VERB_0 )? 0 : params >> 8; /* run disk check */ retVal = dosFsChkRtn( pFd ); if(params == ((params & ~0xff) | DOS_CHK_ONLY)) { cbioIoctl( pVolDesc->pCbio, CBIO_CACHE_FLUSH, (void *)(-1) ); cbioIoctl( pVolDesc->pCbio, CBIO_CACHE_INVAL, 0 ); } pVolDesc->chkLevel = 0; pVolDesc->chkVerbLevel = 0; /* reset dcache driver to recount boot block checksum */ if( TRUE == cbioRdyChgdGet (pVolDesc->pCbio) ) { retVal = ERROR; /* volume was changed during check disk */ } else { cbioIoctl( pVolDesc->pCbio, CBIO_RESET, NULL ); } return retVal; } /* dosFsChkDsk() *//********************************************************************************* dosFsBadBootMsg - print error message while boot sector parsing.** RETURNS: N/A.*/LOCAL void dosFsBadBootMsg ( u_int dbgLevel, /* message level */ u_int offset, /* offset of invalid field */ u_int val, /* invalid value */ char * pExtraMsg, /* extra message */ u_int line /* line number of error detecting code */ ) {#ifdef DEBUG printErr( "%s : %u. Malformed boot sector. Offset %u, value %u. %s\n", __FILE__, __LINE__, offset, val, ( (pExtraMsg == NULL)? " " : pExtraMsg ) );#else /* not DEBUG */ ERR_MSG( dbgLevel, "Malformed boot sector. Offset %u, value %u. %s\n", offset, val, ( (pExtraMsg == NULL)? " " : pExtraMsg ), 0,0,0 ); #endif /* DEBUG */ } /********************************************************************************* dosFsBootSecGet - extract boot sector parameters.** This routine reads boot sector from the disk and extracts* current volume parameters from of it.** This routine also performs sanity check of those volume parameters,* that are mutually dependent or alternative.* * This routine also determines the FAT type: FAT32, FAT12, or FAT16.** If read or damaged boot sector is encountered, this routine* searches for backup copy of boot sector and accepts volume* volume configuration from this copy.,** RETURNS: OK or ERROR if disk read error or inconsistent* boot sector data or failure to obtain cbio parameters.** ERRNO:* S_dosFsLib_UNKNOWN_VOLUME_FORMAT*/LOCAL STATUS dosFsBootSecGet ( DOS_VOLUME_DESC_ID pVolDesc /* pointer to volume descriptor */ ) { CBIO_PARAMS cbioParams; u_int work; u_char bootSec[ 512 ] = { 0 }; /* buffer for boot sector data */ u_char pass = 0; u_char tmpType [ DOS_BOOT_FSTYPE_LEN + 1] = { 0 }; pVolDesc->bootSecNum = DOS_BOOT_SEC_NUM; /* zero, per FAT standard */boot_get: /* reset the CBIO device in order to synchronize the boot sector */ if( cbioIoctl(pVolDesc->pCbio, CBIO_RESET, 0 ) == ERROR ) { return ERROR; } /* request the underlying CBIO device parameters */ if (ERROR == cbioParamsGet (pVolDesc->pCbio, &cbioParams)) { return (ERROR); } /* ensure bytesPerBlk is non-zero */ if (0 == cbioParams.bytesPerBlk) { ERR_MSG( 1, "cbioParams.bytesPerBlk cannot be zero.\n", 0,0,0,0,0,0 ); if( TRUE == cbioRdyChgdGet (pVolDesc->pCbio) ) { return (ERROR); } goto error; } /* read relevant boot sector data into bootSec[] */ work = min( cbioParams.bytesPerBlk, (int) sizeof(bootSec) ); if( cbioBytesRW(pVolDesc->pCbio, pVolDesc->bootSecNum, 0 /* offset */, (addr_t)bootSec, work, CBIO_READ, NULL ) == ERROR ) { ERR_MSG( 1, "ERROR reading the device boot sector\n", 0,0,0,0,0,0 ); ERR_MSG( 1, "media not formatted or not present\n", 0,0,0,0,0,0 ); if( TRUE == cbioRdyChgdGet (pVolDesc->pCbio) ) { return (ERROR); } goto error; } /* check for both acceptable Intel 80x86 `jmp' opcodes */ if( bootSec[ DOS_BOOT_JMP ] != 0xe9 && bootSec[ DOS_BOOT_JMP ] != 0xeb ) { dosFsBadBootMsg( 1, DOS_BOOT_JMP, (u_int)bootSec[ DOS_BOOT_JMP ], NULL , __LINE__); goto error; } /* * 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 acceptable, however to have the signature at the end of the * sector. We shall accept either location. SPR#62415. */ /* read the ending 2 bytes of the sector to check signature */ if( cbioBytesRW(pVolDesc->pCbio, pVolDesc->bootSecNum, cbioParams.bytesPerBlk - 2 /* off */, (addr_t)&work, 2, CBIO_READ, NULL ) == ERROR ) { ERR_MSG( 1, "ERROR reading boot sector\n", 0,0,0,0,0,0 ); if( TRUE == cbioRdyChgdGet (pVolDesc->pCbio) ) { return (ERROR); } goto error; } work = DISK_TO_VX_16( &work ); if (0xaa55 != work) /* why have a back door? "&& (work != 0xface)") */ { /* * We did not find the signature word at the end of the sector, * so we will check at the 510/511 offset per the Microsoft FAT spec. * If we cannot find it there, then assume the boot sector is bad. */ if ((bootSec[510] != 0x55) || (bootSec[511] != 0xaa)) { dosFsBadBootMsg( 1, cbioParams.bytesPerBlk - 2, work, "At the end of boot sector", __LINE__ ); goto error; } } /* * Start filling out and verifying the volume descriptor fields * using the data from the boot parameter block. Evaluate the validity * of the data, so that dosFsVolIsFat12() may be safely called. */ /* evaluate bytes per sector */ work = DISK_TO_VX_16( bootSec + DOS_BOOT_BYTES_PER_SEC ); pVolDesc->bytesPerSec = work; if( work == 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -