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 || SPCVerify( 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; 
}