userlibandfileserver/fileserver/sfile/sf_utl.cpp
changeset 0 a41df078684a
child 117 5b5d147c7838
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/userlibandfileserver/fileserver/sfile/sf_utl.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1144 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32\sfile\sf_utl.cpp
+// 
+//
+
+#include "sf_std.h"
+#include <hal.h>
+#include <collate.h>
+
+const TInt KLog2BufGranularity=4; // 2^5 == 32
+
+TBool ComparePaths(const TDesC& aPath1,const TDesC& aPath2)
+//
+// Return ETrue if the paths are identical
+// To catch case "\\F32.\\GROUP\\" == "\\F32\\GROUP\\"
+//
+  	{
+  
+  	TPtrC entry1(NULL,0);
+  	TPtrC entry2(NULL,0);
+  	TInt pos1=0;
+  	TInt pos2=0;
+  
+  	do {
+  		NextInPath(aPath1,entry1,pos1);
+  		NextInPath(aPath2,entry2,pos2);
+  		if (entry1.MatchF(entry2)==KErrNotFound)
+  			return(EFalse);
+  		} while (entry1.Length() && entry2.Length());
+  	
+  	return(ETrue);
+	}
+
+TBool CompareResource(const TDesC & aThePath)
+//
+//compare function for the Resource path true for match
+//
+	{
+	TInt pathLen = aThePath.Length();
+	if(pathLen < KResourceLength)	
+		return EFalse;
+	//if not word aligned then no less efficient than treating as TUint16 
+	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
+	if( (*path32 & 0xFFDFFFFF) != 0x0052005c)			//	'/R' 
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00530045)			// 'ES'
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x0055004F)			// 'OU'
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00430052)			// 'RC'
+		return EFalse;
+	path32++;
+	if(pathLen > KResourceLength)
+		{
+		if( (*path32 & 0xFFFFFFDF) != 0x005c0045)			// 'E/'
+			return EFalse;
+		}
+	else
+		{
+		if( (*path32 & 0x0000FFDF) != 0x00000045)			// 'E'
+			return EFalse;
+		}
+
+	return ETrue;
+	}
+
+TBool CompareSystem(const TDesC & aThePath) 
+//
+//compare function for the system path true for match
+//
+	{
+	TInt pathLen = aThePath.Length();
+	if(pathLen < KSystemLength)	
+		return EFalse;
+	//if not word aligned then no less efficient than treating as TUint16 
+	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
+	if( (*path32 & 0xFFDFFFFF) != 0x0053005c)			//	'/S' 
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00530059)			// 'YS
+		return EFalse;
+	if(pathLen == KSystemLength)
+		return ETrue;
+	path32++;
+	if( (*path32 & 0x0000FFFF) != 0x0000005c)			// '/'
+		return EFalse;
+
+	return ETrue;
+	}
+
+TBool ComparePrivate(const TDesC & aThePath) 
+//
+//compare function to compare if private path being accessed true for match
+//
+	{
+	TInt pathLen = aThePath.Length();
+	if(pathLen < KPrivateLength)	
+		return EFalse;
+	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
+
+	if((*path32 & 0xFFDFFFFF) != 0x0050005c)			//	'/P' 
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00490052)			// 'RI
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00410056)			// 'VA'
+		return EFalse;
+	path32++;
+	if( (*path32 & 0xFFDFFFDF) != 0x00450054)			// 'TE'
+		return EFalse;
+	if(pathLen == KPrivateLength)
+		return ETrue;
+	path32++;
+	if( (*path32 & 0x0000FFFF) != 0x0000005c)			// '/'
+		return EFalse;
+
+	return ETrue;
+	}
+
+TBool SIDCheck(CFsRequest* aRequest, const TDesC& aThePath)
+//
+//	Compare the Private/XXXXXXXX/ portion of a path be accessed to make sure it matches the process SID 
+//
+	{
+	if(aThePath.Length() >= KPrivateLengthCheck)
+		{
+		TSecureId appUID = aRequest->Message().SecureId();
+		TBuf<KSIDLength+1> dirName;
+		dirName.AppendNumFixedWidth(appUID.iId, EHex, 8);
+	
+		TInt match = dirName.CompareF(aThePath.Mid(KSIDPathOffset,KPrivateLength));
+		if(match==KErrNone)
+			return ETrue;
+		else
+			return EFalse;
+		}
+	
+	return EFalse;
+	}
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const TSecurityPolicy* aROCap, const char* aDiag)
+#else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const TSecurityPolicy* aROCap, OnlyCreateWithNull /*aDiag*/)
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+//
+//	Compare the parsed path with protected path names path must be parsed b4 using
+//
+	{
+
+	if(aRequest->Message().Handle() == KLocalMessageHandle)
+		return KErrNone;
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+#ifdef _DEBUG
+	TBuf8<512> diagmsg;
+	TInt len = aThePath.Length();
+	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
+	diagmsg.Collapse();
+	diagmsg.SetLength(len);
+	diagmsg.Append(_L(" Used to call: "));
+	len = User::StringLength((const TUint8*)aDiag);
+	diagmsg.Append((TUint8*)aDiag, len);
+	const char* const diagout = (char*)diagmsg.PtrZ();
+#else //!_DEBUG
+	const char* const diagout = aDiag;
+#endif //_DEBUG
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+
+	if(ComparePrivate(aThePath))
+		{	
+		if(SIDCheck(aRequest, aThePath))
+			return KErrNone;	
+		else
+			{
+			if(aPriCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+				return KErrNone;
+			else
+				return KErrPermissionDenied;
+			}
+		}
+	else if(CompareSystem(aThePath))
+		{
+		if(aSysCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+			return KErrNone;
+		else
+			return KErrPermissionDenied;
+		}
+	else if(CompareResource(aThePath))
+		{
+		if(aROCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+			return KErrNone;
+		else
+			return KErrPermissionDenied;
+		}
+	else
+		return KErrNone;
+ 	}
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const char* aDiag) 
+#else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, OnlyCreateWithNull /*aDiag*/) 
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+//
+//	Compare the parsed path with protected path names path must be parsed b4 using
+//
+	{
+
+	if(aRequest->Message().Handle() == KLocalMessageHandle)
+		return KErrNone;
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+#ifdef _DEBUG
+	TBuf8<512> diagmsg;
+	TInt len = aThePath.Length();
+	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
+	diagmsg.Collapse();
+	diagmsg.SetLength(len);
+	diagmsg.Append(_L(" Used to call: "));
+	len = User::StringLength((const TUint8*)aDiag);
+	diagmsg.Append((TUint8*)aDiag, len);
+	const char* const diagout = (char*)diagmsg.PtrZ();
+#else //!_DEBUG	
+	const char* const diagout = aDiag;
+#endif //_DEBUG
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+
+	if(ComparePrivate(aThePath))
+		{	
+		if(SIDCheck(aRequest, aThePath))
+			return KErrNone;	
+		else
+			{
+			if(aPriCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+				return KErrNone;
+			else
+				return KErrPermissionDenied;
+			}
+		}
+	else if(CompareSystem(aThePath))
+		{
+		if(aSysCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+			return KErrNone;
+		else
+			return KErrPermissionDenied;
+		}
+	else
+		return KErrNone;
+ 	}
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aCap, const char* aDiag, TBool aExactMatchAllowed) 
+#else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aCap, OnlyCreateWithNull /*aDiag*/, TBool aExactMatchAllowed) 
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+//
+//	Compare the parsed path with protected path names path must be parsed b4 using
+//
+	{
+
+	if(aRequest->Message().Handle() == KLocalMessageHandle)
+		return KErrNone;
+
+#ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+#ifdef _DEBUG
+	TBuf8<512> diagmsg;
+	TInt len = aThePath.Length();
+	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
+	diagmsg.Collapse();
+	diagmsg.SetLength(len);
+	diagmsg.Append(_L(" Used to call: "));
+	len = User::StringLength((const TUint8*)aDiag);
+	diagmsg.Append((TUint8*)aDiag, len);
+	const char* const diagout = (char*)diagmsg.PtrZ();
+#else //!_DEBUG	
+	const char* const diagout = aDiag;
+#endif //_DEBUG
+#endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
+
+	if(ComparePrivate(aThePath))
+		{	
+		if(SIDCheck(aRequest, aThePath))
+			return KErrNone;	
+		else
+			{
+			if(aCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+				return KErrNone;
+			else if (aExactMatchAllowed && aThePath.Length() <= KPrivateLength + 1)
+				return KErrNone;
+			else
+				return KErrPermissionDenied;
+			}
+		}
+	else if(CompareSystem(aThePath))
+		{
+		if(aCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
+			return KErrNone;
+		else if (aExactMatchAllowed && aThePath.Length() <= KSystemLength + 1)
+			return KErrNone;
+		else
+			return KErrPermissionDenied;
+		}
+	else
+		return KErrNone;
+	
+	}
+
+
+
+
+void Fault(TFsFault aFault)
+//
+// Fault the file server.
+//
+	{
+
+	__PRINT1(_L("FAULT: TFsFault %d"),aFault);
+	User::Panic(_L("Fserv fault"),aFault);
+	}
+
+/**
+    Get Ptr() from the client and parse it. Allow wild cards.
+    Then get the drive and if the drive is substed get the real name.
+    
+    @param  aP          	message parameter number
+    @param  aRequest    	pointer to the reques object
+    @param  aParse      	parser
+    @param  aUseSessionPath flag specifying whether the session path is to be
+     						used for parsing or not. Default value is ETrue meaning
+     						that the session path is used while parsing.
+
+    @return     system-wide error code.
+*/
+TInt ParseSubst(const TInt aP, CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
+	{
+	__ASSERT_DEBUG(aRequest->Session(),Fault(EParseSubstSession));
+	
+	//-- check the length of the name, passed by client.
+	//-- it shall not be longer than KMaxFileName
+	TInt nameLen=aRequest->GetDesLength(aP);
+	if(nameLen < 0 || nameLen > KMaxFileName)
+	    return KErrBadName;
+	
+	TFileName n;
+	TRAPD(r, aRequest->ReadL(aP,n));
+	
+	if(r==KErrNone)
+		{
+		if(aUseSessionPath)
+			r=aParse.Set(n,NULL,&aRequest->Session()->Path());
+		else
+			r=aParse.Set(n,NULL,NULL);
+		}
+	if (r!=KErrNone)
+		return(r);
+	if(!aUseSessionPath && !aParse.DrivePresent())
+		return(r);
+	TInt drive;
+	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
+		return(r);
+	aRequest->SetDrive(&TheDrives[drive]);
+	if (aRequest->Drive()->Att()&KDriveAttSubsted)
+		{
+		if ((aRequest->Drive()->Subst().Length()+aParse.FullName().Length())>(KMaxFileName+3))
+			return(KErrBadName);
+		aRequest->SetSubstedDrive(aRequest->Drive());
+		// and now set aParse with the full path name
+		n=aRequest->Drive()->Subst().Mid(2);
+		n+=aParse.FullName().Mid(3);
+		TFileName n2=aRequest->SubstedDrive()->Subst().Left(2);
+		r=aParse.Set(n,NULL,&n2);
+		if(r!=KErrNone)
+			return(r);
+		aRequest->SetDrive(&aRequest->Drive()->SubstedDrive());
+		}
+	return(KErrNone);
+	}
+
+
+TInt ParseSubstPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
+//
+// Get Ptr0() from the client and parse it. Allow wild cards.
+// Then get the drive and if the drive is substed get the real name.
+//
+	{
+
+	return(ParseSubst(KMsgPtr0,aRequest,aParse,aUseSessionPath));
+	}
+
+TInt ParseNoWildSubstPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
+//
+// Get Ptr0() from the client and parse it. Dis-allow wild cards.
+// Then get the drive and if the drive is substed get the real name.
+//
+	{
+	TInt r=ParseSubst(KMsgPtr0,aRequest,aParse,aUseSessionPath);
+	if (r!=KErrNone)
+		return(r);	//	Returns KErrBadName if "/" in the name or length > 256 chars
+	
+	if (aParse.IsWild())	//	No *s or ?s allowed in the file name
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+
+TInt ParseNoWildSubstPtr1(CFsRequest* aRequest,TParse& aParse)
+//
+// Get Ptr0() from the client and parse it. Dis-allow wild cards.
+// Then get the drive and if the drive is substed get the real name.
+//
+	{
+	TInt r=ParseSubst(KMsgPtr1, aRequest, aParse);
+	if (r!=KErrNone)
+		return(r);	//	Returns KErrBadName if "/" in the name or length > 256 chars
+	
+	if (aParse.IsWild())	//	No *s or ?s allowed in the file name
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+
+TInt ParseNoWildSubstCheckPathPtr0(CFsRequest* aRequest,TParse& aParse)
+//
+// Get Ptr0() from the client and parse it.
+// Then get the drive and if the drive is substed get the real name.
+// Dis-allow wild cards and the root directory
+//
+	{
+
+	TInt r=ParseSubst(KMsgPtr0,aRequest,aParse);
+	if (r!=KErrNone)
+		return(r);
+	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+TInt ParseNoWildSubstCheckPathPtr1(CFsRequest* aRequest,TParse& aParse)
+//
+// Get Ptr1() from the client and parse it.
+// Then get the drive and if the drive is substed get the real name.
+// Dis-allow wild cards and the root directory
+//
+	{
+
+	TInt r=ParseSubst(KMsgPtr1,aRequest,aParse);
+	if (r!=KErrNone)
+		return(r);
+	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
+		return(KErrBadName);
+
+	return(KErrNone);
+	}
+
+TInt ParseNoWildSubstFileCheckPtr1(CFsRequest* aRequest,TParse& aParse)
+//
+// Get Ptr0() from the client and parse it.
+// Then get the drive and if the drive is substed get the real name.
+// Dis-allow wild cards and the root directory
+// Finally check that there is a name or extension.
+	{
+
+	TInt r=ParseSubst(KMsgPtr1,aRequest,aParse);
+	if (r!=KErrNone)
+		return(r);
+	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
+		return(KErrBadName);
+	if(!aParse.NameOrExtPresent())
+	    return (KErrBadName);
+	return(KErrNone);
+	}
+
+TInt ParseNoWildSubstCheckPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
+//
+// Get Ptr0() from the client and parse it. Dis-allow wild cards.
+// Then get the drive and if the drive is substed get the real name.
+// Finally check that there is a name or extension.
+//
+	{
+
+	TInt r=ParseNoWildSubstPtr0(aRequest,aParse, aUseSessionPath);	
+	if (r!=KErrNone)
+		return(r);
+	if (!aParse.NameOrExtPresent())
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+TInt ParseNoWildSubstCheckPtr1(CFsRequest* aRequest,TParse& aParse)
+//
+// Get Ptr1() from the client and parse it. Dis-allow wild cards.
+// Then get the drive and if the drive is substed get the real name.
+// Finally check that there is a name or extension.
+//
+	{
+
+	TInt r=ParseNoWildSubstPtr1(aRequest,aParse);
+	if (r!=KErrNone)
+		return(r);
+	if (!aParse.NameOrExtPresent())
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+/**
+    Get Ptr0() from the client and parse it.
+
+    @param  aRequest    pointer to the reques object
+    @param  aParse      parser
+
+    @return     system-wide error code.
+*/
+TInt ParsePathPtr0(CFsRequest* aRequest,TParse& aParse)
+	{
+	//-- check the length of the name, passed by client.
+	//-- it shall not be longer than KMaxFileName
+	TInt nameLen=aRequest->GetDesLength(KMsgPtr0);
+	if(nameLen < 0 || nameLen > KMaxFileName)
+	    return KErrBadName;
+
+	TFileName n;
+	TRAPD(r,aRequest->ReadL(KMsgPtr0,n));
+	if (r==KErrNone)
+		r=aParse.SetNoWild(n,NULL,&aRequest->Session()->Path());
+	if (r!=KErrNone)
+		return(r);
+	if (aParse.NameOrExtPresent())
+		return(KErrBadName);
+	TInt drive;
+	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
+		return(r);
+	aRequest->SetDrive(&TheDrives[drive]);
+	return(KErrNone);
+	}
+
+
+TInt ParseNotificationPath(CFsRequest* aRequest, TParse& aParse, TDes& aNotifyPath)
+//
+//	Called by Notify Change extended function when client has submitted a path
+//	which contains a wildcarded initial character to represent the drive
+//	This is required when notification over a number of drives is required
+//
+	{
+	if ((aNotifyPath[0]==KMatchAny)||(aNotifyPath[0]==KMatchOne))
+		{
+	//	Use the default session drive for now
+		TFileName sessionDefault=aRequest->Session()->Path();
+		aNotifyPath[0]=sessionDefault[0];
+		}
+
+	TInt r=aParse.Set(aNotifyPath,NULL,&aRequest->Session()->Path());
+	if (r!=KErrNone)
+		return(r);
+	TInt drive;
+	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
+		return(r);
+	aRequest->SetDrive(&TheDrives[drive]);
+	if (aRequest->Drive()->Att()&KDriveAttSubsted)
+		{
+		if ((aRequest->Drive()->Subst().Length()+aParse.FullName().Length())>(KMaxFileName+3))
+			return(KErrBadName);
+		aRequest->SetSubstedDrive(aRequest->Drive());
+		// and now set aParse with the full path name
+		TFileName n=aRequest->Drive()->Subst().Mid(2);
+		n+=aParse.FullName().Mid(3);
+		TFileName n2=aRequest->SubstedDrive()->Subst().Left(2);
+		r=aParse.Set(n,NULL,&n2);
+		if(r!=KErrNone)
+			return(r);
+		aRequest->SetDrive(&aRequest->Drive()->SubstedDrive());
+		}	
+	if (aParse.IsWild())
+		return(KErrBadName);
+	return(KErrNone);
+	}
+
+
+CFsObject* SessionObjectFromHandle(TInt aHandle,TInt aUniqueID, CSessionFs* aSession)
+//
+// Lookup an object from its handle.
+//
+	{
+	if(aUniqueID==0)
+		return(aSession->Handles().At(aHandle,ETrue));
+	else
+		return(aSession->Handles().At(aHandle,aUniqueID,ETrue));
+	}
+
+
+CFileShare* GetShareFromHandle(CSessionFs* aSession, TInt aHandle)
+//
+// Get the share control block from its handle.
+//
+	{
+	return((CFileShare*)(SessionObjectFromHandle(aHandle,FileShares->UniqueID(),aSession)));
+	}
+
+
+//
+// Returns ETrue if aDes only contains spaces or is zero length
+//
+static TBool IsSpace(const TDesC& aDes)
+	{
+
+	TInt len=aDes.Length();
+	if (len==0)
+		return(EFalse);
+	for (TInt i=0;i<len;i++)
+		{
+		TChar txt=aDes[i];
+		if (!txt.IsSpace())
+			return(EFalse);
+		}
+	return(ETrue);
+	}
+
+TUint32 CalcNameHash(const TDesC& aName) 
+	{
+	const TUint32 KNameHashCRCInitialiser=0x12345678;
+	TUint32 hash=KNameHashCRCInitialiser;
+	Mem::Crc32(hash, aName.Ptr(), aName.Size());
+	return hash;
+	}
+
+
+TBool TNameChecker::IsIllegal(TText& aChar) const
+//
+// Checks aChar != any of < > : " / |
+// \ is also illegal in a name but will be considered a path delimiter
+//
+	{
+	switch (aChar)
+		{
+	case '<':
+	case '>':
+	case ':':
+	case '"':
+	case '/':
+	case '|':
+	case '\000':
+		return(ETrue);
+	default:
+		break;
+		}
+	return(EFalse);
+	}
+
+
+
+TBool TNameChecker::IsIllegalChar(TText& aChar)
+//	
+//	Checks aName for illegal components and returns the offending character if any
+//	No other parsing is performed
+//
+	{
+	TInt len=iName.Length();
+	while (len--)
+		{
+		if (IsIllegal(iName[len]))// '<', '>', ':', '"', '/', '|' or '\000'?
+			{
+			aChar=iName[len];
+			return(ETrue);
+			}
+		}
+	return(EFalse);
+	}
+
+
+TBool TNameChecker::IsIllegalName()
+//
+// Checks name is not _L(".") or _L("..") and that there are no illegal characters
+//
+	{
+
+	TInt pos=iName.LocateReverse(KPathDelimiter)+1;
+	TPtrC fileName(iName.Ptr()+pos,iName.Length()-pos);
+	SetName(fileName);
+	
+	if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
+		return ETrue;
+	TInt len=iName.Length();
+	
+	while (len--)
+		{
+		if (IsIllegal(iName[len]))	//	'<', '>', ':', '"', '/', '|' or '\000'?
+			return(ETrue);
+		}
+	return(EFalse);
+	}
+
+
+TBool TNameChecker::IsIllegalName(TText& aChar)
+//
+//	Check name and path are legal - if not, return the offending component
+//
+	{
+	TInt r=iParse.Set(iName,NULL,NULL);
+	if (r!=KErrNone)
+		return(ETrue);	//	Checks for names > 256 chars etc
+	
+	SetName(iParse.FullName());
+	if (IsIllegalPath(aChar))
+		return(ETrue);	//	Checks for illegal characters in path
+	
+	TInt nameStart=iParse.FullName().LocateReverse(KPathDelimiter)+1;
+	r=(iParse.FullName().Mid(nameStart)).LocateReverse(KPathDelimiter)+1;
+	TPtrC fileName(iName.Ptr()+r,iName.Length()-r);
+	SetName(fileName);
+
+	if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
+		{
+		aChar=iName[0]; 
+		return ETrue;
+		}
+	
+	return (IsIllegalChar(aChar));
+	}
+
+const TInt KSpace = ' ';
+TBool TNameChecker::IsIllegalPath()
+//
+// Checks the path does not contain wildcards or directories _L(".") or _L("..") or just spaces
+//
+	{
+
+	if (iName.Locate(KMatchOne)!=KErrNotFound || iName.Locate(KMatchAny)!=KErrNotFound)
+		return(ETrue);
+
+	TLex pathLex=iName;
+	FOREVER
+		{
+		pathLex.Inc();
+		if (pathLex.Remainder().Length()==0)
+			break;
+		TInt nextPath=pathLex.Remainder().Locate(KPathDelimiter);
+		if (nextPath==0) // Reject double backslashes
+			return(ETrue);
+		if (nextPath==KErrNotFound)
+			nextPath=pathLex.Remainder().Length();
+		pathLex.Mark();
+		pathLex.Inc(nextPath);
+		SetName(pathLex.MarkedToken());
+		if (IsIllegalName())
+			return(ETrue);
+		// check for tailing dots
+		for(TInt i = pathLex.MarkedToken().Length() - 1; i >= 0; --i)
+			{
+			if (pathLex.MarkedToken()[i] == KExtDelimiter)
+				{
+				return ETrue;
+				}
+			else if (pathLex.MarkedToken()[i] == KSpace)
+				{
+				continue;
+				}
+			else
+				{
+				break;
+				}
+			}
+		}
+	return(EFalse);
+	}
+
+
+TBool TNameChecker::IsIllegalPath(TText& aChar)
+//
+//	Checks the path does not contain wildcards or directories _L(".") or _L("..") or just spaces
+//	Returns the first offending character found (if any)
+//
+	{
+	if (iName.Locate(KMatchOne)!=KErrNotFound)
+		{
+		aChar=KMatchOne;
+		return (ETrue);
+		}
+	if (iName.Locate(KMatchAny)!=KErrNotFound)
+		{
+		aChar=KMatchAny;
+		return (ETrue);
+		}
+
+	TLex pathLex=iName;
+	TFileName name;
+	FOREVER
+		{
+		pathLex.Inc();
+		if (pathLex.Remainder().Length()==0)
+			break;
+		TInt nextPath=pathLex.Remainder().Locate(KPathDelimiter);
+		if (nextPath==0) // Reject double backslashes
+			{
+			aChar=KPathDelimiter; 
+			return ETrue;
+			}	
+		if (nextPath==KErrNotFound)
+			nextPath=pathLex.Remainder().Length();
+		pathLex.Mark();
+		pathLex.Inc(nextPath);
+		name=pathLex.MarkedToken();
+		// check for tailing dots
+		for(TInt i = pathLex.MarkedToken().Length() - 1; i >= 0; --i)
+			{
+			if (pathLex.MarkedToken()[i] == KExtDelimiter)
+				{
+				aChar = KExtDelimiter;
+				return ETrue;
+				}
+			else if (pathLex.MarkedToken()[i] == KSpace)
+				{
+				continue;
+				}
+			else
+				{
+				break;
+				}
+			}
+		TInt pos=name.LocateReverse(KPathDelimiter)+1;
+		TPtrC fileName(name.Ptr()+pos,name.Length()-pos);
+		SetName(fileName);
+		if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
+			{
+			aChar=iName[0]; 
+			return ETrue;
+			}
+		
+		if (IsIllegalChar(aChar))
+			return(ETrue);
+		}
+	
+	return(EFalse);
+	}
+
+
+TBool IsIllegalFullName(const TParse& aParse)
+	{
+	TPtrC ptr=aParse.Path();
+	TNameChecker checker(ptr);
+	if (checker.IsIllegalPath())
+		return(ETrue);	//	Checks for illegal characters in path
+	
+	TInt nameStart=aParse.FullName().LocateReverse(KPathDelimiter)+1;
+	checker.SetName(aParse.FullName().Mid(nameStart));
+	
+	if (checker.IsIllegalName())
+		return(ETrue);	//	Checks illegal characters such as ></|". and ..
+	return(EFalse);
+	}
+
+ TBool IsIllegalFullName(const TDesC& aName)
+//
+// Check name and path are legal
+//
+	{
+	TParse parser;
+	TInt r=parser.Set(aName,NULL,NULL);
+	if (r!=KErrNone)
+		return(ETrue);	//	Checks for wild cards, names>256 chars etc
+	
+	return IsIllegalFullName(parser);
+	}
+
+TBool PowerOk()
+//
+// Check the power is OK
+//
+	{
+
+	TBool powerGood=EFalse;
+	TInt r=HAL::Get(HAL::EPowerGood, powerGood);
+	if (r!=KErrNone)
+		return EFalse;
+	return powerGood;
+	}
+
+void AddResource(CMountCB& aMount)
+//
+// Decrement resource counters
+//
+	{
+	__CHECK_DRIVETHREAD(aMount.Drive().DriveNumber());
+	__ASSERT_DEBUG(aMount.LockStatus()<=0,Fault(ERawDiskBadAccessCount2));
+	aMount.DecLock();
+	}
+
+void RemoveResource(CMountCB& aMount)
+//
+// Increment resource counters
+//
+	{
+	__ASSERT_DEBUG(aMount.LockStatus()<0,Fault(ERawDiskBadAccessCount1));
+	aMount.IncLock();
+	}
+
+
+void AddDiskAccess(CMountCB& aMount)
+//
+// Increment resource counters
+//
+	{
+	aMount.IncLock();
+	}
+
+void RemoveDiskAccess(CMountCB& aMount)
+//
+// Decrement resource counters
+//
+	{
+	aMount.DecLock();
+	}
+
+EXPORT_C void AllocBufferL(HBufC*& aBuf,const TDesC& aName)
+//
+// Alloc or ReAlloc buffer 
+//
+	{
+
+	if (aBuf==NULL)
+		{
+		aBuf=aName.AllocL();
+		return;
+		}
+	if (aBuf->Length()<aName.Length())
+		{
+		TInt bufGranularity=(1<<KLog2BufGranularity);
+		TInt size=((aName.Length()+bufGranularity-1)>>KLog2BufGranularity)<<KLog2BufGranularity;
+		aBuf=aBuf->ReAllocL(size);
+		}
+	aBuf->Des()=aName;
+	}
+
+void NextInPath(const TDesC& aPath,TPtrC& anEntry,TInt& aPos)
+//
+// Returns the next entry in the path
+//
+	{
+	
+	anEntry.Set(NULL,0);
+	if ((aPos+1)>=aPath.Length())
+		return;
+	TPtrC path(aPath.Mid(aPos+1)); // Skip delimiter
+	TInt delimiterPos=path.Locate(KPathDelimiter);
+	if (delimiterPos==KErrNotFound)
+		delimiterPos=aPath.Length()-(aPos+1);
+	if (delimiterPos<=0)
+		return;
+
+	if (path[delimiterPos-1]==KExtDelimiter) // return "F32." as "F32"
+		anEntry.Set(aPath.Mid(aPos+1,delimiterPos-1));
+	else
+		anEntry.Set(aPath.Mid(aPos+1,delimiterPos));
+	aPos+=delimiterPos+1;
+	}
+
+TInt MatchUidType(const TUidType &aMatch, const TUidType &aType)
+//
+// Compare aType against aMatch with KNullUid as a wildcard
+//
+	{
+
+	TUid mu=aMatch[2];
+	TUid tu=aType[2];
+	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
+		return KErrNotSupported;
+	mu=aMatch[1];
+	tu=aType[1];
+	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
+		return KErrNotSupported;
+	mu=aMatch[0];
+	tu=aType[0];
+	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
+		return KErrNotSupported;
+	return KErrNone;
+	}
+
+/**
+ * Compare sections of filenames according to locale-independent rules as well
+ * as locale-dependent rules. This is an attempt to get an ordering where
+ * equivalent names sort together but the overall ordering is culturally
+ * acceptable. Sadly, the ordering it gives is not consistent, and it is not
+ * clear how to make it so. Hence this function is deprecated. The correct way
+ * to do this is to code around it: If you need a sorted array for display that
+ * you also need to search for equivalent filenames, either use a linear search
+ * or keep two arrays, one sorted with CompareF, the other with CompareC.
+ * @deprecated 6.1
+ */
+EXPORT_C TInt CompareFilenames(const TDesC& aFileName1,const TDesC& aFileName2)
+// 
+// Compare filenames. Case is ignored and names are normalised
+// (base+accent is equal to composed character) but spaces
+// and punctuation are significant for determining equality.
+// Whether two filenames are identical is the same in all
+// locales, but the ordering of non-identical filenames is locale-specific.
+//
+//
+	{
+	// Create a non-locale-specific collation method that doesn't ignore spaces and punctuation but folds case.
+	TCollationMethod method;
+	method.iFlags = TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
+	method.iMainTable=NULL;	
+	method.iOverrideTable=NULL;	
+	
+	// Get the non-locale-specific order and return it if the names are equal.
+	TInt base_order = aFileName1.CompareC(aFileName2,3,&method);
+	if (base_order == 0)
+		return base_order;
+
+	// Get the locale-specific order and use it unless it is equality, in which case the non-locale-specific order must be used.
+	TInt locale_order = aFileName1.CompareC(aFileName2);
+	return locale_order ? locale_order : base_order;
+	}
+
+void Get8BitDllName(TDes8& aDllName, const TDesC& aFileName)
+//
+//	Convert a 16 bit name to an 8 bit name
+//	No data loss because UNICODE Dlls are currently restricted to 8 bit names
+//	No effect in 8 bit builds - just sets aDllName to aFileName
+//
+	{
+	aDllName.SetLength(aFileName.Length());
+	aDllName.Copy(aFileName);
+	}								
+
+void Get16BitDllName(TDes& aFileName, const TDesC8& aDllName)
+//
+//	Convert an 8 bit name to a 16 bit name - zero padded automatically
+//	No effect in 8 bit builds - just sets aFileName to aDllName
+//
+	{
+	aFileName.SetLength(aDllName.Length());
+	aFileName.Copy(aDllName);	
+	}								
+
+
+/**
+    Checks that there is sufficient disk space available to complete a task taking into account reserved space
+ 
+    @param  aThreshold amount of required free space, in bytes
+    @param  aRequest
+
+    @return KErrNone        on success and if there are _strictly_more_ than aThreshold bytes available on the volume (taking into account reserved space)
+            KErrDiskFull    on success and if there isn't enough space
+            system-wide error code otherwise
+*/
+TInt CheckDiskSpace(TInt64 aThreshold, CFsRequest* aRequest)
+	{
+    const TInt KReservedSpace = aRequest->Drive()->ReservedSpace();
+    const TInt KDriveNumber = aRequest->Drive()->DriveNumber();
+
+	if(KReservedSpace == 0 || KDriveNumber == EDriveZ)
+	    return KErrNone;
+
+    //-- if the drive has a reserved space, take it into account
+	CSessionFs* session=aRequest->Session(); 
+
+    if(!session || !session->ReservedAccess(KDriveNumber))
+        aThreshold += KReservedSpace;
+
+    //-- ask the corresponding file system if there is aThreshold bytes available.
+    //-- for some reason it's required to be strictly > than aThreshold
+    return aRequest->Drive()->RequestFreeSpaceOnMount(aThreshold+1);
+	}								
+
+
+#if defined(_DEBUG) || defined(_DEBUG_RELEASE)
+EXPORT_C TUint32 DebugRegister() {return(DebugReg);}
+#else
+EXPORT_C TUint32 DebugRegister() {return(0);}
+#endif
+
+CLogon* CLogon::NewL()
+//
+// Create the CLogon active object.
+//
+	{
+
+	CLogon* pL=new(ELeave) CLogon(EPriority);
+	CActiveScheduler::Add(pL);
+	return(pL);
+	}
+
+#pragma warning( disable : 4705 )	// statement has no effect
+CLogon::CLogon(TInt aPriority)
+//
+// Constructor
+//
+	: CActive(aPriority)
+	{
+	}
+#pragma warning( default : 4705 )
+
+TInt CLogon::Logon(RThread aThread)
+//
+// Issue a request to logon to the thread.
+//
+	{
+
+	iThread=aThread;
+	iThread.Logon(iStatus);
+		SetActive();
+	if (iStatus==KErrNoMemory)
+		iThread.Kill(KErrNoMemory);
+	else
+		iThread.Resume();
+	iThread.Close();
+	CActiveScheduler::Start();
+	return(iStatus.Int());
+	}
+
+void CLogon::DoCancel()
+//
+// Cancel a pending event.
+//
+	{
+
+	iThread.LogonCancel(iStatus);
+	}
+
+void CLogon::RunL()
+//
+// Thread has terminated.
+//
+	{
+
+	CActiveScheduler::Stop();
+	}
+