40 {//-- do some finalisation work if CMountCB is valid |
40 {//-- do some finalisation work if CMountCB is valid |
41 if(FileAttModified()) |
41 if(FileAttModified()) |
42 { |
42 { |
43 IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush |
43 IndicateFileTimeModified(ETrue); //-- this will force writing file modification time to the media on Flush |
44 TRAP_IGNORE(FlushAllL()); |
44 TRAP_IGNORE(FlushAllL()); |
45 } |
45 } |
46 } |
46 } |
47 |
47 |
48 delete[] iSeekIndex; |
48 delete[] iSeekIndex; |
49 } |
49 } |
50 |
50 |
51 |
51 |
52 void CFatFileCB::CreateSeekIndex() |
52 void CFatFileCB::CreateSeekIndex() |
53 // |
53 // |
54 // Create a seek index |
54 // Create a seek index |
55 // |
55 // |
56 { |
56 { |
57 |
57 |
58 iSeekIndex = new TUint32[KSeekIndexSize]; |
58 iSeekIndex = new TUint32[KSeekIndexSize]; |
59 if (iSeekIndex == NULL) |
59 if (iSeekIndex == NULL) |
60 return; |
60 return; |
61 |
61 |
62 Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize); |
62 Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize); |
63 |
63 |
64 iSeekIndexSize=CalcSeekIndexSize(FCB_FileSize()); |
64 iSeekIndexSize=CalcSeekIndexSize(FCB_FileSize()); |
65 } |
65 } |
66 |
66 |
67 TInt CFatFileCB::SeekToPosition(TUint aNewRelCluster, TUint aClusterOffset) |
67 TInt CFatFileCB::SeekToPosition(TUint aNewRelCluster, TUint aClusterOffset) |
68 // |
68 // |
69 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster |
69 // Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster |
70 // Return aNewRelCluster-aCurrentPos.iCluster |
70 // Return aNewRelCluster-aCurrentPos.iCluster |
71 // |
71 // |
72 { |
72 { |
73 TInt clusterOffset=aClusterOffset; |
73 TInt clusterOffset=aClusterOffset; |
74 TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1; |
74 TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1; |
75 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
75 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
76 |
76 |
77 while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0) |
77 while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0) |
78 { |
78 { |
79 seekPos--; |
79 seekPos--; |
80 clusterOffset--; |
80 clusterOffset--; |
81 } |
81 } |
82 if (clusterOffset==0) // Counted back to the current cluster |
82 if (clusterOffset==0) // Counted back to the current cluster |
83 return(aClusterOffset); |
83 return(aClusterOffset); |
84 if (seekPos<0) |
84 if (seekPos<0) |
85 { |
85 { |
86 iCurrentPos.iCluster=FCB_StartCluster(); |
86 iCurrentPos.iCluster=FCB_StartCluster(); |
87 return(aNewRelCluster); |
87 return(aNewRelCluster); |
88 } |
88 } |
89 |
89 |
90 iCurrentPos.iCluster=iSeekIndex[seekPos]; |
90 iCurrentPos.iCluster=iSeekIndex[seekPos]; |
91 return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize)); |
91 return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize)); |
92 } |
92 } |
93 |
93 |
94 void CFatFileCB::SetSeekIndexValueL(TUint aRelCluster, TUint aStoredCluster) |
94 void CFatFileCB::SetSeekIndexValueL(TUint aRelCluster, TUint aStoredCluster) |
95 // |
95 // |
96 // Sets a value in the seekindex |
96 // Sets a value in the seekindex |
97 // |
97 // |
98 { |
98 { |
99 |
99 |
100 TInt seekPos=(aRelCluster>>iSeekIndexSize)-1; |
100 TInt seekPos=(aRelCluster>>iSeekIndexSize)-1; |
101 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
101 __ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall)); |
102 __ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2)); |
102 __ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2)); |
103 iSeekIndex[seekPos] = aStoredCluster; |
103 iSeekIndex[seekPos] = aStoredCluster; |
104 } |
104 } |
105 |
105 |
106 TBool CFatFileCB::IsSeekBackwards(TUint aPos) |
106 TBool CFatFileCB::IsSeekBackwards(TUint aPos) |
107 // |
107 // |
108 // Return true if aPos<currentPos |
108 // Return true if aPos<currentPos |
109 // |
109 // |
110 { |
110 { |
111 |
111 |
112 TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2(); |
112 TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2(); |
113 TInt offset=ClusterRelativePos(iCurrentPos.iPos); |
113 TInt offset=ClusterRelativePos(iCurrentPos.iPos); |
114 TUint currentPos=cluster+offset; |
114 TUint currentPos=cluster+offset; |
115 return(aPos<currentPos); |
115 return(aPos<currentPos); |
116 } |
116 } |
117 |
117 |
118 void CFatFileCB::CheckPosL(TUint aPos) |
118 void CFatFileCB::CheckPosL(TUint aPos) |
119 // |
119 // |
120 // Check that the file is positioned correctly. |
120 // Check that the file is positioned correctly. |
121 // If aPos<currentPos attempt to guess the new position. |
121 // If aPos<currentPos attempt to guess the new position. |
122 // |
122 // |
123 { |
123 { |
124 __PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos); |
124 __PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos); |
125 if (aPos==iCurrentPos.iPos) |
125 if (aPos==iCurrentPos.iPos) |
126 return; |
126 return; |
127 __ASSERT_DEBUG(aPos <= FCB_FileSize(), Fault(EFatFilePosBeyondEnd)); |
127 __ASSERT_DEBUG(aPos <= FCB_FileSize(), Fault(EFatFilePosBeyondEnd)); |
128 |
128 |
129 if (FileSizeModified() && IsSeekBackwards(aPos)) |
129 if (FileSizeModified() && IsSeekBackwards(aPos)) |
130 FlushDataL(); |
130 FlushDataL(); |
131 |
131 |
132 TUint newRelCluster=aPos>>ClusterSizeLog2(); |
132 TUint newRelCluster=aPos>>ClusterSizeLog2(); |
133 if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) ) |
133 if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) ) |
134 newRelCluster--; |
134 newRelCluster--; |
135 TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2(); |
135 TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2(); |
136 |
136 |
137 if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) ) |
137 if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) ) |
138 oldRelCluster--; |
138 oldRelCluster--; |
139 |
139 |
140 TInt clusterOffset=newRelCluster-oldRelCluster; |
140 TInt clusterOffset=newRelCluster-oldRelCluster; |
141 TUint32 oldCluster=iCurrentPos.iCluster; |
141 TUint32 oldCluster=iCurrentPos.iCluster; |
142 |
142 |
143 iCurrentPos.iPos=aPos; |
143 iCurrentPos.iPos=aPos; |
144 if (clusterOffset==0) |
144 if (clusterOffset==0) |
145 return; |
145 return; |
146 TInt seekOffset=clusterOffset; |
146 TInt seekOffset=clusterOffset; |
147 if (iSeekIndex!=NULL) |
147 if (iSeekIndex!=NULL) |
148 { // Can alter iCurrentPos.iCluster |
148 { // Can alter iCurrentPos.iCluster |
149 seekOffset=SeekToPosition(newRelCluster,seekOffset); |
149 seekOffset=SeekToPosition(newRelCluster,seekOffset); |
150 if (seekOffset==0) |
150 if (seekOffset==0) |
151 return; |
151 return; |
152 } |
152 } |
153 if (clusterOffset==-1 && seekOffset!=1) |
153 if (clusterOffset==-1 && seekOffset!=1) |
154 { // Check previous cluster |
154 { // Check previous cluster |
155 TUint32 cluster=oldCluster-1; |
155 TUint32 cluster=oldCluster-1; |
156 if (FAT().GetNextClusterL(cluster) && cluster==oldCluster) |
156 if (FAT().GetNextClusterL(cluster) && cluster==oldCluster) |
157 { |
157 { |
158 iCurrentPos.iCluster=oldCluster-1; |
158 iCurrentPos.iCluster=oldCluster-1; |
159 return; |
159 return; |
160 } |
160 } |
161 } |
161 } |
162 if (seekOffset<0) |
162 if (seekOffset<0) |
163 { |
163 { |
164 seekOffset=newRelCluster; |
164 seekOffset=newRelCluster; |
165 iCurrentPos.iCluster=FCB_StartCluster(); |
165 iCurrentPos.iCluster=FCB_StartCluster(); |
166 } |
166 } |
167 while (seekOffset--) |
167 while (seekOffset--) |
168 { |
168 { |
169 if (!FAT().GetNextClusterL(iCurrentPos.iCluster)) |
169 if (!FAT().GetNextClusterL(iCurrentPos.iCluster)) |
170 { |
170 { |
171 __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1")); |
171 __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1")); |
172 User::Leave(KErrCorrupt); |
172 User::Leave(KErrCorrupt); |
173 } |
173 } |
174 TInt cluster=newRelCluster-seekOffset; |
174 TInt cluster=newRelCluster-seekOffset; |
175 if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster) |
175 if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster) |
176 SetSeekIndexValueL(cluster,iCurrentPos.iCluster); |
176 SetSeekIndexValueL(cluster,iCurrentPos.iCluster); |
177 } |
177 } |
178 } |
178 } |
179 |
179 |
180 //----------------------------------------------------------------------------- |
180 //----------------------------------------------------------------------------- |
181 /** |
181 /** |
182 Initialize FileCB from file's entry data. |
182 Initialize FileCB from file's entry data. |
183 |
183 |
184 @param aFatDirEntry this file DOS dir entry. |
184 @param aFatDirEntry this file DOS dir entry. |
185 @param aFileDosEntryPos this file DOS entry dir. iterator in the parent directory. |
185 @param aFileDosEntryPos this file DOS entry dir. iterator in the parent directory. |
186 */ |
186 */ |
187 void CFatFileCB::SetupL(const TFatDirEntry& aFatDirEntry, const TEntryPos& aFileDosEntryPos) |
187 void CFatFileCB::SetupL(const TFatDirEntry& aFatDirEntry, const TEntryPos& aFileDosEntryPos) |
188 { |
188 { |
189 __PRINT1(_L("CFatFileCB::SetupL[0x%x]"), this); |
189 __PRINT1(_L("CFatFileCB::SetupL[0x%x]"), this); |
190 |
190 |
191 |
191 |
192 //-- set up a file control block |
192 //-- set up a file control block |
193 iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry); |
193 iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry); |
194 iCurrentPos.iPos=0; |
194 iCurrentPos.iPos=0; |
195 |
195 |
196 SetAtt(aFatDirEntry.Attributes()); |
196 SetAtt(aFatDirEntry.Attributes()); |
197 SetModified(aFatDirEntry.Time(FatMount().TimeOffset())); |
197 SetModified(aFatDirEntry.Time(FatMount().TimeOffset())); |
198 |
198 |
199 FCB_SetStartCluster(iCurrentPos.iCluster); |
199 FCB_SetStartCluster(iCurrentPos.iCluster); |
200 FCB_SetFileSize(aFatDirEntry.Size()); |
200 FCB_SetFileSize(aFatDirEntry.Size()); |
201 |
201 |
202 iFileDosEntryPos = aFileDosEntryPos; |
202 iFileDosEntryPos = aFileDosEntryPos; |
203 |
203 |
204 SetMaxSupportedSize(KMaxSupportedFatFileSize); |
204 SetMaxSupportedSize(KMaxSupportedFatFileSize); |
205 |
205 |
206 //-- create seek index |
206 //-- create seek index |
207 ASSERT(!iSeekIndex); |
207 ASSERT(!iSeekIndex); |
268 |
270 |
269 @leave on media read error |
271 @leave on media read error |
270 |
272 |
271 */ |
273 */ |
272 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) |
274 void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset) |
273 { |
275 { |
274 __PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength); |
276 __PRINT3(_L("CFatFileCB::WriteL[0x%x] pos=%LU len=%d"), this, aPos, aLength); |
275 |
277 |
276 // FAT supports 32 bits only for file size |
278 // FAT supports 32 bits only for file size |
277 TUint64 endPos = aPos + aLength; |
279 TUint64 endPos = aPos + aLength; |
278 if(endPos > KMaxSupportedFatFileSize) |
280 if(endPos > KMaxSupportedFatFileSize) |
279 User::Leave(KErrNotSupported); |
281 User::Leave(KErrNotSupported); |
280 |
282 |
281 FatMount().CheckStateConsistentL(); |
283 FatMount().CheckStateConsistentL(); |
282 FatMount().CheckWritableL(); |
284 FatMount().CheckWritableL(); |
283 const TUint pos = I64LOW(aPos); |
285 const TUint pos = I64LOW(aPos); |
284 CheckPosL(pos); |
286 CheckPosL(pos); |
285 |
287 |
286 const TUint startCluster = FCB_StartCluster(); |
288 const TUint startCluster = FCB_StartCluster(); |
287 const TUint length = (TUint)aLength; |
289 const TUint length = (TUint)aLength; |
|
290 |
|
291 endPos = iCurrentPos.iPos + length; |
|
292 if ((endPos > FCB_FileSize()) || |
|
293 (iCurrentPos.iPos > endPos) ) // Overflow condition |
|
294 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
|
295 |
|
296 TUint startPos=iCurrentPos.iPos; |
|
297 TUint badcluster=0; |
|
298 TUint goodcluster=0; |
|
299 |
|
300 TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0; |
288 |
301 |
289 endPos = iCurrentPos.iPos + length; |
302 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag)); |
290 if ((endPos > FCB_FileSize()) || |
|
291 (iCurrentPos.iPos > endPos) ) // Overflow condition |
|
292 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
|
293 |
303 |
294 TUint startPos=iCurrentPos.iPos; |
304 if (ret == KErrCorrupt || ret == KErrDied) |
295 TUint badcluster=0; |
305 { |
296 TUint goodcluster=0; |
|
297 |
|
298 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster)); |
|
299 |
|
300 if (ret == KErrCorrupt || ret == KErrDied) |
|
301 { |
|
302 if(startCluster == 0) |
306 if(startCluster == 0) |
303 { //Empty File, revert all the clusters allocated. |
307 { //Empty File, revert all the clusters allocated. |
304 const TUint32 cluster = FCB_StartCluster(); |
308 const TUint32 cluster = FCB_StartCluster(); |
305 FCB_SetStartCluster(0); |
309 FCB_SetStartCluster(0); |
306 FCB_SetFileSize(0); |
310 FCB_SetFileSize(0); |
307 IndicateFileSizeModified(ETrue); |
311 IndicateFileSizeModified(ETrue); |
308 |
312 |
309 FlushAllL(); |
313 FlushAllL(); |
310 |
314 |
311 iCurrentPos.iCluster = 0; |
315 iCurrentPos.iCluster = 0; |
312 iCurrentPos.iPos = 0; |
316 iCurrentPos.iPos = 0; |
313 |
317 |
314 FAT().FreeClusterListL(cluster); |
318 FAT().FreeClusterListL(cluster); |
315 FAT().FlushL(); |
319 FAT().FlushL(); |
316 } |
320 } |
317 else |
321 else |
318 { //Calculate the clusters required based on file size, revert extra clusters if allocated. |
322 { //Calculate the clusters required based on file size, revert extra clusters if allocated. |
319 const TUint curSize = FCB_FileSize(); |
323 const TUint curSize = FCB_FileSize(); |
320 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
324 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
321 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
325 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
322 { |
326 { |
323 ClustersNeeded++; |
327 ClustersNeeded++; |
324 } |
328 } |
325 |
329 |
326 TUint32 cluster = FCB_StartCluster(); |
330 TUint32 cluster = FCB_StartCluster(); |
327 while(--ClustersNeeded) |
331 while(--ClustersNeeded) |
328 { |
332 { |
329 FAT().GetNextClusterL(cluster); |
333 FAT().GetNextClusterL(cluster); |
330 } |
334 } |
331 |
335 |
332 iCurrentPos.iCluster = cluster; |
336 iCurrentPos.iCluster = cluster; |
333 |
337 |
334 if (FAT().GetNextClusterL(cluster)) |
338 if (FAT().GetNextClusterL(cluster)) |
335 { |
339 { |
336 FAT().FreeClusterListL(cluster); |
340 FAT().FreeClusterListL(cluster); |
337 } |
341 } |
338 |
342 |
339 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
343 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
340 FAT().FlushL(); |
344 FAT().FlushL(); |
341 } |
345 } |
342 } |
346 } |
343 |
347 |
344 User::LeaveIfError(ret); |
348 User::LeaveIfError(ret); |
345 |
349 |
346 if(badcluster != 0) |
350 if(badcluster != 0) |
347 { |
351 { |
348 if(FCB_StartCluster() == badcluster) |
352 if(FCB_StartCluster() == badcluster) |
349 { |
353 { |
350 FCB_SetStartCluster(goodcluster); |
354 FCB_SetStartCluster(goodcluster); |
351 FlushStartClusterL(); |
355 FlushStartClusterL(); |
352 } |
356 } |
353 else |
357 else |
354 { |
358 { |
355 TUint32 aCluster = FCB_StartCluster(); |
359 TUint32 aCluster = FCB_StartCluster(); |
356 do |
360 do |
357 { |
361 { |
358 if((TUint)badcluster == FAT().ReadL(aCluster)) |
362 if((TUint)badcluster == FAT().ReadL(aCluster)) |
359 { |
363 { |
360 FAT().WriteL(aCluster, goodcluster); |
364 FAT().WriteL(aCluster, goodcluster); |
361 FAT().FlushL(); |
365 FAT().FlushL(); |
362 break; |
366 break; |
363 } |
367 } |
364 } |
368 } |
365 while(FAT().GetNextClusterL(aCluster)); |
369 while(FAT().GetNextClusterL(aCluster)); |
366 } |
370 } |
367 } |
371 } |
368 aLength=iCurrentPos.iPos-startPos; |
372 aLength=iCurrentPos.iPos-startPos; |
369 |
373 |
370 if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize()) |
374 if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize()) |
371 { |
375 { |
372 WriteFileSizeL(pos+aLength); |
376 WriteFileSizeL(pos+aLength); |
373 } |
377 } |
374 |
378 |
375 } |
379 } |
376 |
380 |
377 |
381 |
378 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage) |
382 void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage) |
379 { |
383 { |
380 WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0); |
384 WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0); |
381 } |
385 } |
382 |
386 |
383 |
387 |
384 //----------------------------------------------------------------------------- |
388 //----------------------------------------------------------------------------- |
385 |
389 |
386 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize) |
390 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize) |
387 // |
391 // |
388 // Resize the seek index to accomodate a larger or smaller filesize |
392 // Resize the seek index to accomodate a larger or smaller filesize |
389 // Assumes KSeekIndexSize is a power of 2. |
393 // Assumes KSeekIndexSize is a power of 2. |
390 // |
394 // |
391 { |
395 { |
392 |
396 |
393 TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult); |
397 TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult); |
394 |
398 |
395 |
399 |
396 TInt index=0; |
400 TInt index=0; |
397 TInt indexEnd=KSeekIndexSize; |
401 TInt indexEnd=KSeekIndexSize; |
398 TInt newValEnd=maxNewIndex; |
402 TInt newValEnd=maxNewIndex; |
399 |
403 |
400 if (iSeekIndexSize<aNewMult) |
404 if (iSeekIndexSize<aNewMult) |
401 { |
405 { |
402 TInt newVal=index; |
406 TInt newVal=index; |
403 TInt step=1<<(aNewMult-iSeekIndexSize); |
407 TInt step=1<<(aNewMult-iSeekIndexSize); |
404 index+=step-1; |
408 index+=step-1; |
405 while(index<indexEnd && newVal<newValEnd) |
409 while(index<indexEnd && newVal<newValEnd) |
406 { |
410 { |
407 iSeekIndex[newVal] = iSeekIndex[index]; |
411 iSeekIndex[newVal] = iSeekIndex[index]; |
408 newVal++; |
412 newVal++; |
409 index+=step; |
413 index+=step; |
410 } |
414 } |
411 while(newVal<indexEnd) |
415 while(newVal<indexEnd) |
412 iSeekIndex[newVal++] = 0; |
416 iSeekIndex[newVal++] = 0; |
413 } |
417 } |
414 else |
418 else |
415 { |
419 { |
416 TInt diffSize = iSeekIndexSize-aNewMult; |
420 TInt diffSize = iSeekIndexSize-aNewMult; |
417 TInt oldVal=(KSeekIndexSize>>diffSize) - 1; |
421 TInt oldVal=(KSeekIndexSize>>diffSize) - 1; |
418 TInt newVal=indexEnd-1; |
422 TInt newVal=indexEnd-1; |
419 TInt skip=(1<<diffSize)-1; |
423 TInt skip=(1<<diffSize)-1; |
420 |
424 |
421 if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2) |
425 if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2) |
422 { |
426 { |
423 ClearIndex(0); //-- Invalidate every entry. |
427 ClearIndex(0); //-- Invalidate every entry. |
424 } |
428 } |
425 else |
429 else |
426 { |
430 { |
427 while(newVal>=index) |
431 while(newVal>=index) |
428 { |
432 { |
429 |
433 |
430 iSeekIndex[newVal--] = iSeekIndex[oldVal--]; |
434 iSeekIndex[newVal--] = iSeekIndex[oldVal--]; |
431 |
435 |
432 |
436 |
433 for(TInt i=skip;i>0;i--) |
437 for(TInt i=skip;i>0;i--) |
434 { |
438 { |
435 iSeekIndex[newVal--] = 0; |
439 iSeekIndex[newVal--] = 0; |
436 |
440 |
437 } |
441 } |
438 } |
442 } |
439 } |
443 } |
440 } |
444 } |
441 iSeekIndexSize=aNewMult; |
445 iSeekIndexSize=aNewMult; |
442 } |
446 } |
443 |
447 |
444 |
448 |
445 /** |
449 /** |
446 Zero freed clusters in the index |
450 Zero freed clusters in the index |
447 |
451 |
448 @param aNewSize new size of the file that the index corresponds to. |
452 @param aNewSize new size of the file that the index corresponds to. |
449 if = 0 all existing index will be zero filled |
453 if = 0 all existing index will be zero filled |
450 */ |
454 */ |
451 void CFatFileCB::ClearIndex(TUint aNewSize) |
455 void CFatFileCB::ClearIndex(TUint aNewSize) |
452 { |
456 { |
453 |
457 |
454 if (!iSeekIndex) |
458 if (!iSeekIndex) |
455 return; |
459 return; |
456 |
460 |
457 if(aNewSize==0) |
461 if(aNewSize==0) |
458 { |
462 { |
459 //-- zero fill all the array |
463 //-- zero fill all the array |
460 Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32)); |
464 Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32)); |
461 return; |
465 return; |
462 } |
466 } |
463 |
467 |
464 // Files that fill up a cluster exactly do not have a trailing empty |
468 // Files that fill up a cluster exactly do not have a trailing empty |
465 // cluster. So the entry for that position must also be invalidated |
469 // cluster. So the entry for that position must also be invalidated |
466 aNewSize--; |
470 aNewSize--; |
467 TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2()); |
471 TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2()); |
468 |
472 |
469 TInt indexLen=KSeekIndexSize-firstInvalidIndex; |
473 TInt indexLen=KSeekIndexSize-firstInvalidIndex; |
470 |
474 |
471 Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32)); |
475 Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32)); |
472 } |
476 } |
473 |
477 |
474 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize) |
478 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize) |
475 // |
479 // |
476 // Find the nearest power of 2 > aSize |
480 // Find the nearest power of 2 > aSize |
477 // |
481 // |
478 { |
482 { |
479 TInt count = 0; |
483 TInt count = 0; |
480 const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128 |
484 const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128 |
481 if (aSize<=indexSize) |
485 if (aSize<=indexSize) |
482 return(count); |
486 return(count); |
483 |
487 |
484 while((aSize>>=1)>0) |
488 while((aSize>>=1)>0) |
485 { |
489 { |
486 count++; |
490 count++; |
487 } |
491 } |
488 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
492 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
489 } |
493 } |
490 |
494 |
491 //----------------------------------------------------------------------------- |
495 //----------------------------------------------------------------------------- |
492 /** |
496 /** |
493 Set file size. |
497 Set file size. |
494 @param aSize new file size. |
498 @param aSize new file size. |
495 */ |
499 */ |
496 void CFatFileCB::SetSizeL(TInt64 aSize) |
500 void CFatFileCB::SetSizeL(TInt64 aSize) |
497 { |
501 { |
498 __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); |
502 __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); |
499 |
503 |
500 //-- max. file size for FAT is 4GB-1 |
504 //-- max. file size for FAT is 4GB-1 |
501 if (I64HIGH(aSize)) |
505 if (I64HIGH(aSize)) |
502 User::Leave(KErrNotSupported); |
506 User::Leave(KErrNotSupported); |
503 |
507 |
504 DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); |
508 DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); |
505 } |
509 } |
506 |
510 |
507 |
511 |
508 void CFatFileCB::SetSizeL(TInt aSize) |
512 void CFatFileCB::SetSizeL(TInt aSize) |
509 { |
513 { |
510 SetSizeL(TInt64(aSize)); |
514 SetSizeL(TInt64(aSize)); |
511 } |
515 } |
512 |
516 |
513 //----------------------------------------------------------------------------- |
517 //----------------------------------------------------------------------------- |
514 /** |
518 /** |
515 Shrink file to zero size. |
519 Shrink file to zero size. |
516 */ |
520 */ |
517 void CFatFileCB::DoShrinkFileToZeroSizeL() |
521 void CFatFileCB::DoShrinkFileToZeroSizeL() |
518 { |
522 { |
519 ASSERT(FCB_FileSize()); |
523 ASSERT(FCB_FileSize()); |
520 ASSERT(FileSizeModified()); |
524 ASSERT(FileSizeModified()); |
521 |
525 |
522 ClearIndex(0); // Clear seek index array |
526 ClearIndex(0); // Clear seek index array |
523 |
527 |
524 //-- update file dir. entry |
528 //-- update file dir. entry |
525 const TUint32 cluster = FCB_StartCluster(); |
529 const TUint32 cluster = FCB_StartCluster(); |
526 FCB_SetStartCluster(0); |
530 FCB_SetStartCluster(0); |
527 FCB_SetFileSize(0); |
531 FCB_SetFileSize(0); |
528 FlushAllL(); |
532 FlushAllL(); |
529 |
533 |
530 //-- free cluster list. |
534 //-- free cluster list. |
531 CheckPosL(0); |
535 CheckPosL(0); |
532 FAT().FreeClusterListL(cluster); |
536 FAT().FreeClusterListL(cluster); |
533 FAT().FlushL(); |
537 FAT().FlushL(); |
534 } |
538 } |
535 |
539 |
536 //----------------------------------------------------------------------------- |
540 //----------------------------------------------------------------------------- |
537 /* |
541 /* |
538 Shrink file to smaller size, but > 0 |
542 Shrink file to smaller size, but > 0 |
539 |
543 |
540 @param aNewSize new file size |
544 @param aNewSize new file size |
541 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
545 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
542 */ |
546 */ |
543 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
547 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
544 { |
548 { |
545 ASSERT(FileSizeModified()); |
549 ASSERT(FileSizeModified()); |
546 ASSERT(FCB_FileSize() > aNewSize && aNewSize); |
550 ASSERT(FCB_FileSize() > aNewSize && aNewSize); |
547 |
551 |
548 if(aForceCachesFlush) |
552 if(aForceCachesFlush) |
549 WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry |
553 WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry |
550 |
554 |
551 CheckPosL(aNewSize); |
555 CheckPosL(aNewSize); |
552 |
556 |
553 TUint32 cluster=iCurrentPos.iCluster; |
557 TUint32 cluster=iCurrentPos.iCluster; |
554 if (FAT().GetNextClusterL(cluster)) |
558 |
555 {//-- truncate the cluster chain |
559 if (FAT().GetNextClusterL(cluster)) |
556 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
560 {//-- truncate the cluster chain |
557 FAT().FreeClusterListL(cluster); |
561 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
558 } |
562 FAT().FreeClusterListL(cluster); |
559 |
563 } |
|
564 |
560 ClearIndex(aNewSize); |
565 ClearIndex(aNewSize); |
561 FAT().FlushL(); |
566 FAT().FlushL(); |
562 } |
567 } |
563 |
568 |
564 //----------------------------------------------------------------------------- |
569 //----------------------------------------------------------------------------- |
565 /** |
570 /** |
566 Expand a file. |
571 Expand a file. |
567 |
572 |
568 @param aNewSize new file size. |
573 @param aNewSize new file size. |
569 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
574 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
570 */ |
575 */ |
571 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
576 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
572 { |
577 { |
573 ASSERT(FCB_FileSize() < aNewSize); |
578 ASSERT(FCB_FileSize() < aNewSize); |
574 ASSERT(FileSizeModified()); |
579 ASSERT(FileSizeModified()); |
575 |
580 |
576 const TUint32 KClusterSzLog2 = ClusterSizeLog2(); |
581 const TUint32 KClusterSzLog2 = ClusterSizeLog2(); |
577 const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
582 const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
578 |
583 |
579 |
584 |
580 //-- expanding a file |
585 //-- expanding a file |
581 if (FCB_StartCluster() == 0) |
586 if (FCB_StartCluster() == 0) |
582 {//-- the initial file size is 0 (no cluster chain) |
587 {//-- the initial file size is 0 (no cluster chain) |
583 |
588 |
584 ClearIndex(0); //-- clear seek index array |
589 ClearIndex(0); //-- clear seek index array |
585 //-- FAT().FreeClusterHint() will give us a hint of the last free cluster |
590 //-- FAT().FreeClusterHint() will give us a hint of the last free cluster |
586 const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); |
591 const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); |
587 FAT().FlushL(); |
592 FAT().FlushL(); |
588 |
593 |
589 iCurrentPos.iCluster=tempStartCluster; |
594 iCurrentPos.iCluster=tempStartCluster; |
590 FCB_SetStartCluster(tempStartCluster); |
595 FCB_SetStartCluster(tempStartCluster); |
591 FCB_SetFileSize(aNewSize); |
596 FCB_SetFileSize(aNewSize); |
592 FlushAllL(); |
597 FlushAllL(); |
593 } |
598 } |
594 else |
599 else |
595 { |
600 { |
596 const TUint curSize = FCB_FileSize(); |
601 const TUint curSize = FCB_FileSize(); |
597 const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
602 const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
598 ASSERT(newSizeClusters >= oldSizeClusters); |
603 ASSERT(newSizeClusters >= oldSizeClusters); |
599 const TUint newClusters = newSizeClusters-oldSizeClusters; //-- Number of clusters we need to append to the existing cluster chain |
604 const TUint newClusters = newSizeClusters-oldSizeClusters; //-- Number of clusters we need to append to the existing cluster chain |
600 if (newClusters) |
605 if (newClusters) |
601 { |
606 { |
602 TEntryPos currentPos=iCurrentPos; |
607 TEntryPos currentPos=iCurrentPos; |
603 CheckPosL(FCB_FileSize()); |
608 CheckPosL(FCB_FileSize()); |
604 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
609 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
605 iCurrentPos=currentPos; |
610 iCurrentPos=currentPos; |
606 } |
611 } |
607 |
612 |
608 FAT().FlushL(); |
613 FAT().FlushL(); |
609 |
614 |
610 if(!IsSequentialMode() && aForceCachesFlush) // Write file size directly to its dir. entry if a cache flush |
615 if(!IsSequentialMode() && aForceCachesFlush) // Write file size directly to its dir. entry if a cache flush |
611 WriteFileSizeL(aNewSize); // is needed and rugged FAT is not ignored by client |
616 WriteFileSizeL(aNewSize); // is needed and rugged FAT is not ignored by client |
612 } |
617 } |
613 |
618 |
614 } |
619 } |
615 |
620 |
616 //----------------------------------------------------------------------------- |
621 //----------------------------------------------------------------------------- |
617 /** |
622 /** |
618 Set file size. This can involve extending/truncating file's cluster chain. |
623 Set file size. This can involve extending/truncating file's cluster chain. |
619 @param aSize new file size |
624 @param aSize new file size |
620 @param aForceCachesFlush if ETrue, all changes in metadata will go to the media immediately. |
625 @param aForceCachesFlush if ETrue, all changes in metadata will go to the media immediately. |
621 it is used in Rugged FAT mode. |
626 it is used in Rugged FAT mode. |
622 */ |
627 */ |
623 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) |
628 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) |
624 { |
629 { |
625 __PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush); |
630 __PRINT4(_L("CFatFileCB::DoSetSizeL[0x%x] sz:%d, oldSz:%d, flush:%d"), this, aSize, FCB_FileSize(), aForceCachesFlush); |
626 |
631 |
627 FatMount().CheckStateConsistentL(); |
632 FatMount().CheckStateConsistentL(); |
628 FatMount().CheckWritableL(); |
633 FatMount().CheckWritableL(); |
629 |
634 |
630 |
635 |
631 // Can not change the file size if it is clamped |
636 // Can not change the file size if it is clamped |
632 if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) |
637 if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) |
633 User::Leave(KErrInUse); |
638 User::Leave(KErrInUse); |
634 |
639 |
635 if(aSize == FCB_FileSize()) |
640 if(aSize == FCB_FileSize()) |
636 return; |
641 return; |
637 |
642 |
638 IndicateFileSizeModified(ETrue); |
643 IndicateFileSizeModified(ETrue); |
|
644 IndicateFileAttModified(ETrue); // ensure file size is flushed |
639 |
645 |
640 TInt newIndexMult=CalcSeekIndexSize(aSize); |
646 TInt newIndexMult=CalcSeekIndexSize(aSize); |
641 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
647 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
642 ResizeIndex(newIndexMult,aSize); |
648 ResizeIndex(newIndexMult,aSize); |
643 |
649 |
673 @param aSetAttMask file attributes OR mask |
679 @param aSetAttMask file attributes OR mask |
674 @param aClearAttMask file attributes AND mask |
680 @param aClearAttMask file attributes AND mask |
675 |
681 |
676 */ |
682 */ |
677 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
683 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
678 { |
684 { |
679 __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this); |
685 __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this); |
680 |
686 |
681 FatMount().CheckStateConsistentL(); |
687 FatMount().CheckStateConsistentL(); |
682 FatMount().CheckWritableL(); |
688 FatMount().CheckWritableL(); |
683 |
689 |
684 //-- change file attributes |
690 //-- change file attributes |
685 const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set |
691 const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set |
686 TUint newAtt = Att(); |
692 TUint oldAtt = Att(); |
|
693 TUint newAtt = oldAtt; |
687 |
694 |
688 if (setAttMask|aClearAttMask) |
695 if (setAttMask|aClearAttMask) |
689 { |
696 { |
690 newAtt |= setAttMask; |
697 newAtt |= setAttMask; |
691 newAtt &= ~aClearAttMask; |
698 newAtt &= ~aClearAttMask; |
692 SetAtt(newAtt); |
699 if (newAtt != oldAtt) |
693 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
700 { |
|
701 SetAtt(newAtt); |
|
702 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
|
703 } |
694 } |
704 } |
695 |
705 |
696 //-- set file entry modification time if required |
706 //-- set file entry modification time if required |
697 if (aSetAttMask&KEntryAttModified) |
707 if (aSetAttMask&KEntryAttModified) |
698 { |
708 { |
699 SetModified(aTime); //-- set file modified time |
709 SetModified(aTime); //-- set file modified time |
700 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
710 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
701 IndicateFileTimeModified(ETrue); //-- this will force writing file mod. time to the media on Flush |
711 IndicateFileTimeModified(ETrue); //-- this will force writing file mod. time to the media on Flush |
702 } |
712 } |
703 |
713 |
704 } |
714 } |
705 |
715 |
706 |
716 |
707 //----------------------------------------------------------------------------- |
717 //----------------------------------------------------------------------------- |
708 /** |
718 /** |
709 The same as FlushAllL(). This method is called from RFile::Flush() |
719 The same as FlushAllL(). This method is called from RFile::Flush() |
710 */ |
720 */ |
711 void CFatFileCB::FlushDataL() |
721 void CFatFileCB::FlushDataL() |
712 { |
722 { |
713 __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this); |
723 __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this); |
714 FlushAllL(); |
724 FlushAllL(); |
715 } |
725 } |
716 |
726 |
717 //----------------------------------------------------------------------------- |
727 //----------------------------------------------------------------------------- |
718 /** |
728 /** |
719 Flush the fide directory entry data: files size, attributes, time etc. |
729 Flush the fide directory entry data: files size, attributes, time etc. |
720 */ |
730 */ |
721 void CFatFileCB::FlushAllL() |
731 void CFatFileCB::FlushAllL() |
722 { |
732 { |
723 |
733 |
724 //-- define this symbol in order to enable legacy behaviour, i.e. compulsory updating file dir. entry on flush. |
734 //-- define this symbol in order to enable legacy behaviour, i.e. compulsory updating file dir. entry on flush. |
725 //-- otherwise the FlushAllL() will update the file dir. entry only if it differs from what is on the media, i.e. |
735 //-- otherwise the FlushAllL() will update the file dir. entry only if it differs from what is on the media, i.e. |
726 //-- file size, start cluster, attributes and modification timestamp |
736 //-- file size, start cluster, attributes and modification timestamp |
727 #define ALWAYS_UPDATE_ENTRY_ON_FLUSH |
737 #define ALWAYS_UPDATE_ENTRY_ON_FLUSH |
728 |
738 |
729 __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this); |
739 __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this); |
730 |
740 |
731 if (Mount().IsCurrentMount()==EFalse) |
741 if (Mount().IsCurrentMount()==EFalse) |
732 User::Leave(KErrDisMounted); |
742 User::Leave(KErrDisMounted); |
733 |
743 |
734 FatMount().CheckStateConsistentL(); |
744 FatMount().CheckStateConsistentL(); |
735 FatMount().CheckWritableL(); |
745 FatMount().CheckWritableL(); |
736 |
746 |
737 if(!FileSizeModified() && !FileAttModified() && !FileTimeModified()) |
747 if(!FileSizeModified() && !FileAttModified() && !FileTimeModified()) |
738 return; //-- nothing has changed in the file entry at all |
748 return; //-- nothing has changed in the file entry at all |
739 |
749 |
740 |
750 |
741 //-- read file dir. entry |
751 //-- read file dir. entry |
742 TFatDirEntry entry; |
752 TFatDirEntry entry; |
743 FatMount().ReadDirEntryL(iFileDosEntryPos,entry); |
753 FatMount().ReadDirEntryL(iFileDosEntryPos,entry); |
744 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
754 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
745 |
755 |
746 //-- the problem with KEntryAttModified here is that the file server uses this flag to |
756 //-- the problem with KEntryAttModified here is that the file server uses this flag to |
747 //-- deal with dirty file data. This means that this flag can be set even if there were no changes |
757 //-- deal with dirty file data. This means that this flag can be set even if there were no changes |
748 //-- in file time and attributes. Just check if any of the entry field has changed at all |
758 //-- in file time and attributes. Just check if any of the entry field has changed at all |
749 |
759 |
770 |
780 |
771 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH |
781 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH |
772 |
782 |
773 if(bUpdateDirEntry) |
783 if(bUpdateDirEntry) |
774 {//-- write entry to the media |
784 {//-- write entry to the media |
775 __PRINT(_L(" CFatFileCB::FlushAllL #1")); |
785 __PRINT(_L(" CFatFileCB::FlushAllL #1")); |
776 entry.SetAttributes(Att() & KEntryAttMaskSupported); |
786 entry.SetAttributes(Att() & KEntryAttMaskSupported); |
777 entry.SetSize(FCB_FileSize()); |
787 entry.SetSize(FCB_FileSize()); |
778 entry.SetTime(iModified, timeOffset); |
788 entry.SetTime(iModified, timeOffset); |
779 |
789 |
780 entry.SetStartCluster(FCB_StartCluster()); |
790 entry.SetStartCluster(FCB_StartCluster()); |
781 |
791 |
782 const TBool setNotify = FatMount().GetNotifyUser(); |
792 const TBool setNotify = FatMount().GetNotifyUser(); |
783 if(setNotify) |
793 if(setNotify) |
784 { |
794 { |
785 FatMount().SetNotifyOff(); // do not launch a notifier |
795 FatMount().SetNotifyOff(); // do not launch a notifier |
786 } |
796 } |
787 |
797 |
788 TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry)); |
798 TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry)); |
789 |
799 |
790 if(setNotify) |
800 if(setNotify) |
791 { |
801 { |
792 FatMount().SetNotifyOn(); |
802 FatMount().SetNotifyOn(); |
793 } |
803 } |
794 |
804 |
795 User::LeaveIfError(ret); |
805 User::LeaveIfError(ret); |
796 |
806 |
797 IndicateFileSizeModified(EFalse); |
807 IndicateFileSizeModified(EFalse); |
798 IndicateFileTimeModified(EFalse); |
808 IndicateFileTimeModified(EFalse); |
799 } |
809 } |
800 |
810 |
801 |
811 |
802 //-- KEntryAttModified must be reset anyway |
812 //-- KEntryAttModified must be reset anyway |
803 IndicateFileAttModified(EFalse); |
813 IndicateFileAttModified(EFalse); |
804 } |
814 } |
805 |
815 |
806 //----------------------------------------------------------------------------- |
816 //----------------------------------------------------------------------------- |
807 |
817 |
808 /** |
818 /** |
809 Rename already opened file. |
819 Rename already opened file. |
810 @param aNewName new file name; all trailing dots from the name will be removed |
820 @param aNewName new file name; all trailing dots from the name will be removed |
811 */ |
821 */ |
812 void CFatFileCB::RenameL(const TDesC& aNewName) |
822 void CFatFileCB::RenameL(const TDesC& aNewName) |
813 { |
823 { |
814 __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName); |
824 __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName); |
815 |
825 |
816 FatMount().CheckStateConsistentL(); |
826 FatMount().CheckStateConsistentL(); |
817 FatMount().CheckWritableL(); |
827 FatMount().CheckWritableL(); |
818 |
828 |
819 const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name |
829 const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name |
820 |
830 |
821 |
831 |
822 FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos); |
832 FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos); |
823 |
833 |
824 AllocBufferL(iFileName, fileName); |
834 AllocBufferL(iFileName, fileName); |
825 |
835 |
826 if(!FatMount().IsRuggedFSys()) |
836 if(!FatMount().IsRuggedFSys()) |
827 FAT().FlushL(); |
837 FAT().FlushL(); |
828 } |
838 } |
829 |
839 |
830 |
840 |
831 //*********************************************************** |
841 //*********************************************************** |
832 //* BlockMap interface |
842 //* BlockMap interface |
833 //*********************************************************** |
843 //*********************************************************** |
834 |
844 |
835 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos) |
845 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos) |
836 // |
846 // |
837 // Retrieves the block map of a given section of the file, in the FAT file system. |
847 // Retrieves the block map of a given section of the file, in the FAT file system. |
838 // |
848 // |
839 { |
849 { |
840 __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos); |
850 __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos); |
841 |
851 |
842 if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) ) |
852 if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) ) |
843 return KErrNotSupported; |
853 return KErrNotSupported; |
844 |
854 |
845 TUint startPos = I64LOW(aStartPos); |
855 TUint startPos = I64LOW(aStartPos); |
846 TUint endPos = I64LOW(aEndPos); |
856 TUint endPos = I64LOW(aEndPos); |
847 |
857 |
848 // aEndPos will always be >=0 at this point |
858 // aEndPos will always be >=0 at this point |
849 const TUint length = endPos - startPos; |
859 const TUint length = endPos - startPos; |
850 |
860 |
851 // Store the position of cluster zero in aInfo |
861 // Store the position of cluster zero in aInfo |
852 CFatMountCB& fatMount = FatMount(); |
862 CFatMountCB& fatMount = FatMount(); |
853 |
863 |
854 TInt drvNo=-1; |
864 TInt drvNo=-1; |
855 TBusLocalDrive* locDrv; |
865 TBusLocalDrive* locDrv; |
856 if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives)) |
866 if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives)) |
857 aInfo.iLocalDriveNumber=drvNo; |
867 aInfo.iLocalDriveNumber=drvNo; |
858 else |
868 else |
859 return KErrNotSupported; |
869 return KErrNotSupported; |
860 |
870 |
861 // Fetch the address of cluster 0 |
871 // Fetch the address of cluster 0 |
862 aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum); |
872 aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum); |
863 |
873 |
864 TRAPD(r, CheckPosL(startPos)); |
874 TRAPD(r, CheckPosL(startPos)); |
865 if (r != KErrNone) |
875 if (r != KErrNone) |
866 return r; |
876 return r; |
867 |
877 |
868 aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos); |
878 aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos); |
869 aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2(); |
879 aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2(); |
870 const TUint myStartPos = iCurrentPos.iPos; |
880 const TUint myStartPos = iCurrentPos.iPos; |
871 if ( myStartPos + length > FCB_FileSize()) |
881 if ( myStartPos + length > FCB_FileSize()) |
872 return KErrArgument; |
882 return KErrArgument; |
873 |
883 |
874 TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); |
884 TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); |
875 if (r != KErrNone) |
885 if (r != KErrNone) |
876 return r; |
886 return r; |
877 |
887 |
878 aStartPos = iCurrentPos.iPos; |
888 aStartPos = iCurrentPos.iPos; |
879 if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length))) |
889 if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length))) |
880 return KErrCompletion; |
890 return KErrCompletion; |
881 else |
891 else |
882 return KErrNone; |
892 return KErrNone; |
883 } |
893 } |
884 |
894 |
885 |
895 |
886 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) |
896 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) |
887 { |
897 { |
888 switch(aInterfaceId) |
898 switch(aInterfaceId) |
889 { |
899 { |
890 case EExtendedFileInterface: |
900 case EExtendedFileInterface: |
891 ((CFileCB::MExtendedFileInterface*&) aInterface) = this; |
901 ((CFileCB::MExtendedFileInterface*&) aInterface) = this; |
892 return KErrNone; |
902 return KErrNone; |
893 |
903 |
894 case EBlockMapInterface: |
904 case EBlockMapInterface: |
895 aInterface = (CFileCB::MBlockMapInterface*) this; |
905 aInterface = (CFileCB::MBlockMapInterface*) this; |
896 return KErrNone; |
906 return KErrNone; |
897 |
907 |
898 case EGetLocalDrive: |
908 case EGetLocalDrive: |
899 return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface); |
909 return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface); |
900 |
910 |
901 default: |
911 default: |
902 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput); |
912 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput); |
903 } |
913 } |
904 } |
914 } |
905 |
915 |
906 |
916 |
907 /** |
917 /** |
908 Overwrites file's start cluster (iStartCluster) in its directory entry. |
918 Overwrites file's start cluster (iStartCluster) in its directory entry. |
909 */ |
919 */ |
910 void CFatFileCB::FlushStartClusterL() |
920 void CFatFileCB::FlushStartClusterL() |
911 { |
921 { |
912 __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this); |
922 __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this); |
913 |
923 |
914 CFatMountCB& mount = FatMount(); |
924 CFatMountCB& mount = FatMount(); |
915 TFatDirEntry dirEntry; |
925 TFatDirEntry dirEntry; |
916 |
926 |
917 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
927 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
918 dirEntry.SetStartCluster(FCB_StartCluster()); //-- set new start cluster |
928 dirEntry.SetStartCluster(FCB_StartCluster()); //-- set new start cluster |
919 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
929 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
920 } |
930 } |
921 |
931 |
922 |
932 |
923 /** |
933 /** |
924 This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry. |
934 This is a RuggedFAT - specific method. Writes file size to the corresponding field of its file directory entry. |
925 */ |
935 */ |
926 void CFatFileCB::WriteFileSizeL(TUint aSize) |
936 void CFatFileCB::WriteFileSizeL(TUint aSize) |
927 { |
937 { |
928 __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize); |
938 __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize); |
929 |
939 |
930 CFatMountCB& mount = FatMount(); |
940 CFatMountCB& mount = FatMount(); |
931 TFatDirEntry dirEntry; |
941 TFatDirEntry dirEntry; |
932 |
942 |
933 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
943 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
934 dirEntry.SetSize(aSize); //-- set new size |
944 dirEntry.SetSize(aSize); //-- set new size |
|
945 |
|
946 // As we're updating the directory entry anyway, we might as well update the attributes & time |
|
947 // if these have been modified to save having to update them later... |
|
948 if (FileAttModified()) |
|
949 { |
|
950 dirEntry.SetAttributes(Att() & KEntryAttMaskSupported); |
|
951 IndicateFileAttModified(EFalse); |
|
952 IndicateFileTimeModified(ETrue); //-- this mirrors the behaviour of CFatFileCB::~CFatFileCB() |
|
953 } |
|
954 if (FileTimeModified()) |
|
955 { |
|
956 dirEntry.SetTime(iModified, FatMount().TimeOffset()); |
|
957 IndicateFileTimeModified(EFalse); |
|
958 } |
|
959 |
935 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
960 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
936 |
961 |
937 IndicateFileSizeModified(EFalse); |
962 IndicateFileSizeModified(EFalse); |
938 } |
963 } |
939 |
964 |