os/kernelhwsrv/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32test\scndrv\t_scn32dr1.cpp
    15 //
    16 //
    17 
    18 #include <f32file.h>
    19 #include <e32test.h>
    20 
    21 #include "t_server.h"
    22 
    23 #include "fat_utils.h"
    24 using namespace Fat_Test_Utils;
    25 
    26 #ifdef __VC32__
    27     // Solve compilation problem caused by non-English locale
    28     #pragma setlocale("english")
    29 #endif
    30 
    31 /*
    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
    36 */
    37 
    38 /*
    39   The initial FAT12 directory structure (with cluster number in brackets) is as follows:
    40 
    41   |
    42    - scndrv (2)
    43         |
    44         - dir1 (3-4)
    45         |   |
    46         |   <a very long file name (19 entries)> (5)
    47         |
    48         - dir2 (6)
    49             |
    50             - full (7)
    51             |   |
    52             |   |
    53             |   - <seven 2*32 bytes entries> (11-17)
    54             |
    55             - somedirwith3entries (8)
    56             |
    57             - somedir2with3entries (9)
    58             |
    59             - almostfull(10)
    60                 |
    61                 - <two lots of 6*32 bytes entries> (18+19)
    62 
    63 */
    64 
    65 /*
    66   The initial FAT32 directory structure (with cluster number in brackets is as follows):
    67 
    68   |
    69    - scndrv (3)
    70         |
    71         - dir1 (4)
    72         |   |
    73         |   <a very long file name (19 entries)> (5)
    74         |
    75         - dir2 (6)
    76             |
    77             - full (7)
    78             |   |
    79             |   |
    80             |   - <seven 2*32 bytes entries> (11-17)
    81             |
    82             - somedirwith3entries (8)
    83             |
    84             - somedir2with3entries (9)
    85             |
    86             - almostfull(10)
    87                 |
    88                 - <two lots of 6*32 bytes entries> (18+19)
    89 
    90 */
    91 
    92 GLDEF_D RTest test(_L("T_SCN32DR1"));
    93 
    94 LOCAL_D const TInt KMaxFatEntries  = 2048;
    95 LOCAL_D const TInt KMaxFatSize     = KMaxFatEntries * 4;
    96 
    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;
   106 
   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;
   117 
   118 static TFatType gDiskType = EInvalid;
   119 
   120 LOCAL_D TInt gDriveNumber;
   121 
   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
   136 
   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
   148 
   149 LOCAL_D TFileName LastInFull;
   150 
   151 class TEntryInfo
   152     {
   153 public:
   154     TEntryInfo(TInt aBytePos,TInt aLength):iBytePos(aBytePos),iLength(aLength){}
   155     TEntryInfo(){}
   156 public:
   157     TInt iBytePos;
   158     TInt iLength;
   159     };
   160 
   161 
   162 LOCAL_C TInt DirBufferSize()
   163 //
   164 // returns size in bytes nec for buffer to store relevant disk data
   165 //
   166     {
   167     return(gMaxDataCluster*gBytesPerCluster);
   168     }
   169 
   170 LOCAL_C TInt PosInBytes(TInt aFatIndex)
   171 //
   172 // Return number of bytes into the FAT
   173 //
   174     {
   175     TInt fatPosInBytes = -1;
   176     switch (gDiskType)
   177         {
   178         case EFat32:
   179             fatPosInBytes=aFatIndex<<2;
   180             break;
   181         case EFat16:
   182             fatPosInBytes=aFatIndex<<1;
   183             break;
   184         case EFat12:
   185             fatPosInBytes=(aFatIndex*3>>1);
   186             break;
   187         default:
   188             test(0);
   189         }
   190     return(fatPosInBytes);
   191     }
   192 
   193 LOCAL_C TUint32 MaxClusters()
   194 //
   195 // Return the number of data clusters on the disk
   196 //
   197     {
   198     TUint32 totSec = (BootSector.TotalSectors() ? BootSector.TotalSectors() : BootSector.HugeSectors());
   199     TUint32 numSec = totSec - gFirstDataSector;
   200     return numSec / BootSector.SectorsPerCluster();
   201     }
   202 
   203 LOCAL_C TInt ClusterToByte(TInt aCluster)
   204 //
   205 // converts cluster number to byte offset on disk
   206 //
   207     {
   208     TInt pos;
   209     if (aCluster < 2)
   210         pos = gRootDirStart;
   211     else
   212         pos = (aCluster - 2) * gBytesPerCluster + gFirstDataSector * BootSector.BytesPerSector();
   213     return pos;
   214     }
   215 
   216 LOCAL_C TInt ByteToCluster(TInt aBytePos)
   217 //
   218 // Converts byte offset from root dir buffer to cluster number
   219 //
   220     {
   221     if (aBytePos < gRootDirStart)
   222         return -1;
   223     if (aBytePos < gDataStartBytes)
   224         return 0;
   225     return (aBytePos - gDataStartBytes) / gBytesPerCluster + 2;
   226     }
   227 
   228 LOCAL_C TInt ClusterEntryToBytes(TInt aCluster,TInt aEntry)
   229 //
   230 // converts position in cluster and entry number to byte pos from root directory
   231 //
   232     {
   233     TInt pos;
   234     pos = ClusterToByte(aCluster) - gRootDirStart + aEntry*KSizeOfFatDirEntry;
   235     return pos;
   236     }
   237 
   238 LOCAL_C TInt FindUnMatch(const TUint8* aBuf, const TUint8* aCmp, TInt aLen, TInt aStart=0)
   239 //
   240 // Return position in buffers which doesn't match, or -1 if it matches
   241 //
   242     {
   243     for (TInt i = aStart; i < aStart + aLen; i++)
   244         if (aBuf[i] != aCmp[i])
   245             return i;
   246     return -1;
   247     }
   248 
   249 LOCAL_C TUint32 GetFatEntry(TUint32 aIndex, const TUint8* aFat=NULL)
   250 //
   251 // Read a single FAT entry from disk or FAT copy and return it
   252 //
   253     {
   254     TInt pos = PosInBytes(aIndex);
   255 
   256     TUint8  data[4];
   257     TUint8* ptr = data;
   258 
   259     if (aFat)
   260         ptr = (TUint8*)aFat + pos;
   261     else
   262         {
   263         pos += BootSector.ReservedSectors() * BootSector.BytesPerSector();
   264         TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
   265         test(r==KErrNone);
   266         TPtr8 buf(&data[0], 4);
   267         r=TheRawDisk.Read(pos, buf);
   268         test(r==KErrNone);
   269         TheRawDisk.Close();
   270         }
   271 
   272     TUint32 val = 0;
   273     switch (gDiskType)
   274         {
   275         case EFat32:
   276             val = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24);
   277             break;
   278         case EFat16:
   279             val = ptr[0] + (ptr[1] << 8);
   280             break;
   281         case EFat12:
   282             val = ptr[0] + (ptr[1] << 8);
   283             if (aIndex & 1)
   284                     val >>= 4;
   285             val &= 0xFFF;
   286             break;
   287         default:
   288             test(0);
   289         }
   290     return val;
   291     }
   292 
   293 LOCAL_C void WriteFat(TInt aFatIndex,TInt aValue,const TUint8* aFat)
   294 //
   295 // Write a value to both fats starting at aFat
   296 //
   297     {
   298     TUint8* p=(TUint8*)(aFat+PosInBytes(aFatIndex));
   299     switch (gDiskType)
   300         {
   301         case EFat32:
   302             p[0] = (TUint8) (aValue);
   303             p[1] = (TUint8) (aValue >> 8);
   304             p[2] = (TUint8) (aValue >> 16);
   305             p[3] = (TUint8) (aValue >> 24);
   306             break;
   307         case EFat16:
   308             p[0] = (TUint8) (aValue);
   309             p[1] = (TUint8) (aValue >> 8);
   310             break;
   311         case EFat12:
   312             {
   313             TUint8 mask=0x0F;
   314             TBool odd=(aFatIndex)&1;
   315             TUint8 fatVal;
   316             TInt value=aValue;
   317             if(odd)
   318                 {
   319                 mask<<=4;
   320                 value<<=4;
   321                 fatVal=p[0];
   322                 fatVal&=~mask;
   323                 fatVal|=(TUint8)(value&0xFF);
   324                 p[0]=fatVal;
   325                 p[1]=(TUint8)(value>>8);
   326                 }
   327             else
   328                 {
   329                 p[0]=(TUint8)(value&0xFF);
   330                 fatVal=p[1];
   331                 fatVal&=~mask;
   332                 fatVal|=(TUint8)(value>>8);
   333                 p[1]=fatVal;
   334                 }
   335             }
   336             break;
   337         default:
   338             test(0);
   339         }
   340     return;
   341     }
   342 
   343 static void DoReadBootSector()
   344     {
   345 
   346     TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<<KDefaultSectorLog2, BootSector);
   347     test(nRes == KErrNone);
   348 
   349     if(!BootSector.IsValid())
   350         {
   351         test.Printf(_L("Wrong bootsector! Dump:\n"));
   352         BootSector.PrintDebugInfo();
   353         test(0);
   354         }
   355 
   356     // Calculate derived variables (fixed for a particular disk format)
   357     if (BootSector.RootDirEntries() == 0)
   358         {
   359         test.Printf(_L("Disk is FAT32\n"));
   360         gDiskType = EFat32;
   361         gEndOfChain = 0x0FFFFFFF;
   362         }
   363     else if (BootSector.FatType() == EFat16)
   364         {
   365         test.Printf(_L("Disk is FAT16\n"));
   366         gDiskType = EFat16;
   367         gEndOfChain = 0xFFFF;
   368         }
   369     else
   370         {
   371         test.Printf(_L("Disk is FAT12\n"));
   372         gDiskType = EFat12;
   373         gEndOfChain = 0x0FFF;
   374         }
   375 
   376     gBytesPerCluster   = BootSector.BytesPerSector() * BootSector.SectorsPerCluster();
   377     gFatStartBytes     = BootSector.ReservedSectors() * BootSector.BytesPerSector();
   378     gEntriesPerCluster = gBytesPerCluster / KSizeOfFatDirEntry;
   379 
   380     TBool big = (BootSector.SectorsPerCluster() > 1);
   381     switch (gDiskType)
   382         {
   383         case EFat12:
   384         case EFat16:
   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);
   402             break;
   403         case EFat32:
   404             //
   405             // FAT32 will alway pre-allocate a single cluster for the root directory
   406             //
   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.
   410             //
   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();
   414 
   415             gRootSector         = BootSector.ReservedSectors() + BootSector.NumberOfFats() * gFatSizeSectors;
   416             gFirstDataSector    = gRootSector;
   417 
   418             gDataStartBytes     = gFirstDataSector * BootSector.BytesPerSector();
   419             gRootDirStart       = (BootSector.RootClusterNum() - 2) * gBytesPerCluster + gDataStartBytes;
   420 
   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);
   431             break;
   432         default:
   433             break;
   434         }
   435 
   436     gMaxDataCluster = gClusterDir2_AFull + 2 + (gFirstDataSector / BootSector.SectorsPerCluster() + 1);
   437 
   438     gFatTestEntries = MaxClusters();
   439     if (gFatTestEntries > KMaxFatSize)
   440         gFatTestEntries = KMaxFatSize;
   441     }
   442 
   443 
   444 GLDEF_C void DumpBootSector()
   445 //
   446 // Display (in log) TFatBootSector structure
   447 //
   448     {
   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());
   461 
   462     if (gDiskType == EFat32)
   463         {
   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());
   470         }
   471     }
   472 
   473 GLDEF_C void DumpFat(const TUint8* aFat=NULL)
   474 //
   475 // Dump to the log all those FAT entries which are non-zero
   476 //
   477     {
   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++)
   483         {
   484         TInt32 val = GetFatEntry(i, aFat);
   485         TInt32 msk = 0x0FFFFFFF;
   486         switch (gDiskType)
   487             {
   488             case EFat32:
   489                 msk = 0x0FFFFFFF;
   490                 break;
   491             case EFat16:
   492                 msk = 0xFFFF;
   493                 break;
   494             case EFat12:
   495                 msk = 0x0FFF;
   496                 break;
   497             default:
   498                 test(0);
   499             }
   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);
   506         else if (val > max)
   507             RDebug::Print(_L("    %8d -> 0x%08X"), i, val);
   508         else if (val != 0)
   509             RDebug::Print(_L("    %8d -> %d"), i, val);
   510         }
   511     RDebug::Print(_L("--------------------------------------------"));
   512     }
   513 
   514 GLDEF_C TDes* DirAttributes(TInt aAttrib)
   515 //
   516 // Return a pointer to a local buffer containing the attribute letters.
   517 //
   518     {
   519     LOCAL_D TBuf<6> str;
   520     LOCAL_D char*   atr = "RHSVDA";
   521     str.Fill(TText('-'), 6);
   522     for (TInt i = 0; i < 6; i++)
   523         if ((aAttrib >> i) & 1)
   524             str[i] = atr[i];
   525     return &str;
   526     }
   527 
   528 GLDEF_C TBool IsValidDirEntry(TFatDirEntry* aDir)
   529 //
   530 // Test whether buffer is a valid normal directory entry
   531 //
   532     {
   533     // first character must be 0x05 or greater than space
   534     if (aDir->iData[0] < 0x21 && aDir->iData[0] != 0x05)
   535         return EFalse;
   536     // other characters must be not less than space
   537     for (TInt i = 1; i < 11; i++)
   538         if (aDir->iData[i] < 0x20)
   539             return EFalse;
   540     return ETrue;
   541     }
   542 
   543 GLDEF_C void GetLongNamePart(TDes16& aName, const TUint8* aEntry, TInt aPos, TInt aOffset, TInt aLength)
   544 //
   545 // Extract part of a long name entry into the name buffer.
   546 //
   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
   552 //
   553     {
   554     for (TInt i = 0; i < aLength; i++)
   555         {
   556         TInt at = i * 2 + aOffset;
   557         TInt ch = aEntry[at] + aEntry[at+1] * 256;
   558         aName[aPos++] = TText(ch);
   559         }
   560     }
   561 
   562 GLDEF_C void ExtractNameString(TDes16& aName, const TUint8* aEntry)
   563 //
   564 // Extract a long name part from a directory entry, truncate it at the first
   565 // NUL (0) character and put quotes round it.
   566 //
   567     {
   568     aName.SetLength(15);
   569     TInt len = aName.Length() - 1;
   570     TText qu = '\'';
   571     aName[0] = qu;
   572     GetLongNamePart(aName, aEntry,  1,  1, 5);
   573     GetLongNamePart(aName, aEntry,  6, 14, 6);
   574     GetLongNamePart(aName, aEntry, 12, 28, 2);
   575     TInt i;
   576     for (i = 0; i < len; i++)
   577         if (aName[i] == 0)
   578             break;
   579     aName[i++] = qu;
   580     aName.SetLength(i);
   581     }
   582 
   583 GLDEF_C TBool DumpDirEntry(TInt aNum, const TUint8* aEntry)
   584 //
   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).
   587 //
   588     {
   589     TFatDirEntry* d = (TFatDirEntry*)aEntry;
   590     if (d->IsErased())
   591         {
   592         //RDebug::Print(_L("%5d: ERASED"), aNum);
   593         }
   594     else if (d->IsEndOfDirectory())
   595         {
   596         if (aNum > 0)
   597             RDebug::Print(_L("%5d: ------------- end of directory"), aNum);
   598         return EFalse;
   599         }
   600     else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
   601         {
   602         TBuf16<15> name;
   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);
   607         else
   608             RDebug::Print(_L("%5d: %-15S #%-2d"), aNum, &name, ord & ~KDirLastLongEntry);
   609         }
   610     else if (!IsValidDirEntry(d))
   611         {
   612         if (aNum > 0)
   613             RDebug::Print(_L("%5d: ============= INVALID ENTRY"), aNum);
   614         return EFalse;
   615         }
   616     else
   617         {
   618         TBuf<11> name;
   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());
   622         }
   623     return ETrue;
   624     }
   625 
   626 GLDEF_C void DumpDirCluster(const TUint8* aData, TInt aCluster=0)
   627 //
   628 // Dump directory entries until end of cluster or invalid/end entry found.
   629 //
   630     {
   631     if (aCluster > 2)
   632         aData += (aCluster-2) * gBytesPerCluster;
   633     for (TInt i = 0; i < gBytesPerCluster; i += KSizeOfFatDirEntry)
   634         {
   635         if (DumpDirEntry(i/KSizeOfFatDirEntry, aData))
   636             aData += KSizeOfFatDirEntry;
   637         else
   638             break;
   639         }
   640     }
   641 
   642 GLDEF_C void DumpRootDir(const TUint8* aData)
   643 //
   644 // Dump the data area buffer, trying to interpret directory clusters (only look
   645 // at clusters which are marked as 'used' in the FAT).
   646 //
   647     {
   648     RDebug::Print(_L("Root dir @ 0x%08X:"), gRootDirStart);
   649     for (TInt i = 0; i < BootSector.RootDirEntries(); i++)
   650         {
   651         if (DumpDirEntry(i, aData))
   652             aData += KSizeOfFatDirEntry;
   653         else
   654             break;
   655         }
   656     }
   657 
   658 GLDEF_C void DumpData(const TUint8* aFat, const TUint8* aDir)
   659 //
   660 // Dump the data area buffer, trying to interpret directory clusters (only look
   661 // at clusters which are marked as 'used' in the FAT).
   662 //
   663     {
   664     RDebug::Print(_L("--------------- DATA AREA ------------------"));
   665     if (gDiskType != EFat32)
   666         {
   667         DumpRootDir(aDir);
   668         }
   669     TInt max = (gFatTestEntries < gMaxDataCluster ? gFatTestEntries : gMaxDataCluster);
   670     for (TInt cluster = 2; cluster < max; cluster++)
   671         {
   672         if (GetFatEntry(cluster, aFat) != 0)
   673             {
   674             RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster));
   675             DumpDirCluster(aDir+gDataStartBytes-gRootDirStart, cluster);
   676             }
   677         }
   678     RDebug::Print(_L("--------------------------------------------"));
   679     }
   680 
   681 GLDEF_C void DumpData(const TUint8* aFat, TInt aStart, TInt aEnd = -1)
   682 //
   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).
   687 //
   688     {
   689     if (aStart > gFatTestEntries)
   690         return;
   691     RDebug::Print(_L("--------------- DATA AREA ------------------"));
   692     if (aEnd > gFatTestEntries)
   693         aEnd = gFatTestEntries;
   694     if (aEnd < 0)
   695         aEnd = aStart + 1;
   696     if (aStart < 2 && gDiskType != EFat32)
   697         {
   698         HBufC8* buf=HBufC8::New(BootSector.RootDirEntries() * KSizeOfFatDirEntry);
   699         test(buf != NULL);
   700         TPtr8 ptr=buf->Des();
   701         TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
   702         test(r==KErrNone);
   703         r=TheRawDisk.Read(gRootDirStart, ptr);
   704         test(r==KErrNone);
   705         TheRawDisk.Close();
   706         DumpRootDir(buf->Ptr());
   707         delete(buf);
   708         aStart = 2;
   709         }
   710     for (TInt cluster = aStart; cluster < aEnd; cluster++)
   711         {
   712         if (GetFatEntry(cluster, aFat) != 0)
   713             {
   714             HBufC8* buf=HBufC8::New(gBytesPerCluster);
   715             test(buf!=NULL);
   716             TPtr8 ptr=buf->Des();
   717             TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
   718             test(r==KErrNone);
   719             r=TheRawDisk.Read(ClusterToByte(cluster), ptr);
   720             test(r==KErrNone);
   721             TheRawDisk.Close();
   722             RDebug::Print(_L("Cluster %d @ 0x%08X:"), cluster, ClusterToByte(cluster));
   723             DumpDirCluster(ptr.Ptr());
   724             delete buf;
   725             }
   726         }
   727     RDebug::Print(_L("--------------------------------------------"));
   728     }
   729 
   730 GLDEF_C void DumpHex(const TUint8* aData, TInt aLen, TInt aBase=0)
   731 //
   732 // Dump a block of memory to the log in hex.
   733 //
   734     {
   735     for (TInt base = 0; base < aLen; base += 16)
   736         {
   737         TBuf<16*3+3+16+1> buf;
   738         TInt off;
   739         for (off = base; off < aLen && off < base + 16; off++)
   740             {
   741             buf.Append(TText(' '));
   742             buf.AppendNumFixedWidth(aData[off], EHex, 2);
   743             }
   744         buf.Append(_L("  |"));
   745         for (off = base; off < aLen && off < base + 16; off++)
   746             {
   747             TUint8 ch = aData[off];
   748             buf.Append(ch < 0x20 || ch > 0x7E ? TText('_') : TText(ch));
   749             }
   750         buf.Append(_L("|"));
   751         RDebug::Print(_L("%04X: %S"), base+aBase, &buf);
   752         }
   753     }
   754 
   755 GLDEF_C void DumpHex(const TPtrC8& aData, TInt aLen, TInt aBase=0)
   756 //
   757 // Dump a block of memory to the log in hex.
   758 //
   759     {
   760     DumpHex(aData.Ptr(), aLen, aBase);
   761     }
   762 
   763 GLDEF_C void DumpHex(TInt aPos, TInt aLen, TInt aBase=0)
   764 //
   765 // Dump a block of memory to the log in hex.
   766 //
   767     {
   768     TPtr8 dirBuf=DirBufPtr->Des();
   769     DumpHex(dirBuf.Ptr()+aPos, aLen, aBase);
   770     }
   771 
   772 GLDEF_C void Dump(TEntryInfo& aEntry)
   773 //
   774 // Dump an entry description to the log in hex
   775 //
   776     {
   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);
   780     }
   781 
   782 LOCAL_C TInt GetStartCluster(TInt aCluster, TInt aEntry)
   783 //
   784 // Get the start cluster pertaining to a directory entry in a specific
   785 // directory cluster, return -1 if not available (invalid entry).
   786 //
   787     {
   788     HBufC8* buf=HBufC8::New(gBytesPerCluster*2);
   789     test(buf!=NULL);
   790     TPtr8 ptr=buf->Des();
   791     TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
   792     test(r==KErrNone);
   793     r=TheRawDisk.Read(ClusterToByte(aCluster), ptr);
   794     test(r==KErrNone);
   795     TheRawDisk.Close();
   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)
   799         {
   800         if (d->IsErased() || d->IsEndOfDirectory())
   801             break;
   802         ++aEntry;
   803         d = (TFatDirEntry*)ptr.Ptr() + aEntry;
   804         }
   805     TInt start = d->StartCluster();
   806     if (d->IsErased())
   807         start = -1;
   808     else if (d->IsEndOfDirectory())
   809         start = -1;
   810     else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
   811         start = -1;
   812     else if (!IsValidDirEntry(d))
   813         start = -1;
   814     delete buf;
   815     return start;
   816     }
   817 
   818 LOCAL_C void Format()
   819     {
   820     TInt nRes;
   821 
   822 #if 0
   823     TFatFormatParam fmt;
   824     fmt.iFatType = EFat32;
   825     fmt.iSecPerCluster = 1;
   826 
   827     nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue, &fmt);
   828 #else
   829     nRes = FormatFatDrive(TheFs, CurrentDrive(), ETrue);
   830 #endif
   831 
   832     test(nRes == KErrNone);
   833 
   834     }
   835 
   836 LOCAL_C void CreateDeepDir(TFileName& aDir,TInt aDepth)
   837 //
   838 // Increase directory strucutre by aDepth starting with aDir.
   839 //
   840     {
   841     TFileName num;
   842     num.Num(1);
   843     num+=_L("\\");
   844     TInt r;
   845     while(aDepth--)
   846         {
   847         num[0] = TText(aDepth % 26 + 'A');
   848         aDir+=num;
   849         r=TheFs.MkDir(aDir);
   850         test(r==KErrNone);
   851         }
   852     }
   853 
   854 LOCAL_C void DeleteDeepDir(TFileName& aDir,TInt aDepth)
   855 //
   856 // Delete dir structure.
   857 //
   858     {
   859     TInt r;
   860     while(aDepth--)
   861         {
   862         r=TheFs.RmDir(aDir);
   863         test(r==KErrNone);
   864         aDir.SetLength(aDir.Length()-2);
   865         }
   866     }
   867 
   868 LOCAL_C void CreateMaxDepthDir(TFileName& aDir1,TFileName& aDir2)
   869 //
   870 // Create directory structure with max possible depth-1.
   871 // Achieved by using dir names of one character.
   872 //
   873     {
   874     //create dir structure with depth of 25
   875     CreateDeepDir(aDir1,25);
   876     // split dir structure
   877     aDir2=aDir1;
   878     aDir2+=_L("a\\");
   879     TInt r=TheFs.MkDir(aDir2);
   880     test(r==KErrNone);
   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);
   885     }
   886 
   887 LOCAL_C void DeleteMaxDepthDir(TFileName&aDir1,TFileName&aDir2)
   888 //
   889 // Deletes max depth dir structure.
   890 //
   891     {
   892     DeleteDeepDir(aDir2,64);
   893     TInt r=TheFs.RmDir(aDir2);
   894     test(r==KErrNone);
   895     aDir2.SetLength(aDir2.Length()-2);
   896     DeleteDeepDir(aDir1,102);
   897     DeleteDeepDir(aDir1,24);
   898     }
   899 
   900 LOCAL_C void MakeVeryLongName(TFileName& aLong)
   901 //
   902 // appends a very long file name to aLong
   903 //
   904     {
   905     // create a name to take up 18 vfat entries - (1 sector + 2 entries)
   906     for(TInt i=0;i<234;++i)
   907         {
   908         TInt c='a'+i%26;
   909         aLong.Append(c);
   910         }
   911     }
   912 
   913 GLDEF_C void CreateLongNames(TFileName& aLong, TInt aClusters)
   914 //
   915 // Creates entries to fill up the number of directory clusters
   916 //
   917     {
   918     TInt len = aLong.Length(); // length of directory prefix
   919     MakeVeryLongName(aLong);
   920     TInt count = 0;
   921     RFile temp;
   922     for (TInt i = 0; i < aClusters * gEntriesPerCluster; i += 19)
   923         {
   924         aLong[len+0] = TText(count/26 + 'A');
   925         aLong[len+1] = TText(count%26 + 'A');
   926         count++;
   927         TInt r=temp.Create(TheFs,aLong,EFileShareAny);
   928         test(r==KErrNone);
   929         temp.Close();
   930         }
   931     }
   932 
   933 GLDEF_C void DeleteLongNames(TFileName& aLong, TInt aClusters)
   934 //
   935 // Deletes entries created by CreateLongNames()
   936 //
   937     {
   938     TInt len = aLong.Length(); // length of directory prefix
   939     MakeVeryLongName(aLong);
   940     TInt count = 0;
   941     for (TInt i = 0; i < aClusters * gEntriesPerCluster; i += 19)
   942         {
   943         aLong[len+0] = TText(count/26 + 'A');
   944         aLong[len+1] = TText(count%26 + 'A');
   945         count++;
   946         TInt r=TheFs.Delete(aLong);
   947         test(r==KErrNone || r==KErrNotFound);
   948         }
   949     }
   950 
   951 LOCAL_C void DeleteRootDir(TInt aNum=0)
   952 //
   953 // Delete all entries in the root directory up to the last - aNum
   954 //
   955     {
   956     test.Next(_L("Delete Root Directory Entries"));
   957     TInt maxRootEntries = gRootDirEntries;
   958     TFileName name=_L("\\???xxx");
   959     TInt count=0;
   960     TInt entriesSoFar=2;
   961     TInt r;
   962     count = 0;
   963     for (entriesSoFar=0; entriesSoFar<maxRootEntries - aNum; entriesSoFar+=2)
   964         {
   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);
   970         ++count;
   971         }
   972     }
   973 
   974 LOCAL_C void CreateRootDir()
   975 //
   976 // fill up root directory to 1 clusters by creating entries and then deleting
   977 // them except the last.
   978 //
   979     {
   980     test.Next(_L("Create Root Directory Entries"));
   981     TInt maxRootEntries = gRootDirEntries;
   982     TFileName name=_L("\\???xxx");
   983     TInt count=0;
   984     TInt entriesSoFar=2;
   985     TInt r;
   986     RFile f;
   987     for (entriesSoFar=0; entriesSoFar<maxRootEntries; entriesSoFar+=2)
   988         {
   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);
   993         test(r==KErrNone);
   994         f.Close();
   995         ++count;
   996         }
   997     DeleteRootDir(1);
   998     }
   999 
  1000 LOCAL_C void FillUpRootDir(TInt aFree=0)
  1001 //
  1002 // fill up root directory
  1003 //
  1004     {
  1005     TInt maxRootEntries = gRootDirEntries - aFree;
  1006     TFileName dir=_L("\\??\\");
  1007     TInt count=0;
  1008     TInt entriesSoFar=2;
  1009     TInt r;
  1010     while(entriesSoFar<maxRootEntries)
  1011         {
  1012         dir[1]=(TUint16)(count/26+'a');
  1013         dir[2]=(TUint16)(count%26+'a');
  1014         r=TheFs.MkDir(dir);
  1015         test(r==KErrNone);
  1016         entriesSoFar+=2;
  1017         ++count;
  1018         }
  1019     }
  1020 
  1021 LOCAL_C void UnFillUpRootDir(TInt aFree=0)
  1022 //
  1023 // reverse changes from FillUpRootDir()
  1024 //
  1025     {
  1026     TFileName dir=_L("\\??\\");
  1027     TInt entriesSoFar=gRootDirEntries-aFree;
  1028     TInt count=0;
  1029     TInt r;
  1030     while(entriesSoFar>2)
  1031         {
  1032         dir[1]=TUint16(count/26+'a');
  1033         dir[2]=TUint16(count%26+'a');
  1034         r=TheFs.RmDir(dir);
  1035         test(r==KErrNone);
  1036         entriesSoFar-=2;
  1037         ++count;
  1038         }
  1039     }
  1040 
  1041 LOCAL_C void DeleteDirectoryStructure()
  1042 //
  1043 // deletes the directory structure
  1044 //
  1045     {
  1046     test.Next(_L("Delete Directory Structure"));
  1047     TInt r=TheFs.RmDir(_L("\\scndrv\\dir2\\almostfull\\"));
  1048     test(r==KErrNone);
  1049     TInt entriesNeeded=(gEntriesPerCluster-2) / 2;  //7*2entries + . + .. = full sector
  1050     for (TInt i = 0; i < entriesNeeded; i++)
  1051         {
  1052         TFileName file=_L("\\scndrv\\dir2\\full\\__a");
  1053         file.AppendNum(i);
  1054         r=TheFs.Delete(file);
  1055         test(r==KErrNone||r==KErrNotFound);
  1056         }
  1057     r=TheFs.RmDir(_L("\\scndrv\\dir2\\full\\"));
  1058     test(r==KErrNone);
  1059     r=TheFs.RmDir(_L("\\scndrv\\dir2\\"));
  1060     test(r==KErrNone);
  1061     TFileName veryLongName=(_L("\\scndrv\\dir1\\"));
  1062     MakeVeryLongName(veryLongName);
  1063     r=TheFs.Delete(veryLongName);
  1064     test(r==KErrNone);
  1065     r=TheFs.RmDir(_L("\\scndrv\\dir1\\"));
  1066     test(r==KErrNone);
  1067     r=TheFs.RmDir(_L("\\scndrv\\"));
  1068     test(r==KErrNone);
  1069     }
  1070 
  1071 LOCAL_C void CreateDirectoryStructure()
  1072 //
  1073 // creates the directory structure
  1074 //
  1075     {
  1076     test.Next(_L("Create Directory Structure"));
  1077     // cluster 3 (root dir is cluster 2)
  1078     TInt r=TheFs.MkDir(_L("\\scndrv\\"));
  1079     test(r==KErrNone);
  1080     // cluster 4
  1081     r=TheFs.MkDir(_L("\\scndrv\\dir1\\"));
  1082     test(r==KErrNone);
  1083     TFileName veryLongName=(_L("\\scndrv\\dir1\\"));
  1084     MakeVeryLongName(veryLongName);
  1085     RFile f;
  1086     // cluster 5
  1087     r=f.Create(TheFs,veryLongName,EFileShareAny);
  1088     test(r==KErrNone);
  1089     r=f.SetSize(512);
  1090     test(r==KErrNone);
  1091     f.Close();
  1092     // cluster 6
  1093     r=TheFs.MkDir(_L("\\scndrv\\dir2\\"));
  1094     test(r==KErrNone);
  1095     // cluster 7
  1096     r=TheFs.MkDir(_L("\\scndrv\\dir2\\full\\"));
  1097     test(r==KErrNone);
  1098     // cluster 8
  1099     r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedirwith3entries\\"));
  1100     test(r==KErrNone);
  1101     // cluster 9
  1102     r=TheFs.MkDir(_L("\\scndrv\\dir2\\somedir2with3entries\\"));
  1103     test(r==KErrNone);
  1104     // cluster 10
  1105     r=TheFs.MkDir(_L("\\scndrv\\dir2\\almostfull\\"));
  1106     test(r==KErrNone);
  1107     // cluster 11-17
  1108     TInt entriesNeeded=(gEntriesPerCluster-2) / 2;  //7*2entries + . + .. = full sector
  1109     for (TInt i = 0; i < entriesNeeded; i++)
  1110         {
  1111         TFileName file=_L("\\scndrv\\dir2\\full\\__a");
  1112         file.AppendNum(i);
  1113         LastInFull = file;
  1114         r=f.Create(TheFs,file,EFileShareAny);
  1115         test(r==KErrNone);
  1116         if (i < 7)
  1117             {
  1118             r=f.SetSize(512);
  1119             test(r==KErrNone);
  1120             }
  1121         f.Close();
  1122         }
  1123     // cluster 18-19
  1124     TInt charLength=13*4+1; // name to take up 6 entries
  1125     TFileName file1=_L("\\scndrv\\dir2\\almostfull\\");
  1126     while(charLength--)
  1127         {
  1128         TInt c='A'+charLength%26;
  1129         file1.Append(c);
  1130         }
  1131     TFileName file2=file1;
  1132     file1.AppendNum(1);
  1133     file2.AppendNum(2);
  1134     r=f.Create(TheFs,file1,EFileShareAny);
  1135     test(r==KErrNone);
  1136     r=f.SetSize(512);
  1137     test(r==KErrNone);
  1138     f.Close();
  1139     r=f.Create(TheFs,file2,EFileShareAny);
  1140     test(r==KErrNone);
  1141     r=f.SetSize(512);
  1142     test(r==KErrNone);
  1143     f.Close();
  1144     }
  1145 
  1146 LOCAL_C TUint8* DirPtr(TInt aOffset)
  1147 //
  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.
  1153 //
  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.
  1156 //
  1157     {
  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
  1162     if (!ExtBufPtr)
  1163         {
  1164         // allocate buffer for 2 clusters, starting at the cluster which
  1165         // contains aOffset
  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');
  1174         test(r==KErrNone);
  1175         TPtr8 des(ExtBufPtr->Des());
  1176         r=TheRawDisk.Read(gRootDirStart + ExtBufAdd, des);
  1177         test(r==KErrNone);
  1178         TheRawDisk.Close();
  1179         }
  1180     // convert to offset in the extension buffer
  1181     aOffset -= ExtBufAdd;
  1182     if (aOffset >= ExtBufLen)
  1183         {
  1184         test.Printf(_L("*** ERROR: tried to access cluster %d not in store\n"),
  1185                     (aOffset + ExtBufAdd) / gBytesPerCluster + 2);
  1186         test(0);
  1187         }
  1188     return (TUint8*)ExtBufPtr->Ptr() + aOffset;
  1189     }
  1190 
  1191 LOCAL_C void DirPtrFree()
  1192 //
  1193 // Free the extension buffer and zero the references to it.
  1194 //
  1195     {
  1196     if (ExtBufPtr)
  1197         {
  1198         TInt clust = (ExtBufAdd - (gDataStartBytes - gRootDirStart)) /gBytesPerCluster + 2;
  1199         RDebug::Print(_L("Extension buffer for cluster %d deleted"), clust);
  1200         delete ExtBufPtr;
  1201         ExtBufPtr = NULL;
  1202         ExtBufAdd = 0;
  1203         ExtBufLen = 0;
  1204         }
  1205     }
  1206 
  1207 LOCAL_C void ReadDirDisk(TDes8& aDirBuf, TInt aCluster = -1)
  1208 //
  1209 // reads directory section of disk into buffer
  1210 //
  1211     {
  1212     test(aCluster != 1);
  1213 
  1214     TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
  1215     test(r==KErrNone);
  1216 
  1217     if (aCluster == -1) // all clusters ?
  1218         {
  1219         r=TheRawDisk.Read(gRootDirStart, aDirBuf);
  1220         }
  1221     else if (aCluster == 0) // root directory cluster
  1222         {
  1223         TPtr8 dirPtr = aDirBuf.MidTPtr(0, gBytesPerCluster);
  1224         r=TheRawDisk.Read(gRootDirStart, dirPtr);
  1225         }
  1226     else
  1227         {
  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);
  1234         }
  1235 
  1236     test(r==KErrNone);
  1237     TheRawDisk.Close();
  1238     }
  1239 
  1240 LOCAL_C void ReadFatDisk(TDes8& aFatBuf)
  1241 //
  1242 // reads fat section of disk info buffer
  1243 //
  1244     {
  1245     TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
  1246     test(r==KErrNone);
  1247     r=TheRawDisk.Read(gFatStartBytes, aFatBuf);
  1248     test(r==KErrNone);
  1249     TheRawDisk.Close();
  1250     }
  1251 
  1252 LOCAL_C void WriteDirDisk(TDes8& aDirBuf, TInt aCluster = -1)
  1253 //
  1254 // writes dir buffer to disk
  1255 //
  1256     {
  1257     test(aCluster != 1);
  1258 
  1259     TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
  1260     test(r==KErrNone);
  1261 
  1262     if (aCluster == -1)
  1263         {
  1264         r=TheRawDisk.Write(gRootDirStart, aDirBuf);
  1265         }
  1266     else if (aCluster == 0) // root directory cluster
  1267         {
  1268         TPtr8 dirPtr = aDirBuf.MidTPtr(0, gBytesPerCluster);
  1269         r=TheRawDisk.Write(gRootDirStart, dirPtr);
  1270         }
  1271     else
  1272         {
  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);
  1279         }
  1280 
  1281     test(r==KErrNone);
  1282     if (ExtBufPtr)
  1283         {
  1284         TPtr8 des(ExtBufPtr->Des());
  1285         r=TheRawDisk.Write(gRootDirStart + ExtBufAdd, des);
  1286         test(r==KErrNone);
  1287         }
  1288     TheRawDisk.Close();
  1289     }
  1290 
  1291 LOCAL_C void WriteFatDisk(TDes8& aFatBuf, TInt aStart=0)
  1292 //
  1293 // writes fat buffer to disk
  1294 //
  1295     {
  1296     TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
  1297     test(r==KErrNone);
  1298     TInt fatCount=BootSector.NumberOfFats() - aStart;
  1299     TInt pos = gFatStartBytes + aStart * gFatSizeSectors*BootSector.BytesPerSector();
  1300     while(fatCount--)
  1301         {
  1302         r=TheRawDisk.Write(pos, aFatBuf);
  1303         test(r==KErrNone);
  1304         pos += gFatSizeSectors*BootSector.BytesPerSector();
  1305         }
  1306     TheRawDisk.Close();
  1307     }
  1308 
  1309 LOCAL_C void WriteReservedId(TInt aBytePos)
  1310 //
  1311 // write reserved id to byte 19 of entry starting at aBytePos
  1312 //
  1313     {
  1314     TUint8* pEntry=DirPtr(aBytePos);
  1315     pEntry[19]=1;
  1316     }
  1317 
  1318 LOCAL_C void WriteEndOfDir(TInt aBytePos)
  1319 //
  1320 // write end of directory marker to entry starting at aBytePos
  1321 //
  1322     {
  1323     TUint8* pEntry=DirPtr(aBytePos);
  1324     Mem::FillZ(pEntry,KFatDirNameSize);
  1325     }
  1326 
  1327 LOCAL_C void WriteDelete(TInt aBytePos,TInt aNum)
  1328 //
  1329 // writes 0xe5 to entries starting at aBytePos
  1330 //
  1331     {
  1332     TUint8* pEntry=DirPtr(aBytePos);
  1333     while(aNum--)
  1334         {
  1335         pEntry[0]=0xE5;
  1336         pEntry+=KSizeOfFatDirEntry;
  1337         }
  1338     }
  1339 
  1340 LOCAL_C void WriteCopyDir(TInt aSrc, TInt aDst)
  1341 //
  1342 // Copy one directory entry over another
  1343 //
  1344     {
  1345     TUint8* pSrc=DirPtr(aSrc);
  1346     TUint8* pDst=DirPtr(aDst);
  1347     Mem::Copy(pDst, pSrc, KSizeOfFatDirEntry);
  1348     }
  1349 
  1350 LOCAL_C void InitialiseBuffers()
  1351 //
  1352 // reads disk into buffers
  1353 //
  1354     {
  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);
  1363 
  1364     // Buffers for reading from disk
  1365     FatDiskPtr=HBufC8::New(gFatTestSize);
  1366     test(FatDiskPtr!=NULL);
  1367     DirDiskPtr=HBufC8::New(DirBufferSize());
  1368     test(DirDiskPtr!=NULL);
  1369     }
  1370 
  1371 LOCAL_C TBool IsSameAsDrive(const TDes8& aFatBuf,const TDes8& aDirBuf)
  1372 //
  1373 // compares the two bufs passed in with those on disk
  1374 //
  1375     {
  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);
  1382     if (!fatOk)
  1383         {
  1384         TInt i = FindUnMatch(aFatBuf.Ptr(), fatDisk.Ptr(), fatDisk.Length());
  1385         switch (gDiskType)
  1386             {
  1387             case EFat32:
  1388                 i /= 4;
  1389 
  1390                 if(i == 1)
  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
  1393                     fatOk = ETrue;
  1394                 }
  1395 
  1396                 break;
  1397 
  1398             case EFat16:
  1399                 i /= 2;
  1400 
  1401                 if(i == 1)
  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
  1404                     fatOk = ETrue;
  1405                 }
  1406 
  1407                 break;
  1408 
  1409             case EFat12:
  1410                 i = i*2 / 3;
  1411                 if (GetFatEntry(i, aFatBuf.Ptr()) == GetFatEntry(i, fatDisk.Ptr()))
  1412                     ++i;
  1413                 break;
  1414             default:
  1415                 test(0);
  1416             }
  1417 
  1418         if(fatOk && i==1)
  1419             {
  1420             test.Printf(_L("Skipping FAT[1] entry for FAT16/32 \n"), i);
  1421             }
  1422         else
  1423             {
  1424         test.Printf(_L("FAT entry %d different from expected\n"), i);
  1425 
  1426         RDebug::Print(_L("Expected:\n"));
  1427         DumpFat(aFatBuf.Ptr());
  1428         RDebug::Print(_L("Actual:\n"));
  1429         DumpFat(fatDisk.Ptr());
  1430         }
  1431         }
  1432 
  1433     if (!dirOk)
  1434         {
  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);
  1440 
  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);
  1446 
  1447 		RDebug::Print(_L("Expected:\n"));
  1448 		DumpData(aFatBuf.Ptr(), aDirBuf.Ptr());
  1449 		RDebug::Print(_L("Actual:\n"));
  1450 		DumpData(fatDisk.Ptr(), dirDisk.Ptr());
  1451         }
  1452     else if (ExtBufPtr)
  1453         {
  1454         HBufC8* extPtr = HBufC8::New(ExtBufLen);
  1455         test(extPtr != NULL);
  1456         TInt r=TheRawDisk.Open(TheFs,gSessionPath[0]-'A');
  1457         test(r==KErrNone);
  1458         TPtr8 des(extPtr->Des());
  1459         r=TheRawDisk.Read(ExtBufAdd+gRootDirStart, des);
  1460         test(r==KErrNone);
  1461         TheRawDisk.Close();
  1462         TInt i = FindUnMatch(ExtBufPtr->Ptr(), extPtr->Ptr(), ExtBufLen);
  1463         if (i >= 0)
  1464             {
  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());
  1477             dirOk = EFalse;
  1478             }
  1479         delete extPtr;
  1480         }
  1481 
  1482     return(fatOk && dirOk);
  1483     }
  1484 
  1485 LOCAL_C void WriteErased(TEntryInfo aTrg,TInt aToDelete)
  1486 //
  1487 // writes erased marker, starting at dos entry and working backwards
  1488 // used to simulate a part entry40*BootSector.BytesPerSector()
  1489 //
  1490     {
  1491     TInt toStart=aTrg.iBytePos+(aTrg.iLength-1)*KSizeOfFatDirEntry;
  1492     TPtr8 dirBuf=DirBufPtr->Des();
  1493     while(aToDelete--)
  1494         {
  1495         dirBuf[toStart]=0xE5;
  1496         toStart-=KSizeOfFatDirEntry;
  1497         }
  1498     }
  1499 
  1500 LOCAL_C void CreatePartialEntry(TEntryInfo aTrg,TInt aToDelete,TBool aAddEOfDir)
  1501 //
  1502 // creates a partial entry
  1503 //
  1504     {
  1505     WriteErased(aTrg,aToDelete);
  1506     if(aAddEOfDir)
  1507         WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry);
  1508     TPtr8 dirBuf=DirBufPtr->Des();
  1509     WriteDirDisk(dirBuf);
  1510     }
  1511 
  1512 LOCAL_C TBool TestPartialEntry(TEntryInfo aEntry)
  1513 //
  1514 // tests that scandrive deals with a partial entry and returns the result
  1515 //
  1516     {
  1517     test.Next(_L("TestPartialEntry"));
  1518     TInt r=TheFs.ScanDrive(gSessionPath);
  1519     test(r==KErrNone);
  1520     WriteDelete(aEntry.iBytePos,aEntry.iLength);
  1521 
  1522     TPtr8 fatBuf=FatBufPtr->Des();
  1523     TPtr8 dirBuf=DirBufPtr->Des();
  1524 
  1525     TBool res=IsSameAsDrive(fatBuf,dirBuf);
  1526     return(res);
  1527     }
  1528 
  1529 LOCAL_C void CreateMatchingEntry(TEntryInfo aTrg,TEntryInfo aSrc,TBool aAddEOfDir)
  1530 //
  1531 // creates matching entry
  1532 //
  1533     {
  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);
  1539     if(aAddEOfDir)
  1540         WriteEndOfDir(aTrg.iBytePos+aTrg.iLength*KSizeOfFatDirEntry);
  1541     TPtr8 dirBuf=DirBufPtr->Des();
  1542     WriteDirDisk(dirBuf);
  1543     }
  1544 
  1545 LOCAL_C TBool TestMatchingEntry(TEntryInfo aToDelete)
  1546 //
  1547 // tests that scandrive deals with matching entries correctly
  1548 //
  1549     {
  1550     test.Next(_L("TestMatchingEntries"));
  1551     WriteDelete(aToDelete.iBytePos,aToDelete.iLength);
  1552     TInt r=TheFs.ScanDrive(gSessionPath);
  1553     test(r==KErrNone);
  1554 
  1555     TPtr8 fatBuf=FatBufPtr->Des();
  1556     TPtr8 dirBuf=DirBufPtr->Des();
  1557 
  1558     TBool res=IsSameAsDrive(fatBuf,dirBuf);
  1559     DirPtrFree();
  1560     return(res);
  1561     }
  1562 
  1563 
  1564 LOCAL_C void TestExtendedChars()
  1565 //
  1566 // tests that extended characters corresponding to ISO Latin 1
  1567 // characters 128-255 are recognised as valid by scandrive
  1568 //
  1569     {
  1570     test.Next(_L("TestExtendedChars()"));
  1571     Format();
  1572 
  1573     _LIT(KRoot,"\\");
  1574     CDir* dirs;
  1575     // check no entries in the root directory
  1576     TInt r=TheFs.GetDir(KRoot,KEntryAttMaskSupported,ESortNone,dirs);
  1577     test(r==KErrNone);
  1578     test(dirs->Count()==0);
  1579     delete(dirs);
  1580     dirs=NULL;
  1581 
  1582     // create file
  1583     _LIT(KOrigShortName,"P_SSI.TXT");
  1584 
  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
  1588 
  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
  1592 
  1593 
  1594     RFile file;
  1595     r=file.Replace(TheFs,TestFileName,EFileShareExclusive);
  1596     test(r==KErrNone);
  1597     file.Close();
  1598 
  1599     // get short name
  1600     TFileName shortName;
  1601     r=TheFs.GetShortName(TestFileName,shortName);
  1602     test(r==KErrNone);
  1603     test(shortName==KOrigShortName);
  1604 
  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);
  1609     RRawDisk raw;
  1610     r=raw.Open(TheFs,gSessionPath[0]-'A');
  1611     test(r==KErrNone);
  1612     TBuf8<1> buf(1);
  1613 
  1614     //-- change 2nd character in the short name (Fat DOS entry)
  1615     buf[0]=(TUint8)'\xC4';
  1616     r=raw.Write(gRootDirStart+bytePos+1,buf);
  1617     test(r==KErrNone);
  1618 
  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);
  1623     test(r==KErrNone);
  1624 
  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);
  1630     test(r==KErrNone);
  1631     shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8);
  1632     shortName.Copy(shortNameBuf8);
  1633     raw.Close();
  1634 
  1635 
  1636     test(shortName==ExtShortName);
  1637     DumpData(NULL, 0, 20);
  1638     //TheFs.SetDebugRegister(KFSYS);
  1639     r=TheFs.ScanDrive(gSessionPath);
  1640     TheFs.SetDebugRegister(0);
  1641     test(r==KErrNone);
  1642     DumpData(NULL, 0, 20);
  1643 
  1644     // retrieve short name from media.
  1645     r=raw.Open(TheFs,gSessionPath[0]-'A');
  1646     test(r==KErrNone);
  1647     bytePos=ClusterEntryToBytes(0,1);
  1648     r=raw.Read(gRootDirStart+bytePos,shortNameBuf8);
  1649     test(r==KErrNone);
  1650     shortNameBuf8 = DosNameFromStdFormat(shortNameBuf8);
  1651     shortName.Copy(shortNameBuf8);
  1652     raw.Close();
  1653 
  1654     test(shortName==ExtShortName);
  1655 
  1656     // delete file
  1657     r=TheFs.Delete(TestFileName);
  1658     test(r==KErrNone);
  1659     }
  1660 
  1661 LOCAL_C void TestMountAndScan()
  1662 //
  1663 // test MountFileSystemAndScan()
  1664 //
  1665     {
  1666     TFullName extName;
  1667     TBool primaryExtensionExists = EFalse;
  1668 
  1669     test.Next(_L("TestMountAndScan"));
  1670     HBufC8* newFat=HBufC8::New(gFatTestSize);
  1671     test(newFat!=NULL);
  1672     TPtr8 fat=newFat->Des();
  1673     TPtr8 origFat=FatBufPtr->Des();
  1674     TPtr8 origDir=DirBufPtr->Des();
  1675 
  1676     // set cluster of \scndrv\dir1\ to a hanging cluster
  1677     ReadFatDisk(fat);
  1678     WriteFat(gClusterDir1ext,35,fat.Ptr());
  1679     WriteFat(35,36,fat.Ptr());
  1680     WriteFatDisk(fat);
  1681     // set the default path to something other than the current drive
  1682     TFileName fsName;
  1683     TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A');
  1684     test(r==KErrNone);
  1685     TFileName origDefPath, newDefPath;
  1686     r=TheFs.SessionPath(origDefPath);
  1687     test(r==KErrNone);
  1688     newDefPath=origDefPath;
  1689     newDefPath[0]=(TText)'z';
  1690     r=TheFs.SetSessionPath(newDefPath);
  1691     test(r==KErrNone);
  1692     r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0);
  1693     if (r == KErrNone)
  1694         {
  1695         primaryExtensionExists = ETrue;
  1696         }
  1697     r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A');
  1698     test(r==KErrNone);
  1699     // mount file system and check scandrive corrects error
  1700     TBool isMount;
  1701     if (primaryExtensionExists)
  1702         r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount);
  1703     else
  1704         r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount);
  1705     test(isMount && r==KErrNone);
  1706     TBool res=IsSameAsDrive(origFat,origDir);
  1707     test(res);
  1708 
  1709     r=TheFs.SetSessionPath(origDefPath);
  1710     test(r==KErrNone);
  1711     delete newFat;
  1712     }
  1713 
  1714 
  1715 LOCAL_C void TestConsecutiveMountAndScans()
  1716 //
  1717 // test fix for DEF093072: [codebase]MountFileSystemAndScan returns err -21 but ok flag
  1718 //
  1719     {
  1720     TFullName extName;
  1721     TBool primaryExtensionExists = EFalse;
  1722     TFileName fsName;
  1723     TInt r=TheFs.FileSystemName(fsName,gSessionPath[0]-'A');
  1724     test(r==KErrNone);
  1725     r = TheFs.ExtensionName(extName,gSessionPath[0]-'A',0);
  1726     if (r == KErrNone)
  1727         {
  1728         primaryExtensionExists = ETrue;
  1729         }
  1730     r=TheFs.DismountFileSystem(fsName,gSessionPath[0]-'A');
  1731     test(r==KErrNone);
  1732 
  1733     // RFs::MountFileSystemAndScan twice consecutively
  1734     // first time
  1735     TBool isMount;
  1736     if (primaryExtensionExists)
  1737         r=TheFs.MountFileSystemAndScan(fsName,extName,gSessionPath[0]-'A',isMount);
  1738     else
  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);
  1744     else
  1745         r=TheFs.MountFileSystemAndScan(fsName,gSessionPath[0]-'A',isMount);
  1746     test(!isMount && r==KErrAccessDenied);
  1747     }
  1748 
  1749 LOCAL_C void DoHangingClusters()
  1750 //
  1751 // Tests that scandrive removes hanging clusters
  1752 //
  1753     {
  1754     test.Next(_L("Check Hanging clusters"));
  1755     HBufC8* newFat=HBufC8::New(gFatTestSize);
  1756     test(newFat!=NULL);
  1757     TPtr8 fat=newFat->Des();
  1758     TPtr8 origFat=FatBufPtr->Des();
  1759     TPtr8 origDir=DirBufPtr->Des();
  1760 
  1761     // set cluster of \scndrv\dir1\ to a hanging cluster
  1762     test.Start(_L("Test hanging cluster in \\scndrv\\dir1\\"));
  1763     ReadFatDisk(fat);
  1764     WriteFat(gClusterDir1ext,35,fat.Ptr());
  1765     WriteFat(35,36,fat.Ptr());
  1766     WriteFatDisk(fat);
  1767     TInt r=TheFs.ScanDrive(gSessionPath);
  1768     test(r==KErrNone);
  1769     TBool res=IsSameAsDrive(origFat,origDir);
  1770     test(res);
  1771 
  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"));
  1775     ReadFatDisk(fat);
  1776     WriteFat(gClusterDir1ext,39,fat.Ptr());
  1777     WriteFat(39,500,fat.Ptr());
  1778     WriteFat(500,gEndOfChain,fat.Ptr());
  1779     WriteFatDisk(fat);
  1780     r=TheFs.ScanDrive(gSessionPath);
  1781     test(r==KErrNone);
  1782     res=IsSameAsDrive(origFat,origDir);
  1783     test(res);
  1784 
  1785     // set cluster of \scndrv\ to a hanging cluster
  1786     test.Next(_L("Test hanging cluster of \\scndrv\\"));
  1787     ReadFatDisk(fat);
  1788     WriteFat(gClusterScnDrv,511,fat.Ptr());
  1789     WriteFatDisk(fat);
  1790     r=TheFs.ScanDrive(gSessionPath);
  1791     test(r==KErrNone);
  1792     res=IsSameAsDrive(origFat,origDir);
  1793     test(res);
  1794 
  1795     delete newFat;
  1796     test.End();
  1797     }
  1798 
  1799 LOCAL_C void DoLostClusters()
  1800 //
  1801 // Tests that scandrive removes lost clusters
  1802 //
  1803     {
  1804     test.Next(_L("Check lost clusters"));
  1805     HBufC8* newFat=HBufC8::New(gFatTestSize);
  1806     test(newFat!=NULL);
  1807     TPtr8 fat=newFat->Des();
  1808     TPtr8 origFat=FatBufPtr->Des();
  1809     TPtr8 origDir=DirBufPtr->Des();
  1810     ReadFatDisk(origFat);
  1811     ReadDirDisk(origDir);
  1812 
  1813     // write cluster chain
  1814     test.Start(_L("Test removal of lost cluster chain"));
  1815     ReadFatDisk(fat);
  1816     for(TInt i=25;i<35;++i)
  1817         WriteFat(i,i+1,fat.Ptr());
  1818     WriteFat(35,gEndOfChain,fat.Ptr());
  1819     WriteFatDisk(fat);
  1820     TInt r=TheFs.ScanDrive(gSessionPath);
  1821     test(r==KErrNone);
  1822     TBool res=IsSameAsDrive(origFat,origDir);
  1823     test(res);
  1824 
  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)
  1828         {
  1829         TInt off = j*BootSector.BytesPerSector()+j*7%512;
  1830         fat[off]=1;
  1831         }
  1832     WriteFatDisk(fat);
  1833     r=TheFs.ScanDrive(gSessionPath);
  1834     test(r==KErrNone);
  1835     res=IsSameAsDrive(origFat,origDir);
  1836     test(res);
  1837 
  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);
  1842     test(r==KErrNone);
  1843     res=IsSameAsDrive(origFat,origDir);
  1844     test(res);
  1845 
  1846     delete newFat;
  1847     test.End();
  1848     }
  1849 
  1850 LOCAL_C void DoPartEntries()
  1851 //
  1852 // Tests that scandrive detects/corrects partial entries
  1853 //
  1854     {
  1855     RFile temp;
  1856     TInt last;
  1857     TBool res;
  1858     test.Start(_L("Check partial entries"));
  1859     TPtr8 fatBuf=FatBufPtr->Des();
  1860     TPtr8 dirBuf=DirBufPtr->Des();
  1861 
  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);
  1866 
  1867     if (BootSector.RootDirEntries() != 0)
  1868         {
  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"));
  1872         FillUpRootDir(2);
  1873         r=temp.Create(TheFs,_L("\\temp"),EFileShareAny);
  1874         test(r==KErrNone);
  1875         temp.Close();
  1876         ReadDirDisk(dirBuf);
  1877         ReadFatDisk(fatBuf);
  1878         TEntryInfo partial1(ClusterEntryToBytes(gClusterRootDir,BootSector.RootDirEntries()-2),2);
  1879         CreatePartialEntry(partial1,1,EFalse);
  1880         res=TestPartialEntry(partial1);
  1881         test(res);
  1882         UnFillUpRootDir(2);
  1883         ReadDirDisk(dirBuf);
  1884         ReadFatDisk(fatBuf);
  1885         }
  1886 
  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
  1893     if (last > 0)
  1894         WriteFat(last,0,fatBuf.Ptr());
  1895     res=TestPartialEntry(partial2);
  1896     test(res);
  1897 
  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)
  1906         {
  1907         TInt next = GetFatEntry(entry, fatBuf.Ptr());
  1908         WriteFat(entry,0,fatBuf.Ptr());
  1909         entry = next;
  1910         }
  1911     if (last > 0)
  1912         WriteFat(last,0,fatBuf.Ptr());
  1913     r=TheFs.ScanDrive(gSessionPath);
  1914     test(r==KErrNone);
  1915     res=IsSameAsDrive(fatBuf,dirBuf);
  1916     test(res);
  1917 
  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);
  1921     test(r==KErrNone);
  1922     temp.Close();
  1923     ReadDirDisk(dirBuf);
  1924     ReadFatDisk(fatBuf);
  1925     TEntryInfo partial3(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),2);
  1926     CreatePartialEntry(partial3,1,EFalse);
  1927     res=TestPartialEntry(partial3);
  1928     test(res);
  1929 
  1930     // use entry in \scndrv\dir2\almostfull\ 
  1931     test.Next(_L("Partial entry preceeding end-of-dir marker"));
  1932     last = GetStartCluster(gClusterDir2_AFull,14);
  1933     if (last > 0)
  1934         WriteFat(last,0,fatBuf.Ptr());
  1935     last = GetStartCluster(gClusterDir2_AFull,8);
  1936     if (last > 0)
  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);
  1943     test(res);
  1944 
  1945 	// NOTE:
  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
  1950 	//	DBCS charater.
  1951 
  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);
  1956 //	temp.Close();
  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);
  1965 //	test(res);
  1966 
  1967     if (BootSector.SectorsPerCluster() == 1)
  1968         {
  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);
  1978         test(r==KErrNone);
  1979         temp.Close();
  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());
  1984         if (last > 0)
  1985             WriteFat(last,0,fatBuf.Ptr());
  1986         TEntryInfo partial5(ClusterEntryToBytes(gClusterDir2_Full,gEntriesPerCluster-2),19);
  1987         CreatePartialEntry(partial5,7,EFalse);
  1988         res=TestPartialEntry(partial5);
  1989         test(res);
  1990         r=TheFs.Delete(longFile);
  1991         test(r==KErrNone || r==KErrNotFound);
  1992         r=TheFs.Delete(_L("\\temp"));
  1993         test(r==KErrNone || r==KErrNotFound);
  1994         }
  1995     ReadDirDisk(dirBuf);
  1996 
  1997     test.End();
  1998     }
  1999 
  2000 LOCAL_C void DoMatchingEntries()
  2001 //
  2002 // Tests that scandrive detects/corrects entries with the same start cluster
  2003 // Copies entry to new location - replicates start cluster
  2004 //
  2005     {
  2006     test.Next(_L("Check matching entries"));
  2007     TPtr8 fatBuf=FatBufPtr->Des();
  2008     TPtr8 dirBuf=DirBufPtr->Des();
  2009     ReadDirDisk(dirBuf);
  2010     ReadFatDisk(fatBuf);
  2011 
  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);
  2018     test(res);
  2019 
  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);
  2027     test(res);
  2028 
  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);
  2036     test(res);
  2037 
  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\\"));
  2043     test(r==KErrNone);
  2044     r=TheFs.RmDir(_L("\\scndrv\\dir2\\somedir2with3entries\\"));
  2045     test(r==KErrNone);
  2046     // ensure directory is expanded
  2047     RFile temp;
  2048     r=temp.Create(TheFs,_L("\\scndrv\\dir2\\full\\temp"),EFileShareAny);
  2049     test(r==KErrNone);
  2050     temp.Close();
  2051     r=TheFs.Delete(_L("\\scndrv\\dir2\\full\\temp"));
  2052     test(r==KErrNone);
  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);
  2059     test(res);
  2060 
  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);
  2065     test(r==KErrNone);
  2066     TFileName veryLongName=_L("\\scndrv\\dir2\\full\\");
  2067     MakeVeryLongName(veryLongName);
  2068     r=temp.Create(TheFs,veryLongName,EFileShareAny);
  2069     test(r==KErrNone);
  2070     temp.Close();
  2071     r=TheFs.Delete(veryLongName);
  2072     test(r==KErrNone);
  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);
  2079     test(res);
  2080 
  2081     test.End();
  2082     }
  2083 
  2084 
  2085 LOCAL_C void DoMaxDepth()
  2086 //
  2087 // Test directory structure with max possible depth
  2088 //
  2089     {
  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("\\");
  2096     TFileName dir2;
  2097     CreateMaxDepthDir(dir1,dir2);
  2098     ReadDirDisk(dirBuf);
  2099     ReadFatDisk(fatBuf);
  2100     // run scandisk and compare
  2101     TInt r=TheFs.ScanDrive(gSessionPath);
  2102     test(r==KErrNone);
  2103     TBool res=IsSameAsDrive(fatBuf,dirBuf);
  2104     test(res);
  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);
  2110     test(res);
  2111     // DeleteMaxDepthStructure
  2112     DeleteMaxDepthDir(dir1,dir2);
  2113     test.End();
  2114     }
  2115 
  2116 LOCAL_C void DoRootDir()
  2117 //
  2118 // Check that a full root directory is searched OK
  2119 //
  2120     {
  2121     test.Next(_L("Check a full root directory"));
  2122     FillUpRootDir();
  2123     TPtr8 fatBuf=FatBufPtr->Des();
  2124     TPtr8 dirBuf=DirBufPtr->Des();
  2125     ReadDirDisk(dirBuf);
  2126     ReadFatDisk(fatBuf);
  2127 
  2128     TInt r=TheFs.ScanDrive(gSessionPath);
  2129     test(r==KErrNone);
  2130 
  2131     TBool res=IsSameAsDrive(fatBuf,dirBuf);
  2132     test(res);
  2133     UnFillUpRootDir();
  2134     }
  2135 
  2136 LOCAL_C void TestNonVfatNames(const TPtrC& aDirName, TInt aDirCluster, TInt aEntry=2)
  2137 //
  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.
  2143 //
  2144 // The layout, for 1 sector per cluster, is thus like:
  2145 //    0 .
  2146 //    1 ..
  2147 //    2 TEMPFILE.000
  2148 //    3 TEMPFILE.001
  2149 //      ...
  2150 //   14 tempfile.012 VFAT
  2151 //   15 TEMPFILE.012
  2152 //
  2153 // or for an almost full directory
  2154 //
  2155 //    0 .
  2156 //    1 ..
  2157 //      whatever...
  2158 //   14 TEMPFILE.000
  2159 //   15 end of directory
  2160 //
  2161     {
  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;
  2166 
  2167     TInt maxEntry = gEntriesPerCluster;
  2168     if (aDirName.Compare(_L("\\")) == KErrNone)
  2169         maxEntry = Min(gRootDirEntries, gEntriesPerCluster);
  2170 
  2171     TInt entry = aEntry;
  2172     TInt r = KErrNone;
  2173     TInt i;
  2174 
  2175     while (entry > gEntriesPerCluster)
  2176         {
  2177         entry -= gEntriesPerCluster;
  2178         cluster++;
  2179         }
  2180 
  2181     TInt nFiles = maxEntry - entry - 1;
  2182     TInt startEntry = entry;
  2183 
  2184     test.Printf(_L("cluster %d, entry %d maxEntry %d, nFiles %d\n"), cluster, entry, maxEntry, nFiles);
  2185 
  2186     TBuf8<256> buf;
  2187     buf.Fill('*', 256);
  2188 
  2189     // Set up files, ignoring used slots
  2190     TInt filesThisTime = nFiles;
  2191     TInt totalFilesCreated = 0;
  2192     FOREVER
  2193         {
  2194         //
  2195         // Create a number of VFat entries
  2196         //
  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.
  2201         //
  2202         filesThisTime = (nFiles - totalFilesCreated) >> 1;
  2203         if(filesThisTime == 0)
  2204             {
  2205             if(nFiles == totalFilesCreated)
  2206                 {
  2207                 test.Printf(_L("Created all Non-VFAT entries\n"));
  2208                 break;
  2209                 }
  2210 
  2211             //...creating the final entry
  2212             filesThisTime = 1;
  2213             }
  2214 
  2215         for (i = 0; i < filesThisTime; i++)
  2216             {
  2217             TFileName name(aDirName);
  2218             name.Append(_L("tempfile."));
  2219             name.AppendNumFixedWidth(i+totalFilesCreated, EHex, 3);
  2220             RFile f;
  2221             r = f.Create(TheFs, name, EFileShareAny);
  2222             test(r == KErrNone);
  2223             r = f.Write(buf);
  2224             test(r == KErrNone);
  2225             f.Close();
  2226             }
  2227 
  2228         //
  2229         // Move DOS FAT entries up using RRawDisk, deleting the original VFAT entries
  2230         //
  2231         ReadDirDisk(dirBuf, cluster);
  2232         TInt dosEntry = entry + 1;
  2233         for (i = 0; i < filesThisTime; i++)
  2234             {
  2235             // Copy VFAT to Non-VFAT entries
  2236             if (entry+2 < maxEntry || nFiles < 2)
  2237                 {
  2238                 TInt posVFAT = ClusterEntryToBytes(cluster, entry);
  2239                 TInt posEOD = ClusterEntryToBytes(cluster, entry+1);
  2240                 TInt posDOS = ClusterEntryToBytes(cluster, dosEntry);
  2241 
  2242                 WriteCopyDir(posDOS, posVFAT);  // Copy the DOS entry
  2243                 WriteDelete(posDOS,2);          // Delete the original entry
  2244                 WriteEndOfDir(posEOD);          // Write End Of Directory
  2245 
  2246                 entry += 1;
  2247                 dosEntry += 2;
  2248                 }
  2249             else
  2250                 {
  2251                 // last entry has VFAT intact, to fill cluster
  2252                 entry += 2;
  2253                 }
  2254 
  2255             }
  2256 
  2257         WriteDirDisk(dirBuf, cluster);
  2258         totalFilesCreated += filesThisTime;
  2259         test.Printf(_L("   created %d entries\n"), totalFilesCreated);
  2260         }
  2261 
  2262     ReadDirDisk(dirBuf);
  2263     ReadFatDisk(fatBuf);
  2264 
  2265     DumpData(NULL, aDirCluster, cluster+1);
  2266 
  2267     test.Printf(_L("Running ScanDrive\n"), filesThisTime);
  2268     r=TheFs.ScanDrive(gSessionPath);
  2269     test(r==KErrNone);
  2270 
  2271     TBool res=IsSameAsDrive(fatBuf,dirBuf);
  2272     test(res);
  2273 
  2274     test.Printf(_L("Deleting %d files\n"), nFiles);
  2275     for (i = 0; i < nFiles; i++)
  2276         {
  2277         TFileName name(aDirName);
  2278         name.Append(_L("tempfile."));
  2279         name.AppendNumFixedWidth(i, EHex, 3);
  2280         r = TheFs.Delete(name);
  2281         test(r == KErrNone);
  2282         }
  2283 
  2284     ReadDirDisk(dirBuf);
  2285     ReadFatDisk(fatBuf);
  2286     WriteEndOfDir(ClusterEntryToBytes(cluster, startEntry));
  2287     WriteDirDisk(dirBuf);
  2288 
  2289     test.Printf(_L("Running ScanDrive\n"), filesThisTime);
  2290     r=TheFs.ScanDrive(gSessionPath);
  2291     test(r==KErrNone);
  2292     res=IsSameAsDrive(fatBuf,dirBuf);
  2293     test(res);
  2294     }
  2295 
  2296 LOCAL_C void DoNonVfatNames()
  2297 //
  2298 // Check that files without 'long' entries are kept intact
  2299 //
  2300     {
  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);
  2306     }
  2307 
  2308 
  2309 LOCAL_C void DoTests()
  2310     {
  2311 
  2312     Format();
  2313     DoReadBootSector();
  2314     DumpBootSector();
  2315     InitialiseBuffers();
  2316     CreateRootDir();
  2317     CreateDirectoryStructure();
  2318     TPtr8 fatBuf=FatBufPtr->Des();
  2319     TPtr8 dirBuf=DirBufPtr->Des();
  2320     ReadDirDisk(dirBuf);
  2321     ReadFatDisk(fatBuf);
  2322     DumpFat();
  2323     DumpData(NULL, DirBufPtr->Ptr());
  2324 
  2325     DoNonVfatNames();
  2326     DoRootDir();
  2327     DoMaxDepth();
  2328     DoMatchingEntries();
  2329     DoPartEntries();
  2330     DoLostClusters();
  2331     DoHangingClusters();
  2332     TestMountAndScan();
  2333     TestConsecutiveMountAndScans();
  2334     DeleteDirectoryStructure();
  2335     DeleteRootDir();
  2336     TestExtendedChars();
  2337 
  2338     DumpBootSector();
  2339     DumpFat();
  2340     DumpData(NULL, 0, 200);
  2341 
  2342     delete FatDiskPtr;
  2343     delete DirDiskPtr;
  2344     delete FatBufPtr;
  2345     delete DirBufPtr;
  2346     }
  2347 
  2348 
  2349 void CallTestsL()
  2350     {
  2351     TInt r;
  2352     r = TheFs.CharToDrive(gSessionPath[0], gDriveNumber);
  2353     test( KErrNone == r );
  2354 
  2355 
  2356     //-- set up console output
  2357     Fat_Test_Utils::SetConsole(test.Console());
  2358 
  2359     //-- print drive information
  2360     PrintDrvInfo(TheFs, gDriveNumber);
  2361 
  2362     if (!Is_Fat(TheFs, gDriveNumber))
  2363         {
  2364         test.Printf(_L("CallTestsL: Skipped: test requires FAT filesystem\n"));
  2365         return;
  2366         }
  2367 
  2368     // check this is not the internal ram drive
  2369     TVolumeInfo v;
  2370     r=TheFs.Volume(v);
  2371     test(r==KErrNone);
  2372     if(v.iDrive.iMediaAtt&KMediaAttVariableSize)
  2373         {
  2374         test.Printf(_L("Error: Internal ram drive not tested\n"));
  2375         return;
  2376         }
  2377 
  2378     r=TheFs.SetSessionPath(gSessionPath);
  2379     test(r==KErrNone);
  2380 
  2381     DoTests();
  2382 
  2383     return;
  2384     }
  2385 
  2386 
  2387 
  2388 
  2389 
  2390