📄 dosvdirlib.c
字号:
} /* check result */ if( status == ERROR ) { goto ret; } status = ERROR; /* *pDiskName == LAST_DIRENT */ if( IS_ROOT( pFd ) && nEntries + nEntInName > pDirDesc->rootMaxEntries ) { goto ret; } /* will create new entry on this place, if required */ if( pFreeEnt->sector == 0 ) { pFreeEnt->deNum = nEntries; pFreeEnt->sector = pFd->curSec; pFreeEnt->offset = pFd->pos; }ret: if( status != ERROR ) /* file found; fill file descriptor */ { dosVDirFillFd( pFd, pDiskName + aliasOff, &lnPtr ); } *pFreeEntLen = freeChankLen; /* Return numbers of free ents */ semGive( pDirDesc->bufSem ); return status; } /* dosVDirLkupInDir() */ /***************************************************************************** dosVDirAliasCreate - create alias for long file name.** This routine takes 1 first byte of file name and expands it* with ~ and 6 decimal digits of sequence number of alias's* entry in directory. Then it takes three characters of long name* following last dot symbol and puts them to alias extension.** RETURNS: N/A.*/LOCAL void dosVDirAliasCreate ( DOS_DIR_PDESCR_ID pDirDesc, PATH_ARRAY_ID pNamePtr, u_char * pAlias, /* dst alias */ u_int entNum /* empty entry in directory */ ) { u_char * pSrc; /* loop pointer to src name */ u_char * pDst; /* loop pointer to dst alias */ char entNumBuf[ DOS_STDNAME_LEN + DOS_STDEXT_LEN + 1 ]; entNum = 1000000 - entNum % 1000000; bfill( (char *)pAlias, DOS_STDNAME_LEN + DOS_STDEXT_LEN, SPACE ); pSrc = pNamePtr->pName; pDst = pAlias; /* pass top dots in name */ for( ; *pSrc == DOT; pSrc ++ ); assert( *pSrc != EOS ); for( ; *pSrc != DOT && pSrc != pNamePtr->pName + pNamePtr->nameLen && pDst != pAlias + DOS_STDNAME_LEN; pSrc++, pDst++ ) { if( dosVDirCharEncode( pSrc, pDst, shortNamesChar ) == ERROR ) break; } /* encode directory entry number */ sprintf( entNumBuf, "%c%u", TILDA, entNum ); entNum = strlen( entNumBuf ); if( pDst > pAlias + DOS_STDNAME_LEN - entNum ) pDst = pAlias + DOS_STDNAME_LEN - entNum; bcopy( entNumBuf, (char *)pDst, entNum ); /* === extension === */ pDst = pAlias + DOS_STDNAME_LEN; /* find last DOT */ for( pSrc = pNamePtr->pName + pNamePtr->nameLen - 1; pSrc != pNamePtr->pName && *pSrc != DOT; pSrc -- ); /* encode 3 extension characters */ if( pSrc == pNamePtr->pName ) return; /* no extension */ /* *pSrc == DOT */ for( pSrc++; pDst != pAlias + DOS_STDNAME_LEN + DOS_STDEXT_LEN && pSrc != pNamePtr->pName + pNamePtr->nameLen; pSrc++, pDst++ ) { if( dosVDirCharEncode( pSrc, pDst, shortNamesChar ) == ERROR ) { *pDst = SPACE; break; } } DBG_PRN_STR( 700, "result: %s\n", pAlias, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen,0 ); } /* dosVDirAliasCreate() */#ifdef __unused__/***************************************************************************** dosVDirFullDeUpdate - update fields in long name directory entries.** This routine deletes full long name entry or updates.** RETURNS: OK or ERROR if disk write error occurred.*/LOCAL STATUS dosVDirFullDeUpdate ( DOS_FILE_DESC_ID pFd, /* directory descriptor */ u_int operation /* DH_DELETE */ ) { DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; DOS_FILE_DESC workFd = {0}; /* temporary file descriptor */ DOS_FILE_HDL workFileHdl; /* temporary file handle */ UINT32 value = 0; /* start cluster number in disk format */ STATUS st = ERROR; u_char nEnt; /* entries per long name */ u_char fieldOff = 0, fieldLen = 0; if( operation == DH_DELETE ) { fieldOff = 0; fieldLen = 1; *(u_char *)&value = DOS_DEL_MARK; } else { assert( FALSE ); } /* init file descriptor */ bzero( (char *)&workFileHdl, sizeof( workFileHdl ) ); workFd.pVolDesc = pVolDesc; workFd.pFileHdl = &workFileHdl; workFd.pFileHdl->startClust = pFd->pFileHdl->dirHdl.parDirStartCluster; /* get number of entries per long name */ if( pFd->pFileHdl->dirHdl.lnSector == 0 ) { /* short name only */ nEnt = 0; workFd.curSec = pFd->pFileHdl->dirHdl.sector; workFd.pos = pFd->pFileHdl->dirHdl.offset; } else /* long name */ { workFd.curSec = pFd->pFileHdl->dirHdl.lnSector; workFd.pos = pFd->pFileHdl->dirHdl.lnOffset; if( cbioBytesRW( pVolDesc->pCbio, workFd.curSec, OFFSET_IN_SET( pVolDesc, workFd.pos ), &nEnt, 1, CBIO_READ, NULL ) == ERROR ) { return ERROR; } if( (nEnt & DOS_VLAST_ENTRY) == 0 ) { ERR_MSG(10, "Long name terminating flag missing\n", 0,0,0,0 ); return ERROR; } } 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; } /* update all directory entries */ for( nEnt = (nEnt & VFAT_ENTNUM_MASK), (st = dosVDirDeStore( &workFd, fieldOff, fieldLen, &value, PUT_CURRENT )); st != ERROR && nEnt > 0; nEnt -- ) { st = dosVDirDeStore( &workFd, fieldOff, fieldLen, &value, PUT_NEXT ); } return st; } /* dosVDirFullDeUpdate() */#endif /* __unused__ *//***************************************************************************** dosVDirUpdateEntry - set new directory entry contents.** This routine pulls file size, attributes and so on out of* file descriptor and stores it in the correspondence 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.** RETURNS: OK or ERROR if name is invalid or disk access error occurred.**/LOCAL STATUS dosVDirUpdateEntry ( DOS_FILE_DESC_ID pFd, u_int flags, time_t curTime /* time to encode */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; u_char dirent[ DOS_DIRENT_STD_LEN ]; /* directory entry buffer */ curTime = ( curTime == 0 )? time( NULL ) : curTime; /* root directory has not its own entry */ if( IS_ROOT( pFd ) ) { if( (flags & DH_TIME_MODIFY) != 0 ) pDirDesc->rootModifTime = curTime; else assert( (flags & DH_TIME_MODIFY) != 0 ); return OK; } if( flags & DH_DELETE ) /* delete entry */ { DIRENT_PTR dePtr; u_int nEnt = 0; if( pFd->pFileHdl->dirHdl.lnSector == 0 ) { /* short name only */ dePtr.sector = pFd->pFileHdl->dirHdl.sector; dePtr.offset = pFd->pFileHdl->dirHdl.offset; nEnt = 1; } else /* long name */ { dePtr.sector = pFd->pFileHdl->dirHdl.lnSector; dePtr.offset = pFd->pFileHdl->dirHdl.lnOffset; } return dosVDirEntryDel( pFd->pVolDesc, &dePtr, nEnt, TRUE ); } /* get directory entry */ if( dosVDirDirentGet( pFd, dirent, FD_ENTRY ) == ERROR ) return ERROR; /* * encode other fields, but also start cluster, because entire * directory entry will be stored */ START_CLUST_ENCODE( &pDirDesc->deDesc, pFd->pFileHdl->startClust, dirent ); dirent[ pDirDesc->deDesc.atrribOff ] = pFd->pFileHdl->attrib; VX_TO_DISK_32( pFd->pFileHdl->size, dirent + pDirDesc->deDesc.sizeOff ); if( pDirDesc->deDesc.extSizeOff != (u_char) NONE ) { EXT_SIZE_ENCODE( &pDirDesc->deDesc, dirent, pFd->pFileHdl->size ); } dosVDirTDEncode( pDirDesc, dirent, flags, curTime ); /* store directory entry */ return cbioBytesRW( pFd->pVolDesc->pCbio, pFd->pFileHdl->dirHdl.sector, OFFSET_IN_SEC( pFd->pVolDesc, pFd->pFileHdl->dirHdl.offset ), (addr_t)dirent, pDirDesc->deDesc.dirEntSize, CBIO_WRITE, &pFd->pFileHdl->dirHdl.cookie ); } /* dosVDirUpdateEntry *//***************************************************************************** dosVDirFileCreateInDir - create new entry in directory.** This routine creates new directory entry in place of* deleted entry. If no deleted entry large enough found in directory,* additional entry created at the directory tail.** <pFreeEnt> must contain a pointer into an appropriate deleted entry in* the directory or into free space in bottom of the directory.* If <pFreeEnt->sector> eq. to 0 indicates,* that no free entries found in directory and* <pFd> reached directory end. In this case one more cluster is* added to directory chain and new file is created in it.** RETURNS: OK or ERROR if new entry can not be created.** ERRNO:* S_dosFsLib_DIR_READ_ONLY* S_dosFsLib_INVALID_PARAMETER* S_dosFsLib_ROOT_DIR_FULL* */LOCAL STATUS dosVDirFileCreateInDir ( DOS_FILE_DESC_ID pFd, /* directory descriptor */ PATH_ARRAY_ID pNamePtr, u_int options, /* creat flags */ DIRENT_PTR_ID pFreeEnt, /* empty entry in directory */ int freeEntLen /* Number of contig empty entries in directory */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; DOS_DIR_HDL_ID pDirHdl = (void *)&(pFd->pFileHdl->dirHdl); cookie_t cookie; /* temp buffer */ u_char * dirent = pDirDesc->nameBuf; /* directory entry buffer */ u_char * alias; /* long name alias */ u_int whichEntry; u_int allocFlag; int numEnt; /* directory entries per full VFAT entry */ int i; SHORT_ENCODE shortNameEncode = STRICT_SHORT; /* encodding of short name strategy */ STATUS retStat = ERROR; u_char chkSum = 0; /* alias checksum */ u_char parentIsRoot = 0; /* creation in root */ /* check permissions */ if( pFd->pFileHdl->attrib & DOS_ATTR_RDONLY ) { errnoSet( S_dosFsLib_DIR_READ_ONLY ); return ERROR; } /* only file and directory can be created */ if( !( S_ISREG( options ) || S_ISDIR( options ) ) ) { errnoSet( S_dosFsLib_INVALID_PARAMETER ); return ERROR; } if( IS_ROOT( pFd ) ) parentIsRoot = 1; /* protect buffers */ if( semTake( pDirDesc->bufSem, WAIT_FOREVER ) == ERROR ) return ERROR; /* check/encode file name */ numEnt = dosVDirNameEncode( pDirDesc, pNamePtr, dirent, &shortNameEncode ); if( numEnt == ERROR ) goto ret; /* set alias pointer */ alias = dirent + ( numEnt - 1 ) * DOS_DIRENT_STD_LEN; /* * if name can not be directly encoded as short, * create special alias. */ if ( *alias == EOS ) { assert( alias != dirent ); dosVDirAliasCreate( pDirDesc, pNamePtr, alias, pFreeEnt->deNum + numEnt ); } /* encode time fields */ dosVDirTDEncode( pDirDesc, alias, DH_TIME_CREAT | DH_TIME_MODIFY | DH_TIME_ACCESS, time( NULL ) ); /* alias checksum */ chkSum = dosVDirChkSum( alias ); /* use empty entry, that was found during path lkup */ if( pFreeEnt->sector != 0 ) { /* point file descriptor onto the deleted entry position */ if( IS_ROOT( pFd ) && pDirDesc->rootMaxEntries < (u_int)(-1) ) { pFd->nSec += pFd->curSec - pFreeEnt->sector; pFd->curSec = pFreeEnt->sector; } else if( pF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -