📄 doschklib.c
字号:
/* dosChkLib.c - DOS file system sanity check utility */ /* Copyright 1999-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01o,10nov01,jkf SPR#67890, chkdsk writes to RDONLY device01n,18oct01,jkf warning cleaning.01n,18sep00,nrj Fixed SPR#34108, check the write mode before synchronzing the FAT01m,29feb00,jkf T3 changes01l,31aug99,jkf changes for new CBIO API. Changed date check logic. Added docs for date check. Added global for date check. Default debug global to zero.01k,31jul99,jkf T2 merge, tidiness & spelling.01j,28sep98,vld gnu extensions dropped from DBG_MSG/ERR_MSG macros01i,13oct98,vld fixed message positioning on screen, - '\b' avoided.01h,23sep98,vld added usage of reserved FAT32 copy for data buffering in reduced memory environments, bit map of FAT entries is filled in parallel with 4-byte MAP array in this case01g,23sep98,vld fixed bug of backward time setting01f,23sep98,vld disable FAT mirroring while check disk in progress; synchronize FAT copies after check disk.01e,17sep98,vld FAT copy number argument added to calls of clustValueSet()/clustValueGet();01d,08jul98,vld print64Lib.h moved to h/private directory.01c,08jul98,vld fixed bug in dosFsChkTree() of deletion invalid name entry through other file descriptor.01b,02jul98,lrn review doc and messages01a,18jan98,vld written, preliminary*//*DESCRIPTIONThis library is part of dosFsLib, it manages the Consistency Checkingprocedure, which may be invoked automatically during device mountprocedure, or manual by means of the FIOCHKDSK ioctl.be checked which is managed by that particular handler.Check disk requires temporary buffer large enough to store informationon every FAT entry. Memory requirements can be a problem for FAT32volumes. If no enough available, temporary data is buffered insecond (reserved) FAT copy, that can take extremely long time on a slow processors.The minimum acceptable system time & date is set by the global variable(time_t) dosChkMinDate. If the system time is greater than that value, it is assumed that a hardware clock mechanism is in place and the time setting is honored. If dosChkLib detects that the system is set to an earlier date than dosChkMinDate, the system date will be adjusted to either the most recent date found on the file system volume or the minimum acceptable system time & date, whichever is later. A warning indicicating the new system time is displayed on the console when this occurs.Do not set dosChkMinDate prior to 1980!INTERNAL*//* includes */#include "vxWorks.h"#include "private/dosFsVerP.h"#include "stat.h"#include "time.h"#include "dirent.h"#include "stdio.h"#include "stdlib.h"#include "string.h"#include "errnoLib.h"#include "memLib.h"#include "taskLib.h"#include "time.h"#include "timers.h"#include "tickLib.h"#include "dosFsLib.h"#include "private/print64Lib.h"#include "private/dosFsLibP.h"/* defines *//* macros */#undef DBG_MSG#undef ERR_MSG#undef NDEBUG#ifdef DEBUG# undef LOCAL# define LOCAL# undef ERR_SET_SELF# define ERR_SET_SELF# define DBG_MSG( lvl, fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 ) \ { if( (lvl) <= dosChkDebug ) \ 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_MSG(lvl,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) {}# define ERR_MSG( lvl, fmt, a1,a2,a3,a4,a5,a6 ) \ { if( (lvl) <= dosChkDebug ) \ logMsg( __FILE__ " : " fmt, (int)(a1), (int)(a2), \ (int)(a3), (int)(a4), (int)(a5), (int)(a6) ); }#endif /* DEBUG */#include "assert.h"#define DOSCHKLIB_YEAR_VALUE (((60*60)*24)*365*21)int dosChkDebug = 0;time_t dosChkMinDate = (time_t) DOSCHKLIB_YEAR_VALUE;/* error messages */#define CHK_CROSS_L_START_MSG "\"%s\" is cross-linked on first cluster. "#define CHK_START_MSG "%s - disk check in progress ..."#define CHK_NOT_ROOM_MSG "%s - Not enough room to run check disk.\n"#define CHK_LOST_CHAINS_MSG " - lost chains "#define CHK_DEL_MSG " Entry will be deleted. "#define CHK_REMAIN_MSG "Entry remains intact. "#define CHK_CLUST_VAL "(cluster %lu, value %lu)."#define CHK_SHORT_CHAIN_MSG "\"%s\" file larger then its chain of clusters"#define CHK_BAD_DIR_MSG "\"%s\" directory has invalid structure."#define CHK_DIR_LVL_OVERFL "directory nesting limit reached, \"%s\" skipped"#define CHK_ROOT_CHAIN "%s - Root directory cluster chain is corrupted.\n"#define CHK_ROOT_TRUNC_MSG " Root directory truncated. \n"#define CHK_BAD_NAME "\"%s\" is an illegal name. "#define CHK_FAIL_MSG " Check disk failed. \n"\ " Disk should be formatted.\n"#define CHK_NOT_REPAIRED "%s - Errors detected. "\ "To correct disk structure, please start "\ "check disk with a permission to repair."#define CHK_RESTORE_FREE "Errors detected. "\ "All corrections stored to disk "\ "and lost chains recovered."#define CHK_BAD_START_MSG "\"%s\" has illegal start cluster"#define CHK_CROSS_START_MSG "\"%s\" cross-linked at start"#define CHK_BAD_CHAIN_MSG "\"%s\" has illegal cluster in chain"#define CHK_CROSS_LINK_MSG "\"%s\" cross-linked with another chain"#define CHK_LONG_CHAIN_MSG "\"%s\" too many clusters in file, adjusted."#define CHK_BAD_CLUST_MSG "illegal cluster"#define CHK_NO_ERRORS "%s - Volume is OK "#define START_CLUST_MASK 0x80000000#define LOST_CHAIN_MARK 0xc0000000#define MARK_SET 1#define MARK_GET 2#define IS_BUSY 3#define MARK_BUF_INIT 255/* typedefs *//* check disk status */ typedef enum { CHK_OK=OK, CHK_SIZE_ERROR, CHK_RESTART, CHK_BAD_DIR, CHK_BAD_FILE, CHK_CROSS_LINK, CHK_BAD_CHAIN, CHK_BAD_START, CHK_ERROR=ERROR } CHK_STATUS; /* dosChkMsg() argument */typedef enum { CURRENT_PATH, GET_PATH } MSG_PATH;/* dosChkEntryFind() argument */typedef enum { FIND_BY_CLUST, FIND_BY_NAME } CHK_SEARCH_KEY_TYPE;/* globals *//* locals *//* forward declarations */LOCAL void dosChkChainUnmark ( DOS_FILE_DESC_ID pFd /* pointer to file descriptor */ );LOCAL STATUS dosChkChainStartGet ( DOS_FILE_DESC_ID pFd, /* pointer to file descriptor */ uint32_t entNum, uint32_t * pParDirStartClust, uint32_t * pStartClust );LOCAL CHK_STATUS dosChkChainVerify ( DOS_FILE_DESC_ID pFd /* pointer to file descriptor */ );LOCAL STATUS dosChkLostFind ( DOS_FILE_DESC_ID pFd /* pointer to file descriptor */ );LOCAL STATUS dosChkLostFree ( DOS_FILE_DESC_ID pFd /* pointer to file descriptor */ );/********************************************************************************* dosChkStatPrint - print statistics.** RETURNS: N/A.*/LOCAL void dosChkStatPrint ( DOS_FILE_DESC_ID pFd ) { DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; CHK_DSK_DESC_ID pChkDesc = pFd->pVolDesc->pChkDesc; fsize_t valBuf; if( pVolDesc->chkVerbLevel < (DOS_CHK_VERB_1 >> 8) ) return; /* print statistics */ print64Fine( "\n" " total # of clusters: ", pVolDesc->nFatEnts, "\n", 10 ); print64Fine( " # of free clusters: ", pChkDesc->chkNFreeClusts, "\n", 10 ); print64Fine( " # of bad clusters: ", pChkDesc->chkNBadClusts, "\n", 10 ); valBuf = pChkDesc->chkNFreeClusts; valBuf = ( valBuf * pVolDesc->secPerClust ) << pVolDesc->secSizeShift; print64Mult( " total free space: ", valBuf, "\n", 10 ); valBuf = (fsize_t)pVolDesc->pFatDesc->maxContig( pFd ) << pVolDesc->secSizeShift; print64Fine( " max contiguous free space: ", valBuf, " bytes\n", 10 ); print64Fine( " # of files: ", pChkDesc->chkNFiles, "\n", 10 ); print64Fine( " # of folders: ", pChkDesc->chkNDirs, "\n", 10 ); print64Mult( " total bytes in files: ", pChkDesc->chkTotalFSize, "\n", 10 ); print64Fine( " # of lost chains: ", pChkDesc->chkNLostChains, "\n", 10 ); print64Mult( " total bytes in lost chains: ", pChkDesc->chkTotalBytesInLostChains, "\n", 10 ); } /********************************************************************************* dosChkFinish - print statistics and deallocate resources.** RETURNS: N/A.*/LOCAL void dosChkFinish ( DOS_FILE_DESC_ID pFd ) { if( pFd->pVolDesc->pChkDesc->chkFatMap != NULL ) KHEAP_FREE(((char *)pFd->pVolDesc->pChkDesc->chkFatMap)); KHEAP_FREE(((char *)pFd->pVolDesc->pChkDesc)); pFd->pVolDesc->pChkDesc = NULL; return; } /* dosChkFinish() */ /********************************************************************************* dosChkEntryMark - set/get FAT entry marker.** RETURNS: marker value on MARK_GET operation, STATUS on MARK_SET* and MARK_BUF_INIT operation.*/uint32_t dosChkEntryMark ( DOS_FILE_DESC_ID pFd, u_int operation, /* MARK_SET/MARK_GET/MARK_BUF_INIT */ uint32_t entryNum, uint32_t mark ) { DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; CHK_DSK_DESC_ID pChkDesc = pVolDesc->pChkDesc; uint8_t fatCopyNum = 0; if (! pChkDesc->bufToDisk) { switch (operation) { case MARK_GET : case IS_BUSY : return pChkDesc->chkFatMap [entryNum]; case MARK_SET : pChkDesc->chkFatMap [entryNum] = mark; break; case MARK_BUF_INIT : bzero ((char *)pChkDesc->chkFatMap, pVolDesc->nFatEnts * sizeof( *pVolDesc->pChkDesc->chkFatMap )); break; default: assert (FALSE); } return OK; } else /* use reserved FAT copy as buffer */ { fatCopyNum = pVolDesc->pFatDesc->activeCopyNum + 1; switch (operation) { case MARK_GET : pVolDesc->pFatDesc->clustValueGet (pFd, fatCopyNum, entryNum, &mark ); return mark; case IS_BUSY : return pChkDesc->chkFatMap [ entryNum / 8 / sizeof(*pChkDesc->chkFatMap)] & (1 << (entryNum & (sizeof(*pChkDesc->chkFatMap) * 8 - 1))); case MARK_SET : pChkDesc->chkFatMap [ entryNum / 8 / sizeof(*pChkDesc->chkFatMap)] |= 1 << (entryNum & (sizeof(*pChkDesc->chkFatMap) * 8 - 1)); return pVolDesc->pFatDesc->clustValueSet ( pFd, fatCopyNum, entryNum, DOS_FAT_RAW, mark ); case MARK_BUF_INIT : bzero ((char *)pChkDesc->chkFatMap, pVolDesc->nFatEnts / 8 + 4); return pVolDesc->pFatDesc->clustValueSet( pFd, fatCopyNum, 0, DOS_FAT_SET_ALL, 0 ); default: assert (FALSE); } } return ERROR; } /* dosChkEntryMark() *//********************************************************************************* dosChkEntryFind - find entry in directory.** This routine searches directory, that starts from <dirStartClust>,* for entry, by entry name or start cluster. File descriptor* <pFd> is filled for entry found and entry name is placed into* <pChkDesc->chkDir>.** RETURNS: OK or ERROR if disk access error.*/LOCAL STATUS dosChkEntryFind ( DOS_FILE_DESC_ID pFd, UINT32 dirStartClust, void * key, /* start clust value or name buffer */ CHK_SEARCH_KEY_TYPE keyType ) { UINT32 startClust = (UINT32)key; DIR * pDir = &pFd->pVolDesc->pChkDesc->chkDir; DOS_FILE_DESC fd; DOS_FILE_HDL flHdl; fd = *pFd; flHdl = *pFd->pFileHdl; fd.pFileHdl = &flHdl; if( dirStartClust == 0 ) /* parent is root */ { if( pFd->pVolDesc->pDirDesc->pathLkup( &fd, "", 0 ) == ERROR ) return ERROR; } else if( dirStartClust == (UINT32)NONE ) /* search for root */ { if( pFd->pVolDesc->pDirDesc->pathLkup( &fd, "", 0 ) == ERROR ) return ERROR; strcpy( pDir->dd_dirent.d_name, pFd->pVolDesc->devHdr.name ); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -