|
1 // ps.cpp |
|
2 // |
|
3 // Copyright (c) 2005 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <fshell/common.mmh> |
|
14 #include <fshell/ltkutils.h> |
|
15 #include <fshell/heaputils.h> |
|
16 #include "ps.h" |
|
17 |
|
18 _LIT(KDefaultMatch, "*"); |
|
19 |
|
20 CCommandBase* CCmdPs::NewLC() |
|
21 { |
|
22 CCmdPs* self = new(ELeave) CCmdPs(); |
|
23 CleanupStack::PushL(self); |
|
24 self->BaseConstructL(); |
|
25 return self; |
|
26 } |
|
27 |
|
28 CCmdPs::~CCmdPs() |
|
29 { |
|
30 delete iMatch; |
|
31 delete iFormatter; |
|
32 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
33 iMemoryAccess.Close(); |
|
34 #endif |
|
35 } |
|
36 |
|
37 CCmdPs::CCmdPs() |
|
38 { |
|
39 } |
|
40 |
|
41 const TDesC& CCmdPs::Name() const |
|
42 { |
|
43 _LIT(KName, "ps"); |
|
44 return KName; |
|
45 } |
|
46 |
|
47 void CCmdPs::DoRunL() |
|
48 { |
|
49 if (iMatch == NULL) |
|
50 { |
|
51 iMatch = KDefaultMatch().AllocL(); |
|
52 } |
|
53 |
|
54 iFormatter = CTextFormatter::NewL(Stdout()); |
|
55 |
|
56 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
57 TInt err = RMemoryAccess::LoadDriver(); |
|
58 if ((err == KErrNone) || (err == KErrAlreadyExists)) |
|
59 { |
|
60 err = iMemoryAccess.Open(); |
|
61 } |
|
62 if (err) |
|
63 { |
|
64 PrintWarning(_L("Unable to load memory access device driver: %d"), err); |
|
65 } |
|
66 #endif |
|
67 |
|
68 #if defined(__WINS__) && !defined(EKA2) |
|
69 TFindThread finder(*iMatch); |
|
70 RThread process; |
|
71 #else |
|
72 TFindProcess finder(*iMatch); |
|
73 RProcess process; |
|
74 #endif |
|
75 |
|
76 |
|
77 if (iProcessId) |
|
78 { |
|
79 User::LeaveIfError(process.Open(iProcessId)); |
|
80 CleanupClosePushL(process); |
|
81 iProcessName = process.Name(); |
|
82 PrintInfoL(process); |
|
83 CleanupStack::PopAndDestroy(&process); |
|
84 } |
|
85 else |
|
86 { |
|
87 while (finder.Next(iProcessName) == KErrNone) |
|
88 { |
|
89 TInt err = process.Open(finder); |
|
90 if (err) |
|
91 { |
|
92 PrintWarning(_L("Unable to open handle to process %S: %d"), &iProcessName, err); |
|
93 continue; |
|
94 } |
|
95 if ((iExcludeDead && (process.ExitType() != EExitPending)) || (iOnlyDead && (process.ExitType() == EExitPending))) |
|
96 { |
|
97 process.Close(); |
|
98 continue; |
|
99 } |
|
100 CleanupClosePushL(process); |
|
101 PrintInfoL(process); |
|
102 CleanupStack::PopAndDestroy(&process); |
|
103 } |
|
104 } |
|
105 |
|
106 Write(iFormatter->Descriptor()); |
|
107 Complete(); |
|
108 } |
|
109 |
|
110 void CCmdPs::ArgumentsL(RCommandArgumentList& aArguments) |
|
111 { |
|
112 _LIT(KArg1, "process_id"); |
|
113 aArguments.AppendUintL(iProcessId, KArg1); |
|
114 } |
|
115 |
|
116 void CCmdPs::OptionsL(RCommandOptionList& aOptions) |
|
117 { |
|
118 _LIT(KOptVerbose, "verbose"); |
|
119 aOptions.AppendBoolL(iVerbose, KOptVerbose); |
|
120 |
|
121 _LIT(KOptMatch, "match"); |
|
122 aOptions.AppendStringL(iMatch, KOptMatch); |
|
123 |
|
124 _LIT(KOptHuman, "human"); |
|
125 aOptions.AppendBoolL(iHuman, KOptHuman); |
|
126 |
|
127 _LIT(KOptPriority, "priority"); |
|
128 aOptions.AppendBoolL(iPrintPriority, KOptPriority); |
|
129 |
|
130 _LIT(KOptExclude, "exclude-dead"); |
|
131 aOptions.AppendBoolL(iExcludeDead, KOptExclude); |
|
132 |
|
133 _LIT(KOptOnlyDead, "only-dead"); |
|
134 aOptions.AppendBoolL(iOnlyDead, KOptOnlyDead); |
|
135 |
|
136 _LIT(KOptHandleCount, "handle-count"); |
|
137 aOptions.AppendBoolL(iHandleCount, KOptHandleCount); |
|
138 |
|
139 #if defined(EKA2) || !defined(__WINS__) |
|
140 _LIT(KOptThreads, "threads"); |
|
141 aOptions.AppendBoolL(iPrintThreads, KOptThreads); |
|
142 |
|
143 _LIT(KOptStack, "stacks"); |
|
144 aOptions.AppendBoolL(iPrintStackInfo, KOptStack); |
|
145 |
|
146 _LIT(KOptHeap, "heaps"); |
|
147 aOptions.AppendBoolL(iPrintHeapInfo, KOptHeap); |
|
148 |
|
149 _LIT(KOptCpu, "cpu-time"); |
|
150 aOptions.AppendBoolL(iPrintCpuTime, KOptCpu); |
|
151 |
|
152 _LIT(KOptChunk, "chunks"); |
|
153 aOptions.AppendBoolL(iPrintChunkInfo, KOptChunk); |
|
154 |
|
155 _LIT(KOptFileName, "filename"); |
|
156 aOptions.AppendBoolL(iPrintFileName, KOptFileName); |
|
157 |
|
158 _LIT(KOptMemoryInfo, "memory"); |
|
159 aOptions.AppendBoolL(iPrintMemoryInfo, KOptMemoryInfo); |
|
160 #endif |
|
161 #if !defined(EKA2) && !defined(__WINS__) |
|
162 _LIT(KOptCommandLine, "command_line"); |
|
163 aOptions.AppendBoolL(iPrintCommandLine, KOptCommandLine); |
|
164 #endif |
|
165 #if !defined(EKA2) |
|
166 _LIT(KOptFlags, "flags"); |
|
167 aOptions.AppendBoolL(iPrintFlags, KOptFlags); |
|
168 #endif |
|
169 |
|
170 _LIT(KOptAddresses, "addresses"); |
|
171 aOptions.AppendBoolL(iAddresses, KOptAddresses); |
|
172 } |
|
173 |
|
174 #if defined(__WINS__) && !defined(EKA2) |
|
175 void CCmdPs::PrintInfoL(RThread& aProcess) |
|
176 #else |
|
177 void CCmdPs::PrintInfoL(RProcess& aProcess) |
|
178 #endif |
|
179 { |
|
180 TInt processHandleCount = 0; |
|
181 |
|
182 TBool dead = aProcess.ExitType() != EExitPending; |
|
183 iFormatter->AppendFormatL(_L("%u "), TUint(aProcess.Id())); |
|
184 if (dead) iFormatter->AppendL(_L("[")); |
|
185 if (iVerbose) |
|
186 { |
|
187 iFormatter->AppendL(iProcessName); |
|
188 } |
|
189 else |
|
190 { |
|
191 TFullName name = iProcessName; |
|
192 LtkUtils::MakeProcessNameFriendly(name); |
|
193 iFormatter->AppendL(name); |
|
194 } |
|
195 if (dead) iFormatter->AppendL(_L("]")); |
|
196 iFormatter->AppendL(_L("\r\n")); |
|
197 |
|
198 iProcessName.Append(_L("::*")); |
|
199 |
|
200 if (iPrintThreads) |
|
201 { |
|
202 iFormatter->AppendL(_L("\tThreads:\r\n")); |
|
203 TFindThread threadFinder(iProcessName); |
|
204 RThread thread; |
|
205 while (threadFinder.Next(iThreadName) == KErrNone) |
|
206 { |
|
207 TInt err = thread.Open(threadFinder); |
|
208 if (err) |
|
209 { |
|
210 if ((err != KErrPermissionDenied) || iVerbose) |
|
211 { |
|
212 PrintWarning(_L("Unable to open handle to thread %S: %d"), &iThreadName, err); |
|
213 } |
|
214 continue; |
|
215 } |
|
216 if ((iExcludeDead && (thread.ExitType() != EExitPending)) || (iOnlyDead && (thread.ExitType() == EExitPending))) |
|
217 { |
|
218 thread.Close(); |
|
219 continue; |
|
220 } |
|
221 |
|
222 CleanupClosePushL(thread); |
|
223 iThreadName = thread.Name(); |
|
224 #ifdef EKA2 |
|
225 iFormatter->AppendFormatL(_L("\t\t%Lu %S\r\n"), thread.Id().Id(), &iThreadName); |
|
226 #else |
|
227 iFormatter->AppendFormatL(_L("\t\t%u %S\r\n"), thread.Id(), &iThreadName); |
|
228 #endif |
|
229 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
230 if (iAddresses && iMemoryAccess.Handle()) |
|
231 { |
|
232 TObjectKernelInfo objectInfo; |
|
233 TPckg<TObjectKernelInfo> objectInfoPckg(objectInfo); |
|
234 TInt err = iMemoryAccess.GetObjectInfoByHandle(EThread, RThread().Id(), thread.Handle(), objectInfoPckg); |
|
235 if (err == KErrNone) |
|
236 { |
|
237 iFormatter->AppendFormatL(_L("\t\t\tAddress: 0x%08x\r\n"), objectInfo.iAddressOfKernelObject); |
|
238 } |
|
239 } |
|
240 #endif // FSHELL_MEMORY_ACCESS_SUPPORT |
|
241 if (iPrintPriority) |
|
242 { |
|
243 iFormatter->AppendFormatL(_L("\t\t\tPriority: %d\r\n"), thread.Priority()); |
|
244 } |
|
245 PrintStackInfoL(thread, iThreadName); |
|
246 PrintHeapInfoL(thread, iThreadName); |
|
247 PrintCpuTimeL(thread, iThreadName); |
|
248 if (iHandleCount) |
|
249 { |
|
250 TInt threadHandleCount; |
|
251 thread.HandleCount(processHandleCount, threadHandleCount); |
|
252 iFormatter->AppendFormatL(_L("\t\t\tHandle count: %d\r\n"), threadHandleCount); |
|
253 } |
|
254 CleanupStack::PopAndDestroy(&thread); |
|
255 } |
|
256 } |
|
257 if (iPrintPriority) |
|
258 { |
|
259 iFormatter->AppendFormatL(_L("\tPriority: %d\r\n"), aProcess.Priority()); |
|
260 } |
|
261 #if defined(EKA2) || !defined(__WINS__) |
|
262 PrintChunkInfoL(iProcessName); |
|
263 if (iPrintFileName) |
|
264 { |
|
265 TFileName fileName(aProcess.FileName()); |
|
266 iFormatter->AppendFormatL(_L("\tFile name: %S\r\n"), &fileName); |
|
267 } |
|
268 if (iPrintMemoryInfo) |
|
269 { |
|
270 TProcessMemoryInfo memoryInfo; |
|
271 TInt err = aProcess.GetMemoryInfo(memoryInfo); |
|
272 if (err) |
|
273 { |
|
274 PrintWarning(_L("Couldn't read memory information: %d"), err); |
|
275 } |
|
276 else |
|
277 { |
|
278 iFormatter->AppendFormatL(_L("\tCode base: 0x%08x\r\n"), memoryInfo.iCodeBase); |
|
279 PrintSizeL(_L("\tCode size: "), memoryInfo.iCodeSize); |
|
280 iFormatter->AppendFormatL(_L("\tConst data base: 0x%08x\r\n"), memoryInfo.iConstDataBase); |
|
281 PrintSizeL(_L("\tConst data size: "), memoryInfo.iConstDataSize); |
|
282 iFormatter->AppendFormatL(_L("\tInitialised data base: 0x%08x\r\n"), memoryInfo.iInitialisedDataBase); |
|
283 PrintSizeL(_L("\tInitialised data size: "), memoryInfo.iInitialisedDataSize); |
|
284 iFormatter->AppendFormatL(_L("\tUninitialised data base: 0x%08x\r\n"), memoryInfo.iUninitialisedDataBase); |
|
285 PrintSizeL(_L("\tUninitialised data size: "), memoryInfo.iUninitialisedDataSize); |
|
286 } |
|
287 } |
|
288 #endif |
|
289 #if !defined(EKA2) && !defined(__WINS__) |
|
290 if (iPrintCommandLine) |
|
291 { |
|
292 HBufC* cl = HBufC::NewL(aProcess.CommandLineLength()); |
|
293 TPtr clPtr(cl->Des()); |
|
294 aProcess.CommandLine(clPtr); |
|
295 iFormatter->AppendFormatL(_L("\tCommand line: %S\r\n"), cl); |
|
296 delete cl; |
|
297 } |
|
298 #endif |
|
299 if (iPrintFlags) |
|
300 { |
|
301 #ifndef EKA2 |
|
302 iFormatter->AppendFormatL(_L("\tSystem: %d\r\n\tProtected: %d\r\n"), aProcess.System(), aProcess.Protected()); |
|
303 #endif |
|
304 #if !defined(__WINS__) && !defined(EKA2) |
|
305 iFormatter->AppendFormatL(_L("\tLoaded from RAM: %d\r\n"), aProcess.LoadedFromRam()); |
|
306 #endif |
|
307 } |
|
308 |
|
309 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
310 if (iAddresses && iMemoryAccess.Handle()) |
|
311 { |
|
312 TObjectKernelInfo objectInfo; |
|
313 TPckg<TObjectKernelInfo> objectInfoPckg(objectInfo); |
|
314 TInt err = iMemoryAccess.GetObjectInfoByHandle(EProcess, RThread().Id(), aProcess.Handle(), objectInfoPckg); |
|
315 if (err == KErrNone) |
|
316 { |
|
317 iFormatter->AppendFormatL(_L("\tAddress: 0x%08x\r\n"), objectInfo.iAddressOfKernelObject); |
|
318 } |
|
319 } |
|
320 #endif // FSHELL_MEMORY_ACCESS_SUPPORT |
|
321 |
|
322 if (iHandleCount) |
|
323 { |
|
324 if (iPrintThreads) |
|
325 { |
|
326 iFormatter->AppendFormatL(_L("\tProcess handle count: %d\r\n"), processHandleCount); |
|
327 } |
|
328 else |
|
329 { |
|
330 // Summarise the total handle count for this process and all its threads. |
|
331 TInt threadHandleCount = 0; |
|
332 TFindThread threadFinder(iProcessName); |
|
333 RThread thread; |
|
334 while (threadFinder.Next(iThreadName) == KErrNone) |
|
335 { |
|
336 TInt err = thread.Open(threadFinder); |
|
337 if (err) |
|
338 { |
|
339 continue; |
|
340 } |
|
341 TInt thc; |
|
342 thread.HandleCount(processHandleCount, thc); |
|
343 thread.Close(); |
|
344 threadHandleCount += thc; |
|
345 } |
|
346 iFormatter->AppendFormatL(_L("\tTotal handle count: %d\r\n"), processHandleCount + threadHandleCount); |
|
347 } |
|
348 } |
|
349 } |
|
350 |
|
351 void CCmdPs::PrintStackInfoL(RThread& aThread, const TDesC& aThreadName) |
|
352 { |
|
353 #ifdef EKA2 |
|
354 if (iPrintStackInfo) |
|
355 { |
|
356 TThreadStackInfo stackInfo; |
|
357 TInt err = aThread.StackInfo(stackInfo); |
|
358 if (err) |
|
359 { |
|
360 PrintWarning(_L("Unable to get stack info for thread %S: %d"), &aThreadName, err); |
|
361 } |
|
362 else |
|
363 { |
|
364 const TInt stackSize = stackInfo.iBase - stackInfo.iLimit; |
|
365 iFormatter->AppendFormatL(_L("\t\t\tStack info:\r\n")); |
|
366 PrintSizeL(_L("\t\t\t\tSize: "), stackSize); |
|
367 iFormatter->AppendFormatL(_L("\t\t\t\tBase: 0x%08x\r\n"), stackInfo.iBase); |
|
368 iFormatter->AppendFormatL(_L("\t\t\t\tLimit: 0x%08x\r\n"), stackInfo.iLimit); |
|
369 iFormatter->AppendFormatL(_L("\t\t\t\tExpand limit: 0x%08x\r\n"), stackInfo.iExpandLimit); |
|
370 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
371 if (iMemoryAccess.Handle()) |
|
372 { |
|
373 const TInt KBufSize = 4096; // The largest amount RMemoryAccess allows us to copy in one go. |
|
374 HBufC8* stackBuf = HBufC8::NewLC(KBufSize); |
|
375 TPtr8 stackBufPtr(stackBuf->Des()); |
|
376 TThreadMemoryAccessParamsBuf accessParamsBuf; |
|
377 TThreadMemoryAccessParams& accessParams = accessParamsBuf(); |
|
378 accessParams.iId = (TInt)aThread.Id().Id(); |
|
379 TInt numBytesRead = 0; |
|
380 TInt numUnusedBytes = 0; |
|
381 while (numBytesRead < stackSize) |
|
382 { |
|
383 accessParams.iAddr = (TUint8*)stackInfo.iLimit + numBytesRead; |
|
384 accessParams.iSize = Min(KBufSize, stackSize - numBytesRead); |
|
385 stackBufPtr.Zero(); |
|
386 err = iMemoryAccess.GetThreadMem(accessParamsBuf, stackBufPtr); |
|
387 if (err) |
|
388 { |
|
389 PrintWarning(_L("Unable to read stack data for thread %S: %d"), &aThreadName, err); |
|
390 break; |
|
391 } |
|
392 else |
|
393 { |
|
394 const TInt bufLength = stackBuf->Length(); |
|
395 for (TInt i = 0; i < bufLength; ++i) |
|
396 { |
|
397 if ((*stackBuf)[i] != 0x29) |
|
398 { |
|
399 break; |
|
400 } |
|
401 ++numUnusedBytes; |
|
402 } |
|
403 numBytesRead += bufLength; |
|
404 } |
|
405 } |
|
406 if (err == KErrNone) |
|
407 { |
|
408 const TInt numUsedBytes = stackSize - numUnusedBytes; |
|
409 iFormatter->AppendFormatL(_L("\t\t\t\tHigh water mark: 0x%08x ("), stackInfo.iBase - numUsedBytes); |
|
410 if (iHuman) |
|
411 { |
|
412 iFormatter->AppendHumanReadableSizeL(numUsedBytes, EUnaligned); |
|
413 iFormatter->AppendFormatL(_L(")\r\n")); |
|
414 } |
|
415 else |
|
416 { |
|
417 iFormatter->AppendFormatL(_L("%d bytes)\r\n"), numUsedBytes); |
|
418 } |
|
419 } |
|
420 CleanupStack::PopAndDestroy(stackBuf); |
|
421 } |
|
422 #endif // FSHELL_MEMORY_ACCESS_SUPPORT |
|
423 } |
|
424 } |
|
425 #endif // EKA2 |
|
426 } |
|
427 |
|
428 #if defined(EKA2) && defined(FSHELL_MEMORY_ACCESS_SUPPORT) |
|
429 void CCmdPs::PrintHeapInfoL(RThread& aThread, const TDesC& aThreadName) |
|
430 { |
|
431 if (iPrintHeapInfo && iMemoryAccess.Handle()) |
|
432 { |
|
433 LtkUtils::RProxyAllocatorHelper allocHelper; |
|
434 CleanupClosePushL(allocHelper); |
|
435 TInt err = allocHelper.Open(iMemoryAccess, TUint(aThread.Id())); |
|
436 if (err) |
|
437 { |
|
438 PrintWarning(_L("Couldn't open allocator helper for thread %S: %d"), &aThreadName, err); |
|
439 } |
|
440 else |
|
441 { |
|
442 TInt committed = allocHelper.CommittedSize(); |
|
443 TInt alloced = allocHelper.AllocatedSize(); |
|
444 PrintSizeL(_L("\t\t\tHeap size: "), committed); |
|
445 iFormatter->AppendFormatL(_L("\t\t\tAlloc count: %d\r\n"), allocHelper.AllocationCount()); |
|
446 PrintSizeL(_L("\t\t\tAlloc size: "), alloced); |
|
447 } |
|
448 CleanupStack::PopAndDestroy(&allocHelper); |
|
449 } |
|
450 } |
|
451 #else |
|
452 void CCmdPs::PrintHeapInfoL(RThread&, const TDesC&) |
|
453 { |
|
454 } |
|
455 #endif |
|
456 |
|
457 #ifdef EKA2 |
|
458 void CCmdPs::PrintCpuTimeL(RThread& aThread, const TDesC& aThreadName) |
|
459 { |
|
460 if (iPrintCpuTime) |
|
461 { |
|
462 TTimeIntervalMicroSeconds time; |
|
463 TInt err = aThread.GetCpuTime(time); |
|
464 if (err) |
|
465 { |
|
466 PrintWarning(_L("Unable to get CPU time for thread %S: %d"), &aThreadName, err); |
|
467 } |
|
468 else |
|
469 { |
|
470 iFormatter->AppendFormatL(_L("\t\t\tCPU time: %Lu\r\n"), time.Int64()); |
|
471 } |
|
472 } |
|
473 } |
|
474 #else |
|
475 void CCmdPs::PrintCpuTimeL(RThread&, const TDesC&) |
|
476 { |
|
477 } |
|
478 #endif |
|
479 |
|
480 void CCmdPs::PrintChunkInfoL(const TDesC& aProcessName) |
|
481 { |
|
482 if (iPrintChunkInfo) |
|
483 { |
|
484 iFormatter->AppendL(_L("\tChunks:\r\n")); |
|
485 TFindChunk findChunk(aProcessName); |
|
486 while (findChunk.Next(iChunkName) == KErrNone) |
|
487 { |
|
488 TPtrC shortChunkName(iChunkName.Mid(aProcessName.Length() - 1)); |
|
489 iFormatter->AppendFormatL(_L("\t\t%S\r\n"), &shortChunkName); |
|
490 #ifdef EKA2 |
|
491 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT |
|
492 if (iMemoryAccess.Handle()) |
|
493 { |
|
494 TChunkKernelInfo chunkInfo; |
|
495 TPckg<TChunkKernelInfo> chunkInfoPckg(chunkInfo); |
|
496 TInt err = iMemoryAccess.GetObjectInfo(EChunk, iChunkName, chunkInfoPckg); |
|
497 if (err) |
|
498 { |
|
499 PrintWarning(_L("Unable to get info for chunk %S: %d"), &iChunkName, err); |
|
500 } |
|
501 else |
|
502 { |
|
503 iFormatter->AppendFormatL(_L("\t\t\tAddress: 0x%08x\r\n"), chunkInfo.iAddressOfKernelObject); |
|
504 PrintSizeL(_L("\t\t\tSize: "), chunkInfo.iSize); |
|
505 PrintSizeL(_L("\t\t\tMax size: "), chunkInfo.iMaxSize); |
|
506 iFormatter->AppendFormatL(_L("\t\t\tType: %d\r\n"), chunkInfo.iChunkType); |
|
507 } |
|
508 } |
|
509 #endif // FSHELL_MEMORY_ACCESS_SUPPORT |
|
510 #else // !EKA2 |
|
511 RChunk chunk; |
|
512 TInt err = chunk.Open(findChunk); |
|
513 if (err) |
|
514 { |
|
515 PrintWarning(_L("Unable to open chunk %S: %d"), &iChunkName, err); |
|
516 } |
|
517 else |
|
518 { |
|
519 CleanupClosePushL(chunk); |
|
520 PrintSizeL(_L("\t\t\tSize: "), chunk.Size()); |
|
521 PrintSizeL(_L("\t\t\tMax size: "), chunk.MaxSize()); |
|
522 CleanupStack::PopAndDestroy(&chunk); |
|
523 } |
|
524 #endif // EKA2 |
|
525 } |
|
526 } |
|
527 } |
|
528 |
|
529 void CCmdPs::PrintSizeL(const TDesC& aCaption, TInt aSize) |
|
530 { |
|
531 if (iHuman) |
|
532 { |
|
533 iFormatter->AppendL(aCaption); |
|
534 iFormatter->AppendHumanReadableSizeL(aSize, EUnaligned); |
|
535 _LIT(KNewLine, "\r\n"); |
|
536 iFormatter->AppendL(KNewLine); |
|
537 } |
|
538 else |
|
539 { |
|
540 _LIT(KFormat, "%S%d\r\n"); |
|
541 iFormatter->AppendFormatL(KFormat, &aCaption, aSize); |
|
542 } |
|
543 } |
|
544 |
|
545 #ifdef EXE_BUILD |
|
546 EXE_BOILER_PLATE(CCmdPs) |
|
547 #endif |
|
548 |