sl@0: // Copyright (c) 2008-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 "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: //
sl@0: 
sl@0: #include "crccheck.h"
sl@0: 
sl@0: const TInt TDBMS_CRCChecks::SetSessionPath(const TDesC& aPath)
sl@0: 	{
sl@0: 	return ifs.SetSessionPath(aPath);
sl@0: 	}
sl@0: 
sl@0: TInt TDBMS_CRCChecks::FileCrcL(const RFile& aFile, TUint32 &asum)
sl@0: 	{
sl@0: 	const TInt KFileCrcBufSize = 1024;
sl@0: 
sl@0: 	TInt err;
sl@0: 	TInt pos = 0;
sl@0: 	// Seek to the beginning of the file.
sl@0: 	if( (err = aFile.Seek(ESeekStart, pos)) != KErrNone)
sl@0: 		return err;
sl@0: 
sl@0: 	RBuf8 buffer;
sl@0: 	if((err = buffer.Create(KFileCrcBufSize)) != KErrNone)
sl@0: 		return err;
sl@0: 	CleanupClosePushL(buffer);
sl@0: 	asum=0;
sl@0: 	for(;;)
sl@0: 		{
sl@0: 		err = aFile.Read(buffer, KFileCrcBufSize);
sl@0: 		if(err) break;
sl@0: 		TInt len = buffer.Length();
sl@0: 		if(len == 0) break;
sl@0: 		Mem::Crc32(asum, (TAny*) buffer.Ptr(), len);
sl@0: 		}
sl@0: 	CleanupStack::PopAndDestroy(1, &buffer);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: const TInt TDBMS_CRCChecks::GenerateCrcL(const TPtrC aFile)
sl@0: 	{
sl@0: 	RFile file;
sl@0: 	TInt err = file.Open(ifs, aFile, EFileRead);
sl@0: 	RDebug::Print(_L("==================== File open=%S, err=%d\n"), &aFile, err);
sl@0: 	if(err != KErrNone) 
sl@0: 		return err;
sl@0: 	CleanupClosePushL(file);
sl@0: 
sl@0: 	TestCheckInfo tcinf;
sl@0: 	err = file.Size(tcinf.filesz);
sl@0: 	if(err)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(1);
sl@0: 		return err;
sl@0: 		}
sl@0: 	err = FileCrcL(file, tcinf.crc);
sl@0: 	if(err)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(1);
sl@0: 		return err;
sl@0: 		}
sl@0:     err = iarray.Append(tcinf);
sl@0: 	CleanupStack::PopAndDestroy(1);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: const TInt TDBMS_CRCChecks::RecordCount()
sl@0: 	{
sl@0: 	return iarray.Count();
sl@0: 	}
sl@0: 
sl@0: const TestCheckInfo TDBMS_CRCChecks::operator[](const TInt aidx)
sl@0: 	{
sl@0: 	return iarray[aidx];
sl@0: 	}
sl@0: 
sl@0: const TInt TDBMS_CRCChecks::DumpCrcRecordsL(const TDesC &alog)
sl@0: 	{
sl@0: 	RFile logfile;
sl@0: 	TInt err = logfile.Replace(ifs, alog, EFileWrite);
sl@0: 	RDebug::Print(_L("==================== File replace=%S, err=%d\n"), &alog, err);
sl@0: 	if(err != KErrNone)
sl@0: 		return err;
sl@0: 	CleanupClosePushL(logfile);
sl@0: 	TBuf8<0x100> output;
sl@0: 
sl@0: 	for(TInt i=0 ; i<RecordCount() ; i++)
sl@0: 		{
sl@0: 		output.SetLength(0);
sl@0: 		TestCheckInfo tc = iarray[i];
sl@0: 		output.AppendFormat(_L8("%d %d 0x%08x\n"), i+1, tc.filesz, tc.crc );
sl@0: 		err = logfile.Write(output);
sl@0: 		if(err) break;
sl@0: 		}
sl@0: 	CleanupStack::PopAndDestroy(1);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: const TInt TDBMS_CRCChecks::ValidateCrcRecordsL(const TDesC &alog)
sl@0: 	{
sl@0: 	RFile logfile;
sl@0: 	TInt err = logfile.Open(ifs, alog, EFileRead);
sl@0: 	RDebug::Print(_L("==================== File open=%S, err=%d\n"), &alog, err);
sl@0: 	if(err != KErrNone)
sl@0: 		return err;
sl@0: 	CleanupClosePushL(logfile);
sl@0:    	
sl@0: 	TInt logfilesz;
sl@0: 	if((err = logfile.Size(logfilesz)) != KErrNone)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(1);
sl@0: 		return err;
sl@0: 		}
sl@0: 
sl@0: 	RBuf8 input;
sl@0: 	if((err = input.Create(logfilesz)) != KErrNone)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(1);
sl@0: 		return err;
sl@0: 		}
sl@0: 	CleanupClosePushL(input);
sl@0: 	// Read the entire file.
sl@0: 	err = logfile.Read(input);
sl@0: 	if(err != KErrNone)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(2);
sl@0: 		return err;
sl@0: 		}
sl@0: 	TInt nread = input.Length();
sl@0: 	if(nread != logfilesz)
sl@0: 		{
sl@0: 		CleanupStack::PopAndDestroy(2);
sl@0: 		User::Leave(KErrCorrupt);  // wrong error.
sl@0: 		}
sl@0: 
sl@0: 	TPtrC8 slice;
sl@0: 	slice.Set(input);
sl@0: 	TInt offset=0;
sl@0: 	TBuf8<0x100> expected;
sl@0: 	TInt i; // we check this after the loop...
sl@0: 	for(i=0; ; i++)
sl@0: 		{
sl@0: 		// Find the next carriage return in the file. 'slice' represents
sl@0: 		// the next bit of the file before the next carriage return.
sl@0: 		// Will this break on Symbian? That has '\r\n'...
sl@0: 		TInt nextcr = slice.Locate(TChar('\n'));
sl@0: 		// If no carriage return is found we must have reached the end of
sl@0: 		// the file.
sl@0: 		if(nextcr == KErrNotFound)
sl@0: 		  	break;
sl@0: 		// 'got' is the current line from the file, including the carriage
sl@0: 		// return.
sl@0: 		TPtrC8 got = slice.Left(nextcr+1);
sl@0: 
sl@0: 		// Before we construct the string this object expects to see,
sl@0: 		// check we're not out of array..
sl@0: 		// The number of lines in the file we checking should match what
sl@0: 		// we have in our internal array.
sl@0: 		if(i >= iarray.Count())
sl@0: 			{
sl@0: 			err = ECrcCheckMoreRecords;
sl@0: 			break;
sl@0: 			}
sl@0: 
sl@0: 		// Construct a string from our internal data that is expected to be
sl@0: 		// the same as the data read in from the crc file.
sl@0: 		expected.SetLength(0);
sl@0: 		TestCheckInfo tc = iarray[i];
sl@0: 		expected.AppendFormat(_L8("%d %d 0x%08x\n"), i+1, tc.filesz, tc.crc );
sl@0:         // Compare what we've got to what we expect.
sl@0: 		if(got.Compare(expected) != 0)
sl@0: 			{
sl@0: 			err = ECrcCheckMismatch;
sl@0: 			break;
sl@0: 			}
sl@0: 
sl@0: 		offset += nextcr + 1;
sl@0: 		slice.Set(input.Mid(offset));
sl@0: 		}
sl@0: 	// The number of lines in the file we checking should match what
sl@0: 	// we have in our internal array. Here this indicates that we seem to
sl@0: 	// have more in our array than appear in the file.
sl@0: 	if(!err && (i != iarray.Count()))
sl@0: 		err = ECrcCheckFewerRecords;
sl@0: 	CleanupStack::PopAndDestroy(2);
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: const void TDBMS_CRCChecks::ErrorReportL(const TInt aerr, TPtrC& aerrmsg)
sl@0: 	{
sl@0: 	switch(aerr)
sl@0: 		{
sl@0: 		case KErrNotFound:
sl@0: 				aerrmsg.Set(_L("Failed to open CRC log file.\n"));
sl@0: 				break;
sl@0: 		case KErrNoMemory:
sl@0: 				aerrmsg.Set(_L("Out of memory.\n"));
sl@0: 				break;
sl@0: 		case KErrNone:
sl@0: 		case ECrcCheckOk:
sl@0: 				aerrmsg.Set(_L("CRC check ok.\n"));
sl@0: 				break;
sl@0: 		case ECrcCheckMismatch:
sl@0: 				aerrmsg.Set(_L("CRC mismatch.\n"));
sl@0: 				break;
sl@0: 		case ECrcCheckFewerRecords:
sl@0: 				aerrmsg.Set(_L("Fewer CRCs than in the file!\n"));
sl@0: 				break;
sl@0: 		case ECrcCheckMoreRecords:
sl@0: 				aerrmsg.Set(_L("More CRCs in the file than I have!\n"));
sl@0: 				break;
sl@0: 		default:
sl@0: 				aerrmsg.Set(_L("Broken!\n")); // PANIC?
sl@0: 				break;
sl@0: 		}
sl@0: 	return;
sl@0: 	}
sl@0: 
sl@0: #ifdef CRC_TEST
sl@0: int E32Main(void)
sl@0: 	{
sl@0: 	CTrapCleanup *cleanup = CTrapCleanup::New();
sl@0: 	__ASSERT_ALWAYS(cleanup != NULL, User::Invariant());
sl@0: 
sl@0: 	TDBMS_CRCChecks mycrc;
sl@0: 	TInt err;
sl@0:    	TRAPD(lc, err = mycrc.GenerateCrcL(_L("crcchecks.mmp")));
sl@0:    	TRAP(lc, err = mycrc.GenerateCrcL(_L("bld.inf")));
sl@0: 
sl@0: 	TRAP(lc, err = mycrc.DumpCrcRecordsL(_L("wibble")));
sl@0:    	TRAP(lc, err = mycrc.GenerateCrcL(_L("t_alter.mmp")));
sl@0: 	TRAP(lc, err = mycrc.ValidateCrcRecordsL(_L("wibble")));
sl@0: 	switch(err)
sl@0: 		{
sl@0: 		case TDBMS_CRCChecks::ECrcCheckMismatch:
sl@0: 				printf("Got CRC mismatch\n");
sl@0: 				break;
sl@0: 		case TDBMS_CRCChecks::ECrcCheckFewerRecords:
sl@0: 				printf("I have more CRCs than in the file!\n");
sl@0: 				break;
sl@0: 		case TDBMS_CRCChecks::ECrcCheckMoreRecords:
sl@0: 				printf("More CRCs in the file than I have!\n");
sl@0: 				break;
sl@0: 		default:
sl@0: 				printf("Broken!\n");
sl@0: 				break;
sl@0: 		}
sl@0: 	printf("Leavecode = %d, err = %d\n", lc, err );
sl@0: 
sl@0: 	delete cleanup;
sl@0: 	}
sl@0: #endif