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