--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/filesystem/fat/t_tscan32.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,2055 @@
+// Copyright (c) 1998-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:
+// f32test\scndrv\t_tscan32.cpp
+//
+//
+
+#include <f32file.h>
+#include <e32test.h>
+
+#include "t_server.h"
+
+#include "fat_utils.h"
+using namespace Fat_Test_Utils;
+
+/*
+Series of tests to check that the combination of a ruggedised fat file
+system and scandisk prevents the file system from becoming corrupt in the
+event of a power failure. CheckDisk is used to test that directory
+structure is not corrupt. This test is only suitable with a drive that uses
+the fat file system but not the internal ram drive (due to the indirection)
+table. Only works with debug builds due to RFs::ControlIo only debug function
+*/
+
+GLDEF_D TFileName StartupExeName=_L(""); // initialised at run time
+
+#ifdef _DEBUG
+GLREF_D RTest test;
+GLDEF_D TInt TheFunctionNumber;
+GLDEF_D TInt TheOpNumber;
+GLDEF_D TInt TheFailCount;
+GLDEF_D TBool IsReset;
+GLDEF_D TFileName TestExeName=_L("?:\\T_SCANDR.EXE"); //Renaming it to fit in one root dir entry.
+GLDEF_D TFileName LogFileName=_L("?:\\T_SCANDR.LOG"); //Renaming it to fit in one root dir entry.
+
+const TInt KControlIoWriteFailOn=0; // commands to pass into RFs::ControlIo
+const TInt KControlIoWriteFailOff=1;
+const TInt KMaxFatEntries = 2048;
+const TInt KDirAttrReadOnly = 0x01;
+const TInt KDirAttrHidden = 0x02;
+const TInt KDirAttrSystem = 0x04;
+const TInt KDirAttrVolumeId = 0x08;
+const TInt KDirAttrDirectory = 0x10;
+const TInt KDirAttrArchive = 0x20;
+const TInt KDirAttrLongName = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
+const TInt KDirAttrLongMask = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
+const TInt KDirLastLongEntry = 0x40;
+
+GLDEF_D TInt WriteFailValue;
+
+LOCAL_C TFatBootSector BootSector;
+LOCAL_D RRawDisk TheRawDisk;
+
+static TFatType gDiskType = EInvalid;
+
+LOCAL_D TInt gTotalSectors;
+LOCAL_D TInt gBytesPerCluster;
+LOCAL_D TInt gRootDirSectors;
+LOCAL_D TInt gRootDirEntries;
+LOCAL_D TInt gRootDirStart;
+LOCAL_D TInt gRootSector;
+LOCAL_D TInt gFatStartBytes;
+LOCAL_D TInt gFatTestEntries;
+LOCAL_D TInt gFatSizeSectors;
+LOCAL_D TInt gFirstDataSector;
+LOCAL_D TInt gDataStartBytes;
+LOCAL_D TInt gClusterCount;
+
+LOCAL_D HBufC8* gFatBuf = NULL;
+LOCAL_D TInt gFatAddr = -1;
+
+enum TFatChain {EChainStd,EChainAlternate,EChainBackwards,EChainForwards};
+
+LOCAL_C TBool IsInternalRam()
+//
+// Returns true if the selected drive is variable size (i.e. RAM drive)
+//
+ {
+ TVolumeInfo v;
+ TInt r=TheFs.Volume(v,gSessionPath[0]-'A');
+ test(r==KErrNone);
+ return(v.iDrive.iMediaAtt&KMediaAttVariableSize);
+ }
+
+LOCAL_C void WriteLogFile()
+//
+// Writes state of test to end of LogFileName
+//
+ {
+ test.Printf(_L("Writelogfile()\n"));
+ RFile log;
+ TInt r=log.Open(TheFs,LogFileName,EFileShareExclusive|EFileWrite);
+ if(r!=KErrNone)
+ test.Printf(_L("error=%d\n"),r);
+ test(r==KErrNone);
+ TInt size;
+ r=log.Size(size);
+ test(r==KErrNone);
+ TBuf8<16> buf;
+ buf.SetLength(4);
+ buf[0]=(TUint8)TheFunctionNumber;
+ buf[1]=(TUint8)TheOpNumber;
+ buf[2]=(TUint8)TheFailCount;
+ buf[3]='\n';
+ r=log.Write(size,buf,buf.Length());
+ test(r==KErrNone);
+ test.Printf(_L("Written func=%d,op=%d,fail=%d\n"),TheFunctionNumber,TheOpNumber,TheFailCount);
+ log.Close();
+ }
+
+LOCAL_C TInt SetWriteFailOn(TInt aFailCount)
+//
+// Sets write to metadata to fail on aFailCount with WriteFailValue
+//
+ {
+ TInt16 args[2];
+ TPtr8 des((TUint8*)args,4,4);
+ args[0]=(TUint16)aFailCount;
+ args[1]=(TUint16)WriteFailValue;
+ TInt r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOn,des);
+ return(r);
+ }
+
+GLDEF_C void ReadLogFile()
+//
+// Reads state of test from end of LogFileName and sets global variables
+//
+ {
+ test.Next(_L("ReadLogFile"));
+ RFile log;
+ TInt r=log.Open(TheFs,LogFileName,EFileShareExclusive);
+ if(r!=KErrNone)
+ test.Printf(_L("error in ReadLogFile()=%d\n"),r);
+ test(r==KErrNone);
+ test(r==KErrNone);
+ TInt fileSize;
+ r=log.Size(fileSize);
+ if(fileSize==0)
+ {
+ TheFunctionNumber=0;
+ TheOpNumber=0;
+ TheFailCount=0;
+ }
+ else
+ {
+ TBuf8<4> buf;
+ r=log.Read(fileSize-4,buf,4);
+ TheFunctionNumber=buf[0];
+ TheOpNumber=buf[1];
+ TheFailCount=buf[2];
+ }
+ log.Close();
+ test.Printf(_L("func=%d,op=%d,fail=%d\n"),TheFunctionNumber,TheOpNumber,TheFailCount);
+ }
+
+LOCAL_C TUint32 MaxClusters()
+ //
+ // Return the number of data clusters on the disk
+ //
+ {
+ TUint32 totSec = (BootSector.TotalSectors() ? BootSector.TotalSectors() : BootSector.HugeSectors());
+ TUint32 numSec = totSec - gFirstDataSector;
+ return numSec / BootSector.SectorsPerCluster();
+ }
+
+LOCAL_C TInt ClusterToByte(TInt aCluster)
+ //
+ // converts cluster number to byte offset on disk
+ //
+ {
+ TInt sector = (aCluster - 2) * gBytesPerCluster + gFirstDataSector * BootSector.BytesPerSector();
+ return sector;
+ }
+
+/**
+ Fill media with zeroes from aStartPos to aEndPos
+*/
+static void DoZeroFillMedia(TInt64 aStartPos, TInt64 aEndPos, RRawDisk& aWriter)
+{
+ test(aStartPos >=0 && aEndPos >=0 && aStartPos < aEndPos);
+
+ if(aStartPos == aEndPos)
+ return;
+
+ RBuf8 buf;
+ TInt nRes;
+
+ const TUint32 KBufSz=65536*2; //-- buffer with zeroes
+
+ nRes = buf.CreateMax(KBufSz);
+ test(nRes == KErrNone);
+
+ buf.FillZ();
+
+ TUint32 rem = (TUint32)(aEndPos - aStartPos);
+ while(rem)
+ {
+ const TUint32 bytesToWrite=Min(rem, KBufSz);
+
+ TPtrC8 ptr(buf.Ptr(), bytesToWrite);
+ nRes = aWriter.Write(aStartPos, ptr);
+ test(nRes == KErrNone || nRes == KErrDiskFull);
+
+ aStartPos+=bytesToWrite;
+ rem-=bytesToWrite;
+ }
+
+
+ buf.Close();
+}
+
+//
+// Clear the disk data area to a known value which won't be confused with
+// directory entries etc.
+//
+LOCAL_C void ClearDiskData()
+ {
+
+ TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
+ test(r==KErrNone);
+
+ TUint32 startPos = gDataStartBytes;
+ if (gDiskType == EFat32)
+ startPos += gBytesPerCluster;
+
+ const TUint32 endPos = startPos + gFatTestEntries*gBytesPerCluster;
+
+ test.Printf(_L("ClearDiskData() from pos:%u to pos:%u\n"), startPos, endPos);
+
+ DoZeroFillMedia(startPos, endPos, TheRawDisk);
+
+ TheRawDisk.Close();
+ }
+
+LOCAL_C TInt PosInBytes(TInt aFatIndex)
+//
+// Return number of bytes into the FAT
+//
+ {
+ TInt fatPosInBytes = -1;
+ switch (gDiskType)
+ {
+ case EFat32:
+ fatPosInBytes=aFatIndex<<2;
+ break;
+ case EFat16:
+ fatPosInBytes=aFatIndex<<1;
+ break;
+ case EFat12:
+ fatPosInBytes=(aFatIndex*3>>1);
+ break;
+ default:
+ test(0);
+ }
+ return(fatPosInBytes);
+ }
+
+static void DoReadBootSector()
+ {
+
+ TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<<KDefaultSectorLog2, BootSector);
+ test(nRes == KErrNone);
+
+ if(!BootSector.IsValid())
+ {
+ test.Printf(_L("Wrong bootsector! Dump:\n"));
+ BootSector.PrintDebugInfo();
+ test(0);
+ }
+ // Calculate derived variables (fixed for a particular disk format)
+ gBytesPerCluster = BootSector.BytesPerSector() * BootSector.SectorsPerCluster();
+ gRootDirSectors = ((BootSector.RootDirEntries() * KSizeOfFatDirEntry + BootSector.BytesPerSector() - 1) / BootSector.BytesPerSector());
+ gFatStartBytes = BootSector.ReservedSectors() * BootSector.BytesPerSector();
+ gFatSizeSectors = (BootSector.FatSectors() ? BootSector.FatSectors() : BootSector.FatSectors32());
+ gRootSector = BootSector.ReservedSectors() + BootSector.NumberOfFats() * gFatSizeSectors;
+ gRootDirStart = gRootSector * BootSector.BytesPerSector();
+ gFirstDataSector = gRootSector + gRootDirSectors;
+
+ gFatTestEntries = MaxClusters();
+ if (gFatTestEntries > KMaxFatEntries)
+ gFatTestEntries = KMaxFatEntries;
+
+ if (BootSector.RootDirEntries() == 0)
+ {
+ test.Printf(_L("**** Is Fat32\n"));
+ gDiskType = EFat32;
+ gRootDirEntries = BootSector.RootDirEntries();
+ }
+ else if (BootSector.FatType() == EFat16)
+ {
+ test.Printf(_L("**** Is Fat16\n"));
+ gDiskType = EFat16;
+ gRootDirEntries = BootSector.RootDirEntries();
+ }
+ else
+ {
+ test.Printf(_L("**** Is Fat12\n"));
+ gDiskType = EFat12;
+ gRootDirEntries = gBytesPerCluster * 1 / KSizeOfFatDirEntry;
+ }
+ gTotalSectors = (BootSector.TotalSectors() ? BootSector.TotalSectors() : BootSector.HugeSectors());
+ gClusterCount = (gTotalSectors - gFirstDataSector) / BootSector.SectorsPerCluster();
+ gDataStartBytes = gFirstDataSector * BootSector.BytesPerSector();
+ }
+
+GLDEF_C TUint32 GetFatEntry(TUint32 aIndex, const TUint8* aFat=NULL)
+//
+// Read a single FAT entry from disk or FAT copy and return it
+//
+ {
+
+
+ if (!gFatBuf)
+ {
+ gFatBuf=HBufC8::New(gBytesPerCluster);
+ test(gFatBuf!=NULL);
+ gFatAddr = -1;
+ }
+
+ const TUint8* ptr;
+
+ if (aFat)
+ {
+ ptr = (TUint8*)aFat + PosInBytes(aIndex);
+ }
+ else
+ {
+ TInt pos = PosInBytes(aIndex) + gFatStartBytes;
+ if (gFatAddr < 0 || pos < gFatAddr || pos >= gFatAddr + gBytesPerCluster)
+ {
+ TPtr8 ptr=gFatBuf->Des();
+ TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
+ test(r==KErrNone);
+ r=TheRawDisk.Read(pos, ptr);
+ test(r==KErrNone);
+ TheRawDisk.Close();
+ gFatAddr = pos;
+ }
+ ptr = gFatBuf->Ptr() + pos-gFatAddr;
+ }
+
+ TUint32 val = 0;
+ switch (gDiskType)
+ {
+ case EFat32:
+ val = *(TUint32*)ptr;
+ break;
+ case EFat16:
+ val = *(TUint16*)ptr;
+ break;
+ case EFat12:
+ val = *(TUint16*)ptr;
+ if (aIndex & 1)
+ val >>= 4;
+ val &= 0xFFF;
+ break;
+ default:
+ test(0);
+ }
+ return val;
+ }
+
+GLDEF_C void DumpBootSector()
+//
+// Display (in log) TFatBootSector structure
+//
+ {
+ RDebug::Print(_L("iBytesPerSector = %8d"), BootSector.BytesPerSector());
+ RDebug::Print(_L("iSectorsPerCluster = %8d"), BootSector.SectorsPerCluster());
+ RDebug::Print(_L("iReservedSectors = %8d"), BootSector.ReservedSectors());
+ RDebug::Print(_L("iNumberOfFats = %8d"), BootSector.NumberOfFats());
+ RDebug::Print(_L("iRootDirEntries = %8d"), BootSector.RootDirEntries());
+ RDebug::Print(_L("iTotalSectors = %8d"), BootSector.TotalSectors());
+ RDebug::Print(_L("iMediaDescriptor = %8d"), BootSector.MediaDescriptor());
+ RDebug::Print(_L("iFatSectors = %8d"), BootSector.FatSectors());
+ RDebug::Print(_L("iSectorsPerTrack = %8d"), BootSector.SectorsPerTrack());
+ RDebug::Print(_L("iNumberOfHeads = %8d"), BootSector.NumberOfHeads());
+ RDebug::Print(_L("iHiddenSectors = %8d"), BootSector.HiddenSectors());
+ RDebug::Print(_L("iHugeSectors = %8d"), BootSector.HugeSectors());
+
+ //New for FAT32
+
+ if(BootSector.RootDirEntries() == 0) //indicates we have FAT32 volume
+ {
+ RDebug::Print(_L("FatSectors32 = %8d"), BootSector.FatSectors32());
+ RDebug::Print(_L("FATFlags = %8d"), BootSector.FATFlags());
+ RDebug::Print(_L("VersionNumber = %8d"), BootSector.VersionNumber());
+ RDebug::Print(_L("RootClusterNum = %8d (0x%08X)"), BootSector.RootClusterNum(), gRootDirStart);
+ RDebug::Print(_L("FSInfoSectorNum = %8d (0x%08X)"), BootSector.FSInfoSectorNum(), BootSector.FSInfoSectorNum() * BootSector.BytesPerSector());
+ RDebug::Print(_L("BkBootRecSector = %8d (0x%08X)"), BootSector.BkBootRecSector(), BootSector.BkBootRecSector() * BootSector.BytesPerSector());
+ }
+ TInt fatEntries = gFatSizeSectors*BootSector.BytesPerSector();
+ switch (gDiskType)
+ {
+ case EFat32:
+ fatEntries /= 4;
+ break;
+ case EFat16:
+ fatEntries /= 2;
+ break;
+ case EFat12:
+ fatEntries *= 3;
+ fatEntries /= 2;
+ break;
+ default:
+ test(0);
+ }
+ RDebug::Print(_L("ClusterCount = %8d (%d bytes)"), gClusterCount, gClusterCount*gBytesPerCluster);
+ RDebug::Print(_L("FatEntries = %8d (%d sectors)"), fatEntries, gFatSizeSectors);
+ RDebug::Print(_L("RootSector = %8d (0x%08X)"), gRootSector, gRootDirStart);
+ RDebug::Print(_L("FirstDataSector = %8d (0x%08X)"), gFirstDataSector, gDataStartBytes);
+ }
+
+GLDEF_C void DumpFat(const TUint8* aFat=NULL)
+//
+// Dump to the log all those FAT entries which are non-zero
+//
+ {
+ TInt32 max = MaxClusters();
+ if (max > KMaxFatEntries)
+ max = KMaxFatEntries;
+ RDebug::Print(_L("---------------- DUMP OF FAT ---------------"));
+ for (TInt32 i = 0; i < max; i++)
+ {
+ TInt32 val = GetFatEntry(i, aFat);
+ TInt32 msk = 0x0FFFFFFF;
+ switch (gDiskType)
+ {
+ case EFat32:
+ msk = 0x0FFFFFFF;
+ break;
+ case EFat16:
+ msk = 0xFFFF;
+ break;
+ case EFat12:
+ msk = 0x0FFF;
+ break;
+ default:
+ test(0);
+ }
+ if ((val & msk) == (0x0FFFFFFF & msk))
+ RDebug::Print(_L(" %8d -> EOC"), i);
+ else if ((val & msk) == (0x0FFFFFF8 & msk))
+ RDebug::Print(_L(" %8d -> Media"), i);
+ else if ((val & msk) == (0x0FFFFFF7 & msk))
+ RDebug::Print(_L(" %8d -> BAD"), i);
+ else if (val > max)
+ RDebug::Print(_L(" %8d -> 0x%08X"), i, val);
+ else if (val != 0)
+ RDebug::Print(_L(" %8d -> %d"), i, val);
+ }
+ RDebug::Print(_L("--------------------------------------------"));
+ }
+
+GLDEF_C TDes* DirAttributes(TInt aAttrib)
+//
+// Return a pointer to a local buffer containing the attribute letters.
+//
+ {
+ LOCAL_D TBuf<6> str(_L("------"));
+ LOCAL_D char* atr = "RHSVDA";
+ for (TInt i = 0; i < 6; i++)
+ if ((aAttrib >> i) & 1)
+ str[i] = atr[i];
+ return &str;
+ }
+
+GLDEF_C TBool IsValidDirChar(TUint8 aChar, TUint8 aMin=0x20)
+//
+// Test whether a character is valid as part of a short filename, aMin is to
+// distinguish between first character (which can't be space) and later ones
+// which can include space but nothing less. Note that E5 is a valid character
+// in any position, even though it means 'erased' in the first character.
+//
+ {
+ const TUint8* inval = (TUint8*)"\x22\x2A\x2B\x2C\x2E\x2F\x3A\x3B\x3C\x3D\x3E\x3F\x5B\x5C\x5D\x7C";
+ if (aChar < aMin)
+ return EFalse;
+ for (const TUint8* p = inval; *p; p++)
+ if (aChar == *p)
+ return EFalse;
+ return ETrue;
+ }
+
+GLDEF_C TBool IsValidDirEntry(TFatDirEntry* aDir)
+//
+// Test whether buffer is a valid normal directory entry
+//
+ {
+ // top two bits of attributes must be zero
+ if (aDir->iData[11] & 0xC0)
+ return EFalse;
+ // first character must be 0x05 or greater than space
+ if (!IsValidDirChar(aDir->iData[0], 0x21) && aDir->iData[0] != 0x05)
+ return EFalse;
+ // other characters in name must be not less than space
+ for (TInt i = 1; i < 11; i++)
+ if (!IsValidDirChar(aDir->iData[i]))
+ return EFalse;
+ return ETrue;
+ }
+
+GLDEF_C void GetLongNamePart(TDes16& aName, const TUint8* aEntry, TInt aPos, TInt aOffset, TInt aLength)
+//
+// Extract part of a long name entry into the name buffer.
+//
+// @param aName buffer to put name
+// @param aEntry directory entry raw data
+// @param aPos character in buffer to start name segment
+// @param aOffset offset in directory entry of the segment
+// @param aLength number of characters in the segment
+//
+ {
+ for (TInt i = 0; i < aLength; i++)
+ {
+ TInt at = i * 2 + aOffset;
+ TInt ch = aEntry[at] + aEntry[at+1] * 256;
+ aName[aPos++] = TText(ch);
+ }
+ }
+
+GLDEF_C void ExtractNameString(TDes16& aName, const TUint8* aEntry)
+//
+// Extract a long name part from a directory entry, truncate it at the first
+// NUL (0) character and put quotes round it.
+//
+ {
+ aName.SetLength(15);
+ TInt len = aName.Length() - 1;
+ TText qu = '\'';
+ aName[0] = qu;
+ GetLongNamePart(aName, aEntry, 1, 1, 5);
+ GetLongNamePart(aName, aEntry, 6, 14, 6);
+ GetLongNamePart(aName, aEntry, 12, 28, 2);
+ TInt i;
+ for (i = 0; i < len; i++)
+ if (aName[i] == 0)
+ break;
+ aName[i++] = qu;
+ aName.SetLength(i);
+ }
+
+GLDEF_C TBool DumpDirEntry(TInt aNum, const TUint8* aEntry)
+//
+// Dump a single directory entry to the log. Return false if it was end of
+// directory or an invalid entry (and don't display it).
+//
+ {
+ TFatDirEntry* d = (TFatDirEntry*)aEntry;
+ if (d->IsErased())
+ {
+ // RDebug::Print(_L("%5d: ERASED"), aNum);
+ }
+ else if (d->IsEndOfDirectory())
+ return EFalse;
+ else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+ {
+ TBuf16<15> name;
+ ExtractNameString(name, aEntry);
+ TInt ord = aEntry[0];
+ if (ord & KDirLastLongEntry)
+ RDebug::Print(_L("%5d: %-15S #%-2d LAST"), aNum, &name, ord & ~KDirLastLongEntry);
+ else
+ RDebug::Print(_L("%5d: %-15S #%-2d"), aNum, &name, ord & ~KDirLastLongEntry);
+ }
+ else if (!IsValidDirEntry(d))
+ return EFalse;
+ else
+ {
+ TBuf<11> name;
+ name.Copy(d->Name());
+ RDebug::Print(_L("%5d: '%S' %S cluster %d"),
+ aNum, &name, DirAttributes(d->Attributes()), d->StartCluster());
+ }
+ return ETrue;
+ }
+
+GLDEF_C void DumpDirCluster(const TUint8* aData, TInt aCluster=0)
+//
+// Dump directory entries until end of cluster or invalid/end entry found.
+//
+ {
+ if (aCluster > 2)
+ aData += (aCluster-2) * gBytesPerCluster;
+ for (TInt i = 0; i < gBytesPerCluster; i += KSizeOfFatDirEntry)
+ {
+ if (DumpDirEntry(i/KSizeOfFatDirEntry, aData))
+ aData += KSizeOfFatDirEntry;
+ else
+ break;
+ }
+ }
+
+GLDEF_C void DumpData(const TUint8* aFat, TInt aStart, TInt aEnd)
+//
+// Dump clusters from disk (allows dumping of clusters not in our buffers).
+// Only look at clusters marked as 'used' in the FAT. Note that if aFat is
+// NULL the FAT entries will also be read from disk (slower but allows for ones
+// outside our copy in memory).
+//
+ {
+ if (aStart > gFatTestEntries)
+ return;
+ RDebug::Print(_L("--------------- DATA AREA ------------------"));
+ if (aEnd > gFatTestEntries)
+ aEnd = gFatTestEntries;
+ for (TInt cluster = aStart; cluster < aEnd; cluster++)
+ {
+ if (GetFatEntry(cluster, aFat) != 0)
+ {
+ HBufC8* buf=HBufC8::New(gBytesPerCluster);
+ test(buf!=NULL);
+ TPtr8 ptr=buf->Des();
+ TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
+ test(r==KErrNone);
+ r=TheRawDisk.Read(ClusterToByte(cluster), ptr);
+ test(r==KErrNone);
+ TheRawDisk.Close();
+ RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster));
+ DumpDirCluster(ptr.Ptr());
+ delete buf;
+ }
+ }
+ RDebug::Print(_L("--------------------------------------------"));
+ }
+
+GLDEF_C void DumpHex(const TUint8* aData, TInt aLen)
+//
+// Dump a block of memory to the log in hex.
+//
+ {
+ for (TInt base = 0; base < aLen; base += 16)
+ {
+ TBuf<16*3> buf;
+ TInt off;
+ for (off = base; off < aLen && off < base + 16; off++)
+ {
+ buf.Append(TText(' '));
+ buf.AppendNumFixedWidth(aData[off], EHex, 2);
+ }
+ RDebug::Print(_L("%04X: %S"), off, &buf);
+ }
+ }
+
+static void QuickFormat()
+ {
+ /*
+ TFatFormatParam fmt;
+ fmt.iFatType = EFat32;
+ fmt.iSecPerCluster =1;
+ FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fmt);
+ */
+ FormatFatDrive(TheFs, CurrentDrive(), ETrue);
+ }
+
+
+LOCAL_C void MakeVeryLongName(TFileName& aLong)
+//
+// appends a very long file name to aLong
+//
+ {
+ // create a name to take up 18 vfat entries - (1 sector + 2 entries)
+ for(TInt i=0;i<234;++i)
+ {
+ TInt c='a'+i%26;
+ aLong.Append(c);
+ }
+ }
+
+LOCAL_C void MakeEntryName(TFileName& aName,TInt aLength)
+//
+// Appends aLength characters to aName
+//
+ {
+ for(TInt i=0;i<aLength;++i)
+ {
+ TInt c='A'+i%26;
+ aName.Append(c);
+ }
+ }
+
+LOCAL_C void FillUpRootDir(TInt aFree=0)
+//
+// Fill up root directory
+//
+ {
+ TInt maxRootEntries = gRootDirEntries -aFree;
+ TFileName dir=_L("\\??\\");
+ TInt count=0;
+ TInt entriesSoFar;
+ if(IsReset)
+ entriesSoFar=2+2+2+2; // \\t_scn32dr3.exe + \\sys + \\t_scn32dr3.log + \\f32-tst
+ else
+ entriesSoFar=0;
+ TInt r;
+ while(entriesSoFar<maxRootEntries)
+ {
+ dir[1]=TUint16(count/26+'a');
+ dir[2]=TUint16(count%26+'a');
+ r=TheFs.MkDir(dir);
+ test(r==KErrNone);
+ entriesSoFar+=2;
+ ++count;
+ }
+ }
+
+LOCAL_C void UnFillUpRootDir(TInt aFree=0)
+//
+// Reverse changes from FillUpRootDir()
+//
+ {
+ TFileName dir=_L("\\??\\");
+ TInt entriesSoFar=gRootDirEntries -aFree;
+ TInt count=0;
+ TInt r;
+ TInt existing;
+ if(IsReset)
+ existing=2+2+2+2; // \\t_scn32dr3.exe + \\sys + \\t_scn32dr3.log + \\f32-tst
+ else
+ existing=0;
+ while(entriesSoFar>existing)
+ {
+ dir[1]=TUint16(count/26+'a');
+ dir[2]=TUint16(count%26+'a');
+ r=TheFs.RmDir(dir);
+ test(r==KErrNone);
+ entriesSoFar-=2;
+ ++count;
+ }
+ }
+
+void InitialiseWriteBuffer(TDes8& buf)
+//
+//
+//
+ {
+ for(TInt i=0;i<buf.Length();++i)
+ buf[i]=(TUint8)('a'+i%26);
+ }
+
+LOCAL_C TBool EntryExists(const TDesC& aName)
+//
+// Returns ETrue if aName is found
+//
+ {
+ TEntry entry;
+ TInt r=TheFs.Entry(aName,entry);
+ test(r==KErrNone||r==KErrNotFound);
+ return(r==KErrNone?(TBool)ETrue:(TBool)EFalse);
+ }
+
+LOCAL_C TInt EntriesPerFatSector()
+//
+// Returns number of entries in one fat table sector
+//
+ {
+ switch (gDiskType)
+ {
+ case EFat32:
+ return(BootSector.BytesPerSector()/4);
+ case EFat16:
+ return(BootSector.BytesPerSector()/2);
+ case EFat12:
+ return(BootSector.BytesPerSector()*2/3);
+ default:
+ test(0);
+ }
+ return -1;
+ }
+
+LOCAL_C TBool OneEntryExists(const TDesC& aOldName,const TDesC& aNewName)
+//
+// Returns ETrue if only one of two entries exists
+//
+ {
+ TBool oldExists=EntryExists(aOldName);
+ TBool newExists=EntryExists(aNewName);
+ return((!oldExists&&newExists)||(oldExists&&!newExists));
+ }
+
+LOCAL_C void GetEntryDetails(const TDesC& aName,TEntry& aEntry)
+//
+// returns entry details for the entry with aName
+//
+ {
+ TInt r=TheFs.Entry(aName,aEntry);
+ test(r==KErrNone);
+ }
+
+LOCAL_C TBool IsSameEntryDetails(TEntry aOldEntry,TEntry aNewEntry)
+//
+//
+//
+ {
+ return(aOldEntry.iAtt==aNewEntry.iAtt&&aOldEntry.iSize==aNewEntry.iSize&&aOldEntry.iModified==aNewEntry.iModified);
+ }
+
+LOCAL_C void CreateAlternate(const TDesC& aNameOne,const TDesC& aNameTwo)
+//
+// Creates altenate entries which take up one sector of fat table.
+// By subsequently deleting one of these entries a new entry can be made
+// with cluster chain that is not contiguous.
+//
+ {
+ TInt entries=EntriesPerFatSector();
+ RFile file1,file2;
+ TInt size1,size2;
+ size1=size2=0;
+ TInt r=file1.Create(TheFs,aNameOne,EFileShareAny);
+ test(r==KErrNone);
+ r=file2.Create(TheFs,aNameTwo,EFileShareAny);
+ test(r==KErrNone);
+ // one entry for file1 for every 40 entries for file2
+ // if file 1 subseqently deleted then 7 entries available
+ // in that fat sector - ~3.5kb file size - for fat16
+ TInt ratio=40;
+ TBool first=ETrue;
+ while(entries>0)
+ {
+ if(first)
+ {
+ size1+=gBytesPerCluster;
+ r=file1.SetSize(size1);
+ test(r==KErrNone);
+ first=EFalse;
+ --entries;
+ }
+ else
+ {
+ size2+=gBytesPerCluster*ratio;
+ r=file1.SetSize(size1);
+ test(r==KErrNone);
+ first=ETrue;
+ entries-=ratio;
+ }
+ }
+ file1.Close();
+ file2.Close();
+ }
+
+LOCAL_C TInt ThrottleDirEntries(TInt aDirEntries)
+ {
+ // throttle the number of entries needed, since for large cluster
+ // sizes, this can take forever (eg 2GB card -> a cluster size of 32K
+ // -> 1024 entries per cluster
+ const TInt KMaxDirEntries = 2048;
+ if (aDirEntries > KMaxDirEntries)
+ {
+ RDebug::Print(_L("Reducing directory entries from %d to %d"),
+ aDirEntries, KMaxDirEntries);
+ aDirEntries = KMaxDirEntries;
+ }
+ return aDirEntries;
+ }
+
+
+LOCAL_C void CleanDirectory(const TDesC& aName,TInt aClusters)
+//
+// Removes entries in the directory
+//
+ {
+ if (aClusters < 1)
+ return;
+ TInt entriesPerCluster=gBytesPerCluster/32;
+ TInt entriesNeeded = entriesPerCluster * aClusters;
+
+ entriesNeeded = ThrottleDirEntries(entriesNeeded);
+
+ TInt maxFileNameLen = 250 - aName.Length();
+ TInt nameEntries = 1 + (maxFileNameLen+12) / 13;
+ TInt namesNeeded = (entriesNeeded + nameEntries-1) / nameEntries;
+ TInt entry = 0;
+ for(TInt i = 0; i < namesNeeded; ++i)
+ {
+ if (entriesNeeded - entry < nameEntries)
+ maxFileNameLen = (entriesNeeded - entry - 1) * 13;
+ TFileName fn;
+ fn.AppendNum(entry);
+ fn.Append('_');
+ while (fn.Length() < maxFileNameLen)
+ fn.Append('0');
+ TFileName fullName(aName);
+ fullName.Append(fn);
+ TInt r = TheFs.Delete(fullName);
+ test(r == KErrNone);
+ entry += 1 + (fn.Length() + 12) / 13;
+ }
+ RDebug::Print(_L("CleanDirectory(%S, %d)"), &aName, aClusters);
+ }
+
+LOCAL_C void ExpandDirectory(const TDesC& aName,TInt aClusters)
+//
+// Expands the directory by aClusters
+//
+ {
+ if (aClusters < 1)
+ return;
+ TInt entriesPerCluster=gBytesPerCluster/32;
+ TInt entriesNeeded = entriesPerCluster * aClusters;
+
+ entriesNeeded = ThrottleDirEntries(entriesNeeded);
+
+ TInt maxFileNameLen = 250 - aName.Length();
+ TInt nameEntries = 1 + (maxFileNameLen+12) / 13;
+ TInt namesNeeded = (entriesNeeded + nameEntries-1) / nameEntries;
+ TInt entry = 0;
+ for(TInt i = 0; i < namesNeeded; ++i)
+ {
+ if (entriesNeeded - entry < nameEntries)
+ maxFileNameLen = (entriesNeeded - entry - 1) * 13;
+ TFileName fn;
+ fn.AppendNum(entry);
+ fn.Append('_');
+ while (fn.Length() < maxFileNameLen)
+ fn.Append('0');
+ TFileName fullName(aName);
+ fullName.Append(fn);
+ RFile file;
+ TInt r = file.Create(TheFs,fullName,EFileShareAny);
+ test(r == KErrNone);
+ file.Close();
+ entry += 1 + (fn.Length() + 12) / 13;
+ }
+ // to leave a directory expanded by aClusters but with no additional entries
+ RDebug::Print(_L("ExpandDirectory(%S, %d)"), &aName, aClusters);
+ CleanDirectory(aName,aClusters);
+ }
+
+LOCAL_C TInt DeleteAlternateEntry(const TDesC& aName,TBool aIsDir)
+//
+// Deletes entry aName and corresponding entries created for EChainAlternate
+//
+ {
+ TInt r=TheFs.Delete(_L("\\fat\\file2"));
+ test(r==KErrNone||KErrNotFound);
+ if(aIsDir)
+ return(TheFs.RmDir(aName));
+ else
+ return(TheFs.Delete(aName));
+ }
+
+LOCAL_C TInt CreateAlternateEntry(const TDesC& aName,TBool aIsDir,TInt aSize)
+//
+// Creates entry with aName where cluster chain grows forward but not contiguously.
+// Assumes that no holes in fat clusters.
+//
+ {
+ TInt r=DeleteAlternateEntry(aName,aIsDir);
+ test(r==KErrNone||r==KErrNotFound);
+ RFile file;
+ if(aIsDir)
+ {
+ r=TheFs.MkDir(aName);
+ if(r!=KErrNone)
+ return(r);
+ }
+ else
+ {
+ r=file.Create(TheFs,aName,EFileShareAny);
+ if(r!=KErrNone)
+ return(r);
+ r=file.SetSize(1); //ensure file allocated a start cluster
+ test(r==KErrNone);
+ }
+ CreateAlternate(_L("\\fat\\file1"),_L("\\fat\\file2"));
+ r=TheFs.Delete(_L("\\fat\\file1"));
+ test(r==KErrNone);
+ if(aIsDir)
+ ExpandDirectory(aName,aSize);
+ else
+ {
+ r=file.SetSize(aSize);
+ test(r==KErrNone);
+ file.Close();
+ }
+ return(KErrNone);
+ }
+
+LOCAL_C TInt DeleteForwardEntry(const TDesC& aName,TBool aIsDir)
+//
+// Deletes entry with aName and corresponding entries created for EChainForward
+//
+ {
+ TInt r=TheFs.Delete(_L("\\fat\\file2"));
+ test(r==KErrNone||r==KErrNotFound);
+ r=TheFs.Delete(_L("\\fat\\file4"));
+ test(r==KErrNone||r==KErrNotFound);
+ r=TheFs.Delete(_L("\\fat\\file5"));
+ test(r==KErrNone||r==KErrNotFound);
+ if(aIsDir)
+ r=TheFs.RmDir(aName);
+ else
+ r=TheFs.Delete(aName);
+ return r;
+ }
+
+LOCAL_C TInt CreateForwardEntry(const TDesC& aName,TBool aIsDir,TInt aSize)
+//
+// Creates an entry whose cluster chain first goes forward (upto 3.5kb for fat16 file)
+// and then backwards
+//
+ {
+ TInt r=DeleteForwardEntry(aName,aIsDir);
+ test(r==KErrNone||r==KErrNotFound);
+ RFile file1,file2,entry;
+ r=file1.Create(TheFs,_L("\\fat\\file1"),EFileShareAny);
+ test(r==KErrNone);
+ r=file1.SetSize(EntriesPerFatSector()*gBytesPerCluster);
+ test(r==KErrNone);
+ r=file2.Create(TheFs,_L("\\fat\\file2"),EFileShareAny);
+ test(r==KErrNone);
+ r=file2.SetSize(EntriesPerFatSector()*gBytesPerCluster);
+ test(r==KErrNone);
+ if(aIsDir)
+ {
+ r=TheFs.MkDir(aName);
+ if(r!=KErrNone)
+ return(r);
+ }
+ else
+ {
+ r=entry.Create(TheFs,aName,EFileShareAny);
+ if(r!=KErrNone)
+ return(r);
+ r=entry.SetSize(1); // ensure entry has start cluster allocated
+ test(r==KErrNone);
+ }
+ CreateAlternate(_L("\\fat\\file3"),_L("\\fat\\file4"));
+ RFile file5;
+ r=file5.Create(TheFs,_L("\\fat\\file5"),EFileShareAny);
+ test(r==KErrNone);
+ r=file5.SetSize(EntriesPerFatSector()*gBytesPerCluster*2);
+ test(r==KErrNone);
+ file1.Close();
+ file2.Close();
+ file5.Close();
+ r=TheFs.Delete(_L("\\fat\\file1"));
+ test(r==KErrNone);
+ r=TheFs.Delete(_L("\\fat\\file3"));
+ test(r==KErrNone);
+ if(aIsDir)
+ ExpandDirectory(aName,aSize);
+ else
+ {
+ r=entry.SetSize(aSize);
+ test(r==KErrNone);
+ entry.Close();
+ }
+ return(KErrNone);
+ }
+
+LOCAL_C TInt DeleteBackwardEntry(const TDesC& aName,TBool aIsDir)
+//
+// Deletes entry with aName and corresponding entries created for EChainBackwards
+//
+ {
+ TInt r=TheFs.Delete(_L("\\fat\\file2"));
+ test(r==KErrNone||r==KErrNotFound);
+ r=TheFs.Delete(_L("\\fat\\file3"));
+ test(r==KErrNone||r==KErrNotFound);
+ if(aIsDir)
+ r=TheFs.RmDir(aName);
+ else
+ r=TheFs.Delete(aName);
+ return r;
+ }
+
+LOCAL_C TInt CreateBackwardEntry(const TDesC& aName,TBool aIsDir,TInt aSize)
+//
+// Creates an entry whose fat cluster chain first goes backwards(upto 3.5kb for fat16 file)
+// and then forwards
+//
+ {
+ TInt r=DeleteBackwardEntry(aName,aIsDir);
+ test(r==KErrNone||r==KErrNotFound);
+ CreateAlternate(_L("\\fat\\file1"),_L("\\fat\\file2"));
+ RFile entry;
+ if(aIsDir)
+ {
+ r=TheFs.MkDir(aName);
+ if(r!=KErrNone)
+ return(r);
+ }
+ else
+ {
+ r=entry.Create(TheFs,aName,EFileShareAny);
+ if(r!=KErrNone)
+ return(r);
+ r=entry.SetSize(1);
+ test(r==KErrNone);
+ }
+ RFile file3;
+ r=file3.Create(TheFs,_L("\\fat\\file3"),EFileShareAny);
+ test(r==KErrNone);
+ r=file3.SetSize(EntriesPerFatSector()*gBytesPerCluster);
+ test(r==KErrNone);
+ r=TheFs.Delete(_L("\\fat\\file1"));
+ test(r==KErrNone);
+ file3.Close();
+ if(aIsDir)
+ ExpandDirectory(aName,aSize);
+ else
+ {
+ r=entry.SetSize(aSize);
+ test(r==KErrNone);
+ entry.Close();
+ }
+ return(KErrNone);
+ }
+
+LOCAL_C TInt DeleteStdEntry(const TDesC& aName,TBool aIsDir)
+//
+// Deletes entry with aName
+//
+ {
+ if(aIsDir)
+ return(TheFs.RmDir(aName));
+ else
+ return(TheFs.Delete(aName));
+ }
+
+LOCAL_C TInt CreateStdEntry(const TDesC& aName,TBool aIsDir,TInt aSize)
+//
+// Creates entry with aName where the cluster chain grows contiguously
+//
+ {
+ TInt r=DeleteStdEntry(aName,aIsDir);
+ test(r==KErrNone||r==KErrNotFound);
+ if(aIsDir)
+ {
+ r=TheFs.MkDir(aName);
+ if(r==KErrNone)
+ ExpandDirectory(aName,aSize);
+ return(r);
+ }
+ else
+ {
+ RFile file;
+ r=file.Create(TheFs,aName,EFileShareAny);
+ if(r==KErrNone)
+ {
+ r=file.SetSize(aSize);
+ test(r==KErrNone);
+ }
+ else if(r==KErrAlreadyExists)
+ {
+ TInt res =file.Open(TheFs,aName,EFileShareAny);
+ test(res==KErrNone);
+ }
+ else
+ return(r);
+ file.Close();
+ return(r);
+ }
+ }
+
+LOCAL_C TInt CreateEntry(const TDesC& aName,TBool aIsDir,TFatChain aChain,TInt aSize)
+//
+// Creates entry with aName whose fat cluster chain characteristics determined by aChain
+//
+ {
+ switch(aChain)
+ {
+ case(EChainStd):return(CreateStdEntry(aName,aIsDir,aSize));
+ case(EChainAlternate):return(CreateAlternateEntry(aName,aIsDir,aSize));
+ case(EChainBackwards):return(CreateBackwardEntry(aName,aIsDir,aSize));
+ case(EChainForwards):return(CreateForwardEntry(aName,aIsDir,aSize));
+ default:return(KErrGeneral);
+ }
+ }
+
+LOCAL_C TInt DeleteEntry(const TDesC& aName,TBool aIsDir,TFatChain aChain)
+//
+// Delete entry with aName
+//
+ {
+ switch(aChain)
+ {
+ case(EChainStd):return(DeleteStdEntry(aName,aIsDir));
+ case(EChainAlternate):return(DeleteAlternateEntry(aName,aIsDir));
+ case(EChainBackwards):return(DeleteBackwardEntry(aName,aIsDir));
+ case(EChainForwards):return(DeleteForwardEntry(aName,aIsDir));
+ default:return(KErrGeneral);
+ }
+ }
+
+LOCAL_C void TestRFsDelete(const TDesC& aName,TFatChain aChain,TInt aFileSize)
+//
+// test RFs::Delete
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Start(_L("TestRFsDelete"));
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=TheFs.Delete(aName);
+ if(r==KErrNone)
+ break;
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(!EntryExists(aName));
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFsRmDir(const TDesC& aName,TFatChain aChain,TInt aDirSize)
+//
+// test RFs::RmDir
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFsRmDir"));
+ switch (aChain)
+ {
+ case EChainStd:
+ RDebug::Print(_L("Chain Std %S size %d"), &aName, aDirSize);
+ break;
+ case EChainAlternate:
+ RDebug::Print(_L("Chain Alternate %S size %d"), &aName, aDirSize);
+ break;
+ case EChainBackwards:
+ RDebug::Print(_L("Chain Backwards %S size %d"), &aName, aDirSize);
+ break;
+ case EChainForwards:
+ RDebug::Print(_L("Chain Forwards %S size %d"), &aName, aDirSize);
+ break;
+ default:
+ break;
+ }
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aName,ETrue,aChain,aDirSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=TheFs.RmDir(aName);
+ if(r==KErrNone)
+ break;
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ RDebug::Print(_L("%6d: ScanDrive = %d"), __LINE__, r);
+ if (r != KErrNone)
+ {
+ RDebug::Print(_L("ScanDrive fail %d"), r);
+ DumpFat();
+ DumpData(NULL, 0, 200);
+ }
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ RDebug::Print(_L("%6d: CheckDisk = %d"), __LINE__, r);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(!EntryExists(aName));
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFsMkDir(const TDesC& aName)
+//
+// test RFs::MkDir
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFsMkDir"));
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=DeleteEntry(aName,ETrue,EChainStd);
+ test(r==KErrNone||r==KErrNotFound);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=TheFs.MkDir(aName);
+ if(r==KErrNone)
+ break;
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aName));
+ r=DeleteEntry(aName,ETrue,EChainStd);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFsRename(const TDesC& aOldName,const TDesC& aNewName,TBool aIsDir,TFatChain aChain,TInt aSize)
+//
+// test RFs::Rename
+//
+ {
+ test.Next(_L("TestRFsRename"));
+ TInt failCount=TheFailCount;
+ TInt r;
+ TEntry oldEntryInfo,newEntryInfo;
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aOldName,aIsDir,aChain,aSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ r=DeleteEntry(aNewName,aIsDir,aChain);
+ test(r==KErrNone||r==KErrNotFound);
+ GetEntryDetails(aOldName,oldEntryInfo);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=TheFs.Rename(aOldName,aNewName);
+ if(r==KErrNone)
+ break;
+ if(r!=WriteFailValue)
+ {
+ test.Printf(_L("r=%d\n"),r);
+ test(EFalse);
+ }
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ // no start cluster if aSize==0
+ if(aSize!=0)
+ test(OneEntryExists(aOldName,aNewName));
+ ++failCount;
+ }
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aNewName) && !EntryExists(aOldName));
+ GetEntryDetails(aNewName,newEntryInfo);
+ test(IsSameEntryDetails(oldEntryInfo,newEntryInfo));
+ r=DeleteEntry(aNewName,aIsDir,aChain);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFsReplace(const TDesC& aOldName, const TDesC& aNewName,TBool aBothExist,TFatChain aChain,TInt aFileSize)
+//
+// test RFs::Replace
+//
+ {
+
+ TInt failCount=TheFailCount;
+ TInt r;
+ if(aBothExist)
+ test.Next(_L("TestRFsReplace with new name existing"));
+ else
+ test.Next(_L("TestRFsReplace with new name not existing"));
+ TEntry oldEntryInfo,newEntryInfo;
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aOldName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ if(aBothExist)
+ {
+ r=CreateEntry(aNewName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ }
+ else
+ {
+ r=DeleteEntry(aNewName,EFalse,aChain);
+ test(r==KErrNone||r==KErrNotFound);
+ }
+ GetEntryDetails(aOldName,oldEntryInfo);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=TheFs.Replace(aOldName,aNewName);
+ if(r==KErrNone)
+ break;
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ if(!aBothExist && aFileSize!=0)
+ test(OneEntryExists(aOldName,aNewName));
+ else if(aBothExist)
+ test(EntryExists(aOldName)||EntryExists(aNewName));
+ ++failCount;
+ }
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aNewName) && !EntryExists(aOldName));
+ GetEntryDetails(aNewName,newEntryInfo);
+ test(IsSameEntryDetails(oldEntryInfo,newEntryInfo));
+ r=DeleteEntry(aNewName,EFalse,aChain);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFileCreate(const TDesC& aName)
+//
+// test RFile::Create
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileCreate"));
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=DeleteEntry(aName,EFalse,EChainStd);
+ test(r==KErrNone||r==KErrNotFound);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Create(TheFs,aName,EFileShareAny);
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aName));
+ r=DeleteEntry(aName,EFalse,EChainStd);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFileTemp(const TDesC& aPath)
+//
+// test RFile::Temp
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileTemp"));
+ TFileName temp;
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Temp(TheFs,aPath,temp,EFileShareAny);
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(temp));
+ r=DeleteEntry(temp,EFalse,EChainStd);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFileRename(const TDesC& aOldName, const TDesC& aNewName,TFatChain aChain,TInt aFileSize)
+//
+// test RFile::Rename
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileRename"));
+ TEntry oldEntryInfo,newEntryInfo;
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aOldName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ r=DeleteEntry(aNewName,EFalse,aChain);
+ test(r==KErrNone||r==KErrNotFound);
+ GetEntryDetails(aOldName,oldEntryInfo);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ RFile file;
+ r=file.Open(TheFs,aOldName,EFileShareExclusive|EFileWrite);
+ test(r==KErrNone);
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ r=file.Rename(aNewName);
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ test(r==WriteFailValue);
+ file.Close();
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ if(aFileSize)
+ test(OneEntryExists(aOldName,aNewName));
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aNewName) && !EntryExists(aOldName));
+ GetEntryDetails(aNewName,newEntryInfo);
+ test(IsSameEntryDetails(oldEntryInfo,newEntryInfo));
+ r=DeleteEntry(aNewName,EFalse,aChain);
+ test(r==KErrNone);
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFileReplace(const TDesC& aName,TBool aAlreadyExists,TFatChain aChain,TInt aFileSize)
+//
+// test RFile::Replace
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileReplace"));
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ if(aAlreadyExists)
+ {
+ r=CreateEntry(aName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ }
+ else
+ {
+ r=DeleteEntry(aName,EFalse,aChain);
+ test(r==KErrNone||r==KErrNotFound);
+ }
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Replace(TheFs,aName,EFileShareAny);
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ test(EntryExists(aName));
+ r=DeleteEntry(aName,EFalse,aChain);
+ test(r==KErrNone);
+ if(!aAlreadyExists)
+ {
+ ++TheOpNumber;
+ TheFailCount=0;
+ }
+ else
+ {
+ ++TheFunctionNumber;
+ TheOpNumber=TheFailCount=0;
+ }
+ }
+
+LOCAL_C void TestRFileSetSize(const TDesC& aName,TFatChain aChain,TInt aOldFileSize,TInt aNewFileSize)
+//
+// test RFile::SetSize
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileSetSize"));
+ test.Printf(_L("old size=%d new size=%d\n"),aOldFileSize,aNewFileSize);
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aName,EFalse,aChain,aOldFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Open(TheFs,aName,EFileShareAny|EFileWrite);
+ test(r==KErrNone);
+ r=file.SetSize(aNewFileSize);
+ // close the file before testing the return value!
+ file.Close();
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ file.Close();
+ test(r==WriteFailValue);
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ r=file.Open(TheFs,aName,EFileShareAny|EFileWrite);
+ test(r==KErrNone);
+ TInt size;
+ r=file.Size(size);
+ test(r==KErrNone);
+ test(size==aNewFileSize||size==aOldFileSize);
+ file.Close();
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Open(TheFs,aName,EFileShareAny);
+ test(r==KErrNone);
+ TInt fileSize;
+ r=file.Size(fileSize);
+ test(r==KErrNone);
+ test(aNewFileSize==fileSize);
+ file.Close();
+ r=DeleteEntry(aName,EFalse,aChain);
+ test(r==KErrNone);
+ ++TheFunctionNumber;
+ TheFailCount=0;
+ }
+
+LOCAL_C void TestRFileWrite(const TDesC& aName,TFatChain aChain,TInt aFileSize,TInt aPos,TInt aLength)
+//
+// test RFile::Write
+//
+ {
+ TInt failCount=TheFailCount;
+ TInt r;
+ test.Next(_L("TestRFileWrite"));
+ test.Printf(_L("aFileSize=%d,aPos=%d,aLength=%d\n"),aFileSize,aPos,aLength);
+ TInt newSize=(aFileSize>=aPos+aLength)?aFileSize:aPos+aLength;
+ HBufC8* desPtr;
+ desPtr=HBufC8::New(aLength);
+ test(desPtr!=NULL);
+ TPtr8 des=desPtr->Des();
+ des.SetLength(aLength);
+ InitialiseWriteBuffer(des);
+ FOREVER
+ {
+ test.Printf(_L("failCount=%d\n"),failCount);
+ r=CreateEntry(aName,EFalse,aChain,aFileSize);
+ test(r==KErrNone||r==KErrAlreadyExists);
+ if(IsReset)
+ {
+ ++TheFailCount;
+ WriteLogFile();
+ }
+ r=SetWriteFailOn(failCount);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Open(TheFs,aName,EFileShareAny|EFileWrite);
+ test(r==KErrNone);
+ r=file.Write(aPos,des,aLength);
+ if(r==KErrNone)
+ {
+ r=TheFs.ControlIo(gSessionPath[0]-'A',KControlIoWriteFailOff);
+ test(r==KErrNone);
+ file.Close();
+ break;
+ }
+ test(r==WriteFailValue);
+ file.Close();
+ r=TheFs.ScanDrive(gSessionPath);
+ test(r==KErrNone);
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ file.Open(TheFs,aName,EFileShareAny);
+ test(r==KErrNone);
+ TInt fileSize;
+ r=file.Size(fileSize);
+ // with fair scheduling enabled it's possible for the file
+ // size to grow even if the write appears to have failed...
+// test(fileSize==aFileSize||fileSize==newSize);
+ test(fileSize>=aFileSize && fileSize <= newSize);
+
+ file.Close();
+ ++failCount;
+ }
+ r=TheFs.CheckDisk(gSessionPath);
+ test(r==KErrNone);
+ RFile file;
+ r=file.Open(TheFs,aName,EFileShareAny);
+ test(r==KErrNone);
+ TInt fileSize;
+ r=file.Size(fileSize);
+ test(r==KErrNone);
+ test(newSize==fileSize);
+ HBufC8* desPtr2;
+ desPtr2=HBufC8::New(aLength);
+ test(desPtr2!=NULL);
+ TPtr8 des2=desPtr2->Des();
+ des2.SetLength(aLength);
+ r=file.Read(aPos,des2,des2.Length());
+ test(r==KErrNone);
+ r=des2.Compare(des);
+ test(r==0);
+ file.Close();
+ r=DeleteEntry(aName,EFalse,aChain);
+ test(r==KErrNone);
+ delete desPtr;
+ delete desPtr2;
+ ++TheFunctionNumber;
+ TheFailCount=0;
+ }
+
+
+LOCAL_C void TestOperations(const TDesC& aOldName,const TDesC& aNewName,TFatChain aChain,TInt aFileSize, TInt aDirClusters)
+//
+// Tests the specified operations
+//
+ {
+ TFileName oldDirName=aOldName;
+ TFileName newDirName=aNewName;
+ // create directory for directory operations
+ oldDirName+=_L("\\");
+ newDirName+=_L("\\");
+ // locate path for RFile::Temp
+ TInt pathPos=aOldName.LocateReverse('\\')+1;
+ TFileName tempPath=aOldName.Left(pathPos);
+ test.Printf(_L("aOldName=%S\n"),&aOldName);
+ test.Printf(_L("aNewName=%S\n"),&aNewName);
+ test.Printf(_L("tempPath=%S\n"),&tempPath);
+ switch(TheOpNumber)
+ {
+ case(0):TestRFsDelete(aOldName,aChain,aFileSize);
+ case(1):TestRFsRmDir(oldDirName,aChain,aDirClusters);
+ case(2):TestRFsMkDir(oldDirName);
+ case(3):TestRFsRename(aOldName,aNewName,EFalse,aChain,aFileSize);
+ case(4):TestRFsRename(oldDirName,newDirName,ETrue,aChain,aDirClusters);
+ case(5):TestRFsReplace(aOldName,aNewName,EFalse,aChain,aFileSize);
+ case(6):TestRFsReplace(aOldName,aNewName,ETrue,aChain,aFileSize);
+ case(7):TestRFileCreate(aOldName);
+ case(8):TestRFileTemp(tempPath);
+ case(9):TestRFileRename(aOldName,aNewName,aChain,aFileSize);
+ case(10):TestRFileReplace(aOldName,EFalse,aChain,aFileSize);
+ case(11):TestRFileReplace(aOldName,ETrue,aChain,aFileSize);break;
+ default:test(EFalse);
+ }
+ test.End();
+ }
+
+LOCAL_C void TestOperation0()
+//
+//
+//
+ {
+ // tests entries in root directory
+ test.Next(_L("TestOperation0"));
+ TestOperations(_L("\\entryWithTwoVfats"),_L("\\anotherEntryWithTwo"),EChainStd,0,0);
+ }
+
+LOCAL_C void TestOperation1()
+//
+//
+//
+ {
+ // tests entries in a full root directory
+ test.Next(_L("TestOperation1"));
+ if(TheFailCount==0)
+ FillUpRootDir(4);
+ TestOperations(_L("\\entryOne"),_L("\\entryTwo"),EChainStd,512,0);
+ UnFillUpRootDir(4);
+ }
+
+LOCAL_C void TestOperation2()
+//
+//
+//
+ {
+ // tests entries in same subdir
+ test.Next(_L("TestOperation2"));
+ TestOperations(_L("\\test\\subdir1\\NameWithFourVFatEntriesWaffle"),_L("\\test\\subdir1\\aEntry"),EChainAlternate,5120,1);
+ }
+
+
+LOCAL_C void TestOperation3()
+//
+//
+//
+ {
+ // tests entries in different subdir
+ test.Next(_L("TestOperation3"));
+ TestOperations(_L("\\test\\subdir1\\NameWithThreeEntries"),_L("\\ANother\\aEntrytwo"),EChainAlternate,15000,10);
+ }
+
+
+LOCAL_C void TestOperation4()
+//
+//
+//
+ {
+ // tests entries with cluster chain of EChainForwards
+ test.Next(_L("TestOperation4"));
+ TestOperations(_L("\\test\\subdir1\\aEntry"),_L("\\aEntry"),EChainForwards,12799,25);
+ }
+
+
+LOCAL_C void TestOperation5()
+//
+//
+//
+ {
+ // tests entries with cluster chain of EChainBackwards
+ test.Next(_L("TestOperation5"));
+ TestOperations(_L("\\test\\subdir1\\aEntry"),_L("\\ANother\\EntrywithThree"),EChainBackwards,51199,10);
+ }
+
+LOCAL_C void TestOperation6()
+//
+//
+//
+ {
+ // tests entries where old name has a very long name
+ test.Next(_L("TestOperation6"));
+ TFileName longName=_L("\\test\\subdir1\\");
+ MakeVeryLongName(longName);
+ TestOperations(longName,_L("\\ANother\\e1"),EChainAlternate,5100,0);
+ }
+
+LOCAL_C void TestOperation7()
+//
+//
+//
+ {
+ // tests entries where new name fills up subdir cluster
+ test.Next(_L("TestOperation7"));
+ TFileName name=_L("\\test\\subdir2\\");
+ // add entry with 7 vfat entries
+ MakeEntryName(name,80);
+ if(TheFailCount==0)
+ CreateEntry(name,EFalse,EChainStd,1);
+ TestOperations(_L("\\test\\subdir2\\EntryWithThree"),_L("\\test\\subdir2\\EntryWithThree-"),EChainStd,512,0);
+ DeleteEntry(name,EFalse,EChainStd);
+ }
+
+LOCAL_C void TestOperation8()
+//
+//
+//
+ {
+ // tests entries where new name is first entry in new subdir cluster
+ test.Next(_L("TestOperation8"));
+ TFileName name=_L("\\test\\subdir2\\");
+ // add entry with 10 vfat entries
+ MakeEntryName(name,125);
+ if(TheFailCount==0)
+ CreateEntry(name,EFalse,EChainStd,175000);
+ TestOperations(_L("\\test\\subdir2\\Entrywith3three"),_L("\\test\\subdir2\\entrywiththree-"),EChainStd,512,1);
+ DeleteEntry(name,EFalse,EChainStd);
+ }
+
+GLDEF_C void DoTests()
+ {
+ TInt r;
+ if(!IsReset && IsInternalRam())
+ {
+ test.Printf(_L("Error: Internal ram drive not tested\n"));
+ return;
+ }
+ if(!IsReset)
+ QuickFormat();
+
+ DoReadBootSector();
+ DumpBootSector();
+ ClearDiskData();
+
+ r=TheFs.SetSessionPath(gSessionPath);
+ test(r==KErrNone);
+
+ switch(TheFunctionNumber)
+ {
+ case(0):TestOperation0();
+ case(1):{
+ TestOperation1();
+ r=TheFs.MkDir(_L("\\fat\\"));
+ test(r==KErrNone);
+ r=TheFs.MkDir(_L("\\test\\"));
+ test(r==KErrNone);
+ r=TheFs.MkDir(_L("\\ANother\\"));
+ test(r==KErrNone);
+ r=TheFs.MkDir(_L("\\test\\subdir1\\"));
+ test(r==KErrNone);
+ r=TheFs.MkDir(_L("\\test\\subdir2\\"));
+ test(r==KErrNone);}
+ case(2):{
+ TestOperation2();
+ // add some filler files
+ CreateEntry(_L("\\test\\subdir1\\FillerOne"),EFalse,EChainStd,512);
+ CreateEntry(_L("\\test\\subdir1\\FillerTwo"),EFalse,EChainStd,1024);}
+ case(3):TestOperation3();
+ case(4):{
+ TestOperation4();
+ // add some filler files
+ CreateEntry(_L("\\ANother\\FillerThree"),EFalse,EChainStd,1536);
+ CreateEntry(_L("\\test\\subdir1\\FillerFour"),EFalse,EChainStd,2048);}
+ case(5):TestOperation5();
+ case(6):TestOperation6();
+ case(7):TestOperation7();
+ case(8):TestOperation8();
+ // increase size of file
+ case(9):TestRFileSetSize(_L("\\entry1"),EChainStd,0,512);
+ case(10):TestRFileSetSize(_L("\\entry1"),EChainAlternate,0,1025);
+ case(11):TestRFileSetSize(_L("\\entry1"),EChainStd,1,512);
+ // seek index (of CFatFileCB) resized
+ case(12):TestRFileSetSize(_L("\\entry1"),EChainForwards,512,66666);
+ // seek index resized
+ case(13):TestRFileSetSize(_L("\\entry1"),EChainBackwards,32779,131074);
+ // decrease size of file
+ // seek index resized
+ case(14):TestRFileSetSize(_L("\\entry1"),EChainForwards,133000,32768);
+ // seek index resized
+ case(15):TestRFileSetSize(_L("\\entry1"),EChainBackwards,65536,1);
+ // seek index resized
+ case(16):TestRFileSetSize(_L("\\entry1"),EChainAlternate,66554,0);
+ case(17):TestRFileSetSize(_L("\\entry1"),EChainStd,1024,1);
+ case(18):TestRFileSetSize(_L("\\entry1"),EChainAlternate,512,0);
+ case(19):TestRFileWrite(_L("\\entry2"),EChainStd,0,0,512);
+ case(20):TestRFileWrite(_L("\\entry2"),EChainAlternate,5120,512,1024);
+ case(21):TestRFileWrite(_L("\\entry2"),EChainForwards,3584,3584,5000);
+ case(22):TestRFileWrite(_L("\\entry2"),EChainBackwards,3000,2999,2000);
+ // seek index resized
+ case(23):TestRFileWrite(_L("\\entry2"),EChainBackwards,64000,64000,3000);
+ // seek index resized
+ case(24):TestRFileWrite(_L("\\entry2"),EChainForwards,131072,2,4000);break;
+ default:test(EFalse);
+ }
+ DeleteEntry(_L("\\test\\subdir1\\FillerFour"),EFalse,EChainStd);
+ DeleteEntry(_L("\\ANother\\FillerThree"),EFalse,EChainStd);
+ DeleteEntry(_L("\\test\\subdir1\\FillerTwo"),EFalse,EChainStd);
+ DeleteEntry(_L("\\test\\subdir1\\FillerOne"),EFalse,EChainStd);
+ r=TheFs.RmDir(_L("\\test\\subdir2\\"));
+ test(r==KErrNone);
+ r=TheFs.RmDir(_L("\\test\\subdir1\\"));
+ test(r==KErrNone);
+ r=TheFs.RmDir(_L("\\ANother\\"));
+ test(r==KErrNone);
+ r=TheFs.RmDir(_L("\\test\\"));
+ test(r==KErrNone);
+ r=TheFs.RmDir(_L("\\fat\\"));
+ test(r==KErrNone);
+ if (gFatBuf)
+ {
+ delete gFatBuf;
+ gFatBuf = NULL;
+ }
+ }
+#endif