📄 dosdiroldlib.c
字号:
switch( which ) { case DH_TIME_CREAT: tOff = pDirDesc->deDesc.creatTimeOff; dOff = pDirDesc->deDesc.creatDateOff; break; case DH_TIME_MODIFY: tOff = pDirDesc->deDesc.modifTimeOff; dOff = pDirDesc->deDesc.modifDateOff; break; case DH_TIME_ACCESS: tOff = pDirDesc->deDesc.accessTimeOff; dOff = pDirDesc->deDesc.accessDateOff; break; default: assert( FALSE ); } if( dOff != (u_char)NONE ) { dtBuf = DISK_TO_VX_16( pDirent + dOff ); tm.tm_mday = dtBuf & 0x1f; /* ANSI months are zero-based */ tm.tm_mon = ((dtBuf >> 5) & 0x0f) - 1; /* DOS starts at 1980, ANSI starts at 1900 */ tm.tm_year = ((dtBuf >> 9) & 0x7f) + 1980 - 1900; } if( tOff != (u_char)NONE ) { dtBuf = DISK_TO_VX_16( pDirent + tOff ); tm.tm_sec = (dtBuf & 0x1f) << 1; tm.tm_min = (dtBuf >> 5) & 0x3f; tm.tm_hour = (dtBuf >> 11) & 0x1f; } /* encode into time_t format */ return mktime( &tm ); } /* dosDirOldTDDecode() *//***************************************************************************** dosDirOldTDEncode - encode time-date to disk format.** This routine takes time value is provided in <curTime> argument* and encodes it into directory entry format.* * Parameter <timesMask> defines which time fields to fill. Following* values can be bitwise or-ed:* DH_TIME_CREAT, DH_TIME_MODIFY, DH_TIME_ACCESS.** RETURNS: N/A.*/LOCAL void dosDirOldTDEncode ( DOS_DIR_PDESCR_ID pDirDesc, u_char * pDirEnt, u_int timesMask, time_t curTime /* time to encode */ ) { struct tm tm; /* buffer for split time-date */ u_char timeB[2], dateB[2]; /* buffers for encoding */ localtime_r( &curTime, &tm ); /* encode time */ VX_TO_DISK_16( ( tm.tm_sec >> 1 ) | ( tm.tm_min << 5 ) | ( tm.tm_hour << 11 ), timeB ); /* * encode date; * in <pDate> year is related to 1980, but in tm,-to 1900 */ tm.tm_year = ( tm.tm_year < 80 )? 80 : tm.tm_year; VX_TO_DISK_16( tm.tm_mday | ( ( tm.tm_mon + 1 ) << 5 ) | ( ( tm.tm_year - 80 ) << 9 ), dateB ); /* put time-date into directory entry buffer */ if( timesMask & DH_TIME_CREAT && pDirDesc->deDesc.creatDateOff != (u_char)NONE ) { pDirEnt[ pDirDesc->deDesc.creatTimeOff ] = timeB[0]; pDirEnt[ pDirDesc->deDesc.creatTimeOff + 1 ] = timeB[1]; pDirEnt[ pDirDesc->deDesc.creatDateOff ] = dateB[0]; pDirEnt[ pDirDesc->deDesc.creatDateOff + 1 ] = dateB[1]; } if( timesMask & DH_TIME_MODIFY && pDirDesc->deDesc.modifDateOff != (u_char)NONE ) { pDirEnt[ pDirDesc->deDesc.modifTimeOff ] = timeB[0]; pDirEnt[ pDirDesc->deDesc.modifTimeOff + 1 ] = timeB[1]; pDirEnt[ pDirDesc->deDesc.modifDateOff ] = dateB[0]; pDirEnt[ pDirDesc->deDesc.modifDateOff + 1 ] = dateB[1]; } if( timesMask & DH_TIME_ACCESS && pDirDesc->deDesc.accessDateOff != (u_char)NONE ) { if( pDirDesc->deDesc.accessTimeOff != (u_char)NONE ) { pDirEnt[ pDirDesc->deDesc.accessTimeOff ] = timeB[0]; pDirEnt[ pDirDesc->deDesc.accessTimeOff + 1 ] = timeB[1]; } pDirEnt[ pDirDesc->deDesc.accessDateOff ] = dateB[0]; pDirEnt[ pDirDesc->deDesc.accessDateOff + 1 ] = dateB[1]; } } /* dosDirOldTDEncode() */ /***************************************************************************** dosDirOldNameEncode - encode name to disk format.** This routine encodes incoming file name to current volume* directory structure format* (8+3 uppercase or VxLong names). in the same time incoming* name is verified to be composed of valid characters.** RETURNS: OK or ERROR if name is invalid.* * ERRNO:* S_dosFsLib_ILLEGAL_NAME*/LOCAL STATUS dosDirOldNameEncode ( DOS_DIR_PDESCR_ID pDirDesc, PATH_ARRAY_ID pNamePtr, /* name buffer */ u_char * pDstName /* buffer for name in disk format */ ) { u_char const * nameTransTbl; /* name translation table */ u_char * pSrc; /* source name dynamic ptr */ u_char * pDstBuf; /* for debug output only */ int i,j; /* work */ u_char extLen = pDirDesc->deDesc.extLen; /* extension length (0 - no extension) */ pDstBuf = pDstName; nameTransTbl = ( pDirDesc->nameStyle == STDDOS )? shortNamesChar : longNamesChar; bfill( (char *) pDstName, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen, SPACE ); /* encode name and check it by the way */ DBG_MSG( 600, "",0 ,0,0,0,0,0,0,0); DBG_PRN_STR( 600, "%s\n", pNamePtr->pName, pNamePtr->nameLen, 0 ); for( i = 0, pSrc = pNamePtr->pName; i < min( pDirDesc->deDesc.nameLen, pNamePtr->nameLen ); i++, pDstName++, pSrc++ ) { /* check for extension */ if( extLen != 0 && *pSrc == DOT ) break; /* allow all high characters */ if( *pSrc & 0x80 ) { *pDstName = *pSrc; continue; } *pDstName = nameTransTbl[ *pSrc ]; if( *pDstName == INVALID_CHAR ) goto error; } /* check state */ if( i == pNamePtr->nameLen ) goto retOK; /* name finished */ if( extLen != 0 ) /* traditional DOS: 8.3 */ { if( *pSrc != DOT ) /* name too long */ goto error; pSrc++; /* pass DOT */ pDstName += pDirDesc->deDesc.nameLen - i; i++; } else /* vxWorks old long names */ goto error; /* name too long */ /* encode extension */ for( j = 0; j < extLen && i < pNamePtr->nameLen; i++, j++, pDstName++, pSrc++ ) { /* allow all high characters */ if( *pSrc & 0x80 ) { *pDstName = *pSrc; continue; } *pDstName = nameTransTbl[ *pSrc ]; if( *pDstName == INVALID_CHAR ) goto error; } /* check status */ if( i < pNamePtr->nameLen ) /* extension too long */ goto error;retOK: DBG_PRN_STR( 600, "result: %s\n", pDstBuf, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen,0 ); return OK; error: errnoSet( S_dosFsLib_ILLEGAL_NAME ); return ERROR; } /* dosDirOldNameEncode() */ /***************************************************************************** dosDirOldDirentGet - get directory entry from disk.** This routine reads directory entry from disk. ** <which> argument defines which entry to get.* This routine can be* used for readdir (<which> = RD_FIRST/RD_CURRENT/RD_NEXT),* in what case <pFd> describes the* directory is being read, or for getting directory entry* corresponding to <pFd> (<which> = FD_ENTRY).** RETURNS: OK or ERROR if directory chain end reached or* disk access error.*/LOCAL STATUS dosDirOldDirentGet ( DOS_FILE_DESC_ID pFd, /* dos file descriptor to fill */ u_char * pDirEnt, RDE_OPTION which /* which entry to get */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; DOS_DIR_HDL_ID pDirHdl = (void *)&(pFd->pFileHdl->dirHdl); int dirEntSize = pDirDesc->deDesc.dirEntSize; DOS_FILE_DESC workFd; /* prepare to operation */ if( which == FD_ENTRY ) /* get directory entry of file */ { DBG_MSG( 600, "pFd = %p, FD_ENTRY\n", pFd ,0,0,0,0,0,0,0); /* * it is being read directory entry of the file/dir, * pointed by file descriptor. * Prepare working fd. */ workFd = *pFd; workFd.curSec = pDirHdl->sector; workFd.pos = pDirHdl->offset; workFd.cbioCookie = pDirHdl->cookie; goto getEntry; } /* readdir */ if( which == RD_CURRENT ) /* read current dir entry */ { assert( pFd->nSec != 0 ); assert( pFd->curSec != 0 ); goto getEntry; } if( which == RD_FIRST ) /* read start dir entry */ { DBG_MSG( 600, "pFd = %p, RD_FIRST\n", pFd ,0,0,0,0,0,0,0); dosDirOldRewindDir( pFd ); /* rewind directory */ } else if( which == RD_NEXT ) /* read next dir entry */ { DBG_MSG( 600, "pFd = %p, RD_NEXT\n", pFd ,0,0,0,0,0,0,0); assert( pFd->curSec != 0 ); /* correct position */ pFd->pos += dirEntSize; /* check for sector bounds */ if( OFFSET_IN_SEC( pFd->pVolDesc, pFd->pos ) == 0 ) { pFd->curSec++; pFd->nSec--; } } else /* impossible flag */ { assert( which != which ); } /* may be contiguous block finished - get next contiguous block */ if( pFd->nSec == 0 ) { if( pFd->pVolDesc->pFatDesc->getNext( pFd, FAT_NOT_ALLOC ) == ERROR ) { return ERROR; } pFd->cbioCookie = (cookie_t) NULL; /* we jumped to other sector */ } workFd = *pFd; getEntry: assert( OFFSET_IN_SEC( workFd.pVolDesc, workFd.pos ) <= workFd.pVolDesc->bytesPerSec - dirEntSize ); /* read directory entry */ if( cbioBytesRW( workFd.pVolDesc->pCbio, workFd.curSec, OFFSET_IN_SEC( workFd.pVolDesc, workFd.pos), (addr_t)pDirEnt, dirEntSize, CBIO_READ, &workFd.cbioCookie ) == ERROR ) { return ERROR; } DBG_PRN_STR( 600, "entry: %s\n", pDirEnt, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen,0 ); return OK; } /* dosDirOldDirentGet() */ /***************************************************************************** dosDirOldLkupInDir - look in directory for specified name.** This routine searches directory, that is pointed by <pFd> for name, that* is pointed by <pNamePtr> structure and fills <pFd> in accordance with* directory entry data, if found.** If name not found, <pFreeEnt> will be filled with pointer onto* some deleted entry in directory or onto free space in last directory* cluster. If both not found,* <pFreeEnt->sector> is set to 0.** RETURNS: OK or ERROR if name not found or invalid name.*/LOCAL STATUS dosDirOldLkupInDir ( DOS_FILE_DESC_ID pFd, /* dos file descriptor to fill */ PATH_ARRAY_ID pNamePtr, /* name buffer */ DIRENT_PTR_ID pFreeEnt /* empty entry in directory */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; STATUS status; /* search result status */ u_int nEntries; /* number of entries in directory */ u_short nameLen; /* name length on disk */ u_char name[ DOS_VX_LONG_NAME_LEN ]; /* name in disk format */ u_char dirent[ DOS_VX_DIRENT_LEN ]; /* directory entry buffer */ nameLen = pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen; DBG_MSG( 400, "pFd = %p", pFd ,0,0,0,0,0,0,0); DBG_PRN_STR( 400, "name: %s\n", pNamePtr->pName, pNamePtr->nameLen, 0 ); pFreeEnt->sector = 0; pFreeEnt->offset = 0; /* prepare name */ if( dosDirOldNameEncode( pDirDesc, pNamePtr, name ) == ERROR ) return ERROR; for( nEntries = 0, (status = dosDirOldDirentGet( pFd, dirent, RD_FIRST )); (status != ERROR) && *dirent != LAST_DIRENT; status = dosDirOldDirentGet( pFd, dirent, RD_NEXT ), nEntries++ ) { /* pass volume label */ if( *(dirent + pDirDesc->deDesc.atrribOff) & DOS_ATTR_VOL_LABEL ) continue; /* pass deleted entry, that later can be used to store new entry */ if( *dirent == DOS_DEL_MARK ) { pFreeEnt->sector = pFd->curSec; pFreeEnt->offset = pFd->pos; continue; } /* compare names */ if( bcmp( (char *)name, (char *)dirent, nameLen ) == 0 ) { break; } } /* check result */ if( status == ERROR || ( IS_ROOT( pFd ) && nEntries > pDirDesc->rootMaxEntries ) ) { return ERROR; } if( *dirent == LAST_DIRENT ) { /* will create new entry on this place, if required */ if( pFreeEnt->sector == 0 ) { pFreeEnt->sector = pFd->curSec; pFreeEnt->offset = pFd->pos; } return ERROR; } /* file found; fill file descriptor */ dosDirOldFillFd( pFd, dirent ); return OK; } /* dosDirOldLkupInDir() */ /***************************************************************************** dosDirOldClustAdd - add and init cluster to directory.** RETURNS: OK or ERROR if no more cluster could be allocated.*/LOCAL STATUS dosDirOldClustAdd ( DOS_FILE_DESC_ID pFd ) { block_t sec; /* work count */ /* allocate cluster */ if( pFd->pVolDesc->pFatDesc->getNext( pFd, FAT_ALLOC_ONE ) == ERROR ) return ERROR; assert( pFd->pFileHdl->startClust != 0 ); /* fill cluster: */ for( sec = pFd->curSec; sec < pFd->curSec + pFd->nSec; sec ++ ) { if( cbioIoctl(pFd->pVolDesc->pCbio, CBIO_CACHE_NEWBLK, (void *)sec ) == ERROR ) { return ERROR; } } return OK; } /* dosDirOldClustAdd() *//***************************************************************************** dosDirOldUpdateEntry - set new directory entry contents.** This routine pulls file size, attributes and so on out of* file descriptor and stores in the file directory entry.* * This function is also used for entry deletion. In this* case <flags> have to be set to DH_DELETE.** Time value provided in <curTime> can be encoded into appropriate* fields within directory entry structure in accordance with* <flags> argument. <flags> can be or-ed of* DH_TIME_CREAT, DH_TIME_MODIFY or DH_TIME_ACCESS.* If <curTime> is 0, current system time is used.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -