userlibandfileserver/fileserver/sfile/sf_file.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15  
       
    16 #include "sf_std.h"
       
    17 #include "sf_file_cache.h"
       
    18 #include "cl_std.h"
       
    19 
       
    20 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
       
    21 
       
    22 TInt OutputTraceInfo(CFsRequest* aRequest,TCorruptNameRec* aNameRec)
       
    23 	{	
       
    24 	RThread tT;
       
    25 	RProcess tP;
       
    26 	TBool nameUnknown=EFalse;
       
    27 	TInt r=aRequest->Message().Client(tT,EOwnerThread);
       
    28 	if(r!=KErrNone)
       
    29 		{
       
    30 		nameUnknown=ETrue;
       
    31 		}
       
    32 	else
       
    33 		{
       
    34 		r=tT.Process(tP);
       
    35 		if(r!=KErrNone)	
       
    36 			{
       
    37 			tT.Close();	
       
    38 			nameUnknown=ETrue;
       
    39 			}
       
    40 		}
       
    41 	TName n;
       
    42 	if(!nameUnknown)
       
    43 		{
       
    44 		n=tP.Name();
       
    45 		TInt b=n.Locate('[');
       
    46 		if (b>=0)
       
    47 			n.SetLength(b);
       
    48 		tP.Close();
       
    49 		tT.Close();
       
    50 		}
       
    51 	else
       
    52 		{
       
    53 		n=_L("*Unknown*");
       
    54 		}
       
    55 	TPtrC t(aRequest->Src().FullName());
       
    56 	// output a message via the debug port
       
    57 	RDebug::Print(_L("@@@@ Corrupt file check %S tried to open %S"),&n,&t);
       
    58 	// make a new log record & chain it in
       
    59 	TCorruptLogRec* pLogRec= new TCorruptLogRec;
       
    60 	if(pLogRec==NULL)
       
    61 		return KErrNoMemory;
       
    62 	TPtrC nPtr(n);
       
    63 	if(pLogRec->Construct(aNameRec,&nPtr,gCorruptLogRecordList)!=KErrNone)
       
    64 		{
       
    65 		delete pLogRec;
       
    66 		return KErrNoMemory;
       
    67 		}
       
    68 	else
       
    69 		{
       
    70 		gCorruptLogRecordList=pLogRec;
       
    71 		// really a count of number of log records
       
    72 		gNumberOfCorruptHits++;
       
    73 		}
       
    74 	return KErrNone;
       
    75 	}
       
    76 
       
    77 TCorruptLogRec::TCorruptLogRec()
       
    78 	:iProcessName(NULL),iNameRec(NULL),iNext(NULL)
       
    79 	{}
       
    80 
       
    81 TCorruptLogRec::~TCorruptLogRec()
       
    82 	{ // free off name memory
       
    83 	delete iProcessName;
       
    84 	}
       
    85 
       
    86 
       
    87 void TCorruptLogRec::DestroyList()
       
    88 	{
       
    89 	TCorruptLogRec* pList=gCorruptLogRecordList;
       
    90 
       
    91 	while(pList!=NULL)
       
    92 		{
       
    93 		TCorruptLogRec* pThis=pList;
       
    94 		pList=pList->iNext;
       
    95 		delete pThis;
       
    96 		}
       
    97 	gCorruptLogRecordList=NULL;
       
    98 	gNumberOfCorruptHits=0;
       
    99 	}
       
   100 
       
   101 TInt TCorruptLogRec::Construct(TCorruptNameRec* aNameRec, TPtrC* aProcessName, TCorruptLogRec* aChain)
       
   102 	{
       
   103 	iProcessName=aProcessName->Alloc();
       
   104 	if(iProcessName==NULL)
       
   105 		return KErrNoMemory;
       
   106 
       
   107 	iNameRec=aNameRec;
       
   108 	iNext=aChain;
       
   109 	return KErrNone;
       
   110 	}
       
   111 
       
   112 TInt TCorruptLogRec::GetLogRecord(TFsDebugCorruptLogRecordBuf& aLogRecord,TInt aLogRecNum)
       
   113 	{
       
   114 	if(aLogRecNum<=0)
       
   115 		{
       
   116 		return KErrArgument;
       
   117 		}
       
   118 	else if(aLogRecNum>gNumberOfCorruptHits)
       
   119 		{
       
   120 		return KErrNotFound;
       
   121 		}
       
   122 
       
   123 	TCorruptLogRec* pList=gCorruptLogRecordList;
       
   124 
       
   125 	for(TInt i=1;i<aLogRecNum && pList!=NULL;i++)
       
   126 		{	
       
   127 		pList=pList->iNext;
       
   128 		}
       
   129 
       
   130 	TInt r=KErrNotFound;
       
   131 
       
   132 	if(pList)
       
   133 		{
       
   134 		aLogRecord().iProcessName=pList->iProcessName->Des();
       
   135 		aLogRecord().iFileName=pList->iNameRec->Name();
       
   136 		aLogRecord().iError=pList->iNameRec->ReturnCode();
       
   137 		r=KErrNone;
       
   138 		}
       
   139 
       
   140 	return r;
       
   141 	}
       
   142 
       
   143 TCorruptNameRec::TCorruptNameRec()
       
   144 :iName(NULL),iNext(NULL){} 
       
   145 
       
   146 TInt TCorruptNameRec::Construct(TPtr* aName,TInt aReturnCode, TBool aUseOnce, TCorruptNameRec* aChain)
       
   147 	{
       
   148 	iName=aName->Alloc();
       
   149 	if(iName==NULL)
       
   150 		return KErrNoMemory;
       
   151 	iReturnCode=aReturnCode;
       
   152 	iUseOnce=aUseOnce;
       
   153 	iConsumed=EFalse;
       
   154 	iNext=aChain;
       
   155 	return KErrNone;
       
   156 	}
       
   157 
       
   158 void TCorruptNameRec::ResetListConsumed()
       
   159 	{
       
   160 	TCorruptNameRec* pList=gCorruptFileNameList;
       
   161 	while(pList!=NULL)
       
   162 		{
       
   163 		pList->iConsumed=EFalse;
       
   164 		pList=pList->Next();
       
   165 		}
       
   166 	}
       
   167 
       
   168 LOCAL_C void checkCorruptNamesList(CFsRequest* aRequest, TInt &aError)
       
   169 	{
       
   170 	aError=KErrNone;
       
   171 	TPtrC path(aRequest->Src().FullName());
       
   172 	TCorruptNameRec* pList=gCorruptFileNameList;
       
   173 	while(pList)
       
   174 		{
       
   175 		if(pList->Name().MatchF(path)==0)
       
   176 			{
       
   177 			if(!pList->Consumed())
       
   178 				{
       
   179 				aError=pList->ReturnCode();
       
   180 				pList->SetConsumed();
       
   181 				OutputTraceInfo(aRequest,pList);
       
   182 				}
       
   183 			break;
       
   184 			}
       
   185 		pList=pList->Next();
       
   186 		}
       
   187 	}
       
   188 #endif
       
   189 
       
   190 
       
   191 LOCAL_C TInt DoInitNoParse(CFsRequest* aRequest)
       
   192 //
       
   193 // Common init for read and write access to files
       
   194 //
       
   195 	{
       
   196 	CFileShare* share = GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
       
   197 	if(!share)
       
   198 		return(KErrBadHandle);
       
   199 	aRequest->SetDrive(&share->File().Drive());
       
   200 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
       
   201 	return KErrNone;
       
   202 	}
       
   203 
       
   204 _LIT(KDrivePath,"?:");
       
   205 LOCAL_C TInt DoInitialise(CFsRequest* aRequest)
       
   206 //
       
   207 //	Common initialisation code use file share to determine asychronicity
       
   208 //
       
   209 	{
       
   210 	CFileShare* share = GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
       
   211 	if(!share)
       
   212 		return(KErrBadHandle);
       
   213 	aRequest->SetDrive(&share->File().Drive());
       
   214 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
       
   215 	TBuf<2> drive(KDrivePath);
       
   216 	drive[0]=TText(aRequest->DriveNumber()+'A');
       
   217 	aRequest->Src().Set(share->File().FileName(),NULL,&drive);
       
   218 	return KErrNone;
       
   219 	}
       
   220 
       
   221 LOCAL_C TInt InitialiseScratchToShare(CFsRequest* aRequest)
       
   222 //
       
   223 // Common code used to initialise the scratch value to the CFileShare* from the request
       
   224 //	
       
   225 	{
       
   226 	CFileShare* share=GetShareFromHandle(aRequest->Session(), aRequest->Message().Int3());
       
   227 	if(!share)
       
   228 		return(KErrBadHandle);
       
   229 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
       
   230 
       
   231 	return(KErrNone);
       
   232 	}
       
   233 
       
   234 LOCAL_C TInt FsFileOpenL(CFsRequest* aRequest, TFileOpen anOpen)
       
   235 //
       
   236 // Open a file.
       
   237 //
       
   238 	{
       
   239 	TInt r;
       
   240     
       
   241     TUint32 mode=aRequest->Message().Int1();
       
   242 	if (anOpen==EFileCreate || anOpen==EFileReplace)
       
   243 		{
       
   244 		r = CheckDiskSpace(0, aRequest);
       
   245 		if(r != KErrNone)
       
   246             return r;
       
   247         
       
   248         mode|=EFileWrite;
       
   249 		}
       
   250 
       
   251 	TInt h;
       
   252     r=aRequest->Drive()->FileOpen(aRequest,h,aRequest->Src().FullName().Mid(2),mode,anOpen);
       
   253 	if (r!=KErrNone)
       
   254 		return(r);
       
   255 	
       
   256     TPtrC8 pH((TUint8*)&h,sizeof(TInt));
       
   257 	TRAP(r, aRequest->WriteL(KMsgPtr3,pH))
       
   258 	CheckForLeaveAfterOpenL(r, aRequest, h);
       
   259 	aRequest->Session()->IncResourceCount();
       
   260 	
       
   261     return(KErrNone);
       
   262 	}
       
   263 
       
   264 TInt TFsFileOpen::DoRequestL(CFsRequest* aRequest)
       
   265 //
       
   266 //
       
   267 //
       
   268 	{
       
   269 	__PRINT(_L("TFsFileOpen::DoRequestL(CFsRequest* aRequest)"));
       
   270 	return FsFileOpenL(aRequest, EFileOpen);
       
   271 	}
       
   272 
       
   273 TInt TFsFileCreate::DoRequestL(CFsRequest* aRequest)
       
   274 //
       
   275 //
       
   276 //
       
   277 	{
       
   278 
       
   279 	__PRINT(_L("TFsFileCreate::DoRequestL(CFsRequest* aRequest)"));
       
   280 	return FsFileOpenL(aRequest, EFileCreate);
       
   281 	}
       
   282 
       
   283 TInt TFsFileCreate::Initialise(CFsRequest* aRequest)
       
   284 //
       
   285 //
       
   286 //
       
   287 	{
       
   288 	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
       
   289  	if (r!=KErrNone)
       
   290 		return(r);
       
   291 	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileCreate,&KCapFsPriFileCreate,&KCapFsROFileCreate, __PLATSEC_DIAGNOSTIC_STRING("Create File")); 
       
   292 	if (r!=KErrNone)
       
   293 		return(r);
       
   294 	if (OpenOnDriveZOnly)
       
   295 		{
       
   296 		aRequest->SetDrive(&TheDrives[EDriveZ]);
       
   297 		aRequest->SetSubstedDrive(NULL);
       
   298 		}
       
   299 	return(r);
       
   300 	}
       
   301 
       
   302 
       
   303 
       
   304 TInt TFsFileReplace::DoRequestL(CFsRequest* aRequest)
       
   305 //
       
   306 //
       
   307 //
       
   308 	{
       
   309 	__PRINT(_L("TFsFileReplace::DoRequestL(CFsRequest* aRequest)"));
       
   310 	return FsFileOpenL(aRequest, EFileReplace);
       
   311 	}
       
   312 
       
   313 TInt TFsFileReplace::Initialise(CFsRequest* aRequest)
       
   314 //
       
   315 //
       
   316 //
       
   317 	{
       
   318 	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
       
   319  	if (r!=KErrNone)
       
   320 		return(r);
       
   321 	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileReplace,&KCapFsPriFileReplace,&KCapFsROFileReplace, __PLATSEC_DIAGNOSTIC_STRING("Replace File")); 
       
   322 	if (r!=KErrNone)
       
   323 		return(r);
       
   324 
       
   325 	if (OpenOnDriveZOnly)	// Yuck! yet another global
       
   326 		{
       
   327 		aRequest->SetDrive(&TheDrives[EDriveZ]);
       
   328 		aRequest->SetSubstedDrive(NULL);
       
   329 		}
       
   330 	return(r);
       
   331 	}
       
   332 
       
   333 
       
   334 #ifdef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   335 
       
   336 #define __PLATSEC_DIAGNOSTIC_MESSAGE(s)	NULL
       
   337 static const TInt KMsgBuffSize = KMaxPath;
       
   338 
       
   339 #else
       
   340 
       
   341 	#if defined(_UNICODE) && !defined(__KERNEL_MODE__)
       
   342 
       
   343 static const TInt KCharMsgMaxLen = KMaxPath - 1;
       
   344 static const TInt KMsgBuffSize = KMaxPath;
       
   345 
       
   346 	#else
       
   347 
       
   348 static const TInt KCharMsgMaxLen = 50;
       
   349 static const TInt KMsgBuffSize = KMaxPath + KMsgMaxLen + 1;
       
   350 
       
   351 	#endif	// #if defined(_UNICODE) && !defined(__KERNEL_MODE__)
       
   352 
       
   353 // Local function to format a message
       
   354 static
       
   355 const char* FmtPlatSecMessage(TBufC<KMsgBuffSize>& buff, CFsRequest& req, const char* str)
       
   356     {
       
   357     char* p = (char*)buff.Ptr();
       
   358 	const char* const base = p;
       
   359     // copy message string (if any)
       
   360     if(str)
       
   361         {
       
   362         while(*str && p < &base[KCharMsgMaxLen - 2]) // 2 for trailing ": "
       
   363             *p++ = *str++;
       
   364         *p++ = ':';
       
   365         *p++ = ' ';
       
   366         }
       
   367     // append filename
       
   368     const TDesC& fname = req.Src().FullName();
       
   369     const TInt end = Min(fname.Length(), 
       
   370                          KMsgBuffSize * sizeof(*buff.Ptr()) - (p - base) - 1);
       
   371     for(TInt i = 0; i < end; ++i)
       
   372         *p++ = (char)fname[i];
       
   373     *p = 0;
       
   374     return base;
       
   375     }
       
   376     
       
   377 #define __PLATSEC_DIAGNOSTIC_MESSAGE(s) FmtPlatSecMessage(thisPath, *aRequest, s)
       
   378 
       
   379 #endif	// #ifdef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   380 
       
   381 
       
   382 TInt TFsFileOpen::Initialise(CFsRequest* aRequest)
       
   383 //
       
   384 // Parse and execute FileOpen service otherwise sets flag for  
       
   385 // asynchronous service
       
   386 //
       
   387 	{
       
   388 	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
       
   389  	if (r!=KErrNone)
       
   390 		return(r);
       
   391 
       
   392 	TBufC<KMsgBuffSize> thisPath(aRequest->Src().FullName().Mid(2));
       
   393 	TUint32 mode = (aRequest->Message().Int1() & ~(EFileStreamText | EFileReadAsyncAll | EFileBigFile));
       
   394 
       
   395 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
       
   396 // see if file is on our "Most Wanted" list
       
   397 	TInt errorCode;
       
   398 	checkCorruptNamesList(aRequest,errorCode);
       
   399 	if(errorCode!=KErrNone)
       
   400 		{
       
   401 		return errorCode;
       
   402 		}
       
   403 #endif
       
   404 
       
   405 	CFsMessageRequest* msgRequest = (CFsMessageRequest*)aRequest;
       
   406 	if (OpenOnDriveZOnly)
       
   407 		{
       
   408 		aRequest->SetDrive(&TheDrives[EDriveZ]);
       
   409 		aRequest->SetSubstedDrive(NULL);
       
   410 		}
       
   411 
       
   412 	if(msgRequest->IsPluginRequest())
       
   413 		{
       
   414 		// Always allow plugins to open files, regardless of the clients policy
       
   415 		return KErrNone;
       
   416 		}
       
   417 
       
   418 	if(ComparePrivate(thisPath))
       
   419 		{
       
   420 		if(! SIDCheck(aRequest,thisPath))
       
   421 			{
       
   422 			if(!KCapFsPriFileOpen.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in private path")))
       
   423 				return KErrPermissionDenied;
       
   424 			}
       
   425 		}
       
   426 	else if(CompareResource(thisPath))
       
   427 		{
       
   428  		if(mode != EFileShareReadersOrWriters && mode != EFileShareReadersOnly && mode != EFileRead) 
       
   429  		// File opening mode EFileShareReadersOrWriters|EFileRead will fail the above test and not 
       
   430  		// be checked for policy, whereas file opening mode EFileShareReadersOrWriters|EFileWrite 
       
   431  		// will pass the test and will be checked for policy. 
       
   432  		// EFileRead is 0 whereas EFileWrite is non 0.
       
   433  			{
       
   434 			if(!KCapFsROFileOpenWr.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in resource path")))
       
   435 				return KErrPermissionDenied;
       
   436 			}
       
   437 		}
       
   438 	else if(CompareSystem(thisPath))
       
   439 		{
       
   440 		if(!(mode & EFileShareReadersOnly) && (mode & EFileWrite))
       
   441 			{
       
   442 			if(!KCapFsSysFileOpenWr.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in system path")))
       
   443 				return KErrPermissionDenied;
       
   444 			}
       
   445 		else
       
   446 			{
       
   447 			if(!KCapFsSysFileOpenRd.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_MESSAGE("File Open in system path")))
       
   448 				return KErrPermissionDenied;
       
   449 			}
       
   450 		}
       
   451 
       
   452 	return(r);
       
   453 	}
       
   454 
       
   455 #undef __PLATSEC_DIAGNOSTIC_MESSAGE	
       
   456 	
       
   457 TInt TFsIsFileOpen::DoRequestL(CFsRequest* aRequest)
       
   458 //
       
   459 // Return whether a file is open or not
       
   460 //
       
   461 	{
       
   462 
       
   463 	__PRINT(_L("TFsIsFileOpen::DoRequestL(CFsRequest* aRequest)"));
       
   464 	CFileCB* file;
       
   465 	TInt r=aRequest->Drive()->IsFileOpen(aRequest->Src().FullName().Mid(2),file);
       
   466 	if (r!=KErrNone)
       
   467 		return(r);
       
   468 	TBool isOpen = file?(TBool)ETrue:(TBool)EFalse;
       
   469 	TPtrC8 pA((TUint8*)&isOpen,sizeof(TBool));
       
   470 	aRequest->WriteL(KMsgPtr1,pA);
       
   471 	return(KErrNone);
       
   472 	}
       
   473 
       
   474 TInt TFsIsFileOpen::Initialise(CFsRequest* aRequest)
       
   475 //
       
   476 //
       
   477 //
       
   478 	{
       
   479 	TInt r=ParseNoWildSubstCheckPtr0(aRequest,aRequest->Src());
       
   480 	if (r!=KErrNone)
       
   481 		return(r);
       
   482 	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysIsFileOpen,&KCapFsPriIsFileOpen, __PLATSEC_DIAGNOSTIC_STRING("Is File Open")); 
       
   483 	return(r);
       
   484 	}
       
   485 
       
   486 
       
   487 TInt TFsListOpenFiles::DoRequestL(CFsRequest* aRequest)
       
   488 //
       
   489 // List open files
       
   490 //
       
   491 	{
       
   492 	
       
   493 	__PRINT(_L("TFsListOpenFiles::DoRequestL(CFsRequest* aRequest)"));
       
   494 
       
   495 	TOpenFileListPos listPos;
       
   496 	TPckg<TOpenFileListPos> listPkg(listPos);
       
   497 	aRequest->ReadL(KMsgPtr0,listPkg);
       
   498 	TBuf8<KEntryArraySize> entryArray(0);
       
   499 	
       
   500 	TThreadId idClient;
       
   501 	TPckgC<TThreadId> id(idClient);	
       
   502 
       
   503 	CSessionFs* session;
       
   504 	TBool fileFound=(listPos.iEntryListPos) ? (TBool)ETrue : EFalse;
       
   505 	TInt entryListPos;
       
   506 	TInt count;
       
   507 Start:
       
   508 	FOREVER
       
   509 		{
       
   510 		session=(*TheFileServer)[listPos.iSession];	//this global may not be the best way AJ
       
   511 		if (session==NULL)
       
   512 			goto End;
       
   513 		session->Handles().Lock();
       
   514 		count=session->Handles().Count();
       
   515 		if (count)
       
   516 			break;
       
   517 		session->Handles().Unlock();
       
   518 		listPos.iSession++;
       
   519 		}
       
   520 
       
   521 	entryListPos=listPos.iEntryListPos;
       
   522 	while (entryListPos<count)
       
   523 		{
       
   524 		CObjPromotion* obj=(CObjPromotion*)session->Handles()[entryListPos];
       
   525 		if (obj==NULL || obj->UniqueID()!=FileShares->UniqueID())
       
   526 			{
       
   527 			entryListPos++;
       
   528 			continue; // Is not a CFileShare
       
   529 			}
       
   530 		CFileCB& fileCb=((CFileShare*)obj)->File();
       
   531 
       
   532 		TEntry fileEntry;
       
   533 		// Set kEntryAttPacked to indicate it is in packed form
       
   534 		fileEntry.iAtt=fileCb.Att() | KEntryAttPacked;
       
   535 		TInt64 fileSize = fileCb.Size64();
       
   536 		fileEntry.iSize = I64LOW(fileSize);
       
   537 		fileEntry.iModified=fileCb.Modified();
       
   538 		fileEntry.iName=fileCb.FileName();
       
   539 		
       
   540 		// Pack - Copy iSizeHigh and reset iReserved in packed form
       
   541 		TUint32* pSizeHigh = PtrAdd((TUint32*)&fileEntry, EntrySize(fileEntry, EFalse));
       
   542 		
       
   543 		*pSizeHigh++ = I64HIGH(fileSize);	// Copy iSizeHigh
       
   544 		*pSizeHigh 	 = 0;					// Reset iReserved
       
   545 		
       
   546 		TInt entrySize=EntrySize(fileEntry, ETrue);
       
   547 		if (entryArray.Length()+entrySize>entryArray.MaxLength())
       
   548 			break;
       
   549 		TPtrC8 pfileEntry((TUint8*)&fileEntry,entrySize);
       
   550 		entryArray.Append(pfileEntry);
       
   551 		entryListPos++;
       
   552 		}
       
   553 	idClient = session->ThreadId();
       
   554 	session->Handles().Unlock();
       
   555 
       
   556 	if (entryArray.Length()==0)
       
   557 		listPos.iSession++;
       
   558 	if (fileFound==EFalse && entryArray.Length()==0)
       
   559 		goto Start;
       
   560 	listPos.iEntryListPos=entryListPos;
       
   561 
       
   562 End:
       
   563 	aRequest->WriteL(KMsgPtr1,id);
       
   564 	aRequest->WriteL(KMsgPtr0,listPkg);
       
   565 	aRequest->WriteL(KMsgPtr2,entryArray);
       
   566 	return(KErrNone);
       
   567 	}
       
   568 
       
   569 TInt TFsListOpenFiles::Initialise(CFsRequest* /*aRequest*/)
       
   570 //
       
   571 //
       
   572 //
       
   573 	{
       
   574 	return KErrNone;
       
   575 	}
       
   576 
       
   577 LOCAL_C void FsFileTempFinishL(CFsRequest* aRequest,TFileName& aN,TInt aH)
       
   578 	{
       
   579 
       
   580 	aRequest->WriteL(KMsgPtr2,aRequest->Src().Drive());
       
   581 	aRequest->WriteL(KMsgPtr2,aN,2);
       
   582 	TPtrC8 pH((TUint8*)&aH,sizeof(TInt));
       
   583 	aRequest->WriteL(KMsgPtr3,pH);
       
   584 	}
       
   585 
       
   586 TInt TFsFileTemp::DoRequestL(CFsRequest* aRequest)
       
   587 //
       
   588 // Create a temporary file.
       
   589 //
       
   590 	{
       
   591 	__PRINT(_L("TFsFileTemp::DoRequestL(CFsRequest* aRequest)"));
       
   592     
       
   593     TInt r = CheckDiskSpace(0, aRequest);
       
   594     if(r != KErrNone)
       
   595         return r;
       
   596 	
       
   597     TFileName n;
       
   598 	TInt h;
       
   599 	r=aRequest->Drive()->FileTemp(aRequest,h,aRequest->Src().FullName().Mid(2),n,aRequest->Message().Int1());
       
   600 	if (r!=KErrNone)
       
   601 		return(r);
       
   602 	
       
   603     TRAP(r, FsFileTempFinishL(aRequest,n,h))
       
   604 	CheckForLeaveAfterOpenL(r,aRequest,h);
       
   605 	aRequest->Session()->IncResourceCount();
       
   606 	
       
   607     return(KErrNone);
       
   608 	}
       
   609 
       
   610 TInt TFsFileTemp::Initialise(CFsRequest* aRequest)
       
   611 //
       
   612 //
       
   613 //
       
   614 	{
       
   615 	TInt r=ParseNoWildSubstPtr0(aRequest,aRequest->Src());
       
   616 	if (r!=KErrNone)
       
   617 		return(r);
       
   618 	r=PathCheck(aRequest,aRequest->Src().FullName().Mid(2),&KCapFsSysFileTemp,&KCapFsPriFileTemp,&KCapFsROFileTemp, __PLATSEC_DIAGNOSTIC_STRING("Temp File")); 
       
   619 	if (r!=KErrNone)
       
   620 		return(r);
       
   621 	if (aRequest->Src().NameOrExtPresent())
       
   622 		return(KErrBadName);
       
   623 	return(r);
       
   624 	}
       
   625 
       
   626 
       
   627 TInt TFsFileRead::DoRequestL(CFsRequest* aRequest)
       
   628 //
       
   629 // Read from a file.
       
   630 //
       
   631 	{
       
   632 	
       
   633 	__PRINT(_L("TFsFileRead::DoRequestL(CFsRequest* aRequest)"));
       
   634 	__PRINT1(_L("aRequest->Session() = 0x%x"),aRequest->Session());
       
   635 
       
   636 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
   637 	__ASSERT_DEBUG(msgRequest.CurrentOperationPtr() != NULL, Fault(EBadOperationIndex));
       
   638 	TMsgOperation& currentOperation = msgRequest.CurrentOperation();
       
   639 
       
   640 	CFileShare* share;
       
   641 	CFileCB* file;
       
   642 	GetFileFromScratch(aRequest, share, file);
       
   643 
       
   644 	TInt r = file->CheckMount();
       
   645 	__PRINT1(_L("share->CheckMount() returned = %d"),r);
       
   646 	if (r!=KErrNone)
       
   647 		return(r);
       
   648 
       
   649 	TInt& len = currentOperation.iReadWriteArgs.iLength;
       
   650 	TInt& totalLen = currentOperation.iReadWriteArgs.iTotalLength;
       
   651 	TInt64 pos = currentOperation.iReadWriteArgs.iPos;
       
   652 	TInt& offset = currentOperation.iReadWriteArgs.iOffset;
       
   653 
       
   654 	// Fair scheduling - 
       
   655 	// Needs extended file API to work (so that we can sepcify an offset)
       
   656 	// Also needs a separate drive thread to prevent excessive stack usage
       
   657 	len = Min(len, totalLen);
       
   658 	if (file->ExtendedFileInterfaceSupported() && !FsThreadManager::IsDriveSync(aRequest->DriveNumber(), EFalse))
       
   659 		{
       
   660 		len = Min(len, file->FairSchedulingLen());
       
   661 		}
       
   662 	if (pos == KCurrentPosition64)
       
   663 		pos = share->iPos;
       
   664 
       
   665 	currentOperation.iReadWriteArgs.iPos = pos;
       
   666 
       
   667 	__ASSERT_DEBUG(len > 0, Fault(EInvalidReadLength));
       
   668 	__ASSERT_DEBUG(len <= totalLen, Fault(EInvalidReadLength));
       
   669 
       
   670 	// The mount and any extensions must all support local buffers in order to support
       
   671 	// internally generated requests (ie - requests originating from plugins)
       
   672 	if ((aRequest->Message().Handle() == KLocalMessageHandle || !currentOperation.iClientRequest) && !file->LocalBufferSupport())
       
   673 		{
       
   674 		r = KErrNotSupported;
       
   675 		}
       
   676 
       
   677 	TInt reqLen = len;
       
   678 	if(r == KErrNone)
       
   679 		{
       
   680 		if (currentOperation.iClientRequest)	
       
   681 			{
       
   682 			// Current operation points to a descriptor
       
   683 			// The request originated from a client (with a normal message handle) or a plugin (KLocalMessageHandle)
       
   684 			TRAP(r,file->ReadL(pos, len, (TPtr8*) aRequest->Message().Ptr0(), aRequest->Message(), offset))
       
   685 			}
       
   686 		else
       
   687 			{
       
   688 			// Current operation points to a local buffer
       
   689 			// The request originated from the file server (e.g. file cache) with a local message handle (KLocalMessageHandle)
       
   690 			TPtr8 dataDesc((TUint8*) currentOperation.iReadWriteArgs.iData + currentOperation.iReadWriteArgs.iOffset, len, len);
       
   691 			const RLocalMessage msg;
       
   692 			TRAP(r,file->ReadL(pos, len, &dataDesc, msg, 0));
       
   693 			}
       
   694 		}
       
   695 
       
   696 
       
   697 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
       
   698 	CCacheManager* manager = CCacheManagerFactory::CacheManager();
       
   699 	if (manager)
       
   700 		{
       
   701 		manager->Stats().iUncachedPacketsRead++;
       
   702 		manager->Stats().iUncachedBytesRead+= len;
       
   703 		}
       
   704 #endif
       
   705 
       
   706 //RDebug::Print(_L("ReadR: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
       
   707 
       
   708 
       
   709 #if defined (_DEBUG_READ_AHEAD)
       
   710 	RDebug::Print(_L("ReadR: req %08X pos %ld\t len %d nextPos %ld file %08X\n"), aRequest, pos, len, pos + len, file);
       
   711 #endif
       
   712 
       
   713 	offset+= len;
       
   714 	currentOperation.iReadWriteArgs.iPos+= len;
       
   715 	totalLen-= reqLen;
       
   716 
       
   717 
       
   718 	// update the file share's position IF this request came from the client
       
   719 	if (share && r==KErrNone && currentOperation.iClientRequest)
       
   720 		{
       
   721 		__e32_atomic_store_ord64(&share->iPos, pos + len);
       
   722 		}
       
   723 
       
   724 	// re-issue request if not complete (to support fair scheduling)
       
   725 	if (r == KErrNone && totalLen > 0)
       
   726 		return CFsRequest::EReqActionBusy;	// dispatch request again to back of queue
       
   727 
       
   728 	return(r);
       
   729 	}
       
   730 
       
   731 
       
   732 TInt TFsFileRead::Initialise(CFsRequest* aRequest)
       
   733 //
       
   734 //
       
   735 //
       
   736 	{
       
   737 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
   738 
       
   739 	TInt r = DoInitNoParse(aRequest);
       
   740 	if (r != KErrNone)
       
   741 		return r;
       
   742 
       
   743 	CFileShare* share;
       
   744 	CFileCB* file;
       
   745 	GetFileFromScratch(aRequest, share, file);
       
   746 
       
   747 	TMsgOperation* msgOp = msgRequest.CurrentOperationPtr();
       
   748 	if (!msgOp)	// initialised already ?
       
   749 		{
       
   750 		r = msgRequest.PushOperation(TFsFileRead::Complete);
       
   751 		if (r != KErrNone)
       
   752 			return r;
       
   753 		msgOp = msgRequest.CurrentOperationPtr();
       
   754 		}
       
   755 	// try to serialize requests to prevent asynchronous requests being processed out of sequence -
       
   756 	// this isn't possible if a plugin is loaded as this may issue it's own requests 
       
   757 	if (!share->RequestStart(&msgRequest))
       
   758 		return CFsRequest::EReqActionPending;
       
   759 
       
   760 	TDrive& drive = share->File().Drive();
       
   761 
       
   762 	TInt64 pos, reqPos;
       
   763 	TInt len, reqLen;
       
   764 
       
   765 	reqLen = len = aRequest->Message().Int1();
       
   766 
       
   767 	if(aRequest->IsDescData(KMsgPtr2))
       
   768 		{//-- 64-bit file addressing, absolute read position is TInt64
       
   769 			TPckg<TInt64> pkPos(reqPos);
       
   770 			aRequest->ReadL(KMsgPtr2, pkPos);
       
   771 		}
       
   772 	else
       
   773 		{
       
   774 		if(aRequest->Message().Int2() == (TInt)I64LOW(KCurrentPosition64))
       
   775 			reqPos = KCurrentPosition64; // Position is KCurrentPosition64 (-1)
       
   776 		else //-- legacy, RFile addressing
       
   777 			reqPos = MAKE_TINT64(0,aRequest->Message().Int2());	// Position is absolute value < 4GB, it's TUint
       
   778 		}
       
   779 	
       
   780     msgOp->iClientPosition = pos = reqPos;
       
   781 	
       
   782 	if (len < 0)
       
   783 		return KErrArgument;
       
   784 
       
   785 	if (len == 0)
       
   786 		return CFsRequest::EReqActionComplete;
       
   787 	
       
   788 	if (pos == KCurrentPosition64)
       
   789 		pos = share->iPos;
       
   790 
       
   791 	const TInt64 fileSize = file->CachedSize64();
       
   792 	if (pos > fileSize)
       
   793 		pos = fileSize;
       
   794 
       
   795 	if ((r = file->CheckLock64(share,pos,len)) != KErrNone)
       
   796 		return r;
       
   797 
       
   798 	
       
   799 	TDes8* pD = (TDes8*) aRequest->Message().Ptr0();
       
   800 
       
   801 	if((share->iMode & EFileReadAsyncAll) && (aRequest->Message().ClientStatus() != NULL))
       
   802 		{
       
   803 		drive.Lock();
       
   804 		if (pos + len > fileSize)
       
   805 			{
       
   806 			r = share->File().AddAsyncReadRequest(share, reqPos, reqLen, aRequest);
       
   807 			drive.UnLock();
       
   808 			return (r == KErrNone)?CFsRequest::EReqActionComplete:r;
       
   809 			}
       
   810 		drive.UnLock();
       
   811 		}
       
   812 	
       
   813     if (pos == fileSize)
       
   814 		{
       
   815 		__e32_atomic_store_ord64(&share->iPos, pos);
       
   816 		r = aRequest->Write(KMsgPtr0, KNullDesC8);
       
   817 		return(r == KErrNone?CFsRequest::EReqActionComplete:r);
       
   818 		}
       
   819 	
       
   820     if (pos + len > fileSize)
       
   821 		{
       
   822 		// filesize - pos shall of TInt size
       
   823 		// Hence to suppress warning
       
   824 		len = (TInt)(fileSize - pos);
       
   825 		}
       
   826 
       
   827 	msgOp->Set(pos, len, (TDesC8*) pD);
       
   828 
       
   829 //RDebug::Print(_L("ReadI: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
       
   830 
       
   831 #if defined (_DEBUG_READ_AHEAD)
       
   832 	RDebug::Print(_L("ReadI: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
       
   833 #endif
       
   834 
       
   835 	return KErrNone;
       
   836 	}
       
   837 
       
   838 TInt TFsFileRead::PostInitialise(CFsRequest* aRequest)
       
   839 	{
       
   840 	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
       
   841 	CFileCB* file = &share->File();
       
   842 	TInt r = KErrNone;
       
   843 
       
   844 	CFileCache* fileCache = file->FileCache();
       
   845 	if (fileCache)
       
   846 		{
       
   847 		r = fileCache->ReadBuffered(*(CFsMessageRequest*)aRequest, share->iMode);
       
   848 
       
   849 		// if we're not reading from cache, force read ahead position & length to be recalculated
       
   850 		if (r == KErrNone)
       
   851 			fileCache->ResetReadAhead();
       
   852 		}
       
   853 	
       
   854 	return r;
       
   855 	}
       
   856 
       
   857 TInt TFsFileRead::Complete(CFsRequest* aRequest)
       
   858 	{
       
   859 //		RDebug::Print(_L("TFsFileRead::Complete() aRequest %08X"), aRequest); 
       
   860 
       
   861 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
   862 	
       
   863 	CFileShare* share;
       
   864 	CFileCB* file;
       
   865 	GetFileFromScratch(aRequest, share, file);
       
   866 
       
   867 	// Flag the request as having ended to allow another async read to occur
       
   868 	share->RequestEnd(&msgRequest);
       
   869 
       
   870 
       
   871 	// issue read-ahead
       
   872 	CFileCache* fileCache = file->FileCache();
       
   873 	if (fileCache && msgRequest.LastError() == KErrNone)
       
   874 		fileCache->ReadAhead(msgRequest, share->iMode);
       
   875 
       
   876 	return CFsRequest::EReqActionComplete;
       
   877 	}
       
   878 
       
   879 
       
   880 void GetFileFromScratch(CFsRequest* aRequest, CFileShare*& aShare, CFileCB*& aFile)
       
   881 	{
       
   882 
       
   883 	TInt64 scratchValue = aRequest->ScratchValue64();
       
   884 	TBool scratchValueIsShare  I64HIGH(scratchValue);
       
   885 	TUint32 scratchValueLow = I64LOW(scratchValue);
       
   886 	
       
   887 	aShare = NULL;
       
   888 	aFile = NULL;
       
   889 
       
   890 	if (scratchValueIsShare)
       
   891 		{
       
   892 		aShare = (CFileShare*) scratchValueLow;
       
   893 		if (aShare)
       
   894 			aFile = &aShare->File();
       
   895 		}
       
   896 	else
       
   897 		{
       
   898 		aFile = (CFileCB*) scratchValueLow;
       
   899 		}
       
   900 	}
       
   901 
       
   902 /**
       
   903     Common init preamble for TFsFileWrite::Initialise() and TFsFileWrite::DoRequestL()
       
   904     
       
   905     @param   aShare     pointer to the file share
       
   906     @param   aFile      pointer to the file object this function is called for
       
   907     @param   aPos       file position to write data. Note that it can be KCurrentPosition64 i.e. KMaxTUint64
       
   908     @param   aLen       length of the data to write
       
   909     @param   aFileSize  current file size
       
   910     @param   aFsOp      File Server message code. See TFsMessage. It must be ether EFsFileWrite for normal write, or EFsFileWriteDirty when file cache flushes dirty data
       
   911 */
       
   912 
       
   913 TInt TFsFileWrite::CommonInit(CFileShare* aShare, CFileCB* aFile, TInt64& aPos, TInt& aLen, TInt64 aFileSize, TFsMessage aFsOp)
       
   914 	{
       
   915 	
       
   916     if (aShare && aPos==KCurrentPosition64)
       
   917 		{//-- write to the current position in the file
       
   918 		aPos = aShare->iPos;
       
   919 		}
       
   920 
       
   921 	if(aPos > aFileSize)
       
   922 		aPos = aFileSize;
       
   923 
       
   924         //-- check that the new position won't exceed maximum file size
       
   925         {
       
   926         const TUint64 endPos = aPos+aLen;
       
   927 
       
   928 	    //-- Large file mode check. Legacy RFile size can't exceed 2G-1
       
   929         if(aShare && !(aShare->IsFileModeBig()) && (endPos > KMaxLegacyFileSize))
       
   930 		    return KErrTooBig;
       
   931 
       
   932         //-- check CMountCB limitation on maximum file size
       
   933         if(endPos > aFile->MaxSupportedSize())
       
   934             return KErrNotSupported; //-- this is for the sake of error codes consistency; current FSYs return 
       
   935                                      //-- this code in the case of accessing a file beyond its limit
       
   936        }
       
   937 
       
   938 	if (aShare)
       
   939 		{
       
   940 		TInt r;
       
   941 		if ((r=aFile->CheckLock64(aShare,aPos,aLen))!=KErrNone)
       
   942 			return(r);
       
   943 		}
       
   944 
       
   945     ASSERT(aFsOp == EFsFileWrite || aFsOp == EFsFileWriteDirty);
       
   946     if(aFsOp == EFsFileWrite)
       
   947         {//-- this call is originated from explicit file write operation. Set 'Archive' attribute and new file time.
       
   948         aFile->SetArchiveAttribute(); //-- it will also set KEntryAttModified
       
   949         }
       
   950     else
       
   951         {//-- don't touch data and attributes if it is cache flushing dirty data
       
   952         aFile->iAtt |= KEntryAttModified;
       
   953         }
       
   954 
       
   955 
       
   956 	return KErrNone;
       
   957 	}
       
   958 
       
   959 void TFsFileWrite::CommonEnd(CFsMessageRequest* aMsgRequest, TInt aRetVal, TUint64 aInitSize, TUint64 aNewSize, TInt64 aNewPos, TBool aFileWrite)
       
   960 //
       
   961 // Common end for TFsFileWrite::DoRequestL() and CFileCache::WriteBuffered()
       
   962 //
       
   963 	{
       
   964 
       
   965 	CFileShare* share;
       
   966 	CFileCB* file;
       
   967 	GetFileFromScratch(aMsgRequest, share, file);
       
   968 	CFileCache* fileCache = file->FileCache();
       
   969 	ASSERT(aFileWrite || fileCache);
       
   970 
       
   971 	TMsgOperation& currentOperation = aMsgRequest->CurrentOperation();
       
   972 
       
   973 	if (aRetVal == KErrNone || aRetVal == CFsRequest::EReqActionComplete)
       
   974 		{
       
   975 		if (share)
       
   976 			{
       
   977 			__e32_atomic_store_ord64(&share->iPos, aNewPos);
       
   978 			}
       
   979 		
       
   980 		if ((TUint64)aNewPos > aNewSize)
       
   981 			{
       
   982 			if(aFileWrite)
       
   983 				file->SetSize64(aNewPos, EFalse);
       
   984 			else
       
   985 				fileCache->SetSize64(aNewPos);
       
   986 			aNewSize = aNewPos;
       
   987 			}
       
   988 		
       
   989 		// ensure cached file is at least as big as uncached file
       
   990 		if (fileCache && fileCache->Size64() < aNewPos)
       
   991 			{
       
   992 			file->SetCachedSize64(aNewPos);
       
   993 			}
       
   994 		
       
   995 		// Service async reads if the file has grown & this is the last fair-scheduled request
       
   996 		
       
   997 		// If the file has grown, flag this and call CFileCB::NotifyAsyncReaders()
       
   998 		// later in TFsFileWrite::Complete() - we need to delay the call because
       
   999 		// CFileCB::NotifyAsyncReaders() may requeue a request which will cause 
       
  1000 		// the drive thread to spin because this file share is still marked as in use
       
  1001 		// (by CFileShare::RequestStart())
       
  1002 		if((aNewSize > aInitSize) && (currentOperation.iReadWriteArgs.iTotalLength == 0))
       
  1003 			{
       
  1004 			file->SetNotifyAsyncReadersPending(ETrue);
       
  1005 			}
       
  1006 		
       
  1007         file->iAtt |= KEntryAttModified;
       
  1008 
       
  1009 		}
       
  1010 	else if (aRetVal == KErrCorrupt)
       
  1011 		file->SetFileCorrupt(ETrue);
       
  1012 	else if (aRetVal == KErrBadPower || (aRetVal == KErrAbort && !PowerOk()))
       
  1013 		file->SetBadPower(ETrue);
       
  1014 
       
  1015 	file->ResetReadAhead();
       
  1016 	aMsgRequest->SetFreeChanged(aNewSize != aInitSize);
       
  1017 	}
       
  1018 
       
  1019 TInt TFsFileWrite::DoRequestL(CFsRequest* aRequest)
       
  1020 //
       
  1021 // Write to a file.
       
  1022 //
       
  1023 	{
       
  1024 	__PRINT(_L("TFsFileWrite::DoRequestL(CFsRequest* aRequest)"));
       
  1025 
       
  1026 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
  1027 	__ASSERT_DEBUG(msgRequest.CurrentOperationPtr() != NULL, Fault(EBadOperationIndex));
       
  1028 	TMsgOperation& currentOperation = msgRequest.CurrentOperation();
       
  1029 
       
  1030 	TInt r;
       
  1031 
       
  1032 	CFileShare* share;
       
  1033 	CFileCB* file;
       
  1034 	GetFileFromScratch(aRequest, share, file);
       
  1035 
       
  1036 	TInt64 initSize = file->Size64();
       
  1037 
       
  1038 	r = file->CheckMount();
       
  1039 	if (r!=KErrNone)
       
  1040 		return(r);
       
  1041 
       
  1042 
       
  1043 	TInt& len = currentOperation.iReadWriteArgs.iLength;
       
  1044 
       
  1045 	// Fair scheduling - 
       
  1046 	// Needs extended file API to work (so that we can specify an offset)
       
  1047 	// Also needs a separate drive thread to prevent excessive stack usage
       
  1048 	len = Min(len, currentOperation.iReadWriteArgs.iTotalLength);
       
  1049 	if (file->ExtendedFileInterfaceSupported() && !FsThreadManager::IsDriveSync(aRequest->DriveNumber(), EFalse))
       
  1050 		{
       
  1051 		len = Min(len, file->FairSchedulingLen());
       
  1052 		}
       
  1053 
       
  1054 	__ASSERT_DEBUG(len <= currentOperation.iReadWriteArgs.iTotalLength, Fault(EInvalidWriteLength));
       
  1055 	
       
  1056 	
       
  1057     const TFsMessage fsOp = (TFsMessage)aRequest->Operation()->Function(); 
       
  1058     r = CommonInit(share, file, currentOperation.iReadWriteArgs.iPos, len, initSize, fsOp);
       
  1059 
       
  1060 	if (r != KErrNone)
       
  1061 		return r;
       
  1062 	
       
  1063     TInt64 pos = currentOperation.iReadWriteArgs.iPos;
       
  1064 
       
  1065 	TInt64 upos = pos+len;
       
  1066 	if (upos > initSize)
       
  1067 		{
       
  1068 		r = CheckDiskSpace(upos - initSize, aRequest);
       
  1069         if(r != KErrNone)
       
  1070             return r;
       
  1071 		}
       
  1072 
       
  1073 	// The mount and any extensions must all support local buffers in order to support
       
  1074 	// internally generated requests (ie - requests originating from plugins)
       
  1075 	if ((aRequest->Message().Handle() == KLocalMessageHandle || !currentOperation.iClientRequest) && !file->LocalBufferSupport())
       
  1076 		{
       
  1077 		r = KErrNotSupported;
       
  1078 		}
       
  1079 
       
  1080 	if(r == KErrNone)
       
  1081 		{
       
  1082 		if (currentOperation.iClientRequest)
       
  1083 			{
       
  1084 			TRAP(r,file->WriteL(pos, len, (const TPtrC8*) aRequest->Message().Ptr0(), aRequest->Message(), currentOperation.iReadWriteArgs.iOffset))
       
  1085 			}
       
  1086 		else
       
  1087 			{
       
  1088 			TPtr8 dataDesc((TUint8*) currentOperation.iReadWriteArgs.iData + currentOperation.iReadWriteArgs.iOffset, len, len);
       
  1089 			const RLocalMessage msg;
       
  1090 			TRAP(r,file->WriteL(pos, len, &dataDesc, msg, 0));
       
  1091 			}
       
  1092 		}
       
  1093 
       
  1094 //RDebug::Print(_L("WriteR: req %08X pos %ld\t len %d file %08X\n"), aRequest, pos, len, file);
       
  1095 
       
  1096 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
       
  1097 	CCacheManager* manager = CCacheManagerFactory::CacheManager();
       
  1098 	if (manager)
       
  1099 		{
       
  1100 		manager->Stats().iUncachedPacketsWritten++;
       
  1101 		manager->Stats().iUncachedBytesWritten+= len;
       
  1102 		}
       
  1103 #endif
       
  1104 
       
  1105 	if (r == KErrNone)
       
  1106 		{
       
  1107 		// update position, offset  & length remaining
       
  1108 		currentOperation.iReadWriteArgs.iOffset+= len;
       
  1109 		currentOperation.iReadWriteArgs.iPos+= len;
       
  1110 		currentOperation.iReadWriteArgs.iTotalLength-= len;
       
  1111 		}
       
  1112 	TUint64 currentSize = MAKE_TUINT64(file->iBody->iSizeHigh,file->iSize);
       
  1113 	CommonEnd(&msgRequest, r, initSize, currentSize, pos+len, ETrue);
       
  1114 	
       
  1115 	// re-issue request if not complete (to support fair scheduling)
       
  1116 	if (r == KErrNone && currentOperation.iReadWriteArgs.iTotalLength > 0)
       
  1117 		return CFsRequest::EReqActionBusy;	// dispatch request again to back of queue
       
  1118 
       
  1119 	return(r);
       
  1120 	}
       
  1121 
       
  1122 TInt TFsFileWrite::Initialise(CFsRequest* aRequest)
       
  1123 //
       
  1124 //
       
  1125 //
       
  1126 	{
       
  1127 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
  1128 
       
  1129 	TInt r = DoInitNoParse(aRequest);
       
  1130 	if (r != KErrNone)
       
  1131 		return r;
       
  1132 
       
  1133 	// If the drive has been dismounted, don't even attempt to write to the file as that
       
  1134 	// will create dirty data which can then not be flushed without hitting ASSERTs etc.
       
  1135 	if (!FsThreadManager::IsDriveAvailable(aRequest->DriveNumber(), EFalse))
       
  1136 		return KErrNotReady;
       
  1137 
       
  1138 	CFileShare* share;
       
  1139 	CFileCB* file;
       
  1140 	GetFileFromScratch(aRequest, share, file);
       
  1141 
       
  1142 	// Bail out if there's a new mount which isn't ours - this would fail
       
  1143 	// later on anyway when TFsFileWrite::DoRequestL() called CFileCB::CheckMount()
       
  1144 	if ( !file->Drive().IsCurrentMount(file->Mount())  )
       
  1145 		return KErrDisMounted;
       
  1146 
       
  1147 
       
  1148 	TMsgOperation* msgOp = msgRequest.CurrentOperationPtr();
       
  1149 	if (!msgOp)	// initialised already ?
       
  1150 		{
       
  1151 		r = msgRequest.PushOperation(TFsFileWrite::Complete);
       
  1152 		if (r != KErrNone)
       
  1153 			return r;
       
  1154 		msgOp = msgRequest.CurrentOperationPtr();
       
  1155 		}
       
  1156 	// try to serialize requests to prevent asynchronous requests being processed out of sequence -
       
  1157 	// this isn't possible if a plugin is loaded as this may issue it's own requests 
       
  1158 	if (share && !share->RequestStart(&msgRequest))
       
  1159 		return CFsRequest::EReqActionPending;
       
  1160 	
       
  1161 	TInt64 pos;
       
  1162 	
       
  1163 	if(aRequest->IsDescData(KMsgPtr2))
       
  1164 		{//-- 64-bit file addressing, absolute read position is TInt64
       
  1165 			TPckg<TInt64> pkPos(pos);
       
  1166 			aRequest->ReadL(KMsgPtr2, pkPos);
       
  1167 		}
       
  1168 	else
       
  1169 		{
       
  1170 		if(aRequest->Message().Int2() == (TInt)I64LOW(KCurrentPosition64))
       
  1171 			pos = KCurrentPosition64;// Position is KCurrentPosition64 (-1)
       
  1172 		else
       
  1173 			pos = MAKE_TINT64(0,aRequest->Message().Int2());// Position is absolute value < 4GB, it's a TUint type
       
  1174 		}
       
  1175 
       
  1176 	msgOp->iClientPosition = pos;
       
  1177 	TInt len = aRequest->Message().Int1();
       
  1178 
       
  1179 	TDesC8* pD = (TDes8*) aRequest->Message().Ptr0();
       
  1180 	
       
  1181 	if (len == 0)
       
  1182 		return CFsRequest::EReqActionComplete;
       
  1183 	
       
  1184 	if (len < 0)
       
  1185 		return KErrArgument;
       
  1186 	
       
  1187 	//if this request was sent down from a plugin, then we want to
       
  1188 	//ignore the mode that the files was opened in.
       
  1189 	if (share && !msgRequest.IsPluginRequest())
       
  1190 		{
       
  1191 		if ((share->iMode & EFileWrite)==0 || 
       
  1192 			(share->iMode & KFileShareMask) == EFileShareReadersOnly)
       
  1193 			{
       
  1194 			return(KErrAccessDenied);
       
  1195 			}
       
  1196 		}
       
  1197 	
       
  1198 	
       
  1199     const TFsMessage fsOp = (TFsMessage)aRequest->Operation()->Function(); 
       
  1200     r = CommonInit(share, file, pos, len, file->CachedSize64(), fsOp);
       
  1201 	if (r != KErrNone)
       
  1202 		return r;
       
  1203 
       
  1204 	msgOp->Set(pos, len, pD);
       
  1205 
       
  1206 	return KErrNone;
       
  1207 	}
       
  1208 
       
  1209 
       
  1210 TInt TFsFileWrite::PostInitialise(CFsRequest* aRequest)
       
  1211 	{
       
  1212 	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
       
  1213 	CFileCB* file = &share->File();
       
  1214 	TInt r = KErrNone;
       
  1215 
       
  1216 	CFileCache* fileCache = file->FileCache();
       
  1217 	if (fileCache)
       
  1218 		{
       
  1219 		// If there's no data left proceed straight to completion stage
       
  1220 		// This can happen when re-posting a completed write request to 
       
  1221 		// start the dirty data timer
       
  1222 		if (((CFsMessageRequest*) aRequest)->CurrentOperation().iReadWriteArgs.iTotalLength == 0)
       
  1223 			return CFsRequest::EReqActionComplete;
       
  1224 
       
  1225 		r = fileCache->WriteBuffered(*(CFsMessageRequest*)aRequest, share->iMode);
       
  1226 		}
       
  1227 	
       
  1228 	return r;
       
  1229 	}
       
  1230 
       
  1231 TInt TFsFileWrite::Complete(CFsRequest* aRequest)
       
  1232 	{
       
  1233 	CFsMessageRequest& msgRequest = *(CFsMessageRequest*) aRequest;
       
  1234 	
       
  1235 
       
  1236 	CFileShare* share;
       
  1237 	CFileCB* file;
       
  1238 	GetFileFromScratch(aRequest, share, file);
       
  1239 
       
  1240 	if (share)
       
  1241 		share->RequestEnd(&msgRequest);
       
  1242 
       
  1243 	if (file->NotifyAsyncReadersPending())
       
  1244 		file->NotifyAsyncReaders();
       
  1245 	
       
  1246 	return CFsRequest::EReqActionComplete;
       
  1247 	}
       
  1248 
       
  1249 TInt TFsFileLock::DoRequestL(CFsRequest* aRequest)
       
  1250 //
       
  1251 // Lock a region of the file.
       
  1252 //
       
  1253 	{
       
  1254 
       
  1255 	__PRINT(_L("TFsFileLock::DoRequestL(CFsRequest* aRequest)"));
       
  1256 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1257 
       
  1258 	// We must wait for ALL shares to have no active requests (see RequestStart())
       
  1259 	// and post this request to the back of the queue if there are any. This is to 
       
  1260 	// avoid a fair-scheduled write from writing to a locked region of a file
       
  1261 	CSessionFs* session = aRequest->Session();
       
  1262 	if (session)
       
  1263 		{
       
  1264 		TBool fileInUse = EFalse;
       
  1265 		session->Handles().Lock();
       
  1266 		TInt count = session->Handles().Count();
       
  1267 		CFileCB* file = &share->File();
       
  1268 
       
  1269 		for (TInt n=0; n<count; n++)
       
  1270 			{
       
  1271 			CObjPromotion* obj = (CObjPromotion*)session->Handles()[n];
       
  1272 			if (obj != NULL && 
       
  1273 				obj->UniqueID() == FileShares->UniqueID() &&
       
  1274 				(file == &((CFileShare*) obj)->File()) &&
       
  1275 				((CFileShare*) obj)->RequestInProgress())
       
  1276 				{
       
  1277 				CFsMessageRequest& msgRequest = *(CFsMessageRequest*)aRequest;
       
  1278 				if(msgRequest.IsPluginRequest())
       
  1279 					break;
       
  1280 
       
  1281 				fileInUse = ETrue;
       
  1282 				break;
       
  1283 				}
       
  1284 			}
       
  1285 		session->Handles().Unlock();
       
  1286 		if (fileInUse)
       
  1287 			return CFsRequest::EReqActionBusy;
       
  1288 		}
       
  1289 	
       
  1290 	TInt64 pos, length;
       
  1291 	if(aRequest->IsDescData(KMsgPtr0))
       
  1292 		{
       
  1293 		TPckg<TInt64> pkPos(pos);
       
  1294 		aRequest->ReadL(KMsgPtr0, pkPos);
       
  1295 		}
       
  1296 	else
       
  1297 		{
       
  1298 		pos = MAKE_TINT64(0, aRequest->Message().Int0());
       
  1299 		}
       
  1300 	
       
  1301     if(aRequest->IsDescData(KMsgPtr1))
       
  1302 		{
       
  1303 		TPckg<TInt64> pkLength(length);
       
  1304 		aRequest->ReadL(KMsgPtr1, pkLength);
       
  1305 		if(length <= 0)
       
  1306 			User::Leave(ELockLengthZero);
       
  1307 		}
       
  1308 	else
       
  1309 		{
       
  1310 		length = aRequest->Message().Int1();
       
  1311 		if(length <= 0) 
       
  1312 			User::Leave(ELockLengthZero);
       
  1313 		}
       
  1314 	return(share->File().AddLock64(share, pos, length));
       
  1315 	}
       
  1316 
       
  1317 TInt TFsFileLock::Initialise(CFsRequest* aRequest)
       
  1318 //
       
  1319 //
       
  1320 //
       
  1321 	{
       
  1322 	return(DoInitNoParse(aRequest));
       
  1323 	}
       
  1324 
       
  1325 
       
  1326 TInt TFsFileUnlock::DoRequestL(CFsRequest* aRequest)
       
  1327 //
       
  1328 // Unlock a region of the file.
       
  1329 //
       
  1330 	{
       
  1331 	__PRINT(_L("TFsFileUnlock::DoRequestL(CFsRequest* aRequest)"));
       
  1332 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1333 	
       
  1334 	TInt64 pos, length;
       
  1335 	
       
  1336     if(aRequest->IsDescData(KMsgPtr0))
       
  1337 		{
       
  1338 		TPckg<TInt64> pkPos(pos);
       
  1339 		aRequest->ReadL(KMsgPtr0, pkPos);
       
  1340 		}
       
  1341 	else
       
  1342 		{
       
  1343 		pos = MAKE_TINT64(0, aRequest->Message().Int0());
       
  1344 		}
       
  1345 	
       
  1346     if(aRequest->IsDescData(KMsgPtr1))
       
  1347 		{
       
  1348 		TPckg<TInt64> pkLength(length);
       
  1349 		aRequest->ReadL(KMsgPtr1, pkLength);
       
  1350 		if(length <= 0)
       
  1351 			User::Leave(EUnlockLengthZero);
       
  1352 		}
       
  1353 	else
       
  1354 		{
       
  1355 		length = aRequest->Message().Int1();
       
  1356 		if(length <= 0) 
       
  1357 			User::Leave(EUnlockLengthZero);
       
  1358 		}
       
  1359 	return(share->File().RemoveLock64(share, pos, length));
       
  1360 	}
       
  1361 
       
  1362 TInt TFsFileUnlock::Initialise(CFsRequest* aRequest)
       
  1363 //
       
  1364 //
       
  1365 //
       
  1366 	{
       
  1367 	return(DoInitNoParse(aRequest));
       
  1368 	}
       
  1369 
       
  1370 
       
  1371 TInt TFsFileSeek::DoRequestL(CFsRequest* aRequest)
       
  1372 //
       
  1373 // Set the file position.
       
  1374 //
       
  1375 	{
       
  1376 
       
  1377 	__PRINT(_L("TFsFileSeek::DoRequestL(CFsRequest* aRequest)"));
       
  1378 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1379 	TInt64 size = share->File().CachedSize64();
       
  1380 	TInt64 pos;
       
  1381 	if(aRequest->IsDescData(KMsgPtr0))
       
  1382 		{
       
  1383 		TPckg<TInt64> pkPos(pos);
       
  1384 		aRequest->ReadL(KMsgPtr0, pkPos);
       
  1385 		}
       
  1386 	else
       
  1387 		{
       
  1388 		pos = aRequest->Message().Int0();
       
  1389 		}
       
  1390 	
       
  1391 	TInt r,t;
       
  1392 	
       
  1393 	if (share->iPos != pos)
       
  1394 		share->File().ResetReadAhead();
       
  1395 	
       
  1396 	switch (aRequest->Message().Int1())
       
  1397 		{
       
  1398 	case ESeekCurrent:
       
  1399 		pos+=share->iPos;
       
  1400 		if (pos<0)
       
  1401 			pos=0;
       
  1402 		
       
  1403         if (pos>size)
       
  1404 			pos=size;
       
  1405 
       
  1406 		// Large file mode check
       
  1407 		if((!(share->IsFileModeBig())) && ((TUint64)pos > KMaxLegacyFileSize))
       
  1408 			return (KErrTooBig);
       
  1409 
       
  1410 		break;
       
  1411 	case ESeekEnd:
       
  1412 		pos+=size;
       
  1413 		if (pos<0)
       
  1414 			pos=0;
       
  1415 		if (pos>size)
       
  1416 			pos=size;
       
  1417 		// Large file mode check
       
  1418 		if((!(share->IsFileModeBig())) && ((TUint64)pos > KMaxLegacyFileSize))
       
  1419 			return (KErrTooBig);
       
  1420 		
       
  1421         break;
       
  1422 	case ESeekAddress:
       
  1423 		t = (TUint)pos;
       
  1424 		r = share->File().Address(t);
       
  1425 		pos = (TUint)t;
       
  1426 		if(KErrNone != r)
       
  1427 			return(r);
       
  1428 		goto writeBackPos;
       
  1429 	case ESeekStart:
       
  1430 		if (pos>=0)
       
  1431             {
       
  1432             share->iPos = pos;
       
  1433             return KErrNone;
       
  1434             }
       
  1435 		return(KErrArgument);
       
  1436 	default:
       
  1437 		return(KErrArgument);
       
  1438 		}
       
  1439 	__e32_atomic_store_ord64(&share->iPos, pos);
       
  1440 writeBackPos:
       
  1441 	TPckgC<TInt64> pkNewPos(pos);
       
  1442 	aRequest->WriteL(KMsgPtr2, pkNewPos);
       
  1443 	return(KErrNone);
       
  1444 	}
       
  1445 
       
  1446 TInt TFsFileSeek::Initialise(CFsRequest* aRequest)
       
  1447 //
       
  1448 //
       
  1449 //
       
  1450 	{
       
  1451 	return(DoInitNoParse(aRequest));
       
  1452 	}
       
  1453 
       
  1454 
       
  1455 TInt TFsFileFlush::DoRequestL(CFsRequest* aRequest)
       
  1456 //
       
  1457 // Commit any data in memory to the media.
       
  1458 //
       
  1459 	{
       
  1460 
       
  1461 	__PRINT(_L("TFsFileFlush::DoRequestL(CFsRequest* aRequest)"));
       
  1462 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1463 
       
  1464 	// if any write requests are being fair scheduled, wait for them to complete
       
  1465 	if (share->RequestInProgress())
       
  1466 		return CFsRequest::EReqActionBusy;
       
  1467 
       
  1468 	// flush the write cache
       
  1469 	TInt r;
       
  1470 	CFileCache* fileCache = share->File().FileCache();
       
  1471 	if (fileCache && (r = fileCache->FlushDirty(aRequest)) != CFsRequest::EReqActionComplete)
       
  1472 	    {
       
  1473 		//To be used in notification framework
       
  1474 	    //CFsMessageRequest& msgRequest = (CFsMessageRequest&)*aRequest;
       
  1475 	    //msgRequest.iUID = msgRequest.Message().Identity();
       
  1476 		return r;
       
  1477 	    }
       
  1478 
       
  1479 	if ((share->File().Att()&KEntryAttModified)==0)
       
  1480 		return(KErrNone);
       
  1481 	if ((share->iMode&EFileWrite)==0)
       
  1482 		return(KErrAccessDenied);
       
  1483 	r=share->CheckMount();
       
  1484 	if (r!=KErrNone)
       
  1485 		return(r);
       
  1486 
       
  1487 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataL, EF32TraceUidFileSys, &share->File());
       
  1488 	TRAP(r,share->File().FlushDataL());
       
  1489 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataLRet, EF32TraceUidFileSys, r);
       
  1490 
       
  1491 	return(r);
       
  1492 	}
       
  1493 
       
  1494 TInt TFsFileFlush::Initialise(CFsRequest* aRequest)
       
  1495 //
       
  1496 //
       
  1497 //
       
  1498 	{
       
  1499 	return(DoInitNoParse(aRequest));
       
  1500 	}
       
  1501 
       
  1502 
       
  1503 TInt TFsFileSize::DoRequestL(CFsRequest* aRequest)
       
  1504 //
       
  1505 // Get the file size.
       
  1506 //
       
  1507 	{
       
  1508 
       
  1509 	__PRINT(_L("TFsFileSize::DoRequestL(CFsRequest* aRequest)"));
       
  1510 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1511 	TInt64 size = share->File().CachedSize64();
       
  1512 	// Large file mode check and error handling is done at client library side.
       
  1513 	// Return file size even if it is greater than 2GB - 1.
       
  1514 	TPckgC<TInt64> pkSize(size);
       
  1515 	aRequest->WriteL(KMsgPtr0, pkSize);
       
  1516 	return(KErrNone);
       
  1517 	}
       
  1518 
       
  1519 TInt TFsFileSize::Initialise(CFsRequest* aRequest)
       
  1520 //
       
  1521 //
       
  1522 //
       
  1523 	{
       
  1524 	return(DoInitNoParse(aRequest));
       
  1525 	}
       
  1526 
       
  1527 
       
  1528 TInt TFsFileSetSize::DoRequestL(CFsRequest* aRequest)
       
  1529 //
       
  1530 // Set the file size.
       
  1531 //
       
  1532 	{
       
  1533 	__PRINT(_L("TFsFileSetSize::DoRequestL(CFsRequest* aRequest)"));
       
  1534 
       
  1535 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1536 	if ((share->iMode&EFileWrite)==0)
       
  1537 		return(KErrAccessDenied);
       
  1538 	TInt r=share->CheckMount();
       
  1539 	if (r!=KErrNone)
       
  1540 		return(r);
       
  1541 
       
  1542 	TInt64 size;
       
  1543 	if(aRequest->IsDescData(KMsgPtr0))
       
  1544 		{
       
  1545 		TPckg<TInt64> pkSize(size);
       
  1546 		aRequest->ReadL(KMsgPtr0, pkSize);
       
  1547 		}
       
  1548 	else
       
  1549 		{
       
  1550 		size = aRequest->Message().Int0();
       
  1551 		}
       
  1552 
       
  1553 	if(size < 0)
       
  1554 		User::Leave(ESizeNegative);
       
  1555 	
       
  1556 	// Large file mode check
       
  1557 	if((!(share->IsFileModeBig())) && ((TUint64)size > KMaxLegacyFileSize))
       
  1558 		return (KErrTooBig);
       
  1559 	
       
  1560 	CFileCB& file=share->File();
       
  1561 
       
  1562 	// flush the write cache
       
  1563 	CFileCache* fileCache = share->File().FileCache();
       
  1564 	if (fileCache && (r = fileCache->FlushDirty(aRequest)) != CFsRequest::EReqActionComplete)
       
  1565 		return r;
       
  1566 	
       
  1567 	if (size==file.Size64())
       
  1568 		return(KErrNone);
       
  1569 	
       
  1570 	TBool fileHasGrown = size > file.Size64();
       
  1571 	if (fileHasGrown)
       
  1572 		{
       
  1573 		r = CheckDiskSpace(size - file.Size64(), aRequest);
       
  1574         if(r != KErrNone)
       
  1575             return r;
       
  1576 
       
  1577 		r=file.CheckLock64(share,file.Size64(),size-file.Size64());
       
  1578 		}	
       
  1579 	else
       
  1580 		r=file.CheckLock64(share,size,file.Size64()-size);
       
  1581 	if (r!=KErrNone)
       
  1582 		return(r);
       
  1583 	__PRINT1(_L("Owner mount size before SetSize() = %d"),I64LOW(file.Mount().Size()));
       
  1584 	TRAP(r,file.SetSizeL(size))
       
  1585 	if (r!=KErrNone)
       
  1586 		{
       
  1587 		//	Set size failed
       
  1588 		__PRINT1(_L("SetSize() failed = %d"),r);
       
  1589 		__PRINT1(_L("Owner mount size now = %d"),I64LOW(file.Mount().Size()));
       
  1590 		return(r);
       
  1591 		}
       
  1592 	file.SetArchiveAttribute();
       
  1593 	file.SetSize64(size, EFalse);
       
  1594 	file.SetCachedSize64(size);
       
  1595 
       
  1596 	if(fileHasGrown)
       
  1597 		file.NotifyAsyncReaders();	// Service outstanding async reads if the file has grown
       
  1598 
       
  1599 	return(r);
       
  1600 	}
       
  1601 
       
  1602 TInt TFsFileSetSize::Initialise(CFsRequest* aRequest)
       
  1603 //
       
  1604 //
       
  1605 //
       
  1606 	{
       
  1607 	return(DoInitNoParse(aRequest));
       
  1608 	}
       
  1609 
       
  1610 
       
  1611 TInt TFsFileAtt::DoRequestL(CFsRequest* aRequest)
       
  1612 //
       
  1613 // Get the file attributes.
       
  1614 //
       
  1615 	{
       
  1616 
       
  1617 	__PRINT(_L("TFsFileAtt::DoRequestL(CFsRequest* aRequest)"));
       
  1618 	
       
  1619     TInt r = CheckDiskSpace(0, aRequest);
       
  1620     if(r != KErrNone)
       
  1621         return r;
       
  1622 
       
  1623 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1624 //	TInt att=(TInt)aRequest->FileShare()->File().Att()&KEntryAttMaskSupported;
       
  1625 	TInt att=(TInt)share->File().Att();	// DRM: let ROM XIP attribute through
       
  1626 	TPtrC8 pA((TUint8*)&att,sizeof(TInt));
       
  1627 	aRequest->WriteL(KMsgPtr0,pA);
       
  1628 	
       
  1629     return(KErrNone);
       
  1630 	}
       
  1631 
       
  1632 TInt TFsFileAtt::Initialise(CFsRequest* aRequest)
       
  1633 //
       
  1634 //
       
  1635 //
       
  1636 	{
       
  1637 	return(DoInitNoParse(aRequest));
       
  1638 	}
       
  1639 
       
  1640 
       
  1641 TInt TFsFileSetAtt::DoRequestL(CFsRequest* aRequest)
       
  1642 //
       
  1643 // Set the file attributes.
       
  1644 //
       
  1645 	{
       
  1646 	__PRINT(_L("TFsFileSetAtt::DoRequestL(CSessionFs* aSession)"));
       
  1647     
       
  1648     TInt r = CheckDiskSpace(0, aRequest);
       
  1649     if(r != KErrNone)
       
  1650         return r;
       
  1651 
       
  1652 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1653 	r=share->CheckMount();
       
  1654 	if (r!=KErrNone)
       
  1655 		return(r);
       
  1656 	
       
  1657     if ((share->iMode&EFileWrite)==EFalse)
       
  1658 		return(KErrAccessDenied);
       
  1659 	
       
  1660     TUint setAttMask=(TUint)(aRequest->Message().Int0());
       
  1661 	TUint clearAttMask=(TUint)aRequest->Message().Int1();
       
  1662 	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);
       
  1663 
       
  1664 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
       
  1665 	TRAP(r,share->File().SetEntryL(TTime(0),setAttMask,clearAttMask))
       
  1666 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
       
  1667 
       
  1668 	return(r);
       
  1669 	}
       
  1670 
       
  1671 
       
  1672 TInt TFsFileSetAtt::Initialise(CFsRequest* aRequest)
       
  1673 //
       
  1674 //	Call GetShareFromHandle to determine asynchronicity ***
       
  1675 //
       
  1676 	{
       
  1677 	return(DoInitNoParse(aRequest));
       
  1678 	}
       
  1679 
       
  1680 
       
  1681 TInt TFsFileModified::DoRequestL(CFsRequest* aRequest)
       
  1682 //
       
  1683 // Get the modified date and time.
       
  1684 //
       
  1685 	{
       
  1686 	__PRINT(_L("TFsFileModified::DoRequestL(CFsRequest* aRequest)"));
       
  1687 
       
  1688     TInt r = CheckDiskSpace(0, aRequest);
       
  1689     if(r != KErrNone)
       
  1690         return r;
       
  1691         	
       
  1692 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1693 	TTime mod=share->File().Modified();
       
  1694 	TPtrC8 pM((TUint8*)&mod,sizeof(TTime));
       
  1695 	aRequest->WriteL(KMsgPtr0,pM);
       
  1696 	
       
  1697     return(KErrNone);
       
  1698 	}
       
  1699 
       
  1700 
       
  1701 TInt TFsFileModified::Initialise(CFsRequest* aRequest)
       
  1702 //
       
  1703 //	Call GetShareFromHandle to determine asynchronicity ***
       
  1704 //
       
  1705 	{
       
  1706 	return(DoInitNoParse(aRequest));
       
  1707 	}
       
  1708 
       
  1709 
       
  1710 TInt TFsFileSetModified::DoRequestL(CFsRequest* aRequest)
       
  1711 //
       
  1712 // Set the modified date and time.
       
  1713 //
       
  1714 	{
       
  1715 	__PRINT(_L("TFsFileSetModified::DoRequestL(CFsRequest* aRequest)"));
       
  1716     
       
  1717     TInt r = CheckDiskSpace(0, aRequest);
       
  1718     if(r != KErrNone)
       
  1719         return r;
       
  1720 
       
  1721 
       
  1722 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1723 	r=share->CheckMount();
       
  1724 	if (r!=KErrNone)
       
  1725 		return(r);
       
  1726 
       
  1727 	if ((share->iMode&EFileWrite)==EFalse)
       
  1728 		return(KErrAccessDenied);
       
  1729 	
       
  1730 	TTime time;
       
  1731 	TPtr8 t((TUint8*)&time,sizeof(TTime));
       
  1732 	aRequest->ReadL(KMsgPtr0,t);
       
  1733 
       
  1734 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, KEntryAttModified,0);
       
  1735 	TRAP(r,share->File().SetEntryL(time,KEntryAttModified,0))
       
  1736 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
       
  1737 
       
  1738 	return(r);
       
  1739 	}
       
  1740 
       
  1741 
       
  1742 TInt TFsFileSetModified::Initialise(CFsRequest* aRequest)
       
  1743 //
       
  1744 //	Call GetShareFromHandle to determine asynchronicity ***
       
  1745 //
       
  1746 	{
       
  1747 	return(DoInitNoParse(aRequest));
       
  1748 	}
       
  1749 
       
  1750 TInt TFsFileSet::DoRequestL(CFsRequest* aRequest)
       
  1751 //
       
  1752 // Set the attributes and the modified date and time.
       
  1753 //
       
  1754 	{
       
  1755 	__PRINT(_L("TFsFileSet::DoRequestL(CFsRequest* aRequest)"));
       
  1756 
       
  1757     TInt r = CheckDiskSpace(0, aRequest);
       
  1758     if(r != KErrNone)
       
  1759         return r;
       
  1760 
       
  1761 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1762 	r=share->CheckMount();
       
  1763 	if (r!=KErrNone)
       
  1764 		return(r);
       
  1765 	
       
  1766     if (share->File().Att()&KEntryAttReadOnly)
       
  1767 		return(KErrAccessDenied);
       
  1768 	
       
  1769     if ((share->iMode&EFileWrite)==0)
       
  1770 		{
       
  1771 		if(share->File().Drive().IsWriteProtected())
       
  1772 			return(KErrAccessDenied);
       
  1773 		}
       
  1774 	
       
  1775     TTime time;
       
  1776 	TPtr8 t((TUint8*)&time,sizeof(TTime));
       
  1777 	aRequest->ReadL(KMsgPtr0,t);
       
  1778 	TUint setAttMask=(TUint)(aRequest->Message().Int1()|KEntryAttModified);
       
  1779 	TUint clearAttMask=(TUint)aRequest->Message().Int2();
       
  1780 	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);//	Validate attributes
       
  1781 
       
  1782 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
       
  1783 	TRAP(r,share->File().SetEntryL(time,setAttMask,clearAttMask))
       
  1784 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
       
  1785 
       
  1786 	return(r);
       
  1787 	}
       
  1788 
       
  1789 TInt TFsFileSet::Initialise(CFsRequest* aRequest)
       
  1790 //
       
  1791 //
       
  1792 //
       
  1793 	{
       
  1794 	return(DoInitNoParse(aRequest));
       
  1795 	}
       
  1796 
       
  1797 
       
  1798 TInt TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)
       
  1799 //
       
  1800 // The access to a file may be changed from share exclusive to share readers only or vice versa.
       
  1801 // KErrAccessDenied is returned if the file has multiple readers.
       
  1802 //
       
  1803 	{
       
  1804 	__PRINT(_L("TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)"));
       
  1805 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1806 	TInt r=share->CheckMount();
       
  1807 	if (r!=KErrNone)
       
  1808 		return(r);
       
  1809 	
       
  1810 	const TFileMode currentMode = (TFileMode)share->iMode;
       
  1811 	const TFileMode newMode = (TFileMode)aRequest->Message().Int0();
       
  1812 	
       
  1813 		// check argument 
       
  1814 		// (only EFileShareExclusive and EFileShareReadersOnly are allowed)
       
  1815 	if((newMode & ~EFileShareReadersOnly) != 0)
       
  1816 		return KErrArgument;
       
  1817 	
       
  1818 		// check if the file is in EFileShareAny mode
       
  1819 	if( (currentMode & EFileShareAny) ||
       
  1820 	    // or the file has been opened for writing in EFileShareExclusive mode, 
       
  1821 		// and an attempt is made to change the access mode to EFileShareReadersOnly
       
  1822 		((currentMode & EFileWrite) && 
       
  1823 		 (currentMode & KFileShareMask) == EFileShareExclusive && 
       
  1824 		 newMode == EFileShareReadersOnly) )
       
  1825 		return KErrAccessDenied;
       
  1826 
       
  1827 		// check if an attempt is made to change the share mode to EFileShareExclusive
       
  1828 		// while the file has multiple readers
       
  1829 	if (newMode == EFileShareExclusive && (currentMode & KFileShareMask) != EFileShareExclusive)
       
  1830 		{ 
       
  1831 		// Check no other CFileCB is reading the file.
       
  1832 		FileShares->Lock();
       
  1833 		TInt count=FileShares->Count();
       
  1834 		TBool found=EFalse;
       
  1835 		while(count--)
       
  1836 			{
       
  1837 			CFileShare* fileShare=(CFileShare*)(*FileShares)[count];
       
  1838 			if (&fileShare->File()==&share->File())
       
  1839 				{
       
  1840 				if (found)
       
  1841 					{
       
  1842 					FileShares->Unlock();
       
  1843 					return(KErrAccessDenied);
       
  1844 					}
       
  1845 				found=ETrue;
       
  1846 				}
       
  1847 			}
       
  1848 		FileShares->Unlock();
       
  1849 		}
       
  1850 	share->iMode&=~KFileShareMask;
       
  1851 	share->iMode|=newMode;
       
  1852 	share->File().SetShare(newMode);
       
  1853 	return(KErrNone);
       
  1854 	}
       
  1855 
       
  1856 
       
  1857 TInt TFsFileChangeMode::Initialise(CFsRequest* aRequest)
       
  1858 //
       
  1859 //
       
  1860 //
       
  1861 	{
       
  1862 	TInt r = DoInitNoParse(aRequest);
       
  1863 	if(r != KErrNone)
       
  1864 		return r;
       
  1865 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1866 	if(CompareResource(share->File().FileName().Mid(2)) )
       
  1867 		{
       
  1868 		if(!KCapFsFileChangeMode.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("File Change Mode")))
       
  1869 			return KErrPermissionDenied;
       
  1870 		}
       
  1871 	return KErrNone;
       
  1872 	}
       
  1873 
       
  1874 
       
  1875 TInt TFsFileRename::DoRequestL(CFsRequest* aRequest)
       
  1876 //
       
  1877 // Rename the file if it was openned EFileShareExclusive
       
  1878 //
       
  1879 	{
       
  1880 	__PRINT(_L("TFsFileRename::DoRequestL(CFsRequest* aRequest)"));
       
  1881 
       
  1882     TInt r = CheckDiskSpace(0, aRequest);
       
  1883     if(r != KErrNone)
       
  1884         return r;
       
  1885 
       
  1886 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1887 	r=share->CheckMount();
       
  1888 	if (r!=KErrNone)
       
  1889 		return(r);
       
  1890 
       
  1891 	TInt currentMode=(share->iMode&KFileShareMask);
       
  1892 	if ((currentMode&EFileShareAny) || (currentMode&EFileShareReadersOnly))
       
  1893 		return(KErrAccessDenied); // File must be EFileShareExclusive
       
  1894 
       
  1895 	if ((share->iMode&EFileWrite)==0)
       
  1896 		return(KErrAccessDenied); // File must have write permission
       
  1897 
       
  1898 	TPtrC filePath = aRequest->Dest().FullName().Mid(2);
       
  1899 	CFileCB& file = share->File();
       
  1900 
       
  1901 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameL, EF32TraceUidFileSys, 
       
  1902 		(TUint) &file, filePath);
       
  1903 	TRAP(r,file.RenameL(filePath));
       
  1904 	TRACERETMULT1(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameLRet, EF32TraceUidFileSys, r);
       
  1905 
       
  1906 	// Re-write the file's folded name & re-calculate the hash
       
  1907 	if (r == KErrNone)
       
  1908 		{
       
  1909 		TFileName filePathF;
       
  1910 		filePathF.CopyF(filePath);
       
  1911 	    TRAP(r, AllocBufferL(file.iFileNameF, filePathF));
       
  1912 		file.iNameHash=CalcNameHash(*file.iFileNameF);
       
  1913 		}
       
  1914 
       
  1915 	return(r);
       
  1916 	}
       
  1917 
       
  1918 TInt TFsFileRename::Initialise(CFsRequest* aRequest)
       
  1919 //
       
  1920 //
       
  1921 //
       
  1922 	{
       
  1923 	TInt r=DoInitialise(aRequest);
       
  1924 	if(r!=KErrNone)
       
  1925 		return(r);
       
  1926 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1927 	TFileName newName;
       
  1928 	TRAP(r,aRequest->ReadL(KMsgPtr0,newName));
       
  1929 	if(r!=KErrNone)
       
  1930 		return(r);
       
  1931 	TDriveUnit currentDrive(share->File().Mount().Drive().DriveNumber());
       
  1932 	TDriveName driveName=currentDrive.Name();
       
  1933 	r=aRequest->Dest().Set(newName,&share->File().FileName(),&driveName);
       
  1934 	if (r!=KErrNone)
       
  1935 		return(r);
       
  1936 	if (aRequest->Dest().IsWild())
       
  1937 		return(KErrBadName);
       
  1938 	TInt driveNo;
       
  1939 	if ((r=RFs::CharToDrive(aRequest->Dest().Drive()[0],driveNo))!=KErrNone)
       
  1940 		return(r);
       
  1941 	TDrive& drive=TheDrives[driveNo];
       
  1942  	if(drive.IsSubsted())
       
  1943 		{
       
  1944 		if ((drive.Subst().Length()+aRequest->Dest().FullName().Length())>(KMaxFileName+3))
       
  1945 			return(KErrBadName);
       
  1946 		TFileName n=drive.Subst();
       
  1947 		n+=aRequest->Dest().FullName().Mid(3);
       
  1948 		r=aRequest->Dest().Set(n,NULL,NULL);
       
  1949 		if(r!=KErrNone)
       
  1950 			return(r);
       
  1951 		}
       
  1952 
       
  1953 	TDriveUnit newDrive(aRequest->Dest().Drive());
       
  1954 	if (newDrive!=currentDrive)
       
  1955 		return(KErrBadName);
       
  1956 	if (IsIllegalFullName(aRequest->Dest().FullName().Mid(2)))
       
  1957 		return(KErrBadName);
       
  1958 	r=PathCheck(aRequest,aRequest->Dest().FullName().Mid(2),&KCapFsSysFileRename,&KCapFsPriFileRename,&KCapFsROFileRename, __PLATSEC_DIAGNOSTIC_STRING("File Rename"));
       
  1959 	return(r);
       
  1960 	}
       
  1961 
       
  1962 
       
  1963 TInt TFsFileDrive::DoRequestL(CFsRequest* aRequest)
       
  1964 //
       
  1965 // Get the drive info for the file.
       
  1966 //
       
  1967 	{
       
  1968 	__PRINT(_L("TFsFileDrive::DoRequestL(CFsRequest* aRequest)"));
       
  1969 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  1970 	TDrive *dr = &share->File().Drive();
       
  1971 
       
  1972 	TPckgBuf<TInt> pkiF(dr->DriveNumber());		// copy drive number to user
       
  1973 	aRequest->WriteL(KMsgPtr0, pkiF);
       
  1974 
       
  1975 	TDriveInfo di;								// copy drive info to user
       
  1976 	dr->DriveInfo(di);
       
  1977 	TPckgC<TDriveInfo> pkdiF(di);
       
  1978 	aRequest->WriteL(KMsgPtr1, pkdiF);
       
  1979 
       
  1980 	return(KErrNone);
       
  1981 	}
       
  1982 
       
  1983 
       
  1984 TInt TFsFileDrive::Initialise(CFsRequest* aRequest)
       
  1985 //
       
  1986 //
       
  1987 //
       
  1988 	{
       
  1989 	return(DoInitNoParse(aRequest));
       
  1990 	}
       
  1991 
       
  1992 
       
  1993 TInt TFsFileDuplicate::DoRequestL(CFsRequest* aRequest)
       
  1994 //
       
  1995 // Duplicate the received file handle ready for transfer to another process.
       
  1996 // The new file handle is written back to the client in a a mangled form to prevent
       
  1997 // it from being used. Calling TFsFileAdopt will de-mangle the handle.
       
  1998 //
       
  1999 	{
       
  2000 	CFileShare* pS = (CFileShare*)aRequest->ScratchValue();
       
  2001 
       
  2002 	// get the file control block from the client's file share
       
  2003 	CFileCB& fileCB = pS->File();
       
  2004 
       
  2005 	// Create a new file share and initialize it with the 
       
  2006 	// client file share's file control block, position & mode
       
  2007 	
       
  2008 	CFileShare* pNewFileShare = new CFileShare(&fileCB);
       
  2009 	if (pNewFileShare == NULL)
       
  2010 		return KErrNoMemory;
       
  2011 
       
  2012 	// We need to call CFileCB::PromoteShare immediately after the CFileShare 
       
  2013 	// instance is created since the destructor calls CFileCB::DemoteShare()
       
  2014 	// which checks the share count is non-zero
       
  2015 	pNewFileShare->iMode = pS->iMode;
       
  2016 	fileCB.PromoteShare(pNewFileShare);
       
  2017 	
       
  2018 	
       
  2019 	TInt r = fileCB.Open();	// increment the ref count
       
  2020 
       
  2021 	if (r == KErrNone)
       
  2022 		TRAP(r, pNewFileShare->InitL());
       
  2023 	__e32_atomic_store_ord64(&pNewFileShare->iPos, pS->iPos);
       
  2024 	
       
  2025 	// Add new file share to the global file share container
       
  2026 	if (r == KErrNone)
       
  2027 		TRAP(r, FileShares->AddL(pNewFileShare,ETrue));
       
  2028 	
       
  2029 	// Add new file share to list owned by this session
       
  2030 	TInt newHandle;
       
  2031 	if (r == KErrNone)
       
  2032 		TRAP(r,newHandle = aRequest->Session()->Handles().AddL(pNewFileShare,ETrue));
       
  2033 
       
  2034 	if (r!=KErrNone)
       
  2035 		{
       
  2036 		pNewFileShare->Close();
       
  2037 		return r;
       
  2038 		}
       
  2039 
       
  2040 	newHandle^= KSubSessionMangleBit;
       
  2041 
       
  2042 	TPtrC8 pH((TUint8*)&newHandle, sizeof(TInt));
       
  2043 	aRequest->WriteL(KMsgPtr3, pH);
       
  2044 	aRequest->Session()->IncResourceCount();
       
  2045 	return(KErrNone);
       
  2046 	}
       
  2047 
       
  2048 TInt TFsFileDuplicate::Initialise(CFsRequest* aRequest)
       
  2049 	{
       
  2050 	TInt handle = aRequest->Message().Int0();
       
  2051 	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
       
  2052 	
       
  2053 	// If the handle is invalid, either panic (CFsMessageRequest::Dispatch() will 
       
  2054 	// panic if we return KErrBadHandle) or complete the request with KErrArgument.
       
  2055 	// The latter case is the behaviour for the (deprecated) RFile::Adopt() to
       
  2056 	// prevent a server from panicing if the passed file handle is invalid.
       
  2057 	if(!share)
       
  2058 		return aRequest->Message().Int1()?KErrBadHandle:KErrArgument;
       
  2059 
       
  2060 	aRequest->SetDrive(&share->File().Drive());
       
  2061 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
       
  2062 	return(KErrNone);
       
  2063 	}
       
  2064 
       
  2065 
       
  2066 
       
  2067 TInt TFsFileAdopt::DoRequestL(CFsRequest* aRequest)
       
  2068 //
       
  2069 // Adopt the passed file handle. This assumes that the handle has already been 
       
  2070 // duplicated by calling TFsFileDuplicate and is therefore mangled.
       
  2071 //
       
  2072 	{
       
  2073 	if (((CFileShare*)aRequest->ScratchValue()) == NULL)
       
  2074 		return KErrBadHandle;
       
  2075 	
       
  2076 	TInt adoptType = aRequest->Message().Int1();
       
  2077 	// EFileBigFile mode check
       
  2078 	switch(adoptType)
       
  2079 		{
       
  2080 		case KFileAdopt32:
       
  2081 			// Request is from RFile::Adopt or RFile::AdoptFromXXX: Force NO EFileBigFile
       
  2082 			((CFileShare*)aRequest->ScratchValue())->iMode &= ~EFileBigFile;
       
  2083 			break;
       
  2084 		case KFileAdopt64:
       
  2085 			// Request is from RFile64::AdoptFromXXX: Force EFileBigFile
       
  2086 			((CFileShare*)aRequest->ScratchValue())->iMode |= EFileBigFile;
       
  2087 			break;
       
  2088 		case KFileDuplicate:
       
  2089 			// Request is from RFile::Duplucate
       
  2090 			// adopt original file mode - do nothing
       
  2091 			break;
       
  2092 		//default:
       
  2093 			// Do nothing
       
  2094 		}
       
  2095 	
       
  2096 	// De-mangle the existing sub-session handle and return it to the client
       
  2097 	TInt newHandle = aRequest->Message().Int0() ^ KSubSessionMangleBit;
       
  2098 
       
  2099 	TPtrC8 pH((TUint8*)&newHandle,sizeof(TInt));
       
  2100 	aRequest->WriteL(KMsgPtr3,pH);
       
  2101 	return(KErrNone);
       
  2102 	}
       
  2103 
       
  2104 TInt TFsFileAdopt::Initialise(CFsRequest* aRequest)
       
  2105 	{
       
  2106 	TInt handle = aRequest->Message().Int0() ^KSubSessionMangleBit;
       
  2107 
       
  2108 	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
       
  2109 	// Normally returning KErrBadHandle will result in a panic, but when a server calls 
       
  2110 	// RFile::AdoptXXX() and it's client has given it a bad handle then it's not a good 
       
  2111 	// idea to panic the server. So we return KErrNone here and allow 
       
  2112 	// TFsFileAdopt::DoRequestL() to return KErrBadHandle
       
  2113 	if (share)
       
  2114 		aRequest->SetDrive(&share->File().Drive());
       
  2115 
       
  2116 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
       
  2117 	return(KErrNone);
       
  2118 	}
       
  2119 
       
  2120 
       
  2121 TInt TFsFileName::DoRequestL(CFsRequest* aRequest)
       
  2122 //
       
  2123 // Get the name of a file. 
       
  2124 // i.e. including the name & extension but excluding the drive and path
       
  2125 //
       
  2126 	{
       
  2127 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
       
  2128 
       
  2129 	// Search backwards until a backslash is found
       
  2130 	// This should always succeed as this is a full pathname
       
  2131 	TPtrC name(share->File().FileName());
       
  2132 	TInt offset = name.LocateReverse('\\');
       
  2133 	aRequest->WriteL(KMsgPtr0, name.Mid(offset+1));
       
  2134 
       
  2135 	return(KErrNone);
       
  2136 	}
       
  2137 
       
  2138 TInt TFsFileName::Initialise(CFsRequest* aRequest)
       
  2139 //
       
  2140 // Get the full name of a file, including path and drive 
       
  2141 //
       
  2142 //
       
  2143 	{
       
  2144 	return InitialiseScratchToShare(aRequest);
       
  2145 	}
       
  2146 	
       
  2147 	
       
  2148 TInt TFsFileFullName::DoRequestL(CFsRequest* aRequest)
       
  2149 //
       
  2150 // Get the full name of a file, including path and drive 
       
  2151 //
       
  2152 	{
       
  2153 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
       
  2154 
       
  2155 	// Write the drive letter and ':'
       
  2156 	TBuf<2> driveBuf(KDrivePath);
       
  2157 	driveBuf[0]=TText('A' + share->File().Drive().DriveNumber());
       
  2158 	aRequest->WriteL(KMsgPtr0, driveBuf);
       
  2159 
       
  2160 	// Write the file and path including leading '\'
       
  2161 	TPtrC name(share->File().FileName());
       
  2162 	aRequest->WriteL(KMsgPtr0, name, 2);
       
  2163 	
       
  2164 	return(KErrNone);
       
  2165 	}
       
  2166 
       
  2167 
       
  2168 TInt TFsFileFullName::Initialise(CFsRequest* aRequest)
       
  2169 //
       
  2170 //
       
  2171 //
       
  2172 	{
       
  2173 	return InitialiseScratchToShare(aRequest);
       
  2174 	}
       
  2175 
       
  2176 TInt TFsGetMediaSerialNumber::DoRequestL(CFsRequest* aRequest)
       
  2177 //
       
  2178 // Acquire capability from media and return serial number if supported.
       
  2179 //
       
  2180     {
       
  2181     // Get request parameters
       
  2182     const TInt drvNum = aRequest->Message().Int1();
       
  2183 
       
  2184 	// Get media capability
       
  2185     TLocalDriveCapsV5Buf capsBuf;
       
  2186 
       
  2187 	TInt r = KErrNone;
       
  2188 
       
  2189 	// is the drive local?
       
  2190 	if (!IsProxyDrive(drvNum))
       
  2191 		{
       
  2192 		// if not valid local drive, use default values in localDriveCaps
       
  2193 		// if valid local drive and not locked, use TBusLocalDrive::Caps() values
       
  2194 		// if valid drive and locked, hard-code attributes
       
  2195 		r = GetLocalDrive(drvNum).Caps(capsBuf);
       
  2196 		}
       
  2197 	else  // this need to be made a bit nicer
       
  2198 		{   
       
  2199 		CExtProxyDrive* pD = GetProxyDrive(drvNum);
       
  2200 		if(pD)
       
  2201 			r = pD->Caps(capsBuf);
       
  2202 		else
       
  2203 			r = KErrNotReady;
       
  2204 		}
       
  2205 	
       
  2206 	if (r != KErrNone)
       
  2207         return r;
       
  2208 
       
  2209     TLocalDriveCapsV5& capsV5 = capsBuf();
       
  2210 
       
  2211     // Return serial number if supported
       
  2212     if (capsV5.iSerialNumLength == 0)
       
  2213         return KErrNotSupported;
       
  2214 
       
  2215     TPtrC8 snPtr(capsV5.iSerialNum, capsV5.iSerialNumLength);
       
  2216     aRequest->WriteL(KMsgPtr0, snPtr);
       
  2217 
       
  2218 	return KErrNone;
       
  2219     }
       
  2220 
       
  2221 TInt TFsGetMediaSerialNumber::Initialise(CFsRequest* aRequest)
       
  2222 //
       
  2223 // Validate drive number and its attributes passed in a request object.
       
  2224 //
       
  2225     {
       
  2226     const TInt drvNum = aRequest->Message().Int1();
       
  2227 
       
  2228     TInt nRes = ValidateDrive(drvNum, aRequest);
       
  2229     if(nRes != KErrNone)
       
  2230         return KErrBadName; //-- incorrect drive number
       
  2231 
       
  2232     if(aRequest->Drive()->IsSubsted())
       
  2233         return KErrNotSupported; //-- the drive is substed, this operation doesn't make a sense
       
  2234     
       
  2235     if(!IsValidLocalDriveMapping(drvNum))
       
  2236 	    return KErrNotReady;
       
  2237 
       
  2238     return KErrNone;
       
  2239     }
       
  2240 
       
  2241 TInt TFsBlockMap::Initialise(CFsRequest* aRequest)
       
  2242 	{
       
  2243 	TInt r = DoInitNoParse(aRequest);
       
  2244 	if(r!=KErrNone)
       
  2245 		return r;
       
  2246 
       
  2247 	TInt blockMapUsage = aRequest->Message().Int2();
       
  2248 	if ( blockMapUsage == EBlockMapUsagePaging )
       
  2249 		{
       
  2250 		CFileShare* share = (CFileShare*) aRequest->ScratchValue();
       
  2251 		CFileCB& file = share->File();
       
  2252 
       
  2253 		// To determine whether the drive where this file resides is pageable, we need to locate 
       
  2254 		// the specific TBusLocalDrive object first; querying the drive attributes directly from the 
       
  2255 		// (composite) file system is no good as this API treats all slave file systems as "ROM & not pageable.
       
  2256 		TBusLocalDrive* localDrive;
       
  2257 		TInt r = file.LocalDrive(localDrive);
       
  2258 		if (r != KErrNone)
       
  2259 			return r;
       
  2260 		TLocalDriveCapsV4Buf caps;
       
  2261 		r = localDrive->Caps(caps);
       
  2262 		if (r != KErrNone)
       
  2263 			return r;
       
  2264 		__PRINT4(_L("TFsBlockMap::Initialise, drive %d file %S iMediaAtt %08X iDriveAtt %08X\n"), file.DriveNumber(), &file.FileName(), caps().iMediaAtt, caps().iDriveAtt);
       
  2265 		if ( !(caps().iDriveAtt & KDriveAttPageable))
       
  2266 			return KErrNotSupported;
       
  2267 		}
       
  2268 
       
  2269 	return KErrNone;
       
  2270 	}
       
  2271 
       
  2272 TInt TFsBlockMap::DoRequestL(CFsRequest* aRequest)
       
  2273 	{
       
  2274 	__PRINT(_L("TFsBlockMap::DoRequestL(CFsRequest* aRequest)"));
       
  2275 	__PRINT1(_L("aRequest->Session() = 0x%x"), aRequest->Session());
       
  2276 
       
  2277 	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
       
  2278 
       
  2279 	TInt r = share->CheckMount();
       
  2280 
       
  2281 	__PRINT1(_L("share->CheckMount() returned - %d"), r);
       
  2282 	if ( r != KErrNone )
       
  2283 		return(r);
       
  2284 
       
  2285 	SBlockMapInfo reqInfo;
       
  2286 	SBlockMapArgs args;
       
  2287 	TPckg<SBlockMapArgs> pkArgs(args);
       
  2288 	aRequest->ReadL(KMsgPtr1, pkArgs);
       
  2289 
       
  2290 	CFileCB& file = share->File();
       
  2291 	TInt64& reqStartPos = args.iStartPos;
       
  2292 	TInt64 reqEndPos = args.iEndPos;
       
  2293 
       
  2294 	if ( ( reqStartPos > file.Size64() ) || ( reqStartPos < 0 ) )
       
  2295 		return KErrArgument;
       
  2296 
       
  2297 	const TInt64 KReadToEOF = -1;
       
  2298 	if ( reqEndPos != KReadToEOF )
       
  2299  		{
       
  2300 		if ( !( reqEndPos >= reqStartPos ) )
       
  2301 			return KErrArgument;
       
  2302 		}
       
  2303 	else
       
  2304 		reqEndPos = file.Size64();
       
  2305 
       
  2306 	// If the requested start position is equal to the size of the file
       
  2307 	// then we read no data and return an empty BlockMap.
       
  2308 	if ( reqStartPos == file.Size64() || reqEndPos == 0 || reqEndPos == reqStartPos )
       
  2309 		{
       
  2310 		TPckg<SBlockMapInfo> pkInfo(reqInfo);
       
  2311 		TRAP(r,aRequest->WriteL(KMsgPtr0,pkInfo) );
       
  2312  		if ( r == KErrNone )
       
  2313  			return(KErrArgument);
       
  2314 		else
       
  2315 			return(r);
       
  2316 		}
       
  2317 	r = share->File().BlockMap(reqInfo, reqStartPos, reqEndPos);
       
  2318 	TPckg<SBlockMapInfo> pkInfo(reqInfo);
       
  2319 	aRequest->WriteL(KMsgPtr0, pkInfo);
       
  2320 	aRequest->WriteL(KMsgPtr1, pkArgs);
       
  2321 
       
  2322 	return(r);
       
  2323 	}
       
  2324 
       
  2325 #pragma warning( disable : 4705 )	// statement has no effect
       
  2326 /**
       
  2327 Default constructor
       
  2328 */
       
  2329 EXPORT_C CFileCB::CFileCB()
       
  2330 	{
       
  2331 	}
       
  2332 #pragma warning( default : 4705 )
       
  2333 
       
  2334 
       
  2335 
       
  2336 
       
  2337 /**
       
  2338 Destructor.
       
  2339 
       
  2340 Frees resources before destruction of the object.
       
  2341 */
       
  2342 EXPORT_C CFileCB::~CFileCB()
       
  2343 	{
       
  2344 	// NB Must be careful to close the file cache BEFORE deleting iFileNameF
       
  2345 	// as CFileCache may steal it (!)
       
  2346 	if (FileCache())
       
  2347 		FileCache()->Close();
       
  2348 	if (iBody && iBody->iDeleteOnClose)
       
  2349 		{
       
  2350 		TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteL, EF32TraceUidFileSys, DriveNumber(), FileName());
       
  2351 		TInt r;
       
  2352 		TRAP(r, iMount->DeleteL(FileName()));
       
  2353 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteLRet, EF32TraceUidFileSys, r);
       
  2354 		}
       
  2355 
       
  2356 	if(iMount)
       
  2357 		iMount->Close();
       
  2358 	if (iMountLink.iNext!=NULL)
       
  2359 		{
       
  2360 		iMountLink.Deque();
       
  2361 		}
       
  2362 	delete iFileName;
       
  2363 	delete iFileNameF;
       
  2364 	if (iFileLocks)
       
  2365 		{
       
  2366 		iFileLocks->Close();
       
  2367 		delete iFileLocks;
       
  2368 		}
       
  2369 
       
  2370 	delete iBody;
       
  2371 	}
       
  2372 
       
  2373 /**
       
  2374     Initialise CFileCB object.
       
  2375     @internalTechnology
       
  2376 
       
  2377     @param  aDrive
       
  2378     @param  aCreatedDrive
       
  2379     @param  aName           file name descriptor
       
  2380 */
       
  2381 EXPORT_C void CFileCB::InitL(TDrive* aDrive, TDrive* aCreatedDrive, HBufC* aName)
       
  2382 	{
       
  2383 	// Take ownership of heap-allocated objects aName and aLock before attempting any memory allocation 
       
  2384 	// to avoid leaking memory
       
  2385 	iFileName = aName;
       
  2386 
       
  2387     DoInitL(aDrive->DriveNumber());
       
  2388 	iDrive=aDrive;
       
  2389 	iCreatedDrive=aCreatedDrive;
       
  2390 	TFileName tempName;
       
  2391 	tempName.CopyF(*aName);
       
  2392 	iFileNameF=tempName.AllocL();
       
  2393 	iNameHash=CalcNameHash(*iFileNameF);
       
  2394 	
       
  2395 
       
  2396 	
       
  2397 	// see whether the file system supports the CFileCB extended API
       
  2398 	MExtendedFileInterface* extendedFileInterface = NULL;
       
  2399 	GetInterfaceTraced(CFileCB::EExtendedFileInterface, (void*&) extendedFileInterface, NULL);
       
  2400 	iBody = new(ELeave)CFileBody(this, extendedFileInterface);
       
  2401 
       
  2402 	iMount=&iDrive->CurrentMount();
       
  2403 	iBody->InitL();
       
  2404 	User::LeaveIfError(iMount->Open());
       
  2405 	
       
  2406 	//-- create file locks array
       
  2407     ASSERT(!iFileLocks);
       
  2408     iFileLocks = new(ELeave) TFileLocksArray(KFileShareLockGranularity, _FOFF(TFileShareLock, iPosLow));
       
  2409 
       
  2410     }
       
  2411 	
       
  2412 
       
  2413 TInt CFileCB::FindLock(TInt aPosLow,TInt aPosHigh)
       
  2414 	{
       
  2415 	return FindLock64(aPosLow, aPosHigh);
       
  2416 	}
       
  2417 
       
  2418 TInt CFileCB::AddLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
       
  2419 	{
       
  2420 	return AddLock64(aFileShare, aPos, aLength);
       
  2421 	}
       
  2422 
       
  2423 TInt CFileCB::RemoveLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
       
  2424 	{
       
  2425 	return RemoveLock64(aFileShare, aPos, aLength);
       
  2426 	}
       
  2427 
       
  2428 TInt CFileCB::CheckLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
       
  2429 	{
       
  2430 	return CheckLock64(aFileShare, aPos, aLength);
       
  2431 	}
       
  2432 
       
  2433 /**
       
  2434     Remove any locks held by aFileShare.
       
  2435 */
       
  2436 void CFileCB::RemoveLocks(CFileShare* aFileShare)
       
  2437 	{
       
  2438 
       
  2439 	TInt i=0;
       
  2440 	while (i<FileLocks().Count())
       
  2441 		{
       
  2442 		if (FileLocks()[i].MatchOwner(aFileShare))
       
  2443 			FileLocks().Remove(i);
       
  2444 		else
       
  2445 			i++;
       
  2446 		}
       
  2447 	}
       
  2448 
       
  2449 
       
  2450 void CFileCB::PromoteShare(CFileShare* aShare)
       
  2451 //
       
  2452 // Manages share promotion after the share has been added to the FilsShares container.
       
  2453 //
       
  2454 //  - Assumes the share has already been validated using ValidateShare()
       
  2455 //
       
  2456 //  - The count of promoted shares (ie - non-EFileShareReadersOrWriters) is incremented
       
  2457 //	  to allow the share mode to be demoted when the last promoted share is closed.
       
  2458 //
       
  2459 	{
       
  2460 	TShare reqShare = (TShare)(aShare->iMode & KFileShareMask);
       
  2461 	if(reqShare != EFileShareReadersOrWriters)
       
  2462 		{
       
  2463 		iBody->iPromotedShares++;
       
  2464 		iShare = reqShare;
       
  2465 		}
       
  2466 	}
       
  2467 
       
  2468 
       
  2469 void CFileCB::DemoteShare(CFileShare* aShare)
       
  2470 //
       
  2471 // Manages share demotion after the share has been removed from the FileShares container.
       
  2472 //
       
  2473 //  - If the share being removed is not EFileShareReadersOrWriters, then the current
       
  2474 //	  share mode may require demotion back to EFileShareReadersOrWriters.
       
  2475 //
       
  2476 //	- This is determined by the iPromotedShares count, incremented in PromoteShare()
       
  2477 //
       
  2478 	{
       
  2479 	if((aShare->iMode & KFileShareMask) != EFileShareReadersOrWriters)
       
  2480 		{
       
  2481 		if(--iBody->iPromotedShares == 0)
       
  2482 			{
       
  2483 			// Don't worry if the file has never been opened as EFileShareReadersOrWriters
       
  2484 			//  - in this case the CFileCB object is about to be closed anyway.
       
  2485 			iShare = EFileShareReadersOrWriters;
       
  2486 			}
       
  2487 		}
       
  2488 	__ASSERT_DEBUG(iBody->iPromotedShares>=0,Fault(EFileShareBadPromoteCount));
       
  2489 	}
       
  2490 
       
  2491 
       
  2492 RArray<TAsyncReadRequest>& CFileCB::AsyncReadRequests()
       
  2493 //
       
  2494 // Gets a reference to the pending asynchronous read requests for this file.
       
  2495 //
       
  2496 //  - The request is completed when all data is available or the request is cancelled.
       
  2497 //
       
  2498 	{
       
  2499 	return(*iBody->iAsyncReadRequests);
       
  2500 	}
       
  2501 
       
  2502 
       
  2503 TInt CFileCB::AddAsyncReadRequest(CFileShare* aShareP, TInt64 aPos, TInt aLen, CFsRequest* aRequestP)
       
  2504 //
       
  2505 // Adds a pending asynchronous read request to the list.
       
  2506 //
       
  2507 //  - The request is completed when all data is available or the request is cancelled.
       
  2508 //
       
  2509 	{
       
  2510 
       
  2511 	__ASSERT_ALWAYS(aRequestP->Operation()->Function() == EFsFileRead, Fault(EBaseRequestMessage));
       
  2512 	
       
  2513 	TAsyncReadRequest req(aPos + aLen, aShareP, aRequestP);
       
  2514 	TInt err = AsyncReadRequests().InsertInSignedKeyOrderAllowRepeats(req);
       
  2515 	if(err != KErrNone)
       
  2516 		return err;
       
  2517 
       
  2518 	aRequestP->SetCompleted(EFalse);
       
  2519 	return KErrNone;
       
  2520 	}
       
  2521 
       
  2522 
       
  2523 TInt CFileCB::CancelAsyncReadRequest(CFileShare* aShareP, TRequestStatus* aStatusP)
       
  2524 //
       
  2525 // Cancels (and completes) an outstanding read request for the specified share.
       
  2526 //
       
  2527 //	- aStatusP == NULL cancels all outstanding read requests.
       
  2528 //
       
  2529 	{
       
  2530 
       
  2531 	TInt i=0;
       
  2532 	Drive().Lock();
       
  2533 	while (i < AsyncReadRequests().Count())
       
  2534 		{
       
  2535 		TAsyncReadRequest& req = AsyncReadRequests()[i];
       
  2536 		if(req.CompleteIfMatching(aShareP, aStatusP, KErrCancel))
       
  2537 			{
       
  2538 			iBody->iAsyncReadRequests->Remove(i);
       
  2539 			if(aStatusP != NULL)
       
  2540 				{
       
  2541 				Drive().UnLock();
       
  2542 				return KErrNone;
       
  2543 				}
       
  2544 			}
       
  2545 		else
       
  2546 			{
       
  2547 			i++;
       
  2548 			}
       
  2549 		}
       
  2550 
       
  2551 	Drive().UnLock();
       
  2552 	return KErrNone;
       
  2553 	}
       
  2554 
       
  2555 
       
  2556 void CFileCB::NotifyAsyncReaders()
       
  2557 //
       
  2558 // Determine if any outstanding read requests require completion.
       
  2559 //
       
  2560 //  - Called whenever the file size changes (due to a write operation or SetSize)
       
  2561 //
       
  2562 //  - Any outstanding read requests are re-issued (rather then completed in the 
       
  2563 //    context of the current operation so not to affect performance of the writer).
       
  2564 //
       
  2565 //  - Should the file size shrink before the request is serviced, the request will
       
  2566 //    be added back onto the queue.
       
  2567 //
       
  2568 //	- A future optimisation may issue the request as data becomes available (which
       
  2569 //	  would minimise the final latency between writer and reader) but the current
       
  2570 //	  implementation reads all requested data in one operation.
       
  2571 //
       
  2572 	{
       
  2573 	Drive().Lock();
       
  2574 	
       
  2575 	SetNotifyAsyncReadersPending(EFalse);
       
  2576 
       
  2577 	while(AsyncReadRequests().Count())
       
  2578 		{
       
  2579 		TAsyncReadRequest& req = AsyncReadRequests()[0];
       
  2580 		if(req.iEndPos > CachedSize64())
       
  2581 			break;
       
  2582 
       
  2583 		// Make a copy and then remove it from the queue before releasing the lock - 
       
  2584 		// because the file server thread could append to the RArray and this might 
       
  2585 		// cause a re-allocation which would move the whole array (!)
       
  2586 		TAsyncReadRequest reqCopy = req;
       
  2587 		AsyncReadRequests().Remove(0);
       
  2588 		Drive().UnLock();
       
  2589 
       
  2590 		// allocate a new request, push a TMsgOperation onto the request's stack (duplicating
       
  2591 		// the functionality of TFsFileRead::Initialise()) & dispatch the request
       
  2592 		CFsClientMessageRequest* pRequest = NULL;
       
  2593 		const TOperation& oP = OperationArray[EFsFileRead];
       
  2594 		TInt r = RequestAllocator::GetMessageRequest(oP, reqCopy.iMessage, pRequest);
       
  2595 		if (r != KErrNone)
       
  2596 			{
       
  2597 			reqCopy.iMessage.Complete(r);	// complete the client's message with an error
       
  2598 			continue;
       
  2599 			}
       
  2600 		pRequest->Set(reqCopy.iMessage, oP, reqCopy.iSessionP);
       
  2601 
       
  2602 		r = DoInitNoParse(pRequest);
       
  2603 		if (r != KErrNone)
       
  2604 			{
       
  2605 			pRequest->Complete(r);		// complete the client's message with an error
       
  2606 			continue;
       
  2607 			}
       
  2608 		
       
  2609 		r = pRequest->PushOperation(TFsFileRead::Complete);
       
  2610 		if (r != KErrNone)
       
  2611 			{
       
  2612 			pRequest->Complete(r);		// complete the client's message with an error
       
  2613 			continue;
       
  2614 			}
       
  2615 
       
  2616 		pRequest->CurrentOperation().Set(
       
  2617 			reqCopy.iEndPos - pRequest->Message().Int1(), 
       
  2618 			pRequest->Message().Int1(), 
       
  2619 			(TDes8*) pRequest->Message().Ptr0());
       
  2620 
       
  2621 		// don't call Initialise()
       
  2622 		pRequest->SetState(CFsRequest::EReqStatePostInitialise);
       
  2623 
       
  2624 		pRequest->Dispatch();
       
  2625 		Drive().Lock();
       
  2626 		}
       
  2627 	Drive().UnLock();
       
  2628 	}
       
  2629 
       
  2630 
       
  2631 /**
       
  2632 Gets the address of the file that the file control block represents. 
       
  2633 
       
  2634 The default implementation returns KErrNotSupported and should only
       
  2635 be overridden for ROM file systems.
       
  2636 
       
  2637 @param aPos On return, should contain the address of the file that
       
  2638             the file control block represents.
       
  2639 
       
  2640 @return KErrNone, if successful,otherwise one of the other system wide error
       
  2641         codes,
       
  2642 */
       
  2643 EXPORT_C TInt CFileCB::Address(TInt& /*aPos*/) const
       
  2644 	{
       
  2645 
       
  2646 	return(KErrNotSupported);
       
  2647 	}
       
  2648 
       
  2649 
       
  2650 /**
       
  2651 Sets the archive attribute, KEntryAttArchive, in iAtt.
       
  2652 */
       
  2653 EXPORT_C void CFileCB::SetArchiveAttribute()
       
  2654 	{
       
  2655 
       
  2656 	iAtt|=KEntryAttArchive;
       
  2657 	iAtt|=KEntryAttModified;
       
  2658 	iModified.UniversalTime();
       
  2659 	}
       
  2660 
       
  2661 
       
  2662 EXPORT_C TInt CFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* /*aInput*/)
       
  2663 	{
       
  2664 	switch(aInterfaceId)
       
  2665 		{
       
  2666 		case EGetLocalDrive:
       
  2667 			return Mount().LocalDrive((TBusLocalDrive*&) aInterface);
       
  2668 		default:
       
  2669 			return(KErrNotSupported);
       
  2670 		}
       
  2671 	}
       
  2672 
       
  2673 
       
  2674 CFileCache* CFileCB::FileCache() const
       
  2675 	{return iBody?iBody->iFileCache:NULL;}
       
  2676 
       
  2677 TBool CFileCB::LocalBufferSupport() const
       
  2678 	{return iBody?iBody->iLocalBufferSupport:EFalse;}
       
  2679 
       
  2680 void CFileCB::SetLocalBufferSupport(TBool aEnabled)
       
  2681 	{iBody->iLocalBufferSupport = aEnabled;}
       
  2682 
       
  2683 TInt CFileCB::CheckMount()
       
  2684 //
       
  2685 // Check that the media is still mounted.
       
  2686 //
       
  2687 	{
       
  2688 
       
  2689 	TDrive& d = Drive();
       
  2690 	TInt r=d.CheckMount();
       
  2691 	if (r!=KErrNone)
       
  2692 		return(r);
       
  2693 	if (&Mount() != &d.CurrentMount())
       
  2694 		return(KErrDisMounted);
       
  2695 	if (FileCorrupt())
       
  2696 		return(KErrCorrupt);
       
  2697 	if (BadPower())
       
  2698 		{
       
  2699 		if (PowerOk())
       
  2700 			SetBadPower(EFalse);
       
  2701 		else
       
  2702 			return(KErrBadPower);
       
  2703 		}
       
  2704 	return(KErrNone);
       
  2705 	}
       
  2706 
       
  2707 TInt64 CFileCB::CachedSize64() const
       
  2708 	{
       
  2709 	CFileCache* fileCache = iBody?iBody->iFileCache:NULL;
       
  2710 	return fileCache? fileCache->Size64(): Size64();
       
  2711 	}
       
  2712 
       
  2713 void CFileCB::SetCachedSize64(TInt64 aSize)
       
  2714 	{
       
  2715 	if (FileCache())
       
  2716 		FileCache()->SetSize64(aSize);
       
  2717 	else
       
  2718 		SetSize64(aSize, EFalse);	// assume not locked
       
  2719 	}
       
  2720 
       
  2721 /**
       
  2722 Constructor.
       
  2723 Locks the mount resource to which the shared file resides.
       
  2724 
       
  2725 @param aFileCB File to be shared.
       
  2726 */
       
  2727 CFileShare::CFileShare(CFileCB* aFileCB)
       
  2728 	: iFile(aFileCB)
       
  2729 	{
       
  2730 	AddResource(iFile->Mount());
       
  2731 	}
       
  2732 
       
  2733 /**
       
  2734 Destructor.
       
  2735 
       
  2736 Frees mount resource to which the shared file resides,
       
  2737 removes share status from the shared file and finally closes
       
  2738 the file.
       
  2739 */
       
  2740 CFileShare::~CFileShare()
       
  2741 	{
       
  2742 	// We shouldn't be deleting the file share with a valid request queue or there will be request (& memory) leakage
       
  2743 	__ASSERT_DEBUG(iCurrentRequest == NULL, Fault(ERequestQueueNotEmpty));
       
  2744 
       
  2745 	RemoveResource(iFile->Mount());
       
  2746 	iFile->RemoveLocks(this);
       
  2747 	iFile->DemoteShare(this);
       
  2748 	iFile->CancelAsyncReadRequest(this, NULL);
       
  2749 	iFile->Close();
       
  2750 	}
       
  2751 
       
  2752 /**
       
  2753 Check that the media is still mounted.
       
  2754 
       
  2755 @return KErrNone if successful.
       
  2756         KErrDisMounted if media has dismounted.
       
  2757         KErrCorrupted if shared file is corrupted.
       
  2758         KErrBadPower if insufficent power supply.
       
  2759         or other system wide error code.
       
  2760 */
       
  2761 TInt CFileShare::CheckMount()
       
  2762 	{
       
  2763 	return File().CheckMount();
       
  2764 	}
       
  2765 
       
  2766 /**
       
  2767 Initialise the object
       
  2768 */
       
  2769 void CFileShare::InitL()
       
  2770 	{
       
  2771 	DoInitL(iFile->Drive().DriveNumber());
       
  2772 
       
  2773 	// override the close operation so that we can flush the write cache if necessary
       
  2774 	iRequest->Set(FileShareCloseOp,NULL);
       
  2775 	iRequest->SetDriveNumber(DriveNumber());
       
  2776 	iRequest->SetScratchValue((TUint)this);
       
  2777 	}
       
  2778 
       
  2779 // Mark the start of a request - 
       
  2780 // the is to prevent fair-scheduled async read/writes from being processed out of sequence. This is especially 
       
  2781 // important when considering a client which appends to a file by issuing more than one asynchronous request as each
       
  2782 // write request must be entirely satisfied before a subsequent request can append to the file
       
  2783 TBool CFileShare::RequestStart(CFsMessageRequest* aRequest)
       
  2784 	{
       
  2785 	TBool ret;
       
  2786 	
       
  2787 	TDrive& drive = File().Drive();
       
  2788 	drive.Lock();
       
  2789 
       
  2790 	if (iCurrentRequest == NULL || iCurrentRequest == aRequest)
       
  2791 		{
       
  2792 		iCurrentRequest = aRequest;
       
  2793 		ret = ETrue;
       
  2794 		}
       
  2795 	else
       
  2796 		{
       
  2797 		// add to end of linked list of requests if there is already an active request for this share
       
  2798 		CFsClientMessageRequest* request;
       
  2799 		for (request = (CFsClientMessageRequest*) iCurrentRequest; request->iNext != NULL; request = request->iNext)
       
  2800 			{
       
  2801 			}
       
  2802 		request->iNext = (CFsClientMessageRequest*) aRequest;
       
  2803 		ret =  EFalse;
       
  2804 		}
       
  2805 
       
  2806 	drive.UnLock();
       
  2807 	return ret;
       
  2808 	}
       
  2809 
       
  2810 
       
  2811 // Mark the end of a request
       
  2812 void CFileShare::RequestEnd(CFsMessageRequest* aRequest)
       
  2813 	{
       
  2814 	TDrive& drive = File().Drive();
       
  2815 	drive.Lock();
       
  2816 
       
  2817 	if (aRequest == iCurrentRequest)
       
  2818 		{
       
  2819 		// Any requests in the queue ?
       
  2820 		if (((CFsClientMessageRequest*) iCurrentRequest)->iNext)
       
  2821 			{
       
  2822 			iCurrentRequest = ((CFsClientMessageRequest*) aRequest)->iNext;
       
  2823 			((CFsClientMessageRequest*) aRequest)->iNext = NULL;
       
  2824 
       
  2825 			// if the current request has been cancelled, cancel all requests in the queue
       
  2826 			TInt lastError = aRequest->LastError();
       
  2827 			if (lastError == KErrCancel || lastError == KErrNotReady)
       
  2828 				{
       
  2829 				// take ownership of this queue and make it invisible to anyone else by setting iCurrentRequest to NULL
       
  2830 				CFsClientMessageRequest* currentRequest = (CFsClientMessageRequest*) iCurrentRequest;
       
  2831 				iCurrentRequest = NULL;
       
  2832 				drive.UnLock();
       
  2833 				while(currentRequest)
       
  2834 					{
       
  2835 					CFsClientMessageRequest* nextRequest = ((CFsClientMessageRequest*) currentRequest)->iNext;
       
  2836 					((CFsClientMessageRequest*) currentRequest)->iNext = NULL;
       
  2837 					currentRequest->Complete(lastError);
       
  2838 					currentRequest = nextRequest;
       
  2839 					}
       
  2840 				}
       
  2841 			else
       
  2842 				{
       
  2843 				drive.UnLock();
       
  2844 				iCurrentRequest->Dispatch(EFalse);
       
  2845 				}
       
  2846 			}
       
  2847 		else	// queue empty
       
  2848 			{
       
  2849 			iCurrentRequest = NULL;
       
  2850 			drive.UnLock();
       
  2851 			}
       
  2852 		}
       
  2853 	else	// if (aRequest == iCurrentRequest)
       
  2854 		{
       
  2855 		drive.UnLock();
       
  2856 		}
       
  2857 	}
       
  2858 
       
  2859 TBool CFileShare::RequestInProgress() const
       
  2860 	{
       
  2861 	return (iCurrentRequest != NULL)?(TBool)ETrue:(TBool)EFalse;
       
  2862 	}
       
  2863 
       
  2864 
       
  2865 
       
  2866 /**
       
  2867 Initialise the object
       
  2868 */
       
  2869 TInt TFsCloseFileShare::DoRequestL(CFsRequest* aRequest)
       
  2870 //
       
  2871 	{
       
  2872 	__PRINT(_L("TFsCloseFileCache::DoRequestL()"));
       
  2873 	
       
  2874 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  2875 
       
  2876 	// flush the write cache before closing the file share
       
  2877 	TInt r;
       
  2878 	CFileCache* fileCache = share->File().FileCache();
       
  2879 	if (fileCache && (r = fileCache->FlushDirty(aRequest)) == CFsRequest::EReqActionBusy)
       
  2880 		return r;
       
  2881 	
       
  2882 	return KErrNone;
       
  2883 	}
       
  2884 
       
  2885 TInt TFsCloseFileShare::Complete(CFsRequest* aRequest)
       
  2886 	{
       
  2887 	__PRINT(_L("TFsCloseFileShare::Complete()"));
       
  2888 	return TFsCloseObject::Complete(aRequest);
       
  2889 	}
       
  2890 
       
  2891 
       
  2892 TAsyncReadRequest::TAsyncReadRequest(TInt64 aEndPos, CFileShare* aOwningShareP, CFsRequest* aRequestP)
       
  2893 //
       
  2894 // Constructor for TAsyncReadRequest
       
  2895 //	- Maintains information about oustanding async read requests
       
  2896 //
       
  2897   : iEndPos(aEndPos), 
       
  2898 	iOwningShareP(aOwningShareP)
       
  2899 	{
       
  2900 	iMessage  = aRequestP->Message();
       
  2901 	iSessionP = aRequestP->Session();
       
  2902 	iStatusP  = iMessage.ClientStatus();
       
  2903 	}
       
  2904 
       
  2905 
       
  2906 TBool TAsyncReadRequest::CompleteIfMatching(CFileShare* aShareP, TRequestStatus* aStatusP, TInt aError)
       
  2907 //
       
  2908 // Completes an asynchronous read request.
       
  2909 //
       
  2910 	{
       
  2911 	if (iOwningShareP == aShareP && (aStatusP == NULL || aStatusP == iStatusP))
       
  2912 		{
       
  2913 		iMessage.Complete(aError);
       
  2914 		return ETrue;
       
  2915 		}
       
  2916 
       
  2917 	return EFalse;
       
  2918 	}
       
  2919 
       
  2920 
       
  2921 TInt TFsFileReadCancel::Initialise(CFsRequest* aRequest)
       
  2922 //
       
  2923 // Initialise function for RFile::ReadCancel [EFsReadCancel]
       
  2924 //
       
  2925 	{
       
  2926 	return InitialiseScratchToShare(aRequest);
       
  2927 	}
       
  2928 
       
  2929 
       
  2930 TInt TFsFileReadCancel::DoRequestL(CFsRequest* aRequest)
       
  2931 //
       
  2932 // Request function for RFile::ReadCancel [EFsReadCancel]
       
  2933 //
       
  2934 	{
       
  2935 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
       
  2936 	TRequestStatus* status = (TRequestStatus*)aRequest->Message().Ptr0();
       
  2937 	share->File().CancelAsyncReadRequest(share, status);
       
  2938 	return(KErrNone);
       
  2939 	}
       
  2940 
       
  2941 void CFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
       
  2942 	{
       
  2943 	TRACETHREADID(aMessage);
       
  2944 	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadL, EF32TraceUidFileSys, 
       
  2945 		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
       
  2946 
       
  2947 	iBody->iExtendedFileInterface->ReadL(aPos,aLength,aDes,aMessage,aOffset);
       
  2948 
       
  2949 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadLRet, EF32TraceUidFileSys, KErrNone);
       
  2950 	}
       
  2951 
       
  2952 void CFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
       
  2953 	{
       
  2954 	TRACETHREADID(aMessage);
       
  2955 	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteL, EF32TraceUidFileSys, 
       
  2956 		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
       
  2957 
       
  2958 	iBody->iExtendedFileInterface->WriteL(aPos,aLength,aDes,aMessage,aOffset);
       
  2959 
       
  2960 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteLRet, EF32TraceUidFileSys, KErrNone);
       
  2961 	}
       
  2962 
       
  2963 void CFileCB::SetSizeL(TInt64 aSize)
       
  2964 	{
       
  2965 	TRACE3(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeL, EF32TraceUidFileSys, this, I64LOW(aSize), I64HIGH(aSize));
       
  2966 
       
  2967 	iBody->iExtendedFileInterface->SetSizeL(aSize);
       
  2968 
       
  2969 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeLRet, EF32TraceUidFileSys, KErrNone);
       
  2970 	}
       
  2971 
       
  2972 TBool CFileCB::ExtendedFileInterfaceSupported()
       
  2973 	{
       
  2974 	return iBody->ExtendedFileInterfaceSupported();
       
  2975 	}
       
  2976 
       
  2977 TInt CFileCB::FairSchedulingLen() const
       
  2978 	{
       
  2979 	return iBody->iFairSchedulingLen;
       
  2980 	}
       
  2981 
       
  2982 void CFileCB::SetNotifyAsyncReadersPending(TBool aNotifyAsyncReadersPending)
       
  2983 //
       
  2984 // Notify the asynchronous reader that a file has grown so that it may service outstanding async reads
       
  2985 //
       
  2986 	{
       
  2987 	iBody->iNotifyAsyncReadersPending = aNotifyAsyncReadersPending;
       
  2988 	}
       
  2989 
       
  2990 TBool CFileCB::NotifyAsyncReadersPending() const
       
  2991 	{
       
  2992 	return iBody->iNotifyAsyncReadersPending;
       
  2993 	}
       
  2994 
       
  2995 
       
  2996 void CFileCB::ResetReadAhead()
       
  2997 	{
       
  2998 	CFileCache* fileCache = FileCache();
       
  2999 	if (fileCache)
       
  3000 		fileCache->ResetReadAhead();
       
  3001 	}
       
  3002 
       
  3003 void CFileCB::SetDeleteOnClose()
       
  3004 	{
       
  3005 	iBody->iDeleteOnClose = ETrue;
       
  3006 	}
       
  3007 
       
  3008 TBool CFileCB::DeleteOnClose() const
       
  3009 	{
       
  3010 	return iBody->iDeleteOnClose;
       
  3011 	}
       
  3012 
       
  3013 TInt CFileCB::GetInterfaceTraced(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
       
  3014 	{
       
  3015 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterface, EF32TraceUidFileSys, aInterfaceId, aInput);
       
  3016 
       
  3017 	TInt r = GetInterface(aInterfaceId, aInterface, aInput);
       
  3018 
       
  3019 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterfaceRet, EF32TraceUidFileSys, r, aInterface);
       
  3020 
       
  3021 	return r;
       
  3022 	}
       
  3023 
       
  3024 CFileBody::CFileBody(CFileCB* aFileCB, CFileCB::MExtendedFileInterface* aExtendedFileInterface)
       
  3025   : iFileCB(aFileCB),
       
  3026 	iExtendedFileInterface(aExtendedFileInterface ? aExtendedFileInterface : this),
       
  3027 	iSizeHigh(0)
       
  3028 	{
       
  3029 	iFairSchedulingLen = TFileCacheSettings::FairSchedulingLen(iFileCB->DriveNumber());
       
  3030     iMaxSupportedFileSize = KMaxSupportedFileSize;
       
  3031 	}
       
  3032 
       
  3033 
       
  3034 CFileBody::~CFileBody()
       
  3035 	{
       
  3036 	if (iAsyncReadRequests)
       
  3037 		{
       
  3038 		iAsyncReadRequests->Close();
       
  3039 		delete iAsyncReadRequests;
       
  3040 		}
       
  3041 	}
       
  3042 
       
  3043 
       
  3044 void CFileBody::InitL()
       
  3045 	{
       
  3046 	iAsyncReadRequests = new(ELeave) RArray<TAsyncReadRequest>(KAsyncRequestArrayGranularity, _FOFF(TAsyncReadRequest, iEndPos));
       
  3047 	}
       
  3048 
       
  3049 
       
  3050 
       
  3051 TInt TFsFileClamp::Initialise(CFsRequest* aRequest)
       
  3052 //
       
  3053 // Initialise function for RFile::Clamp [EFsFileClamp]
       
  3054 //
       
  3055 	{
       
  3056 	TSecureId aUID = aRequest->Message().SecureId();	
       
  3057     if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
       
  3058 		{
       
  3059 		SSecurityInfo info;
       
  3060 		info.iVendorId=0;
       
  3061 		info.iCaps.iCaps[0]=0;
       
  3062 		info.iCaps.iCaps[1]=0;
       
  3063 		info.iSecureId=KEstartUidValue;
       
  3064 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
       
  3065 		info.iSecureId=KFileServerUidValue;
       
  3066 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
       
  3067 		return KErrPermissionDenied;
       
  3068 		}
       
  3069 
       
  3070 	TInt r=DoInitialise(aRequest);
       
  3071 	if(r!=KErrNone)
       
  3072 		return r;
       
  3073 
       
  3074 	// The clamp API is only supported on non-removable media
       
  3075 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  3076 	TDriveInfo di;
       
  3077 	share->File().Drive().DriveInfo(di);
       
  3078 	if (!(di.iDriveAtt & KDriveAttInternal))
       
  3079 		r = KErrNotSupported;
       
  3080 
       
  3081 	return(r);
       
  3082 	}
       
  3083 
       
  3084 
       
  3085 TInt TFsFileClamp::DoRequestL(CFsRequest* aRequest)
       
  3086 //
       
  3087 // Request function for RFile::Clamp [EFsFileClamp]
       
  3088 //
       
  3089 	{
       
  3090 	TInt r;
       
  3091 
       
  3092 	// Flush data for this file, if it is open for writing, before clamping
       
  3093 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
       
  3094 
       
  3095 	if (((share->iMode&EFileWrite)) || ((share->File().Att()&KEntryAttModified)))
       
  3096 		{
       
  3097 		r=share->CheckMount();
       
  3098 		if (r!=KErrNone)
       
  3099 			return(r);
       
  3100 
       
  3101 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataL, EF32TraceUidFileSys, &share->File());
       
  3102 		TRAP(r,share->File().FlushDataL());
       
  3103 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataLRet, EF32TraceUidFileSys, r);
       
  3104 
       
  3105 		if(r!=KErrNone)
       
  3106 			return(r);
       
  3107 		}
       
  3108 
       
  3109 	RFileClamp clamp;
       
  3110 	r=aRequest->Drive()->ClampFile(aRequest->Src().FullName().Mid(2),
       
  3111 									(TAny*)(&clamp));
       
  3112 	// Write clamp information to user
       
  3113 	TPckgC<RFileClamp> pkClamp(clamp);
       
  3114 	aRequest->WriteL(KMsgPtr0, pkClamp);
       
  3115 	return r;
       
  3116 	}
       
  3117 
       
  3118 
       
  3119 TInt TFsUnclamp::Initialise(CFsRequest* aRequest)
       
  3120 //
       
  3121 // Initialise function for RFs::Unclamp [EFsUnclamp]
       
  3122 //
       
  3123 	{
       
  3124 	TSecureId aUID = aRequest->Message().SecureId();	
       
  3125     if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
       
  3126 		{
       
  3127 		SSecurityInfo info;
       
  3128 		info.iVendorId=0;
       
  3129 		info.iCaps.iCaps[0]=0;
       
  3130 		info.iCaps.iCaps[1]=0;
       
  3131 		info.iSecureId=KEstartUidValue;
       
  3132 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
       
  3133 		info.iSecureId=KFileServerUidValue;
       
  3134 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
       
  3135 		return KErrPermissionDenied;
       
  3136 		}
       
  3137 	RFileClamp clamp;
       
  3138 	TPckg<RFileClamp> pkClamp(clamp);
       
  3139 	aRequest->ReadL(KMsgPtr0, pkClamp);
       
  3140 	TInt driveNo=(I64HIGH(clamp.iCookie[1]));
       
  3141 	TDrive& drive=TheDrives[driveNo];
       
  3142 	aRequest->SetDrive(&drive);
       
  3143 	return KErrNone;
       
  3144 	}
       
  3145 
       
  3146 
       
  3147 TInt TFsUnclamp::DoRequestL(CFsRequest* aRequest)
       
  3148 //
       
  3149 // Request function for RFs::Unclamp [EFsUnclamp]
       
  3150 //
       
  3151 	{
       
  3152 	RFileClamp clamp;
       
  3153 	TPckg<RFileClamp> pkClamp(clamp);
       
  3154 	aRequest->ReadL(KMsgPtr0, pkClamp);
       
  3155 	TDrive* drive=aRequest->Drive();
       
  3156 	CMountCB* mount=(CMountCB*)&(drive->CurrentMount());
       
  3157 	return(drive->UnclampFile(mount,&clamp));
       
  3158 	}
       
  3159 
       
  3160 CMountBody::CMountBody(CMountCB* aMountCB, CMountCB::MFileAccessor* aFileAccessor, CMountCB::MFileExtendedInterface* aFileInterface)
       
  3161 //
       
  3162 // Constructor for private body class
       
  3163 //
       
  3164   : iMountCB(aMountCB),
       
  3165 	iFileAccessor(aFileAccessor?aFileAccessor:this),
       
  3166 	iFileExtendedInterface(aFileInterface?aFileInterface:this)
       
  3167 	{
       
  3168 	}
       
  3169 
       
  3170 CMountBody::~CMountBody()
       
  3171 //
       
  3172 // Destructor for private body class
       
  3173 //
       
  3174 	{
       
  3175 	__ASSERT_DEBUG(iClampIdentifiers.Count() == 0, User::Invariant());
       
  3176 	iClampIdentifiers.Close();
       
  3177 	}
       
  3178 
       
  3179 TInt CMountBody::ClampFile(const TInt aDriveNo,const TDesC& aName,TAny* aHandle)
       
  3180 	{
       
  3181 	// Need CMountCB::MFileAccessor interface support
       
  3182 	if(iFileAccessor==this)
       
  3183 		return KErrNotSupported;
       
  3184 
       
  3185 	// Get unique identifier for the file
       
  3186 	TInt64 uniqueId = 0;
       
  3187 	TInt r = iFileAccessor->GetFileUniqueId(aName,uniqueId);
       
  3188 	if(r!=KErrNone)
       
  3189 			return r;
       
  3190 
       
  3191 	// Populate the RFileClamp clamp instance and store it in iClampIdentifiers
       
  3192 	RFileClamp* newClamp = (RFileClamp*)aHandle;
       
  3193 	newClamp->iCookie[0]=uniqueId;
       
  3194 	newClamp->iCookie[1]=MAKE_TINT64(aDriveNo,++iClampCount);
       
  3195 	r = iClampIdentifiers.InsertInOrder((const RFileClamp&)*newClamp,&CompareClampsByIdAndCount);
       
  3196 	if(r != KErrNone)
       
  3197 		return r;
       
  3198 
       
  3199 	// Indicate that (at least) one file is clamped on this drive
       
  3200 	iMountCB->Drive().SetClampFlag(ETrue);
       
  3201 	AddResource(*iMountCB);
       
  3202 	return KErrNone;
       
  3203 	}
       
  3204 
       
  3205 
       
  3206 TInt CMountBody::UnclampFile(RFileClamp* aHandle)
       
  3207 	{
       
  3208 	// Need CMountCB::MFileAccessor interface support
       
  3209 	if(iFileAccessor==this)
       
  3210 		return KErrNotSupported;
       
  3211 
       
  3212 	TInt idx;
       
  3213 	if((idx = iClampIdentifiers.Find((const RFileClamp&)*aHandle,&FindClampByIdAndCount)) < KErrNone)
       
  3214 		{
       
  3215 		// This file is not 'clamped'
       
  3216 		return idx;
       
  3217 		}
       
  3218 
       
  3219 	// If we're removing the last clamp and a dismount has been deferred (due to files being clamped),
       
  3220 	// then DeferredDismount() will trigger a dismount: before this happens we need to flush all
       
  3221 	// dirty data on this drive; 
       
  3222 	TDrive& drive = iMountCB->Drive();
       
  3223 	TInt noOfClamps = NoOfClamps();
       
  3224 	if (noOfClamps == 1 && drive.DismountDeferred())
       
  3225 		{
       
  3226 		TInt r = drive.FlushCachedFileInfo(ETrue);
       
  3227 		if (r == CFsRequest::EReqActionBusy)
       
  3228 			return r;
       
  3229 		}
       
  3230 
       
  3231 	RemoveResource(*iMountCB);
       
  3232 	iClampIdentifiers.Remove(idx);
       
  3233 
       
  3234 	TInt r = KErrNone;
       
  3235 	// If this was the last clamp, check for outstanding dismount requests
       
  3236 	if (noOfClamps == 1)
       
  3237 		{
       
  3238 		ASSERT(NoOfClamps() == 0);
       
  3239 		drive.SetClampFlag(EFalse);
       
  3240 		if (drive.DismountDeferred())
       
  3241 			r = drive.DeferredDismount();
       
  3242 		}
       
  3243 
       
  3244 	return r;
       
  3245 	}
       
  3246 
       
  3247 
       
  3248 TInt CMountBody::IsFileClamped(const TInt64 aUniqueId)
       
  3249 	{
       
  3250 	// Need CMountCB::MFileAccessor interface support
       
  3251 	if(iFileAccessor==this)
       
  3252 		return KErrNotSupported;
       
  3253 
       
  3254 	// Encapsulate the unique identifier in an appropriate class
       
  3255 	RFileClamp newClamp;
       
  3256 	newClamp.iCookie[0]=aUniqueId;
       
  3257 	// Search for (any) entry in iClampIdentifiers holding this value
       
  3258 	TInt index=iClampIdentifiers.Find((const RFileClamp&)newClamp,&FindClampById);
       
  3259 	return (index==KErrNotFound?0:1);
       
  3260 	}
       
  3261 
       
  3262 TInt CMountBody::NoOfClamps()
       
  3263 	{
       
  3264 	// Need CMountCB::MFileAccessor interface support
       
  3265 	if(iFileAccessor==this)
       
  3266 		return KErrNotSupported;
       
  3267 
       
  3268 	// This will return zero if ClampFile has not previously been invoked
       
  3269 	return iClampIdentifiers.Count();
       
  3270 	}
       
  3271 
       
  3272 TInt CMountBody::CompareClampsById(const RFileClamp& aClampA, const RFileClamp& aClampB)
       
  3273 	{
       
  3274 	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return 1;
       
  3275 	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return -1;
       
  3276 	return 0;
       
  3277 	}
       
  3278 
       
  3279 TInt CMountBody::CompareClampsByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
       
  3280 	{
       
  3281 	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return 1;
       
  3282 	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return -1;
       
  3283 	// Now compare the count values
       
  3284 	if(I64LOW(aClampA.iCookie[1]) > I64LOW(aClampB.iCookie[1])) return 1;
       
  3285 	if(I64LOW(aClampA.iCookie[1]) < I64LOW(aClampB.iCookie[1])) return -1;
       
  3286 	return 0;
       
  3287 	}
       
  3288 
       
  3289 TInt CMountBody::FindClampById(const RFileClamp& aClampA, const RFileClamp& aClampB)
       
  3290 	{
       
  3291 	return (TInt)(!CompareClampsById(aClampA, aClampB));
       
  3292 	}
       
  3293 
       
  3294 
       
  3295 TInt CMountBody::FindClampByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
       
  3296 	{
       
  3297 	return (TInt)(!CompareClampsByIdAndCount(aClampA, aClampB));
       
  3298 	}
       
  3299 
       
  3300 void CMountBody::SetProxyDriveDismounted()
       
  3301 	{
       
  3302 	iProxyDriveDismounted = ETrue;
       
  3303 	}
       
  3304 
       
  3305 TBool CMountBody::ProxyDriveDismounted()
       
  3306 	{
       
  3307 	return iProxyDriveDismounted;
       
  3308 	}
       
  3309 
       
  3310 
       
  3311 TInt CMountBody::GetFileUniqueId(const TDesC& /*aName*/, TInt64& /*aUniqueId*/)
       
  3312 	{
       
  3313 	return KErrNotSupported;
       
  3314 	}
       
  3315 TInt CMountBody::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
       
  3316 	{
       
  3317 	return KErrNotSupported;
       
  3318 	}
       
  3319 TInt CMountBody::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
       
  3320 	{
       
  3321 	return KErrNotSupported;
       
  3322 	}
       
  3323 TInt CMountBody::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
       
  3324 	{
       
  3325 	return KErrNotSupported;
       
  3326 	}
       
  3327 void CMountBody::ReadSection64L(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
       
  3328 	{
       
  3329 	if((TUint64)aPos > KMaxLegacyFileSize)
       
  3330 		User::Leave(KErrNotSupported);
       
  3331 
       
  3332 	iMountCB->ReadSectionL(aName, I64LOW(aPos), aTrg, aLength, aMessage);
       
  3333 	}
       
  3334 
       
  3335 TBool CFileBody::ExtendedFileInterfaceSupported()
       
  3336 	{
       
  3337 	return (iExtendedFileInterface==this) ? (TBool)EFalse : (TBool)ETrue;
       
  3338 	}
       
  3339 
       
  3340 // default implementations of MExtendedFileInterface
       
  3341 void CFileBody::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
       
  3342 	{
       
  3343 	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
       
  3344 		User::Leave(KErrNotSupported);
       
  3345 
       
  3346 	iFileCB->ReadL((TInt) aPos, aLength, aDes, aMessage);
       
  3347 	}
       
  3348 
       
  3349 void CFileBody::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
       
  3350 	{
       
  3351 	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
       
  3352 		User::Leave(KErrNotSupported);
       
  3353 
       
  3354 	iFileCB->WriteL((TInt) aPos, aLength, aDes, aMessage);
       
  3355 	}
       
  3356 
       
  3357 void CFileBody::SetSizeL(TInt64 aSize)
       
  3358 	{
       
  3359 	if ((TUint64)aSize > KMaxLegacyFileSize)
       
  3360 		User::Leave(KErrNotSupported);
       
  3361 
       
  3362 	iFileCB->SetSizeL((TInt) aSize);
       
  3363 	}
       
  3364 
       
  3365 //---------------------------------------------------------------------------------------------------------------------
       
  3366 /**
       
  3367     This method allows file system to set maximum file size it supports.
       
  3368     This can be called on instantiation of the CFileCB derived class object by the file system implementation.
       
  3369     If this method is not called, the iMaxSupportedFileSize will have default value KMaxTUint64
       
  3370 
       
  3371     @param aMaxFileSize maximum file size supported by file system
       
  3372 */
       
  3373 EXPORT_C void CFileCB::SetMaxSupportedSize(TUint64 aMaxFileSize)
       
  3374     {
       
  3375     iBody->iMaxSupportedFileSize = aMaxFileSize;    
       
  3376     }
       
  3377 
       
  3378 /**
       
  3379     @return maximum supported file size (depends on the file system created it)
       
  3380 */
       
  3381 TUint64 CFileCB::MaxSupportedSize(void) const
       
  3382     {
       
  3383     return iBody->iMaxSupportedFileSize;
       
  3384     }
       
  3385 
       
  3386 //---------------------------------------------------------------------------------------------------------------------
       
  3387 
       
  3388 /**
       
  3389 Gets the size of the file.
       
  3390 
       
  3391 This is 64-bit variant for CFileCB::Size().
       
  3392 This shall be used by File Systems supporting file size > 4GB - 1 to query the file size 
       
  3393 inplace of CFileCB::Size() or CFileCB::iSize.
       
  3394 
       
  3395 @see CFileCB::iSize
       
  3396 @see CFileCB::Size() 
       
  3397 
       
  3398 @prototype
       
  3399 
       
  3400 @return The size of the file.
       
  3401 */
       
  3402 EXPORT_C TInt64 CFileCB::Size64() const
       
  3403 	{
       
  3404 	__ASSERT_DEBUG(iBody != NULL, Fault(EFileBodyIsNull));
       
  3405 	const TInt64 size = MAKE_TINT64(iBody->iSizeHigh,iSize);
       
  3406 	return size;
       
  3407 	}
       
  3408 
       
  3409 //---------------------------------------------------------------------------------------------------------------------
       
  3410 /**
       
  3411 Sets the size of the file.
       
  3412 
       
  3413 This is 64-bit variant for CFileCB::SetSize().
       
  3414 This should be used by File Systems supporting file size > 4GB - 1 to set the file size 
       
  3415 inplace of CFileCB::SetSize() or CFileCB::iSize.
       
  3416 
       
  3417 @see CFileCB::iSize
       
  3418 @see CFileCB::SetSize() 
       
  3419 
       
  3420 @prototype
       
  3421 
       
  3422 @param aSize The size of the file.
       
  3423 @param aDriveLocked The status of the Drive Lock. If it is EFalse,
       
  3424 the file size shall be modified after acquiring the iLock mutex and if it is ETrue, 
       
  3425 the file size shall be modified without aquiring the iLock mutex.  
       
  3426 */
       
  3427 EXPORT_C void CFileCB::SetSize64(TInt64 aSize, TBool aDriveLocked)
       
  3428 	{
       
  3429 	if(aDriveLocked)
       
  3430 		{
       
  3431 		iSize = (TInt)I64LOW(aSize);
       
  3432 		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
       
  3433 		}
       
  3434 	else
       
  3435 		{
       
  3436 		Drive().Lock();
       
  3437 		iSize = (TInt)I64LOW(aSize);
       
  3438 		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
       
  3439 		Drive().UnLock();
       
  3440 		}
       
  3441 	}
       
  3442 
       
  3443 
       
  3444 /** used to organize key comparison for the TFileShareLock*/
       
  3445 TInt LockOrder(const TFileShareLock& aMatch, const TFileShareLock& anEntry)
       
  3446 	{
       
  3447 
       
  3448 	if(aMatch.PosLow() > anEntry.PosLow())
       
  3449 		return 1;
       
  3450 	else if(aMatch.PosLow() < anEntry.PosLow())
       
  3451 		return -1;
       
  3452 	else
       
  3453 		return 0;
       
  3454    
       
  3455     }
       
  3456 
       
  3457 //---------------------------------------------------------------------------------------------------------------------
       
  3458 /**
       
  3459     Find a lock inclusive of aPosLow to aPosHigh.
       
  3460 */
       
  3461 TInt CFileCB::FindLock64(TInt64 aPosLow, TInt64 aPosHigh)
       
  3462     {
       
  3463 
       
  3464 	const TInt count=FileLocks().Count();
       
  3465 	for (TInt i=0; i<count; i++)
       
  3466 		{
       
  3467             
       
  3468             const TFileShareLock& lock=FileLocks()[i];
       
  3469 
       
  3470             if(lock.PosLow() > (TUint64)aPosHigh)
       
  3471                 return KErrNotFound;
       
  3472 
       
  3473             if(lock.MatchByPos(aPosLow, aPosHigh))
       
  3474                 return i;
       
  3475 		}
       
  3476 
       
  3477 	return KErrNotFound;
       
  3478 	}
       
  3479 
       
  3480 //---------------------------------------------------------------------------------------------------------------------
       
  3481 /**
       
  3482     Add a lock on a range.
       
  3483 */
       
  3484 TInt CFileCB::AddLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
       
  3485 	{
       
  3486 	const TUint64 posHigh=aPos+aLength-1;
       
  3487 	
       
  3488         
       
  3489         {//-- Lock overflow check
       
  3490         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
       
  3491 	    if(posHigh > KMaxFileSize)
       
  3492                 return KErrArgument;
       
  3493         }
       
  3494     
       
  3495     
       
  3496     TInt r=CheckLock64(NULL, aPos, aLength);
       
  3497 	if (r!=KErrNone)
       
  3498 		return r;
       
  3499 	
       
  3500     TFileShareLock lock(aFileShare, aPos, posHigh);
       
  3501 
       
  3502     TLinearOrder<TFileShareLock> lockOrder(LockOrder);
       
  3503 	r=FileLocks().InsertInOrder(lock, lockOrder);
       
  3504 	__ASSERT_ALWAYS(r!=KErrAlreadyExists,Fault(EFileDuplicateLock));
       
  3505 	
       
  3506     return r;
       
  3507 	}
       
  3508 
       
  3509 //---------------------------------------------------------------------------------------------------------------------
       
  3510 /**
       
  3511     Remove a lock on a range.
       
  3512 */
       
  3513 TInt CFileCB::RemoveLock64(CFileShare* aFileShare, TInt64 aPos, TInt64 aLength)
       
  3514 	{
       
  3515 	const TUint64 posHigh = aPos+aLength-1;
       
  3516 
       
  3517         {//-- Lock overflow check
       
  3518         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
       
  3519 	    if(posHigh > KMaxFileSize)
       
  3520                 return KErrArgument;
       
  3521         }
       
  3522     
       
  3523 	const TInt pos=FindLock64(aPos, posHigh);
       
  3524 	if (pos==KErrNotFound)
       
  3525 		return KErrNotFound;
       
  3526 	
       
  3527     const TFileShareLock& lock=FileLocks()[pos];
       
  3528     if (!lock.MatchOwner(aFileShare) || lock.PosLow() != (TUint64)aPos || lock.PosHigh() != posHigh)
       
  3529 		return KErrNotFound;
       
  3530 	
       
  3531    
       
  3532     FileLocks().Remove(pos);
       
  3533 
       
  3534 	return KErrNone;
       
  3535 	}
       
  3536 
       
  3537 //---------------------------------------------------------------------------------------------------------------------
       
  3538 /** 
       
  3539     Check if a range is available.
       
  3540     @param  aFileShare pointer to FileShare object. NULL only when is called from CFileCB::AddLock64()
       
  3541 
       
  3542 */
       
  3543 TInt CFileCB::CheckLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
       
  3544 	{
       
  3545 	const TUint64 posHigh=aPos+aLength-1;
       
  3546 	
       
  3547     //-- Lock overflow check. It is OK to have a lock that is beyond the real file size.
       
  3548     //-- if aFileShare == NULL, this is the call from AddLock64 and the position is already checked.
       
  3549     if(aFileShare)
       
  3550         {
       
  3551         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
       
  3552 	    if(posHigh > KMaxFileSize)
       
  3553             return KErrNone; //-- OK, there can't be any locks beyond the max. supported file length
       
  3554         }
       
  3555 
       
  3556 
       
  3557 	TInt lockIdx=FindLock64(aPos, posHigh);
       
  3558 	if (lockIdx == KErrNotFound)
       
  3559 		return KErrNone;
       
  3560 
       
  3561     const TInt count=FileLocks().Count();
       
  3562 	const TFileShareLock* lock=(&FileLocks()[lockIdx]);
       
  3563 
       
  3564 	for(;;)
       
  3565 		{
       
  3566 		if (!lock->MatchOwner(aFileShare))
       
  3567 			return KErrLocked;
       
  3568 
       
  3569 		if (lock->PosHigh() >= posHigh)
       
  3570 			break;
       
  3571 		
       
  3572         lockIdx++;
       
  3573 		if (lockIdx >= count)
       
  3574 			break;
       
  3575 
       
  3576 		lock=&FileLocks()[lockIdx];
       
  3577 		
       
  3578         if (posHigh < lock->PosLow())
       
  3579 			break;
       
  3580 		}
       
  3581 
       
  3582     return KErrNone;
       
  3583 	}
       
  3584 
       
  3585 
       
  3586 //#####################################################################################################################
       
  3587 //#  TFileShareLock class implementation
       
  3588 //#####################################################################################################################
       
  3589 
       
  3590 TFileShareLock::TFileShareLock(const CFileShare* aOwner, TUint64 aPosLow, TUint64 aPosHigh) 
       
  3591                : iOwner(aOwner), iPosLow(aPosLow), iPosHigh(aPosHigh) 
       
  3592     {
       
  3593     }
       
  3594 
       
  3595 
       
  3596    
       
  3597 TUint64 TFileShareLock::PosLow()  const 
       
  3598     {
       
  3599     return iPosLow;
       
  3600     }
       
  3601 
       
  3602 
       
  3603 TUint64 TFileShareLock::PosHigh() const 
       
  3604     {
       
  3605     return iPosHigh;
       
  3606     }
       
  3607 
       
  3608 TBool TFileShareLock::MatchOwner(const CFileShare* aShare) const 
       
  3609     {
       
  3610     return (aShare == iOwner);
       
  3611     }
       
  3612 
       
  3613 /**
       
  3614     @return ETrue if aPosLow and PosHigh match the lock boundaries
       
  3615 */
       
  3616 TBool TFileShareLock::MatchByPos(TUint64 aPosLow, TUint64 aPosHigh) const
       
  3617     {
       
  3618         if(PosLow() > aPosHigh)
       
  3619             return EFalse;
       
  3620 
       
  3621 		if ((aPosLow  >= PosLow() && aPosLow   <= PosHigh()) ||
       
  3622 			(aPosHigh >= PosLow() && aPosHigh  <= PosHigh()) ||
       
  3623 			(aPosLow  <= PosLow() && aPosHigh  >= PosHigh() ))
       
  3624 			{
       
  3625 			return ETrue;
       
  3626 			}
       
  3627 
       
  3628          return EFalse;
       
  3629     }
       
  3630 
       
  3631 
       
  3632 
       
  3633 
       
  3634 
       
  3635 
       
  3636 
       
  3637 
       
  3638 
       
  3639 
       
  3640 
       
  3641 
       
  3642 
       
  3643 
       
  3644