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); |
270 |
270 |
271 @leave on media read error |
271 @leave on media read error |
272 |
272 |
273 */ |
273 */ |
274 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) |
275 { |
275 { |
276 __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); |
277 |
277 |
278 // FAT supports 32 bits only for file size |
278 // FAT supports 32 bits only for file size |
279 TUint64 endPos = aPos + aLength; |
279 TUint64 endPos = aPos + aLength; |
280 if(endPos > KMaxSupportedFatFileSize) |
280 if(endPos > KMaxSupportedFatFileSize) |
281 User::Leave(KErrNotSupported); |
281 User::Leave(KErrNotSupported); |
282 |
282 |
283 FatMount().CheckStateConsistentL(); |
283 FatMount().CheckStateConsistentL(); |
284 FatMount().CheckWritableL(); |
284 FatMount().CheckWritableL(); |
285 const TUint pos = I64LOW(aPos); |
285 const TUint pos = I64LOW(aPos); |
286 CheckPosL(pos); |
286 CheckPosL(pos); |
287 |
287 |
288 const TUint startCluster = FCB_StartCluster(); |
288 const TUint startCluster = FCB_StartCluster(); |
289 const TUint length = (TUint)aLength; |
289 const TUint length = (TUint)aLength; |
290 |
290 |
291 endPos = iCurrentPos.iPos + length; |
291 endPos = iCurrentPos.iPos + length; |
292 if ((endPos > FCB_FileSize()) || |
292 if ((endPos > FCB_FileSize()) || |
293 (iCurrentPos.iPos > endPos) ) // Overflow condition |
293 (iCurrentPos.iPos > endPos) ) // Overflow condition |
294 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
294 DoSetSizeL(iCurrentPos.iPos+length,EFalse); |
295 |
295 |
296 TUint startPos=iCurrentPos.iPos; |
296 TUint startPos=iCurrentPos.iPos; |
297 TUint badcluster=0; |
297 TUint badcluster=0; |
298 TUint goodcluster=0; |
298 TUint goodcluster=0; |
299 |
299 |
300 TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0; |
300 TUint flag = DirectIOMode(aMessage) ? RLocalDrive::ELocDrvDirectIO : 0; |
301 |
301 |
302 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag)); |
302 TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster, flag)); |
303 |
303 |
304 if (ret == KErrCorrupt || ret == KErrDied) |
304 if (ret == KErrCorrupt || ret == KErrDied) |
305 { |
305 { |
306 if(startCluster == 0) |
306 if(startCluster == 0) |
307 { //Empty File, revert all the clusters allocated. |
307 { //Empty File, revert all the clusters allocated. |
308 const TUint32 cluster = FCB_StartCluster(); |
308 const TUint32 cluster = FCB_StartCluster(); |
309 FCB_SetStartCluster(0); |
309 FCB_SetStartCluster(0); |
310 FCB_SetFileSize(0); |
310 FCB_SetFileSize(0); |
311 IndicateFileSizeModified(ETrue); |
311 IndicateFileSizeModified(ETrue); |
312 |
312 |
313 FlushAllL(); |
313 FlushAllL(); |
314 |
314 |
315 iCurrentPos.iCluster = 0; |
315 iCurrentPos.iCluster = 0; |
316 iCurrentPos.iPos = 0; |
316 iCurrentPos.iPos = 0; |
317 |
317 |
318 FAT().FreeClusterListL(cluster); |
318 FAT().FreeClusterListL(cluster); |
319 FAT().FlushL(); |
319 FAT().FlushL(); |
320 } |
320 } |
321 else |
321 else |
322 { //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. |
323 const TUint curSize = FCB_FileSize(); |
323 const TUint curSize = FCB_FileSize(); |
324 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
324 TUint ClustersNeeded = curSize >> ClusterSizeLog2(); |
325 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
325 if(curSize > (ClustersNeeded << ClusterSizeLog2())) |
326 { |
326 { |
327 ClustersNeeded++; |
327 ClustersNeeded++; |
328 } |
328 } |
329 |
329 |
330 TUint32 cluster = FCB_StartCluster(); |
330 TUint32 cluster = FCB_StartCluster(); |
331 while(--ClustersNeeded) |
331 while(--ClustersNeeded) |
332 { |
332 { |
333 FAT().GetNextClusterL(cluster); |
333 FAT().GetNextClusterL(cluster); |
334 } |
334 } |
335 |
335 |
336 iCurrentPos.iCluster = cluster; |
336 iCurrentPos.iCluster = cluster; |
337 |
337 |
338 if (FAT().GetNextClusterL(cluster)) |
338 if (FAT().GetNextClusterL(cluster)) |
339 { |
339 { |
340 FAT().FreeClusterListL(cluster); |
340 FAT().FreeClusterListL(cluster); |
341 } |
341 } |
342 |
342 |
343 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
343 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
344 FAT().FlushL(); |
344 FAT().FlushL(); |
345 } |
345 } |
346 } |
346 } |
347 |
347 |
348 User::LeaveIfError(ret); |
348 User::LeaveIfError(ret); |
349 |
349 |
350 if(badcluster != 0) |
350 if(badcluster != 0) |
351 { |
351 { |
352 if(FCB_StartCluster() == badcluster) |
352 if(FCB_StartCluster() == badcluster) |
353 { |
353 { |
354 FCB_SetStartCluster(goodcluster); |
354 FCB_SetStartCluster(goodcluster); |
355 FlushStartClusterL(); |
355 FlushStartClusterL(); |
356 } |
356 } |
357 else |
357 else |
358 { |
358 { |
359 TUint32 aCluster = FCB_StartCluster(); |
359 TUint32 aCluster = FCB_StartCluster(); |
360 do |
360 do |
361 { |
361 { |
362 if((TUint)badcluster == FAT().ReadL(aCluster)) |
362 if((TUint)badcluster == FAT().ReadL(aCluster)) |
363 { |
363 { |
364 FAT().WriteL(aCluster, goodcluster); |
364 FAT().WriteL(aCluster, goodcluster); |
365 FAT().FlushL(); |
365 FAT().FlushL(); |
366 break; |
366 break; |
367 } |
367 } |
368 } |
368 } |
369 while(FAT().GetNextClusterL(aCluster)); |
369 while(FAT().GetNextClusterL(aCluster)); |
370 } |
370 } |
371 } |
371 } |
372 aLength=iCurrentPos.iPos-startPos; |
372 aLength=iCurrentPos.iPos-startPos; |
373 |
373 |
374 if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize()) |
374 if(!IsSequentialMode() && FatMount().IsRuggedFSys() && pos+(TUint)aLength > FCB_FileSize()) |
375 { |
375 { |
376 WriteFileSizeL(pos+aLength); |
376 WriteFileSizeL(pos+aLength); |
377 } |
377 } |
378 |
378 |
379 } |
379 } |
380 |
380 |
381 |
381 |
382 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) |
383 { |
383 { |
384 WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0); |
384 WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0); |
385 } |
385 } |
386 |
386 |
387 |
387 |
388 //----------------------------------------------------------------------------- |
388 //----------------------------------------------------------------------------- |
389 |
389 |
390 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize) |
390 void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize) |
391 // |
391 // |
392 // Resize the seek index to accomodate a larger or smaller filesize |
392 // Resize the seek index to accomodate a larger or smaller filesize |
393 // Assumes KSeekIndexSize is a power of 2. |
393 // Assumes KSeekIndexSize is a power of 2. |
394 // |
394 // |
395 { |
395 { |
396 |
396 |
397 TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult); |
397 TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult); |
398 |
398 |
399 |
399 |
400 TInt index=0; |
400 TInt index=0; |
401 TInt indexEnd=KSeekIndexSize; |
401 TInt indexEnd=KSeekIndexSize; |
402 TInt newValEnd=maxNewIndex; |
402 TInt newValEnd=maxNewIndex; |
403 |
403 |
404 if (iSeekIndexSize<aNewMult) |
404 if (iSeekIndexSize<aNewMult) |
405 { |
405 { |
406 TInt newVal=index; |
406 TInt newVal=index; |
407 TInt step=1<<(aNewMult-iSeekIndexSize); |
407 TInt step=1<<(aNewMult-iSeekIndexSize); |
408 index+=step-1; |
408 index+=step-1; |
409 while(index<indexEnd && newVal<newValEnd) |
409 while(index<indexEnd && newVal<newValEnd) |
410 { |
410 { |
411 iSeekIndex[newVal] = iSeekIndex[index]; |
411 iSeekIndex[newVal] = iSeekIndex[index]; |
412 newVal++; |
412 newVal++; |
413 index+=step; |
413 index+=step; |
414 } |
414 } |
415 while(newVal<indexEnd) |
415 while(newVal<indexEnd) |
416 iSeekIndex[newVal++] = 0; |
416 iSeekIndex[newVal++] = 0; |
417 } |
417 } |
418 else |
418 else |
419 { |
419 { |
420 TInt diffSize = iSeekIndexSize-aNewMult; |
420 TInt diffSize = iSeekIndexSize-aNewMult; |
421 TInt oldVal=(KSeekIndexSize>>diffSize) - 1; |
421 TInt oldVal=(KSeekIndexSize>>diffSize) - 1; |
422 TInt newVal=indexEnd-1; |
422 TInt newVal=indexEnd-1; |
423 TInt skip=(1<<diffSize)-1; |
423 TInt skip=(1<<diffSize)-1; |
424 |
424 |
425 if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2) |
425 if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2) |
426 { |
426 { |
427 ClearIndex(0); //-- Invalidate every entry. |
427 ClearIndex(0); //-- Invalidate every entry. |
428 } |
428 } |
429 else |
429 else |
430 { |
430 { |
431 while(newVal>=index) |
431 while(newVal>=index) |
432 { |
432 { |
433 |
433 |
434 iSeekIndex[newVal--] = iSeekIndex[oldVal--]; |
434 iSeekIndex[newVal--] = iSeekIndex[oldVal--]; |
435 |
435 |
436 |
436 |
437 for(TInt i=skip;i>0;i--) |
437 for(TInt i=skip;i>0;i--) |
438 { |
438 { |
439 iSeekIndex[newVal--] = 0; |
439 iSeekIndex[newVal--] = 0; |
440 |
440 |
441 } |
441 } |
442 } |
442 } |
443 } |
443 } |
444 } |
444 } |
445 iSeekIndexSize=aNewMult; |
445 iSeekIndexSize=aNewMult; |
446 } |
446 } |
447 |
447 |
448 |
448 |
449 /** |
449 /** |
450 Zero freed clusters in the index |
450 Zero freed clusters in the index |
451 |
451 |
452 @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. |
453 if = 0 all existing index will be zero filled |
453 if = 0 all existing index will be zero filled |
454 */ |
454 */ |
455 void CFatFileCB::ClearIndex(TUint aNewSize) |
455 void CFatFileCB::ClearIndex(TUint aNewSize) |
456 { |
456 { |
457 |
457 |
458 if (!iSeekIndex) |
458 if (!iSeekIndex) |
459 return; |
459 return; |
460 |
460 |
461 if(aNewSize==0) |
461 if(aNewSize==0) |
462 { |
462 { |
463 //-- zero fill all the array |
463 //-- zero fill all the array |
464 Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32)); |
464 Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32)); |
465 return; |
465 return; |
466 } |
466 } |
467 |
467 |
468 // 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 |
469 // cluster. So the entry for that position must also be invalidated |
469 // cluster. So the entry for that position must also be invalidated |
470 aNewSize--; |
470 aNewSize--; |
471 TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2()); |
471 TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2()); |
472 |
472 |
473 TInt indexLen=KSeekIndexSize-firstInvalidIndex; |
473 TInt indexLen=KSeekIndexSize-firstInvalidIndex; |
474 |
474 |
475 Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32)); |
475 Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32)); |
476 } |
476 } |
477 |
477 |
478 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize) |
478 TInt CFatFileCB::CalcSeekIndexSize(TUint aSize) |
479 // |
479 // |
480 // Find the nearest power of 2 > aSize |
480 // Find the nearest power of 2 > aSize |
481 // |
481 // |
482 { |
482 { |
483 TInt count = 0; |
483 TInt count = 0; |
484 const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128 |
484 const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128 |
485 if (aSize<=indexSize) |
485 if (aSize<=indexSize) |
486 return(count); |
486 return(count); |
487 |
487 |
488 while((aSize>>=1)>0) |
488 while((aSize>>=1)>0) |
489 { |
489 { |
490 count++; |
490 count++; |
491 } |
491 } |
492 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
492 return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1); |
493 } |
493 } |
494 |
494 |
495 //----------------------------------------------------------------------------- |
495 //----------------------------------------------------------------------------- |
496 /** |
496 /** |
497 Set file size. |
497 Set file size. |
498 @param aSize new file size. |
498 @param aSize new file size. |
499 */ |
499 */ |
500 void CFatFileCB::SetSizeL(TInt64 aSize) |
500 void CFatFileCB::SetSizeL(TInt64 aSize) |
501 { |
501 { |
502 __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); |
502 __PRINT2(_L("CFatFileCB::SetSizeL[0x%x] sz=%LU"), this, aSize); |
503 |
503 |
504 //-- max. file size for FAT is 4GB-1 |
504 //-- max. file size for FAT is 4GB-1 |
505 if (I64HIGH(aSize)) |
505 if (I64HIGH(aSize)) |
506 User::Leave(KErrNotSupported); |
506 User::Leave(KErrNotSupported); |
507 |
507 |
508 DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); |
508 DoSetSizeL(I64LOW(aSize), FatMount().IsRuggedFSys()); |
509 } |
509 } |
510 |
510 |
511 |
511 |
512 void CFatFileCB::SetSizeL(TInt aSize) |
512 void CFatFileCB::SetSizeL(TInt aSize) |
513 { |
513 { |
514 SetSizeL(TInt64(aSize)); |
514 SetSizeL(TInt64(aSize)); |
515 } |
515 } |
516 |
516 |
517 //----------------------------------------------------------------------------- |
517 //----------------------------------------------------------------------------- |
518 /** |
518 /** |
519 Shrink file to zero size. |
519 Shrink file to zero size. |
520 */ |
520 */ |
521 void CFatFileCB::DoShrinkFileToZeroSizeL() |
521 void CFatFileCB::DoShrinkFileToZeroSizeL() |
522 { |
522 { |
523 ASSERT(FCB_FileSize()); |
523 ASSERT(FCB_FileSize()); |
524 ASSERT(FileSizeModified()); |
524 ASSERT(FileSizeModified()); |
525 |
525 |
526 ClearIndex(0); // Clear seek index array |
526 ClearIndex(0); // Clear seek index array |
527 |
527 |
528 //-- update file dir. entry |
528 //-- update file dir. entry |
529 const TUint32 cluster = FCB_StartCluster(); |
529 const TUint32 cluster = FCB_StartCluster(); |
530 FCB_SetStartCluster(0); |
530 FCB_SetStartCluster(0); |
531 FCB_SetFileSize(0); |
531 FCB_SetFileSize(0); |
532 FlushAllL(); |
532 FlushAllL(); |
533 |
533 |
534 //-- free cluster list. |
534 //-- free cluster list. |
535 CheckPosL(0); |
535 CheckPosL(0); |
536 FAT().FreeClusterListL(cluster); |
536 FAT().FreeClusterListL(cluster); |
537 FAT().FlushL(); |
537 FAT().FlushL(); |
538 } |
538 } |
539 |
539 |
540 //----------------------------------------------------------------------------- |
540 //----------------------------------------------------------------------------- |
541 /* |
541 /* |
542 Shrink file to smaller size, but > 0 |
542 Shrink file to smaller size, but > 0 |
543 |
543 |
544 @param aNewSize new file size |
544 @param aNewSize new file size |
545 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
545 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
546 */ |
546 */ |
547 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
547 void CFatFileCB::DoShrinkFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
548 { |
548 { |
549 ASSERT(FileSizeModified()); |
549 ASSERT(FileSizeModified()); |
550 ASSERT(FCB_FileSize() > aNewSize && aNewSize); |
550 ASSERT(FCB_FileSize() > aNewSize && aNewSize); |
551 |
551 |
552 if(aForceCachesFlush) |
552 if(aForceCachesFlush) |
553 WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry |
553 WriteFileSizeL(aNewSize); //-- write file size directly to its dir. entry |
554 |
554 |
555 CheckPosL(aNewSize); |
555 CheckPosL(aNewSize); |
556 |
556 |
557 TUint32 cluster=iCurrentPos.iCluster; |
557 TUint32 cluster=iCurrentPos.iCluster; |
558 if (FAT().GetNextClusterL(cluster)) |
558 |
559 {//-- truncate the cluster chain |
559 if (FAT().GetNextClusterL(cluster)) |
560 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
560 {//-- truncate the cluster chain |
561 FAT().FreeClusterListL(cluster); |
561 FAT().WriteFatEntryEofL(iCurrentPos.iCluster); |
562 } |
562 FAT().FreeClusterListL(cluster); |
563 |
563 } |
|
564 |
564 ClearIndex(aNewSize); |
565 ClearIndex(aNewSize); |
565 FAT().FlushL(); |
566 FAT().FlushL(); |
566 } |
567 } |
567 |
568 |
568 //----------------------------------------------------------------------------- |
569 //----------------------------------------------------------------------------- |
569 /** |
570 /** |
570 Expand a file. |
571 Expand a file. |
571 |
572 |
572 @param aNewSize new file size. |
573 @param aNewSize new file size. |
573 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
574 @param aForceCachesFlush if ETrue, all file/FAT caches will be flushed |
574 */ |
575 */ |
575 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
576 void CFatFileCB::DoExpandFileL(TUint32 aNewSize, TBool aForceCachesFlush) |
576 { |
577 { |
577 ASSERT(FCB_FileSize() < aNewSize); |
578 ASSERT(FCB_FileSize() < aNewSize); |
578 ASSERT(FileSizeModified()); |
579 ASSERT(FileSizeModified()); |
579 |
580 |
580 const TUint32 KClusterSzLog2 = ClusterSizeLog2(); |
581 const TUint32 KClusterSzLog2 = ClusterSizeLog2(); |
581 const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
582 const TUint32 newSizeClusters = (TUint32)(((TUint64)aNewSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
582 |
583 |
583 |
584 |
584 //-- expanding a file |
585 //-- expanding a file |
585 if (FCB_StartCluster() == 0) |
586 if (FCB_StartCluster() == 0) |
586 {//-- the initial file size is 0 (no cluster chain) |
587 {//-- the initial file size is 0 (no cluster chain) |
587 |
588 |
588 ClearIndex(0); //-- clear seek index array |
589 ClearIndex(0); //-- clear seek index array |
589 //-- 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 |
590 const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); |
591 const TUint32 tempStartCluster=FAT().AllocateClusterListL(newSizeClusters, FAT().FreeClusterHint()); |
591 FAT().FlushL(); |
592 FAT().FlushL(); |
592 |
593 |
593 iCurrentPos.iCluster=tempStartCluster; |
594 iCurrentPos.iCluster=tempStartCluster; |
594 FCB_SetStartCluster(tempStartCluster); |
595 FCB_SetStartCluster(tempStartCluster); |
595 FCB_SetFileSize(aNewSize); |
596 FCB_SetFileSize(aNewSize); |
596 FlushAllL(); |
597 FlushAllL(); |
597 } |
598 } |
598 else |
599 else |
599 { |
600 { |
600 const TUint curSize = FCB_FileSize(); |
601 const TUint curSize = FCB_FileSize(); |
601 const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
602 const TUint32 oldSizeClusters = ((curSize + Pow2(KClusterSzLog2) - 1) >> KClusterSzLog2); |
602 ASSERT(newSizeClusters >= oldSizeClusters); |
603 ASSERT(newSizeClusters >= oldSizeClusters); |
603 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 |
604 if (newClusters) |
605 if (newClusters) |
605 { |
606 { |
606 TEntryPos currentPos=iCurrentPos; |
607 TEntryPos currentPos=iCurrentPos; |
607 CheckPosL(FCB_FileSize()); |
608 CheckPosL(FCB_FileSize()); |
608 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
609 FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster); |
609 iCurrentPos=currentPos; |
610 iCurrentPos=currentPos; |
610 } |
611 } |
611 |
612 |
612 FAT().FlushL(); |
613 FAT().FlushL(); |
613 |
614 |
614 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 |
615 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 |
616 } |
617 } |
617 |
618 |
618 } |
619 } |
619 |
620 |
620 //----------------------------------------------------------------------------- |
621 //----------------------------------------------------------------------------- |
621 /** |
622 /** |
622 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. |
623 @param aSize new file size |
624 @param aSize new file size |
624 @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. |
625 it is used in Rugged FAT mode. |
626 it is used in Rugged FAT mode. |
626 */ |
627 */ |
627 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) |
628 void CFatFileCB::DoSetSizeL(TUint aSize, TBool aForceCachesFlush) |
628 { |
629 { |
629 __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); |
630 |
631 |
631 FatMount().CheckStateConsistentL(); |
632 FatMount().CheckStateConsistentL(); |
632 FatMount().CheckWritableL(); |
633 FatMount().CheckWritableL(); |
633 |
634 |
634 |
635 |
635 // Can not change the file size if it is clamped |
636 // Can not change the file size if it is clamped |
636 if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) |
637 if(Mount().IsFileClamped(MAKE_TINT64(0,FCB_StartCluster())) > 0) |
637 User::Leave(KErrInUse); |
638 User::Leave(KErrInUse); |
638 |
639 |
639 if(aSize == FCB_FileSize()) |
640 if(aSize == FCB_FileSize()) |
640 return; |
641 return; |
641 |
642 |
642 IndicateFileSizeModified(ETrue); |
643 IndicateFileSizeModified(ETrue); |
|
644 IndicateFileAttModified(ETrue); // ensure file size is flushed |
643 |
645 |
644 TInt newIndexMult=CalcSeekIndexSize(aSize); |
646 TInt newIndexMult=CalcSeekIndexSize(aSize); |
645 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
647 if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize) |
646 ResizeIndex(newIndexMult,aSize); |
648 ResizeIndex(newIndexMult,aSize); |
647 |
649 |
677 @param aSetAttMask file attributes OR mask |
679 @param aSetAttMask file attributes OR mask |
678 @param aClearAttMask file attributes AND mask |
680 @param aClearAttMask file attributes AND mask |
679 |
681 |
680 */ |
682 */ |
681 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
683 void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask) |
682 { |
684 { |
683 __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this); |
685 __PRINT1(_L("CFatFileCB::SetEntryL[0x%x]"), this); |
684 |
686 |
685 FatMount().CheckStateConsistentL(); |
687 FatMount().CheckStateConsistentL(); |
686 FatMount().CheckWritableL(); |
688 FatMount().CheckWritableL(); |
687 |
689 |
688 //-- change file attributes |
690 //-- change file attributes |
689 const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set |
691 const TUint setAttMask = (aSetAttMask & KEntryAttMaskSupported); //-- supported attributes to set |
690 TUint newAtt = Att(); |
692 TUint oldAtt = Att(); |
|
693 TUint newAtt = oldAtt; |
691 |
694 |
692 if (setAttMask|aClearAttMask) |
695 if (setAttMask|aClearAttMask) |
693 { |
696 { |
694 newAtt |= setAttMask; |
697 newAtt |= setAttMask; |
695 newAtt &= ~aClearAttMask; |
698 newAtt &= ~aClearAttMask; |
696 SetAtt(newAtt); |
699 if (newAtt != oldAtt) |
697 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
700 { |
|
701 SetAtt(newAtt); |
|
702 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
|
703 } |
698 } |
704 } |
699 |
705 |
700 //-- set file entry modification time if required |
706 //-- set file entry modification time if required |
701 if (aSetAttMask&KEntryAttModified) |
707 if (aSetAttMask&KEntryAttModified) |
702 { |
708 { |
703 SetModified(aTime); //-- set file modified time |
709 SetModified(aTime); //-- set file modified time |
704 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
710 IndicateFileAttModified(ETrue); //-- indicate that file attributes have changed |
705 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 |
706 } |
712 } |
707 |
713 |
708 } |
714 } |
709 |
715 |
710 |
716 |
711 //----------------------------------------------------------------------------- |
717 //----------------------------------------------------------------------------- |
712 /** |
718 /** |
713 The same as FlushAllL(). This method is called from RFile::Flush() |
719 The same as FlushAllL(). This method is called from RFile::Flush() |
714 */ |
720 */ |
715 void CFatFileCB::FlushDataL() |
721 void CFatFileCB::FlushDataL() |
716 { |
722 { |
717 __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this); |
723 __PRINT1(_L("CFatFileCB::FlushDataL[0x%x]"), this); |
718 FlushAllL(); |
724 FlushAllL(); |
719 } |
725 } |
720 |
726 |
721 //----------------------------------------------------------------------------- |
727 //----------------------------------------------------------------------------- |
722 /** |
728 /** |
723 Flush the fide directory entry data: files size, attributes, time etc. |
729 Flush the fide directory entry data: files size, attributes, time etc. |
724 */ |
730 */ |
725 void CFatFileCB::FlushAllL() |
731 void CFatFileCB::FlushAllL() |
726 { |
732 { |
727 |
733 |
728 //-- 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. |
729 //-- 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. |
730 //-- file size, start cluster, attributes and modification timestamp |
736 //-- file size, start cluster, attributes and modification timestamp |
731 #define ALWAYS_UPDATE_ENTRY_ON_FLUSH |
737 #define ALWAYS_UPDATE_ENTRY_ON_FLUSH |
732 |
738 |
733 __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this); |
739 __PRINT1(_L("CFatFileCB::FlushAllL[0x%x]"), this); |
734 |
740 |
735 if (Mount().IsCurrentMount()==EFalse) |
741 if (Mount().IsCurrentMount()==EFalse) |
736 User::Leave(KErrDisMounted); |
742 User::Leave(KErrDisMounted); |
737 |
743 |
738 FatMount().CheckStateConsistentL(); |
744 FatMount().CheckStateConsistentL(); |
739 FatMount().CheckWritableL(); |
745 FatMount().CheckWritableL(); |
740 |
746 |
741 if(!FileSizeModified() && !FileAttModified() && !FileTimeModified()) |
747 if(!FileSizeModified() && !FileAttModified() && !FileTimeModified()) |
742 return; //-- nothing has changed in the file entry at all |
748 return; //-- nothing has changed in the file entry at all |
743 |
749 |
744 |
750 |
745 //-- read file dir. entry |
751 //-- read file dir. entry |
746 TFatDirEntry entry; |
752 TFatDirEntry entry; |
747 FatMount().ReadDirEntryL(iFileDosEntryPos,entry); |
753 FatMount().ReadDirEntryL(iFileDosEntryPos,entry); |
748 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
754 __ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt)); |
749 |
755 |
750 //-- 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 |
751 //-- 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 |
752 //-- 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 |
753 |
759 |
774 |
780 |
775 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH |
781 #endif //#ifndef ALWAYS_UPDATE_ENTRY_TS_ON_FLUSH |
776 |
782 |
777 if(bUpdateDirEntry) |
783 if(bUpdateDirEntry) |
778 {//-- write entry to the media |
784 {//-- write entry to the media |
779 __PRINT(_L(" CFatFileCB::FlushAllL #1")); |
785 __PRINT(_L(" CFatFileCB::FlushAllL #1")); |
780 entry.SetAttributes(Att() & KEntryAttMaskSupported); |
786 entry.SetAttributes(Att() & KEntryAttMaskSupported); |
781 entry.SetSize(FCB_FileSize()); |
787 entry.SetSize(FCB_FileSize()); |
782 entry.SetTime(iModified, timeOffset); |
788 entry.SetTime(iModified, timeOffset); |
783 |
789 |
784 entry.SetStartCluster(FCB_StartCluster()); |
790 entry.SetStartCluster(FCB_StartCluster()); |
785 |
791 |
786 const TBool setNotify = FatMount().GetNotifyUser(); |
792 const TBool setNotify = FatMount().GetNotifyUser(); |
787 if(setNotify) |
793 if(setNotify) |
788 { |
794 { |
789 FatMount().SetNotifyOff(); // do not launch a notifier |
795 FatMount().SetNotifyOff(); // do not launch a notifier |
790 } |
796 } |
791 |
797 |
792 TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry)); |
798 TRAPD(ret, FatMount().WriteDirEntryL(iFileDosEntryPos,entry)); |
793 |
799 |
794 if(setNotify) |
800 if(setNotify) |
795 { |
801 { |
796 FatMount().SetNotifyOn(); |
802 FatMount().SetNotifyOn(); |
797 } |
803 } |
798 |
804 |
799 User::LeaveIfError(ret); |
805 User::LeaveIfError(ret); |
800 |
806 |
801 IndicateFileSizeModified(EFalse); |
807 IndicateFileSizeModified(EFalse); |
802 IndicateFileTimeModified(EFalse); |
808 IndicateFileTimeModified(EFalse); |
803 } |
809 } |
804 |
810 |
805 |
811 |
806 //-- KEntryAttModified must be reset anyway |
812 //-- KEntryAttModified must be reset anyway |
807 IndicateFileAttModified(EFalse); |
813 IndicateFileAttModified(EFalse); |
808 } |
814 } |
809 |
815 |
810 //----------------------------------------------------------------------------- |
816 //----------------------------------------------------------------------------- |
811 |
817 |
812 /** |
818 /** |
813 Rename already opened file. |
819 Rename already opened file. |
814 @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 |
815 */ |
821 */ |
816 void CFatFileCB::RenameL(const TDesC& aNewName) |
822 void CFatFileCB::RenameL(const TDesC& aNewName) |
817 { |
823 { |
818 __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName); |
824 __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName); |
819 |
825 |
820 FatMount().CheckStateConsistentL(); |
826 FatMount().CheckStateConsistentL(); |
821 FatMount().CheckWritableL(); |
827 FatMount().CheckWritableL(); |
822 |
828 |
823 const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name |
829 const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name |
824 |
830 |
825 |
831 |
826 FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos); |
832 FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename, iFileDosEntryPos); |
827 |
833 |
828 AllocBufferL(iFileName, fileName); |
834 AllocBufferL(iFileName, fileName); |
829 |
835 |
830 if(!FatMount().IsRuggedFSys()) |
836 if(!FatMount().IsRuggedFSys()) |
831 FAT().FlushL(); |
837 FAT().FlushL(); |
832 } |
838 } |
833 |
839 |
834 |
840 |
835 //*********************************************************** |
841 //*********************************************************** |
836 //* BlockMap interface |
842 //* BlockMap interface |
837 //*********************************************************** |
843 //*********************************************************** |
838 |
844 |
839 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos) |
845 TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos) |
840 // |
846 // |
841 // 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. |
842 // |
848 // |
843 { |
849 { |
844 __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos); |
850 __PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos); |
845 |
851 |
846 if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) ) |
852 if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) ) |
847 return KErrNotSupported; |
853 return KErrNotSupported; |
848 |
854 |
849 TUint startPos = I64LOW(aStartPos); |
855 TUint startPos = I64LOW(aStartPos); |
850 TUint endPos = I64LOW(aEndPos); |
856 TUint endPos = I64LOW(aEndPos); |
851 |
857 |
852 // aEndPos will always be >=0 at this point |
858 // aEndPos will always be >=0 at this point |
853 const TUint length = endPos - startPos; |
859 const TUint length = endPos - startPos; |
854 |
860 |
855 // Store the position of cluster zero in aInfo |
861 // Store the position of cluster zero in aInfo |
856 CFatMountCB& fatMount = FatMount(); |
862 CFatMountCB& fatMount = FatMount(); |
857 |
863 |
858 TInt drvNo=-1; |
864 TInt drvNo=-1; |
859 TBusLocalDrive* locDrv; |
865 TBusLocalDrive* locDrv; |
860 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)) |
861 aInfo.iLocalDriveNumber=drvNo; |
867 aInfo.iLocalDriveNumber=drvNo; |
862 else |
868 else |
863 return KErrNotSupported; |
869 return KErrNotSupported; |
864 |
870 |
865 // Fetch the address of cluster 0 |
871 // Fetch the address of cluster 0 |
866 aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum); |
872 aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum); |
867 |
873 |
868 TRAPD(r, CheckPosL(startPos)); |
874 TRAPD(r, CheckPosL(startPos)); |
869 if (r != KErrNone) |
875 if (r != KErrNone) |
870 return r; |
876 return r; |
871 |
877 |
872 aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos); |
878 aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos); |
873 aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2(); |
879 aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2(); |
874 const TUint myStartPos = iCurrentPos.iPos; |
880 const TUint myStartPos = iCurrentPos.iPos; |
875 if ( myStartPos + length > FCB_FileSize()) |
881 if ( myStartPos + length > FCB_FileSize()) |
876 return KErrArgument; |
882 return KErrArgument; |
877 |
883 |
878 TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); |
884 TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo)); |
879 if (r != KErrNone) |
885 if (r != KErrNone) |
880 return r; |
886 return r; |
881 |
887 |
882 aStartPos = iCurrentPos.iPos; |
888 aStartPos = iCurrentPos.iPos; |
883 if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length))) |
889 if ((I64LOW(aStartPos) == FCB_FileSize()) || ( I64LOW(aStartPos) == (myStartPos + length))) |
884 return KErrCompletion; |
890 return KErrCompletion; |
885 else |
891 else |
886 return KErrNone; |
892 return KErrNone; |
887 } |
893 } |
888 |
894 |
889 |
895 |
890 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) |
896 TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput) |
891 { |
897 { |
892 switch(aInterfaceId) |
898 switch(aInterfaceId) |
893 { |
899 { |
894 case EExtendedFileInterface: |
900 case EExtendedFileInterface: |
895 ((CFileCB::MExtendedFileInterface*&) aInterface) = this; |
901 ((CFileCB::MExtendedFileInterface*&) aInterface) = this; |
896 return KErrNone; |
902 return KErrNone; |
897 |
903 |
898 case EBlockMapInterface: |
904 case EBlockMapInterface: |
899 aInterface = (CFileCB::MBlockMapInterface*) this; |
905 aInterface = (CFileCB::MBlockMapInterface*) this; |
900 return KErrNone; |
906 return KErrNone; |
901 |
907 |
902 case EGetLocalDrive: |
908 case EGetLocalDrive: |
903 return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface); |
909 return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface); |
904 |
910 |
905 default: |
911 default: |
906 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput); |
912 return CFileCB::GetInterface(aInterfaceId,aInterface,aInput); |
907 } |
913 } |
908 } |
914 } |
909 |
915 |
910 |
916 |
911 /** |
917 /** |
912 Overwrites file's start cluster (iStartCluster) in its directory entry. |
918 Overwrites file's start cluster (iStartCluster) in its directory entry. |
913 */ |
919 */ |
914 void CFatFileCB::FlushStartClusterL() |
920 void CFatFileCB::FlushStartClusterL() |
915 { |
921 { |
916 __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this); |
922 __PRINT1(_L("CFatFileCB::FlushStartClusterL[0x%x]"), this); |
917 |
923 |
918 CFatMountCB& mount = FatMount(); |
924 CFatMountCB& mount = FatMount(); |
919 TFatDirEntry dirEntry; |
925 TFatDirEntry dirEntry; |
920 |
926 |
921 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
927 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
922 dirEntry.SetStartCluster(FCB_StartCluster()); //-- set new start cluster |
928 dirEntry.SetStartCluster(FCB_StartCluster()); //-- set new start cluster |
923 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
929 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
924 } |
930 } |
925 |
931 |
926 |
932 |
927 /** |
933 /** |
928 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. |
929 */ |
935 */ |
930 void CFatFileCB::WriteFileSizeL(TUint aSize) |
936 void CFatFileCB::WriteFileSizeL(TUint aSize) |
931 { |
937 { |
932 __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize); |
938 __PRINT2(_L("CFatFileCB::WriteFileSizeL[0x%x], sz:%d"), this, aSize); |
933 |
939 |
934 CFatMountCB& mount = FatMount(); |
940 CFatMountCB& mount = FatMount(); |
935 TFatDirEntry dirEntry; |
941 TFatDirEntry dirEntry; |
936 |
942 |
937 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
943 mount.ReadDirEntryL(iFileDosEntryPos, dirEntry); //-- read this file's dir. entry |
938 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 |
939 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
960 mount.WriteDirEntryL(iFileDosEntryPos, dirEntry);//-- write the entry back |
940 |
961 |
941 IndicateFileSizeModified(EFalse); |
962 IndicateFileSizeModified(EFalse); |
942 } |
963 } |
943 |
964 |