Update contrib.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // f32\etshell\ts_com.cpp
20 // Solve compilation problem caused by non-English locale
21 #pragma setlocale("english")
31 #include <nkern/nk_trace.h>
32 #include "filesystem_fat.h"
34 TPtrC ptrFormatHelp=_L("Drive:[\\] [fat12|fat16|fat32] [spc:X] [rs:Y] [ft:Z] [/Q][/S][/E][/F]\nfat12 or fat16 or fat32 specifies explicit FAT type\nspc:X specifies \"X\" sectors per cluster\nrs:Y specifies \"Y\" reserved sectors\nft:Z specifies \"Z\" FAT tables (1 or 2)\n\n/q - QuickFormat, /s - SpecialFormat, /e - ForcedErase\n/f - force formatting (ignore volume being in use)");
35 TPtrC ptrMountHelp=_L("Drive:[\\] <fsy:X> <fs:Y> [pext:Z] [/S][/U][/F][/R]\n'X' *.fsy module name, like elocal.fsy\n'Y' file system name, like 'FAT'\n'Z' optional primary extension module name\n/U - dismount FS from the drive e.g 'mount d: /u' \n/F - force mounting with dismounting existing FS \n/S - mount drive as synchronous\n/R - remount the file system ");
39 const TShellCommand CShell::iCommand[ENoShellCommands]=
41 // TShellCommand(_L("BLANK"),_L("Help"),_L("-?"),TShellCommand::EDSwitch,ShellFunction::BLANK),
42 TShellCommand(_L("ATTRIB"),_L("Displays or changes file attributes"),_L("[drive:][path][filename] [+R | -R] [+H |-H] [+S | -S] [+A | -A] [/p]\n\n /p - Pause after each screen of information"), TShellCommand::EPSwitch, ShellFunction::Attrib),
43 TShellCommand(_L("CD"),_L("Change the current directory for a drive"),_L("[path] [/d]\n\n /d - Change drive"),TShellCommand::EDSwitch,ShellFunction::Cd),
44 TShellCommand(_L("CHKDEPS"),_L("Check the dependencies of an executable or a Dll (ARM only)"),_L("[Filename.EXE] or [Filename.DLL]"),0,ShellFunction::ChkDeps),
45 TShellCommand(_L("CHKDSK"),_L("Check disk for corruption"),_L("[drive:] [/s][/f|/u]\n\n/s - start ScanDrive instead of CheckDisk\n/f - finalise drive\n/u - unfinalise drive"),TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::EUSwitch,ShellFunction::ChkDsk),
46 TShellCommand(_L("COPY"),_L("Copy one (or more) file(s)"),_L("source [destination]"),TShellCommand::ESSwitch,ShellFunction::Copy),
47 TShellCommand(_L("DEL"),_L("Delete one file"),_L("[drive:][path][filename]"),TShellCommand::ESSwitch,ShellFunction::Del),
48 TShellCommand(_L("DIR"),_L("Show directory contents"),_L("[drive:][path][filename] [/p][/w]\n\n /p - Pause after each screen of information\n /w - Wide format"),TShellCommand::EPSwitch|TShellCommand::EWSwitch|TShellCommand::EASwitch,ShellFunction::Dir),
49 // TShellCommand(_L("EDLIN"),_L("Edit a text file"),_L("[drive:][path][filename] [/p]\n\n /p - Pause after each screen of information"),TShellCommand::EPSwitch,ShellFunction::Edit),
50 TShellCommand(_L("FORMAT"),_L("Format a disk"),ptrFormatHelp,TShellCommand::EQSwitch|TShellCommand::ESSwitch|TShellCommand::EESwitch|TShellCommand::EFSwitch,ShellFunction::Format),
51 TShellCommand(_L("GOBBLE"),_L("Create a file"),_L("[filename] size [/e]\n\n /e - create an empty file, without writing any data"),TShellCommand::EESwitch,ShellFunction::Gobble),
52 TShellCommand(_L("HEXDUMP"),_L("Display the contents of a file in hexadecimal"),_L("[drive:][path][filename] [/p]\n\n /p - Pause after each screen of information\n\n Hit escape to exit from hexdump "),TShellCommand::EPSwitch,ShellFunction::Hexdump),
53 TShellCommand(_L("LABEL"),_L("Set or return the volume label"),_L("[newlabel]"),0,ShellFunction::VolumeLabel),
54 TShellCommand(_L("MD"),_L("Make a new directory"),_L("name"),0,ShellFunction::Md),
55 TShellCommand(_L("MOVE"),_L("Move files"),_L("name [destination]"),TShellCommand::ESSwitch,ShellFunction::Move),
56 TShellCommand(_L("PS"),_L("Display information about processes"),_L(""),0,ShellFunction::Ps),
57 TShellCommand(_L("RENAME"),_L("Rename a file"),_L("oldfilename newfilename"),TShellCommand::ESSwitch,ShellFunction::Rename),
58 TShellCommand(_L("RD"),_L("Delete one directory"),_L("[drive:][path]directoryname"),TShellCommand::ESSwitch,ShellFunction::Rd),
59 TShellCommand(_L("START"),_L("Run a program in a separate window"),_L("filename[.exe]"),0,ShellFunction::Start),
60 TShellCommand(_L("TIME"),_L("Display the system time"),_L(""),0,ShellFunction::Time),
61 TShellCommand(_L("TRACE"),_L("Set the debug trace mask"),_L("[mask value in hex] [index] [/S/L/F/T/I/N/M/O/C/H]\n /S - KFSERV\n /L - KFLDR\n /F - KFSYS\n /T - KLFFS\n /I - KISO9660\n /N - KNTFS\n /M - KTHRD\n /O - KROFS\n /C - KCOMPFS\n /H - KCACHE"),TShellCommand::ELSwitch|TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::ETSwitch|TShellCommand::EISwitch|TShellCommand::ENSwitch|TShellCommand::EMSwitch|TShellCommand::EOSwitch|TShellCommand::ECSwitch|TShellCommand::EHSwitch,ShellFunction::Trace),
62 TShellCommand(_L("TREE"),_L("Graphically display the directory structure"),_L("[drive:][path] [/f][/p]\n\n /f - Show files\n /p - Pause after each screen of information"),TShellCommand::EFSwitch|TShellCommand::EPSwitch,ShellFunction::Tree),
63 TShellCommand(_L("TYPE"),_L("Display the contents of a text file"),_L("[drive:][path]filename [/p]\n\n /p - Pause after each screen of information"),TShellCommand::EPSwitch,ShellFunction::Type),
64 TShellCommand(_L("VNAME"),_L("Check whether a filename is valid. Return any invalid character"),_L("[drive:][path]filename \n\n "),0,ShellFunction::ValidName),
65 TShellCommand(_L("LOCK"),_L("Lock a password-enabled media"),_L("drive-number cur-pswd new-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Lock),
66 TShellCommand(_L("UNLOCK"),_L("Unlock a locked password-enabled media"),_L("drive-number cur-pswd [/s]"), TShellCommand::ESSwitch, ShellFunction::Unlock),
67 TShellCommand(_L("CLEAR"),_L("Clear password from password-enabled media"),_L("drive-number cur-pswd"), 0x00000000, ShellFunction::Clear),
68 TShellCommand(_L("SETSIZE"),_L("Set size of a file"),_L("[filename] size"),0,ShellFunction::SetSize),
69 TShellCommand(_L("DEBUGPORT"),_L("Set or get debug port"),_L("[port]"),0,ShellFunction::DebugPort),
70 TShellCommand(_L("PLUGIN"),_L("Manage Plugins"),_L("[name][/A][/R][/M][/D]"),TShellCommand::EASwitch|TShellCommand::ERSwitch|TShellCommand::EMSwitch|TShellCommand::EDSwitch,ShellFunction::Plugin),
71 TShellCommand(_L("DRVINFO"),_L("Print information about present drive(s) in the system"),_L("[DriveLetter:[\\]] [/p]\n/p - pause after each drive"),TShellCommand::EPSwitch,ShellFunction::DrvInfo),
72 TShellCommand(_L("SYSINFO"),_L("Print information about system features and status"),_L(""),0,ShellFunction::SysInfo),
73 TShellCommand(_L("MOUNT"),_L("Mount / dismount file system on specified drive"),ptrMountHelp,TShellCommand::EUSwitch|TShellCommand::ESSwitch|TShellCommand::EFSwitch|TShellCommand::ERSwitch,ShellFunction::MountFileSystem),
74 TShellCommand(_L("ECHO"),_L("Print out the command line to the console and standard debug port."),_L("[line to print out]"),0,ShellFunction::ConsoleEcho),
75 TShellCommand(_L("RUNEXEC"),_L("Run a program in a loop"),_L("count filename[.exe] [/E/S/R]\n /E - exit early on error\n /S - count in seconds\n zero - run forever\n /R - reset debug regs after each run"),TShellCommand::EESwitch|TShellCommand::ESSwitch|TShellCommand::ERSwitch,ShellFunction::RunExec),
80 LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN);
81 LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW);
83 _LIT(KLitNewLine,"\n");
84 void CShell::NewLine()
86 TheConsole->Printf(KLitNewLine());
90 // Skip the hexadecimal prefix if present and return EHex. Return
91 // EDecimal otherwise.
94 static TRadix ParseHexaPrefixIfAny(TLex& aLex)
97 if (aLex.Remainder().Length() > 2)
101 if (aLex.MarkedToken().MatchF(KPrefix) != KErrNotFound)
113 // Used to locate spaces in the command line, and return the next word
116 TWord::TWord(const TDesC& aDes)
117 : iSpace(0),iNextSpace(0)
126 void TWord::Init(const TDesC& aDes)
128 // Resets to the start of the buffer
134 TInt TWord::FindNextWord(TDes& aWord)
136 // Returns the next word from the buffer
139 iSpace=aWord.Locate(' ');
141 if (iSpace==KErrNotFound) // No spaces in command line
143 if (aWord.Length()==0) // Command line has zero length:
144 return (KErrNotFound); // User just typed "command"
146 { // User typed "command aWord"
153 else if (iSpace<aWord.Length()) // Spaces may be command switches or part of the filename
155 iRightString=(aWord.Right((aWord.Length()-iSpace)-1));
157 iNextSpace=iRightString.Locate(' '); // Check for another space
158 if (iNextSpace==KErrNotFound) // No more spaces
160 iNextWord=iRightString;
161 return((iDes.Length())-(iRightString.Length()));// Position of the (last) word
164 if (iNextSpace<iRightString.Length()) // More spaces - assign iNextWord to be
165 { // the text in between the two spaces
166 iNextWord=(iRightString.Left(iNextSpace));
167 return ((iDes.Length())-(iRightString.Length()));// Position of the word
171 return(KErrNotFound);
175 return(KErrNotFound);
178 //-------------------------------------------------------------------------
181 TInt ShellFunction::Cd(TDes& aPath,TUint aSwitches)
186 ShellFunction::StripQuotes(aPath);
188 TBool drvNameOnly=aPath.Length()==2 && aPath[1]==KDriveDelimiter;
189 TBool dSwitchSet=aSwitches&TShellCommand::EDSwitch;
190 if (aPath.Length()==0 || (drvNameOnly && !dSwitchSet))
192 TInt drvNum=(aPath.Length() ? aPath[0] : TheShell->currentPath[0])-'A';
193 if (drvNum<0 || drvNum>=KMaxDrives)
195 CShell::TheConsole->Printf(_L("%S\n"),&TheShell->drivePaths[drvNum]);
198 if (aPath.Find(_L("*"))!=KErrNotFound)
200 if (aPath[aPath.Length()-1]!=KPathDelimiter && !drvNameOnly)
201 aPath.Append(KPathDelimiter);
203 TChar drvLetter = aPath[0];
204 drvLetter.UpperCase();
205 aPath[0] = (TText) drvLetter;
207 TInt r=GetFullPath(aPath,dirParse);
210 TPtrC fullName=dirParse.FullName();
212 r=dir.Open(TheShell->TheFs,fullName,KEntryAttMaskSupported);
216 if (dSwitchSet || fullName[0]==TheShell->currentPath[0])
217 r=TheShell->TheFs.SetSessionPath(dirParse.DriveAndPath());
219 TheShell->SetDrivePath(dirParse.DriveAndPath());
223 TInt ShellFunction::ChkDeps(TDes& aPath,TUint /*aSwitches*/)
225 ShellFunction::StripQuotes(aPath);
228 TBool appendedExe=EFalse;
230 // Determine whether aPath is an executable or a Dll
232 TInt r=aPath.FindF(_L(".EXE"));
235 r=aPath.FindF(_L(".DLL"));
236 if (r==KErrNotFound)// aPath does not include .exe or .dll extensions
238 aPath.Append(_L(".EXE")); // append a .exe extension
243 if (aPath.Length()>2 && aPath[1]==':' && aPath[2]!='\\')
246 __ASSERT_ALWAYS(RFs::CharToDrive(aPath[0],drive)==KErrNone,User::Panic(_L("Invalid drive letter"),0));
247 TheShell->currentPath=TheShell->drivePaths[drive];
249 aPath.Insert(0,TheShell->currentPath);
251 if (aPath.Length()>2 && aPath[1]!=':')
254 aPath.Insert(0,TheShell->currentPath);
256 aPath.Insert(0,TheShell->currentPath.Left(2));
260 r=file.Open(CShell::TheFs,aPath,EFileStream);
261 if (r!=KErrNone) // File could not be opened
263 if (appendedExe) // If .EXE was appended earlier
265 // Remove .EXE and append .DLL instead. Try to open the file again
266 // If this fails too, the user entered an invalid filename that is neither
267 // an executable or a Dll
268 aPath.Delete(aPath.Length()-4,4);
270 aPath.Append(_L(".DLL")); // Try a .DLL extension
271 r=file.Open(CShell::TheFs,aPath,EFileStream);
272 if (r!=KErrNone) // Still could not open file
273 return(r); // Neither an executable or a Dll
274 // Runs to here if the file is opened -> .DLL extension appended
277 return(r); // User had typed in an incorrect filename with
278 // a .DLL or .EXE extension
283 TRAPD(leaveCode,check.ConstructL());// Allocates 4 elements at a time
284 if (leaveCode!=KErrNone) // If function leaves
285 return(leaveCode); // return the leave code
287 TRAPD(result,check.GetImportDataL(aPath,NULL));
288 if (result==KErrGeneral)
290 CShell::TheConsole->Printf(_L(" %S has no import data\n"),&aPath);
294 check.ListArray(); // Print out the results of DllCheck
299 // Check disk for corruption
303 // ChkDsk DriveLetter:[\] [/S] [/F] [/U]
305 // /S : Starts a ScanDrive instead of CheckDisk
306 // /F : Finalise given drive
307 // /U : UnFinalise given drive
309 TInt ShellFunction::ChkDsk(TDes& aPath,TUint aSwitches)
311 ShellFunction::StripQuotes(aPath);
313 const TBool bRunScanDrv = aSwitches & TShellCommand::ESSwitch;
314 const TBool bFinaliseDrv = aSwitches & TShellCommand::EFSwitch;
315 const TBool bUnFinaliseDrv = aSwitches & TShellCommand::EUSwitch;
320 if(aPath.Length() < 1)
326 nRes=CShell::TheFs.CharToDrive(aPath[0], drive);
329 if (nRes != KErrNone)
331 CShell::TheConsole->Printf(_L("Wrong drive specified!\n"));
336 {//-- run ScanDrive on the specified drive
337 CShell::TheConsole->Printf(_L("Starting ScanDrive...\n"));
338 nRes=TheShell->TheFs.ScanDrive(aPath);
341 CShell::TheConsole->Printf(_L("No errors.\n"));
344 else if(bFinaliseDrv)
345 {//-- finalise the drive
346 nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EFinal_RW);
350 CShell::TheConsole->Printf(_L("Drive %c: is finalised RW\n"), 'A'+drive);
352 else if(bUnFinaliseDrv)
353 {//-- Unfinalise the drive
354 nRes = CShell::TheFs.FinaliseDrive(drive, RFs::EForceUnfinalise);
358 CShell::TheConsole->Printf(_L("Drive %c: is Unfinalised\n"), 'A'+drive);
361 {//-- run CheckDisk on the specified drive
362 nRes=TheShell->TheFs.CheckDisk(aPath);
369 CShell::TheConsole->Printf(_L("Complete - no errors\n"));
372 CShell::TheConsole->Printf(_L("Error - File cluster chain contains a bad value (<2 or >maxCluster)\n"));
375 CShell::TheConsole->Printf(_L("Error - Two files are linked to the same cluster\n"));
378 CShell::TheConsole->Printf(_L("Error - Unallocated cluster contains a value != 0\n"));
381 CShell::TheConsole->Printf(_L("Error - Size of file != number of clusters in chain\n"));
384 CShell::TheConsole->Printf(_L("Undefined Error value\n"));
390 TInt ShellFunction::Copy(TDes& aPath,TUint aSwitches)
394 // COPY [/A | /B] source [/A | /B] [+ source [/A | /B] [+ ...]] [destination] [/A | /B]] [/V] [/N]
395 // source Specifies the file or files to be copied.
396 // /A Indicates an ASCII text file.
397 // /B Indicates a binary file.
398 // destination Specifies the directory and/or filename for the new file(s).
399 // /V Verifies that new files are written correctly.
400 // /Y Supresses prompting to confirm you want to overwrite existing destination file
401 // /N Uses short filename, if available, when copying a file with a non-8dot3 name.
403 // To append files, specify a single file for destination, but multiple files
404 // for source (using wildcards or file1+file2+file3 format).
408 // COPY source [destination]
409 // source Specifies the file or files to be copied to the current directory
411 // Modified November 1997 to allow spaces in filenames
414 if (aPath.Length() == 0)
415 return KErrNotFound; // no source file
417 ShellFunction::StripQuotes(aPath);
419 TBuf<KShellMaxCommandLine> destination;
420 TBuf<KShellMaxCommandLine> tempPath;
423 TBool endOfCommandLine=EFalse;
425 // Check if the word returned is a valid filename. If not, scan the next
426 // word too in case the filename contains spaces. If, at the end of the
427 // the line, the filename is not recognised, it is invalid. If there are no
428 // spaces the user has not used the correct format for this command.
430 TInt r=word.FindNextWord(aPath);
434 if (r==0) // No destination was specified
436 // Work out the destination
437 tempPath.SetLength(0);
438 r=GetFullPath(tempPath,dirPath);
441 destination=dirPath.FullName();
442 // Now get the path of the source
444 r=GetFullPath(tempPath,dirPath);
447 endOfCommandLine=ETrue; // So we don't get stuck in an infinite loop
451 // Work out the destination
452 destination=aPath.Right(aPath.Length()-r);
453 if (!destination.Compare(_L(".")))
454 GetFullPath(destination,dirPath);
455 // Now get the path of the source
457 tempPath.SetLength(r);
458 r=GetFullPath(tempPath,dirPath);
463 TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
464 TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
465 r=CShell::TheFileMan->Copy(dirPath.FullName(),destination,switches);
467 return(r); // Copy was successful
469 else // Not a valid filename - move one word along the command line
470 r=word.FindNextWord(word.iRightString);
471 } while ((r>=0)&&(!endOfCommandLine));
473 if (r<0) // Some error
475 else // End of command line, user typed invalid line, return not found
476 return (KErrNotFound);
480 TInt ShellFunction::VolumeLabel(TDes& aPath,TUint /*aSwitches*/)
482 Sets or returns the default path
484 @param aPath The volume label being set or returned
487 ShellFunction::StripQuotes(aPath);
491 TInt r=CShell::TheFs.CharToDrive(CShell::currentPath[0], drive);
494 if (aPath.Length()==0)
496 r=CShell::TheFs.Volume(vol, drive);
498 CShell::TheConsole->Printf(_L("Volume = %S\n"),&vol.iName);
501 r=CShell::TheFs.SetVolumeLabel(aPath, drive);
505 TInt ShellFunction::Del(TDes& aPath,TUint aSwitches)
508 if (aPath.Length()==0)
511 ShellFunction::StripQuotes(aPath);
513 GetFullPath(aPath,filePath);
514 TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
515 TUint switches=(recursive) ? CFileMan::ERecurse : 0;
516 TInt r=CShell::TheFileMan->Delete(filePath.FullName(),switches);
521 void ShellFunction::AlignTextIntoColumns(RPointerArray<HBufC>& aText)
522 //function which tries to arrange text as a set of columns if console width greater then the longest string
525 if (aText.Count()<=0) return;
526 //detect the longest string
527 for (TInt i=0;i<aText.Count();i++)
528 if (aText[i]->Length()>aText[ind]->Length())
530 TInt max_string_length=aText[ind]->Length()+2;
532 //calculate how many columns fit into the screen
533 TInt number_of_columns=(CShell::TheConsole->ScreenSize().iWidth)/max_string_length;
535 //if we cannot fit more than one column into screen when we do nothing
536 if (number_of_columns<2) return;
538 //calculate column width
539 TInt column_width=CShell::TheConsole->ScreenSize().iWidth/number_of_columns;
541 TInt current_source_string=0;
542 TInt current_destination_string=0;
544 TInt count=aText.Count();
545 //join strings together into string which fits in a single line
546 while (current_source_string<count)
548 TPtr string= aText[current_destination_string++]->Des();
551 for (TInt i=0;i<number_of_columns;i++)
553 if (current_source_string==count)
555 //skip several characters to keep even distance between columns
556 for (TInt j=0;j<to_skip;j++)
557 string.Append(_L(" "));
560 string=(*aText[current_source_string]);
562 string.Append(*aText[current_source_string]);
563 to_skip=column_width-aText[current_source_string]->Length();
564 current_source_string++;
568 //resize aText array to the new size
570 for (TInt j=aText.Count()-1;j>=current_destination_string;j--)
579 void ShellFunction::OutputContentsToConsole(RPointerArray<HBufC>& aText,TUint aSwitches)
580 //outputs content of the buffer to console according to settings passed in aSwitches
582 if ((aText.Count()>0)&&((aSwitches&TShellCommand::EWSwitch)!=0))
583 AlignTextIntoColumns(aText);
585 for (TInt i=0;i<aText.Count();i++)
587 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),*aText[i]);
588 CShell::OutputStringToConsole(EFalse,_L("\n"));
596 void ShellFunction::OutputDirContentL(CDir* aDirList,RPointerArray<HBufC>& aText,TUint aSwitches)
597 //outputs content of a directory to console according to settings passed in aSwitches
599 TInt count=aDirList->Count();
600 TInt fileCount=0, dirCount=0, printCount=0;
603 //compose an array of strings describing entries in the directory
604 for (TInt j=0;j<count;j++)
607 TEntry entry=(*aDirList)[j];
608 TDateTime modTime=entry.iModified.DateTime();
609 if ((aSwitches&TShellCommand::EWSwitch)!=0)//if we are asked to output brief information about directory content
611 TInt length=(KMaxFileName>CShell::TheConsole->ScreenSize().iWidth)?KMaxFileName:CShell::TheConsole->ScreenSize().iWidth;
612 buf = HBufC::NewL(length);
614 CleanupStack::PushL(buf);
615 TPtr name=buf->Des();
621 name.Insert(0,_L("["));
626 byteCount+=entry.FileSize();
630 else//if we are asked to output full information about directory content
632 buf = HBufC::NewL(KMaxFileName+100);//reserve additional space for the creation time information
633 CleanupStack::PushL(buf);
634 TPtr name=buf->Des();
640 name.Format(_L(" %- 26S <DIR> %+02d/%+02d/%- 4d %02d:%02d:%02d.%06d"),
641 &entry.iName,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
645 TInt64 entrySize = entry.FileSize();
646 byteCount+=entrySize;
648 name.Format(_L(" %- 32S%+ 15Lu %+02d/%+02d/%- 4d %02d:%02d:%02d.%06d"),
649 &entry.iName,entrySize,modTime.Day()+1,modTime.Month()+1,modTime.Year(),modTime.Hour(),modTime.Minute(),modTime.Second(),modTime.MicroSecond());
652 User::LeaveIfError(aText.Append(buf ));
654 //print the contents if a screen size of data is available. This will prevent huge buffer allocation.
655 if(printCount == CShell::TheConsole->ScreenSize().iHeight)
657 OutputContentsToConsole(aText,aSwitches);
663 OutputContentsToConsole(aText,aSwitches);
665 //output summary information
666 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L(" %d File%c\n"),fileCount,(fileCount==1)?' ':'s');
669 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L(" %lu byte%c\n"),byteCount,(fileCount==1)?' ':'s');
672 TBuf<50> buf;// allocate string long enough for additional information(number of directories)
673 buf.Format(_L(" %d Director"),dirCount);
675 buf.AppendFormat(_L("y\n"));
677 buf.AppendFormat(_L("ies\n"));
679 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
682 TInt ShellFunction::Dir(TDes& aPath,TUint aSwitches)
684 // Modified December 1997, to sort entries alphabetically
687 ShellFunction::StripQuotes(aPath);
692 // Parses the given path to give a full path
693 GetFullPath(aPath,dirParse);
694 // Sets aPath to a full path name
695 aPath=dirParse.FullName();
696 if (aPath[aPath.Length()-1]==KPathDelimiter)
698 else if (aPath.Locate(KMatchAny)==KErrNotFound && aPath.Locate(KMatchOne)==KErrNotFound && file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir)!=KErrNone)
699 aPath.Append(_L("\\*"));
702 TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
705 CShell::TheConsole->Printf(_L("File or directory not found\n"));
710 r=TheShell->TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,anEntryList);
716 CleanupStack::PushL(anEntryList);
718 //Sets the new length of path to the position of the last path delimiter +1
719 aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
720 CShell::TheConsole->Printf(_L("Directory of %S\n"),&aPath);
722 //allocate array to be used as an output buffer
723 RPointerArray<HBufC>* text=new(ELeave) RPointerArray<HBufC>();
724 TRAPD(error,OutputDirContentL(anEntryList,*text,aSwitches));
725 //we are not interesed in the error code because we need empty the buffer in any case
726 for (TInt i=0;i<text->Count();i++)
729 CleanupStack::PopAndDestroy(anEntryList);
738 TInt ShellFunction::Edit(TDes& /*aPath*/,TUint /*aSwitches*/)
740 // Dummy, used by edlin (now retired)
747 TInt ShellFunction::Attrib(TDes& aPath,TUint aSwitches)
749 ShellFunction::StripQuotes(aPath);
751 // Use TWord::NextWord(aPath) to find any spaces in the command line
752 TWord nextWord(aPath);
753 TInt r=nextWord.FindNextWord(aPath);
755 const TPtrC settings[8]={(_L("+R")),(_L("-R")),(_L("+H")),(_L("-H")),(_L("+S")),(_L("-S")),(_L("+A")),(_L("-A"))};
756 TInt numberOfSettings=(sizeof(settings)/sizeof(*settings));
758 if (r==KErrNotFound) // User just typed ATTRIB
759 aPath.SetLength(aPath.Length());
760 else if (r==0) // User typed ATTRIB aWord
761 { // Check the word for a valid attributes
762 for (TInt index=0; index<numberOfSettings; index++)
764 signal=(nextWord.iNextWord).FindF(settings[index]);
765 if (signal!=KErrNotFound)
768 if (signal==KErrNotFound) // No valid attributes settings
769 aPath.SetLength(aPath.Length());
770 else // Valid attributes settings
773 else // User typed ATTRIB aWord1 aWord2
774 { // Check the word for a valid attributes switch
775 while (r!=KErrNotFound)
777 for (TInt index=0; index<numberOfSettings; index++)
779 signal=(nextWord.iNextWord).FindF(settings[index]);
780 if (signal!=KErrNotFound)
783 if (signal!=KErrNotFound) // Matched valid switches
785 // Divide up command line
786 // Include all settings (in case of "ATTRIB aWord +R +S")
787 nextWord.iRightString=aPath.Right(aPath.Length()-r);
791 else // No valid switches found in word
792 r=nextWord.FindNextWord(nextWord.iRightString); // Check the next word
793 if (r==0) // Reached the end of a spaced command line without finding settings
795 nextWord.iRightString=aPath.Right(r);
802 GetFullPath(aPath,dirParse);
803 aPath=dirParse.FullName();
806 if (aPath[aPath.Length()-1]==KPathDelimiter)
808 else if( (aPath.Locate(KMatchAny)==KErrNotFound) && (aPath.Locate(KMatchOne)==KErrNotFound) )
810 TInt error=file.Open(TheShell->TheFs,aPath,KEntryAttMatchExclude|KEntryAttDir);
812 aPath.Append(_L("\\*"));//Path does not end in a valid file
814 file.Close();// Path ends in a valid file
817 // Changes attributes settings (files only) if requested and if necessary
821 r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,entryList);
824 CleanupStack::PushL(entryList);
825 TInt entryCount=entryList->Count();
827 TBuf<KShellMaxCommandLine> aSessionPath;
828 r=TheShell->TheFs.SessionPath(aSessionPath);
829 // Temporarily assign session path to be the path requested
830 // Use the heap as we're running out of stack space
831 HBufC* pTempPath=NULL;
832 TRAP(r,pTempPath=HBufC::NewL(aPath.Length()))
835 CleanupStack::PopAndDestroy(entryList);
839 pTempPath->Des().SetLength(aPath.LocateReverse(KPathDelimiter)+1);
840 r=TheShell->TheFs.SetSessionPath(pTempPath->Des());
841 User::Free(pTempPath);
843 // Looks clumsy, but necessary to change attributes of files in higher level directories
844 for (TInt i=0;i<entryCount;i++)
846 TEntry entry=(*entryList)[i];
849 for (TInt index=0; index<numberOfSettings; index++)
853 signal=(nextWord.iRightString).FindF(settings[index]);
854 if (signal==KErrNotFound)
860 attToSet|=KEntryAttReadOnly;
863 attToRemove|=KEntryAttReadOnly;
866 attToSet|=KEntryAttHidden;
869 attToRemove|=KEntryAttHidden;
872 attToSet|=KEntryAttSystem;
875 attToRemove|=KEntryAttSystem;
878 attToSet|=KEntryAttArchive;
881 attToRemove|=KEntryAttArchive;
883 default: // Will never reach here
886 r=TheShell->TheFs.SetAtt((entry.iName),attToSet,attToRemove);
892 // Set session path to previous setting
893 r=TheShell->TheFs.SetSessionPath(aSessionPath);
894 CleanupStack::PopAndDestroy(entryList);
897 // Runs to here if no requested attributes changes:
898 CDir* alphaEntryList;
899 r=CShell::TheFs.GetDir(aPath,KEntryAttMaskSupported,ESortByName,alphaEntryList);
902 TInt count=alphaEntryList->Count();
905 r=dir.Open(TheShell->TheFs,aPath,KEntryAttMaskSupported);
908 delete alphaEntryList;
912 aPath.SetLength(aPath.LocateReverse(KPathDelimiter)+1);
918 // Lists attributes settings (files only)
919 for (TInt j=0;j<count;j++)
921 entry=alphaEntryList->operator[](j);
924 TBuf<4> attrBuf=entry.IsReadOnly()?_L("R"):_L("");
925 if (entry.IsHidden())
927 if (entry.IsSystem())
929 if (entry.IsArchive())
931 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L(" %-10S %S%S\n"),&attrBuf, &aPath,&entry.iName);
939 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),_L("No files found in %S\n"),&aPath);
941 delete alphaEntryList;
949 //--------------------------------------------------------
952 Format TMediaType description.
954 @param aDrvInfo drive info structure
955 @param aPrintBuf buffer where the information will be printed to.
957 void FormatDrvMediaTypeInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
959 aPrintBuf.Format(_L("TMediaType:%d "),aDrvInfo.iType);
961 switch(aDrvInfo.iType)
963 case EMediaNotPresent: aPrintBuf.Append(_L("EMediaNotPresent")); break;
964 case EMediaUnknown: aPrintBuf.Append(_L("EMediaUnknown")); break;
965 case EMediaFloppy: aPrintBuf.Append(_L("EMediaFloppy")); break;
966 case EMediaHardDisk: aPrintBuf.Append(_L("EMediaHardDisk")); break;
967 case EMediaCdRom: aPrintBuf.Append(_L("EMediaCdRom")); break;
968 case EMediaRam: aPrintBuf.Append(_L("EMediaRam")); break;
969 case EMediaFlash: aPrintBuf.Append(_L("EMediaFlash")); break;
970 case EMediaRom: aPrintBuf.Append(_L("EMediaRom")); break;
971 case EMediaRemote: aPrintBuf.Append(_L("EMediaRemote")); break;
972 case EMediaNANDFlash: aPrintBuf.Append(_L("EMediaNANDFlash")); break;
973 case EMediaRotatingMedia: aPrintBuf.Append(_L("EMediaRotatingMedia"));break;
975 default: aPrintBuf.Append(_L("??? Unknown Type")); break;
979 aPrintBuf.Append(_L("\n"));
982 //--------------------------------------------------------
985 Format DriveAtt description.
987 @param aDrvInfo drive info structure
988 @param aPrintBuf buffer where the information will be printed to.
990 void FormatDriveAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
992 aPrintBuf.Format(_L("DriveAtt:0x%x "),aDrvInfo.iDriveAtt);
994 if(aDrvInfo.iDriveAtt & KDriveAttLocal) aPrintBuf.Append(_L("KDriveAttLocal,"));
995 if(aDrvInfo.iDriveAtt & KDriveAttRom) aPrintBuf.Append(_L("KDriveAttRom,"));
996 if(aDrvInfo.iDriveAtt & KDriveAttRedirected) aPrintBuf.Append(_L("KDriveAttRedirected,"));
997 if(aDrvInfo.iDriveAtt & KDriveAttSubsted) aPrintBuf.Append(_L("KDriveAttSubsted,"));
998 if(aDrvInfo.iDriveAtt & KDriveAttInternal) aPrintBuf.Append(_L("KDriveAttInternal,"));
999 if(aDrvInfo.iDriveAtt & KDriveAttRemovable) aPrintBuf.Append(_L("KDriveAttRemovable"));
1001 if(aDrvInfo.iDriveAtt & KDriveAttRemote) aPrintBuf.Append(_L("KDriveAttRemote"));
1002 if(aDrvInfo.iDriveAtt & KDriveAttTransaction) aPrintBuf.Append(_L("KDriveAttTransaction"));
1004 if(aDrvInfo.iDriveAtt & KDriveAttPageable) aPrintBuf.Append(_L("KDriveAttPageable"));
1005 if(aDrvInfo.iDriveAtt & KDriveAttLogicallyRemovable) aPrintBuf.Append(_L("KDriveAttLogicallyRemovable"));
1006 if(aDrvInfo.iDriveAtt & KDriveAttHidden) aPrintBuf.Append(_L("KDriveAttHidden"));
1008 aPrintBuf.Append(_L("\n"));
1011 //--------------------------------------------------------
1014 Format MediaAtt description.
1016 @param aDrvInfo drive info structure
1017 @param aPrintBuf buffer where the information will be printed to.
1019 void FormatMediaAttInfo(const TDriveInfo& aDrvInfo, TDes& aPrintBuf)
1021 aPrintBuf.Format(_L("MediaAtt:0x%x "),aDrvInfo.iMediaAtt);
1023 if(aDrvInfo.iMediaAtt & KMediaAttVariableSize) aPrintBuf.Append(_L("KMediaAttVariableSize,"));
1024 if(aDrvInfo.iMediaAtt & KMediaAttDualDensity) aPrintBuf.Append(_L("KMediaAttDualDensity,"));
1025 if(aDrvInfo.iMediaAtt & KMediaAttFormattable) aPrintBuf.Append(_L("KMediaAttFormattable,"));
1026 if(aDrvInfo.iMediaAtt & KMediaAttWriteProtected) aPrintBuf.Append(_L("KMediaAttWriteProtected,"));
1027 if(aDrvInfo.iMediaAtt & KMediaAttLockable) aPrintBuf.Append(_L("KMediaAttLockable,"));
1028 if(aDrvInfo.iMediaAtt & KMediaAttLocked) aPrintBuf.Append(_L("KMediaAttLocked"));
1030 if(aDrvInfo.iMediaAtt & KMediaAttHasPassword) aPrintBuf.Append(_L("KMediaAttHasPassword"));
1031 if(aDrvInfo.iMediaAtt & KMediaAttReadWhileWrite) aPrintBuf.Append(_L("KMediaAttReadWhileWrite"));
1032 if(aDrvInfo.iMediaAtt & KMediaAttDeleteNotify) aPrintBuf.Append(_L("KMediaAttDeleteNotify"));
1033 if(aDrvInfo.iMediaAtt & KMediaAttPageable) aPrintBuf.Append(_L("KMediaAttPageable"));
1036 aPrintBuf.Append(_L("\n"));
1039 //--------------------------------------------------------
1042 Format TVolumeInfo description.
1044 @param volInfo volume information
1045 @param aPrintBuf buffer where the information will be printed to.
1047 void FormatVolInfo(const TVolumeInfo& volInfo , TDes& aPrintBuf)
1049 aPrintBuf.Format(_L("VolSz:%ld Free:%ld\n"),volInfo.iSize, volInfo.iFree);
1050 aPrintBuf.AppendFormat(_L("VolId:0x%x VolName:%S\n"),volInfo.iUniqueID, &volInfo.iName);
1053 //--------------------------------------------------------
1055 /** Bit flags that specify which information will be printed by PrintDrvInfo() */
1056 enum TPrintDrvInfoFlags
1058 EFSInfo = 0x01, //-- file system information
1059 EFSInfoEx = 0x02, //-- extended file system information
1060 EMediaTypeInfo = 0x04, //-- media type
1061 EMediaAttInfo = 0x08, //-- media attributes etc.
1062 EDrvAttInfo = 0x10, //-- drive attributes etc
1063 EVolInfo = 0x20, //-- volume information
1068 //-----------------------------------------------------------------------------------------------------------------------
1070 Prints information about specified drive.
1072 @param aFs file system object
1073 @param aDrvNum drive number
1074 @param apConsole pointer to the console to print information into
1075 @param aFlags specifies which information to print out, @see TPrintDrvInfoFlags
1077 @return standard error code
1079 TInt PrintDrvInfo(RFs& aFs, TInt aDrvNum, CConsoleBase* apConsole, TUint aFlags = EAll)
1082 TDriveInfo driveInfo;
1083 TVolumeInfo volInfo;
1087 nRes = aFs.Drive(driveInfo, aDrvNum);
1088 if(nRes != KErrNone)
1090 CShell::TheConsole->Printf(_L("Error: %d\n"), nRes);
1091 return nRes; //-- can't get information about the drive
1095 nRes = aFs.Volume(volInfo, aDrvNum);
1096 const TBool bVolumeOK = (nRes == KErrNone);
1098 {//-- can't get information about the volume. It might be just corrupt/unformatted
1099 CShell::TheConsole->Printf(_L("Error getting volume info. code: %d\n"), nRes);
1100 if(nRes == KErrCorrupt)
1102 CShell::TheConsole->Printf(_L("The volume might be corrupted or not formatted.\n"));
1107 //-- Print out information about file system installed
1108 if(aFlags & EFSInfo)
1111 apConsole->Printf(_L("\nDrive %c: number:%d\n"), 'A'+aDrvNum, aDrvNum);
1113 //-- print the FS name
1114 if(aFs.FileSystemName(Buf, aDrvNum) == KErrNone)
1118 nRes = aFs.FileSystemSubType(aDrvNum, fsName);
1119 if(nRes == KErrNone && Buf.CompareF(fsName) !=KErrNone)
1121 Buf.AppendFormat(_L(" (%S)"), &fsName);
1124 //-- try to find out primary extension name if present
1125 nRes = aFs.ExtensionName(fsName, aDrvNum, 0);
1126 if(nRes == KErrNone)
1128 Buf.AppendFormat(_L(" PExt:%S"), &fsName);
1132 apConsole->Printf(_L("Mounted FS:%S\n"), &Buf);
1134 //-- print out the list of supported file systems if there are more than 1
1135 nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, 0+1); //-- try to get 2nd child name
1136 if(nRes == KErrNone)
1138 Buf.Copy(_L("Supported FS: "));
1141 nRes = aFs.SupportedFileSystemName(fsName, aDrvNum, i);
1142 if(nRes != KErrNone)
1145 Buf.AppendFormat(_L("%S, "), &fsName);
1148 Buf.Append(_L("\n"));
1149 apConsole->Printf(Buf);
1154 //-- print out FileSystem volume finalisation info
1155 if(bVolumeOK && (aFlags & EFSInfoEx))
1158 TPckgBuf<TBool> boolPckg;
1159 nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveFinalised, boolPckg);
1160 if(nRes == KErrNone)
1163 apConsole->Printf(_L("Volume Finalised\n"));
1165 apConsole->Printf(_L("Volume Not finalised\n"));
1169 }//if(aFlags & EFSInfo)
1171 //-- print media attributes
1172 if(aFlags & EMediaTypeInfo)
1174 FormatDrvMediaTypeInfo(driveInfo, Buf);
1175 apConsole->Printf(Buf);
1179 //-- print drive attributes
1180 if(aFlags & EDrvAttInfo)
1182 FormatDriveAttInfo(driveInfo, Buf);
1183 apConsole->Printf(Buf);
1186 //-- print media attributes
1187 if(aFlags & EMediaAttInfo)
1189 FormatMediaAttInfo(driveInfo, Buf);
1190 apConsole->Printf(Buf);
1194 //-- print volume information
1195 if(bVolumeOK && (aFlags & EVolInfo))
1197 FormatVolInfo(volInfo, Buf);
1198 apConsole->Printf(Buf);
1204 //-----------------------------------------------------------------------------------------------------------------------
1207 Extracts drive specifier from the given string that shall look like 'd:\' or 'd:'
1208 And converts it to the drive number.
1210 @param aStr a string with drive specifier
1211 @return Drive number EDriveA..EDriveZ if drive letter is correct
1212 negative value (KErrArgument) if drive specifier is incorrect
1214 TInt DoExtractDriveLetter(const TDesC& aStr)
1220 token.Set(lex.NextToken());
1222 if(token.Length() < 2 || token.Length() > 3 || token[1] != ':')
1223 return KErrArgument;
1225 if(token.Length() == 3 && token[2] != '\\')
1226 return KErrArgument;
1228 const TChar chDrv = token[0];
1229 const TInt drvNum = chDrv.GetUpperCase() - (TUint)'A'; //-- drive number
1231 if(drvNum < 0 || drvNum > EDriveZ)
1232 return KErrArgument;
1235 //-- ensure that the only drive token specified
1236 token.Set(lex.NextToken());
1238 return KErrArgument;
1245 //-----------------------------------------------------------------------------------------------------------------------
1247 // Print information about specified drive or about all present drives in the system.
1249 // DRVINFO [DriveLetter:[\]] [/p]
1251 // if drive letter is specified print out information about only this one.
1252 // /P : pause after each drive
1254 TInt ShellFunction::DrvInfo(TDes& aArgs, TUint aSwitches)
1259 const TInt KCmdLineLen = aArgs.Length();
1260 if(KCmdLineLen == 0)
1261 {//-- print information about all drives in the system
1265 {//-- print info about specified drive
1266 nDrv = DoExtractDriveLetter(aArgs);
1269 CShell::TheConsole->Printf(_L("Invalid drive specifier!\n"));
1275 TDriveList driveList;
1277 //-- get drives list
1278 nRes=TheShell->TheFs.DriveList(driveList);
1279 if(nRes != KErrNone)
1281 CShell::TheConsole->Printf(_L("\nError: %d"), nRes);
1286 {//-- the drive is specified
1287 if(!driveList[nDrv])
1289 CShell::TheConsole->Printf(_L("Invalid drive specification\n"));
1293 PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
1296 {//-- print information about all drives in the system
1297 for (nDrv=0; nDrv < KMaxDrives; nDrv++)
1299 if(!driveList[nDrv])
1300 continue; //-- skip unexisting drive
1302 PrintDrvInfo(TheShell->TheFs, nDrv, CShell::TheConsole);
1304 if(aSwitches & TShellCommand::EPSwitch)
1305 {//-- /p switch, pause after each drive
1306 CShell::TheConsole->Printf(_L("\n--- press any key to continue or Esc to exit ---\n"));
1308 TKeyCode key = CShell::TheConsole->Getch();
1309 if (key==EKeyEscape)
1314 CShell::TheConsole->Printf(_L("\n----------\n"));
1322 //-----------------------------------------------------------------------------------------------------------------------
1325 Just a helper method. Looks for a given pattern in the given string and returns the rest of the found token.
1326 @param aSrc source string
1327 @param aPattern pattern to look for
1328 @param aToken if the aPattern is found in the string, will contain characters from the pattern end to the next space.
1330 @return EFalse if the aPattern wasn't found in aSrc
1331 ETrue otherwise and the rest of the token in aToken
1333 static TBool DoFindToken(const TDesC& aSrc, const TDesC& aPattern, TPtrC& aToken)
1341 token.Set(lex.NextToken());
1343 if(token.Length() == 0)
1346 if(token.FindF(aPattern) == 0)
1347 {//-- found a requires patern, extract substring next to it
1348 aToken.Set(token.Right(token.Length() - aPattern.Length()));
1362 //-----------------------------------------------------------------------------------------------------------------------
1363 TInt DoDismountFS(RFs& aFs, TInt aDrvNum)
1368 nRes = aFs.FileSystemName(fsName, aDrvNum);
1370 if(nRes != KErrNone)
1371 return KErrNotFound;//-- nothing to dismount
1373 nRes = aFs.DismountFileSystem(fsName, aDrvNum);
1374 if(nRes != KErrNone)
1376 CShell::TheConsole->Printf(_L("Can't dismount FS!\n"));
1381 CShell::TheConsole->Printf(_L("'%S' filesystem dismounted from drive %c:\n"), &fsName, 'A'+aDrvNum);
1386 //-----------------------------------------------------------------------------------------------------------------------
1387 TInt DoRemountFS(RFs& aFs, TInt aDrvNum)
1393 //-- 1. get file system name
1394 nRes = aFs.FileSystemName(fsName, aDrvNum);
1395 if(nRes != KErrNone)
1396 return KErrNotFound;
1398 //-- 2. find out if the drive sync/async
1399 TPckgBuf<TBool> drvSyncBuf;
1400 TBool& drvSynch = drvSyncBuf();
1402 nRes = aFs.QueryVolumeInfoExt(aDrvNum, EIsDriveSync, drvSyncBuf);
1403 if(nRes != KErrNone)
1404 {//-- pretend that the drive is asynch. in the case of file system being corrupted. this is 99.9% true
1408 //-- 3. find out primary extension name if it is present; we will need to add it again when mounting the FS
1409 //-- other extensions (non-primary) are not supported yet
1410 nRes = aFs.ExtensionName(pextName, aDrvNum, 0);
1411 if(nRes != KErrNone)
1413 pextName.SetLength(0);
1416 //-- 3.1 check if the drive has non-primary extensions, fail in this case
1419 nRes = aFs.ExtensionName(extName, aDrvNum, 1);
1420 if(nRes == KErrNone)
1422 CShell::TheConsole->Printf(_L("Non-primary extensions are not supported!\n"));
1423 return KErrNotSupported;
1427 //-- 4. dismount the file system
1428 nRes = DoDismountFS(aFs, aDrvNum);
1429 if(nRes != KErrNone)
1432 //-- 5. mount the FS back
1433 if(pextName.Length() > 0)
1434 {//-- we need to mount FS with the primary extension
1435 nRes = aFs.AddExtension(pextName);
1436 if(nRes != KErrNone && nRes != KErrAlreadyExists)
1441 nRes = aFs.MountFileSystem(fsName, pextName, aDrvNum, drvSynch);
1444 {//-- the FS did not have primary extension
1445 nRes = aFs.MountFileSystem(fsName, aDrvNum, drvSynch);
1448 if(nRes == KErrNone)
1450 CShell::TheConsole->Printf(_L("mounted filesystem:%S\n"), &fsName);
1456 //-----------------------------------------------------------------------------------------------------------------------
1458 Mount or dismount the file system on the specified drive.
1460 MOUNT <DriveLetter:[\]> <FSY:xxx> <FS:yyy> [PEXT:zzz] [/S] [/U]
1462 xxx is the *.fsy file system plugin name, like "elocal.fsy" or "elocal"
1463 yyy is the file system name that the fsy module exports, like "FAT"
1464 zzz is the optional parameter that specifies primary extension name
1466 /u dismounts a filesystem on the specified drive; e.g. "mount d: /u"
1467 /s for mounting FS specifies that the drive will be mounted as synchronous one.
1468 /f for forcing mounting the FS; the previous one will be automatically dismounted
1469 /r remount existing FS (dismount and mount it back)
1471 TInt ShellFunction::MountFileSystem(TDes& aArgs, TUint aSwitches)
1473 ShellFunction::StripQuotes(aArgs);
1479 RFs& fs = TheShell->TheFs;
1482 //-- extract drive specification; this must be 1st token
1483 _LIT(KErrInvalidDrive, "Invalid drive specifier\n");
1485 TPtrC token = lex.NextToken();
1487 nRes = DoExtractDriveLetter(token);
1490 CShell::TheConsole->Printf(KErrInvalidDrive);
1491 return KErrArgument;
1494 const TInt drvNum = nRes; //-- this is the drive number;
1497 //-- remounting the existing FS (/R switch)
1498 if(aSwitches & TShellCommand::ERSwitch)
1500 nRes = DoRemountFS(fs, drvNum);
1504 //-- check if we dismounting the FS (/U switch)
1505 if(aSwitches & TShellCommand::EUSwitch)
1507 nRes = DoDismountFS(fs, drvNum);
1509 if(nRes == KErrNotFound)
1510 {//-- nothing to dismount
1511 CShell::TheConsole->Printf(_L("specified drive doesn't have FS mounted\n"));
1518 //-- check if we need to forcedly dismount the existing FS (/F switch)
1519 if(aSwitches & TShellCommand::EFSwitch)
1521 nRes = DoDismountFS(fs, drvNum);
1523 if(nRes != KErrNotFound && nRes !=KErrNone)
1527 //-- request to mount the filesystem
1529 //-- 1. check that the specified drive doesn't have already mounted file system
1530 nRes = fs.FileSystemName(fsName, drvNum);
1531 if(nRes == KErrNone)
1533 CShell::TheConsole->Printf(_L("specified drive already has '%S' file system mounted.\n"), &fsName);
1534 CShell::TheConsole->Printf(_L("Dismount it first using '/U' switch or use '/F' switch.\n"));
1538 //-- 2. check '/S' switch that specifies synchronous drive
1539 const TBool bDrvSynch = aSwitches & TShellCommand::ESSwitch;
1541 //-- 3. extract FSY name, file system name and optional primary extension name from the command line parameters
1542 _LIT(KFSY_Param, "fsy:");
1543 _LIT(KFsName_Param, "fs:");
1544 _LIT(KPrimExt_Param, "pext:");
1550 if(!DoFindToken(aArgs, KFSY_Param, ptrFSYName))
1551 {//-- FSY plugin name, like "elocal.fsy"
1552 CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFSY_Param);
1556 if(!DoFindToken(aArgs, KFsName_Param, ptrFSName))
1557 {//-- file system name, like "FAT"
1558 CShell::TheConsole->Printf(_L("'%S' parameter is required!\n"), &KFsName_Param);
1562 //-- note: it is possible to find out the file system name from loaded .fsy plugin.
1563 //-- but it will require some coding. Probably later.
1566 //-- optional primary extension name, like "something.fxt"
1567 const TBool bPExtPresent = DoFindToken(aArgs, KPrimExt_Param, ptrPExtName);
1570 //-- add new file system + optional extension
1571 nRes = fs.AddFileSystem(ptrFSYName);
1572 if(nRes != KErrNone && nRes != KErrAlreadyExists)
1574 CShell::TheConsole->Printf(_L("Can't load '%S' file system plugin!\n"), &ptrFSYName);
1580 nRes = fs.AddExtension(ptrPExtName);
1581 if(nRes != KErrNone && nRes != KErrAlreadyExists)
1583 CShell::TheConsole->Printf(_L("Can't load '%S' FS extension plugin!\n"), &ptrPExtName);
1588 //-- 4. mount new file system + optional primary extension
1591 nRes = fs.MountFileSystem(ptrFSName, ptrPExtName, drvNum, bDrvSynch);
1595 nRes = fs.MountFileSystem(ptrFSName, drvNum, bDrvSynch);
1598 CShell::TheConsole->Printf(_L("Mounting new file system...\n"));
1600 if(nRes != KErrNone && nRes != KErrCorrupt)
1601 {//-- KErrCorrupt might mean that the FS mounted OK onto the drive, but ve volume itself needs formatting
1602 CShell::TheConsole->Printf(_L("Error mounting the filesystem! (%d)\n"), nRes);
1607 PrintDrvInfo(fs, drvNum, CShell::TheConsole, EFSInfo | EVolInfo);
1613 //-----------------------------------------------------------------------------------------------------------------------
1616 Format the specified disk
1618 FORMAT DriveLetter:[\] [fat12|fat16|fat32] [spc:X] [rs:Y] [ft:Z] [/Q] [/S] [/E]
1620 fat12|fat16|fat32 : specifies explicitly FAT type to format drive with (if it is a FAT drive)
1621 spc:X "X" specifies FAT sectors per cluster, e.g. spc:16
1622 rs:Y "Y" specifies the number of reserved sectors (FAT FS only)
1623 ft:Z "Z" specifies the number of FAT tables 1 or 2 (FAT FS only)
1626 /E : Remove Password and Format
1627 /F : force formatting, even if there are files opened on the drive
1630 TInt ShellFunction::Format(TDes& aPath, TUint aSwitches)
1632 _LIT(KFormatStars,"********************");
1634 using namespace FileSystem_FAT;
1636 ShellFunction::StripQuotes(aPath);
1639 TUint fmtMode = ESpecialFormat;
1641 //-- Format /Q - quick format
1642 if (aSwitches & TShellCommand::EQSwitch)
1643 fmtMode|=EQuickFormat;
1645 //-- Format /S - special format
1646 if (aSwitches & TShellCommand::ESSwitch)
1647 fmtMode|=ESpecialFormat;
1649 //-- Format /E - force erase
1650 if (aSwitches & TShellCommand::EESwitch)
1651 fmtMode|=EForceErase;
1653 //-- Format /F - force format. The volume will be formatted even if there are files or directories opened on this drive
1654 if (aSwitches & TShellCommand::EFSwitch)
1655 fmtMode|=EForceFormat;
1663 //-- 1st token - drive path; it shall look like "d:"
1665 TPtrC ptrPath = lex.NextToken();
1667 const TInt nDrv = DoExtractDriveLetter(ptrPath);
1670 CShell::TheConsole->Printf(_L("type \"format /?\" for help.\n"));
1676 EFsNameNotSpecified,
1682 TFmtState formattingState = EFsNameNotSpecified;
1683 TName fsName; //-- file system name
1686 TVolFormatParamBuf volFmtParamBuf;
1687 TVolFormatParam& volFmtParam = volFmtParamBuf();
1691 //-- 2nd token - file system name.
1692 //-- FAT fs is a special case, because it has subtypes; FAT FS name can be: FAT, FAT12, FAT16, FAT32
1693 //-- everything else is considered as another file system name
1695 TPtrC ptrFsName = lex.NextToken();
1696 TFatSubType fatSubType = ENotSpecified;
1698 if(ptrFsName.Length() > 0)
1699 {//-- there is a 2nd token, though it is not guaranteed to be the FS name
1700 formattingState = EFormattingOtherFS;
1702 if(ptrFsName.FindF(KFileSystemName_FAT) == 0)
1703 {//-- it looks like "FATxx"
1704 fsName.Copy(KFileSystemName_FAT);
1706 if(ptrFsName.CompareF(KFileSystemName_FAT) == 0)
1707 fatSubType = ENotSpecified; //-- generic "FAT", no subtype
1708 else if(ptrFsName.CompareF(KFSSubType_FAT12) == 0)
1709 fatSubType = EFat12;
1710 else if(ptrFsName.CompareF(KFSSubType_FAT16) == 0)
1711 fatSubType = EFat16;
1712 else if(ptrFsName.CompareF(KFSSubType_FAT32) == 0)
1713 fatSubType = EFat32;
1715 fsName.Copy(ptrFsName); //-- none of the FAT types, probably some weird FS name.
1719 fsName.Copy(ptrFsName);
1723 if(fsName == KFileSystemName_FAT)
1724 formattingState = EFormattingFAT;
1728 if(formattingState != EFsNameNotSpecified)
1729 volFmtParam.SetFileSystemName(fsName);
1731 //-- process formatting parameters if they are present
1733 _LIT(KTok_SPC, "spc:"); //-- "sectors per cluster"; valid for: FAT, exFAT
1734 _LIT(KTok_RsvdSect, "rs:"); //-- "reserved sectors" ; valid for: FAT
1735 _LIT(KTok_NumFATs, "ft:"); //-- "number of FATs" ; valid for: FAT, exFAT
1736 _LIT(KFsNameExFat, "exfat");
1739 TPtrC ptrParams = lex.Remainder();
1744 //-- if we formatting FAT, process FAT-specific formatting parameters
1745 if(formattingState == EFormattingFAT)
1747 //-- Changing base class via derived class interface is OK here, all derived classes has the same layout and size as TVolFormatParam
1748 TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
1750 volFmtParamFAT.Init();
1753 if(fatSubType != ENotSpecified)
1754 volFmtParamFAT.SetFatSubType(fatSubType);
1756 //-- process "Sectors per cluster" token
1757 if(DoFindToken(ptrParams, KTok_SPC, token))
1759 lexParam.Assign(token);
1760 lexParam.SkipSpace();
1761 nRes = lexParam.Val(nVal);
1762 if(nRes == KErrNone)
1764 volFmtParamFAT.SetSectPerCluster(nVal);
1768 CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
1773 //-- process "reserved sectors" token
1774 if(DoFindToken(ptrParams, KTok_RsvdSect, token))
1776 lexParam.Assign(token);
1777 lexParam.SkipSpace();
1778 nRes = lexParam.Val(nVal);
1779 if(nRes == KErrNone && nVal >0 )
1781 volFmtParamFAT.SetReservedSectors(nVal);
1785 CShell::TheConsole->Printf(_L("Invalid Reserved Sectors value!\n"));
1790 //-- process "FAT tables" token
1791 if(DoFindToken(ptrParams, KTok_NumFATs, token))
1793 lexParam.Assign(token);
1794 lexParam.SkipSpace();
1795 nRes = lexParam.Val(nVal);
1796 if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
1798 volFmtParamFAT.SetNumFATs(nVal);
1802 CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
1807 }//if(formattingState == EFormattingFAT)
1808 else if(formattingState == EFormattingOtherFS && fsName.CompareF(KFsNameExFat)==0)
1809 {//-- this is actually a h***k. exFAT exported public header file with specific data structures might not be available at all.
1811 //-- this is more serious hack. The parameters layout (SPC & NumFatTables) in the structure is the same for FAT and exFAT
1812 //-- use TVolFormatParam_FAT because this code doesn't know about TVolFormatParam_exFAT
1813 TVolFormatParam_FAT& volFmtParamFAT = (TVolFormatParam_FAT&)volFmtParam;
1815 //-- process "Sectors per cluster" token
1816 if(DoFindToken(ptrParams, KTok_SPC, token))
1818 lexParam.Assign(token);
1819 lexParam.SkipSpace();
1820 nRes = lexParam.Val(nVal);
1821 if(nRes == KErrNone)
1823 volFmtParamFAT.SetSectPerCluster(nVal);
1827 CShell::TheConsole->Printf(_L("Invalid SectorsPerCluster value!\n"));
1832 //-- process "FAT tables" token
1833 if(DoFindToken(ptrParams, KTok_NumFATs, token))
1835 lexParam.Assign(token);
1836 lexParam.SkipSpace();
1837 nRes = lexParam.Val(nVal);
1838 if(nRes == KErrNone && nVal >= 1 && nVal <= 2)
1840 volFmtParamFAT.SetNumFATs(nVal);
1844 CShell::TheConsole->Printf(_L("Invalid FAT tables number value!\n"));
1852 //-------- actual formatting
1853 if(formattingState == EFsNameNotSpecified)
1855 nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt);
1859 CShell::TheConsole->Printf(_L("The new file system is:%S\n"), &fsName);
1860 nRes = format.Open(TheShell->TheFs, ptrPath, fmtMode, fmtCnt, volFmtParamBuf);
1863 if(nRes == KErrNone)
1865 while(fmtCnt && nRes == KErrNone)
1867 TInt length=(104-fmtCnt)/5;
1868 length=Min(length,KFormatStars().Length());
1869 TPtrC stars=KFormatStars().Left(length);
1870 CShell::TheConsole->Printf(_L("\r%S"),&stars);
1871 nRes=format.Next(fmtCnt);
1876 if(nRes == KErrNone)
1878 CShell::TheConsole->Printf(_L("\r%S"),&KFormatStars);
1885 //-- format errors processing
1886 if(nRes != KErrNone)
1888 CShell::TheConsole->Printf(_L("Format failed.\n"));
1894 CShell::TheConsole->Printf(_L("Format complete.\n"));
1898 case KErrArgument: //-- FORMAT has rejected specified parameters
1899 CShell::TheConsole->Printf(_L("Possible reason: Invalid combination of formatting parameters.\n"));
1903 case KErrNotSupported: //-- trying to format SD card with parameters or not supported FS name specified
1904 CShell::TheConsole->Printf(_L("Possible reasons: media does not support special formatting or specified file system is not supported\n"));
1908 case KErrNotFound: //-- possible reason: unrecognisable media and automounter FS + formatting without specifying the FS name
1909 CShell::TheConsole->Printf(_L("Possible reason: Unable to chose appropriate file system (not specified)\n"));
1922 //-----------------------------------------------------------------------------------------------------------------------
1924 TInt ShellFunction::Hexdump(TDes& aPath,TUint aSwitches)
1926 ShellFunction::StripQuotes(aPath);
1930 TInt r=file.Open(TheShell->TheFs,aPath,EFileStream);
1937 const TInt KLineLength = 16;
1939 TBuf8<KLineLength> line;
1941 if (r != KErrNone || line.Length() == 0)
1944 TBuf<KLineLength*3+2> hexaRep;
1945 TBuf<KLineLength> asciiRep;
1946 for (TInt i=0; i<KLineLength; i++)
1948 if (i == KLineLength/2)
1950 hexaRep.Append(' ');
1951 hexaRep.Append(i<line.Length() ? '|' : ' ');
1954 hexaRep.Append(' ');
1956 if (i<line.Length())
1958 hexaRep.AppendNumFixedWidth(line[i], EHex, 2);
1959 asciiRep.Append(TChar(line[i]).IsPrint() ? line[i] : '.');
1962 hexaRep.AppendFill(' ', 2);
1965 _LIT(KPrompt , " Hit escape to quit hexdump or any other key to continue\n");
1966 _LIT(KLineFmt, " %+07x0:%S %S\n");
1967 TKeyCode key=CShell::OutputStringToConsole(KPrompt ,(aSwitches&TShellCommand::EPSwitch)!=0,KLineFmt, offset++,&hexaRep, &asciiRep);
1969 if (key==EKeyEscape)
1981 Create a file. The file can be empty or filled with random data.
1982 The maximal file size depends on the file system of the drive.
1984 Gobble <file name> <aaaa|0xbbbb> [/E]
1986 aaaa file size decimal
1987 bbbb file size hexadecimal, shall be prefixed with '0x'
1989 /e for creating an empty file, do not fill it with data
1991 TInt ShellFunction::Gobble(TDes& aPath,TUint aSwitches)
1993 ShellFunction::StripQuotes(aPath);
1995 TInt fileNameLen=aPath.LocateReverse(' ');
1996 if (fileNameLen==KErrNotFound) // No spaces implies no filelength specified
1998 CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
2002 TInt fileLength=(aPath.Length()-fileNameLen);
2004 return (KErrTooBig); // Too many digits - too large!
2005 TBuf<16> rightString=aPath.Right(fileLength);
2006 aPath.SetLength(fileNameLen);
2008 TLex size(rightString);
2010 TRadix radix=ParseHexaPrefixIfAny(size);
2013 TInt r=size.Val(fileSize,radix);
2014 if (r!=KErrNone || ! size.Eos())
2016 CShell::TheConsole->Printf(_L("Please specify a file length\n"));
2020 if (aPath.Length()==0)
2021 aPath=_L("GOBBLE.DAT");
2024 GetFullPath(aPath,fileName);
2027 const TInt KBufSize=65536; //-- buffer size for writing data
2028 const TUint32 K1Megabyte = 1<<20; //-- 1M, 1048576
2029 TInt64 cntBytes = 0;
2030 TUint32 cntMegaBytes =0;
2032 //-- allocate buffer for data
2034 r = buf.CreateMax(KBufSize);
2038 //-- initialize buffer with random rubbish
2039 //Mem::Fill((void*)buf.Ptr(),KBufSize,0xa3);
2041 TInt64 rndSeed = Math::Random();
2042 for(TInt i=0; i<KBufSize; ++i)
2044 buf[i] = (TUint8)Math::Rand(rndSeed);
2049 TInt64 rem = fileSize;
2052 TTimeIntervalSeconds timeTaken;
2054 startTime.UniversalTime(); //-- take start time
2056 r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
2060 //-- this can make write faster on rugged fat.
2061 if(aSwitches&TShellCommand::EESwitch)
2062 {//-- /e switch is specified, create an empty file without writing data
2063 CShell::TheConsole->Printf(_L("Creating an empty file, size:%LD bytes\n"), fileSize);
2066 r=file.SetSize(fileSize);
2071 if(!(aSwitches&TShellCommand::EESwitch))
2072 {//-- fill created file with randomn data
2076 const TInt s=(TInt)Min((TInt64)KBufSize, rem);
2078 r=file.Write(buf, s);
2084 //-- print out number of megabytes written
2086 if(cntBytes > 0 && (cntBytes & (K1Megabyte-1))==0)
2089 CShell::TheConsole->Printf(_L("%u MB written.\n"),cntMegaBytes);
2096 endTime.UniversalTime(); //-- take end time
2099 endTime.SecondsFrom(startTime, timeTaken);
2101 CShell::TheConsole->Printf(_L("Total bytes written:%LD\n"), cntBytes);
2102 CShell::TheConsole->Printf(_L("Time taken:%d Sec.\n"), timeTaken.Int());
2110 if(r!= KErrAlreadyExists) //this is to ensure that an existing file does not get deleted
2111 CShell::TheFs.Delete(fileName.FullName());
2113 CShell::TheConsole->Printf(_L("Error - could not create file, code:%d\n"), r);
2118 TInt ShellFunction::Md(TDes& aPath,TUint /*aSwitches*/)
2120 if (aPath.Length()==0)
2121 return(KErrBadName);
2123 ShellFunction::StripQuotes(aPath);
2125 if (aPath[aPath.Length()-1]!=KPathDelimiter)
2126 aPath.Append(KPathDelimiter);
2129 TInt r = GetFullPath(aPath,dirPath);
2134 return(TheShell->TheFs.MkDir(dirPath.FullName()));
2137 TInt ShellFunction::Move(TDes& aPath,TUint aSwitches)
2140 // Modified to add more helpful error messages and allow spaced filenames
2141 ShellFunction::StripQuotes(aPath);
2143 TBuf<KShellMaxCommandLine> newName;
2144 TBuf<KShellMaxCommandLine> tempPath=aPath;
2148 TInt r=word.FindNextWord(aPath);
2149 // Check if the word returned is a valid filename. If not, scan the next
2150 // word too in case the filename contains spaces. If, at the end of the
2151 // the line, the filename is not recognised, it is invalid. If there are no
2152 // spaces the user has not used the correct format for this command.
2156 newName=aPath.Right(aPath.Length()-r);
2157 tempPath.SetLength(r);
2159 TInt result=GetFullPath(tempPath,oldName);
2160 if (result!=KErrNone)
2163 TBool validFileOrDir = EFalse;
2165 result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
2166 if (result==KErrNone) // A valid filename
2169 validFileOrDir = ETrue;
2171 else // Not a valid filename - move one word along the command line
2173 // Not a valid filename - Could be a directory...
2175 result=directory.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclusive|KEntryAttDir);
2176 if (result == KErrNone)
2179 validFileOrDir = ETrue;
2185 TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
2186 TUint switches=(recursive) ? CFileMan::EOverWrite|CFileMan::ERecurse : CFileMan::EOverWrite;
2187 r=CShell::TheFileMan->Move(oldName.FullName(),newName,switches);
2188 if (r==KErrAccessDenied)
2190 CShell::TheConsole->Printf(_L("Access denied - cannot move %S\n"),&tempPath);
2191 CShell::TheConsole->Printf(_L("To move %Sinto directory %S append \\ to the full destination\n"),&tempPath,&newName);
2197 r=word.FindNextWord(word.iRightString);
2199 if (r<0) // r = some error code
2200 return (r); // Error in filename or destination
2202 return (KErrNotFound);
2205 TInt GetChunkInfo(TAny* aPtr)
2209 TFullName* namePtr=(TFullName*)aPtr;
2210 findHb.Find(*namePtr);
2214 TInt r=c.Open(findHb);
2215 if(r==KErrPermissionDenied)
2217 CShell::TheConsole->Printf(_L("...Chunk is protected. No info available.\n"));
2221 CShell::TheConsole->Printf(_L("...Size %dk MaxSize %dk Base 0x%x\n"),c.Size()/1024,c.MaxSize()/1024,c.Base());
2225 #if defined (__WINS__)
2228 if (aFN.Match(_L("*ESHELL*"))<0)
2235 TInt GetThreadInfo(TAny* aPtr)
2236 // New function added by WR, November 1997
2239 TFindThread* findHb = (TFindThread*)aPtr;
2241 TInt err = t.Open(*findHb);
2242 if (err != KErrNone)
2244 detail.Format(_L("... can't open thread, err=%d\n"), err);
2245 CShell::TheConsole->Printf(detail);
2249 TExitType exit = t.ExitType();
2250 TBuf<KMaxExitCategoryName> exitCat=t.ExitCategory();
2251 TThreadId threadId = t.Id();
2252 TUint id = *(TUint*)&threadId;
2254 TInt pid = t.Process(proc);
2257 TProcessId procId = proc.Id();
2258 pid = *(TInt*)&procId;
2265 detail.Format(_L("... ID %d (Proc %d), running\n"), id, pid);
2269 detail.Format(_L("... ID %d (Proc %d), panic \"%S\" %d\n"), id, pid,
2270 &exitCat, t.ExitReason());
2273 detail.Format(_L("... ID %d (Proc %d), killed %d\n"), id, pid, t.ExitReason());
2275 case EExitTerminate:
2276 detail.Format(_L("... ID %d (Proc %d), terminated %d\n"), id, pid, t.ExitReason());
2279 detail.Format(_L("... ID %d (Proc %d), ?exit type %d?\n"), id, pid, exit);
2283 CShell::TheConsole->Printf(detail);
2286 // End of modification
2288 // Class for showing information about processes
2293 TInt DisplayMessage(const TFullName& aName);
2294 TInt DisplayCmdUnknown();
2295 TInt GetAll(const TDes& aName);
2296 TInt GetProcesses(const TDes& aName);
2297 TInt GetThreads(const TDes& aName);
2298 TInt GetChunks(const TDes& aName);
2299 TInt GetServers(const TDes& aName);
2300 // TInt GetSessions(const TDes& aName);
2301 TInt GetLibraries(const TDes& aName);
2302 // TInt GetLogicalChannels(const TDes& aName);
2303 TInt GetLogicalDevices(const TDes& aName);
2304 TInt GetPhysicalDevices(const TDes& aName);
2305 TInt GetSemaphores(const TDes& aName);
2306 TInt GetMutexes(const TDes& aName);
2308 void DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription);
2309 TInt Prepare(const TFullName& aName);
2310 TInt Prepare(const TFullName& aName,TCallBack& aCallBack);
2311 TInt Display(TFullName& aName);
2312 TFullName iPrevName;
2313 TCallBack iCallBack;
2317 TInt TShowProcInfo::DisplayHelp()
2320 DisplayHelpLine(_L("H or ?"),_L("Show Help"));
2321 DisplayHelpLine(_L("Q"),_L("Quit Process Status Mode"));
2322 DisplayHelpLine(_L("X<name>"),_L("Switch to a particular Process domain"));
2323 DisplayHelpLine(_L("X"),_L("Go Back to standard Process Status Mode"));
2324 DisplayHelpLine(_L("A"),_L("Display all container objects"));
2325 DisplayHelpLine(_L("P"),_L("List all Processes (irrespective of current domain)"));
2326 DisplayHelpLine(_L("T"),_L("List Threads"));
2327 DisplayHelpLine(_L("C"),_L("List Chunks, their sizes, maximum sizes and addresses"));
2328 DisplayHelpLine(_L("S"),_L("List Servers"));
2329 // DisplayHelpLine(_L("I"),_L("List Sessions"));
2330 DisplayHelpLine(_L("L"),_L("List Libraries"));
2331 // DisplayHelpLine(_L("G"),_L("List Logical Channels"));
2332 DisplayHelpLine(_L("V"),_L("List Logical Devices"));
2333 DisplayHelpLine(_L("D"),_L("List Physical Devices"));
2334 DisplayHelpLine(_L("E"),_L("List Semaphores"));
2335 DisplayHelpLine(_L("M"),_L("List Mutexes"));
2339 TInt TShowProcInfo::DisplayMessage(const TFullName& aMessage)
2341 CShell::OutputStringToConsole(ETrue,aMessage);
2346 TInt TShowProcInfo::DisplayCmdUnknown()
2348 CShell::OutputStringToConsole(ETrue,_L("Not supported\n"));
2352 TInt TShowProcInfo::GetAll(const TDes& aName)
2355 GetProcesses(aName);
2359 // GetSessions(aName);
2360 GetLibraries(aName);
2361 // GetLogicalChannels(aName);
2362 GetLogicalDevices(aName);
2363 GetPhysicalDevices(aName);
2364 GetSemaphores(aName);
2369 TInt TShowProcInfo::GetProcesses(const TDes& aName)
2372 TFindProcess findHb;
2375 Prepare(_L("PROCESSES"));
2376 while (findHb.Next(name)==KErrNone)
2383 TInt TShowProcInfo::GetThreads(const TDes& aName)
2389 TAny* findPtr=(TAny*)&findHb;
2391 // Modified by WR, November 1997
2392 TCallBack threadCallBack(GetThreadInfo,findPtr);
2393 Prepare(_L("THREADS"),threadCallBack);
2394 while (findHb.Next(name)==KErrNone)
2402 message.Format(_L("? No threads called %S"), &aName);
2403 DisplayMessage(message);
2406 // End of modification
2410 TInt TShowProcInfo::GetChunks(const TDes& aName)
2416 TAny* namePtr=(TAny*)&name;
2417 TCallBack chunkCallBack(GetChunkInfo,namePtr);
2418 Prepare(_L("CHUNKS & SIZES"),chunkCallBack);
2419 TInt totalChunkSize=0;
2420 TInt protectedChunks = 0;
2421 while (findHb.Next(name)==KErrNone)
2425 TInt r=c.Open(findHb);
2430 totalChunkSize+=c.Size()/1024;
2434 #if defined(__WINS__)
2437 if (name.Match(_L("*ESHELL*"))<0)
2442 CShell::OutputStringToConsole(ETrue,_L(" Total Chunk Size = %dk\n"),totalChunkSize);
2444 CShell::OutputStringToConsole(ETrue,_L(" %d Protected chunks not counted\n"),protectedChunks);
2448 TInt TShowProcInfo::GetServers(const TDes& aName)
2454 Prepare(_L("SERVERS"));
2455 while (findHb.Next(name)==KErrNone)
2462 /* TInt TShowProcInfo::GetSessions(const TDes& aName)
2465 TFindSession findHb;
2468 Prepare(_L("SESSIONS"));
2469 while (findHb.Next(name)==KErrNone)
2476 TInt TShowProcInfo::GetLibraries(const TDes& aName)
2479 TFindLibrary findHb;
2482 Prepare(_L("LIBRARIES"));
2483 while (findHb.Next(name)==KErrNone)
2490 TInt TShowProcInfo::GetLogicalChannels(const TDes& aName)
2493 TFindLogicalChannel findHb;
2496 Prepare(_L("LOGICAL CHANNELS"));
2497 while (findHb.Next(name)==KErrNone)
2505 TInt TShowProcInfo::GetLogicalDevices(const TDes& aName)
2508 TFindLogicalDevice findHb;
2511 Prepare(_L("LOGICAL DEVICES"));
2512 while (findHb.Next(name)==KErrNone)
2519 TInt TShowProcInfo::GetPhysicalDevices(const TDes& aName)
2522 TFindPhysicalDevice findHb;
2525 Prepare(_L("PHYSICAL DEVICES"));
2526 while (findHb.Next(name)==KErrNone)
2533 TInt TShowProcInfo::GetSemaphores(const TDes& aName)
2535 TFindSemaphore findHb;
2538 Prepare(_L("SEMAPHORES"));
2539 while (findHb.Next(name)==KErrNone)
2546 TInt TShowProcInfo::GetMutexes(const TDes& aName)
2552 Prepare(_L("MUTEXES"));
2553 while (findHb.Next(name)==KErrNone)
2560 void TShowProcInfo::DisplayHelpLine(const TDesC& aCommand, const TDesC& aDescription)
2562 CShell::OutputStringToConsole(ETrue,_L("%- *S%S\n"),8,&aCommand,&aDescription);
2566 TInt TShowProcInfo::Prepare(const TFullName& aName)
2570 CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
2575 TInt TShowProcInfo::Prepare(const TFullName& aName,TCallBack& aCallBack)
2579 CShell::OutputStringToConsole(ETrue,_L("--%S-->\n"),&aName);
2581 iCallBack=aCallBack;
2585 TInt TShowProcInfo::Display(TFullName& aName)
2587 // Modifications by WR, November 1997
2590 TFullName prevName=iPrevName;
2593 TInt posA=aName.Match(_L("*::*"));
2596 TInt posI=prevName.Match(_L("*::*"));
2597 while ((posI>=0) && (posA>=0))
2599 TFullName tempAName=(aName.Left(posA));
2600 TFullName tempIName=(prevName.Left(posI));
2601 if (tempAName.Compare(tempIName)==0)
2604 aName.Delete(0,posA+2);
2605 prevName.Delete(0,posI+2);
2606 posA=aName.Match(_L("*::*"));
2607 posI=prevName.Match(_L("*::*"));
2614 TPtrC16 temp_desc=aName.Left(posA);
2615 CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+temp_desc.Left(posA).Length(),&temp_desc);
2617 aName.Delete(0,posA+2);
2618 posA=aName.Match(_L("*::*"));
2621 CShell::OutputStringToConsole(ETrue,_L("%+ *S\n"),toTab+aName.Length(),&(aName));
2627 CShell::TheConsole->SetCursorPosRel(TPoint(toTab,0));
2628 iCallBack.CallBack();
2632 // End of modification
2633 TInt ShellFunction::Ps(TDes& /* aPath */,TUint /* aSwitches */)
2635 // satisfy information requests about container objects
2639 TShowProcInfo showProcInfo;
2641 TBuf<0x1> asterisk=_L("*");
2642 TName processPrefix=asterisk;
2644 TBool processSelected=EFalse;
2645 TBuf<0x16> prompt=_L("ps>");
2646 r=showProcInfo.GetProcesses(processPrefix);
2650 CShell::TheEditor->Edit(prompt, &command, ETrue);
2651 while (command.Length() && !abort && r==KErrNone)
2654 while ((pos=command.Locate(' '))>=0)
2655 command.Delete(pos,1);
2656 if (!command.Length())
2658 command.UpperCase();
2659 if (command.CompareF(_L("EXIT"))==0)
2665 command.Delete(0,1);
2674 showProcInfo.DisplayHelp();
2680 TBuf<0x11> chosenP=command;
2681 if (chosenP.Length()<1)
2683 if (processSelected)
2685 r=showProcInfo.DisplayMessage(_L(" -> back to standard Process Status mode"));
2686 processPrefix=asterisk;
2688 processSelected=EFalse;
2694 chosenP.Append(asterisk);
2696 findP.Find(chosenP);
2698 if (findP.Next(findName)!=KErrNone)
2700 r=showProcInfo.DisplayMessage(_L("command prefixes no processes"));
2701 //r=showProcInfo.GetProcesses(asterisk);
2705 if (findP.Next(findName)==KErrNone)
2707 r=showProcInfo.DisplayMessage(_L("command prefixes more than one process"));
2708 r=showProcInfo.GetProcesses(chosenP);
2712 processSelected=ETrue;
2713 processPrefix=chosenP;
2714 prompt=processPrefix;
2715 prompt.Append(_L(">"));
2722 r=showProcInfo.GetAll(processPrefix);
2727 r=showProcInfo.GetProcesses(asterisk);
2730 r=showProcInfo.GetThreads(processPrefix);
2733 r=showProcInfo.GetChunks(processPrefix);
2736 r=showProcInfo.GetServers(processPrefix);
2739 r=showProcInfo.GetSessions(processPrefix);
2742 r=showProcInfo.GetLibraries(processPrefix);
2745 // r=showProcInfo.GetLogicalChannels(processPrefix);
2748 r=showProcInfo.GetLogicalDevices(processPrefix);
2751 r=showProcInfo.GetPhysicalDevices(processPrefix);
2754 r=showProcInfo.GetSemaphores(processPrefix);
2757 r=showProcInfo.GetMutexes(processPrefix);
2761 showProcInfo.DisplayCmdUnknown();
2767 while(!abort && r==KErrNone);
2771 TInt ShellFunction::Rename(TDes& aPath,TUint aSwitches)
2773 // Modified December 1997 to allow for filenames containing spaces
2775 TBuf<KShellMaxCommandLine> newName;
2776 TBuf<KShellMaxCommandLine> tempPath=aPath;
2780 TInt r=word.FindNextWord(aPath);
2781 // Check if the word returned is a valid filename. If not, scan the next
2782 // word too in case the filename contains spaces. If, at the end of the
2783 // the line, the filename is not recognised, it is invalid. If there are no
2784 // spaces the user has not used the correct format for this command.
2788 newName=aPath.Right(aPath.Length()-r);
2789 tempPath.SetLength(r);
2791 TInt result=GetFullPath(tempPath,oldName);
2792 if (result!=KErrNone)
2795 if (tempPath[tempPath.Length()-2]==KPathDelimiter)
2796 tempPath.SetLength(tempPath.Length()-2);
2798 result=file.Open(TheShell->TheFs,tempPath,KEntryAttMatchExclude|KEntryAttDir);
2799 if (result==KErrNone) // A valid filename
2802 TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
2803 TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
2804 r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
2805 // r=TheShell->TheFs.Rename(oldName.FullName(),newName);
2810 // May be a request to rename a directory
2812 result=dir.Open(TheShell->TheFs,tempPath,KEntryAttMatchMask);
2813 if (result==KErrNone) // A valid directory name
2816 TBool recursive=((aSwitches&TShellCommand::ESSwitch)!=0);
2817 TUint switches=(recursive) ? CFileMan::EOverWrite : 0;
2818 r=CShell::TheFileMan->Rename(oldName.FullName(),newName,switches);
2819 // r=TheShell->TheFs.Rename(oldName.FullName(),newName);
2823 // Not a valid file or directory name - move one word along the command line
2824 r=word.FindNextWord(word.iRightString);
2828 if (r<0) // Error in filename or destination
2830 else // End of command line, user typed invalid line
2831 return (KErrNotFound);
2835 TInt ShellFunction::Rd(TDes& aPath,TUint /*aSwitches*/)
2837 if (aPath.Length()==0)
2838 return(KErrBadName);
2839 if (aPath[aPath.Length()-1]!=KPathDelimiter)
2840 aPath.Append(KPathDelimiter);
2842 TInt r = GetFullPath(aPath,dirPath);
2846 // Check whether the directory actually exists.
2848 r=directory.Open(TheShell->TheFs,dirPath.FullName(),KEntryAttMatchExclusive|KEntryAttDir);
2851 CShell::TheConsole->Printf(_L("Directory %S was not found\n"),&dirPath.FullName());
2856 TInt ret=TheShell->TheFs.RmDir(dirPath.FullName());
2859 CShell::TheConsole->Printf(_L("Directory %S was removed\n"),&dirPath.FullName());
2860 else if(ret==KErrInUse)
2862 CShell::TheConsole->Printf(_L("Directory %S is in use and cannot be deleted\n"),&dirPath.FullName());
2869 TInt ShellFunction::Start(TDes& aProg,TUint /*aSwitches*/)
2871 // Runs a program without waiting for completion
2875 TInt bat=aProg.FindF(_L(".BAT"));
2876 TInt space=aProg.Locate(' ');
2877 TInt r=KErrArgument;
2878 if (bat>=0 && (space<0 || space>bat))
2879 r=CShell::RunBatch(aProg);
2880 else if (aProg.Length()!=0)
2881 r=CShell::RunExecutable(aProg,EFalse);
2885 TInt ShellFunction::Time(TDes&,TUint /*aSwitches*/)
2889 TDateTime dateTime(time.DateTime());
2890 CShell::TheConsole->Printf(_L(" %+02d/%+02d/%+04d %+02d:%+02d:%+02d.%+06d\n"),dateTime.Day()+1,dateTime.Month()+1,dateTime.Year(),dateTime.Hour(),dateTime.Minute(),dateTime.Second(),dateTime.MicroSecond());
2894 TInt ShellFunction::Trace(TDes& aState,TUint aSwitches)
2896 // Turn on trace information
2900 if (aSwitches&TShellCommand::ESSwitch)
2902 if (aSwitches&TShellCommand::ELSwitch)
2904 if (aSwitches&TShellCommand::EFSwitch)
2906 if (aSwitches&TShellCommand::ETSwitch)
2908 if (aSwitches&TShellCommand::EISwitch)
2910 if (aSwitches&TShellCommand::ENSwitch)
2912 if (aSwitches&TShellCommand::EMSwitch)
2914 if (aSwitches&TShellCommand::EOSwitch)
2916 if (aSwitches&TShellCommand::ECSwitch)
2918 if (aSwitches&TShellCommand::EHSwitch)
2920 TheShell->TheFs.SetDebugRegister(debugVal);
2924 if (aState.Length())
2926 TBuf<KShellMaxCommandLine> indexArg;
2931 TInt r2=lex.Val(val,EHex);
2933 TInt r=word.FindNextWord(aState);
2937 indexArg = aState.Right(aState.Length()-r);
2939 lex.Val(index,EDecimal);
2946 TInt shift = index % 32;
2948 val = UserSvr::DebugMask(index);
2949 if (aState.Left(2)==_L("on"))
2951 else if (aState.Left(3)==_L("off"))
2957 User::SetDebugMask(val, index);
2958 CShell::TheConsole->Printf(_L("SetDebugMask(0x%x, %d)\n"), val, index);
2963 for (TInt j=0; j<8; j++)
2964 CShell::TheConsole->Printf(_L("DebugMask(%d) = 0x%08X\n"), j, UserSvr::DebugMask(j));
2970 TInt ShellFunction::Tree(TDes& aPath,TUint aSwitches)
2973 CShell::TheConsole->Printf(_L("\n %S\n"),&aPath);
2974 if (aPath.Right(1)==_L("\\"))
2977 aPath.Append(_L("\\*"));
2978 TBuf<256> buf=_L(" ");
2979 TInt dirCount=ShowDirectoryTree(aPath,aSwitches,buf);
2980 buf.Format(_L("\n Found %d subdirector"),dirCount);
2982 buf.AppendFormat(_L("y\n"));
2984 buf.AppendFormat(_L("ies\n"));
2986 CShell::OutputStringToConsole(((aSwitches&TShellCommand::EPSwitch)!=0),buf);
2991 TInt ShellFunction::ShowDirectoryTree(TDes& aPath,TUint aSwitches,TDes& aTreeGraph)
2993 // Recursive fn. to draw tree of dir aPath (needs to be suffixed with '*')
2998 TInt r=dir.Open(TheShell->TheFs,aPath,KEntryAttDir);
3002 while ((r=dir.Read(next))==KErrNone && !next.IsDir())
3005 // lint info 722: Suspicious use of ; in previous line...
3006 if (aSwitches&TShellCommand::EFSwitch)
3009 if (dirFile.Open(TheShell->TheFs,aPath,0)==KErrNone)
3011 while (dirFile.Read(entry)==KErrNone)
3012 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,(r==KErrNone)?_L("%S\x00B3 %S\n"):_L("%S %S\n"),&aTreeGraph,&entry.iName);
3021 while ((r=dir.Read(next))==KErrNone && !next.IsDir())
3024 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,aTreeGraph);
3027 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
3028 aTreeGraph.Append(_L("\x00B3 "));
3032 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("\x00C0\x00C4\x00C4%S\n"),&entry.iName);
3033 aTreeGraph.Append(_L(" "));
3035 aPath.Insert(aPath.Length()-1,entry.iName);
3036 aPath.Insert(aPath.Length()-1,_L("\\"));
3037 dirCount+=1+ShowDirectoryTree(aPath,aSwitches,aTreeGraph);
3038 aPath.Delete(aPath.Length()-2-entry.iName.Length(),entry.iName.Length()+1);
3039 aTreeGraph.SetLength(aTreeGraph.Length()-3);
3041 while (r==KErrNone);
3044 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error EOF %d\n"),r);
3048 CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,_L("Error in Open %d\n"),r);
3052 void ByteSwap(TDes16& aDes)
3054 TUint8* p=(TUint8*)aDes.Ptr();
3055 TUint8* pE=p+aDes.Size();
3058 c=*p, *p=p[1], p[1]=c;
3061 _LIT(KLitPercentS, "%S");
3062 TInt ShellFunction::Type(TDes& aPath,TUint aSwitches)
3066 TInt r=file.Open(TheShell->TheFs,aPath,EFileStreamText|EFileShareReadersOnly);
3069 TBuf8<0x200> tmpbuf;
3071 TInt state=0; // 0=start of file, 1=ASCII, 2=UNICODE little-endian, 3=UNICODE big-endian
3072 TKeyCode key=EKeyNull;
3079 r=file.Read(tmpbuf);
3091 TUint c=(tmpbuf[1]<<8)|tmpbuf[0];
3106 --l, tmpbuf.SetLength(l);
3107 buf.Set((TText*)tmpbuf.Ptr(),l/sizeof(TText));
3110 TPtr wbuf( (TText*)buf.Ptr(), buf.Length(), buf.Length() );
3119 while ((r=buf.Locate('\n'))!=KErrNotFound)
3122 TPtrC bufLeft=buf.Left(r+1);
3123 key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &bufLeft);
3124 buf.Set(buf.Mid(r+1));
3126 if(key == EKeyEscape)
3130 nchars=buf.Length();
3133 key = CShell::OutputStringToConsole((aSwitches&TShellCommand::EPSwitch)!=0,KLitPercentS(), &buf);
3134 if(key == EKeyEscape)
3139 } while(l==tmpbuf.MaxLength());
3148 void ShellFunction::ParsePath(TDes& aPath)
3150 if (aPath.Length()>0 && aPath[0]==KPathDelimiter)
3153 if (aPath.Length()<2 || aPath[1]!=':')
3154 pathParse.SetNoWild(TheShell->currentPath,NULL,NULL);
3157 if (aPath.Length()>=3 && aPath[2]==KPathDelimiter)
3159 pathParse.SetNoWild(TheShell->drivePaths[User::UpperCase(aPath[0])-'A'],NULL,NULL);
3162 if (aPath.Length()>=2 && aPath.Left(2).Compare(_L(".."))==0)
3166 while (aPath.Length()>=3 && aPath.Left(3).Compare(_L("\\.."))==0)
3171 if (aPath.Length()!=0 && aPath[0]==KPathDelimiter)
3174 aPath.Insert(0,pathParse.FullName());
3177 TBool ShellFunction::Certain()
3179 CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
3180 TInt r=User::UpperCase(CShell::TheConsole->Getch());
3181 while ((!(r=='Y'))&&(!(r=='N')))
3183 CShell::TheConsole->Printf(_L("%c is invalid\n"),r);
3184 CShell::TheConsole->Printf(_L("Are you sure? Y/N..."));
3185 r=User::UpperCase(CShell::TheConsole->Getch());
3187 CShell::TheConsole->Printf(_L("%c\n"),r);
3191 TInt ShellFunction::GetFullPath(TDes& aPath,TParse& aParse)
3193 // Parse a path of the form "[C:][\\]AAA\\..\\.\\BBB\\xxx.yyy" where:
3194 // . indicates the current directory
3195 // .. indicates move to the parent directory
3196 // An optional "\\" at the start of the path indicates the path is not relative to the current path
3201 if (aPath.Length()>0 && aPath[aPath.Length()-1]=='.')
3202 aPath.Append(KPathDelimiter);
3203 if (aPath.Length()==0)
3204 r=aParse.Set(TheShell->currentPath,NULL,NULL);
3205 else if (aPath[0]==KPathDelimiter)
3206 r=aParse.Set(aPath,&TheShell->currentPath,NULL);
3207 else if (aPath.Length()>=2 && aPath[1]==KDriveDelimiter)
3210 r=RFs::CharToDrive(aPath[0],drvNum);
3212 r=aParse.Set(aPath,&TheShell->drivePaths[drvNum],NULL);
3216 if (aPath.LocateReverse(KPathDelimiter)>=0)
3218 if (aPath.Length()+TheShell->currentPath.Length()>aPath.MaxLength())
3219 return(KErrBadName);
3220 aPath.Insert(0,TheShell->currentPath);
3222 r=aParse.Set(aPath,&TheShell->currentPath,NULL);
3226 if (aParse.Path().Find(_L(".\\"))==KErrNotFound)
3228 if (aParse.Path().Find(_L("...\\"))!=KErrNotFound)
3229 return(KErrBadName);
3231 TPtrC path(aParse.DriveAndPath());
3232 TInt pos=path.Find(_L(".\\"));
3233 if (path[pos-1]!='.' && path[pos-1]!='\\')
3234 return(KErrNone); // FileName ending in .
3235 TInt isParent=(path[pos-1]=='.') ? 1 : 0;
3236 r=dirParse.Set(path.Left(pos-isParent),NULL,NULL);
3241 path.Set(path.Right(path.Length()-pos-2));
3242 pos=path.Find(_L(".\\"));
3248 else if (pos!=KErrNotFound)
3249 isParent=(path[pos-1]=='.') ? 1 : 0;
3250 TInt len=(pos==KErrNotFound) ? path.Length() : pos-isParent;
3251 r=AddRelativePath(dirParse,path.Left(len));
3252 if (r!=KErrNone || pos==KErrNotFound)
3258 TBuf<KMaxFileName> nameAndExt=aParse.NameAndExt();
3259 aParse.Set(dirParse.FullName(),&nameAndExt,NULL);
3263 void ShellFunction::StripQuotes(TDes& aVal)
3265 for(TInt idx=0;idx<aVal.Length();idx++)
3267 while((idx < aVal.Length()) && (aVal[idx] == '"'))
3269 aVal.Delete(idx, 1);
3274 TInt ShellFunction::ValidName(TDes& aPath,TUint /*aSwitches*/)
3276 // Check whether the name has any invalid characters
3279 TBool tooShort=EFalse;
3282 TPtr ptr(&badChar,sizeof(TText),sizeof(TText));
3284 TBool validName=TheShell->TheFs.IsValidName(aPath,badChar);
3286 CShell::TheConsole->Printf(_L("'%S' is a valid name\n"),&aPath);
3290 CShell::TheConsole->Printf(_L("'%S' is not a valid name.\n"),&aPath);
3292 CShell::TheConsole->Printf(_L("The '%S' character is not allowed\n"),&ptr);
3297 LOCAL_C TInt pswd_DrvNbr(TDes &aPath, TInt &aDN)
3299 // password utility function to extract drive number from cmd string.
3306 LOCAL_C TInt pswd_Password(TDes &aPath, TInt aPWNbr, TMediaPassword &aPW)
3308 // utility function to extract indexed password from command string. A
3309 // dash is interpreted as the null password.
3312 __ASSERT_DEBUG(aPWNbr >= 1, User::Panic(_L("Invalid pswd nbr"), 0));
3317 for (TInt i = 0; i <= aPWNbr; ++i)
3320 return KErrNotFound;
3322 ptScan.Set(l.NextToken());
3325 // take remainder of command line and terminate after password
3327 for (TInt j = 0; j < ptScan.Length() && ! TChar(ptScan[j]).IsSpace(); ++j)
3329 pswd.Append(ptScan[j]);
3336 // fill aPW with contents of pswd, not converting to ASCII
3337 const TInt byteLen = pswd.Length() * 2;
3338 if (byteLen > KMaxMediaPassword)
3339 return KErrArgument;
3341 aPW.Copy(reinterpret_cast<const TUint8 *>(pswd.Ptr()), byteLen);
3346 TInt ShellFunction::Lock(TDes &aPath, TUint aSwitches)
3348 // Locks a password-enabled media.
3353 TMediaPassword curPswd;
3354 TMediaPassword newPswd;
3355 TBool store = aSwitches & TShellCommand::ESSwitch;
3357 if ((r = pswd_DrvNbr(aPath, dn)) < 0)
3360 if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
3363 if ((r = pswd_Password(aPath, 2, newPswd)) < 0)
3366 return TheShell->TheFs.LockDrive(dn, curPswd, newPswd, store);
3369 TInt ShellFunction::Unlock(TDes &aPath, TUint aSwitches)
3371 // Unlocks a password-enabled media.
3376 TMediaPassword curPswd;
3377 TBool store = aSwitches & TShellCommand::ESSwitch;
3379 if ((r = pswd_DrvNbr(aPath, dn)) < 0)
3382 if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
3385 return TheShell->TheFs.UnlockDrive(dn, curPswd, store);
3388 TInt ShellFunction::Clear(TDes &aPath, TUint /* aSwitches */)
3390 // Clears a password from a password-enabled media.
3395 TMediaPassword curPswd;
3397 if ((r = pswd_DrvNbr(aPath, dn)) < 0)
3400 if ((r = pswd_Password(aPath, 1, curPswd)) < 0)
3403 return TheShell->TheFs.ClearPassword(dn, curPswd);
3406 TInt ShellFunction::SetSize(TDes& aPath,TUint /*aSwitches*/)
3408 // Set size of a file, create this if it does not exist
3411 TInt fileNameLen=aPath.LocateReverse(' ');
3412 if (fileNameLen==KErrNotFound) // No spaces implies no filelength specified
3414 CShell::TheConsole->Printf(_L("Please specify a file name and a file length\n"));
3419 TInt fileLength=(aPath.Length()-fileNameLen);
3421 return (KErrTooBig); // Too many digits - too large!
3422 TBuf<16> rightString=aPath.Right(fileLength);
3423 aPath.SetLength(fileNameLen);
3425 TLex size(rightString);
3428 TRadix radix=ParseHexaPrefixIfAny(size);
3430 TInt r=size.Val(fileSize,radix);
3431 if (r!=KErrNone || ! size.Eos())
3433 CShell::TheConsole->Printf(_L("Please specify a file length\n"));
3438 GetFullPath(aPath,fileName);
3440 r=file.Open(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
3442 r=file.Create(CShell::TheFs,fileName.FullName(),EFileRead|EFileWrite);
3445 r=file.SetSize(fileSize);
3448 CShell::TheConsole->Printf(_L("Error (%d) - could not set size of file\n"),r);
3452 CShell::TheConsole->Printf(_L("Error (%d) - could not create or open file\n"),r);
3453 CShell::TheFs.Delete(fileName.FullName());
3458 TInt ShellFunction::DebugPort(TDes& aArgs, TUint /*aSwitches*/)
3460 // Set or get the debug port from the command line (debugport)
3463 _LIT(KGetPortLit, "Debug port is %d (0x%x)\n");
3464 _LIT(KSetPortLit, "Debug port set to %d (0x%x)\n");
3471 TInt r = HAL::Get(HALData::EDebugPort, port);
3474 CShell::TheConsole->Printf(KGetPortLit, (TUint32)port, (TUint32)port);
3478 TRadix radix=EDecimal;
3479 if (s.Remainder().Length()>2)
3483 if (s.MarkedToken().MatchF(_L("0x"))!=KErrNotFound)
3498 r = s.Val(port.u, radix);
3501 if (r != KErrNone || ! s.Eos())
3503 r = HAL::Set(HALData::EDebugPort, port.s);
3506 CShell::TheConsole->Printf(KSetPortLit, port.s, port.u);
3512 TInt ShellFunction::Plugin(TDes& aName,TUint aSwitches)
3514 TInt err = KErrNone;
3517 case TShellCommand::EASwitch:
3519 err = CShell::TheFs.AddPlugin(aName);
3520 CShell::TheConsole->Printf(_L("Add Plugin: %S [r:%d]\n"), &aName, err);
3523 case TShellCommand::ERSwitch:
3525 err = CShell::TheFs.RemovePlugin(aName);
3526 CShell::TheConsole->Printf(_L("Remove Plugin: %S [r:%d]\n"), &aName, err);
3529 case TShellCommand::EMSwitch:
3531 err = CShell::TheFs.MountPlugin(aName);
3532 CShell::TheConsole->Printf(_L("Mount Plugin: %S [r:%d]\n"), &aName, err);
3535 case TShellCommand::EDSwitch:
3537 err = CShell::TheFs.DismountPlugin(aName);
3538 CShell::TheConsole->Printf(_L("Dismount Plugin: %S [r:%d]\n"), &aName, err);
3549 _LIT(KCrNl, "\r\n");
3551 void SIPrintf(TRefByValue<const TDesC16> aFmt, ...)
3555 VA_START(list, aFmt);
3556 // coverity[uninit_use_in_call]
3557 buf.FormatList(aFmt, list);
3559 RDebug::RawPrint(buf);
3560 CShell::TheConsole->Printf(buf);
3564 Run a specified executable in a loop.
3566 RUNEXEC <count> <command [args]> [/E] [/S] [/R]
3568 count - loop count; zero (0) means: forever
3569 command - the executable to run. Arguments can be supplied.
3571 command arguments cannot contain /? switches as the shell strips these out.
3572 command cannot contain spaces.
3574 /E terminates the loop if the program exits with an error
3576 /S makes the shell interpret "count" as a number of seconds
3577 The shell will not attempt to terminate "command" early if it is still running after
3578 "count" seconds. It will terminate the loop only after "command" has exited.
3580 /R will make the shell reset debug registers / trace flags after each iteration.
3581 This is to be used if the program modifies tracing flags for its own purposes but exits
3582 abnormally; if /R is used, later iterations will run the program from the same initial
3583 tracing state each time.
3584 Limitation: This flag does not yet affect BTrace / UTrace state.
3586 Switches can be combined; "RUNEXEC 2000 testprg /E/S/R" keeps running "testprg" till an error
3587 occurs, or more than 2000 seconds have passed, and resets the debug state after each iteration.
3589 TInt ShellFunction::RunExec(TDes& aProg, TUint aSwitches)
3591 _LIT(KRunExecFailedProcessCreate, "Failed to spawn command %S: error %d\n");
3592 _LIT(KRunExecReportStatusAndTime, "Total elapsed time: %d msecs, Iteration %d: Exit type %d,%d,%S\n");
3594 TBuf<KShellMaxCommandLine> parameters(0);
3597 TTime timeStart, timeCurrent;
3598 TTimeIntervalMicroSeconds timeTaken;
3600 // The first parameter must be a valid decimal integer.
3601 for (r=0; r < aProg.Length() && TChar(aProg[r]).IsDigit(); r++)
3602 count = count * 10 + (aProg[r] - '0');
3603 if (r == 0 || r == aProg.Length() || TChar(aProg[r]).IsSpace() == EFalse)
3604 return (KErrArgument);
3605 aProg = aProg.Mid(r+1);
3607 TBool exitOnErr = (aSwitches & TShellCommand::EESwitch);
3608 TBool resetDebugRegs = (aSwitches & TShellCommand::ERSwitch);
3609 TBool countIsSecs = (aSwitches & TShellCommand::ESSwitch);
3610 TBool forever = (count == 0);
3612 timeStart.HomeTime();
3614 // copy out the parameters - if any
3615 r = aProg.Locate(' ');
3616 if(r != KErrNotFound)
3618 parameters = aProg.Mid(r+1);
3622 // Make sure the executable name qualifies as a pathname.
3624 if (aProg.FindF(_L(".EXE")) == KErrNotFound && (aProg.Length()+4) <= KShellMaxCommandLine)
3625 aProg.Append(_L(".EXE"));
3628 SIPrintf(_L("RUNEXEC: command %S, parameters %S, count %d, forever %d, issecs %d, exiterr %d"),
3629 &aProg, ¶meters, count, forever, countIsSecs, exitOnErr);
3635 RProcess newProcess;
3636 TRequestStatus status = KRequestPending;
3638 TBuf<KMaxExitCategoryName> exitCat(0);
3640 r = newProcess.Create(aProg, parameters);
3643 SIPrintf(KRunExecFailedProcessCreate, &aProg, r);
3644 return (r); // this is systematic - must return
3646 newProcess.Logon(status);
3647 newProcess.Resume();
3648 User::WaitForRequest(status);
3649 exitType = newProcess.ExitType();
3650 exitCat = newProcess.ExitCategory();
3651 retcode = newProcess.ExitReason();
3654 timeCurrent.HomeTime();
3655 timeTaken = timeCurrent.MicroSecondsFrom(timeStart);
3656 TInt msecs = I64LOW(timeTaken.Int64() / 1000);
3657 SIPrintf(KRunExecReportStatusAndTime, msecs, i+1, exitType, retcode, &exitCat);
3661 TheShell->TheFs.SetDebugRegister(0);
3662 User::SetDebugMask(0);
3667 if ((exitOnErr && (exitType != EExitKill || status != KErrNone)) || // err occurred, leave requested ?
3668 (countIsSecs && count != 0 && timeTaken.Int64() > (TInt64)1000000 * (TInt64)count) || // time elapsed ?
3669 (!forever && i >= count)) // loop done ?
3676 // System information command
3679 TBool DebugNum(TInt aBitNum)
3681 __ASSERT_ALWAYS(aBitNum >= 0 && aBitNum <= KMAXTRACE, User::Panic(_L("Bad bit num"), 0));
3682 TInt index = aBitNum >> 5;
3683 TInt m = UserSvr::DebugMask(index) & (1 << (aBitNum & 31));
3687 void SIHeading(TRefByValue<const TDesC16> aFmt, ...)
3691 VA_START(list, aFmt);
3693 buf.AppendFormatList(aFmt, list);
3695 RDebug::RawPrint(buf);
3696 CShell::TheConsole->Printf(buf);
3697 buf.Fill('=', buf.Length()-4);
3699 RDebug::RawPrint(buf);
3700 CShell::TheConsole->Printf(buf);
3703 void SIBoolean(const TDesC& aFmt, TBool aVal)
3705 _LIT(KEnabled, "enabled");
3706 _LIT(KDisabled, "disabled");
3707 SIPrintf(aFmt, aVal ? &KEnabled : &KDisabled);
3710 TInt ShellFunction::SysInfo(TDes& /*aArgs*/, TUint /*aSwitches*/)
3712 SIHeading(_L("Kernel Features"));
3713 SIBoolean(_L("Crazy scheduler delays are %S."), DebugNum(KCRAZYSCHEDDELAY));
3714 SIBoolean(_L("Crazy scheduler priorities and timeslicing are %S."),
3715 UserSvr::HalFunction(EHalGroupKernel, EKernelHalConfigFlags, 0, 0) & EKernelConfigCrazyScheduling);
3721 //-------------------------------------------------------------------------
3723 Print out the command line to the console and standard debug port.
3725 TInt ShellFunction::ConsoleEcho(TDes& aArgs, TUint /*aSwitches*/)