sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32test\fat32\t_compat32.cpp sl@0: // sl@0: // sl@0: sl@0: #define __E32TEST_EXTENSION__ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "t_server.h" sl@0: sl@0: #include "fat_utils.h" sl@0: using namespace Fat_Test_Utils; sl@0: sl@0: RTest test(_L("T_COMPAT32")); sl@0: sl@0: static RRawDisk TheDisk; sl@0: static TFatBootSector gBootSector; sl@0: sl@0: sl@0: static void QuickFormat() sl@0: { sl@0: FormatFatDrive(TheFs, CurrentDrive(), ETrue); sl@0: } sl@0: sl@0: static void ReadBootSector(TFatBootSector& aBootSector) sl@0: { sl@0: sl@0: TInt nRes = ReadBootSector(TheFs, CurrentDrive(), KBootSectorNum<Count(); sl@0: sl@0: test(count==1); sl@0: delete entryCount; sl@0: } sl@0: sl@0: sl@0: // sl@0: // Renaming a 8.3 filename with upper and lower case letters which is, actually out of FAT specs. sl@0: // I.e. VFAT entries are valid, but DOS entry has a lower case symbol, which is wrong. sl@0: // sl@0: LOCAL_C void Test2(TNameCase aCase) sl@0: { sl@0: test.Next(_L("Rename a file with a wrong DOS entry")); sl@0: QuickFormat(); sl@0: RFile file; sl@0: TInt r; sl@0: sl@0: //-- N.B. This shall be the before any dir. entries creation in the root dir sl@0: //-- because it directly accesses the directory's 1st file sl@0: DoFiddleWithFileNames(aCase); sl@0: sl@0: r=file.Create(TheFs,_L("\\TEST"),EFileRead); sl@0: test(r==KErrNone); sl@0: file.Close(); sl@0: sl@0: r=TheFs.Rename(_L("\\TEST"),_L("\\Word")); sl@0: test(r==KErrAlreadyExists); sl@0: r=TheFs.Delete(_L("\\TEST")); sl@0: test(r==KErrNone); sl@0: sl@0: CDir* entryCount; sl@0: r=TheFs.GetDir(_L("\\*.*"),KEntryAttMaskSupported,ESortNone,entryCount); sl@0: test(r==KErrNone); sl@0: TInt count=entryCount->Count(); sl@0: test(count==1); sl@0: delete entryCount; sl@0: } sl@0: sl@0: sl@0: //--------------------------------------------- sl@0: //! @SYMTestCaseID PBASE-T_COMPAT32-0686 sl@0: //! @SYMTestType CT sl@0: //! @SYMREQ DEF115314 sl@0: //! @SYMTestCaseDesc Test character '`' (0x60) is recognized as a legal char for short file names. sl@0: //! @SYMTestActions Creates a file named "\x60\x60\x60.TXT", checks only DOS entry is created for sl@0: //! it and its short name equals "```.TXT" instead of "___.TXT" sl@0: //! @SYMTestExpectedResults The operation completes with error code KErrNone; sl@0: //! @SYMTestPriority High sl@0: //! @SYMTestStatus Implemented sl@0: //--------------------------------------------- sl@0: void TestDEF115314() sl@0: { sl@0: test.Next(_L("Test DEF115314: TTG:<`(0x60) code cannot be used as valid Short File Name>")); sl@0: QuickFormat(); sl@0: RFile file; sl@0: TInt r; sl@0: sl@0: TFileName fn; sl@0: fn.Format(_L("%c:\\\x60\x60\x60.TXT"), (TUint8)gDriveToTest); sl@0: sl@0: r = TheFs.Delete(fn); sl@0: test(r==KErrNone || r==KErrNotFound); sl@0: sl@0: r = file.Create(TheFs, fn, EFileRead); sl@0: test(r==KErrNone); sl@0: file.Close(); sl@0: sl@0: r=TheDisk.Open(TheFs,CurrentDrive()); sl@0: test(r==KErrNone); sl@0: sl@0: //-- read 1st dir. it should be DOS Entry sl@0: const TInt posEntry1=gBootSector.RootDirStartSector() << KDefaultSectorLog2; //-- dir entry1 position sl@0: TFatDirEntry fatEntry1; sl@0: TPtr8 ptrEntry1((TUint8*)&fatEntry1,sizeof(TFatDirEntry)); sl@0: test(TheDisk.Read(posEntry1, ptrEntry1)==KErrNone); sl@0: TheDisk.Close(); sl@0: test(!fatEntry1.IsVFatEntry()); sl@0: sl@0: // tests short name sl@0: TFileName sn; sl@0: r = TheFs.GetShortName(fn, sn); sl@0: test(r==KErrNone); sl@0: test(sn.Compare(_L("```.TXT"))==0); sl@0: sl@0: r = TheFs.Delete(fn); sl@0: test(r==KErrNone); sl@0: } sl@0: sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: _LIT(KTestLocale, "t_tlocl_cp932.dll"); sl@0: _LIT(KTestUnicodeFileName, "\\\x65B0\x6587\x4EF6"); sl@0: #endif //_DEBUG || _DEBUG_RELEASE sl@0: sl@0: //--------------------------------------------- sl@0: //! @SYMTestCaseID PBASE-T_COMPAT32-0685 sl@0: //! @SYMTestType CT sl@0: //! @SYMREQ DEF113633 sl@0: //! @SYMTestCaseDesc Test FAT volume creates VFat entries for short unicode named files sl@0: //! @SYMTestActions Enables FatUtilityFunctions. Loads cp932 codepage dll. Create a file sl@0: //! named as "\x65B0\x6587\x4EF6", checks both a VFat entry and a DOS sl@0: //! entry have been created for the file. sl@0: //! @SYMTestExpectedResults The operation completes with error code KErrNone; sl@0: //! @SYMTestPriority High sl@0: //! @SYMTestStatus Implemented sl@0: //--------------------------------------------- sl@0: void TestDEF113633() sl@0: { sl@0: test.Next(_L("Test DEF113633 - FAT should create VFat entries for unicode character contained file names")); sl@0: #if defined(_DEBUG) || defined(_DEBUG_RELEASE) sl@0: QuickFormat(); sl@0: RFile file; sl@0: TInt r; sl@0: TInt drvNum; sl@0: sl@0: r = TheFs.CharToDrive(gDriveToTest,drvNum); sl@0: test(r==KErrNone); sl@0: sl@0: // turn on FatUtilityFunctions sl@0: r = TheFs.ControlIo(drvNum, KControlIoEnableFatUtilityFunctions); sl@0: test(r==KErrNone); sl@0: sl@0: // load cp932 codepage dll sl@0: r = UserSvr::ChangeLocale(KTestLocale); sl@0: test(r==KErrNone); sl@0: sl@0: // create file "\x65B0\x6587\x4EF6", check DOS entry & VFat entry sl@0: r = file.Create(TheFs, KTestUnicodeFileName, EFileRead); sl@0: test(r==KErrNone); sl@0: file.Close(); sl@0: sl@0: r=TheDisk.Open(TheFs,CurrentDrive()); sl@0: test(r==KErrNone); sl@0: sl@0: //-- read 1st dir. it should be VFat sl@0: // const TInt posEntry1=gRootDirStart; //-- dir entry1 position sl@0: const TInt posEntry1=gBootSector.RootDirStartSector() << KDefaultSectorLog2; //-- dir entry1 position sl@0: TFatDirEntry fatEntry1; sl@0: TPtr8 ptrEntry1((TUint8*)&fatEntry1,sizeof(TFatDirEntry)); sl@0: sl@0: test(TheDisk.Read(posEntry1, ptrEntry1)==KErrNone); sl@0: sl@0: test(fatEntry1.IsVFatEntry()); sl@0: sl@0: test(fatEntry1.iData[0] == 0x41); //-- must have only 2 entries sl@0: sl@0: //-- read DOS entry now sl@0: TFatDirEntry fatEntry2; sl@0: TPtr8 ptrEntry2((TUint8*)&fatEntry2,sizeof(TFatDirEntry)); sl@0: const TInt posEntry2 = posEntry1 + sizeof(TFatDirEntry); //-- dir entry2 position sl@0: sl@0: test(TheDisk.Read(posEntry2, ptrEntry2)==KErrNone); sl@0: sl@0: //-- ensure that the name and checksum are correct sl@0: test(!fatEntry2.IsVFatEntry()); sl@0: test(fatEntry1.iData[13] == CalculateShortNameCheckSum(fatEntry2.Name())); sl@0: sl@0: // delete file sl@0: TheDisk.Close(); sl@0: r = TheFs.Delete(KTestUnicodeFileName); sl@0: test(r==KErrNone); sl@0: sl@0: // turn off FatUtilityFunctions sl@0: r = TheFs.ControlIo(drvNum, KControlIoDisableFatUtilityFunctions); sl@0: test(r==KErrNone); sl@0: sl@0: #else sl@0: test.Printf(_L("Test only runs on DEBUG builds, see test logs of debug builds for details.")); sl@0: #endif // _DEBUG) || _DEBUG_RELEASE sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: //--------------------------------------------- sl@0: // If the parent directory of a directory is the root directory, sl@0: // the '..' entry should point to start cluster 0 in any case sl@0: //--------------------------------------------- sl@0: void TestPDEF116912() sl@0: { sl@0: test.Next(_L("Test PDEF116912 - Check that '..' parent cluster address is 0 after renaming\n")); sl@0: sl@0: TInt drvNum; sl@0: test(KErrNone == TheFs.CharToDrive(gDriveToTest, drvNum)); sl@0: sl@0: if(!Is_Fat32(TheFs, drvNum)) sl@0: { sl@0: _LIT(KMessage, "Test only applicable to FAT32 file systems. Skipping.\n"); sl@0: test.Printf(KMessage); sl@0: return; sl@0: } sl@0: sl@0: QuickFormat(); sl@0: sl@0: _LIT(KDirA, "\\dirA\\"); sl@0: _LIT(KDirB, "\\dirB\\"); sl@0: sl@0: test(KErrNone == TheFs.MkDir(KDirA)); sl@0: test(KErrNone == TheFs.Rename(KDirA, KDirB)); sl@0: sl@0: test(gBootSector.IsValid()); sl@0: TInt mediaPosition = gBootSector.RootDirStartSector() * gBootSector.BytesPerSector(); sl@0: sl@0: TFatDirEntry dirEntry; sl@0: TPtr8 ptrEntry((TUint8*) &dirEntry,sizeof(TFatDirEntry)); sl@0: sl@0: _LIT8(KDirBMatchPattern, "DIRB *"); sl@0: _LIT8(KDotDotMatchPattern, ".. *"); sl@0: sl@0: const TInt KMaxEntriesToSearch = (gBootSector.SectorsPerCluster() * gBootSector.BytesPerSector()) / KSizeOfFatDirEntry; sl@0: test(KErrNone == TheDisk.Open(TheFs, drvNum)); sl@0: sl@0: for(TInt c = 0; c < KMaxEntriesToSearch; c++) sl@0: { sl@0: test(KErrNone == TheDisk.Read(mediaPosition, ptrEntry)); sl@0: sl@0: if(KErrNotFound == ptrEntry.Match(KDirBMatchPattern)) sl@0: { sl@0: // keep scanning sl@0: mediaPosition += sizeof(TFatDirEntry); sl@0: } sl@0: else sl@0: { sl@0: // found, locate '..' entry sl@0: test(dirEntry.StartCluster() >= KFatFirstSearchCluser); sl@0: mediaPosition = gBootSector.FirstDataSector(); sl@0: mediaPosition += (dirEntry.StartCluster() - KFatFirstSearchCluser) * gBootSector.SectorsPerCluster(); sl@0: mediaPosition *= gBootSector.BytesPerSector(); sl@0: mediaPosition += KSizeOfFatDirEntry; // '..' is always the 2nd entry sl@0: sl@0: test(KErrNone == TheDisk.Read(mediaPosition, ptrEntry)); sl@0: sl@0: test(KErrNotFound != ptrEntry.Match(KDotDotMatchPattern)); sl@0: test(dirEntry.StartCluster() == 0); sl@0: sl@0: TheDisk.Close(); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: // dirB entry not found - test failed sl@0: TheDisk.Close(); sl@0: test(0); sl@0: } sl@0: sl@0: //--------------------------------------------- sl@0: /** sl@0: Test replacing files by theis short names sl@0: */ sl@0: void TestReplaceByShortName() sl@0: { sl@0: test.Next(_L("Test replacing files using short names\n")); sl@0: QuickFormat(); sl@0: sl@0: _LIT(KLongName1, "abcdefghi.txt"); sl@0: _LIT(KShortName1, "ABCDEF~1.TXT"); sl@0: const TInt KFile1Sz = 100; sl@0: sl@0: _LIT(KLongName2, "abcdefghij.txt"); sl@0: _LIT(KShortName2, "ABCDEF~2.TXT"); sl@0: const TInt KFile2Sz = 200; sl@0: sl@0: sl@0: TInt nRes; sl@0: TFileName fn; sl@0: TEntry entry; sl@0: sl@0: TheFs.SetSessionPath(_L("\\")); sl@0: sl@0: nRes = CreateCheckableStuffedFile(TheFs, KLongName1, KFile1Sz); sl@0: test_KErrNone(nRes); sl@0: sl@0: nRes = TheFs.GetShortName(KLongName1, fn); sl@0: test(nRes == KErrNone && fn == KShortName1); //-- just check short name generation sl@0: sl@0: nRes =CreateCheckableStuffedFile(TheFs, KLongName2, KFile2Sz); sl@0: test_KErrNone(nRes); sl@0: sl@0: nRes = TheFs.GetShortName(KLongName2, fn); sl@0: test(nRes == KErrNone && fn == KShortName2); //-- just check short name generation sl@0: sl@0: //-- try to replace the file with itself using its short name alias sl@0: //-- nothing shall happen and the file must remain the same sl@0: nRes = TheFs.Replace(KLongName1, KShortName1); sl@0: test(nRes == KErrNone); sl@0: sl@0: nRes = TheFs.Entry(KLongName1, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz); sl@0: sl@0: nRes = TheFs.Entry(KShortName1, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz); sl@0: sl@0: sl@0: nRes = TheFs.Replace(KShortName1, KLongName1); sl@0: test(nRes == KErrNone); sl@0: sl@0: nRes = TheFs.Entry(KLongName1, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz); sl@0: sl@0: nRes = TheFs.Entry(KShortName1, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz); sl@0: sl@0: nRes = VerifyCheckableFile(TheFs, KLongName1); sl@0: test(nRes == KErrNone); sl@0: sl@0: nRes = VerifyCheckableFile(TheFs, KShortName1); sl@0: test(nRes == KErrNone); sl@0: sl@0: sl@0: //-- replace "abcdefghi.txt" by "ABCDEF~2.TXT" which is the alias for "abcdefghij.txt" sl@0: //-- expected: contents and all attributes of the "abcdefghij.txt" is replaced with "abcdefghi.txt" sl@0: //-- "abcdefghi.txt" entries gets deleted. sl@0: sl@0: nRes = TheFs.Replace(KLongName1, KShortName2); sl@0: test(nRes == KErrNone); sl@0: sl@0: //User::After(5*K1Sec); sl@0: /* sl@0: nRes = VerifyCheckableFile(TheFs, KLongName2); sl@0: test(nRes == KErrNone); sl@0: sl@0: nRes = VerifyCheckableFile(TheFs, KShortName2); sl@0: test(nRes == KErrNone); sl@0: */ sl@0: sl@0: sl@0: nRes = TheFs.Entry(KLongName2, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz); sl@0: sl@0: nRes = TheFs.Entry(KShortName2, entry); sl@0: test(nRes == KErrNone); sl@0: test(entry.iSize == KFile1Sz && entry.iName == KLongName2); sl@0: sl@0: sl@0: } sl@0: sl@0: sl@0: GLDEF_C void CallTestsL() sl@0: // sl@0: // Call tests that may leave sl@0: // sl@0: { sl@0: sl@0: TInt drvNum; sl@0: TInt r=TheFs.CharToDrive(gDriveToTest,drvNum); sl@0: test(r==KErrNone); sl@0: sl@0: if (!Is_Fat(TheFs,drvNum)) sl@0: { sl@0: test.Printf(_L("CallTestsL: Skipped: Requires FAT filesystem to run.\n")); sl@0: return; sl@0: } sl@0: sl@0: sl@0: //-- set up console output sl@0: SetConsole(test.Console()); sl@0: sl@0: //-- print drive information sl@0: PrintDrvInfo(TheFs, drvNum); sl@0: sl@0: GetBootInfo(); sl@0: sl@0: Test1(EUpper); // Test directory entries with 8.3 uppercase (no VFAT entries expected) sl@0: Test1(ELower); // Test directory entries with 8.3 lowercase ( VFAT entries expected) sl@0: Test1(EMixed); // Test directory entries with 8.3 mixed ( VFAT entries expected) sl@0: sl@0: Test2(EUpper); // Test directory entries with 8.3 uppercase (no VFAT entries expected) sl@0: Test2(ELower); // Test directory entries with 8.3 lowercase ( VFAT entries expected) sl@0: Test2(EMixed); // Test directory entries with 8.3 mixed ( VFAT entries expected) sl@0: sl@0: TestDEF115314(); sl@0: TestDEF113633(); sl@0: TestPDEF116912(); sl@0: sl@0: TestReplaceByShortName(); sl@0: sl@0: } sl@0: sl@0: sl@0: