kerneltest/f32test/fileutils/src/fat_utils.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:26:05 +0100
branchRCL_3
changeset 136 743008598095
parent 81 e7d2d738d3c2
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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 <e32cons.h>
#include <e32math.h>

//-------------------------------------------------------------------------------------------------------------------

/**
    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<KSizeOfFSInfo> 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<KSizeOfFSInfo> 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<KSizeOfFatBootSector> 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<KDefaultSectorSize> 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 */
TUint 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  */
TUint32 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(TUint 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(TUint32 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];
    }