diff -r 000000000000 -r 96e5fb8b040d kerneltest/f32test/fileutils/src/fat_utils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/f32test/fileutils/src/fat_utils.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,1301 @@ +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// @file +// various FAT test utilities +// +// + + +#include "fat_utils.h" +using namespace Fat_Test_Utils; + + + +//------------------------------------------------------------------------------------------------------------------- + +//-- define this macro if it is necessarily to exclude all stuff that uses RFs, consoles etc. +//-- may be useful if this code is used for file server extensions. mmp file is a good place to define this macro. +#ifndef FAT_UTILS_LEAN_AND_MEAN + +#include +#include + +//------------------------------------------------------------------------------------------------------------------- + +/** + Format FAT volume + + @param aFs reference to the FS session + @param aDrive drive number + @param aQuickFormat if True, a quick format will be performed. otherwise - full + @param apFmtParams pointer to the optional format parameters. if NULL, it means tha no options specified + @param aForceErase if True, use media force erase. + + @return system-wide error codes. +*/ +TInt Fat_Test_Utils::FormatFatDrive(RFs &aFs, TInt aDrive, TBool aQuickFormat, const TFatFormatParam* apFmtParams/*=NULL*/, TBool aForceErase /*=EFalse*/) +{ + TPtrC fmtTypeName = (aQuickFormat ? _L("Quick") : _L("Full")); + DoPrintf(_L("~ Fat_Test_Utils::FormatFatDrive() drv:%d, type:%S\n"),aDrive, &fmtTypeName); + + ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ); + + RFormat format; + TUint fmtMode=0; + TInt fmtCnt=0; + TInt prevCnt; + TInt nRes; + + if(aQuickFormat) + fmtMode |= EQuickFormat; + + if(aForceErase) + fmtMode |= EForceErase; + + TBuf<10> drvName; + drvName.Format(_L("%C:"),'A'+aDrive); + + if(!apFmtParams) + {//-- no format parameters specified + //DoPrintf(_L("~ Format parameters - not specified\n")); + nRes = format.Open(aFs, drvName, fmtMode, fmtCnt); + if(nRes!=KErrNone) + goto Fail; + } + else + {//-- some extra parameters specified, use special format + fmtMode |= ESpecialFormat; + TLDFormatInfo formatInfo; + + TBuf<100> buf; + buf.Copy(_L("~ Format parameters: ")); + + if(apFmtParams->iFatType) + {//-- FAT type is specified + buf.AppendFormat(_L("FAT%d"), apFmtParams->iFatType); + formatInfo.iFATBits = (TLDFormatInfo::TFATBits)apFmtParams->iFatType; + } + + const TUint16 spc = (TUint16)apFmtParams->iSecPerCluster; + if(spc) + {//-- sectors per cluster value is specified + buf.AppendFormat(_L(", spc:%d"), spc); + formatInfo.iSectorsPerCluster = spc; + } + + const TUint16 rsvdSec = (TUint16)apFmtParams->iReservedSectors; + if(rsvdSec) + {//-- reserved sectors numer is specified + buf.AppendFormat(_L(", rsvdSec:%d"), rsvdSec); + formatInfo.iReservedSectors = rsvdSec; + } + + buf.Append(_L("\n")); + DoPrintf(buf); + + TSpecialFormatInfoBuf formatInfoBuf(formatInfo); + nRes = format.Open(aFs, drvName, fmtMode, fmtCnt, formatInfoBuf); + if(nRes!=KErrNone) + goto Fail; + + } + + //-- do format steps + prevCnt=fmtCnt; + while(fmtCnt) + { + nRes = format.Next(fmtCnt); + if(nRes!=KErrNone) + goto Fail; + + if(fmtCnt != prevCnt) + { + DoPrintf(_L(".")); + prevCnt = fmtCnt; + } + } + + //-- formatting has finished + DoPrintf(_L("\n")); + format.Close(); + return KErrNone; + + Fail: + format.Close(); + DoPrintf(_L("~ Fat_Test_Utils::FormatFatDrive() failed! code:%d\n"), nRes); + + return nRes; +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Read FAT FSInfo sector via RRawDisk interface. + @param aFs reference to the FS session + @param aDrive drive number + @param aMediaPos media position (0 for the main boot sector) + @param aFsInfo where to read data + + @return standard error codes +*/ +TInt Fat_Test_Utils::ReadFSInfoSector(RFs &aFs, TInt aDrive, TInt64 aMediaPos, TFSInfo& aFsInfo) +{ + DoPrintf(_L("~ Fat_Test_Utils::ReadFSInfoSector() drv:%d, pos:0x%x\n"),aDrive, (TUint32)aMediaPos); + + TInt nRes = KErrNone; + + TBuf8 fsInfoSecBuf(KSizeOfFSInfo); + TRAP(nRes, DoMediaRawReadL(aFs, aDrive, aMediaPos, fsInfoSecBuf.Size(), fsInfoSecBuf)); + + if(nRes == KErrNone) + {//-- take FSInfo data from the buffer + aFsInfo.Internalize(fsInfoSecBuf); + } + + return nRes; +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Write FAT FSInfo sector via RRawDisk interface. + @param aFs reference to the FS session + @param aDrive drive number + @param aMediaPos media position (0 for the main boot sector) + @param aFsInfo data to write + + @return standard error codes +*/ +TInt Fat_Test_Utils::WriteFSInfoSector(RFs &aFs, TInt aDrive, TInt64 aMediaPos, const TFSInfo& aFsInfo) +{ + DoPrintf(_L("~ Fat_Test_Utils::WriteFSInfoSector() drv:%d, pos:0x%x\n"),aDrive, (TUint32)aMediaPos); + + TInt nRes = KErrNone; + TBuf8 fsInfoSecBuf; + + //-- put data to the sector buffer + aFsInfo.Externalize(fsInfoSecBuf); + + TRAP(nRes, DoMediaRawWriteL(aFs, aDrive, aMediaPos, fsInfoSecBuf)) + + return nRes; +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Read FAT boot sector via RRawDisk interface. + @param aFs reference to the FS session + @param aDrive drive number + @param aMediaPos media position (0 for the main boot sector) + @param aBootSector where to read data + + @return standard error codes +*/ +TInt Fat_Test_Utils::ReadBootSector(RFs &aFs, TInt aDrive, TInt64 aMediaPos, TFatBootSector& aBootSector) +{ + DoPrintf(_L("~ Fat_Test_Utils::ReadBootSector() drv:%d, pos:0x%x\n"),aDrive, (TUint32)aMediaPos); + + TInt nRes = KErrNone; + TBuf8 bootSecBuf(KSizeOfFatBootSector); + + TRAP(nRes, DoMediaRawReadL(aFs, aDrive, aMediaPos, bootSecBuf.Size(), bootSecBuf)); + + if(nRes==KErrNone) + {//-- initialise TFatBootSector object + aBootSector.Internalize(bootSecBuf); + } + + return nRes; +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Write FAT boot sector via RRawDisk interface. + @param aFs reference to the FS session + @param aDrive drive number + @param aMediaPos media position (0 for the main boot sector) + @param aBootSector data to write + + @return standard error codes +*/ +TInt Fat_Test_Utils::WriteBootSector(RFs &aFs, TInt aDrive, TInt64 aMediaPos, const TFatBootSector& aBootSector) +{ + DoPrintf(_L("~ Fat_Test_Utils::WriteBootSector() drv:%d, pos:0x%x\n"),aDrive, (TUint32)aMediaPos); + + TBuf8 bootSecBuf(KDefaultSectorSize); + + //-- externalize boot sector to the data buffer + bootSecBuf.FillZ(); + aBootSector.Externalize(bootSecBuf); + + //-- put a boot sector signature to the last 2 bytes + bootSecBuf[KDefaultSectorSize-2] = 0x55; + bootSecBuf[KDefaultSectorSize-1] = 0xaa; + + //-- write boot sector data to the media + TInt nRes=KErrNone; + TRAP(nRes, DoMediaRawWriteL(aFs, aDrive, aMediaPos, bootSecBuf)); + + return nRes; +} +//------------------------------------------------------------------------------------------------------------------- +/** + Obtain FAT type for the given drive + + @return TFatType enum values. if aDrive has not FAT FS, EInvalid value is returned +*/ +TFatType Fat_Test_Utils::GetFatType(RFs &aFs, TInt aDrive) +{ + if(Is_Fat16(aFs, aDrive)) + return EFat16; + else if(Is_Fat32(aFs, aDrive)) + return EFat32; + else if(Is_Fat12(aFs, aDrive)) + return EFat12; + + return EInvalid; +} + +//------------------------------------------------------------------------------------------------------------------- + +#endif //FAT_UTILS_LEAN_AND_MEAN + + + + +TFatFormatParam::TFatFormatParam() +{ + iFatType = EInvalid; + iSecPerCluster = 0; + iReservedSectors = 0; +} + +//------------------------------------------------------------------------------------------------------------------- + +TFatBootSector::TFatBootSector() +{ + Initialise(); +} + +/** initialises the boot sector data */ +void TFatBootSector::Initialise() +{ + Mem::FillZ(this, sizeof(TFatBootSector)); +} + +TBool TFatBootSector::operator==(const TFatBootSector& aRhs) +{ + ASSERT(&aRhs != this); + if(&aRhs == this) + return ETrue; //-- comparing with itself + + return (Mem::Compare((TUint8*)this, sizeof(TFatBootSector), (TUint8*)&aRhs, sizeof(TFatBootSector)) == 0); +} + + +/** + @return ETrue if the boot sector contents seems to be valid +*/ +TBool TFatBootSector::IsValid() const +{ + const TFatType fatType = FatType(); //-- it will check SectorsPerCluster etc. + + if(fatType == EInvalid || ReservedSectors() < 1 || NumberOfFats() < 1) + goto Invalid; + + if(fatType == EFat32) + { + if(VersionNumber()!= 0 || FatSectors()!=0 || FatSectors32()<1 || RootClusterNum()<(TUint32)KFatFirstSearchCluser || + TotalSectors()!=0 || HugeSectors() <5 || RootDirEntries() !=0) + { + goto Invalid; //-- these values are not compliant with FAT specs + } + } + else //-- FAT12/16 + { + if(TotalSectors() >0 && HugeSectors() >0 ) + goto Invalid; //-- values clash + + const TUint32 totSectors = Max(TotalSectors(), HugeSectors()); + const TUint32 rootDirStartSec = ReservedSectors() + FatSectors()*NumberOfFats(); //-- root directory start sector + + if(FatSectors() < 1 || rootDirStartSec < 3 || RootDirEntries() < 1 || totSectors < 5) + goto Invalid; //-- these values are not compliant with FAT specs + } + + return ETrue; + + Invalid: + DoPrintf(_L("~ TFatBootSector::IsValid() failed!\n")); + + return EFalse; +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Initialize boot sector object from the given bufer. Does not validate the data. + @param aBuf buffer with data. +*/ +void TFatBootSector::Internalize(const TDesC8& aBuf) +{ + ASSERT(aBuf.Size() >= KSizeOfFatBootSector); + + Initialise(); + + TInt pos=0; + + Mem::Copy(&iJumpInstruction, &aBuf[pos],3); pos+=3; // 0 TUint8 iJumpInstruction[3] + Mem::Copy(&iVendorId,&aBuf[pos],KVendorIdSize); pos+=KVendorIdSize; // 3 TUint8 iVendorId[KVendorIdSize] + Mem::Copy(&iBytesPerSector,&aBuf[pos],2); pos+=2; // 11 TUint16 iBytesPerSector + Mem::Copy(&iSectorsPerCluster,&aBuf[pos],1); pos+=1; // 13 TUint8 iSectorsPerCluster + Mem::Copy(&iReservedSectors,&aBuf[pos],2); pos+=2; // 14 TUint16 iReservedSectors + Mem::Copy(&iNumberOfFats,&aBuf[pos],1); pos+=1; // 16 TUint8 iNumberOfFats + Mem::Copy(&iRootDirEntries,&aBuf[pos],2); pos+=2; // 17 TUint16 iRootDirEntries + Mem::Copy(&iTotalSectors,&aBuf[pos],2); pos+=2; // 19 TUint16 iTotalSectors + Mem::Copy(&iMediaDescriptor,&aBuf[pos],1); pos+=1; // 21 TUint8 iMediaDescriptor + Mem::Copy(&iFatSectors,&aBuf[pos],2); pos+=2; // 22 TUint16 iFatSectors + Mem::Copy(&iSectorsPerTrack,&aBuf[pos],2); pos+=2; // 24 TUint16 iSectorsPerTrack + Mem::Copy(&iNumberOfHeads,&aBuf[pos],2); pos+=2; // 26 TUint16 iNumberOfHeads + Mem::Copy(&iHiddenSectors,&aBuf[pos],4); pos+=4; // 28 TUint32 iHiddenSectors + Mem::Copy(&iHugeSectors,&aBuf[pos],4); pos+=4; // 32 TUint32 iHugeSectors + + if(RootDirEntries() == 0) //-- we have FAT32 volume + { + Mem::Copy(&iFatSectors32, &aBuf[pos],4); pos+=4; // 36 TUint32 iFatSectors32 + Mem::Copy(&iFATFlags, &aBuf[pos],2); pos+=2; // 40 TUint16 iFATFlags + Mem::Copy(&iVersionNumber, &aBuf[pos],2); pos+=2; // 42 TUint16 iVersionNumber + Mem::Copy(&iRootClusterNum, &aBuf[pos],4); pos+=4; // 44 TUint32 iRootClusterNum + Mem::Copy(&iFSInfoSectorNum, &aBuf[pos],2); pos+=2; // 48 TUint16 iFSInfoSectorNum + Mem::Copy(&iBkBootRecSector, &aBuf[pos],2); // 50 TUint16 iBkBootRecSector + pos+=(2+12); //extra 12 for the reserved bytes + } + + Mem::Copy(&iPhysicalDriveNumber,&aBuf[pos],1); pos+=1;// 36|64 TUint8 iPhysicalDriveNumber + Mem::Copy(&iReserved,&aBuf[pos],1); pos+=1;// 37|65 TUint8 iReserved + Mem::Copy(&iExtendedBootSignature,&aBuf[pos],1);pos+=1;// 38|66 TUint8 iExtendedBootSignature + Mem::Copy(&iUniqueID,&aBuf[pos],4); pos+=4;// 39|67 TUint32 iUniqueID + Mem::Copy(&iVolumeLabel,&aBuf[pos],KVolumeLabelSize); // 43|71 TUint8 iVolumeLabel[KVolumeLabelSize] + pos+=KVolumeLabelSize; + + // 54|82 TUint8 iFileSysType[KFileSysTypeSize] + ASSERT(aBuf.Size() >= pos+KFileSysTypeSize); + Mem::Copy(&iFileSysType,&aBuf[pos],KFileSysTypeSize); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Externalize boot sector object to the given data buffer. + @param aBuf buffer to externalize. +*/ +void TFatBootSector::Externalize(TDes8& aBuf) const +{ + ASSERT(aBuf.MaxSize() >= KSizeOfFatBootSector); + + if(aBuf.Size() < KSizeOfFatBootSector) + aBuf.SetLength(KSizeOfFatBootSector); + + TInt pos=0; + + Mem::Copy(&aBuf[pos],&iJumpInstruction,3); pos+=3; + Mem::Copy(&aBuf[pos],&iVendorId,KVendorIdSize); pos+=8; + Mem::Copy(&aBuf[pos],&iBytesPerSector,2); pos+=2; + Mem::Copy(&aBuf[pos],&iSectorsPerCluster,1); pos+=1; + Mem::Copy(&aBuf[pos],&iReservedSectors,2); pos+=2; + Mem::Copy(&aBuf[pos],&iNumberOfFats,1); pos+=1; + Mem::Copy(&aBuf[pos],&iRootDirEntries,2); pos+=2; + Mem::Copy(&aBuf[pos],&iTotalSectors,2); pos+=2; + Mem::Copy(&aBuf[pos],&iMediaDescriptor,1); pos+=1; + Mem::Copy(&aBuf[pos],&iFatSectors,2); pos+=2; + Mem::Copy(&aBuf[pos],&iSectorsPerTrack,2); pos+=2; + Mem::Copy(&aBuf[pos],&iNumberOfHeads,2); pos+=2; + Mem::Copy(&aBuf[pos],&iHiddenSectors,4); pos+=4; + Mem::Copy(&aBuf[pos],&iHugeSectors,4); pos+=4; + + if(iFatSectors == 0) + { + Mem::Copy(&aBuf[pos], &iFatSectors32,4); pos+=4; + Mem::Copy(&aBuf[pos], &iFATFlags, 2); pos+=2; + Mem::Copy(&aBuf[pos], &iVersionNumber, 2); pos+=2; + Mem::Copy(&aBuf[pos], &iRootClusterNum, 4); pos+=4; + Mem::Copy(&aBuf[pos], &iFSInfoSectorNum, 2);pos+=2; + Mem::Copy(&aBuf[pos], &iBkBootRecSector, 2);pos+=2; + + //extra 12 for the reserved bytes + ASSERT(aBuf.Size() >= pos+12); + Mem::FillZ(&aBuf[pos],12); + pos+=12; + } + + Mem::Copy(&aBuf[pos],&iPhysicalDriveNumber,1); pos+=1; + Mem::FillZ(&aBuf[pos],1); pos+=1; + Mem::Copy(&aBuf[pos],&iExtendedBootSignature,1);pos+=1; + Mem::Copy(&aBuf[pos],&iUniqueID,4); pos+=4; + + Mem::Copy(&aBuf[pos],&iVolumeLabel,KVolumeLabelSize); + pos+=KVolumeLabelSize; + + ASSERT(aBuf.MaxSize() >= pos+KFileSysTypeSize); + Mem::Copy(&aBuf[pos],&iFileSysType,KFileSysTypeSize); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** replaces all non-printable characters in a buffer with spaces */ +static void FixDes(TDes& aDes) +{ + for(TInt i=0; i< aDes.Length(); ++i) + { + TChar ch=aDes[i]; + if(!ch.IsPrint()) + aDes[i]=' '; + } +} + +/** + Print out the boot sector info. +*/ +void TFatBootSector::PrintDebugInfo() const +{ + TBuf<40> buf; + + DoPrintf(_L("======== BootSector info: =======\n")); + + buf.Copy(FileSysType()); FixDes(buf); + DoPrintf(_L("FAT type:%S\n"),&buf); + + buf.Copy(VendorId()); FixDes(buf); + DoPrintf(_L("Vendor ID:%S\n"),&buf); + + DoPrintf(_L("BytesPerSector: %d\n"),BytesPerSector()); + DoPrintf(_L("SectorsPerCluster: %d\n"),SectorsPerCluster()); + DoPrintf(_L("ReservedSectors: %d\n"),ReservedSectors()); + DoPrintf(_L("NumberOfFats: %d\n"),NumberOfFats()); + DoPrintf(_L("RootDirEntries: %d\n"),RootDirEntries()); + DoPrintf(_L("Total Sectors: %d\n"),TotalSectors()); + DoPrintf(_L("MediaDescriptor: 0x%x\n"),MediaDescriptor()); + DoPrintf(_L("FatSectors: %d\n"),FatSectors()); + DoPrintf(_L("SectorsPerTrack: %d\n"),SectorsPerTrack()); + DoPrintf(_L("NumberOfHeads: %d\n"),NumberOfHeads()); + DoPrintf(_L("HugeSectors: %d\n"),HugeSectors()); + DoPrintf(_L("Fat32 Sectors: %d\n"),FatSectors32()); + DoPrintf(_L("Fat32 Flags: %d\n"),FATFlags()); + DoPrintf(_L("Fat32 Version Number: %d\n"),VersionNumber()); + DoPrintf(_L("Root Cluster Number: %d\n"),RootClusterNum()); + DoPrintf(_L("FSInfo Sector Number: %d\n"),FSInfoSectorNum()); + DoPrintf(_L("Backup Boot Rec Sector Number: %d\n"),BkBootRecSector()); + DoPrintf(_L("PhysicalDriveNumber:%d\n"),PhysicalDriveNumber()); + DoPrintf(_L("ExtendedBootSignature: %d\n"),ExtendedBootSignature()); + DoPrintf(_L("UniqueID: 0x%x\n"),UniqueID()); + + buf.Copy(VolumeLabel()); FixDes(buf); + DoPrintf(_L("VolumeLabel:%S\n"),&buf); + + DoPrintf(_L("=============================\n")); +} + +//------------------------------------------------------------------------------------------------------------------- + + +/** + Determine FAT type according to the information from boot sector, see FAT32 specs. + @return FAT type. +*/ +TFatType TFatBootSector::FatType(void) const + { + + //-- check iBytesPerSector validity; it shall be one of: 512,1024,2048,4096 + if(!IsPowerOf2(iBytesPerSector) || iBytesPerSector < 512 || iBytesPerSector > 4096) + return EInvalid; //-- invalid iBytesPerSector value + + //-- check iSectorsPerCluster validity, it shall be one of: 1,2,4,8...128 + if(!IsPowerOf2(iSectorsPerCluster) || iSectorsPerCluster > 128) + return EInvalid; //-- invalid iSectorsPerCluster value + + const TUint32 rootDirSectors = (iRootDirEntries*KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector; + const TUint32 fatSz = iFatSectors ? iFatSectors : iFatSectors32; + const TUint32 totSec = iTotalSectors ? iTotalSectors : iHugeSectors; + const TUint32 dataSec = totSec - (iReservedSectors + (iNumberOfFats * fatSz) + rootDirSectors); + const TUint32 clusterCnt = dataSec / iSectorsPerCluster; + + //-- magic. see FAT specs for details. + if(clusterCnt < 4085) + return EFat12; + else if(clusterCnt < 65525) + return EFat16; + else + return EFat32; + + } + +//------------------------------------------------------------------------------------------------------------------- + +/** Returns Sectors in Fat table for 32 bit volume */ +TUint32 TFatBootSector::FatSectors32() const +{return iFatSectors32;} + +/** Fat flags */ +TUint16 TFatBootSector::FATFlags() const +{return iFATFlags;} + +/** Version number of the file system */ +TUint16 TFatBootSector::VersionNumber() const +{return iVersionNumber;} + +/** Cluster number of the root directory */ +TUint32 TFatBootSector::RootClusterNum() const +{return iRootClusterNum;} + +/** Sector number containing the FSIInfo structure */ +TUint16 TFatBootSector::FSInfoSectorNum() const +{return iFSInfoSectorNum;} + +/** Backup boot sector */ +TUint16 TFatBootSector::BkBootRecSector() const +{return iBkBootRecSector;} + +/** Sets the number of sectors in Fat table for 32 bit volume */ +void TFatBootSector::SetFatSectors32(TUint32 aFatSectors32) +{iFatSectors32 = aFatSectors32;} + +/** Sets the Fat flags */ +void TFatBootSector::SetFATFlags(TUint16 aFATFlags) +{iFATFlags = aFATFlags;} + +/** Sets the version number of the file system */ +void TFatBootSector::SetVersionNumber(TUint16 aVersionNumber) +{iVersionNumber = aVersionNumber;} + +/** Sets the cluster number of the root directory */ +void TFatBootSector::SetRootClusterNum(TUint32 aRootClusterNum) +{iRootClusterNum = aRootClusterNum;} + +/** Set the sector number containing the FSIInfo structure */ +void TFatBootSector::SetFSInfoSectorNum(TUint16 aFSInfoSectorNum) +{iFSInfoSectorNum = aFSInfoSectorNum;} + +/** Set the backup boot sector */ +void TFatBootSector::SetBkBootRecSector(TUint16 aBkBootRecSector) +{iBkBootRecSector = aBkBootRecSector;} + +/** Returns the vendor ID of the file system that formatted the volume */ +const TPtrC8 TFatBootSector::VendorId() const +{return TPtrC8(iVendorId,KVendorIdSize);} + +/** Return the bytes per sector */ +TUint16 TFatBootSector::BytesPerSector() const +{return iBytesPerSector;} + +/** Returns the sectors per cluster ratio */ +TInt TFatBootSector::SectorsPerCluster() const +{return iSectorsPerCluster;} + +/** Returns the number of reserved sectors on the volume */ +TInt TFatBootSector::ReservedSectors() const +{return iReservedSectors;} + +/** Returns the number of Fats on the volume */ +TInt TFatBootSector::NumberOfFats() const +{return iNumberOfFats;} + +/** Returns the number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32 */ +TInt TFatBootSector::RootDirEntries() const +{return iRootDirEntries;} + +/** Returns the total sectors on the volume, zero for FAT32 */ +TInt TFatBootSector::TotalSectors() const +{return iTotalSectors;} + +/** Returns the media descriptor */ +TUint8 TFatBootSector::MediaDescriptor() const +{return iMediaDescriptor;} + +/** Returns sectors used for the Fat table, zero for FAT32 */ +TInt TFatBootSector::FatSectors() const +{return iFatSectors;} + +/** Returns sectors per track */ +TInt TFatBootSector::SectorsPerTrack() const +{return iSectorsPerTrack;} + +/** Returns the number of heads */ +TInt TFatBootSector::NumberOfHeads() const +{return iNumberOfHeads;} + +/** Returns the number of hidden sectors in the volume */ +TInt TFatBootSector::HiddenSectors() const +{return iHiddenSectors;} + +/** Returns total sectors in the volume, Used if totalSectors > 65535 */ +TInt TFatBootSector::HugeSectors() const +{return iHugeSectors;} + +/** Returns the physical drive number, not used in Symbian OS */ +TInt TFatBootSector::PhysicalDriveNumber() const +{return iPhysicalDriveNumber;} + +/** Returns the extended boot signiture */ +TInt TFatBootSector::ExtendedBootSignature() const +{return iExtendedBootSignature;} + +/** Returns the unique volume ID */ +TUint32 TFatBootSector::UniqueID() const +{return iUniqueID;} + +/** Returns the volume's label */ +const TPtrC8 TFatBootSector::VolumeLabel() const +{return TPtrC8(iVolumeLabel,KVolumeLabelSize);} + +/** Returns the file system type */ +const TPtrC8 TFatBootSector::FileSysType() const +{return TPtrC8(iFileSysType,KFileSysTypeSize);} + +/** Returns the boot sector signiture */ +TInt TFatBootSector::BootSectorSignature() const +{return KBootSectorSignature;} + +/** Set the jump instruction */ +void TFatBootSector::SetJumpInstruction() +{iJumpInstruction[0]=0xE9;iJumpInstruction[2]=0x90;} + +/** Set the vendor ID of the file system that formatted the volume */ +void TFatBootSector::SetVendorID(const TDesC8& aDes) +{ + ASSERT(aDes.Length()<=KVendorIdSize); + TPtr8 buf(iVendorId,KVendorIdSize); + buf=aDes; +} + +/** Sets the bytes per sector */ +void TFatBootSector::SetBytesPerSector(TInt aBytesPerSector) +{ + ASSERT(!(aBytesPerSector&~KMaxTUint16)); + iBytesPerSector=(TUint16)aBytesPerSector; +} + +/** Set the sectors per cluster ratio */ +void TFatBootSector::SetSectorsPerCluster(TInt aSectorsPerCluster) +{ + ASSERT(!(aSectorsPerCluster&~KMaxTUint8)); + iSectorsPerCluster=(TUint8)aSectorsPerCluster; +} + + +/** Sets the number of reserved sectors on the volume */ +void TFatBootSector::SetReservedSectors(TInt aReservedSectors) +{ + ASSERT(!(aReservedSectors&~KMaxTUint16)); + iReservedSectors=(TUint16)aReservedSectors; +} + +/** Sets the number of Fats on the volume */ +void TFatBootSector::SetNumberOfFats(TInt aNumberOfFats) +{ + ASSERT(!(aNumberOfFats&~KMaxTUint8)); + iNumberOfFats=(TUint8)aNumberOfFats; +} + +/** Number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32 */ +void TFatBootSector::SetRootDirEntries(TInt aRootDirEntries) +{ + ASSERT(!(aRootDirEntries&~KMaxTUint16)); + iRootDirEntries=(TUint16)aRootDirEntries; +} + +/** Total sectors on the volume, zero for FAT32 */ +void TFatBootSector::SetTotalSectors(TInt aTotalSectors) +{ + ASSERT(!(aTotalSectors&~KMaxTUint16)); + iTotalSectors=(TUint16)aTotalSectors; +} + +/** Set the media descriptor */ +void TFatBootSector::SetMediaDescriptor(TUint8 aMediaDescriptor) +{iMediaDescriptor=aMediaDescriptor;} + +/** Sectors used for the Fat table, zero for FAT32 */ +void TFatBootSector::SetFatSectors(TInt aFatSectors) +{ + ASSERT(!(aFatSectors&~KMaxTUint16)); + iFatSectors=(TUint16)aFatSectors; +} + +/** Set the sectors per track */ +void TFatBootSector::SetSectorsPerTrack(TInt aSectorsPerTrack) +{ + ASSERT(!(aSectorsPerTrack&~KMaxTUint16)); + iSectorsPerTrack=(TUint16)aSectorsPerTrack; +} + +/** Set the number of heads */ +void TFatBootSector::SetNumberOfHeads(TInt aNumberOfHeads) +{ + ASSERT(!(aNumberOfHeads&~KMaxTUint16)); + iNumberOfHeads=(TUint16)aNumberOfHeads; +} + +/** Set the number of hidden sectors in the volume */ +void TFatBootSector::SetHiddenSectors(TUint32 aHiddenSectors) +{ + iHiddenSectors=(TUint32)(aHiddenSectors); +} + +/** Set the total sectors in the volume, Used if totalSectors > 65535 */ +void TFatBootSector::SetHugeSectors(TUint32 aHugeSectors) +{iHugeSectors=aHugeSectors;} + + +/** Physical drive number, not used in Symbian OS */ +void TFatBootSector::SetPhysicalDriveNumber(TInt aPhysicalDriveNumber) +{ + ASSERT(!(aPhysicalDriveNumber&~KMaxTUint8)); + iPhysicalDriveNumber=(TUint8)aPhysicalDriveNumber; +} + +/** Set the reserved byte value */ +void TFatBootSector::SetReservedByte(TUint8 aReservedByte) +{iReserved=aReservedByte;} + +/** Set the extended boot signiture */ +void TFatBootSector::SetExtendedBootSignature(TInt anExtendedBootSignature) +{ + ASSERT(!(anExtendedBootSignature&~KMaxTUint8)); + iExtendedBootSignature=(TUint8)anExtendedBootSignature; +} + +/** Set the unique volume ID */ +void TFatBootSector::SetUniqueID(TUint32 anUniqueID) +{iUniqueID=anUniqueID;} + +/** Set the volume's label */ +void TFatBootSector::SetVolumeLabel(const TDesC8& aDes) +{ + ASSERT(aDes.Length()<=KVolumeLabelSize); + TPtr8 buf(iVolumeLabel,KVolumeLabelSize); + buf=aDes; +} + +/** Set the file system type */ +void TFatBootSector::SetFileSysType(const TDesC8& aDes) +{ + ASSERT(aDes.Length()<=8); + TPtr8 buf(iFileSysType,8); + buf=aDes; +} + + +/** @return The first Fat sector number */ +TInt TFatBootSector::FirstFatSector() const +{ + __ASSERT_ALWAYS(IsValid(), User::Invariant()); + return ReservedSectors(); +} + +/** + @return Number of sectors in root directory. 0 for FAT32 +*/ +TUint32 TFatBootSector::RootDirSectors() const +{ + __ASSERT_ALWAYS(IsValid(), User::Invariant()); + return ( (RootDirEntries()*KSizeOfFatDirEntry + (BytesPerSector()-1)) / BytesPerSector() ); +} + + +/** @return Start sector number of the root directory */ +TInt TFatBootSector::RootDirStartSector() const +{ + __ASSERT_ALWAYS(IsValid(), User::Invariant()); + + const TUint32 firstNonFatSec = ReservedSectors() + TotalFatSectors()*NumberOfFats(); + + if(FatType() == EFat32) + {//-- FAT32 root dir is a file, calculate the position by it's 1st cluster number. FAT[0]+FAT[1] are reserved. + return (firstNonFatSec + (RootClusterNum()-KFatFirstSearchCluser) * SectorsPerCluster()); + } + else + {//-- FAT12/16 root dir starts just after the FATs + return firstNonFatSec; + } + +} + +/** @return first data sector number. for FAT32 it includes the root directory */ +TInt TFatBootSector::FirstDataSector() const +{ + return( ReservedSectors() + NumberOfFats()*TotalFatSectors() + RootDirSectors() ); +} + +/** @return FAT-type independent sector count on the volume */ +TUint32 TFatBootSector::VolumeTotalSectorNumber() const +{ + __ASSERT_ALWAYS(IsValid(), User::Invariant()); + return HugeSectors() ? (TUint32)HugeSectors() : (TUint32)TotalSectors(); +} + +/** @return FAT-type independent number of sectors in one FAT */ +TUint32 TFatBootSector::TotalFatSectors() const +{ + __ASSERT_ALWAYS(IsValid(), User::Invariant()); + return FatSectors32() ? FatSectors32() : (TUint32)FatSectors(); +} + + +//------------------------------------------------------------------------------------------------------------------- + + +const TUint32 KLeadSignature = 0x41615252; ///< FSInfo Lead signiture value +const TUint32 KStructureSignature = 0x61417272; ///< FSInfo Structure signiture value +const TUint32 KTrailingSignature = 0xAA550000; ///< FSInfo Trailing signiture + +TFSInfo::TFSInfo() +{ + Initialise(); +} +//------------------------------------------------------------------------------------------------------------------- + +/** Initialise the data */ +void TFSInfo::Initialise() +{ + Mem::FillZ(this, sizeof(TFSInfo)); + + iLeadSig = KLeadSignature; + iStructureSig = KStructureSignature; + iTrainlingSig = KTrailingSignature; +} + + +TBool TFSInfo::operator==(const TFSInfo& aRhs) +{ + ASSERT(&aRhs != this); + if(&aRhs == this) + return ETrue; //-- comparing with itself + + return (Mem::Compare((TUint8*)this, sizeof(TFSInfo), (TUint8*)&aRhs, sizeof(TFSInfo)) == 0); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + @return ETrue if FSInfo sector contents seems to be valid +*/ +TBool TFSInfo::IsValid() const +{ + return (iLeadSig == KLeadSignature && iStructureSig == KStructureSignature && iTrainlingSig == KTrailingSignature); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Initialize FSInfo sector object from the given bufer. Does not validate the data. + @param aBuf buffer with data. +*/ +void TFSInfo::Internalize(const TDesC8& aBuf) +{ + ASSERT((TUint32)aBuf.Size() >= KSizeOfFSInfo); + + TInt pos=0; + + Mem::Copy(&iLeadSig, &aBuf[pos],4); pos+=(KFSInfoReserved1Size+4); + Mem::Copy(&iStructureSig, &aBuf[pos],4); pos+=4; + Mem::Copy(&iFreeCount,&aBuf[pos],4); pos+=4; + Mem::Copy(&iNextFree,&aBuf[pos],4); pos+=(4+KFSInfoReserved2Size); + Mem::Copy(&iTrainlingSig,&aBuf[pos],4); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Externalize FSInfo sector object to the given data buffer. + @param aBuf buffer to externalize. +*/ +void TFSInfo::Externalize(TDes8& aBuf) const +{ + ASSERT((TUint32)aBuf.MaxSize() >= KSizeOfFSInfo); + + aBuf.SetLength(KSizeOfFSInfo); + aBuf.FillZ(); + + TInt pos=0; + + Mem::Copy(&aBuf[pos],&KLeadSignature,4); pos+=4; + pos+=KFSInfoReserved1Size; + Mem::Copy(&aBuf[pos],&KStructureSignature,4); pos+=4; + Mem::Copy(&aBuf[pos],&iFreeCount,4); pos+=4; + Mem::Copy(&aBuf[pos],&iNextFree,4); pos+=4; + pos+=KFSInfoReserved2Size; + Mem::Copy(&aBuf[pos],&KTrailingSignature,4); +} + +//------------------------------------------------------------------------------------------------------------------- + +/** + Print out the FSInfo sector info. +*/ +void TFSInfo::PrintDebugInfo() const +{ + DoPrintf(_L("==== FSInfoSector : ====\n")); + DoPrintf(_L("FSI_LeadSig: 0x%x\n"),iLeadSig); + DoPrintf(_L("FSI_StrucSig: 0x%x\n"),iStructureSig); + DoPrintf(_L("FSI_FreeCount: 0x%x\n"),iFreeCount); + DoPrintf(_L("FSI_NxtFree: 0x%x\n"),iNextFree); + DoPrintf(_L("FSI_TrailSig: 0x%x\n"),iTrainlingSig); + DoPrintf(_L("========================\n")); +} + +TUint32 TFSInfo::FreeClusterCount() const +{ + return iFreeCount; +} + +TUint32 TFSInfo::NextFreeCluster() const +{ + return iNextFree; +} + + +void TFSInfo::SetFreeClusterCount(TUint32 aFreeCount) +{ + iFreeCount = aFreeCount; +} + +void TFSInfo::SetNextFreeCluster(TUint32 aNextCluster) +{ + iNextFree = aNextCluster; +} + + +//------------------------------------------------------------------------------------------------------------------- + +/** + Deciphers the dos time/date entry information and converts to TTime +*/ +TTime Fat_Test_Utils::DosTimeToTTime(TInt aDosTime,TInt aDosDate) + { + TInt secMask=0x1F; + TInt minMask=0x07E0; + TInt hrMask=0xF800; + TInt dayMask=0x1F; + TInt monthMask=0x01E0; + TInt yearMask=0xFE00; + + TInt secs=(aDosTime&secMask)*2; + TInt mins=(aDosTime&minMask)>>5; + TInt hrs=(aDosTime&hrMask)>>11; + TInt days=(aDosDate&dayMask)-1; + TMonth months=(TMonth)(((aDosDate&monthMask)>>5)-1); + TInt years=((aDosDate&yearMask)>>9)+1980; + + TDateTime datetime; + TInt ret=datetime.Set(years,months,days,hrs,mins,secs,0); + if (ret==KErrNone) + return(TTime(datetime)); + return(TTime(0)); + } + +/** +Converts a TTime to a dos time +*/ +TInt Fat_Test_Utils::DosTimeFromTTime(const TTime& aTime) + { + TDateTime dateTime=aTime.DateTime(); + TInt dosSecs=dateTime.Second()/2; + TInt dosMins=dateTime.Minute()<<5; + TInt dosHrs=dateTime.Hour()<<11; + return dosSecs|dosMins|dosHrs; + } + +/** +Converts a TTime to a dos date +*/ +TInt Fat_Test_Utils::DosDateFromTTime(const TTime& aTime) + { + + TDateTime dateTime=aTime.DateTime(); + TInt dosDays=dateTime.Day()+1; + TInt dosMonths=(dateTime.Month()+1)<<5; + TInt dosYears=(dateTime.Year()-1980)<<9; + return dosDays|dosMonths|dosYears; + } + + +/** +Converts xxx.yyy to standard format aaaaaaaayyy +*/ +TBuf8<12> Fat_Test_Utils::DosNameToStdFormat(const TDesC8& aDosName) + { + ASSERT(aDosName.Length()>=0 && aDosName.Length()<=KMaxFatFileName); + + TBuf8<12> result; + Mem::Fill((TUint8*)result.Ptr(),result.MaxSize(),' '); + TInt dotPos=aDosName.Locate('.'); + if (dotPos==KErrNotFound) + { + result=aDosName; + result.SetLength(11); + return result; + } + result=aDosName.Left(dotPos); + result.SetLength(11); + TPtr8 ext(&result[8],3); + ext=aDosName.Right(aDosName.Length()-dotPos-1); + return result; + } + +/** +Converts aaaaaaaayyy to dos name format xxx.yyy +*/ +TBuf8<12> Fat_Test_Utils::DosNameFromStdFormat(const TDesC8& aStdFormatName) + { + ASSERT(aStdFormatName.Length()==11); + + TBuf8<12> result; + TInt nameLen=aStdFormatName.Locate(' '); + if (nameLen>8 || nameLen==KErrNotFound) + nameLen=8; + result=aStdFormatName.Left(nameLen); + TPtrC8 ext(&aStdFormatName[8],3); + TInt extLen=ext.Locate(' '); + if (extLen) + result.Append(TChar('.')); + if (extLen==KErrNotFound) + extLen=3; + result.Append(ext.Left(extLen)); + if(result.Length() && result[0]==0x05 ) + { + result[0]=0xE5; + } + return result; + } + +/** +Return the number of VFat entries required to describe a filename of length aNameLength +*/ +TInt Fat_Test_Utils::NumberOfVFatEntries(TInt aNameLength) + { + TInt numberOfEntries=0; + if (aNameLength%KMaxVFatEntryName) + aNameLength++; // Include a zero terminator +// If aNameLength is a exact multiple of KMaxVFatEntryName, don't bother +// with a zero terminator - it just adds an unnecessary directory entry + + numberOfEntries=(1+(aNameLength/KMaxVFatEntryName)); + + if (aNameLength%KMaxVFatEntryName) + numberOfEntries++; + + return(numberOfEntries); + } + +/** +Calculate a checksum to tie the vFat and dos names together +*/ +TUint8 Fat_Test_Utils::CalculateShortNameCheckSum(const TDesC8& aShortName) + { + + TUint8 cksum=0; + for (TInt i=0;i<11;i++) + cksum =(TUint8)((((cksum&1)<<7)|((cksum&0xfe)>>1))+aShortName[i]); + + return(cksum); + } + + +//------------------------------------------------------------------------------------------------------------------- + + +#define pDir ((SFatDirEntry*)&iData[0]) +const TUint8 KEntryErasedMarker=0xE5; + + +TFatDirEntry::TFatDirEntry() + { + InitZ(); + } + +/** zero-fill the entry contents */ +void TFatDirEntry::InitZ() + { + Mem::FillZ(iData, KSizeOfFatDirEntry); + } + + +/** +@return ETrue if the Directory entry contains garbage data +*/ +TBool TFatDirEntry::IsGarbage() const + { + return (iData[0]==0xFF); + } + +/** +Return the Dos name of a directory entry +@return A descriptor containing the Dos name of a directory entry +*/ +const TPtrC8 TFatDirEntry::Name() const + {return TPtrC8((TUint8*)&(pDir->iName),KFatDirNameSize);} + +/** @return The attributes for the Directory entry */ +TInt TFatDirEntry::Attributes() const + {return pDir->iAttributes;} + +/** @return Time of file creation */ +TTime TFatDirEntry::Time() const + {return DosTimeToTTime(pDir->iTime,pDir->iDate);} + +/** @return The Start cluster for the file or directory for this entry */ +TInt TFatDirEntry::StartCluster() const + { + const TUint16 KStClustMaskHi = 0x0FFF; + return ((pDir->iStartClusterHi&KStClustMaskHi)<<16) | pDir->iStartClusterLo; + } + +/** @return The size of file or directory for this entry */ +TUint32 TFatDirEntry::Size() const + {return pDir->iSize;} + +/** @return True if the entry is erased */ +TBool TFatDirEntry::IsErased() const + {return (TBool)(iData[0]==KEntryErasedMarker);} + +/** @return True if the entry refers to the current directory */ +TBool TFatDirEntry::IsCurrentDirectory() const + {return (TBool)(iData[0]==KDotEntryByte && iData[1]==KBlankSpace);} + +/** @return True if the Entry refers to the parent directory */ +TBool TFatDirEntry::IsParentDirectory() const + {return (TBool)(iData[0]==KDotEntryByte && iData[1]==KDotEntryByte);} + +/** @return True if end of directory */ +TBool TFatDirEntry::IsEndOfDirectory() const + {return (TBool)(iData[0]==0x00);} + +/** +Set the Dos name of a directory entry +@param aDes A descriptor containg the name +*/ +void TFatDirEntry::SetName(const TDesC8& aDes) + { + ASSERT(aDes.Length()<=KFatDirNameSize); + TPtr8 name(pDir->iName,KFatDirNameSize); + name=aDes; + } + +/** +Set the file or directory attributes for this entry +@param anAtts The file or directory attributes +*/ +void TFatDirEntry::SetAttributes(TInt anAtts) + { + ASSERT(!(anAtts&~KMaxTUint8)); + pDir->iAttributes=(TUint8)anAtts; + } + +/** +Set the creation time and data of the directory entry +@param aTime Creation time of the file or directory +*/ +void TFatDirEntry::SetTime(TTime aTime) + { + pDir->iTime=(TUint16)DosTimeFromTTime(aTime); + pDir->iDate=(TUint16)DosDateFromTTime(aTime); + } + +void TFatDirEntry::SetCreateTime(TTime aTime) + { + pDir->iTimeC=(TUint16)DosTimeFromTTime(aTime); + pDir->iDateC=(TUint16)DosDateFromTTime(aTime); + } + +/** +Set the start cluster number of the file or directory refered to by the entry +@param aStartCluster The start cluster number +*/ +void TFatDirEntry::SetStartCluster(TInt aStartCluster) + { + const TUint32 KHalfWordMask = 0x0000FFFF; + pDir->iStartClusterLo=(TUint16)(aStartCluster & KHalfWordMask); + pDir->iStartClusterHi=(TUint16)((aStartCluster>>16) & KHalfWordMask); + } + +/** +Set the size of the file or directory refered to by the entry +@param aFileSize Size of the file +*/ +void TFatDirEntry::SetSize(TUint32 aFileSize) + {pDir->iSize=aFileSize;} + +/** Set the directory entry as erased */ +void TFatDirEntry::SetErased() + {iData[0]=KEntryErasedMarker;} + +/** Set the current entry to refer to the current directory */ +void TFatDirEntry::SetCurrentDirectory() + { + iData[0]='.'; + Mem::Fill(&iData[1],KFatDirNameSize-1,' '); + } + +/** Set the current entry to refer to the parent directory */ +void TFatDirEntry::SetParentDirectory() + { + iData[0]='.';iData[1]='.'; + Mem::Fill(&iData[2],KFatDirNameSize-2,' '); + } + +/** Set the current entry to be the end of directory marker */ +void TFatDirEntry::SetEndOfDirectory() + {Mem::FillZ(&iData[0],KFatDirNameSize);} + +/** @return True if the entry is the start of a long name set of entries */ +TBool TFatDirEntry::IsLongNameStart() const + {return (TBool)((iData[0]&0x40) != 0);} + +/** @return True is the Entry is a VFat entry */ +TBool TFatDirEntry::IsVFatEntry() const + {return (TBool)(Attributes()==KVFatEntryAttribute && IsEndOfDirectory()==EFalse);} + +/** @return The number of following VFat entries */ +TInt TFatDirEntry::NumFollowing() const + {return (iData[0]&0x3F);} + + +TUint8 TFatDirEntry::CheckSum() const + { + ASSERT(IsVFatEntry()); + return iData[13]; + } + + + + + + + + + + + + + + + + + + + + +