os/kernelhwsrv/userlibandfileserver/fileserver/sfile/sf_utl.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 // f32\sfile\sf_utl.cpp
    15 // 
    16 //
    17 
    18 #include "sf_std.h"
    19 #include <hal.h>
    20 #include <collate.h>
    21 
    22 const TInt KLog2BufGranularity=4; // 2^5 == 32
    23 
    24 TBool ComparePaths(const TDesC& aPath1,const TDesC& aPath2)
    25 //
    26 // Return ETrue if the paths are identical
    27 // To catch case "\\F32.\\GROUP\\" == "\\F32\\GROUP\\"
    28 //
    29   	{
    30   
    31   	TPtrC entry1(NULL,0);
    32   	TPtrC entry2(NULL,0);
    33   	TInt pos1=0;
    34   	TInt pos2=0;
    35   
    36   	do {
    37   		NextInPath(aPath1,entry1,pos1);
    38   		NextInPath(aPath2,entry2,pos2);
    39   		if (entry1.MatchF(entry2)==KErrNotFound)
    40   			return(EFalse);
    41   		} while (entry1.Length() && entry2.Length());
    42   	
    43   	return(ETrue);
    44 	}
    45 
    46 TBool CompareResource(const TDesC & aThePath)
    47 //
    48 //compare function for the Resource path true for match
    49 //
    50 	{
    51 	TInt pathLen = aThePath.Length();
    52 	if(pathLen < KResourceLength)	
    53 		return EFalse;
    54 	//if not word aligned then no less efficient than treating as TUint16 
    55 	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
    56 	if( (*path32 & 0xFFDFFFFF) != 0x0052005c)			//	'/R' 
    57 		return EFalse;
    58 	path32++;
    59 	if( (*path32 & 0xFFDFFFDF) != 0x00530045)			// 'ES'
    60 		return EFalse;
    61 	path32++;
    62 	if( (*path32 & 0xFFDFFFDF) != 0x0055004F)			// 'OU'
    63 		return EFalse;
    64 	path32++;
    65 	if( (*path32 & 0xFFDFFFDF) != 0x00430052)			// 'RC'
    66 		return EFalse;
    67 	path32++;
    68 	if(pathLen > KResourceLength)
    69 		{
    70 		if( (*path32 & 0xFFFFFFDF) != 0x005c0045)			// 'E/'
    71 			return EFalse;
    72 		}
    73 	else
    74 		{
    75 		if( (*path32 & 0x0000FFDF) != 0x00000045)			// 'E'
    76 			return EFalse;
    77 		}
    78 
    79 	return ETrue;
    80 	}
    81 
    82 TBool CompareSystem(const TDesC & aThePath) 
    83 //
    84 //compare function for the system path true for match
    85 //
    86 	{
    87 	TInt pathLen = aThePath.Length();
    88 	if(pathLen < KSystemLength)	
    89 		return EFalse;
    90 	//if not word aligned then no less efficient than treating as TUint16 
    91 	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
    92 	if( (*path32 & 0xFFDFFFFF) != 0x0053005c)			//	'/S' 
    93 		return EFalse;
    94 	path32++;
    95 	if( (*path32 & 0xFFDFFFDF) != 0x00530059)			// 'YS
    96 		return EFalse;
    97 	if(pathLen == KSystemLength)
    98 		return ETrue;
    99 	path32++;
   100 	if( (*path32 & 0x0000FFFF) != 0x0000005c)			// '/'
   101 		return EFalse;
   102 
   103 	return ETrue;
   104 	}
   105 
   106 TBool ComparePrivate(const TDesC & aThePath) 
   107 //
   108 //compare function to compare if private path being accessed true for match
   109 //
   110 	{
   111 	TInt pathLen = aThePath.Length();
   112 	if(pathLen < KPrivateLength)	
   113 		return EFalse;
   114 	const TUint32 * path32 = reinterpret_cast<const TUint32*>(aThePath.Ptr());
   115 
   116 	if((*path32 & 0xFFDFFFFF) != 0x0050005c)			//	'/P' 
   117 		return EFalse;
   118 	path32++;
   119 	if( (*path32 & 0xFFDFFFDF) != 0x00490052)			// 'RI
   120 		return EFalse;
   121 	path32++;
   122 	if( (*path32 & 0xFFDFFFDF) != 0x00410056)			// 'VA'
   123 		return EFalse;
   124 	path32++;
   125 	if( (*path32 & 0xFFDFFFDF) != 0x00450054)			// 'TE'
   126 		return EFalse;
   127 	if(pathLen == KPrivateLength)
   128 		return ETrue;
   129 	path32++;
   130 	if( (*path32 & 0x0000FFFF) != 0x0000005c)			// '/'
   131 		return EFalse;
   132 
   133 	return ETrue;
   134 	}
   135 
   136 TBool SIDCheck(CFsRequest* aRequest, const TDesC& aThePath)
   137 //
   138 //	Compare the Private/XXXXXXXX/ portion of a path be accessed to make sure it matches the process SID 
   139 //
   140 	{
   141 	if(aThePath.Length() >= KPrivateLengthCheck)
   142 		{
   143 		TSecureId appUID = aRequest->Message().SecureId();
   144 		TBuf<KSIDLength+1> dirName;
   145 		dirName.AppendNumFixedWidth(appUID.iId, EHex, 8);
   146 	
   147 		TInt match = dirName.CompareF(aThePath.Mid(KSIDPathOffset,KPrivateLength));
   148 		if(match==KErrNone)
   149 			return ETrue;
   150 		else
   151 			return EFalse;
   152 		}
   153 	
   154 	return EFalse;
   155 	}
   156 
   157 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   158 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const TSecurityPolicy* aROCap, const char* aDiag)
   159 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   160 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const TSecurityPolicy* aROCap, OnlyCreateWithNull /*aDiag*/)
   161 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   162 //
   163 //	Compare the parsed path with protected path names path must be parsed b4 using
   164 //
   165 	{
   166 
   167 	if(aRequest->Message().Handle() == KLocalMessageHandle)
   168 		return KErrNone;
   169 
   170 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   171 #ifdef _DEBUG
   172 	TBuf8<512> diagmsg;
   173 	TInt len = aThePath.Length();
   174 	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
   175 	diagmsg.Collapse();
   176 	diagmsg.SetLength(len);
   177 	diagmsg.Append(_L(" Used to call: "));
   178 	len = User::StringLength((const TUint8*)aDiag);
   179 	diagmsg.Append((TUint8*)aDiag, len);
   180 	const char* const diagout = (char*)diagmsg.PtrZ();
   181 #else //!_DEBUG
   182 	const char* const diagout = aDiag;
   183 #endif //_DEBUG
   184 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   185 
   186 	if(ComparePrivate(aThePath))
   187 		{	
   188 		if(SIDCheck(aRequest, aThePath))
   189 			return KErrNone;	
   190 		else
   191 			{
   192 			if(aPriCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   193 				return KErrNone;
   194 			else
   195 				return KErrPermissionDenied;
   196 			}
   197 		}
   198 	else if(CompareSystem(aThePath))
   199 		{
   200 		if(aSysCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   201 			return KErrNone;
   202 		else
   203 			return KErrPermissionDenied;
   204 		}
   205 	else if(CompareResource(aThePath))
   206 		{
   207 		if(aROCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   208 			return KErrNone;
   209 		else
   210 			return KErrPermissionDenied;
   211 		}
   212 	else
   213 		return KErrNone;
   214  	}
   215 
   216 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   217 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, const char* aDiag) 
   218 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   219 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aSysCap, const TSecurityPolicy* aPriCap, OnlyCreateWithNull /*aDiag*/) 
   220 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   221 //
   222 //	Compare the parsed path with protected path names path must be parsed b4 using
   223 //
   224 	{
   225 
   226 	if(aRequest->Message().Handle() == KLocalMessageHandle)
   227 		return KErrNone;
   228 
   229 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   230 #ifdef _DEBUG
   231 	TBuf8<512> diagmsg;
   232 	TInt len = aThePath.Length();
   233 	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
   234 	diagmsg.Collapse();
   235 	diagmsg.SetLength(len);
   236 	diagmsg.Append(_L(" Used to call: "));
   237 	len = User::StringLength((const TUint8*)aDiag);
   238 	diagmsg.Append((TUint8*)aDiag, len);
   239 	const char* const diagout = (char*)diagmsg.PtrZ();
   240 #else //!_DEBUG	
   241 	const char* const diagout = aDiag;
   242 #endif //_DEBUG
   243 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   244 
   245 	if(ComparePrivate(aThePath))
   246 		{	
   247 		if(SIDCheck(aRequest, aThePath))
   248 			return KErrNone;	
   249 		else
   250 			{
   251 			if(aPriCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   252 				return KErrNone;
   253 			else
   254 				return KErrPermissionDenied;
   255 			}
   256 		}
   257 	else if(CompareSystem(aThePath))
   258 		{
   259 		if(aSysCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   260 			return KErrNone;
   261 		else
   262 			return KErrPermissionDenied;
   263 		}
   264 	else
   265 		return KErrNone;
   266  	}
   267 
   268 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   269 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aCap, const char* aDiag, TBool aExactMatchAllowed) 
   270 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   271 TInt PathCheck(CFsRequest* aRequest, const TDesC& aThePath, const TSecurityPolicy* aCap, OnlyCreateWithNull /*aDiag*/, TBool aExactMatchAllowed) 
   272 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   273 //
   274 //	Compare the parsed path with protected path names path must be parsed b4 using
   275 //
   276 	{
   277 
   278 	if(aRequest->Message().Handle() == KLocalMessageHandle)
   279 		return KErrNone;
   280 
   281 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   282 #ifdef _DEBUG
   283 	TBuf8<512> diagmsg;
   284 	TInt len = aThePath.Length();
   285 	diagmsg.Append((TUint8*)aThePath.Ptr(),len*2);
   286 	diagmsg.Collapse();
   287 	diagmsg.SetLength(len);
   288 	diagmsg.Append(_L(" Used to call: "));
   289 	len = User::StringLength((const TUint8*)aDiag);
   290 	diagmsg.Append((TUint8*)aDiag, len);
   291 	const char* const diagout = (char*)diagmsg.PtrZ();
   292 #else //!_DEBUG	
   293 	const char* const diagout = aDiag;
   294 #endif //_DEBUG
   295 #endif //!__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
   296 
   297 	if(ComparePrivate(aThePath))
   298 		{	
   299 		if(SIDCheck(aRequest, aThePath))
   300 			return KErrNone;	
   301 		else
   302 			{
   303 			if(aCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   304 				return KErrNone;
   305 			else if (aExactMatchAllowed && aThePath.Length() <= KPrivateLength + 1)
   306 				return KErrNone;
   307 			else
   308 				return KErrPermissionDenied;
   309 			}
   310 		}
   311 	else if(CompareSystem(aThePath))
   312 		{
   313 		if(aCap->CheckPolicy(aRequest->Message(), __PLATSEC_DIAGNOSTIC_STRING(diagout)))
   314 			return KErrNone;
   315 		else if (aExactMatchAllowed && aThePath.Length() <= KSystemLength + 1)
   316 			return KErrNone;
   317 		else
   318 			return KErrPermissionDenied;
   319 		}
   320 	else
   321 		return KErrNone;
   322 	
   323 	}
   324 
   325 
   326 
   327 
   328 void Fault(TFsFault aFault)
   329 //
   330 // Fault the file server.
   331 //
   332 	{
   333 
   334 	__PRINT1(_L("FAULT: TFsFault %d"),aFault);
   335 	User::Panic(_L("Fserv fault"),aFault);
   336 	}
   337 
   338 /**
   339     Get Ptr() from the client and parse it. Allow wild cards.
   340     Then get the drive and if the drive is substed get the real name.
   341     
   342     @param  aP          	message parameter number
   343     @param  aRequest    	pointer to the reques object
   344     @param  aParse      	parser
   345     @param  aUseSessionPath flag specifying whether the session path is to be
   346      						used for parsing or not. Default value is ETrue meaning
   347      						that the session path is used while parsing.
   348 
   349     @return     system-wide error code.
   350 */
   351 TInt ParseSubst(const TInt aP, CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
   352 	{
   353 	__ASSERT_DEBUG(aRequest->Session(),Fault(EParseSubstSession));
   354 	
   355 	//-- check the length of the name, passed by client.
   356 	//-- it shall not be longer than KMaxFileName
   357 	TInt nameLen=aRequest->GetDesLength(aP);
   358 	if(nameLen < 0 || nameLen > KMaxFileName)
   359 	    return KErrBadName;
   360 	
   361 	TFileName n;
   362 	TRAPD(r, aRequest->ReadL(aP,n));
   363 	
   364 	if(r==KErrNone)
   365 		{
   366 		if(aUseSessionPath)
   367 			r=aParse.Set(n,NULL,&aRequest->Session()->Path());
   368 		else
   369 			r=aParse.Set(n,NULL,NULL);
   370 		}
   371 	if (r!=KErrNone)
   372 		return(r);
   373 	if(!aUseSessionPath && !aParse.DrivePresent())
   374 		return(r);
   375 	TInt drive;
   376 	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
   377 		return(r);
   378 	aRequest->SetDrive(&TheDrives[drive]);
   379 	if (aRequest->Drive()->Att()&KDriveAttSubsted)
   380 		{
   381 		if ((aRequest->Drive()->Subst().Length()+aParse.FullName().Length())>(KMaxFileName+3))
   382 			return(KErrBadName);
   383 		aRequest->SetSubstedDrive(aRequest->Drive());
   384 		// and now set aParse with the full path name
   385 		n=aRequest->Drive()->Subst().Mid(2);
   386 		n+=aParse.FullName().Mid(3);
   387 		TFileName n2=aRequest->SubstedDrive()->Subst().Left(2);
   388 		r=aParse.Set(n,NULL,&n2);
   389 		if(r!=KErrNone)
   390 			return(r);
   391 		aRequest->SetDrive(&aRequest->Drive()->SubstedDrive());
   392 		}
   393 	return(KErrNone);
   394 	}
   395 
   396 
   397 TInt ParseSubstPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
   398 //
   399 // Get Ptr0() from the client and parse it. Allow wild cards.
   400 // Then get the drive and if the drive is substed get the real name.
   401 //
   402 	{
   403 
   404 	return(ParseSubst(KMsgPtr0,aRequest,aParse,aUseSessionPath));
   405 	}
   406 
   407 TInt ParseNoWildSubstPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
   408 //
   409 // Get Ptr0() from the client and parse it. Dis-allow wild cards.
   410 // Then get the drive and if the drive is substed get the real name.
   411 //
   412 	{
   413 	TInt r=ParseSubst(KMsgPtr0,aRequest,aParse,aUseSessionPath);
   414 	if (r!=KErrNone)
   415 		return(r);	//	Returns KErrBadName if "/" in the name or length > 256 chars
   416 	
   417 	if (aParse.IsWild())	//	No *s or ?s allowed in the file name
   418 		return(KErrBadName);
   419 	return(KErrNone);
   420 	}
   421 
   422 
   423 TInt ParseNoWildSubstPtr1(CFsRequest* aRequest,TParse& aParse)
   424 //
   425 // Get Ptr0() from the client and parse it. Dis-allow wild cards.
   426 // Then get the drive and if the drive is substed get the real name.
   427 //
   428 	{
   429 	TInt r=ParseSubst(KMsgPtr1, aRequest, aParse);
   430 	if (r!=KErrNone)
   431 		return(r);	//	Returns KErrBadName if "/" in the name or length > 256 chars
   432 	
   433 	if (aParse.IsWild())	//	No *s or ?s allowed in the file name
   434 		return(KErrBadName);
   435 	return(KErrNone);
   436 	}
   437 
   438 
   439 TInt ParseNoWildSubstCheckPathPtr0(CFsRequest* aRequest,TParse& aParse)
   440 //
   441 // Get Ptr0() from the client and parse it.
   442 // Then get the drive and if the drive is substed get the real name.
   443 // Dis-allow wild cards and the root directory
   444 //
   445 	{
   446 
   447 	TInt r=ParseSubst(KMsgPtr0,aRequest,aParse);
   448 	if (r!=KErrNone)
   449 		return(r);
   450 	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
   451 		return(KErrBadName);
   452 	return(KErrNone);
   453 	}
   454 
   455 TInt ParseNoWildSubstCheckPathPtr1(CFsRequest* aRequest,TParse& aParse)
   456 //
   457 // Get Ptr1() from the client and parse it.
   458 // Then get the drive and if the drive is substed get the real name.
   459 // Dis-allow wild cards and the root directory
   460 //
   461 	{
   462 
   463 	TInt r=ParseSubst(KMsgPtr1,aRequest,aParse);
   464 	if (r!=KErrNone)
   465 		return(r);
   466 	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
   467 		return(KErrBadName);
   468 
   469 	return(KErrNone);
   470 	}
   471 
   472 TInt ParseNoWildSubstFileCheckPtr1(CFsRequest* aRequest,TParse& aParse)
   473 //
   474 // Get Ptr0() from the client and parse it.
   475 // Then get the drive and if the drive is substed get the real name.
   476 // Dis-allow wild cards and the root directory
   477 // Finally check that there is a name or extension.
   478 	{
   479 
   480 	TInt r=ParseSubst(KMsgPtr1,aRequest,aParse);
   481 	if (r!=KErrNone)
   482 		return(r);
   483 	if (aParse.IsWild() || (aParse.IsRoot() && !aParse.NameOrExtPresent()))
   484 		return(KErrBadName);
   485 	if(!aParse.NameOrExtPresent())
   486 	    return (KErrBadName);
   487 	return(KErrNone);
   488 	}
   489 
   490 TInt ParseNoWildSubstCheckPtr0(CFsRequest* aRequest,TParse& aParse, TBool aUseSessionPath)
   491 //
   492 // Get Ptr0() from the client and parse it. Dis-allow wild cards.
   493 // Then get the drive and if the drive is substed get the real name.
   494 // Finally check that there is a name or extension.
   495 //
   496 	{
   497 
   498 	TInt r=ParseNoWildSubstPtr0(aRequest,aParse, aUseSessionPath);	
   499 	if (r!=KErrNone)
   500 		return(r);
   501 	if (!aParse.NameOrExtPresent())
   502 		return(KErrBadName);
   503 	return(KErrNone);
   504 	}
   505 
   506 TInt ParseNoWildSubstCheckPtr1(CFsRequest* aRequest,TParse& aParse)
   507 //
   508 // Get Ptr1() from the client and parse it. Dis-allow wild cards.
   509 // Then get the drive and if the drive is substed get the real name.
   510 // Finally check that there is a name or extension.
   511 //
   512 	{
   513 
   514 	TInt r=ParseNoWildSubstPtr1(aRequest,aParse);
   515 	if (r!=KErrNone)
   516 		return(r);
   517 	if (!aParse.NameOrExtPresent())
   518 		return(KErrBadName);
   519 	return(KErrNone);
   520 	}
   521 
   522 /**
   523     Get Ptr0() from the client and parse it.
   524 
   525     @param  aRequest    pointer to the reques object
   526     @param  aParse      parser
   527 
   528     @return     system-wide error code.
   529 */
   530 TInt ParsePathPtr0(CFsRequest* aRequest,TParse& aParse)
   531 	{
   532 	//-- check the length of the name, passed by client.
   533 	//-- it shall not be longer than KMaxFileName
   534 	TInt nameLen=aRequest->GetDesLength(KMsgPtr0);
   535 	if(nameLen < 0 || nameLen > KMaxFileName)
   536 	    return KErrBadName;
   537 
   538 	TFileName n;
   539 	TRAPD(r,aRequest->ReadL(KMsgPtr0,n));
   540 	if (r==KErrNone)
   541 		r=aParse.SetNoWild(n,NULL,&aRequest->Session()->Path());
   542 	if (r!=KErrNone)
   543 		return(r);
   544 	if (aParse.NameOrExtPresent())
   545 		return(KErrBadName);
   546 	TInt drive;
   547 	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
   548 		return(r);
   549 	aRequest->SetDrive(&TheDrives[drive]);
   550 	return(KErrNone);
   551 	}
   552 
   553 
   554 TInt ParseNotificationPath(CFsRequest* aRequest, TParse& aParse, TDes& aNotifyPath)
   555 //
   556 //	Called by Notify Change extended function when client has submitted a path
   557 //	which contains a wildcarded initial character to represent the drive
   558 //	This is required when notification over a number of drives is required
   559 //
   560 	{
   561 	if ((aNotifyPath[0]==KMatchAny)||(aNotifyPath[0]==KMatchOne))
   562 		{
   563 	//	Use the default session drive for now
   564 		TFileName sessionDefault=aRequest->Session()->Path();
   565 		aNotifyPath[0]=sessionDefault[0];
   566 		}
   567 
   568 	TInt r=aParse.Set(aNotifyPath,NULL,&aRequest->Session()->Path());
   569 	if (r!=KErrNone)
   570 		return(r);
   571 	TInt drive;
   572 	if ((r=RFs::CharToDrive(aParse.Drive()[0],drive))!=KErrNone)
   573 		return(r);
   574 	aRequest->SetDrive(&TheDrives[drive]);
   575 	if (aRequest->Drive()->Att()&KDriveAttSubsted)
   576 		{
   577 		if ((aRequest->Drive()->Subst().Length()+aParse.FullName().Length())>(KMaxFileName+3))
   578 			return(KErrBadName);
   579 		aRequest->SetSubstedDrive(aRequest->Drive());
   580 		// and now set aParse with the full path name
   581 		TFileName n=aRequest->Drive()->Subst().Mid(2);
   582 		n+=aParse.FullName().Mid(3);
   583 		TFileName n2=aRequest->SubstedDrive()->Subst().Left(2);
   584 		r=aParse.Set(n,NULL,&n2);
   585 		if(r!=KErrNone)
   586 			return(r);
   587 		aRequest->SetDrive(&aRequest->Drive()->SubstedDrive());
   588 		}	
   589 	if (aParse.IsWild())
   590 		return(KErrBadName);
   591 	return(KErrNone);
   592 	}
   593 
   594 
   595 CFsObject* SessionObjectFromHandle(TInt aHandle,TInt aUniqueID, CSessionFs* aSession)
   596 //
   597 // Lookup an object from its handle.
   598 //
   599 	{
   600 	if(aUniqueID==0)
   601 		return(aSession->Handles().At(aHandle,ETrue));
   602 	else
   603 		return(aSession->Handles().At(aHandle,aUniqueID,ETrue));
   604 	}
   605 
   606 
   607 CFileShare* GetShareFromHandle(CSessionFs* aSession, TInt aHandle)
   608 //
   609 // Get the share control block from its handle.
   610 //
   611 	{
   612 	return((CFileShare*)(SessionObjectFromHandle(aHandle,FileShares->UniqueID(),aSession)));
   613 	}
   614 
   615 
   616 //
   617 // Returns ETrue if aDes only contains spaces or is zero length
   618 //
   619 static TBool IsSpace(const TDesC& aDes)
   620 	{
   621 
   622 	TInt len=aDes.Length();
   623 	if (len==0)
   624 		return(EFalse);
   625 	for (TInt i=0;i<len;i++)
   626 		{
   627 		TChar txt=aDes[i];
   628 		if (!txt.IsSpace())
   629 			return(EFalse);
   630 		}
   631 	return(ETrue);
   632 	}
   633 
   634 TUint32 CalcNameHash(const TDesC& aName) 
   635 	{
   636 	const TUint32 KNameHashCRCInitialiser=0x12345678;
   637 	TUint32 hash=KNameHashCRCInitialiser;
   638 	Mem::Crc32(hash, aName.Ptr(), aName.Size());
   639 	return hash;
   640 	}
   641 
   642 
   643 TBool TNameChecker::IsIllegal(TText& aChar) const
   644 //
   645 // Checks aChar != any of < > : " / |
   646 // \ is also illegal in a name but will be considered a path delimiter
   647 //
   648 	{
   649 	switch (aChar)
   650 		{
   651 	case '<':
   652 	case '>':
   653 	case ':':
   654 	case '"':
   655 	case '/':
   656 	case '|':
   657 	case '\000':
   658 		return(ETrue);
   659 	default:
   660 		break;
   661 		}
   662 	return(EFalse);
   663 	}
   664 
   665 
   666 
   667 TBool TNameChecker::IsIllegalChar(TText& aChar)
   668 //	
   669 //	Checks aName for illegal components and returns the offending character if any
   670 //	No other parsing is performed
   671 //
   672 	{
   673 	TInt len=iName.Length();
   674 	while (len--)
   675 		{
   676 		if (IsIllegal(iName[len]))// '<', '>', ':', '"', '/', '|' or '\000'?
   677 			{
   678 			aChar=iName[len];
   679 			return(ETrue);
   680 			}
   681 		}
   682 	return(EFalse);
   683 	}
   684 
   685 
   686 TBool TNameChecker::IsIllegalName()
   687 //
   688 // Checks name is not _L(".") or _L("..") and that there are no illegal characters
   689 //
   690 	{
   691 
   692 	TInt pos=iName.LocateReverse(KPathDelimiter)+1;
   693 	TPtrC fileName(iName.Ptr()+pos,iName.Length()-pos);
   694 	SetName(fileName);
   695 	
   696 	if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
   697 		return ETrue;
   698 	TInt len=iName.Length();
   699 	
   700 	while (len--)
   701 		{
   702 		if (IsIllegal(iName[len]))	//	'<', '>', ':', '"', '/', '|' or '\000'?
   703 			return(ETrue);
   704 		}
   705 	return(EFalse);
   706 	}
   707 
   708 
   709 TBool TNameChecker::IsIllegalName(TText& aChar)
   710 //
   711 //	Check name and path are legal - if not, return the offending component
   712 //
   713 	{
   714 	TInt r=iParse.Set(iName,NULL,NULL);
   715 	if (r!=KErrNone)
   716 		return(ETrue);	//	Checks for names > 256 chars etc
   717 	
   718 	SetName(iParse.FullName());
   719 	if (IsIllegalPath(aChar))
   720 		return(ETrue);	//	Checks for illegal characters in path
   721 	
   722 	TInt nameStart=iParse.FullName().LocateReverse(KPathDelimiter)+1;
   723 	r=(iParse.FullName().Mid(nameStart)).LocateReverse(KPathDelimiter)+1;
   724 	TPtrC fileName(iName.Ptr()+r,iName.Length()-r);
   725 	SetName(fileName);
   726 
   727 	if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
   728 		{
   729 		aChar=iName[0]; 
   730 		return ETrue;
   731 		}
   732 	
   733 	return (IsIllegalChar(aChar));
   734 	}
   735 
   736 const TInt KSpace = ' ';
   737 TBool TNameChecker::IsIllegalPath()
   738 //
   739 // Checks the path does not contain wildcards or directories _L(".") or _L("..") or just spaces
   740 //
   741 	{
   742 
   743 	if (iName.Locate(KMatchOne)!=KErrNotFound || iName.Locate(KMatchAny)!=KErrNotFound)
   744 		return(ETrue);
   745 
   746 	TLex pathLex=iName;
   747 	FOREVER
   748 		{
   749 		pathLex.Inc();
   750 		if (pathLex.Remainder().Length()==0)
   751 			break;
   752 		TInt nextPath=pathLex.Remainder().Locate(KPathDelimiter);
   753 		if (nextPath==0) // Reject double backslashes
   754 			return(ETrue);
   755 		if (nextPath==KErrNotFound)
   756 			nextPath=pathLex.Remainder().Length();
   757 		pathLex.Mark();
   758 		pathLex.Inc(nextPath);
   759 		SetName(pathLex.MarkedToken());
   760 		if (IsIllegalName())
   761 			return(ETrue);
   762 		// check for tailing dots
   763 		for(TInt i = pathLex.MarkedToken().Length() - 1; i >= 0; --i)
   764 			{
   765 			if (pathLex.MarkedToken()[i] == KExtDelimiter)
   766 				{
   767 				return ETrue;
   768 				}
   769 			else if (pathLex.MarkedToken()[i] == KSpace)
   770 				{
   771 				continue;
   772 				}
   773 			else
   774 				{
   775 				break;
   776 				}
   777 			}
   778 		}
   779 	return(EFalse);
   780 	}
   781 
   782 
   783 TBool TNameChecker::IsIllegalPath(TText& aChar)
   784 //
   785 //	Checks the path does not contain wildcards or directories _L(".") or _L("..") or just spaces
   786 //	Returns the first offending character found (if any)
   787 //
   788 	{
   789 	if (iName.Locate(KMatchOne)!=KErrNotFound)
   790 		{
   791 		aChar=KMatchOne;
   792 		return (ETrue);
   793 		}
   794 	if (iName.Locate(KMatchAny)!=KErrNotFound)
   795 		{
   796 		aChar=KMatchAny;
   797 		return (ETrue);
   798 		}
   799 
   800 	TLex pathLex=iName;
   801 	TFileName name;
   802 	FOREVER
   803 		{
   804 		pathLex.Inc();
   805 		if (pathLex.Remainder().Length()==0)
   806 			break;
   807 		TInt nextPath=pathLex.Remainder().Locate(KPathDelimiter);
   808 		if (nextPath==0) // Reject double backslashes
   809 			{
   810 			aChar=KPathDelimiter; 
   811 			return ETrue;
   812 			}	
   813 		if (nextPath==KErrNotFound)
   814 			nextPath=pathLex.Remainder().Length();
   815 		pathLex.Mark();
   816 		pathLex.Inc(nextPath);
   817 		name=pathLex.MarkedToken();
   818 		// check for tailing dots
   819 		for(TInt i = pathLex.MarkedToken().Length() - 1; i >= 0; --i)
   820 			{
   821 			if (pathLex.MarkedToken()[i] == KExtDelimiter)
   822 				{
   823 				aChar = KExtDelimiter;
   824 				return ETrue;
   825 				}
   826 			else if (pathLex.MarkedToken()[i] == KSpace)
   827 				{
   828 				continue;
   829 				}
   830 			else
   831 				{
   832 				break;
   833 				}
   834 			}
   835 		TInt pos=name.LocateReverse(KPathDelimiter)+1;
   836 		TPtrC fileName(name.Ptr()+pos,name.Length()-pos);
   837 		SetName(fileName);
   838 		if (iName==_L(".") || iName==_L("..") || IsSpace(iName))
   839 			{
   840 			aChar=iName[0]; 
   841 			return ETrue;
   842 			}
   843 		
   844 		if (IsIllegalChar(aChar))
   845 			return(ETrue);
   846 		}
   847 	
   848 	return(EFalse);
   849 	}
   850 
   851 
   852 TBool IsIllegalFullName(const TParse& aParse)
   853 	{
   854 	TPtrC ptr=aParse.Path();
   855 	TNameChecker checker(ptr);
   856 	if (checker.IsIllegalPath())
   857 		return(ETrue);	//	Checks for illegal characters in path
   858 	
   859 	TInt nameStart=aParse.FullName().LocateReverse(KPathDelimiter)+1;
   860 	checker.SetName(aParse.FullName().Mid(nameStart));
   861 	
   862 	if (checker.IsIllegalName())
   863 		return(ETrue);	//	Checks illegal characters such as ></|". and ..
   864 	return(EFalse);
   865 	}
   866 
   867  TBool IsIllegalFullName(const TDesC& aName)
   868 //
   869 // Check name and path are legal
   870 //
   871 	{
   872 	TParse parser;
   873 	TInt r=parser.Set(aName,NULL,NULL);
   874 	if (r!=KErrNone)
   875 		return(ETrue);	//	Checks for wild cards, names>256 chars etc
   876 	
   877 	return IsIllegalFullName(parser);
   878 	}
   879 
   880 TBool PowerOk()
   881 //
   882 // Check the power is OK
   883 //
   884 	{
   885 
   886 	TBool powerGood=EFalse;
   887 	TInt r=HAL::Get(HAL::EPowerGood, powerGood);
   888 	if (r!=KErrNone)
   889 		return EFalse;
   890 	return powerGood;
   891 	}
   892 
   893 void AddResource(CMountCB& aMount)
   894 //
   895 // Decrement resource counters
   896 //
   897 	{
   898 	__CHECK_DRIVETHREAD(aMount.Drive().DriveNumber());
   899 	__ASSERT_DEBUG(aMount.LockStatus()<=0,Fault(ERawDiskBadAccessCount2));
   900 	aMount.DecLock();
   901 	}
   902 
   903 void RemoveResource(CMountCB& aMount)
   904 //
   905 // Increment resource counters
   906 //
   907 	{
   908 	__ASSERT_DEBUG(aMount.LockStatus()<0,Fault(ERawDiskBadAccessCount1));
   909 	aMount.IncLock();
   910 	}
   911 
   912 
   913 void AddDiskAccess(CMountCB& aMount)
   914 //
   915 // Increment resource counters
   916 //
   917 	{
   918 	aMount.IncLock();
   919 	}
   920 
   921 void RemoveDiskAccess(CMountCB& aMount)
   922 //
   923 // Decrement resource counters
   924 //
   925 	{
   926 	aMount.DecLock();
   927 	}
   928 
   929 EXPORT_C void AllocBufferL(HBufC*& aBuf,const TDesC& aName)
   930 //
   931 // Alloc or ReAlloc buffer 
   932 //
   933 	{
   934 
   935 	if (aBuf==NULL)
   936 		{
   937 		aBuf=aName.AllocL();
   938 		return;
   939 		}
   940 	if (aBuf->Length()<aName.Length())
   941 		{
   942 		TInt bufGranularity=(1<<KLog2BufGranularity);
   943 		TInt size=((aName.Length()+bufGranularity-1)>>KLog2BufGranularity)<<KLog2BufGranularity;
   944 		aBuf=aBuf->ReAllocL(size);
   945 		}
   946 	aBuf->Des()=aName;
   947 	}
   948 
   949 void NextInPath(const TDesC& aPath,TPtrC& anEntry,TInt& aPos)
   950 //
   951 // Returns the next entry in the path
   952 //
   953 	{
   954 	
   955 	anEntry.Set(NULL,0);
   956 	if ((aPos+1)>=aPath.Length())
   957 		return;
   958 	TPtrC path(aPath.Mid(aPos+1)); // Skip delimiter
   959 	TInt delimiterPos=path.Locate(KPathDelimiter);
   960 	if (delimiterPos==KErrNotFound)
   961 		delimiterPos=aPath.Length()-(aPos+1);
   962 	if (delimiterPos<=0)
   963 		return;
   964 
   965 	if (path[delimiterPos-1]==KExtDelimiter) // return "F32." as "F32"
   966 		anEntry.Set(aPath.Mid(aPos+1,delimiterPos-1));
   967 	else
   968 		anEntry.Set(aPath.Mid(aPos+1,delimiterPos));
   969 	aPos+=delimiterPos+1;
   970 	}
   971 
   972 TInt MatchUidType(const TUidType &aMatch, const TUidType &aType)
   973 //
   974 // Compare aType against aMatch with KNullUid as a wildcard
   975 //
   976 	{
   977 
   978 	TUid mu=aMatch[2];
   979 	TUid tu=aType[2];
   980 	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
   981 		return KErrNotSupported;
   982 	mu=aMatch[1];
   983 	tu=aType[1];
   984 	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
   985 		return KErrNotSupported;
   986 	mu=aMatch[0];
   987 	tu=aType[0];
   988 	if (mu!=KNullUid && tu!=KNullUid && mu!=tu)
   989 		return KErrNotSupported;
   990 	return KErrNone;
   991 	}
   992 
   993 /**
   994  * Compare sections of filenames according to locale-independent rules as well
   995  * as locale-dependent rules. This is an attempt to get an ordering where
   996  * equivalent names sort together but the overall ordering is culturally
   997  * acceptable. Sadly, the ordering it gives is not consistent, and it is not
   998  * clear how to make it so. Hence this function is deprecated. The correct way
   999  * to do this is to code around it: If you need a sorted array for display that
  1000  * you also need to search for equivalent filenames, either use a linear search
  1001  * or keep two arrays, one sorted with CompareF, the other with CompareC.
  1002  * @deprecated 6.1
  1003  */
  1004 EXPORT_C TInt CompareFilenames(const TDesC& aFileName1,const TDesC& aFileName2)
  1005 // 
  1006 // Compare filenames. Case is ignored and names are normalised
  1007 // (base+accent is equal to composed character) but spaces
  1008 // and punctuation are significant for determining equality.
  1009 // Whether two filenames are identical is the same in all
  1010 // locales, but the ordering of non-identical filenames is locale-specific.
  1011 //
  1012 //
  1013 	{
  1014 	// Create a non-locale-specific collation method that doesn't ignore spaces and punctuation but folds case.
  1015 	TCollationMethod method;
  1016 	method.iFlags = TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase;
  1017 	method.iMainTable=NULL;	
  1018 	method.iOverrideTable=NULL;	
  1019 	
  1020 	// Get the non-locale-specific order and return it if the names are equal.
  1021 	TInt base_order = aFileName1.CompareC(aFileName2,3,&method);
  1022 	if (base_order == 0)
  1023 		return base_order;
  1024 
  1025 	// Get the locale-specific order and use it unless it is equality, in which case the non-locale-specific order must be used.
  1026 	TInt locale_order = aFileName1.CompareC(aFileName2);
  1027 	return locale_order ? locale_order : base_order;
  1028 	}
  1029 
  1030 void Get8BitDllName(TDes8& aDllName, const TDesC& aFileName)
  1031 //
  1032 //	Convert a 16 bit name to an 8 bit name
  1033 //	No data loss because UNICODE Dlls are currently restricted to 8 bit names
  1034 //	No effect in 8 bit builds - just sets aDllName to aFileName
  1035 //
  1036 	{
  1037 	aDllName.SetLength(aFileName.Length());
  1038 	aDllName.Copy(aFileName);
  1039 	}								
  1040 
  1041 void Get16BitDllName(TDes& aFileName, const TDesC8& aDllName)
  1042 //
  1043 //	Convert an 8 bit name to a 16 bit name - zero padded automatically
  1044 //	No effect in 8 bit builds - just sets aFileName to aDllName
  1045 //
  1046 	{
  1047 	aFileName.SetLength(aDllName.Length());
  1048 	aFileName.Copy(aDllName);	
  1049 	}								
  1050 
  1051 
  1052 /**
  1053     Checks that there is sufficient disk space available to complete a task taking into account reserved space
  1054  
  1055     @param  aThreshold amount of required free space, in bytes
  1056     @param  aRequest
  1057 
  1058     @return KErrNone        on success and if there are _strictly_more_ than aThreshold bytes available on the volume (taking into account reserved space)
  1059             KErrDiskFull    on success and if there isn't enough space
  1060             system-wide error code otherwise
  1061 */
  1062 TInt CheckDiskSpace(TInt64 aThreshold, CFsRequest* aRequest)
  1063 	{
  1064     const TInt KReservedSpace = aRequest->Drive()->ReservedSpace();
  1065     const TInt KDriveNumber = aRequest->Drive()->DriveNumber();
  1066 
  1067 	if(KReservedSpace == 0 || KDriveNumber == EDriveZ)
  1068 	    return KErrNone;
  1069 
  1070     //-- if the drive has a reserved space, take it into account
  1071 	CSessionFs* session=aRequest->Session(); 
  1072 
  1073     if(!session || !session->ReservedAccess(KDriveNumber))
  1074         aThreshold += KReservedSpace;
  1075 
  1076     //-- ask the corresponding file system if there is aThreshold bytes available.
  1077     //-- for some reason it's required to be strictly > than aThreshold
  1078     return aRequest->Drive()->RequestFreeSpaceOnMount(aThreshold+1);
  1079 	}								
  1080 
  1081 
  1082 #if defined(_DEBUG) || defined(_DEBUG_RELEASE)
  1083 EXPORT_C TUint32 DebugRegister() {return(DebugReg);}
  1084 #else
  1085 EXPORT_C TUint32 DebugRegister() {return(0);}
  1086 #endif
  1087 
  1088 CLogon* CLogon::NewL()
  1089 //
  1090 // Create the CLogon active object.
  1091 //
  1092 	{
  1093 
  1094 	CLogon* pL=new(ELeave) CLogon(EPriority);
  1095 	CActiveScheduler::Add(pL);
  1096 	return(pL);
  1097 	}
  1098 
  1099 #pragma warning( disable : 4705 )	// statement has no effect
  1100 CLogon::CLogon(TInt aPriority)
  1101 //
  1102 // Constructor
  1103 //
  1104 	: CActive(aPriority)
  1105 	{
  1106 	}
  1107 #pragma warning( default : 4705 )
  1108 
  1109 TInt CLogon::Logon(RThread aThread)
  1110 //
  1111 // Issue a request to logon to the thread.
  1112 //
  1113 	{
  1114 
  1115 	iThread=aThread;
  1116 	iThread.Logon(iStatus);
  1117 		SetActive();
  1118 	if (iStatus==KErrNoMemory)
  1119 		iThread.Kill(KErrNoMemory);
  1120 	else
  1121 		iThread.Resume();
  1122 	iThread.Close();
  1123 	CActiveScheduler::Start();
  1124 	return(iStatus.Int());
  1125 	}
  1126 
  1127 void CLogon::DoCancel()
  1128 //
  1129 // Cancel a pending event.
  1130 //
  1131 	{
  1132 
  1133 	iThread.LogonCancel(iStatus);
  1134 	}
  1135 
  1136 void CLogon::RunL()
  1137 //
  1138 // Thread has terminated.
  1139 //
  1140 	{
  1141 
  1142 	CActiveScheduler::Stop();
  1143 	}
  1144