os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_find.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1996-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\sfsrv\cl_find.cpp
    15 // 
    16 //
    17 
    18 #include "cl_std.h"
    19 
    20 #define gPathDelimiter TChar(';')
    21 enum TMode {EFindByDrives,EFindByDrivesInPath,EFindByPath};
    22 
    23 TInt TFindFile::DoFindInDir()
    24 //
    25 // Look for aFileName in aDir
    26 //
    27 	{
    28 
    29 	if (iDir==NULL)
    30 		{
    31 		TEntry entry;
    32 		TInt r=iFs->Entry(iFile.FullName(),entry);
    33 		if (r==KErrNone /*|| r==KErrAccessDenied*/)
    34 			return(KErrNone);
    35 		else if (r==KErrNoMemory)
    36 			return r;
    37 		else if (r==KErrPermissionDenied)
    38 			return (KErrPermissionDenied);
    39 		else
    40 			return(KErrNotFound);
    41 		}
    42 	TInt r=iFs->GetDir(iFile.FullName(),KEntryAttMaskSupported|KEntryAttAllowUid,ESortByName,*iDir);
    43 	if (r==KErrNoMemory)
    44 		return r;
    45 	else if (r==KErrPermissionDenied)
    46 		return r;
    47 	else if (r!=KErrNone)
    48 		return(KErrNotFound);
    49 	if ((*iDir)->Count()==0)
    50 		{
    51 		delete (*iDir);
    52 		*iDir=NULL;
    53 		return(KErrNotFound);
    54 		}
    55 	else
    56 		return(KErrNone);
    57 	}
    58 
    59 TInt TFindFile::DoFindNextInPath()
    60 //
    61 // Look for aFileName along the path and increment aPathPos
    62 //
    63 	{
    64 
    65 	if (iMode==EFindByDrivesInPath)
    66 		{
    67 		TInt r=DoFindNextInDriveList();
    68 		if (r==KErrNone)
    69 			return(KErrNone);
    70 		if (r!=KErrNotFound)
    71 			return(r);
    72 		iMode=EFindByPath;
    73 		}
    74 	FOREVER
    75 		{
    76 		if (iPath->Length()<iPathPos)
    77 			return(KErrNotFound);
    78 		TPtrC path(iPath->Ptr()+iPathPos,iPath->Length()-iPathPos);
    79 		TInt r=path.Locate(gPathDelimiter);
    80 		if (r==KErrNotFound)
    81 			r=path.Length();
    82 		path.Set(path.Ptr(),r);
    83 		iPathPos+=r+1;
    84 		TFileName fileName=iFile.NameAndExt();
    85 		iFile.Set(fileName,&path,NULL);
    86 		if (iFile.FullName().Length()>=2 && iFile.FullName()[1]==KDriveDelimiter)
    87 			{
    88 			TInt r=DoFindInDir();
    89 			if (r==KErrNone)
    90 				return(KErrNone);
    91 			if (r!=KErrNotFound)
    92 				return(r);
    93 			continue;
    94 			}
    95 		iMode=EFindByDrivesInPath;
    96 		
    97 		r=FindByDir(fileName,path);
    98 		if (r==KErrNone)
    99 			return(KErrNone);
   100 		if (r!=KErrNotFound)
   101 			return(r);
   102 		}
   103 
   104 	}
   105 
   106 TInt TFindFile::DoFindNextInDriveList()
   107 //
   108 // Look for aFileName in all available drives in order
   109 //
   110 	{
   111 	
   112 	TInt found;	
   113 	TDriveInfo driveInfo;
   114 	const TUint matchedFlags= iMatchMask & KDriveAttMatchedFlags;  //KDriveAttMatchedFlags = 0xFFF
   115 	const TUint matchedAtt = iMatchMask & KDriveAttMatchedAtt;	 //KDriveAttMatchedAtt = 0x0FFF0000
   116 	
   117 	if (iMatchMask == (KDriveAttExclude | KDriveAttMatchedFlags ) ) //If all drives are excluded.
   118 		return KErrNotFound;
   119 
   120 	FOREVER
   121 		{
   122 				
   123 		found =0;
   124 		TInt currentDrive=iCurrentDrive;
   125 		
   126 		
   127 		if (iCurrentDrive==-1)
   128 			currentDrive=EDriveZ;
   129 			
   130 		
   131 		if (currentDrive<=-2)
   132 			return(KErrNotFound);	
   133 			
   134 				
   135 		iCurrentDrive--;
   136 
   137 		if (!iDrvList[currentDrive])
   138 			continue;
   139 
   140 		TInt err = iFs->Drive(driveInfo,currentDrive);
   141 
   142 		if(iMatchMask == 0)
   143 			{
   144 			if (iDrvList[currentDrive] & KDriveAttRemote)
   145 				continue;									// NOT allowed on REMOTE DRIVE
   146 			if ((iDrvList[currentDrive] & (KDriveAttLocal|KDriveAttRom))==0)
   147 				continue;
   148 			}
   149 		else 	
   150 			{									
   151  
   152 			if(matchedFlags != 0 )
   153 				{
   154 
   155 				switch(matchedAtt)
   156 					{ //found ==0 means that this drive attributes didn't match the flags
   157 					
   158 					case KDriveAttExclude :
   159 						found = (driveInfo.iDriveAtt & matchedFlags ) ? 0:iDrvList[currentDrive] ;
   160 						break;
   161 
   162 					case 0:
   163 						found = (driveInfo.iDriveAtt & matchedFlags) ? iDrvList[currentDrive]:0 ;
   164 						break;
   165 
   166 
   167 					case KDriveAttExclusive :
   168 						if(matchedFlags != KDriveAttLogicallyRemovable)
   169 							{
   170 
   171 							found = ((TUint8)(driveInfo.iDriveAtt) == matchedFlags)  ?iDrvList[currentDrive]:0;
   172 								
   173 							}
   174 						else 
   175 							{
   176 							found = (driveInfo.iDriveAtt == (matchedFlags | KDriveAttRemovable) )  ?iDrvList[currentDrive]:0;
   177 							}
   178 						
   179 						break;
   180 
   181 					case KDriveAttExclude | KDriveAttExclusive:
   182 						if(matchedFlags != KDriveAttLogicallyRemovable)
   183 							{
   184 						
   185 							found = ((TUint8)(driveInfo.iDriveAtt) == matchedFlags)  ?0:iDrvList[currentDrive];
   186 								
   187 							}
   188 						else 
   189 							{
   190 							found = (driveInfo.iDriveAtt == (matchedFlags | KDriveAttRemovable))  ?0:iDrvList[currentDrive];
   191 							}
   192 						
   193 						break;
   194 
   195 					default: 
   196 						Panic(EFindFileIllegalAttribute);			
   197 							
   198 					}
   199 				}
   200 
   201 			else  //matchedFlags == 0.
   202 				{
   203 				
   204 				if (matchedAtt== KDriveAttAll)		
   205 					found= iDrvList[currentDrive];
   206 				else 
   207 					Panic(EFindFileIllegalAttribute);		
   208 									
   209 				}
   210 			
   211 		
   212 		
   213 			if( found == 0)
   214 				continue;			
   215 
   216 			}
   217 		
   218 		// Don't scan a locked drive
   219 		
   220 		if( err == KErrNone)
   221 			{		
   222 			if(driveInfo.iMediaAtt & KMediaAttLocked)
   223 				continue;
   224 			}
   225 		
   226 
   227 		TParse fileName;
   228 		TChar driveLetter;
   229 		RFs::DriveToChar(currentDrive,driveLetter);
   230 		TBuf<4> drive;
   231 		drive.SetLength(2);
   232 		drive[0]=(TText)driveLetter;
   233 		drive[1]=':';
   234 		TPtrC nameAndExt(iFile.NameAndExt());
   235 		TPtrC path(iFile.Path());
   236 		fileName.Set(nameAndExt,&path,&drive);
   237 		iFile=fileName;
   238 		TInt r=DoFindInDir();
   239 		if (r==KErrNone)
   240 			return(KErrNone);
   241 		if (r!=KErrNotFound)
   242 			return(r);
   243 		}	
   244 	}
   245 
   246 
   247 
   248 
   249 EXPORT_C TFindFile::TFindFile(RFs& aFs)
   250 	: iFs(&aFs), iPathPos(0), iCurrentDrive(0), iMode(-1), iMatchMask(0)
   251 /**
   252 Constructor taking a file server session.
   253 
   254 @param aFs File server session.
   255 */
   256 	{
   257 	
   258 	iFile.Set(_L(""),NULL,NULL);
   259 	}
   260 
   261 
   262 
   263 
   264 TInt TFindFile::DoFindByPath(const TDesC& aFileName,const TDesC* aPath)
   265 //
   266 // Look for a file in each directory in the path
   267 // Make initial check for aFileName in the current directory
   268 //
   269 	{
   270 	
   271 	if (aFileName.Length() <= 0) 
   272 		return(KErrArgument);
   273 	
   274 	TInt r=iFile.Set(aFileName,NULL,NULL);
   275 	if (r!=KErrNone)
   276 		return(r);
   277 	iPath=aPath;
   278 	iPathPos=0;
   279 	iMode=EFindByPath;
   280 	r=DoFindInDir();	
   281 	
   282 	
   283 	if (r==KErrNone)
   284 		return(KErrNone);
   285 	if (r!=KErrNotFound)
   286 		return(r);
   287 	if ((iPath==NULL) || (iPath->Length()==0))
   288 		return(KErrNotFound);
   289 	
   290 	
   291 	r=DoFindNextInPath();
   292 	return(r);
   293 	}
   294 
   295 TInt TFindFile::DoFindByDir(const TDesC& aFileName,const TDesC& aDir)
   296 //
   297 // Look for aFileName in aDir on each connected drive
   298 // Make initial check for aFileName in aDir on current drive
   299 //
   300 	{
   301 		
   302 	if (aFileName.Length() <= 0) 
   303 		return(KErrArgument);
   304 
   305 	TInt r=iFs->Parse(aFileName,aDir,iFile);
   306 	if (r!=KErrNone)
   307 		return(r);
   308 	TInt searchResult=DoFindInDir();
   309 	if(searchResult==KErrNoMemory)                       
   310 		return(searchResult);
   311 	
   312 	if(searchResult==KErrPermissionDenied)
   313 		return (KErrPermissionDenied);
   314 	
   315 	r=iFs->DriveList(iDrvList,KDriveAttAll);
   316 	if (r!=KErrNone)
   317 		return(r);
   318 	TInt drive;
   319 	r=RFs::CharToDrive(iFile.Drive()[0],drive);
   320 	if (r!=KErrNone)
   321 		return(r);
   322 	iDrvList[drive]=0; // Drive 'drive' has already been searched
   323 	iCurrentDrive=EDriveY;
   324 	iMode=EFindByDrives;
   325 	if (searchResult==KErrNone)
   326 		return(KErrNone);
   327 	
   328 	
   329 	return(DoFindNextInDriveList());
   330 	}
   331 
   332 
   333 
   334 
   335 EXPORT_C TInt TFindFile::FindByPath(const TDesC& aFileName,const TDesC* aPath)
   336 /**
   337 Searches for a file/directory in one or more directories in the path.
   338 
   339 The search ends when the file/directory is found, or when every directory
   340 specified in the path list has been unsuccessfully searched.
   341 
   342 Notes:
   343 	
   344 1. For the equivalent search using wildcards, use FindWildByPath().
   345 
   346 2. After a file has been found, use TFindFile::File() to get the fully qualified path of the file. To
   347    search for the next occurrence, use TFindFile::Find().
   348 
   349 @param aFileName The filename to search for. If this specifies a directory as well
   350                  as a filename, then that directory is searched first.
   351 @param aPath     A list of directories to be searched. Paths in this list must
   352                  be separated by a semicolon character, but a semicolon is not
   353                  required after the	final path. The directories are searched in
   354                  the order in which they occur in the list. If a path in
   355                  the list contains a drive letter, that drive alone is searched.
   356                  If a path contains no drive letter, the function searches for
   357                  the file in that directory on every available drive in turn,
   358                  beginning with drive Y:, in descending alphabetical order
   359                  and ending with drive Z:.When path is empty then session path 
   360                  will be used for the search.
   361 
   362 @return KErrNone, if the filename was found;
   363         KErrNotFound, if the filename was not found.
   364         KErrArgument, if the filename is empty. 
   365 
   366 @see TFindFile::FindWildByPath
   367 @see TFindFile::File
   368 @see TFindFile::Find
   369 */
   370 	{
   371 
   372 	iDir=NULL;
   373 	return(DoFindByPath(aFileName,aPath));
   374 	}
   375 
   376 
   377 
   378 
   379 EXPORT_C TInt TFindFile::FindByDir(const TDesC& aFileName,const TDesC& aDir)
   380 /**
   381 Searches for a file/directory in a directory on all available drives.
   382 
   383 The	search ends when the file/directory is found, or when every available
   384 drive has been unsuccessfully searched.
   385 
   386 Notes:
   387 
   388 1. A drive letter may be specified in aDirPath.
   389    If a drive is specified, then that drive is searched first. If no drive is
   390    specified, then the drive specified in the session path is searched first.
   391    The remaining available drives are then searched in descending alphabetical
   392    order, from Y: to A:, and ending with the Z: drive. Using function SetFindMask
   393    it is possible to specify a combination of attributes that the drives to be 
   394    searched must match.
   395    
   396 
   397 2. For the corresponding search using wildcards, use FindWildByDir().
   398 
   399 3. After a file has been found, use TFindFile::File() to get the fully
   400    qualified path and filename. To search for the next occurrence,
   401    use TFindFile::Find().
   402 
   403 @param aFileName The filename to search for. If a path is specified, it
   404                  overrides the path specified in aDir. If no path is specified,
   405                  the path contained in aDir is used.
   406 @param aDir      A single path indicating a directory to be searched on each
   407                  drive.When path is empty then session path will be used for the search.
   408 
   409 @return KErrNone, if the file was found, otherwise one of the system-wide error codes, including:
   410         KErrNotFound, if the file was not found;
   411         KErrPermissionDenied, if the client does not have appropriate capabilities for the directory to be searched;
   412 		KErrArgument, if the filename is empty.
   413 
   414 @see TFindFile::FindWildByDir()
   415 @see TFindFile::File()
   416 @see TFindFile::Find()
   417 @see TFindFile::SetFindMask()
   418 */
   419 	{
   420 
   421 	iDir=NULL;
   422 	return(DoFindByDir(aFileName,aDir));
   423 	}
   424 
   425 
   426 
   427 
   428 EXPORT_C TInt TFindFile::FindWildByPath(const TDesC& aFileName,const TDesC* aPath,CDir*& aDir)
   429 /**
   430 Searches for one or more files/directories in the directories contained in a
   431 path list.
   432 
   433 Wildcard characters can be specified. The search ends when one or more
   434 filenames matching aFileName is found, or when every
   435 directory in the path list has been unsuccessfully searched.
   436 To begin searching again after a successful match has been made,
   437 use FindWild().
   438 
   439 Using function SetFindMask it is possible to specify a combination of 
   440 attributes that the drives to be searched must match.
   441 
   442 Notes:
   443 
   444 1. The caller of the function is responsible for deleting
   445    aDir after the function has returned.
   446 
   447 2. Calling TFindFile::File() after a successful search gets the drive letter
   448    and directory containing the file(s). The filenames can be retrieved via
   449    the array of TEntry::iName objects contained in aDir. If you want to
   450    retrieve the fully qualified path of a file, you need to parse the path and
   451    the filename.
   452    
   453 @param aFileName The filename to search for. May contain wildcards. If
   454                  it specifies a directory as well as a filename, then that
   455                  directory is searched first.
   456 @param aPath     List of directories to search. Paths in this list must be
   457                  separated by a semicolon character, but a semicolon is not
   458                  required after the final path. The directories are searched
   459                  in the order in which they occur in the list.
   460                  Directories must be fully qualified, including
   461                  a drive letter, and the name must end with a backslash.
   462 @param aDir      On return, contains the entries for all files matching
   463 				 aFileName in the first directory in which a match occurred.
   464 
   465 @return KErrNone, if one or more matching files was	found;
   466         KErrNotFound, if no matching file was found in any of the directories.
   467         KErrArgument, if the filename is empty.
   468 
   469 @see TFindFile::FindWild
   470 @see TFindFile::File
   471 @see TEntry::iName
   472 @see TFindFile::SetFindMask()
   473 */
   474 	{
   475 
   476 	iDir=&aDir;
   477 	return(DoFindByPath(aFileName,aPath));
   478 	}
   479 
   480 
   481 
   482 
   483 EXPORT_C TInt TFindFile::FindWildByDir(const TDesC& aFileName,const TDesC& aDirPath,CDir*& aDir)
   484 /**
   485 Searches, using wildcards, for one or more files/directories in a specified
   486 directory.
   487 
   488 If no matching file is found in that directory, all available drives are
   489 searched in descending alphabetical order, from Y: to A:, and ending
   490 with the Z: drive.Using function SetFindMask it is possible to specify a 
   491 combination of attributes that the drives to be searched must match.
   492 
   493 The search ends when one or more matching filenames are found, or when every 
   494 available drive has been unsuccessfully searched. To begin searching again 
   495 after a successful match has been made, use FindWild(). Wildcards may be
   496 specified in the filename.
   497 
   498 Notes:
   499 
   500 1. A drive letter may be specified in aDirPath (or in aFileName). If a drive 
   501    is specified, that drive is searched first, followed by the other available 
   502    drives, in descending alphabetical order. If no drive is specified, the drive 
   503    contained in the session path is searched first.
   504 
   505 2. The function sets aDir to NULL, then allocates memory for it before appending 
   506    entries to the list. Therefore, aDir should have no memory allocated to it 
   507    before this function is called, otherwise this memory will become orphaned.
   508 
   509 3. The caller of this function is responsible for deleting aDir after the function 
   510    has returned.
   511 
   512 4. Calling TFindFile::File() after a successful search returns the drive letter 
   513    and directory containing the file(s). Filenames may be retrieved via the array 
   514    of TEntry::iNames contained in aDir. If you want to retrieve the fully 
   515    qualified path of a file, you will need to parse the path and the filename.
   516 
   517 @param aFileName The filename to search for. May contain wildcards. If a path 
   518                  is specified, it overrides the path specified in aDirPath.
   519                  If no path is specified, the path contained in aDirPath is
   520                  used in the search.
   521 @param aDirPath  Path indicating a directory to search on each drive.
   522 @param aDir      On return, contains the entries for all files
   523                  matching aFileName.
   524                  
   525 @return KErrNone if one or more matching files was found;
   526         KErrNotFound if no matching file was found in the directory on any 
   527         of the drives.
   528         KErrArgument, if the filename is empty. 
   529                 
   530 @see TFindFile::FindWild
   531 @see TFindFile::File
   532 @see TFindFile::SetFindMask()
   533 */
   534 	{
   535 
   536 	iDir=&aDir;
   537 	return(DoFindByDir(aFileName,aDirPath));
   538 	}
   539 
   540 
   541 
   542 
   543 TInt TFindFile::DoFind()
   544 //
   545 // Find the next match
   546 //
   547 	{
   548 
   549 	TInt ret=KErrNone;
   550 	switch(iMode)
   551 		{
   552 	case EFindByDrives:
   553 		ret=DoFindNextInDriveList();
   554 		break;
   555 	case EFindByPath:
   556 	case EFindByDrivesInPath:
   557 		ret=DoFindNextInPath();
   558 		break;
   559 	default:
   560 		Panic(EFindFileIllegalMode);
   561 		}
   562 	return(ret);
   563 	}
   564 
   565 
   566 
   567 
   568 EXPORT_C TInt TFindFile::Find()
   569 /**
   570 Searches for the next file/directory.
   571 
   572 This should be used after a successful call to FindByPath() or FindByDir(), 
   573 to find the next occurrence of the filename in the path or drive list.
   574 
   575 Using function SetFindMask it is possible to specify a combination of 
   576 attributes that the drives to be searched must match.
   577 
   578 Note:
   579 
   580 1. After a file/directory has been found, use TFindFile::File() to get the
   581    fully qualified path and filename.
   582 
   583 @return KErrNone, if another occurrence of the file was found;
   584         KErrNotFound, if no more occurrences were found.
   585         
   586 @see TFindFile::FindByPath
   587 @see TFindFile::FindByDir
   588 @see TFindFile::File
   589 @see TFindFile::SetFindMask()
   590 
   591 */
   592 	{
   593 
   594 //	iDir=NULL;
   595 	return(DoFind());
   596 	}
   597 
   598 
   599 
   600 
   601 EXPORT_C TInt TFindFile::FindWild(CDir*& aDir)
   602 /**
   603 Searches for the next file/directory.
   604 
   605 This should be used after a successful call to FindWildByPath()
   606 or FindWildByDir(), for the next occurrences of the filename in the
   607 path or drive list.Using function SetFindMask it is possible to specify a 
   608 combination of attributes that the drives to be searched must match.
   609 
   610 Notes:
   611 
   612 1. The caller of this function is responsible for deleting aDir after
   613    the function has returned 
   614 
   615 2. Calling TFindFile::File() after a successful search, will return
   616    the drive letter and the directory containing the file(s).
   617    The filenames may be retrieved via the array of TEntry::iName objects
   618    contained in aDir. If you want to retrieve the fully qualified
   619    path of a file, you will need to parse the path and the filename using
   620    the TParse class or derived classes.
   621 
   622 @param aDir On return, contains the entries for all matching files found in
   623             the next directory.
   624             
   625 @return KErrNone, if further occurrences were found;
   626         KErrNotFound, if no more matching files were found.
   627 
   628 
   629 @see TParse
   630 @see TEntry::iName
   631 @see TFindFile::File
   632 @see TFindFile::FindWildByPath
   633 @see TFindFile::FindWildByDir
   634 @see TFindFile::SetFindMask()
   635 */
   636 	{
   637 
   638 	iDir=&aDir;
   639 	return(DoFind());
   640 	}
   641 
   642 
   643 
   644 EXPORT_C TInt TFindFile::SetFindMask(TUint aMask)
   645 /**
   646 Can be used in order to specify a combination of drive attributes that the drives 
   647 to be searched must match. When searching without specifying a mask, all drives, except the 
   648 remote ones will be returned.
   649 
   650 @param aMask The combination of drive attributes that we want the drives to match. 
   651 
   652 @return KErrNone, if the mask supplied is correct.
   653         KErrArgument, if the mask supplied is invalid.
   654 */
   655 
   656 	 {	
   657 	 TInt r =ValidateMatchMask(aMask);
   658 	 if(r!=KErrNone) 
   659 	 	return r;
   660 	 else
   661 	 	{
   662 	 	if(aMask != 0)
   663 			iMatchMask = aMask;
   664 		else 		
   665 			iMatchMask  = (KDriveAttExclude |KDriveAttMatchedFlags) ; //KDriveAttMatchedFlags ==0xFF so this exclude all drives in DoFindNextInDriveList
   666 	 	
   667 	 	return KErrNone;
   668 	 	
   669 	 	}
   670 	 
   671 	
   672 											
   673 	 }
   674