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