www.pudn.com > SmartFDISK.zip > fat16.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. * ****************************************************************************/ /* * fat16.cpp : Source file for Class TFAT16 */ #define Uses_FATBase #define Uses_FAT16 #include "Kernel.H" #include "FATMacro.h" #include#define MAXBLOCKSIZE 32768uL /****************************************************************************/ /* Functions for class TFAT16 */ /****************************************************************************/ BYTE TFAT16::FAT16BootRecord[]= { #include "FAT16BR.h" }; TFAT16::TFAT16() : TFATBase() { } TFAT16::TFAT16( TPartition * part ) { Initialize( part ); } int32 TFAT16::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 && *((DWORD*)(buf+BOOTIDOFFSET)) == GOODBOOTID ) { memcpy( &ParamBlock, buf + BPBOFFSET, SIZEOFBPB16 ); if( ParamBlock.com.BytesPerSector == Partition->GetSectorSize() && ParamBlock.bpb16.ExtBootRecordID == EXTBRID ) { if( strncmp( (char*) ParamBlock.bpb16.SystemType, FAT16FSNAME, strlen(FAT16FSNAME) ) ==0 ) { FATType = 16; Formated = True; } else if( strncmp( (char*) ParamBlock.bpb16.SystemType, FAT12FSNAME, strlen(FAT16FSNAME) ) ==0 ) { FATType = 12; Formated = True; } } } delete buf; return errno; } int32 TFAT16::WriteBootRecord() { BYTE *buf; int32 errno; if( !IsUseable() || ( FATType != 16 && FATType != 12 ) ) return 0x300; buf = new BYTE[ Partition->GetSectorSize() ]; if( buf==NULL ) return 0x400; memcpy( buf, FAT16BootRecord, Partition->GetSectorSize() ); memcpy( buf+BPBOFFSET, &ParamBlock, SIZEOFBPB16 ); if( (errno=Partition->Write( 0, 1, buf )) ==0 ) errno=Partition->Verify( 0, 1 ); delete buf; if( errno==0 ) Changed=False; return errno; } int32 TFAT16::CreateBootRecord(DWORD MinBlockSize) { DWORD SPF, sectors, MaxCluster; WORD SPC,BPC2; TDiskGeometry geometry; 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 = 1; ParamBlock.com.NumberOfFAT = 2; ParamBlock.com.RootEntries = 512; ParamBlock.com.TotalSectors = ( sectors > 65535uL ) ? 0 : ((WORD)sectors); ParamBlock.com.MediaDescriptor = 0xF8; ParamBlock.com.SectorsPerTrack = geometry.SectorsPerTrack; ParamBlock.com.Heads = geometry.Heads; ParamBlock.com.HiddenSectors = Partition->GetRelativeSector(); ParamBlock.com.BigTotalSectors = sectors; ParamBlock.bpb16.DriveNumber = Partition->GetHardDrive()->GetDriveNumber(); ParamBlock.bpb16.BootReserved = 0; ParamBlock.bpb16.ExtBootRecordID= EXTBRID; ParamBlock.bpb16.SerialNumber = (DWORD)random(); memset( ParamBlock.bpb16.VolumeLabel, 0, sizeof(BYTE) * 11 ); if( Partition->GetSectors() < 32768uL ) FATType = 12; else FATType = 16; MaxCluster = (1uL)< = MaxCluster || SPC = FIRSTCLUSTER + GetTotalClusters() ) return 0; SectorSize = Partition->GetSectorSize(); if( FATType == 16 ) { Sector = cluster * 2uL / SectorSize; Offset = ((cluster * 2uL) % SectorSize) / 2uL; if( FATBufStartSector < 0 || Sector < FATBufStartSector || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.com.SectorsPerFAT ) FATBufStartSector = ParamBlock.com.SectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() !=0 ) return 0; } Result = (DWORD) ((WORD*)(FATBuf+(Sector - FATBufStartSector)*SectorSize))[Offset]; } else if( FATType == 12 ) { Sector = cluster * 3uL / ( SectorSize * 2uL ); Offset = ((cluster * 3uL) % ( SectorSize * 2uL )) / 2uL; FAT12Index = ((cluster * 3uL) % ( SectorSize * 2uL )) % 2uL; if( FATBufStartSector < 0 || Sector = FATBufStartSector + FATBufSectors - 1 && SectorSize - Offset < 2 ) || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.com.SectorsPerFAT ) FATBufStartSector = ParamBlock.com.SectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() !=0 ) return 0; } if( FAT12Index == 0 ) Result= ((DWORD)(FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset]) | ( (((DWORD)(FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset+1])<<8) & 0x0F00 ); else if( FAT12Index == 1 ) Result= ( ((DWORD)(FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset]) >> 4 ) | ( ((DWORD)(FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset+1]) << 4 ); } return Result; } int32 TFAT16::WriteFATEntry( DWORD cluster, DWORD entry ) { int32 Sector=0, Offset=0; BYTE FAT12Index=0; WORD SectorSize; int i; if( !IsUseable() || ( FATType != 16 && FATType != 12 ) ) return 0x300; if( cluster >= FIRSTCLUSTER + GetTotalClusters() ) return 0x401; SectorSize = Partition->GetSectorSize(); if( FATType == 16 ) { Sector = cluster * 2uL / SectorSize; Offset = ((cluster * 2uL) % SectorSize) / 2uL; if( FATBufStartSector < 0 || Sector < FATBufStartSector || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.com.SectorsPerFAT ) FATBufStartSector = ParamBlock.com.SectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() != 0 ) return 0x302; } ((WORD*)(FATBuf+(Sector - FATBufStartSector)*SectorSize))[Offset]= (WORD)entry; FATBufChanged = True; } else if( FATType == 12 ) { Sector = cluster * 3uL / ( SectorSize * 2uL ); Offset = ((cluster * 3uL) % ( SectorSize * 2uL )) / 2uL; FAT12Index = ((cluster * 3uL) % ( SectorSize * 2uL )) % 2uL; if( FATBufStartSector < 0 || Sector = FATBufStartSector + FATBufSectors - 1 && SectorSize - Offset < 2 ) || Sector >= FATBufStartSector + FATBufSectors ) { FlushFATBuf(); FATBufStartSector = Sector; if( FATBufStartSector + FATBufSectors > ParamBlock.com.SectorsPerFAT ) FATBufStartSector = ParamBlock.com.SectorsPerFAT - FATBufSectors; if( ReadFATtoBuf() != 0 ) return 0x302; } if( FAT12Index == 0 ) { (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset] = (BYTE) (entry & 0x00FF); (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset+1] &= 0xF0; (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset+1] |= (BYTE)( (entry>>8) & 0x0F); } else if( FAT12Index == 1 ) { (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset] &= 0x0F; (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset] |= (BYTE) ((entry << 4) & 0x00F0); (FATBuf+(Sector - FATBufStartSector)*SectorSize)[Offset+1] = (BYTE) ((entry >> 4) & 0x00FF); } FATBufChanged = True; } return 0; } int32 TFAT16::ClearFATTable() { BYTE *buf; DWORD start, sect; int32 errno; if( !IsUseable() || ( FATType != 16 && FATType != 12 ) ) return 0x300; start = ParamBlock.com.ReservedSectors; buf =new BYTE[ Partition->GetSectorSize() ]; if( buf==NULL ) return 0x400; memset( buf,0,Partition->GetSectorSize() ); for( int i=0; i< ParamBlock.com.NumberOfFAT; i++ ) { for( sect = 0; sect < ParamBlock.com.SectorsPerFAT; sect ++ ) if( (errno= Partition-> Write(start + sect + ParamBlock.com.SectorsPerFAT * (DWORD)i,1, buf)) != 0 ) return errno; } WriteFATEntry( 0, 0xFFF8 ); WriteFATEntry( 1, 0xFFFF ); FlushFATBuf(); delete buf; return 0; } int32 TFAT16::ClearRootDir() { BYTE *buf; DWORD start, sect, total; if( !IsUseable() || ( FATType != 16 && FATType != 12 ) ) return 0x300; start = ParamBlock.com.ReservedSectors; start += (DWORD)ParamBlock.com.NumberOfFAT * (DWORD)ParamBlock.com.SectorsPerFAT; total = (DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE / ParamBlock.com.BytesPerSector; if( ((DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE) % ParamBlock.com.BytesPerSector != 0 ) total ++; buf = new BYTE[ Partition->GetSectorSize() ]; if( buf==NULL ) return 0x400; memset( buf,0,Partition->GetSectorSize() ); for( sect = 0; sect< total; sect++ ) Partition->Write( sect + start, 1, buf ); delete buf; return 0; } DWORD TFAT16::GetClusterLBA( DWORD cluster ) { DWORD Start, Offset; if( !IsUseable() || ( FATType != 16 && FATType != 12 ) ) return 0; if( cluster < FIRSTCLUSTER || cluster >= FIRSTCLUSTER + GetTotalClusters() ) return 0; Start = ParamBlock.com.ReservedSectors; Start += (DWORD)ParamBlock.com.NumberOfFAT * (DWORD)ParamBlock.com.SectorsPerFAT; Start += (DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE / ParamBlock.com.BytesPerSector; if( ((DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE) % ParamBlock.com.BytesPerSector != 0 ) Start ++; Offset = (cluster - FIRSTCLUSTER) * ParamBlock.com.SectorsPerCluster; return Start + Offset; } DWORD TFAT16::GetTotalClusters() { DWORD TotalSect; if( !IsUseable() ) return 0; TotalSect = ParamBlock.com.BigTotalSectors; if( TotalSect == 0 ) TotalSect = Partition->GetSectors(); TotalSect -= ParamBlock.com.ReservedSectors; TotalSect -= (DWORD)ParamBlock.com.SectorsPerFAT * ParamBlock.com.NumberOfFAT; TotalSect -= (DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE / ParamBlock.com.BytesPerSector; if( ((DWORD)ParamBlock.com.RootEntries * DIRENTRYSIZE) % ParamBlock.com.BytesPerSector != 0 ) TotalSect --; return TotalSect / ParamBlock.com.SectorsPerCluster; } int32 TFAT16::ReadFATtoBuf() { short i; for( i=0; i< ParamBlock.com.NumberOfFAT; i++ ) if( Partition->Read( ParamBlock.com.ReservedSectors + ParamBlock.com.SectorsPerFAT*i + FATBufStartSector,FATBufSectors,FATBuf ) == 0 ) return 0; if( i >= ParamBlock.com.NumberOfFAT ) return 1; } int32 TFAT16::FlushFATBuf() { if( FATBufChanged == False ) return 0; for( int i=0; i< ParamBlock.com.NumberOfFAT; i++ ) Partition->Write( ParamBlock.com.ReservedSectors + ParamBlock.com.SectorsPerFAT*i + FATBufStartSector,FATBufSectors,FATBuf ); FATBufChanged = False; return 0; }