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