Update contrib.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32test\scndrv\t_scn32dr1.cpp
23 #include "fat_utils.h"
24 using namespace Fat_Test_Utils;
27 // Solve compilation problem caused by non-English locale
28 #pragma setlocale("english")
32 T_testscndrv tests the scandrive utility. Errors in this test will be
33 introduced using the RRawdDisk class. The correct fixup is tested by rereading
34 the disk. Drives tested are the default path(epoc) and X: (wins). This test
35 returns immediately if used on the internal ram drive
39 The initial FAT12 directory structure (with cluster number in brackets) is as follows:
46 | <a very long file name (19 entries)> (5)
53 | - <seven 2*32 bytes entries> (11-17)
55 - somedirwith3entries (8)
57 - somedir2with3entries (9)
61 - <two lots of 6*32 bytes entries> (18+19)
66 The initial FAT32 directory structure (with cluster number in brackets is as follows):
73 | <a very long file name (19 entries)> (5)
80 | - <seven 2*32 bytes entries> (11-17)
82 - somedirwith3entries (8)
84 - somedir2with3entries (9)
88 - <two lots of 6*32 bytes entries> (18+19)
92 GLDEF_D RTest test(_L("T_SCN32DR1"));
94 LOCAL_D const TInt KMaxFatEntries = 2048;
95 LOCAL_D const TInt KMaxFatSize = KMaxFatEntries * 4;
97 LOCAL_D const TInt KDirAttrReadOnly = 0x01;
98 LOCAL_D const TInt KDirAttrHidden = 0x02;
99 LOCAL_D const TInt KDirAttrSystem = 0x04;
100 LOCAL_D const TInt KDirAttrVolumeId = 0x08;
101 LOCAL_D const TInt KDirAttrDirectory = 0x10;
102 LOCAL_D const TInt KDirAttrArchive = 0x20;
103 LOCAL_D const TInt KDirAttrLongName = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
104 LOCAL_D const TInt KDirAttrLongMask = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
105 LOCAL_D const TInt KDirLastLongEntry = 0x40;
107 LOCAL_D RRawDisk TheRawDisk;
108 LOCAL_D TFatBootSector BootSector;
109 LOCAL_D TFileName TheDrive=_L("?:\\");
110 LOCAL_D HBufC8* FatBufPtr = NULL;
111 LOCAL_D HBufC8* DirBufPtr = NULL;
112 LOCAL_D HBufC8* ExtBufPtr = NULL;
113 LOCAL_D TInt32 ExtBufAdd = 0;
114 LOCAL_D TInt32 ExtBufLen = 0;
115 LOCAL_D HBufC8* FatDiskPtr = NULL;
116 LOCAL_D HBufC8* DirDiskPtr = NULL;
118 static TFatType gDiskType = EInvalid;
120 LOCAL_D TInt gDriveNumber;
122 LOCAL_D TInt gBytesPerCluster;
123 LOCAL_D TInt gEntriesPerCluster;
124 LOCAL_D TInt gRootDirSectors;
125 LOCAL_D TInt gRootDirEntries;
126 LOCAL_D TInt gRootDirStart; // in bytes
127 LOCAL_D TInt gRootSector;
128 LOCAL_D TInt gFatStartBytes;
129 LOCAL_D TInt gFatTestSize; // in bytes
130 LOCAL_D TInt gFatTestEntries;
131 LOCAL_D TInt gFatSizeSectors;
132 LOCAL_D TInt gFirstDataSector;
133 LOCAL_D TInt gMaxDataCluster;
134 LOCAL_D TInt gDataStartBytes;
135 LOCAL_D TInt gEndOfChain; // for FAT12/16/32
137 // cluster numbers in 1 and >1 sector per cluster modes
138 LOCAL_D TInt gClusterRootDir; // 2 2
139 LOCAL_D TInt gClusterScnDrv; // 3 3
140 LOCAL_D TInt gClusterDir1; // 4 4
141 LOCAL_D TInt gClusterDir1ext; // 5 4
142 LOCAL_D TInt gClusterDir2; // 7 6
143 LOCAL_D TInt gClusterDir2_Full; // 8 7
144 LOCAL_D TInt gClusterDir2_SD3E; // 9 8
145 LOCAL_D TInt gClusterDir2_SD23E; // 10 9
146 LOCAL_D TInt gClusterDir2_AFull; // 11 10
147 LOCAL_D TInt gClusterEndMaxDepth; // 147 146
149 LOCAL_D TFileName LastInFull;
154 TEntryInfo(TInt aBytePos,TInt aLength):iBytePos(aBytePos),iLength(aLength){}
162 LOCAL_C TInt DirBufferSize()
164 // returns size in bytes nec for buffer to store relevant disk data
167 return(gMaxDataCluster*gBytesPerCluster);
170 LOCAL_C TInt PosInBytes(TInt aFatIndex)
172 // Return number of bytes into the FAT
175 TInt fatPosInBytes = -1;
179 fatPosInBytes=aFatIndex<<2;
182 fatPosInBytes=aFatIndex<<1;
185 fatPosInBytes=(aFatIndex*3>>1);
190 return(fatPosInBytes);
193 LOCAL_C TUint32 MaxClusters()
195 // Return the number of data clusters on the disk
198 TUint32 totSec = (BootSector.TotalSectors() ? BootSector.TotalSectors() : BootSector.HugeSectors());
199 TUint32 numSec = totSec - gFirstDataSector;
200 return numSec / BootSector.SectorsPerCluster();
203 LOCAL_C TInt ClusterToByte(TInt aCluster)
205 // converts cluster number to byte offset on disk
212 pos = (aCluster - 2) * gBytesPerCluster + gFirstDataSector * BootSector.BytesPerSector();
216 LOCAL_C TInt ByteToCluster(TInt aBytePos)
218 // Converts byte offset from root dir buffer to cluster number
221 if (aBytePos < gRootDirStart)
223 if (aBytePos < gDataStartBytes)
225 return (aBytePos - gDataStartBytes) / gBytesPerCluster + 2;
228 LOCAL_C TInt ClusterEntryToBytes(TInt aCluster,TInt aEntry)
230 // converts position in cluster and entry number to byte pos from root directory
234 pos = ClusterToByte(aCluster) - gRootDirStart + aEntry*KSizeOfFatDirEntry;
238 LOCAL_C TInt FindUnMatch(const TUint8* aBuf, const TUint8* aCmp, TInt aLen, TInt aStart=0)
240 // Return position in buffers which doesn't match, or -1 if it matches
243 for (TInt i = aStart; i < aStart + aLen; i++)
244 if (aBuf[i] != aCmp[i])
249 LOCAL_C TUint32 GetFatEntry(TUint32 aIndex, const TUint8* aFat=NULL)
251 // Read a single FAT entry from disk or FAT copy and return it
254 TInt pos = PosInBytes(aIndex);
260 ptr = (TUint8*)aFat + pos;
263 pos += BootSector.ReservedSectors() * BootSector.BytesPerSector();
264 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
266 TPtr8 buf(&data[0], 4);
267 r=TheRawDisk.Read(pos, buf);
276 val = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
279 val = ptr[0] + (ptr[1] << 8);
282 val = ptr[0] + (ptr[1] << 8);
293 LOCAL_C void WriteFat(TInt aFatIndex,TInt aValue,const TUint8* aFat)
295 // Write a value to both fats starting at aFat
298 TUint8* p=(TUint8*)(aFat+PosInBytes(aFatIndex));
302 p[0] = (TUint8) (aValue);
303 p[1] = (TUint8) (aValue >> 8);
304 p[2] = (TUint8) (aValue >> 16);
305 p[3] = (TUint8) (aValue >> 24);
308 p[0] = (TUint8) (aValue);
309 p[1] = (TUint8) (aValue >> 8);
314 TBool odd=(aFatIndex)&1;
323 fatVal|=(TUint8)(value&0xFF);
325 p[1]=(TUint8)(value>>8);
329 p[0]=(TUint8)(value&0xFF);
332 fatVal|=(TUint8)(value>>8);
343 static void DoReadBootSector()
346 TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<<KDefaultSectorLog2, BootSector);
347 test(nRes == KErrNone);
349 if(!BootSector.IsValid())
351 test.Printf(_L("Wrong bootsector! Dump:\n"));
352 BootSector.PrintDebugInfo();
356 // Calculate derived variables (fixed for a particular disk format)
357 if (BootSector.RootDirEntries() == 0)
359 test.Printf(_L("Disk is FAT32\n"));
361 gEndOfChain = 0x0FFFFFFF;
363 else if (BootSector.FatType() == EFat16)
365 test.Printf(_L("Disk is FAT16\n"));
367 gEndOfChain = 0xFFFF;
371 test.Printf(_L("Disk is FAT12\n"));
373 gEndOfChain = 0x0FFF;
376 gBytesPerCluster = BootSector.BytesPerSector() * BootSector.SectorsPerCluster();
377 gFatStartBytes = BootSector.ReservedSectors() * BootSector.BytesPerSector();
378 gEntriesPerCluster = gBytesPerCluster / KSizeOfFatDirEntry;
380 TBool big = (BootSector.SectorsPerCluster() > 1);
385 gRootDirEntries = BootSector.RootDirEntries();
386 gRootDirSectors = ((gRootDirEntries * KSizeOfFatDirEntry + BootSector.BytesPerSector() - 1) / BootSector.BytesPerSector());
387 gFatSizeSectors = BootSector.FatSectors();
388 gRootSector = BootSector.ReservedSectors() + BootSector.NumberOfFats() * gFatSizeSectors;
389 gFirstDataSector = gRootSector + gRootDirSectors;
390 gDataStartBytes = gFirstDataSector * BootSector.BytesPerSector();
391 gRootDirStart = gRootSector * BootSector.BytesPerSector();
392 gClusterRootDir = (big ? 0 : 0);
393 gClusterScnDrv = (big ? 2 : 2);
394 gClusterDir1 = (big ? 3 : 3);
395 gClusterDir1ext = (big ? 3 : 4);
396 gClusterDir2 = (big ? 5 : 6);
397 gClusterDir2_Full = (big ? 6 : 7);
398 gClusterDir2_SD3E = (big ? 7 : 8);
399 gClusterDir2_SD23E = (big ? 8 : 9);
400 gClusterDir2_AFull = (big ? 9 : 10);
401 gClusterEndMaxDepth = (big ? 145 : 146);
405 // FAT32 will alway pre-allocate a single cluster for the root directory
407 // - The following calculations may look wierd (as the spec says that the FAT32 root dir
408 // is not fixed) but for the purposes of this test we assume that root dir is only
409 // one cluster in size, so we don't fill up the disk trying to fill up the root dir.
411 gRootDirEntries = gBytesPerCluster * 1 / KSizeOfFatDirEntry; // Maximum entries within default FAT32 root directory (before extension)
412 gRootDirSectors = 0; // FAT32 has no fixed root directory sectors over which to skip
413 gFatSizeSectors = BootSector.FatSectors32();
415 gRootSector = BootSector.ReservedSectors() + BootSector.NumberOfFats() * gFatSizeSectors;
416 gFirstDataSector = gRootSector;
418 gDataStartBytes = gFirstDataSector * BootSector.BytesPerSector();
419 gRootDirStart = (BootSector.RootClusterNum() - 2) * gBytesPerCluster + gDataStartBytes;
421 gClusterRootDir = (big ? 2 : 2);
422 gClusterScnDrv = (big ? 3 : 3);
423 gClusterDir1 = (big ? 4 : 4);
424 gClusterDir1ext = (big ? 4 : 5);
425 gClusterDir2 = (big ? 6 : 7);
426 gClusterDir2_Full = (big ? 7 : 8);
427 gClusterDir2_SD3E = (big ? 8 : 9);
428 gClusterDir2_SD23E = (big ? 9 : 10);
429 gClusterDir2_AFull = (big ? 10 : 11);
430 gClusterEndMaxDepth = (big ? 146 : 147);
436 gMaxDataCluster = gClusterDir2_AFull + 2 + (gFirstDataSector / BootSector.SectorsPerCluster() + 1);
438 gFatTestEntries = MaxClusters();
439 if (gFatTestEntries > KMaxFatSize)
440 gFatTestEntries = KMaxFatSize;
444 GLDEF_C void DumpBootSector()
446 // Display (in log) TFatBootSector structure
449 RDebug::Print(_L("iBytesPerSector = %8d"), BootSector.BytesPerSector());
450 RDebug::Print(_L("iSectorsPerCluster = %8d"), BootSector.SectorsPerCluster());
451 RDebug::Print(_L("iReservedSectors = %8d"), BootSector.ReservedSectors());
452 RDebug::Print(_L("iNumberOfFats = %8d"), BootSector.NumberOfFats());
453 RDebug::Print(_L("iRootDirEntries = %8d"), BootSector.RootDirEntries());
454 RDebug::Print(_L("iTotalSectors = %8d"), BootSector.TotalSectors());
455 RDebug::Print(_L("iMediaDescriptor = %8d"), BootSector.MediaDescriptor());
456 RDebug::Print(_L("iFatSectors = %8d"), BootSector.FatSectors());
457 RDebug::Print(_L("iSectorsPerTrack = %8d"), BootSector.SectorsPerTrack());
458 RDebug::Print(_L("iNumberOfHeads = %8d"), BootSector.NumberOfHeads());
459 RDebug::Print(_L("iHiddenSectors = %8d"), BootSector.HiddenSectors());
460 RDebug::Print(_L("iHugeSectors = %8d"), BootSector.HugeSectors());
462 if (gDiskType == EFat32)
464 RDebug::Print(_L("iFatSectors32 = %8d"), BootSector.FatSectors32());
465 RDebug::Print(_L("iFATFlags = %8d"), BootSector.FATFlags());
466 RDebug::Print(_L("iVersionNumber = %8d"), BootSector.VersionNumber());
467 RDebug::Print(_L("iRootClusterNum = %8d (0x%08X)"), BootSector.RootClusterNum(), gRootDirStart);
468 RDebug::Print(_L("iFSInfoSectorNum = %8d (0x%08X)"), BootSector.FSInfoSectorNum(), BootSector.FSInfoSectorNum() * BootSector.BytesPerSector());
469 RDebug::Print(_L("iBkBootRecSector = %8d (0x%08X)"), BootSector.BkBootRecSector(), BootSector.BkBootRecSector() * BootSector.BytesPerSector());
473 GLDEF_C void DumpFat(const TUint8* aFat=NULL)
475 // Dump to the log all those FAT entries which are non-zero
478 TInt32 max = MaxClusters();
479 if (max > KMaxFatEntries)
480 max = KMaxFatEntries;
481 RDebug::Print(_L("---------------- DUMP OF FAT ---------------"));
482 for (TInt32 i = 0; i < max; i++)
484 TInt32 val = GetFatEntry(i, aFat);
485 TInt32 msk = 0x0FFFFFFF;
500 if ((val & msk) == (0x0FFFFFFF & msk))
501 RDebug::Print(_L(" %8d -> EOC"), i);
502 else if ((val & msk) == (0x0FFFFFF8 & msk))
503 RDebug::Print(_L(" %8d -> Media"), i);
504 else if ((val & msk) == (0x0FFFFFF7 & msk))
505 RDebug::Print(_L(" %8d -> BAD"), i);
507 RDebug::Print(_L(" %8d -> 0x%08X"), i, val);
509 RDebug::Print(_L(" %8d -> %d"), i, val);
511 RDebug::Print(_L("--------------------------------------------"));
514 GLDEF_C TDes* DirAttributes(TInt aAttrib)
516 // Return a pointer to a local buffer containing the attribute letters.
520 LOCAL_D char* atr = "RHSVDA";
521 str.Fill(TText('-'), 6);
522 for (TInt i = 0; i < 6; i++)
523 if ((aAttrib >> i) & 1)
528 GLDEF_C TBool IsValidDirEntry(TFatDirEntry* aDir)
530 // Test whether buffer is a valid normal directory entry
533 // first character must be 0x05 or greater than space
534 if (aDir->iData[0] < 0x21 && aDir->iData[0] != 0x05)
536 // other characters must be not less than space
537 for (TInt i = 1; i < 11; i++)
538 if (aDir->iData[i] < 0x20)
543 GLDEF_C void GetLongNamePart(TDes16& aName, const TUint8* aEntry, TInt aPos, TInt aOffset, TInt aLength)
545 // Extract part of a long name entry into the name buffer.
547 // @param aName buffer to put name
548 // @param aEntry directory entry raw data
549 // @param aPos character in buffer to start name segment
550 // @param aOffset offset in directory entry of the segment
551 // @param aLength number of characters in the segment
554 for (TInt i = 0; i < aLength; i++)
556 TInt at = i * 2 + aOffset;
557 TInt ch = aEntry[at] + aEntry[at+1] * 256;
558 aName[aPos++] = TText(ch);
562 GLDEF_C void ExtractNameString(TDes16& aName, const TUint8* aEntry)
564 // Extract a long name part from a directory entry, truncate it at the first
565 // NUL (0) character and put quotes round it.
569 TInt len = aName.Length() - 1;
572 GetLongNamePart(aName, aEntry, 1, 1, 5);
573 GetLongNamePart(aName, aEntry, 6, 14, 6);
574 GetLongNamePart(aName, aEntry, 12, 28, 2);
576 for (i = 0; i < len; i++)
583 GLDEF_C TBool DumpDirEntry(TInt aNum, const TUint8* aEntry)
585 // Dump a single directory entry to the log. Return false if it was end of
586 // directory or an invalid entry (and don't display it).
589 TFatDirEntry* d = (TFatDirEntry*)aEntry;
592 //RDebug::Print(_L("%5d: ERASED"), aNum);
594 else if (d->IsEndOfDirectory())
597 RDebug::Print(_L("%5d: ------------- end of directory"), aNum);
600 else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
603 ExtractNameString(name, aEntry);
604 TInt ord = aEntry[0];
605 if (ord & KDirLastLongEntry)
606 RDebug::Print(_L("%5d: %-15S #%-2d LAST"), aNum, &name, ord & ~KDirLastLongEntry);
608 RDebug::Print(_L("%5d: %-15S #%-2d"), aNum, &name, ord & ~KDirLastLongEntry);
610 else if (!IsValidDirEntry(d))
613 RDebug::Print(_L("%5d: ============= INVALID ENTRY"), aNum);
619 name.Copy(d->Name());
620 RDebug::Print(_L("%5d: '%S' %S start %-5d size %d"),
621 aNum, &name, DirAttributes(d->Attributes()), d->StartCluster(), d->Size());
626 GLDEF_C void DumpDirCluster(const TUint8* aData, TInt aCluster=0)
628 // Dump directory entries until end of cluster or invalid/end entry found.
632 aData += (aCluster-2) * gBytesPerCluster;
633 for (TInt i = 0; i < gBytesPerCluster; i += KSizeOfFatDirEntry)
635 if (DumpDirEntry(i/KSizeOfFatDirEntry, aData))
636 aData += KSizeOfFatDirEntry;
642 GLDEF_C void DumpRootDir(const TUint8* aData)
644 // Dump the data area buffer, trying to interpret directory clusters (only look
645 // at clusters which are marked as 'used' in the FAT).
648 RDebug::Print(_L("Root dir @ 0x%08X:"), gRootDirStart);
649 for (TInt i = 0; i < BootSector.RootDirEntries(); i++)
651 if (DumpDirEntry(i, aData))
652 aData += KSizeOfFatDirEntry;
658 GLDEF_C void DumpData(const TUint8* aFat, const TUint8* aDir)
660 // Dump the data area buffer, trying to interpret directory clusters (only look
661 // at clusters which are marked as 'used' in the FAT).
664 RDebug::Print(_L("--------------- DATA AREA ------------------"));
665 if (gDiskType != EFat32)
669 TInt max = (gFatTestEntries < gMaxDataCluster ? gFatTestEntries : gMaxDataCluster);
670 for (TInt cluster = 2; cluster < max; cluster++)
672 if (GetFatEntry(cluster, aFat) != 0)
674 RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster));
675 DumpDirCluster(aDir+gDataStartBytes-gRootDirStart, cluster);
678 RDebug::Print(_L("--------------------------------------------"));
681 GLDEF_C void DumpData(const TUint8* aFat, TInt aStart, TInt aEnd = -1)
683 // Dump clusters from disk (allows dumping of clusters not in our buffers).
684 // Only look at clusters marked as 'used' in the FAT. Note that if aFat is
685 // NULL the FAT entries will also be read from disk (slower but allows for ones
686 // outside our copy in memory).
689 if (aStart > gFatTestEntries)
691 RDebug::Print(_L("--------------- DATA AREA ------------------"));
692 if (aEnd > gFatTestEntries)
693 aEnd = gFatTestEntries;
696 if (aStart < 2 && gDiskType != EFat32)
698 HBufC8* buf=HBufC8::New(BootSector.RootDirEntries() * KSizeOfFatDirEntry);
700 TPtr8 ptr=buf->Des();
701 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
703 r=TheRawDisk.Read(gRootDirStart, ptr);
706 DumpRootDir(buf->Ptr());
710 for (TInt cluster = aStart; cluster < aEnd; cluster++)
712 if (GetFatEntry(cluster, aFat) != 0)
714 HBufC8* buf=HBufC8::New(gBytesPerCluster);
716 TPtr8 ptr=buf->Des();
717 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
719 r=TheRawDisk.Read(ClusterToByte(cluster), ptr);
722 RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster));
723 DumpDirCluster(ptr.Ptr());
727 RDebug::Print(_L("--------------------------------------------"));
730 GLDEF_C void DumpHex(const TUint8* aData, TInt aLen, TInt aBase=0)
732 // Dump a block of memory to the log in hex.
735 for (TInt base = 0; base < aLen; base += 16)
737 TBuf<16*3+3+16+1> buf;
739 for (off = base; off < aLen && off < base + 16; off++)
741 buf.Append(TText(' '));
742 buf.AppendNumFixedWidth(aData[off], EHex, 2);
744 buf.Append(_L(" |"));
745 for (off = base; off < aLen && off < base + 16; off++)
747 TUint8 ch = aData[off];
748 buf.Append(ch < 0x20 || ch > 0x7E ? TText('_') : TText(ch));
751 RDebug::Print(_L("%04X: %S"), base+aBase, &buf);
755 GLDEF_C void DumpHex(const TPtrC8& aData, TInt aLen, TInt aBase=0)
757 // Dump a block of memory to the log in hex.
760 DumpHex(aData.Ptr(), aLen, aBase);
763 GLDEF_C void DumpHex(TInt aPos, TInt aLen, TInt aBase=0)
765 // Dump a block of memory to the log in hex.
768 TPtr8 dirBuf=DirBufPtr->Des();
769 DumpHex(dirBuf.Ptr()+aPos, aLen, aBase);
772 GLDEF_C void Dump(TEntryInfo& aEntry)
774 // Dump an entry description to the log in hex
777 RDebug::Print(_L("--- TEntryInfo 0x%08X, %d"), aEntry.iBytePos, aEntry.iLength);
778 TInt len = aEntry.iLength*KSizeOfFatDirEntry;
779 DumpHex(aEntry.iBytePos, len, aEntry.iBytePos);
782 LOCAL_C TInt GetStartCluster(TInt aCluster, TInt aEntry)
784 // Get the start cluster pertaining to a directory entry in a specific
785 // directory cluster, return -1 if not available (invalid entry).
788 HBufC8* buf=HBufC8::New(gBytesPerCluster*2);
790 TPtr8 ptr=buf->Des();
791 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
793 r=TheRawDisk.Read(ClusterToByte(aCluster), ptr);
796 RDebug::Print(_L("Cluster %d @ 0x%08X:"), aCluster, ClusterToByte(aCluster));
797 TFatDirEntry* d = (TFatDirEntry*)ptr.Ptr() + aEntry;
798 while ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName && aEntry < gEntriesPerCluster)
800 if (d->IsErased() || d->IsEndOfDirectory())
803 d = (TFatDirEntry*)ptr.Ptr() + aEntry;
805 TInt start = d->StartCluster();
808 else if (d->IsEndOfDirectory())
810 else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
812 else if (!IsValidDirEntry(d))
818 LOCAL_C void Format()
824 fmt.iFatType = EFat32;
825 fmt.iSecPerCluster = 1;
827 nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fmt);
829 nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue);
832 test(nRes == KErrNone);
836 LOCAL_C void CreateDeepDir(TFileName& aDir,TInt aDepth)
838 // Increase directory strucutre by aDepth starting with aDir.
847 num[0] = TText(aDepth % 26 + 'A');
854 LOCAL_C void DeleteDeepDir(TFileName& aDir,TInt aDepth)
856 // Delete dir structure.
864 aDir.SetLength(aDir.Length()-2);
868 LOCAL_C void CreateMaxDepthDir(TFileName& aDir1,TFileName& aDir2)
870 // Create directory structure with max possible depth-1.
871 // Achieved by using dir names of one character.
874 //create dir structure with depth of 25
875 CreateDeepDir(aDir1,25);
876 // split dir structure
879 TInt r=TheFs.MkDir(aDir2);
881 // create dir with depth of 126 directories - one short of max depth
882 CreateDeepDir(aDir1,101);
883 // create dir with depth of 90
884 CreateDeepDir(aDir2,64);
887 LOCAL_C void DeleteMaxDepthDir(TFileName&aDir1,TFileName&aDir2)
889 // Deletes max depth dir structure.
892 DeleteDeepDir(aDir2,64);
893 TInt r=TheFs.RmDir(aDir2);
895 aDir2.SetLength(aDir2.Length()-2);
896 DeleteDeepDir(aDir1,102);
897 DeleteDeepDir(aDir1,24);
900 LOCAL_C void MakeVeryLongName(TFileName& aLong)
902 // appends a very long file name to aLong
905 // create a name to take up 18 vfat entries - (1 sector + 2 entries)
906 for(TInt i=0;i<234;++i)
913 GLDEF_C void CreateLongNames(TFileName& aLong, TInt aClusters)
915 // Creates entries to fill up the number of directory clusters
918 TInt len = aLong.Length(); // length of directory prefix
919 MakeVeryLongName(aLong);
922 for (TInt i = 0; i < aClusters * gEntriesPerCluster; i += 19)
924 aLong[len+0] = TText(count/26 + 'A');
925 aLong[len+1] = TText(count%26 + 'A');
927 TInt r=temp.Create(TheFs,aLong,EFileShareAny);
933 GLDEF_C void DeleteLongNames(TFileName& aLong, TInt aClusters)
935 // Deletes entries created by CreateLongNames()
938 TInt len = aLong.Length(); // length of directory prefix
939 MakeVeryLongName(aLong);
941 for (TInt i = 0; i < aClusters * gEntriesPerCluster; i += 19)
943 aLong[len+0] = TText(count/26 + 'A');
944 aLong[len+1] = TText(count%26 + 'A');
946 TInt r=TheFs.Delete(aLong);
947 test(r==KErrNone || r==KErrNotFound);
951 LOCAL_C void DeleteRootDir(TInt aNum=0)
953 // Delete all entries in the root directory up to the last - aNum
956 test.Next(_L("Delete Root Directory Entries"));
957 TInt maxRootEntries = gRootDirEntries;
958 TFileName name=_L("\\???xxx");
963 for (entriesSoFar=0; entriesSoFar<maxRootEntries - aNum; entriesSoFar+=2)
965 name[1]=(TUint16)(count/26/26+'a');
966 name[2]=(TUint16)(count/26%26+'a');
967 name[3]=(TUint16)(count%26+'a');
968 r=TheFs.Delete(name);
969 test(r==KErrNone || r==KErrNotFound);
974 LOCAL_C void CreateRootDir()
976 // fill up root directory to 1 clusters by creating entries and then deleting
977 // them except the last.
980 test.Next(_L("Create Root Directory Entries"));
981 TInt maxRootEntries = gRootDirEntries;
982 TFileName name=_L("\\???xxx");
987 for (entriesSoFar=0; entriesSoFar<maxRootEntries; entriesSoFar+=2)
989 name[1]=(TUint16)(count/26/26+'a');
990 name[2]=(TUint16)(count/26%26+'a');
991 name[3]=(TUint16)(count%26+'a');
992 r=f.Create(TheFs, name, EFileWrite);
1000 LOCAL_C void FillUpRootDir(TInt aFree=0)
1002 // fill up root directory
1005 TInt maxRootEntries = gRootDirEntries - aFree;
1006 TFileName dir=_L("\\??\\");
1008 TInt entriesSoFar=2;
1010 while(entriesSoFar<maxRootEntries)
1012 dir[1]=(TUint16)(count/26+'a');
1013 dir[2]=(TUint16)(count%26+'a');
1021 LOCAL_C void UnFillUpRootDir(TInt aFree=0)
1023 // reverse changes from FillUpRootDir()
1026 TFileName dir=_L("\\??\\");
1027 TInt entriesSoFar=gRootDirEntries-aFree;
1030 while(entriesSoFar>2)
1032 dir[1]=TUint16(count/26+'a');
1033 dir[2]=TUint16(count%26+'a');
1041 LOCAL_C void DeleteDirectoryStructure()
1043 // deletes the directory structure
1046 test.Next(_L("Delete Directory Structure"));
1047 TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\almostfull\\"));
1049 TInt entriesNeeded=(gEntriesPerCluster-2) / 2; //7*2entries + . + .. = full sector
1050 for (TInt i = 0; i < entriesNeeded; i++)
1052 TFileName file=_L("\\scndrv\\dir2\\full\\__a");
1054 r=TheFs.Delete(file);
1055 test(r==KErrNone||r==KErrNotFound);
1057 r=TheFs.RmDir(_L("\\scndrv\\dir2\\full\\"));
1059 r=TheFs.RmDir(_L("\\scndrv\\dir2\\"));
1061 TFileName veryLongName=(_L("\\scndrv\\dir1\\"));
1062 MakeVeryLongName(veryLongName);
1063 r=TheFs.Delete(veryLongName);
1065 r=TheFs.RmDir(_L("\\scndrv\\dir1\\"));
1067 r=TheFs.RmDir(_L("\\scndrv\\"));
1071 LOCAL_C void CreateDirectoryStructure()
1073 // creates the directory structure
1076 test.Next(_L("Create Directory Structure"));
1077 // cluster 3 (root dir is cluster 2)
1078 TInt r=TheFs.MkDir(_L("\\scndrv\\"));
1081 r=TheFs.MkDir(_L("\\scndrv\\dir1\\"));
1083 TFileName veryLongName=(_L("\\scndrv\\dir1\\"));
1084 MakeVeryLongName(veryLongName);
1087 r=f.Create(TheFs,veryLongName,EFileShareAny);
1093 r=TheFs.MkDir(_L("\\scndrv\\dir2\\"));
1096 r=TheFs.MkDir(_L("\\scndrv\\dir2\\full\\"));
1099 r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedirwith3entries\\"));
1102 r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedir2with3entries\\"));
1105 r=TheFs.MkDir(_L("\\scndrv\\dir2\\almostfull\\"));
1108 TInt entriesNeeded=(gEntriesPerCluster-2) / 2; //7*2entries + . + .. = full sector
1109 for (TInt i = 0; i < entriesNeeded; i++)
1111 TFileName file=_L("\\scndrv\\dir2\\full\\__a");
1114 r=f.Create(TheFs,file,EFileShareAny);
1124 TInt charLength=13*4+1; // name to take up 6 entries
1125 TFileName file1=_L("\\scndrv\\dir2\\almostfull\\");
1128 TInt c='A'+charLength%26;
1131 TFileName file2=file1;
1134 r=f.Create(TheFs,file1,EFileShareAny);
1139 r=f.Create(TheFs,file2,EFileShareAny);
1146 LOCAL_C TUint8* DirPtr(TInt aOffset)
1148 // Return a pointer to the offset in the dir buffer, or in the special
1149 // extension buffer if the dir buffer isn't large enough. If the extension
1150 // buffer is needed, it is read from disk when it is created (2 clusters, to
1151 // allow for entries spanning cluster boundaries). Errors will occur if
1152 // another cluster is needed before the extension has been released.
1154 // Note that if an extension buffer is allocated then writing a dir buffer to
1155 // disk will also write the extension buffer and any changes made in it.
1158 // if the offset is in store, return its byte address
1159 if (aOffset < DirBufPtr->Des().MaxLength())
1160 return (TUint8*)DirBufPtr->Ptr() + aOffset;
1161 // not in main buffer, see if extension is allocated already
1164 // allocate buffer for 2 clusters, starting at the cluster which
1166 ExtBufLen = 2 * gBytesPerCluster;
1167 ExtBufPtr = HBufC8::New(ExtBufLen);
1168 test(ExtBufPtr != NULL);
1169 // read the clusters in
1170 ExtBufAdd = aOffset - aOffset % gBytesPerCluster;
1171 TInt clust = (ExtBufAdd - (gDataStartBytes - gRootDirStart)) /gBytesPerCluster + 2;
1172 RDebug::Print(_L("Extension buffer for cluster %d allocated"), clust);
1173 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1175 TPtr8 des(ExtBufPtr->Des());
1176 r=TheRawDisk.Read(gRootDirStart + ExtBufAdd, des);
1180 // convert to offset in the extension buffer
1181 aOffset -= ExtBufAdd;
1182 if (aOffset >= ExtBufLen)
1184 test.Printf(_L("*** ERROR: tried to access cluster %d not in store\n"),
1185 (aOffset + ExtBufAdd) / gBytesPerCluster + 2);
1188 return (TUint8*)ExtBufPtr->Ptr() + aOffset;
1191 LOCAL_C void DirPtrFree()
1193 // Free the extension buffer and zero the references to it.
1198 TInt clust = (ExtBufAdd - (gDataStartBytes - gRootDirStart)) /gBytesPerCluster + 2;
1199 RDebug::Print(_L("Extension buffer for cluster %d deleted"), clust);
1207 LOCAL_C void ReadDirDisk(TDes8& aDirBuf, TInt aCluster = -1)
1209 // reads directory section of disk into buffer
1212 test(aCluster != 1);
1214 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1217 if (aCluster == -1) // all clusters ?
1219 r=TheRawDisk.Read(gRootDirStart, aDirBuf);
1221 else if (aCluster == 0) // root directory cluster
1223 TPtr8 dirPtr = aDirBuf.MidTPtr(0, gBytesPerCluster);
1224 r=TheRawDisk.Read(gRootDirStart, dirPtr);
1228 // directory buffer starts at root directory, so
1229 // calculate offset from there.
1230 TInt pos = ((aCluster - 2) * gBytesPerCluster) +
1231 (gRootDirSectors * BootSector.BytesPerSector());
1232 TPtr8 dirPtr = aDirBuf.MidTPtr(pos, gBytesPerCluster);
1233 r=TheRawDisk.Read(gRootDirStart + pos, dirPtr);
1240 LOCAL_C void ReadFatDisk(TDes8& aFatBuf)
1242 // reads fat section of disk info buffer
1245 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1247 r=TheRawDisk.Read(gFatStartBytes, aFatBuf);
1252 LOCAL_C void WriteDirDisk(TDes8& aDirBuf, TInt aCluster = -1)
1254 // writes dir buffer to disk
1257 test(aCluster != 1);
1259 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1264 r=TheRawDisk.Write(gRootDirStart, aDirBuf);
1266 else if (aCluster == 0) // root directory cluster
1268 TPtr8 dirPtr = aDirBuf.MidTPtr(0, gBytesPerCluster);
1269 r=TheRawDisk.Write(gRootDirStart, dirPtr);
1273 // directory buffer starts at root directory, so
1274 // calculate offset from there.
1275 TInt pos = ((aCluster - 2) * gBytesPerCluster) +
1276 (gRootDirSectors * BootSector.BytesPerSector());
1277 TPtr8 dirPtr = aDirBuf.MidTPtr(pos, gBytesPerCluster);
1278 r=TheRawDisk.Write(gRootDirStart + pos, dirPtr);
1284 TPtr8 des(ExtBufPtr->Des());
1285 r=TheRawDisk.Write(gRootDirStart + ExtBufAdd, des);
1291 LOCAL_C void WriteFatDisk(TDes8& aFatBuf, TInt aStart=0)
1293 // writes fat buffer to disk
1296 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1298 TInt fatCount=BootSector.NumberOfFats() - aStart;
1299 TInt pos = gFatStartBytes + aStart * gFatSizeSectors*BootSector.BytesPerSector();
1302 r=TheRawDisk.Write(pos, aFatBuf);
1304 pos += gFatSizeSectors*BootSector.BytesPerSector();
1309 LOCAL_C void WriteReservedId(TInt aBytePos)
1311 // write reserved id to byte 19 of entry starting at aBytePos
1314 TUint8* pEntry=DirPtr(aBytePos);
1318 LOCAL_C void WriteEndOfDir(TInt aBytePos)
1320 // write end of directory marker to entry starting at aBytePos
1323 TUint8* pEntry=DirPtr(aBytePos);
1324 Mem::FillZ(pEntry,KFatDirNameSize);
1327 LOCAL_C void WriteDelete(TInt aBytePos,TInt aNum)
1329 // writes 0xe5 to entries starting at aBytePos
1332 TUint8* pEntry=DirPtr(aBytePos);
1336 pEntry+=KSizeOfFatDirEntry;
1340 LOCAL_C void WriteCopyDir(TInt aSrc, TInt aDst)
1342 // Copy one directory entry over another
1345 TUint8* pSrc=DirPtr(aSrc);
1346 TUint8* pDst=DirPtr(aDst);
1347 Mem::Copy(pDst, pSrc, KSizeOfFatDirEntry);
1350 LOCAL_C void InitialiseBuffers()
1352 // reads disk into buffers
1355 gFatTestEntries = MaxClusters();
1356 if (gFatTestEntries > KMaxFatSize)
1357 gFatTestEntries = KMaxFatSize;
1358 gFatTestSize = PosInBytes(gFatTestEntries);
1359 FatBufPtr=HBufC8::New(gFatTestSize);
1360 test(FatBufPtr!=NULL);
1361 DirBufPtr=HBufC8::New(DirBufferSize());
1362 test(DirBufPtr!=NULL);
1364 // Buffers for reading from disk
1365 FatDiskPtr=HBufC8::New(gFatTestSize);
1366 test(FatDiskPtr!=NULL);
1367 DirDiskPtr=HBufC8::New(DirBufferSize());
1368 test(DirDiskPtr!=NULL);
1371 LOCAL_C TBool IsSameAsDrive(const TDes8& aFatBuf,const TDes8& aDirBuf)
1373 // compares the two bufs passed in with those on disk
1376 TPtr8 fatDisk=FatDiskPtr->Des();
1377 TPtr8 dirDisk=DirDiskPtr->Des();
1378 ReadDirDisk(dirDisk);
1379 ReadFatDisk(fatDisk);
1380 TBool fatOk = (aFatBuf.Compare(fatDisk)==0);
1381 TBool dirOk = (aDirBuf.Compare(dirDisk)==0);
1384 TInt i = FindUnMatch(aFatBuf.Ptr(), fatDisk.Ptr(), fatDisk.Length());
1391 {//-- mismatch in FAT[1] for FAT16/FAT32 it is OK because FAT[1] is used by volume finalisation
1392 //-- to store Volume Clean Shutdown flag
1402 {//-- mismatch in FAT[1] for FAT16/FAT32 it is OK because FAT[1] is used by volume finalisation
1403 //-- to store Volume Clean Shutdown flag
1411 if (GetFatEntry(i, aFatBuf.Ptr()) == GetFatEntry(i, fatDisk.Ptr()))
1420 test.Printf(_L("Skipping FAT[1] entry for FAT16/32 \n"), i);
1424 test.Printf(_L("FAT entry %d different from expected\n"), i);
1426 RDebug::Print(_L("Expected:\n"));
1427 DumpFat(aFatBuf.Ptr());
1428 RDebug::Print(_L("Actual:\n"));
1429 DumpFat(fatDisk.Ptr());
1435 TInt i = FindUnMatch(aDirBuf.Ptr(), dirDisk.Ptr(), dirDisk.Length());
1436 TInt clust = ByteToCluster(i);
1437 TInt entry = i % gBytesPerCluster / KSizeOfFatDirEntry;
1438 test.Printf(_L("DIR different from expected\n"));
1439 test.Printf(_L(" at pos %d sector %d cluster %d entry %d:\n"), i, i / BootSector.BytesPerSector(), clust, entry);
1441 RDebug::Print(_L("Expected:\n"));
1442 DumpHex(aDirBuf.Ptr() + i, 32);
1443 RDebug::Print(_L("-------------"));
1444 RDebug::Print(_L("Actual:\n"));
1445 DumpHex(dirDisk.Ptr() + i, 32);
1447 RDebug::Print(_L("Expected:\n"));
1448 DumpData(aFatBuf.Ptr(), aDirBuf.Ptr());
1449 RDebug::Print(_L("Actual:\n"));
1450 DumpData(fatDisk.Ptr(), dirDisk.Ptr());
1454 HBufC8* extPtr = HBufC8::New(ExtBufLen);
1455 test(extPtr != NULL);
1456 TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
1458 TPtr8 des(extPtr->Des());
1459 r=TheRawDisk.Read(ExtBufAdd+gRootDirStart, des);
1462 TInt i = FindUnMatch(ExtBufPtr->Ptr(), extPtr->Ptr(), ExtBufLen);
1465 TInt extcl = (ExtBufAdd - (gDataStartBytes-gRootDirStart)) / gBytesPerCluster + 2;
1466 TInt clust = i / gBytesPerCluster;
1467 TInt entry = i % gBytesPerCluster / KSizeOfFatDirEntry;
1468 test.Printf(_L("DIR different from expected\n"));
1469 test.Printf(_L(" at cluster %d entry %d:\n"), extcl+clust, entry);
1470 DumpHex(ExtBufPtr->Ptr() + clust * gBytesPerCluster + entry * KSizeOfFatDirEntry, 32);
1471 RDebug::Print(_L("-------------"));
1472 DumpHex(extPtr->Ptr() + clust * gBytesPerCluster + entry * KSizeOfFatDirEntry, 32);
1473 // RDebug::Print(_L("Expected:\n"));
1474 // DumpData(aFatBuf.Ptr(), aDirBuf.Ptr());
1475 // RDebug::Print(_L("Actual:\n"));
1476 // DumpData(fatDisk.Ptr(), dirDisk.Ptr());
1482 return(fatOk && dirOk);
1485 LOCAL_C void WriteErased(TEntryInfo aTrg,TInt aToDelete)
1487 // writes erased marker, starting at dos entry and working backwards
1488 // used to simulate a part entry40*BootSector.BytesPerSector()
1491 TInt toStart=aTrg.iBytePos+(aTrg.iLength-1)*KSizeOfFatDirEntry;
1492 TPtr8 dirBuf=DirBufPtr->Des();
1495 dirBuf[toStart]=0xE5;
1496 toStart-=KSizeOfFatDirEntry;
1500 LOCAL_C void CreatePartialEntry(TEntryInfo aTrg,TInt aToDelete,TBool aAddEOfDir)
1502 // creates a partial entry
1505 WriteErased(aTrg,aToDelete);
1507 WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry);
1508 TPtr8 dirBuf=DirBufPtr->Des();
1509 WriteDirDisk(dirBuf);
1512 LOCAL_C TBool TestPartialEntry(TEntryInfo aEntry)
1514 // tests that scandrive deals with a partial entry and returns the result
1517 test.Next(_L("TestPartialEntry"));
1518 TInt r=TheFs.ScanDrive(gSessionPath);
1520 WriteDelete(aEntry.iBytePos,aEntry.iLength);
1522 TPtr8 fatBuf=FatBufPtr->Des();
1523 TPtr8 dirBuf=DirBufPtr->Des();
1525 TBool res=IsSameAsDrive(fatBuf,dirBuf);
1529 LOCAL_C void CreateMatchingEntry(TEntryInfo aTrg,TEntryInfo aSrc,TBool aAddEOfDir)
1531 // creates matching entry
1534 test.Next(_L("Create entry with start cluster already used"));
1535 TUint8* src = DirPtr(aSrc.iBytePos);
1536 TUint8* dst = DirPtr(aTrg.iBytePos);
1537 Mem::Copy(dst, src, aSrc.iLength*KSizeOfFatDirEntry);
1538 WriteReservedId(aTrg.iBytePos+(aTrg.iLength-1)*KSizeOfFatDirEntry);
1540 WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry);
1541 TPtr8 dirBuf=DirBufPtr->Des();
1542 WriteDirDisk(dirBuf);
1545 LOCAL_C TBool TestMatchingEntry(TEntryInfo aToDelete)
1547 // tests that scandrive deals with matching entries correctly
1550 test.Next(_L("TestMatchingEntries"));
1551 WriteDelete(aToDelete.iBytePos,aToDelete.iLength);
1552 TInt r=TheFs.ScanDrive(gSessionPath);
1555 TPtr8 fatBuf=FatBufPtr->Des();
1556 TPtr8 dirBuf=DirBufPtr->Des();
1558 TBool res=IsSameAsDrive(fatBuf,dirBuf);
1564 LOCAL_C void TestExtendedChars()
1566 // tests that extended characters corresponding to ISO Latin 1
1567 // characters 128-255 are recognised as valid by scandrive
1570 test.Next(_L("TestExtendedChars()"));
1575 // check no entries in the root directory
1576 TInt r=TheFs.GetDir(KRoot,KEntryAttMaskSupported,ESortNone,dirs);
1578 test(dirs->Count()==0);
1583 _LIT(KOrigShortName,"P_SSI.TXT");
1585 //_LIT(KTestFile,"\\p\xE4ssi.txt"); //-- this causes problems for VC6 and default locale different from English
1586 TBuf<64> TestFileName(_L("\\p$ssi.txt"));
1587 TestFileName[2] = 0xe4; //-- replace '$' with this code
1589 //_LIT(KExtShortName,"P\xC4SSI.TXT"); //-- this causes problems for VC6 and default locale different from English
1590 TBuf<64> ExtShortName(_L("P$SSI.TXT"));
1591 ExtShortName[1] = 0xC4; //-- replace '$' with this code
1595 r=file.Replace(TheFs,TestFileName,EFileShareExclusive);
1600 TFileName shortName;
1601 r=TheFs.GetShortName(TestFileName,shortName);
1603 test(shortName==KOrigShortName);
1605 // must be first entry in root, modify to read like
1606 // a windows-generated short name (ie. contains extended character)
1607 DumpData(NULL, 0, 20);
1608 TInt bytePos=ClusterEntryToBytes(0,1);
1610 r=raw.Open(TheFs,gSessionPath[0]-'A');
1614 //-- change 2nd character in the short name (Fat DOS entry)
1615 buf[0]=(TUint8)'\xC4';
1616 r=raw.Write(gRootDirStart+bytePos+1,buf);
1619 //-- fix the fiddled short name checksum in the corresponding VFat entry
1620 bytePos=ClusterEntryToBytes(0,0);
1621 buf[0]=(TUint8)0x2f;
1622 r=raw.Write(gRootDirStart+bytePos+13,buf);
1625 // retrieve short name from media.
1626 // Note: do not use RFs::GetShortName() as its behaviours are code page dependent.
1627 bytePos=ClusterEntryToBytes(0,1);
1628 TBuf8<11> shortNameBuf8;
1629 r=raw.Read(gRootDirStart+bytePos,shortNameBuf8);
1631 shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8);
1632 shortName.Copy(shortNameBuf8);
1636 test(shortName==ExtShortName);
1637 DumpData(NULL, 0, 20);
1638 //TheFs.SetDebugRegister(KFSYS);
1639 r=TheFs.ScanDrive(gSessionPath);
1640 TheFs.SetDebugRegister(0);
1642 DumpData(NULL, 0, 20);
1644 // retrieve short name from media.
1645 r=raw.Open(TheFs,gSessionPath[0]-'A');
1647 bytePos=ClusterEntryToBytes(0,1);
1648 r=raw.Read(gRootDirStart+bytePos,shortNameBuf8);
1650 shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8);
1651 shortName.Copy(shortNameBuf8);
1654 test(shortName==ExtShortName);
1657 r=TheFs.Delete(TestFileName);
1661 LOCAL_C void TestMountAndScan()
1663 // test MountFileSystemAndScan()
1667 TBool primaryExtensionExists = EFalse;
1669 test.Next(_L("TestMountAndScan"));
1670 HBufC8* newFat=HBufC8::New(gFatTestSize);
1672 TPtr8 fat=newFat->Des();
1673 TPtr8 origFat=FatBufPtr->Des();
1674 TPtr8 origDir=DirBufPtr->Des();
1676 // set cluster of \scndrv\dir1\ to a hanging cluster
1678 WriteFat(gClusterDir1ext,35,fat.Ptr());
1679 WriteFat(35,36,fat.Ptr());
1681 // set the default path to something other than the current drive
1683 TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A');
1685 TFileName origDefPath, newDefPath;
1686 r=TheFs.SessionPath(origDefPath);
1688 newDefPath=origDefPath;
1689 newDefPath[0]=(TText)'z';
1690 r=TheFs.SetSessionPath(newDefPath);
1692 r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0);
1695 primaryExtensionExists = ETrue;
1697 r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A');
1699 // mount file system and check scandrive corrects error
1701 if (primaryExtensionExists)
1702 r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount);
1704 r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount);
1705 test(isMount && r==KErrNone);
1706 TBool res=IsSameAsDrive(origFat,origDir);
1709 r=TheFs.SetSessionPath(origDefPath);
1715 LOCAL_C void TestConsecutiveMountAndScans()
1717 // test fix for DEF093072: [codebase]MountFileSystemAndScan returns err -21 but ok flag
1721 TBool primaryExtensionExists = EFalse;
1723 TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A');
1725 r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0);
1728 primaryExtensionExists = ETrue;
1730 r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A');
1733 // RFs::MountFileSystemAndScan twice consecutively
1736 if (primaryExtensionExists)
1737 r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount);
1739 r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount);
1740 test(isMount && r==KErrNone);
1741 // and a second time
1742 if (primaryExtensionExists)
1743 r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount);
1745 r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount);
1746 test(!isMount && r==KErrAccessDenied);
1749 LOCAL_C void DoHangingClusters()
1751 // Tests that scandrive removes hanging clusters
1754 test.Next(_L("Check Hanging clusters"));
1755 HBufC8* newFat=HBufC8::New(gFatTestSize);
1757 TPtr8 fat=newFat->Des();
1758 TPtr8 origFat=FatBufPtr->Des();
1759 TPtr8 origDir=DirBufPtr->Des();
1761 // set cluster of \scndrv\dir1\ to a hanging cluster
1762 test.Start(_L("Test hanging cluster in \\scndrv\\dir1\\"));
1764 WriteFat(gClusterDir1ext,35,fat.Ptr());
1765 WriteFat(35,36,fat.Ptr());
1767 TInt r=TheFs.ScanDrive(gSessionPath);
1769 TBool res=IsSameAsDrive(origFat,origDir);
1772 // set cluster chain of first entry of \scndrv\dir1\ to
1773 // larger size than file size
1774 test.Next(_L("Test hanging cluster in first entry"));
1776 WriteFat(gClusterDir1ext,39,fat.Ptr());
1777 WriteFat(39,500,fat.Ptr());
1778 WriteFat(500,gEndOfChain,fat.Ptr());
1780 r=TheFs.ScanDrive(gSessionPath);
1782 res=IsSameAsDrive(origFat,origDir);
1785 // set cluster of \scndrv\ to a hanging cluster
1786 test.Next(_L("Test hanging cluster of \\scndrv\\"));
1788 WriteFat(gClusterScnDrv,511,fat.Ptr());
1790 r=TheFs.ScanDrive(gSessionPath);
1792 res=IsSameAsDrive(origFat,origDir);
1799 LOCAL_C void DoLostClusters()
1801 // Tests that scandrive removes lost clusters
1804 test.Next(_L("Check lost clusters"));
1805 HBufC8* newFat=HBufC8::New(gFatTestSize);
1807 TPtr8 fat=newFat->Des();
1808 TPtr8 origFat=FatBufPtr->Des();
1809 TPtr8 origDir=DirBufPtr->Des();
1810 ReadFatDisk(origFat);
1811 ReadDirDisk(origDir);
1813 // write cluster chain
1814 test.Start(_L("Test removal of lost cluster chain"));
1816 for(TInt i=25;i<35;++i)
1817 WriteFat(i,i+1,fat.Ptr());
1818 WriteFat(35,gEndOfChain,fat.Ptr());
1820 TInt r=TheFs.ScanDrive(gSessionPath);
1822 TBool res=IsSameAsDrive(origFat,origDir);
1825 // write semi-random changes to first fat
1826 test.Next(_L("Test semi-random changes to first fat"));
1827 for(TInt j=1;j<gFatTestSize/BootSector.BytesPerSector();++j)
1829 TInt off = j*BootSector.BytesPerSector()+j*7%512;
1833 r=TheFs.ScanDrive(gSessionPath);
1835 res=IsSameAsDrive(origFat,origDir);
1838 // write semi-random changes to second fat
1839 test.Next(_L("Test semi-random changes to second fat"));
1840 WriteFatDisk(fat, 1);
1841 r=TheFs.ScanDrive(gSessionPath);
1843 res=IsSameAsDrive(origFat,origDir);
1850 LOCAL_C void DoPartEntries()
1852 // Tests that scandrive detects/corrects partial entries
1858 test.Start(_L("Check partial entries"));
1859 TPtr8 fatBuf=FatBufPtr->Des();
1860 TPtr8 dirBuf=DirBufPtr->Des();
1862 TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedirwith3entries\\"));
1863 test(r==KErrNone || r==KErrNotFound || KErrPathNotFound);
1864 r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedir2with3entries\\"));
1865 test(r==KErrNone || r==KErrNotFound || KErrPathNotFound);
1867 if (BootSector.RootDirEntries() != 0)
1869 // Can only do this on FAT12/16, FAT32 root directory is extensible
1870 // partial entry that fills up the root dir
1871 test.Next(_L("Partial entry at end of rootdir"));
1873 r=temp.Create(TheFs,_L("\\temp"),EFileShareAny);
1876 ReadDirDisk(dirBuf);
1877 ReadFatDisk(fatBuf);
1878 TEntryInfo partial1(ClusterEntryToBytes(gClusterRootDir,BootSector.RootDirEntries()-2),2);
1879 CreatePartialEntry(partial1,1,EFalse);
1880 res=TestPartialEntry(partial1);
1883 ReadDirDisk(dirBuf);
1884 ReadFatDisk(fatBuf);
1887 // use first entry \scndrv\dir2\almostfull\
1888 test.Next(_L("Partial entry in middle of subdir"));
1889 last = GetStartCluster(gClusterDir2_AFull,7);
1890 TEntryInfo partial2(ClusterEntryToBytes(gClusterDir2_AFull,2),6);
1891 CreatePartialEntry(partial2,3,EFalse);
1892 // entry has been allocated a cluster which scandrive should delete along with partial entry
1894 WriteFat(last,0,fatBuf.Ptr());
1895 res=TestPartialEntry(partial2);
1898 // reduce size of \scndrv\dir2\full\
1899 test.Next(_L("Test directory reclaim"));
1900 last = GetStartCluster(gClusterDir2_Full,gEntriesPerCluster-2);
1901 WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2));
1902 WriteDirDisk(dirBuf);
1903 TInt entry = GetFatEntry(gClusterDir2_Full, fatBuf.Ptr());
1904 WriteFat(gClusterDir2_Full,gEndOfChain,fatBuf.Ptr());
1905 while (entry && (entry & gEndOfChain) != gEndOfChain)
1907 TInt next = GetFatEntry(entry, fatBuf.Ptr());
1908 WriteFat(entry,0,fatBuf.Ptr());
1912 WriteFat(last,0,fatBuf.Ptr());
1913 r=TheFs.ScanDrive(gSessionPath);
1915 res=IsSameAsDrive(fatBuf,dirBuf);
1918 // use last entry of first cluster in \scndrv\dir2\full\
1919 test.Next(_L("Partial entry at end of subdir"));
1920 r=temp.Create(TheFs,_L("\\scndrv\\dir2\\full\\temp"),EFileShareAny);
1923 ReadDirDisk(dirBuf);
1924 ReadFatDisk(fatBuf);
1925 TEntryInfo partial3(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),2);
1926 CreatePartialEntry(partial3,1,EFalse);
1927 res=TestPartialEntry(partial3);
1930 // use entry in \scndrv\dir2\almostfull\
1931 test.Next(_L("Partial entry preceeding end-of-dir marker"));
1932 last = GetStartCluster(gClusterDir2_AFull,14);
1934 WriteFat(last,0,fatBuf.Ptr());
1935 last = GetStartCluster(gClusterDir2_AFull,8);
1937 WriteFat(last,0,fatBuf.Ptr());
1938 WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_AFull,14));
1939 WriteDirDisk(dirBuf);
1940 TEntryInfo partial4(ClusterEntryToBytes(gClusterDir2_AFull,8),6);
1941 CreatePartialEntry(partial4,4,EFalse);
1942 res=TestPartialEntry(partial4);
1946 // Following test case is not valid anymore after fixing of
1947 // PDEF128576: Unicode name file deleted after Scandrive
1948 // In the fixes, we decided to discard file name checking in ScanDrive,
1949 // as it is impossible for ScanDrive to judge if the illegal byte is part of a legal
1952 // create entry in \scndrv\dir2\almostfull\
1953 // test.Next(_L("Partial entry with invalid dos name"));
1954 // r=temp.Create(TheFs,_L("\\scndrv\\dir2\\almostfull\\Dodgy file name"),EFileShareAny);
1955 // test(r==KErrNone);
1957 // ReadDirDisk(dirBuf);
1958 // TInt dosStart=ClusterEntryToBytes(gClusterDir2_AFull,4);
1959 // dirBuf[dosStart+4]=0x1;
1960 // WriteDirDisk(dirBuf);
1961 // r=TheFs.ScanDrive(gSessionPath);
1962 // test(r==KErrNone);
1963 // WriteDelete(dosStart-2*32,3);
1964 // res=IsSameAsDrive(fatBuf,dirBuf);
1967 if (BootSector.SectorsPerCluster() == 1)
1969 // use entry created in \scndrv\dir2\
1970 test.Next(_L("Partial entry spanning more than two clusters"));
1971 last = GetStartCluster(gClusterDir2_Full,gEntriesPerCluster-1);
1972 WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2));
1973 WriteEndOfDir(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-1));
1974 WriteDirDisk(dirBuf);
1975 TFileName longFile=_L("\\scndrv\\dir2\\full\\");
1976 MakeVeryLongName(longFile);
1977 r=temp.Create(TheFs,longFile,EFileShareAny);
1980 ReadDirDisk(dirBuf);
1981 WriteFat(gClusterDir2_Full,gClusterDir2_SD3E,fatBuf.Ptr());
1982 WriteFat(gClusterDir2_SD3E,gClusterDir2_SD23E,fatBuf.Ptr());
1983 WriteFat(gClusterDir2_SD23E,gEndOfChain,fatBuf.Ptr());
1985 WriteFat(last,0,fatBuf.Ptr());
1986 TEntryInfo partial5(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),19);
1987 CreatePartialEntry(partial5,7,EFalse);
1988 res=TestPartialEntry(partial5);
1990 r=TheFs.Delete(longFile);
1991 test(r==KErrNone || r==KErrNotFound);
1992 r=TheFs.Delete(_L("\\temp"));
1993 test(r==KErrNone || r==KErrNotFound);
1995 ReadDirDisk(dirBuf);
2000 LOCAL_C void DoMatchingEntries()
2002 // Tests that scandrive detects/corrects entries with the same start cluster
2003 // Copies entry to new location - replicates start cluster
2006 test.Next(_L("Check matching entries"));
2007 TPtr8 fatBuf=FatBufPtr->Des();
2008 TPtr8 dirBuf=DirBufPtr->Des();
2009 ReadDirDisk(dirBuf);
2010 ReadFatDisk(fatBuf);
2012 // first entry in \scndrv\almostfull\ + root dir
2013 test.Start(_L("matching entries in subdir + root dir"));
2014 TEntryInfo from1(ClusterEntryToBytes(gClusterDir2_AFull,2),6);
2015 TEntryInfo to1(ClusterEntryToBytes(gClusterRootDir,2),6);
2016 CreateMatchingEntry(to1,from1,EFalse);
2017 TBool res=TestMatchingEntry(to1);
2020 // matching entries between 2 subdirs, one which has a full cluster
2021 // first entry in \scndrv\dir2\full\ + end of \scndrv\dir2\almostfull\
2022 test.Next(_L("matching entries between 2 subdirs"));
2023 TEntryInfo from2(ClusterEntryToBytes(gClusterDir2_Full,2),2);
2024 TEntryInfo to2(ClusterEntryToBytes(gClusterDir2_AFull,14),2);
2025 CreateMatchingEntry(to2,from2,EFalse);
2026 res=TestMatchingEntry(to2);
2029 // matching entries between two subdirs - one with end of dir marker next
2030 // \scndrv\dir2\somedirwith3entries to \scndrv\
2031 test.Next(_L("matching entries between two subdirs"));
2032 TEntryInfo from3(ClusterEntryToBytes(gClusterDir2,4),3);
2033 TEntryInfo to3(ClusterEntryToBytes(gClusterScnDrv,6),3);
2034 CreateMatchingEntry(to3,from3,ETrue);
2035 res=TestMatchingEntry(to3);
2038 // matching entries in same subdir, one in new cluster - irrelevant if matching names
2039 // 1st and last entries in \scndrv\dir2\full\
2040 test.Next(_L("matching entries in same subdir"));
2041 // delete entries to allow contiguous clusters in \scndrv\dir2\full directory
2042 TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedirwith3entries\\"));
2044 r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedir2with3entries\\"));
2046 // ensure directory is expanded
2048 r=temp.Create(TheFs,_L("\\scndrv\\dir2\\full\\temp"),EFileShareAny);
2051 r=TheFs.Delete(_L("\\scndrv\\dir2\\full\\temp"));
2053 ReadDirDisk(dirBuf);
2054 ReadFatDisk(fatBuf);
2055 TEntryInfo from4(ClusterEntryToBytes(gClusterDir2_Full,4),2);
2056 TEntryInfo to4(ClusterEntryToBytes(gClusterDir2_Full+1,0),2);
2057 CreateMatchingEntry(to4,from4,ETrue);
2058 res=TestMatchingEntry(to4);
2061 // \scndrv\dir1\very long name to \\scndrv\dir2\full\
2062 test.Next(_L("matching entries in diff dirs + new cluster"));
2063 // delete last entry in directory
2064 r=TheFs.Delete(LastInFull);
2066 TFileName veryLongName=_L("\\scndrv\\dir2\\full\\");
2067 MakeVeryLongName(veryLongName);
2068 r=temp.Create(TheFs,veryLongName,EFileShareAny);
2071 r=TheFs.Delete(veryLongName);
2073 ReadDirDisk(dirBuf);
2074 ReadFatDisk(fatBuf);
2075 TEntryInfo from5(ClusterEntryToBytes(gClusterDir1,2),19);
2076 TEntryInfo to5(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),19);
2077 CreateMatchingEntry(to5,from5,EFalse);
2078 res=TestMatchingEntry(to5);
2085 LOCAL_C void DoMaxDepth()
2087 // Test directory structure with max possible depth
2090 test.Next(_L("Check max directory depth"));
2091 test.Start(_L("Using single character names"));
2092 TPtr8 fatBuf=FatBufPtr->Des();
2093 TPtr8 dirBuf=DirBufPtr->Des();
2094 // Create dir structure
2095 TFileName dir1=_L("\\");
2097 CreateMaxDepthDir(dir1,dir2);
2098 ReadDirDisk(dirBuf);
2099 ReadFatDisk(fatBuf);
2100 // run scandisk and compare
2101 TInt r=TheFs.ScanDrive(gSessionPath);
2103 TBool res=IsSameAsDrive(fatBuf,dirBuf);
2105 // Create a entry with matching start cluster and check fixed up
2106 TEntryInfo from(ClusterEntryToBytes(gClusterDir2_AFull,2),6);
2107 TEntryInfo to(ClusterEntryToBytes(gClusterEndMaxDepth,2),6);
2108 CreateMatchingEntry(to,from,ETrue);
2109 res=TestMatchingEntry(to);
2111 // DeleteMaxDepthStructure
2112 DeleteMaxDepthDir(dir1,dir2);
2116 LOCAL_C void DoRootDir()
2118 // Check that a full root directory is searched OK
2121 test.Next(_L("Check a full root directory"));
2123 TPtr8 fatBuf=FatBufPtr->Des();
2124 TPtr8 dirBuf=DirBufPtr->Des();
2125 ReadDirDisk(dirBuf);
2126 ReadFatDisk(fatBuf);
2128 TInt r=TheFs.ScanDrive(gSessionPath);
2131 TBool res=IsSameAsDrive(fatBuf,dirBuf);
2136 LOCAL_C void TestNonVfatNames(const TPtrC& aDirName, TInt aDirCluster, TInt aEntry=2)
2138 // Check that files without 'long' entries are kept intact. Creates files with
2139 // a DOS type name, and for each one created except the last deletes the VFAT
2140 // entry by copying the DOS entry over it and writing end of directory. This
2141 // leaves a VFAT entry at the end of the directory, except when there is only
2142 // room for one file.
2144 // The layout, for 1 sector per cluster, is thus like:
2150 // 14 tempfile.012 VFAT
2153 // or for an almost full directory
2159 // 15 end of directory
2162 test.Printf(_L("Test cluster %2d, aEntry %d: %S\n"), aDirCluster, aEntry, &aDirName);
2163 TPtr8 fatBuf=FatBufPtr->Des();
2164 TPtr8 dirBuf=DirBufPtr->Des();
2165 TInt cluster = aDirCluster;
2167 TInt maxEntry = gEntriesPerCluster;
2168 if (aDirName.Compare(_L("\\")) == KErrNone)
2169 maxEntry = Min(gRootDirEntries, gEntriesPerCluster);
2171 TInt entry = aEntry;
2175 while (entry > gEntriesPerCluster)
2177 entry -= gEntriesPerCluster;
2181 TInt nFiles = maxEntry - entry - 1;
2182 TInt startEntry = entry;
2184 test.Printf(_L("cluster %d, entry %d maxEntry %d, nFiles %d\n"), cluster, entry, maxEntry, nFiles);
2189 // Set up files, ignoring used slots
2190 TInt filesThisTime = nFiles;
2191 TInt totalFilesCreated = 0;
2195 // Create a number of VFat entries
2197 // - We create as many as we can fit in the cluster in one go.
2198 // This is faster than creating a single entry then copying, as writing the
2199 // entries one at a time using RRawDisk causes a remount of the file system,
2200 // which can take a very long time on a large disk.
2202 filesThisTime = (nFiles - totalFilesCreated) >> 1;
2203 if(filesThisTime == 0)
2205 if(nFiles == totalFilesCreated)
2207 test.Printf(_L("Created all Non-VFAT entries\n"));
2211 //...creating the final entry
2215 for (i = 0; i < filesThisTime; i++)
2217 TFileName name(aDirName);
2218 name.Append(_L("tempfile."));
2219 name.AppendNumFixedWidth(i+totalFilesCreated, EHex, 3);
2221 r = f.Create(TheFs, name, EFileShareAny);
2222 test(r == KErrNone);
2224 test(r == KErrNone);
2229 // Move DOS FAT entries up using RRawDisk, deleting the original VFAT entries
2231 ReadDirDisk(dirBuf, cluster);
2232 TInt dosEntry = entry + 1;
2233 for (i = 0; i < filesThisTime; i++)
2235 // Copy VFAT to Non-VFAT entries
2236 if (entry+2 < maxEntry || nFiles < 2)
2238 TInt posVFAT = ClusterEntryToBytes(cluster, entry);
2239 TInt posEOD = ClusterEntryToBytes(cluster, entry+1);
2240 TInt posDOS = ClusterEntryToBytes(cluster, dosEntry);
2242 WriteCopyDir(posDOS, posVFAT); // Copy the DOS entry
2243 WriteDelete(posDOS,2); // Delete the original entry
2244 WriteEndOfDir(posEOD); // Write End Of Directory
2251 // last entry has VFAT intact, to fill cluster
2257 WriteDirDisk(dirBuf, cluster);
2258 totalFilesCreated += filesThisTime;
2259 test.Printf(_L(" created %d entries\n"), totalFilesCreated);
2262 ReadDirDisk(dirBuf);
2263 ReadFatDisk(fatBuf);
2265 DumpData(NULL, aDirCluster, cluster+1);
2267 test.Printf(_L("Running ScanDrive\n"), filesThisTime);
2268 r=TheFs.ScanDrive(gSessionPath);
2271 TBool res=IsSameAsDrive(fatBuf,dirBuf);
2274 test.Printf(_L("Deleting %d files\n"), nFiles);
2275 for (i = 0; i < nFiles; i++)
2277 TFileName name(aDirName);
2278 name.Append(_L("tempfile."));
2279 name.AppendNumFixedWidth(i, EHex, 3);
2280 r = TheFs.Delete(name);
2281 test(r == KErrNone);
2284 ReadDirDisk(dirBuf);
2285 ReadFatDisk(fatBuf);
2286 WriteEndOfDir(ClusterEntryToBytes(cluster, startEntry));
2287 WriteDirDisk(dirBuf);
2289 test.Printf(_L("Running ScanDrive\n"), filesThisTime);
2290 r=TheFs.ScanDrive(gSessionPath);
2292 res=IsSameAsDrive(fatBuf,dirBuf);
2296 LOCAL_C void DoNonVfatNames()
2298 // Check that files without 'long' entries are kept intact
2301 test.Next(_L("Check non-VFAT file names"));
2302 TestNonVfatNames(_L("\\"), gClusterRootDir, 2);
2303 TestNonVfatNames(_L("\\scndrv\\dir1\\"), gClusterDir1, 2+19);
2304 TestNonVfatNames(_L("\\scndrv\\dir2\\somedirwith3entries\\"), gClusterDir2_SD3E, 2);
2305 TestNonVfatNames(_L("\\scndrv\\dir2\\almostfull\\"), gClusterDir2_AFull, 14);
2309 LOCAL_C void DoTests()
2315 InitialiseBuffers();
2317 CreateDirectoryStructure();
2318 TPtr8 fatBuf=FatBufPtr->Des();
2319 TPtr8 dirBuf=DirBufPtr->Des();
2320 ReadDirDisk(dirBuf);
2321 ReadFatDisk(fatBuf);
2323 DumpData(NULL, DirBufPtr->Ptr());
2328 DoMatchingEntries();
2331 DoHangingClusters();
2333 TestConsecutiveMountAndScans();
2334 DeleteDirectoryStructure();
2336 TestExtendedChars();
2340 DumpData(NULL, 0, 200);
2352 r = TheFs.CharToDrive(gSessionPath[0], gDriveNumber);
2353 test( KErrNone == r );
2356 //-- set up console output
2357 Fat_Test_Utils::SetConsole(test.Console());
2359 //-- print drive information
2360 PrintDrvInfo(TheFs, gDriveNumber);
2362 if (!Is_Fat(TheFs, gDriveNumber))
2364 test.Printf(_L("CallTestsL: Skipped: test requires FAT filesystem\n"));
2368 // check this is not the internal ram drive
2372 if(v.iDrive.iMediaAtt&KMediaAttVariableSize)
2374 test.Printf(_L("Error: Internal ram drive not tested\n"));
2378 r=TheFs.SetSessionPath(gSessionPath);