www.pudn.com > SmartFDISK.zip > fat32.cpp
/**************************************************************************** * * Smart FDISK * * This program is a powerful Harddisk Partitioning Tool including a * easy-to-use Boot Manager. * * * Copyright (C) 1999 Suzhe (suzhe@263.net) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ****************************************************************************/ /* * fat32.cpp : Source file for Class TFAT32 */ #define Uses_FATBase #define Uses_FAT32 #include "Kernel.H" #include "FATMacro.h" #include#define MAXBLOCKSIZE 32768uL /****************************************************************************/ /* Functions for class TFAT32 */ /****************************************************************************/ BYTE TFAT32::FAT32BootRecord1[]= { #include "FAT32BR1.h" }; BYTE TFAT32::FAT32BootRecord2[]= { #include "FAT32BR2.h" }; TFAT32::TFAT32() : TFATBase() { PreInit(); } TFAT32::TFAT32( TPartition * part ) { PreInit(); Initialize( part ); } void TFAT32::PreInit() { memset( &ExtFSInfo, 0, sizeof(FAT_BFFSInfo) ); } void TFAT32::ShutDown() { TFATBase::ShutDown(); PreInit(); } int32 TFAT32::ReadBootRecord() { BYTE *buf; int32 errno=0; if( !IsUseable() ) return 0x300; Formated = False; buf = new BYTE[ Partition->GetSectorSize() ]; if( buf==NULL ) return 0x400; if( (errno=Partition->Read( 0, 1, buf )) == 0 ) { if( *((DWORD*)(buf+BOOTIDOFFSET)) == GOODBOOTID ) { memcpy( &ParamBlock, buf + BPBOFFSET, SIZEOFBPB32 ); if( ParamBlock.com.BytesPerSector == Partition->GetSectorSize() && ParamBlock.bpb32.ExtBootRecordID == EXTBRID && strncmp( (char*) ParamBlock.bpb32.SystemType, FAT32FSNAME, strlen(FAT32FSNAME))==0 ) { FATType = 32; Formated = True; if( ParamBlock.bpb32.FSInfoSector != 0xFFFF && (errno=Partition->Read(ParamBlock.bpb32.FSInfoSector,1,buf)) == 0) { if( *((DWORD*)buf) == EXTBOOTSIG ) memcpy( &ExtFSInfo, buf + BFFSINFOOFFSET, sizeof(FAT_BFFSInfo) ); } } } } delete buf; return errno; } int32 TFAT32::WriteBootRecord() { BYTE *buf; int32 errno; if( !IsUseable() || FATType != 32 ) return 0x300; buf = new BYTE[ Partition->GetSectorSize() ]; if( buf==NULL ) return 0x400; memcpy( buf, FAT32BootRecord1, Partition->GetSectorSize() ); memcpy( buf+BPBOFFSET, &ParamBlock, SIZEOFBPB32 ); if( (errno=Partition->Write( 0, 1, buf )) == 0 ) { Partition->Write( ParamBlock.bpb32.BackupBootSector, 1, buf ); memset( buf, 0, Partition->GetSectorSize() ); *((DWORD*)buf) = EXTBOOTSIG; ExtFSInfo.Signature = FSINFOSIG; ExtFSInfo.EndSig = GOODBOOTID; memcpy( buf + BFFSINFOOFFSET, &ExtFSInfo, sizeof(FAT_BFFSInfo) ); Partition->Write( ParamBlock.bpb32.FSInfoSector, 1, buf ); Partition->Write( ParamBlock.bpb32.FSInfoSector+ ParamBlock.bpb32.BackupBootSector, 1, buf ); memcpy( buf, FAT32BootRecord2, Partition->GetSectorSize() ); *((DWORD*)(buf+BOOTIDOFFSET)) = GOODBOOTID; Partition->Write( ParamBlock.bpb32.FSInfoSector+1, 1, buf ); Partition->Write( ParamBlock.bpb32.FSInfoSector+ ParamBlock.bpb32.BackupBootSector+1, 1, buf ); } delete buf; if( errno!=0 ) return errno; errno=Partition->Verify( 0, 1 ); if( errno==0 ) Changed=False; return errno; } int32 TFAT32::CreateBootRecord(DWORD MinBlockSize) { DWORD SPF, sectors, MaxCluster; WORD SPC,BPC2; TDiskGeometry geometry; int i; srand(time(0)); if( !IsUseable() ) return 0x300; if( MinBlockSize > MAXBLOCKSIZE ) MinBlockSize=MAXBLOCKSIZE; MinBlockSize /= Partition->GetSectorSize(); sectors = Partition->GetSectors(); Partition->GetHardDrive()->GetGeometry( geometry ); strncpy( (char*) ParamBlock.com.OemID, OEMID, 8 ); ParamBlock.com.BytesPerSector = Partition->GetSectorSize(); ParamBlock.com.ReservedSectors = 32; ParamBlock.com.NumberOfFAT = 2; ParamBlock.com.RootEntries = 0; ParamBlock.com.TotalSectors = 0; ParamBlock.com.MediaDescriptor = 0xF8; ParamBlock.com.SectorsPerFAT = 0; ParamBlock.com.SectorsPerTrack = geometry.SectorsPerTrack; ParamBlock.com.Heads = geometry.Heads; ParamBlock.com.HiddenSectors = Partition->GetRelativeSector(); ParamBlock.com.BigTotalSectors = sectors; ParamBlock.bpb32.ExtFlags = 0; ParamBlock.bpb32.FSVersion = 0; ParamBlock.bpb32.RootDirStartCluster = 2; ParamBlock.bpb32.FSInfoSector = 1; ParamBlock.bpb32.BackupBootSector = 6; ParamBlock.bpb32.DriveNumber = Partition->GetHardDrive()->GetDriveNumber(); ParamBlock.bpb32.BootReserved = 0; ParamBlock.bpb32.ExtBootRecordID = EXTBRID; ParamBlock.bpb32.SerialNumber = (DWORD)random(); memset( ParamBlock.bpb32.VolumeLabel, 0, sizeof(BYTE) * 11 ); strncpy( (char*) ParamBlock.bpb32.SystemType, FAT32FSNAME, 8 ); for( i=strlen( FAT32FSNAME ); i< 8; i++ ) ParamBlock.bpb32.SystemType[i]=32; FATType = 32; MaxCluster = 0x10000000uL; for(SPC=2; sectors / (DWORD)SPC >= MaxCluster || SPC Verify( ParamBlock.bpb32.FSInfoSector, 2 ) == 0 ) break; ParamBlock.bpb32.FSInfoSector +=2 ; ParamBlock.bpb32.BackupBootSector +=2; } ExtFSInfo.Signature = FSINFOSIG; ExtFSInfo.FreeClusterCount = 0xFFFFFFFF; ExtFSInfo.NextFreeCluster = FIRSTCLUSTER; ExtFSInfo.EndSig = GOODBOOTID; return 0; } DWORD TFAT32::ReadFATEntry( DWORD cluster ) { int32 Sector=0, Offset=0; DWORD Result=0; WORD SectorSize; int i; if( !IsUseable() || FATType != 32 ) return 0; if( cluster < FIRSTCLUSTER || cluster >= FIRSTCLUSTER + GetTotalClusters() ) return 0; SectorSize = Partition->GetSectorSize(); if( FATType == 32 ) { Sector = cluster * 4uL / SectorSize; Offset = ((cluster * 4uL) % SectorSize) / 4uL; if( FATBufStartSector < 0 || Sector < FATBufStartSector || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.bpb32.BigSectorsPerFAT ) FATBufStartSector = ParamBlock.bpb32.BigSectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() !=0 ) return 0; } Result = ((DWORD*)(FATBuf+(Sector - FATBufStartSector)*SectorSize))[Offset]; } return Result; } int32 TFAT32::WriteFATEntry( DWORD cluster, DWORD entry ) { int32 Sector=0, Offset=0; WORD SectorSize; int i; if( !IsUseable() || FATType != 32 ) return 0x300; if( cluster >= FIRSTCLUSTER + GetTotalClusters() ) return 0x401; SectorSize = Partition->GetSectorSize(); if( FATType == 32 ) { Sector = cluster * 4uL / SectorSize; Offset = ((cluster * 4uL) % SectorSize) / 4uL; if( FATBufStartSector < 0 || Sector < FATBufStartSector || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.bpb32.BigSectorsPerFAT ) FATBufStartSector = ParamBlock.com.SectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() != 0 ) return 0x302; } ((DWORD*)(FATBuf+(Sector - FATBufStartSector)*SectorSize))[Offset] = entry & 0x0FFFFFFFuL; FATBufChanged = True; } return 0; } int32 TFAT32::ClearFATTable() { BYTE *buf; DWORD start, sect, delta, amount; int32 errno; if( !IsUseable() || FATType != 32 ) return 0x300; start = ParamBlock.com.ReservedSectors; buf =new BYTE[ 32768uL ]; if( buf==NULL ) return 0x400; memset( buf, 0, 32768uL ); delta = 32768uL / Partition->GetSectorSize(); for( int i=0; i< ParamBlock.com.NumberOfFAT; i++ ) { for( sect = 0; sect < ParamBlock.bpb32.BigSectorsPerFAT; sect+=delta ) { amount =((sect - ParamBlock.bpb32.BigSectorsPerFAT)) >= delta ? delta : ((sect - ParamBlock.bpb32.BigSectorsPerFAT)); if( (errno = Partition->Write(start + sect + ParamBlock.bpb32.BigSectorsPerFAT * (DWORD)i, amount, buf))!= 0 ) return errno; } } delete buf; WriteFATEntry( 0, 0x0FFFFFF8 ); WriteFATEntry( 1, 0x0FFFFFFF ); WriteFATEntry( ParamBlock.bpb32.RootDirStartCluster, 0X0FFFFFFF ); FlushFATBuf(); return 0; } int32 TFAT32::ClearRootDir() { BYTE *buf; DWORD start, sect, total; int32 errno; if( !IsUseable() || FATType != 32 ) return 0x300; buf =new BYTE[ GetBlockSize() ]; if( buf==NULL ) return 0x400; memset( buf,0,GetBlockSize() ); errno=WriteCluster( ParamBlock.bpb32.RootDirStartCluster, 1, buf ); delete buf; return errno; } DWORD TFAT32::GetClusterLBA( DWORD cluster ) { DWORD Start, Offset; if( cluster < FIRSTCLUSTER ) return 0; Start = ParamBlock.com.ReservedSectors; Start += (DWORD)ParamBlock.com.NumberOfFAT * (DWORD)ParamBlock.bpb32.BigSectorsPerFAT; Offset = (cluster - FIRSTCLUSTER) * ParamBlock.com.SectorsPerCluster; if( Start + Offset > Partition->GetSectors() - ParamBlock.com.SectorsPerCluster ) return 0; return Start + Offset; } DWORD TFAT32::GetTotalClusters() { DWORD TotalSect; if( !IsUseable() ) return 0; TotalSect = ParamBlock.com.BigTotalSectors; if( TotalSect == 0 ) TotalSect = Partition->GetSectors(); TotalSect -= ParamBlock.com.ReservedSectors; TotalSect -= ParamBlock.bpb32.BigSectorsPerFAT * ParamBlock.com.NumberOfFAT; return TotalSect / ParamBlock.com.SectorsPerCluster; } int32 TFAT32::ReadFATtoBuf() { int i; for( i=0; i< ParamBlock.com.NumberOfFAT; i++ ) if( Partition->Read( ParamBlock.com.ReservedSectors + ParamBlock.bpb32.BigSectorsPerFAT*i + FATBufStartSector,FATBufSectors,FATBuf ) == 0 ) return 0; if( i >= ParamBlock.com.NumberOfFAT ) return 1; } int32 TFAT32::FlushFATBuf() { if( FATBufChanged == False ) return 0; for( int i=0; i< ParamBlock.com.NumberOfFAT; i++ ) Partition->Write( ParamBlock.com.ReservedSectors + ParamBlock.bpb32.BigSectorsPerFAT*i + FATBufStartSector,FATBufSectors,FATBuf ); FATBufChanged = False; return 0; }