|
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 } |