📄 dosvdirlib.c
字号:
pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen,0 ); return retVal; error: bzero( (char *)pDstBuf, DOS_DIRENT_STD_LEN ); return NO_SHORT; } /* dosVDirNameEncodeShort() */ /***************************************************************************** dosVDirNameEncode - encode name to disk format.** This routine encodes incoming file name into Windows-95 long names* format. During encoding the* name is verified to be composed of valid characters.* * The source name is* split into several directory entries, that has valid format,* unless alias checksum.* Also src name is attempted to be encoded in short manner.** RETURNS: directory entries per long name include alias or (-1) if name is* illegal.* * ERRNO:* S_dosFsLib_ILLEGAL_NAME*/LOCAL int dosVDirNameEncode ( DOS_DIR_PDESCR_ID pDirDesc, PATH_ARRAY_ID pNamePtr, /* name buffer */ u_char * pDstName, /* buffer for name in disk format */ SHORT_ENCODE * pShortEncodeStrat /* short name encodding */ /* strategy/result */ ) { u_char * pSrc = pNamePtr->pName; /* source name dynamic ptr */ u_char * pDst; /* ptr to encoded destination entry */ u_char numEnt; /* entries per long name */ u_char entNum, chNum; /* loop counters */ if( pNamePtr->nameLen > DOS_VFAT_NAME_LEN ) goto error; /* number of entries per long name */ numEnt = ( pNamePtr->nameLen + CHAR_PER_VENTRY - 1 ) / CHAR_PER_VENTRY; /* try to encode src name as short */ bzero( (char *)pDstName, DOS_DIRENT_STD_LEN ); if( ( dosVDirNameEncodeShort( pDirDesc, pNamePtr, pDstName ) == STRICT_SHORT ) ) { if( *pShortEncodeStrat == STRICT_SHORT ) { return 1; } *pShortEncodeStrat = STRICT_SHORT; } else { *pShortEncodeStrat = NOT_STRICT_SHORT; } bcopy( (char *)pDstName, (char *)pDstName + numEnt * DOS_DIRENT_STD_LEN, DOS_DIRENT_STD_LEN ); bzero( (char *)pDstName, numEnt * DOS_DIRENT_STD_LEN ); /* start encoding from bottom (first) entry */ pDst = pDstName + (numEnt - 1) * DOS_DIRENT_STD_LEN; for( entNum = 1; entNum <= numEnt; entNum ++, pDst -= DOS_DIRENT_STD_LEN ) { *pDst = entNum; /* encode entry number */ *(pDst + pDirDesc->deDesc.atrribOff) = DOS_ATTR_VFAT; /* VFAT long name representation */ /* encode characters */ for( chNum = 0; chNum < CHAR_PER_VENTRY && pSrc < pNamePtr->pName + pNamePtr->nameLen; pSrc ++, chNum ++ ) { if( dosVDirCharEncode( pSrc, pDst + chOffsets[ chNum ], longNamesChar ) == ERROR ) { goto error; } } /* fill extra characters in last entry with 0xff */ for( chNum ++; chNum < CHAR_PER_VENTRY; chNum ++ ) { assert( pSrc >= pNamePtr->pName + pNamePtr->nameLen ); *(pDst + chOffsets[ chNum ]) = 0xff; *(pDst + chOffsets[ chNum ] + 1) = 0xff; } } /* mark last entry */ pDst += DOS_DIRENT_STD_LEN; *pDst |= DOS_VLAST_ENTRY; return numEnt + 1;error: errnoSet( S_dosFsLib_ILLEGAL_NAME ); return (-1); } /* dosVDirNameEncode() */ /***************************************************************************** dosVDirClustNext - get next or add and init cluster to directory.** RETURNS: OK or ERROR if end of directory is reached or* no more cluster could be allocated or disk is full.*/LOCAL STATUS dosVDirClustNext ( DOS_FILE_DESC_ID pFd, u_int alloc /* 0 or DH_ALLOC */ ) { block_t sec; /* work count */ /* get next/allocate cluster */ alloc = ( alloc == 0 ) ? FAT_NOT_ALLOC : FAT_ALLOC_ONE; if( pFd->pVolDesc->pFatDesc->getNext( pFd, alloc ) == ERROR ) return ERROR; assert( pFd->pFileHdl->startClust != 0 ); if( alloc == FAT_NOT_ALLOC ) return OK; /* init 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); } /* dosVDirClustNext() *//***************************************************************************** dosVDirDirentGet - get bundle directory entry from disk.** This routine reads bundle directory entry from disk. * On this level each entry containing part of long name is accepted* independent of others.** <which> argument defines which entry to get.* This routine can be* used for readdir (<which> = RD_FIRST/RD_CURRENT/RD_NEXT),* in that 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 dosVDirDirentGet ( 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); dosVDirRewindDir( 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: /* 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; } /* dosVDirDirentGet() *//***************************************************************************** dosVDirDeStore - store some contiguous fields of directory entry.** This routine stores <nBytes> pointed by <pData> starting* from offset <offset> in directory entry is currently* pointed by <pFd> or next to this one, depending on* the <which> argument.* * <which> can be one of PUT_CURRENT or PUT_NEXT bitwise or-ed with* DH_ALLOC, if new directory entry is being created.** RETURNS: OK or ERROR if write error occurred.*/LOCAL STATUS dosVDirDeStore ( DOS_FILE_DESC_ID pFd, /* directory descriptor */ off_t offset, /* offset in directory entry */ size_t nBytes, /* num of bytes to write */ void * pData, /* ptr to data buffer */ u_int which /* (PUT_CURRENT or PUT_NEXT) ored with */ /* DH_ALLOC */ ) { DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; if( (which & PUT_NEXT) != 0 ) { pFd->pos += DOS_DIRENT_STD_LEN; if( OFFSET_IN_SEC( pFd->pVolDesc, pFd->pos ) == 0 ) { pFd->curSec ++; pFd->nSec --; } } if( pFd->nSec == 0 ) /* current cluster group exhausted */ { if( dosVDirClustNext( pFd, (which & DH_ALLOC) ) == ERROR ) return ERROR; } /* store data */ if( cbioBytesRW( pVolDesc->pCbio, pFd->curSec, OFFSET_IN_SEC( pVolDesc, pFd->pos ) + offset, pData, nBytes, CBIO_WRITE, &pFd->cbioCookie ) == ERROR ) { return ERROR; } return OK; } /* dosVDirDeStore() *//***************************************************************************** dosVDirEntryDel - mark long name as deleted.* * This routine marks <nEnt> traditional directory entries as deleted.* Entries are started from position is pointed by <pLnPtr>.** RETURNS: OK or ERROR if disk access failed.*/LOCAL STATUS dosVDirEntryDel ( DOS_VOLUME_DESC_ID pVolDesc,/* dos volume descriptor */ DIRENT_PTR_ID pLnPtr, /* long name start ptr */ u_int nEnt, /* number of entries to mark as deleted */ /* 0 - to accept the number from disk */ BOOL always /* delete independent of is check disk */ /* in progress or not */ ) { DOS_DIR_PDESCR_ID pDirDesc; DOS_FILE_DESC workFd = {0}; /* temporary file descriptor */ DOS_FILE_HDL workFileHdl; /* temporary file handle */ u_char dirent[ DOS_DIRENT_STD_LEN ]; /* directory entry buffer */ cookie_t cookie = (cookie_t) NULL; /* temp buffer */ u_int which; if( ! always && pVolDesc->chkLevel <= DOS_CHK_ONLY ) return OK;#if TRUE /* SPR#70968 fix enabled */ /* * 01o,09nov01,jkf SPR#70968, chkdsk destroys boot sector * * When chkdsk() is in repair mode(DOS_CHK_REPAIR): it can * destroy the boot sector's first byte (sector 0, offset 0) * by writing DOS_DEL_MARK(0xe5). The cause of the problem is * function dosVDirEntryDel() lacks a sanity check for * pLnPtr->sector being zero. * * Workaround: * * Add an "if" statement to check if pLnPtr is illegal: * * if( ! always && pVolDesc->chkLevel <= DOS_CHK_ONLY ) * return OK; * * /@ SPR#70968: check if pLnPtr is illegal @/ * * if ( 0 == pLnPtr->sector ) * return ERROR; */ if ( 0 == pLnPtr->sector ) { /* return ERROR if long name start pointer is from 0 sector */ return (ERROR); }#endif /* SPR#70968 fix enabled */ pDirDesc = (void *)pVolDesc->pDirDesc; bzero( (char *)&workFileHdl, sizeof( workFileHdl ) ); workFd.pVolDesc = pVolDesc; workFd.pFileHdl = &workFileHdl; workFd.curSec = pLnPtr->sector; workFd.pos = pLnPtr->offset; workFileHdl.startClust = NONE; /* don't care */ if( workFd.curSec < pVolDesc->dataStartSec ) { /* old root */ workFd.nSec = pVolDesc->dataStartSec - workFd.curSec; } else if( pVolDesc->pFatDesc->seek( &workFd, workFd.curSec, 0 ) == ERROR ) { assert( FALSE ); return ERROR; } /* get number of entries per long name */ if( nEnt == 0 ) { if( cbioBytesRW(pVolDesc->pCbio, workFd.curSec, OFFSET_IN_SEC( pVolDesc, workFd.pos ), (addr_t)dirent, DOS_DIRENT_STD_LEN, CBIO_READ, &cookie ) == ERROR ) { return ERROR; } assert( dirent[ pDirDesc->deDesc.atrribOff ] == DOS_ATTR_VFAT ); nEnt = ( *dirent & VFAT_ENTNUM_MASK ) + 1 /* include alias */; } /* mark all directory entries */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -