kerneltest/f32test/filesystem/fat/t_fatcorrupt.cpp
changeset 0 a41df078684a
child 109 b3a1d9898418
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2005-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\server\t_fatcorrupt.cpp
       
    15 //
       
    16 //
       
    17 
       
    18 //! @SYMTestCaseID FSBASE-CR-JHAS-68YPX7
       
    19 //! @SYMTestType CT
       
    20 //! @SYMREQ CR JHAS-68YPX7
       
    21 //! @SYMTestCaseDesc Test functionality of handling corrupt data on disk
       
    22 //! @SYMTestStatus Implemented
       
    23 //! @SYMTestActions Use fat test extension to test read/write/format
       
    24 //! @SYMTestExpectedResults Read bad sector fail, others pass
       
    25 //! @SYMTestPriority Medium
       
    26 //! @SYMAuthor Ying Shi
       
    27 //! @SYMCreationDate 20/05/2005
       
    28 //! @See EFat and EFat32 components
       
    29 //! @file f32test\server\t_fatcorrupt.cpp
       
    30 
       
    31 #include <f32file.h>
       
    32 #include <e32test.h>
       
    33 #include <e32math.h>
       
    34 
       
    35 #include "t_server.h"
       
    36 #include "t_fatext.h"
       
    37 
       
    38 using namespace Fat_Test_Utils;
       
    39 
       
    40 GLDEF_D RTest test(_L("T_FATCORRUPT"));
       
    41 
       
    42 static TInt gDrive;
       
    43 static TBuf16<2> gDriveName(2);
       
    44 static TFileName gFileSystem;
       
    45 static TFullName gExtName;
       
    46 static TBool gExtExists=EFalse;
       
    47 static TFatBootSector BootSector;
       
    48 
       
    49 static TInt gBadList[3];
       
    50 
       
    51 _LIT(KExtName,"FATTEST");
       
    52 
       
    53 
       
    54 void RestoreEnv();
       
    55 
       
    56 /**
       
    57     Do format steps and print progress
       
    58 
       
    59     @param  aFormat     specifies the format object
       
    60     @param  aStepsCnt   format steps counter from RFormat::Open
       
    61 
       
    62     @return format completion error code
       
    63 */
       
    64 static TInt DoFormatSteps(RFormat& aFormat, TInt aStepsCnt)
       
    65 {
       
    66     TInt nRes = KErrNone;
       
    67     TInt prevCnt = aStepsCnt;
       
    68 
       
    69     while (aStepsCnt && nRes == KErrNone)
       
    70         {
       
    71          if(prevCnt != aStepsCnt)
       
    72             {
       
    73             test.Printf(_L("."));
       
    74             prevCnt = aStepsCnt;
       
    75             }
       
    76 
       
    77         nRes = aFormat.Next(aStepsCnt);
       
    78         }
       
    79 
       
    80     test.Printf(_L("\n\r"));
       
    81 
       
    82     return nRes;
       
    83 }
       
    84 
       
    85 
       
    86 #define TESTL(con) TestL(con,r,__LINE__)
       
    87 
       
    88 void TestL(TBool aCondition, TInt aError, TInt aLine = 0)
       
    89     {
       
    90     if (!aCondition)
       
    91         {
       
    92         RDebug::Printf("Test fail at line: %d with error code %d",aLine, aError);
       
    93         RestoreEnv();
       
    94         }
       
    95     test(aCondition);
       
    96     }
       
    97 
       
    98 //-------------------------------------------------------------
       
    99 
       
   100 void RestoreEnv()
       
   101     {
       
   102     test.Printf(_L("RestoreEnv()\n"));
       
   103 
       
   104     TInt r = TheFs.DismountExtension(KExtName, gDrive);
       
   105     test(r==KErrNone);
       
   106     r = TheFs.RemoveExtension(KExtName);
       
   107     test(r==KErrNone);
       
   108 
       
   109     if(gExtExists)      // remount existing secondary extension
       
   110         {
       
   111         test(TheFs.MountExtension(gExtName, gDrive)==KErrNone);
       
   112         }
       
   113 
       
   114 
       
   115     //-- We need a full format, because quick format preserves bad sectors marked in FAT
       
   116     r = FormatFatDrive(TheFs, gDrive, EFalse);
       
   117     test(r == KErrNone);
       
   118 
       
   119     }
       
   120 
       
   121 //-------------------------------------------------------------
       
   122 
       
   123 // Remount drive with FAT test extension
       
   124 TBool PrepareMount()
       
   125     {
       
   126     test.Printf(_L("PrepareMountL(), drive:%d \n"),gDrive);
       
   127 
       
   128     TInt r = TheFs.AddExtension(KExtName);
       
   129     test(r==KErrNone || r==KErrAlreadyExists);
       
   130     r = TheFs.ExtensionName(gExtName,gDrive,0);
       
   131     if (r == KErrNone)              // an extension already exists -> dismount it
       
   132         {
       
   133         test.Printf(_L("Drive %d has extension, attempt dismounting it\n"),gDrive);
       
   134         r=TheFs.DismountExtension(gExtName,gDrive);
       
   135         if(r==KErrAccessDenied)     // primary extension
       
   136             {
       
   137             test.Printf(_L("Drive %d has primary extension, skip\n"),gDrive);
       
   138             test(TheFs.RemoveExtension(KExtName) == KErrNone);
       
   139             return EFalse;
       
   140             }
       
   141         test(r==KErrNone);
       
   142         gExtExists=ETrue;
       
   143         }
       
   144     test(r == KErrNone || r==KErrNotFound);
       
   145     r = TheFs.MountExtension(KExtName, gDrive);
       
   146     if (r != KErrNone)
       
   147         test(TheFs.RemoveExtension(KExtName) == KErrNone);
       
   148     test(r==KErrNone);
       
   149     return ETrue;
       
   150     }
       
   151 
       
   152 //-------------------------------------------------------------
       
   153 
       
   154 void MarkClustersL()
       
   155     {
       
   156     TInt size = sizeof(gBadList) / sizeof(TInt);
       
   157     for (TInt i=0; i<size; i++)
       
   158         {
       
   159         TInt r = TheFs.ControlIo(gDrive,CFatTestProxyDrive::EMark,(TAny*)gBadList[i],NULL);
       
   160         TESTL(r == KErrNone);
       
   161         }
       
   162     }
       
   163 
       
   164 //-------------------------------------------------------------
       
   165 
       
   166 /**
       
   167     Create 3 empty files on the volume
       
   168 */
       
   169 void CreateFiles()
       
   170     {
       
   171     TInt r;
       
   172     RFile file;
       
   173     TBuf<10> fileName01;
       
   174     fileName01.Append(_L("?:\\file01"));
       
   175     fileName01[0] = (TUint16)gDriveToTest;
       
   176     r = file.Create(TheFs, fileName01, EFileWrite);
       
   177     TESTL(r==KErrNone||r==KErrAlreadyExists);
       
   178     file.Close();
       
   179 
       
   180     TBuf<10> fileName02;
       
   181     fileName02.Append(_L("?:\\file02"));
       
   182     fileName02[0] = (TUint16)gDriveToTest;
       
   183     r = file.Create(TheFs, fileName02, EFileWrite);
       
   184     TESTL(r==KErrNone||r==KErrAlreadyExists);
       
   185     file.Close();
       
   186 
       
   187     TBuf<10> fileName03;
       
   188     fileName03.Append(_L("?:\\file03"));
       
   189     fileName03[0] = (TUint16)gDriveToTest;
       
   190     r = file.Create(TheFs, fileName03, EFileWrite);
       
   191     TESTL(r==KErrNone||r==KErrAlreadyExists);
       
   192     file.Close();
       
   193     }
       
   194 
       
   195 //-------------------------------------------------------------
       
   196 
       
   197 /**
       
   198     Read/Write to the file with damaged clusters
       
   199 */
       
   200 void DoTestReadWriteL()
       
   201     {
       
   202     CreateFiles();
       
   203 
       
   204     // Get disk mount information
       
   205     TPckgBuf<TInt> dataPositionBuf;
       
   206     TPckgBuf<TInt> sectorsPerClusterBuf;
       
   207 
       
   208     TInt r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EGetDataPosition,dataPositionBuf);
       
   209     TESTL(r==KErrNone);
       
   210 
       
   211     //-- media position of the 1st data sector on the volume.
       
   212     //-- for FAT32 this is the 2nd cluster of the data ares, because 1st belongs to the root dir.
       
   213     const TInt dataPosition = dataPositionBuf();
       
   214 
       
   215     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::ESectorsPerCluster,sectorsPerClusterBuf);
       
   216     TESTL(r==KErrNone);
       
   217 
       
   218     const TInt sectorsPerCluster = sectorsPerClusterBuf(); //-- FAT sectors per cluster
       
   219 
       
   220 
       
   221 
       
   222     // Calculate file data sectors
       
   223     // For FAT32, first data sector falls under root directory, and current FAT32
       
   224     // file system implementation does not take care of handling bad sectors in
       
   225     // root directory so changing start sector to be the start sector of the file,
       
   226     // instead of first data sector.
       
   227     TInt f01_StartSector;
       
   228     if(Is_Fat32(TheFs,gDrive))
       
   229     {
       
   230         f01_StartSector = (dataPosition >> KDefaultSectorLog2);
       
   231         test.Printf(_L("FAT32, dataPosition: %d, sec:%d, spc:%d\n"), dataPosition, f01_StartSector, sectorsPerCluster);
       
   232     }
       
   233     else
       
   234     {
       
   235         f01_StartSector = (dataPosition >> KDefaultSectorLog2);
       
   236         test.Printf(_L("dataPosition: %d, sec:%d, spc:%d\n"), dataPosition, f01_StartSector, sectorsPerCluster);
       
   237     }
       
   238 
       
   239     //TInt f01end = f01beg + sectorsPerCluster - 1;
       
   240     //TInt f02beg = f01end + 1;
       
   241     //TInt f02end = f02beg + sectorsPerCluster - 1;
       
   242     //TInt f03beg = f02end + 1;
       
   243     //TInt f03end = f03beg + sectorsPerCluster - 1;
       
   244 
       
   245     test.Next(_L("Test file write"));
       
   246 
       
   247     //-- mark the sector that file01 starts with as bad
       
   248     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EMark,(TAny*)(f01_StartSector),NULL);
       
   249     TESTL(r==KErrNone);
       
   250 
       
   251     TBuf<10> fileName01;
       
   252     fileName01.Append(_L("?:\\file01"));
       
   253     fileName01[0] = (TUint16)gDriveToTest;
       
   254 
       
   255     RFile file;
       
   256 
       
   257     //-- write to the file with bad sector
       
   258     r = file.Open(TheFs, fileName01, EFileWrite);
       
   259     TESTL(r==KErrNone);
       
   260 
       
   261     TInt size = 2 * sectorsPerCluster * KDefaultSectorSize;   //-- 2 clusters
       
   262     RBuf8 writeBuf01;
       
   263 
       
   264     r = writeBuf01.CreateMax(size);
       
   265     TESTL(r == KErrNone);
       
   266 
       
   267     r = file.Write(writeBuf01, size);
       
   268     TESTL(r==KErrNone);
       
   269 
       
   270     file.Close();
       
   271 
       
   272     test.Next(_L("Test file read"));
       
   273 
       
   274     //-- unmark bas sector
       
   275     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EUnmark,(TAny*)(f01_StartSector),NULL);
       
   276     TESTL(r==KErrNone);
       
   277 
       
   278     //-- mark the 2nd cluster in the file as bad
       
   279     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EMark,(TAny*)(f01_StartSector+sectorsPerCluster),NULL);
       
   280     TESTL(r==KErrNone);
       
   281 
       
   282     r = file.Open(TheFs, fileName01, EFileRead);
       
   283     TESTL(r==KErrNone);
       
   284 
       
   285     //-- read the file from "corrupted" media
       
   286     r = file.Read(writeBuf01, size);
       
   287     TESTL(r==KErrCorrupt); //-- the file must be corrupted
       
   288 
       
   289     file.Close();
       
   290 
       
   291     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EUnmarkAll, NULL, NULL);
       
   292     TESTL(r==KErrNone);
       
   293 
       
   294     writeBuf01.Close();
       
   295 
       
   296     }
       
   297 
       
   298 
       
   299 //-------------------------------------------------------------------------------------------------------
       
   300 
       
   301 /**
       
   302     Suggest FAT volume metrics by volume size in sectors. Pay attention to the KMaxSectorsPerCluster constant.
       
   303 
       
   304     @param  aVolSizeInSectors   FAT volume size in sectors
       
   305     @param  apSectPerCluster    on return here will be suggested number of sectors per cluster
       
   306     @param  apRootDirEntries    on return here will be suggested max. number of root dir. entries.
       
   307 */
       
   308 void SuggestVolMetrics(TUint aVolSizeInSectors, TUint16 *apSectPerCluster, TUint *apRootDirEntries=NULL)
       
   309 {
       
   310     const TUint16  KMaxSectorsPerCluster = 32; //-- maximal number sectors per cluster to use
       
   311           TUint16  sectorsPerCluster;
       
   312           TUint    rootDirEntries;
       
   313 
       
   314     //-- suggest Sector per Cluster value, most suitable for the given volume size. (taken from CFatFormatCB::InitFormatDataForFixedSizeDiskUser(...))
       
   315     if (aVolSizeInSectors < 4096) // < 2MB
       
   316         {
       
   317         sectorsPerCluster = 1;
       
   318         rootDirEntries    = 128;
       
   319         }
       
   320     else if (aVolSizeInSectors < 8192) // < 4MB
       
   321         {
       
   322         sectorsPerCluster = Min(KMaxSectorsPerCluster, 2);
       
   323         rootDirEntries = 256;
       
   324         }
       
   325     else if (aVolSizeInSectors < 32768) // < 16MB
       
   326         {
       
   327         sectorsPerCluster = Min(KMaxSectorsPerCluster, 4);
       
   328         rootDirEntries = 512;
       
   329         }
       
   330     else if (aVolSizeInSectors < 1048576) // < 512MB
       
   331         {
       
   332         sectorsPerCluster = Min(KMaxSectorsPerCluster, 8);
       
   333         rootDirEntries = 512;
       
   334         }
       
   335     else // FAT32
       
   336         {
       
   337         sectorsPerCluster = KMaxSectorsPerCluster;
       
   338         rootDirEntries = 512;
       
   339         }
       
   340 
       
   341     //---------------------------------------
       
   342     if(apSectPerCluster)
       
   343         *apSectPerCluster = sectorsPerCluster;
       
   344 
       
   345     if(apRootDirEntries)
       
   346         *apRootDirEntries = rootDirEntries;
       
   347 
       
   348 }
       
   349 
       
   350 //-------------------------------------------------------------
       
   351 
       
   352 /**
       
   353     Test user-specific FAT format. FAT type 12,16 or 32 will depend on disk size.
       
   354     @param  aQuick if not 0 a quick format will be performed.
       
   355 */
       
   356 void DoTestUserFormatL(TBool aQuick, TBool aMark)
       
   357     {
       
   358     const TUint32   KKiloByte = 1024;
       
   359 
       
   360     TInt r;
       
   361 
       
   362     //-- obtain current FAT volume metrics
       
   363     TVolumeInfo volInfo;
       
   364     r = TheFs.Volume(volInfo, gDrive);
       
   365     TESTL(r == KErrNone);
       
   366 
       
   367     const TInt64    volSize = volInfo.iSize; //-- volume size in bytes
       
   368     const TUint     volSizeInSectors = TUint(volSize >> KDefaultSectorLog2); //-- sectors per volume
       
   369 
       
   370     TUint16   sectorsPerCluster=0;
       
   371     TUint     rootDirEntries = 0;
       
   372     TUint     fatType = 0;
       
   373 
       
   374     //-- roughly suggest FAT type for this volume, if FAT type is incorrect, RFormat will fail.
       
   375     //-- suggest Sector per Cluster value, most suitable for this volume size  (taken from CFatFormatCB::InitFormatDataForFixedSizeDiskUser(...))
       
   376     SuggestVolMetrics(volSizeInSectors, &sectorsPerCluster, &rootDirEntries);
       
   377 
       
   378     const TUint totVolClusterCnt = volSizeInSectors / sectorsPerCluster; //-- total clusters per this volume
       
   379 
       
   380     //-- doesn't count here FAT size, RootDir size and reserved sectors. For rough estimations only, otherwise
       
   381     //-- it will be far too complicated.
       
   382     const TUint dataClusterCnt = totVolClusterCnt;
       
   383 
       
   384     //-- magic. see FAT specs for details.
       
   385     if(dataClusterCnt < 4085)
       
   386         fatType = TLDFormatInfo::EFB12;
       
   387     else if(dataClusterCnt < 65525)
       
   388         fatType = TLDFormatInfo::EFB16;
       
   389     else
       
   390         fatType = TLDFormatInfo::EFB32;
       
   391 
       
   392     test.Printf(_L("Formatting drive %C:, size=%uKB, SecPerClust=%u, FAT%d\n"), ('A'+gDrive), (TUint32)(volSize/KKiloByte), sectorsPerCluster, fatType);
       
   393 
       
   394     //-- formatting the volume
       
   395     TInt formatCnt;
       
   396     TLDFormatInfo formatInfo;
       
   397 
       
   398     formatInfo.iSectorsPerCluster = sectorsPerCluster;
       
   399     formatInfo.iFATBits = (TLDFormatInfo::TFATBits)fatType;
       
   400 
       
   401     TSpecialFormatInfoBuf formatInfoBuf(formatInfo);
       
   402     RFormat formatUser;
       
   403 
       
   404     if (aQuick)
       
   405         {
       
   406         r = formatUser.Open(TheFs, gDriveName, ESpecialFormat|EQuickFormat, formatCnt, formatInfoBuf);
       
   407         TESTL(r == KErrNone);
       
   408         }
       
   409     else
       
   410         {
       
   411         r = formatUser.Open(TheFs, gDriveName, ESpecialFormat, formatCnt, formatInfoBuf);
       
   412         TESTL(r == KErrNone);
       
   413         }
       
   414 
       
   415     if(aMark)
       
   416         {
       
   417         MarkClustersL();
       
   418         }
       
   419 
       
   420     r = DoFormatSteps(formatUser, formatCnt);
       
   421     TESTL(r == KErrNone || r == KErrNotSupported);
       
   422 
       
   423     formatUser.Close();
       
   424 
       
   425     if (r == KErrNotSupported)
       
   426         {
       
   427         test.Printf(_L("Media does not support ESpecialFormat"));
       
   428         return;
       
   429         }
       
   430 
       
   431     //-- format has finished, Check format validity
       
   432     TPckgBuf<TInt> sbuf;
       
   433     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::ESectorsPerCluster, sbuf);
       
   434     TESTL(r==KErrNone);
       
   435     const TInt resSectorsPerCluster = sbuf();
       
   436 
       
   437     TPckgBuf<TInt64> sizebuf;
       
   438     r = TheFs.ControlIo(gDrive, CTestProxyDrive::EDiskSize, sizebuf);
       
   439     TESTL(r==KErrNone);
       
   440     const TInt64 resVolSize = sizebuf();
       
   441 
       
   442     //-- Check fat type
       
   443     TPckgBuf<TInt> tbuf;
       
   444     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EFatType, tbuf);
       
   445     TESTL(r==KErrNone);
       
   446     const TUint resFatType = tbuf();
       
   447 
       
   448     test.Printf(_L("Format result:, size=%uKB, SecPerClust=%u, FAT%d\n"), (TUint32)(resVolSize/KKiloByte), resSectorsPerCluster, resFatType);
       
   449 
       
   450     TESTL(resFatType == fatType);
       
   451 
       
   452     //-- user-defined format CFatFormatCB::InitFormatDataForFixedSizeDiskUser(TInt aDiskSizeInSectors)
       
   453     //-- can decide decides how many SectorsPerCluster will be on the volume. As the result, requested and resulted values can be different.
       
   454     TESTL(resSectorsPerCluster == sectorsPerCluster);
       
   455 
       
   456     //-- check whole drive
       
   457     test.Next(_L("Check Disk"));
       
   458     r = TheFs.CheckDisk(gDriveName);
       
   459     TESTL(r==KErrNone);
       
   460     }
       
   461 
       
   462 //-------------------------------------------------------------
       
   463 
       
   464 /** Randomly generate several sector numbers in FAT data area, which will be marked as bad. */
       
   465 static void CreateBadList()
       
   466 {
       
   467     static TInt64 rndSeed = Math::Random();
       
   468     const TInt size = sizeof(gBadList) / sizeof(TInt);
       
   469 
       
   470     //const TUint32 dataStartSector = BootSector.FirstFreeSector(); //-- 1st sector number of the data area (after the root directory for fat12/16)
       
   471 
       
   472     //-- 1st sector number of the data area.
       
   473     //-- for fat12/16 it will be 1st sector after the root directory
       
   474     //-- for fat32 it will be the 1st sector of the second cluster after the root directory. At present we don't handle the 1st bad cluster of the root dir.
       
   475     TUint32 dataStartSector;
       
   476 
       
   477     if(BootSector.FatType() == EFat32)
       
   478     {
       
   479         dataStartSector = BootSector.RootDirStartSector() + 1*BootSector.SectorsPerCluster();
       
   480     }
       
   481     else
       
   482     {
       
   483         dataStartSector = BootSector.FirstDataSector();
       
   484     }
       
   485 
       
   486 
       
   487     test.Printf(_L("data start sector:%d, total sectors:%d\n"), dataStartSector, BootSector.VolumeTotalSectorNumber());
       
   488 
       
   489      //-- randomly generate bad sectors numbers in the FAT volume data area
       
   490     for(TInt i = 0; i<size; ++i)
       
   491      {
       
   492         const TUint32 rand = ((TUint32)Math::Rand(rndSeed)) % (BootSector.VolumeTotalSectorNumber() - dataStartSector);
       
   493         const TUint32 sectNum = dataStartSector + rand;
       
   494 
       
   495         gBadList[i] = sectNum;
       
   496         test.Printf(_L("Value of gBadList[%d] is %d\n"), i, gBadList[i]);
       
   497      }
       
   498 
       
   499 }
       
   500 
       
   501 
       
   502 //-------------------------------------------------------------
       
   503 
       
   504 /**
       
   505     Read and validate the boot sector
       
   506 */
       
   507 static void ReadBootSector()
       
   508 {
       
   509     test.Printf(_L("Reading Boot sector...\n"));
       
   510 
       
   511     TInt nRes = ReadBootSector(TheFs, gDrive, KBootSectorNum << KDefaultSectorLog2, BootSector);
       
   512     test(nRes == KErrNone);
       
   513 
       
   514     if(!BootSector.IsValid())
       
   515     {
       
   516         test.Printf(_L("The boot sector is invalid! dump:\n"));
       
   517         BootSector.PrintDebugInfo();
       
   518         test(0);
       
   519     }
       
   520 
       
   521 }
       
   522 
       
   523 //
       
   524 // Write version number to disk using raw disk write
       
   525 // For FAT 32 the version number is written to the backup boot sector as well.
       
   526 //
       
   527 void WriteVersionNumber()
       
   528 {
       
   529     //-- boot sector version number is already corrupt in ChangeVersionNumberAndMountL()
       
   530     test.Printf(_L("writing boot sector version number.\n"));
       
   531 
       
   532     TInt nRes;
       
   533 
       
   534     //-- 1. corrupt a backup boot sector if it is on the volume. This will prevent
       
   535     //-- using a valid backup boot sector instead of corrupted main one.
       
   536     //-- we need to do it before corrupting the main one, because RawWrite causes volume remount.
       
   537     TFatBootSector bs1;
       
   538     const TUint32 KBkBootSecPos = KBkBootSectorNum << KDefaultSectorLog2;
       
   539 
       
   540     nRes = ReadBootSector(TheFs, gDrive, KBkBootSecPos, bs1);
       
   541     if(nRes == KErrNone && bs1.IsValid())
       
   542     {//-- write corrupted backup boot sector
       
   543         nRes = WriteBootSector(TheFs, gDrive, KBkBootSecPos, BootSector);
       
   544         test(nRes == KErrNone);
       
   545     }
       
   546 
       
   547     //-- write main boot sector from the pos 0
       
   548     nRes = WriteBootSector(TheFs, gDrive, KBootSectorNum << KDefaultSectorLog2, BootSector);
       
   549     test(nRes == KErrNone);
       
   550 }
       
   551 
       
   552 //
       
   553 // Root Cluster Number update test
       
   554 //
       
   555 void DoTestRootClusterUpdate()
       
   556 {
       
   557     test.Next(_L("Performing fat32 root cluster number update check\n"));
       
   558 
       
   559     //Mark cluster 2 as bad by raw access.
       
   560     RRawDisk rawDisk;
       
   561 
       
   562     TInt r=rawDisk.Open(TheFs,gSessionPath[0]-'A');
       
   563     test(r==KErrNone);
       
   564 
       
   565     //Mark Cluster 2  & 3 as bad
       
   566     const TInt fatStartPos = BootSector.FirstFatSector() * BootSector.BytesPerSector();
       
   567     TInt64 pos = 8 + fatStartPos;
       
   568 
       
   569     TBuf8<4> data(4);
       
   570     data[0] = 0xF7;
       
   571     data[1] = 0xFF;
       
   572     data[2] = 0xFF;
       
   573     data[3] = 0x0F;
       
   574 
       
   575     r=rawDisk.Write(pos, data);
       
   576     test(r==KErrNone);
       
   577 
       
   578     pos += 4;
       
   579     r = rawDisk.Write(pos, data);
       
   580     test(r==KErrNone);
       
   581 
       
   582     rawDisk.Close();
       
   583 
       
   584     //-- quick format the drive
       
   585     r = FormatFatDrive(TheFs, gDrive, ETrue);
       
   586     test(r==KErrNone);
       
   587 
       
   588     const TUint oldClusterNum = BootSector.RootClusterNum();
       
   589     ReadBootSector();
       
   590 
       
   591     test.Printf(_L("Old Rool clNum:%d, new:%d\n"), oldClusterNum, BootSector.RootClusterNum());
       
   592 
       
   593     test(BootSector.RootClusterNum() != oldClusterNum);
       
   594 
       
   595 }
       
   596 
       
   597 //
       
   598 //Make version number invalid and try to mount
       
   599 //
       
   600 void ChangeVersionNumberAndMountL()
       
   601 {
       
   602     test.Printf(_L("Change fat32 version number and remount\n"));
       
   603 
       
   604     TFullName name;
       
   605 
       
   606     BootSector.SetVersionNumber(0x707); //-- corrupt Version number in the boot sector
       
   607 
       
   608     WriteVersionNumber();
       
   609 
       
   610     TInt r = TheFs.FileSystemName(name, gDrive);
       
   611     test(r == KErrNone);
       
   612 
       
   613     r = DismountFileSystem(TheFs, name, gDrive);
       
   614     test(r == KErrNone);
       
   615 
       
   616     r = MountFileSystem(TheFs, name, gDrive);
       
   617 
       
   618     test(r == KErrCorrupt);
       
   619 
       
   620 }
       
   621 
       
   622 
       
   623 //
       
   624 // Test version number
       
   625 //
       
   626 void DoTestVersionNumber()
       
   627 {
       
   628     test.Next(_L("Performing fat32 version number check\n"));
       
   629     TFullName name;
       
   630     TInt count;
       
   631 
       
   632     ReadBootSector();
       
   633     ChangeVersionNumberAndMountL();
       
   634 
       
   635     // Test quick format
       
   636     RFormat formatQuick;
       
   637     TInt r = formatQuick.Open(TheFs, gDriveName, EQuickFormat, count);
       
   638     test(r == KErrNone);
       
   639 
       
   640     r = DoFormatSteps(formatQuick, count);
       
   641     test(r == KErrNone);
       
   642 
       
   643     formatQuick.Close();
       
   644 
       
   645     ReadBootSector();
       
   646     r = TheFs.FileSystemName(name, gDrive);
       
   647     test(r == KErrNone);
       
   648 
       
   649     r = DismountFileSystem(TheFs, name, gDrive);
       
   650     test(r == KErrNone);
       
   651 
       
   652     r = MountFileSystem(TheFs, name, gDrive);
       
   653     test(r == KErrNone);
       
   654 
       
   655 }
       
   656 
       
   657 //
       
   658 // Test format disk with bad clusters
       
   659 //
       
   660 void DoTestFormatL()
       
   661     {
       
   662     test.Next(_L("Test full format\n"));
       
   663 
       
   664     // Test full format
       
   665     TInt count;
       
   666     TInt r = KErrNone;
       
   667 
       
   668     RFormat formatFull;
       
   669     r = formatFull.Open(TheFs, gDriveName, EFullFormat, count);
       
   670     TESTL(r == KErrNone);
       
   671 
       
   672     // Insert bad clusters, based on the boot sector info obtained by the initial format
       
   673     MarkClustersL();
       
   674 
       
   675     r = DoFormatSteps(formatFull, count);
       
   676     TESTL(r == KErrNone);
       
   677 
       
   678     formatFull.Close();
       
   679 
       
   680     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EUnmarkAll, NULL, NULL);
       
   681     TESTL(r==KErrNone);
       
   682 
       
   683     test.Next(_L("Test quick format"));
       
   684 
       
   685     // Test quick format
       
   686     RFormat formatQuick;
       
   687     r = formatQuick.Open(TheFs, gDriveName, EQuickFormat, count);
       
   688     TESTL(r == KErrNone);
       
   689 
       
   690     r = DoFormatSteps(formatQuick, count);
       
   691     TESTL(r == KErrNone);
       
   692 
       
   693     formatQuick.Close();
       
   694 
       
   695     test.Next(_L("Test full format"));
       
   696 
       
   697     // Test full format
       
   698     RFormat formatFull2;
       
   699     r = formatFull2.Open(TheFs, gDriveName, EFullFormat, count);
       
   700     TESTL(r == KErrNone);
       
   701     MarkClustersL();
       
   702 
       
   703     r = DoFormatSteps(formatFull2, count);
       
   704     TESTL(r == KErrNone);
       
   705 
       
   706     formatFull2.Close();
       
   707 
       
   708     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EUnmarkAll, NULL, NULL);
       
   709     TESTL(r==KErrNone);
       
   710 
       
   711     test.Next(_L("Test user specific format"));
       
   712 
       
   713     // Test user specific format
       
   714     DoTestUserFormatL(EFalse, EFalse);
       
   715     ReadBootSector();
       
   716     CreateBadList();
       
   717     DoTestUserFormatL(EFalse, ETrue);
       
   718 
       
   719     r = TheFs.ControlIo(gDrive, CFatTestProxyDrive::EUnmarkAll, NULL, NULL);
       
   720     TESTL(r==KErrNone);
       
   721 
       
   722     test.Next(_L("Test user specific quick format"));
       
   723 
       
   724     // Test user specific quick format
       
   725     DoTestUserFormatL(ETrue, EFalse);
       
   726     }
       
   727 
       
   728 void DoTestL()
       
   729     {
       
   730     // Make sure the card is formatted, then extract boot sector info
       
   731 
       
   732     TInt count;
       
   733     RFormat formatFull;
       
   734 
       
   735     //Mini SD cards works properly only with ESpecialFormat. Fix for Defect DEF091659
       
   736     TInt r = formatFull.Open(TheFs, gDriveName, ESpecialFormat, count);
       
   737     test(r == KErrNone);
       
   738 
       
   739     r = DoFormatSteps(formatFull, count);
       
   740     test(r == KErrNone);
       
   741 
       
   742     formatFull.Close();
       
   743 
       
   744     ReadBootSector();
       
   745     //...and create the bad sector list
       
   746     CreateBadList();
       
   747 
       
   748     DoTestReadWriteL();
       
   749 
       
   750     DoTestFormatL();
       
   751     }
       
   752 
       
   753 
       
   754 //-------------------------------------------------------------
       
   755 
       
   756 void CallTestsL()
       
   757     {
       
   758 #if !(defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE))
       
   759     test.Printf(_L("Tests only run in debug mode"));
       
   760     return;
       
   761 #else
       
   762     // Only test FAT filesystem
       
   763     TInt r;
       
   764     r = TheFs.CharToDrive(gDriveToTest, gDrive);
       
   765     test(r == KErrNone);
       
   766     gDriveName[0] = (TText)gDriveToTest;
       
   767     gDriveName[1] = ':';
       
   768 
       
   769     //-- set up console output
       
   770     Fat_Test_Utils::SetConsole(test.Console());
       
   771 
       
   772     //-- print drive information
       
   773     PrintDrvInfo(TheFs, gDrive);
       
   774 
       
   775     if (!Is_Fat(TheFs, gDrive))
       
   776         {
       
   777         test.Printf(_L("Drive %d is not FAT file system\n"),gDrive);
       
   778         return;
       
   779         }
       
   780 
       
   781     // No need for variable size disk
       
   782     TDriveInfo info;
       
   783     r = TheFs.Drive(info, gDrive);
       
   784     test(r == KErrNone);
       
   785     if (info.iMediaAtt & KMediaAttVariableSize)
       
   786         {
       
   787         test.Printf(_L("Drive %d is variable-size disk, skip\n"),gDrive);
       
   788         return;
       
   789         }
       
   790 
       
   791     //-- perform FAT32 specific tests
       
   792 
       
   793     if(Is_Fat32(TheFs, gDrive) && !Is_Automounter(TheFs, gDrive))
       
   794     {//-- these tests tend to corrupt the volume; Automounter can't cope with it easily
       
   795         DoTestVersionNumber();
       
   796         DoTestRootClusterUpdate();
       
   797     }
       
   798 
       
   799     //-- install test extension etc.
       
   800     if(!PrepareMount())
       
   801         return;
       
   802 
       
   803     //-- perform the rest of the tests
       
   804     DoTestL();
       
   805 
       
   806     //-- dismount the extension and format the drive
       
   807     //-- there is an issue here: if one of the tests fail, the extension won't be dismounted, which
       
   808     //-- will cause total crash.
       
   809     RestoreEnv();
       
   810 #endif
       
   811     }
       
   812 
       
   813 
       
   814 
       
   815