Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
6.7 KiB

  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. ls.c
  5. Abstract:
  6. Shell app "ls"
  7. Revision History
  8. --*/
  9. #include "shell.h"
  10. /*
  11. *
  12. */
  13. EFI_STATUS
  14. InitializeLS (
  15. IN EFI_HANDLE ImageHandle,
  16. IN EFI_SYSTEM_TABLE *SystemTable
  17. );
  18. VOID
  19. LsCurDir (
  20. IN CHAR16 *CurDir
  21. );
  22. VOID
  23. LsDir (
  24. IN SHELL_FILE_ARG *Arg
  25. );
  26. VOID
  27. LsDumpFileInfo (
  28. IN EFI_FILE_INFO *Info
  29. );
  30. /*
  31. *
  32. */
  33. CHAR16 *LsLastDir;
  34. UINTN LsCount;
  35. UINTN LsDirs;
  36. UINTN LsFiles;
  37. UINT64 LsDirSize;
  38. UINT64 LsFileSize;
  39. UINTN LsTotalDirs;
  40. UINTN LsTotalFiles;
  41. UINT64 LsTotalDirSize;
  42. UINT64 LsTotalFileSize;
  43. BOOLEAN PageBreaks;
  44. UINTN TempColumn;
  45. UINTN ScreenCount;
  46. UINTN ScreenSize;
  47. /*
  48. *
  49. */
  50. EFI_DRIVER_ENTRY_POINT(InitializeLS)
  51. EFI_STATUS
  52. InitializeLS (
  53. IN EFI_HANDLE ImageHandle,
  54. IN EFI_SYSTEM_TABLE *SystemTable
  55. )
  56. {
  57. CHAR16 **Argv;
  58. UINTN Argc;
  59. CHAR16 *p;
  60. UINTN Index;
  61. LIST_ENTRY DirList;
  62. LIST_ENTRY *Link;
  63. SHELL_FILE_ARG *Arg;
  64. /*
  65. * Check to see if the app is to install as a "internal command"
  66. * to the shell
  67. */
  68. InstallInternalShellCommand (
  69. ImageHandle, SystemTable, InitializeLS,
  70. L"ls", /* command */
  71. L"ls [-b] [dir] [dir] ...", /* command syntax */
  72. L"Obtain directory listing", /* 1 line descriptor */
  73. NULL /* command help page */
  74. );
  75. /*
  76. * We are no being installed as an internal command driver, initialize
  77. * as an nshell app and run
  78. */
  79. InitializeShellApplication (ImageHandle, SystemTable);
  80. Argv = SI->Argv;
  81. Argc = SI->Argc;
  82. LsTotalDirs = 0;
  83. LsTotalFiles = 0;
  84. LsTotalDirSize = 0;
  85. LsTotalFileSize = 0;
  86. LsLastDir = NULL;
  87. LsCount = 0;
  88. InitializeListHead (&DirList);
  89. /*
  90. * Scan args for flags
  91. */
  92. PageBreaks = FALSE;
  93. for (Index = 1; Index < Argc; Index += 1) {
  94. if (Argv[Index][0] == '-') {
  95. for (p = Argv[Index]+1; *p; p++) {
  96. switch (*p) {
  97. case 'b' :
  98. case 'B' :
  99. PageBreaks = TRUE;
  100. ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
  101. ScreenCount = 0;
  102. break;
  103. default:
  104. Print (L"ls: Unkown flag %s\n", Argv[Index]);
  105. goto Done;
  106. }
  107. }
  108. }
  109. }
  110. /*
  111. * Dir each directory indicated by the args
  112. */
  113. for (Index = 1; Index < Argc; Index += 1) {
  114. if (Argv[Index][0] != '-') {
  115. ShellFileMetaArg (Argv[Index], &DirList);
  116. }
  117. }
  118. /*
  119. * If no directory arguments supplied, then dir the current directory
  120. */
  121. if (IsListEmpty(&DirList)) {
  122. ShellFileMetaArg(L".", &DirList);
  123. }
  124. /*
  125. * Perform dir's on the directories
  126. */
  127. for (Link=DirList.Flink; Link!=&DirList; Link=Link->Flink) {
  128. Arg = CR(Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
  129. LsDir (Arg);
  130. }
  131. /*
  132. * Dump final totals
  133. */
  134. LsCurDir (NULL);
  135. if (LsCount > 1) {
  136. Print (L"\n Total %10,d File%c %12,ld bytes",
  137. LsTotalFiles,
  138. LsTotalFiles <= 1 ? ' ':'s',
  139. LsTotalFileSize
  140. );
  141. Print (L"\n Total %10,d Dir%c %12,ld bytes\n\n",
  142. LsTotalDirs,
  143. LsTotalDirs <= 1 ? ' ':'s',
  144. LsTotalDirSize
  145. );
  146. }
  147. Done:
  148. ShellFreeFileList (&DirList);
  149. return EFI_SUCCESS;
  150. }
  151. VOID
  152. LsCurDir (
  153. IN CHAR16 *CurDir
  154. )
  155. {
  156. if (!LsLastDir || !CurDir || StriCmp(LsLastDir, CurDir)) {
  157. if (LsLastDir) {
  158. Print (L"\n %10,d File%c %12,ld bytes",
  159. LsFiles,
  160. LsFiles <= 1 ? ' ':'s',
  161. LsFileSize
  162. );
  163. Print (L"\n %10,d Dir%c %12,ld bytes\n\n",
  164. LsDirs,
  165. LsDirs <= 1 ? ' ':'s',
  166. LsTotalDirSize
  167. );
  168. LsCount += 1;
  169. }
  170. LsDirs = 0;
  171. LsFiles = 0;
  172. LsDirSize = 0;
  173. LsFileSize = 0;
  174. LsLastDir = CurDir;
  175. if (CurDir) {
  176. Print (L"Directory of %hs\n", CurDir);
  177. }
  178. }
  179. }
  180. VOID
  181. LsDir (
  182. IN SHELL_FILE_ARG *Arg
  183. )
  184. {
  185. EFI_FILE_INFO *Info;
  186. UINTN BufferSize, bs;
  187. EFI_STATUS Status;
  188. Info = NULL;
  189. if (EFI_ERROR(Arg->Status)) {
  190. Print(L"ls: could not list file %hs - %r\n", Arg->FullName, Arg->Status);
  191. goto Done;
  192. }
  193. BufferSize = SIZE_OF_EFI_FILE_INFO + 1024;
  194. Info = AllocatePool (BufferSize);
  195. if (!Info) {
  196. goto Done;
  197. }
  198. if (Arg->Info->Attribute & EFI_FILE_DIRECTORY) {
  199. /* BUGBUG: dump volume info here */
  200. LsCurDir (Arg->FullName);
  201. /*
  202. * Read all the file entries
  203. */
  204. Arg->Handle->SetPosition (Arg->Handle, 0);
  205. for (; ;) {
  206. bs = BufferSize;
  207. Status = Arg->Handle->Read (Arg->Handle, &bs, Info);
  208. if (EFI_ERROR(Status)) {
  209. goto Done;
  210. }
  211. if (bs == 0) {
  212. break;
  213. }
  214. LsDumpFileInfo (Info);
  215. }
  216. } else {
  217. /* Dump the single file */
  218. LsCurDir (Arg->ParentName);
  219. LsDumpFileInfo (Arg->Info);
  220. }
  221. Done:
  222. if (Info) {
  223. FreePool (Info);
  224. }
  225. }
  226. VOID
  227. LsDumpFileInfo (
  228. IN EFI_FILE_INFO *Info
  229. )
  230. {
  231. CHAR16 ReturnStr[1];
  232. Print (L" %t %s %c %11,ld ",
  233. &Info->ModificationTime,
  234. Info->Attribute & EFI_FILE_DIRECTORY ? L"<DIR>" : L" ",
  235. Info->Attribute & EFI_FILE_READ_ONLY ? 'r' : ' ',
  236. Info->FileSize,
  237. Info->FileName
  238. );
  239. Print (L"%s\n", Info->FileName);
  240. if (Info->Attribute & EFI_FILE_DIRECTORY) {
  241. LsTotalDirs++;
  242. LsDirs++;
  243. LsTotalDirSize += Info->FileSize;
  244. LsDirSize += Info->FileSize;
  245. } else {
  246. LsTotalFiles++;
  247. LsFiles++;
  248. LsTotalFileSize += Info->FileSize;
  249. LsFileSize += Info->FileSize;
  250. }
  251. if (PageBreaks) {
  252. ScreenCount++;
  253. if (ScreenCount > ScreenSize - 4) {
  254. ScreenCount = 0;
  255. Print (L"\nPress Return to contiue :");
  256. Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
  257. Print (L"\n\n");
  258. }
  259. }
  260. }