|
1 // Copyright (c) 2005-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 // f32test\ext\fat_ext.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 //! @SYMTestCaseID FSBASE-CR-JHAS-68YPX7 |
|
19 //! @SYMTestType CT |
|
20 //! @SYMREQ CR JHAS-68YPX7 |
|
21 //! @SYMTestCaseDesc Test facility used by and bad disk handling test |
|
22 //! @SYMTestStatus Implemented |
|
23 //! @SYMTestActions Provided plug-in test extension for FAT |
|
24 //! @SYMTestExpectedResults N/A |
|
25 //! @SYMTestPriority Low |
|
26 //! @SYMAuthor Ying Shi |
|
27 //! @SYMCreationDate 20/05/2005 |
|
28 //! @See EFat and EFat32 components |
|
29 //! @file f32test\ext\fat_ext.cpp |
|
30 |
|
31 #include <e32math.h> |
|
32 #include "t_fatext.h" |
|
33 |
|
34 //-------------------------- CFatTestProxyDrive -------------------------- |
|
35 |
|
36 CFatTestProxyDrive* CFatTestProxyDrive::NewL(CProxyDrive* aProxyDrive, CMountCB* aMount) |
|
37 { |
|
38 __PRINT(_L("CFatTestProxyDrive::NewL")); |
|
39 CFatTestProxyDrive* drive = new(ELeave) CFatTestProxyDrive(aProxyDrive,aMount); |
|
40 return(drive); |
|
41 } |
|
42 |
|
43 CFatTestProxyDrive::CFatTestProxyDrive(CProxyDrive* aProxyDrive, CMountCB* aMount) |
|
44 : CTestProxyDrive(aProxyDrive,aMount) |
|
45 { |
|
46 __PRINT(_L("CFatTestProxyDrive::CFatTestProxyDrive")); |
|
47 InitL(); |
|
48 } |
|
49 |
|
50 TInt CFatTestProxyDrive::Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aMessageHandle,TInt aOffset,TInt aFlags) |
|
51 { |
|
52 // __PRINT(_L("CFatTestProxyDrive::Read")); |
|
53 if (CheckEvent(aPos,aLength)) |
|
54 return KErrCorrupt; |
|
55 |
|
56 return CTestProxyDrive::Read(aPos,aLength,aTrg,aMessageHandle,aOffset,aFlags); |
|
57 } |
|
58 |
|
59 TInt CFatTestProxyDrive::Read(TInt64 aPos,TInt aLength,const TAny* aTrg,TInt aMessageHandle,TInt aOffset) |
|
60 { |
|
61 return Read(aPos,aLength,aTrg,aMessageHandle,aOffset,0); |
|
62 } |
|
63 |
|
64 TInt CFatTestProxyDrive::Read(TInt64 aPos,TInt aLength,TDes8& aTrg) |
|
65 { |
|
66 return Read(aPos,aLength,&aTrg,KLocalMessageHandle,0,0); |
|
67 } |
|
68 |
|
69 TInt CFatTestProxyDrive::Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aMessageHandle,TInt anOffset,TInt aFlags) |
|
70 { |
|
71 // __PRINT(_L("CFatTestProxyDrive::Write")); |
|
72 if (CheckEvent(aPos,aLength)) |
|
73 return KErrCorrupt; |
|
74 |
|
75 return CTestProxyDrive::Write(aPos,aLength,aSrc,aMessageHandle,anOffset,aFlags); |
|
76 } |
|
77 |
|
78 TInt CFatTestProxyDrive::Write(TInt64 aPos,TInt aLength,const TAny* aSrc,TInt aMessageHandle,TInt anOffset) |
|
79 { |
|
80 return Write(aPos,aLength,aSrc,aMessageHandle,anOffset,0); |
|
81 } |
|
82 |
|
83 TInt CFatTestProxyDrive::Write(TInt64 aPos,const TDesC8& aSrc) |
|
84 { |
|
85 return Write(aPos,aSrc.Length(),&aSrc,KLocalMessageHandle,0,0); |
|
86 } |
|
87 |
|
88 TInt CFatTestProxyDrive::Format(TFormatInfo& anInfo) |
|
89 { |
|
90 //__PRINT(_L("CFatTestProxyDrive::Format")); |
|
91 TInt len; |
|
92 TInt64 pos = ((TInt64)anInfo.i512ByteSectorsFormatted) << KDefaultSectorLog2; |
|
93 // base function call in order to get anInfo.iMaxBytesPerFormat |
|
94 // for the first time |
|
95 if (anInfo.iMaxBytesPerFormat == 0) |
|
96 { |
|
97 TInt r = CTestProxyDrive::Format(anInfo); |
|
98 len = anInfo.iMaxBytesPerFormat; |
|
99 if (CheckEvent(pos,len)) |
|
100 { |
|
101 anInfo.i512ByteSectorsFormatted = 0; |
|
102 return KErrCorrupt; |
|
103 } |
|
104 return r; |
|
105 } |
|
106 len = anInfo.iMaxBytesPerFormat; |
|
107 if (CheckEvent(pos,len)) |
|
108 return KErrCorrupt; |
|
109 return CTestProxyDrive::Format(anInfo); |
|
110 } |
|
111 |
|
112 TInt CFatTestProxyDrive::Format(TInt64 aPos,TInt aLength) |
|
113 { |
|
114 __PRINT(_L("CFatTestProxyDrive::Format")); |
|
115 if (CheckEvent(aPos,aLength)) |
|
116 return KErrCorrupt; |
|
117 |
|
118 return CTestProxyDrive::Format(aPos, aLength); |
|
119 } |
|
120 |
|
121 void CFatTestProxyDrive::DoInitL() |
|
122 { |
|
123 __PRINT(_L("CFatTestProxyDrive::DoInit")); |
|
124 if (!CheckMount()) |
|
125 User::Leave(KErrNotReady); |
|
126 |
|
127 |
|
128 iTotalSectors = iBootSector.VolumeTotalSectorNumber(); |
|
129 } |
|
130 |
|
131 TInt CFatTestProxyDrive::DoControlIO(const RMessagePtr2& aMessage,TInt aCommand,TAny* aParam1,TAny* aParam2) |
|
132 { |
|
133 __PRINT(_L("CFatTestProxyDrive::DoControlIO")); |
|
134 |
|
135 // read boot sector & update iFatType etc |
|
136 CheckMount(); |
|
137 |
|
138 TInt r = KErrNone; |
|
139 |
|
140 // Make sure that the information is up to date. |
|
141 if ((r=ReadBootSector()) != KErrNone) |
|
142 { |
|
143 __PRINT1(_L("ReadBootSector error: %d"), r); |
|
144 return EFalse; |
|
145 } |
|
146 |
|
147 switch(aCommand+EExtCustom) |
|
148 { |
|
149 case ESectorsPerCluster: |
|
150 r = aMessage.Write(2, TPckgBuf<TInt>(iBootSector.SectorsPerCluster())); |
|
151 break; |
|
152 case EFatType: |
|
153 r = aMessage.Write(2, TPckgBuf<TInt>(iBootSector.FatType())); |
|
154 break; |
|
155 |
|
156 case EGetDataPosition: |
|
157 { |
|
158 //-- obtain 1st data sector media position. This is actually a nasty hack; |
|
159 //-- we expect that the drive will be freshly formatted, thust the root dir is empty and the first file we create there |
|
160 //-- will occupy the certain place. |
|
161 TUint32 dataSec; |
|
162 |
|
163 if(iBootSector.FatType() !=EFat32) |
|
164 dataSec = iBootSector.FirstDataSector(); |
|
165 else |
|
166 {//-- for FAT32 we assume that the root dir takes exactly 1 cluster. Another dirty trick |
|
167 dataSec = iBootSector.RootDirStartSector() + 1*iBootSector.SectorsPerCluster(); |
|
168 } |
|
169 __PRINT1(_L("EGetDataPosition, sec:%d"), dataSec); |
|
170 r = aMessage.Write(2, TPckgBuf<TInt>(dataSec << KDefaultSectorLog2)); |
|
171 } |
|
172 break; |
|
173 |
|
174 default: |
|
175 r = CBaseExtProxyDrive::ControlIO(aMessage,aCommand,aParam1,aParam2); |
|
176 __PRINT2(_L("Get unknown command %d error %d"), aCommand, r); |
|
177 } |
|
178 return r; |
|
179 } |
|
180 |
|
181 TBool CFatTestProxyDrive::DoCheckEvent(TInt64 aPos, TInt aLength) |
|
182 { |
|
183 //__PRINT2(_L("CFatTestProxyDrive::DoCheckEvent() pos:%d, len:%d"), (TUint32)aPos, aLength); |
|
184 |
|
185 if (aPos<0 || aLength<=0 || (aPos>>KDefaultSectorLog2)>=iTotalSectors) |
|
186 return EFalse; |
|
187 |
|
188 TInt begin = (TInt)(aPos >> KDefaultSectorLog2); |
|
189 TInt end = (TInt)((aPos+aLength-1) >> KDefaultSectorLog2); |
|
190 end = Min(end, iTotalSectors-1); |
|
191 |
|
192 if (iEventType == ENext) |
|
193 { |
|
194 Mark(begin); |
|
195 iEventType = ENone; |
|
196 iLastErrorReason = TErrorInfo::EBadSector; |
|
197 iSuccessBytes = 0; |
|
198 return ETrue; |
|
199 } |
|
200 |
|
201 if (iEventType == EDeterministic) |
|
202 { |
|
203 if (iCount <= end-begin+1) |
|
204 { |
|
205 iCount = 0; |
|
206 Mark(begin+iCount-1); |
|
207 iEventType = ENone; |
|
208 iLastErrorReason = TErrorInfo::EBadSector; |
|
209 iSuccessBytes = (iCount-1) << KDefaultSectorLog2; |
|
210 return ETrue; |
|
211 } |
|
212 else |
|
213 iCount -= end-begin+1; |
|
214 } |
|
215 |
|
216 TInt i; |
|
217 for (i=begin; i<=end; i++) |
|
218 if (IsMarked(i)) |
|
219 { |
|
220 __PRINT(_L("CFatTestProxyDrive::DoCheckEvent() Sector Marked as bad!")); |
|
221 iLastErrorReason = TErrorInfo::EBadSector; |
|
222 iSuccessBytes = (i-begin) << KDefaultSectorLog2; |
|
223 return ETrue; |
|
224 } |
|
225 |
|
226 return EFalse; |
|
227 } |
|
228 |
|
229 TBool CFatTestProxyDrive::CheckMount() |
|
230 { |
|
231 __PRINT(_L("CFatTestProxyDrive::CheckMount")); |
|
232 |
|
233 //-- read boot sector |
|
234 if (ReadBootSector() != KErrNone) |
|
235 { |
|
236 __PRINT(_L("ReadBootSector error: %d")); |
|
237 return EFalse; |
|
238 } |
|
239 |
|
240 //-- validate boot sector |
|
241 if(!iBootSector.IsValid()) |
|
242 { |
|
243 goto BadBootSector; |
|
244 } |
|
245 |
|
246 if (iBootSector.FatType() == EFat32) // fat 32 |
|
247 { |
|
248 if (iBootSector.RootDirEntries() != 0 || |
|
249 iBootSector.TotalSectors() != 0 || |
|
250 iBootSector.HugeSectors() == 0 || |
|
251 iBootSector.FatSectors32() == 0 || |
|
252 iBootSector.RootClusterNum() < 2) |
|
253 { |
|
254 goto BadBootSector; |
|
255 } |
|
256 } |
|
257 else // fat16/12 |
|
258 { |
|
259 if (iBootSector.RootDirEntries() == 0 || |
|
260 (iBootSector.TotalSectors() == 0 && iBootSector.HugeSectors() == 0)) |
|
261 { |
|
262 goto BadBootSector; |
|
263 } |
|
264 } |
|
265 |
|
266 //-- boot sector is OK |
|
267 return ETrue; |
|
268 |
|
269 //-- Invalid boot sector |
|
270 BadBootSector: |
|
271 |
|
272 __PRINT(_L("Boot sector is invalid! dump:")); |
|
273 iBootSector.PrintDebugInfo(); |
|
274 return EFalse; |
|
275 |
|
276 |
|
277 |
|
278 } |
|
279 |
|
280 TInt CFatTestProxyDrive::ReadBootSector() |
|
281 { |
|
282 __PRINT(_L("CFatTestProxyDrive::ReadBootSector")); |
|
283 |
|
284 const TInt KBufSz = KSizeOfFatBootSector; |
|
285 |
|
286 TBuf8<KBufSz> bootSecBuf(KBufSz); |
|
287 TInt r = CTestProxyDrive::Read(0, KBufSz, bootSecBuf); |
|
288 if (r != KErrNone) |
|
289 return r; |
|
290 |
|
291 //-- initialise TFatBootSector object |
|
292 iBootSector.Internalize(bootSecBuf); |
|
293 |
|
294 return KErrNone; |
|
295 } |
|
296 |
|
297 |
|
298 // -------------------------- CFatTestProxyDriveFactory -------------------------- |
|
299 |
|
300 /** |
|
301 Factory class constructor |
|
302 @internalTechnology |
|
303 */ |
|
304 CFatTestProxyDriveFactory::CFatTestProxyDriveFactory() |
|
305 { |
|
306 } |
|
307 |
|
308 /** |
|
309 Factory class installer |
|
310 @internalTechnology |
|
311 */ |
|
312 TInt CFatTestProxyDriveFactory::Install() |
|
313 { |
|
314 __PRINT(_L("CFatTestProxyDriveFactory::Install")); |
|
315 _LIT(KFatTestExt,"FatTest"); |
|
316 return(SetName(&KFatTestExt)); |
|
317 } |
|
318 |
|
319 /** |
|
320 @internalTechnology |
|
321 */ |
|
322 CProxyDrive* CFatTestProxyDriveFactory::NewProxyDriveL(CProxyDrive* aProxy,CMountCB* aMount) |
|
323 { |
|
324 __PRINT(_L("CFatTestProxyDriveFactory::NewProxyDriveL")); |
|
325 return(CFatTestProxyDrive::NewL(aProxy,aMount)); |
|
326 } |
|
327 |
|
328 |
|
329 |
|
330 /** |
|
331 @internalTechnology |
|
332 */ |
|
333 extern "C" { |
|
334 EXPORT_C CProxyDriveFactory* CreateFileSystem() |
|
335 { |
|
336 __PRINT(_L("CreateFileSystem")); |
|
337 return new CFatTestProxyDriveFactory(); |
|
338 } |
|
339 } |