📄 dosvdirlib.c
字号:
/* dosVDirLib.c - MS-DOS VFAT-style Long File names dir handler */ /* Copyright 1999-2002 Wind River Systems, Inc. *//*modification history--------------------01p,10dec01,jkf SPR#72039, various fixes from Mr. T. Johnson.01o,09nov01,jkf SPR#70968, chkdsk destroys boot sector01n,21aug01,jkf SPR#69031, common code for both AE & 5.x.01m,06mar01,jkf SPR#34704, rootNSec calculation must round up.01n,01aug00,dat SPR 31480, directory cluster corruption fix (neeraj)01l,07mar00,jkf Corrected pentium specific compiler warning "using %eax instead of %ax due to l" (source of P6 reg stall?)01k,29feb00,jkf T3 changes, cleanup. 01j,31aug99,jkf changes for new CBIO API.01i,31jul99,jkf moved the fix for SPR#28276 from dosVDirFileCreateInDir() to dosVDirNameEncodeShort because it was only mangling the name in 01g and not creating an alias for it, no SPR.01h,31jul99,jkf default debug global to zero, no SPR.01g,31jul99,jkf Fixed dosVDirFileCreateInDir to mangle 8.3 names containing char-space-char, per MS compatability. MS Scandisk and Norton Disk Doctor stops reporting a false orphaned LFN which they repair by removing it. SPR#2827601f,31jul99,jkf T2 merge, tidiness & spelling.01e,07dec98,lrn minor Show output cosmetics01d,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 review doc01a,18jan98,vld written,*//*DESCRIPTIONThis library is part of dosFsLib and is designed to handle theVFAT "long filename" standard disk directory structure.VFAT is the file name format initially introduced with OS/2 operatingsystem, and subsequently adopted by Microsoft in Windows 95 and NToperating systems for FAT-based file systems.With this format, every file has a Long Name which occupies a number ofdirectory entries, and a short file name which adheres to the vintageMS-DOS file naming conventions. The later are called aliases.This handler performs its lookup only by file long names, not by aliases,in other words, the aliases, are provided only for data interchange withMicrosoft implementations of FAT, and are ignored otherwise.Aliases, that are created for long file names are Windows95/98 compatible,that means, they are readable from Windows applications, but they arenot produced from the corresponding long file name.In this implementation the alias is made of numbers to ensure thatevery alias is unique in its directory without having to scan the entiredirectory. This ensure determinism.Therefore if a volume written with this handler is every transported toan old MS-DOS system or comparable implementation of dosFs,which only accepts vintage 8.3 file names, the names of files will notbe readily associated with their original names, and thus practicallyunusable. The goal was to ensure determinism and file safety.Uppercase 8.3 filename that follow strict 8.3 rules such as "UPPERFIL.TXT" will not be stored in a long filename. Lowercase 8.3 Filenames such as "Upperfil.txt" will have a readablealias created of "UPPERFIL.TXT" Lowercase 8.3 Filenames such as "File " will have an alias created of "FILE ".Filenames with a sequence of char, space, char strings. Such as "3D Pipes.scr" will also have a munged alias created akin to "3~999997".The routine dosVDirInit() routine has to be called once to install this handler into dosFsLib. Once that has been done this directoryhandler will be automatically mounted for each new DOS volume being mounted and containing VFAT or early DOS directory structure.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 */#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) <= dosVDirDebug ) { \ 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) <= dosVDirDebug ) \ 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) <= dosVDirDebug ) \ 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 */#define VFAT_MAX_ENT ( (DOS_VFAT_NAME_LEN + CHAR_PER_VENTRY - 1) \ / CHAR_PER_VENTRY ) /* max directory entries required */ /* to store VFAT long name */#define MAX_VFAT_FULL_DIRENT ( DOS_DIRENT_STD_LEN * (VFAT_MAX_ENT + 1) ) /* max space of long name + alias */ /* may occupy on disk */#define CHAR_PER_VENTRY 13 /* num of characters of long name */ /* encoded within directory entry */#define VFAT_ENTNUM_MASK 0x1f /* mask of "entry number within */ /* long name" field */ #define DOS_VFAT_CHKSUM_OFF 13#define DOS_ATTR_VFAT 0x0f /* value of attribute field for */ /* directory entries, that encodes */ /* VFAT long name *//* special characters */#define DOS_VLAST_ENTRY 0x40 /* last entry in long name representation *//* special function argument value */#define DH_ALLOC (1<<7) /* add cluster to directory chain */#define PUT_CURRENT (1<<0) /* store currently pointed directory entry */#define PUT_NEXT (1<<1) /* store next directory entry *//* macros *//* typedefs */typedef enum {RD_FIRST, RD_CURRENT, RD_NEXT, FD_ENTRY} RDE_OPTION; /* function argument */typedef enum {STRICT_SHORT, NOT_STRICT_SHORT, NO_SHORT} SHORT_ENCODE; /* function argument */typedef struct DOS_VDIR_DESCR /* directory handler's part of */ /* volume descriptor */ { DOS_DIR_PDESCR genDirDesc; /* generic descriptor */ } DOS_VDIR_DESCR;typedef DOS_VDIR_DESCR * DOS_VDIR_DESCR_ID;/* globals */unsigned int dosVDirDebug = 0;/* locals *//* positions of filename characters encoding within VFAT directory entry */LOCAL const u_char chOffsets[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };/* 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{|}~|" ;#ifdef ERR_SET_SELF/******************************************************************************** errnoSetOut - put error message** This routine is called instead errnoSet during debugging.*/static VOID errnoSetOut(char * file, int line, const char * str, int errCode ) { if( errCode != OK && strcmp( str, "errnoBuf" ) != 0 ) printf( " %s : line %d : %s = %p, task %p\n", file, line, str, (void *)errCode, (void *)taskIdSelf() ); errno = errCode; }#endif /* ERR_SET_SELF *//***************************************************************************** dosVDirFillFd - fill file descriptor for directory entry.** RETURNS: N/A.*/LOCAL void dosVDirFillFd ( DOS_FILE_DESC_ID pFd, /* dos file descriptor to fill */ u_char * pDirEnt, /* directory entry from disk */ DIRENT_PTR_ID pLnPtr /* start of long name */ ) { 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 == 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; pDirHdl->lnSector = 0; pDirHdl->lnOffset = 0; 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; /* long name ptr */ if( pLnPtr != NULL ) { pDirHdl->lnSector = pLnPtr->sector; pDirHdl->lnOffset = pLnPtr->offset; } else /* just a short name */ { pDirHdl->lnSector = 0; pDirHdl->lnOffset = 0; } 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 ); } DBG_MSG( 100, "StartCluster = %u = %p, size = %lu\n", pFd->pFileHdl->startClust, (void *)pFd->pFileHdl->startClust, (u_long)pFd->pFileHdl->size & 0xffffffff ,0,0,0,0,0); 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; } /* dosVDirFillFd() *//***************************************************************************** dosVDirRewindDir - 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 dosVDirRewindDir ( 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 ); } } /* dosVDirRewindDir() */ /***************************************************************************** dosVDirPathParse - parse a full pathname into an array of names.** This routine is similar to pathParse(), but on the contrary 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 * correspondence 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -