os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_prel.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\sfile\sf_prel.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "sf_std.h"
sl@0
    19
#include "u32std.h"
sl@0
    20
#include <e32hal.h>
sl@0
    21
#include "sf_cache_man.h"
sl@0
    22
sl@0
    23
_LIT(KLitInitCompleteThread,"InitCompleteThread");
sl@0
    24
sl@0
    25
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
    26
_LIT(KCorruptFileNamesList,"CorruptFileNames.lst");
sl@0
    27
_LIT(KSysData,"\\sys\\data\\");
sl@0
    28
_LIT(KSystemData,"\\system\\data\\");
sl@0
    29
/**
sl@0
    30
ASCII text file reader constructor
sl@0
    31
This code is more or less lifted directly from estart.cpp
sl@0
    32
*/
sl@0
    33
TText8FileReader::TText8FileReader()
sl@0
    34
	{
sl@0
    35
sl@0
    36
	iBufPos=-1;
sl@0
    37
	iFileDataBuf=NULL;
sl@0
    38
	iFileSize=0;	
sl@0
    39
	}
sl@0
    40
sl@0
    41
/**
sl@0
    42
ASCII text file reader destructor
sl@0
    43
*/	
sl@0
    44
TText8FileReader::~TText8FileReader()
sl@0
    45
	{
sl@0
    46
	
sl@0
    47
	delete[] iFileDataBuf;
sl@0
    48
	}	
sl@0
    49
sl@0
    50
/**	
sl@0
    51
Supply an ASCII text file for the file reader. 
sl@0
    52
This function reads the entire contents of this file into a buffer, converting to
sl@0
    53
unicode / folding each character. Subsequent parsing of the file data is all done from this
sl@0
    54
buffer.
sl@0
    55
@param aFile The file to be read. Must already be opened for read access in EFileStreamText mode.  
sl@0
    56
@return	KErrNone if no error.
sl@0
    57
*/
sl@0
    58
TInt TText8FileReader::Set(RFile& aFile)
sl@0
    59
	{
sl@0
    60
	
sl@0
    61
	iFile=aFile;
sl@0
    62
	iBuf.Zero();
sl@0
    63
	iBufPos=0;
sl@0
    64
	
sl@0
    65
	// Read the size of the file
sl@0
    66
	TInt r=iFile.Size(iFileSize);
sl@0
    67
	if (r!=KErrNone || !iFileSize)
sl@0
    68
		return(KErrGeneral);
sl@0
    69
	
sl@0
    70
	// Allocate a buffer to read in the 
sl@0
    71
	iFileDataBuf=new TText[iFileSize+1];	// +1 in case need to NULL terminate the end of the last string
sl@0
    72
	if (iFileDataBuf==NULL)
sl@0
    73
		return(KErrNoMemory);
sl@0
    74
sl@0
    75
	// Read the entire contents of the file into the buffer
sl@0
    76
	TPtr fdata(NULL,0);	
sl@0
    77
	TInt pos=0;
sl@0
    78
	r=iFile.Seek(ESeekStart,pos);
sl@0
    79
	while (pos<iFileSize)
sl@0
    80
		{
sl@0
    81
		if ((r=iFile.Read(iBuf))!=KErrNone)
sl@0
    82
			return(r);
sl@0
    83
		fdata.Set((iFileDataBuf+pos),0,iBuf.Length());	
sl@0
    84
		fdata.Copy(iBuf);
sl@0
    85
		fdata.Fold();
sl@0
    86
		pos+=iBuf.Length();	
sl@0
    87
		}
sl@0
    88
	return(KErrNone);	
sl@0
    89
	}
sl@0
    90
	
sl@0
    91
/**
sl@0
    92
Return the next record from the text file.
sl@0
    93
@param aPtr A TPtr which is setup with the address and length of the next record, referencing
sl@0
    94
the data in the reader's buffer.
sl@0
    95
@return	KErrNone if a record is successfully loaded into the buffer, KErrEof if the end of the
sl@0
    96
file is encountered, KErrGeneral if a file hasn't been set.
sl@0
    97
*/
sl@0
    98
TInt TText8FileReader::Read(TPtr& aPtr)
sl@0
    99
	{
sl@0
   100
	
sl@0
   101
	// Check that Set() has been called.
sl@0
   102
	if (iBufPos<0)
sl@0
   103
		return(KErrGeneral);
sl@0
   104
		
sl@0
   105
	// Check if we have run into the end of the file	
sl@0
   106
	TInt bufRemainder=(iFileSize-iBufPos);
sl@0
   107
	if (!bufRemainder)
sl@0
   108
		return(KErrEof);
sl@0
   109
		
sl@0
   110
	// Setup the descriptor passed with the next record - don't include the record terminator
sl@0
   111
	// The line terminators are CR + LF for DOS
sl@0
   112
	// whereas only LF for Unix line endings
sl@0
   113
	aPtr.Set((iFileDataBuf+iBufPos),bufRemainder,bufRemainder);
sl@0
   114
	TInt len=aPtr.Locate('\n');
sl@0
   115
	if (len != KErrNotFound)
sl@0
   116
		{
sl@0
   117
		iBufPos += len;
sl@0
   118
	    // Check for DOS line ending to support both DOS and Unix formats
sl@0
   119
	    if ((len != 0) && (iFileDataBuf[iBufPos-1] == '\r'))
sl@0
   120
			{
sl@0
   121
			len--;
sl@0
   122
			}
sl@0
   123
		aPtr.SetLength(len);
sl@0
   124
		}
sl@0
   125
	else
sl@0
   126
		iBufPos=iFileSize;
sl@0
   127
	
sl@0
   128
	// Point iBufPos to the next non-empty line
sl@0
   129
	while (iBufPos<iFileSize && (iFileDataBuf[iBufPos]=='\n' || iFileDataBuf[iBufPos]=='\r'))
sl@0
   130
		iBufPos++;
sl@0
   131
	return(KErrNone);
sl@0
   132
	}
sl@0
   133
sl@0
   134
/**
sl@0
   135
Parse a record and split it into filename, error code & use once flag
sl@0
   136
@param aLine, this a a record from read from the file
sl@0
   137
@param aName, this is the parsed filename component of the record
sl@0
   138
@param aReturnCode, the error code that will be returned when an attempt is made to open the file
sl@0
   139
@param aUseOnce, flag which states whether the error should persist over more than one open attempt
sl@0
   140
@return error code, if the record is malformed return KErrCorrupt (ironic, what?) else KErrNone
sl@0
   141
*/
sl@0
   142
TInt ParseCorruptNamesRecord(TPtr aLine, TPtr& aName, TInt& aReturnCode, TBool&  aUseOnce)
sl@0
   143
	{
sl@0
   144
	aName.Set(NULL,0,0);
sl@0
   145
	// Remove leading spaces
sl@0
   146
	aLine.TrimLeft();
sl@0
   147
	TPtr remainderPtr(aLine);
sl@0
   148
sl@0
   149
	// collect pathname
sl@0
   150
	TInt lenFileName=remainderPtr.Locate(',');
sl@0
   151
	if(lenFileName<1)
sl@0
   152
		return KErrCorrupt;
sl@0
   153
	TPtr pathNamePtr(remainderPtr.LeftTPtr(lenFileName));
sl@0
   154
	// Remove trailing spaces
sl@0
   155
	pathNamePtr.TrimRight();
sl@0
   156
	// Parse the pathname to see if it could be valid, do not allow wild cards
sl@0
   157
	TParse fileParse;
sl@0
   158
	TInt r=fileParse.SetNoWild(pathNamePtr,NULL,NULL);
sl@0
   159
	if(r!=KErrNone)
sl@0
   160
		return KErrCorrupt;
sl@0
   161
sl@0
   162
	// move over delimiter to collect the user supplied return code
sl@0
   163
	// see first if sufficient length in the record
sl@0
   164
	TInt lenRemainder=remainderPtr.Length();
sl@0
   165
	if(lenRemainder<lenFileName+2)
sl@0
   166
		return KErrCorrupt;
sl@0
   167
sl@0
   168
	remainderPtr.Set(remainderPtr.MidTPtr(lenFileName+1));
sl@0
   169
	remainderPtr.TrimLeft();
sl@0
   170
	TInt lenReturnCode=remainderPtr.Locate(',');
sl@0
   171
	if(lenReturnCode<1)
sl@0
   172
		return KErrCorrupt;
sl@0
   173
sl@0
   174
	TPtr returnCodePtr(remainderPtr.LeftTPtr(lenReturnCode));
sl@0
   175
	TLex lexLine(returnCodePtr);
sl@0
   176
	TInt returnCode;
sl@0
   177
	if(lexLine.Val(returnCode)!=KErrNone)
sl@0
   178
		return KErrCorrupt;
sl@0
   179
sl@0
   180
	lenRemainder=remainderPtr.Length();
sl@0
   181
	if(lenRemainder<lenReturnCode+2)
sl@0
   182
		return KErrCorrupt;
sl@0
   183
sl@0
   184
	// collect the useOnce flag value
sl@0
   185
	remainderPtr.Set(remainderPtr.MidTPtr(lenReturnCode+1));
sl@0
   186
	remainderPtr.Trim();
sl@0
   187
	TBool useOnce;
sl@0
   188
	// This must either be "EVERY" or "ONCE"
sl@0
   189
	if (remainderPtr.MatchF(_L("EVERY"))!=KErrNotFound)
sl@0
   190
		useOnce=EFalse;
sl@0
   191
	else if(remainderPtr.MatchF(_L("ONCE"))!=KErrNotFound)
sl@0
   192
		useOnce=ETrue;
sl@0
   193
	else
sl@0
   194
		return KErrCorrupt;
sl@0
   195
sl@0
   196
	// Everything has worked out, so set up output args
sl@0
   197
sl@0
   198
	aName.Set(pathNamePtr);
sl@0
   199
	aReturnCode=returnCode;
sl@0
   200
	aUseOnce=useOnce;
sl@0
   201
	return KErrNone;
sl@0
   202
	}
sl@0
   203
sl@0
   204
/**
sl@0
   205
Open c:\CorruptFileNames.lst
sl@0
   206
File contains a set of text records
sl@0
   207
Each record has comma delimited fields and has the form:
sl@0
   208
 <filename>, <errorCode>, <[ONCE,EVERY]>
sl@0
   209
e.g.
sl@0
   210
c:\system\bin\bt.lst, -6,EVERY
sl@0
   211
the filename should be fully qualified,
sl@0
   212
errorCode should be a literal not a symbol
sl@0
   213
EVERY means that every attempt to open the file will be failed
sl@0
   214
ONCE means that only the first access to the file will be failed
sl@0
   215
*/
sl@0
   216
sl@0
   217
TInt FindHitListFile(RFs aFs)
sl@0
   218
	{
sl@0
   219
	TFindFile finder(aFs);
sl@0
   220
	TInt r=finder.FindByDir(KCorruptFileNamesList,_L("\\"));
sl@0
   221
	if(r!=KErrNone)
sl@0
   222
		{
sl@0
   223
		r=finder.FindByDir(KCorruptFileNamesList,KSysData);
sl@0
   224
		}
sl@0
   225
sl@0
   226
	if(r!=KErrNone)
sl@0
   227
		{
sl@0
   228
		r=finder.FindByDir(KCorruptFileNamesList,KSystemData);
sl@0
   229
		}
sl@0
   230
sl@0
   231
	if(r==KErrNone)
sl@0
   232
		{  // This is stored as a global because the name can be retrieved by a user api
sl@0
   233
		gCorruptFileNamesListFile=finder.File().Alloc();
sl@0
   234
		if(gCorruptFileNamesListFile==NULL)
sl@0
   235
			{
sl@0
   236
			r=KErrNoMemory;
sl@0
   237
			}
sl@0
   238
		}
sl@0
   239
	return r;
sl@0
   240
	}
sl@0
   241
sl@0
   242
void CreateCorruptFileNamesList()
sl@0
   243
	{
sl@0
   244
	RFs fs;
sl@0
   245
	fs.Connect();
sl@0
   246
	TInt r=FindHitListFile(fs);
sl@0
   247
	if(r!=KErrNone)
sl@0
   248
		return;
sl@0
   249
	RFile f;
sl@0
   250
	r=f.Open(fs,*gCorruptFileNamesListFile,EFileShareExclusive|EFileStreamText|EFileRead);
sl@0
   251
	if(r!=KErrNone)
sl@0
   252
		{
sl@0
   253
		return;
sl@0
   254
		}
sl@0
   255
	// Create a corrupt filenames file reader and pass it the file object. This will also result in the copying of the contents of
sl@0
   256
	// the file into reader's buffer. Filename information read from the file will include pointers to text strings in
sl@0
   257
	// this buffer and so the reader object must not be deleted until processing is complete.
sl@0
   258
	__PRINT1(_L("@@@@ Using Corrupt names file %S"),gCorruptFileNamesListFile);
sl@0
   259
sl@0
   260
	TText8FileReader* namesFile=new TText8FileReader;	
sl@0
   261
	if (!namesFile)
sl@0
   262
		{
sl@0
   263
		f.Close();
sl@0
   264
		return;
sl@0
   265
		}
sl@0
   266
sl@0
   267
	r=namesFile->Set(f);
sl@0
   268
	f.Close();
sl@0
   269
	fs.Close();
sl@0
   270
	if(r==KErrNone)
sl@0
   271
		{
sl@0
   272
		// Parse each drive mapping record in turn, saving the information in an array of mapping structures - one for
sl@0
   273
		// each valid record.
sl@0
   274
		TPtr linePtr(NULL,0);
sl@0
   275
		while ((r=namesFile->Read(linePtr))==KErrNone)
sl@0
   276
			{		
sl@0
   277
			TInt returnCode;
sl@0
   278
			TBool useOnce;
sl@0
   279
			TPtr namePtr(NULL,0);
sl@0
   280
			if (ParseCorruptNamesRecord(linePtr,namePtr,returnCode,useOnce)==KErrNone)
sl@0
   281
				{
sl@0
   282
				// Valid corrupt filename record found
sl@0
   283
				TCorruptNameRec* newRec=new TCorruptNameRec;
sl@0
   284
				if(!newRec)
sl@0
   285
					{
sl@0
   286
					break;
sl@0
   287
					}
sl@0
   288
				if(newRec->Construct(&namePtr,returnCode,useOnce,gCorruptFileNameList)!=KErrNone)
sl@0
   289
					{
sl@0
   290
					delete newRec;
sl@0
   291
					newRec=NULL;
sl@0
   292
					break;
sl@0
   293
					}
sl@0
   294
	
sl@0
   295
				gCorruptFileNameList=newRec;
sl@0
   296
				}
sl@0
   297
			else
sl@0
   298
				{
sl@0
   299
				__PRINT1(_L("@@@@@ Bad Parse corrupt file name record %S\n"),&linePtr);
sl@0
   300
				}
sl@0
   301
			}
sl@0
   302
		}
sl@0
   303
sl@0
   304
	delete namesFile;
sl@0
   305
	}
sl@0
   306
#endif
sl@0
   307
sl@0
   308
TInt InitCompleteThread(TAny* aPtr)
sl@0
   309
	{
sl@0
   310
	__PRINT(KLitInitCompleteThread);
sl@0
   311
	RMessagePtr2 message=*(RMessagePtr2*)aPtr;
sl@0
   312
	RThread::Rendezvous(0);
sl@0
   313
sl@0
   314
sl@0
   315
	//
sl@0
   316
#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
sl@0
   317
	CreateCorruptFileNamesList();
sl@0
   318
#endif
sl@0
   319
sl@0
   320
	TInt r = KErrNone;
sl@0
   321
	message.Complete(r);
sl@0
   322
	return(KErrNone);
sl@0
   323
	}
sl@0
   324
sl@0
   325
sl@0
   326
TInt TFsStartupInitComplete::DoRequestL(CFsRequest *aRequest)
sl@0
   327
//
sl@0
   328
// do further initialisation once necessary startup init complete outside file server
sl@0
   329
//
sl@0
   330
	{
sl@0
   331
	if(StartupInitCompleted)
sl@0
   332
		return(KErrAlreadyExists);
sl@0
   333
sl@0
   334
sl@0
   335
	StartupInitCompleted=ETrue;
sl@0
   336
	RMessagePtr2 msg=aRequest->Message();
sl@0
   337
	RThread thread;
sl@0
   338
	TInt r=thread.Create(KLitInitCompleteThread,InitCompleteThread,KDefaultStackSize,NULL,&msg);
sl@0
   339
	if (KErrNone == r)
sl@0
   340
		{
sl@0
   341
		TRequestStatus s;
sl@0
   342
		thread.Rendezvous(s);
sl@0
   343
		if (s==KRequestPending)
sl@0
   344
			thread.Resume();
sl@0
   345
		else
sl@0
   346
			thread.Kill(0);
sl@0
   347
		thread.Close();
sl@0
   348
		User::WaitForRequest(s);
sl@0
   349
		r = s.Int();
sl@0
   350
		}
sl@0
   351
	return(KErrNone);
sl@0
   352
	}
sl@0
   353
sl@0
   354
TInt TFsStartupInitComplete::Initialise(CFsRequest* /*aRequest*/)
sl@0
   355
//
sl@0
   356
//
sl@0
   357
//
sl@0
   358
	{
sl@0
   359
	return KErrNone;
sl@0
   360
	}