os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_file.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1620 //	TInt att=(TInt)aRequest->FileShare()->File().Att()&KEntryAttMaskSupported;
  1621 	TInt att=(TInt)share->File().Att();	// DRM: let ROM XIP attribute through
  1622 	TPtrC8 pA((TUint8*)&att,sizeof(TInt));
  1623 	aRequest->WriteL(KMsgPtr0,pA);
  1624 	
  1625     return(KErrNone);
  1626 	}
  1627 
  1628 TInt TFsFileAtt::Initialise(CFsRequest* aRequest)
  1629 //
  1630 //
  1631 //
  1632 	{
  1633 	return(DoInitNoParse(aRequest));
  1634 	}
  1635 
  1636 
  1637 TInt TFsFileSetAtt::DoRequestL(CFsRequest* aRequest)
  1638 //
  1639 // Set the file attributes.
  1640 //
  1641 	{
  1642 	__PRINT(_L("TFsFileSetAtt::DoRequestL(CSessionFs* aSession)"));
  1643     
  1644     TInt r = CheckDiskSpace(0, aRequest);
  1645     if(r != KErrNone)
  1646         return r;
  1647 
  1648 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1649 	r=share->CheckMount();
  1650 	if (r!=KErrNone)
  1651 		return(r);
  1652 	
  1653     if ((share->iMode&EFileWrite)==EFalse)
  1654 		return(KErrAccessDenied);
  1655 	
  1656     TUint setAttMask=(TUint)(aRequest->Message().Int0());
  1657 	TUint clearAttMask=(TUint)aRequest->Message().Int1();
  1658 	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);
  1659 
  1660 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
  1661 	TRAP(r,share->File().SetEntryL(TTime(0),setAttMask,clearAttMask))
  1662 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
  1663 
  1664 	return(r);
  1665 	}
  1666 
  1667 
  1668 TInt TFsFileSetAtt::Initialise(CFsRequest* aRequest)
  1669 //
  1670 //	Call GetShareFromHandle to determine asynchronicity ***
  1671 //
  1672 	{
  1673 	return(DoInitNoParse(aRequest));
  1674 	}
  1675 
  1676 
  1677 TInt TFsFileModified::DoRequestL(CFsRequest* aRequest)
  1678 //
  1679 // Get the modified date and time.
  1680 //
  1681 	{
  1682 	__PRINT(_L("TFsFileModified::DoRequestL(CFsRequest* aRequest)"));
  1683         	
  1684 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1685 	TTime mod=share->File().Modified();
  1686 	TPtrC8 pM((TUint8*)&mod,sizeof(TTime));
  1687 	aRequest->WriteL(KMsgPtr0,pM);
  1688 	
  1689     return(KErrNone);
  1690 	}
  1691 
  1692 
  1693 TInt TFsFileModified::Initialise(CFsRequest* aRequest)
  1694 //
  1695 //	Call GetShareFromHandle to determine asynchronicity ***
  1696 //
  1697 	{
  1698 	return(DoInitNoParse(aRequest));
  1699 	}
  1700 
  1701 
  1702 TInt TFsFileSetModified::DoRequestL(CFsRequest* aRequest)
  1703 //
  1704 // Set the modified date and time.
  1705 //
  1706 	{
  1707 	__PRINT(_L("TFsFileSetModified::DoRequestL(CFsRequest* aRequest)"));
  1708     
  1709     TInt r = CheckDiskSpace(0, aRequest);
  1710     if(r != KErrNone)
  1711         return r;
  1712 
  1713 
  1714 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1715 	r=share->CheckMount();
  1716 	if (r!=KErrNone)
  1717 		return(r);
  1718 
  1719 	if ((share->iMode&EFileWrite)==EFalse)
  1720 		return(KErrAccessDenied);
  1721 	
  1722 	TTime time;
  1723 	TPtr8 t((TUint8*)&time,sizeof(TTime));
  1724 	aRequest->ReadL(KMsgPtr0,t);
  1725 
  1726 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, KEntryAttModified,0);
  1727 	TRAP(r,share->File().SetEntryL(time,KEntryAttModified,0))
  1728 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
  1729 
  1730 	return(r);
  1731 	}
  1732 
  1733 
  1734 TInt TFsFileSetModified::Initialise(CFsRequest* aRequest)
  1735 //
  1736 //	Call GetShareFromHandle to determine asynchronicity ***
  1737 //
  1738 	{
  1739 	return(DoInitNoParse(aRequest));
  1740 	}
  1741 
  1742 TInt TFsFileSet::DoRequestL(CFsRequest* aRequest)
  1743 //
  1744 // Set the attributes and the modified date and time.
  1745 //
  1746 	{
  1747 	__PRINT(_L("TFsFileSet::DoRequestL(CFsRequest* aRequest)"));
  1748 
  1749     TInt r = CheckDiskSpace(0, aRequest);
  1750     if(r != KErrNone)
  1751         return r;
  1752 
  1753 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1754 	r=share->CheckMount();
  1755 	if (r!=KErrNone)
  1756 		return(r);
  1757 	
  1758     if (share->File().Att()&KEntryAttReadOnly)
  1759 		return(KErrAccessDenied);
  1760 	
  1761     if ((share->iMode&EFileWrite)==0)
  1762 		{
  1763 		if(share->File().Drive().IsWriteProtected())
  1764 			return(KErrAccessDenied);
  1765 		}
  1766 	
  1767     TTime time;
  1768 	TPtr8 t((TUint8*)&time,sizeof(TTime));
  1769 	aRequest->ReadL(KMsgPtr0,t);
  1770 	TUint setAttMask=(TUint)(aRequest->Message().Int1()|KEntryAttModified);
  1771 	TUint clearAttMask=(TUint)aRequest->Message().Int2();
  1772 	ValidateAtts(share->File().Att(),setAttMask,clearAttMask);//	Validate attributes
  1773 
  1774 	TRACE5(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryL, EF32TraceUidFileSys, &share->File(), 0, 0, setAttMask,clearAttMask);
  1775 	TRAP(r,share->File().SetEntryL(time,setAttMask,clearAttMask))
  1776 	TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetEntryLRet, EF32TraceUidFileSys, r);
  1777 
  1778 	return(r);
  1779 	}
  1780 
  1781 TInt TFsFileSet::Initialise(CFsRequest* aRequest)
  1782 //
  1783 //
  1784 //
  1785 	{
  1786 	return(DoInitNoParse(aRequest));
  1787 	}
  1788 
  1789 
  1790 TInt TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)
  1791 //
  1792 // The access to a file may be changed from share exclusive to share readers only or vice versa.
  1793 // KErrAccessDenied is returned if the file has multiple readers.
  1794 //
  1795 	{
  1796 	__PRINT(_L("TFsFileChangeMode::DoRequestL(CFsRequest* aRequest)"));
  1797 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1798 	TInt r=share->CheckMount();
  1799 	if (r!=KErrNone)
  1800 		return(r);
  1801 	
  1802 	const TFileMode currentMode = (TFileMode)share->iMode;
  1803 	const TFileMode newMode = (TFileMode)aRequest->Message().Int0();
  1804 	
  1805 		// check argument 
  1806 		// (only EFileShareExclusive and EFileShareReadersOnly are allowed)
  1807 	if((newMode & ~EFileShareReadersOnly) != 0)
  1808 		return KErrArgument;
  1809 	
  1810 		// check if the file is in EFileShareAny mode
  1811 	if( (currentMode & EFileShareAny) ||
  1812 	    // or the file has been opened for writing in EFileShareExclusive mode, 
  1813 		// and an attempt is made to change the access mode to EFileShareReadersOnly
  1814 		((currentMode & EFileWrite) && 
  1815 		 (currentMode & KFileShareMask) == EFileShareExclusive && 
  1816 		 newMode == EFileShareReadersOnly) )
  1817 		return KErrAccessDenied;
  1818 
  1819 		// check if an attempt is made to change the share mode to EFileShareExclusive
  1820 		// while the file has multiple readers
  1821 	if (newMode == EFileShareExclusive && (currentMode & KFileShareMask) != EFileShareExclusive)
  1822 		{ 
  1823 		// Check no other CFileCB is reading the file.
  1824 		FileShares->Lock();
  1825 		TInt count=FileShares->Count();
  1826 		TBool found=EFalse;
  1827 		while(count--)
  1828 			{
  1829 			CFileShare* fileShare=(CFileShare*)(*FileShares)[count];
  1830 			if (&fileShare->File()==&share->File())
  1831 				{
  1832 				if (found)
  1833 					{
  1834 					FileShares->Unlock();
  1835 					return(KErrAccessDenied);
  1836 					}
  1837 				found=ETrue;
  1838 				}
  1839 			}
  1840 		FileShares->Unlock();
  1841 		}
  1842 	share->iMode&=~KFileShareMask;
  1843 	share->iMode|=newMode;
  1844 	share->File().SetShare(newMode);
  1845 	return(KErrNone);
  1846 	}
  1847 
  1848 
  1849 TInt TFsFileChangeMode::Initialise(CFsRequest* aRequest)
  1850 //
  1851 //
  1852 //
  1853 	{
  1854 	TInt r = DoInitNoParse(aRequest);
  1855 	if(r != KErrNone)
  1856 		return r;
  1857 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1858 	if(CompareResource(share->File().FileName().Mid(2)) )
  1859 		{
  1860 		if(!KCapFsFileChangeMode.CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING("File Change Mode")))
  1861 			return KErrPermissionDenied;
  1862 		}
  1863 	return KErrNone;
  1864 	}
  1865 
  1866 
  1867 TInt TFsFileRename::DoRequestL(CFsRequest* aRequest)
  1868 //
  1869 // Rename the file if it was openned EFileShareExclusive
  1870 //
  1871 	{
  1872 	__PRINT(_L("TFsFileRename::DoRequestL(CFsRequest* aRequest)"));
  1873 
  1874     TInt r = CheckDiskSpace(0, aRequest);
  1875     if(r != KErrNone)
  1876         return r;
  1877 
  1878 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1879 	r=share->CheckMount();
  1880 	if (r!=KErrNone)
  1881 		return(r);
  1882 
  1883 	TInt currentMode=(share->iMode&KFileShareMask);
  1884 	if ((currentMode&EFileShareAny) || (currentMode&EFileShareReadersOnly))
  1885 		return(KErrAccessDenied); // File must be EFileShareExclusive
  1886 
  1887 	if ((share->iMode&EFileWrite)==0)
  1888 		return(KErrAccessDenied); // File must have write permission
  1889 
  1890 	TPtrC filePath = aRequest->Dest().FullName().Mid(2);
  1891 	CFileCB& file = share->File();
  1892 
  1893 	TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameL, EF32TraceUidFileSys, 
  1894 		(TUint) &file, filePath);
  1895 	TRAP(r,file.RenameL(filePath));
  1896 	TRACERETMULT1(UTF::EBorder, UTraceModuleFileSys::ECFileCBRenameLRet, EF32TraceUidFileSys, r);
  1897 
  1898 	// Re-write the file's folded name & re-calculate the hash
  1899 	if (r == KErrNone)
  1900 		{
  1901 		TFileName filePathF;
  1902 		filePathF.CopyF(filePath);
  1903 	    TRAP(r, AllocBufferL(file.iFileNameF, filePathF));
  1904 		file.iNameHash=CalcNameHash(*file.iFileNameF);
  1905 		}
  1906 
  1907 	return(r);
  1908 	}
  1909 
  1910 TInt TFsFileRename::Initialise(CFsRequest* aRequest)
  1911 //
  1912 //
  1913 //
  1914 	{
  1915 	TInt r=DoInitialise(aRequest);
  1916 	if(r!=KErrNone)
  1917 		return(r);
  1918 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1919 	TFileName newName;
  1920 	TRAP(r,aRequest->ReadL(KMsgPtr0,newName));
  1921 	if(r!=KErrNone)
  1922 		return(r);
  1923 	TDriveUnit currentDrive(share->File().Mount().Drive().DriveNumber());
  1924 	TDriveName driveName=currentDrive.Name();
  1925 	r=aRequest->Dest().Set(newName,&share->File().FileName(),&driveName);
  1926 	if (r!=KErrNone)
  1927 		return(r);
  1928 	if (aRequest->Dest().IsWild())
  1929 		return(KErrBadName);
  1930 	TInt driveNo;
  1931 	if ((r=RFs::CharToDrive(aRequest->Dest().Drive()[0],driveNo))!=KErrNone)
  1932 		return(r);
  1933 	TDrive& drive=TheDrives[driveNo];
  1934  	if(drive.IsSubsted())
  1935 		{
  1936 		if ((drive.Subst().Length()+aRequest->Dest().FullName().Length())>(KMaxFileName+3))
  1937 			return(KErrBadName);
  1938 		TFileName n=drive.Subst();
  1939 		n+=aRequest->Dest().FullName().Mid(3);
  1940 		r=aRequest->Dest().Set(n,NULL,NULL);
  1941 		if(r!=KErrNone)
  1942 			return(r);
  1943 		}
  1944 
  1945 	TDriveUnit newDrive(aRequest->Dest().Drive());
  1946 	if (newDrive!=currentDrive)
  1947 		return(KErrBadName);
  1948 	if (IsIllegalFullName(aRequest->Dest().FullName().Mid(2)))
  1949 		return(KErrBadName);
  1950 	r=PathCheck(aRequest,aRequest->Dest().FullName().Mid(2),&KCapFsSysFileRename,&KCapFsPriFileRename,&KCapFsROFileRename, __PLATSEC_DIAGNOSTIC_STRING("File Rename"));
  1951 	return(r);
  1952 	}
  1953 
  1954 
  1955 TInt TFsFileDrive::DoRequestL(CFsRequest* aRequest)
  1956 //
  1957 // Get the drive info for the file.
  1958 //
  1959 	{
  1960 	__PRINT(_L("TFsFileDrive::DoRequestL(CFsRequest* aRequest)"));
  1961 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  1962 	TDrive *dr = &share->File().Drive();
  1963 
  1964 	TPckgBuf<TInt> pkiF(dr->DriveNumber());		// copy drive number to user
  1965 	aRequest->WriteL(KMsgPtr0, pkiF);
  1966 
  1967 	TDriveInfo di;								// copy drive info to user
  1968 	dr->DriveInfo(di);
  1969 	TPckgC<TDriveInfo> pkdiF(di);
  1970 	aRequest->WriteL(KMsgPtr1, pkdiF);
  1971 
  1972 	return(KErrNone);
  1973 	}
  1974 
  1975 
  1976 TInt TFsFileDrive::Initialise(CFsRequest* aRequest)
  1977 //
  1978 //
  1979 //
  1980 	{
  1981 	return(DoInitNoParse(aRequest));
  1982 	}
  1983 
  1984 
  1985 TInt TFsFileDuplicate::DoRequestL(CFsRequest* aRequest)
  1986 //
  1987 // Duplicate the received file handle ready for transfer to another process.
  1988 // The new file handle is written back to the client in a a mangled form to prevent
  1989 // it from being used. Calling TFsFileAdopt will de-mangle the handle.
  1990 //
  1991 	{
  1992 	CFileShare* pS = (CFileShare*)aRequest->ScratchValue();
  1993 
  1994 	// get the file control block from the client's file share
  1995 	CFileCB& fileCB = pS->File();
  1996 
  1997 	// Create a new file share and initialize it with the 
  1998 	// client file share's file control block, position & mode
  1999 	
  2000 	CFileShare* pNewFileShare = new CFileShare(&fileCB);
  2001 	if (pNewFileShare == NULL)
  2002 		return KErrNoMemory;
  2003 
  2004 	// We need to call CFileCB::PromoteShare immediately after the CFileShare 
  2005 	// instance is created since the destructor calls CFileCB::DemoteShare()
  2006 	// which checks the share count is non-zero
  2007 	pNewFileShare->iMode = pS->iMode;
  2008 	fileCB.PromoteShare(pNewFileShare);
  2009 	
  2010 	
  2011 	TInt r = fileCB.Open();	// increment the ref count
  2012 
  2013 	if (r == KErrNone)
  2014 		TRAP(r, pNewFileShare->InitL());
  2015 	__e32_atomic_store_ord64(&pNewFileShare->iPos, pS->iPos);
  2016 	
  2017 	// Add new file share to the global file share container
  2018 	if (r == KErrNone)
  2019 		TRAP(r, FileShares->AddL(pNewFileShare,ETrue));
  2020 	
  2021 	// Add new file share to list owned by this session
  2022 	TInt newHandle;
  2023 	if (r == KErrNone)
  2024 		TRAP(r,newHandle = aRequest->Session()->Handles().AddL(pNewFileShare,ETrue));
  2025 
  2026 	if (r!=KErrNone)
  2027 		{
  2028 		pNewFileShare->Close();
  2029 		return r;
  2030 		}
  2031 
  2032 	newHandle^= KSubSessionMangleBit;
  2033 
  2034 	TPtrC8 pH((TUint8*)&newHandle, sizeof(TInt));
  2035 	aRequest->WriteL(KMsgPtr3, pH);
  2036 	aRequest->Session()->IncResourceCount();
  2037 	return(KErrNone);
  2038 	}
  2039 
  2040 TInt TFsFileDuplicate::Initialise(CFsRequest* aRequest)
  2041 	{
  2042 	TInt handle = aRequest->Message().Int0();
  2043 	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
  2044 	
  2045 	// If the handle is invalid, either panic (CFsMessageRequest::Dispatch() will 
  2046 	// panic if we return KErrBadHandle) or complete the request with KErrArgument.
  2047 	// The latter case is the behaviour for the (deprecated) RFile::Adopt() to
  2048 	// prevent a server from panicing if the passed file handle is invalid.
  2049 	if(!share)
  2050 		return aRequest->Message().Int1()?KErrBadHandle:KErrArgument;
  2051 
  2052 	aRequest->SetDrive(&share->File().Drive());
  2053 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
  2054 	return(KErrNone);
  2055 	}
  2056 
  2057 
  2058 
  2059 TInt TFsFileAdopt::DoRequestL(CFsRequest* aRequest)
  2060 //
  2061 // Adopt the passed file handle. This assumes that the handle has already been 
  2062 // duplicated by calling TFsFileDuplicate and is therefore mangled.
  2063 //
  2064 	{
  2065 	if (((CFileShare*)aRequest->ScratchValue()) == NULL)
  2066 		return KErrBadHandle;
  2067 	
  2068 	TInt adoptType = aRequest->Message().Int1();
  2069 	// EFileBigFile mode check
  2070 	switch(adoptType)
  2071 		{
  2072 		case KFileAdopt32:
  2073 			// Request is from RFile::Adopt or RFile::AdoptFromXXX: Force NO EFileBigFile
  2074 			((CFileShare*)aRequest->ScratchValue())->iMode &= ~EFileBigFile;
  2075 			break;
  2076 		case KFileAdopt64:
  2077 			// Request is from RFile64::AdoptFromXXX: Force EFileBigFile
  2078 			((CFileShare*)aRequest->ScratchValue())->iMode |= EFileBigFile;
  2079 			break;
  2080 		case KFileDuplicate:
  2081 			// Request is from RFile::Duplucate
  2082 			// adopt original file mode - do nothing
  2083 			break;
  2084 		//default:
  2085 			// Do nothing
  2086 		}
  2087 	
  2088 	// De-mangle the existing sub-session handle and return it to the client
  2089 	TInt newHandle = aRequest->Message().Int0() ^ KSubSessionMangleBit;
  2090 
  2091 	TPtrC8 pH((TUint8*)&newHandle,sizeof(TInt));
  2092 	aRequest->WriteL(KMsgPtr3,pH);
  2093 	return(KErrNone);
  2094 	}
  2095 
  2096 TInt TFsFileAdopt::Initialise(CFsRequest* aRequest)
  2097 	{
  2098 	TInt handle = aRequest->Message().Int0() ^KSubSessionMangleBit;
  2099 
  2100 	CFileShare* share = GetShareFromHandle(aRequest->Session(), handle);
  2101 	// Normally returning KErrBadHandle will result in a panic, but when a server calls 
  2102 	// RFile::AdoptXXX() and it's client has given it a bad handle then it's not a good 
  2103 	// idea to panic the server. So we return KErrNone here and allow 
  2104 	// TFsFileAdopt::DoRequestL() to return KErrBadHandle
  2105 	if (share)
  2106 		aRequest->SetDrive(&share->File().Drive());
  2107 
  2108 	aRequest->SetScratchValue64( MAKE_TINT64(ETrue, (TUint) share) );
  2109 	return(KErrNone);
  2110 	}
  2111 
  2112 
  2113 TInt TFsFileName::DoRequestL(CFsRequest* aRequest)
  2114 //
  2115 // Get the name of a file. 
  2116 // i.e. including the name & extension but excluding the drive and path
  2117 //
  2118 	{
  2119 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
  2120 
  2121 	// Search backwards until a backslash is found
  2122 	// This should always succeed as this is a full pathname
  2123 	TPtrC name(share->File().FileName());
  2124 	TInt offset = name.LocateReverse('\\');
  2125 	aRequest->WriteL(KMsgPtr0, name.Mid(offset+1));
  2126 
  2127 	return(KErrNone);
  2128 	}
  2129 
  2130 TInt TFsFileName::Initialise(CFsRequest* aRequest)
  2131 //
  2132 // Get the full name of a file, including path and drive 
  2133 //
  2134 //
  2135 	{
  2136 	return InitialiseScratchToShare(aRequest);
  2137 	}
  2138 	
  2139 	
  2140 TInt TFsFileFullName::DoRequestL(CFsRequest* aRequest)
  2141 //
  2142 // Get the full name of a file, including path and drive 
  2143 //
  2144 	{
  2145 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
  2146 
  2147 	// Write the drive letter and ':'
  2148 	TBuf<2> driveBuf(KDrivePath);
  2149 	driveBuf[0]=TText('A' + share->File().Drive().DriveNumber());
  2150 	aRequest->WriteL(KMsgPtr0, driveBuf);
  2151 
  2152 	// Write the file and path including leading '\'
  2153 	TPtrC name(share->File().FileName());
  2154 	aRequest->WriteL(KMsgPtr0, name, 2);
  2155 	
  2156 	return(KErrNone);
  2157 	}
  2158 
  2159 
  2160 TInt TFsFileFullName::Initialise(CFsRequest* aRequest)
  2161 //
  2162 //
  2163 //
  2164 	{
  2165 	return InitialiseScratchToShare(aRequest);
  2166 	}
  2167 
  2168 TInt TFsGetMediaSerialNumber::DoRequestL(CFsRequest* aRequest)
  2169 //
  2170 // Acquire capability from media and return serial number if supported.
  2171 //
  2172     {
  2173     // Get request parameters
  2174     const TInt drvNum = aRequest->Message().Int1();
  2175 
  2176 	// Get media capability
  2177     TLocalDriveCapsV5Buf capsBuf;
  2178 
  2179 	TInt r = KErrNone;
  2180 
  2181 	// is the drive local?
  2182 	if (!IsProxyDrive(drvNum))
  2183 		{
  2184 		// if not valid local drive, use default values in localDriveCaps
  2185 		// if valid local drive and not locked, use TBusLocalDrive::Caps() values
  2186 		// if valid drive and locked, hard-code attributes
  2187 		r = GetLocalDrive(drvNum).Caps(capsBuf);
  2188 		}
  2189 	else  // this need to be made a bit nicer
  2190 		{   
  2191 		CExtProxyDrive* pD = GetProxyDrive(drvNum);
  2192 		if(pD)
  2193 			r = pD->Caps(capsBuf);
  2194 		else
  2195 			r = KErrNotReady;
  2196 		}
  2197 	
  2198 	if (r != KErrNone)
  2199         return r;
  2200 
  2201     TLocalDriveCapsV5& capsV5 = capsBuf();
  2202 
  2203     // Return serial number if supported
  2204     if (capsV5.iSerialNumLength == 0)
  2205         return KErrNotSupported;
  2206 
  2207     TPtrC8 snPtr(capsV5.iSerialNum, capsV5.iSerialNumLength);
  2208     aRequest->WriteL(KMsgPtr0, snPtr);
  2209 
  2210 	return KErrNone;
  2211     }
  2212 
  2213 TInt TFsGetMediaSerialNumber::Initialise(CFsRequest* aRequest)
  2214 //
  2215 // Validate drive number and its attributes passed in a request object.
  2216 //
  2217     {
  2218     const TInt drvNum = aRequest->Message().Int1();
  2219 
  2220     TInt nRes = ValidateDrive(drvNum, aRequest);
  2221     if(nRes != KErrNone)
  2222         return KErrBadName; //-- incorrect drive number
  2223 
  2224     if(aRequest->Drive()->IsSubsted())
  2225         return KErrNotSupported; //-- the drive is substed, this operation doesn't make a sense
  2226     
  2227     if(!IsValidLocalDriveMapping(drvNum))
  2228 	    return KErrNotReady;
  2229 
  2230     return KErrNone;
  2231     }
  2232 
  2233 TInt TFsBlockMap::Initialise(CFsRequest* aRequest)
  2234 	{
  2235 	TInt r = DoInitNoParse(aRequest);
  2236 	if(r!=KErrNone)
  2237 		return r;
  2238 
  2239 	TInt blockMapUsage = aRequest->Message().Int2();
  2240 	if ( blockMapUsage == EBlockMapUsagePaging )
  2241 		{
  2242 		CFileShare* share = (CFileShare*) aRequest->ScratchValue();
  2243 		CFileCB& file = share->File();
  2244 
  2245 		// To determine whether the drive where this file resides is pageable, we need to locate 
  2246 		// the specific TBusLocalDrive object first; querying the drive attributes directly from the 
  2247 		// (composite) file system is no good as this API treats all slave file systems as "ROM & not pageable.
  2248 		TBusLocalDrive* localDrive;
  2249 		TInt r = file.LocalDrive(localDrive);
  2250 		if (r != KErrNone)
  2251 			return r;
  2252 		TLocalDriveCapsV4Buf caps;
  2253 		r = localDrive->Caps(caps);
  2254 		if (r != KErrNone)
  2255 			return r;
  2256 		__PRINT4(_L("TFsBlockMap::Initialise, drive %d file %S iMediaAtt %08X iDriveAtt %08X\n"), file.DriveNumber(), &file.FileName(), caps().iMediaAtt, caps().iDriveAtt);
  2257 		if ( !(caps().iDriveAtt & KDriveAttPageable))
  2258 			return KErrNotSupported;
  2259 		}
  2260 
  2261 	return KErrNone;
  2262 	}
  2263 
  2264 TInt TFsBlockMap::DoRequestL(CFsRequest* aRequest)
  2265 	{
  2266 	__PRINT(_L("TFsBlockMap::DoRequestL(CFsRequest* aRequest)"));
  2267 	__PRINT1(_L("aRequest->Session() = 0x%x"), aRequest->Session());
  2268 
  2269 	CFileShare* share = (CFileShare*) aRequest->ScratchValue();
  2270 
  2271 	TInt r = share->CheckMount();
  2272 
  2273 	__PRINT1(_L("share->CheckMount() returned - %d"), r);
  2274 	if ( r != KErrNone )
  2275 		return(r);
  2276 
  2277 	SBlockMapInfo reqInfo;
  2278 	SBlockMapArgs args;
  2279 	TPckg<SBlockMapArgs> pkArgs(args);
  2280 	aRequest->ReadL(KMsgPtr1, pkArgs);
  2281 
  2282 	CFileCB& file = share->File();
  2283 	TInt64& reqStartPos = args.iStartPos;
  2284 	TInt64 reqEndPos = args.iEndPos;
  2285 
  2286 	if ( ( reqStartPos > file.Size64() ) || ( reqStartPos < 0 ) )
  2287 		return KErrArgument;
  2288 
  2289 	const TInt64 KReadToEOF = -1;
  2290 	if ( reqEndPos != KReadToEOF )
  2291  		{
  2292 		if ( !( reqEndPos >= reqStartPos ) )
  2293 			return KErrArgument;
  2294 		}
  2295 	else
  2296 		reqEndPos = file.Size64();
  2297 
  2298 	// If the requested start position is equal to the size of the file
  2299 	// then we read no data and return an empty BlockMap.
  2300 	if ( reqStartPos == file.Size64() || reqEndPos == 0 || reqEndPos == reqStartPos )
  2301 		{
  2302 		TPckg<SBlockMapInfo> pkInfo(reqInfo);
  2303 		TRAP(r,aRequest->WriteL(KMsgPtr0,pkInfo) );
  2304  		if ( r == KErrNone )
  2305  			return(KErrArgument);
  2306 		else
  2307 			return(r);
  2308 		}
  2309 	r = share->File().BlockMap(reqInfo, reqStartPos, reqEndPos);
  2310 	TPckg<SBlockMapInfo> pkInfo(reqInfo);
  2311 	aRequest->WriteL(KMsgPtr0, pkInfo);
  2312 	aRequest->WriteL(KMsgPtr1, pkArgs);
  2313 
  2314 	return(r);
  2315 	}
  2316 
  2317 #pragma warning( disable : 4705 )	// statement has no effect
  2318 /**
  2319 Default constructor
  2320 */
  2321 EXPORT_C CFileCB::CFileCB()
  2322 	{
  2323 	}
  2324 #pragma warning( default : 4705 )
  2325 
  2326 
  2327 
  2328 
  2329 /**
  2330 Destructor.
  2331 
  2332 Frees resources before destruction of the object.
  2333 */
  2334 EXPORT_C CFileCB::~CFileCB()
  2335 	{
  2336 	// NB Must be careful to close the file cache BEFORE deleting iFileNameF
  2337 	// as CFileCache may steal it (!)
  2338 	if (FileCache())
  2339 		FileCache()->Close();
  2340 	if (iBody && iBody->iDeleteOnClose)
  2341 		{
  2342 		TRACEMULT2(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteL, EF32TraceUidFileSys, DriveNumber(), FileName());
  2343 		TInt r;
  2344 		TRAP(r, iMount->DeleteL(FileName()));
  2345 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECMountCBDeleteLRet, EF32TraceUidFileSys, r);
  2346 		}
  2347 
  2348 	if(iMount)
  2349 		iMount->Close();
  2350 	if (iMountLink.iNext!=NULL)
  2351 		{
  2352 		iMountLink.Deque();
  2353 		}
  2354 	delete iFileName;
  2355 	delete iFileNameF;
  2356 	if (iFileLocks)
  2357 		{
  2358 		iFileLocks->Close();
  2359 		delete iFileLocks;
  2360 		}
  2361 
  2362 	delete iBody;
  2363 	}
  2364 
  2365 /**
  2366     Initialise CFileCB object.
  2367     @internalTechnology
  2368 
  2369     @param  aDrive
  2370     @param  aCreatedDrive
  2371     @param  aName           file name descriptor
  2372 */
  2373 EXPORT_C void CFileCB::InitL(TDrive* aDrive, TDrive* aCreatedDrive, HBufC* aName)
  2374 	{
  2375 	// Take ownership of heap-allocated objects aName and aLock before attempting any memory allocation 
  2376 	// to avoid leaking memory
  2377 	iFileName = aName;
  2378 
  2379     DoInitL(aDrive->DriveNumber());
  2380 	iDrive=aDrive;
  2381 	iCreatedDrive=aCreatedDrive;
  2382 	TFileName tempName;
  2383 	tempName.CopyF(*aName);
  2384 	iFileNameF=tempName.AllocL();
  2385 	iNameHash=CalcNameHash(*iFileNameF);
  2386 	
  2387 
  2388 	
  2389 	// see whether the file system supports the CFileCB extended API
  2390 	MExtendedFileInterface* extendedFileInterface = NULL;
  2391 	GetInterfaceTraced(CFileCB::EExtendedFileInterface, (void*&) extendedFileInterface, NULL);
  2392 	iBody = new(ELeave)CFileBody(this, extendedFileInterface);
  2393 
  2394 	iMount=&iDrive->CurrentMount();
  2395 	iBody->InitL();
  2396 	User::LeaveIfError(iMount->Open());
  2397 	
  2398 	//-- create file locks array
  2399     ASSERT(!iFileLocks);
  2400     iFileLocks = new(ELeave) TFileLocksArray(KFileShareLockGranularity, _FOFF(TFileShareLock, iPosLow));
  2401 
  2402     }
  2403 	
  2404 
  2405 TInt CFileCB::FindLock(TInt aPosLow,TInt aPosHigh)
  2406 	{
  2407 	return FindLock64(aPosLow, aPosHigh);
  2408 	}
  2409 
  2410 TInt CFileCB::AddLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
  2411 	{
  2412 	return AddLock64(aFileShare, aPos, aLength);
  2413 	}
  2414 
  2415 TInt CFileCB::RemoveLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
  2416 	{
  2417 	return RemoveLock64(aFileShare, aPos, aLength);
  2418 	}
  2419 
  2420 TInt CFileCB::CheckLock(CFileShare* aFileShare,TInt aPos,TInt aLength)
  2421 	{
  2422 	return CheckLock64(aFileShare, aPos, aLength);
  2423 	}
  2424 
  2425 /**
  2426     Remove any locks held by aFileShare.
  2427 */
  2428 void CFileCB::RemoveLocks(CFileShare* aFileShare)
  2429 	{
  2430 
  2431 	TInt i=0;
  2432 	while (i<FileLocks().Count())
  2433 		{
  2434 		if (FileLocks()[i].MatchOwner(aFileShare))
  2435 			FileLocks().Remove(i);
  2436 		else
  2437 			i++;
  2438 		}
  2439 	}
  2440 
  2441 
  2442 void CFileCB::PromoteShare(CFileShare* aShare)
  2443 //
  2444 // Manages share promotion after the share has been added to the FilsShares container.
  2445 //
  2446 //  - Assumes the share has already been validated using ValidateShare()
  2447 //
  2448 //  - The count of promoted shares (ie - non-EFileShareReadersOrWriters) is incremented
  2449 //	  to allow the share mode to be demoted when the last promoted share is closed.
  2450 //
  2451 	{
  2452 	TShare reqShare = (TShare)(aShare->iMode & KFileShareMask);
  2453 	if(reqShare != EFileShareReadersOrWriters)
  2454 		{
  2455 		iBody->iPromotedShares++;
  2456 		iShare = reqShare;
  2457 		}
  2458 	}
  2459 
  2460 
  2461 void CFileCB::DemoteShare(CFileShare* aShare)
  2462 //
  2463 // Manages share demotion after the share has been removed from the FileShares container.
  2464 //
  2465 //  - If the share being removed is not EFileShareReadersOrWriters, then the current
  2466 //	  share mode may require demotion back to EFileShareReadersOrWriters.
  2467 //
  2468 //	- This is determined by the iPromotedShares count, incremented in PromoteShare()
  2469 //
  2470 	{
  2471 	if((aShare->iMode & KFileShareMask) != EFileShareReadersOrWriters)
  2472 		{
  2473 		if(--iBody->iPromotedShares == 0)
  2474 			{
  2475 			// Don't worry if the file has never been opened as EFileShareReadersOrWriters
  2476 			//  - in this case the CFileCB object is about to be closed anyway.
  2477 			iShare = EFileShareReadersOrWriters;
  2478 			}
  2479 		}
  2480 	__ASSERT_DEBUG(iBody->iPromotedShares>=0,Fault(EFileShareBadPromoteCount));
  2481 	}
  2482 
  2483 
  2484 RArray<TAsyncReadRequest>& CFileCB::AsyncReadRequests()
  2485 //
  2486 // Gets a reference to the pending asynchronous read requests for this file.
  2487 //
  2488 //  - The request is completed when all data is available or the request is cancelled.
  2489 //
  2490 	{
  2491 	return(*iBody->iAsyncReadRequests);
  2492 	}
  2493 
  2494 
  2495 TInt CFileCB::AddAsyncReadRequest(CFileShare* aShareP, TInt64 aPos, TInt aLen, CFsRequest* aRequestP)
  2496 //
  2497 // Adds a pending asynchronous read request to the list.
  2498 //
  2499 //  - The request is completed when all data is available or the request is cancelled.
  2500 //
  2501 	{
  2502 
  2503 	__ASSERT_ALWAYS(aRequestP->Operation()->Function() == EFsFileRead, Fault(EBaseRequestMessage));
  2504 	
  2505 	TAsyncReadRequest req(aPos + aLen, aShareP, aRequestP);
  2506 	TInt err = AsyncReadRequests().InsertInSignedKeyOrderAllowRepeats(req);
  2507 	if(err != KErrNone)
  2508 		return err;
  2509 
  2510 	aRequestP->SetCompleted(EFalse);
  2511 	return KErrNone;
  2512 	}
  2513 
  2514 
  2515 TInt CFileCB::CancelAsyncReadRequest(CFileShare* aShareP, TRequestStatus* aStatusP)
  2516 //
  2517 // Cancels (and completes) an outstanding read request for the specified share.
  2518 //
  2519 //	- aStatusP == NULL cancels all outstanding read requests.
  2520 //
  2521 	{
  2522 
  2523 	TInt i=0;
  2524 	Drive().Lock();
  2525 	while (i < AsyncReadRequests().Count())
  2526 		{
  2527 		TAsyncReadRequest& req = AsyncReadRequests()[i];
  2528 		if(req.CompleteIfMatching(aShareP, aStatusP, KErrCancel))
  2529 			{
  2530 			iBody->iAsyncReadRequests->Remove(i);
  2531 			if(aStatusP != NULL)
  2532 				{
  2533 				Drive().UnLock();
  2534 				return KErrNone;
  2535 				}
  2536 			}
  2537 		else
  2538 			{
  2539 			i++;
  2540 			}
  2541 		}
  2542 
  2543 	Drive().UnLock();
  2544 	return KErrNone;
  2545 	}
  2546 
  2547 
  2548 void CFileCB::NotifyAsyncReaders()
  2549 //
  2550 // Determine if any outstanding read requests require completion.
  2551 //
  2552 //  - Called whenever the file size changes (due to a write operation or SetSize)
  2553 //
  2554 //  - Any outstanding read requests are re-issued (rather then completed in the 
  2555 //    context of the current operation so not to affect performance of the writer).
  2556 //
  2557 //  - Should the file size shrink before the request is serviced, the request will
  2558 //    be added back onto the queue.
  2559 //
  2560 //	- A future optimisation may issue the request as data becomes available (which
  2561 //	  would minimise the final latency between writer and reader) but the current
  2562 //	  implementation reads all requested data in one operation.
  2563 //
  2564 	{
  2565 	Drive().Lock();
  2566 	
  2567 	SetNotifyAsyncReadersPending(EFalse);
  2568 
  2569 	while(AsyncReadRequests().Count())
  2570 		{
  2571 		TAsyncReadRequest& req = AsyncReadRequests()[0];
  2572 		if(req.iEndPos > CachedSize64())
  2573 			break;
  2574 
  2575 		// Make a copy and then remove it from the queue before releasing the lock - 
  2576 		// because the file server thread could append to the RArray and this might 
  2577 		// cause a re-allocation which would move the whole array (!)
  2578 		TAsyncReadRequest reqCopy = req;
  2579 		AsyncReadRequests().Remove(0);
  2580 		Drive().UnLock();
  2581 
  2582 		// allocate a new request, push a TMsgOperation onto the request's stack (duplicating
  2583 		// the functionality of TFsFileRead::Initialise()) & dispatch the request
  2584 		CFsClientMessageRequest* pRequest = NULL;
  2585 		const TOperation& oP = OperationArray[EFsFileRead];
  2586 		TInt r = RequestAllocator::GetMessageRequest(oP, reqCopy.iMessage, pRequest);
  2587 		if (r != KErrNone)
  2588 			{
  2589 			reqCopy.iMessage.Complete(r);	// complete the client's message with an error
  2590 			continue;
  2591 			}
  2592 		pRequest->Set(reqCopy.iMessage, oP, reqCopy.iSessionP);
  2593 
  2594 		r = DoInitNoParse(pRequest);
  2595 		if (r != KErrNone)
  2596 			{
  2597 			pRequest->Complete(r);		// complete the client's message with an error
  2598 			continue;
  2599 			}
  2600 		
  2601 		r = pRequest->PushOperation(TFsFileRead::Complete);
  2602 		if (r != KErrNone)
  2603 			{
  2604 			pRequest->Complete(r);		// complete the client's message with an error
  2605 			continue;
  2606 			}
  2607 
  2608 		pRequest->CurrentOperation().Set(
  2609 			reqCopy.iEndPos - pRequest->Message().Int1(), 
  2610 			pRequest->Message().Int1(), 
  2611 			(TDes8*) pRequest->Message().Ptr0());
  2612 
  2613 		// don't call Initialise()
  2614 		pRequest->SetState(CFsRequest::EReqStatePostInitialise);
  2615 
  2616 		pRequest->Dispatch();
  2617 		Drive().Lock();
  2618 		}
  2619 	Drive().UnLock();
  2620 	}
  2621 
  2622 
  2623 /**
  2624 Gets the address of the file that the file control block represents. 
  2625 
  2626 The default implementation returns KErrNotSupported and should only
  2627 be overridden for ROM file systems.
  2628 
  2629 @param aPos On return, should contain the address of the file that
  2630             the file control block represents.
  2631 
  2632 @return KErrNone, if successful,otherwise one of the other system wide error
  2633         codes,
  2634 */
  2635 EXPORT_C TInt CFileCB::Address(TInt& /*aPos*/) const
  2636 	{
  2637 
  2638 	return(KErrNotSupported);
  2639 	}
  2640 
  2641 
  2642 /**
  2643 Sets the archive attribute, KEntryAttArchive, in iAtt.
  2644 */
  2645 EXPORT_C void CFileCB::SetArchiveAttribute()
  2646 	{
  2647 
  2648 	iAtt|=KEntryAttArchive;
  2649 	iAtt|=KEntryAttModified;
  2650 	iModified.UniversalTime();
  2651 	}
  2652 
  2653 
  2654 EXPORT_C TInt CFileCB::GetInterface(TInt aInterfaceId,TAny*& aInterface,TAny* /*aInput*/)
  2655 	{
  2656 	switch(aInterfaceId)
  2657 		{
  2658 		case EGetLocalDrive:
  2659 			return Mount().LocalDrive((TBusLocalDrive*&) aInterface);
  2660 		default:
  2661 			return(KErrNotSupported);
  2662 		}
  2663 	}
  2664 
  2665 
  2666 CFileCache* CFileCB::FileCache() const
  2667 	{return iBody?iBody->iFileCache:NULL;}
  2668 
  2669 TBool CFileCB::LocalBufferSupport() const
  2670 	{return iBody?iBody->iLocalBufferSupport:EFalse;}
  2671 
  2672 void CFileCB::SetLocalBufferSupport(TBool aEnabled)
  2673 	{iBody->iLocalBufferSupport = aEnabled;}
  2674 
  2675 TInt CFileCB::CheckMount()
  2676 //
  2677 // Check that the media is still mounted.
  2678 //
  2679 	{
  2680 
  2681 	TDrive& d = Drive();
  2682 	TInt r=d.CheckMount();
  2683 	if (r!=KErrNone)
  2684 		return(r);
  2685 	if (&Mount() != &d.CurrentMount())
  2686 		return(KErrDisMounted);
  2687 	if (FileCorrupt())
  2688 		return(KErrCorrupt);
  2689 	if (BadPower())
  2690 		{
  2691 		if (PowerOk())
  2692 			SetBadPower(EFalse);
  2693 		else
  2694 			return(KErrBadPower);
  2695 		}
  2696 	return(KErrNone);
  2697 	}
  2698 
  2699 TInt64 CFileCB::CachedSize64() const
  2700 	{
  2701 	CFileCache* fileCache = iBody?iBody->iFileCache:NULL;
  2702 	return fileCache? fileCache->Size64(): Size64();
  2703 	}
  2704 
  2705 void CFileCB::SetCachedSize64(TInt64 aSize)
  2706 	{
  2707 	if (FileCache())
  2708 		FileCache()->SetSize64(aSize);
  2709 	else
  2710 		SetSize64(aSize, EFalse);	// assume not locked
  2711 	}
  2712 
  2713 /**
  2714 Constructor.
  2715 Locks the mount resource to which the shared file resides.
  2716 
  2717 @param aFileCB File to be shared.
  2718 */
  2719 CFileShare::CFileShare(CFileCB* aFileCB)
  2720 	: iFile(aFileCB)
  2721 	{
  2722 	AddResource(iFile->Mount());
  2723 	}
  2724 
  2725 /**
  2726 Destructor.
  2727 
  2728 Frees mount resource to which the shared file resides,
  2729 removes share status from the shared file and finally closes
  2730 the file.
  2731 */
  2732 CFileShare::~CFileShare()
  2733 	{
  2734 	// We shouldn't be deleting the file share with a valid request queue or there will be request (& memory) leakage
  2735 	__ASSERT_DEBUG(iCurrentRequest == NULL, Fault(ERequestQueueNotEmpty));
  2736 
  2737 	RemoveResource(iFile->Mount());
  2738 	iFile->RemoveLocks(this);
  2739 	iFile->DemoteShare(this);
  2740 	iFile->CancelAsyncReadRequest(this, NULL);
  2741 	iFile->Close();
  2742 	}
  2743 
  2744 /**
  2745 Check that the media is still mounted.
  2746 
  2747 @return KErrNone if successful.
  2748         KErrDisMounted if media has dismounted.
  2749         KErrCorrupted if shared file is corrupted.
  2750         KErrBadPower if insufficent power supply.
  2751         or other system wide error code.
  2752 */
  2753 TInt CFileShare::CheckMount()
  2754 	{
  2755 	return File().CheckMount();
  2756 	}
  2757 
  2758 /**
  2759 Initialise the object
  2760 */
  2761 void CFileShare::InitL()
  2762 	{
  2763 	DoInitL(iFile->Drive().DriveNumber());
  2764 
  2765 	// override the close operation so that we can flush the write cache if necessary
  2766 	iRequest->Set(FileShareCloseOp,NULL);
  2767 	iRequest->SetDriveNumber(DriveNumber());
  2768 	iRequest->SetScratchValue((TUint)this);
  2769 	}
  2770 
  2771 // Mark the start of a request - 
  2772 // the is to prevent fair-scheduled async read/writes from being processed out of sequence. This is especially 
  2773 // important when considering a client which appends to a file by issuing more than one asynchronous request as each
  2774 // write request must be entirely satisfied before a subsequent request can append to the file
  2775 TBool CFileShare::RequestStart(CFsMessageRequest* aRequest)
  2776 	{
  2777 	TBool ret;
  2778 	
  2779 	TDrive& drive = File().Drive();
  2780 	drive.Lock();
  2781 
  2782 	if (iCurrentRequest == NULL || iCurrentRequest == aRequest)
  2783 		{
  2784 		iCurrentRequest = aRequest;
  2785 		ret = ETrue;
  2786 		}
  2787 	else
  2788 		{
  2789 		// add to end of linked list of requests if there is already an active request for this share
  2790 		CFsClientMessageRequest* request;
  2791 		for (request = (CFsClientMessageRequest*) iCurrentRequest; request->iNext != NULL; request = request->iNext)
  2792 			{
  2793 			}
  2794 		request->iNext = (CFsClientMessageRequest*) aRequest;
  2795 		ret =  EFalse;
  2796 		}
  2797 
  2798 	drive.UnLock();
  2799 	return ret;
  2800 	}
  2801 
  2802 
  2803 // Mark the end of a request
  2804 void CFileShare::RequestEnd(CFsMessageRequest* aRequest)
  2805 	{
  2806 	TDrive& drive = File().Drive();
  2807 	drive.Lock();
  2808 
  2809 	if (aRequest == iCurrentRequest)
  2810 		{
  2811 		// Any requests in the queue ?
  2812 		if (((CFsClientMessageRequest*) iCurrentRequest)->iNext)
  2813 			{
  2814 			iCurrentRequest = ((CFsClientMessageRequest*) aRequest)->iNext;
  2815 			((CFsClientMessageRequest*) aRequest)->iNext = NULL;
  2816 
  2817 			// if the current request has been cancelled, cancel all requests in the queue
  2818 			TInt lastError = aRequest->LastError();
  2819 			if (lastError == KErrCancel || lastError == KErrNotReady)
  2820 				{
  2821 				// take ownership of this queue and make it invisible to anyone else by setting iCurrentRequest to NULL
  2822 				CFsClientMessageRequest* currentRequest = (CFsClientMessageRequest*) iCurrentRequest;
  2823 				iCurrentRequest = NULL;
  2824 				drive.UnLock();
  2825 				while(currentRequest)
  2826 					{
  2827 					CFsClientMessageRequest* nextRequest = ((CFsClientMessageRequest*) currentRequest)->iNext;
  2828 					((CFsClientMessageRequest*) currentRequest)->iNext = NULL;
  2829 					currentRequest->Complete(lastError);
  2830 					currentRequest = nextRequest;
  2831 					}
  2832 				}
  2833 			else
  2834 				{
  2835 				drive.UnLock();
  2836 				iCurrentRequest->Dispatch(EFalse);
  2837 				}
  2838 			}
  2839 		else	// queue empty
  2840 			{
  2841 			iCurrentRequest = NULL;
  2842 			drive.UnLock();
  2843 			}
  2844 		}
  2845 	else	// if (aRequest == iCurrentRequest)
  2846 		{
  2847 		drive.UnLock();
  2848 		}
  2849 	}
  2850 
  2851 TBool CFileShare::RequestInProgress() const
  2852 	{
  2853 	return (iCurrentRequest != NULL)?(TBool)ETrue:(TBool)EFalse;
  2854 	}
  2855 
  2856 
  2857 
  2858 /**
  2859 Initialise the object
  2860 */
  2861 TInt TFsCloseFileShare::DoRequestL(CFsRequest* aRequest)
  2862 //
  2863 	{
  2864 	__PRINT(_L("TFsCloseFileCache::DoRequestL()"));
  2865 	
  2866 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  2867 
  2868 	// flush the write cache before closing the file share
  2869 	TInt r;
  2870 	CFileCache* fileCache = share->File().FileCache();
  2871 	if (fileCache && (r = fileCache->FlushDirty(aRequest)) == CFsRequest::EReqActionBusy)
  2872 		return r;
  2873 	
  2874 	return KErrNone;
  2875 	}
  2876 
  2877 TInt TFsCloseFileShare::Complete(CFsRequest* aRequest)
  2878 	{
  2879 	__PRINT(_L("TFsCloseFileShare::Complete()"));
  2880 	return TFsCloseObject::Complete(aRequest);
  2881 	}
  2882 
  2883 
  2884 TAsyncReadRequest::TAsyncReadRequest(TInt64 aEndPos, CFileShare* aOwningShareP, CFsRequest* aRequestP)
  2885 //
  2886 // Constructor for TAsyncReadRequest
  2887 //	- Maintains information about oustanding async read requests
  2888 //
  2889   : iEndPos(aEndPos), 
  2890 	iOwningShareP(aOwningShareP)
  2891 	{
  2892 	iMessage  = aRequestP->Message();
  2893 	iSessionP = aRequestP->Session();
  2894 	iStatusP  = iMessage.ClientStatus();
  2895 	}
  2896 
  2897 
  2898 TBool TAsyncReadRequest::CompleteIfMatching(CFileShare* aShareP, TRequestStatus* aStatusP, TInt aError)
  2899 //
  2900 // Completes an asynchronous read request.
  2901 //
  2902 	{
  2903 	if (iOwningShareP == aShareP && (aStatusP == NULL || aStatusP == iStatusP))
  2904 		{
  2905 		iMessage.Complete(aError);
  2906 		return ETrue;
  2907 		}
  2908 
  2909 	return EFalse;
  2910 	}
  2911 
  2912 
  2913 TInt TFsFileReadCancel::Initialise(CFsRequest* aRequest)
  2914 //
  2915 // Initialise function for RFile::ReadCancel [EFsReadCancel]
  2916 //
  2917 	{
  2918 	return InitialiseScratchToShare(aRequest);
  2919 	}
  2920 
  2921 
  2922 TInt TFsFileReadCancel::DoRequestL(CFsRequest* aRequest)
  2923 //
  2924 // Request function for RFile::ReadCancel [EFsReadCancel]
  2925 //
  2926 	{
  2927 	CFileShare* share = (CFileShare*)aRequest->ScratchValue();
  2928 	TRequestStatus* status = (TRequestStatus*)aRequest->Message().Ptr0();
  2929 	share->File().CancelAsyncReadRequest(share, status);
  2930 	return(KErrNone);
  2931 	}
  2932 
  2933 void CFileCB::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
  2934 	{
  2935 	TRACETHREADID(aMessage);
  2936 	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadL, EF32TraceUidFileSys, 
  2937 		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
  2938 
  2939 	iBody->iExtendedFileInterface->ReadL(aPos,aLength,aDes,aMessage,aOffset);
  2940 
  2941 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBReadLRet, EF32TraceUidFileSys, KErrNone);
  2942 	}
  2943 
  2944 void CFileCB::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
  2945 	{
  2946 	TRACETHREADID(aMessage);
  2947 	TRACE7(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteL, EF32TraceUidFileSys, 
  2948 		this, I64LOW(aPos), I64HIGH(aPos), aLength, aDes, threadId, aOffset);
  2949 
  2950 	iBody->iExtendedFileInterface->WriteL(aPos,aLength,aDes,aMessage,aOffset);
  2951 
  2952 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBWriteLRet, EF32TraceUidFileSys, KErrNone);
  2953 	}
  2954 
  2955 void CFileCB::SetSizeL(TInt64 aSize)
  2956 	{
  2957 	TRACE3(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeL, EF32TraceUidFileSys, this, I64LOW(aSize), I64HIGH(aSize));
  2958 
  2959 	iBody->iExtendedFileInterface->SetSizeL(aSize);
  2960 
  2961 	TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBSetSizeLRet, EF32TraceUidFileSys, KErrNone);
  2962 	}
  2963 
  2964 TBool CFileCB::ExtendedFileInterfaceSupported()
  2965 	{
  2966 	return iBody->ExtendedFileInterfaceSupported();
  2967 	}
  2968 
  2969 TInt CFileCB::FairSchedulingLen() const
  2970 	{
  2971 	return iBody->iFairSchedulingLen;
  2972 	}
  2973 
  2974 void CFileCB::SetNotifyAsyncReadersPending(TBool aNotifyAsyncReadersPending)
  2975 //
  2976 // Notify the asynchronous reader that a file has grown so that it may service outstanding async reads
  2977 //
  2978 	{
  2979 	iBody->iNotifyAsyncReadersPending = aNotifyAsyncReadersPending;
  2980 	}
  2981 
  2982 TBool CFileCB::NotifyAsyncReadersPending() const
  2983 	{
  2984 	return iBody->iNotifyAsyncReadersPending;
  2985 	}
  2986 
  2987 
  2988 void CFileCB::ResetReadAhead()
  2989 	{
  2990 	CFileCache* fileCache = FileCache();
  2991 	if (fileCache)
  2992 		fileCache->ResetReadAhead();
  2993 	}
  2994 
  2995 void CFileCB::SetDeleteOnClose()
  2996 	{
  2997 	iBody->iDeleteOnClose = ETrue;
  2998 	}
  2999 
  3000 TBool CFileCB::DeleteOnClose() const
  3001 	{
  3002 	return iBody->iDeleteOnClose;
  3003 	}
  3004 
  3005 TInt CFileCB::GetInterfaceTraced(TInt aInterfaceId, TAny*& aInterface, TAny* aInput)
  3006 	{
  3007 	TRACE2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterface, EF32TraceUidFileSys, aInterfaceId, aInput);
  3008 
  3009 	TInt r = GetInterface(aInterfaceId, aInterface, aInput);
  3010 
  3011 	TRACERET2(UTF::EBorder, UTraceModuleFileSys::ECFileCBGetInterfaceRet, EF32TraceUidFileSys, r, aInterface);
  3012 
  3013 	return r;
  3014 	}
  3015 
  3016 CFileBody::CFileBody(CFileCB* aFileCB, CFileCB::MExtendedFileInterface* aExtendedFileInterface)
  3017   : iFileCB(aFileCB),
  3018 	iExtendedFileInterface(aExtendedFileInterface ? aExtendedFileInterface : this),
  3019 	iSizeHigh(0)
  3020 	{
  3021 	iFairSchedulingLen = TFileCacheSettings::FairSchedulingLen(iFileCB->DriveNumber());
  3022     iMaxSupportedFileSize = KMaxSupportedFileSize;
  3023 	}
  3024 
  3025 
  3026 CFileBody::~CFileBody()
  3027 	{
  3028 	if (iAsyncReadRequests)
  3029 		{
  3030 		iAsyncReadRequests->Close();
  3031 		delete iAsyncReadRequests;
  3032 		}
  3033 	}
  3034 
  3035 
  3036 void CFileBody::InitL()
  3037 	{
  3038 	iAsyncReadRequests = new(ELeave) RArray<TAsyncReadRequest>(KAsyncRequestArrayGranularity, _FOFF(TAsyncReadRequest, iEndPos));
  3039 	}
  3040 
  3041 
  3042 
  3043 TInt TFsFileClamp::Initialise(CFsRequest* aRequest)
  3044 //
  3045 // Initialise function for RFile::Clamp [EFsFileClamp]
  3046 //
  3047 	{
  3048 	TSecureId aUID = aRequest->Message().SecureId();	
  3049     if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
  3050 		{
  3051 		SSecurityInfo info;
  3052 		info.iVendorId=0;
  3053 		info.iCaps.iCaps[0]=0;
  3054 		info.iCaps.iCaps[1]=0;
  3055 		info.iSecureId=KEstartUidValue;
  3056 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
  3057 		info.iSecureId=KFileServerUidValue;
  3058 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Clamp");
  3059 		return KErrPermissionDenied;
  3060 		}
  3061 
  3062 	TInt r=DoInitialise(aRequest);
  3063 	if(r!=KErrNone)
  3064 		return r;
  3065 
  3066 	// The clamp API is only supported on non-removable media
  3067 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  3068 	TDriveInfo di;
  3069 	share->File().Drive().DriveInfo(di);
  3070 	if (!(di.iDriveAtt & KDriveAttInternal))
  3071 		r = KErrNotSupported;
  3072 
  3073 	return(r);
  3074 	}
  3075 
  3076 
  3077 TInt TFsFileClamp::DoRequestL(CFsRequest* aRequest)
  3078 //
  3079 // Request function for RFile::Clamp [EFsFileClamp]
  3080 //
  3081 	{
  3082 	TInt r;
  3083 
  3084 	// Flush data for this file, if it is open for writing, before clamping
  3085 	CFileShare* share=(CFileShare*)aRequest->ScratchValue();
  3086 
  3087 	if (((share->iMode&EFileWrite)) || ((share->File().Att()&KEntryAttModified)))
  3088 		{
  3089 		r=share->CheckMount();
  3090 		if (r!=KErrNone)
  3091 			return(r);
  3092 
  3093 		TRACE1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataL, EF32TraceUidFileSys, &share->File());
  3094 		TRAP(r,share->File().FlushDataL());
  3095 		TRACERET1(UTF::EBorder, UTraceModuleFileSys::ECFileCBFlushDataLRet, EF32TraceUidFileSys, r);
  3096 
  3097 		if(r!=KErrNone)
  3098 			return(r);
  3099 		}
  3100 
  3101 	RFileClamp clamp;
  3102 	r=aRequest->Drive()->ClampFile(aRequest->Src().FullName().Mid(2),
  3103 									(TAny*)(&clamp));
  3104 	// Write clamp information to user
  3105 	TPckgC<RFileClamp> pkClamp(clamp);
  3106 	aRequest->WriteL(KMsgPtr0, pkClamp);
  3107 	return r;
  3108 	}
  3109 
  3110 
  3111 TInt TFsUnclamp::Initialise(CFsRequest* aRequest)
  3112 //
  3113 // Initialise function for RFs::Unclamp [EFsUnclamp]
  3114 //
  3115 	{
  3116 	TSecureId aUID = aRequest->Message().SecureId();	
  3117     if (aUID!=KEstartUidValue && aUID!=KFileServerUidValue)
  3118 		{
  3119 		SSecurityInfo info;
  3120 		info.iVendorId=0;
  3121 		info.iCaps.iCaps[0]=0;
  3122 		info.iCaps.iCaps[1]=0;
  3123 		info.iSecureId=KEstartUidValue;
  3124 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
  3125 		info.iSecureId=KFileServerUidValue;
  3126 		PlatSec::PolicyCheckFail(aRequest->Message(),info,"File Unclamp");
  3127 		return KErrPermissionDenied;
  3128 		}
  3129 	RFileClamp clamp;
  3130 	TPckg<RFileClamp> pkClamp(clamp);
  3131 	aRequest->ReadL(KMsgPtr0, pkClamp);
  3132 	TInt driveNo=(I64HIGH(clamp.iCookie[1]));
  3133 	TDrive& drive=TheDrives[driveNo];
  3134 	aRequest->SetDrive(&drive);
  3135 	return KErrNone;
  3136 	}
  3137 
  3138 
  3139 TInt TFsUnclamp::DoRequestL(CFsRequest* aRequest)
  3140 //
  3141 // Request function for RFs::Unclamp [EFsUnclamp]
  3142 //
  3143 	{
  3144 	RFileClamp clamp;
  3145 	TPckg<RFileClamp> pkClamp(clamp);
  3146 	aRequest->ReadL(KMsgPtr0, pkClamp);
  3147 	TDrive* drive=aRequest->Drive();
  3148 	CMountCB* mount=(CMountCB*)&(drive->CurrentMount());
  3149 	return(drive->UnclampFile(mount,&clamp));
  3150 	}
  3151 
  3152 CMountBody::CMountBody(CMountCB* aMountCB, CMountCB::MFileAccessor* aFileAccessor, CMountCB::MFileExtendedInterface* aFileInterface)
  3153 //
  3154 // Constructor for private body class
  3155 //
  3156   : iMountCB(aMountCB),
  3157 	iFileAccessor(aFileAccessor?aFileAccessor:this),
  3158 	iFileExtendedInterface(aFileInterface?aFileInterface:this)
  3159 	{
  3160 	}
  3161 
  3162 CMountBody::~CMountBody()
  3163 //
  3164 // Destructor for private body class
  3165 //
  3166 	{
  3167 	__ASSERT_DEBUG(iClampIdentifiers.Count() == 0, User::Invariant());
  3168 	iClampIdentifiers.Close();
  3169 	}
  3170 
  3171 TInt CMountBody::ClampFile(const TInt aDriveNo,const TDesC& aName,TAny* aHandle)
  3172 	{
  3173 	// Need CMountCB::MFileAccessor interface support
  3174 	if(iFileAccessor==this)
  3175 		return KErrNotSupported;
  3176 
  3177 	// Get unique identifier for the file
  3178 	TInt64 uniqueId = 0;
  3179 	TInt r = iFileAccessor->GetFileUniqueId(aName,uniqueId);
  3180 	if(r!=KErrNone)
  3181 			return r;
  3182 
  3183 	// Populate the RFileClamp clamp instance and store it in iClampIdentifiers
  3184 	RFileClamp* newClamp = (RFileClamp*)aHandle;
  3185 	newClamp->iCookie[0]=uniqueId;
  3186 	newClamp->iCookie[1]=MAKE_TINT64(aDriveNo,++iClampCount);
  3187 	r = iClampIdentifiers.InsertInOrder((const RFileClamp&)*newClamp,&CompareClampsByIdAndCount);
  3188 	if(r != KErrNone)
  3189 		return r;
  3190 
  3191 	// Indicate that (at least) one file is clamped on this drive
  3192 	iMountCB->Drive().SetClampFlag(ETrue);
  3193 	AddResource(*iMountCB);
  3194 	return KErrNone;
  3195 	}
  3196 
  3197 
  3198 TInt CMountBody::UnclampFile(RFileClamp* aHandle)
  3199 	{
  3200 	// Need CMountCB::MFileAccessor interface support
  3201 	if(iFileAccessor==this)
  3202 		return KErrNotSupported;
  3203 
  3204 	TInt idx;
  3205 	if((idx = iClampIdentifiers.Find((const RFileClamp&)*aHandle,&FindClampByIdAndCount)) < KErrNone)
  3206 		{
  3207 		// This file is not 'clamped'
  3208 		return idx;
  3209 		}
  3210 
  3211 	// If we're removing the last clamp and a dismount has been deferred (due to files being clamped),
  3212 	// then DeferredDismount() will trigger a dismount: before this happens we need to flush all
  3213 	// dirty data on this drive; 
  3214 	TDrive& drive = iMountCB->Drive();
  3215 	TInt noOfClamps = NoOfClamps();
  3216 	if (noOfClamps == 1 && drive.DismountDeferred())
  3217 		{
  3218 		TInt r = drive.FlushCachedFileInfo(ETrue);
  3219 		if (r == CFsRequest::EReqActionBusy)
  3220 			return r;
  3221 		}
  3222 
  3223 	RemoveResource(*iMountCB);
  3224 	iClampIdentifiers.Remove(idx);
  3225 
  3226 	TInt r = KErrNone;
  3227 	// If this was the last clamp, check for outstanding dismount requests
  3228 	if (noOfClamps == 1)
  3229 		{
  3230 		ASSERT(NoOfClamps() == 0);
  3231 		drive.SetClampFlag(EFalse);
  3232 		if (drive.DismountDeferred())
  3233 			r = drive.DeferredDismount();
  3234 		}
  3235 
  3236 	return r;
  3237 	}
  3238 
  3239 
  3240 TInt CMountBody::IsFileClamped(const TInt64 aUniqueId)
  3241 	{
  3242 	// Need CMountCB::MFileAccessor interface support
  3243 	if(iFileAccessor==this)
  3244 		return KErrNotSupported;
  3245 
  3246 	// Encapsulate the unique identifier in an appropriate class
  3247 	RFileClamp newClamp;
  3248 	newClamp.iCookie[0]=aUniqueId;
  3249 	// Search for (any) entry in iClampIdentifiers holding this value
  3250 	TInt index=iClampIdentifiers.Find((const RFileClamp&)newClamp,&FindClampById);
  3251 	return (index==KErrNotFound?0:1);
  3252 	}
  3253 
  3254 TInt CMountBody::NoOfClamps()
  3255 	{
  3256 	// Need CMountCB::MFileAccessor interface support
  3257 	if(iFileAccessor==this)
  3258 		return KErrNotSupported;
  3259 
  3260 	// This will return zero if ClampFile has not previously been invoked
  3261 	return iClampIdentifiers.Count();
  3262 	}
  3263 
  3264 TInt CMountBody::CompareClampsById(const RFileClamp& aClampA, const RFileClamp& aClampB)
  3265 	{
  3266 	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return 1;
  3267 	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return -1;
  3268 	return 0;
  3269 	}
  3270 
  3271 TInt CMountBody::CompareClampsByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
  3272 	{
  3273 	if(aClampA.iCookie[0] > aClampB.iCookie[0]) return 1;
  3274 	if(aClampA.iCookie[0] < aClampB.iCookie[0]) return -1;
  3275 	// Now compare the count values
  3276 	if(I64LOW(aClampA.iCookie[1]) > I64LOW(aClampB.iCookie[1])) return 1;
  3277 	if(I64LOW(aClampA.iCookie[1]) < I64LOW(aClampB.iCookie[1])) return -1;
  3278 	return 0;
  3279 	}
  3280 
  3281 TInt CMountBody::FindClampById(const RFileClamp& aClampA, const RFileClamp& aClampB)
  3282 	{
  3283 	return (TInt)(!CompareClampsById(aClampA, aClampB));
  3284 	}
  3285 
  3286 
  3287 TInt CMountBody::FindClampByIdAndCount(const RFileClamp& aClampA, const RFileClamp& aClampB)
  3288 	{
  3289 	return (TInt)(!CompareClampsByIdAndCount(aClampA, aClampB));
  3290 	}
  3291 
  3292 void CMountBody::SetProxyDriveDismounted()
  3293 	{
  3294 	iProxyDriveDismounted = ETrue;
  3295 	}
  3296 
  3297 TBool CMountBody::ProxyDriveDismounted()
  3298 	{
  3299 	return iProxyDriveDismounted;
  3300 	}
  3301 
  3302 
  3303 TInt CMountBody::GetFileUniqueId(const TDesC& /*aName*/, TInt64& /*aUniqueId*/)
  3304 	{
  3305 	return KErrNotSupported;
  3306 	}
  3307 TInt CMountBody::Spare3(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
  3308 	{
  3309 	return KErrNotSupported;
  3310 	}
  3311 TInt CMountBody::Spare2(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
  3312 	{
  3313 	return KErrNotSupported;
  3314 	}
  3315 TInt CMountBody::Spare1(TInt /*aVal*/, TAny* /*aPtr1*/, TAny* /*aPtr2*/)
  3316 	{
  3317 	return KErrNotSupported;
  3318 	}
  3319 void CMountBody::ReadSection64L(const TDesC& aName,TInt64 aPos,TAny* aTrg,TInt aLength,const RMessagePtr2& aMessage)
  3320 	{
  3321 	if((TUint64)aPos > KMaxLegacyFileSize)
  3322 		User::Leave(KErrNotSupported);
  3323 
  3324 	iMountCB->ReadSectionL(aName, I64LOW(aPos), aTrg, aLength, aMessage);
  3325 	}
  3326 
  3327 TBool CFileBody::ExtendedFileInterfaceSupported()
  3328 	{
  3329 	return (iExtendedFileInterface==this) ? (TBool)EFalse : (TBool)ETrue;
  3330 	}
  3331 
  3332 // default implementations of MExtendedFileInterface
  3333 void CFileBody::ReadL(TInt64 aPos,TInt& aLength,TDes8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
  3334 	{
  3335 	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
  3336 		User::Leave(KErrNotSupported);
  3337 
  3338 	iFileCB->ReadL((TInt) aPos, aLength, aDes, aMessage);
  3339 	}
  3340 
  3341 void CFileBody::WriteL(TInt64 aPos,TInt& aLength,const TDesC8* aDes,const RMessagePtr2& aMessage, TInt aOffset)
  3342 	{
  3343 	if ((TUint64)aPos > KMaxLegacyFileSize || aOffset > 0)
  3344 		User::Leave(KErrNotSupported);
  3345 
  3346 	iFileCB->WriteL((TInt) aPos, aLength, aDes, aMessage);
  3347 	}
  3348 
  3349 void CFileBody::SetSizeL(TInt64 aSize)
  3350 	{
  3351 	if ((TUint64)aSize > KMaxLegacyFileSize)
  3352 		User::Leave(KErrNotSupported);
  3353 
  3354 	iFileCB->SetSizeL((TInt) aSize);
  3355 	}
  3356 
  3357 //---------------------------------------------------------------------------------------------------------------------
  3358 /**
  3359     This method allows file system to set maximum file size it supports.
  3360     This can be called on instantiation of the CFileCB derived class object by the file system implementation.
  3361     If this method is not called, the iMaxSupportedFileSize will have default value KMaxTUint64
  3362 
  3363     @param aMaxFileSize maximum file size supported by file system
  3364 */
  3365 EXPORT_C void CFileCB::SetMaxSupportedSize(TUint64 aMaxFileSize)
  3366     {
  3367     iBody->iMaxSupportedFileSize = aMaxFileSize;    
  3368     }
  3369 
  3370 /**
  3371     @return maximum supported file size (depends on the file system created it)
  3372 */
  3373 TUint64 CFileCB::MaxSupportedSize(void) const
  3374     {
  3375     return iBody->iMaxSupportedFileSize;
  3376     }
  3377 
  3378 //---------------------------------------------------------------------------------------------------------------------
  3379 
  3380 /**
  3381 Gets the size of the file.
  3382 
  3383 This is 64-bit variant for CFileCB::Size().
  3384 This shall be used by File Systems supporting file size > 4GB - 1 to query the file size 
  3385 inplace of CFileCB::Size() or CFileCB::iSize.
  3386 
  3387 @see CFileCB::iSize
  3388 @see CFileCB::Size() 
  3389 
  3390 @prototype
  3391 
  3392 @return The size of the file.
  3393 */
  3394 EXPORT_C TInt64 CFileCB::Size64() const
  3395 	{
  3396 	__ASSERT_DEBUG(iBody != NULL, Fault(EFileBodyIsNull));
  3397 	const TInt64 size = MAKE_TINT64(iBody->iSizeHigh,iSize);
  3398 	return size;
  3399 	}
  3400 
  3401 //---------------------------------------------------------------------------------------------------------------------
  3402 /**
  3403 Sets the size of the file.
  3404 
  3405 This is 64-bit variant for CFileCB::SetSize().
  3406 This should be used by File Systems supporting file size > 4GB - 1 to set the file size 
  3407 inplace of CFileCB::SetSize() or CFileCB::iSize.
  3408 
  3409 @see CFileCB::iSize
  3410 @see CFileCB::SetSize() 
  3411 
  3412 @prototype
  3413 
  3414 @param aSize The size of the file.
  3415 @param aDriveLocked The status of the Drive Lock. If it is EFalse,
  3416 the file size shall be modified after acquiring the iLock mutex and if it is ETrue, 
  3417 the file size shall be modified without aquiring the iLock mutex.  
  3418 */
  3419 EXPORT_C void CFileCB::SetSize64(TInt64 aSize, TBool aDriveLocked)
  3420 	{
  3421 	if(aDriveLocked)
  3422 		{
  3423 		iSize = (TInt)I64LOW(aSize);
  3424 		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
  3425 		}
  3426 	else
  3427 		{
  3428 		Drive().Lock();
  3429 		iSize = (TInt)I64LOW(aSize);
  3430 		iBody->iSizeHigh = (TInt)I64HIGH(aSize);
  3431 		Drive().UnLock();
  3432 		}
  3433 	}
  3434 
  3435 
  3436 /** used to organize key comparison for the TFileShareLock*/
  3437 TInt LockOrder(const TFileShareLock& aMatch, const TFileShareLock& anEntry)
  3438 	{
  3439 
  3440 	if(aMatch.PosLow() > anEntry.PosLow())
  3441 		return 1;
  3442 	else if(aMatch.PosLow() < anEntry.PosLow())
  3443 		return -1;
  3444 	else
  3445 		return 0;
  3446    
  3447     }
  3448 
  3449 //---------------------------------------------------------------------------------------------------------------------
  3450 /**
  3451     Find a lock inclusive of aPosLow to aPosHigh.
  3452 */
  3453 TInt CFileCB::FindLock64(TInt64 aPosLow, TInt64 aPosHigh)
  3454     {
  3455 
  3456 	const TInt count=FileLocks().Count();
  3457 	for (TInt i=0; i<count; i++)
  3458 		{
  3459             
  3460             const TFileShareLock& lock=FileLocks()[i];
  3461 
  3462             if(lock.PosLow() > (TUint64)aPosHigh)
  3463                 return KErrNotFound;
  3464 
  3465             if(lock.MatchByPos(aPosLow, aPosHigh))
  3466                 return i;
  3467 		}
  3468 
  3469 	return KErrNotFound;
  3470 	}
  3471 
  3472 //---------------------------------------------------------------------------------------------------------------------
  3473 /**
  3474     Add a lock on a range.
  3475 */
  3476 TInt CFileCB::AddLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
  3477 	{
  3478 	const TUint64 posHigh=aPos+aLength-1;
  3479 	
  3480         
  3481         {//-- Lock overflow check
  3482         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
  3483 	    if(posHigh > KMaxFileSize)
  3484                 return KErrArgument;
  3485         }
  3486     
  3487     
  3488     TInt r=CheckLock64(NULL, aPos, aLength);
  3489 	if (r!=KErrNone)
  3490 		return r;
  3491 	
  3492     TFileShareLock lock(aFileShare, aPos, posHigh);
  3493 
  3494     TLinearOrder<TFileShareLock> lockOrder(LockOrder);
  3495 	r=FileLocks().InsertInOrder(lock, lockOrder);
  3496 	__ASSERT_ALWAYS(r!=KErrAlreadyExists,Fault(EFileDuplicateLock));
  3497 	
  3498     return r;
  3499 	}
  3500 
  3501 //---------------------------------------------------------------------------------------------------------------------
  3502 /**
  3503     Remove a lock on a range.
  3504 */
  3505 TInt CFileCB::RemoveLock64(CFileShare* aFileShare, TInt64 aPos, TInt64 aLength)
  3506 	{
  3507 	const TUint64 posHigh = aPos+aLength-1;
  3508 
  3509         {//-- Lock overflow check
  3510         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
  3511 	    if(posHigh > KMaxFileSize)
  3512                 return KErrArgument;
  3513         }
  3514     
  3515 	const TInt pos=FindLock64(aPos, posHigh);
  3516 	if (pos==KErrNotFound)
  3517 		return KErrNotFound;
  3518 	
  3519     const TFileShareLock& lock=FileLocks()[pos];
  3520     if (!lock.MatchOwner(aFileShare) || lock.PosLow() != (TUint64)aPos || lock.PosHigh() != posHigh)
  3521 		return KErrNotFound;
  3522 	
  3523    
  3524     FileLocks().Remove(pos);
  3525 
  3526 	return KErrNone;
  3527 	}
  3528 
  3529 //---------------------------------------------------------------------------------------------------------------------
  3530 /** 
  3531     Check if a range is available.
  3532     @param  aFileShare pointer to FileShare object. NULL only when is called from CFileCB::AddLock64()
  3533 
  3534 */
  3535 TInt CFileCB::CheckLock64(CFileShare* aFileShare,TInt64 aPos,TInt64 aLength)
  3536 	{
  3537 	const TUint64 posHigh=aPos+aLength-1;
  3538 	
  3539     //-- Lock overflow check. It is OK to have a lock that is beyond the real file size.
  3540     //-- if aFileShare == NULL, this is the call from AddLock64 and the position is already checked.
  3541     if(aFileShare)
  3542         {
  3543         const TUint64 KMaxFileSize = aFileShare->IsFileModeBig() ? MaxSupportedSize() : KMaxLegacyFileSize;
  3544 	    if(posHigh > KMaxFileSize)
  3545             return KErrNone; //-- OK, there can't be any locks beyond the max. supported file length
  3546         }
  3547 
  3548 
  3549 	TInt lockIdx=FindLock64(aPos, posHigh);
  3550 	if (lockIdx == KErrNotFound)
  3551 		return KErrNone;
  3552 
  3553     const TInt count=FileLocks().Count();
  3554 	const TFileShareLock* lock=(&FileLocks()[lockIdx]);
  3555 
  3556 	for(;;)
  3557 		{
  3558 		if (!lock->MatchOwner(aFileShare))
  3559 			return KErrLocked;
  3560 
  3561 		if (lock->PosHigh() >= posHigh)
  3562 			break;
  3563 		
  3564         lockIdx++;
  3565 		if (lockIdx >= count)
  3566 			break;
  3567 
  3568 		lock=&FileLocks()[lockIdx];
  3569 		
  3570         if (posHigh < lock->PosLow())
  3571 			break;
  3572 		}
  3573 
  3574     return KErrNone;
  3575 	}
  3576 
  3577 
  3578 //#####################################################################################################################
  3579 //#  TFileShareLock class implementation
  3580 //#####################################################################################################################
  3581 
  3582 TFileShareLock::TFileShareLock(const CFileShare* aOwner, TUint64 aPosLow, TUint64 aPosHigh) 
  3583                : iOwner(aOwner), iPosLow(aPosLow), iPosHigh(aPosHigh) 
  3584     {
  3585     }
  3586 
  3587 
  3588    
  3589 TUint64 TFileShareLock::PosLow()  const 
  3590     {
  3591     return iPosLow;
  3592     }
  3593 
  3594 
  3595 TUint64 TFileShareLock::PosHigh() const 
  3596     {
  3597     return iPosHigh;
  3598     }
  3599 
  3600 TBool TFileShareLock::MatchOwner(const CFileShare* aShare) const 
  3601     {
  3602     return (aShare == iOwner);
  3603     }
  3604 
  3605 /**
  3606     @return ETrue if aPosLow and PosHigh match the lock boundaries
  3607 */
  3608 TBool TFileShareLock::MatchByPos(TUint64 aPosLow, TUint64 aPosHigh) const
  3609     {
  3610         if(PosLow() > aPosHigh)
  3611             return EFalse;
  3612 
  3613 		if ((aPosLow  >= PosLow() && aPosLow   <= PosHigh()) ||
  3614 			(aPosHigh >= PosLow() && aPosHigh  <= PosHigh()) ||
  3615 			(aPosLow  <= PosLow() && aPosHigh  >= PosHigh() ))
  3616 			{
  3617 			return ETrue;
  3618 			}
  3619 
  3620          return EFalse;
  3621     }
  3622 
  3623 
  3624 
  3625 
  3626 
  3627 
  3628 
  3629 
  3630 
  3631 
  3632 
  3633 
  3634 
  3635 
  3636