📄 dosdiroldlib.c
字号:
/* dosDirOldLib.c - MS-DOS old style names dir handler */ /* Copyright 1999-2002 Wind River Systems, Inc. *//*modification history--------------------01j,29apr02,jkf SPR#72255, upon file creation, set the create, modification, and access time fields to match creation rather than using the epoch (0).01i,10dec01,jkf SPR#72039, various fixes from Mr. T. Johnson.01h,21aug01,jkf SPR#69031, common code for both AE & 5.x.01g,06mar01,jkf SPR#34704, rootNSec calculation must round up.01f,29feb00,jkf T3 merge01e,31jul99,jkf T2 merge, tidiness & spelling.01d,22nov98,vld all offsets of directory entry changed to be counted in absolute offset from parent directory start01c,28sep98,vld gnu extensions dropped from DBG_MSG/ERR_MSG macros01b,02jul98,lrn doc review01a,18jan98,vld written*//*DESCRIPTIONThis library is part of dosFsLib and is designed to handlethe DOS4.0 standard disk directory structure as well asvxWorks proprietary long names in case sensitive manner.File names in DOS4.0 are composed of a 8 characters name and3 characters extension separated by dot character.They are stored on disk in uppercase mode, and name lookupis case insensitive. New VFAT file name standard alsosupports DOS4.0 directory structure, and if both handlers(this one and dosVDirLib) are installed, VFAT handler take precedence,and will be used for such a volume by default.VxWorks proprietary long names are composed of up to 40 charactersand are fully case sensitive. Also, files with length greater, than4GB can be stored on the volume is formatted with VxWorks proprietarylong names directory structure.Routine dosDirOldLibInit() has to be called once to install thisinto dosFsLib directory handlers list. Once it has been done this directoryhandler will be automatically mounted on each new appropriate volumebeing mounted.SEE ALSO:dosFsLib.*//* includes */#include "vxWorks.h"#include "private/dosFsVerP.h"#include "stat.h"#include "dirent.h"#include "time.h"#include "stdio.h"#include "ctype.h"#include "taskLib.h"#include "stdlib.h"#include "string.h"#include "semLib.h"#include "logLib.h"#include "errnoLib.h"#include "time.h"#include "utime.h"#include "memLib.h"#include "private/dosFsLibP.h"#include "private/dosDirLibP.h"/* defines *//* macros */#undef DBG_PRN_STR#undef DBG_MSG#undef ERR_MSG#undef NDEBUG #ifdef DEBUG# undef LOCAL# define LOCAL# undef ERR_SET_SELF# define ERR_SET_SELF# define DBG_PRN_STR( lvl, fmt, pStr, len, arg ) \ { if( (lvl) <= dosDirOldDebug ) { \ char cBuf = ((char *)(pStr))[len]; \ (pStr)[len] = EOS; \ printErr( (fmt),(pStr),(arg) ); \ ((char *)(pStr))[len] = cBuf; } }# define DBG_MSG( lvl, fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 ) \ { if( (lvl) <= dosDirOldDebug ) \ printErr( "%s : %d : " fmt, \ __FILE__, __LINE__, arg1,arg2, \ arg3,arg4,arg5,arg6,arg7,arg8 ); }# define ERR_MSG( lvl, fmt, a1,a2,a3,a4,a5,a6 ) \ { logMsg( __FILE__ " : " fmt, (int)(a1), (int)(a2), \ (int)(a3), (int)(a4), (int)(a5), (int)(a6) ); }#else /* NO DEBUG */# define NDEBUG# define DBG_PRN_STR( lvl, fmt, pStr, len, arg ) {}# define DBG_MSG(lvl,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) {}# define ERR_MSG( lvl, fmt, a1,a2,a3,a4,a5,a6 ) \ { if( (lvl) <= dosDirOldDebug ) \ logMsg( __FILE__ " : " fmt, (int)(a1), (int)(a2), \ (int)(a3), (int)(a4), (int)(a5), (int)(a6) ); }#endif /* DEBUG */ #include "assert.h"#ifdef ERR_SET_SELF# define errnoSet( err ) errnoSetOut( __FILE__, __LINE__, #err, (err) )#endif /* ERR_SET_SELF *//* vxWorks long names specific *//* typedefs */typedef enum {RD_FIRST, RD_CURRENT, RD_NEXT, FD_ENTRY} RDE_OPTION; /* function argument */typedef struct DOS_DIROLD_DESC /* directory handler's part of */ /* volume descriptor */ { DOS_DIR_PDESCR genDirDesc; /* generic descriptor */ } DOS_DIROLD_DESC;typedef DOS_DIROLD_DESC * DOS_DIROLD_DESC_ID;/* globals */int dosDirOldDebug = 1;/* locals *//* valid filename characters table ('|' is invalid character) */static const u_char shortNamesChar[] = /* 0123456789abcdef */ "||||||||||||||||" "||||||||||||||||" " !|#$%&'()|||-||" "0123456789||||||" "@ABCDEFGHIJKLMNO" "PQRSTUVWXYZ|||^_" "`ABCDEFGHIJKLMNO" "PQRSTUVWXYZ{|}~|" , longNamesChar[] = /* 0123456789abcdef */ "||||||||||||||||" "||||||||||||||||" " !|#$%&'()|+,-.|" "0123456789|;|=||" "@ABCDEFGHIJKLMNO" "PQRSTUVWXYZ[|]^_" "`abcdefghijklmno" "pqrstuvwxyz{|}~|" ;/* forward declarations */#ifdef ERR_SET_SELF/******************************************************************************** errnoSetOut - put error message** This routine is called instead errnoSet during debugging.*/static VOID errnoSetOut(char * pFile, int line, const char * pStr, int errCode ) { if( errCode != OK && strcmp( str, "errnoBuf" ) != 0 ) printf( " %s : line %d : %s = %p, task %p\n", pFile, line, pStr, (void *)errCode, (void *)taskIdSelf() ); errno = errCode; }#endif /* ERR_SET_SELF */ /***************************************************************************** dosDirOldFillFd - fill file descriptor for directory entry.** RETURNS: N/A.*/LOCAL void dosDirOldFillFd ( DOS_FILE_DESC_ID pFd, /* dos file descriptor to fill */ u_char * pDirEnt /* directory entry from disk */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; DOS_DIR_HDL_ID pDirHdl = (void *)&(pFd->pFileHdl->dirHdl); DIRENT_DESCR_ID pDeDesc; pDeDesc = &pDirDesc->deDesc; if( pDirEnt == (u_char *) NULL ) /* root directory */ { DBG_MSG( 600, "root directory\n", 0,0,0,0,0,0,0,0 ); ROOT_SET( pFd ); /* via <parDirStartCluster> field */ pFd->curSec = pDirDesc->dirDesc.rootStartSec; pFd->nSec = pDirDesc->dirDesc.rootNSec; pFd->pos = 0; pFd->pFileHdl->attrib = DOS_ATTR_DIRECTORY; pFd->pFileHdl->startClust = pDirDesc->rootStartClust; pDirHdl->sector = NONE; pDirHdl->offset = NONE; pFd->cbioCookie = (cookie_t) NULL; pDirHdl->cookie = (cookie_t) NULL; goto rewind; } /* at the beginning fill directory handle using file descriptor */ pDirHdl->parDirStartCluster = pFd->pFileHdl->startClust; pDirHdl->sector = pFd->curSec; pDirHdl->offset = pFd->pos; pDirHdl->cookie = pFd->cbioCookie; pFd->cbioCookie = (cookie_t) NULL; /* disassemble directory entry */ pFd->pos = 0; pFd->curSec = 0; pFd->nSec = 0; pFd->pFileHdl->attrib = *(pDirEnt + pDeDesc->atrribOff); pFd->pFileHdl->startClust = START_CLUST_DECODE( pFd->pVolDesc, pDeDesc, pDirEnt ); pFd->pFileHdl->size = DISK_TO_VX_32(pDirEnt + pDeDesc->sizeOff); if( pDeDesc->extSizeOff != (u_char) NONE ) { pFd->pFileHdl->size += EXT_SIZE_DECODE( pDeDesc, pDirEnt ); } rewind: DBG_MSG( 600, "pFd = %p " "dir hdl (sec-of-par = %u sector = %u offset = %u)\n" "pFileHdl = %p " "(startClust = %u size = %lu attr = %p)\n", pFd, pDirHdl->parDirStartCluster, pDirHdl->sector, pDirHdl->offset, pFd->pFileHdl, pFd->pFileHdl->startClust, pFd->pFileHdl->size, (void *)((int)pFd->pFileHdl->attrib) ); /* * cause FAT to start from start cluster and * get start contiguous block */ bzero( (char *)&pFd->fatHdl, sizeof( pFd->fatHdl ) ); return; } /* dosDirOldFillFd() *//***************************************************************************** dosDirOldRewindDir - rewind directory pointed by pFd.** This routine sets current sector in pFd to directory start sector* and current position (offset in sector) to 0.** RETURNS: N/A.*/LOCAL void dosDirOldRewindDir ( DOS_FILE_DESC_ID pFd /* dos file descriptor to fill */ ) { DOS_DIR_PDESCR_ID pDirDesc = (void *)pFd->pVolDesc->pDirDesc; pFd->pos = 0; pFd->nSec = 0; pFd->curSec = 0; /* for FAT32 curSec = rootNSec = 0 */ if( IS_ROOT( pFd ) && pDirDesc->dirDesc.rootNSec != 0 ) { pFd->curSec = pDirDesc->dirDesc.rootStartSec; pFd->nSec = pDirDesc->dirDesc.rootNSec; return; } /* regular file or FAT32 root */ /* * cause FAT to start from start cluster and * get start contiguous block */ if( pFd->pVolDesc->pFatDesc->seek( pFd, FH_FILE_START, 0 ) == ERROR ) { assert( FALSE ); } } /* dosDirOldRewindDir() */ /***************************************************************************** dosDirOldPathParse - parse a full pathname into an array of names.** This routine is similar to pathParse(), except it does not * allocate additional buffers nor changes the path string.** Parses a path in directory tree which has directory names* separated by '/' or '\\'s. It fills the supplied array of* structures with pointers to directory and file names and * corresponding name length.** All occurrences of '//', '.' and '..'* are right removed from path. All tail dots and spaces are broken from* each name, that is name like "abc. . ." is treated as just "abc".** For instance, "/usr/vw/data/../dir/file" gets parsed into** .CS* namePtrArray* |---------|* ---------------------------o |* | | 3 |* | |---------|* | -----------------------o |* | | | 2 |* | | |---------|* | | ------------o |* | | | | 3 |* | | | |---------|* | | | --------o |* | | | | | 4 |* | | | | |---------|* v v v v | NULL |* | | | | | 0 |* | | | | |---------|* v v v v * |------------------------|* |usr/vw/data/../dir/file |* |-------\-----/----------|* ignored** .CE** RETURNS: number of levels in path.** ERRNO:* S_dosFsLib_ILLEGAL_PATH* S_dosFsLib_ILLEGAL_NAME*/LOCAL int dosDirOldPathParse ( DOS_VOLUME_DESC_ID pVolDesc, u_char * path, PATH_ARRAY_ID pnamePtrArray ) { FAST u_int numPathLevels; FAST u_char * pName; FAST u_char * pRegChar; /* last not DOT and not SPACE char */ pnamePtrArray[0].pName = NULL; /* go throw path string from left to right */ pName = path; numPathLevels = 0; while( *pName != EOS ) /* there is 'break' in loop also */ { /* pass slashes */ if( *pName == SLASH || *pName == BACK_SLASH ) { pName++; continue; } /* process special names ( "." ".." ) */ if( *pName == DOT ) { /* "/./" - ignore "current directory" */ if( *(pName + 1) == EOS || *(pName + 1) == SLASH || *(pName + 1) == BACK_SLASH ) { pName ++; continue; } /* "/../" - goto one level back */ if( (*(pName + 1) == DOT) && ( *(pName + 2) == EOS || *(pName + 2) == SLASH || *(pName + 2) == BACK_SLASH ) ) { if( numPathLevels > 0 ) numPathLevels --; pName +=2; continue; } } /* if( *pName == DOT ) */ /* regular name: insert it into array */ if( numPathLevels >= DOS_MAX_DIR_LEVELS ) break; /* max level overloaded */ pnamePtrArray[numPathLevels].pName = pName; pnamePtrArray[numPathLevels + 1].pName = NULL; pRegChar = NULL; while( *pName != SLASH && *pName != BACK_SLASH && *pName != EOS ) { if( *pName != DOT || *pName == SPACE ) pRegChar = pName; pName++; } /* name can not contain only dots */ if( pRegChar == NULL ) { errnoSet( S_dosFsLib_ILLEGAL_NAME ); return ERROR; } pnamePtrArray[numPathLevels].nameLen = pRegChar + 1 - pnamePtrArray[numPathLevels].pName; numPathLevels++; } /* while( *pName != EOS ) */ /* check result */ if( *pName != EOS ) /* path termination has not been reached */ { errnoSet( S_dosFsLib_ILLEGAL_PATH ); return ERROR; }#ifdef DEBUG DBG_MSG( 600, "path: %s, result: \n", path ,0,0,0,0,0,0,0); pName = (void *)pnamePtrArray; for( ; pnamePtrArray->pName != NULL; pnamePtrArray++ ) { int i = pnamePtrArray - (PATH_ARRAY_ID)pName + 1; DBG_PRN_STR( 600, "%s : %d", pnamePtrArray->pName, pnamePtrArray->nameLen, i ); } DBG_PRN_STR(600, "\b\b \n", "", 0, 0);#endif /* DEBUG */ return numPathLevels; } /* dosDirOldPathParse() */ /***************************************************************************** dosDirOldTDDecode - decode time-date field from disk format.** This routine decodes required date-time field in the directory* entry into time_t format.* * Parameter which defines which time field to decode. It* can be one of:* DH_TIME_CREAT, DH_TIME_MODIFY, DH_TIME_ACCESS.** RETURNS: time in time_t format.**/LOCAL time_t dosDirOldTDDecode ( DOS_DIR_PDESCR_ID pDirDesc, u_char * pDirent, /* directory entry buffer */ u_int which /* what field to decode: one of */ /* DH_TIME_CREAT, DH_TIME_MODIFY or DH_TIME_ACCESS */ ) { struct tm tm = {0}; /* broken down time buffer */ UINT16 dtBuf; /* 16-bit buffer */ u_char tOff = 0, dOff = 0; /* field offset */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -