]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg/ShellProtocol: sort files by FullName in RemoveDupInFileList()
authorLaszlo Ersek <lersek@redhat.com>
Wed, 13 Jan 2021 08:54:51 +0000 (09:54 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Tue, 19 Jan 2021 18:23:28 +0000 (18:23 +0000)
The current implementation of EfiShellRemoveDupInFileList():
- has quadratic time complexity, as a disadvantage, and
- needs no dynamic memory, as an advantage.

Because the UEFI Shell Spec requires
EFI_SHELL_PROTOCOL.RemoveDupInFileList() to succeed at all times, keep the
current method as a fallback (it cannot fail due to needing no dynamic
memory).

However, as a higher priority option, call the new ShellSortFileList()
function at first, separating out and releasing duplicates.
(ShellSortFileList() can fail due to EFI_OUT_OF_RESOURCES.)

Beyond improving the runtime of EfiShellRemoveDupInFileList(), this change
has the extremely desirable effect that the ShellOpenFileMetaArg()
function in the ShellPkg/Library/UefiShellLib instance will produce file
lists that are sorted by FullName.

Consequently, when used with wildcards, the ATTRIB, CP, FOR, LOAD,
LOADPCIROM, LS, MV, RM, TOUCH, TYPE commands will process files in
FullName order. (LS in recursive mode uses wildcards internally.)

Before:

> FS2:\> dir -r -sfo apps
> [...]
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\X64"
> FileInfo,"FS2:\apps\AARCH64"
> FileInfo,"FS2:\"
> FileInfo,"FS2:\apps\IA32"
> FileInfo,"FS2:\apps\X64\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\X64\SmiHandlerProfileInfo.efi"
> FileInfo,"FS2:\apps\X64\"
> FileInfo,"FS2:\apps\X64\VariableInfo.efi"
> FileInfo,"FS2:\apps\X64\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\X64\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\X64\Cpuid.efi"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\AARCH64\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\AARCH64\"
> FileInfo,"FS2:\apps\AARCH64\VariableInfo.efi"
> FileInfo,"FS2:\apps\AARCH64\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\AARCH64\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\IA32\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\IA32\SmiHandlerProfileInfo.efi"
> FileInfo,"FS2:\apps\IA32\"
> FileInfo,"FS2:\apps\IA32\VariableInfo.efi"
> FileInfo,"FS2:\apps\IA32\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\IA32\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\IA32\Cpuid.efi"
> FileInfo,"FS2:\apps\"

After:

> FS2:\> dir -r -sfo apps
> [...]
> FileInfo,"FS2:\"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\AARCH64"
> FileInfo,"FS2:\apps\IA32"
> FileInfo,"FS2:\apps\X64"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\AARCH64\"
> FileInfo,"FS2:\apps\AARCH64\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\AARCH64\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\AARCH64\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\AARCH64\VariableInfo.efi"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\IA32\"
> FileInfo,"FS2:\apps\IA32\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\IA32\Cpuid.efi"
> FileInfo,"FS2:\apps\IA32\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\IA32\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\IA32\SmiHandlerProfileInfo.efi"
> FileInfo,"FS2:\apps\IA32\VariableInfo.efi"
> FileInfo,"FS2:\apps\"
> FileInfo,"FS2:\apps\X64\"
> FileInfo,"FS2:\apps\X64\AcpiViewApp.efi"
> FileInfo,"FS2:\apps\X64\Cpuid.efi"
> FileInfo,"FS2:\apps\X64\DumpDynPcd.efi"
> FileInfo,"FS2:\apps\X64\MemoryProfileInfo.efi"
> FileInfo,"FS2:\apps\X64\SmiHandlerProfileInfo.efi"
> FileInfo,"FS2:\apps\X64\VariableInfo.efi"

Regarding LS in non-SFO mode, the stability of ShellSortFileList() shows.
The ShellSortFileList() call added to LS in the previous patch re-sorts
the output of ShellOpenFileMetaArg(); and so this patch improves the
ordering between identical FileNames:

Before:

> FS2:\> dir -r apps
> Directory of: FS2:\apps\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53 <DIR>         4,096  AARCH64
> 12/22/2020  17:53 <DIR>         4,096  IA32
> 12/22/2020  17:53 <DIR>         4,096  X64
>           0 File(s)           0 bytes
>           5 Dir(s)
> Directory of: FS2:\apps\X64\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             126,656  AcpiViewApp.efi
> 12/22/2020  17:53              38,784  Cpuid.efi
> 12/22/2020  17:52              18,752  DumpDynPcd.efi
> 12/22/2020  17:52              26,304  MemoryProfileInfo.efi
> 12/22/2020  17:52              34,240  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              11,456  VariableInfo.efi
>           6 File(s)     256,192 bytes
>           2 Dir(s)
> Directory of: FS2:\apps\AARCH64\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             139,264  AcpiViewApp.efi
> 12/22/2020  17:52              32,768  DumpDynPcd.efi
> 12/22/2020  17:52              40,960  MemoryProfileInfo.efi
> 12/22/2020  17:52              20,480  VariableInfo.efi
>           4 File(s)     233,472 bytes
>           2 Dir(s)
> Directory of: FS2:\apps\IA32\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             105,536  AcpiViewApp.efi
> 12/22/2020  17:53              36,096  Cpuid.efi
> 12/22/2020  17:52              17,344  DumpDynPcd.efi
> 12/22/2020  17:52              24,192  MemoryProfileInfo.efi
> 12/22/2020  17:52              30,720  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              10,880  VariableInfo.efi
>           6 File(s)     224,768 bytes
>           2 Dir(s)
>
> FS2:\> dir apps\*\*.efi
> Directory of: FS2:\apps\*\
> 12/22/2020  17:53             126,656  AcpiViewApp.efi
> 12/22/2020  17:53             139,264  AcpiViewApp.efi
> 12/22/2020  17:53             105,536  AcpiViewApp.efi
> 12/22/2020  17:53              38,784  Cpuid.efi
> 12/22/2020  17:53              36,096  Cpuid.efi
> 12/22/2020  17:52              18,752  DumpDynPcd.efi
> 12/22/2020  17:52              32,768  DumpDynPcd.efi
> 12/22/2020  17:52              17,344  DumpDynPcd.efi
> 12/22/2020  17:52              26,304  MemoryProfileInfo.efi
> 12/22/2020  17:52              40,960  MemoryProfileInfo.efi
> 12/22/2020  17:52              24,192  MemoryProfileInfo.efi
> 12/22/2020  17:52              34,240  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              30,720  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              11,456  VariableInfo.efi
> 12/22/2020  17:52              20,480  VariableInfo.efi
> 12/22/2020  17:52              10,880  VariableInfo.efi
>          16 File(s)     714,432 bytes
>           0 Dir(s)

After:

> FS2:\> dir -r apps
> Directory of: FS2:\apps\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53 <DIR>         4,096  AARCH64
> 12/22/2020  17:53 <DIR>         4,096  IA32
> 12/22/2020  17:53 <DIR>         4,096  X64
>           0 File(s)           0 bytes
>           5 Dir(s)
> Directory of: FS2:\apps\AARCH64\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             139,264  AcpiViewApp.efi
> 12/22/2020  17:52              32,768  DumpDynPcd.efi
> 12/22/2020  17:52              40,960  MemoryProfileInfo.efi
> 12/22/2020  17:52              20,480  VariableInfo.efi
>           4 File(s)     233,472 bytes
>           2 Dir(s)
> Directory of: FS2:\apps\IA32\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             105,536  AcpiViewApp.efi
> 12/22/2020  17:53              36,096  Cpuid.efi
> 12/22/2020  17:52              17,344  DumpDynPcd.efi
> 12/22/2020  17:52              24,192  MemoryProfileInfo.efi
> 12/22/2020  17:52              30,720  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              10,880  VariableInfo.efi
>           6 File(s)     224,768 bytes
>           2 Dir(s)
> Directory of: FS2:\apps\X64\
> 01/01/1970  01:00 <DIR> r           0  .
> 01/01/1970  01:00 <DIR> r           0  ..
> 12/22/2020  17:53             126,656  AcpiViewApp.efi
> 12/22/2020  17:53              38,784  Cpuid.efi
> 12/22/2020  17:52              18,752  DumpDynPcd.efi
> 12/22/2020  17:52              26,304  MemoryProfileInfo.efi
> 12/22/2020  17:52              34,240  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              11,456  VariableInfo.efi
>           6 File(s)     256,192 bytes
>           2 Dir(s)
>
> FS2:\> dir apps\*\*.efi
> Directory of: FS2:\apps\*\
> 12/22/2020  17:53             139,264  AcpiViewApp.efi
> 12/22/2020  17:53             105,536  AcpiViewApp.efi
> 12/22/2020  17:53             126,656  AcpiViewApp.efi
> 12/22/2020  17:53              36,096  Cpuid.efi
> 12/22/2020  17:53              38,784  Cpuid.efi
> 12/22/2020  17:52              32,768  DumpDynPcd.efi
> 12/22/2020  17:52              17,344  DumpDynPcd.efi
> 12/22/2020  17:52              18,752  DumpDynPcd.efi
> 12/22/2020  17:52              40,960  MemoryProfileInfo.efi
> 12/22/2020  17:52              24,192  MemoryProfileInfo.efi
> 12/22/2020  17:52              26,304  MemoryProfileInfo.efi
> 12/22/2020  17:52              30,720  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              34,240  SmiHandlerProfileInfo.efi
> 12/22/2020  17:52              20,480  VariableInfo.efi
> 12/22/2020  17:52              10,880  VariableInfo.efi
> 12/22/2020  17:52              11,456  VariableInfo.efi
>          16 File(s)     714,432 bytes
>           0 Dir(s)

Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3151
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
Message-Id: <20210113085453.10168-9-lersek@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
ShellPkg/Application/Shell/ShellProtocol.c

index 4e639fe35e4f289f3ea0401d981646cd15c63555..e79c39058b3e5d1d9f0051931291625ed3799771 100644 (file)
@@ -1855,6 +1855,8 @@ EfiShellRemoveDupInFileList(
   IN EFI_SHELL_FILE_INFO **FileList\r
   )\r
 {\r
+  EFI_STATUS          Status;\r
+  EFI_SHELL_FILE_INFO *Duplicates;\r
   EFI_SHELL_FILE_INFO *ShellFileListItem;\r
   EFI_SHELL_FILE_INFO *ShellFileListItem2;\r
   EFI_SHELL_FILE_INFO *TempNode;\r
@@ -1862,6 +1864,20 @@ EfiShellRemoveDupInFileList(
   if (FileList == NULL || *FileList == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
+\r
+  Status = ShellSortFileList (\r
+             FileList,\r
+             &Duplicates,\r
+             ShellSortFileListByFullName\r
+             );\r
+  if (!EFI_ERROR (Status)) {\r
+    EfiShellFreeFileList (&Duplicates);\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Fall back to the slow method that needs no extra memory, and so cannot\r
+  // fail.\r
+  //\r
   for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)\r
       ; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link)\r
       ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link)\r