First public contribution.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
15 // various FAT utilities
19 #include "f32_test_utils.h"
20 using namespace F32_Test_Utils;
22 #include "filesystem_fat.h"
24 //-------------------------------------------------------------------------------------------------------------------
26 //-- define this macro if it is necessarily to exclude all stuff that uses RFs, consoles etc.
27 //-- may be useful if this code is used for file server extensions. mmp file is a good place to define this macro.
28 #ifndef FAT_UTILS_LEAN_AND_MEAN
33 //-- Note that the writable static data are not allowed in DLLs i.e. plugins or somethig else.
34 //-- Thus it needs to be thrown away by preprocessing in such a case.
36 static CConsoleBase* pConsole = NULL; //-- pointer to the text console for printing out data
37 static TBool bPrintOutEnabled = ETrue; //-- global flag, if EFalse, all printing out is disabled
40 Set the console where the ouput will go.
41 @param apConsole pointer to the console. if NULL, the print out will be debug port only.
43 void F32_Test_Utils::SetConsole(CConsoleBase* apConsole)
49 Enable or disable printing out. See DoPrintf()
50 @param bEnable If ETrue, print out is enabled
51 @return previous value of the global bPrintOutEnabled flag
53 TBool F32_Test_Utils::EnablePrintOutput(TBool bEnable)
55 TBool bPrevVal = bPrintOutEnabled;
56 bPrintOutEnabled = bEnable;
62 Print out the drive information.
64 @param aFs reference to the FS session
65 @param aDrive drive number
66 @return system-wide error codes.
68 TInt F32_Test_Utils::PrintDrvInfo(RFs &aFs, TInt aDrive)
76 nRes = aFs.Drive(driveInfo, aDrive);
80 nRes = aFs.Volume(volInfo, aDrive);
84 DoPrintf(_L("Drive %c: #%d\n"), 'A'+aDrive, aDrive);
86 //-- print the FS name
87 nRes = aFs.FileSystemName(Buf, aDrive);
91 //-- to find out FS sub type
93 nRes = aFs.FileSystemSubType(aDrive, fsName);
94 if(nRes == KErrNone && Buf.CompareF(fsName) !=KErrNone)
96 Buf.AppendFormat(_L(" (%S)"), &fsName);
100 DoPrintf(_L("FS name: %S\n"), &Buf);
102 //-- print drive and media attributes
103 DoPrintf(_L("MediaType: 0x%x\n"), driveInfo.iType);
104 DoPrintf(_L("DriveAtt:0x%x\n"),driveInfo.iDriveAtt);
105 DoPrintf(_L("MediaAtt:0x%x\n"),driveInfo.iMediaAtt);
107 //-- volume information
108 DoPrintf(_L("VolId:0x%x\n"),volInfo.iUniqueID);
109 DoPrintf(_L("VolSz:%ld (%ldK)\n"),volInfo.iSize, volInfo.iSize/1024);
110 DoPrintf(_L("Free:%ld (%ldK)\n"),volInfo.iFree, volInfo.iFree/1024);
115 //-------------------------------------------------------------------------------------------------------------------
119 Fill a media region with a given byte pattern
121 @param aFs reference to the FS session
122 @param aDrive drive number
123 @param aMediaStartPos media region start position
124 @param aMediaEndPos media region end position
125 @param aBytePattern byte to fill the media region with
127 @return system-wide error codes.
129 TInt F32_Test_Utils::FillMedia(RFs &aFs, TInt aDrive, TInt64 aMediaStartPos, TInt64 aMediaEndPos, TUint8 aBytePattern/*=0*/)
131 DoPrintf(_L("~ F32_Test_Utils::FillMedia() drv:%d, from:%u to:%u\n"),aDrive, (TUint32)aMediaStartPos, (TUint32)aMediaEndPos);
133 ASSERT(aMediaStartPos<=aMediaEndPos && aMediaStartPos >=0 && aMediaEndPos >=0);
135 TInt nRes = KErrNone;
137 const TUint32 KBufSz=65536; //-- zero-buffer size, bytes
139 //-- create a buffer, filled with given pattern
140 nRes = buf.CreateMax(KBufSz);
141 ASSERT(nRes == KErrNone);
142 buf.Fill(aBytePattern);
144 TUint32 rem = (TUint32)(aMediaEndPos - aMediaStartPos);
147 const TUint32 bytesToWrite=Min(rem, KBufSz);
148 TPtrC8 ptrData(buf.Ptr(), bytesToWrite);
150 nRes = MediaRawWrite(aFs, aDrive, aMediaStartPos, ptrData);
151 if(nRes != KErrNone && nRes != KErrDiskFull)
154 aMediaStartPos+=bytesToWrite;
164 //-------------------------------------------------------------------------------------------------------------------
167 Raw read from the media.
169 @param aFs reference to the FS session
170 @param aDrive drive number
171 @param aMediaPos media position
172 @param aLen how many bytes to read
173 @param aData descriptor for the data
175 @return system-wide error code.
177 TInt F32_Test_Utils::MediaRawRead(RFs &aFs, TInt aDrive, TInt64 aMediaPos, TUint32 aLen, TDes8& aData)
180 TRAP(nRes, DoMediaRawReadL(aFs, aDrive, aMediaPos, aLen, aData));
184 //-------------------------------------------------------------------------------------------------------------------
187 Raw write to the media.
189 @param aFs reference to the FS session
190 @param aDrive drive number
191 @param aMediaPos media position
192 @param aData descriptor with the data to write
194 @return system-wide error code.
196 TInt F32_Test_Utils::MediaRawWrite(RFs &aFs, TInt aDrive, TInt64 aMediaPos, const TDesC8& aData)
199 TRAP(nRes, DoMediaRawWriteL(aFs, aDrive, aMediaPos, aData));
204 //-------------------------------------------------------------------------------------------------------------------
205 void F32_Test_Utils::DoMediaRawReadL(RFs &aFs, TInt aDrive, TInt64 aMediaPos, TUint32 aLen, TDes8& aData)
207 ASSERT(aMediaPos>=0);
208 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
210 if((TUint32)aData.MaxSize() < aLen)
211 User::Leave(KErrArgument);
216 aData.SetLength(aLen);
219 CleanupClosePushL(rawDisk);
221 User::LeaveIfError(rawDisk.Open(aFs, aDrive));
222 User::LeaveIfError(rawDisk.Read(aMediaPos, aData));
224 CleanupStack::PopAndDestroy(&rawDisk);
227 //-------------------------------------------------------------------------------------------------------------------
228 void F32_Test_Utils::DoMediaRawWriteL(RFs &aFs, TInt aDrive, TInt64 aMediaPos, const TDesC8& aData)
230 ASSERT(aMediaPos>=0);
231 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
233 if(aData.Size() == 0)
237 CleanupClosePushL(rawDisk);
239 User::LeaveIfError(rawDisk.Open(aFs, aDrive));
240 User::LeaveIfError(rawDisk.Write(aMediaPos, (TDesC8&)aData));
242 CleanupStack::PopAndDestroy(&rawDisk);
245 //-------------------------------------------------------------------------------------------------------------------
247 _LIT(KFsName_LFFS, "lffs");
248 _LIT(KFsName_Win32, "Win32");
249 _LIT(KFsName_ExFAT, "ExFat");
250 _LIT(KFsName_AutoMonuter, "automounter");
252 /** @return ETrue if "Automounter" FS is mounted on this drive */
253 TBool F32_Test_Utils::Is_Automounter(RFs &aFs, TInt aDrive)
255 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
257 TInt r = aFs.FileSystemName(f, aDrive);
258 __ASSERT_ALWAYS((r==KErrNone) && (f.Length()>0), User::Invariant());
260 return (f.CompareF(KFsName_AutoMonuter) == 0 );
264 /** @return ETrue if "lffs" FS is mounted on this drive */
265 TBool F32_Test_Utils::Is_Lffs(RFs &aFs, TInt aDrive)
267 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
269 TInt r = aFs.FileSystemName(f, aDrive);
270 __ASSERT_ALWAYS((r==KErrNone) && (f.Length()>0), User::Invariant());
272 return (f.CompareF(KFsName_LFFS) == 0 );
276 /** @return ETrue if "Win32" FS is mounted on this drive (i.e this is emulator's drive c:) */
277 TBool F32_Test_Utils::Is_Win32(RFs &aFs, TInt aDrive)
279 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
281 TInt r = aFs.FileSystemName(f, aDrive);
282 __ASSERT_ALWAYS((r==KErrNone) && (f.Length()>0), User::Invariant());
284 return (f.CompareF(KFsName_Win32) == 0 );
287 /** @return ETrue if the filesystem if FAT (fat12/16/32) */
288 TBool F32_Test_Utils::Is_Fat(RFs &aFs, TInt aDrive)
290 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
292 TInt nRes = aFs.FileSystemName(fsName, aDrive);
293 __ASSERT_ALWAYS((nRes==KErrNone) && (fsName.Length()>0), User::Invariant());
295 if(fsName.CompareF(KFileSystemName_FAT) == 0)
296 return ETrue; //-- "FAT" FS is explicitly mounted on this drive
298 //-- try analyse file system subtype for the case of automounter FS
299 nRes = aFs.FileSystemSubType(aDrive,fsName);
303 return (fsName.CompareF(KFSSubType_FAT16) == 0 || fsName.CompareF(KFSSubType_FAT32) == 0 || fsName.CompareF(KFSSubType_FAT12) == 0);
306 /** returns ETrue if "exFAT" FS is mounted on this drive */
307 TBool F32_Test_Utils::Is_ExFat(RFs &aFs, TInt aDrive)
309 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
311 TInt nRes = aFs.FileSystemName(fsName, aDrive);
312 __ASSERT_ALWAYS((nRes==KErrNone) && (fsName.Length()>0), User::Invariant());
314 if(fsName.CompareF(KFsName_ExFAT) == 0 )
315 return ETrue; //-- "exFAT" FS is explicitly mounted on this drive
317 //-- try analyse file system subtype for the case of automounter FS
318 nRes = aFs.FileSystemSubType(aDrive,fsName);
322 return (fsName.CompareF(KFsName_ExFAT) == 0);
325 /** @return ETrue if the filesystem if FAT32 */
326 TBool F32_Test_Utils::Is_Fat32(RFs &aFs, TInt aDrive)
328 if(!Is_Fat(aFs, aDrive))
332 TInt nRes = aFs.FileSystemSubType(aDrive,fsName);
337 return (fsName.CompareF(KFSSubType_FAT32) == 0);
341 /** @return ETrue if the filesystem if FAT16 */
342 TBool F32_Test_Utils::Is_Fat16(RFs &aFs, TInt aDrive)
344 if(!Is_Fat(aFs, aDrive))
348 TInt nRes = aFs.FileSystemSubType(aDrive,fsName);
353 return (fsName.CompareF(KFSSubType_FAT16) == 0);
357 /** @return ETrue if the filesystem if FAT12 */
358 TBool F32_Test_Utils::Is_Fat12(RFs &aFs, TInt aDrive)
360 if(!Is_Fat(aFs, aDrive))
364 TInt nRes = aFs.FileSystemSubType(aDrive,fsName);
369 return (fsName.CompareF(KFSSubType_FAT12) == 0);
374 static void DoCreateCheckableFileL(RFile64& aFile, TUint64 aSize)
377 ASSERT(aSize >= TMD5::HashSize);
379 //-- 1. set file size
380 User::LeaveIfError(aFile.SetSize((TInt)aSize));
382 //-- 2. leave place for the 16-bytes MD5 hash in the file beginning
383 TInt64 filePos = TMD5::HashSize;
384 User::LeaveIfError(aFile.Seek(ESeekStart,filePos));
385 aSize-=TMD5::HashSize;
389 //-- 3. fill the file with random bytes
390 const TInt KBufSize=65536; //-- buffer size for writing data
391 TInt64 rndSeed = aSize % 43283;
396 buf.CreateMaxL(KBufSize);
398 TUint64 prevSz = aSize;
401 //-- initialize buffer with random rubbish
402 for(TInt i=0; i<KBufSize; ++i)
404 buf[i] = (TUint8)Math::Rand(rndSeed);
407 const TUint32 nBytes = (TUint32)Min((TUint64)KBufSize, aSize);
408 TPtrC8 ptrData(buf.Ptr(), nBytes);
409 User::LeaveIfError(aFile.Write(ptrData)); //-- write data to the file
410 md5Hash.Update(ptrData); //-- update MD5 hash
414 if((prevSz - aSize) >= K1MegaByte)
425 //-- 4. write MD5 hash to the beginning of the file
427 User::LeaveIfError(aFile.Seek(ESeekStart,filePos));
428 User::LeaveIfError(aFile.Write(md5Hash.Final()));
433 static void DoVerifyCheckableFileL(RFile64& aFile)
436 User::LeaveIfError(aFile.Size(fileSize));
438 if(fileSize < TMD5::HashSize)
439 User::Leave(KErrCorrupt); //-- MD5 hash is 16 bytes, it's the minimal file size
441 //-- 1. read MD5 header from the file
442 TBuf8<TMD5::HashSize> md5Header(TMD5::HashSize);
443 User::LeaveIfError(aFile.Read(md5Header));
444 fileSize -= TMD5::HashSize;
446 //-- 2. read the rest of the data and calculate the checksum
450 const TInt KBufSize=65536; //-- buffer size for writing data
451 buf.CreateMaxL(KBufSize);
453 TUint64 prevSz = fileSize;
456 User::LeaveIfError(aFile.Read(buf)); //-- read data from the file
457 if (buf.Length() == 0)
458 User::Leave(KErrEof);
459 md5Hash.Update(buf); //-- update MD5 hash
461 fileSize-=buf.Length();
463 if((prevSz - fileSize) >= K1MegaByte)
473 if(md5Hash.Final() != md5Header)
474 User::Leave(KErrCorrupt); //-- the file is corrupt
477 //-------------------------------------------------------------------------------------------------------------------
480 Creates a file filled with random data. The file has a 16-byte MD5 header at the start, so it is possible to
481 verify the data validity later. Thus the minimal file size is 16 bytes. The file with the iven name may already
482 exist; in this case it will be replaced.
484 @param aFs reference to the FS session
485 @param aFileName name of the file to be created / replaced
486 @param aSize size of the file; 16 bytes min.
488 @return Standard error code
490 TInt F32_Test_Utils::CreateCheckableStuffedFile(RFs& aFs, const TDesC& aFileName, TUint64 aSize)
493 DoPrintf(_L("~ F32_Test_Utils::CreateCheckableStuffedFile() file:%S, Size:%LU\n"), &aFileName, aSize);
495 if(aSize < TMD5::HashSize)
496 return KErrArgument; //-- MD5 hash is 16 bytes, it's the minimal file size
500 //-- 1. create a file
501 TInt nRes = file.Replace(aFs, aFileName, EFileWrite);
505 TRAP(nRes, DoCreateCheckableFileL(file, aSize));
513 Verify previously created file that has MD5 header at the beginning. See CreateCheckableStuffedFile(...)
515 @param aFs reference to the FS session
516 @param aFileName name of the file to be verified
518 @return Standard error code. KErrNone if the file contents matches the MD5 header.
520 TInt F32_Test_Utils::VerifyCheckableFile(RFs& aFs, const TDesC& aFileName)
522 DoPrintf(_L("~ F32_Test_Utils::VerifyCheckableFile() file:%S\n"), &aFileName);
526 //-- 1. create a file
527 TInt nRes = file.Open(aFs, aFileName, EFileRead);
531 TRAP(nRes, DoVerifyCheckableFileL(file));
540 Create an empty file (not filled with anything). The size of the file is set by using RFile::SetSize().
541 For FAT this will result in allocating a cluster chain in FAT fable, for the file systems that support sparse files (like LFFS)
542 this might not work as expected.
544 @param aFs reference to the FS session
545 @param aFileName name of the file to be created / replaced
546 @param aSize size of the file
548 @return Standard error code
550 TInt F32_Test_Utils::CreateEmptyFile(RFs& aFs, const TDesC& aFileName, TUint64 aSize)
552 DoPrintf(_L("~ F32_Test_Utils::CreateEmptyFile() file:%S, sz:%LU\n"), &aFileName, aSize);
556 //-- 1. create a file
557 TInt nRes = file.Replace(aFs, aFileName, EFileWrite);
561 //-- 2. set file size
562 nRes = file.SetSize(aSize);
569 //-------------------------------------------------------------------------------------------------------------------
572 Dismount and mount the filesystem again, optionally taking time when the mount starts.
573 The FS can have extensions added into it; this function will handle only the primary extension (if it is present) and
574 will mont the FS with it. Non-primary extensions are not supported yet.
577 @param aFs reference to the FS session
578 @param aDrive drive number
579 @param apTimeMountStart pointer to the TTime object, that can be called TTime::UniversalTime() on mount start (this can be
580 used for measuring time taken to mount the FS).
581 if NULL, no action will be taken.
583 @return error code from the RFs::MountFileSystem()
586 TInt F32_Test_Utils::RemountFS(RFs& aFs, TInt aDrive, TTime* apTimeMountStart/*=NULL*/)
589 DoPrintf(_L("~ F32_Test_Utils::RemountingFS at drive:%d\n"), aDrive);
591 TFSDescriptor fsDescriptor;
593 //-- 1. get current FS information
594 nRes = GetFileSystemDescriptor(aFs, aDrive, fsDescriptor);
598 //-- 2. dismount the file system
599 if(fsDescriptor.iPExtName.Length() > 0)
601 DoPrintf(_L("~ Dismounting FS:%S with ext:%S\n"), &fsDescriptor.iFsName, &fsDescriptor.iPExtName);
605 DoPrintf(_L("~ Dismounting FS:%S\n"), &fsDescriptor.iFsName);
608 nRes = aFs.DismountFileSystem(fsDescriptor.iFsName, aDrive);
615 //-- 3. mount it again
617 apTimeMountStart->UniversalTime(); //-- take Mount start time
620 nRes = MountFileSystem(aFs, aDrive, fsDescriptor);
624 //-------------------------------------------------------------------------------------------------------------------
626 TFSDescriptor::TFSDescriptor()
631 void TFSDescriptor::Init()
633 iFsName.SetLength(0);
634 iPExtName.SetLength(0);
635 iDriveSynch = EFalse;
638 TBool TFSDescriptor::operator==(const TFSDescriptor& aRhs) const
640 ASSERT(this != &aRhs);
641 return (iFsName.CompareF(aRhs.iFsName) == 0 && iPExtName.CompareF(aRhs.iPExtName) == 0 && iDriveSynch == aRhs.iDriveSynch);
645 //-------------------------------------------------------------------------------------------------------------------
647 Gets the information about file system mounted on a drive. This information can be later used for mounting this FS back if it is going to be dismounted
649 @param aFs reference to the FS session
650 @param aDrive drive number
651 @param aFsDesc file system descriptor
653 @return standard error code
655 TInt F32_Test_Utils::GetFileSystemDescriptor(RFs &aFs, TInt aDrive, TFSDescriptor& aFsDesc)
659 //-- 1. get file system name
660 nRes = aFs.FileSystemName(aFsDesc.iFsName, aDrive);
667 //-- 2. find out if the drive sync/async
668 TPckgBuf<TBool> drvSyncBuf;
669 nRes = aFs.QueryVolumeInfoExt(aDrive, EIsDriveSync, drvSyncBuf);
671 {//-- pretend that the drive is asynch. in the case of file system being corrupted. this is 99.9% true
672 aFsDesc.iDriveSynch = EFalse;
676 aFsDesc.iDriveSynch = drvSyncBuf();
679 //-- 3. find out primary extension name if it is present; we will need to add it again when mounting the FS
680 //-- other extensions (non-primary) are not supported yet
681 nRes = aFs.ExtensionName(aFsDesc.iPExtName, aDrive, 0);
684 aFsDesc.iPExtName.SetLength(0);
687 //-- 3.1 check if the drive has non-primary extensions, fail in this case
689 nRes = aFs.ExtensionName(extName, aDrive, 1);
692 DoPrintf(_L("~ F32_Test_Utils::GetFileSystemDescriptor: Non-primary extensions are not supported!\n"));
693 return KErrNotSupported;
700 //-------------------------------------------------------------------------------------------------------------------
702 Mount the file system by the information provided in the FS descriptor
704 @param aFs reference to the FS session
705 @param aDrive drive number
706 @param aFsDesc file system descriptor containing all necessary information to mount the FS.
708 @return standard error code
710 TInt F32_Test_Utils::MountFileSystem(RFs &aFs, TInt aDrive, const TFSDescriptor& aFsDesc)
712 DoPrintf(_L("~ F32_Test_Utils::MountFileSystem() drive:%d Name:%S\n"), aDrive, &aFsDesc.iFsName);
715 if(aFsDesc.iFsName.Length() <=0 )
722 //-- mount File system
723 const TBool bPrimaryExt = (aFsDesc.iPExtName.Length() > 0);
726 {//-- we need to mount FS with the primary extension
727 nRes = aFs.AddExtension(aFsDesc.iPExtName);
728 if(nRes != KErrNone && nRes != KErrAlreadyExists)
734 nRes = aFs.MountFileSystem(aFsDesc.iFsName, aFsDesc.iPExtName, aDrive, aFsDesc.iDriveSynch);
737 {//-- the FS did not have primary extension
738 nRes = aFs.MountFileSystem(aFsDesc.iFsName, aDrive, aFsDesc.iDriveSynch);
745 //-------------------------------------------------------------------------------------------------------------------
747 Format volume, regardless the file system installed.
749 @param aFs reference to the FS session
750 @param aDrive drive number
751 @param aQuickFormat if True, a quick format will be performed. otherwise - full
752 @return system-wide error codes.
754 TInt F32_Test_Utils::FormatDrive(RFs &aFs, TInt aDrive, TBool aQuickFormat)
756 TPtrC fmtTypeName = (aQuickFormat ? _L("Quick") : _L("Full"));
757 DoPrintf(_L("~ F32_Test_Utils::FormatDrive() drv:%d, type:%S\n"),aDrive, &fmtTypeName);
759 ASSERT(aDrive >= EDriveA && aDrive <= EDriveZ);
768 fmtMode |= EQuickFormat;
771 // fmtMode |= EForceErase;
774 drvName.Format(_L("%C:"),'A'+aDrive);
776 nRes = format.Open(aFs, drvName, fmtMode, fmtCnt);
784 nRes = format.Next(fmtCnt);
788 if(fmtCnt != prevCnt)
795 //-- formatting has finished
802 DoPrintf(_L("~ F32_Test_Utils::FormatFatDrive() failed! code:%d\n"), nRes);
808 #endif //FAT_UTILS_LEAN_AND_MEAN
811 //-------------------------------------------------------------------------------------------------------------------
813 printing interface. Prints out to the console (if is set) and to the debug interface
814 if pConsole is NULL will print to the debug port only.
816 void F32_Test_Utils::DoPrintf(TRefByValue<const TDesC> aFmt,...)
818 #ifndef FAT_UTILS_LEAN_AND_MEAN
819 if(!bPrintOutEnabled)
820 return; //-- disabled by global flag
821 #endif //FAT_UTILS_LEAN_AND_MEAN
824 VA_START(list, aFmt);
827 buf.FormatList(aFmt, list); //-- ignore overflows
829 #ifndef FAT_UTILS_LEAN_AND_MEAN
832 pConsole->Write(buf);
834 #endif //FAT_UTILS_LEAN_AND_MEAN
836 const TInt bufLen = buf.Length();
837 if(bufLen >0 && buf[bufLen-1] == '\n')
839 buf.Insert(bufLen-1, _L("\r"));
842 RDebug::RawPrint(buf);
845 //-------------------------------------------------------------------------------------------------------------------
847 TBool F32_Test_Utils::IsPowerOf2(TUint32 aVal)
852 return !(aVal & (aVal-1));
856 //-------------------------------------------------------------------------------------------------------------------
857 TUint32 F32_Test_Utils::Log2(TUint32 aVal)
859 __ASSERT_COMPILE(sizeof(TUint32) == 4);
864 if(!(aVal >> 16)) {bitPos-=16; aVal<<=16;}
865 if(!(aVal >> 24)) {bitPos-=8; aVal<<=8 ;}
866 if(!(aVal >> 28)) {bitPos-=4; aVal<<=4 ;}
867 if(!(aVal >> 30)) {bitPos-=2; aVal<<=2 ;}
868 if(!(aVal >> 31)) {bitPos-=1;}
874 //-------------------------------------------------------------------------------------------------------------------
876 //###################################################################################################################
877 //# TMD5 class implementation
878 //###################################################################################################################
881 #define T_MASK ((TUint32)~0)
882 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
883 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
884 #define T3 0x242070db
885 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
886 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
887 #define T6 0x4787c62a
888 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
889 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
890 #define T9 0x698098d8
891 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
892 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
893 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
894 #define T13 0x6b901122
895 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
896 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
897 #define T16 0x49b40821
898 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
899 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
900 #define T19 0x265e5a51
901 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
902 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
903 #define T22 0x02441453
904 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
905 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
906 #define T25 0x21e1cde6
907 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
908 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
909 #define T28 0x455a14ed
910 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
911 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
912 #define T31 0x676f02d9
913 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
914 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
915 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
916 #define T35 0x6d9d6122
917 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
918 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
919 #define T38 0x4bdecfa9
920 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
921 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
922 #define T41 0x289b7ec6
923 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
924 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
925 #define T44 0x04881d05
926 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
927 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
928 #define T47 0x1fa27cf8
929 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
930 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
931 #define T50 0x432aff97
932 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
933 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
934 #define T53 0x655b59c3
935 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
936 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
937 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
938 #define T57 0x6fa87e4f
939 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
940 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
941 #define T60 0x4e0811a1
942 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
943 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
944 #define T63 0x2ad7d2bb
945 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
953 //-------------------------------------------------------------------------------------------------------------------
955 void TMD5::Md5_process(const TUint8 *data /*[64]*/)
958 a = iState.abcd[0], b = iState.abcd[1],
959 c = iState.abcd[2], d = iState.abcd[3];
965 static const TInt w = 1;
966 if (*((const TUint8 *)&w))
968 if (!((data - (const TUint8 *)0) & 3)) {
969 X = (const TUint32 *)data;
971 memcpy(xbuf, data, 64);
977 const TUint8 *xp = data;
980 X = xbuf; /* (dynamic only) */
981 for (i = 0; i < 16; ++i, xp += 4)
982 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
986 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
988 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
989 #define SET(a, b, c, d, k, s, Ti)\
990 t = a + F(b,c,d) + X[k] + Ti;\
991 a = ROTATE_LEFT(t, s) + b
992 SET(a, b, c, d, 0, 7, T1);
993 SET(d, a, b, c, 1, 12, T2);
994 SET(c, d, a, b, 2, 17, T3);
995 SET(b, c, d, a, 3, 22, T4);
996 SET(a, b, c, d, 4, 7, T5);
997 SET(d, a, b, c, 5, 12, T6);
998 SET(c, d, a, b, 6, 17, T7);
999 SET(b, c, d, a, 7, 22, T8);
1000 SET(a, b, c, d, 8, 7, T9);
1001 SET(d, a, b, c, 9, 12, T10);
1002 SET(c, d, a, b, 10, 17, T11);
1003 SET(b, c, d, a, 11, 22, T12);
1004 SET(a, b, c, d, 12, 7, T13);
1005 SET(d, a, b, c, 13, 12, T14);
1006 SET(c, d, a, b, 14, 17, T15);
1007 SET(b, c, d, a, 15, 22, T16);
1010 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
1011 #define SET(a, b, c, d, k, s, Ti)\
1012 t = a + G(b,c,d) + X[k] + Ti;\
1013 a = ROTATE_LEFT(t, s) + b
1014 SET(a, b, c, d, 1, 5, T17);
1015 SET(d, a, b, c, 6, 9, T18);
1016 SET(c, d, a, b, 11, 14, T19);
1017 SET(b, c, d, a, 0, 20, T20);
1018 SET(a, b, c, d, 5, 5, T21);
1019 SET(d, a, b, c, 10, 9, T22);
1020 SET(c, d, a, b, 15, 14, T23);
1021 SET(b, c, d, a, 4, 20, T24);
1022 SET(a, b, c, d, 9, 5, T25);
1023 SET(d, a, b, c, 14, 9, T26);
1024 SET(c, d, a, b, 3, 14, T27);
1025 SET(b, c, d, a, 8, 20, T28);
1026 SET(a, b, c, d, 13, 5, T29);
1027 SET(d, a, b, c, 2, 9, T30);
1028 SET(c, d, a, b, 7, 14, T31);
1029 SET(b, c, d, a, 12, 20, T32);
1032 #define H(x, y, z) ((x) ^ (y) ^ (z))
1033 #define SET(a, b, c, d, k, s, Ti)\
1034 t = a + H(b,c,d) + X[k] + Ti;\
1035 a = ROTATE_LEFT(t, s) + b
1036 SET(a, b, c, d, 5, 4, T33);
1037 SET(d, a, b, c, 8, 11, T34);
1038 SET(c, d, a, b, 11, 16, T35);
1039 SET(b, c, d, a, 14, 23, T36);
1040 SET(a, b, c, d, 1, 4, T37);
1041 SET(d, a, b, c, 4, 11, T38);
1042 SET(c, d, a, b, 7, 16, T39);
1043 SET(b, c, d, a, 10, 23, T40);
1044 SET(a, b, c, d, 13, 4, T41);
1045 SET(d, a, b, c, 0, 11, T42);
1046 SET(c, d, a, b, 3, 16, T43);
1047 SET(b, c, d, a, 6, 23, T44);
1048 SET(a, b, c, d, 9, 4, T45);
1049 SET(d, a, b, c, 12, 11, T46);
1050 SET(c, d, a, b, 15, 16, T47);
1051 SET(b, c, d, a, 2, 23, T48);
1054 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
1055 #define SET(a, b, c, d, k, s, Ti)\
1056 t = a + I(b,c,d) + X[k] + Ti;\
1057 a = ROTATE_LEFT(t, s) + b
1058 SET(a, b, c, d, 0, 6, T49);
1059 SET(d, a, b, c, 7, 10, T50);
1060 SET(c, d, a, b, 14, 15, T51);
1061 SET(b, c, d, a, 5, 21, T52);
1062 SET(a, b, c, d, 12, 6, T53);
1063 SET(d, a, b, c, 3, 10, T54);
1064 SET(c, d, a, b, 10, 15, T55);
1065 SET(b, c, d, a, 1, 21, T56);
1066 SET(a, b, c, d, 8, 6, T57);
1067 SET(d, a, b, c, 15, 10, T58);
1068 SET(c, d, a, b, 6, 15, T59);
1069 SET(b, c, d, a, 13, 21, T60);
1070 SET(a, b, c, d, 4, 6, T61);
1071 SET(d, a, b, c, 11, 10, T62);
1072 SET(c, d, a, b, 2, 15, T63);
1073 SET(b, c, d, a, 9, 21, T64);
1076 iState.abcd[0] += a;
1077 iState.abcd[1] += b;
1078 iState.abcd[2] += c;
1079 iState.abcd[3] += d;
1083 //-------------------------------------------------------------------------------------------------------------------
1084 void TMD5::Md5_append(const TUint8 *data, TInt nbytes)
1086 const TUint8 *p = data;
1090 TInt offset = (iState.count[0] >> 3) & 63;
1091 TUint32 nbits = (TUint32)(nbytes << 3);
1096 iState.count[1] += nbytes >> 29;
1097 iState.count[0] += nbits;
1098 if (iState.count[0] < nbits)
1103 TInt copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
1105 memcpy(iState.buf + offset, p, copy);
1106 if (offset + copy < 64)
1110 Md5_process(iState.buf);
1113 for (; left >= 64; p += 64, left -= 64)
1117 memcpy(iState.buf, p, left);
1122 void TMD5::Md5_finish()
1124 static const TUint8 pad[64] = {
1125 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1133 for (i = 0; i < 8; ++i)
1134 data[i] = (TUint8)(iState.count[i >> 2] >> ((i & 3) << 3));
1135 Md5_append(pad, ((55 - (iState.count[0] >> 3)) & 63) + 1);
1136 Md5_append(data, 8);
1137 for (i = 0; i < 16; ++i)
1138 iDigest[i] = (TUint8)(iState.abcd[i >> 2] >> ((i & 3) << 3));
1142 //-------------------------------------------------------------------------------------------------------------------
1144 /** reset MD5 to initial state */
1147 iState.count[0] = iState.count[1] = 0;
1148 iState.abcd[0] = 0x67452301;
1149 iState.abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
1150 iState.abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
1151 iState.abcd[3] = 0x10325476;
1156 Update MD5 with some data
1157 @param aMessage descriptor with data
1159 void TMD5::Update(const TDesC8& aMessage)
1161 Md5_append((const TUint8*)aMessage.Ptr(), aMessage.Length());
1165 Finalise MD5 calculation
1166 @param aMessage descriptor with data
1167 @return pointer to 16-byte array with MD5 hash
1169 TPtrC8 TMD5::Final(const TDesC8& aMessage)
1173 return TPtrC8(iDigest, HashSize);
1178 Finalise MD5 calculation
1179 @return pointer to 16-byte array with MD5 hash
1181 TPtrC8 TMD5::Final()
1184 return TPtrC8(iDigest, HashSize);