os/kernelhwsrv/userlibandfileserver/fileserver/etshell/ts_com.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/etshell/ts_com.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,3729 @@
     1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// f32\etshell\ts_com.cpp
    1.18 +// Shell commands
    1.19 +// 
    1.20 +//
    1.21 +
    1.22 +#ifdef __VC32__
    1.23 +  // Solve compilation problem caused by non-English locale
    1.24 +  #pragma setlocale("english")
    1.25 +#endif
    1.26 +
    1.27 +#include "ts_std.h"
    1.28 +
    1.29 +#include <hal.h>
    1.30 +#include <d32locd.h>
    1.31 +#include <e32math.h>
    1.32 +#include "u32std.h"
    1.33 +#include <u32hal.h>
    1.34 +#include <nkern/nk_trace.h>
    1.35 +#include "filesystem_fat.h"
    1.36 +
    1.37 +    TPtrC ptrFormatHelp=_L("Drive:[\\] [fat12|fat16|fat32] [spc:X] [rs:Y] [ft:Z] [/Q][/S][/E][/F]\nfat12 or fat16 or fat32 specifies explicit FAT type\nspc:X specifies \"X\" sectors per cluster\nrs:Y specifies \"Y\" reserved sectors\nft:Z specifies \"Z\" FAT tables (1 or 2)\n\n/q - QuickFormat, /s - SpecialFormat, /e - ForcedErase\n/f - force formatting (ignore volume being in use)");
    1.38 +    TPtrC ptrMountHelp=_L("Drive:[\\]  <fsy:X> <fs:Y> [pext:Z] [/S][/U][/F][/R]\n'X' *.fsy module name, like elocal.fsy\n'Y' file system name, like 'FAT'\n'Z' optional primary extension module name\n/U - dismount FS from the drive e.g 'mount d: /u' \n/F - force mounting with dismounting existing FS \n/S - mount drive as synchronous\n/R - remount the file system ");
    1.39 +
    1.40 +
    1.41 +//	lint -e40,e30
    1.42 +const TShellCommand CShell::iCommand[ENoShellCommands]=
    1.43 +	{
    1.44 +//	TShellCommand(_L("BLANK"),_L("Help"),_L("-?"),TShellCommand::EDSwitch,ShellFunction::BLANK),
    1.45 +	TShellCommand(_L("ATTRIB"),_L("Displays or changes file attributes"),_L("[drive:][path][filename] [+R | -R] [+H |-H] [+S | -S] [+A | -A] [/p]\n\n  /p - Pause after each screen of information"), TShellCommand::EPSwitch, ShellFunction::Attrib),
    1.46 +	TShellCommand(_L("CD"),_L("Change the current directory for a drive"),_L("[path] [/d]\n\n  /d - Change drive"),TShellCommand::EDSwitch,ShellFunction::Cd),
    1.47 +	TShellCommand(_L("CHKDEPS"),_L("Check the dependencies of an executable or a Dll (ARM only)"),_L("[Filename.EXE] or [Filename.DLL]"),0,ShellFunction::ChkDeps),
    1.48 +	TShellCommand(_L("CHKDSK"),_L("Check disk for corruption"),_L("[drive:] [/s][/f|/u]\n\n/s - start ScanDrive instead of CheckDisk\n/f - finalise drive\n/u - unfinalise drive"),TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::EUSwitch,ShellFunction::ChkDsk),
    1.49 +	TShellCommand(_L("COPY"),_L("Copy one (or more) file(s)"),_L("source [destination]"),TShellCommand::ESSwitch,ShellFunction::Copy),
    1.50 +	TShellCommand(_L("DEL"),_L("Delete one file"),_L("[drive:][path][filename]"),TShellCommand::ESSwitch,ShellFunction::Del),
    1.51 +	TShellCommand(_L("DIR"),_L("Show directory contents"),_L("[drive:][path][filename] [/p][/w]\n\n  /p - Pause after each screen of information\n  /w - Wide format"),TShellCommand::EPSwitch|TShellCommand::EWSwitch|TShellCommand::EASwitch,ShellFunction::Dir),
    1.52 +//	TShellCommand(_L("EDLIN"),_L("Edit a text file"),_L("[drive:][path][filename] [/p]\n\n  /p - Pause after each screen of information"),TShellCommand::EPSwitch,ShellFunction::Edit),
    1.53 +    TShellCommand(_L("FORMAT"),_L("Format a disk"),ptrFormatHelp,TShellCommand::EQSwitch|TShellCommand::ESSwitch|TShellCommand::EESwitch|TShellCommand::EFSwitch,ShellFunction::Format),
    1.54 +    TShellCommand(_L("GOBBLE"),_L("Create a file"),_L("[filename] size [/e]\n\n /e - create an empty file, without writing any data"),TShellCommand::EESwitch,ShellFunction::Gobble),
    1.55 +	TShellCommand(_L("HEXDUMP"),_L("Display the contents of a file in hexadecimal"),_L("[drive:][path][filename] [/p]\n\n  /p - Pause after each screen of information\n\n  Hit escape to exit from hexdump "),TShellCommand::EPSwitch,ShellFunction::Hexdump),
    1.56 +	TShellCommand(_L("LABEL"),_L("Set or return the volume label"),_L("[newlabel]"),0,ShellFunction::VolumeLabel),
    1.57 +	TShellCommand(_L("MD"),_L("Make a new directory"),_L("name"),0,ShellFunction::Md),
    1.58 +	TShellCommand(_L("MOVE"),_L("Move files"),_L("name [destination]"),TShellCommand::ESSwitch,ShellFunction::Move),
    1.59 +	TShellCommand(_L("PS"),_L("Display information about processes"),_L(""),0,ShellFunction::Ps),
    1.60 +	TShellCommand(_L("RENAME"),_L("Rename a file"),_L("oldfilename newfilename"),TShellCommand::ESSwitch,ShellFunction::Rename),
    1.61 +	TShellCommand(_L("RD"),_L("Delete one directory"),_L("[drive:][path]directoryname"),TShellCommand::ESSwitch,ShellFunction::Rd),
    1.62 +	TShellCommand(_L("START"),_L("Run a program in a separate window"),_L("filename[.exe]"),0,ShellFunction::Start),
    1.63 +	TShellCommand(_L("TIME"),_L("Display the system time"),_L(""),0,ShellFunction::Time),
    1.64 +	TShellCommand(_L("TRACE"),_L("Set the debug trace mask"),_L("[mask value in hex] [index] [/S/L/F/T/I/N/M/O/C/H]\n  /S - KFSERV\n  /L - KFLDR\n  /F - KFSYS\n  /T - KLFFS\n  /I - KISO9660\n  /N - KNTFS\n  /M - KTHRD\n  /O - KROFS\n  /C - KCOMPFS\n  /H - KCACHE"),TShellCommand::ELSwitch|TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::ETSwitch|TShellCommand::EISwitch|TShellCommand::ENSwitch|TShellCommand::EMSwitch|TShellCommand::EOSwitch|TShellCommand::ECSwitch|TShellCommand::EHSwitch,ShellFunction::Trace),
    1.65 +	TShellCommand(_L("TREE"),_L("Graphically display the directory structure"),_L("[drive:][path] [/f][/p]\n\n  /f - Show files\n  /p - Pause after each screen of information"),TShellCommand::EFSwitch|TShellCommand::EPSwitch,ShellFunction::Tree),
    1.66 +	TShellCommand(_L("TYPE"),_L("Display the contents of a text file"),_L("[drive:][path]filename [/p]\n\n  /p - Pause after each screen of information"),TShellCommand::EPSwitch,ShellFunction::Type),
    1.67 +	TShellCommand(_L("VNAME"),_L("Check whether a filename is valid.  Return any invalid character"),_L("[drive:][path]filename \n\n "),0,ShellFunction::ValidName),
    1.68 +	TShellCommand(_L("LOCK"),_L("Lock a password-enabled media"),_L("drive-number cur-pswd new-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Lock),
    1.69 +	TShellCommand(_L("UNLOCK"),_L("Unlock a locked password-enabled media"),_L("drive-number cur-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Unlock),
    1.70 +	TShellCommand(_L("CLEAR"),_L("Clear password from password-enabled media"),_L("drive-number cur-pswd"), 0x00000000, ShellFunction::Clear),
    1.71 +	TShellCommand(_L("SETSIZE"),_L("Set size of a file"),_L("[filename] size"),0,ShellFunction::SetSize),
    1.72 +	TShellCommand(_L("DEBUGPORT"),_L("Set or get debug port"),_L("[port]"),0,ShellFunction::DebugPort),
    1.73 +	TShellCommand(_L("PLUGIN"),_L("Manage Plugins"),_L("[name][/A][/R][/M][/D]"),TShellCommand::EASwitch|TShellCommand::ERSwitch|TShellCommand::EMSwitch|TShellCommand::EDSwitch,ShellFunction::Plugin),
    1.74 +    TShellCommand(_L("DRVINFO"),_L("Print information about present drive(s) in the system"),_L("[DriveLetter:[\\]] [/p]\n/p - pause after each drive"),TShellCommand::EPSwitch,ShellFunction::DrvInfo),
    1.75 +	TShellCommand(_L("SYSINFO"),_L("Print information about system features and status"),_L(""),0,ShellFunction::SysInfo),
    1.76 +    TShellCommand(_L("MOUNT"),_L("Mount / dismount file system on specified drive"),ptrMountHelp,TShellCommand::EUSwitch|TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::ERSwitch,ShellFunction::MountFileSystem),
    1.77 +    TShellCommand(_L("ECHO"),_L("Print out the command line to the console and standard debug port."),_L("[line to print out]"),0,ShellFunction::ConsoleEcho),
    1.78 +	TShellCommand(_L("RUNEXEC"),_L("Run a program in a loop"),_L("count filename[.exe] [/E/S/R]\n	/E - exit early on error\n	/S - count in seconds\n	     zero - run forever\n	/R - reset debug regs after each run"),TShellCommand::EESwitch|TShellCommand::ESSwitch|TShellCommand::ERSwitch,ShellFunction::RunExec),
    1.79 +
    1.80 +    };
    1.81 +
    1.82 +
    1.83 +LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN);
    1.84 +LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW);
    1.85 +
    1.86 +_LIT(KLitNewLine,"\n");
    1.87 +void CShell::NewLine()
    1.88 +	{
    1.89 +	TheConsole->Printf(KLitNewLine());
    1.90 +	}
    1.91 +
    1.92 +//
    1.93 +// Skip the hexadecimal prefix if present and return EHex.  Return
    1.94 +// EDecimal otherwise.
    1.95 +//
    1.96 +
    1.97 +static TRadix ParseHexaPrefixIfAny(TLex& aLex)
    1.98 +	{
    1.99 +	_LIT(KPrefix, "0x");
   1.100 +	if (aLex.Remainder().Length() > 2)
   1.101 +		{
   1.102 +		aLex.Mark();
   1.103 +		aLex.Inc(2);
   1.104 +		if (aLex.MarkedToken().MatchF(KPrefix) != KErrNotFound)
   1.105 +			return EHex;
   1.106 +		else
   1.107 +			aLex.UnGetToMark();
   1.108 +		}
   1.109 +
   1.110 +	return EDecimal;
   1.111 +	}
   1.112 +
   1.113 +
   1.114 +//
   1.115 +//	TWord class
   1.116 +//	Used to locate spaces in the command line, and return the next word
   1.117 +//
   1.118 +
   1.119 +TWord::TWord(const TDesC& aDes)
   1.120 +	: iSpace(0),iNextSpace(0)
   1.121 +//
   1.122 +//	Constructor
   1.123 +//
   1.124 +	{
   1.125 +	Init(aDes);
   1.126 +	}
   1.127 +
   1.128 +
   1.129 +void TWord::Init(const TDesC& aDes)
   1.130 +//
   1.131 +// Resets to the start of the buffer
   1.132 +//
   1.133 +	{
   1.134 +	iDes.Set(aDes);
   1.135 +	}
   1.136 +
   1.137 +TInt TWord::FindNextWord(TDes& aWord)
   1.138 +//
   1.139 +//	Returns the next word from the buffer
   1.140 +//
   1.141 +	{
   1.142 +	iSpace=aWord.Locate(' ');
   1.143 +
   1.144 +	if (iSpace==KErrNotFound)		//	No spaces in command line
   1.145 +		{
   1.146 +		if (aWord.Length()==0)		//	Command line has zero length:
   1.147 +			return (KErrNotFound);	//	User just typed "command"
   1.148 +		else
   1.149 +			{						//	User typed "command aWord"
   1.150 +			iRightString=aWord;
   1.151 +			iNextWord=aWord;
   1.152 +			return (0);
   1.153 +			}
   1.154 +		}
   1.155 +
   1.156 +	else if (iSpace<aWord.Length())	//	Spaces may be command switches or part of the filename
   1.157 +		{
   1.158 +		iRightString=(aWord.Right((aWord.Length()-iSpace)-1));
   1.159 +
   1.160 +		iNextSpace=iRightString.Locate(' ');	//	Check for another space
   1.161 +		if (iNextSpace==KErrNotFound)			//	No more spaces
   1.162 +			{
   1.163 +			iNextWord=iRightString;
   1.164 +			return((iDes.Length())-(iRightString.Length()));//	Position of the (last) word
   1.165 +			}
   1.166 +
   1.167 +		if (iNextSpace<iRightString.Length())	//	More spaces - assign iNextWord to be
   1.168 +			{									//	the text in between the two spaces
   1.169 +			iNextWord=(iRightString.Left(iNextSpace));
   1.170 +			return ((iDes.Length())-(iRightString.Length()));//	Position of the word
   1.171 +			}
   1.172 +
   1.173 +		else
   1.174 +			return(KErrNotFound);
   1.175 +		}
   1.176 +
   1.177 +	else
   1.178 +		return(KErrNotFound);
   1.179 +	}
   1.180 +
   1.181 +//-------------------------------------------------------------------------
   1.182 +
   1.183 +
   1.184 +TInt ShellFunction::Cd(TDes& aPath,TUint aSwitches)
   1.185 +//
   1.186 +// Change directory
   1.187 +//
   1.188 +	{
   1.189 +	ShellFunction::StripQuotes(aPath);
   1.190 +
   1.191 +	TBool drvNameOnly=aPath.Length()==2 && aPath[1]==KDriveDelimiter;
   1.192 +	TBool dSwitchSet=aSwitches&TShellCommand::EDSwitch;
   1.193 +	if (aPath.Length()==0 || (drvNameOnly && !dSwitchSet))
   1.194 +		{
   1.195 +		TInt drvNum=(aPath.Length() ? aPath[0] : TheShell->currentPath[0])-'A';
   1.196 +		if (drvNum<0 || drvNum>=KMaxDrives)
   1.197 +			return(KErrBadName);
   1.198 +		CShell::TheConsole->Printf(_L("%S\n"),&TheShell->drivePaths[drvNum]);
   1.199 +		return(KErrNone);
   1.200 +		}
   1.201 +	if (aPath.Find(_L("*"))!=KErrNotFound)
   1.202 +		return(KErrBadName);
   1.203 +	if (aPath[aPath.Length()-1]!=KPathDelimiter && !drvNameOnly)
   1.204 +		aPath.Append(KPathDelimiter);
   1.205 +	aPath.Append('*');
   1.206 +	TChar drvLetter = aPath[0];
   1.207 +	drvLetter.UpperCase();
   1.208 +	aPath[0] = (TText) drvLetter;
   1.209 +	TParse dirParse;
   1.210 +	TInt r=GetFullPath(aPath,dirParse);
   1.211 +	if (r!=KErrNone)
   1.212 +		return(KErrBadName);
   1.213 +	TPtrC fullName=dirParse.FullName();
   1.214 +	RDir dir;
   1.215 +	r=dir.Open(TheShell->TheFs,fullName,KEntryAttMaskSupported);
   1.216 +	if (r!=KErrNone)
   1.217 +		return(r);
   1.218 +	dir.Close();
   1.219 +	if (dSwitchSet || fullName[0]==TheShell->currentPath[0])
   1.220 +		r=TheShell->TheFs.SetSessionPath(dirParse.DriveAndPath());
   1.221 +	if (r==KErrNone)
   1.222 +		TheShell->SetDrivePath(dirParse.DriveAndPath());
   1.223 +	return(r);
   1.224 +	}
   1.225 +
   1.226 +TInt ShellFunction::ChkDeps(TDes& aPath,TUint /*aSwitches*/)
   1.227 +	{
   1.228 +	ShellFunction::StripQuotes(aPath);
   1.229 +
   1.230 +	aPath.Trim();
   1.231 +	TBool appendedExe=EFalse;
   1.232 +
   1.233 +//	Determine whether aPath is an executable or a Dll
   1.234 +
   1.235 +	TInt r=aPath.FindF(_L(".EXE"));
   1.236 +	if (r==KErrNotFound)
   1.237 +		{
   1.238 +		r=aPath.FindF(_L(".DLL"));
   1.239 +		if (r==KErrNotFound)//	aPath does not include .exe or .dll extensions
   1.240 +			{
   1.241 +			aPath.Append(_L(".EXE"));	//	append a .exe extension
   1.242 +			appendedExe=ETrue;
   1.243 +			}
   1.244 +		}
   1.245 +
   1.246 +	if (aPath.Length()>2 && aPath[1]==':' && aPath[2]!='\\')
   1.247 +		{
   1.248 +		TInt drive;
   1.249 +		__ASSERT_ALWAYS(RFs::CharToDrive(aPath[0],drive)==KErrNone,User::Panic(_L("Invalid drive letter"),0));
   1.250 + 		TheShell->currentPath=TheShell->drivePaths[drive];
   1.251 +   		aPath.Delete(0,2);
   1.252 +   		aPath.Insert(0,TheShell->currentPath);
   1.253 +		}
   1.254 +	if (aPath.Length()>2 && aPath[1]!=':')
   1.255 +		{
   1.256 +		if (aPath[0]!='\\')
   1.257 +    		aPath.Insert(0,TheShell->currentPath);
   1.258 +		else
   1.259 +			aPath.Insert(0,TheShell->currentPath.Left(2));
   1.260 +		}
   1.261 +
   1.262 +	RFile file;
   1.263 +	r=file.Open(CShell::TheFs,aPath,EFileStream);
   1.264 +	if (r!=KErrNone)	//		File could not be opened
   1.265 +		{
   1.266 +		if (appendedExe)	//	If .EXE was appended earlier
   1.267 +			{
   1.268 +//	Remove .EXE and append .DLL instead.  Try to open the file again
   1.269 +//	If this fails too, the user entered an invalid filename that is neither
   1.270 +//	an executable or a Dll
   1.271 +			aPath.Delete(aPath.Length()-4,4);
   1.272 +			appendedExe=EFalse;
   1.273 +			aPath.Append(_L(".DLL"));	//	Try a .DLL extension
   1.274 +			r=file.Open(CShell::TheFs,aPath,EFileStream);
   1.275 +			if (r!=KErrNone)	//	Still could not open file
   1.276 +				return(r);	//	Neither an executable or a Dll
   1.277 +		//	Runs to here if the file is opened -> .DLL extension appended
   1.278 +			}
   1.279 +		else
   1.280 +			return(r);	//	User had typed in an incorrect filename with
   1.281 +						//	a .DLL or .EXE extension
   1.282 +		}
   1.283 +
   1.284 +	file.Close();
   1.285 +	CDllChecker check;
   1.286 +	TRAPD(leaveCode,check.ConstructL());//	Allocates 4 elements at a time
   1.287 +	if (leaveCode!=KErrNone)	//	If function leaves
   1.288 +		return(leaveCode);		//	return the leave code
   1.289 +
   1.290 +	TRAPD(result,check.GetImportDataL(aPath,NULL));
   1.291 +	if (result==KErrGeneral)
   1.292 +		{
   1.293 +		CShell::TheConsole->Printf(_L(" %S has no import data\n"),&aPath);
   1.294 +		return(KErrNone);
   1.295 +		}
   1.296 +	else
   1.297 +		check.ListArray();	//	Print out the results of DllCheck
   1.298 +	return(KErrNone);
   1.299 +	}
   1.300 +
   1.301 +//
   1.302 +// Check disk for corruption
   1.303 +//
   1.304 +// Spec:
   1.305 +//
   1.306 +// ChkDsk DriveLetter:[\] [/S] [/F] [/U]
   1.307 +//
   1.308 +//			/S : Starts a ScanDrive instead of CheckDisk
   1.309 +//			/F : Finalise given drive
   1.310 +//			/U : UnFinalise given drive
   1.311 +
   1.312 +TInt ShellFunction::ChkDsk(TDes& aPath,TUint aSwitches)
   1.313 +	{
   1.314 +	ShellFunction::StripQuotes(aPath);
   1.315 +    
   1.316 +    const TBool bRunScanDrv     = aSwitches & TShellCommand::ESSwitch;
   1.317 +    const TBool bFinaliseDrv    = aSwitches & TShellCommand::EFSwitch;
   1.318 +    const TBool bUnFinaliseDrv  = aSwitches & TShellCommand::EUSwitch; 
   1.319 +
   1.320 +    TInt nRes;
   1.321 +    TInt drive=EDriveZ;
   1.322 +
   1.323 +	if(aPath.Length() < 1)
   1.324 +    {
   1.325 +        nRes = KErrArgument;
   1.326 +    }
   1.327 +    else
   1.328 +    {
   1.329 +        nRes=CShell::TheFs.CharToDrive(aPath[0], drive);
   1.330 +	}
   1.331 +
   1.332 +    if (nRes != KErrNone)
   1.333 +	{
   1.334 +    	CShell::TheConsole->Printf(_L("Wrong drive specified!\n"));
   1.335 +        return nRes;
   1.336 +    }
   1.337 +    
   1.338 +    if(bRunScanDrv)
   1.339 +    {//-- run ScanDrive on the specified drive
   1.340 +        CShell::TheConsole->Printf(_L("Starting ScanDrive...\n"));
   1.341 +        nRes=TheShell->TheFs.ScanDrive(aPath);
   1.342 +        if(nRes == KErrNone)
   1.343 +        {
   1.344 +            CShell::TheConsole->Printf(_L("No errors.\n"));
   1.345 +        }
   1.346 +    }
   1.347 +    else if(bFinaliseDrv)
   1.348 +    {//-- finalise the drive
   1.349 +        nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EFinal_RW);
   1.350 +        if(nRes != KErrNone)
   1.351 +            return nRes;
   1.352 +
   1.353 +        CShell::TheConsole->Printf(_L("Drive %c: is finalised RW\n"), 'A'+drive);
   1.354 +    }
   1.355 +    else if(bUnFinaliseDrv)
   1.356 +    {//-- Unfinalise the drive
   1.357 +        nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EForceUnfinalise);
   1.358 +        if(nRes != KErrNone)
   1.359 +            return nRes;
   1.360 +
   1.361 +        CShell::TheConsole->Printf(_L("Drive %c: is Unfinalised\n"), 'A'+drive);
   1.362 +    }
   1.363 +    else
   1.364 +    {//-- run CheckDisk on the specified drive
   1.365 +        nRes=TheShell->TheFs.CheckDisk(aPath);
   1.366 +	    if (nRes<0)
   1.367 +		    return(nRes);
   1.368 +
   1.369 +	    switch(nRes)
   1.370 +		    {
   1.371 +	    case 0:
   1.372 +		    CShell::TheConsole->Printf(_L("Complete - no errors\n"));
   1.373 +		    break;
   1.374 +	    case 1:
   1.375 +		    CShell::TheConsole->Printf(_L("Error - File cluster chain contains a bad value (<2 or >maxCluster)\n"));
   1.376 +		    break;
   1.377 +	    case 2:
   1.378 +		    CShell::TheConsole->Printf(_L("Error - Two files are linked to the same cluster\n"));
   1.379 +		    break;
   1.380 +	    case 3:
   1.381 +		    CShell::TheConsole->Printf(_L("Error - Unallocated cluster contains a value != 0\n"));
   1.382 +		    break;
   1.383 +	    case 4:
   1.384 +		    CShell::TheConsole->Printf(_L("Error - Size of file != number of clusters in chain\n"));
   1.385 +		    break;
   1.386 +	    default:
   1.387 +		    CShell::TheConsole->Printf(_L("Undefined Error value\n"));
   1.388 +		    }
   1.389 +	 }
   1.390 +    return nRes;
   1.391 +	}
   1.392 +
   1.393 +TInt ShellFunction::Copy(TDes& aPath,TUint aSwitches)
   1.394 +//
   1.395 +// DOS spec:
   1.396 +//
   1.397 +// COPY [/A | /B] source [/A | /B] [+ source [/A | /B] [+ ...]] [destination] [/A | /B]] [/V] [/N]
   1.398 +// source		Specifies the file or files to be copied.
   1.399 +// /A			Indicates an ASCII text file.
   1.400 +// /B			Indicates a binary file.
   1.401 +// destination	Specifies the directory and/or filename for the new file(s).
   1.402 +// /V			Verifies that new files are written correctly.
   1.403 +// /Y			Supresses prompting to confirm you want to overwrite existing destination file
   1.404 +// /N			Uses short filename, if available, when copying a file with a non-8dot3 name.
   1.405 +//
   1.406 +// To append files, specify a single file for destination, but multiple files
   1.407 +// for source (using wildcards or file1+file2+file3 format).
   1.408 +//
   1.409 +// My spec:
   1.410 +//
   1.411 +// COPY source [destination]
   1.412 +// source		Specifies the file or files to be copied to the current directory
   1.413 +
   1.414 +// Modified November 1997 to allow spaces in filenames
   1.415 +
   1.416 +	{
   1.417 +	if (aPath.Length() == 0)
   1.418 +	    return KErrNotFound;    // no source file
   1.419 +
   1.420 +	ShellFunction::StripQuotes(aPath);
   1.421 +
   1.422 +	TBuf<KShellMaxCommandLine> destination;
   1.423 +	TBuf<KShellMaxCommandLine> tempPath;
   1.424 +	TWord word(aPath);
   1.425 +
   1.426 +	TBool endOfCommandLine=EFalse;
   1.427 +
   1.428 +//	Check if the word returned is a valid filename.  If not, scan the next
   1.429 +//	word too in case the filename contains spaces.  If, at the end of the
   1.430 +//	the line, the filename is not recognised, it is invalid.  If there are no
   1.431 +//	spaces the user has not used the correct format for this command.
   1.432 +
   1.433 +	TInt r=word.FindNextWord(aPath);
   1.434 +	do	{
   1.435 +		TParse dirPath;
   1.436 +
   1.437 +		if (r==0)	//	No destination was specified
   1.438 +			{
   1.439 +		//	Work out the destination
   1.440 +			tempPath.SetLength(0);
   1.441 +			r=GetFullPath(tempPath,dirPath);
   1.442 +			if (r!=KErrNone)
   1.443 +				return(r);
   1.444 +			destination=dirPath.FullName();
   1.445 +		//	Now get the path of the source
   1.446 +			tempPath=aPath;
   1.447 +			r=GetFullPath(tempPath,dirPath);
   1.448 +			if (r!=KErrNone)
   1.449 +				return(r);
   1.450 +			endOfCommandLine=ETrue;	//	So we don't get stuck in an infinite loop
   1.451 +			}
   1.452 +		else
   1.453 +			{
   1.454 +		//	Work out the destination
   1.455 +			destination=aPath.Right(aPath.Length()-r);
   1.456 +			if (!destination.Compare(_L(".")))
   1.457 +				GetFullPath(destination,dirPath);
   1.458 +		//	Now get the path of the source
   1.459 +			tempPath=aPath;
   1.460 +			tempPath.SetLength(r);
   1.461 +			r=GetFullPath(tempPath,dirPath);
   1.462 +			if (r!=KErrNone)
   1.463 +				return(r);
   1.464 +			}
   1.465 +
   1.466 +		TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
   1.467 +		TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
   1.468 +		r=CShell::TheFileMan->Copy(dirPath.FullName(),destination,switches);
   1.469 +		if (r==KErrNone)
   1.470 +			return(r);	//	Copy was successful
   1.471 +
   1.472 +		else			//	Not a valid filename - move one word along the command line
   1.473 +			r=word.FindNextWord(word.iRightString);
   1.474 +		} while ((r>=0)&&(!endOfCommandLine));
   1.475 +
   1.476 +	if (r<0)			//	Some error
   1.477 +		return (r);
   1.478 +	else				//	End of command line, user typed invalid line, return not found
   1.479 +		return (KErrNotFound);
   1.480 +	}
   1.481 +
   1.482 +
   1.483 +TInt ShellFunction::VolumeLabel(TDes& aPath,TUint /*aSwitches*/)
   1.484 +/**
   1.485 +Sets or returns the default path
   1.486 +
   1.487 +@param aPath The volume label being set or returned
   1.488 +*/
   1.489 +	{
   1.490 +	ShellFunction::StripQuotes(aPath);
   1.491 +
   1.492 +	TVolumeInfo vol;
   1.493 +	TInt drive;
   1.494 +	TInt r=CShell::TheFs.CharToDrive(CShell::currentPath[0], drive);
   1.495 +	if (r!=KErrNone)
   1.496 +		return(r);
   1.497 +	if (aPath.Length()==0)
   1.498 +		{
   1.499 +		r=CShell::TheFs.Volume(vol, drive);
   1.500 +		if (r==KErrNone)
   1.501 +			CShell::TheConsole->Printf(_L("Volume = %S\n"),&vol.iName);
   1.502 +		return(r);
   1.503 +		}
   1.504 +	r=CShell::TheFs.SetVolumeLabel(aPath, drive);
   1.505 +	return(r);
   1.506 +	}
   1.507 +
   1.508 +TInt ShellFunction::Del(TDes& aPath,TUint aSwitches)
   1.509 +	{
   1.510 +	TParse filePath;
   1.511 +	if (aPath.Length()==0)
   1.512 +		return(KErrNone);
   1.513 +
   1.514 +	ShellFunction::StripQuotes(aPath);
   1.515 +
   1.516 +	GetFullPath(aPath,filePath);
   1.517 +	TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
   1.518 +	TUint switches=(recursive) ? CFileMan::ERecurse : 0;
   1.519 +	TInt r=CShell::TheFileMan->Delete(filePath.FullName(),switches);
   1.520 +	return(r);
   1.521 +	}
   1.522 +
   1.523 +
   1.524 +void ShellFunction::AlignTextIntoColumns(RPointerArray<HBufC>& aText)
   1.525 +//function which tries to arrange text as a set of columns if console width greater then the longest string
   1.526 +{
   1.527 +	TInt ind=0;
   1.528 +	if (aText.Count()<=0) return;
   1.529 +	//detect the longest string
   1.530 +	for (TInt i=0;i<aText.Count();i++)
   1.531 +		if (aText[i]->Length()>aText[ind]->Length())
   1.532 +			ind=i;
   1.533 +	TInt max_string_length=aText[ind]->Length()+2;
   1.534 +
   1.535 +	//calculate how many columns fit into the screen
   1.536 +	TInt number_of_columns=(CShell::TheConsole->ScreenSize().iWidth)/max_string_length;
   1.537 +
   1.538 +	//if we cannot fit more than one column into screen when we do nothing
   1.539 +	if (number_of_columns<2) return;
   1.540 +
   1.541 +	//calculate column width
   1.542 +	TInt column_width=CShell::TheConsole->ScreenSize().iWidth/number_of_columns;
   1.543 +
   1.544 +	TInt current_source_string=0;
   1.545 +	TInt current_destination_string=0;
   1.546 +
   1.547 +	TInt count=aText.Count();
   1.548 +	//join strings together into string which fits in a single line
   1.549 +	while (current_source_string<count)
   1.550 +		{
   1.551 +		TPtr string= aText[current_destination_string++]->Des();
   1.552 +		TInt to_skip=0;
   1.553 +
   1.554 +		for (TInt i=0;i<number_of_columns;i++)
   1.555 +			{
   1.556 +			if (current_source_string==count)
   1.557 +				break;
   1.558 +			//skip several characters to keep even distance between columns
   1.559 +			for (TInt j=0;j<to_skip;j++)
   1.560 +				string.Append(_L(" "));
   1.561 +
   1.562 +			if (i==0)
   1.563 +				string=(*aText[current_source_string]);
   1.564 +			else
   1.565 +				string.Append(*aText[current_source_string]);
   1.566 +			to_skip=column_width-aText[current_source_string]->Length();
   1.567 +			current_source_string++;
   1.568 +			}
   1.569 +		}
   1.570 +
   1.571 +	//resize aText array to the new size
   1.572 +
   1.573 +	for (TInt j=aText.Count()-1;j>=current_destination_string;j--)
   1.574 +		{
   1.575 +		delete aText[j];
   1.576 +		aText.Remove(j);
   1.577 +		}
   1.578 +
   1.579 +}
   1.580 +
   1.581 +
   1.582 +void ShellFunction::OutputContentsToConsole(RPointerArray<HBufC>& aText,TUint aSwitches)
   1.583 +//outputs content of the buffer to console according to settings passed in aSwitches
   1.584 +	{
   1.585 +	if ((aText.Count()>0)&&((aSwitches&TShellCommand::EWSwitch)!=0))
   1.586 +		AlignTextIntoColumns(aText);
   1.587 +
   1.588 +	for (TInt i=0;i<aText.Count();i++)
   1.589 +		{
   1.590 +		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),*aText[i]);
   1.591 +		CShell::OutputStringToConsole(EFalse,_L("\n"));
   1.592 +		delete aText[i];
   1.593 +		}
   1.594 +	//empty string array
   1.595 +	aText.Reset();
   1.596 +	}
   1.597 +
   1.598 +
   1.599 +void ShellFunction::OutputDirContentL(CDir* aDirList,RPointerArray<HBufC>& aText,TUint aSwitches)
   1.600 +//outputs content of a directory to console according to settings passed in aSwitches
   1.601 +	{
   1.602 +	TInt count=aDirList->Count();
   1.603 +	TInt fileCount=0, dirCount=0, printCount=0;
   1.604 +	TInt64 byteCount=0;
   1.605 +
   1.606 +	//compose an array of strings describing entries in the directory
   1.607 +	for (TInt j=0;j<count;j++)
   1.608 +		{
   1.609 +		HBufC* buf=NULL;
   1.610 +		TEntry entry=(*aDirList)[j];
   1.611 +		TDateTime modTime=entry.iModified.DateTime();
   1.612 +		if ((aSwitches&TShellCommand::EWSwitch)!=0)//if we are asked to output brief information about directory content
   1.613 +			{
   1.614 +			TInt length=(KMaxFileName>CShell::TheConsole->ScreenSize().iWidth)?KMaxFileName:CShell::TheConsole->ScreenSize().iWidth;
   1.615 +			buf = HBufC::NewL(length);
   1.616 +
   1.617 +			CleanupStack::PushL(buf);
   1.618 +			TPtr name=buf->Des();
   1.619 +			name=entry.iName;
   1.620 +
   1.621 +			if (entry.IsDir())
   1.622 +				{
   1.623 +				dirCount++;
   1.624 +				name.Insert(0,_L("["));
   1.625 +				name.Append(']');
   1.626 +				}
   1.627 +			else
   1.628 +				{
   1.629 +				byteCount+=entry.FileSize();
   1.630 +				fileCount++;
   1.631 +				}
   1.632 +			}
   1.633 +		else//if we are asked to output full information about directory content
   1.634 +			{
   1.635 +			buf = HBufC::NewL(KMaxFileName+100);//reserve additional space for the creation time information
   1.636 +			CleanupStack::PushL(buf);
   1.637 +			TPtr name=buf->Des();
   1.638 +			name=entry.iName;
   1.639 +
   1.640 +			if (entry.IsDir())
   1.641 +				{
   1.642 +				dirCount++;
   1.643 +				name.Format(_L(" %- 26S   <DIR>         %+02d/%+02d/%- 4d  %02d:%02d:%02d.%06d"),
   1.644 +											&entry.iName,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
   1.645 +				}
   1.646 +			else
   1.647 +				{
   1.648 +				TInt64 entrySize = entry.FileSize();
   1.649 +				byteCount+=entrySize;
   1.650 +				fileCount++;
   1.651 + 				name.Format(_L(" %- 32S%+ 15Lu   %+02d/%+02d/%- 4d  %02d:%02d:%02d.%06d"),
   1.652 + 											&entry.iName,entrySize,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
   1.653 +				}
   1.654 +			}
   1.655 +		User::LeaveIfError(aText.Append(buf ));
   1.656 +		printCount++;
   1.657 +		//print the contents if a screen size of data is available. This will prevent huge buffer allocation.
   1.658 +		if(printCount == CShell::TheConsole->ScreenSize().iHeight)
   1.659 +			{
   1.660 +			OutputContentsToConsole(aText,aSwitches);
   1.661 +			printCount=0;
   1.662 +			}
   1.663 +		CleanupStack::Pop();
   1.664 +
   1.665 +		}
   1.666 +	OutputContentsToConsole(aText,aSwitches);
   1.667 +
   1.668 +	//output summary information
   1.669 +	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("    %d File%c\n"),fileCount,(fileCount==1)?' ':'s');
   1.670 +	if (fileCount!=0)
   1.671 +		{
   1.672 +		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("  %lu byte%c\n"),byteCount,(fileCount==1)?' ':'s');
   1.673 +		}
   1.674 +
   1.675 +	TBuf<50> buf;// allocate string long enough for additional information(number of directories)
   1.676 +	buf.Format(_L("    %d Director"),dirCount);
   1.677 +	if (dirCount==1)
   1.678 +		buf.AppendFormat(_L("y\n"));
   1.679 +	else
   1.680 +		buf.AppendFormat(_L("ies\n"));
   1.681 +
   1.682 +	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
   1.683 +	}
   1.684 +
   1.685 +TInt ShellFunction::Dir(TDes& aPath,TUint aSwitches)
   1.686 +//
   1.687 +//	Modified December 1997, to sort entries alphabetically
   1.688 +//
   1.689 +	{
   1.690 +	ShellFunction::StripQuotes(aPath);
   1.691 +
   1.692 +	RDir    dir;
   1.693 +	RFile64 file;
   1.694 +	TParse dirParse;
   1.695 +//	Parses the given path to give a full path
   1.696 +	GetFullPath(aPath,dirParse);
   1.697 +//	Sets aPath to a full path name
   1.698 +	aPath=dirParse.FullName();
   1.699 +	if (aPath[aPath.Length()-1]==KPathDelimiter)
   1.700 +		aPath.Append('*');
   1.701 +	else if (aPath.Locate(KMatchAny)==KErrNotFound && aPath.Locate(KMatchOne)==KErrNotFound && file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir)!=KErrNone)
   1.702 +		aPath.Append(_L("\\*"));
   1.703 +	else file.Close();
   1.704 +
   1.705 +	TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
   1.706 +	if (r!=KErrNone)
   1.707 +		{
   1.708 +		CShell::TheConsole->Printf(_L("File or directory not found\n"));
   1.709 +		return(KErrNone);
   1.710 +		}
   1.711 +
   1.712 +	CDir* anEntryList;
   1.713 +	r=TheShell->TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,anEntryList);
   1.714 +	if (r!=KErrNone)
   1.715 +		{
   1.716 +		dir.Close();
   1.717 +		return(r);
   1.718 +		}
   1.719 +    CleanupStack::PushL(anEntryList);
   1.720 +
   1.721 +	//Sets the new length of path to the position of the last path delimiter +1
   1.722 +	aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
   1.723 +	CShell::TheConsole->Printf(_L("Directory of %S\n"),&aPath);
   1.724 +
   1.725 +	//allocate array to be used as an output buffer
   1.726 +	RPointerArray<HBufC>* text=new(ELeave) RPointerArray<HBufC>();
   1.727 +	TRAPD(error,OutputDirContentL(anEntryList,*text,aSwitches));
   1.728 +	//we are not interesed in the error code because we need empty the buffer in any case
   1.729 +	for (TInt i=0;i<text->Count();i++)
   1.730 +		delete (*text)[i];
   1.731 +	delete text;
   1.732 +	CleanupStack::PopAndDestroy(anEntryList);
   1.733 +	dir.Close();
   1.734 +	if (error )
   1.735 +		return (error);
   1.736 +	else
   1.737 +		return(KErrNone);
   1.738 +	};
   1.739 +
   1.740 +
   1.741 +TInt ShellFunction::Edit(TDes& /*aPath*/,TUint /*aSwitches*/)
   1.742 +//
   1.743 +//	Dummy, used by edlin (now retired)
   1.744 +//
   1.745 +	{
   1.746 +	return(KErrNone);
   1.747 +	}
   1.748 +
   1.749 +
   1.750 +TInt ShellFunction::Attrib(TDes& aPath,TUint aSwitches)
   1.751 +{
   1.752 +	ShellFunction::StripQuotes(aPath);
   1.753 +
   1.754 +//	Use TWord::NextWord(aPath) to find any spaces in the command line
   1.755 +	TWord nextWord(aPath);
   1.756 +	TInt r=nextWord.FindNextWord(aPath);
   1.757 +	TInt signal=0;
   1.758 +	const TPtrC settings[8]={(_L("+R")),(_L("-R")),(_L("+H")),(_L("-H")),(_L("+S")),(_L("-S")),(_L("+A")),(_L("-A"))};
   1.759 +	TInt numberOfSettings=(sizeof(settings)/sizeof(*settings));
   1.760 +
   1.761 +	if (r==KErrNotFound)	//	User just typed ATTRIB
   1.762 +		aPath.SetLength(aPath.Length());
   1.763 +	else if (r==0)				//	User typed ATTRIB aWord
   1.764 +		{						//	Check the word for a valid attributes
   1.765 +		for (TInt index=0; index<numberOfSettings; index++)
   1.766 +			{
   1.767 +			signal=(nextWord.iNextWord).FindF(settings[index]);
   1.768 +			if (signal!=KErrNotFound)
   1.769 +				break;
   1.770 +			}
   1.771 +		if (signal==KErrNotFound)	//	No valid attributes settings
   1.772 +			aPath.SetLength(aPath.Length());
   1.773 +		else						//	Valid attributes settings
   1.774 +			aPath.SetLength(r);
   1.775 +		}
   1.776 +	else	//	User typed ATTRIB aWord1 aWord2
   1.777 +		{	//	Check the word for a valid attributes switch
   1.778 +		while (r!=KErrNotFound)
   1.779 +			{
   1.780 +			for (TInt index=0; index<numberOfSettings; index++)
   1.781 +				{
   1.782 +				signal=(nextWord.iNextWord).FindF(settings[index]);
   1.783 +				if (signal!=KErrNotFound)
   1.784 +					break;
   1.785 +				}
   1.786 +			if (signal!=KErrNotFound)  //	Matched valid switches
   1.787 +				{
   1.788 +			//	Divide up command line
   1.789 +			//	Include all settings (in case of "ATTRIB aWord +R +S")
   1.790 +				nextWord.iRightString=aPath.Right(aPath.Length()-r);
   1.791 +				aPath.SetLength(r);
   1.792 +				break;
   1.793 +				}
   1.794 +			else							//	No valid switches found in word
   1.795 +				r=nextWord.FindNextWord(nextWord.iRightString);	//	Check the next word
   1.796 +				if (r==0)	//	Reached the end of a spaced command line without finding settings
   1.797 +					{
   1.798 +					nextWord.iRightString=aPath.Right(r);
   1.799 +					break;
   1.800 +					}
   1.801 +			}
   1.802 +		}
   1.803 +
   1.804 +	TParse dirParse;
   1.805 +	GetFullPath(aPath,dirParse);
   1.806 +	aPath=dirParse.FullName();
   1.807 +
   1.808 +	RFile64 file;
   1.809 +	if (aPath[aPath.Length()-1]==KPathDelimiter)
   1.810 +		aPath.Append('*');
   1.811 +	else if( (aPath.Locate(KMatchAny)==KErrNotFound) && (aPath.Locate(KMatchOne)==KErrNotFound) )
   1.812 +		{
   1.813 +		TInt error=file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir);
   1.814 +		if (error!=KErrNone)
   1.815 +			aPath.Append(_L("\\*"));//Path does not end in a valid file
   1.816 +		else
   1.817 +			file.Close();//	Path ends in a valid file
   1.818 +		}
   1.819 +
   1.820 +//	Changes attributes settings (files only) if requested and if necessary
   1.821 +	if (r!=KErrNotFound)
   1.822 +		{
   1.823 +		CDir* entryList;
   1.824 +		r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,entryList);
   1.825 +		if (r!=KErrNone)
   1.826 +			return (r);
   1.827 +		CleanupStack::PushL(entryList);
   1.828 +		TInt entryCount=entryList->Count();
   1.829 +//		Save session path
   1.830 +		TBuf<KShellMaxCommandLine> aSessionPath;
   1.831 +		r=TheShell->TheFs.SessionPath(aSessionPath);
   1.832 +//		Temporarily assign session path to be the path requested
   1.833 +//		Use the heap as we're running out of stack space
   1.834 +		HBufC* pTempPath=NULL;
   1.835 +		TRAP(r,pTempPath=HBufC::NewL(aPath.Length()))
   1.836 +		if (r!=KErrNone)
   1.837 +			{
   1.838 +			CleanupStack::PopAndDestroy(entryList);
   1.839 +			return (r);
   1.840 +			}
   1.841 +		*pTempPath=aPath;
   1.842 +		pTempPath->Des().SetLength(aPath.LocateReverse(KPathDelimiter)+1);
   1.843 +		r=TheShell->TheFs.SetSessionPath(pTempPath->Des());
   1.844 +		User::Free(pTempPath);
   1.845 +
   1.846 +//		Looks clumsy, but necessary to change attributes of files in higher level directories
   1.847 +		for (TInt i=0;i<entryCount;i++)
   1.848 +			{
   1.849 +			TEntry entry=(*entryList)[i];
   1.850 +			if (!entry.IsDir())
   1.851 +				{
   1.852 +				for (TInt index=0; index<numberOfSettings; index++)
   1.853 +					{
   1.854 +					TInt attToSet=0;
   1.855 +					TInt attToRemove=0;
   1.856 +					signal=(nextWord.iRightString).FindF(settings[index]);
   1.857 +					if (signal==KErrNotFound)
   1.858 +						continue;
   1.859 +					else
   1.860 +						switch (index)
   1.861 +						{
   1.862 +					case 0:
   1.863 +						attToSet|=KEntryAttReadOnly;
   1.864 +						break;
   1.865 +					case 1:
   1.866 +						attToRemove|=KEntryAttReadOnly;
   1.867 +						break;
   1.868 +					case 2:
   1.869 +						attToSet|=KEntryAttHidden;
   1.870 +						break;
   1.871 +					case 3:
   1.872 +						attToRemove|=KEntryAttHidden;
   1.873 +						break;
   1.874 +					case 4:
   1.875 +						attToSet|=KEntryAttSystem;
   1.876 +						break;
   1.877 +					case 5:
   1.878 +						attToRemove|=KEntryAttSystem;
   1.879 +						break;
   1.880 +					case 6:
   1.881 +						attToSet|=KEntryAttArchive;
   1.882 +						break;
   1.883 +					case 7:
   1.884 +						attToRemove|=KEntryAttArchive;
   1.885 +						break;
   1.886 +					default:	//	Will never reach here
   1.887 +						break;
   1.888 +						}
   1.889 +					r=TheShell->TheFs.SetAtt((entry.iName),attToSet,attToRemove);
   1.890 +					continue;
   1.891 +					}
   1.892 +				}
   1.893 +			else continue;
   1.894 +			}
   1.895 +//		Set session path to previous setting
   1.896 +		r=TheShell->TheFs.SetSessionPath(aSessionPath);
   1.897 +		CleanupStack::PopAndDestroy(entryList);
   1.898 +		}
   1.899 +
   1.900 +//	Runs to here if no requested attributes changes:
   1.901 +	CDir* alphaEntryList;
   1.902 +	r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,alphaEntryList);
   1.903 +	if (r!=KErrNone)
   1.904 +		return (r);
   1.905 +	TInt count=alphaEntryList->Count();
   1.906 +
   1.907 +	RDir dir;
   1.908 +	r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
   1.909 +	if (r!=KErrNone)
   1.910 +        {
   1.911 +        delete alphaEntryList;
   1.912 +		return(r);
   1.913 +        }
   1.914 +
   1.915 +	aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
   1.916 +
   1.917 +
   1.918 +	TEntry entry;
   1.919 +	TUint fileCount=0;
   1.920 +
   1.921 +//	Lists attributes settings (files only)
   1.922 +	for (TInt j=0;j<count;j++)
   1.923 +		{
   1.924 +		entry=alphaEntryList->operator[](j);
   1.925 +		if (!entry.IsDir())
   1.926 +			{
   1.927 +			TBuf<4> attrBuf=entry.IsReadOnly()?_L("R"):_L("");
   1.928 +			if (entry.IsHidden())
   1.929 +				attrBuf.Append('H');
   1.930 +			if (entry.IsSystem())
   1.931 +				attrBuf.Append('S');
   1.932 +			if (entry.IsArchive())
   1.933 +				attrBuf.Append('A');
   1.934 +			CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L(" %-10S %S%S\n"),&attrBuf, &aPath,&entry.iName);
   1.935 +			fileCount++;
   1.936 +			}
   1.937 +		}
   1.938 +
   1.939 +	dir.Close();
   1.940 +
   1.941 +	if (fileCount==0)
   1.942 +		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("No files found in %S\n"),&aPath);
   1.943 +
   1.944 +	delete alphaEntryList;
   1.945 +	return(KErrNone);
   1.946 +  }
   1.947 +
   1.948 +
   1.949 +
   1.950 +
   1.951 +
   1.952 +//--------------------------------------------------------
   1.953 +
   1.954 +/**
   1.955 +    Format TMediaType description.
   1.956 +
   1.957 +    @param  aDrvInfo    drive info structure
   1.958 +    @param  aPrintBuf   buffer where the information will be printed to.
   1.959 +*/
   1.960 +void FormatDrvMediaTypeInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
   1.961 +    {
   1.962 +        aPrintBuf.Format(_L("TMediaType:%d "),aDrvInfo.iType);
   1.963 +
   1.964 +        switch(aDrvInfo.iType)
   1.965 +        {
   1.966 +        case EMediaNotPresent:      aPrintBuf.Append(_L("EMediaNotPresent"));   break;
   1.967 +        case EMediaUnknown:	        aPrintBuf.Append(_L("EMediaUnknown"));      break;
   1.968 +        case EMediaFloppy:          aPrintBuf.Append(_L("EMediaFloppy"));       break;
   1.969 +        case EMediaHardDisk:        aPrintBuf.Append(_L("EMediaHardDisk"));     break;
   1.970 +        case EMediaCdRom:		    aPrintBuf.Append(_L("EMediaCdRom"));        break;
   1.971 +        case EMediaRam:             aPrintBuf.Append(_L("EMediaRam"));          break;
   1.972 +        case EMediaFlash:           aPrintBuf.Append(_L("EMediaFlash"));        break;
   1.973 +        case EMediaRom:             aPrintBuf.Append(_L("EMediaRom"));          break;
   1.974 +        case EMediaRemote:          aPrintBuf.Append(_L("EMediaRemote"));       break;
   1.975 +        case EMediaNANDFlash:       aPrintBuf.Append(_L("EMediaNANDFlash"));    break;
   1.976 +        case EMediaRotatingMedia:   aPrintBuf.Append(_L("EMediaRotatingMedia"));break;
   1.977 +        
   1.978 +        default:                    aPrintBuf.Append(_L("??? Unknown Type"));   break;
   1.979 +        };
   1.980 +
   1.981 +
   1.982 +        aPrintBuf.Append(_L("\n"));
   1.983 +    }
   1.984 +
   1.985 +//--------------------------------------------------------
   1.986 +
   1.987 +/**
   1.988 +    Format DriveAtt description.
   1.989 +
   1.990 +    @param  aDrvInfo    drive info structure
   1.991 +    @param  aPrintBuf   buffer where the information will be printed to.
   1.992 +*/
   1.993 +void FormatDriveAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
   1.994 +    {
   1.995 +        aPrintBuf.Format(_L("DriveAtt:0x%x "),aDrvInfo.iDriveAtt);
   1.996 +
   1.997 +        if(aDrvInfo.iDriveAtt & KDriveAttLocal)         aPrintBuf.Append(_L("KDriveAttLocal,"));
   1.998 +        if(aDrvInfo.iDriveAtt & KDriveAttRom)           aPrintBuf.Append(_L("KDriveAttRom,"));
   1.999 +        if(aDrvInfo.iDriveAtt & KDriveAttRedirected)    aPrintBuf.Append(_L("KDriveAttRedirected,"));
  1.1000 +        if(aDrvInfo.iDriveAtt & KDriveAttSubsted)       aPrintBuf.Append(_L("KDriveAttSubsted,"));
  1.1001 +        if(aDrvInfo.iDriveAtt & KDriveAttInternal)      aPrintBuf.Append(_L("KDriveAttInternal,"));
  1.1002 +        if(aDrvInfo.iDriveAtt & KDriveAttRemovable)     aPrintBuf.Append(_L("KDriveAttRemovable"));
  1.1003 +
  1.1004 +        if(aDrvInfo.iDriveAtt & KDriveAttRemote)        aPrintBuf.Append(_L("KDriveAttRemote"));
  1.1005 +        if(aDrvInfo.iDriveAtt & KDriveAttTransaction)   aPrintBuf.Append(_L("KDriveAttTransaction"));
  1.1006 +
  1.1007 +        if(aDrvInfo.iDriveAtt & KDriveAttPageable)              aPrintBuf.Append(_L("KDriveAttPageable"));
  1.1008 +        if(aDrvInfo.iDriveAtt & KDriveAttLogicallyRemovable)    aPrintBuf.Append(_L("KDriveAttLogicallyRemovable"));
  1.1009 +        if(aDrvInfo.iDriveAtt & KDriveAttHidden)                aPrintBuf.Append(_L("KDriveAttHidden"));
  1.1010 +
  1.1011 +        aPrintBuf.Append(_L("\n"));
  1.1012 +    }
  1.1013 +
  1.1014 +//--------------------------------------------------------
  1.1015 +
  1.1016 +/**
  1.1017 +    Format MediaAtt description.
  1.1018 +
  1.1019 +    @param  aDrvInfo    drive info structure
  1.1020 +    @param  aPrintBuf   buffer where the information will be printed to.
  1.1021 +*/
  1.1022 +void FormatMediaAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
  1.1023 +    {
  1.1024 +        aPrintBuf.Format(_L("MediaAtt:0x%x "),aDrvInfo.iMediaAtt);
  1.1025 +
  1.1026 +        if(aDrvInfo.iMediaAtt & KMediaAttVariableSize)      aPrintBuf.Append(_L("KMediaAttVariableSize,"));
  1.1027 +        if(aDrvInfo.iMediaAtt & KMediaAttDualDensity)       aPrintBuf.Append(_L("KMediaAttDualDensity,"));
  1.1028 +        if(aDrvInfo.iMediaAtt & KMediaAttFormattable)       aPrintBuf.Append(_L("KMediaAttFormattable,"));
  1.1029 +        if(aDrvInfo.iMediaAtt & KMediaAttWriteProtected)    aPrintBuf.Append(_L("KMediaAttWriteProtected,"));
  1.1030 +        if(aDrvInfo.iMediaAtt & KMediaAttLockable)          aPrintBuf.Append(_L("KMediaAttLockable,"));
  1.1031 +        if(aDrvInfo.iMediaAtt & KMediaAttLocked)            aPrintBuf.Append(_L("KMediaAttLocked"));
  1.1032 +
  1.1033 +        if(aDrvInfo.iMediaAtt & KMediaAttHasPassword)       aPrintBuf.Append(_L("KMediaAttHasPassword"));
  1.1034 +        if(aDrvInfo.iMediaAtt & KMediaAttReadWhileWrite)    aPrintBuf.Append(_L("KMediaAttReadWhileWrite"));
  1.1035 +        if(aDrvInfo.iMediaAtt & KMediaAttDeleteNotify)      aPrintBuf.Append(_L("KMediaAttDeleteNotify"));
  1.1036 +        if(aDrvInfo.iMediaAtt & KMediaAttPageable)          aPrintBuf.Append(_L("KMediaAttPageable"));
  1.1037 +        
  1.1038 +
  1.1039 +        aPrintBuf.Append(_L("\n"));
  1.1040 +    }
  1.1041 +
  1.1042 +//--------------------------------------------------------
  1.1043 +
  1.1044 +/**
  1.1045 +    Format TVolumeInfo description.
  1.1046 +
  1.1047 +    @param  volInfo     volume information
  1.1048 +    @param  aPrintBuf   buffer where the information will be printed to.
  1.1049 +*/
  1.1050 +void FormatVolInfo(const TVolumeInfo& volInfo , TDes& aPrintBuf)
  1.1051 +    {
  1.1052 +   	aPrintBuf.Format(_L("VolSz:%ld Free:%ld\n"),volInfo.iSize, volInfo.iFree);
  1.1053 +   	aPrintBuf.AppendFormat(_L("VolId:0x%x VolName:%S\n"),volInfo.iUniqueID, &volInfo.iName);
  1.1054 +    }
  1.1055 +
  1.1056 +//--------------------------------------------------------
  1.1057 +
  1.1058 +/** Bit flags that specify which information will be printed by PrintDrvInfo() */
  1.1059 +enum TPrintDrvInfoFlags
  1.1060 +{
  1.1061 +    EFSInfo         = 0x01, //-- file system information
  1.1062 +    EFSInfoEx       = 0x02, //-- extended file system information
  1.1063 +    EMediaTypeInfo  = 0x04, //-- media type
  1.1064 +    EMediaAttInfo   = 0x08, //-- media attributes etc.
  1.1065 +    EDrvAttInfo     = 0x10, //-- drive attributes etc
  1.1066 +    EVolInfo        = 0x20, //-- volume information
  1.1067 +
  1.1068 +    EAll            = 0xFFFF
  1.1069 +};
  1.1070 +
  1.1071 +//-----------------------------------------------------------------------------------------------------------------------
  1.1072 +/**
  1.1073 +    Prints information about specified drive.
  1.1074 +
  1.1075 +    @param  aFs         file system object
  1.1076 +    @param  aDrvNum     drive number
  1.1077 +    @param  apConsole   pointer to the console to print information into
  1.1078 +    @param  aFlags      specifies which information to print out, @see TPrintDrvInfoFlags
  1.1079 +
  1.1080 +    @return standard error code
  1.1081 +*/
  1.1082 +TInt PrintDrvInfo(RFs& aFs, TInt aDrvNum, CConsoleBase* apConsole, TUint aFlags = EAll)
  1.1083 +    {
  1.1084 +	TInt        nRes;
  1.1085 +	TDriveInfo 	driveInfo;
  1.1086 +	TVolumeInfo volInfo;
  1.1087 +	TBuf<256>   Buf;
  1.1088 +
  1.1089 +	//-- get drive info
  1.1090 +	nRes = aFs.Drive(driveInfo, aDrvNum);
  1.1091 +	if(nRes != KErrNone)
  1.1092 +		{
  1.1093 +		CShell::TheConsole->Printf(_L("Error: %d\n"), nRes);
  1.1094 +		return nRes;   //-- can't get information about the drive
  1.1095 +		}
  1.1096 +
  1.1097 +	
  1.1098 +    nRes = aFs.Volume(volInfo, aDrvNum);
  1.1099 +    const TBool bVolumeOK  = (nRes == KErrNone);
  1.1100 +	if(!bVolumeOK)
  1.1101 +	{//-- can't get information about the volume. It might be just corrupt/unformatted
  1.1102 +		CShell::TheConsole->Printf(_L("Error getting volume info. code: %d\n"), nRes);
  1.1103 +        if(nRes == KErrCorrupt)
  1.1104 +        {
  1.1105 +            CShell::TheConsole->Printf(_L("The volume might be corrupted or not formatted.\n"));
  1.1106 +        }
  1.1107 +	}
  1.1108 +
  1.1109 +
  1.1110 +	//-- Print out information about file system installed
  1.1111 +	if(aFlags & EFSInfo)
  1.1112 +    {
  1.1113 +        
  1.1114 +        apConsole->Printf(_L("\nDrive %c: number:%d\n"), 'A'+aDrvNum, aDrvNum);
  1.1115 +
  1.1116 +	    //-- print the FS name
  1.1117 +	    if(aFs.FileSystemName(Buf, aDrvNum) == KErrNone)
  1.1118 +	    {
  1.1119 +	        TFSName fsName;
  1.1120 +            
  1.1121 +            nRes = aFs.FileSystemSubType(aDrvNum, fsName); 
  1.1122 +            if(nRes == KErrNone && Buf.CompareF(fsName) !=KErrNone)
  1.1123 +            {
  1.1124 +                Buf.AppendFormat(_L(" (%S)"), &fsName);
  1.1125 +            }
  1.1126 +
  1.1127 +            //-- try to find out primary extension name if present
  1.1128 +            nRes = aFs.ExtensionName(fsName, aDrvNum, 0);
  1.1129 +            if(nRes == KErrNone)
  1.1130 +            {   
  1.1131 +                 Buf.AppendFormat(_L(" PExt:%S"), &fsName);
  1.1132 +            }
  1.1133 +
  1.1134 +
  1.1135 +            apConsole->Printf(_L("Mounted FS:%S\n"), &Buf);
  1.1136 +
  1.1137 +            //-- print out the list of supported file systems if there are more than 1
  1.1138 +            nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, 0+1); //-- try to get 2nd child name
  1.1139 +            if(nRes == KErrNone)
  1.1140 +            {
  1.1141 +                Buf.Copy(_L("Supported FS: "));
  1.1142 +                for(TInt i=0; ;++i)
  1.1143 +                {
  1.1144 +                    nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, i); 
  1.1145 +                    if(nRes != KErrNone)
  1.1146 +                        break;
  1.1147 +
  1.1148 +                    Buf.AppendFormat(_L("%S, "), &fsName);
  1.1149 +                }
  1.1150 +            
  1.1151 +                Buf.Append(_L("\n"));
  1.1152 +                apConsole->Printf(Buf);
  1.1153 +            }
  1.1154 +
  1.1155 +
  1.1156 +
  1.1157 +            //-- print out FileSystem volume finalisation info
  1.1158 +            if(bVolumeOK && (aFlags & EFSInfoEx))
  1.1159 +            {
  1.1160 +
  1.1161 +                TPckgBuf<TBool> boolPckg;
  1.1162 +                nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveFinalised, boolPckg);
  1.1163 +                if(nRes == KErrNone)
  1.1164 +                {
  1.1165 +                    if(boolPckg() >0)
  1.1166 +                        apConsole->Printf(_L("Volume Finalised\n"));
  1.1167 +                    else
  1.1168 +                        apConsole->Printf(_L("Volume Not finalised\n"));
  1.1169 +                }
  1.1170 +            }
  1.1171 +	    }
  1.1172 +    }//if(aFlags & EFSInfo)
  1.1173 +
  1.1174 +	//-- print media attributes
  1.1175 +	if(aFlags & EMediaTypeInfo)
  1.1176 +    {
  1.1177 +        FormatDrvMediaTypeInfo(driveInfo, Buf);
  1.1178 +	    apConsole->Printf(Buf);
  1.1179 +
  1.1180 +	}
  1.1181 +    
  1.1182 +    //-- print drive attributes
  1.1183 +	if(aFlags & EDrvAttInfo)
  1.1184 +    {
  1.1185 +        FormatDriveAttInfo(driveInfo, Buf);
  1.1186 +	    apConsole->Printf(Buf);
  1.1187 +    }
  1.1188 +
  1.1189 +    //-- print media attributes
  1.1190 +	if(aFlags & EMediaAttInfo)
  1.1191 +    {
  1.1192 +	    FormatMediaAttInfo(driveInfo, Buf);
  1.1193 +	    apConsole->Printf(Buf);
  1.1194 +    }
  1.1195 +
  1.1196 +
  1.1197 +	//-- print volume information
  1.1198 +	if(bVolumeOK && (aFlags & EVolInfo))
  1.1199 +    {
  1.1200 +	    FormatVolInfo(volInfo, Buf);
  1.1201 +	    apConsole->Printf(Buf);
  1.1202 +    }
  1.1203 +	
  1.1204 +    return KErrNone;
  1.1205 +	}
  1.1206 +
  1.1207 +//-----------------------------------------------------------------------------------------------------------------------
  1.1208 +
  1.1209 +/**
  1.1210 +    Extracts drive specifier from the given string that shall look like 'd:\' or 'd:'
  1.1211 +    And converts it to the drive number.
  1.1212 +    
  1.1213 +    @param  aStr a string with drive specifier
  1.1214 +    @return Drive number EDriveA..EDriveZ if drive letter is correct
  1.1215 +            negative value (KErrArgument) if drive specifier is incorrect
  1.1216 +*/
  1.1217 +TInt DoExtractDriveLetter(const TDesC& aStr)
  1.1218 +{
  1.1219 +    TLex    lex(aStr);    
  1.1220 +    TPtrC   token;
  1.1221 +
  1.1222 +    lex.SkipSpace();
  1.1223 +    token.Set(lex.NextToken());
  1.1224 +    
  1.1225 +    if(token.Length() < 2 || token.Length() > 3 || token[1] != ':')
  1.1226 +        return KErrArgument;
  1.1227 +
  1.1228 +    if(token.Length() == 3 && token[2] != '\\')
  1.1229 +        return KErrArgument;
  1.1230 +
  1.1231 +    const TChar chDrv = token[0];
  1.1232 +    const TInt drvNum = chDrv.GetUpperCase() - (TUint)'A'; //-- drive number
  1.1233 +
  1.1234 +    if(drvNum < 0 || drvNum > EDriveZ)
  1.1235 +        return KErrArgument;
  1.1236 +
  1.1237 +
  1.1238 +    //-- ensure that the only drive token specified
  1.1239 +    token.Set(lex.NextToken());
  1.1240 +    if(token.Length())
  1.1241 +        return KErrArgument;
  1.1242 +
  1.1243 +    return drvNum;
  1.1244 +
  1.1245 +}
  1.1246 +
  1.1247 +
  1.1248 +//-----------------------------------------------------------------------------------------------------------------------
  1.1249 +//
  1.1250 +// Print information about specified drive or about all present drives in the system.
  1.1251 +//
  1.1252 +// DRVINFO [DriveLetter:[\]] [/p]
  1.1253 +//
  1.1254 +//          if drive letter is specified print out information about only this one.
  1.1255 +//			/P : pause after each drive
  1.1256 +//
  1.1257 +TInt ShellFunction::DrvInfo(TDes& aArgs, TUint aSwitches)
  1.1258 +	{
  1.1259 +
  1.1260 +	TInt nDrv=-1;
  1.1261 +
  1.1262 +	const TInt KCmdLineLen = aArgs.Length();
  1.1263 +	if(KCmdLineLen == 0)
  1.1264 +		{//-- print information about all drives in the system
  1.1265 +		nDrv = -1;
  1.1266 +		}
  1.1267 +	else
  1.1268 +		{//-- print info about specified drive
  1.1269 +		nDrv = DoExtractDriveLetter(aArgs);
  1.1270 +        if(nDrv < 0)
  1.1271 +            {
  1.1272 +            CShell::TheConsole->Printf(_L("Invalid drive specifier!\n"));    
  1.1273 +            return KErrNone;
  1.1274 +            }
  1.1275 +		}
  1.1276 +
  1.1277 +	TInt nRes;
  1.1278 +	TDriveList 	driveList;
  1.1279 +
  1.1280 +	//-- get drives list
  1.1281 +	nRes=TheShell->TheFs.DriveList(driveList);
  1.1282 +	if(nRes != KErrNone)
  1.1283 +		{
  1.1284 +		CShell::TheConsole->Printf(_L("\nError: %d"), nRes);
  1.1285 +		return nRes;
  1.1286 +		}
  1.1287 +
  1.1288 +	if(nDrv >=0)
  1.1289 +		{//-- the drive is specified
  1.1290 +		if(!driveList[nDrv])
  1.1291 +			{
  1.1292 +			CShell::TheConsole->Printf(_L("Invalid drive specification\n"));
  1.1293 +			return KErrNone;
  1.1294 +			}
  1.1295 +
  1.1296 +		PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
  1.1297 +		}
  1.1298 +	else
  1.1299 +		{//-- print information about all drives in the system
  1.1300 +		for (nDrv=0; nDrv < KMaxDrives; nDrv++)
  1.1301 +			{
  1.1302 +			if(!driveList[nDrv])
  1.1303 +				continue;   //-- skip unexisting drive
  1.1304 +
  1.1305 +			PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
  1.1306 +
  1.1307 +			if(aSwitches & TShellCommand::EPSwitch)
  1.1308 +				{//-- /p switch, pause after each drive
  1.1309 +				CShell::TheConsole->Printf(_L("\n--- press any key to continue or Esc to exit ---\n"));
  1.1310 +
  1.1311 +				TKeyCode key = CShell::TheConsole->Getch();
  1.1312 +				if (key==EKeyEscape)
  1.1313 +					break;
  1.1314 +				}
  1.1315 +			else
  1.1316 +				{
  1.1317 +				CShell::TheConsole->Printf(_L("\n----------\n"));
  1.1318 +				}
  1.1319 +		}
  1.1320 +	}
  1.1321 +
  1.1322 +	return KErrNone;
  1.1323 +	}
  1.1324 +
  1.1325 +//-----------------------------------------------------------------------------------------------------------------------
  1.1326 +
  1.1327 +/**
  1.1328 +    Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
  1.1329 +    @param  aSrc        source string
  1.1330 +    @param  aPattern    pattern to look for
  1.1331 +    @param  aToken      if the aPattern is found in the string, will contain characters from the pattern end to the next space.
  1.1332 +
  1.1333 +    @return EFalse if the aPattern wasn't found in aSrc
  1.1334 +            ETrue otherwise and the rest of the token in aToken
  1.1335 +*/
  1.1336 +static TBool DoFindToken(const TDesC& aSrc, const TDesC& aPattern, TPtrC& aToken)
  1.1337 +{
  1.1338 +    TLex    lex(aSrc);
  1.1339 +    TPtrC   token;
  1.1340 +
  1.1341 +    for(;;)
  1.1342 +    {
  1.1343 +        lex.SkipSpace();
  1.1344 +        token.Set(lex.NextToken());
  1.1345 +
  1.1346 +        if(token.Length() == 0)
  1.1347 +            return EFalse;
  1.1348 +
  1.1349 +        if(token.FindF(aPattern) == 0)
  1.1350 +        {//-- found a requires patern, extract substring next to it
  1.1351 +            aToken.Set(token.Right(token.Length() - aPattern.Length()));
  1.1352 +            break;
  1.1353 +        }
  1.1354 +
  1.1355 +
  1.1356 +    }
  1.1357 +
  1.1358 +    return ETrue;
  1.1359 +}
  1.1360 +
  1.1361 +
  1.1362 +
  1.1363 +
  1.1364 +
  1.1365 +//-----------------------------------------------------------------------------------------------------------------------
  1.1366 +TInt DoDismountFS(RFs& aFs, TInt aDrvNum)
  1.1367 +{
  1.1368 +    TInt        nRes;
  1.1369 +    TBuf<40>    fsName;
  1.1370 +
  1.1371 +    nRes = aFs.FileSystemName(fsName, aDrvNum);
  1.1372 +
  1.1373 +    if(nRes != KErrNone)
  1.1374 +        return KErrNotFound;//-- nothing to dismount
  1.1375 +        
  1.1376 +    nRes = aFs.DismountFileSystem(fsName, aDrvNum);
  1.1377 +    if(nRes != KErrNone)
  1.1378 +    {
  1.1379 +        CShell::TheConsole->Printf(_L("Can't dismount FS!\n"));
  1.1380 +        return nRes;
  1.1381 +    }
  1.1382 +    else
  1.1383 +    {
  1.1384 +    CShell::TheConsole->Printf(_L("'%S' filesystem dismounted from drive %c:\n"), &fsName, 'A'+aDrvNum);
  1.1385 +    return KErrNone;
  1.1386 +    }
  1.1387 +}
  1.1388 +
  1.1389 +//-----------------------------------------------------------------------------------------------------------------------
  1.1390 +TInt DoRemountFS(RFs& aFs, TInt aDrvNum)
  1.1391 +{
  1.1392 +    TInt        nRes;
  1.1393 +    TBuf<40>    fsName;
  1.1394 +    TBuf<40>    pextName;
  1.1395 +
  1.1396 +    //-- 1. get file system name
  1.1397 +    nRes = aFs.FileSystemName(fsName, aDrvNum);
  1.1398 +    if(nRes != KErrNone)
  1.1399 +        return KErrNotFound;
  1.1400 +
  1.1401 +    //-- 2. find out if the drive sync/async
  1.1402 +    TPckgBuf<TBool> drvSyncBuf;
  1.1403 +    TBool& drvSynch = drvSyncBuf();
  1.1404 +
  1.1405 +    nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveSync, drvSyncBuf);
  1.1406 +    if(nRes != KErrNone)
  1.1407 +    {//-- pretend that the drive is asynch. in the case of file system being corrupted. this is 99.9% true
  1.1408 +       drvSynch = EFalse;
  1.1409 +    }
  1.1410 +   
  1.1411 +    //-- 3. find out primary extension name if it is present; we will need to add it again when mounting the FS
  1.1412 +    //-- other extensions (non-primary) are not supported yet
  1.1413 +    nRes = aFs.ExtensionName(pextName, aDrvNum, 0);
  1.1414 +    if(nRes != KErrNone)
  1.1415 +    {
  1.1416 +        pextName.SetLength(0);
  1.1417 +    }
  1.1418 +    
  1.1419 +    //-- 3.1 check if the drive has non-primary extensions, fail in this case
  1.1420 +    {
  1.1421 +        TBuf<40> extName;
  1.1422 +        nRes = aFs.ExtensionName(extName, aDrvNum, 1);
  1.1423 +        if(nRes == KErrNone)
  1.1424 +        {   
  1.1425 +            CShell::TheConsole->Printf(_L("Non-primary extensions are not supported!\n"));
  1.1426 +            return KErrNotSupported;
  1.1427 +        }
  1.1428 +    }
  1.1429 +
  1.1430 +    //-- 4. dismount the file system
  1.1431 +    nRes = DoDismountFS(aFs, aDrvNum);
  1.1432 +    if(nRes != KErrNone)
  1.1433 +        return nRes;
  1.1434 +
  1.1435 +    //-- 5. mount the FS back
  1.1436 +    if(pextName.Length() > 0)
  1.1437 +    {//-- we need to mount FS with the primary extension
  1.1438 +        nRes = aFs.AddExtension(pextName);
  1.1439 +        if(nRes != KErrNone && nRes != KErrAlreadyExists)
  1.1440 +        {
  1.1441 +            return nRes;
  1.1442 +        }
  1.1443 +        
  1.1444 +        nRes = aFs.MountFileSystem(fsName, pextName, aDrvNum, drvSynch);
  1.1445 +    }
  1.1446 +    else
  1.1447 +    {//-- the FS did not have primary extension
  1.1448 +        nRes = aFs.MountFileSystem(fsName, aDrvNum, drvSynch);
  1.1449 +    }
  1.1450 +
  1.1451 +    if(nRes == KErrNone)
  1.1452 +    {
  1.1453 +        CShell::TheConsole->Printf(_L("mounted filesystem:%S\n"), &fsName);
  1.1454 +    }
  1.1455 +
  1.1456 +    return nRes;
  1.1457 +}
  1.1458 +
  1.1459 +//-----------------------------------------------------------------------------------------------------------------------
  1.1460 +/**
  1.1461 +    Mount or dismount the file system on the specified drive.
  1.1462 +
  1.1463 +    MOUNT <DriveLetter:[\]> <FSY:xxx> <FS:yyy> [PEXT:zzz] [/S] [/U]
  1.1464 +  
  1.1465 +    xxx is the *.fsy file system plugin name, like "elocal.fsy" or "elocal"
  1.1466 +    yyy is the file system name that the fsy module exports, like "FAT"
  1.1467 +    zzz is the optional parameter that specifies primary extension name
  1.1468 +
  1.1469 +    /u dismounts a filesystem on the specified drive; e.g. "mount d: /u"
  1.1470 +    /s for mounting FS specifies that the drive will be mounted as synchronous one.
  1.1471 +    /f for forcing mounting the FS; the previous one will be automatically dismounted
  1.1472 +    /r remount existing FS (dismount and mount it back)
  1.1473 +*/
  1.1474 +TInt ShellFunction::MountFileSystem(TDes& aArgs, TUint aSwitches)
  1.1475 +{
  1.1476 +	ShellFunction::StripQuotes(aArgs);
  1.1477 +    aArgs.UpperCase();
  1.1478 + 
  1.1479 +    TLex        lex(aArgs);
  1.1480 +    TInt        nRes;
  1.1481 +    TBuf<40>    fsName;
  1.1482 +    RFs&        fs = TheShell->TheFs; 
  1.1483 +
  1.1484 +
  1.1485 +    //-- extract drive specification; this must be 1st token
  1.1486 +    _LIT(KErrInvalidDrive, "Invalid drive specifier\n");
  1.1487 +    lex.SkipSpace();
  1.1488 +    TPtrC token = lex.NextToken(); 
  1.1489 +    
  1.1490 +    nRes = DoExtractDriveLetter(token);
  1.1491 +    if(nRes < 0)
  1.1492 +    {
  1.1493 +        CShell::TheConsole->Printf(KErrInvalidDrive);
  1.1494 +        return KErrArgument;
  1.1495 +    }
  1.1496 +
  1.1497 +    const TInt drvNum = nRes; //-- this is the drive number;
  1.1498 +
  1.1499 +
  1.1500 +    //-- remounting the existing FS (/R switch)
  1.1501 +    if(aSwitches & TShellCommand::ERSwitch)
  1.1502 +    {
  1.1503 +        nRes = DoRemountFS(fs, drvNum);
  1.1504 +        return nRes;
  1.1505 +    }
  1.1506 +    
  1.1507 +    //-- check if we dismounting the FS (/U switch)
  1.1508 +    if(aSwitches & TShellCommand::EUSwitch)
  1.1509 +    {
  1.1510 +        nRes = DoDismountFS(fs, drvNum);
  1.1511 +        
  1.1512 +        if(nRes == KErrNotFound)
  1.1513 +        {//-- nothing to dismount
  1.1514 +            CShell::TheConsole->Printf(_L("specified drive doesn't have FS mounted\n"));
  1.1515 +            return KErrNone;
  1.1516 +        }
  1.1517 +
  1.1518 +        return nRes;
  1.1519 +    }
  1.1520 +    
  1.1521 +    //-- check if we need to forcedly dismount the existing FS (/F switch)
  1.1522 +    if(aSwitches & TShellCommand::EFSwitch)
  1.1523 +    {
  1.1524 +        nRes = DoDismountFS(fs, drvNum);
  1.1525 +        
  1.1526 +        if(nRes != KErrNotFound && nRes !=KErrNone)
  1.1527 +            return nRes;
  1.1528 +    }
  1.1529 +
  1.1530 +    //-- request to mount the filesystem
  1.1531 +
  1.1532 +    //-- 1. check that the specified drive doesn't have already mounted file system
  1.1533 +    nRes = fs.FileSystemName(fsName, drvNum);
  1.1534 +    if(nRes == KErrNone)
  1.1535 +    {
  1.1536 +        CShell::TheConsole->Printf(_L("specified drive already has '%S' file system mounted.\n"), &fsName);
  1.1537 +        CShell::TheConsole->Printf(_L("Dismount it first using '/U' switch or use '/F' switch.\n"));
  1.1538 +        return KErrNone;
  1.1539 +    }
  1.1540 +
  1.1541 +    //-- 2. check '/S' switch that specifies synchronous drive
  1.1542 +    const TBool bDrvSynch = aSwitches & TShellCommand::ESSwitch;
  1.1543 +
  1.1544 +    //-- 3. extract FSY name, file system name and optional primary extension name from the command line parameters
  1.1545 +    _LIT(KFSY_Param,     "fsy:");
  1.1546 +    _LIT(KFsName_Param,  "fs:");
  1.1547 +    _LIT(KPrimExt_Param, "pext:");
  1.1548 +
  1.1549 +    TPtrC ptrFSYName;
  1.1550 +    TPtrC ptrFSName;
  1.1551 +    TPtrC ptrPExtName;
  1.1552 +
  1.1553 +    if(!DoFindToken(aArgs, KFSY_Param, ptrFSYName))
  1.1554 +    {//-- FSY plugin name, like "elocal.fsy"
  1.1555 +        CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFSY_Param);
  1.1556 +        return KErrNone;
  1.1557 +    }
  1.1558 +
  1.1559 +    if(!DoFindToken(aArgs, KFsName_Param, ptrFSName))
  1.1560 +    {//-- file system name, like "FAT"
  1.1561 +        CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFsName_Param);
  1.1562 +        return KErrNone;
  1.1563 +    }
  1.1564 +
  1.1565 +    //-- note: it is possible to find out the file system name from loaded .fsy plugin.
  1.1566 +    //-- but it will require some coding. Probably later.
  1.1567 +
  1.1568 +
  1.1569 +    //-- optional primary extension name, like "something.fxt"
  1.1570 +    const TBool bPExtPresent = DoFindToken(aArgs, KPrimExt_Param, ptrPExtName);
  1.1571 +
  1.1572 +
  1.1573 +    //-- add new file system + optional extension
  1.1574 +    nRes = fs.AddFileSystem(ptrFSYName);
  1.1575 +    if(nRes != KErrNone && nRes != KErrAlreadyExists)
  1.1576 +    {
  1.1577 +        CShell::TheConsole->Printf(_L("Can't load '%S' file system plugin!\n"), &ptrFSYName);        
  1.1578 +        return nRes;
  1.1579 +    }
  1.1580 +
  1.1581 +    if(bPExtPresent)
  1.1582 +    {
  1.1583 +        nRes = fs.AddExtension(ptrPExtName);
  1.1584 +        if(nRes != KErrNone && nRes != KErrAlreadyExists)
  1.1585 +        {
  1.1586 +            CShell::TheConsole->Printf(_L("Can't load '%S' FS extension plugin!\n"), &ptrPExtName);        
  1.1587 +            return nRes;
  1.1588 +        }
  1.1589 +    }
  1.1590 +
  1.1591 +    //-- 4. mount new file system + optional primary extension
  1.1592 +    if(bPExtPresent)
  1.1593 +    {
  1.1594 +        nRes = fs.MountFileSystem(ptrFSName, ptrPExtName, drvNum, bDrvSynch);
  1.1595 +    }
  1.1596 +    else
  1.1597 +    {
  1.1598 +        nRes = fs.MountFileSystem(ptrFSName, drvNum, bDrvSynch);
  1.1599 +    }
  1.1600 +
  1.1601 +    CShell::TheConsole->Printf(_L("Mounting new file system...\n"));        
  1.1602 +
  1.1603 +    if(nRes != KErrNone && nRes != KErrCorrupt)
  1.1604 +    {//-- KErrCorrupt might mean that the FS mounted OK onto the drive, but ve volume itself needs formatting
  1.1605 +        CShell::TheConsole->Printf(_L("Error mounting the filesystem! (%d)\n"), nRes);
  1.1606 +        return nRes;
  1.1607 +    }
  1.1608 +
  1.1609 +
  1.1610 +    PrintDrvInfo(fs, drvNum, CShell::TheConsole, EFSInfo | EVolInfo);
  1.1611 +
  1.1612 +    return KErrNone;
  1.1613 +}
  1.1614 +
  1.1615 +
  1.1616 +//-----------------------------------------------------------------------------------------------------------------------
  1.1617 +
  1.1618 +/**
  1.1619 +    Format the specified disk
  1.1620 +
  1.1621 +    FORMAT DriveLetter:[\] [fat12|fat16|fat32] [spc:X] [rs:Y] [ft:Z] [/Q] [/S] [/E]
  1.1622 +
  1.1623 +        fat12|fat16|fat32 : specifies explicitly FAT type to format drive with (if it is a FAT drive)
  1.1624 +        spc:X   "X" specifies FAT sectors per cluster, e.g. spc:16
  1.1625 +        rs:Y    "Y" specifies the number of reserved sectors  (FAT FS only)
  1.1626 +        ft:Z    "Z" specifies the number of FAT tables 1 or 2 (FAT FS only)
  1.1627 +		/Q : Quick Format
  1.1628 +		/S : Special Format
  1.1629 +		/E : Remove Password and Format
  1.1630 +        /F : force formatting, even if there are files opened on the drive
  1.1631 +*/
  1.1632 +
  1.1633 +TInt ShellFunction::Format(TDes& aPath, TUint aSwitches)
  1.1634 +	{
  1.1635 +    _LIT(KFormatStars,"********************");
  1.1636 +
  1.1637 +	using namespace FileSystem_FAT;
  1.1638 +
  1.1639 +    ShellFunction::StripQuotes(aPath);
  1.1640 +    aPath.UpperCase();
  1.1641 +
  1.1642 +    TUint fmtMode = ESpecialFormat;
  1.1643 +
  1.1644 +    //-- Format /Q - quick format
  1.1645 +    if (aSwitches & TShellCommand::EQSwitch)
  1.1646 +		fmtMode|=EQuickFormat;
  1.1647 +
  1.1648 +    //-- Format /S - special format
  1.1649 +	if (aSwitches & TShellCommand::ESSwitch)
  1.1650 +		fmtMode|=ESpecialFormat;
  1.1651 +
  1.1652 +	//-- Format /E - force erase
  1.1653 +    if (aSwitches & TShellCommand::EESwitch)
  1.1654 +		fmtMode|=EForceErase;
  1.1655 +
  1.1656 +	//-- Format /F - force format. The volume will be formatted even if there are files or directories opened on this drive
  1.1657 +    if (aSwitches & TShellCommand::EFSwitch)
  1.1658 +		fmtMode|=EForceFormat;
  1.1659 +
  1.1660 +
  1.1661 +	TInt    fmtCnt = 0;
  1.1662 +	RFormat format;
  1.1663 +	TInt    nRes;
  1.1664 +    TLex    lex(aPath);
  1.1665 +    
  1.1666 +    //-- 1st token - drive path; it shall look like "d:"
  1.1667 +    lex.SkipSpace();
  1.1668 +    TPtrC ptrPath = lex.NextToken();    
  1.1669 +    
  1.1670 +    const TInt nDrv = DoExtractDriveLetter(ptrPath);
  1.1671 +    if(nDrv < 0 )
  1.1672 +        {
  1.1673 +        CShell::TheConsole->Printf(_L("type \"format /?\" for help.\n"));
  1.1674 +        return KErrNone;
  1.1675 +        }
  1.1676 +
  1.1677 +    enum TFmtState
  1.1678 +        {
  1.1679 +        EFsNameNotSpecified,
  1.1680 +        EFormattingFAT,
  1.1681 +        EFormattingOtherFS
  1.1682 +        };
  1.1683 +    
  1.1684 +    
  1.1685 +    TFmtState formattingState = EFsNameNotSpecified;
  1.1686 +    TName fsName; //-- file system name
  1.1687 +
  1.1688 +
  1.1689 +    TVolFormatParamBuf volFmtParamBuf;
  1.1690 +    TVolFormatParam& volFmtParam = volFmtParamBuf();
  1.1691 +    
  1.1692 +
  1.1693 +
  1.1694 +    //-- 2nd token - file system name. 
  1.1695 +    //-- FAT fs is a special case, because it has subtypes; FAT FS name can be: FAT, FAT12, FAT16, FAT32
  1.1696 +    //-- everything else is considered as another file system name
  1.1697 +    lex.SkipSpace();
  1.1698 +    TPtrC ptrFsName = lex.NextToken();    
  1.1699 +    TFatSubType fatSubType = ENotSpecified;
  1.1700 +    
  1.1701 +    if(ptrFsName.Length() > 0)
  1.1702 +        {//-- there is a 2nd token, though it is not guaranteed to be the FS name
  1.1703 +        formattingState = EFormattingOtherFS;
  1.1704 +        
  1.1705 +        if(ptrFsName.FindF(KFileSystemName_FAT) == 0)
  1.1706 +            {//-- it looks like "FATxx"
  1.1707 +            fsName.Copy(KFileSystemName_FAT); 
  1.1708 +
  1.1709 +            if(ptrFsName.CompareF(KFileSystemName_FAT) == 0)
  1.1710 +                fatSubType = ENotSpecified; //-- generic "FAT", no subtype
  1.1711 +            else if(ptrFsName.CompareF(KFSSubType_FAT12) == 0)
  1.1712 +                fatSubType = EFat12;
  1.1713 +            else if(ptrFsName.CompareF(KFSSubType_FAT16) == 0)
  1.1714 +                fatSubType = EFat16;
  1.1715 +            else if(ptrFsName.CompareF(KFSSubType_FAT32) == 0)
  1.1716 +                fatSubType = EFat32;
  1.1717 +            else
  1.1718 +                fsName.Copy(ptrFsName); //-- none of the FAT types, probably some weird FS name.
  1.1719 +            }
  1.1720 +        else
  1.1721 +            {
  1.1722 +            fsName.Copy(ptrFsName); 
  1.1723 +            }
  1.1724 +        }
  1.1725 +
  1.1726 +    if(fsName == KFileSystemName_FAT) 
  1.1727 +        formattingState = EFormattingFAT;
  1.1728 +    
  1.1729 +    volFmtParam.Init();
  1.1730 +
  1.1731 +    if(formattingState != EFsNameNotSpecified)
  1.1732 +        volFmtParam.SetFileSystemName(fsName);
  1.1733 +
  1.1734 +    //-- process formatting parameters if they are present
  1.1735 +
  1.1736 +    _LIT(KTok_SPC,      "spc:");    //-- "sectors per cluster"; valid for: FAT, exFAT
  1.1737 +    _LIT(KTok_RsvdSect, "rs:");     //-- "reserved sectors"   ; valid for: FAT
  1.1738 +    _LIT(KTok_NumFATs,  "ft:");     //-- "number of FATs"     ; valid for: FAT, exFAT
  1.1739 +    _LIT(KFsNameExFat,  "exfat");
  1.1740 +
  1.1741 +    TPtrC   token;
  1.1742 +    TPtrC   ptrParams = lex.Remainder();
  1.1743 +    TLex    lexParam;
  1.1744 +    TInt    nVal;
  1.1745 +
  1.1746 +    
  1.1747 +    //-- if we formatting FAT, process FAT-specific formatting parameters
  1.1748 +    if(formattingState == EFormattingFAT)
  1.1749 +        {
  1.1750 +        //-- Changing base class via derived class interface is OK here, all derived classes has the same layout and size as TVolFormatParam
  1.1751 +        TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
  1.1752 +        
  1.1753 +        volFmtParamFAT.Init();
  1.1754 +
  1.1755 +        //-- FAT sub type
  1.1756 +        if(fatSubType != ENotSpecified)
  1.1757 +            volFmtParamFAT.SetFatSubType(fatSubType);
  1.1758 +        
  1.1759 +        //-- process "Sectors per cluster" token
  1.1760 +        if(DoFindToken(ptrParams, KTok_SPC, token))
  1.1761 +            {
  1.1762 +            lexParam.Assign(token);
  1.1763 +            lexParam.SkipSpace();
  1.1764 +            nRes = lexParam.Val(nVal);
  1.1765 +            if(nRes == KErrNone)
  1.1766 +                {
  1.1767 +                volFmtParamFAT.SetSectPerCluster(nVal);
  1.1768 +                }
  1.1769 +                else
  1.1770 +                {
  1.1771 +                CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
  1.1772 +                return KErrNone;
  1.1773 +                }
  1.1774 +            }
  1.1775 +
  1.1776 +        //-- process "reserved sectors" token
  1.1777 +        if(DoFindToken(ptrParams, KTok_RsvdSect, token))
  1.1778 +            {
  1.1779 +            lexParam.Assign(token);
  1.1780 +            lexParam.SkipSpace();
  1.1781 +            nRes = lexParam.Val(nVal);
  1.1782 +            if(nRes == KErrNone && nVal >0 )
  1.1783 +                {
  1.1784 +                volFmtParamFAT.SetReservedSectors(nVal);
  1.1785 +                }
  1.1786 +            else
  1.1787 +                {
  1.1788 +                CShell::TheConsole->Printf(_L("Invalid Reserved Sectors value!\n"));
  1.1789 +                return KErrNone;
  1.1790 +                }
  1.1791 +            }
  1.1792 +        
  1.1793 +        //-- process "FAT tables" token
  1.1794 +        if(DoFindToken(ptrParams, KTok_NumFATs, token))
  1.1795 +            {
  1.1796 +            lexParam.Assign(token);
  1.1797 +            lexParam.SkipSpace();
  1.1798 +            nRes = lexParam.Val(nVal);
  1.1799 +            if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
  1.1800 +                {
  1.1801 +                volFmtParamFAT.SetNumFATs(nVal);
  1.1802 +                }
  1.1803 +            else
  1.1804 +                {
  1.1805 +                CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
  1.1806 +                return KErrNone;
  1.1807 +                }
  1.1808 +            }
  1.1809 +         
  1.1810 +        }//if(formattingState == EFormattingFAT)
  1.1811 +    else if(formattingState == EFormattingOtherFS && fsName.CompareF(KFsNameExFat)==0)
  1.1812 +        {//-- this is actually a h***k. exFAT exported public header file with specific data structures might not be available at all.
  1.1813 +
  1.1814 +        //-- this is more serious hack. The parameters layout (SPC & NumFatTables) in the structure is the same for FAT and exFAT
  1.1815 +        //-- use TVolFormatParam_FAT because this code doesn't know about TVolFormatParam_exFAT
  1.1816 +        TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
  1.1817 +
  1.1818 +        //-- process "Sectors per cluster" token
  1.1819 +        if(DoFindToken(ptrParams, KTok_SPC, token))
  1.1820 +            {
  1.1821 +            lexParam.Assign(token);
  1.1822 +            lexParam.SkipSpace();
  1.1823 +            nRes = lexParam.Val(nVal);
  1.1824 +            if(nRes == KErrNone)
  1.1825 +                {
  1.1826 +                volFmtParamFAT.SetSectPerCluster(nVal);
  1.1827 +                }
  1.1828 +                else
  1.1829 +                {
  1.1830 +                CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
  1.1831 +                return KErrNone;
  1.1832 +                }
  1.1833 +            }
  1.1834 +
  1.1835 +        //-- process "FAT tables" token
  1.1836 +        if(DoFindToken(ptrParams, KTok_NumFATs, token))
  1.1837 +            {
  1.1838 +            lexParam.Assign(token);
  1.1839 +            lexParam.SkipSpace();
  1.1840 +            nRes = lexParam.Val(nVal);
  1.1841 +            if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
  1.1842 +                {
  1.1843 +                volFmtParamFAT.SetNumFATs(nVal);
  1.1844 +                }
  1.1845 +            else
  1.1846 +                {
  1.1847 +                CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
  1.1848 +                return KErrNone;
  1.1849 +                }
  1.1850 +            }
  1.1851 +    
  1.1852 +        }
  1.1853 +    
  1.1854 +
  1.1855 +    //-------- actual formatting
  1.1856 +    if(formattingState == EFsNameNotSpecified)
  1.1857 +        {
  1.1858 +        nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt);
  1.1859 +        }
  1.1860 +    else
  1.1861 +        {
  1.1862 +        CShell::TheConsole->Printf(_L("The new file system is:%S\n"), &fsName);
  1.1863 +        nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt, volFmtParamBuf);
  1.1864 +        }
  1.1865 +
  1.1866 +	if(nRes == KErrNone)
  1.1867 +	    {
  1.1868 +	    while(fmtCnt && nRes == KErrNone)
  1.1869 +		    {
  1.1870 +		    TInt length=(104-fmtCnt)/5;
  1.1871 +		    length=Min(length,KFormatStars().Length());
  1.1872 +		    TPtrC stars=KFormatStars().Left(length);
  1.1873 +		    CShell::TheConsole->Printf(_L("\r%S"),&stars);
  1.1874 +		    nRes=format.Next(fmtCnt);
  1.1875 +		    }
  1.1876 +	    
  1.1877 +        format.Close();
  1.1878 +
  1.1879 +        if(nRes == KErrNone)
  1.1880 +            {
  1.1881 +            CShell::TheConsole->Printf(_L("\r%S"),&KFormatStars);
  1.1882 +	        CShell::NewLine();
  1.1883 +	        }
  1.1884 +        
  1.1885 +	    }
  1.1886 +
  1.1887 +
  1.1888 +    //-- format errors processing
  1.1889 +    if(nRes != KErrNone)
  1.1890 +        {
  1.1891 +        CShell::TheConsole->Printf(_L("Format failed.\n"));
  1.1892 +        }
  1.1893 +
  1.1894 +    switch(nRes)
  1.1895 +        {
  1.1896 +        case KErrNone:
  1.1897 +            CShell::TheConsole->Printf(_L("Format complete.\n"));
  1.1898 +        break;
  1.1899 +
  1.1900 +        
  1.1901 +        case KErrArgument: //-- FORMAT has rejected specified parameters
  1.1902 +            CShell::TheConsole->Printf(_L("Possible reason: Invalid combination of formatting parameters.\n"));
  1.1903 +            nRes = KErrNone;
  1.1904 +        break;
  1.1905 +
  1.1906 +        case KErrNotSupported: //-- trying to format SD card with parameters or not supported FS name specified
  1.1907 +            CShell::TheConsole->Printf(_L("Possible reasons: media does not support special formatting or specified file system is not supported\n"));
  1.1908 +            nRes = KErrNone;
  1.1909 +        break;
  1.1910 +
  1.1911 +        case KErrNotFound: //-- possible reason: unrecognisable media and automounter FS + formatting without specifying the FS name
  1.1912 +            CShell::TheConsole->Printf(_L("Possible reason: Unable to chose appropriate file system (not specified)\n"));
  1.1913 +            nRes = KErrNone;
  1.1914 +        break;
  1.1915 +
  1.1916 +
  1.1917 +        default:
  1.1918 +        break;
  1.1919 +        };
  1.1920 +    
  1.1921 +    
  1.1922 +    return nRes;
  1.1923 +    }
  1.1924 +
  1.1925 +//-----------------------------------------------------------------------------------------------------------------------
  1.1926 +
  1.1927 +TInt ShellFunction::Hexdump(TDes& aPath,TUint aSwitches)
  1.1928 +	{
  1.1929 +	ShellFunction::StripQuotes(aPath);
  1.1930 +
  1.1931 +	ParsePath(aPath);
  1.1932 +	RFile file;
  1.1933 +	TInt r=file.Open(TheShell->TheFs,aPath,EFileStream);
  1.1934 +	if (r!=KErrNone)
  1.1935 +		return(r);
  1.1936 +
  1.1937 +	TInt offset=0;
  1.1938 +	for (;;)
  1.1939 +		{
  1.1940 +		const TInt KLineLength = 16;
  1.1941 +
  1.1942 +		TBuf8<KLineLength> line;
  1.1943 +		r=file.Read(line);
  1.1944 +		if (r != KErrNone || line.Length() == 0)
  1.1945 +			break;
  1.1946 +
  1.1947 +		TBuf<KLineLength*3+2> hexaRep;
  1.1948 +		TBuf<KLineLength> asciiRep;
  1.1949 +		for (TInt i=0; i<KLineLength; i++)
  1.1950 +			{
  1.1951 +			if (i == KLineLength/2)
  1.1952 +				{
  1.1953 +				hexaRep.Append(' ');
  1.1954 +				hexaRep.Append(i<line.Length() ? '|' : ' ');
  1.1955 +				}
  1.1956 +
  1.1957 +			hexaRep.Append(' ');
  1.1958 +
  1.1959 +			if (i<line.Length())
  1.1960 +				{
  1.1961 +				hexaRep.AppendNumFixedWidth(line[i], EHex, 2);
  1.1962 +				asciiRep.Append(TChar(line[i]).IsPrint() ? line[i] : '.');
  1.1963 +				}
  1.1964 +			else
  1.1965 +				hexaRep.AppendFill(' ', 2);
  1.1966 +			}
  1.1967 +
  1.1968 +		_LIT(KPrompt , " Hit escape to quit hexdump or any other key to continue\n");
  1.1969 +		_LIT(KLineFmt, " %+07x0:%S %S\n");
  1.1970 +		TKeyCode key=CShell::OutputStringToConsole(KPrompt ,(aSwitches&TShellCommand::EPSwitch)!=0,KLineFmt, offset++,&hexaRep, &asciiRep);
  1.1971 +
  1.1972 +		if (key==EKeyEscape)
  1.1973 +				break;
  1.1974 +		}
  1.1975 +
  1.1976 +	if (r == KErrNone)
  1.1977 +		CShell::NewLine();
  1.1978 +
  1.1979 +	file.Close();
  1.1980 +	return r;
  1.1981 +	}
  1.1982 +
  1.1983 +/**
  1.1984 +    Create a file. The file can be empty or filled with random data.
  1.1985 +    The maximal file size depends on the file system of the drive.
  1.1986 +
  1.1987 +    Gobble <file name> <aaaa|0xbbbb>  [/E]
  1.1988 +
  1.1989 +    aaaa file size decimal
  1.1990 +    bbbb file size hexadecimal, shall be prefixed with '0x'
  1.1991 +    
  1.1992 +    /e for creating an empty file, do not fill it with data
  1.1993 +*/
  1.1994 +TInt ShellFunction::Gobble(TDes& aPath,TUint aSwitches)
  1.1995 +	{
  1.1996 +	ShellFunction::StripQuotes(aPath);
  1.1997 +
  1.1998 +	TInt fileNameLen=aPath.LocateReverse(' ');
  1.1999 +	if (fileNameLen==KErrNotFound)	//	No spaces implies no filelength specified
  1.2000 +		{
  1.2001 +		CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
  1.2002 +		return (KErrNone);
  1.2003 +		}
  1.2004 +
  1.2005 +	TInt fileLength=(aPath.Length()-fileNameLen);
  1.2006 +	if (fileLength>16)
  1.2007 +		return (KErrTooBig);	//	Too many digits - too large!
  1.2008 +	TBuf<16> rightString=aPath.Right(fileLength);
  1.2009 +	aPath.SetLength(fileNameLen);
  1.2010 +
  1.2011 +	TLex size(rightString);
  1.2012 +	size.SkipSpace();
  1.2013 +	TRadix radix=ParseHexaPrefixIfAny(size);
  1.2014 +	
  1.2015 +    TInt64 fileSize;
  1.2016 +	TInt r=size.Val(fileSize,radix);
  1.2017 +	if (r!=KErrNone || ! size.Eos())
  1.2018 +		{
  1.2019 +		CShell::TheConsole->Printf(_L("Please specify a file length\n"));
  1.2020 +		return (KErrNone);
  1.2021 +		}
  1.2022 +
  1.2023 +	if (aPath.Length()==0)
  1.2024 +		aPath=_L("GOBBLE.DAT");
  1.2025 +
  1.2026 +	TParse fileName;
  1.2027 +	GetFullPath(aPath,fileName);
  1.2028 +	RFile64 file;
  1.2029 +
  1.2030 +    const TInt    KBufSize=65536; //-- buffer size for writing data
  1.2031 +    const TUint32 K1Megabyte = 1<<20; //-- 1M, 1048576
  1.2032 +    TInt64 cntBytes = 0;
  1.2033 +    TUint32 cntMegaBytes =0;
  1.2034 +
  1.2035 +    //-- allocate buffer for data
  1.2036 +    RBuf8 buf;
  1.2037 +    r = buf.CreateMax(KBufSize);
  1.2038 +    if(r != KErrNone)
  1.2039 +        return r;
  1.2040 +
  1.2041 +    //-- initialize buffer with random rubbish
  1.2042 +    //Mem::Fill((void*)buf.Ptr(),KBufSize,0xa3);
  1.2043 +    {
  1.2044 +        TInt64 rndSeed = Math::Random();
  1.2045 +        for(TInt i=0; i<KBufSize; ++i)
  1.2046 +        {
  1.2047 +            buf[i] = (TUint8)Math::Rand(rndSeed);
  1.2048 +        }
  1.2049 +    }
  1.2050 +
  1.2051 +
  1.2052 +    TInt64  rem = fileSize;
  1.2053 +    TTime startTime;
  1.2054 +    TTime endTime;
  1.2055 +    TTimeIntervalSeconds timeTaken;
  1.2056 +
  1.2057 +    startTime.UniversalTime(); //-- take start time
  1.2058 +
  1.2059 +    r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
  1.2060 +    if(r != KErrNone)
  1.2061 +        goto fail;
  1.2062 +
  1.2063 +    //-- this can make write faster on rugged fat.
  1.2064 +    if(aSwitches&TShellCommand::EESwitch)
  1.2065 +    {//-- /e switch is specified, create an empty file without writing data
  1.2066 +        CShell::TheConsole->Printf(_L("Creating an empty file, size:%LD bytes\n"), fileSize);
  1.2067 +    }
  1.2068 +
  1.2069 +    r=file.SetSize(fileSize);
  1.2070 +    if(r != KErrNone)
  1.2071 +        goto fail;
  1.2072 +
  1.2073 +
  1.2074 +    if(!(aSwitches&TShellCommand::EESwitch))
  1.2075 +    {//-- fill created file with randomn data
  1.2076 +
  1.2077 +	    while(rem)
  1.2078 +	    {
  1.2079 +	        const TInt s=(TInt)Min((TInt64)KBufSize, rem);
  1.2080 +
  1.2081 +            r=file.Write(buf, s);
  1.2082 +		    if(r!=KErrNone)
  1.2083 +		        goto fail;
  1.2084 +
  1.2085 +            rem-=s;
  1.2086 +
  1.2087 +            //-- print out number of megabytes written
  1.2088 +            cntBytes+=s;
  1.2089 +            if(cntBytes > 0 && (cntBytes & (K1Megabyte-1))==0)
  1.2090 +            {
  1.2091 +                ++cntMegaBytes;
  1.2092 +                CShell::TheConsole->Printf(_L("%u MB written.\n"),cntMegaBytes);
  1.2093 +            }
  1.2094 +        }//while(rem)
  1.2095 +
  1.2096 +    }
  1.2097 +
  1.2098 +    file.Close();
  1.2099 +    endTime.UniversalTime(); //-- take end time
  1.2100 +    buf.Close();
  1.2101 +
  1.2102 +    endTime.SecondsFrom(startTime, timeTaken);
  1.2103 +
  1.2104 +    CShell::TheConsole->Printf(_L("Total bytes written:%LD\n"), cntBytes);
  1.2105 +    CShell::TheConsole->Printf(_L("Time taken:%d Sec.\n"), timeTaken.Int());
  1.2106 +
  1.2107 +    return r;
  1.2108 +
  1.2109 +    //-- failure.
  1.2110 + fail:
  1.2111 +    file.Close();
  1.2112 +    buf.Close();
  1.2113 +    if(r!= KErrAlreadyExists) //this is to ensure that an existing file does not get deleted
  1.2114 +	    CShell::TheFs.Delete(fileName.FullName());
  1.2115 +
  1.2116 +    CShell::TheConsole->Printf(_L("Error - could not create file, code:%d\n"), r);
  1.2117 +
  1.2118 +    return r;
  1.2119 +	}
  1.2120 +
  1.2121 +TInt ShellFunction::Md(TDes& aPath,TUint /*aSwitches*/)
  1.2122 +	{
  1.2123 +	if (aPath.Length()==0)
  1.2124 +		return(KErrBadName);
  1.2125 +
  1.2126 +	ShellFunction::StripQuotes(aPath);
  1.2127 +
  1.2128 +	if (aPath[aPath.Length()-1]!=KPathDelimiter)
  1.2129 +		aPath.Append(KPathDelimiter);
  1.2130 +
  1.2131 +	TParse dirPath;
  1.2132 +	TInt r = GetFullPath(aPath,dirPath);
  1.2133 +	if(r!=KErrNone)
  1.2134 +		{
  1.2135 +		return(r);
  1.2136 +		}
  1.2137 +	return(TheShell->TheFs.MkDir(dirPath.FullName()));
  1.2138 +	}
  1.2139 +
  1.2140 +TInt ShellFunction::Move(TDes& aPath,TUint aSwitches)
  1.2141 +	{
  1.2142 +
  1.2143 +//	Modified to add more helpful error messages and allow spaced filenames
  1.2144 +	ShellFunction::StripQuotes(aPath);
  1.2145 +
  1.2146 +	TBuf<KShellMaxCommandLine> newName;
  1.2147 +	TBuf<KShellMaxCommandLine> tempPath=aPath;
  1.2148 +	RFile64 file;
  1.2149 +	TWord   word(aPath);
  1.2150 +
  1.2151 +	TInt r=word.FindNextWord(aPath);
  1.2152 +//	Check if the word returned is a valid filename.  If not, scan the next
  1.2153 +//	word too in case the filename contains spaces.  If, at the end of the
  1.2154 +//	the line, the filename is not recognised, it is invalid.  If there are no
  1.2155 +//	spaces the user has not used the correct format for this command.
  1.2156 +
  1.2157 +	while (r>0)
  1.2158 +		{
  1.2159 +		newName=aPath.Right(aPath.Length()-r);
  1.2160 +		tempPath.SetLength(r);
  1.2161 +		TParse oldName;
  1.2162 +		TInt result=GetFullPath(tempPath,oldName);
  1.2163 +		if (result!=KErrNone)
  1.2164 +			return(r);
  1.2165 +
  1.2166 +		TBool validFileOrDir = EFalse;
  1.2167 +
  1.2168 +		result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
  1.2169 +		if (result==KErrNone)	//	A valid filename
  1.2170 +			{
  1.2171 +			file.Close();
  1.2172 +			validFileOrDir = ETrue;
  1.2173 +			}
  1.2174 +		else	//	Not a valid filename - move one word along the command line
  1.2175 +			{
  1.2176 +			// Not a valid filename - Could be a directory...
  1.2177 +			RDir directory;
  1.2178 +			result=directory.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclusive|KEntryAttDir);
  1.2179 +			if (result == KErrNone)
  1.2180 +				{
  1.2181 +				directory.Close();
  1.2182 +				validFileOrDir = ETrue;
  1.2183 +				}
  1.2184 +			}
  1.2185 +
  1.2186 +		if(validFileOrDir)
  1.2187 +			{
  1.2188 +			TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
  1.2189 +			TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
  1.2190 +			r=CShell::TheFileMan->Move(oldName.FullName(),newName,switches);
  1.2191 +			if (r==KErrAccessDenied)
  1.2192 +				{
  1.2193 +				CShell::TheConsole->Printf(_L("Access denied - cannot move %S\n"),&tempPath);
  1.2194 +				CShell::TheConsole->Printf(_L("To move %Sinto directory %S append \\ to the full destination\n"),&tempPath,&newName);
  1.2195 +				return (KErrNone);
  1.2196 +				}
  1.2197 +			return(r);
  1.2198 +			}
  1.2199 +
  1.2200 +		r=word.FindNextWord(word.iRightString);
  1.2201 +		}
  1.2202 +	if (r<0)		//	r = some error code
  1.2203 +		return (r);	//	Error in filename or destination
  1.2204 +	else						//	r = 0
  1.2205 +		return (KErrNotFound);
  1.2206 +	}
  1.2207 +
  1.2208 +TInt GetChunkInfo(TAny* aPtr)
  1.2209 +	{
  1.2210 +
  1.2211 +	TFindChunk findHb;
  1.2212 +	TFullName* namePtr=(TFullName*)aPtr;
  1.2213 +	findHb.Find(*namePtr);
  1.2214 +	TFullName aFN;
  1.2215 +	findHb.Next(aFN);
  1.2216 +	RChunk c;
  1.2217 +	TInt r=c.Open(findHb);
  1.2218 +	if(r==KErrPermissionDenied)
  1.2219 +		{
  1.2220 +		CShell::TheConsole->Printf(_L("...Chunk is protected. No info available.\n"));
  1.2221 +		}
  1.2222 +	else
  1.2223 +		{
  1.2224 +		CShell::TheConsole->Printf(_L("...Size %dk MaxSize %dk Base 0x%x\n"),c.Size()/1024,c.MaxSize()/1024,c.Base());
  1.2225 +		c.Close();
  1.2226 +		}
  1.2227 +/*
  1.2228 +#if defined (__WINS__)
  1.2229 +	c.Close();
  1.2230 +#else
  1.2231 +	if (aFN.Match(_L("*ESHELL*"))<0)
  1.2232 +		c.Close();
  1.2233 +#endif
  1.2234 +*/
  1.2235 +	return r;
  1.2236 +	};
  1.2237 +
  1.2238 +TInt GetThreadInfo(TAny* aPtr)
  1.2239 +//	New function added by WR, November 1997
  1.2240 +	{
  1.2241 +	TBuf<80> detail;
  1.2242 +	TFindThread* findHb = (TFindThread*)aPtr;
  1.2243 +	RThread t;
  1.2244 +	TInt err = t.Open(*findHb);
  1.2245 +	if (err != KErrNone)
  1.2246 +		{
  1.2247 +		detail.Format(_L("... can't open thread, err=%d\n"), err);
  1.2248 +		CShell::TheConsole->Printf(detail);
  1.2249 +		return KErrNone;
  1.2250 +		}
  1.2251 +
  1.2252 +	TExitType exit = t.ExitType();
  1.2253 +	TBuf<KMaxExitCategoryName> exitCat=t.ExitCategory();
  1.2254 +	TThreadId threadId = t.Id();
  1.2255 +	TUint id = *(TUint*)&threadId;
  1.2256 +	RProcess proc;
  1.2257 +	TInt pid = t.Process(proc);
  1.2258 +	if (pid==KErrNone)
  1.2259 +		{
  1.2260 +		TProcessId procId = proc.Id();
  1.2261 +		pid = *(TInt*)&procId;
  1.2262 +		proc.Close();
  1.2263 +		}
  1.2264 +
  1.2265 +	switch (exit)
  1.2266 +		{
  1.2267 +	case EExitPending:
  1.2268 +		detail.Format(_L("... ID %d (Proc %d), running\n"), id, pid);
  1.2269 +		break;
  1.2270 +	case EExitPanic:
  1.2271 +	//	lint -e50
  1.2272 +		detail.Format(_L("... ID %d (Proc %d), panic \"%S\" %d\n"), id, pid,
  1.2273 +			&exitCat, t.ExitReason());
  1.2274 +		break;
  1.2275 +	case EExitKill:
  1.2276 +		detail.Format(_L("... ID %d (Proc %d), killed %d\n"), id, pid, t.ExitReason());
  1.2277 +		break;
  1.2278 +	case EExitTerminate:
  1.2279 +		detail.Format(_L("... ID %d (Proc %d), terminated %d\n"), id, pid, t.ExitReason());
  1.2280 +		break;
  1.2281 +	default:
  1.2282 +		detail.Format(_L("... ID %d (Proc %d), ?exit type %d?\n"), id, pid, exit);
  1.2283 +		break;
  1.2284 +		}
  1.2285 +	t.Close();
  1.2286 +	CShell::TheConsole->Printf(detail);
  1.2287 +	return KErrNone;
  1.2288 +	};
  1.2289 +//	End of modification
  1.2290 +
  1.2291 +// Class for showing information about processes
  1.2292 +class TShowProcInfo
  1.2293 +	{
  1.2294 +public:
  1.2295 +	TInt DisplayHelp();
  1.2296 +	TInt DisplayMessage(const TFullName& aName);
  1.2297 +	TInt DisplayCmdUnknown();
  1.2298 +	TInt GetAll(const TDes& aName);
  1.2299 +	TInt GetProcesses(const TDes& aName);
  1.2300 +	TInt GetThreads(const TDes& aName);
  1.2301 +	TInt GetChunks(const TDes& aName);
  1.2302 +	TInt GetServers(const TDes& aName);
  1.2303 +//	TInt GetSessions(const TDes& aName);
  1.2304 +	TInt GetLibraries(const TDes& aName);
  1.2305 +//	TInt GetLogicalChannels(const TDes& aName);
  1.2306 +	TInt GetLogicalDevices(const TDes& aName);
  1.2307 +	TInt GetPhysicalDevices(const TDes& aName);
  1.2308 +	TInt GetSemaphores(const TDes& aName);
  1.2309 +	TInt GetMutexes(const TDes& aName);
  1.2310 +private:
  1.2311 +	void DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription);
  1.2312 +	TInt Prepare(const TFullName& aName);
  1.2313 +	TInt Prepare(const TFullName& aName,TCallBack& aCallBack);
  1.2314 +	TInt Display(TFullName& aName);
  1.2315 +	TFullName iPrevName;
  1.2316 +	TCallBack iCallBack;
  1.2317 +	TBool useCallBack;
  1.2318 +	};
  1.2319 +
  1.2320 +TInt TShowProcInfo::DisplayHelp()
  1.2321 +	{
  1.2322 +
  1.2323 +	DisplayHelpLine(_L("H or ?"),_L("Show Help"));
  1.2324 +	DisplayHelpLine(_L("Q"),_L("Quit Process Status Mode"));
  1.2325 +	DisplayHelpLine(_L("X<name>"),_L("Switch to a particular Process domain"));
  1.2326 +	DisplayHelpLine(_L("X"),_L("Go Back to standard Process Status Mode"));
  1.2327 +	DisplayHelpLine(_L("A"),_L("Display all container objects"));
  1.2328 +	DisplayHelpLine(_L("P"),_L("List all Processes (irrespective of current domain)"));
  1.2329 +	DisplayHelpLine(_L("T"),_L("List Threads"));
  1.2330 +	DisplayHelpLine(_L("C"),_L("List Chunks, their sizes, maximum sizes and addresses"));
  1.2331 +	DisplayHelpLine(_L("S"),_L("List Servers"));
  1.2332 +//	DisplayHelpLine(_L("I"),_L("List Sessions"));
  1.2333 +	DisplayHelpLine(_L("L"),_L("List Libraries"));
  1.2334 +//	DisplayHelpLine(_L("G"),_L("List Logical Channels"));
  1.2335 +	DisplayHelpLine(_L("V"),_L("List Logical Devices"));
  1.2336 +	DisplayHelpLine(_L("D"),_L("List Physical Devices"));
  1.2337 +	DisplayHelpLine(_L("E"),_L("List Semaphores"));
  1.2338 +	DisplayHelpLine(_L("M"),_L("List Mutexes"));
  1.2339 +	return KErrNone;
  1.2340 +	}
  1.2341 +
  1.2342 +TInt TShowProcInfo::DisplayMessage(const TFullName& aMessage)
  1.2343 +	{
  1.2344 +	CShell::OutputStringToConsole(ETrue,aMessage);
  1.2345 +	CShell::NewLine();
  1.2346 +	return KErrNone;
  1.2347 +	}
  1.2348 +
  1.2349 +TInt TShowProcInfo::DisplayCmdUnknown()
  1.2350 +	{
  1.2351 +	CShell::OutputStringToConsole(ETrue,_L("Not supported\n"));
  1.2352 +	return KErrNone;
  1.2353 +	}
  1.2354 +
  1.2355 +TInt TShowProcInfo::GetAll(const TDes& aName)
  1.2356 +	{
  1.2357 +
  1.2358 +	GetProcesses(aName);
  1.2359 +	GetThreads(aName);
  1.2360 +	GetChunks(aName);
  1.2361 +	GetServers(aName);
  1.2362 +//	GetSessions(aName);
  1.2363 +	GetLibraries(aName);
  1.2364 +//	GetLogicalChannels(aName);
  1.2365 +	GetLogicalDevices(aName);
  1.2366 +	GetPhysicalDevices(aName);
  1.2367 +	GetSemaphores(aName);
  1.2368 +	GetMutexes(aName);
  1.2369 +	return KErrNone;
  1.2370 +	}
  1.2371 +
  1.2372 +TInt TShowProcInfo::GetProcesses(const TDes& aName)
  1.2373 +	{
  1.2374 +
  1.2375 +	TFindProcess findHb;
  1.2376 +	findHb.Find(aName);
  1.2377 +	TFullName name;
  1.2378 +	Prepare(_L("PROCESSES"));
  1.2379 +	while (findHb.Next(name)==KErrNone)
  1.2380 +		{
  1.2381 +		Display(name);
  1.2382 +		}
  1.2383 +	return KErrNone;
  1.2384 +	}
  1.2385 +
  1.2386 +TInt TShowProcInfo::GetThreads(const TDes& aName)
  1.2387 +	{
  1.2388 +	TInt threads=0;
  1.2389 +	TFindThread findHb;
  1.2390 +	findHb.Find(aName);
  1.2391 +	TFullName name;
  1.2392 +	TAny* findPtr=(TAny*)&findHb;
  1.2393 +
  1.2394 +//	Modified by WR, November 1997
  1.2395 +	TCallBack threadCallBack(GetThreadInfo,findPtr);
  1.2396 +	Prepare(_L("THREADS"),threadCallBack);
  1.2397 +	while (findHb.Next(name)==KErrNone)
  1.2398 +		{
  1.2399 +		Display(name);
  1.2400 +		threads += 1;
  1.2401 +		}
  1.2402 +	if (threads==0)
  1.2403 +		{
  1.2404 +		TFullName message;
  1.2405 +		message.Format(_L("? No threads called %S"), &aName);
  1.2406 +		DisplayMessage(message);
  1.2407 +		}
  1.2408 +	return KErrNone;
  1.2409 +//	End of modification
  1.2410 +	}
  1.2411 +
  1.2412 +
  1.2413 +TInt TShowProcInfo::GetChunks(const TDes& aName)
  1.2414 +	{
  1.2415 +
  1.2416 +	TFindChunk findHb;
  1.2417 +	findHb.Find(aName);
  1.2418 +	TFullName name;
  1.2419 +	TAny* namePtr=(TAny*)&name;
  1.2420 +	TCallBack chunkCallBack(GetChunkInfo,namePtr);
  1.2421 +	Prepare(_L("CHUNKS & SIZES"),chunkCallBack);
  1.2422 +	TInt totalChunkSize=0;
  1.2423 +	TInt protectedChunks = 0;
  1.2424 +	while (findHb.Next(name)==KErrNone)
  1.2425 +		{
  1.2426 +		Display(name);
  1.2427 +		RChunk c;
  1.2428 +		TInt r=c.Open(findHb);
  1.2429 +		if(r!=KErrNone)
  1.2430 +			++protectedChunks;
  1.2431 +		else
  1.2432 +			{
  1.2433 +			totalChunkSize+=c.Size()/1024;
  1.2434 +			c.Close();
  1.2435 +			}
  1.2436 +/*
  1.2437 +#if defined(__WINS__)
  1.2438 +		c.Close();
  1.2439 +#else
  1.2440 +		if (name.Match(_L("*ESHELL*"))<0)
  1.2441 +			c.Close();
  1.2442 +#endif
  1.2443 +*/
  1.2444 +		}
  1.2445 +	CShell::OutputStringToConsole(ETrue,_L("  Total Chunk Size = %dk\n"),totalChunkSize);
  1.2446 +	if(protectedChunks)
  1.2447 +		CShell::OutputStringToConsole(ETrue,_L("  %d Protected chunks not counted\n"),protectedChunks);
  1.2448 +	return KErrNone;
  1.2449 +	}
  1.2450 +
  1.2451 +TInt TShowProcInfo::GetServers(const TDes& aName)
  1.2452 +	{
  1.2453 +
  1.2454 +	TFindServer findHb;
  1.2455 +	findHb.Find(aName);
  1.2456 +	TFullName name;
  1.2457 +	Prepare(_L("SERVERS"));
  1.2458 +	while (findHb.Next(name)==KErrNone)
  1.2459 +		{
  1.2460 +		Display(name);
  1.2461 +		}
  1.2462 +	return KErrNone;
  1.2463 +	}
  1.2464 +
  1.2465 +/*	TInt TShowProcInfo::GetSessions(const TDes& aName)
  1.2466 +	{
  1.2467 +
  1.2468 +	TFindSession findHb;
  1.2469 +	findHb.Find(aName);
  1.2470 +	TFullName name;
  1.2471 +	Prepare(_L("SESSIONS"));
  1.2472 +	while (findHb.Next(name)==KErrNone)
  1.2473 +		{
  1.2474 +		Display(name);
  1.2475 +		}
  1.2476 +	return KErrNone;
  1.2477 +	}
  1.2478 +*/
  1.2479 +TInt TShowProcInfo::GetLibraries(const TDes& aName)
  1.2480 +	{
  1.2481 +
  1.2482 +	TFindLibrary findHb;
  1.2483 +	findHb.Find(aName);
  1.2484 +	TFullName name;
  1.2485 +	Prepare(_L("LIBRARIES"));
  1.2486 +	while (findHb.Next(name)==KErrNone)
  1.2487 +		{
  1.2488 +		Display(name);
  1.2489 +		}
  1.2490 +	return KErrNone;
  1.2491 +	}
  1.2492 +/*
  1.2493 +TInt TShowProcInfo::GetLogicalChannels(const TDes& aName)
  1.2494 +	{
  1.2495 +
  1.2496 +	TFindLogicalChannel findHb;
  1.2497 +	findHb.Find(aName);
  1.2498 +	TFullName name;
  1.2499 +	Prepare(_L("LOGICAL CHANNELS"));
  1.2500 +	while (findHb.Next(name)==KErrNone)
  1.2501 +		{
  1.2502 +		Display(name);
  1.2503 +		}
  1.2504 +	return KErrNone;
  1.2505 +	}
  1.2506 +*/
  1.2507 +
  1.2508 +TInt TShowProcInfo::GetLogicalDevices(const TDes& aName)
  1.2509 +	{
  1.2510 +
  1.2511 +	TFindLogicalDevice findHb;
  1.2512 +	findHb.Find(aName);
  1.2513 +	TFullName name;
  1.2514 +	Prepare(_L("LOGICAL DEVICES"));
  1.2515 +	while (findHb.Next(name)==KErrNone)
  1.2516 +		{
  1.2517 +		Display(name);
  1.2518 +		}
  1.2519 +	return KErrNone;
  1.2520 +	}
  1.2521 +
  1.2522 +TInt TShowProcInfo::GetPhysicalDevices(const TDes& aName)
  1.2523 +	{
  1.2524 +
  1.2525 +	TFindPhysicalDevice findHb;
  1.2526 +	findHb.Find(aName);
  1.2527 +	TFullName name;
  1.2528 +	Prepare(_L("PHYSICAL DEVICES"));
  1.2529 +	while (findHb.Next(name)==KErrNone)
  1.2530 +		{
  1.2531 +		Display(name);
  1.2532 +		}
  1.2533 +	return KErrNone;
  1.2534 +	}
  1.2535 +
  1.2536 +TInt TShowProcInfo::GetSemaphores(const TDes& aName)
  1.2537 +	{
  1.2538 +	TFindSemaphore findHb;
  1.2539 +	findHb.Find(aName);
  1.2540 +	TFullName name;
  1.2541 +	Prepare(_L("SEMAPHORES"));
  1.2542 +	while (findHb.Next(name)==KErrNone)
  1.2543 +		{
  1.2544 +		Display(name);
  1.2545 +		}
  1.2546 +	return KErrNone;
  1.2547 +	}
  1.2548 +
  1.2549 +TInt TShowProcInfo::GetMutexes(const TDes& aName)
  1.2550 +	{
  1.2551 +
  1.2552 +	TFindMutex findHb;
  1.2553 +	findHb.Find(aName);
  1.2554 +	TFullName name;
  1.2555 +	Prepare(_L("MUTEXES"));
  1.2556 +	while (findHb.Next(name)==KErrNone)
  1.2557 +		{
  1.2558 +		Display(name);
  1.2559 +		}
  1.2560 +	return KErrNone;
  1.2561 +	}
  1.2562 +
  1.2563 +void TShowProcInfo::DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription)
  1.2564 +	{
  1.2565 +	CShell::OutputStringToConsole(ETrue,_L("%- *S%S\n"),8,&aCommand,&aDescription);
  1.2566 +	}
  1.2567 +
  1.2568 +
  1.2569 +TInt TShowProcInfo::Prepare(const TFullName& aName)
  1.2570 +	{
  1.2571 +
  1.2572 +	iPrevName=_L("");
  1.2573 +	CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
  1.2574 +	useCallBack=EFalse;
  1.2575 +	return KErrNone;
  1.2576 +	}
  1.2577 +
  1.2578 +TInt TShowProcInfo::Prepare(const TFullName& aName,TCallBack& aCallBack)
  1.2579 +	{
  1.2580 +
  1.2581 +	iPrevName=_L("");
  1.2582 +	CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
  1.2583 +	useCallBack=ETrue;
  1.2584 +	iCallBack=aCallBack;
  1.2585 +	return KErrNone;
  1.2586 +	}
  1.2587 +
  1.2588 +TInt TShowProcInfo::Display(TFullName& aName)
  1.2589 +
  1.2590 +//	Modifications by WR, November 1997
  1.2591 +	{
  1.2592 +
  1.2593 +	TFullName prevName=iPrevName;
  1.2594 +	iPrevName=aName;
  1.2595 +	TInt toTab=0;
  1.2596 +	TInt posA=aName.Match(_L("*::*"));
  1.2597 +	if (posA>=0)
  1.2598 +		{
  1.2599 +		TInt posI=prevName.Match(_L("*::*"));
  1.2600 +		while ((posI>=0) && (posA>=0))
  1.2601 +			{
  1.2602 +			TFullName tempAName=(aName.Left(posA));
  1.2603 +			TFullName tempIName=(prevName.Left(posI));
  1.2604 +			if (tempAName.Compare(tempIName)==0)
  1.2605 +				{
  1.2606 +				toTab+=3;
  1.2607 +				aName.Delete(0,posA+2);
  1.2608 +				prevName.Delete(0,posI+2);
  1.2609 +				posA=aName.Match(_L("*::*"));
  1.2610 +				posI=prevName.Match(_L("*::*"));
  1.2611 +				}
  1.2612 +			else
  1.2613 +				break;
  1.2614 +			}
  1.2615 +		while (posA>=0)
  1.2616 +			{
  1.2617 +			TPtrC16 temp_desc=aName.Left(posA);
  1.2618 +			CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+temp_desc.Left(posA).Length(),&temp_desc);
  1.2619 +			toTab+=3;
  1.2620 +			aName.Delete(0,posA+2);
  1.2621 +			posA=aName.Match(_L("*::*"));
  1.2622 +			}
  1.2623 +		}
  1.2624 +	CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+aName.Length(),&(aName));
  1.2625 +
  1.2626 +
  1.2627 +	if (useCallBack)
  1.2628 +		{
  1.2629 +		toTab+=3;
  1.2630 +		CShell::TheConsole->SetCursorPosRel(TPoint(toTab,0));
  1.2631 +		iCallBack.CallBack();
  1.2632 +		}
  1.2633 +	return KErrNone;
  1.2634 +	}
  1.2635 +//	End of modification
  1.2636 +TInt ShellFunction::Ps(TDes& /* aPath */,TUint /* aSwitches */)
  1.2637 +//
  1.2638 +// satisfy information requests about container objects
  1.2639 +//
  1.2640 +	{
  1.2641 +
  1.2642 +	TShowProcInfo showProcInfo;
  1.2643 +	TInt r=KErrNone;
  1.2644 +    TBuf<0x1> asterisk=_L("*");
  1.2645 +	TName processPrefix=asterisk;
  1.2646 +	TBool abort=EFalse;
  1.2647 +	TBool processSelected=EFalse;
  1.2648 +	TBuf<0x16> prompt=_L("ps>");
  1.2649 +	r=showProcInfo.GetProcesses(processPrefix);
  1.2650 +	do
  1.2651 +		{
  1.2652 +		TBuf<0x10> command;
  1.2653 +		CShell::TheEditor->Edit(prompt, &command, ETrue);
  1.2654 +		while (command.Length() && !abort && r==KErrNone)
  1.2655 +			{
  1.2656 +			TInt pos;
  1.2657 +			while ((pos=command.Locate(' '))>=0)
  1.2658 +				command.Delete(pos,1);
  1.2659 +			if (!command.Length())
  1.2660 +				break;
  1.2661 +			command.UpperCase();
  1.2662 +			if (command.CompareF(_L("EXIT"))==0)
  1.2663 +				{
  1.2664 +				abort=ETrue;
  1.2665 +				break;
  1.2666 +				}
  1.2667 +			TText c=command[0];
  1.2668 +			command.Delete(0,1);
  1.2669 +			switch (c)
  1.2670 +				{
  1.2671 +				case 'Q':
  1.2672 +					abort=ETrue;
  1.2673 +					break;
  1.2674 +				case 'H':
  1.2675 +				case '?':
  1.2676 +					{
  1.2677 +					showProcInfo.DisplayHelp();
  1.2678 +					command.Zero();
  1.2679 +					}
  1.2680 +					break;
  1.2681 +				case 'X':
  1.2682 +					{
  1.2683 +					TBuf<0x11> chosenP=command;
  1.2684 +					if (chosenP.Length()<1)
  1.2685 +					    {
  1.2686 +					    if (processSelected)
  1.2687 +						    {
  1.2688 +						    r=showProcInfo.DisplayMessage(_L(" -> back to standard Process Status mode"));
  1.2689 +						    processPrefix=asterisk;
  1.2690 +						    prompt=_L("ps>");
  1.2691 +						    processSelected=EFalse;
  1.2692 +						    }
  1.2693 +					    command.Zero();
  1.2694 +						break;
  1.2695 +					    }
  1.2696 +					command.Zero();
  1.2697 +					chosenP.Append(asterisk);
  1.2698 +					TFindProcess findP;
  1.2699 +					findP.Find(chosenP);
  1.2700 +					TFullName findName;
  1.2701 +					if (findP.Next(findName)!=KErrNone)
  1.2702 +						{
  1.2703 +						r=showProcInfo.DisplayMessage(_L("command prefixes no processes"));
  1.2704 +						//r=showProcInfo.GetProcesses(asterisk);
  1.2705 +						}
  1.2706 +					else
  1.2707 +						{
  1.2708 +						if (findP.Next(findName)==KErrNone)
  1.2709 +							{
  1.2710 +							r=showProcInfo.DisplayMessage(_L("command prefixes more than one process"));
  1.2711 +							r=showProcInfo.GetProcesses(chosenP);
  1.2712 +							}
  1.2713 +						else
  1.2714 +							{
  1.2715 +							processSelected=ETrue;
  1.2716 +							processPrefix=chosenP;
  1.2717 +							prompt=processPrefix;
  1.2718 +							prompt.Append(_L(">"));
  1.2719 +							}
  1.2720 +						}
  1.2721 +					}
  1.2722 +					break;
  1.2723 +				case 'A':
  1.2724 +					{
  1.2725 +					r=showProcInfo.GetAll(processPrefix);
  1.2726 +					command.Zero();
  1.2727 +					}
  1.2728 +					break;
  1.2729 +				case 'P':
  1.2730 +					r=showProcInfo.GetProcesses(asterisk);
  1.2731 +					break;
  1.2732 +				case 'T':
  1.2733 +					r=showProcInfo.GetThreads(processPrefix);
  1.2734 +					break;
  1.2735 +				case 'C':
  1.2736 +					r=showProcInfo.GetChunks(processPrefix);
  1.2737 +					break;
  1.2738 +				case 'S':
  1.2739 +					r=showProcInfo.GetServers(processPrefix);
  1.2740 +					break;
  1.2741 +/*				case 'I':
  1.2742 +					r=showProcInfo.GetSessions(processPrefix);
  1.2743 +					break;
  1.2744 +*/				case 'L':
  1.2745 +					r=showProcInfo.GetLibraries(processPrefix);
  1.2746 +					break;
  1.2747 +//				case 'G':
  1.2748 +//					r=showProcInfo.GetLogicalChannels(processPrefix);
  1.2749 +//					break;
  1.2750 +				case 'V':
  1.2751 +					r=showProcInfo.GetLogicalDevices(processPrefix);
  1.2752 +					break;
  1.2753 +				case 'D':
  1.2754 +					r=showProcInfo.GetPhysicalDevices(processPrefix);
  1.2755 +					break;
  1.2756 +				case 'E':
  1.2757 +					r=showProcInfo.GetSemaphores(processPrefix);
  1.2758 +					break;
  1.2759 +				case 'M':
  1.2760 +					r=showProcInfo.GetMutexes(processPrefix);
  1.2761 +					break;
  1.2762 +				default:
  1.2763 +					{
  1.2764 +					showProcInfo.DisplayCmdUnknown();
  1.2765 +					command.Zero();
  1.2766 +					}
  1.2767 +				}
  1.2768 +			}
  1.2769 +		}
  1.2770 +	while(!abort && r==KErrNone);
  1.2771 +		return KErrNone;
  1.2772 +	}
  1.2773 +
  1.2774 +TInt ShellFunction::Rename(TDes& aPath,TUint aSwitches)
  1.2775 +	{
  1.2776 +//	Modified December 1997 to allow for filenames containing spaces
  1.2777 +
  1.2778 +	TBuf<KShellMaxCommandLine> newName;
  1.2779 +	TBuf<KShellMaxCommandLine> tempPath=aPath;
  1.2780 +	RFile64 file;
  1.2781 +	TWord   word(aPath);
  1.2782 +
  1.2783 +	TInt r=word.FindNextWord(aPath);
  1.2784 +//	Check if the word returned is a valid filename.  If not, scan the next
  1.2785 +//	word too in case the filename contains spaces.  If, at the end of the
  1.2786 +//	the line, the filename is not recognised, it is invalid.  If there are no
  1.2787 +//	spaces the user has not used the correct format for this command.
  1.2788 +
  1.2789 +	while (r>0)
  1.2790 +		{
  1.2791 +		newName=aPath.Right(aPath.Length()-r);
  1.2792 +		tempPath.SetLength(r);
  1.2793 +		TParse oldName;
  1.2794 +		TInt result=GetFullPath(tempPath,oldName);
  1.2795 +		if (result!=KErrNone)
  1.2796 +			return(r);
  1.2797 +
  1.2798 +		if (tempPath[tempPath.Length()-2]==KPathDelimiter)
  1.2799 +			tempPath.SetLength(tempPath.Length()-2);
  1.2800 +
  1.2801 +		result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
  1.2802 +		if (result==KErrNone)	//	A valid filename
  1.2803 +			{
  1.2804 +			file.Close();
  1.2805 +			TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
  1.2806 +			TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
  1.2807 +			r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
  1.2808 +		//	r=TheShell->TheFs.Rename(oldName.FullName(),newName);
  1.2809 +			return(r);
  1.2810 +			}
  1.2811 +		else
  1.2812 +			{
  1.2813 +		//	May be a request to rename a directory
  1.2814 +			RDir dir;
  1.2815 +			result=dir.Open(TheShell->TheFs,tempPath,KEntryAttMatchMask);
  1.2816 +			if (result==KErrNone)	//	A valid directory name
  1.2817 +				{
  1.2818 +				dir.Close();
  1.2819 +				TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
  1.2820 +				TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
  1.2821 +				r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
  1.2822 +			//	r=TheShell->TheFs.Rename(oldName.FullName(),newName);
  1.2823 +				return(r);
  1.2824 +				}
  1.2825 +			else
  1.2826 +		//	Not a valid file or directory name - move one word along the command line
  1.2827 +				r=word.FindNextWord(word.iRightString);
  1.2828 +			}
  1.2829 +		}
  1.2830 +
  1.2831 +	if (r<0)	//	Error in filename or destination
  1.2832 +		return (r);
  1.2833 +	else		//	End of command line, user typed invalid line
  1.2834 +		return (KErrNotFound);
  1.2835 +
  1.2836 +}
  1.2837 +
  1.2838 +TInt ShellFunction::Rd(TDes& aPath,TUint /*aSwitches*/)
  1.2839 +	{
  1.2840 +	if (aPath.Length()==0)
  1.2841 +		return(KErrBadName);
  1.2842 +	if (aPath[aPath.Length()-1]!=KPathDelimiter)
  1.2843 +		aPath.Append(KPathDelimiter);
  1.2844 +	TParse dirPath;
  1.2845 +	TInt r = GetFullPath(aPath,dirPath);
  1.2846 +	if(r!=KErrNone)
  1.2847 +		return r;
  1.2848 +
  1.2849 +//	Check whether the directory actually exists.
  1.2850 +	RDir directory;
  1.2851 +	r=directory.Open(TheShell->TheFs,dirPath.FullName(),KEntryAttMatchExclusive|KEntryAttDir);
  1.2852 +	if (r!=KErrNone)
  1.2853 +		{
  1.2854 +		CShell::TheConsole->Printf(_L("Directory %S was not found\n"),&dirPath.FullName());
  1.2855 +		return (KErrNone);
  1.2856 +		}
  1.2857 +	directory.Close();
  1.2858 +
  1.2859 +	TInt ret=TheShell->TheFs.RmDir(dirPath.FullName());
  1.2860 +    
  1.2861 +    if (ret==KErrNone)
  1.2862 +	    CShell::TheConsole->Printf(_L("Directory %S was removed\n"),&dirPath.FullName());
  1.2863 +    else if(ret==KErrInUse)
  1.2864 +	    {
  1.2865 +		CShell::TheConsole->Printf(_L("Directory %S is in use and cannot be deleted\n"),&dirPath.FullName());
  1.2866 +		return KErrNone;
  1.2867 +		}
  1.2868 +	
  1.2869 +    return(ret);
  1.2870 +	}
  1.2871 +
  1.2872 +TInt ShellFunction::Start(TDes& aProg,TUint /*aSwitches*/)
  1.2873 +//
  1.2874 +// Runs a program without waiting for completion
  1.2875 +//
  1.2876 +	{
  1.2877 +
  1.2878 +	TInt bat=aProg.FindF(_L(".BAT"));
  1.2879 +	TInt space=aProg.Locate(' ');
  1.2880 +	TInt r=KErrArgument;
  1.2881 +	if (bat>=0 && (space<0 || space>bat))
  1.2882 +		r=CShell::RunBatch(aProg);
  1.2883 +	else if (aProg.Length()!=0)
  1.2884 +		r=CShell::RunExecutable(aProg,EFalse);
  1.2885 +	return(r);
  1.2886 +	}
  1.2887 +
  1.2888 +TInt ShellFunction::Time(TDes&,TUint /*aSwitches*/)
  1.2889 +	{
  1.2890 +	TTime time;
  1.2891 +	time.HomeTime();
  1.2892 +	TDateTime dateTime(time.DateTime());
  1.2893 +	CShell::TheConsole->Printf(_L("  %+02d/%+02d/%+04d %+02d:%+02d:%+02d.%+06d\n"),dateTime.Day()+1,dateTime.Month()+1,dateTime.Year(),dateTime.Hour(),dateTime.Minute(),dateTime.Second(),dateTime.MicroSecond());
  1.2894 +	return(KErrNone);
  1.2895 +	}
  1.2896 +
  1.2897 +TInt ShellFunction::Trace(TDes& aState,TUint aSwitches)
  1.2898 +//
  1.2899 +// Turn on trace information
  1.2900 +//
  1.2901 +    {
  1.2902 +	TInt debugVal=0;
  1.2903 +	if (aSwitches&TShellCommand::ESSwitch)
  1.2904 +		debugVal|=KFSERV;
  1.2905 +	if (aSwitches&TShellCommand::ELSwitch)
  1.2906 +		debugVal|=KFLDR;
  1.2907 +	if (aSwitches&TShellCommand::EFSwitch)
  1.2908 +		debugVal|=KFSYS;
  1.2909 +	if (aSwitches&TShellCommand::ETSwitch)
  1.2910 +		debugVal|=KLFFS;
  1.2911 +	if (aSwitches&TShellCommand::EISwitch)
  1.2912 +		debugVal|=KISO9660;
  1.2913 +	if (aSwitches&TShellCommand::ENSwitch)
  1.2914 +		debugVal|=KNTFS;
  1.2915 +	if (aSwitches&TShellCommand::EMSwitch)
  1.2916 +		debugVal|=KTHRD;
  1.2917 +	if (aSwitches&TShellCommand::EOSwitch)
  1.2918 +		debugVal|=KROFS;
  1.2919 +	if (aSwitches&TShellCommand::ECSwitch)
  1.2920 +		debugVal|=KCOMPFS;
  1.2921 +	if (aSwitches&TShellCommand::EHSwitch)
  1.2922 +		debugVal|=KCACHE;
  1.2923 +	TheShell->TheFs.SetDebugRegister(debugVal);
  1.2924 +
  1.2925 +	aSwitches=0;
  1.2926 +
  1.2927 +	if (aState.Length())
  1.2928 +		{
  1.2929 +		TBuf<KShellMaxCommandLine> indexArg;
  1.2930 +		TWord word(aState);
  1.2931 +
  1.2932 +		TLex lex=aState;
  1.2933 +		TUint val;
  1.2934 +		TInt r2=lex.Val(val,EHex);
  1.2935 +
  1.2936 +		TInt r=word.FindNextWord(aState);
  1.2937 +		TUint index;
  1.2938 +		if (r>0)
  1.2939 +			{
  1.2940 +			indexArg = aState.Right(aState.Length()-r);
  1.2941 +			lex=indexArg;
  1.2942 +			lex.Val(index,EDecimal);
  1.2943 +			}
  1.2944 +		else
  1.2945 +			index = 0;
  1.2946 +
  1.2947 +		if (r2 != KErrNone)
  1.2948 +			{
  1.2949 +			TInt shift = index % 32;
  1.2950 +			index /= 32;
  1.2951 +			val = UserSvr::DebugMask(index);
  1.2952 +			if (aState.Left(2)==_L("on"))
  1.2953 +				val |= 1<<shift;
  1.2954 +			else if (aState.Left(3)==_L("off"))
  1.2955 +				val &= ~(1<<shift);
  1.2956 +			}
  1.2957 +
  1.2958 +		if (index < 256)
  1.2959 +			{
  1.2960 +			User::SetDebugMask(val, index);
  1.2961 +			CShell::TheConsole->Printf(_L("SetDebugMask(0x%x, %d)\n"), val, index);
  1.2962 +			}
  1.2963 +		}
  1.2964 +	else
  1.2965 +		{
  1.2966 +		for (TInt j=0; j<8; j++)
  1.2967 +			CShell::TheConsole->Printf(_L("DebugMask(%d) = 0x%08X\n"), j, UserSvr::DebugMask(j));
  1.2968 +		}
  1.2969 +
  1.2970 +    return(KErrNone);
  1.2971 +    }
  1.2972 +
  1.2973 +TInt ShellFunction::Tree(TDes& aPath,TUint aSwitches)
  1.2974 +	{
  1.2975 +	ParsePath(aPath);
  1.2976 +	CShell::TheConsole->Printf(_L("\n  %S\n"),&aPath);
  1.2977 +	if (aPath.Right(1)==_L("\\"))
  1.2978 +		aPath.Append('*');
  1.2979 +	else
  1.2980 +		aPath.Append(_L("\\*"));
  1.2981 +	TBuf<256> buf=_L("  ");
  1.2982 +	TInt dirCount=ShowDirectoryTree(aPath,aSwitches,buf);
  1.2983 +	buf.Format(_L("\n    Found %d subdirector"),dirCount);
  1.2984 +	if (dirCount==1)
  1.2985 +		buf.AppendFormat(_L("y\n"));
  1.2986 +	else
  1.2987 +		buf.AppendFormat(_L("ies\n"));
  1.2988 +
  1.2989 +	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
  1.2990 +
  1.2991 +	return(KErrNone);
  1.2992 +	}
  1.2993 +
  1.2994 +TInt ShellFunction::ShowDirectoryTree(TDes& aPath,TUint aSwitches,TDes& aTreeGraph)
  1.2995 +//
  1.2996 +// Recursive fn. to draw tree of dir aPath (needs to be suffixed with '*')
  1.2997 +//
  1.2998 +	{
  1.2999 +	TInt dirCount=0;
  1.3000 +	RDir dir;
  1.3001 +	TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttDir);
  1.3002 +	if (r==KErrNone)
  1.3003 +		{
  1.3004 +		TEntry next,entry;
  1.3005 +		while ((r=dir.Read(next))==KErrNone && !next.IsDir())
  1.3006 +			{
  1.3007 +			}
  1.3008 +		//	lint info 722: Suspicious use of ; in previous line...
  1.3009 +		if (aSwitches&TShellCommand::EFSwitch)
  1.3010 +			{
  1.3011 +			RDir dirFile;
  1.3012 +			if (dirFile.Open(TheShell->TheFs,aPath,0)==KErrNone)
  1.3013 +				{
  1.3014 +				while (dirFile.Read(entry)==KErrNone)
  1.3015 +					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,(r==KErrNone)?_L("%S\x00B3   %S\n"):_L("%S   %S\n"),&aTreeGraph,&entry.iName);
  1.3016 +
  1.3017 +				dirFile.Close();
  1.3018 +				}
  1.3019 +			}
  1.3020 +		if (r==KErrNone)
  1.3021 +			do
  1.3022 +				{
  1.3023 +				entry=next;
  1.3024 +				while ((r=dir.Read(next))==KErrNone && !next.IsDir())
  1.3025 +					;
  1.3026 +
  1.3027 +				CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,aTreeGraph);
  1.3028 +				if (r==KErrNone)
  1.3029 +					{
  1.3030 +					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
  1.3031 +					aTreeGraph.Append(_L("\x00B3  "));
  1.3032 +					}
  1.3033 +				else
  1.3034 +					{
  1.3035 +					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
  1.3036 +					aTreeGraph.Append(_L("   "));
  1.3037 +					}
  1.3038 +				aPath.Insert(aPath.Length()-1,entry.iName);
  1.3039 +				aPath.Insert(aPath.Length()-1,_L("\\"));
  1.3040 +				dirCount+=1+ShowDirectoryTree(aPath,aSwitches,aTreeGraph);
  1.3041 +				aPath.Delete(aPath.Length()-2-entry.iName.Length(),entry.iName.Length()+1);
  1.3042 +				aTreeGraph.SetLength(aTreeGraph.Length()-3);
  1.3043 +				}
  1.3044 +			while (r==KErrNone);
  1.3045 +		dir.Close();
  1.3046 +		if (r!=KErrEof)
  1.3047 +			CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error EOF %d\n"),r);
  1.3048 +
  1.3049 +		}
  1.3050 +	else
  1.3051 +		CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error in Open %d\n"),r);
  1.3052 +	return(dirCount);
  1.3053 +	}
  1.3054 +
  1.3055 +void ByteSwap(TDes16& aDes)
  1.3056 +	{
  1.3057 +	TUint8* p=(TUint8*)aDes.Ptr();
  1.3058 +	TUint8* pE=p+aDes.Size();
  1.3059 +	TUint8 c;
  1.3060 +	for (; p<pE; p+=2)
  1.3061 +		c=*p, *p=p[1], p[1]=c;
  1.3062 +	}
  1.3063 +
  1.3064 +_LIT(KLitPercentS, "%S");
  1.3065 +TInt ShellFunction::Type(TDes& aPath,TUint aSwitches)
  1.3066 +	{
  1.3067 +	ParsePath(aPath);
  1.3068 +	RFile file;
  1.3069 +	TInt r=file.Open(TheShell->TheFs,aPath,EFileStreamText|EFileShareReadersOnly);
  1.3070 +	if (r!=KErrNone)
  1.3071 +		return r;
  1.3072 +	TBuf8<0x200> tmpbuf;
  1.3073 +	TBuf<0x200> ubuf;
  1.3074 +	TInt state=0;	// 0=start of file, 1=ASCII, 2=UNICODE little-endian, 3=UNICODE big-endian
  1.3075 +    TKeyCode key=EKeyNull;
  1.3076 +
  1.3077 +	TInt nchars=0;
  1.3078 +	TInt l;
  1.3079 +	
  1.3080 +	do
  1.3081 +		{
  1.3082 +		r=file.Read(tmpbuf);
  1.3083 +		if (r!=KErrNone)
  1.3084 +			{
  1.3085 +			file.Close();
  1.3086 +			return r;
  1.3087 +			}
  1.3088 +		
  1.3089 +		l=tmpbuf.Length();
  1.3090 +		if (state==0)
  1.3091 +			{
  1.3092 +			if (l>=2)
  1.3093 +				{
  1.3094 +				TUint c=(tmpbuf[1]<<8)|tmpbuf[0];
  1.3095 +				if (c==0xfeff)
  1.3096 +					state=2;
  1.3097 +				else if (c==0xfffe)
  1.3098 +					state=3;
  1.3099 +				else
  1.3100 +					state=1;
  1.3101 +				}
  1.3102 +			else
  1.3103 +				state=1;
  1.3104 +			}
  1.3105 +		TPtrC buf;
  1.3106 +		if (state>1)
  1.3107 +			{
  1.3108 +			if (l&1)
  1.3109 +				--l, tmpbuf.SetLength(l);
  1.3110 +			buf.Set((TText*)tmpbuf.Ptr(),l/sizeof(TText));
  1.3111 +			if (state==3)
  1.3112 +				{
  1.3113 +				TPtr wbuf( (TText*)buf.Ptr(), buf.Length(), buf.Length() );
  1.3114 +				ByteSwap(wbuf);
  1.3115 +				}
  1.3116 +			}
  1.3117 +		else
  1.3118 +			{
  1.3119 +			ubuf.Copy(tmpbuf);
  1.3120 +			buf.Set(ubuf);
  1.3121 +			}
  1.3122 +		while ((r=buf.Locate('\n'))!=KErrNotFound)
  1.3123 +			{
  1.3124 +			nchars=0;
  1.3125 +			TPtrC bufLeft=buf.Left(r+1);
  1.3126 +			key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &bufLeft);
  1.3127 +			buf.Set(buf.Mid(r+1));
  1.3128 +	
  1.3129 +    		if(key == EKeyEscape) 
  1.3130 +                goto exit;
  1.3131 +			}
  1.3132 +
  1.3133 +		nchars=buf.Length();
  1.3134 +		if (nchars)
  1.3135 +			{
  1.3136 +            key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &buf);
  1.3137 +    		if(key == EKeyEscape) 
  1.3138 +                goto exit;
  1.3139 +
  1.3140 +            }
  1.3141 +
  1.3142 +		} while(l==tmpbuf.MaxLength());
  1.3143 +
  1.3144 +   exit: 	
  1.3145 +    
  1.3146 +	file.Close();
  1.3147 +	CShell::NewLine();
  1.3148 +	return KErrNone;
  1.3149 +	}
  1.3150 +
  1.3151 +void ShellFunction::ParsePath(TDes& aPath)
  1.3152 +	{
  1.3153 +	if (aPath.Length()>0 && aPath[0]==KPathDelimiter)
  1.3154 +		return;
  1.3155 +	TParse pathParse;
  1.3156 +	if (aPath.Length()<2 || aPath[1]!=':')
  1.3157 +		pathParse.SetNoWild(TheShell->currentPath,NULL,NULL);
  1.3158 +	else
  1.3159 +		{
  1.3160 +		if (aPath.Length()>=3 && aPath[2]==KPathDelimiter)
  1.3161 +			return;
  1.3162 +		pathParse.SetNoWild(TheShell->drivePaths[User::UpperCase(aPath[0])-'A'],NULL,NULL);
  1.3163 +		aPath.Delete(0,2);
  1.3164 +		}
  1.3165 +	if (aPath.Length()>=2 && aPath.Left(2).Compare(_L(".."))==0)
  1.3166 +		{
  1.3167 +		aPath.Delete(0,2);
  1.3168 +		pathParse.PopDir();
  1.3169 +		while (aPath.Length()>=3 && aPath.Left(3).Compare(_L("\\.."))==0)
  1.3170 +			{
  1.3171 +			aPath.Delete(0,3);
  1.3172 +			pathParse.PopDir();
  1.3173 +			}
  1.3174 +		if (aPath.Length()!=0 && aPath[0]==KPathDelimiter)
  1.3175 +			aPath.Delete(0,1);
  1.3176 +		}
  1.3177 +	aPath.Insert(0,pathParse.FullName());
  1.3178 +	}
  1.3179 +
  1.3180 +TBool ShellFunction::Certain()
  1.3181 +	{
  1.3182 +	CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
  1.3183 +	TInt r=User::UpperCase(CShell::TheConsole->Getch());
  1.3184 +	while ((!(r=='Y'))&&(!(r=='N')))
  1.3185 +		{
  1.3186 +		CShell::TheConsole->Printf(_L("%c is invalid\n"),r);
  1.3187 +		CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
  1.3188 +		r=User::UpperCase(CShell::TheConsole->Getch());
  1.3189 +		}
  1.3190 +	CShell::TheConsole->Printf(_L("%c\n"),r);
  1.3191 +	return(r=='Y');
  1.3192 +	}
  1.3193 +
  1.3194 +TInt ShellFunction::GetFullPath(TDes& aPath,TParse& aParse)
  1.3195 +//
  1.3196 +// Parse a path of the form "[C:][\\]AAA\\..\\.\\BBB\\xxx.yyy" where:
  1.3197 +// .  indicates the current directory
  1.3198 +// .. indicates move to the parent directory
  1.3199 +// An optional "\\" at the start of the path indicates the path is not relative to the current path
  1.3200 +//
  1.3201 +	{
  1.3202 +
  1.3203 +	TInt r;
  1.3204 +	if (aPath.Length()>0 && aPath[aPath.Length()-1]=='.')
  1.3205 +		aPath.Append(KPathDelimiter);
  1.3206 +	if (aPath.Length()==0)
  1.3207 +		r=aParse.Set(TheShell->currentPath,NULL,NULL);
  1.3208 +	else if (aPath[0]==KPathDelimiter)
  1.3209 +		r=aParse.Set(aPath,&TheShell->currentPath,NULL);
  1.3210 +	else if (aPath.Length()>=2 && aPath[1]==KDriveDelimiter)
  1.3211 +		{
  1.3212 +		TInt drvNum;
  1.3213 +		r=RFs::CharToDrive(aPath[0],drvNum);
  1.3214 +		if (r==KErrNone)
  1.3215 +			r=aParse.Set(aPath,&TheShell->drivePaths[drvNum],NULL);
  1.3216 +		}
  1.3217 +	else
  1.3218 +		{
  1.3219 +		if (aPath.LocateReverse(KPathDelimiter)>=0)
  1.3220 +			{
  1.3221 +			if (aPath.Length()+TheShell->currentPath.Length()>aPath.MaxLength())
  1.3222 +				return(KErrBadName);
  1.3223 +			aPath.Insert(0,TheShell->currentPath);
  1.3224 +			}
  1.3225 +		r=aParse.Set(aPath,&TheShell->currentPath,NULL);
  1.3226 +		}
  1.3227 +	if (r!=KErrNone)
  1.3228 +		return(r);
  1.3229 +	if (aParse.Path().Find(_L(".\\"))==KErrNotFound)
  1.3230 +		return(KErrNone);
  1.3231 +	if (aParse.Path().Find(_L("...\\"))!=KErrNotFound)
  1.3232 +		return(KErrBadName);
  1.3233 +	TParse dirParse;
  1.3234 +	TPtrC path(aParse.DriveAndPath());
  1.3235 +	TInt pos=path.Find(_L(".\\"));
  1.3236 +	if (path[pos-1]!='.' && path[pos-1]!='\\')
  1.3237 +		return(KErrNone); // FileName ending in .
  1.3238 +	TInt isParent=(path[pos-1]=='.') ? 1 : 0;
  1.3239 +	r=dirParse.Set(path.Left(pos-isParent),NULL,NULL);
  1.3240 +	while(r==KErrNone)
  1.3241 +		{
  1.3242 +		if (isParent)
  1.3243 +			dirParse.PopDir();
  1.3244 +		path.Set(path.Right(path.Length()-pos-2));
  1.3245 +		pos=path.Find(_L(".\\"));
  1.3246 +		if (pos==0)
  1.3247 +			{
  1.3248 +			isParent=0;
  1.3249 +			continue;
  1.3250 +			}
  1.3251 +		else if (pos!=KErrNotFound)
  1.3252 +			isParent=(path[pos-1]=='.') ? 1 : 0;
  1.3253 +		TInt len=(pos==KErrNotFound) ? path.Length() : pos-isParent;
  1.3254 +		r=AddRelativePath(dirParse,path.Left(len));
  1.3255 +		if (r!=KErrNone || pos==KErrNotFound)
  1.3256 +			break;
  1.3257 +		}
  1.3258 +	if (r!=KErrNone)
  1.3259 +		return(r);
  1.3260 +//	lint -e50
  1.3261 +	TBuf<KMaxFileName> nameAndExt=aParse.NameAndExt();
  1.3262 +	aParse.Set(dirParse.FullName(),&nameAndExt,NULL);
  1.3263 +	return(KErrNone);
  1.3264 +	}
  1.3265 +
  1.3266 +void ShellFunction::StripQuotes(TDes& aVal)
  1.3267 +	{
  1.3268 +	for(TInt idx=0;idx<aVal.Length();idx++)
  1.3269 +		{
  1.3270 +		while((idx < aVal.Length()) && (aVal[idx] == '"'))
  1.3271 +			{
  1.3272 +			aVal.Delete(idx, 1);
  1.3273 +			}
  1.3274 +		}
  1.3275 +	}
  1.3276 +
  1.3277 +TInt ShellFunction::ValidName(TDes& aPath,TUint /*aSwitches*/)
  1.3278 +//
  1.3279 +//	Check whether the name has any invalid characters
  1.3280 +//
  1.3281 +	{
  1.3282 +	TBool tooShort=EFalse;
  1.3283 +
  1.3284 +	TText badChar;
  1.3285 +	TPtr ptr(&badChar,sizeof(TText),sizeof(TText));
  1.3286 +
  1.3287 +	TBool validName=TheShell->TheFs.IsValidName(aPath,badChar);
  1.3288 +	if (validName)
  1.3289 +		CShell::TheConsole->Printf(_L("'%S' is a valid name\n"),&aPath);
  1.3290 +	else
  1.3291 +		{
  1.3292 +		if (!tooShort)
  1.3293 +			CShell::TheConsole->Printf(_L("'%S' is not a valid name.\n"),&aPath);
  1.3294 +
  1.3295 +		CShell::TheConsole->Printf(_L("The '%S' character is not allowed\n"),&ptr);
  1.3296 +		}
  1.3297 +	return (KErrNone);
  1.3298 +	}
  1.3299 +
  1.3300 +LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN)
  1.3301 +//
  1.3302 +// password utility function to extract drive number from cmd string.
  1.3303 +//
  1.3304 +	{
  1.3305 +	TLex l(aPath);
  1.3306 +	return l.Val(aDN);
  1.3307 +	}
  1.3308 +
  1.3309 +LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW)
  1.3310 +//
  1.3311 +// utility function to extract indexed password from command string.  A
  1.3312 +// dash is interpreted as the null password.
  1.3313 +//
  1.3314 +	{
  1.3315 +	__ASSERT_DEBUG(aPWNbr >= 1, User::Panic(_L("Invalid pswd nbr"), 0));
  1.3316 +
  1.3317 +	TLex l(aPath);
  1.3318 +
  1.3319 +	TPtrC ptScan;
  1.3320 +	for (TInt i = 0; i <= aPWNbr; ++i)
  1.3321 +		{
  1.3322 +		if (l.Eos())
  1.3323 +			return KErrNotFound;
  1.3324 +		else
  1.3325 +			ptScan.Set(l.NextToken());
  1.3326 +		}
  1.3327 +
  1.3328 +	// take remainder of command line and terminate after password
  1.3329 +	TBuf<256> pswd;
  1.3330 +	for (TInt j = 0; j < ptScan.Length() && ! TChar(ptScan[j]).IsSpace(); ++j)
  1.3331 +		{
  1.3332 +		pswd.Append(ptScan[j]);
  1.3333 +		}
  1.3334 +
  1.3335 +	aPW.Zero();
  1.3336 +	if (pswd[0] == '-')
  1.3337 +		return KErrNone;
  1.3338 +
  1.3339 +	// fill aPW with contents of pswd, not converting to ASCII
  1.3340 +	const TInt byteLen = pswd.Length() * 2;
  1.3341 +	if (byteLen > KMaxMediaPassword)
  1.3342 +		return KErrArgument;
  1.3343 +
  1.3344 +	aPW.Copy(reinterpret_cast<const TUint8 *>(pswd.Ptr()), byteLen);
  1.3345 +
  1.3346 +	return KErrNone;
  1.3347 +	}
  1.3348 +
  1.3349 +TInt ShellFunction::Lock(TDes &aPath, TUint aSwitches)
  1.3350 +//
  1.3351 +// Locks a password-enabled media.
  1.3352 +//
  1.3353 +	{
  1.3354 +	TInt r;
  1.3355 +	TInt dn;
  1.3356 +	TMediaPassword curPswd;
  1.3357 +	TMediaPassword newPswd;
  1.3358 +	TBool store = aSwitches & TShellCommand::ESSwitch;
  1.3359 +
  1.3360 +	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
  1.3361 +		return r;
  1.3362 +
  1.3363 +	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
  1.3364 +		return r;
  1.3365 +
  1.3366 +	if ((r = pswd_Password(aPath, 2, newPswd)) < 0)
  1.3367 +		return r;
  1.3368 +
  1.3369 +	return TheShell->TheFs.LockDrive(dn, curPswd, newPswd, store);
  1.3370 +	}
  1.3371 +
  1.3372 +TInt ShellFunction::Unlock(TDes &aPath, TUint aSwitches)
  1.3373 +//
  1.3374 +// Unlocks a password-enabled media.
  1.3375 +//
  1.3376 +	{
  1.3377 +	TInt r;
  1.3378 +	TInt dn;
  1.3379 +	TMediaPassword curPswd;
  1.3380 +	TBool store = aSwitches & TShellCommand::ESSwitch;
  1.3381 +
  1.3382 +	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
  1.3383 +		return r;
  1.3384 +
  1.3385 +	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
  1.3386 +		return r;
  1.3387 +
  1.3388 +	return TheShell->TheFs.UnlockDrive(dn, curPswd, store);
  1.3389 +	}
  1.3390 +
  1.3391 +TInt ShellFunction::Clear(TDes &aPath, TUint /* aSwitches */)
  1.3392 +//
  1.3393 +// Clears a password from a password-enabled media.
  1.3394 +//
  1.3395 +	{
  1.3396 +	TInt r;
  1.3397 +	TInt dn;
  1.3398 +	TMediaPassword curPswd;
  1.3399 +
  1.3400 +	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
  1.3401 +		return r;
  1.3402 +
  1.3403 +	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
  1.3404 +		return r;
  1.3405 +
  1.3406 +	return TheShell->TheFs.ClearPassword(dn, curPswd);
  1.3407 +	}
  1.3408 +
  1.3409 +TInt ShellFunction::SetSize(TDes& aPath,TUint /*aSwitches*/)
  1.3410 +//
  1.3411 +// Set size of a file, create this if it does not exist
  1.3412 +//
  1.3413 +	{
  1.3414 +	TInt fileNameLen=aPath.LocateReverse(' ');
  1.3415 +	if (fileNameLen==KErrNotFound)	//	No spaces implies no filelength specified
  1.3416 +		{
  1.3417 +		CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
  1.3418 +		return (KErrNone);
  1.3419 +		}
  1.3420 +
  1.3421 +
  1.3422 +	TInt fileLength=(aPath.Length()-fileNameLen);
  1.3423 +	if (fileLength>16)
  1.3424 +		return (KErrTooBig);	//	Too many digits - too large!
  1.3425 +	TBuf<16> rightString=aPath.Right(fileLength);
  1.3426 +	aPath.SetLength(fileNameLen);
  1.3427 +
  1.3428 +	TLex size(rightString);
  1.3429 +	size.SkipSpace();
  1.3430 +
  1.3431 +	TRadix radix=ParseHexaPrefixIfAny(size);
  1.3432 +	TUint32 fileSize;
  1.3433 +	TInt r=size.Val(fileSize,radix);
  1.3434 +	if (r!=KErrNone || ! size.Eos())
  1.3435 +		{
  1.3436 +		CShell::TheConsole->Printf(_L("Please specify a file length\n"));
  1.3437 +		return KErrNone;
  1.3438 +		}
  1.3439 +
  1.3440 +	TParse fileName;
  1.3441 +	GetFullPath(aPath,fileName);
  1.3442 +	RFile64 file;
  1.3443 +	r=file.Open(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
  1.3444 +	if(r==KErrNotFound)
  1.3445 +		r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
  1.3446 +	if (r==KErrNone)
  1.3447 +		{
  1.3448 +		r=file.SetSize(fileSize);
  1.3449 +		file.Close();
  1.3450 +		if(r!=KErrNone)
  1.3451 +			CShell::TheConsole->Printf(_L("Error (%d) - could not set size of file\n"),r);
  1.3452 +		}
  1.3453 +	else
  1.3454 +		{
  1.3455 +		CShell::TheConsole->Printf(_L("Error (%d) - could not create or open file\n"),r);
  1.3456 +		CShell::TheFs.Delete(fileName.FullName());
  1.3457 +		}
  1.3458 +	return(r);
  1.3459 +	}
  1.3460 +
  1.3461 +TInt ShellFunction::DebugPort(TDes& aArgs, TUint /*aSwitches*/)
  1.3462 +//
  1.3463 +// Set or get the debug port from the command line (debugport)
  1.3464 +//
  1.3465 +	{
  1.3466 +	_LIT(KGetPortLit, "Debug port is %d (0x%x)\n");
  1.3467 +	_LIT(KSetPortLit, "Debug port set to %d (0x%x)\n");
  1.3468 +
  1.3469 +	TLex s(aArgs);
  1.3470 +	s.SkipSpace();
  1.3471 +	if (s.Eos())
  1.3472 +		{
  1.3473 +		TInt port;
  1.3474 +		TInt r = HAL::Get(HALData::EDebugPort, port);
  1.3475 +		if (r != KErrNone)
  1.3476 +			return r;
  1.3477 +		CShell::TheConsole->Printf(KGetPortLit, (TUint32)port, (TUint32)port);
  1.3478 +		}
  1.3479 +	else
  1.3480 +		{
  1.3481 +		TRadix radix=EDecimal;
  1.3482 +		if (s.Remainder().Length()>2)
  1.3483 +			{
  1.3484 +			s.Mark();
  1.3485 +			s.Inc(2);
  1.3486 +			if (s.MarkedToken().MatchF(_L("0x"))!=KErrNotFound)
  1.3487 +				radix=EHex;
  1.3488 +			else
  1.3489 +				s.UnGetToMark();
  1.3490 +			}
  1.3491 +
  1.3492 +        union Port
  1.3493 +            {
  1.3494 +		    TUint32 u;
  1.3495 +            TInt32 s;
  1.3496 +            };
  1.3497 +
  1.3498 +        Port port;
  1.3499 +        TInt r;
  1.3500 +        if (radix == EHex)
  1.3501 +            r = s.Val(port.u, radix);
  1.3502 +        else
  1.3503 +            r = s.Val(port.s);
  1.3504 +		if (r != KErrNone || ! s.Eos())
  1.3505 +			return KErrBadName;
  1.3506 +		r = HAL::Set(HALData::EDebugPort, port.s);
  1.3507 +		if (r != KErrNone)
  1.3508 +			return r;
  1.3509 +		CShell::TheConsole->Printf(KSetPortLit, port.s, port.u);
  1.3510 +		}
  1.3511 +
  1.3512 +	return KErrNone;
  1.3513 +	}
  1.3514 +
  1.3515 +TInt ShellFunction::Plugin(TDes& aName,TUint aSwitches)
  1.3516 +	{
  1.3517 +	TInt err = KErrNone;
  1.3518 +	switch(aSwitches)
  1.3519 +		{
  1.3520 +		case TShellCommand::EASwitch:
  1.3521 +			{
  1.3522 +			err = CShell::TheFs.AddPlugin(aName);
  1.3523 +			CShell::TheConsole->Printf(_L("Add Plugin: %S [r:%d]\n"), &aName, err);
  1.3524 +			break;
  1.3525 +			}
  1.3526 +		case TShellCommand::ERSwitch:
  1.3527 +			{
  1.3528 +			err = CShell::TheFs.RemovePlugin(aName);
  1.3529 +			CShell::TheConsole->Printf(_L("Remove Plugin: %S [r:%d]\n"), &aName, err);
  1.3530 +			break;
  1.3531 +			}
  1.3532 +		case TShellCommand::EMSwitch:
  1.3533 +			{
  1.3534 +			err = CShell::TheFs.MountPlugin(aName);
  1.3535 +			CShell::TheConsole->Printf(_L("Mount Plugin: %S [r:%d]\n"), &aName, err);
  1.3536 +			break;
  1.3537 +			}
  1.3538 +		case TShellCommand::EDSwitch:
  1.3539 +			{
  1.3540 +			err = CShell::TheFs.DismountPlugin(aName);
  1.3541 +			CShell::TheConsole->Printf(_L("Dismount Plugin: %S [r:%d]\n"), &aName, err);
  1.3542 +			break;
  1.3543 +			}
  1.3544 +		default:
  1.3545 +			{
  1.3546 +			break;
  1.3547 +			}
  1.3548 +		}
  1.3549 +	return err;
  1.3550 +	}
  1.3551 +
  1.3552 +_LIT(KCrNl, "\r\n");
  1.3553 +
  1.3554 +void SIPrintf(TRefByValue<const TDesC16> aFmt, ...)
  1.3555 +	{
  1.3556 +	TBuf<256> buf;
  1.3557 +	VA_LIST list;					
  1.3558 +	VA_START(list, aFmt);
  1.3559 +	// coverity[uninit_use_in_call]
  1.3560 +	buf.FormatList(aFmt, list);			
  1.3561 +	buf.Append(KCrNl);					
  1.3562 +	RDebug::RawPrint(buf);
  1.3563 +	CShell::TheConsole->Printf(buf);
  1.3564 +	}
  1.3565 +
  1.3566 +/**
  1.3567 +	Run a specified executable in a loop.
  1.3568 +
  1.3569 +	RUNEXEC <count> <command [args]> [/E] [/S] [/R]
  1.3570 +
  1.3571 +	count	- loop count; zero (0) means: forever
  1.3572 +	command	- the executable to run. Arguments can be supplied.
  1.3573 +			  Limitations:
  1.3574 +			  command arguments cannot contain /? switches as the shell strips these out.
  1.3575 +			  command cannot contain spaces.
  1.3576 +
  1.3577 +	/E	terminates the loop if the program exits with an error
  1.3578 +
  1.3579 +	/S	makes the shell interpret "count" as a number of seconds
  1.3580 +		The shell will not attempt to terminate "command" early if it is still running after
  1.3581 +		"count" seconds. It will terminate the loop only after "command" has exited.
  1.3582 +
  1.3583 +	/R	will make the shell reset debug registers / trace flags after each iteration.
  1.3584 +		This is to be used if the program modifies tracing flags for its own purposes but exits
  1.3585 +		abnormally; if /R is used, later iterations will run the program from the same initial
  1.3586 +		tracing	state each time.
  1.3587 +		Limitation: This flag does not yet affect BTrace / UTrace state.
  1.3588 +
  1.3589 +	Switches can be combined; "RUNEXEC 2000 testprg /E/S/R" keeps running "testprg"	till an error
  1.3590 +	occurs, or more than 2000 seconds have passed, and resets the debug	state after each iteration.
  1.3591 +*/
  1.3592 +TInt ShellFunction::RunExec(TDes& aProg, TUint aSwitches)
  1.3593 +	{
  1.3594 +	_LIT(KRunExecFailedProcessCreate, "Failed to spawn command %S: error %d\n");
  1.3595 +	_LIT(KRunExecReportStatusAndTime, "Total elapsed time: %d msecs, Iteration %d: Exit type %d,%d,%S\n");
  1.3596 +	aProg.TrimAll();
  1.3597 +	TBuf<KShellMaxCommandLine> parameters(0);
  1.3598 +	TInt r;
  1.3599 +	TInt count = 0;
  1.3600 +	TTime timeStart, timeCurrent;
  1.3601 +	TTimeIntervalMicroSeconds timeTaken;
  1.3602 +
  1.3603 +	// The first parameter must be a valid decimal integer.
  1.3604 +	for (r=0; r < aProg.Length() && TChar(aProg[r]).IsDigit(); r++)
  1.3605 +		count = count * 10 + (aProg[r] - '0');
  1.3606 +	if (r == 0 || r == aProg.Length() || TChar(aProg[r]).IsSpace() == EFalse)
  1.3607 +		return (KErrArgument);
  1.3608 +	aProg = aProg.Mid(r+1);
  1.3609 +
  1.3610 +	TBool exitOnErr = (aSwitches & TShellCommand::EESwitch);
  1.3611 +	TBool resetDebugRegs = (aSwitches & TShellCommand::ERSwitch);
  1.3612 +	TBool countIsSecs = (aSwitches & TShellCommand::ESSwitch);
  1.3613 +	TBool forever = (count == 0);
  1.3614 +
  1.3615 +	timeStart.HomeTime();
  1.3616 +
  1.3617 +	// copy out the parameters - if any
  1.3618 +	r = aProg.Locate(' ');
  1.3619 +	if(r != KErrNotFound)
  1.3620 +		{
  1.3621 +		parameters = aProg.Mid(r+1);
  1.3622 +		aProg.SetLength(r);
  1.3623 +		}
  1.3624 +
  1.3625 +	// Make sure the executable name qualifies as a pathname.
  1.3626 +	aProg.UpperCase();
  1.3627 +	if (aProg.FindF(_L(".EXE")) == KErrNotFound && (aProg.Length()+4) <= KShellMaxCommandLine)
  1.3628 +		aProg.Append(_L(".EXE"));
  1.3629 +
  1.3630 +#ifdef _DEBUG
  1.3631 +	SIPrintf(_L("RUNEXEC: command %S, parameters %S, count %d, forever %d, issecs %d, exiterr %d"),
  1.3632 +		&aProg, &parameters, count, forever, countIsSecs, exitOnErr); 
  1.3633 +#endif
  1.3634 +	TInt i=0;
  1.3635 +	FOREVER
  1.3636 +		{
  1.3637 +		TInt retcode;
  1.3638 +		RProcess newProcess;
  1.3639 +		TRequestStatus status = KRequestPending;
  1.3640 +		TExitType exitType;
  1.3641 +		TBuf<KMaxExitCategoryName> exitCat(0);
  1.3642 +
  1.3643 +		r = newProcess.Create(aProg, parameters);
  1.3644 +		if (r != KErrNone)
  1.3645 +			{
  1.3646 +			SIPrintf(KRunExecFailedProcessCreate, &aProg, r);
  1.3647 +			return (r);						// this is systematic - must return
  1.3648 +			}
  1.3649 +		newProcess.Logon(status);
  1.3650 +		newProcess.Resume();
  1.3651 +		User::WaitForRequest(status);
  1.3652 +		exitType = newProcess.ExitType();
  1.3653 +		exitCat = newProcess.ExitCategory();
  1.3654 +		retcode = newProcess.ExitReason();
  1.3655 +		newProcess.Close();
  1.3656 +
  1.3657 +		timeCurrent.HomeTime();
  1.3658 +		timeTaken = timeCurrent.MicroSecondsFrom(timeStart);
  1.3659 +		TInt msecs = I64LOW(timeTaken.Int64() / 1000);
  1.3660 +		SIPrintf(KRunExecReportStatusAndTime, msecs, i+1, exitType, retcode, &exitCat);
  1.3661 +
  1.3662 +		if (resetDebugRegs)
  1.3663 +			{
  1.3664 +			TheShell->TheFs.SetDebugRegister(0);
  1.3665 +			User::SetDebugMask(0);
  1.3666 +			}
  1.3667 +
  1.3668 +		i++;
  1.3669 +
  1.3670 +		if ((exitOnErr && (exitType != EExitKill || status != KErrNone)) ||							// err occurred, leave requested ?
  1.3671 +			(countIsSecs && count != 0 && timeTaken.Int64() > (TInt64)1000000 * (TInt64)count) ||	// time elapsed ?
  1.3672 +			(!forever && i >= count))																// loop done ?
  1.3673 +			break;
  1.3674 +		}
  1.3675 +	return(KErrNone);
  1.3676 +	}
  1.3677 +
  1.3678 +//
  1.3679 +// System information command
  1.3680 +//
  1.3681 +
  1.3682 +TBool DebugNum(TInt aBitNum)
  1.3683 +	{
  1.3684 +	__ASSERT_ALWAYS(aBitNum >= 0 && aBitNum <= KMAXTRACE, User::Panic(_L("Bad bit num"), 0));
  1.3685 +	TInt index = aBitNum >> 5;
  1.3686 +	TInt m = UserSvr::DebugMask(index) & (1 << (aBitNum & 31));
  1.3687 +	return m != 0;
  1.3688 +	}
  1.3689 +
  1.3690 +void SIHeading(TRefByValue<const TDesC16> aFmt, ...)
  1.3691 +	{
  1.3692 +	TBuf<256> buf;
  1.3693 +	VA_LIST list;
  1.3694 +	VA_START(list, aFmt);
  1.3695 +	buf.Append(KCrNl);
  1.3696 +	buf.AppendFormatList(aFmt, list);
  1.3697 +	buf.Append(KCrNl);
  1.3698 +	RDebug::RawPrint(buf);
  1.3699 +	CShell::TheConsole->Printf(buf);
  1.3700 +	buf.Fill('=', buf.Length()-4);
  1.3701 +	buf.Append(KCrNl);
  1.3702 +	RDebug::RawPrint(buf);
  1.3703 +	CShell::TheConsole->Printf(buf);
  1.3704 +	}
  1.3705 +
  1.3706 +void SIBoolean(const TDesC& aFmt, TBool aVal)
  1.3707 +	{
  1.3708 +	_LIT(KEnabled, "enabled");
  1.3709 +	_LIT(KDisabled, "disabled");
  1.3710 +	SIPrintf(aFmt, aVal ? &KEnabled : &KDisabled);
  1.3711 +	}
  1.3712 +
  1.3713 +TInt ShellFunction::SysInfo(TDes& /*aArgs*/, TUint /*aSwitches*/)
  1.3714 +	{
  1.3715 +	SIHeading(_L("Kernel Features"));
  1.3716 +	SIBoolean(_L("Crazy scheduler delays are %S."), DebugNum(KCRAZYSCHEDDELAY));
  1.3717 +	SIBoolean(_L("Crazy scheduler priorities and timeslicing are %S."),
  1.3718 +				UserSvr::HalFunction(EHalGroupKernel, EKernelHalConfigFlags, 0, 0) & EKernelConfigCrazyScheduling);
  1.3719 +
  1.3720 +	return KErrNone;
  1.3721 +	}
  1.3722 +
  1.3723 +
  1.3724 +//-------------------------------------------------------------------------
  1.3725 +/**
  1.3726 +    Print out the command line to the console and standard debug port.
  1.3727 +*/
  1.3728 +TInt ShellFunction::ConsoleEcho(TDes& aArgs, TUint /*aSwitches*/)
  1.3729 +{
  1.3730 +    SIPrintf(aArgs);
  1.3731 +    return KErrNone;
  1.3732 +}