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