userlibandfileserver/fileserver/sfile/sf_prel.cpp
changeset 0 a41df078684a
child 176 af6ec97d9189
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}