os/kernelhwsrv/userlibandfileserver/fileserver/etshell/ts_com.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// f32\etshell\ts_com.cpp
sl@0
    15
// Shell commands
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#ifdef __VC32__
sl@0
    20
  // Solve compilation problem caused by non-English locale
sl@0
    21
  #pragma setlocale("english")
sl@0
    22
#endif
sl@0
    23
sl@0
    24
#include "ts_std.h"
sl@0
    25
sl@0
    26
#include <hal.h>
sl@0
    27
#include <d32locd.h>
sl@0
    28
#include <e32math.h>
sl@0
    29
#include "u32std.h"
sl@0
    30
#include <u32hal.h>
sl@0
    31
#include <nkern/nk_trace.h>
sl@0
    32
#include "filesystem_fat.h"
sl@0
    33
sl@0
    34
    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)");
sl@0
    35
    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 ");
sl@0
    36
sl@0
    37
sl@0
    38
//	lint -e40,e30
sl@0
    39
const TShellCommand CShell::iCommand[ENoShellCommands]=
sl@0
    40
	{
sl@0
    41
//	TShellCommand(_L("BLANK"),_L("Help"),_L("-?"),TShellCommand::EDSwitch,ShellFunction::BLANK),
sl@0
    42
	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),
sl@0
    43
	TShellCommand(_L("CD"),_L("Change the current directory for a drive"),_L("[path] [/d]\n\n  /d - Change drive"),TShellCommand::EDSwitch,ShellFunction::Cd),
sl@0
    44
	TShellCommand(_L("CHKDEPS"),_L("Check the dependencies of an executable or a Dll (ARM only)"),_L("[Filename.EXE] or [Filename.DLL]"),0,ShellFunction::ChkDeps),
sl@0
    45
	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),
sl@0
    46
	TShellCommand(_L("COPY"),_L("Copy one (or more) file(s)"),_L("source [destination]"),TShellCommand::ESSwitch,ShellFunction::Copy),
sl@0
    47
	TShellCommand(_L("DEL"),_L("Delete one file"),_L("[drive:][path][filename]"),TShellCommand::ESSwitch,ShellFunction::Del),
sl@0
    48
	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),
sl@0
    49
//	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),
sl@0
    50
    TShellCommand(_L("FORMAT"),_L("Format a disk"),ptrFormatHelp,TShellCommand::EQSwitch|TShellCommand::ESSwitch|TShellCommand::EESwitch|TShellCommand::EFSwitch,ShellFunction::Format),
sl@0
    51
    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),
sl@0
    52
	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),
sl@0
    53
	TShellCommand(_L("LABEL"),_L("Set or return the volume label"),_L("[newlabel]"),0,ShellFunction::VolumeLabel),
sl@0
    54
	TShellCommand(_L("MD"),_L("Make a new directory"),_L("name"),0,ShellFunction::Md),
sl@0
    55
	TShellCommand(_L("MOVE"),_L("Move files"),_L("name [destination]"),TShellCommand::ESSwitch,ShellFunction::Move),
sl@0
    56
	TShellCommand(_L("PS"),_L("Display information about processes"),_L(""),0,ShellFunction::Ps),
sl@0
    57
	TShellCommand(_L("RENAME"),_L("Rename a file"),_L("oldfilename newfilename"),TShellCommand::ESSwitch,ShellFunction::Rename),
sl@0
    58
	TShellCommand(_L("RD"),_L("Delete one directory"),_L("[drive:][path]directoryname"),TShellCommand::ESSwitch,ShellFunction::Rd),
sl@0
    59
	TShellCommand(_L("START"),_L("Run a program in a separate window"),_L("filename[.exe]"),0,ShellFunction::Start),
sl@0
    60
	TShellCommand(_L("TIME"),_L("Display the system time"),_L(""),0,ShellFunction::Time),
sl@0
    61
	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),
sl@0
    62
	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),
sl@0
    63
	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),
sl@0
    64
	TShellCommand(_L("VNAME"),_L("Check whether a filename is valid.  Return any invalid character"),_L("[drive:][path]filename \n\n "),0,ShellFunction::ValidName),
sl@0
    65
	TShellCommand(_L("LOCK"),_L("Lock a password-enabled media"),_L("drive-number cur-pswd new-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Lock),
sl@0
    66
	TShellCommand(_L("UNLOCK"),_L("Unlock a locked password-enabled media"),_L("drive-number cur-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Unlock),
sl@0
    67
	TShellCommand(_L("CLEAR"),_L("Clear password from password-enabled media"),_L("drive-number cur-pswd"), 0x00000000, ShellFunction::Clear),
sl@0
    68
	TShellCommand(_L("SETSIZE"),_L("Set size of a file"),_L("[filename] size"),0,ShellFunction::SetSize),
sl@0
    69
	TShellCommand(_L("DEBUGPORT"),_L("Set or get debug port"),_L("[port]"),0,ShellFunction::DebugPort),
sl@0
    70
	TShellCommand(_L("PLUGIN"),_L("Manage Plugins"),_L("[name][/A][/R][/M][/D]"),TShellCommand::EASwitch|TShellCommand::ERSwitch|TShellCommand::EMSwitch|TShellCommand::EDSwitch,ShellFunction::Plugin),
sl@0
    71
    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),
sl@0
    72
	TShellCommand(_L("SYSINFO"),_L("Print information about system features and status"),_L(""),0,ShellFunction::SysInfo),
sl@0
    73
    TShellCommand(_L("MOUNT"),_L("Mount / dismount file system on specified drive"),ptrMountHelp,TShellCommand::EUSwitch|TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::ERSwitch,ShellFunction::MountFileSystem),
sl@0
    74
    TShellCommand(_L("ECHO"),_L("Print out the command line to the console and standard debug port."),_L("[line to print out]"),0,ShellFunction::ConsoleEcho),
sl@0
    75
	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),
sl@0
    76
sl@0
    77
    };
sl@0
    78
sl@0
    79
sl@0
    80
LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN);
sl@0
    81
LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW);
sl@0
    82
sl@0
    83
_LIT(KLitNewLine,"\n");
sl@0
    84
void CShell::NewLine()
sl@0
    85
	{
sl@0
    86
	TheConsole->Printf(KLitNewLine());
sl@0
    87
	}
sl@0
    88
sl@0
    89
//
sl@0
    90
// Skip the hexadecimal prefix if present and return EHex.  Return
sl@0
    91
// EDecimal otherwise.
sl@0
    92
//
sl@0
    93
sl@0
    94
static TRadix ParseHexaPrefixIfAny(TLex& aLex)
sl@0
    95
	{
sl@0
    96
	_LIT(KPrefix, "0x");
sl@0
    97
	if (aLex.Remainder().Length() > 2)
sl@0
    98
		{
sl@0
    99
		aLex.Mark();
sl@0
   100
		aLex.Inc(2);
sl@0
   101
		if (aLex.MarkedToken().MatchF(KPrefix) != KErrNotFound)
sl@0
   102
			return EHex;
sl@0
   103
		else
sl@0
   104
			aLex.UnGetToMark();
sl@0
   105
		}
sl@0
   106
sl@0
   107
	return EDecimal;
sl@0
   108
	}
sl@0
   109
sl@0
   110
sl@0
   111
//
sl@0
   112
//	TWord class
sl@0
   113
//	Used to locate spaces in the command line, and return the next word
sl@0
   114
//
sl@0
   115
sl@0
   116
TWord::TWord(const TDesC& aDes)
sl@0
   117
	: iSpace(0),iNextSpace(0)
sl@0
   118
//
sl@0
   119
//	Constructor
sl@0
   120
//
sl@0
   121
	{
sl@0
   122
	Init(aDes);
sl@0
   123
	}
sl@0
   124
sl@0
   125
sl@0
   126
void TWord::Init(const TDesC& aDes)
sl@0
   127
//
sl@0
   128
// Resets to the start of the buffer
sl@0
   129
//
sl@0
   130
	{
sl@0
   131
	iDes.Set(aDes);
sl@0
   132
	}
sl@0
   133
sl@0
   134
TInt TWord::FindNextWord(TDes& aWord)
sl@0
   135
//
sl@0
   136
//	Returns the next word from the buffer
sl@0
   137
//
sl@0
   138
	{
sl@0
   139
	iSpace=aWord.Locate(' ');
sl@0
   140
sl@0
   141
	if (iSpace==KErrNotFound)		//	No spaces in command line
sl@0
   142
		{
sl@0
   143
		if (aWord.Length()==0)		//	Command line has zero length:
sl@0
   144
			return (KErrNotFound);	//	User just typed "command"
sl@0
   145
		else
sl@0
   146
			{						//	User typed "command aWord"
sl@0
   147
			iRightString=aWord;
sl@0
   148
			iNextWord=aWord;
sl@0
   149
			return (0);
sl@0
   150
			}
sl@0
   151
		}
sl@0
   152
sl@0
   153
	else if (iSpace<aWord.Length())	//	Spaces may be command switches or part of the filename
sl@0
   154
		{
sl@0
   155
		iRightString=(aWord.Right((aWord.Length()-iSpace)-1));
sl@0
   156
sl@0
   157
		iNextSpace=iRightString.Locate(' ');	//	Check for another space
sl@0
   158
		if (iNextSpace==KErrNotFound)			//	No more spaces
sl@0
   159
			{
sl@0
   160
			iNextWord=iRightString;
sl@0
   161
			return((iDes.Length())-(iRightString.Length()));//	Position of the (last) word
sl@0
   162
			}
sl@0
   163
sl@0
   164
		if (iNextSpace<iRightString.Length())	//	More spaces - assign iNextWord to be
sl@0
   165
			{									//	the text in between the two spaces
sl@0
   166
			iNextWord=(iRightString.Left(iNextSpace));
sl@0
   167
			return ((iDes.Length())-(iRightString.Length()));//	Position of the word
sl@0
   168
			}
sl@0
   169
sl@0
   170
		else
sl@0
   171
			return(KErrNotFound);
sl@0
   172
		}
sl@0
   173
sl@0
   174
	else
sl@0
   175
		return(KErrNotFound);
sl@0
   176
	}
sl@0
   177
sl@0
   178
//-------------------------------------------------------------------------
sl@0
   179
sl@0
   180
sl@0
   181
TInt ShellFunction::Cd(TDes& aPath,TUint aSwitches)
sl@0
   182
//
sl@0
   183
// Change directory
sl@0
   184
//
sl@0
   185
	{
sl@0
   186
	ShellFunction::StripQuotes(aPath);
sl@0
   187
sl@0
   188
	TBool drvNameOnly=aPath.Length()==2 && aPath[1]==KDriveDelimiter;
sl@0
   189
	TBool dSwitchSet=aSwitches&TShellCommand::EDSwitch;
sl@0
   190
	if (aPath.Length()==0 || (drvNameOnly && !dSwitchSet))
sl@0
   191
		{
sl@0
   192
		TInt drvNum=(aPath.Length() ? aPath[0] : TheShell->currentPath[0])-'A';
sl@0
   193
		if (drvNum<0 || drvNum>=KMaxDrives)
sl@0
   194
			return(KErrBadName);
sl@0
   195
		CShell::TheConsole->Printf(_L("%S\n"),&TheShell->drivePaths[drvNum]);
sl@0
   196
		return(KErrNone);
sl@0
   197
		}
sl@0
   198
	if (aPath.Find(_L("*"))!=KErrNotFound)
sl@0
   199
		return(KErrBadName);
sl@0
   200
	if (aPath[aPath.Length()-1]!=KPathDelimiter && !drvNameOnly)
sl@0
   201
		aPath.Append(KPathDelimiter);
sl@0
   202
	aPath.Append('*');
sl@0
   203
	TChar drvLetter = aPath[0];
sl@0
   204
	drvLetter.UpperCase();
sl@0
   205
	aPath[0] = (TText) drvLetter;
sl@0
   206
	TParse dirParse;
sl@0
   207
	TInt r=GetFullPath(aPath,dirParse);
sl@0
   208
	if (r!=KErrNone)
sl@0
   209
		return(KErrBadName);
sl@0
   210
	TPtrC fullName=dirParse.FullName();
sl@0
   211
	RDir dir;
sl@0
   212
	r=dir.Open(TheShell->TheFs,fullName,KEntryAttMaskSupported);
sl@0
   213
	if (r!=KErrNone)
sl@0
   214
		return(r);
sl@0
   215
	dir.Close();
sl@0
   216
	if (dSwitchSet || fullName[0]==TheShell->currentPath[0])
sl@0
   217
		r=TheShell->TheFs.SetSessionPath(dirParse.DriveAndPath());
sl@0
   218
	if (r==KErrNone)
sl@0
   219
		TheShell->SetDrivePath(dirParse.DriveAndPath());
sl@0
   220
	return(r);
sl@0
   221
	}
sl@0
   222
sl@0
   223
TInt ShellFunction::ChkDeps(TDes& aPath,TUint /*aSwitches*/)
sl@0
   224
	{
sl@0
   225
	ShellFunction::StripQuotes(aPath);
sl@0
   226
sl@0
   227
	aPath.Trim();
sl@0
   228
	TBool appendedExe=EFalse;
sl@0
   229
sl@0
   230
//	Determine whether aPath is an executable or a Dll
sl@0
   231
sl@0
   232
	TInt r=aPath.FindF(_L(".EXE"));
sl@0
   233
	if (r==KErrNotFound)
sl@0
   234
		{
sl@0
   235
		r=aPath.FindF(_L(".DLL"));
sl@0
   236
		if (r==KErrNotFound)//	aPath does not include .exe or .dll extensions
sl@0
   237
			{
sl@0
   238
			aPath.Append(_L(".EXE"));	//	append a .exe extension
sl@0
   239
			appendedExe=ETrue;
sl@0
   240
			}
sl@0
   241
		}
sl@0
   242
sl@0
   243
	if (aPath.Length()>2 && aPath[1]==':' && aPath[2]!='\\')
sl@0
   244
		{
sl@0
   245
		TInt drive;
sl@0
   246
		__ASSERT_ALWAYS(RFs::CharToDrive(aPath[0],drive)==KErrNone,User::Panic(_L("Invalid drive letter"),0));
sl@0
   247
 		TheShell->currentPath=TheShell->drivePaths[drive];
sl@0
   248
   		aPath.Delete(0,2);
sl@0
   249
   		aPath.Insert(0,TheShell->currentPath);
sl@0
   250
		}
sl@0
   251
	if (aPath.Length()>2 && aPath[1]!=':')
sl@0
   252
		{
sl@0
   253
		if (aPath[0]!='\\')
sl@0
   254
    		aPath.Insert(0,TheShell->currentPath);
sl@0
   255
		else
sl@0
   256
			aPath.Insert(0,TheShell->currentPath.Left(2));
sl@0
   257
		}
sl@0
   258
sl@0
   259
	RFile file;
sl@0
   260
	r=file.Open(CShell::TheFs,aPath,EFileStream);
sl@0
   261
	if (r!=KErrNone)	//		File could not be opened
sl@0
   262
		{
sl@0
   263
		if (appendedExe)	//	If .EXE was appended earlier
sl@0
   264
			{
sl@0
   265
//	Remove .EXE and append .DLL instead.  Try to open the file again
sl@0
   266
//	If this fails too, the user entered an invalid filename that is neither
sl@0
   267
//	an executable or a Dll
sl@0
   268
			aPath.Delete(aPath.Length()-4,4);
sl@0
   269
			appendedExe=EFalse;
sl@0
   270
			aPath.Append(_L(".DLL"));	//	Try a .DLL extension
sl@0
   271
			r=file.Open(CShell::TheFs,aPath,EFileStream);
sl@0
   272
			if (r!=KErrNone)	//	Still could not open file
sl@0
   273
				return(r);	//	Neither an executable or a Dll
sl@0
   274
		//	Runs to here if the file is opened -> .DLL extension appended
sl@0
   275
			}
sl@0
   276
		else
sl@0
   277
			return(r);	//	User had typed in an incorrect filename with
sl@0
   278
						//	a .DLL or .EXE extension
sl@0
   279
		}
sl@0
   280
sl@0
   281
	file.Close();
sl@0
   282
	CDllChecker check;
sl@0
   283
	TRAPD(leaveCode,check.ConstructL());//	Allocates 4 elements at a time
sl@0
   284
	if (leaveCode!=KErrNone)	//	If function leaves
sl@0
   285
		return(leaveCode);		//	return the leave code
sl@0
   286
sl@0
   287
	TRAPD(result,check.GetImportDataL(aPath,NULL));
sl@0
   288
	if (result==KErrGeneral)
sl@0
   289
		{
sl@0
   290
		CShell::TheConsole->Printf(_L(" %S has no import data\n"),&aPath);
sl@0
   291
		return(KErrNone);
sl@0
   292
		}
sl@0
   293
	else
sl@0
   294
		check.ListArray();	//	Print out the results of DllCheck
sl@0
   295
	return(KErrNone);
sl@0
   296
	}
sl@0
   297
sl@0
   298
//
sl@0
   299
// Check disk for corruption
sl@0
   300
//
sl@0
   301
// Spec:
sl@0
   302
//
sl@0
   303
// ChkDsk DriveLetter:[\] [/S] [/F] [/U]
sl@0
   304
//
sl@0
   305
//			/S : Starts a ScanDrive instead of CheckDisk
sl@0
   306
//			/F : Finalise given drive
sl@0
   307
//			/U : UnFinalise given drive
sl@0
   308
sl@0
   309
TInt ShellFunction::ChkDsk(TDes& aPath,TUint aSwitches)
sl@0
   310
	{
sl@0
   311
	ShellFunction::StripQuotes(aPath);
sl@0
   312
    
sl@0
   313
    const TBool bRunScanDrv     = aSwitches & TShellCommand::ESSwitch;
sl@0
   314
    const TBool bFinaliseDrv    = aSwitches & TShellCommand::EFSwitch;
sl@0
   315
    const TBool bUnFinaliseDrv  = aSwitches & TShellCommand::EUSwitch; 
sl@0
   316
sl@0
   317
    TInt nRes;
sl@0
   318
    TInt drive=EDriveZ;
sl@0
   319
sl@0
   320
	if(aPath.Length() < 1)
sl@0
   321
    {
sl@0
   322
        nRes = KErrArgument;
sl@0
   323
    }
sl@0
   324
    else
sl@0
   325
    {
sl@0
   326
        nRes=CShell::TheFs.CharToDrive(aPath[0], drive);
sl@0
   327
	}
sl@0
   328
sl@0
   329
    if (nRes != KErrNone)
sl@0
   330
	{
sl@0
   331
    	CShell::TheConsole->Printf(_L("Wrong drive specified!\n"));
sl@0
   332
        return nRes;
sl@0
   333
    }
sl@0
   334
    
sl@0
   335
    if(bRunScanDrv)
sl@0
   336
    {//-- run ScanDrive on the specified drive
sl@0
   337
        CShell::TheConsole->Printf(_L("Starting ScanDrive...\n"));
sl@0
   338
        nRes=TheShell->TheFs.ScanDrive(aPath);
sl@0
   339
        if(nRes == KErrNone)
sl@0
   340
        {
sl@0
   341
            CShell::TheConsole->Printf(_L("No errors.\n"));
sl@0
   342
        }
sl@0
   343
    }
sl@0
   344
    else if(bFinaliseDrv)
sl@0
   345
    {//-- finalise the drive
sl@0
   346
        nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EFinal_RW);
sl@0
   347
        if(nRes != KErrNone)
sl@0
   348
            return nRes;
sl@0
   349
sl@0
   350
        CShell::TheConsole->Printf(_L("Drive %c: is finalised RW\n"), 'A'+drive);
sl@0
   351
    }
sl@0
   352
    else if(bUnFinaliseDrv)
sl@0
   353
    {//-- Unfinalise the drive
sl@0
   354
        nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EForceUnfinalise);
sl@0
   355
        if(nRes != KErrNone)
sl@0
   356
            return nRes;
sl@0
   357
sl@0
   358
        CShell::TheConsole->Printf(_L("Drive %c: is Unfinalised\n"), 'A'+drive);
sl@0
   359
    }
sl@0
   360
    else
sl@0
   361
    {//-- run CheckDisk on the specified drive
sl@0
   362
        nRes=TheShell->TheFs.CheckDisk(aPath);
sl@0
   363
	    if (nRes<0)
sl@0
   364
		    return(nRes);
sl@0
   365
sl@0
   366
	    switch(nRes)
sl@0
   367
		    {
sl@0
   368
	    case 0:
sl@0
   369
		    CShell::TheConsole->Printf(_L("Complete - no errors\n"));
sl@0
   370
		    break;
sl@0
   371
	    case 1:
sl@0
   372
		    CShell::TheConsole->Printf(_L("Error - File cluster chain contains a bad value (<2 or >maxCluster)\n"));
sl@0
   373
		    break;
sl@0
   374
	    case 2:
sl@0
   375
		    CShell::TheConsole->Printf(_L("Error - Two files are linked to the same cluster\n"));
sl@0
   376
		    break;
sl@0
   377
	    case 3:
sl@0
   378
		    CShell::TheConsole->Printf(_L("Error - Unallocated cluster contains a value != 0\n"));
sl@0
   379
		    break;
sl@0
   380
	    case 4:
sl@0
   381
		    CShell::TheConsole->Printf(_L("Error - Size of file != number of clusters in chain\n"));
sl@0
   382
		    break;
sl@0
   383
	    default:
sl@0
   384
		    CShell::TheConsole->Printf(_L("Undefined Error value\n"));
sl@0
   385
		    }
sl@0
   386
	 }
sl@0
   387
    return nRes;
sl@0
   388
	}
sl@0
   389
sl@0
   390
TInt ShellFunction::Copy(TDes& aPath,TUint aSwitches)
sl@0
   391
//
sl@0
   392
// DOS spec:
sl@0
   393
//
sl@0
   394
// COPY [/A | /B] source [/A | /B] [+ source [/A | /B] [+ ...]] [destination] [/A | /B]] [/V] [/N]
sl@0
   395
// source		Specifies the file or files to be copied.
sl@0
   396
// /A			Indicates an ASCII text file.
sl@0
   397
// /B			Indicates a binary file.
sl@0
   398
// destination	Specifies the directory and/or filename for the new file(s).
sl@0
   399
// /V			Verifies that new files are written correctly.
sl@0
   400
// /Y			Supresses prompting to confirm you want to overwrite existing destination file
sl@0
   401
// /N			Uses short filename, if available, when copying a file with a non-8dot3 name.
sl@0
   402
//
sl@0
   403
// To append files, specify a single file for destination, but multiple files
sl@0
   404
// for source (using wildcards or file1+file2+file3 format).
sl@0
   405
//
sl@0
   406
// My spec:
sl@0
   407
//
sl@0
   408
// COPY source [destination]
sl@0
   409
// source		Specifies the file or files to be copied to the current directory
sl@0
   410
sl@0
   411
// Modified November 1997 to allow spaces in filenames
sl@0
   412
sl@0
   413
	{
sl@0
   414
	if (aPath.Length() == 0)
sl@0
   415
	    return KErrNotFound;    // no source file
sl@0
   416
sl@0
   417
	ShellFunction::StripQuotes(aPath);
sl@0
   418
sl@0
   419
	TBuf<KShellMaxCommandLine> destination;
sl@0
   420
	TBuf<KShellMaxCommandLine> tempPath;
sl@0
   421
	TWord word(aPath);
sl@0
   422
sl@0
   423
	TBool endOfCommandLine=EFalse;
sl@0
   424
sl@0
   425
//	Check if the word returned is a valid filename.  If not, scan the next
sl@0
   426
//	word too in case the filename contains spaces.  If, at the end of the
sl@0
   427
//	the line, the filename is not recognised, it is invalid.  If there are no
sl@0
   428
//	spaces the user has not used the correct format for this command.
sl@0
   429
sl@0
   430
	TInt r=word.FindNextWord(aPath);
sl@0
   431
	do	{
sl@0
   432
		TParse dirPath;
sl@0
   433
sl@0
   434
		if (r==0)	//	No destination was specified
sl@0
   435
			{
sl@0
   436
		//	Work out the destination
sl@0
   437
			tempPath.SetLength(0);
sl@0
   438
			r=GetFullPath(tempPath,dirPath);
sl@0
   439
			if (r!=KErrNone)
sl@0
   440
				return(r);
sl@0
   441
			destination=dirPath.FullName();
sl@0
   442
		//	Now get the path of the source
sl@0
   443
			tempPath=aPath;
sl@0
   444
			r=GetFullPath(tempPath,dirPath);
sl@0
   445
			if (r!=KErrNone)
sl@0
   446
				return(r);
sl@0
   447
			endOfCommandLine=ETrue;	//	So we don't get stuck in an infinite loop
sl@0
   448
			}
sl@0
   449
		else
sl@0
   450
			{
sl@0
   451
		//	Work out the destination
sl@0
   452
			destination=aPath.Right(aPath.Length()-r);
sl@0
   453
			if (!destination.Compare(_L(".")))
sl@0
   454
				GetFullPath(destination,dirPath);
sl@0
   455
		//	Now get the path of the source
sl@0
   456
			tempPath=aPath;
sl@0
   457
			tempPath.SetLength(r);
sl@0
   458
			r=GetFullPath(tempPath,dirPath);
sl@0
   459
			if (r!=KErrNone)
sl@0
   460
				return(r);
sl@0
   461
			}
sl@0
   462
sl@0
   463
		TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
sl@0
   464
		TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
sl@0
   465
		r=CShell::TheFileMan->Copy(dirPath.FullName(),destination,switches);
sl@0
   466
		if (r==KErrNone)
sl@0
   467
			return(r);	//	Copy was successful
sl@0
   468
sl@0
   469
		else			//	Not a valid filename - move one word along the command line
sl@0
   470
			r=word.FindNextWord(word.iRightString);
sl@0
   471
		} while ((r>=0)&&(!endOfCommandLine));
sl@0
   472
sl@0
   473
	if (r<0)			//	Some error
sl@0
   474
		return (r);
sl@0
   475
	else				//	End of command line, user typed invalid line, return not found
sl@0
   476
		return (KErrNotFound);
sl@0
   477
	}
sl@0
   478
sl@0
   479
sl@0
   480
TInt ShellFunction::VolumeLabel(TDes& aPath,TUint /*aSwitches*/)
sl@0
   481
/**
sl@0
   482
Sets or returns the default path
sl@0
   483
sl@0
   484
@param aPath The volume label being set or returned
sl@0
   485
*/
sl@0
   486
	{
sl@0
   487
	ShellFunction::StripQuotes(aPath);
sl@0
   488
sl@0
   489
	TVolumeInfo vol;
sl@0
   490
	TInt drive;
sl@0
   491
	TInt r=CShell::TheFs.CharToDrive(CShell::currentPath[0], drive);
sl@0
   492
	if (r!=KErrNone)
sl@0
   493
		return(r);
sl@0
   494
	if (aPath.Length()==0)
sl@0
   495
		{
sl@0
   496
		r=CShell::TheFs.Volume(vol, drive);
sl@0
   497
		if (r==KErrNone)
sl@0
   498
			CShell::TheConsole->Printf(_L("Volume = %S\n"),&vol.iName);
sl@0
   499
		return(r);
sl@0
   500
		}
sl@0
   501
	r=CShell::TheFs.SetVolumeLabel(aPath, drive);
sl@0
   502
	return(r);
sl@0
   503
	}
sl@0
   504
sl@0
   505
TInt ShellFunction::Del(TDes& aPath,TUint aSwitches)
sl@0
   506
	{
sl@0
   507
	TParse filePath;
sl@0
   508
	if (aPath.Length()==0)
sl@0
   509
		return(KErrNone);
sl@0
   510
sl@0
   511
	ShellFunction::StripQuotes(aPath);
sl@0
   512
sl@0
   513
	GetFullPath(aPath,filePath);
sl@0
   514
	TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
sl@0
   515
	TUint switches=(recursive) ? CFileMan::ERecurse : 0;
sl@0
   516
	TInt r=CShell::TheFileMan->Delete(filePath.FullName(),switches);
sl@0
   517
	return(r);
sl@0
   518
	}
sl@0
   519
sl@0
   520
sl@0
   521
void ShellFunction::AlignTextIntoColumns(RPointerArray<HBufC>& aText)
sl@0
   522
//function which tries to arrange text as a set of columns if console width greater then the longest string
sl@0
   523
{
sl@0
   524
	TInt ind=0;
sl@0
   525
	if (aText.Count()<=0) return;
sl@0
   526
	//detect the longest string
sl@0
   527
	for (TInt i=0;i<aText.Count();i++)
sl@0
   528
		if (aText[i]->Length()>aText[ind]->Length())
sl@0
   529
			ind=i;
sl@0
   530
	TInt max_string_length=aText[ind]->Length()+2;
sl@0
   531
sl@0
   532
	//calculate how many columns fit into the screen
sl@0
   533
	TInt number_of_columns=(CShell::TheConsole->ScreenSize().iWidth)/max_string_length;
sl@0
   534
sl@0
   535
	//if we cannot fit more than one column into screen when we do nothing
sl@0
   536
	if (number_of_columns<2) return;
sl@0
   537
sl@0
   538
	//calculate column width
sl@0
   539
	TInt column_width=CShell::TheConsole->ScreenSize().iWidth/number_of_columns;
sl@0
   540
sl@0
   541
	TInt current_source_string=0;
sl@0
   542
	TInt current_destination_string=0;
sl@0
   543
sl@0
   544
	TInt count=aText.Count();
sl@0
   545
	//join strings together into string which fits in a single line
sl@0
   546
	while (current_source_string<count)
sl@0
   547
		{
sl@0
   548
		TPtr string= aText[current_destination_string++]->Des();
sl@0
   549
		TInt to_skip=0;
sl@0
   550
sl@0
   551
		for (TInt i=0;i<number_of_columns;i++)
sl@0
   552
			{
sl@0
   553
			if (current_source_string==count)
sl@0
   554
				break;
sl@0
   555
			//skip several characters to keep even distance between columns
sl@0
   556
			for (TInt j=0;j<to_skip;j++)
sl@0
   557
				string.Append(_L(" "));
sl@0
   558
sl@0
   559
			if (i==0)
sl@0
   560
				string=(*aText[current_source_string]);
sl@0
   561
			else
sl@0
   562
				string.Append(*aText[current_source_string]);
sl@0
   563
			to_skip=column_width-aText[current_source_string]->Length();
sl@0
   564
			current_source_string++;
sl@0
   565
			}
sl@0
   566
		}
sl@0
   567
sl@0
   568
	//resize aText array to the new size
sl@0
   569
sl@0
   570
	for (TInt j=aText.Count()-1;j>=current_destination_string;j--)
sl@0
   571
		{
sl@0
   572
		delete aText[j];
sl@0
   573
		aText.Remove(j);
sl@0
   574
		}
sl@0
   575
sl@0
   576
}
sl@0
   577
sl@0
   578
sl@0
   579
void ShellFunction::OutputContentsToConsole(RPointerArray<HBufC>& aText,TUint aSwitches)
sl@0
   580
//outputs content of the buffer to console according to settings passed in aSwitches
sl@0
   581
	{
sl@0
   582
	if ((aText.Count()>0)&&((aSwitches&TShellCommand::EWSwitch)!=0))
sl@0
   583
		AlignTextIntoColumns(aText);
sl@0
   584
sl@0
   585
	for (TInt i=0;i<aText.Count();i++)
sl@0
   586
		{
sl@0
   587
		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),*aText[i]);
sl@0
   588
		CShell::OutputStringToConsole(EFalse,_L("\n"));
sl@0
   589
		delete aText[i];
sl@0
   590
		}
sl@0
   591
	//empty string array
sl@0
   592
	aText.Reset();
sl@0
   593
	}
sl@0
   594
sl@0
   595
sl@0
   596
void ShellFunction::OutputDirContentL(CDir* aDirList,RPointerArray<HBufC>& aText,TUint aSwitches)
sl@0
   597
//outputs content of a directory to console according to settings passed in aSwitches
sl@0
   598
	{
sl@0
   599
	TInt count=aDirList->Count();
sl@0
   600
	TInt fileCount=0, dirCount=0, printCount=0;
sl@0
   601
	TInt64 byteCount=0;
sl@0
   602
sl@0
   603
	//compose an array of strings describing entries in the directory
sl@0
   604
	for (TInt j=0;j<count;j++)
sl@0
   605
		{
sl@0
   606
		HBufC* buf=NULL;
sl@0
   607
		TEntry entry=(*aDirList)[j];
sl@0
   608
		TDateTime modTime=entry.iModified.DateTime();
sl@0
   609
		if ((aSwitches&TShellCommand::EWSwitch)!=0)//if we are asked to output brief information about directory content
sl@0
   610
			{
sl@0
   611
			TInt length=(KMaxFileName>CShell::TheConsole->ScreenSize().iWidth)?KMaxFileName:CShell::TheConsole->ScreenSize().iWidth;
sl@0
   612
			buf = HBufC::NewL(length);
sl@0
   613
sl@0
   614
			CleanupStack::PushL(buf);
sl@0
   615
			TPtr name=buf->Des();
sl@0
   616
			name=entry.iName;
sl@0
   617
sl@0
   618
			if (entry.IsDir())
sl@0
   619
				{
sl@0
   620
				dirCount++;
sl@0
   621
				name.Insert(0,_L("["));
sl@0
   622
				name.Append(']');
sl@0
   623
				}
sl@0
   624
			else
sl@0
   625
				{
sl@0
   626
				byteCount+=entry.FileSize();
sl@0
   627
				fileCount++;
sl@0
   628
				}
sl@0
   629
			}
sl@0
   630
		else//if we are asked to output full information about directory content
sl@0
   631
			{
sl@0
   632
			buf = HBufC::NewL(KMaxFileName+100);//reserve additional space for the creation time information
sl@0
   633
			CleanupStack::PushL(buf);
sl@0
   634
			TPtr name=buf->Des();
sl@0
   635
			name=entry.iName;
sl@0
   636
sl@0
   637
			if (entry.IsDir())
sl@0
   638
				{
sl@0
   639
				dirCount++;
sl@0
   640
				name.Format(_L(" %- 26S   <DIR>         %+02d/%+02d/%- 4d  %02d:%02d:%02d.%06d"),
sl@0
   641
											&entry.iName,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
sl@0
   642
				}
sl@0
   643
			else
sl@0
   644
				{
sl@0
   645
				TInt64 entrySize = entry.FileSize();
sl@0
   646
				byteCount+=entrySize;
sl@0
   647
				fileCount++;
sl@0
   648
 				name.Format(_L(" %- 32S%+ 15Lu   %+02d/%+02d/%- 4d  %02d:%02d:%02d.%06d"),
sl@0
   649
 											&entry.iName,entrySize,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
sl@0
   650
				}
sl@0
   651
			}
sl@0
   652
		User::LeaveIfError(aText.Append(buf ));
sl@0
   653
		printCount++;
sl@0
   654
		//print the contents if a screen size of data is available. This will prevent huge buffer allocation.
sl@0
   655
		if(printCount == CShell::TheConsole->ScreenSize().iHeight)
sl@0
   656
			{
sl@0
   657
			OutputContentsToConsole(aText,aSwitches);
sl@0
   658
			printCount=0;
sl@0
   659
			}
sl@0
   660
		CleanupStack::Pop();
sl@0
   661
sl@0
   662
		}
sl@0
   663
	OutputContentsToConsole(aText,aSwitches);
sl@0
   664
sl@0
   665
	//output summary information
sl@0
   666
	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("    %d File%c\n"),fileCount,(fileCount==1)?' ':'s');
sl@0
   667
	if (fileCount!=0)
sl@0
   668
		{
sl@0
   669
		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("  %lu byte%c\n"),byteCount,(fileCount==1)?' ':'s');
sl@0
   670
		}
sl@0
   671
sl@0
   672
	TBuf<50> buf;// allocate string long enough for additional information(number of directories)
sl@0
   673
	buf.Format(_L("    %d Director"),dirCount);
sl@0
   674
	if (dirCount==1)
sl@0
   675
		buf.AppendFormat(_L("y\n"));
sl@0
   676
	else
sl@0
   677
		buf.AppendFormat(_L("ies\n"));
sl@0
   678
sl@0
   679
	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
sl@0
   680
	}
sl@0
   681
sl@0
   682
TInt ShellFunction::Dir(TDes& aPath,TUint aSwitches)
sl@0
   683
//
sl@0
   684
//	Modified December 1997, to sort entries alphabetically
sl@0
   685
//
sl@0
   686
	{
sl@0
   687
	ShellFunction::StripQuotes(aPath);
sl@0
   688
sl@0
   689
	RDir    dir;
sl@0
   690
	RFile64 file;
sl@0
   691
	TParse dirParse;
sl@0
   692
//	Parses the given path to give a full path
sl@0
   693
	GetFullPath(aPath,dirParse);
sl@0
   694
//	Sets aPath to a full path name
sl@0
   695
	aPath=dirParse.FullName();
sl@0
   696
	if (aPath[aPath.Length()-1]==KPathDelimiter)
sl@0
   697
		aPath.Append('*');
sl@0
   698
	else if (aPath.Locate(KMatchAny)==KErrNotFound && aPath.Locate(KMatchOne)==KErrNotFound && file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir)!=KErrNone)
sl@0
   699
		aPath.Append(_L("\\*"));
sl@0
   700
	else file.Close();
sl@0
   701
sl@0
   702
	TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
sl@0
   703
	if (r!=KErrNone)
sl@0
   704
		{
sl@0
   705
		CShell::TheConsole->Printf(_L("File or directory not found\n"));
sl@0
   706
		return(KErrNone);
sl@0
   707
		}
sl@0
   708
sl@0
   709
	CDir* anEntryList;
sl@0
   710
	r=TheShell->TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,anEntryList);
sl@0
   711
	if (r!=KErrNone)
sl@0
   712
		{
sl@0
   713
		dir.Close();
sl@0
   714
		return(r);
sl@0
   715
		}
sl@0
   716
    CleanupStack::PushL(anEntryList);
sl@0
   717
sl@0
   718
	//Sets the new length of path to the position of the last path delimiter +1
sl@0
   719
	aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
sl@0
   720
	CShell::TheConsole->Printf(_L("Directory of %S\n"),&aPath);
sl@0
   721
sl@0
   722
	//allocate array to be used as an output buffer
sl@0
   723
	RPointerArray<HBufC>* text=new(ELeave) RPointerArray<HBufC>();
sl@0
   724
	TRAPD(error,OutputDirContentL(anEntryList,*text,aSwitches));
sl@0
   725
	//we are not interesed in the error code because we need empty the buffer in any case
sl@0
   726
	for (TInt i=0;i<text->Count();i++)
sl@0
   727
		delete (*text)[i];
sl@0
   728
	delete text;
sl@0
   729
	CleanupStack::PopAndDestroy(anEntryList);
sl@0
   730
	dir.Close();
sl@0
   731
	if (error )
sl@0
   732
		return (error);
sl@0
   733
	else
sl@0
   734
		return(KErrNone);
sl@0
   735
	};
sl@0
   736
sl@0
   737
sl@0
   738
TInt ShellFunction::Edit(TDes& /*aPath*/,TUint /*aSwitches*/)
sl@0
   739
//
sl@0
   740
//	Dummy, used by edlin (now retired)
sl@0
   741
//
sl@0
   742
	{
sl@0
   743
	return(KErrNone);
sl@0
   744
	}
sl@0
   745
sl@0
   746
sl@0
   747
TInt ShellFunction::Attrib(TDes& aPath,TUint aSwitches)
sl@0
   748
{
sl@0
   749
	ShellFunction::StripQuotes(aPath);
sl@0
   750
sl@0
   751
//	Use TWord::NextWord(aPath) to find any spaces in the command line
sl@0
   752
	TWord nextWord(aPath);
sl@0
   753
	TInt r=nextWord.FindNextWord(aPath);
sl@0
   754
	TInt signal=0;
sl@0
   755
	const TPtrC settings[8]={(_L("+R")),(_L("-R")),(_L("+H")),(_L("-H")),(_L("+S")),(_L("-S")),(_L("+A")),(_L("-A"))};
sl@0
   756
	TInt numberOfSettings=(sizeof(settings)/sizeof(*settings));
sl@0
   757
sl@0
   758
	if (r==KErrNotFound)	//	User just typed ATTRIB
sl@0
   759
		aPath.SetLength(aPath.Length());
sl@0
   760
	else if (r==0)				//	User typed ATTRIB aWord
sl@0
   761
		{						//	Check the word for a valid attributes
sl@0
   762
		for (TInt index=0; index<numberOfSettings; index++)
sl@0
   763
			{
sl@0
   764
			signal=(nextWord.iNextWord).FindF(settings[index]);
sl@0
   765
			if (signal!=KErrNotFound)
sl@0
   766
				break;
sl@0
   767
			}
sl@0
   768
		if (signal==KErrNotFound)	//	No valid attributes settings
sl@0
   769
			aPath.SetLength(aPath.Length());
sl@0
   770
		else						//	Valid attributes settings
sl@0
   771
			aPath.SetLength(r);
sl@0
   772
		}
sl@0
   773
	else	//	User typed ATTRIB aWord1 aWord2
sl@0
   774
		{	//	Check the word for a valid attributes switch
sl@0
   775
		while (r!=KErrNotFound)
sl@0
   776
			{
sl@0
   777
			for (TInt index=0; index<numberOfSettings; index++)
sl@0
   778
				{
sl@0
   779
				signal=(nextWord.iNextWord).FindF(settings[index]);
sl@0
   780
				if (signal!=KErrNotFound)
sl@0
   781
					break;
sl@0
   782
				}
sl@0
   783
			if (signal!=KErrNotFound)  //	Matched valid switches
sl@0
   784
				{
sl@0
   785
			//	Divide up command line
sl@0
   786
			//	Include all settings (in case of "ATTRIB aWord +R +S")
sl@0
   787
				nextWord.iRightString=aPath.Right(aPath.Length()-r);
sl@0
   788
				aPath.SetLength(r);
sl@0
   789
				break;
sl@0
   790
				}
sl@0
   791
			else							//	No valid switches found in word
sl@0
   792
				r=nextWord.FindNextWord(nextWord.iRightString);	//	Check the next word
sl@0
   793
				if (r==0)	//	Reached the end of a spaced command line without finding settings
sl@0
   794
					{
sl@0
   795
					nextWord.iRightString=aPath.Right(r);
sl@0
   796
					break;
sl@0
   797
					}
sl@0
   798
			}
sl@0
   799
		}
sl@0
   800
sl@0
   801
	TParse dirParse;
sl@0
   802
	GetFullPath(aPath,dirParse);
sl@0
   803
	aPath=dirParse.FullName();
sl@0
   804
sl@0
   805
	RFile64 file;
sl@0
   806
	if (aPath[aPath.Length()-1]==KPathDelimiter)
sl@0
   807
		aPath.Append('*');
sl@0
   808
	else if( (aPath.Locate(KMatchAny)==KErrNotFound) && (aPath.Locate(KMatchOne)==KErrNotFound) )
sl@0
   809
		{
sl@0
   810
		TInt error=file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir);
sl@0
   811
		if (error!=KErrNone)
sl@0
   812
			aPath.Append(_L("\\*"));//Path does not end in a valid file
sl@0
   813
		else
sl@0
   814
			file.Close();//	Path ends in a valid file
sl@0
   815
		}
sl@0
   816
sl@0
   817
//	Changes attributes settings (files only) if requested and if necessary
sl@0
   818
	if (r!=KErrNotFound)
sl@0
   819
		{
sl@0
   820
		CDir* entryList;
sl@0
   821
		r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,entryList);
sl@0
   822
		if (r!=KErrNone)
sl@0
   823
			return (r);
sl@0
   824
		CleanupStack::PushL(entryList);
sl@0
   825
		TInt entryCount=entryList->Count();
sl@0
   826
//		Save session path
sl@0
   827
		TBuf<KShellMaxCommandLine> aSessionPath;
sl@0
   828
		r=TheShell->TheFs.SessionPath(aSessionPath);
sl@0
   829
//		Temporarily assign session path to be the path requested
sl@0
   830
//		Use the heap as we're running out of stack space
sl@0
   831
		HBufC* pTempPath=NULL;
sl@0
   832
		TRAP(r,pTempPath=HBufC::NewL(aPath.Length()))
sl@0
   833
		if (r!=KErrNone)
sl@0
   834
			{
sl@0
   835
			CleanupStack::PopAndDestroy(entryList);
sl@0
   836
			return (r);
sl@0
   837
			}
sl@0
   838
		*pTempPath=aPath;
sl@0
   839
		pTempPath->Des().SetLength(aPath.LocateReverse(KPathDelimiter)+1);
sl@0
   840
		r=TheShell->TheFs.SetSessionPath(pTempPath->Des());
sl@0
   841
		User::Free(pTempPath);
sl@0
   842
sl@0
   843
//		Looks clumsy, but necessary to change attributes of files in higher level directories
sl@0
   844
		for (TInt i=0;i<entryCount;i++)
sl@0
   845
			{
sl@0
   846
			TEntry entry=(*entryList)[i];
sl@0
   847
			if (!entry.IsDir())
sl@0
   848
				{
sl@0
   849
				for (TInt index=0; index<numberOfSettings; index++)
sl@0
   850
					{
sl@0
   851
					TInt attToSet=0;
sl@0
   852
					TInt attToRemove=0;
sl@0
   853
					signal=(nextWord.iRightString).FindF(settings[index]);
sl@0
   854
					if (signal==KErrNotFound)
sl@0
   855
						continue;
sl@0
   856
					else
sl@0
   857
						switch (index)
sl@0
   858
						{
sl@0
   859
					case 0:
sl@0
   860
						attToSet|=KEntryAttReadOnly;
sl@0
   861
						break;
sl@0
   862
					case 1:
sl@0
   863
						attToRemove|=KEntryAttReadOnly;
sl@0
   864
						break;
sl@0
   865
					case 2:
sl@0
   866
						attToSet|=KEntryAttHidden;
sl@0
   867
						break;
sl@0
   868
					case 3:
sl@0
   869
						attToRemove|=KEntryAttHidden;
sl@0
   870
						break;
sl@0
   871
					case 4:
sl@0
   872
						attToSet|=KEntryAttSystem;
sl@0
   873
						break;
sl@0
   874
					case 5:
sl@0
   875
						attToRemove|=KEntryAttSystem;
sl@0
   876
						break;
sl@0
   877
					case 6:
sl@0
   878
						attToSet|=KEntryAttArchive;
sl@0
   879
						break;
sl@0
   880
					case 7:
sl@0
   881
						attToRemove|=KEntryAttArchive;
sl@0
   882
						break;
sl@0
   883
					default:	//	Will never reach here
sl@0
   884
						break;
sl@0
   885
						}
sl@0
   886
					r=TheShell->TheFs.SetAtt((entry.iName),attToSet,attToRemove);
sl@0
   887
					continue;
sl@0
   888
					}
sl@0
   889
				}
sl@0
   890
			else continue;
sl@0
   891
			}
sl@0
   892
//		Set session path to previous setting
sl@0
   893
		r=TheShell->TheFs.SetSessionPath(aSessionPath);
sl@0
   894
		CleanupStack::PopAndDestroy(entryList);
sl@0
   895
		}
sl@0
   896
sl@0
   897
//	Runs to here if no requested attributes changes:
sl@0
   898
	CDir* alphaEntryList;
sl@0
   899
	r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,alphaEntryList);
sl@0
   900
	if (r!=KErrNone)
sl@0
   901
		return (r);
sl@0
   902
	TInt count=alphaEntryList->Count();
sl@0
   903
sl@0
   904
	RDir dir;
sl@0
   905
	r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
sl@0
   906
	if (r!=KErrNone)
sl@0
   907
        {
sl@0
   908
        delete alphaEntryList;
sl@0
   909
		return(r);
sl@0
   910
        }
sl@0
   911
sl@0
   912
	aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
sl@0
   913
sl@0
   914
sl@0
   915
	TEntry entry;
sl@0
   916
	TUint fileCount=0;
sl@0
   917
sl@0
   918
//	Lists attributes settings (files only)
sl@0
   919
	for (TInt j=0;j<count;j++)
sl@0
   920
		{
sl@0
   921
		entry=alphaEntryList->operator[](j);
sl@0
   922
		if (!entry.IsDir())
sl@0
   923
			{
sl@0
   924
			TBuf<4> attrBuf=entry.IsReadOnly()?_L("R"):_L("");
sl@0
   925
			if (entry.IsHidden())
sl@0
   926
				attrBuf.Append('H');
sl@0
   927
			if (entry.IsSystem())
sl@0
   928
				attrBuf.Append('S');
sl@0
   929
			if (entry.IsArchive())
sl@0
   930
				attrBuf.Append('A');
sl@0
   931
			CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L(" %-10S %S%S\n"),&attrBuf, &aPath,&entry.iName);
sl@0
   932
			fileCount++;
sl@0
   933
			}
sl@0
   934
		}
sl@0
   935
sl@0
   936
	dir.Close();
sl@0
   937
sl@0
   938
	if (fileCount==0)
sl@0
   939
		CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("No files found in %S\n"),&aPath);
sl@0
   940
sl@0
   941
	delete alphaEntryList;
sl@0
   942
	return(KErrNone);
sl@0
   943
  }
sl@0
   944
sl@0
   945
sl@0
   946
sl@0
   947
sl@0
   948
sl@0
   949
//--------------------------------------------------------
sl@0
   950
sl@0
   951
/**
sl@0
   952
    Format TMediaType description.
sl@0
   953
sl@0
   954
    @param  aDrvInfo    drive info structure
sl@0
   955
    @param  aPrintBuf   buffer where the information will be printed to.
sl@0
   956
*/
sl@0
   957
void FormatDrvMediaTypeInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
sl@0
   958
    {
sl@0
   959
        aPrintBuf.Format(_L("TMediaType:%d "),aDrvInfo.iType);
sl@0
   960
sl@0
   961
        switch(aDrvInfo.iType)
sl@0
   962
        {
sl@0
   963
        case EMediaNotPresent:      aPrintBuf.Append(_L("EMediaNotPresent"));   break;
sl@0
   964
        case EMediaUnknown:	        aPrintBuf.Append(_L("EMediaUnknown"));      break;
sl@0
   965
        case EMediaFloppy:          aPrintBuf.Append(_L("EMediaFloppy"));       break;
sl@0
   966
        case EMediaHardDisk:        aPrintBuf.Append(_L("EMediaHardDisk"));     break;
sl@0
   967
        case EMediaCdRom:		    aPrintBuf.Append(_L("EMediaCdRom"));        break;
sl@0
   968
        case EMediaRam:             aPrintBuf.Append(_L("EMediaRam"));          break;
sl@0
   969
        case EMediaFlash:           aPrintBuf.Append(_L("EMediaFlash"));        break;
sl@0
   970
        case EMediaRom:             aPrintBuf.Append(_L("EMediaRom"));          break;
sl@0
   971
        case EMediaRemote:          aPrintBuf.Append(_L("EMediaRemote"));       break;
sl@0
   972
        case EMediaNANDFlash:       aPrintBuf.Append(_L("EMediaNANDFlash"));    break;
sl@0
   973
        case EMediaRotatingMedia:   aPrintBuf.Append(_L("EMediaRotatingMedia"));break;
sl@0
   974
        
sl@0
   975
        default:                    aPrintBuf.Append(_L("??? Unknown Type"));   break;
sl@0
   976
        };
sl@0
   977
sl@0
   978
sl@0
   979
        aPrintBuf.Append(_L("\n"));
sl@0
   980
    }
sl@0
   981
sl@0
   982
//--------------------------------------------------------
sl@0
   983
sl@0
   984
/**
sl@0
   985
    Format DriveAtt description.
sl@0
   986
sl@0
   987
    @param  aDrvInfo    drive info structure
sl@0
   988
    @param  aPrintBuf   buffer where the information will be printed to.
sl@0
   989
*/
sl@0
   990
void FormatDriveAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
sl@0
   991
    {
sl@0
   992
        aPrintBuf.Format(_L("DriveAtt:0x%x "),aDrvInfo.iDriveAtt);
sl@0
   993
sl@0
   994
        if(aDrvInfo.iDriveAtt & KDriveAttLocal)         aPrintBuf.Append(_L("KDriveAttLocal,"));
sl@0
   995
        if(aDrvInfo.iDriveAtt & KDriveAttRom)           aPrintBuf.Append(_L("KDriveAttRom,"));
sl@0
   996
        if(aDrvInfo.iDriveAtt & KDriveAttRedirected)    aPrintBuf.Append(_L("KDriveAttRedirected,"));
sl@0
   997
        if(aDrvInfo.iDriveAtt & KDriveAttSubsted)       aPrintBuf.Append(_L("KDriveAttSubsted,"));
sl@0
   998
        if(aDrvInfo.iDriveAtt & KDriveAttInternal)      aPrintBuf.Append(_L("KDriveAttInternal,"));
sl@0
   999
        if(aDrvInfo.iDriveAtt & KDriveAttRemovable)     aPrintBuf.Append(_L("KDriveAttRemovable"));
sl@0
  1000
sl@0
  1001
        if(aDrvInfo.iDriveAtt & KDriveAttRemote)        aPrintBuf.Append(_L("KDriveAttRemote"));
sl@0
  1002
        if(aDrvInfo.iDriveAtt & KDriveAttTransaction)   aPrintBuf.Append(_L("KDriveAttTransaction"));
sl@0
  1003
sl@0
  1004
        if(aDrvInfo.iDriveAtt & KDriveAttPageable)              aPrintBuf.Append(_L("KDriveAttPageable"));
sl@0
  1005
        if(aDrvInfo.iDriveAtt & KDriveAttLogicallyRemovable)    aPrintBuf.Append(_L("KDriveAttLogicallyRemovable"));
sl@0
  1006
        if(aDrvInfo.iDriveAtt & KDriveAttHidden)                aPrintBuf.Append(_L("KDriveAttHidden"));
sl@0
  1007
sl@0
  1008
        aPrintBuf.Append(_L("\n"));
sl@0
  1009
    }
sl@0
  1010
sl@0
  1011
//--------------------------------------------------------
sl@0
  1012
sl@0
  1013
/**
sl@0
  1014
    Format MediaAtt description.
sl@0
  1015
sl@0
  1016
    @param  aDrvInfo    drive info structure
sl@0
  1017
    @param  aPrintBuf   buffer where the information will be printed to.
sl@0
  1018
*/
sl@0
  1019
void FormatMediaAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
sl@0
  1020
    {
sl@0
  1021
        aPrintBuf.Format(_L("MediaAtt:0x%x "),aDrvInfo.iMediaAtt);
sl@0
  1022
sl@0
  1023
        if(aDrvInfo.iMediaAtt & KMediaAttVariableSize)      aPrintBuf.Append(_L("KMediaAttVariableSize,"));
sl@0
  1024
        if(aDrvInfo.iMediaAtt & KMediaAttDualDensity)       aPrintBuf.Append(_L("KMediaAttDualDensity,"));
sl@0
  1025
        if(aDrvInfo.iMediaAtt & KMediaAttFormattable)       aPrintBuf.Append(_L("KMediaAttFormattable,"));
sl@0
  1026
        if(aDrvInfo.iMediaAtt & KMediaAttWriteProtected)    aPrintBuf.Append(_L("KMediaAttWriteProtected,"));
sl@0
  1027
        if(aDrvInfo.iMediaAtt & KMediaAttLockable)          aPrintBuf.Append(_L("KMediaAttLockable,"));
sl@0
  1028
        if(aDrvInfo.iMediaAtt & KMediaAttLocked)            aPrintBuf.Append(_L("KMediaAttLocked"));
sl@0
  1029
sl@0
  1030
        if(aDrvInfo.iMediaAtt & KMediaAttHasPassword)       aPrintBuf.Append(_L("KMediaAttHasPassword"));
sl@0
  1031
        if(aDrvInfo.iMediaAtt & KMediaAttReadWhileWrite)    aPrintBuf.Append(_L("KMediaAttReadWhileWrite"));
sl@0
  1032
        if(aDrvInfo.iMediaAtt & KMediaAttDeleteNotify)      aPrintBuf.Append(_L("KMediaAttDeleteNotify"));
sl@0
  1033
        if(aDrvInfo.iMediaAtt & KMediaAttPageable)          aPrintBuf.Append(_L("KMediaAttPageable"));
sl@0
  1034
        
sl@0
  1035
sl@0
  1036
        aPrintBuf.Append(_L("\n"));
sl@0
  1037
    }
sl@0
  1038
sl@0
  1039
//--------------------------------------------------------
sl@0
  1040
sl@0
  1041
/**
sl@0
  1042
    Format TVolumeInfo description.
sl@0
  1043
sl@0
  1044
    @param  volInfo     volume information
sl@0
  1045
    @param  aPrintBuf   buffer where the information will be printed to.
sl@0
  1046
*/
sl@0
  1047
void FormatVolInfo(const TVolumeInfo& volInfo , TDes& aPrintBuf)
sl@0
  1048
    {
sl@0
  1049
   	aPrintBuf.Format(_L("VolSz:%ld Free:%ld\n"),volInfo.iSize, volInfo.iFree);
sl@0
  1050
   	aPrintBuf.AppendFormat(_L("VolId:0x%x VolName:%S\n"),volInfo.iUniqueID, &volInfo.iName);
sl@0
  1051
    }
sl@0
  1052
sl@0
  1053
//--------------------------------------------------------
sl@0
  1054
sl@0
  1055
/** Bit flags that specify which information will be printed by PrintDrvInfo() */
sl@0
  1056
enum TPrintDrvInfoFlags
sl@0
  1057
{
sl@0
  1058
    EFSInfo         = 0x01, //-- file system information
sl@0
  1059
    EFSInfoEx       = 0x02, //-- extended file system information
sl@0
  1060
    EMediaTypeInfo  = 0x04, //-- media type
sl@0
  1061
    EMediaAttInfo   = 0x08, //-- media attributes etc.
sl@0
  1062
    EDrvAttInfo     = 0x10, //-- drive attributes etc
sl@0
  1063
    EVolInfo        = 0x20, //-- volume information
sl@0
  1064
sl@0
  1065
    EAll            = 0xFFFF
sl@0
  1066
};
sl@0
  1067
sl@0
  1068
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1069
/**
sl@0
  1070
    Prints information about specified drive.
sl@0
  1071
sl@0
  1072
    @param  aFs         file system object
sl@0
  1073
    @param  aDrvNum     drive number
sl@0
  1074
    @param  apConsole   pointer to the console to print information into
sl@0
  1075
    @param  aFlags      specifies which information to print out, @see TPrintDrvInfoFlags
sl@0
  1076
sl@0
  1077
    @return standard error code
sl@0
  1078
*/
sl@0
  1079
TInt PrintDrvInfo(RFs& aFs, TInt aDrvNum, CConsoleBase* apConsole, TUint aFlags = EAll)
sl@0
  1080
    {
sl@0
  1081
	TInt        nRes;
sl@0
  1082
	TDriveInfo 	driveInfo;
sl@0
  1083
	TVolumeInfo volInfo;
sl@0
  1084
	TBuf<256>   Buf;
sl@0
  1085
sl@0
  1086
	//-- get drive info
sl@0
  1087
	nRes = aFs.Drive(driveInfo, aDrvNum);
sl@0
  1088
	if(nRes != KErrNone)
sl@0
  1089
		{
sl@0
  1090
		CShell::TheConsole->Printf(_L("Error: %d\n"), nRes);
sl@0
  1091
		return nRes;   //-- can't get information about the drive
sl@0
  1092
		}
sl@0
  1093
sl@0
  1094
	
sl@0
  1095
    nRes = aFs.Volume(volInfo, aDrvNum);
sl@0
  1096
    const TBool bVolumeOK  = (nRes == KErrNone);
sl@0
  1097
	if(!bVolumeOK)
sl@0
  1098
	{//-- can't get information about the volume. It might be just corrupt/unformatted
sl@0
  1099
		CShell::TheConsole->Printf(_L("Error getting volume info. code: %d\n"), nRes);
sl@0
  1100
        if(nRes == KErrCorrupt)
sl@0
  1101
        {
sl@0
  1102
            CShell::TheConsole->Printf(_L("The volume might be corrupted or not formatted.\n"));
sl@0
  1103
        }
sl@0
  1104
	}
sl@0
  1105
sl@0
  1106
sl@0
  1107
	//-- Print out information about file system installed
sl@0
  1108
	if(aFlags & EFSInfo)
sl@0
  1109
    {
sl@0
  1110
        
sl@0
  1111
        apConsole->Printf(_L("\nDrive %c: number:%d\n"), 'A'+aDrvNum, aDrvNum);
sl@0
  1112
sl@0
  1113
	    //-- print the FS name
sl@0
  1114
	    if(aFs.FileSystemName(Buf, aDrvNum) == KErrNone)
sl@0
  1115
	    {
sl@0
  1116
	        TFSName fsName;
sl@0
  1117
            
sl@0
  1118
            nRes = aFs.FileSystemSubType(aDrvNum, fsName); 
sl@0
  1119
            if(nRes == KErrNone && Buf.CompareF(fsName) !=KErrNone)
sl@0
  1120
            {
sl@0
  1121
                Buf.AppendFormat(_L(" (%S)"), &fsName);
sl@0
  1122
            }
sl@0
  1123
sl@0
  1124
            //-- try to find out primary extension name if present
sl@0
  1125
            nRes = aFs.ExtensionName(fsName, aDrvNum, 0);
sl@0
  1126
            if(nRes == KErrNone)
sl@0
  1127
            {   
sl@0
  1128
                 Buf.AppendFormat(_L(" PExt:%S"), &fsName);
sl@0
  1129
            }
sl@0
  1130
sl@0
  1131
sl@0
  1132
            apConsole->Printf(_L("Mounted FS:%S\n"), &Buf);
sl@0
  1133
sl@0
  1134
            //-- print out the list of supported file systems if there are more than 1
sl@0
  1135
            nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, 0+1); //-- try to get 2nd child name
sl@0
  1136
            if(nRes == KErrNone)
sl@0
  1137
            {
sl@0
  1138
                Buf.Copy(_L("Supported FS: "));
sl@0
  1139
                for(TInt i=0; ;++i)
sl@0
  1140
                {
sl@0
  1141
                    nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, i); 
sl@0
  1142
                    if(nRes != KErrNone)
sl@0
  1143
                        break;
sl@0
  1144
sl@0
  1145
                    Buf.AppendFormat(_L("%S, "), &fsName);
sl@0
  1146
                }
sl@0
  1147
            
sl@0
  1148
                Buf.Append(_L("\n"));
sl@0
  1149
                apConsole->Printf(Buf);
sl@0
  1150
            }
sl@0
  1151
sl@0
  1152
sl@0
  1153
sl@0
  1154
            //-- print out FileSystem volume finalisation info
sl@0
  1155
            if(bVolumeOK && (aFlags & EFSInfoEx))
sl@0
  1156
            {
sl@0
  1157
sl@0
  1158
                TPckgBuf<TBool> boolPckg;
sl@0
  1159
                nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveFinalised, boolPckg);
sl@0
  1160
                if(nRes == KErrNone)
sl@0
  1161
                {
sl@0
  1162
                    if(boolPckg() >0)
sl@0
  1163
                        apConsole->Printf(_L("Volume Finalised\n"));
sl@0
  1164
                    else
sl@0
  1165
                        apConsole->Printf(_L("Volume Not finalised\n"));
sl@0
  1166
                }
sl@0
  1167
            }
sl@0
  1168
	    }
sl@0
  1169
    }//if(aFlags & EFSInfo)
sl@0
  1170
sl@0
  1171
	//-- print media attributes
sl@0
  1172
	if(aFlags & EMediaTypeInfo)
sl@0
  1173
    {
sl@0
  1174
        FormatDrvMediaTypeInfo(driveInfo, Buf);
sl@0
  1175
	    apConsole->Printf(Buf);
sl@0
  1176
sl@0
  1177
	}
sl@0
  1178
    
sl@0
  1179
    //-- print drive attributes
sl@0
  1180
	if(aFlags & EDrvAttInfo)
sl@0
  1181
    {
sl@0
  1182
        FormatDriveAttInfo(driveInfo, Buf);
sl@0
  1183
	    apConsole->Printf(Buf);
sl@0
  1184
    }
sl@0
  1185
sl@0
  1186
    //-- print media attributes
sl@0
  1187
	if(aFlags & EMediaAttInfo)
sl@0
  1188
    {
sl@0
  1189
	    FormatMediaAttInfo(driveInfo, Buf);
sl@0
  1190
	    apConsole->Printf(Buf);
sl@0
  1191
    }
sl@0
  1192
sl@0
  1193
sl@0
  1194
	//-- print volume information
sl@0
  1195
	if(bVolumeOK && (aFlags & EVolInfo))
sl@0
  1196
    {
sl@0
  1197
	    FormatVolInfo(volInfo, Buf);
sl@0
  1198
	    apConsole->Printf(Buf);
sl@0
  1199
    }
sl@0
  1200
	
sl@0
  1201
    return KErrNone;
sl@0
  1202
	}
sl@0
  1203
sl@0
  1204
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1205
sl@0
  1206
/**
sl@0
  1207
    Extracts drive specifier from the given string that shall look like 'd:\' or 'd:'
sl@0
  1208
    And converts it to the drive number.
sl@0
  1209
    
sl@0
  1210
    @param  aStr a string with drive specifier
sl@0
  1211
    @return Drive number EDriveA..EDriveZ if drive letter is correct
sl@0
  1212
            negative value (KErrArgument) if drive specifier is incorrect
sl@0
  1213
*/
sl@0
  1214
TInt DoExtractDriveLetter(const TDesC& aStr)
sl@0
  1215
{
sl@0
  1216
    TLex    lex(aStr);    
sl@0
  1217
    TPtrC   token;
sl@0
  1218
sl@0
  1219
    lex.SkipSpace();
sl@0
  1220
    token.Set(lex.NextToken());
sl@0
  1221
    
sl@0
  1222
    if(token.Length() < 2 || token.Length() > 3 || token[1] != ':')
sl@0
  1223
        return KErrArgument;
sl@0
  1224
sl@0
  1225
    if(token.Length() == 3 && token[2] != '\\')
sl@0
  1226
        return KErrArgument;
sl@0
  1227
sl@0
  1228
    const TChar chDrv = token[0];
sl@0
  1229
    const TInt drvNum = chDrv.GetUpperCase() - (TUint)'A'; //-- drive number
sl@0
  1230
sl@0
  1231
    if(drvNum < 0 || drvNum > EDriveZ)
sl@0
  1232
        return KErrArgument;
sl@0
  1233
sl@0
  1234
sl@0
  1235
    //-- ensure that the only drive token specified
sl@0
  1236
    token.Set(lex.NextToken());
sl@0
  1237
    if(token.Length())
sl@0
  1238
        return KErrArgument;
sl@0
  1239
sl@0
  1240
    return drvNum;
sl@0
  1241
sl@0
  1242
}
sl@0
  1243
sl@0
  1244
sl@0
  1245
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1246
//
sl@0
  1247
// Print information about specified drive or about all present drives in the system.
sl@0
  1248
//
sl@0
  1249
// DRVINFO [DriveLetter:[\]] [/p]
sl@0
  1250
//
sl@0
  1251
//          if drive letter is specified print out information about only this one.
sl@0
  1252
//			/P : pause after each drive
sl@0
  1253
//
sl@0
  1254
TInt ShellFunction::DrvInfo(TDes& aArgs, TUint aSwitches)
sl@0
  1255
	{
sl@0
  1256
sl@0
  1257
	TInt nDrv=-1;
sl@0
  1258
sl@0
  1259
	const TInt KCmdLineLen = aArgs.Length();
sl@0
  1260
	if(KCmdLineLen == 0)
sl@0
  1261
		{//-- print information about all drives in the system
sl@0
  1262
		nDrv = -1;
sl@0
  1263
		}
sl@0
  1264
	else
sl@0
  1265
		{//-- print info about specified drive
sl@0
  1266
		nDrv = DoExtractDriveLetter(aArgs);
sl@0
  1267
        if(nDrv < 0)
sl@0
  1268
            {
sl@0
  1269
            CShell::TheConsole->Printf(_L("Invalid drive specifier!\n"));    
sl@0
  1270
            return KErrNone;
sl@0
  1271
            }
sl@0
  1272
		}
sl@0
  1273
sl@0
  1274
	TInt nRes;
sl@0
  1275
	TDriveList 	driveList;
sl@0
  1276
sl@0
  1277
	//-- get drives list
sl@0
  1278
	nRes=TheShell->TheFs.DriveList(driveList);
sl@0
  1279
	if(nRes != KErrNone)
sl@0
  1280
		{
sl@0
  1281
		CShell::TheConsole->Printf(_L("\nError: %d"), nRes);
sl@0
  1282
		return nRes;
sl@0
  1283
		}
sl@0
  1284
sl@0
  1285
	if(nDrv >=0)
sl@0
  1286
		{//-- the drive is specified
sl@0
  1287
		if(!driveList[nDrv])
sl@0
  1288
			{
sl@0
  1289
			CShell::TheConsole->Printf(_L("Invalid drive specification\n"));
sl@0
  1290
			return KErrNone;
sl@0
  1291
			}
sl@0
  1292
sl@0
  1293
		PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
sl@0
  1294
		}
sl@0
  1295
	else
sl@0
  1296
		{//-- print information about all drives in the system
sl@0
  1297
		for (nDrv=0; nDrv < KMaxDrives; nDrv++)
sl@0
  1298
			{
sl@0
  1299
			if(!driveList[nDrv])
sl@0
  1300
				continue;   //-- skip unexisting drive
sl@0
  1301
sl@0
  1302
			PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
sl@0
  1303
sl@0
  1304
			if(aSwitches & TShellCommand::EPSwitch)
sl@0
  1305
				{//-- /p switch, pause after each drive
sl@0
  1306
				CShell::TheConsole->Printf(_L("\n--- press any key to continue or Esc to exit ---\n"));
sl@0
  1307
sl@0
  1308
				TKeyCode key = CShell::TheConsole->Getch();
sl@0
  1309
				if (key==EKeyEscape)
sl@0
  1310
					break;
sl@0
  1311
				}
sl@0
  1312
			else
sl@0
  1313
				{
sl@0
  1314
				CShell::TheConsole->Printf(_L("\n----------\n"));
sl@0
  1315
				}
sl@0
  1316
		}
sl@0
  1317
	}
sl@0
  1318
sl@0
  1319
	return KErrNone;
sl@0
  1320
	}
sl@0
  1321
sl@0
  1322
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1323
sl@0
  1324
/**
sl@0
  1325
    Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
sl@0
  1326
    @param  aSrc        source string
sl@0
  1327
    @param  aPattern    pattern to look for
sl@0
  1328
    @param  aToken      if the aPattern is found in the string, will contain characters from the pattern end to the next space.
sl@0
  1329
sl@0
  1330
    @return EFalse if the aPattern wasn't found in aSrc
sl@0
  1331
            ETrue otherwise and the rest of the token in aToken
sl@0
  1332
*/
sl@0
  1333
static TBool DoFindToken(const TDesC& aSrc, const TDesC& aPattern, TPtrC& aToken)
sl@0
  1334
{
sl@0
  1335
    TLex    lex(aSrc);
sl@0
  1336
    TPtrC   token;
sl@0
  1337
sl@0
  1338
    for(;;)
sl@0
  1339
    {
sl@0
  1340
        lex.SkipSpace();
sl@0
  1341
        token.Set(lex.NextToken());
sl@0
  1342
sl@0
  1343
        if(token.Length() == 0)
sl@0
  1344
            return EFalse;
sl@0
  1345
sl@0
  1346
        if(token.FindF(aPattern) == 0)
sl@0
  1347
        {//-- found a requires patern, extract substring next to it
sl@0
  1348
            aToken.Set(token.Right(token.Length() - aPattern.Length()));
sl@0
  1349
            break;
sl@0
  1350
        }
sl@0
  1351
sl@0
  1352
sl@0
  1353
    }
sl@0
  1354
sl@0
  1355
    return ETrue;
sl@0
  1356
}
sl@0
  1357
sl@0
  1358
sl@0
  1359
sl@0
  1360
sl@0
  1361
sl@0
  1362
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1363
TInt DoDismountFS(RFs& aFs, TInt aDrvNum)
sl@0
  1364
{
sl@0
  1365
    TInt        nRes;
sl@0
  1366
    TBuf<40>    fsName;
sl@0
  1367
sl@0
  1368
    nRes = aFs.FileSystemName(fsName, aDrvNum);
sl@0
  1369
sl@0
  1370
    if(nRes != KErrNone)
sl@0
  1371
        return KErrNotFound;//-- nothing to dismount
sl@0
  1372
        
sl@0
  1373
    nRes = aFs.DismountFileSystem(fsName, aDrvNum);
sl@0
  1374
    if(nRes != KErrNone)
sl@0
  1375
    {
sl@0
  1376
        CShell::TheConsole->Printf(_L("Can't dismount FS!\n"));
sl@0
  1377
        return nRes;
sl@0
  1378
    }
sl@0
  1379
    else
sl@0
  1380
    {
sl@0
  1381
    CShell::TheConsole->Printf(_L("'%S' filesystem dismounted from drive %c:\n"), &fsName, 'A'+aDrvNum);
sl@0
  1382
    return KErrNone;
sl@0
  1383
    }
sl@0
  1384
}
sl@0
  1385
sl@0
  1386
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1387
TInt DoRemountFS(RFs& aFs, TInt aDrvNum)
sl@0
  1388
{
sl@0
  1389
    TInt        nRes;
sl@0
  1390
    TBuf<40>    fsName;
sl@0
  1391
    TBuf<40>    pextName;
sl@0
  1392
sl@0
  1393
    //-- 1. get file system name
sl@0
  1394
    nRes = aFs.FileSystemName(fsName, aDrvNum);
sl@0
  1395
    if(nRes != KErrNone)
sl@0
  1396
        return KErrNotFound;
sl@0
  1397
sl@0
  1398
    //-- 2. find out if the drive sync/async
sl@0
  1399
    TPckgBuf<TBool> drvSyncBuf;
sl@0
  1400
    TBool& drvSynch = drvSyncBuf();
sl@0
  1401
sl@0
  1402
    nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveSync, drvSyncBuf);
sl@0
  1403
    if(nRes != KErrNone)
sl@0
  1404
    {//-- pretend that the drive is asynch. in the case of file system being corrupted. this is 99.9% true
sl@0
  1405
       drvSynch = EFalse;
sl@0
  1406
    }
sl@0
  1407
   
sl@0
  1408
    //-- 3. find out primary extension name if it is present; we will need to add it again when mounting the FS
sl@0
  1409
    //-- other extensions (non-primary) are not supported yet
sl@0
  1410
    nRes = aFs.ExtensionName(pextName, aDrvNum, 0);
sl@0
  1411
    if(nRes != KErrNone)
sl@0
  1412
    {
sl@0
  1413
        pextName.SetLength(0);
sl@0
  1414
    }
sl@0
  1415
    
sl@0
  1416
    //-- 3.1 check if the drive has non-primary extensions, fail in this case
sl@0
  1417
    {
sl@0
  1418
        TBuf<40> extName;
sl@0
  1419
        nRes = aFs.ExtensionName(extName, aDrvNum, 1);
sl@0
  1420
        if(nRes == KErrNone)
sl@0
  1421
        {   
sl@0
  1422
            CShell::TheConsole->Printf(_L("Non-primary extensions are not supported!\n"));
sl@0
  1423
            return KErrNotSupported;
sl@0
  1424
        }
sl@0
  1425
    }
sl@0
  1426
sl@0
  1427
    //-- 4. dismount the file system
sl@0
  1428
    nRes = DoDismountFS(aFs, aDrvNum);
sl@0
  1429
    if(nRes != KErrNone)
sl@0
  1430
        return nRes;
sl@0
  1431
sl@0
  1432
    //-- 5. mount the FS back
sl@0
  1433
    if(pextName.Length() > 0)
sl@0
  1434
    {//-- we need to mount FS with the primary extension
sl@0
  1435
        nRes = aFs.AddExtension(pextName);
sl@0
  1436
        if(nRes != KErrNone && nRes != KErrAlreadyExists)
sl@0
  1437
        {
sl@0
  1438
            return nRes;
sl@0
  1439
        }
sl@0
  1440
        
sl@0
  1441
        nRes = aFs.MountFileSystem(fsName, pextName, aDrvNum, drvSynch);
sl@0
  1442
    }
sl@0
  1443
    else
sl@0
  1444
    {//-- the FS did not have primary extension
sl@0
  1445
        nRes = aFs.MountFileSystem(fsName, aDrvNum, drvSynch);
sl@0
  1446
    }
sl@0
  1447
sl@0
  1448
    if(nRes == KErrNone)
sl@0
  1449
    {
sl@0
  1450
        CShell::TheConsole->Printf(_L("mounted filesystem:%S\n"), &fsName);
sl@0
  1451
    }
sl@0
  1452
sl@0
  1453
    return nRes;
sl@0
  1454
}
sl@0
  1455
sl@0
  1456
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1457
/**
sl@0
  1458
    Mount or dismount the file system on the specified drive.
sl@0
  1459
sl@0
  1460
    MOUNT <DriveLetter:[\]> <FSY:xxx> <FS:yyy> [PEXT:zzz] [/S] [/U]
sl@0
  1461
  
sl@0
  1462
    xxx is the *.fsy file system plugin name, like "elocal.fsy" or "elocal"
sl@0
  1463
    yyy is the file system name that the fsy module exports, like "FAT"
sl@0
  1464
    zzz is the optional parameter that specifies primary extension name
sl@0
  1465
sl@0
  1466
    /u dismounts a filesystem on the specified drive; e.g. "mount d: /u"
sl@0
  1467
    /s for mounting FS specifies that the drive will be mounted as synchronous one.
sl@0
  1468
    /f for forcing mounting the FS; the previous one will be automatically dismounted
sl@0
  1469
    /r remount existing FS (dismount and mount it back)
sl@0
  1470
*/
sl@0
  1471
TInt ShellFunction::MountFileSystem(TDes& aArgs, TUint aSwitches)
sl@0
  1472
{
sl@0
  1473
	ShellFunction::StripQuotes(aArgs);
sl@0
  1474
    aArgs.UpperCase();
sl@0
  1475
 
sl@0
  1476
    TLex        lex(aArgs);
sl@0
  1477
    TInt        nRes;
sl@0
  1478
    TBuf<40>    fsName;
sl@0
  1479
    RFs&        fs = TheShell->TheFs; 
sl@0
  1480
sl@0
  1481
sl@0
  1482
    //-- extract drive specification; this must be 1st token
sl@0
  1483
    _LIT(KErrInvalidDrive, "Invalid drive specifier\n");
sl@0
  1484
    lex.SkipSpace();
sl@0
  1485
    TPtrC token = lex.NextToken(); 
sl@0
  1486
    
sl@0
  1487
    nRes = DoExtractDriveLetter(token);
sl@0
  1488
    if(nRes < 0)
sl@0
  1489
    {
sl@0
  1490
        CShell::TheConsole->Printf(KErrInvalidDrive);
sl@0
  1491
        return KErrArgument;
sl@0
  1492
    }
sl@0
  1493
sl@0
  1494
    const TInt drvNum = nRes; //-- this is the drive number;
sl@0
  1495
sl@0
  1496
sl@0
  1497
    //-- remounting the existing FS (/R switch)
sl@0
  1498
    if(aSwitches & TShellCommand::ERSwitch)
sl@0
  1499
    {
sl@0
  1500
        nRes = DoRemountFS(fs, drvNum);
sl@0
  1501
        return nRes;
sl@0
  1502
    }
sl@0
  1503
    
sl@0
  1504
    //-- check if we dismounting the FS (/U switch)
sl@0
  1505
    if(aSwitches & TShellCommand::EUSwitch)
sl@0
  1506
    {
sl@0
  1507
        nRes = DoDismountFS(fs, drvNum);
sl@0
  1508
        
sl@0
  1509
        if(nRes == KErrNotFound)
sl@0
  1510
        {//-- nothing to dismount
sl@0
  1511
            CShell::TheConsole->Printf(_L("specified drive doesn't have FS mounted\n"));
sl@0
  1512
            return KErrNone;
sl@0
  1513
        }
sl@0
  1514
sl@0
  1515
        return nRes;
sl@0
  1516
    }
sl@0
  1517
    
sl@0
  1518
    //-- check if we need to forcedly dismount the existing FS (/F switch)
sl@0
  1519
    if(aSwitches & TShellCommand::EFSwitch)
sl@0
  1520
    {
sl@0
  1521
        nRes = DoDismountFS(fs, drvNum);
sl@0
  1522
        
sl@0
  1523
        if(nRes != KErrNotFound && nRes !=KErrNone)
sl@0
  1524
            return nRes;
sl@0
  1525
    }
sl@0
  1526
sl@0
  1527
    //-- request to mount the filesystem
sl@0
  1528
sl@0
  1529
    //-- 1. check that the specified drive doesn't have already mounted file system
sl@0
  1530
    nRes = fs.FileSystemName(fsName, drvNum);
sl@0
  1531
    if(nRes == KErrNone)
sl@0
  1532
    {
sl@0
  1533
        CShell::TheConsole->Printf(_L("specified drive already has '%S' file system mounted.\n"), &fsName);
sl@0
  1534
        CShell::TheConsole->Printf(_L("Dismount it first using '/U' switch or use '/F' switch.\n"));
sl@0
  1535
        return KErrNone;
sl@0
  1536
    }
sl@0
  1537
sl@0
  1538
    //-- 2. check '/S' switch that specifies synchronous drive
sl@0
  1539
    const TBool bDrvSynch = aSwitches & TShellCommand::ESSwitch;
sl@0
  1540
sl@0
  1541
    //-- 3. extract FSY name, file system name and optional primary extension name from the command line parameters
sl@0
  1542
    _LIT(KFSY_Param,     "fsy:");
sl@0
  1543
    _LIT(KFsName_Param,  "fs:");
sl@0
  1544
    _LIT(KPrimExt_Param, "pext:");
sl@0
  1545
sl@0
  1546
    TPtrC ptrFSYName;
sl@0
  1547
    TPtrC ptrFSName;
sl@0
  1548
    TPtrC ptrPExtName;
sl@0
  1549
sl@0
  1550
    if(!DoFindToken(aArgs, KFSY_Param, ptrFSYName))
sl@0
  1551
    {//-- FSY plugin name, like "elocal.fsy"
sl@0
  1552
        CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFSY_Param);
sl@0
  1553
        return KErrNone;
sl@0
  1554
    }
sl@0
  1555
sl@0
  1556
    if(!DoFindToken(aArgs, KFsName_Param, ptrFSName))
sl@0
  1557
    {//-- file system name, like "FAT"
sl@0
  1558
        CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFsName_Param);
sl@0
  1559
        return KErrNone;
sl@0
  1560
    }
sl@0
  1561
sl@0
  1562
    //-- note: it is possible to find out the file system name from loaded .fsy plugin.
sl@0
  1563
    //-- but it will require some coding. Probably later.
sl@0
  1564
sl@0
  1565
sl@0
  1566
    //-- optional primary extension name, like "something.fxt"
sl@0
  1567
    const TBool bPExtPresent = DoFindToken(aArgs, KPrimExt_Param, ptrPExtName);
sl@0
  1568
sl@0
  1569
sl@0
  1570
    //-- add new file system + optional extension
sl@0
  1571
    nRes = fs.AddFileSystem(ptrFSYName);
sl@0
  1572
    if(nRes != KErrNone && nRes != KErrAlreadyExists)
sl@0
  1573
    {
sl@0
  1574
        CShell::TheConsole->Printf(_L("Can't load '%S' file system plugin!\n"), &ptrFSYName);        
sl@0
  1575
        return nRes;
sl@0
  1576
    }
sl@0
  1577
sl@0
  1578
    if(bPExtPresent)
sl@0
  1579
    {
sl@0
  1580
        nRes = fs.AddExtension(ptrPExtName);
sl@0
  1581
        if(nRes != KErrNone && nRes != KErrAlreadyExists)
sl@0
  1582
        {
sl@0
  1583
            CShell::TheConsole->Printf(_L("Can't load '%S' FS extension plugin!\n"), &ptrPExtName);        
sl@0
  1584
            return nRes;
sl@0
  1585
        }
sl@0
  1586
    }
sl@0
  1587
sl@0
  1588
    //-- 4. mount new file system + optional primary extension
sl@0
  1589
    if(bPExtPresent)
sl@0
  1590
    {
sl@0
  1591
        nRes = fs.MountFileSystem(ptrFSName, ptrPExtName, drvNum, bDrvSynch);
sl@0
  1592
    }
sl@0
  1593
    else
sl@0
  1594
    {
sl@0
  1595
        nRes = fs.MountFileSystem(ptrFSName, drvNum, bDrvSynch);
sl@0
  1596
    }
sl@0
  1597
sl@0
  1598
    CShell::TheConsole->Printf(_L("Mounting new file system...\n"));        
sl@0
  1599
sl@0
  1600
    if(nRes != KErrNone && nRes != KErrCorrupt)
sl@0
  1601
    {//-- KErrCorrupt might mean that the FS mounted OK onto the drive, but ve volume itself needs formatting
sl@0
  1602
        CShell::TheConsole->Printf(_L("Error mounting the filesystem! (%d)\n"), nRes);
sl@0
  1603
        return nRes;
sl@0
  1604
    }
sl@0
  1605
sl@0
  1606
sl@0
  1607
    PrintDrvInfo(fs, drvNum, CShell::TheConsole, EFSInfo | EVolInfo);
sl@0
  1608
sl@0
  1609
    return KErrNone;
sl@0
  1610
}
sl@0
  1611
sl@0
  1612
sl@0
  1613
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1614
sl@0
  1615
/**
sl@0
  1616
    Format the specified disk
sl@0
  1617
sl@0
  1618
    FORMAT DriveLetter:[\] [fat12|fat16|fat32] [spc:X] [rs:Y] [ft:Z] [/Q] [/S] [/E]
sl@0
  1619
sl@0
  1620
        fat12|fat16|fat32 : specifies explicitly FAT type to format drive with (if it is a FAT drive)
sl@0
  1621
        spc:X   "X" specifies FAT sectors per cluster, e.g. spc:16
sl@0
  1622
        rs:Y    "Y" specifies the number of reserved sectors  (FAT FS only)
sl@0
  1623
        ft:Z    "Z" specifies the number of FAT tables 1 or 2 (FAT FS only)
sl@0
  1624
		/Q : Quick Format
sl@0
  1625
		/S : Special Format
sl@0
  1626
		/E : Remove Password and Format
sl@0
  1627
        /F : force formatting, even if there are files opened on the drive
sl@0
  1628
*/
sl@0
  1629
sl@0
  1630
TInt ShellFunction::Format(TDes& aPath, TUint aSwitches)
sl@0
  1631
	{
sl@0
  1632
    _LIT(KFormatStars,"********************");
sl@0
  1633
sl@0
  1634
	using namespace FileSystem_FAT;
sl@0
  1635
sl@0
  1636
    ShellFunction::StripQuotes(aPath);
sl@0
  1637
    aPath.UpperCase();
sl@0
  1638
sl@0
  1639
    TUint fmtMode = ESpecialFormat;
sl@0
  1640
sl@0
  1641
    //-- Format /Q - quick format
sl@0
  1642
    if (aSwitches & TShellCommand::EQSwitch)
sl@0
  1643
		fmtMode|=EQuickFormat;
sl@0
  1644
sl@0
  1645
    //-- Format /S - special format
sl@0
  1646
	if (aSwitches & TShellCommand::ESSwitch)
sl@0
  1647
		fmtMode|=ESpecialFormat;
sl@0
  1648
sl@0
  1649
	//-- Format /E - force erase
sl@0
  1650
    if (aSwitches & TShellCommand::EESwitch)
sl@0
  1651
		fmtMode|=EForceErase;
sl@0
  1652
sl@0
  1653
	//-- Format /F - force format. The volume will be formatted even if there are files or directories opened on this drive
sl@0
  1654
    if (aSwitches & TShellCommand::EFSwitch)
sl@0
  1655
		fmtMode|=EForceFormat;
sl@0
  1656
sl@0
  1657
sl@0
  1658
	TInt    fmtCnt = 0;
sl@0
  1659
	RFormat format;
sl@0
  1660
	TInt    nRes;
sl@0
  1661
    TLex    lex(aPath);
sl@0
  1662
    
sl@0
  1663
    //-- 1st token - drive path; it shall look like "d:"
sl@0
  1664
    lex.SkipSpace();
sl@0
  1665
    TPtrC ptrPath = lex.NextToken();    
sl@0
  1666
    
sl@0
  1667
    const TInt nDrv = DoExtractDriveLetter(ptrPath);
sl@0
  1668
    if(nDrv < 0 )
sl@0
  1669
        {
sl@0
  1670
        CShell::TheConsole->Printf(_L("type \"format /?\" for help.\n"));
sl@0
  1671
        return KErrNone;
sl@0
  1672
        }
sl@0
  1673
sl@0
  1674
    enum TFmtState
sl@0
  1675
        {
sl@0
  1676
        EFsNameNotSpecified,
sl@0
  1677
        EFormattingFAT,
sl@0
  1678
        EFormattingOtherFS
sl@0
  1679
        };
sl@0
  1680
    
sl@0
  1681
    
sl@0
  1682
    TFmtState formattingState = EFsNameNotSpecified;
sl@0
  1683
    TName fsName; //-- file system name
sl@0
  1684
sl@0
  1685
sl@0
  1686
    TVolFormatParamBuf volFmtParamBuf;
sl@0
  1687
    TVolFormatParam& volFmtParam = volFmtParamBuf();
sl@0
  1688
    
sl@0
  1689
sl@0
  1690
sl@0
  1691
    //-- 2nd token - file system name. 
sl@0
  1692
    //-- FAT fs is a special case, because it has subtypes; FAT FS name can be: FAT, FAT12, FAT16, FAT32
sl@0
  1693
    //-- everything else is considered as another file system name
sl@0
  1694
    lex.SkipSpace();
sl@0
  1695
    TPtrC ptrFsName = lex.NextToken();    
sl@0
  1696
    TFatSubType fatSubType = ENotSpecified;
sl@0
  1697
    
sl@0
  1698
    if(ptrFsName.Length() > 0)
sl@0
  1699
        {//-- there is a 2nd token, though it is not guaranteed to be the FS name
sl@0
  1700
        formattingState = EFormattingOtherFS;
sl@0
  1701
        
sl@0
  1702
        if(ptrFsName.FindF(KFileSystemName_FAT) == 0)
sl@0
  1703
            {//-- it looks like "FATxx"
sl@0
  1704
            fsName.Copy(KFileSystemName_FAT); 
sl@0
  1705
sl@0
  1706
            if(ptrFsName.CompareF(KFileSystemName_FAT) == 0)
sl@0
  1707
                fatSubType = ENotSpecified; //-- generic "FAT", no subtype
sl@0
  1708
            else if(ptrFsName.CompareF(KFSSubType_FAT12) == 0)
sl@0
  1709
                fatSubType = EFat12;
sl@0
  1710
            else if(ptrFsName.CompareF(KFSSubType_FAT16) == 0)
sl@0
  1711
                fatSubType = EFat16;
sl@0
  1712
            else if(ptrFsName.CompareF(KFSSubType_FAT32) == 0)
sl@0
  1713
                fatSubType = EFat32;
sl@0
  1714
            else
sl@0
  1715
                fsName.Copy(ptrFsName); //-- none of the FAT types, probably some weird FS name.
sl@0
  1716
            }
sl@0
  1717
        else
sl@0
  1718
            {
sl@0
  1719
            fsName.Copy(ptrFsName); 
sl@0
  1720
            }
sl@0
  1721
        }
sl@0
  1722
sl@0
  1723
    if(fsName == KFileSystemName_FAT) 
sl@0
  1724
        formattingState = EFormattingFAT;
sl@0
  1725
    
sl@0
  1726
    volFmtParam.Init();
sl@0
  1727
sl@0
  1728
    if(formattingState != EFsNameNotSpecified)
sl@0
  1729
        volFmtParam.SetFileSystemName(fsName);
sl@0
  1730
sl@0
  1731
    //-- process formatting parameters if they are present
sl@0
  1732
sl@0
  1733
    _LIT(KTok_SPC,      "spc:");    //-- "sectors per cluster"; valid for: FAT, exFAT
sl@0
  1734
    _LIT(KTok_RsvdSect, "rs:");     //-- "reserved sectors"   ; valid for: FAT
sl@0
  1735
    _LIT(KTok_NumFATs,  "ft:");     //-- "number of FATs"     ; valid for: FAT, exFAT
sl@0
  1736
    _LIT(KFsNameExFat,  "exfat");
sl@0
  1737
sl@0
  1738
    TPtrC   token;
sl@0
  1739
    TPtrC   ptrParams = lex.Remainder();
sl@0
  1740
    TLex    lexParam;
sl@0
  1741
    TInt    nVal;
sl@0
  1742
sl@0
  1743
    
sl@0
  1744
    //-- if we formatting FAT, process FAT-specific formatting parameters
sl@0
  1745
    if(formattingState == EFormattingFAT)
sl@0
  1746
        {
sl@0
  1747
        //-- Changing base class via derived class interface is OK here, all derived classes has the same layout and size as TVolFormatParam
sl@0
  1748
        TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
sl@0
  1749
        
sl@0
  1750
        volFmtParamFAT.Init();
sl@0
  1751
sl@0
  1752
        //-- FAT sub type
sl@0
  1753
        if(fatSubType != ENotSpecified)
sl@0
  1754
            volFmtParamFAT.SetFatSubType(fatSubType);
sl@0
  1755
        
sl@0
  1756
        //-- process "Sectors per cluster" token
sl@0
  1757
        if(DoFindToken(ptrParams, KTok_SPC, token))
sl@0
  1758
            {
sl@0
  1759
            lexParam.Assign(token);
sl@0
  1760
            lexParam.SkipSpace();
sl@0
  1761
            nRes = lexParam.Val(nVal);
sl@0
  1762
            if(nRes == KErrNone)
sl@0
  1763
                {
sl@0
  1764
                volFmtParamFAT.SetSectPerCluster(nVal);
sl@0
  1765
                }
sl@0
  1766
                else
sl@0
  1767
                {
sl@0
  1768
                CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
sl@0
  1769
                return KErrNone;
sl@0
  1770
                }
sl@0
  1771
            }
sl@0
  1772
sl@0
  1773
        //-- process "reserved sectors" token
sl@0
  1774
        if(DoFindToken(ptrParams, KTok_RsvdSect, token))
sl@0
  1775
            {
sl@0
  1776
            lexParam.Assign(token);
sl@0
  1777
            lexParam.SkipSpace();
sl@0
  1778
            nRes = lexParam.Val(nVal);
sl@0
  1779
            if(nRes == KErrNone && nVal >0 )
sl@0
  1780
                {
sl@0
  1781
                volFmtParamFAT.SetReservedSectors(nVal);
sl@0
  1782
                }
sl@0
  1783
            else
sl@0
  1784
                {
sl@0
  1785
                CShell::TheConsole->Printf(_L("Invalid Reserved Sectors value!\n"));
sl@0
  1786
                return KErrNone;
sl@0
  1787
                }
sl@0
  1788
            }
sl@0
  1789
        
sl@0
  1790
        //-- process "FAT tables" token
sl@0
  1791
        if(DoFindToken(ptrParams, KTok_NumFATs, token))
sl@0
  1792
            {
sl@0
  1793
            lexParam.Assign(token);
sl@0
  1794
            lexParam.SkipSpace();
sl@0
  1795
            nRes = lexParam.Val(nVal);
sl@0
  1796
            if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
sl@0
  1797
                {
sl@0
  1798
                volFmtParamFAT.SetNumFATs(nVal);
sl@0
  1799
                }
sl@0
  1800
            else
sl@0
  1801
                {
sl@0
  1802
                CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
sl@0
  1803
                return KErrNone;
sl@0
  1804
                }
sl@0
  1805
            }
sl@0
  1806
         
sl@0
  1807
        }//if(formattingState == EFormattingFAT)
sl@0
  1808
    else if(formattingState == EFormattingOtherFS && fsName.CompareF(KFsNameExFat)==0)
sl@0
  1809
        {//-- this is actually a h***k. exFAT exported public header file with specific data structures might not be available at all.
sl@0
  1810
sl@0
  1811
        //-- this is more serious hack. The parameters layout (SPC & NumFatTables) in the structure is the same for FAT and exFAT
sl@0
  1812
        //-- use TVolFormatParam_FAT because this code doesn't know about TVolFormatParam_exFAT
sl@0
  1813
        TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
sl@0
  1814
sl@0
  1815
        //-- process "Sectors per cluster" token
sl@0
  1816
        if(DoFindToken(ptrParams, KTok_SPC, token))
sl@0
  1817
            {
sl@0
  1818
            lexParam.Assign(token);
sl@0
  1819
            lexParam.SkipSpace();
sl@0
  1820
            nRes = lexParam.Val(nVal);
sl@0
  1821
            if(nRes == KErrNone)
sl@0
  1822
                {
sl@0
  1823
                volFmtParamFAT.SetSectPerCluster(nVal);
sl@0
  1824
                }
sl@0
  1825
                else
sl@0
  1826
                {
sl@0
  1827
                CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
sl@0
  1828
                return KErrNone;
sl@0
  1829
                }
sl@0
  1830
            }
sl@0
  1831
sl@0
  1832
        //-- process "FAT tables" token
sl@0
  1833
        if(DoFindToken(ptrParams, KTok_NumFATs, token))
sl@0
  1834
            {
sl@0
  1835
            lexParam.Assign(token);
sl@0
  1836
            lexParam.SkipSpace();
sl@0
  1837
            nRes = lexParam.Val(nVal);
sl@0
  1838
            if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
sl@0
  1839
                {
sl@0
  1840
                volFmtParamFAT.SetNumFATs(nVal);
sl@0
  1841
                }
sl@0
  1842
            else
sl@0
  1843
                {
sl@0
  1844
                CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
sl@0
  1845
                return KErrNone;
sl@0
  1846
                }
sl@0
  1847
            }
sl@0
  1848
    
sl@0
  1849
        }
sl@0
  1850
    
sl@0
  1851
sl@0
  1852
    //-------- actual formatting
sl@0
  1853
    if(formattingState == EFsNameNotSpecified)
sl@0
  1854
        {
sl@0
  1855
        nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt);
sl@0
  1856
        }
sl@0
  1857
    else
sl@0
  1858
        {
sl@0
  1859
        CShell::TheConsole->Printf(_L("The new file system is:%S\n"), &fsName);
sl@0
  1860
        nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt, volFmtParamBuf);
sl@0
  1861
        }
sl@0
  1862
sl@0
  1863
	if(nRes == KErrNone)
sl@0
  1864
	    {
sl@0
  1865
	    while(fmtCnt && nRes == KErrNone)
sl@0
  1866
		    {
sl@0
  1867
		    TInt length=(104-fmtCnt)/5;
sl@0
  1868
		    length=Min(length,KFormatStars().Length());
sl@0
  1869
		    TPtrC stars=KFormatStars().Left(length);
sl@0
  1870
		    CShell::TheConsole->Printf(_L("\r%S"),&stars);
sl@0
  1871
		    nRes=format.Next(fmtCnt);
sl@0
  1872
		    }
sl@0
  1873
	    
sl@0
  1874
        format.Close();
sl@0
  1875
sl@0
  1876
        if(nRes == KErrNone)
sl@0
  1877
            {
sl@0
  1878
            CShell::TheConsole->Printf(_L("\r%S"),&KFormatStars);
sl@0
  1879
	        CShell::NewLine();
sl@0
  1880
	        }
sl@0
  1881
        
sl@0
  1882
	    }
sl@0
  1883
sl@0
  1884
sl@0
  1885
    //-- format errors processing
sl@0
  1886
    if(nRes != KErrNone)
sl@0
  1887
        {
sl@0
  1888
        CShell::TheConsole->Printf(_L("Format failed.\n"));
sl@0
  1889
        }
sl@0
  1890
sl@0
  1891
    switch(nRes)
sl@0
  1892
        {
sl@0
  1893
        case KErrNone:
sl@0
  1894
            CShell::TheConsole->Printf(_L("Format complete.\n"));
sl@0
  1895
        break;
sl@0
  1896
sl@0
  1897
        
sl@0
  1898
        case KErrArgument: //-- FORMAT has rejected specified parameters
sl@0
  1899
            CShell::TheConsole->Printf(_L("Possible reason: Invalid combination of formatting parameters.\n"));
sl@0
  1900
            nRes = KErrNone;
sl@0
  1901
        break;
sl@0
  1902
sl@0
  1903
        case KErrNotSupported: //-- trying to format SD card with parameters or not supported FS name specified
sl@0
  1904
            CShell::TheConsole->Printf(_L("Possible reasons: media does not support special formatting or specified file system is not supported\n"));
sl@0
  1905
            nRes = KErrNone;
sl@0
  1906
        break;
sl@0
  1907
sl@0
  1908
        case KErrNotFound: //-- possible reason: unrecognisable media and automounter FS + formatting without specifying the FS name
sl@0
  1909
            CShell::TheConsole->Printf(_L("Possible reason: Unable to chose appropriate file system (not specified)\n"));
sl@0
  1910
            nRes = KErrNone;
sl@0
  1911
        break;
sl@0
  1912
sl@0
  1913
sl@0
  1914
        default:
sl@0
  1915
        break;
sl@0
  1916
        };
sl@0
  1917
    
sl@0
  1918
    
sl@0
  1919
    return nRes;
sl@0
  1920
    }
sl@0
  1921
sl@0
  1922
//-----------------------------------------------------------------------------------------------------------------------
sl@0
  1923
sl@0
  1924
TInt ShellFunction::Hexdump(TDes& aPath,TUint aSwitches)
sl@0
  1925
	{
sl@0
  1926
	ShellFunction::StripQuotes(aPath);
sl@0
  1927
sl@0
  1928
	ParsePath(aPath);
sl@0
  1929
	RFile file;
sl@0
  1930
	TInt r=file.Open(TheShell->TheFs,aPath,EFileStream);
sl@0
  1931
	if (r!=KErrNone)
sl@0
  1932
		return(r);
sl@0
  1933
sl@0
  1934
	TInt offset=0;
sl@0
  1935
	for (;;)
sl@0
  1936
		{
sl@0
  1937
		const TInt KLineLength = 16;
sl@0
  1938
sl@0
  1939
		TBuf8<KLineLength> line;
sl@0
  1940
		r=file.Read(line);
sl@0
  1941
		if (r != KErrNone || line.Length() == 0)
sl@0
  1942
			break;
sl@0
  1943
sl@0
  1944
		TBuf<KLineLength*3+2> hexaRep;
sl@0
  1945
		TBuf<KLineLength> asciiRep;
sl@0
  1946
		for (TInt i=0; i<KLineLength; i++)
sl@0
  1947
			{
sl@0
  1948
			if (i == KLineLength/2)
sl@0
  1949
				{
sl@0
  1950
				hexaRep.Append(' ');
sl@0
  1951
				hexaRep.Append(i<line.Length() ? '|' : ' ');
sl@0
  1952
				}
sl@0
  1953
sl@0
  1954
			hexaRep.Append(' ');
sl@0
  1955
sl@0
  1956
			if (i<line.Length())
sl@0
  1957
				{
sl@0
  1958
				hexaRep.AppendNumFixedWidth(line[i], EHex, 2);
sl@0
  1959
				asciiRep.Append(TChar(line[i]).IsPrint() ? line[i] : '.');
sl@0
  1960
				}
sl@0
  1961
			else
sl@0
  1962
				hexaRep.AppendFill(' ', 2);
sl@0
  1963
			}
sl@0
  1964
sl@0
  1965
		_LIT(KPrompt , " Hit escape to quit hexdump or any other key to continue\n");
sl@0
  1966
		_LIT(KLineFmt, " %+07x0:%S %S\n");
sl@0
  1967
		TKeyCode key=CShell::OutputStringToConsole(KPrompt ,(aSwitches&TShellCommand::EPSwitch)!=0,KLineFmt, offset++,&hexaRep, &asciiRep);
sl@0
  1968
sl@0
  1969
		if (key==EKeyEscape)
sl@0
  1970
				break;
sl@0
  1971
		}
sl@0
  1972
sl@0
  1973
	if (r == KErrNone)
sl@0
  1974
		CShell::NewLine();
sl@0
  1975
sl@0
  1976
	file.Close();
sl@0
  1977
	return r;
sl@0
  1978
	}
sl@0
  1979
sl@0
  1980
/**
sl@0
  1981
    Create a file. The file can be empty or filled with random data.
sl@0
  1982
    The maximal file size depends on the file system of the drive.
sl@0
  1983
sl@0
  1984
    Gobble <file name> <aaaa|0xbbbb>  [/E]
sl@0
  1985
sl@0
  1986
    aaaa file size decimal
sl@0
  1987
    bbbb file size hexadecimal, shall be prefixed with '0x'
sl@0
  1988
    
sl@0
  1989
    /e for creating an empty file, do not fill it with data
sl@0
  1990
*/
sl@0
  1991
TInt ShellFunction::Gobble(TDes& aPath,TUint aSwitches)
sl@0
  1992
	{
sl@0
  1993
	ShellFunction::StripQuotes(aPath);
sl@0
  1994
sl@0
  1995
	TInt fileNameLen=aPath.LocateReverse(' ');
sl@0
  1996
	if (fileNameLen==KErrNotFound)	//	No spaces implies no filelength specified
sl@0
  1997
		{
sl@0
  1998
		CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
sl@0
  1999
		return (KErrNone);
sl@0
  2000
		}
sl@0
  2001
sl@0
  2002
	TInt fileLength=(aPath.Length()-fileNameLen);
sl@0
  2003
	if (fileLength>16)
sl@0
  2004
		return (KErrTooBig);	//	Too many digits - too large!
sl@0
  2005
	TBuf<16> rightString=aPath.Right(fileLength);
sl@0
  2006
	aPath.SetLength(fileNameLen);
sl@0
  2007
sl@0
  2008
	TLex size(rightString);
sl@0
  2009
	size.SkipSpace();
sl@0
  2010
	TRadix radix=ParseHexaPrefixIfAny(size);
sl@0
  2011
	
sl@0
  2012
    TInt64 fileSize;
sl@0
  2013
	TInt r=size.Val(fileSize,radix);
sl@0
  2014
	if (r!=KErrNone || ! size.Eos())
sl@0
  2015
		{
sl@0
  2016
		CShell::TheConsole->Printf(_L("Please specify a file length\n"));
sl@0
  2017
		return (KErrNone);
sl@0
  2018
		}
sl@0
  2019
sl@0
  2020
	if (aPath.Length()==0)
sl@0
  2021
		aPath=_L("GOBBLE.DAT");
sl@0
  2022
sl@0
  2023
	TParse fileName;
sl@0
  2024
	GetFullPath(aPath,fileName);
sl@0
  2025
	RFile64 file;
sl@0
  2026
sl@0
  2027
    const TInt    KBufSize=65536; //-- buffer size for writing data
sl@0
  2028
    const TUint32 K1Megabyte = 1<<20; //-- 1M, 1048576
sl@0
  2029
    TInt64 cntBytes = 0;
sl@0
  2030
    TUint32 cntMegaBytes =0;
sl@0
  2031
sl@0
  2032
    //-- allocate buffer for data
sl@0
  2033
    RBuf8 buf;
sl@0
  2034
    r = buf.CreateMax(KBufSize);
sl@0
  2035
    if(r != KErrNone)
sl@0
  2036
        return r;
sl@0
  2037
sl@0
  2038
    //-- initialize buffer with random rubbish
sl@0
  2039
    //Mem::Fill((void*)buf.Ptr(),KBufSize,0xa3);
sl@0
  2040
    {
sl@0
  2041
        TInt64 rndSeed = Math::Random();
sl@0
  2042
        for(TInt i=0; i<KBufSize; ++i)
sl@0
  2043
        {
sl@0
  2044
            buf[i] = (TUint8)Math::Rand(rndSeed);
sl@0
  2045
        }
sl@0
  2046
    }
sl@0
  2047
sl@0
  2048
sl@0
  2049
    TInt64  rem = fileSize;
sl@0
  2050
    TTime startTime;
sl@0
  2051
    TTime endTime;
sl@0
  2052
    TTimeIntervalSeconds timeTaken;
sl@0
  2053
sl@0
  2054
    startTime.UniversalTime(); //-- take start time
sl@0
  2055
sl@0
  2056
    r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
sl@0
  2057
    if(r != KErrNone)
sl@0
  2058
        goto fail;
sl@0
  2059
sl@0
  2060
    //-- this can make write faster on rugged fat.
sl@0
  2061
    if(aSwitches&TShellCommand::EESwitch)
sl@0
  2062
    {//-- /e switch is specified, create an empty file without writing data
sl@0
  2063
        CShell::TheConsole->Printf(_L("Creating an empty file, size:%LD bytes\n"), fileSize);
sl@0
  2064
    }
sl@0
  2065
sl@0
  2066
    r=file.SetSize(fileSize);
sl@0
  2067
    if(r != KErrNone)
sl@0
  2068
        goto fail;
sl@0
  2069
sl@0
  2070
sl@0
  2071
    if(!(aSwitches&TShellCommand::EESwitch))
sl@0
  2072
    {//-- fill created file with randomn data
sl@0
  2073
sl@0
  2074
	    while(rem)
sl@0
  2075
	    {
sl@0
  2076
	        const TInt s=(TInt)Min((TInt64)KBufSize, rem);
sl@0
  2077
sl@0
  2078
            r=file.Write(buf, s);
sl@0
  2079
		    if(r!=KErrNone)
sl@0
  2080
		        goto fail;
sl@0
  2081
sl@0
  2082
            rem-=s;
sl@0
  2083
sl@0
  2084
            //-- print out number of megabytes written
sl@0
  2085
            cntBytes+=s;
sl@0
  2086
            if(cntBytes > 0 && (cntBytes & (K1Megabyte-1))==0)
sl@0
  2087
            {
sl@0
  2088
                ++cntMegaBytes;
sl@0
  2089
                CShell::TheConsole->Printf(_L("%u MB written.\n"),cntMegaBytes);
sl@0
  2090
            }
sl@0
  2091
        }//while(rem)
sl@0
  2092
sl@0
  2093
    }
sl@0
  2094
sl@0
  2095
    file.Close();
sl@0
  2096
    endTime.UniversalTime(); //-- take end time
sl@0
  2097
    buf.Close();
sl@0
  2098
sl@0
  2099
    endTime.SecondsFrom(startTime, timeTaken);
sl@0
  2100
sl@0
  2101
    CShell::TheConsole->Printf(_L("Total bytes written:%LD\n"), cntBytes);
sl@0
  2102
    CShell::TheConsole->Printf(_L("Time taken:%d Sec.\n"), timeTaken.Int());
sl@0
  2103
sl@0
  2104
    return r;
sl@0
  2105
sl@0
  2106
    //-- failure.
sl@0
  2107
 fail:
sl@0
  2108
    file.Close();
sl@0
  2109
    buf.Close();
sl@0
  2110
    if(r!= KErrAlreadyExists) //this is to ensure that an existing file does not get deleted
sl@0
  2111
	    CShell::TheFs.Delete(fileName.FullName());
sl@0
  2112
sl@0
  2113
    CShell::TheConsole->Printf(_L("Error - could not create file, code:%d\n"), r);
sl@0
  2114
sl@0
  2115
    return r;
sl@0
  2116
	}
sl@0
  2117
sl@0
  2118
TInt ShellFunction::Md(TDes& aPath,TUint /*aSwitches*/)
sl@0
  2119
	{
sl@0
  2120
	if (aPath.Length()==0)
sl@0
  2121
		return(KErrBadName);
sl@0
  2122
sl@0
  2123
	ShellFunction::StripQuotes(aPath);
sl@0
  2124
sl@0
  2125
	if (aPath[aPath.Length()-1]!=KPathDelimiter)
sl@0
  2126
		aPath.Append(KPathDelimiter);
sl@0
  2127
sl@0
  2128
	TParse dirPath;
sl@0
  2129
	TInt r = GetFullPath(aPath,dirPath);
sl@0
  2130
	if(r!=KErrNone)
sl@0
  2131
		{
sl@0
  2132
		return(r);
sl@0
  2133
		}
sl@0
  2134
	return(TheShell->TheFs.MkDir(dirPath.FullName()));
sl@0
  2135
	}
sl@0
  2136
sl@0
  2137
TInt ShellFunction::Move(TDes& aPath,TUint aSwitches)
sl@0
  2138
	{
sl@0
  2139
sl@0
  2140
//	Modified to add more helpful error messages and allow spaced filenames
sl@0
  2141
	ShellFunction::StripQuotes(aPath);
sl@0
  2142
sl@0
  2143
	TBuf<KShellMaxCommandLine> newName;
sl@0
  2144
	TBuf<KShellMaxCommandLine> tempPath=aPath;
sl@0
  2145
	RFile64 file;
sl@0
  2146
	TWord   word(aPath);
sl@0
  2147
sl@0
  2148
	TInt r=word.FindNextWord(aPath);
sl@0
  2149
//	Check if the word returned is a valid filename.  If not, scan the next
sl@0
  2150
//	word too in case the filename contains spaces.  If, at the end of the
sl@0
  2151
//	the line, the filename is not recognised, it is invalid.  If there are no
sl@0
  2152
//	spaces the user has not used the correct format for this command.
sl@0
  2153
sl@0
  2154
	while (r>0)
sl@0
  2155
		{
sl@0
  2156
		newName=aPath.Right(aPath.Length()-r);
sl@0
  2157
		tempPath.SetLength(r);
sl@0
  2158
		TParse oldName;
sl@0
  2159
		TInt result=GetFullPath(tempPath,oldName);
sl@0
  2160
		if (result!=KErrNone)
sl@0
  2161
			return(r);
sl@0
  2162
sl@0
  2163
		TBool validFileOrDir = EFalse;
sl@0
  2164
sl@0
  2165
		result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
sl@0
  2166
		if (result==KErrNone)	//	A valid filename
sl@0
  2167
			{
sl@0
  2168
			file.Close();
sl@0
  2169
			validFileOrDir = ETrue;
sl@0
  2170
			}
sl@0
  2171
		else	//	Not a valid filename - move one word along the command line
sl@0
  2172
			{
sl@0
  2173
			// Not a valid filename - Could be a directory...
sl@0
  2174
			RDir directory;
sl@0
  2175
			result=directory.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclusive|KEntryAttDir);
sl@0
  2176
			if (result == KErrNone)
sl@0
  2177
				{
sl@0
  2178
				directory.Close();
sl@0
  2179
				validFileOrDir = ETrue;
sl@0
  2180
				}
sl@0
  2181
			}
sl@0
  2182
sl@0
  2183
		if(validFileOrDir)
sl@0
  2184
			{
sl@0
  2185
			TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
sl@0
  2186
			TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
sl@0
  2187
			r=CShell::TheFileMan->Move(oldName.FullName(),newName,switches);
sl@0
  2188
			if (r==KErrAccessDenied)
sl@0
  2189
				{
sl@0
  2190
				CShell::TheConsole->Printf(_L("Access denied - cannot move %S\n"),&tempPath);
sl@0
  2191
				CShell::TheConsole->Printf(_L("To move %Sinto directory %S append \\ to the full destination\n"),&tempPath,&newName);
sl@0
  2192
				return (KErrNone);
sl@0
  2193
				}
sl@0
  2194
			return(r);
sl@0
  2195
			}
sl@0
  2196
sl@0
  2197
		r=word.FindNextWord(word.iRightString);
sl@0
  2198
		}
sl@0
  2199
	if (r<0)		//	r = some error code
sl@0
  2200
		return (r);	//	Error in filename or destination
sl@0
  2201
	else						//	r = 0
sl@0
  2202
		return (KErrNotFound);
sl@0
  2203
	}
sl@0
  2204
sl@0
  2205
TInt GetChunkInfo(TAny* aPtr)
sl@0
  2206
	{
sl@0
  2207
sl@0
  2208
	TFindChunk findHb;
sl@0
  2209
	TFullName* namePtr=(TFullName*)aPtr;
sl@0
  2210
	findHb.Find(*namePtr);
sl@0
  2211
	TFullName aFN;
sl@0
  2212
	findHb.Next(aFN);
sl@0
  2213
	RChunk c;
sl@0
  2214
	TInt r=c.Open(findHb);
sl@0
  2215
	if(r==KErrPermissionDenied)
sl@0
  2216
		{
sl@0
  2217
		CShell::TheConsole->Printf(_L("...Chunk is protected. No info available.\n"));
sl@0
  2218
		}
sl@0
  2219
	else
sl@0
  2220
		{
sl@0
  2221
		CShell::TheConsole->Printf(_L("...Size %dk MaxSize %dk Base 0x%x\n"),c.Size()/1024,c.MaxSize()/1024,c.Base());
sl@0
  2222
		c.Close();
sl@0
  2223
		}
sl@0
  2224
/*
sl@0
  2225
#if defined (__WINS__)
sl@0
  2226
	c.Close();
sl@0
  2227
#else
sl@0
  2228
	if (aFN.Match(_L("*ESHELL*"))<0)
sl@0
  2229
		c.Close();
sl@0
  2230
#endif
sl@0
  2231
*/
sl@0
  2232
	return r;
sl@0
  2233
	};
sl@0
  2234
sl@0
  2235
TInt GetThreadInfo(TAny* aPtr)
sl@0
  2236
//	New function added by WR, November 1997
sl@0
  2237
	{
sl@0
  2238
	TBuf<80> detail;
sl@0
  2239
	TFindThread* findHb = (TFindThread*)aPtr;
sl@0
  2240
	RThread t;
sl@0
  2241
	TInt err = t.Open(*findHb);
sl@0
  2242
	if (err != KErrNone)
sl@0
  2243
		{
sl@0
  2244
		detail.Format(_L("... can't open thread, err=%d\n"), err);
sl@0
  2245
		CShell::TheConsole->Printf(detail);
sl@0
  2246
		return KErrNone;
sl@0
  2247
		}
sl@0
  2248
sl@0
  2249
	TExitType exit = t.ExitType();
sl@0
  2250
	TBuf<KMaxExitCategoryName> exitCat=t.ExitCategory();
sl@0
  2251
	TThreadId threadId = t.Id();
sl@0
  2252
	TUint id = *(TUint*)&threadId;
sl@0
  2253
	RProcess proc;
sl@0
  2254
	TInt pid = t.Process(proc);
sl@0
  2255
	if (pid==KErrNone)
sl@0
  2256
		{
sl@0
  2257
		TProcessId procId = proc.Id();
sl@0
  2258
		pid = *(TInt*)&procId;
sl@0
  2259
		proc.Close();
sl@0
  2260
		}
sl@0
  2261
sl@0
  2262
	switch (exit)
sl@0
  2263
		{
sl@0
  2264
	case EExitPending:
sl@0
  2265
		detail.Format(_L("... ID %d (Proc %d), running\n"), id, pid);
sl@0
  2266
		break;
sl@0
  2267
	case EExitPanic:
sl@0
  2268
	//	lint -e50
sl@0
  2269
		detail.Format(_L("... ID %d (Proc %d), panic \"%S\" %d\n"), id, pid,
sl@0
  2270
			&exitCat, t.ExitReason());
sl@0
  2271
		break;
sl@0
  2272
	case EExitKill:
sl@0
  2273
		detail.Format(_L("... ID %d (Proc %d), killed %d\n"), id, pid, t.ExitReason());
sl@0
  2274
		break;
sl@0
  2275
	case EExitTerminate:
sl@0
  2276
		detail.Format(_L("... ID %d (Proc %d), terminated %d\n"), id, pid, t.ExitReason());
sl@0
  2277
		break;
sl@0
  2278
	default:
sl@0
  2279
		detail.Format(_L("... ID %d (Proc %d), ?exit type %d?\n"), id, pid, exit);
sl@0
  2280
		break;
sl@0
  2281
		}
sl@0
  2282
	t.Close();
sl@0
  2283
	CShell::TheConsole->Printf(detail);
sl@0
  2284
	return KErrNone;
sl@0
  2285
	};
sl@0
  2286
//	End of modification
sl@0
  2287
sl@0
  2288
// Class for showing information about processes
sl@0
  2289
class TShowProcInfo
sl@0
  2290
	{
sl@0
  2291
public:
sl@0
  2292
	TInt DisplayHelp();
sl@0
  2293
	TInt DisplayMessage(const TFullName& aName);
sl@0
  2294
	TInt DisplayCmdUnknown();
sl@0
  2295
	TInt GetAll(const TDes& aName);
sl@0
  2296
	TInt GetProcesses(const TDes& aName);
sl@0
  2297
	TInt GetThreads(const TDes& aName);
sl@0
  2298
	TInt GetChunks(const TDes& aName);
sl@0
  2299
	TInt GetServers(const TDes& aName);
sl@0
  2300
//	TInt GetSessions(const TDes& aName);
sl@0
  2301
	TInt GetLibraries(const TDes& aName);
sl@0
  2302
//	TInt GetLogicalChannels(const TDes& aName);
sl@0
  2303
	TInt GetLogicalDevices(const TDes& aName);
sl@0
  2304
	TInt GetPhysicalDevices(const TDes& aName);
sl@0
  2305
	TInt GetSemaphores(const TDes& aName);
sl@0
  2306
	TInt GetMutexes(const TDes& aName);
sl@0
  2307
private:
sl@0
  2308
	void DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription);
sl@0
  2309
	TInt Prepare(const TFullName& aName);
sl@0
  2310
	TInt Prepare(const TFullName& aName,TCallBack& aCallBack);
sl@0
  2311
	TInt Display(TFullName& aName);
sl@0
  2312
	TFullName iPrevName;
sl@0
  2313
	TCallBack iCallBack;
sl@0
  2314
	TBool useCallBack;
sl@0
  2315
	};
sl@0
  2316
sl@0
  2317
TInt TShowProcInfo::DisplayHelp()
sl@0
  2318
	{
sl@0
  2319
sl@0
  2320
	DisplayHelpLine(_L("H or ?"),_L("Show Help"));
sl@0
  2321
	DisplayHelpLine(_L("Q"),_L("Quit Process Status Mode"));
sl@0
  2322
	DisplayHelpLine(_L("X<name>"),_L("Switch to a particular Process domain"));
sl@0
  2323
	DisplayHelpLine(_L("X"),_L("Go Back to standard Process Status Mode"));
sl@0
  2324
	DisplayHelpLine(_L("A"),_L("Display all container objects"));
sl@0
  2325
	DisplayHelpLine(_L("P"),_L("List all Processes (irrespective of current domain)"));
sl@0
  2326
	DisplayHelpLine(_L("T"),_L("List Threads"));
sl@0
  2327
	DisplayHelpLine(_L("C"),_L("List Chunks, their sizes, maximum sizes and addresses"));
sl@0
  2328
	DisplayHelpLine(_L("S"),_L("List Servers"));
sl@0
  2329
//	DisplayHelpLine(_L("I"),_L("List Sessions"));
sl@0
  2330
	DisplayHelpLine(_L("L"),_L("List Libraries"));
sl@0
  2331
//	DisplayHelpLine(_L("G"),_L("List Logical Channels"));
sl@0
  2332
	DisplayHelpLine(_L("V"),_L("List Logical Devices"));
sl@0
  2333
	DisplayHelpLine(_L("D"),_L("List Physical Devices"));
sl@0
  2334
	DisplayHelpLine(_L("E"),_L("List Semaphores"));
sl@0
  2335
	DisplayHelpLine(_L("M"),_L("List Mutexes"));
sl@0
  2336
	return KErrNone;
sl@0
  2337
	}
sl@0
  2338
sl@0
  2339
TInt TShowProcInfo::DisplayMessage(const TFullName& aMessage)
sl@0
  2340
	{
sl@0
  2341
	CShell::OutputStringToConsole(ETrue,aMessage);
sl@0
  2342
	CShell::NewLine();
sl@0
  2343
	return KErrNone;
sl@0
  2344
	}
sl@0
  2345
sl@0
  2346
TInt TShowProcInfo::DisplayCmdUnknown()
sl@0
  2347
	{
sl@0
  2348
	CShell::OutputStringToConsole(ETrue,_L("Not supported\n"));
sl@0
  2349
	return KErrNone;
sl@0
  2350
	}
sl@0
  2351
sl@0
  2352
TInt TShowProcInfo::GetAll(const TDes& aName)
sl@0
  2353
	{
sl@0
  2354
sl@0
  2355
	GetProcesses(aName);
sl@0
  2356
	GetThreads(aName);
sl@0
  2357
	GetChunks(aName);
sl@0
  2358
	GetServers(aName);
sl@0
  2359
//	GetSessions(aName);
sl@0
  2360
	GetLibraries(aName);
sl@0
  2361
//	GetLogicalChannels(aName);
sl@0
  2362
	GetLogicalDevices(aName);
sl@0
  2363
	GetPhysicalDevices(aName);
sl@0
  2364
	GetSemaphores(aName);
sl@0
  2365
	GetMutexes(aName);
sl@0
  2366
	return KErrNone;
sl@0
  2367
	}
sl@0
  2368
sl@0
  2369
TInt TShowProcInfo::GetProcesses(const TDes& aName)
sl@0
  2370
	{
sl@0
  2371
sl@0
  2372
	TFindProcess findHb;
sl@0
  2373
	findHb.Find(aName);
sl@0
  2374
	TFullName name;
sl@0
  2375
	Prepare(_L("PROCESSES"));
sl@0
  2376
	while (findHb.Next(name)==KErrNone)
sl@0
  2377
		{
sl@0
  2378
		Display(name);
sl@0
  2379
		}
sl@0
  2380
	return KErrNone;
sl@0
  2381
	}
sl@0
  2382
sl@0
  2383
TInt TShowProcInfo::GetThreads(const TDes& aName)
sl@0
  2384
	{
sl@0
  2385
	TInt threads=0;
sl@0
  2386
	TFindThread findHb;
sl@0
  2387
	findHb.Find(aName);
sl@0
  2388
	TFullName name;
sl@0
  2389
	TAny* findPtr=(TAny*)&findHb;
sl@0
  2390
sl@0
  2391
//	Modified by WR, November 1997
sl@0
  2392
	TCallBack threadCallBack(GetThreadInfo,findPtr);
sl@0
  2393
	Prepare(_L("THREADS"),threadCallBack);
sl@0
  2394
	while (findHb.Next(name)==KErrNone)
sl@0
  2395
		{
sl@0
  2396
		Display(name);
sl@0
  2397
		threads += 1;
sl@0
  2398
		}
sl@0
  2399
	if (threads==0)
sl@0
  2400
		{
sl@0
  2401
		TFullName message;
sl@0
  2402
		message.Format(_L("? No threads called %S"), &aName);
sl@0
  2403
		DisplayMessage(message);
sl@0
  2404
		}
sl@0
  2405
	return KErrNone;
sl@0
  2406
//	End of modification
sl@0
  2407
	}
sl@0
  2408
sl@0
  2409
sl@0
  2410
TInt TShowProcInfo::GetChunks(const TDes& aName)
sl@0
  2411
	{
sl@0
  2412
sl@0
  2413
	TFindChunk findHb;
sl@0
  2414
	findHb.Find(aName);
sl@0
  2415
	TFullName name;
sl@0
  2416
	TAny* namePtr=(TAny*)&name;
sl@0
  2417
	TCallBack chunkCallBack(GetChunkInfo,namePtr);
sl@0
  2418
	Prepare(_L("CHUNKS & SIZES"),chunkCallBack);
sl@0
  2419
	TInt totalChunkSize=0;
sl@0
  2420
	TInt protectedChunks = 0;
sl@0
  2421
	while (findHb.Next(name)==KErrNone)
sl@0
  2422
		{
sl@0
  2423
		Display(name);
sl@0
  2424
		RChunk c;
sl@0
  2425
		TInt r=c.Open(findHb);
sl@0
  2426
		if(r!=KErrNone)
sl@0
  2427
			++protectedChunks;
sl@0
  2428
		else
sl@0
  2429
			{
sl@0
  2430
			totalChunkSize+=c.Size()/1024;
sl@0
  2431
			c.Close();
sl@0
  2432
			}
sl@0
  2433
/*
sl@0
  2434
#if defined(__WINS__)
sl@0
  2435
		c.Close();
sl@0
  2436
#else
sl@0
  2437
		if (name.Match(_L("*ESHELL*"))<0)
sl@0
  2438
			c.Close();
sl@0
  2439
#endif
sl@0
  2440
*/
sl@0
  2441
		}
sl@0
  2442
	CShell::OutputStringToConsole(ETrue,_L("  Total Chunk Size = %dk\n"),totalChunkSize);
sl@0
  2443
	if(protectedChunks)
sl@0
  2444
		CShell::OutputStringToConsole(ETrue,_L("  %d Protected chunks not counted\n"),protectedChunks);
sl@0
  2445
	return KErrNone;
sl@0
  2446
	}
sl@0
  2447
sl@0
  2448
TInt TShowProcInfo::GetServers(const TDes& aName)
sl@0
  2449
	{
sl@0
  2450
sl@0
  2451
	TFindServer findHb;
sl@0
  2452
	findHb.Find(aName);
sl@0
  2453
	TFullName name;
sl@0
  2454
	Prepare(_L("SERVERS"));
sl@0
  2455
	while (findHb.Next(name)==KErrNone)
sl@0
  2456
		{
sl@0
  2457
		Display(name);
sl@0
  2458
		}
sl@0
  2459
	return KErrNone;
sl@0
  2460
	}
sl@0
  2461
sl@0
  2462
/*	TInt TShowProcInfo::GetSessions(const TDes& aName)
sl@0
  2463
	{
sl@0
  2464
sl@0
  2465
	TFindSession findHb;
sl@0
  2466
	findHb.Find(aName);
sl@0
  2467
	TFullName name;
sl@0
  2468
	Prepare(_L("SESSIONS"));
sl@0
  2469
	while (findHb.Next(name)==KErrNone)
sl@0
  2470
		{
sl@0
  2471
		Display(name);
sl@0
  2472
		}
sl@0
  2473
	return KErrNone;
sl@0
  2474
	}
sl@0
  2475
*/
sl@0
  2476
TInt TShowProcInfo::GetLibraries(const TDes& aName)
sl@0
  2477
	{
sl@0
  2478
sl@0
  2479
	TFindLibrary findHb;
sl@0
  2480
	findHb.Find(aName);
sl@0
  2481
	TFullName name;
sl@0
  2482
	Prepare(_L("LIBRARIES"));
sl@0
  2483
	while (findHb.Next(name)==KErrNone)
sl@0
  2484
		{
sl@0
  2485
		Display(name);
sl@0
  2486
		}
sl@0
  2487
	return KErrNone;
sl@0
  2488
	}
sl@0
  2489
/*
sl@0
  2490
TInt TShowProcInfo::GetLogicalChannels(const TDes& aName)
sl@0
  2491
	{
sl@0
  2492
sl@0
  2493
	TFindLogicalChannel findHb;
sl@0
  2494
	findHb.Find(aName);
sl@0
  2495
	TFullName name;
sl@0
  2496
	Prepare(_L("LOGICAL CHANNELS"));
sl@0
  2497
	while (findHb.Next(name)==KErrNone)
sl@0
  2498
		{
sl@0
  2499
		Display(name);
sl@0
  2500
		}
sl@0
  2501
	return KErrNone;
sl@0
  2502
	}
sl@0
  2503
*/
sl@0
  2504
sl@0
  2505
TInt TShowProcInfo::GetLogicalDevices(const TDes& aName)
sl@0
  2506
	{
sl@0
  2507
sl@0
  2508
	TFindLogicalDevice findHb;
sl@0
  2509
	findHb.Find(aName);
sl@0
  2510
	TFullName name;
sl@0
  2511
	Prepare(_L("LOGICAL DEVICES"));
sl@0
  2512
	while (findHb.Next(name)==KErrNone)
sl@0
  2513
		{
sl@0
  2514
		Display(name);
sl@0
  2515
		}
sl@0
  2516
	return KErrNone;
sl@0
  2517
	}
sl@0
  2518
sl@0
  2519
TInt TShowProcInfo::GetPhysicalDevices(const TDes& aName)
sl@0
  2520
	{
sl@0
  2521
sl@0
  2522
	TFindPhysicalDevice findHb;
sl@0
  2523
	findHb.Find(aName);
sl@0
  2524
	TFullName name;
sl@0
  2525
	Prepare(_L("PHYSICAL DEVICES"));
sl@0
  2526
	while (findHb.Next(name)==KErrNone)
sl@0
  2527
		{
sl@0
  2528
		Display(name);
sl@0
  2529
		}
sl@0
  2530
	return KErrNone;
sl@0
  2531
	}
sl@0
  2532
sl@0
  2533
TInt TShowProcInfo::GetSemaphores(const TDes& aName)
sl@0
  2534
	{
sl@0
  2535
	TFindSemaphore findHb;
sl@0
  2536
	findHb.Find(aName);
sl@0
  2537
	TFullName name;
sl@0
  2538
	Prepare(_L("SEMAPHORES"));
sl@0
  2539
	while (findHb.Next(name)==KErrNone)
sl@0
  2540
		{
sl@0
  2541
		Display(name);
sl@0
  2542
		}
sl@0
  2543
	return KErrNone;
sl@0
  2544
	}
sl@0
  2545
sl@0
  2546
TInt TShowProcInfo::GetMutexes(const TDes& aName)
sl@0
  2547
	{
sl@0
  2548
sl@0
  2549
	TFindMutex findHb;
sl@0
  2550
	findHb.Find(aName);
sl@0
  2551
	TFullName name;
sl@0
  2552
	Prepare(_L("MUTEXES"));
sl@0
  2553
	while (findHb.Next(name)==KErrNone)
sl@0
  2554
		{
sl@0
  2555
		Display(name);
sl@0
  2556
		}
sl@0
  2557
	return KErrNone;
sl@0
  2558
	}
sl@0
  2559
sl@0
  2560
void TShowProcInfo::DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription)
sl@0
  2561
	{
sl@0
  2562
	CShell::OutputStringToConsole(ETrue,_L("%- *S%S\n"),8,&aCommand,&aDescription);
sl@0
  2563
	}
sl@0
  2564
sl@0
  2565
sl@0
  2566
TInt TShowProcInfo::Prepare(const TFullName& aName)
sl@0
  2567
	{
sl@0
  2568
sl@0
  2569
	iPrevName=_L("");
sl@0
  2570
	CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
sl@0
  2571
	useCallBack=EFalse;
sl@0
  2572
	return KErrNone;
sl@0
  2573
	}
sl@0
  2574
sl@0
  2575
TInt TShowProcInfo::Prepare(const TFullName& aName,TCallBack& aCallBack)
sl@0
  2576
	{
sl@0
  2577
sl@0
  2578
	iPrevName=_L("");
sl@0
  2579
	CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
sl@0
  2580
	useCallBack=ETrue;
sl@0
  2581
	iCallBack=aCallBack;
sl@0
  2582
	return KErrNone;
sl@0
  2583
	}
sl@0
  2584
sl@0
  2585
TInt TShowProcInfo::Display(TFullName& aName)
sl@0
  2586
sl@0
  2587
//	Modifications by WR, November 1997
sl@0
  2588
	{
sl@0
  2589
sl@0
  2590
	TFullName prevName=iPrevName;
sl@0
  2591
	iPrevName=aName;
sl@0
  2592
	TInt toTab=0;
sl@0
  2593
	TInt posA=aName.Match(_L("*::*"));
sl@0
  2594
	if (posA>=0)
sl@0
  2595
		{
sl@0
  2596
		TInt posI=prevName.Match(_L("*::*"));
sl@0
  2597
		while ((posI>=0) && (posA>=0))
sl@0
  2598
			{
sl@0
  2599
			TFullName tempAName=(aName.Left(posA));
sl@0
  2600
			TFullName tempIName=(prevName.Left(posI));
sl@0
  2601
			if (tempAName.Compare(tempIName)==0)
sl@0
  2602
				{
sl@0
  2603
				toTab+=3;
sl@0
  2604
				aName.Delete(0,posA+2);
sl@0
  2605
				prevName.Delete(0,posI+2);
sl@0
  2606
				posA=aName.Match(_L("*::*"));
sl@0
  2607
				posI=prevName.Match(_L("*::*"));
sl@0
  2608
				}
sl@0
  2609
			else
sl@0
  2610
				break;
sl@0
  2611
			}
sl@0
  2612
		while (posA>=0)
sl@0
  2613
			{
sl@0
  2614
			TPtrC16 temp_desc=aName.Left(posA);
sl@0
  2615
			CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+temp_desc.Left(posA).Length(),&temp_desc);
sl@0
  2616
			toTab+=3;
sl@0
  2617
			aName.Delete(0,posA+2);
sl@0
  2618
			posA=aName.Match(_L("*::*"));
sl@0
  2619
			}
sl@0
  2620
		}
sl@0
  2621
	CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+aName.Length(),&(aName));
sl@0
  2622
sl@0
  2623
sl@0
  2624
	if (useCallBack)
sl@0
  2625
		{
sl@0
  2626
		toTab+=3;
sl@0
  2627
		CShell::TheConsole->SetCursorPosRel(TPoint(toTab,0));
sl@0
  2628
		iCallBack.CallBack();
sl@0
  2629
		}
sl@0
  2630
	return KErrNone;
sl@0
  2631
	}
sl@0
  2632
//	End of modification
sl@0
  2633
TInt ShellFunction::Ps(TDes& /* aPath */,TUint /* aSwitches */)
sl@0
  2634
//
sl@0
  2635
// satisfy information requests about container objects
sl@0
  2636
//
sl@0
  2637
	{
sl@0
  2638
sl@0
  2639
	TShowProcInfo showProcInfo;
sl@0
  2640
	TInt r=KErrNone;
sl@0
  2641
    TBuf<0x1> asterisk=_L("*");
sl@0
  2642
	TName processPrefix=asterisk;
sl@0
  2643
	TBool abort=EFalse;
sl@0
  2644
	TBool processSelected=EFalse;
sl@0
  2645
	TBuf<0x16> prompt=_L("ps>");
sl@0
  2646
	r=showProcInfo.GetProcesses(processPrefix);
sl@0
  2647
	do
sl@0
  2648
		{
sl@0
  2649
		TBuf<0x10> command;
sl@0
  2650
		CShell::TheEditor->Edit(prompt, &command, ETrue);
sl@0
  2651
		while (command.Length() && !abort && r==KErrNone)
sl@0
  2652
			{
sl@0
  2653
			TInt pos;
sl@0
  2654
			while ((pos=command.Locate(' '))>=0)
sl@0
  2655
				command.Delete(pos,1);
sl@0
  2656
			if (!command.Length())
sl@0
  2657
				break;
sl@0
  2658
			command.UpperCase();
sl@0
  2659
			if (command.CompareF(_L("EXIT"))==0)
sl@0
  2660
				{
sl@0
  2661
				abort=ETrue;
sl@0
  2662
				break;
sl@0
  2663
				}
sl@0
  2664
			TText c=command[0];
sl@0
  2665
			command.Delete(0,1);
sl@0
  2666
			switch (c)
sl@0
  2667
				{
sl@0
  2668
				case 'Q':
sl@0
  2669
					abort=ETrue;
sl@0
  2670
					break;
sl@0
  2671
				case 'H':
sl@0
  2672
				case '?':
sl@0
  2673
					{
sl@0
  2674
					showProcInfo.DisplayHelp();
sl@0
  2675
					command.Zero();
sl@0
  2676
					}
sl@0
  2677
					break;
sl@0
  2678
				case 'X':
sl@0
  2679
					{
sl@0
  2680
					TBuf<0x11> chosenP=command;
sl@0
  2681
					if (chosenP.Length()<1)
sl@0
  2682
					    {
sl@0
  2683
					    if (processSelected)
sl@0
  2684
						    {
sl@0
  2685
						    r=showProcInfo.DisplayMessage(_L(" -> back to standard Process Status mode"));
sl@0
  2686
						    processPrefix=asterisk;
sl@0
  2687
						    prompt=_L("ps>");
sl@0
  2688
						    processSelected=EFalse;
sl@0
  2689
						    }
sl@0
  2690
					    command.Zero();
sl@0
  2691
						break;
sl@0
  2692
					    }
sl@0
  2693
					command.Zero();
sl@0
  2694
					chosenP.Append(asterisk);
sl@0
  2695
					TFindProcess findP;
sl@0
  2696
					findP.Find(chosenP);
sl@0
  2697
					TFullName findName;
sl@0
  2698
					if (findP.Next(findName)!=KErrNone)
sl@0
  2699
						{
sl@0
  2700
						r=showProcInfo.DisplayMessage(_L("command prefixes no processes"));
sl@0
  2701
						//r=showProcInfo.GetProcesses(asterisk);
sl@0
  2702
						}
sl@0
  2703
					else
sl@0
  2704
						{
sl@0
  2705
						if (findP.Next(findName)==KErrNone)
sl@0
  2706
							{
sl@0
  2707
							r=showProcInfo.DisplayMessage(_L("command prefixes more than one process"));
sl@0
  2708
							r=showProcInfo.GetProcesses(chosenP);
sl@0
  2709
							}
sl@0
  2710
						else
sl@0
  2711
							{
sl@0
  2712
							processSelected=ETrue;
sl@0
  2713
							processPrefix=chosenP;
sl@0
  2714
							prompt=processPrefix;
sl@0
  2715
							prompt.Append(_L(">"));
sl@0
  2716
							}
sl@0
  2717
						}
sl@0
  2718
					}
sl@0
  2719
					break;
sl@0
  2720
				case 'A':
sl@0
  2721
					{
sl@0
  2722
					r=showProcInfo.GetAll(processPrefix);
sl@0
  2723
					command.Zero();
sl@0
  2724
					}
sl@0
  2725
					break;
sl@0
  2726
				case 'P':
sl@0
  2727
					r=showProcInfo.GetProcesses(asterisk);
sl@0
  2728
					break;
sl@0
  2729
				case 'T':
sl@0
  2730
					r=showProcInfo.GetThreads(processPrefix);
sl@0
  2731
					break;
sl@0
  2732
				case 'C':
sl@0
  2733
					r=showProcInfo.GetChunks(processPrefix);
sl@0
  2734
					break;
sl@0
  2735
				case 'S':
sl@0
  2736
					r=showProcInfo.GetServers(processPrefix);
sl@0
  2737
					break;
sl@0
  2738
/*				case 'I':
sl@0
  2739
					r=showProcInfo.GetSessions(processPrefix);
sl@0
  2740
					break;
sl@0
  2741
*/				case 'L':
sl@0
  2742
					r=showProcInfo.GetLibraries(processPrefix);
sl@0
  2743
					break;
sl@0
  2744
//				case 'G':
sl@0
  2745
//					r=showProcInfo.GetLogicalChannels(processPrefix);
sl@0
  2746
//					break;
sl@0
  2747
				case 'V':
sl@0
  2748
					r=showProcInfo.GetLogicalDevices(processPrefix);
sl@0
  2749
					break;
sl@0
  2750
				case 'D':
sl@0
  2751
					r=showProcInfo.GetPhysicalDevices(processPrefix);
sl@0
  2752
					break;
sl@0
  2753
				case 'E':
sl@0
  2754
					r=showProcInfo.GetSemaphores(processPrefix);
sl@0
  2755
					break;
sl@0
  2756
				case 'M':
sl@0
  2757
					r=showProcInfo.GetMutexes(processPrefix);
sl@0
  2758
					break;
sl@0
  2759
				default:
sl@0
  2760
					{
sl@0
  2761
					showProcInfo.DisplayCmdUnknown();
sl@0
  2762
					command.Zero();
sl@0
  2763
					}
sl@0
  2764
				}
sl@0
  2765
			}
sl@0
  2766
		}
sl@0
  2767
	while(!abort && r==KErrNone);
sl@0
  2768
		return KErrNone;
sl@0
  2769
	}
sl@0
  2770
sl@0
  2771
TInt ShellFunction::Rename(TDes& aPath,TUint aSwitches)
sl@0
  2772
	{
sl@0
  2773
//	Modified December 1997 to allow for filenames containing spaces
sl@0
  2774
sl@0
  2775
	TBuf<KShellMaxCommandLine> newName;
sl@0
  2776
	TBuf<KShellMaxCommandLine> tempPath=aPath;
sl@0
  2777
	RFile64 file;
sl@0
  2778
	TWord   word(aPath);
sl@0
  2779
sl@0
  2780
	TInt r=word.FindNextWord(aPath);
sl@0
  2781
//	Check if the word returned is a valid filename.  If not, scan the next
sl@0
  2782
//	word too in case the filename contains spaces.  If, at the end of the
sl@0
  2783
//	the line, the filename is not recognised, it is invalid.  If there are no
sl@0
  2784
//	spaces the user has not used the correct format for this command.
sl@0
  2785
sl@0
  2786
	while (r>0)
sl@0
  2787
		{
sl@0
  2788
		newName=aPath.Right(aPath.Length()-r);
sl@0
  2789
		tempPath.SetLength(r);
sl@0
  2790
		TParse oldName;
sl@0
  2791
		TInt result=GetFullPath(tempPath,oldName);
sl@0
  2792
		if (result!=KErrNone)
sl@0
  2793
			return(r);
sl@0
  2794
sl@0
  2795
		if (tempPath[tempPath.Length()-2]==KPathDelimiter)
sl@0
  2796
			tempPath.SetLength(tempPath.Length()-2);
sl@0
  2797
sl@0
  2798
		result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
sl@0
  2799
		if (result==KErrNone)	//	A valid filename
sl@0
  2800
			{
sl@0
  2801
			file.Close();
sl@0
  2802
			TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
sl@0
  2803
			TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
sl@0
  2804
			r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
sl@0
  2805
		//	r=TheShell->TheFs.Rename(oldName.FullName(),newName);
sl@0
  2806
			return(r);
sl@0
  2807
			}
sl@0
  2808
		else
sl@0
  2809
			{
sl@0
  2810
		//	May be a request to rename a directory
sl@0
  2811
			RDir dir;
sl@0
  2812
			result=dir.Open(TheShell->TheFs,tempPath,KEntryAttMatchMask);
sl@0
  2813
			if (result==KErrNone)	//	A valid directory name
sl@0
  2814
				{
sl@0
  2815
				dir.Close();
sl@0
  2816
				TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
sl@0
  2817
				TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
sl@0
  2818
				r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
sl@0
  2819
			//	r=TheShell->TheFs.Rename(oldName.FullName(),newName);
sl@0
  2820
				return(r);
sl@0
  2821
				}
sl@0
  2822
			else
sl@0
  2823
		//	Not a valid file or directory name - move one word along the command line
sl@0
  2824
				r=word.FindNextWord(word.iRightString);
sl@0
  2825
			}
sl@0
  2826
		}
sl@0
  2827
sl@0
  2828
	if (r<0)	//	Error in filename or destination
sl@0
  2829
		return (r);
sl@0
  2830
	else		//	End of command line, user typed invalid line
sl@0
  2831
		return (KErrNotFound);
sl@0
  2832
sl@0
  2833
}
sl@0
  2834
sl@0
  2835
TInt ShellFunction::Rd(TDes& aPath,TUint /*aSwitches*/)
sl@0
  2836
	{
sl@0
  2837
	if (aPath.Length()==0)
sl@0
  2838
		return(KErrBadName);
sl@0
  2839
	if (aPath[aPath.Length()-1]!=KPathDelimiter)
sl@0
  2840
		aPath.Append(KPathDelimiter);
sl@0
  2841
	TParse dirPath;
sl@0
  2842
	TInt r = GetFullPath(aPath,dirPath);
sl@0
  2843
	if(r!=KErrNone)
sl@0
  2844
		return r;
sl@0
  2845
sl@0
  2846
//	Check whether the directory actually exists.
sl@0
  2847
	RDir directory;
sl@0
  2848
	r=directory.Open(TheShell->TheFs,dirPath.FullName(),KEntryAttMatchExclusive|KEntryAttDir);
sl@0
  2849
	if (r!=KErrNone)
sl@0
  2850
		{
sl@0
  2851
		CShell::TheConsole->Printf(_L("Directory %S was not found\n"),&dirPath.FullName());
sl@0
  2852
		return (KErrNone);
sl@0
  2853
		}
sl@0
  2854
	directory.Close();
sl@0
  2855
sl@0
  2856
	TInt ret=TheShell->TheFs.RmDir(dirPath.FullName());
sl@0
  2857
    
sl@0
  2858
    if (ret==KErrNone)
sl@0
  2859
	    CShell::TheConsole->Printf(_L("Directory %S was removed\n"),&dirPath.FullName());
sl@0
  2860
    else if(ret==KErrInUse)
sl@0
  2861
	    {
sl@0
  2862
		CShell::TheConsole->Printf(_L("Directory %S is in use and cannot be deleted\n"),&dirPath.FullName());
sl@0
  2863
		return KErrNone;
sl@0
  2864
		}
sl@0
  2865
	
sl@0
  2866
    return(ret);
sl@0
  2867
	}
sl@0
  2868
sl@0
  2869
TInt ShellFunction::Start(TDes& aProg,TUint /*aSwitches*/)
sl@0
  2870
//
sl@0
  2871
// Runs a program without waiting for completion
sl@0
  2872
//
sl@0
  2873
	{
sl@0
  2874
sl@0
  2875
	TInt bat=aProg.FindF(_L(".BAT"));
sl@0
  2876
	TInt space=aProg.Locate(' ');
sl@0
  2877
	TInt r=KErrArgument;
sl@0
  2878
	if (bat>=0 && (space<0 || space>bat))
sl@0
  2879
		r=CShell::RunBatch(aProg);
sl@0
  2880
	else if (aProg.Length()!=0)
sl@0
  2881
		r=CShell::RunExecutable(aProg,EFalse);
sl@0
  2882
	return(r);
sl@0
  2883
	}
sl@0
  2884
sl@0
  2885
TInt ShellFunction::Time(TDes&,TUint /*aSwitches*/)
sl@0
  2886
	{
sl@0
  2887
	TTime time;
sl@0
  2888
	time.HomeTime();
sl@0
  2889
	TDateTime dateTime(time.DateTime());
sl@0
  2890
	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());
sl@0
  2891
	return(KErrNone);
sl@0
  2892
	}
sl@0
  2893
sl@0
  2894
TInt ShellFunction::Trace(TDes& aState,TUint aSwitches)
sl@0
  2895
//
sl@0
  2896
// Turn on trace information
sl@0
  2897
//
sl@0
  2898
    {
sl@0
  2899
	TInt debugVal=0;
sl@0
  2900
	if (aSwitches&TShellCommand::ESSwitch)
sl@0
  2901
		debugVal|=KFSERV;
sl@0
  2902
	if (aSwitches&TShellCommand::ELSwitch)
sl@0
  2903
		debugVal|=KFLDR;
sl@0
  2904
	if (aSwitches&TShellCommand::EFSwitch)
sl@0
  2905
		debugVal|=KFSYS;
sl@0
  2906
	if (aSwitches&TShellCommand::ETSwitch)
sl@0
  2907
		debugVal|=KLFFS;
sl@0
  2908
	if (aSwitches&TShellCommand::EISwitch)
sl@0
  2909
		debugVal|=KISO9660;
sl@0
  2910
	if (aSwitches&TShellCommand::ENSwitch)
sl@0
  2911
		debugVal|=KNTFS;
sl@0
  2912
	if (aSwitches&TShellCommand::EMSwitch)
sl@0
  2913
		debugVal|=KTHRD;
sl@0
  2914
	if (aSwitches&TShellCommand::EOSwitch)
sl@0
  2915
		debugVal|=KROFS;
sl@0
  2916
	if (aSwitches&TShellCommand::ECSwitch)
sl@0
  2917
		debugVal|=KCOMPFS;
sl@0
  2918
	if (aSwitches&TShellCommand::EHSwitch)
sl@0
  2919
		debugVal|=KCACHE;
sl@0
  2920
	TheShell->TheFs.SetDebugRegister(debugVal);
sl@0
  2921
sl@0
  2922
	aSwitches=0;
sl@0
  2923
sl@0
  2924
	if (aState.Length())
sl@0
  2925
		{
sl@0
  2926
		TBuf<KShellMaxCommandLine> indexArg;
sl@0
  2927
		TWord word(aState);
sl@0
  2928
sl@0
  2929
		TLex lex=aState;
sl@0
  2930
		TUint val;
sl@0
  2931
		TInt r2=lex.Val(val,EHex);
sl@0
  2932
sl@0
  2933
		TInt r=word.FindNextWord(aState);
sl@0
  2934
		TUint index;
sl@0
  2935
		if (r>0)
sl@0
  2936
			{
sl@0
  2937
			indexArg = aState.Right(aState.Length()-r);
sl@0
  2938
			lex=indexArg;
sl@0
  2939
			lex.Val(index,EDecimal);
sl@0
  2940
			}
sl@0
  2941
		else
sl@0
  2942
			index = 0;
sl@0
  2943
sl@0
  2944
		if (r2 != KErrNone)
sl@0
  2945
			{
sl@0
  2946
			TInt shift = index % 32;
sl@0
  2947
			index /= 32;
sl@0
  2948
			val = UserSvr::DebugMask(index);
sl@0
  2949
			if (aState.Left(2)==_L("on"))
sl@0
  2950
				val |= 1<<shift;
sl@0
  2951
			else if (aState.Left(3)==_L("off"))
sl@0
  2952
				val &= ~(1<<shift);
sl@0
  2953
			}
sl@0
  2954
sl@0
  2955
		if (index < 256)
sl@0
  2956
			{
sl@0
  2957
			User::SetDebugMask(val, index);
sl@0
  2958
			CShell::TheConsole->Printf(_L("SetDebugMask(0x%x, %d)\n"), val, index);
sl@0
  2959
			}
sl@0
  2960
		}
sl@0
  2961
	else
sl@0
  2962
		{
sl@0
  2963
		for (TInt j=0; j<8; j++)
sl@0
  2964
			CShell::TheConsole->Printf(_L("DebugMask(%d) = 0x%08X\n"), j, UserSvr::DebugMask(j));
sl@0
  2965
		}
sl@0
  2966
sl@0
  2967
    return(KErrNone);
sl@0
  2968
    }
sl@0
  2969
sl@0
  2970
TInt ShellFunction::Tree(TDes& aPath,TUint aSwitches)
sl@0
  2971
	{
sl@0
  2972
	ParsePath(aPath);
sl@0
  2973
	CShell::TheConsole->Printf(_L("\n  %S\n"),&aPath);
sl@0
  2974
	if (aPath.Right(1)==_L("\\"))
sl@0
  2975
		aPath.Append('*');
sl@0
  2976
	else
sl@0
  2977
		aPath.Append(_L("\\*"));
sl@0
  2978
	TBuf<256> buf=_L("  ");
sl@0
  2979
	TInt dirCount=ShowDirectoryTree(aPath,aSwitches,buf);
sl@0
  2980
	buf.Format(_L("\n    Found %d subdirector"),dirCount);
sl@0
  2981
	if (dirCount==1)
sl@0
  2982
		buf.AppendFormat(_L("y\n"));
sl@0
  2983
	else
sl@0
  2984
		buf.AppendFormat(_L("ies\n"));
sl@0
  2985
sl@0
  2986
	CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
sl@0
  2987
sl@0
  2988
	return(KErrNone);
sl@0
  2989
	}
sl@0
  2990
sl@0
  2991
TInt ShellFunction::ShowDirectoryTree(TDes& aPath,TUint aSwitches,TDes& aTreeGraph)
sl@0
  2992
//
sl@0
  2993
// Recursive fn. to draw tree of dir aPath (needs to be suffixed with '*')
sl@0
  2994
//
sl@0
  2995
	{
sl@0
  2996
	TInt dirCount=0;
sl@0
  2997
	RDir dir;
sl@0
  2998
	TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttDir);
sl@0
  2999
	if (r==KErrNone)
sl@0
  3000
		{
sl@0
  3001
		TEntry next,entry;
sl@0
  3002
		while ((r=dir.Read(next))==KErrNone && !next.IsDir())
sl@0
  3003
			{
sl@0
  3004
			}
sl@0
  3005
		//	lint info 722: Suspicious use of ; in previous line...
sl@0
  3006
		if (aSwitches&TShellCommand::EFSwitch)
sl@0
  3007
			{
sl@0
  3008
			RDir dirFile;
sl@0
  3009
			if (dirFile.Open(TheShell->TheFs,aPath,0)==KErrNone)
sl@0
  3010
				{
sl@0
  3011
				while (dirFile.Read(entry)==KErrNone)
sl@0
  3012
					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,(r==KErrNone)?_L("%S\x00B3   %S\n"):_L("%S   %S\n"),&aTreeGraph,&entry.iName);
sl@0
  3013
sl@0
  3014
				dirFile.Close();
sl@0
  3015
				}
sl@0
  3016
			}
sl@0
  3017
		if (r==KErrNone)
sl@0
  3018
			do
sl@0
  3019
				{
sl@0
  3020
				entry=next;
sl@0
  3021
				while ((r=dir.Read(next))==KErrNone && !next.IsDir())
sl@0
  3022
					;
sl@0
  3023
sl@0
  3024
				CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,aTreeGraph);
sl@0
  3025
				if (r==KErrNone)
sl@0
  3026
					{
sl@0
  3027
					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
sl@0
  3028
					aTreeGraph.Append(_L("\x00B3  "));
sl@0
  3029
					}
sl@0
  3030
				else
sl@0
  3031
					{
sl@0
  3032
					CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
sl@0
  3033
					aTreeGraph.Append(_L("   "));
sl@0
  3034
					}
sl@0
  3035
				aPath.Insert(aPath.Length()-1,entry.iName);
sl@0
  3036
				aPath.Insert(aPath.Length()-1,_L("\\"));
sl@0
  3037
				dirCount+=1+ShowDirectoryTree(aPath,aSwitches,aTreeGraph);
sl@0
  3038
				aPath.Delete(aPath.Length()-2-entry.iName.Length(),entry.iName.Length()+1);
sl@0
  3039
				aTreeGraph.SetLength(aTreeGraph.Length()-3);
sl@0
  3040
				}
sl@0
  3041
			while (r==KErrNone);
sl@0
  3042
		dir.Close();
sl@0
  3043
		if (r!=KErrEof)
sl@0
  3044
			CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error EOF %d\n"),r);
sl@0
  3045
sl@0
  3046
		}
sl@0
  3047
	else
sl@0
  3048
		CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error in Open %d\n"),r);
sl@0
  3049
	return(dirCount);
sl@0
  3050
	}
sl@0
  3051
sl@0
  3052
void ByteSwap(TDes16& aDes)
sl@0
  3053
	{
sl@0
  3054
	TUint8* p=(TUint8*)aDes.Ptr();
sl@0
  3055
	TUint8* pE=p+aDes.Size();
sl@0
  3056
	TUint8 c;
sl@0
  3057
	for (; p<pE; p+=2)
sl@0
  3058
		c=*p, *p=p[1], p[1]=c;
sl@0
  3059
	}
sl@0
  3060
sl@0
  3061
_LIT(KLitPercentS, "%S");
sl@0
  3062
TInt ShellFunction::Type(TDes& aPath,TUint aSwitches)
sl@0
  3063
	{
sl@0
  3064
	ParsePath(aPath);
sl@0
  3065
	RFile file;
sl@0
  3066
	TInt r=file.Open(TheShell->TheFs,aPath,EFileStreamText|EFileShareReadersOnly);
sl@0
  3067
	if (r!=KErrNone)
sl@0
  3068
		return r;
sl@0
  3069
	TBuf8<0x200> tmpbuf;
sl@0
  3070
	TBuf<0x200> ubuf;
sl@0
  3071
	TInt state=0;	// 0=start of file, 1=ASCII, 2=UNICODE little-endian, 3=UNICODE big-endian
sl@0
  3072
    TKeyCode key=EKeyNull;
sl@0
  3073
sl@0
  3074
	TInt nchars=0;
sl@0
  3075
	TInt l;
sl@0
  3076
	
sl@0
  3077
	do
sl@0
  3078
		{
sl@0
  3079
		r=file.Read(tmpbuf);
sl@0
  3080
		if (r!=KErrNone)
sl@0
  3081
			{
sl@0
  3082
			file.Close();
sl@0
  3083
			return r;
sl@0
  3084
			}
sl@0
  3085
		
sl@0
  3086
		l=tmpbuf.Length();
sl@0
  3087
		if (state==0)
sl@0
  3088
			{
sl@0
  3089
			if (l>=2)
sl@0
  3090
				{
sl@0
  3091
				TUint c=(tmpbuf[1]<<8)|tmpbuf[0];
sl@0
  3092
				if (c==0xfeff)
sl@0
  3093
					state=2;
sl@0
  3094
				else if (c==0xfffe)
sl@0
  3095
					state=3;
sl@0
  3096
				else
sl@0
  3097
					state=1;
sl@0
  3098
				}
sl@0
  3099
			else
sl@0
  3100
				state=1;
sl@0
  3101
			}
sl@0
  3102
		TPtrC buf;
sl@0
  3103
		if (state>1)
sl@0
  3104
			{
sl@0
  3105
			if (l&1)
sl@0
  3106
				--l, tmpbuf.SetLength(l);
sl@0
  3107
			buf.Set((TText*)tmpbuf.Ptr(),l/sizeof(TText));
sl@0
  3108
			if (state==3)
sl@0
  3109
				{
sl@0
  3110
				TPtr wbuf( (TText*)buf.Ptr(), buf.Length(), buf.Length() );
sl@0
  3111
				ByteSwap(wbuf);
sl@0
  3112
				}
sl@0
  3113
			}
sl@0
  3114
		else
sl@0
  3115
			{
sl@0
  3116
			ubuf.Copy(tmpbuf);
sl@0
  3117
			buf.Set(ubuf);
sl@0
  3118
			}
sl@0
  3119
		while ((r=buf.Locate('\n'))!=KErrNotFound)
sl@0
  3120
			{
sl@0
  3121
			nchars=0;
sl@0
  3122
			TPtrC bufLeft=buf.Left(r+1);
sl@0
  3123
			key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &bufLeft);
sl@0
  3124
			buf.Set(buf.Mid(r+1));
sl@0
  3125
	
sl@0
  3126
    		if(key == EKeyEscape) 
sl@0
  3127
                goto exit;
sl@0
  3128
			}
sl@0
  3129
sl@0
  3130
		nchars=buf.Length();
sl@0
  3131
		if (nchars)
sl@0
  3132
			{
sl@0
  3133
            key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &buf);
sl@0
  3134
    		if(key == EKeyEscape) 
sl@0
  3135
                goto exit;
sl@0
  3136
sl@0
  3137
            }
sl@0
  3138
sl@0
  3139
		} while(l==tmpbuf.MaxLength());
sl@0
  3140
sl@0
  3141
   exit: 	
sl@0
  3142
    
sl@0
  3143
	file.Close();
sl@0
  3144
	CShell::NewLine();
sl@0
  3145
	return KErrNone;
sl@0
  3146
	}
sl@0
  3147
sl@0
  3148
void ShellFunction::ParsePath(TDes& aPath)
sl@0
  3149
	{
sl@0
  3150
	if (aPath.Length()>0 && aPath[0]==KPathDelimiter)
sl@0
  3151
		return;
sl@0
  3152
	TParse pathParse;
sl@0
  3153
	if (aPath.Length()<2 || aPath[1]!=':')
sl@0
  3154
		pathParse.SetNoWild(TheShell->currentPath,NULL,NULL);
sl@0
  3155
	else
sl@0
  3156
		{
sl@0
  3157
		if (aPath.Length()>=3 && aPath[2]==KPathDelimiter)
sl@0
  3158
			return;
sl@0
  3159
		pathParse.SetNoWild(TheShell->drivePaths[User::UpperCase(aPath[0])-'A'],NULL,NULL);
sl@0
  3160
		aPath.Delete(0,2);
sl@0
  3161
		}
sl@0
  3162
	if (aPath.Length()>=2 && aPath.Left(2).Compare(_L(".."))==0)
sl@0
  3163
		{
sl@0
  3164
		aPath.Delete(0,2);
sl@0
  3165
		pathParse.PopDir();
sl@0
  3166
		while (aPath.Length()>=3 && aPath.Left(3).Compare(_L("\\.."))==0)
sl@0
  3167
			{
sl@0
  3168
			aPath.Delete(0,3);
sl@0
  3169
			pathParse.PopDir();
sl@0
  3170
			}
sl@0
  3171
		if (aPath.Length()!=0 && aPath[0]==KPathDelimiter)
sl@0
  3172
			aPath.Delete(0,1);
sl@0
  3173
		}
sl@0
  3174
	aPath.Insert(0,pathParse.FullName());
sl@0
  3175
	}
sl@0
  3176
sl@0
  3177
TBool ShellFunction::Certain()
sl@0
  3178
	{
sl@0
  3179
	CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
sl@0
  3180
	TInt r=User::UpperCase(CShell::TheConsole->Getch());
sl@0
  3181
	while ((!(r=='Y'))&&(!(r=='N')))
sl@0
  3182
		{
sl@0
  3183
		CShell::TheConsole->Printf(_L("%c is invalid\n"),r);
sl@0
  3184
		CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
sl@0
  3185
		r=User::UpperCase(CShell::TheConsole->Getch());
sl@0
  3186
		}
sl@0
  3187
	CShell::TheConsole->Printf(_L("%c\n"),r);
sl@0
  3188
	return(r=='Y');
sl@0
  3189
	}
sl@0
  3190
sl@0
  3191
TInt ShellFunction::GetFullPath(TDes& aPath,TParse& aParse)
sl@0
  3192
//
sl@0
  3193
// Parse a path of the form "[C:][\\]AAA\\..\\.\\BBB\\xxx.yyy" where:
sl@0
  3194
// .  indicates the current directory
sl@0
  3195
// .. indicates move to the parent directory
sl@0
  3196
// An optional "\\" at the start of the path indicates the path is not relative to the current path
sl@0
  3197
//
sl@0
  3198
	{
sl@0
  3199
sl@0
  3200
	TInt r;
sl@0
  3201
	if (aPath.Length()>0 && aPath[aPath.Length()-1]=='.')
sl@0
  3202
		aPath.Append(KPathDelimiter);
sl@0
  3203
	if (aPath.Length()==0)
sl@0
  3204
		r=aParse.Set(TheShell->currentPath,NULL,NULL);
sl@0
  3205
	else if (aPath[0]==KPathDelimiter)
sl@0
  3206
		r=aParse.Set(aPath,&TheShell->currentPath,NULL);
sl@0
  3207
	else if (aPath.Length()>=2 && aPath[1]==KDriveDelimiter)
sl@0
  3208
		{
sl@0
  3209
		TInt drvNum;
sl@0
  3210
		r=RFs::CharToDrive(aPath[0],drvNum);
sl@0
  3211
		if (r==KErrNone)
sl@0
  3212
			r=aParse.Set(aPath,&TheShell->drivePaths[drvNum],NULL);
sl@0
  3213
		}
sl@0
  3214
	else
sl@0
  3215
		{
sl@0
  3216
		if (aPath.LocateReverse(KPathDelimiter)>=0)
sl@0
  3217
			{
sl@0
  3218
			if (aPath.Length()+TheShell->currentPath.Length()>aPath.MaxLength())
sl@0
  3219
				return(KErrBadName);
sl@0
  3220
			aPath.Insert(0,TheShell->currentPath);
sl@0
  3221
			}
sl@0
  3222
		r=aParse.Set(aPath,&TheShell->currentPath,NULL);
sl@0
  3223
		}
sl@0
  3224
	if (r!=KErrNone)
sl@0
  3225
		return(r);
sl@0
  3226
	if (aParse.Path().Find(_L(".\\"))==KErrNotFound)
sl@0
  3227
		return(KErrNone);
sl@0
  3228
	if (aParse.Path().Find(_L("...\\"))!=KErrNotFound)
sl@0
  3229
		return(KErrBadName);
sl@0
  3230
	TParse dirParse;
sl@0
  3231
	TPtrC path(aParse.DriveAndPath());
sl@0
  3232
	TInt pos=path.Find(_L(".\\"));
sl@0
  3233
	if (path[pos-1]!='.' && path[pos-1]!='\\')
sl@0
  3234
		return(KErrNone); // FileName ending in .
sl@0
  3235
	TInt isParent=(path[pos-1]=='.') ? 1 : 0;
sl@0
  3236
	r=dirParse.Set(path.Left(pos-isParent),NULL,NULL);
sl@0
  3237
	while(r==KErrNone)
sl@0
  3238
		{
sl@0
  3239
		if (isParent)
sl@0
  3240
			dirParse.PopDir();
sl@0
  3241
		path.Set(path.Right(path.Length()-pos-2));
sl@0
  3242
		pos=path.Find(_L(".\\"));
sl@0
  3243
		if (pos==0)
sl@0
  3244
			{
sl@0
  3245
			isParent=0;
sl@0
  3246
			continue;
sl@0
  3247
			}
sl@0
  3248
		else if (pos!=KErrNotFound)
sl@0
  3249
			isParent=(path[pos-1]=='.') ? 1 : 0;
sl@0
  3250
		TInt len=(pos==KErrNotFound) ? path.Length() : pos-isParent;
sl@0
  3251
		r=AddRelativePath(dirParse,path.Left(len));
sl@0
  3252
		if (r!=KErrNone || pos==KErrNotFound)
sl@0
  3253
			break;
sl@0
  3254
		}
sl@0
  3255
	if (r!=KErrNone)
sl@0
  3256
		return(r);
sl@0
  3257
//	lint -e50
sl@0
  3258
	TBuf<KMaxFileName> nameAndExt=aParse.NameAndExt();
sl@0
  3259
	aParse.Set(dirParse.FullName(),&nameAndExt,NULL);
sl@0
  3260
	return(KErrNone);
sl@0
  3261
	}
sl@0
  3262
sl@0
  3263
void ShellFunction::StripQuotes(TDes& aVal)
sl@0
  3264
	{
sl@0
  3265
	for(TInt idx=0;idx<aVal.Length();idx++)
sl@0
  3266
		{
sl@0
  3267
		while((idx < aVal.Length()) && (aVal[idx] == '"'))
sl@0
  3268
			{
sl@0
  3269
			aVal.Delete(idx, 1);
sl@0
  3270
			}
sl@0
  3271
		}
sl@0
  3272
	}
sl@0
  3273
sl@0
  3274
TInt ShellFunction::ValidName(TDes& aPath,TUint /*aSwitches*/)
sl@0
  3275
//
sl@0
  3276
//	Check whether the name has any invalid characters
sl@0
  3277
//
sl@0
  3278
	{
sl@0
  3279
	TBool tooShort=EFalse;
sl@0
  3280
sl@0
  3281
	TText badChar;
sl@0
  3282
	TPtr ptr(&badChar,sizeof(TText),sizeof(TText));
sl@0
  3283
sl@0
  3284
	TBool validName=TheShell->TheFs.IsValidName(aPath,badChar);
sl@0
  3285
	if (validName)
sl@0
  3286
		CShell::TheConsole->Printf(_L("'%S' is a valid name\n"),&aPath);
sl@0
  3287
	else
sl@0
  3288
		{
sl@0
  3289
		if (!tooShort)
sl@0
  3290
			CShell::TheConsole->Printf(_L("'%S' is not a valid name.\n"),&aPath);
sl@0
  3291
sl@0
  3292
		CShell::TheConsole->Printf(_L("The '%S' character is not allowed\n"),&ptr);
sl@0
  3293
		}
sl@0
  3294
	return (KErrNone);
sl@0
  3295
	}
sl@0
  3296
sl@0
  3297
LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN)
sl@0
  3298
//
sl@0
  3299
// password utility function to extract drive number from cmd string.
sl@0
  3300
//
sl@0
  3301
	{
sl@0
  3302
	TLex l(aPath);
sl@0
  3303
	return l.Val(aDN);
sl@0
  3304
	}
sl@0
  3305
sl@0
  3306
LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW)
sl@0
  3307
//
sl@0
  3308
// utility function to extract indexed password from command string.  A
sl@0
  3309
// dash is interpreted as the null password.
sl@0
  3310
//
sl@0
  3311
	{
sl@0
  3312
	__ASSERT_DEBUG(aPWNbr >= 1, User::Panic(_L("Invalid pswd nbr"), 0));
sl@0
  3313
sl@0
  3314
	TLex l(aPath);
sl@0
  3315
sl@0
  3316
	TPtrC ptScan;
sl@0
  3317
	for (TInt i = 0; i <= aPWNbr; ++i)
sl@0
  3318
		{
sl@0
  3319
		if (l.Eos())
sl@0
  3320
			return KErrNotFound;
sl@0
  3321
		else
sl@0
  3322
			ptScan.Set(l.NextToken());
sl@0
  3323
		}
sl@0
  3324
sl@0
  3325
	// take remainder of command line and terminate after password
sl@0
  3326
	TBuf<256> pswd;
sl@0
  3327
	for (TInt j = 0; j < ptScan.Length() && ! TChar(ptScan[j]).IsSpace(); ++j)
sl@0
  3328
		{
sl@0
  3329
		pswd.Append(ptScan[j]);
sl@0
  3330
		}
sl@0
  3331
sl@0
  3332
	aPW.Zero();
sl@0
  3333
	if (pswd[0] == '-')
sl@0
  3334
		return KErrNone;
sl@0
  3335
sl@0
  3336
	// fill aPW with contents of pswd, not converting to ASCII
sl@0
  3337
	const TInt byteLen = pswd.Length() * 2;
sl@0
  3338
	if (byteLen > KMaxMediaPassword)
sl@0
  3339
		return KErrArgument;
sl@0
  3340
sl@0
  3341
	aPW.Copy(reinterpret_cast<const TUint8 *>(pswd.Ptr()), byteLen);
sl@0
  3342
sl@0
  3343
	return KErrNone;
sl@0
  3344
	}
sl@0
  3345
sl@0
  3346
TInt ShellFunction::Lock(TDes &aPath, TUint aSwitches)
sl@0
  3347
//
sl@0
  3348
// Locks a password-enabled media.
sl@0
  3349
//
sl@0
  3350
	{
sl@0
  3351
	TInt r;
sl@0
  3352
	TInt dn;
sl@0
  3353
	TMediaPassword curPswd;
sl@0
  3354
	TMediaPassword newPswd;
sl@0
  3355
	TBool store = aSwitches & TShellCommand::ESSwitch;
sl@0
  3356
sl@0
  3357
	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
sl@0
  3358
		return r;
sl@0
  3359
sl@0
  3360
	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
sl@0
  3361
		return r;
sl@0
  3362
sl@0
  3363
	if ((r = pswd_Password(aPath, 2, newPswd)) < 0)
sl@0
  3364
		return r;
sl@0
  3365
sl@0
  3366
	return TheShell->TheFs.LockDrive(dn, curPswd, newPswd, store);
sl@0
  3367
	}
sl@0
  3368
sl@0
  3369
TInt ShellFunction::Unlock(TDes &aPath, TUint aSwitches)
sl@0
  3370
//
sl@0
  3371
// Unlocks a password-enabled media.
sl@0
  3372
//
sl@0
  3373
	{
sl@0
  3374
	TInt r;
sl@0
  3375
	TInt dn;
sl@0
  3376
	TMediaPassword curPswd;
sl@0
  3377
	TBool store = aSwitches & TShellCommand::ESSwitch;
sl@0
  3378
sl@0
  3379
	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
sl@0
  3380
		return r;
sl@0
  3381
sl@0
  3382
	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
sl@0
  3383
		return r;
sl@0
  3384
sl@0
  3385
	return TheShell->TheFs.UnlockDrive(dn, curPswd, store);
sl@0
  3386
	}
sl@0
  3387
sl@0
  3388
TInt ShellFunction::Clear(TDes &aPath, TUint /* aSwitches */)
sl@0
  3389
//
sl@0
  3390
// Clears a password from a password-enabled media.
sl@0
  3391
//
sl@0
  3392
	{
sl@0
  3393
	TInt r;
sl@0
  3394
	TInt dn;
sl@0
  3395
	TMediaPassword curPswd;
sl@0
  3396
sl@0
  3397
	if ((r = pswd_DrvNbr(aPath, dn)) < 0)
sl@0
  3398
		return r;
sl@0
  3399
sl@0
  3400
	if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
sl@0
  3401
		return r;
sl@0
  3402
sl@0
  3403
	return TheShell->TheFs.ClearPassword(dn, curPswd);
sl@0
  3404
	}
sl@0
  3405
sl@0
  3406
TInt ShellFunction::SetSize(TDes& aPath,TUint /*aSwitches*/)
sl@0
  3407
//
sl@0
  3408
// Set size of a file, create this if it does not exist
sl@0
  3409
//
sl@0
  3410
	{
sl@0
  3411
	TInt fileNameLen=aPath.LocateReverse(' ');
sl@0
  3412
	if (fileNameLen==KErrNotFound)	//	No spaces implies no filelength specified
sl@0
  3413
		{
sl@0
  3414
		CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
sl@0
  3415
		return (KErrNone);
sl@0
  3416
		}
sl@0
  3417
sl@0
  3418
sl@0
  3419
	TInt fileLength=(aPath.Length()-fileNameLen);
sl@0
  3420
	if (fileLength>16)
sl@0
  3421
		return (KErrTooBig);	//	Too many digits - too large!
sl@0
  3422
	TBuf<16> rightString=aPath.Right(fileLength);
sl@0
  3423
	aPath.SetLength(fileNameLen);
sl@0
  3424
sl@0
  3425
	TLex size(rightString);
sl@0
  3426
	size.SkipSpace();
sl@0
  3427
sl@0
  3428
	TRadix radix=ParseHexaPrefixIfAny(size);
sl@0
  3429
	TUint32 fileSize;
sl@0
  3430
	TInt r=size.Val(fileSize,radix);
sl@0
  3431
	if (r!=KErrNone || ! size.Eos())
sl@0
  3432
		{
sl@0
  3433
		CShell::TheConsole->Printf(_L("Please specify a file length\n"));
sl@0
  3434
		return KErrNone;
sl@0
  3435
		}
sl@0
  3436
sl@0
  3437
	TParse fileName;
sl@0
  3438
	GetFullPath(aPath,fileName);
sl@0
  3439
	RFile64 file;
sl@0
  3440
	r=file.Open(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
sl@0
  3441
	if(r==KErrNotFound)
sl@0
  3442
		r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
sl@0
  3443
	if (r==KErrNone)
sl@0
  3444
		{
sl@0
  3445
		r=file.SetSize(fileSize);
sl@0
  3446
		file.Close();
sl@0
  3447
		if(r!=KErrNone)
sl@0
  3448
			CShell::TheConsole->Printf(_L("Error (%d) - could not set size of file\n"),r);
sl@0
  3449
		}
sl@0
  3450
	else
sl@0
  3451
		{
sl@0
  3452
		CShell::TheConsole->Printf(_L("Error (%d) - could not create or open file\n"),r);
sl@0
  3453
		CShell::TheFs.Delete(fileName.FullName());
sl@0
  3454
		}
sl@0
  3455
	return(r);
sl@0
  3456
	}
sl@0
  3457
sl@0
  3458
TInt ShellFunction::DebugPort(TDes& aArgs, TUint /*aSwitches*/)
sl@0
  3459
//
sl@0
  3460
// Set or get the debug port from the command line (debugport)
sl@0
  3461
//
sl@0
  3462
	{
sl@0
  3463
	_LIT(KGetPortLit, "Debug port is %d (0x%x)\n");
sl@0
  3464
	_LIT(KSetPortLit, "Debug port set to %d (0x%x)\n");
sl@0
  3465
sl@0
  3466
	TLex s(aArgs);
sl@0
  3467
	s.SkipSpace();
sl@0
  3468
	if (s.Eos())
sl@0
  3469
		{
sl@0
  3470
		TInt port;
sl@0
  3471
		TInt r = HAL::Get(HALData::EDebugPort, port);
sl@0
  3472
		if (r != KErrNone)
sl@0
  3473
			return r;
sl@0
  3474
		CShell::TheConsole->Printf(KGetPortLit, (TUint32)port, (TUint32)port);
sl@0
  3475
		}
sl@0
  3476
	else
sl@0
  3477
		{
sl@0
  3478
		TRadix radix=EDecimal;
sl@0
  3479
		if (s.Remainder().Length()>2)
sl@0
  3480
			{
sl@0
  3481
			s.Mark();
sl@0
  3482
			s.Inc(2);
sl@0
  3483
			if (s.MarkedToken().MatchF(_L("0x"))!=KErrNotFound)
sl@0
  3484
				radix=EHex;
sl@0
  3485
			else
sl@0
  3486
				s.UnGetToMark();
sl@0
  3487
			}
sl@0
  3488
sl@0
  3489
        union Port
sl@0
  3490
            {
sl@0
  3491
		    TUint32 u;
sl@0
  3492
            TInt32 s;
sl@0
  3493
            };
sl@0
  3494
sl@0
  3495
        Port port;
sl@0
  3496
        TInt r;
sl@0
  3497
        if (radix == EHex)
sl@0
  3498
            r = s.Val(port.u, radix);
sl@0
  3499
        else
sl@0
  3500
            r = s.Val(port.s);
sl@0
  3501
		if (r != KErrNone || ! s.Eos())
sl@0
  3502
			return KErrBadName;
sl@0
  3503
		r = HAL::Set(HALData::EDebugPort, port.s);
sl@0
  3504
		if (r != KErrNone)
sl@0
  3505
			return r;
sl@0
  3506
		CShell::TheConsole->Printf(KSetPortLit, port.s, port.u);
sl@0
  3507
		}
sl@0
  3508
sl@0
  3509
	return KErrNone;
sl@0
  3510
	}
sl@0
  3511
sl@0
  3512
TInt ShellFunction::Plugin(TDes& aName,TUint aSwitches)
sl@0
  3513
	{
sl@0
  3514
	TInt err = KErrNone;
sl@0
  3515
	switch(aSwitches)
sl@0
  3516
		{
sl@0
  3517
		case TShellCommand::EASwitch:
sl@0
  3518
			{
sl@0
  3519
			err = CShell::TheFs.AddPlugin(aName);
sl@0
  3520
			CShell::TheConsole->Printf(_L("Add Plugin: %S [r:%d]\n"), &aName, err);
sl@0
  3521
			break;
sl@0
  3522
			}
sl@0
  3523
		case TShellCommand::ERSwitch:
sl@0
  3524
			{
sl@0
  3525
			err = CShell::TheFs.RemovePlugin(aName);
sl@0
  3526
			CShell::TheConsole->Printf(_L("Remove Plugin: %S [r:%d]\n"), &aName, err);
sl@0
  3527
			break;
sl@0
  3528
			}
sl@0
  3529
		case TShellCommand::EMSwitch:
sl@0
  3530
			{
sl@0
  3531
			err = CShell::TheFs.MountPlugin(aName);
sl@0
  3532
			CShell::TheConsole->Printf(_L("Mount Plugin: %S [r:%d]\n"), &aName, err);
sl@0
  3533
			break;
sl@0
  3534
			}
sl@0
  3535
		case TShellCommand::EDSwitch:
sl@0
  3536
			{
sl@0
  3537
			err = CShell::TheFs.DismountPlugin(aName);
sl@0
  3538
			CShell::TheConsole->Printf(_L("Dismount Plugin: %S [r:%d]\n"), &aName, err);
sl@0
  3539
			break;
sl@0
  3540
			}
sl@0
  3541
		default:
sl@0
  3542
			{
sl@0
  3543
			break;
sl@0
  3544
			}
sl@0
  3545
		}
sl@0
  3546
	return err;
sl@0
  3547
	}
sl@0
  3548
sl@0
  3549
_LIT(KCrNl, "\r\n");
sl@0
  3550
sl@0
  3551
void SIPrintf(TRefByValue<const TDesC16> aFmt, ...)
sl@0
  3552
	{
sl@0
  3553
	TBuf<256> buf;
sl@0
  3554
	VA_LIST list;					
sl@0
  3555
	VA_START(list, aFmt);
sl@0
  3556
	// coverity[uninit_use_in_call]
sl@0
  3557
	buf.FormatList(aFmt, list);			
sl@0
  3558
	buf.Append(KCrNl);					
sl@0
  3559
	RDebug::RawPrint(buf);
sl@0
  3560
	CShell::TheConsole->Printf(buf);
sl@0
  3561
	}
sl@0
  3562
sl@0
  3563
/**
sl@0
  3564
	Run a specified executable in a loop.
sl@0
  3565
sl@0
  3566
	RUNEXEC <count> <command [args]> [/E] [/S] [/R]
sl@0
  3567
sl@0
  3568
	count	- loop count; zero (0) means: forever
sl@0
  3569
	command	- the executable to run. Arguments can be supplied.
sl@0
  3570
			  Limitations:
sl@0
  3571
			  command arguments cannot contain /? switches as the shell strips these out.
sl@0
  3572
			  command cannot contain spaces.
sl@0
  3573
sl@0
  3574
	/E	terminates the loop if the program exits with an error
sl@0
  3575
sl@0
  3576
	/S	makes the shell interpret "count" as a number of seconds
sl@0
  3577
		The shell will not attempt to terminate "command" early if it is still running after
sl@0
  3578
		"count" seconds. It will terminate the loop only after "command" has exited.
sl@0
  3579
sl@0
  3580
	/R	will make the shell reset debug registers / trace flags after each iteration.
sl@0
  3581
		This is to be used if the program modifies tracing flags for its own purposes but exits
sl@0
  3582
		abnormally; if /R is used, later iterations will run the program from the same initial
sl@0
  3583
		tracing	state each time.
sl@0
  3584
		Limitation: This flag does not yet affect BTrace / UTrace state.
sl@0
  3585
sl@0
  3586
	Switches can be combined; "RUNEXEC 2000 testprg /E/S/R" keeps running "testprg"	till an error
sl@0
  3587
	occurs, or more than 2000 seconds have passed, and resets the debug	state after each iteration.
sl@0
  3588
*/
sl@0
  3589
TInt ShellFunction::RunExec(TDes& aProg, TUint aSwitches)
sl@0
  3590
	{
sl@0
  3591
	_LIT(KRunExecFailedProcessCreate, "Failed to spawn command %S: error %d\n");
sl@0
  3592
	_LIT(KRunExecReportStatusAndTime, "Total elapsed time: %d msecs, Iteration %d: Exit type %d,%d,%S\n");
sl@0
  3593
	aProg.TrimAll();
sl@0
  3594
	TBuf<KShellMaxCommandLine> parameters(0);
sl@0
  3595
	TInt r;
sl@0
  3596
	TInt count = 0;
sl@0
  3597
	TTime timeStart, timeCurrent;
sl@0
  3598
	TTimeIntervalMicroSeconds timeTaken;
sl@0
  3599
sl@0
  3600
	// The first parameter must be a valid decimal integer.
sl@0
  3601
	for (r=0; r < aProg.Length() && TChar(aProg[r]).IsDigit(); r++)
sl@0
  3602
		count = count * 10 + (aProg[r] - '0');
sl@0
  3603
	if (r == 0 || r == aProg.Length() || TChar(aProg[r]).IsSpace() == EFalse)
sl@0
  3604
		return (KErrArgument);
sl@0
  3605
	aProg = aProg.Mid(r+1);
sl@0
  3606
sl@0
  3607
	TBool exitOnErr = (aSwitches & TShellCommand::EESwitch);
sl@0
  3608
	TBool resetDebugRegs = (aSwitches & TShellCommand::ERSwitch);
sl@0
  3609
	TBool countIsSecs = (aSwitches & TShellCommand::ESSwitch);
sl@0
  3610
	TBool forever = (count == 0);
sl@0
  3611
sl@0
  3612
	timeStart.HomeTime();
sl@0
  3613
sl@0
  3614
	// copy out the parameters - if any
sl@0
  3615
	r = aProg.Locate(' ');
sl@0
  3616
	if(r != KErrNotFound)
sl@0
  3617
		{
sl@0
  3618
		parameters = aProg.Mid(r+1);
sl@0
  3619
		aProg.SetLength(r);
sl@0
  3620
		}
sl@0
  3621
sl@0
  3622
	// Make sure the executable name qualifies as a pathname.
sl@0
  3623
	aProg.UpperCase();
sl@0
  3624
	if (aProg.FindF(_L(".EXE")) == KErrNotFound && (aProg.Length()+4) <= KShellMaxCommandLine)
sl@0
  3625
		aProg.Append(_L(".EXE"));
sl@0
  3626
sl@0
  3627
#ifdef _DEBUG
sl@0
  3628
	SIPrintf(_L("RUNEXEC: command %S, parameters %S, count %d, forever %d, issecs %d, exiterr %d"),
sl@0
  3629
		&aProg, &parameters, count, forever, countIsSecs, exitOnErr); 
sl@0
  3630
#endif
sl@0
  3631
	TInt i=0;
sl@0
  3632
	FOREVER
sl@0
  3633
		{
sl@0
  3634
		TInt retcode;
sl@0
  3635
		RProcess newProcess;
sl@0
  3636
		TRequestStatus status = KRequestPending;
sl@0
  3637
		TExitType exitType;
sl@0
  3638
		TBuf<KMaxExitCategoryName> exitCat(0);
sl@0
  3639
sl@0
  3640
		r = newProcess.Create(aProg, parameters);
sl@0
  3641
		if (r != KErrNone)
sl@0
  3642
			{
sl@0
  3643
			SIPrintf(KRunExecFailedProcessCreate, &aProg, r);
sl@0
  3644
			return (r);						// this is systematic - must return
sl@0
  3645
			}
sl@0
  3646
		newProcess.Logon(status);
sl@0
  3647
		newProcess.Resume();
sl@0
  3648
		User::WaitForRequest(status);
sl@0
  3649
		exitType = newProcess.ExitType();
sl@0
  3650
		exitCat = newProcess.ExitCategory();
sl@0
  3651
		retcode = newProcess.ExitReason();
sl@0
  3652
		newProcess.Close();
sl@0
  3653
sl@0
  3654
		timeCurrent.HomeTime();
sl@0
  3655
		timeTaken = timeCurrent.MicroSecondsFrom(timeStart);
sl@0
  3656
		TInt msecs = I64LOW(timeTaken.Int64() / 1000);
sl@0
  3657
		SIPrintf(KRunExecReportStatusAndTime, msecs, i+1, exitType, retcode, &exitCat);
sl@0
  3658
sl@0
  3659
		if (resetDebugRegs)
sl@0
  3660
			{
sl@0
  3661
			TheShell->TheFs.SetDebugRegister(0);
sl@0
  3662
			User::SetDebugMask(0);
sl@0
  3663
			}
sl@0
  3664
sl@0
  3665
		i++;
sl@0
  3666
sl@0
  3667
		if ((exitOnErr && (exitType != EExitKill || status != KErrNone)) ||							// err occurred, leave requested ?
sl@0
  3668
			(countIsSecs && count != 0 && timeTaken.Int64() > (TInt64)1000000 * (TInt64)count) ||	// time elapsed ?
sl@0
  3669
			(!forever && i >= count))																// loop done ?
sl@0
  3670
			break;
sl@0
  3671
		}
sl@0
  3672
	return(KErrNone);
sl@0
  3673
	}
sl@0
  3674
sl@0
  3675
//
sl@0
  3676
// System information command
sl@0
  3677
//
sl@0
  3678
sl@0
  3679
TBool DebugNum(TInt aBitNum)
sl@0
  3680
	{
sl@0
  3681
	__ASSERT_ALWAYS(aBitNum >= 0 && aBitNum <= KMAXTRACE, User::Panic(_L("Bad bit num"), 0));
sl@0
  3682
	TInt index = aBitNum >> 5;
sl@0
  3683
	TInt m = UserSvr::DebugMask(index) & (1 << (aBitNum & 31));
sl@0
  3684
	return m != 0;
sl@0
  3685
	}
sl@0
  3686
sl@0
  3687
void SIHeading(TRefByValue<const TDesC16> aFmt, ...)
sl@0
  3688
	{
sl@0
  3689
	TBuf<256> buf;
sl@0
  3690
	VA_LIST list;
sl@0
  3691
	VA_START(list, aFmt);
sl@0
  3692
	buf.Append(KCrNl);
sl@0
  3693
	buf.AppendFormatList(aFmt, list);
sl@0
  3694
	buf.Append(KCrNl);
sl@0
  3695
	RDebug::RawPrint(buf);
sl@0
  3696
	CShell::TheConsole->Printf(buf);
sl@0
  3697
	buf.Fill('=', buf.Length()-4);
sl@0
  3698
	buf.Append(KCrNl);
sl@0
  3699
	RDebug::RawPrint(buf);
sl@0
  3700
	CShell::TheConsole->Printf(buf);
sl@0
  3701
	}
sl@0
  3702
sl@0
  3703
void SIBoolean(const TDesC& aFmt, TBool aVal)
sl@0
  3704
	{
sl@0
  3705
	_LIT(KEnabled, "enabled");
sl@0
  3706
	_LIT(KDisabled, "disabled");
sl@0
  3707
	SIPrintf(aFmt, aVal ? &KEnabled : &KDisabled);
sl@0
  3708
	}
sl@0
  3709
sl@0
  3710
TInt ShellFunction::SysInfo(TDes& /*aArgs*/, TUint /*aSwitches*/)
sl@0
  3711
	{
sl@0
  3712
	SIHeading(_L("Kernel Features"));
sl@0
  3713
	SIBoolean(_L("Crazy scheduler delays are %S."), DebugNum(KCRAZYSCHEDDELAY));
sl@0
  3714
	SIBoolean(_L("Crazy scheduler priorities and timeslicing are %S."),
sl@0
  3715
				UserSvr::HalFunction(EHalGroupKernel, EKernelHalConfigFlags, 0, 0) & EKernelConfigCrazyScheduling);
sl@0
  3716
sl@0
  3717
	return KErrNone;
sl@0
  3718
	}
sl@0
  3719
sl@0
  3720
sl@0
  3721
//-------------------------------------------------------------------------
sl@0
  3722
/**
sl@0
  3723
    Print out the command line to the console and standard debug port.
sl@0
  3724
*/
sl@0
  3725
TInt ShellFunction::ConsoleEcho(TDes& aArgs, TUint /*aSwitches*/)
sl@0
  3726
{
sl@0
  3727
    SIPrintf(aArgs);
sl@0
  3728
    return KErrNone;
sl@0
  3729
}