📄 fatfilt.c
字号:
type = pv->type;
/*
* WARNING : Routine partEnableFF() uses disk's scratch buffer !
*/
if((type == FAT12_PARTIT) || (type == FAT16_PARTIT) || (type == DOS4_PARTIT))
partEnableFF (pv);
}
}
#endif /* FL_INCLUDE_FAT_MONITOR */
/* watch for MBR (sector #0) update */
pd->secToWatch = (SectorNo) 0;
pd->ffstate = flStateInitialized;
return flOK;
}
#ifdef FL_INCLUDE_FAT_MONITOR
/* --------------------------------------------------------------------------- *
* *
* p a r t E n a b l e F F *
* *
* Installs and enables FAT filter on partition. *
* *
* Parameters: *
* pv : disk partition (filesystem volume) *
* *
* Returns: *
* flOK on success, otherwise error code *
* *
* NOTE: This routine uses disk's scratch buffer. *
* *
* --------------------------------------------------------------------------- */
static FLStatus partEnableFF ( FLffVol * pv )
{
int socNo, diskNo;
FLffDisk * pd;
BPB * bpb;
SectorNo sectors;
SectorNo reservedSectors;
SectorNo rootDirSecNo;
SectorNo rootDirSectors;
SectorNo sectorsPerFAT;
SectorNo rootDirEntries;
unsigned maxCluster;
int partNo;
IOreq ioreq;
#ifdef FL_MALLOC
char * buf;
#else
char buf[SECTOR_SIZE];
#endif
DEBUG_PRINT(("Debug: checking FAT type.\r\n"));
/* arg. sanity check */
if (pv == NULL)
return flBadDriveHandle;
/* break TFFS handle into socket# and disk#, and do sanity check */
socNo = H2S(pv->handle);
diskNo = H2D(pv->handle);
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
return flBadDriveHandle;
/* check if 'pv' belongs to this disk */
pd = ffDisk[socNo][diskNo];
if (pd == NULL)
return flBadDriveHandle;
for (partNo = 0; partNo < pd->parts; partNo++) {
if (pd->part[partNo] == pv)
break;
}
if (partNo >= pd->parts)
return flBadDriveHandle;
#ifdef FL_MALLOC
/* make sure scratch buffer is available */
if (pd->buf == NULL)
return flBufferingError;
buf = pd->buf;
#endif /* FL_MALLOC */
/* make sure FAT filter is off on this partition */
pv->ffEnabled = FALSE;
pv->firstFATsecNo = (SectorNo) -1;
pv->lastFATsecNo = pv->firstFATsecNo;
pv->clusterSize = (unsigned) 0;
/* read BPB */
ioreq.irHandle = pv->handle;
ioreq.irSectorNo = pv->startSecNo;
ioreq.irSectorCount = (SectorNo) 1;
ioreq.irData = (void FAR1 *) buf;
checkStatus( flAbsRead(&ioreq) );
/* Does it look like DOS bootsector ? */
bpb = &( ((DOSBootSector *) buf)->bpb );
if( !((bpb->jumpInstruction[0] == 0xe9)
||
((bpb->jumpInstruction[0] == 0xeb) && (bpb->jumpInstruction[2] == 0x90)))) {
return flNonFATformat;
}
/* Do we handle this sector size ? */
if (UNAL2(bpb->bytesPerSector) != SECTOR_SIZE)
return flFormatNotSupported;
/*
* Is it a bogus BPB (leftover from previous disk partitioning) ?
* Check that there is no overlap with next partition (if one exists).
*/
sectors = UNAL2(bpb->totalSectorsInVolumeDOS3);
if (sectors == (SectorNo)0)
sectors = (SectorNo) LE4(bpb->totalSectorsInVolume);
if ((partNo+1 < pd->parts) && (pd->part[partNo+1] != NULL)) {
if( sectors > (pd->part[partNo+1])->startSecNo - pv->startSecNo )
return flNonFATformat;
}
/* number of sectors in partition as reported by BPB */
pv->sectors = sectors;
/* get number of reserved sectors from BPB, and check it's sanity */
reservedSectors = (SectorNo) LE2(bpb->reservedSectors);
switch( (int)reservedSectors ) {
case 32: /* always the case with FAT 32 */
#ifndef FL_INCLUDE_FAT32
DEBUG_PRINT(("Debug: FAT32 detected.\r\n"));
return flFormatNotSupported;
#endif
case 1: /* must always be the case for FAT 12 and FAT16 */
default:
break;
}
/* get location and size of the first FAT copy */
pv->firstFATsecNo = pv->startSecNo + reservedSectors;
sectorsPerFAT = (SectorNo) LE2(bpb->sectorsPerFAT);
#ifndef FL_INCLUDE_FAT32
if (sectorsPerFAT == 0) { /* always the case with FAT32 */
DEBUG_PRINT(("Debug: FAT32 detected.\r\n"));
return flFormatNotSupported;
}
#endif
pv->lastFATsecNo = pv->firstFATsecNo + sectorsPerFAT - (SectorNo)1;
/* get location and size of root directory */
rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS);
rootDirEntries = (SectorNo) UNAL2(bpb->rootDirectoryEntries);
switch (rootDirEntries) {
#ifndef FL_INCLUDE_FAT32
case 0: /* always the case with FAT32 */
DEBUG_PRINT(("Debug: FAT32 detected.\r\n"));
return flFormatNotSupported;
#endif
default:
if( ((rootDirEntries * DIRECTORY_ENTRY_SIZE) % SECTOR_SIZE) != 0 )
return flNonFATformat;
break;
}
rootDirSectors = (SectorNo)(((rootDirEntries * DIRECTORY_ENTRY_SIZE) - 1) / SECTOR_SIZE) +
(SectorNo)1;
/* get location of data area */
pv->firstDataSecNo = rootDirSecNo + rootDirSectors;
/* get size of FAT cluster in sectors, and check it's sanity */
pv->clusterSize = bpb->sectorsPerCluster;
switch( (int)pv->clusterSize ) {
case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
break;
default:
return flNonFATformat;
}
if ((pv->clusterSize * SECTOR_SIZE) > (32 * 1024))
return flFormatNotSupported;
/* sanity check */
if( (pv->lastFATsecNo < pv->firstFATsecNo) ||
(pv->firstDataSecNo <= pv->lastFATsecNo) ||
(pv->sectors < pv->firstDataSecNo) )
return flNonFATformat;
/* decide which type of FAT is it */
maxCluster = (unsigned)1 + (unsigned)
((pv->sectors - (pv->firstDataSecNo - pv->startSecNo)) / pv->clusterSize);
if (maxCluster < 4085) {
pv->flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */
#ifndef FAT_12BIT
DEBUG_PRINT(("Debug: FAT_12BIT must be defined.\r\n"));
return flFormatNotSupported;
#else
DEBUG_PRINT(("Debug: FAT12 detected.\r\n"));
#endif /* FAT_12BIT */
}
else {
DEBUG_PRINT(("Debug: FAT16 detected.\r\n"));
}
/* turn on FAT filter on this partition */
pv->ffEnabled = TRUE;
return flOK;
}
/* --------------------------------------------------------------------------- *
* *
* p a r t F r e e D e l C l u s t e r s *
* *
* Compare the new contents of the specified FAT sector against the old *
* one on the disk. If any freed clusters are found, issue 'sector delete' *
* calls for all sectors that are occupied by these freed clusters. *
* *
* Parameters: *
* pv : disk partition (filesystem volume) *
* secNo : abs. sector # of the FAT sector *
* newFAT : new contents of this FAT sector *
* *
* Returns: *
* flOK on success, otherwise error code *
* *
* NOTE: This routine uses disk's scratch buffer. *
* *
* --------------------------------------------------------------------------- */
static FLStatus partFreeDelClusters ( FLffVol * pv,
SectorNo secNo,
char FAR1 * newFAT)
{
FLffDisk * pd;
int socNo, diskNo;
unsigned short oldFATentry, newFATentry;
SectorNo iSec;
unsigned firstCluster;
IOreq ioreq;
int offset;
int iPart;
#ifdef FAT_12BIT
int halfBytes;
#endif
#ifdef FL_MALLOC
char * oldFAT;
#else
char oldFAT[SECTOR_SIZE];
#endif
/* arg. sanity check */
if (pv == NULL)
return flBadDriveHandle;
/* break TFFS handle into socket# and disk#, and do sanity check */
socNo = H2S(pv->handle);
diskNo = H2D(pv->handle);
if ((socNo >= ((int) noOfSockets)) || (diskNo >= MAX_TL_PARTITIONS))
return flBadDriveHandle;
/* check if 'pv' belongs to this disk */
pd = ffDisk[socNo][diskNo];
if (pd == NULL)
return flBadDriveHandle;
for (iPart = 0; iPart < pd->parts; iPart++) {
if (pd->part[iPart] == pv)
break;
}
if (iPart >= pd->parts)
return flBadDriveHandle;
#ifdef FL_MALLOC
/* make sure scratch buffer is available */
if (pd->buf == NULL)
return flBufferingError;
oldFAT = pd->buf;
#endif /* FL_MALLOC */
/* read in the FAT sector from the disk */
ioreq.irHandle = pv->handle;
ioreq.irSectorNo = secNo;
ioreq.irSectorCount = 1;
ioreq.irData = (void FAR1 *) oldFAT;
checkStatus( flAbsRead(&ioreq) );
#ifdef FAT_12BIT
/* size of FAT entry in half-bytes */
halfBytes = ((pv->flags & VOLUME_12BIT_FAT) ? 3 : 4);
/* starting cluster */
if (halfBytes == 3) {
firstCluster =
((((unsigned)(secNo - pv->firstFATsecNo)) * (2 * SECTOR_SIZE)) + 2) / 3;
}
else {
firstCluster = ((unsigned)(secNo - pv->firstFATsecNo)) * (SECTOR_SIZE / 2);
}
/* staring data sector */
iSec = (((SectorNo)firstCluster - 2) * pv->clusterSize) + pv->firstDataSecNo;
offset = (firstCluster * ((unsigned) halfBytes)) & ((2 * SECTOR_SIZE) - 1);
/*
* Find if any clusters were logically deleted, and if so, delete them.
*
* NOTE: We are skipping over 12-bit FAT entries which span more than
* one sector.
*/
for (; offset < ((2 * SECTOR_SIZE) - 2);
offset += halfBytes, iSec += pv->clusterSize) {
#ifdef FL_BIG_ENDIAN
oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + (offset / 2)) );
newFATentry = LE2( *(LEushort FAR1 *)(newFAT + (offset / 2)) );
#else
oldFATentry = UNAL2( *(Unaligned FAR0 *)(oldFAT + (offset / 2)) );
newFATentry = UNAL2( *(Unaligned FAR1 *)(newFAT + (offset / 2)) );
#endif /* FL_BIG_ENDIAN */
if (offset & 1) {
oldFATentry >>= 4;
newFATentry >>= 4;
}
else {
if (halfBytes == 3) {
oldFATentry &= 0xfff;
newFATentry &= 0xfff;
}
}
#else /* !FAT_12BIT */
firstCluster = ((unsigned) (secNo - pv->firstFATsecNo) * (SECTOR_SIZE / 2));
iSec = pv->firstDataSecNo +
(((SectorNo)(firstCluster - (unsigned)2)) * pv->clusterSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -