📄 dosfsfat.c
字号:
/* dosFsFat.c - DOS file system File Allocation Table Handler *//* Copyright 1987-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01q,10jan02,chn Renamed some functions to clear up sector/cluster confusion01p,10dec01,jkf SPR#72039, various fixes from Mr. T. Johnson.01o,12oct01,jkf adapted debugging code to be more portable. 01n,02oct01,jkf replaced diab changes lost in 01m.01m,20sep01,jkf SPR#69031, common code for both AE & 5.x.01l,08oct99,jkf added ifdef for HP native tools to ignore GNUish debug macro's01k,31aug99,jkf changes for new CBIO API.01j,31jul99,jkf T2 merge, tidiness & spelling.01i,21dec98,mjc fixed bug in fat16Seek(), changed name of <contigEnd> field in structure <DOS_FILE_HDL> to <contigEndPlus1>01h,23nov98,mjc avoided disk access for seek within contiguous file area;01j,23sep98,vld added FAT mirroring disabling; added routine fat16SyncToggle()01f,20sep98,mjc descriptor structure name changed from DOS_FAT16_DESC to MS_FAT_DESC01e,17sep98,vld added argument "number of FAT copy" to cluster read/write routines;cluster writing routines extended with a"raw" data write to FAT copies other, then active one; routine fat16ClustValueSet() extended to support FAT copy initialization;01d,12jul98,mjc cluster group allocation factor changed from constant to global variable fatClugFac. Assert header files including was moved to be after #ifdef DEBUG statement to allow NDEBUG definition in case when DEBUG is undefined. fat16ContigAlloc() algorithm was changed to 1st fit.01c,01jul98,lrn doc reviewed01b,29jun98,mjc added FAT32, tested01a,23feb98,mjc initially written written.*//*DESCRIPTIONThis module is part of dosFsLib and is designed to manage the threedifferent File Allocation Table formats: FAT12, FAT16 and FAT32.These formats are similar thus are implemented in a single modulewithout the ability to scale out one of these formats for systems whichdo not intend to use them.IMPLEMENTATIONThis FAT handler does not keep any part of the File Allocation Table inmemory, depending entirely on the underlying CBIO module, typically theDisk Cache for the ability to access any FAT entry of any size, i.e.byte-wise access to any particular disk sector.INITIALIZATION*//* includes */#include "vxWorks.h"#include "private/dosFsVerP.h"#include "semLib.h"#include "errnoLib.h"#include "logLib.h"#include "string.h"#include "memLib.h"#include "stdlib.h"#include "stdio.h"#include "taskLib.h"#include "private/print64Lib.h"#include "private/dosFsLibP.h"#include "private/dosFsFatP.h"/* macros */#define _TO_STR(z) _TO_TMP(z)#define _TO_TMP(z) #z#undef ERR_MSG#undef DBG_MSG#undef ERR_PRINT#ifdef DEBUG# undef LOCAL# define LOCAL# define ERR_PRINT /* include errnoSetOut() */# define errnoSet( err ) errnoSetOut( __FILE__, __LINE__, #err, (err) )# define DBG_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6) \ { if ((lvl) <= fat16Debug) \ printErr (__FILE__" : "_TO_STR(__LINE__)" : "fmt, a1, a2, \ a3, a4, a5, a6); }# define ERR_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6) \ { logMsg (__FILE__" : "_TO_STR(__LINE__)" : "fmt, (int)(a1), \ (int)(a2), (int)(a3), (int)(a4), (int)(a5), (int)(a6)); }#else /* NO DEBUG */# undef NDEBUG# define NDEBUG/* fixme: quick dirty hack for native HP native tools build, HP simulator */# if (CPU == SIMHPPA) /* Allow TOOL=hp to build, will cause no effect warnings when TOOL=gnu */# define DBG_MSG# define ERR_MSG# else# define DBG_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6) {}# define ERR_MSG(lvl, fmt, a1, a2, a3, a4, a5, a6) \ { if ((lvl) <= fat16Debug) \ logMsg (__FILE__" : "_TO_STR(__LINE__)" : %s : "fmt, \ (int)(a1), (int)(a2), (int)(a3), (int)(a4), (int)(a5), \ (int)(a6)); }# endif /* (CPU == SIMHPPA) */#endif /* DEBUG */ #include "assert.h"/* defines *//* File System Information Sector number */#define FSINFO_SEC_NUM 1/* Offset of free clusters count field in the File System Information Sector */#define FSINFO_SIGN 484#define FSINFO_FREE_CLUSTS 488#define FSINFO_NEXT_FREE 492/* Read FAT entry error code */#define FAT_CBIO_ERR 1/* Mutex semaphore options */#define ALLOC_SEM_OPTIONS SEM_Q_PRIORITY | SEM_DELETE_SAFE | \ SEM_INVERSION_SAFE#define ENTRY_READ(pFd, copy, entry) \ pFatDesc->entryRead ((pFd), (copy), (entry))#define ENTRY_WRITE(pFd, copy, entry, value) \ pFatDesc->entryWrite ((pFd), (copy), (entry), (value))/* typedefs *//* globals */int fat16Debug = 0; /* debug level */int fatClugFac = 10000; /* cluster allocation group size factor *//* locals */#ifdef ERR_PRINT/******************************************************************************** errnoSetOut - put error message** This routine is called instead errnoSet during debugging.*/LOCAL VOID errnoSetOut(char * pFile, int line, const char * pStr, int errCode ) { /* If it is not errno clearing or setting to previously stored value * (in <errnoBuf> variable), print the error information. */ if( errCode != OK && strcmp( pStr, "errnoBuf" ) != 0 ) printf( "ERROR from %s : line %d : %s = %p, task %p\n", pFile, line, pStr, (void *)errCode, (void *)taskIdSelf() ); errno = errCode; }#endif /* ERR_PRINT *//********************************************************************************* fat16MirrorSect - mirror FAT sector** This routine copies last modified sector of Primary FAT copy to appropriate * sectors of another FAT copies.** RETURNS: OK or ERROR.*/LOCAL STATUS fat16MirrorSect ( FAST DOS_FILE_DESC_ID pFd /* pointer to file descriptor */ ) { FAST DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; /* pointer to volume descriptor */ FAST MS_FAT_DESC_ID pFatDesc = (void *) pVolDesc->pFatDesc; /* pointer to FAT descriptor */ FAST CBIO_DEV_ID pCbio = pVolDesc->pCbio; /* pointer to CBIO device */ FAST uint32_t srcSecNum = pFd->pFileHdl->fatSector; FAST uint32_t dstSecNum; FAST int fatNum; /* FAT copy number */ uint8_t fsinfoBuf [8]; if (srcSecNum == 0) return OK; /* FAT copies synchronization might be disabled */ if ( ! pFatDesc->syncEnabled) return OK; /* * TBD: mirroring disabled (FAT32) * ? Maybe it is worth adding callbacks to process CBIO write errors ? */ for (fatNum = 1, dstSecNum = srcSecNum + pVolDesc->secPerFat; fatNum < pVolDesc->nFats; fatNum++, dstSecNum += pVolDesc->secPerFat) { if (cbioBlkCopy (pCbio, srcSecNum, dstSecNum, 1) != OK) return ERROR; /* ...??? */ } if (pVolDesc->fatType == FAT32) { VX_TO_DISK_32 (pFatDesc->fatEntFreeCnt, &fsinfoBuf[0]); VX_TO_DISK_32 (pFatDesc->groupAllocStart, &fsinfoBuf[4]); if (OK != cbioBytesRW (pCbio, FSINFO_SEC_NUM, FSINFO_FREE_CLUSTS, (addr_t)fsinfoBuf, sizeof (fsinfoBuf), CBIO_WRITE, NULL)) return ERROR; } return OK; } /* fat16MirrorSect *//********************************************************************************* fat16SyncToggle - toggle FAT copies mirroring.* * This routine enables/disables FAT copes mirroring. When mirroring* is enabled all reserved FAT copes are synchronized with active one.* * RETURNES: N/A.*/LOCAL void fat16SyncToggle ( DOS_VOLUME_DESC_ID pVolDesc, BOOL syncEnable ) { MS_FAT_DESC_ID pFatDesc = (MS_FAT_DESC_ID)pVolDesc->pFatDesc; block_t srcSec, dstSec, secNum; uint8_t copyNum; pFatDesc->syncEnabled = syncEnable; if (! syncEnable) return; /* synchronize FAT copies */ /* copy by one sector. It permits always one read - multi write */ srcSec = pFatDesc->fatStartSec + pVolDesc->pFatDesc->activeCopyNum * pVolDesc->secPerFat; for (secNum = 0; secNum < pVolDesc->secPerFat; secNum ++, srcSec ++ ) { for (dstSec = pFatDesc->fatStartSec + secNum, copyNum = 0; copyNum < pVolDesc->nFats; dstSec += pVolDesc->secPerFat, copyNum ++ ) { if (copyNum == pVolDesc->pFatDesc->activeCopyNum) continue; cbioBlkCopy (pVolDesc->pCbio, srcSec, dstSec, 1); } } } /* fat16SyncToggle() *//********************************************************************************* fat12EntRead - read FAT entry from disk* * This routine reads the file allocation table (FAT) entry from a dosFs* volume.** This routine only reads from the first copy of the FAT on disk, even if* other copies exist.* * RETURNS: Contents of the entry, or FAT_CBIO_ERR if error accessing disk.*/LOCAL uint32_t fat12EntRead ( FAST DOS_FILE_DESC_ID pFd, /* pointer to file descriptor */ FAST uint32_t copyNum,/* fat copy number */ FAST uint32_t cluster /* entry number */ ) { FAST DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; /* pointer to volume descriptor */ FAST CBIO_DEV_ID pCbio = pVolDesc->pCbio; /* pointer to CBIO device */ FAST MS_FAT_DESC_ID pFatDesc = (void *) pVolDesc->pFatDesc; /* pointer to FAT descriptor */ FAST uint32_t fatEntry;/* FAT entry */ FAST uint32_t fatOff; /* offset in the FAT */ FAST block_t secNum; /* sector number to read/write */ FAST off_t secOff; /* offset in the sector */ FAST uint32_t nBytes; /* number of bytes */ uint8_t valBuf [2]; /* buffer for value in the entry */ assert ( copyNum < pVolDesc->nFats); assert ( (cluster >= DOS_MIN_CLUST) && (cluster < pFatDesc->nFatEnts) ); /* Offset of the entry in the FAT in bytes */ fatOff = cluster + (cluster >> 1); /* index = cluster * 1.5 */ /* Number of sector containing the entry */ secNum = pFatDesc->fatStartSec + copyNum * pVolDesc->secPerFat + (fatOff >> pVolDesc->secSizeShift); /* Offset of the entry in the sector */ secOff = fatOff & (pVolDesc->bytesPerSec - 1); /* Number of bytes to read */ nBytes = pVolDesc->bytesPerSec - secOff; if (nBytes > 2) nBytes = 2; /* Read entry from disk */ if (cbioBytesRW (pCbio, secNum, secOff, (addr_t)valBuf, nBytes, CBIO_READ, &pFd->fatHdl.cbioCookie) != OK) { pFd->fatHdl.errCode = FAT_CBIO_ERR; return FAT_CBIO_ERR; /* read error */ } if (nBytes == 1) if (cbioBytesRW (pCbio, secNum + 1, 0, (addr_t)(&valBuf[1]), 1, CBIO_READ, &pFd->fatHdl.cbioCookie) != OK) { pFd->fatHdl.errCode = FAT_CBIO_ERR; return FAT_CBIO_ERR; /* read error */ } fatEntry = valBuf [0] | (valBuf [1] << 8); /* copy word, swapping bytes */ if (cluster & 0x1) /* if cluster number is ODD */ fatEntry = (fatEntry >> 4) & 0xfff; /* keep high order 12 bits */ else /* if cluster number is EVEN */ fatEntry &= 0xfff; /* keep low order 12 bits */ return fatEntry; } /* fat12EntRead *//********************************************************************************* fat12EntWrite - write FAT entry to disk* * This routine writes the file allocation table (FAT) entry to a dosFs* volume.** This routine reads the file allocation table (FAT) entry for the* specified cluster and returns it to the caller.** If the value to be written is too large to fit in a FAT entry* (12 bits), it is truncated (high order bits are discarded).** This routine only writes to the first copy of the FAT on disk, even if* other copies exist.* * RETURNS: OK, or ERROR if error accessing disk.*/LOCAL STATUS fat12EntWrite ( FAST DOS_FILE_DESC_ID pFd, /* pointer to file descriptor */ FAST uint32_t copyNum,/* fat copy number */ FAST uint32_t cluster,/* entry number */ FAST uint32_t value /* value to write */ ) { FAST DOS_VOLUME_DESC_ID pVolDesc = pFd->pVolDesc; /* pointer to volume descriptor */ FAST CBIO_DEV_ID pCbio = pVolDesc->pCbio; /* pointer to CBIO device */ FAST MS_FAT_DESC_ID pFatDesc = (void *) pVolDesc->pFatDesc; /* pointer to FAT descriptor */ FAST uint32_t fatOff; /* offset in the FAT */ FAST block_t secNum; /* sector number to read/write */ FAST off_t secOff; /* offset in the sector */ FAST uint32_t nBytes; /* number of bytes */ cookie_t cookie; /* CBIO dev. cookie */ uint8_t valBuf [2]; /* buffer for value in the entry */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -