📄 dosdiroldlib.c
字号:
** RETURNS: OK or ERROR if name is invalid or disk access error* occurred.**/LOCAL STATUS dosDirOldUpdateEntry ( 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_VX_DIRENT_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; } /* get directory entry */ if( dosDirOldDirentGet( pFd, dirent, FD_ENTRY ) == ERROR ) return ERROR; if( flags & DH_DELETE ) /* delete entry */ { *dirent = DOS_DEL_MARK; goto store; } /* encode other fields */ dirent[ pDirDesc->deDesc.atrribOff ] = pFd->pFileHdl->attrib; START_CLUST_ENCODE( &pDirDesc->deDesc, pFd->pFileHdl->startClust, dirent ); 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 ); } dosDirOldTDEncode( pDirDesc, dirent, flags, curTime ); store: /* 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 ); } /* dosDirOldUpdateEntry *//***************************************************************************** dosDirOldFileCreateInDir - create new entry in directory.** This routine creates new directory entry in place of* deleted entry. If no deleted entry found in directory,* additional entry created at the directory tail.** <pFreeEnt> contains pointer onto a deleted entry in* directory or onto free space in last directory* cluster, that have been already allocated. If <pFreeEnt->sector> is 0,* suppose, that no unallocated entry exists in directory and* <pFd> reached directory FAT chain end. In this case one more cluster is* connected to directory chain and new entry 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 dosDirOldFileCreateInDir ( DOS_FILE_DESC_ID pFd, /* directory descriptor */ PATH_ARRAY_ID pNamePtr, u_int creatOpt, /* creat flags */ DIRENT_PTR_ID pFreeEnt /* empty entry 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[ DOS_VX_DIRENT_LEN ] = {0}; /* directory entry buffer */ u_char dirEntSize; u_char parentIsRoot = 0; /* creation in root */ dirEntSize = pDirDesc->deDesc.dirEntSize; /* 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( creatOpt ) || S_ISDIR( creatOpt ) ) ) { errnoSet( S_dosFsLib_INVALID_PARAMETER ); return ERROR; } if( IS_ROOT( pFd ) ) parentIsRoot = 1; /* check/encode file name */ if( dosDirOldNameEncode( pDirDesc, pNamePtr, dirent ) == ERROR ) return ERROR; /* use empty entry, that was found during path lkup */ if( pFreeEnt->sector == 0 ) /* no free entries in directory */ { if( IS_ROOT( pFd ) && pDirDesc->rootMaxEntries < (u_int)(-1) ) { errnoSet( S_dosFsLib_ROOT_DIR_FULL ); return ERROR; } /* allocate one more cluster */ if( dosDirOldClustAdd( pFd ) == ERROR ) return ERROR; pFreeEnt->sector = pFd->curSec; pFreeEnt->offset = pFd->pos; } /* correct parent directory modification date/time */ dosDirOldUpdateEntry( pFd, DH_TIME_MODIFY, time( NULL ) ); /* --- create new entry --- */ /* at the beginning create generic (file) entry */ dosDirOldTDEncode(pDirDesc, dirent, (DH_TIME_CREAT | DH_TIME_MODIFY | DH_TIME_ACCESS), time( NULL ) ); cookie = pDirHdl->cookie; /* backup cbio qsearch cookie */ /* * point file descriptor on the new entree's position and * fill file descriptor for new file */ pFd->curSec = pFreeEnt->sector; pFd->pos = pFreeEnt->offset; dosDirOldFillFd( pFd, dirent ); DBG_MSG( 400, "create %s at: sector = %u offset = %u\n", ( S_ISREG( creatOpt )? "FILE" : "DIRECTORY" ), pFreeEnt->sector, pFreeEnt->offset ,0,0,0,0,0); DBG_PRN_STR( 400, "\tname: %s\n", dirent, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen,0 ); /* write f i l e entry to disk */ if( S_ISREG( creatOpt ) ) { return cbioBytesRW( pFd->pVolDesc->pCbio, pFreeEnt->sector, OFFSET_IN_SEC( pFd->pVolDesc, pFreeEnt->offset ), (addr_t)dirent, dirEntSize, CBIO_WRITE, &cookie ); } /* --- now we deal with directory --- */ *(dirent + pDirDesc->deDesc.atrribOff) = DOS_ATTR_DIRECTORY; pFd->pFileHdl->attrib = DOS_ATTR_DIRECTORY; /* * for directory we have to create two entries: "." and ".." * start - allocate cluster and init it in structure. */ if( dosDirOldClustAdd( pFd ) == ERROR ) return ERROR; START_CLUST_ENCODE( &pDirDesc->deDesc, pFd->pFileHdl->startClust, dirent ); /* * second - init directory entry for "."; * it is similar to directory entry itself, except name */ bfill( (char *)dirent, pDirDesc->deDesc.nameLen + pDirDesc->deDesc.extLen, SPACE ); *dirent = DOT; if( cbioBytesRW( pFd->pVolDesc->pCbio, pFd->curSec, 0, (addr_t)dirent, dirEntSize, CBIO_WRITE, &pDirHdl->cookie ) == ERROR ) { return ERROR; } pFd->pos += dirEntSize; if( OFFSET_IN_SEC( pFd->pVolDesc, pFd->pos ) == 0 ) { pFd->nSec --; pFd->curSec ++; } /* if only one directory entry can be stored in cluster */ if( pFd->nSec == 0 ) { if( dosDirOldClustAdd( pFd ) == ERROR ) return ERROR; } /* third - creat ".." entry, that points to the parent directory */ if( parentIsRoot ) { START_CLUST_ENCODE( &pDirDesc->deDesc, 0, dirent ); } else { START_CLUST_ENCODE( &pDirDesc->deDesc, pDirHdl->parDirStartCluster, dirent ); } *(dirent + 1) = DOT; if( cbioBytesRW( pFd->pVolDesc->pCbio, pFd->curSec, OFFSET_IN_SEC( pFd->pVolDesc, pFd->pos ), (addr_t)dirent, dirEntSize, CBIO_WRITE, &pDirHdl->cookie ) == ERROR ) { return ERROR; } /* now finish directory entry initialization */ dosDirOldRewindDir( pFd ); /* rewind directory */ dosDirOldNameEncode( pDirDesc, pNamePtr, dirent ); START_CLUST_ENCODE( &pDirDesc->deDesc, pFd->pFileHdl->startClust, dirent ); if( cbioBytesRW( pFd->pVolDesc->pCbio, pDirHdl->sector, OFFSET_IN_SEC( pFd->pVolDesc, pDirHdl->offset ), (addr_t)dirent, dirEntSize, CBIO_WRITE, &pDirHdl->cookie ) == ERROR ) { return ERROR; } return OK; } /* dosDirOldFileCreateInDir() */ /***************************************************************************** dosDirOldNameDecode - decode name from directory entry format.** RETURNS: OK or ERROR if no disk entries remain.*/LOCAL void dosDirOldNameDecode ( DOS_DIR_PDESCR_ID pDirDesc, u_char * pDirent, /* directory entry buffer */ u_char * pDstName /* destination for directory name */ ) { u_char * pNameEnd = pDstName; u_char * pDstBuf; /* for debug output */ u_char * pDot = NULL; u_char * pSrc = pDirent; int i, j, nameLen; pDstBuf = pDstName; for( pDot = NULL, nameLen = pDirDesc->deDesc.nameLen, i = 0; i < 2; i++, nameLen = pDirDesc->deDesc.extLen ) { for( j = 0; j < nameLen; j++, pDstName++ ) { *pDstName = *pSrc++; if( *pDstName != SPACE ) pNameEnd = pDstName + 1; } if( pDirDesc->deDesc.extLen == 0 ) /* long name */ break; /* extension */ if( pDot == NULL ) /* separate name and extension */ { pDot = pNameEnd; *pNameEnd++ = DOT; pDstName = pNameEnd; } else if( pDot + 1 == pNameEnd ) { pNameEnd --; /* empty extension - remove dot */ break; } } *pNameEnd = EOS; /* terminate the name */ DBG_MSG( 600, "result: %s\n", pDstBuf ,0,0,0,0,0,0,0); } /* dosDirOldNameDecode() */ /***************************************************************************** dosDirOldReaddir - FIOREADDIR backend.** Optionally this routine fills file descriptor for the encountered entry,* if <pResFd> is not NULL.** RETURNS: OK or ERROR if no disk entries remain.*/LOCAL STATUS dosDirOldReaddir ( DOS_FILE_DESC_ID pFd, /* descriptor of the directory being read */ DIR * pDir, /* destination for directory name */ DOS_FILE_DESC_ID pResFd /* file descriptor to be filled for the */ /* being returned */ /* (if pResFd is not NULL) */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; int readFlag; u_char dirent[ DOS_VX_DIRENT_LEN ]; /* directory entry buffer */ assert( pFd->pFileHdl->attrib & DOS_ATTR_DIRECTORY ); /* check status of directory */ if( (int)pDir->dd_cookie == (-1) ) return ERROR; /* position must be directory entry size aligned */ if( pFd->pos % DOS_STDNAME_LEN != 0 ) { errnoSet( S_dosFsLib_INVALID_PARAMETER ); return ERROR; } readFlag = ( pDir->dd_cookie == 0 )? RD_FIRST : RD_NEXT; do { if( dosDirOldDirentGet( pFd, dirent, readFlag ) == ERROR ) { pDir->dd_cookie = (-1); return ERROR; } readFlag = RD_NEXT; } while( *dirent == DOS_DEL_MARK || (dirent[ pDirDesc->deDesc.atrribOff ] & DOS_ATTR_VOL_LABEL) != 0 ); if( *dirent == LAST_DIRENT ) /* end of directory */ { pDir->dd_cookie = (-1); return ERROR; } /* name decode */ dosDirOldNameDecode( pDirDesc, dirent,(u_char *)pDir->dd_dirent.d_name ); /* fill file descriptor for the entry */ if( pResFd != NULL ) { void * pFileHdl = pResFd->pFileHdl; /* prepare file descriptor contents */ *pResFd = *pFd; pResFd->pFileHdl = pFileHdl; *pResFd->pFileHdl = *pFd->pFileHdl; dosDirOldFillFd( pResFd, dirent ); } pDir->dd_cookie = POS_TO_DD_COOKIE( pFd->pos ); return OK; } /* dosDirOldReaddir() */ /***************************************************************************** dosDirOldPathLkup - lookup for file/dir in tree.** This routine recursively searches directory tree for the <path> and* fills file descriptor for the target entry if successful.* Optionally new entry may be created in accordance with flags* in argument <options>.** DOS4.0 style names are always case insensitive in contrary to* VxLong name, that always are compared case sensitively. So* DOS_O_CASENS is ignored in <options> argument.** <options> : O_CREAT - creat file;* O_CREAT | DOS_ATTR_DIRECTORY - creat directory.* <somth> | DOS_O_CASENS - lkup for name in case sensitive manner (ignored).** RETURNS: OK or ERROR if file not found.** ERRNO:* S_dosFsLib_FILE_NOT_FOUND*/LOCAL STATUS dosDirOldPathLkup ( DOS_FILE_DESC_ID pFd, /* dos file descriptor to fill */ void * path, /* path in tree */ u_int options /* optional creat flags */ ) { PATH_ARRAY namePtrArray [DOS_MAX_DIR_LEVELS + 1]; int numPathLevels; int errnoBuf; /* swap errno */ DIRENT_PTR freeEnt; /* empty (deleted) entry in directory */ u_char dirLevel; /* dynamic directory level counter */ assert( path != NULL ); /* disassemble path */ numPathLevels = dosDirOldPathParse( pFd->pVolDesc, path, namePtrArray ); if( numPathLevels == ERROR ) return ERROR; assert( numPathLevels <= DOS_MAX_DIR_LEVELS ); /* start from root directory */ dosDirOldFillFd( pFd, ROOT_DIRENT ); errnoBuf = errnoGet(); errnoSet( OK ); for( dirLevel = 0; dirLevel < numPathLevels; dirLevel ++ ) { /* only directory can be searched */ if( ! (pFd->pFileHdl->attrib & DOS_ATTR_DIRECTORY) ) break; if( dosDirOldLkupInDir( pFd, namePtrArray + dirLevel, &freeEnt ) == ERROR ) { if( errnoGet() != OK ) /* subsequent error */ return ERROR; break; } } if( errnoGet() == OK ) errnoSet( errnoBuf ); /* check result */ if( dirLevel == numPathLevels ) { return OK; } /* --- file not found --- */ /* only last file in path can be created */ if( dirLevel == numPathLevels - 1 && (options & O_CREAT) ) { if( dosDirOldFileCreateInDir( pFd, namePtrArray + dirLevel,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -