os/kernelhwsrv/userlibandfileserver/fileserver/sfat32/sl_file.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\sfat\sl_file.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "sl_std.h"
sl@0
    19
#include "sl_cache.h"
sl@0
    20
#include <e32math.h>
sl@0
    21
sl@0
    22
const TInt KSeekIndexSize=128; // Cache 128 clusters
sl@0
    23
const TInt KSeekIndexSizeLog2=7;
sl@0
    24
const TInt KFirstClusterNum=2;
sl@0
    25
sl@0
    26
CFatFileCB::CFatFileCB()
sl@0
    27
	{
sl@0
    28
sl@0
    29
	__PRINT1(_L("CFatFileCB created 0x%x"),this);
sl@0
    30
	}
sl@0
    31
sl@0
    32
CFatFileCB::~CFatFileCB()
sl@0
    33
	{
sl@0
    34
	__PRINT1(_L("CFatFileCB deleted 0x%x"),this);
sl@0
    35
sl@0
    36
    //-- a nasty trick to find out if the CFatFileCB is in consistent state on the moment of destruction.
sl@0
    37
    //-- Because of OOM conditions CFatFileCB might not be fully constructed and to be deleted, while FlushAll()
sl@0
    38
    //-- implies valid iMount.
sl@0
    39
    const CMountCB* pMount  = &Mount();
sl@0
    40
    if(pMount)
sl@0
    41
        {//-- do some finalisation work if CMountCB is valid
sl@0
    42
        if (iAtt&KEntryAttModified)
sl@0
    43
            TRAP_IGNORE(FlushAllL());
sl@0
    44
        }
sl@0
    45
sl@0
    46
    delete[] iSeekIndex;
sl@0
    47
	}
sl@0
    48
sl@0
    49
sl@0
    50
void CFatFileCB::CreateSeekIndex()
sl@0
    51
//
sl@0
    52
// Create a seek index
sl@0
    53
//
sl@0
    54
	{
sl@0
    55
sl@0
    56
	iSeekIndex = new TUint32[KSeekIndexSize];
sl@0
    57
	if (iSeekIndex == NULL)
sl@0
    58
		return;
sl@0
    59
sl@0
    60
	Mem::FillZ(iSeekIndex, sizeof(TUint32) * KSeekIndexSize);
sl@0
    61
sl@0
    62
	iSeekIndexSize=CalcSeekIndexSize(Size());
sl@0
    63
	}
sl@0
    64
sl@0
    65
TInt CFatFileCB::SeekToPosition(TInt aNewRelCluster,TInt aClusterOffset)
sl@0
    66
//
sl@0
    67
// Use the seek index to set iCurrentPos.iCluster as close as possible to aNewRelCluster
sl@0
    68
// Return aNewRelCluster-aCurrentPos.iCluster
sl@0
    69
//
sl@0
    70
	{
sl@0
    71
	TInt clusterOffset=aClusterOffset;
sl@0
    72
	TInt seekPos=(aNewRelCluster>>iSeekIndexSize)-1;
sl@0
    73
	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
sl@0
    74
sl@0
    75
	while(seekPos>=0 && iSeekIndex[seekPos]==0 && clusterOffset!=0)
sl@0
    76
		{
sl@0
    77
		seekPos--;
sl@0
    78
		clusterOffset--;
sl@0
    79
		}
sl@0
    80
	if (clusterOffset==0) // Counted back to the current cluster
sl@0
    81
		return(aClusterOffset);
sl@0
    82
	if (seekPos<0)
sl@0
    83
		{
sl@0
    84
		iCurrentPos.iCluster=iStartCluster;
sl@0
    85
		return(aNewRelCluster);
sl@0
    86
		}
sl@0
    87
sl@0
    88
	iCurrentPos.iCluster=iSeekIndex[seekPos];
sl@0
    89
	return(aNewRelCluster-((seekPos+1)<<iSeekIndexSize));
sl@0
    90
	}
sl@0
    91
sl@0
    92
void CFatFileCB::SetSeekIndexValueL(TInt aRelCluster,TInt aStoredCluster)
sl@0
    93
//
sl@0
    94
// Sets a value in the seekindex
sl@0
    95
//
sl@0
    96
	{
sl@0
    97
sl@0
    98
	TInt seekPos=(aRelCluster>>iSeekIndexSize)-1;
sl@0
    99
	__ASSERT_DEBUG(seekPos<KSeekIndexSize,Fault(EFatFileSeekIndexTooSmall));
sl@0
   100
	__ASSERT_DEBUG(seekPos>=0,Fault(EFatFileSeekIndexTooSmall2));
sl@0
   101
	iSeekIndex[seekPos] = aStoredCluster;
sl@0
   102
	}
sl@0
   103
sl@0
   104
TBool CFatFileCB::IsSeekBackwards(TUint aPos)
sl@0
   105
//
sl@0
   106
// Return true if aPos<currentPos
sl@0
   107
//
sl@0
   108
	{
sl@0
   109
	
sl@0
   110
	TUint cluster=iCurrentPos.iCluster<<ClusterSizeLog2();
sl@0
   111
	TInt offset=ClusterRelativePos(iCurrentPos.iPos);
sl@0
   112
	TUint currentPos=cluster+offset;
sl@0
   113
	return(aPos<currentPos);
sl@0
   114
	}
sl@0
   115
sl@0
   116
void CFatFileCB::CheckPosL(TUint aPos)
sl@0
   117
//
sl@0
   118
// Check that the file is positioned correctly.
sl@0
   119
// If aPos<currentPos attempt to guess the new position.
sl@0
   120
//
sl@0
   121
	{
sl@0
   122
	__PRINT1(_L("CFatFileCB::CheckPosL(%d)"), aPos);
sl@0
   123
	if (aPos==iCurrentPos.iPos)
sl@0
   124
		return;
sl@0
   125
    __ASSERT_DEBUG(aPos <= (TUint)Size(), Fault(EFatFilePosBeyondEnd));
sl@0
   126
sl@0
   127
	if (iFileSizeModified && IsSeekBackwards(aPos))
sl@0
   128
		FlushDataL(); 
sl@0
   129
	
sl@0
   130
	TUint newRelCluster=aPos>>ClusterSizeLog2();
sl@0
   131
	if ( aPos && (aPos==(newRelCluster<<ClusterSizeLog2())) )
sl@0
   132
		newRelCluster--;
sl@0
   133
	TUint oldRelCluster=iCurrentPos.iPos>>ClusterSizeLog2();
sl@0
   134
	if ( iCurrentPos.iPos && (iCurrentPos.iPos==(oldRelCluster<<ClusterSizeLog2())) )
sl@0
   135
		oldRelCluster--;	
sl@0
   136
	TInt clusterOffset=newRelCluster-oldRelCluster;
sl@0
   137
	TInt oldCluster=iCurrentPos.iCluster;
sl@0
   138
	iCurrentPos.iPos=aPos;
sl@0
   139
	if (clusterOffset==0)
sl@0
   140
		return;
sl@0
   141
	TInt seekOffset=clusterOffset;
sl@0
   142
	if (iSeekIndex!=NULL)
sl@0
   143
		{ // Can alter iCurrentPos.iCluster
sl@0
   144
		seekOffset=SeekToPosition(newRelCluster,seekOffset);
sl@0
   145
		if (seekOffset==0)
sl@0
   146
			return;
sl@0
   147
		}
sl@0
   148
	if (clusterOffset==-1 && seekOffset!=1)
sl@0
   149
		{ // Check previous cluster
sl@0
   150
		TInt cluster=oldCluster-1;
sl@0
   151
		if (FAT().GetNextClusterL(cluster) && cluster==oldCluster)
sl@0
   152
			{
sl@0
   153
            iCurrentPos.iCluster=oldCluster-1;
sl@0
   154
			return;
sl@0
   155
			}
sl@0
   156
		}
sl@0
   157
	if (seekOffset<0)
sl@0
   158
		{
sl@0
   159
		seekOffset=newRelCluster;
sl@0
   160
		iCurrentPos.iCluster=iStartCluster;
sl@0
   161
		}
sl@0
   162
	while (seekOffset--)
sl@0
   163
		{
sl@0
   164
        if (!FAT().GetNextClusterL(iCurrentPos.iCluster))
sl@0
   165
            {
sl@0
   166
            __PRINT(_L("CFatFileCB::CheckPosL() corrupt#1"));
sl@0
   167
            User::Leave(KErrCorrupt);
sl@0
   168
            }
sl@0
   169
        TInt cluster=newRelCluster-seekOffset;
sl@0
   170
		if (iSeekIndex!=NULL && cluster && (cluster>>iSeekIndexSize)<<iSeekIndexSize==cluster)
sl@0
   171
			SetSeekIndexValueL(cluster,iCurrentPos.iCluster);
sl@0
   172
		}
sl@0
   173
	}
sl@0
   174
sl@0
   175
void CFatFileCB::SetL(const TFatDirEntry& aFatDirEntry,TShare aShare,const TEntryPos& aPos)
sl@0
   176
//
sl@0
   177
// Initialize FileCB from entry data
sl@0
   178
//
sl@0
   179
	{
sl@0
   180
sl@0
   181
	__PRINT(_L("CFatFileCB::SetL"));
sl@0
   182
	SetSize(aFatDirEntry.Size()); 
sl@0
   183
	iCurrentPos.iCluster= FatMount().StartCluster(aFatDirEntry);
sl@0
   184
	iStartCluster=iCurrentPos.iCluster;
sl@0
   185
	iCurrentPos.iPos=0;
sl@0
   186
	iAtt=aFatDirEntry.Attributes();
sl@0
   187
	iModified= aFatDirEntry.Time(FatMount().TimeOffset());
sl@0
   188
	iShare=aShare;
sl@0
   189
	iFileDirPos=aPos;
sl@0
   190
sl@0
   191
    SetMaxSupportedSize(KMaxSupportedFatFileSize);
sl@0
   192
	}
sl@0
   193
sl@0
   194
//-----------------------------------------------------------------------------
sl@0
   195
// from CFileCB::MExtendedFileInterface
sl@0
   196
void CFatFileCB::ReadL(TInt64 aPos,TInt& aLength, TDes8* aDes, const RMessagePtr2& aMessage, TInt aOffset)
sl@0
   197
	{
sl@0
   198
	__PRINT2(_L("CFatFileCB::ReadL aFilePos=%LU aLength=%d"),aPos,aLength);
sl@0
   199
	
sl@0
   200
    if((TUint64)aPos > KMaxSupportedFatFileSize-1)
sl@0
   201
        User::Leave(KErrNotSupported);  //-- max. position in the file is 0xFFFFFFFE
sl@0
   202
sl@0
   203
    FatMount().CheckStateConsistentL();
sl@0
   204
    
sl@0
   205
	CheckPosL(I64LOW(aPos));
sl@0
   206
	
sl@0
   207
	const TUint startPos = iCurrentPos.iPos;
sl@0
   208
	const TUint curSize  = (TUint)Size();
sl@0
   209
	const TUint length   = (TUint)aLength;
sl@0
   210
	
sl@0
   211
	if((startPos + length > curSize) || (startPos > startPos + length) )
sl@0
   212
		aLength=curSize-startPos;
sl@0
   213
	
sl@0
   214
    FatMount().ReadFromClusterListL(iCurrentPos,aLength,aDes,aMessage,aOffset);
sl@0
   215
	aLength=iCurrentPos.iPos-startPos;
sl@0
   216
	}
sl@0
   217
sl@0
   218
sl@0
   219
void CFatFileCB::ReadL(TInt aFilePos,TInt& aLength,const TAny* aTrg,const RMessagePtr2& aMessage)
sl@0
   220
	{
sl@0
   221
	ReadL(TInt64(aFilePos),aLength,(TDes8*) aTrg,aMessage, 0);
sl@0
   222
	}
sl@0
   223
sl@0
   224
//-----------------------------------------------------------------------------
sl@0
   225
// from CFileCB::MExtendedFileInterface
sl@0
   226
void CFatFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aSrc,const RMessagePtr2& aMessage, TInt aOffset)
sl@0
   227
	{
sl@0
   228
	__PRINT2(_L("CFatFileCB::WriteL aFilePos=%LU aLength=%d"),aPos,aLength);
sl@0
   229
	// FAT supports 32 bits only for file size
sl@0
   230
   	TUint64 endPos = aPos + aLength;
sl@0
   231
   	if(endPos > KMaxSupportedFatFileSize)
sl@0
   232
   		User::Leave(KErrNotSupported);
sl@0
   233
   	
sl@0
   234
    FatMount().CheckStateConsistentL();
sl@0
   235
    FatMount().CheckWritableL();
sl@0
   236
    const TUint pos = I64LOW(aPos);
sl@0
   237
  	CheckPosL(pos);
sl@0
   238
  	
sl@0
   239
	const TUint startCluster = (TUint)iStartCluster;
sl@0
   240
	const TUint length       = (TUint)aLength;
sl@0
   241
	
sl@0
   242
	endPos = iCurrentPos.iPos + length; 
sl@0
   243
	if ((endPos           > (TUint)Size()) ||
sl@0
   244
	    (iCurrentPos.iPos > endPos)         ) // Overflow condition 
sl@0
   245
		DoSetSizeL(iCurrentPos.iPos+length,EFalse);
sl@0
   246
   	
sl@0
   247
	TUint startPos=iCurrentPos.iPos;
sl@0
   248
	TInt badcluster=0;
sl@0
   249
	TInt goodcluster=0;
sl@0
   250
   	
sl@0
   251
	TRAPD(ret, FatMount().WriteToClusterListL(iCurrentPos,aLength,aSrc,aMessage,aOffset,badcluster, goodcluster));
sl@0
   252
   	
sl@0
   253
	if (ret == KErrCorrupt || ret == KErrDied)
sl@0
   254
		{
sl@0
   255
        if(startCluster == 0)
sl@0
   256
			{ //Empty File, revert all the clusters allocated.
sl@0
   257
			TInt cluster = iStartCluster;
sl@0
   258
			iStartCluster = 0;
sl@0
   259
			SetSize(0);
sl@0
   260
			FlushAllL();
sl@0
   261
sl@0
   262
			iCurrentPos.iCluster = 0;
sl@0
   263
			iCurrentPos.iPos = 0;
sl@0
   264
sl@0
   265
			FAT().FreeClusterListL(cluster);
sl@0
   266
			FAT().FlushL();
sl@0
   267
			}
sl@0
   268
		else
sl@0
   269
			{ //Calculate the clusters required based on file size, revert extra clusters if allocated.
sl@0
   270
			const TUint curSize = (TUint)Size();
sl@0
   271
			TUint ClustersNeeded = curSize >> ClusterSizeLog2();
sl@0
   272
			if(curSize > (ClustersNeeded << ClusterSizeLog2()))
sl@0
   273
				{
sl@0
   274
				ClustersNeeded++;
sl@0
   275
				}
sl@0
   276
sl@0
   277
			TInt cluster = iStartCluster;
sl@0
   278
			while(--ClustersNeeded)
sl@0
   279
				{
sl@0
   280
				FAT().GetNextClusterL(cluster);
sl@0
   281
				}
sl@0
   282
                
sl@0
   283
			iCurrentPos.iCluster = cluster;
sl@0
   284
sl@0
   285
			if (FAT().GetNextClusterL(cluster))
sl@0
   286
				{
sl@0
   287
				FAT().FreeClusterListL(cluster);
sl@0
   288
				}
sl@0
   289
sl@0
   290
			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
sl@0
   291
			FAT().FlushL();
sl@0
   292
			}
sl@0
   293
		}
sl@0
   294
sl@0
   295
	User::LeaveIfError(ret);
sl@0
   296
sl@0
   297
	if(badcluster != 0)
sl@0
   298
		{
sl@0
   299
		if(iStartCluster == badcluster)
sl@0
   300
			{
sl@0
   301
			iStartCluster = goodcluster;
sl@0
   302
			FlushStartClusterL();
sl@0
   303
			}
sl@0
   304
		else
sl@0
   305
			{
sl@0
   306
			TInt aCluster = iStartCluster;
sl@0
   307
			do
sl@0
   308
				{
sl@0
   309
                if((TUint)badcluster == FAT().ReadL(aCluster))
sl@0
   310
					{
sl@0
   311
					FAT().WriteL(aCluster, goodcluster);
sl@0
   312
					FAT().FlushL();
sl@0
   313
					break;
sl@0
   314
					}
sl@0
   315
				}
sl@0
   316
			while(FAT().GetNextClusterL(aCluster));
sl@0
   317
			}
sl@0
   318
		}
sl@0
   319
	aLength=iCurrentPos.iPos-startPos;
sl@0
   320
sl@0
   321
	if(FatMount().IsRuggedFSys() && pos+(TUint)aLength>(TUint)Size())
sl@0
   322
		{
sl@0
   323
		WriteFileSizeL(pos+aLength);
sl@0
   324
		}
sl@0
   325
sl@0
   326
	}
sl@0
   327
sl@0
   328
sl@0
   329
void CFatFileCB::WriteL(TInt aFilePos,TInt& aLength,const TAny* aSrc,const RMessagePtr2& aMessage)
sl@0
   330
	{
sl@0
   331
	WriteL(TInt64(aFilePos),aLength,(TDesC8*) aSrc,aMessage, 0);
sl@0
   332
	}
sl@0
   333
sl@0
   334
sl@0
   335
sl@0
   336
//-----------------------------------------------------------------------------
sl@0
   337
sl@0
   338
void CFatFileCB::ResizeIndex(TInt aNewMult,TUint aNewSize)
sl@0
   339
//
sl@0
   340
// Resize the seek index to accomodate a larger or smaller filesize
sl@0
   341
// Assumes KSeekIndexSize is a power of 2.
sl@0
   342
//
sl@0
   343
	{
sl@0
   344
sl@0
   345
	TInt maxNewIndex=aNewSize>>(ClusterSizeLog2()+aNewMult);
sl@0
   346
sl@0
   347
sl@0
   348
	TInt    index=0;
sl@0
   349
	TInt	indexEnd=KSeekIndexSize;
sl@0
   350
	TInt	newValEnd=maxNewIndex;
sl@0
   351
sl@0
   352
	if (iSeekIndexSize<aNewMult)
sl@0
   353
		{
sl@0
   354
		TInt newVal=index;
sl@0
   355
		TInt step=1<<(aNewMult-iSeekIndexSize);
sl@0
   356
		index+=step-1;
sl@0
   357
		while(index<indexEnd && newVal<newValEnd)
sl@0
   358
			{
sl@0
   359
			iSeekIndex[newVal] =  iSeekIndex[index];
sl@0
   360
			newVal++;
sl@0
   361
			index+=step;
sl@0
   362
			}
sl@0
   363
		while(newVal<indexEnd)
sl@0
   364
			iSeekIndex[newVal++] =  0;
sl@0
   365
		}
sl@0
   366
	else
sl@0
   367
		{
sl@0
   368
		TInt diffSize = iSeekIndexSize-aNewMult;
sl@0
   369
		TInt oldVal=(KSeekIndexSize>>diffSize) - 1;
sl@0
   370
		TInt newVal=indexEnd-1;
sl@0
   371
		TInt skip=(1<<diffSize)-1;
sl@0
   372
sl@0
   373
		if ((iSeekIndexSize - aNewMult) > KSeekIndexSizeLog2)
sl@0
   374
			{
sl@0
   375
            ClearIndex(0); //-- Invalidate every entry.
sl@0
   376
			}
sl@0
   377
		else
sl@0
   378
			{
sl@0
   379
			while(newVal>=index)
sl@0
   380
				{
sl@0
   381
sl@0
   382
				iSeekIndex[newVal--] =  iSeekIndex[oldVal--];
sl@0
   383
sl@0
   384
sl@0
   385
				for(TInt i=skip;i>0;i--)
sl@0
   386
					{	
sl@0
   387
					iSeekIndex[newVal--] = 0;
sl@0
   388
sl@0
   389
					}
sl@0
   390
				}
sl@0
   391
			}
sl@0
   392
		}
sl@0
   393
	iSeekIndexSize=aNewMult;
sl@0
   394
	}
sl@0
   395
sl@0
   396
sl@0
   397
/**
sl@0
   398
    Zero freed clusters in the index
sl@0
   399
sl@0
   400
    @param  aNewSize new size of the file that the index corresponds to.
sl@0
   401
            if = 0  all existing index will be zero filled
sl@0
   402
*/ 
sl@0
   403
void CFatFileCB::ClearIndex(TUint aNewSize)
sl@0
   404
	{
sl@0
   405
sl@0
   406
	if (!iSeekIndex)
sl@0
   407
	    return;
sl@0
   408
sl@0
   409
    if(aNewSize==0)
sl@0
   410
    	{
sl@0
   411
    	//-- zero fill all the array
sl@0
   412
        Mem::FillZ(iSeekIndex, KSeekIndexSize*sizeof(TUint32));
sl@0
   413
		return;
sl@0
   414
    	}
sl@0
   415
sl@0
   416
	// Files that fill up a cluster exactly do not have a trailing empty
sl@0
   417
	// cluster. So the entry for that position must also be invalidated
sl@0
   418
	aNewSize--;
sl@0
   419
	TInt firstInvalidIndex=aNewSize>>(iSeekIndexSize+ClusterSizeLog2());
sl@0
   420
		
sl@0
   421
	TInt indexLen=KSeekIndexSize-firstInvalidIndex;
sl@0
   422
sl@0
   423
	Mem::FillZ(iSeekIndex+firstInvalidIndex, indexLen * sizeof(TUint32));
sl@0
   424
	}
sl@0
   425
sl@0
   426
TInt CFatFileCB::CalcSeekIndexSize(TUint aSize)
sl@0
   427
//
sl@0
   428
// Find the nearest power of 2 > aSize
sl@0
   429
//
sl@0
   430
	{
sl@0
   431
	TInt count = 0;
sl@0
   432
	const TUint indexSize=KSeekIndexSize<<ClusterSizeLog2();//KSeekIndexSize=128
sl@0
   433
	if (aSize<=indexSize)
sl@0
   434
	  return(count);
sl@0
   435
	
sl@0
   436
	while((aSize>>=1)>0)
sl@0
   437
		{
sl@0
   438
		count++;
sl@0
   439
		}
sl@0
   440
	return (count - (KSeekIndexSizeLog2 + ClusterSizeLog2()) + 1);
sl@0
   441
	}
sl@0
   442
sl@0
   443
//-----------------------------------------------------------------------------
sl@0
   444
sl@0
   445
void CFatFileCB::SetSizeL(TInt64 aSize)
sl@0
   446
	{
sl@0
   447
	__PRINT(_L("CFatFileCB::SetSizeL"));
sl@0
   448
	
sl@0
   449
	// FAT supports 32 bits only for file size
sl@0
   450
	if (I64HIGH(aSize))
sl@0
   451
		User::Leave(KErrNotSupported);
sl@0
   452
sl@0
   453
	if(FatMount().IsRuggedFSys())
sl@0
   454
		DoSetSizeL(I64LOW(aSize),ETrue);
sl@0
   455
	else
sl@0
   456
		DoSetSizeL(I64LOW(aSize),EFalse);
sl@0
   457
	}
sl@0
   458
sl@0
   459
sl@0
   460
void CFatFileCB::SetSizeL(TInt aSize)
sl@0
   461
//
sl@0
   462
// Envelope function around DoSetSizeL to enable aSize to
sl@0
   463
// be written to disk for rugged fat file system
sl@0
   464
//
sl@0
   465
	{
sl@0
   466
	SetSizeL(TInt64(aSize));
sl@0
   467
	}
sl@0
   468
sl@0
   469
void CFatFileCB::DoSetSizeL(TUint aSize,TBool aIsSizeWrite)
sl@0
   470
//
sl@0
   471
// Extend or truncate the file.
sl@0
   472
// Expects the modified attribute and iSize are set afterwards.
sl@0
   473
// Does not alter iCurrentPos, the current file position.
sl@0
   474
// Writes size of file to disk if aIsSizeWrite set
sl@0
   475
//
sl@0
   476
	{
sl@0
   477
	__PRINT2(_L("CFatFileCB::DoSetSizeL sz:%d, fileWrite=%d"),aSize ,aIsSizeWrite);
sl@0
   478
sl@0
   479
    FatMount().CheckStateConsistentL();
sl@0
   480
    FatMount().CheckWritableL();
sl@0
   481
sl@0
   482
	
sl@0
   483
	// Can not change the file size if it is clamped
sl@0
   484
	if(Mount().IsFileClamped(MAKE_TINT64(0,iStartCluster)) > 0)
sl@0
   485
		User::Leave(KErrInUse);
sl@0
   486
	
sl@0
   487
	iFileSizeModified=ETrue;
sl@0
   488
sl@0
   489
	TInt newIndexMult=CalcSeekIndexSize(aSize);
sl@0
   490
	if (iSeekIndex!=NULL && newIndexMult!=iSeekIndexSize)
sl@0
   491
		ResizeIndex(newIndexMult,aSize);
sl@0
   492
	if (aSize == 0)
sl@0
   493
		{
sl@0
   494
		if (Size() != 0)
sl@0
   495
			{
sl@0
   496
            ClearIndex(0); //-- clear seek index array
sl@0
   497
			TInt cluster=iStartCluster;
sl@0
   498
			iStartCluster = 0;
sl@0
   499
			SetSize(0);
sl@0
   500
			FlushAllL();
sl@0
   501
			CheckPosL(0);
sl@0
   502
			FAT().FreeClusterListL(cluster);
sl@0
   503
			FAT().FlushL();
sl@0
   504
			}
sl@0
   505
		return;
sl@0
   506
		}
sl@0
   507
	if (aSize<(TUint)Size())
sl@0
   508
		{
sl@0
   509
		if(aIsSizeWrite)		// write file size if decreasing
sl@0
   510
				WriteFileSizeL(aSize);
sl@0
   511
		CheckPosL(aSize);
sl@0
   512
		TInt cluster=iCurrentPos.iCluster;
sl@0
   513
		if (FAT().GetNextClusterL(cluster))
sl@0
   514
			{
sl@0
   515
			FAT().WriteFatEntryEofL(iCurrentPos.iCluster);
sl@0
   516
			FAT().FreeClusterListL(cluster);
sl@0
   517
			}
sl@0
   518
		ClearIndex(aSize);
sl@0
   519
		FAT().FlushL();
sl@0
   520
		return;
sl@0
   521
		}
sl@0
   522
	
sl@0
   523
	TUint newSize=aSize>>ClusterSizeLog2();	//	Number of clusters we now need
sl@0
   524
	if (aSize > (newSize<<ClusterSizeLog2()))
sl@0
   525
		newSize++;	//	File size is not an exact multiple of cluster size
sl@0
   526
					//	Increment the number of clusters required to accomodate tail
sl@0
   527
	
sl@0
   528
	if (iStartCluster==0)
sl@0
   529
		{
sl@0
   530
        //-- FAT().FreeClusterHint() will give us a hint of the last free cluster
sl@0
   531
        ClearIndex(0); //-- clear seek index array
sl@0
   532
        TInt tempStartCluster=FAT().AllocateClusterListL(newSize, FAT().FreeClusterHint());
sl@0
   533
		FAT().FlushL();
sl@0
   534
		iCurrentPos.iCluster=tempStartCluster;
sl@0
   535
		iStartCluster=tempStartCluster;
sl@0
   536
		SetSize(aSize);
sl@0
   537
		FlushAllL();
sl@0
   538
		}
sl@0
   539
	else
sl@0
   540
		{
sl@0
   541
		const TUint curSize = (TUint)Size(); 
sl@0
   542
		TUint oldSize=curSize>>ClusterSizeLog2();	//	Number of clusters we had previously
sl@0
   543
		if (curSize>(oldSize<<ClusterSizeLog2()))
sl@0
   544
			oldSize++;
sl@0
   545
	
sl@0
   546
		TInt newClusters=newSize-oldSize;	//	Number of clusters we need to prepare
sl@0
   547
		if (newClusters)
sl@0
   548
			{
sl@0
   549
			TEntryPos currentPos=iCurrentPos;
sl@0
   550
			CheckPosL(Size());
sl@0
   551
			FAT().ExtendClusterListL(newClusters,iCurrentPos.iCluster);
sl@0
   552
			iCurrentPos=currentPos;
sl@0
   553
			}
sl@0
   554
		FAT().FlushL();
sl@0
   555
		if(aIsSizeWrite)			// write file size if increasing
sl@0
   556
			WriteFileSizeL(aSize);
sl@0
   557
		}
sl@0
   558
	}
sl@0
   559
sl@0
   560
//-----------------------------------------------------------------------------
sl@0
   561
/**
sl@0
   562
    Set the entry's attributes and modified time.
sl@0
   563
*/
sl@0
   564
void CFatFileCB::SetEntryL(const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
sl@0
   565
	{
sl@0
   566
	__PRINT(_L("CFatFileCB::SetEntryL"));
sl@0
   567
    
sl@0
   568
    FatMount().CheckStateConsistentL();
sl@0
   569
    FatMount().CheckWritableL();
sl@0
   570
sl@0
   571
	TUint setAttMask=aSetAttMask&KEntryAttMaskSupported;
sl@0
   572
	if (setAttMask|aClearAttMask)
sl@0
   573
		{
sl@0
   574
		iAtt|=setAttMask;
sl@0
   575
		iAtt&=(~aClearAttMask);
sl@0
   576
		}
sl@0
   577
	if (aSetAttMask&KEntryAttModified)
sl@0
   578
		iModified=aTime;
sl@0
   579
	iAtt|=KEntryAttModified;
sl@0
   580
	}
sl@0
   581
sl@0
   582
/**
sl@0
   583
    This is a RuggedFAT - specific method. Writes file size to the corresponding field of this
sl@0
   584
    file direcrory entry.
sl@0
   585
*/
sl@0
   586
void CFatFileCB::WriteFileSizeL(TUint aSize)
sl@0
   587
	{
sl@0
   588
	__PRINT(_L("CFatFileCB::WriteFileSizeL"));
sl@0
   589
	TEntryPos entryPos=iFileDirPos;
sl@0
   590
	entryPos.iPos+=_FOFF(SFatDirEntry,iSize);
sl@0
   591
	TPtrC8 size((TUint8*)&aSize,sizeof(TUint));
sl@0
   592
	
sl@0
   593
    //-- use directory cache when dealing with directories
sl@0
   594
    FatMount().DirWriteL(entryPos,size);
sl@0
   595
	iFileSizeModified=EFalse;
sl@0
   596
    }
sl@0
   597
sl@0
   598
//-----------------------------------------------------------------------------
sl@0
   599
/** 
sl@0
   600
    Flush file size, attributes, time etc. to the media.
sl@0
   601
    It doesn't matter if whole directory entry is being written of only part of it. Anyway, a single DOS
sl@0
   602
    dir. entry always fits into 1 sector.
sl@0
   603
*/
sl@0
   604
void CFatFileCB::FlushDataL()
sl@0
   605
	{
sl@0
   606
	__PRINT(_L("CFatFileCB::FlushDataL"));
sl@0
   607
    FlushAllL();
sl@0
   608
	}
sl@0
   609
sl@0
   610
//-----------------------------------------------------------------------------
sl@0
   611
/** 
sl@0
   612
    Flush the fide directory entry data: files size, attributes, time etc. 
sl@0
   613
*/
sl@0
   614
void CFatFileCB::FlushAllL()
sl@0
   615
	{
sl@0
   616
	__PRINT(_L("CFatFileCB::FlushAllL()"));
sl@0
   617
sl@0
   618
    if (Mount().IsCurrentMount()==EFalse)
sl@0
   619
		User::Leave(KErrDisMounted);
sl@0
   620
sl@0
   621
    FatMount().CheckStateConsistentL();
sl@0
   622
    FatMount().CheckWritableL();
sl@0
   623
sl@0
   624
	TFatDirEntry entry;
sl@0
   625
	FatMount().ReadDirEntryL(iFileDirPos,entry);
sl@0
   626
	__ASSERT_ALWAYS(entry.IsEndOfDirectory()==EFalse,User::Leave(KErrCorrupt));
sl@0
   627
	entry.SetAttributes(iAtt&KEntryAttMaskSupported);
sl@0
   628
	entry.SetSize(Size());
sl@0
   629
	entry.SetTime(iModified, FatMount().TimeOffset());
sl@0
   630
	entry.SetStartCluster(iStartCluster);
sl@0
   631
sl@0
   632
	TBool setNotify = FatMount().GetNotifyUser();
sl@0
   633
	if(setNotify)
sl@0
   634
		{
sl@0
   635
		FatMount().SetNotifyOff();	// do not launch a notifier
sl@0
   636
		}
sl@0
   637
sl@0
   638
	TRAPD(ret, FatMount().WriteDirEntryL(iFileDirPos,entry));
sl@0
   639
	
sl@0
   640
	if(setNotify)
sl@0
   641
		{
sl@0
   642
		FatMount().SetNotifyOn();
sl@0
   643
		}
sl@0
   644
sl@0
   645
	User::LeaveIfError(ret);
sl@0
   646
	iAtt&=(~KEntryAttModified);
sl@0
   647
	iFileSizeModified=EFalse;
sl@0
   648
	}
sl@0
   649
sl@0
   650
//-----------------------------------------------------------------------------
sl@0
   651
sl@0
   652
/**
sl@0
   653
    Rename already opened file.
sl@0
   654
    @param  aNewName new file name; all trailing dots from the name will be removed
sl@0
   655
*/
sl@0
   656
void CFatFileCB::RenameL(const TDesC& aNewName)
sl@0
   657
	{
sl@0
   658
    __PRINT2(_L("CFatFileCB::RenameL[0x%x], name:%S"),this, &aNewName);
sl@0
   659
sl@0
   660
    FatMount().CheckStateConsistentL();
sl@0
   661
    FatMount().CheckWritableL();
sl@0
   662
sl@0
   663
    const TPtrC fileName = RemoveTrailingDots(aNewName); //-- remove trailing dots from the name
sl@0
   664
sl@0
   665
sl@0
   666
	FatMount().DoRenameOrReplaceL(*iFileName, fileName, CFatMountCB::EModeRename,iFileDirPos);
sl@0
   667
	
sl@0
   668
    AllocBufferL(iFileName, fileName);
sl@0
   669
	
sl@0
   670
	if(!FatMount().IsRuggedFSys())
sl@0
   671
		FAT().FlushL();
sl@0
   672
	}
sl@0
   673
sl@0
   674
sl@0
   675
//***********************************************************
sl@0
   676
//* BlockMap interface
sl@0
   677
//***********************************************************
sl@0
   678
	
sl@0
   679
TInt CFatFileCB::BlockMap(SBlockMapInfo& aInfo, TInt64& aStartPos, TInt64 aEndPos)
sl@0
   680
//
sl@0
   681
// Retrieves the block map of a given section of the file, in the FAT file system.
sl@0
   682
//	
sl@0
   683
	{
sl@0
   684
	__PRINT2(_L("CFatFileCB::BlockMap aStartPos=%ld aEndPos=%ld"), aStartPos, aEndPos);
sl@0
   685
	
sl@0
   686
	if ( I64HIGH(aStartPos) || I64HIGH(aEndPos) )
sl@0
   687
		return KErrNotSupported;
sl@0
   688
sl@0
   689
    TUint startPos = I64LOW(aStartPos);
sl@0
   690
	TUint endPos = I64LOW(aEndPos);
sl@0
   691
sl@0
   692
	// aEndPos will always be >=0 at this point
sl@0
   693
	const TUint length = endPos - startPos;
sl@0
   694
	
sl@0
   695
	// Store the position of cluster zero in aInfo
sl@0
   696
	CFatMountCB& fatMount = FatMount();
sl@0
   697
sl@0
   698
	TInt drvNo=-1;
sl@0
   699
	TBusLocalDrive* locDrv;
sl@0
   700
	if((fatMount.LocalDrive()->GetLocalDrive(locDrv)==KErrNone) && ((drvNo=GetLocalDriveNumber(locDrv))>=0) && (drvNo<KMaxLocalDrives))
sl@0
   701
		aInfo.iLocalDriveNumber=drvNo;
sl@0
   702
	else
sl@0
   703
		return KErrNotSupported;
sl@0
   704
sl@0
   705
	// Fetch the address of cluster 0
sl@0
   706
	aInfo.iStartBlockAddress = fatMount.FAT().DataPositionInBytes(KFirstClusterNum);
sl@0
   707
sl@0
   708
	TRAPD(r, CheckPosL(startPos));
sl@0
   709
	if (r != KErrNone)
sl@0
   710
		return r;
sl@0
   711
sl@0
   712
	aInfo.iBlockStartOffset = fatMount.ClusterRelativePos(iCurrentPos.iPos);
sl@0
   713
	aInfo.iBlockGranularity = 1 << FatMount().ClusterSizeLog2();
sl@0
   714
	const TUint myStartPos = iCurrentPos.iPos;
sl@0
   715
	if ( myStartPos + length > (TUint)Size())
sl@0
   716
		return KErrArgument;
sl@0
   717
sl@0
   718
	TRAP(r, FatMount().BlockMapReadFromClusterListL(iCurrentPos, length, aInfo));
sl@0
   719
	if (r != KErrNone)
sl@0
   720
		return r;
sl@0
   721
sl@0
   722
	aStartPos = iCurrentPos.iPos;
sl@0
   723
	if ((I64LOW(aStartPos) == (TUint)Size()) || ( I64LOW(aStartPos) == (myStartPos + length)))
sl@0
   724
		return KErrCompletion;
sl@0
   725
	else
sl@0
   726
		return KErrNone;
sl@0
   727
	}
sl@0
   728
sl@0
   729
sl@0
   730
sl@0
   731
TInt CFatFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* aInput)
sl@0
   732
	{
sl@0
   733
	switch(aInterfaceId)
sl@0
   734
		{
sl@0
   735
		case EExtendedFileInterface:
sl@0
   736
			((CFileCB::MExtendedFileInterface*&) aInterface) = this;
sl@0
   737
			return KErrNone;
sl@0
   738
sl@0
   739
		case EBlockMapInterface:
sl@0
   740
			aInterface = (CFileCB::MBlockMapInterface*) this;
sl@0
   741
			return KErrNone;
sl@0
   742
sl@0
   743
		case EGetLocalDrive:
sl@0
   744
			return FatMount().LocalDrive()->GetLocalDrive((TBusLocalDrive*&) aInterface);
sl@0
   745
sl@0
   746
		default:
sl@0
   747
			return CFileCB::GetInterface(aInterfaceId,aInterface,aInput);
sl@0
   748
		}
sl@0
   749
	}
sl@0
   750
sl@0
   751
sl@0
   752
sl@0
   753
sl@0
   754
/**
sl@0
   755
    Overwrites file's start cluster (iStartCluster) in its directory entry.
sl@0
   756
*/
sl@0
   757
void CFatFileCB::FlushStartClusterL()
sl@0
   758
	{
sl@0
   759
	__PRINT(_L("CFatFileCB::FlushStartClusterL"));
sl@0
   760
sl@0
   761
    CFatMountCB& mount = FatMount();
sl@0
   762
    TFatDirEntry dirEntry;
sl@0
   763
    
sl@0
   764
    mount.ReadDirEntryL(iFileDirPos, dirEntry);      //-- read this file's dir. entry
sl@0
   765
    dirEntry.SetStartCluster(iStartCluster);         //-- set new start cluster
sl@0
   766
    mount.WriteDirEntryL(iFileDirPos, dirEntry);//-- write the entry back
sl@0
   767
	}
sl@0
   768
sl@0
   769
sl@0
   770
sl@0
   771
sl@0
   772