mirror of https://github.com/acidanthera/audk.git
OvmfPkg/VirtioFsDxe: add helper for composing rename/move destination path
The EFI_FILE_PROTOCOL.SetInfo() member is somewhat under-specified; one of its modes of operation is renaming/moving the file. In order to create the destination pathname in canonical format, 2*2=4 cases have to be considered. For the sake of discussion, assume the current canonical pathname of a VIRTIO_FS_FILE is "/home/user/f1.txt". Then, consider the following rename/move requests from EFI_FILE_PROTOCOL.SetInfo(): Destination requested Destination Move into Destination in by SetInfo() relative? directory? canonical format --------------------- ----------- ---------- ----------------------- L"\\dir\\f2.txt" no no "/dir/f2.txt" L"\\dir\\" no yes "/dir/f1.txt" L"dir\\f2.txt" yes no "/home/user/dir/f2.txt" L"dir\\" yes yes "/home/user/dir/f1.txt" Add the VirtioFsComposeRenameDestination() function, for composing the last column from the current canonical pathname and the SetInfo() input. The function works on the following principles: - The prefix of the destination path is "/", if the SetInfo() rename request is absolute. Otherwise, the dest prefix is the "current directory" (the most specific parent directory) of the original pathname (in the above example, "/home/user"). - The suffix of the destination path is precisely the SetInfo() request string, if the "move into directory" convenience format -- the trailing backslash -- is not used. (In the above example, L"\\dir\\f2.txt" and L"dir\\f2.txt".) Otherwise, the suffix is the SetInfo() request, plus the original basename (in the above example, L"\\dir\\f1.txt" and L"dir\\f1.txt"). - The complete destination is created by fusing the dest prefix and the dest suffix, using the VirtioFsAppendPath() function. Cc: Ard Biesheuvel <ard.biesheuvel@arm.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Philippe Mathieu-Daudé <philmd@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3097 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20201216211125.19496-43-lersek@redhat.com> Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
This commit is contained in:
parent
bea1f51d6e
commit
c3f76ef89d
|
@ -1783,6 +1783,200 @@ VirtioFsGetBasename (
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Format the destination of a rename/move operation as a dynamically allocated
|
||||||
|
canonical pathname.
|
||||||
|
|
||||||
|
Any dot-dot in RhsPath16 that would remove the root directory is dropped, and
|
||||||
|
reported through RootEscape, without failing the function call.
|
||||||
|
|
||||||
|
@param[in] LhsPath8 The source pathname operand of the rename/move
|
||||||
|
operation, expressed as a canonical pathname (as
|
||||||
|
defined in the description of VirtioFsAppendPath()).
|
||||||
|
The root directory "/" cannot be renamed/moved, and
|
||||||
|
will be rejected.
|
||||||
|
|
||||||
|
@param[in] RhsPath16 The destination pathname operand expressed as a
|
||||||
|
UEFI-style CHAR16 pathname.
|
||||||
|
|
||||||
|
If RhsPath16 starts with a backslash, then RhsPath16
|
||||||
|
is considered absolute. Otherwise, RhsPath16 is
|
||||||
|
interpreted relative to the most specific parent
|
||||||
|
directory found in LhsPath8.
|
||||||
|
|
||||||
|
Independently, if RhsPath16 ends with a backslash
|
||||||
|
(i.e., RhsPath16 is given in the "move into
|
||||||
|
directory" convenience form), then RhsPath16 is
|
||||||
|
interpreted with the basename of LhsPath8 appended.
|
||||||
|
Otherwise, the last pathname component of RhsPath16
|
||||||
|
is taken as the last pathname component of the
|
||||||
|
rename/move destination.
|
||||||
|
|
||||||
|
An empty RhsPath16 is rejected.
|
||||||
|
|
||||||
|
@param[out] ResultPath8 The POSIX-style, canonical format pathname that
|
||||||
|
leads to the renamed/moved file. After use, the
|
||||||
|
caller is responsible for freeing ResultPath8.
|
||||||
|
|
||||||
|
@param[out] RootEscape Set to TRUE if at least one dot-dot component in
|
||||||
|
RhsPath16 attempted to escape the root directory;
|
||||||
|
set to FALSE otherwise.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS ResultPath8 has been produced. RootEscape has
|
||||||
|
been output.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER LhsPath8 is "/".
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER RhsPath16 is zero-length.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER RhsPath16 failed the
|
||||||
|
VIRTIO_FS_MAX_PATHNAME_LENGTH check.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES ResultPath8 would have failed the
|
||||||
|
VIRTIO_FS_MAX_PATHNAME_LENGTH check.
|
||||||
|
|
||||||
|
@retval EFI_UNSUPPORTED RhsPath16 contains a character that either
|
||||||
|
falls outside of the printable ASCII set, or
|
||||||
|
is a forward slash.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
VirtioFsComposeRenameDestination (
|
||||||
|
IN CHAR8 *LhsPath8,
|
||||||
|
IN CHAR16 *RhsPath16,
|
||||||
|
OUT CHAR8 **ResultPath8,
|
||||||
|
OUT BOOLEAN *RootEscape
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Lengths are expressed as numbers of characters (CHAR8 or CHAR16),
|
||||||
|
// excluding terminating NULs. Sizes are expressed as byte counts, including
|
||||||
|
// the bytes taken up by terminating NULs.
|
||||||
|
//
|
||||||
|
UINTN RhsLen;
|
||||||
|
UINTN LhsBasename16Size;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN LhsBasenameLen;
|
||||||
|
UINTN DestSuffix16Size;
|
||||||
|
CHAR16 *DestSuffix16;
|
||||||
|
CHAR8 *DestPrefix8;
|
||||||
|
|
||||||
|
//
|
||||||
|
// An empty destination operand for the rename/move operation is not allowed.
|
||||||
|
//
|
||||||
|
RhsLen = StrLen (RhsPath16);
|
||||||
|
if (RhsLen == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Enforce length restriction on RhsPath16.
|
||||||
|
//
|
||||||
|
if (RhsLen > VIRTIO_FS_MAX_PATHNAME_LENGTH) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine the length of the basename of LhsPath8.
|
||||||
|
//
|
||||||
|
LhsBasename16Size = 0;
|
||||||
|
Status = VirtioFsGetBasename (LhsPath8, NULL, &LhsBasename16Size);
|
||||||
|
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||||
|
ASSERT (LhsBasename16Size >= sizeof (CHAR16));
|
||||||
|
ASSERT (LhsBasename16Size % sizeof (CHAR16) == 0);
|
||||||
|
LhsBasenameLen = LhsBasename16Size / sizeof (CHAR16) - 1;
|
||||||
|
if (LhsBasenameLen == 0) {
|
||||||
|
//
|
||||||
|
// The root directory cannot be renamed/moved.
|
||||||
|
//
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Resolve the "move into directory" convenience form in RhsPath16.
|
||||||
|
//
|
||||||
|
if (RhsPath16[RhsLen - 1] == L'\\') {
|
||||||
|
//
|
||||||
|
// Append the basename of LhsPath8 as a CHAR16 string to RhsPath16.
|
||||||
|
//
|
||||||
|
DestSuffix16Size = RhsLen * sizeof (CHAR16) + LhsBasename16Size;
|
||||||
|
DestSuffix16 = AllocatePool (DestSuffix16Size);
|
||||||
|
if (DestSuffix16 == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
CopyMem (DestSuffix16, RhsPath16, RhsLen * sizeof (CHAR16));
|
||||||
|
Status = VirtioFsGetBasename (LhsPath8, DestSuffix16 + RhsLen,
|
||||||
|
&LhsBasename16Size);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Just create a copy of RhsPath16.
|
||||||
|
//
|
||||||
|
DestSuffix16Size = (RhsLen + 1) * sizeof (CHAR16);
|
||||||
|
DestSuffix16 = AllocateCopyPool (DestSuffix16Size, RhsPath16);
|
||||||
|
if (DestSuffix16 == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the destination operand is absolute, it will be interpreted relative to
|
||||||
|
// the root directory.
|
||||||
|
//
|
||||||
|
// Otherwise (i.e., if the destination operand is relative), then create the
|
||||||
|
// canonical pathname that the destination operand is interpreted relatively
|
||||||
|
// to; that is, the canonical pathname of the most specific parent directory
|
||||||
|
// found in LhsPath8.
|
||||||
|
//
|
||||||
|
if (DestSuffix16[0] == L'\\') {
|
||||||
|
DestPrefix8 = AllocateCopyPool (sizeof "/", "/");
|
||||||
|
if (DestPrefix8 == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto FreeDestSuffix16;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UINTN LhsLen;
|
||||||
|
UINTN DestPrefixLen;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Strip the basename of LhsPath8.
|
||||||
|
//
|
||||||
|
LhsLen = AsciiStrLen (LhsPath8);
|
||||||
|
ASSERT (LhsBasenameLen < LhsLen);
|
||||||
|
DestPrefixLen = LhsLen - LhsBasenameLen;
|
||||||
|
ASSERT (LhsPath8[DestPrefixLen - 1] == '/');
|
||||||
|
//
|
||||||
|
// If we're not at the root directory, strip the slash too.
|
||||||
|
//
|
||||||
|
if (DestPrefixLen > 1) {
|
||||||
|
DestPrefixLen--;
|
||||||
|
}
|
||||||
|
DestPrefix8 = AllocatePool (DestPrefixLen + 1);
|
||||||
|
if (DestPrefix8 == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto FreeDestSuffix16;
|
||||||
|
}
|
||||||
|
CopyMem (DestPrefix8, LhsPath8, DestPrefixLen);
|
||||||
|
DestPrefix8[DestPrefixLen] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now combine DestPrefix8 and DestSuffix16 into the final canonical
|
||||||
|
// pathname.
|
||||||
|
//
|
||||||
|
Status = VirtioFsAppendPath (DestPrefix8, DestSuffix16, ResultPath8,
|
||||||
|
RootEscape);
|
||||||
|
|
||||||
|
FreePool (DestPrefix8);
|
||||||
|
//
|
||||||
|
// Fall through.
|
||||||
|
//
|
||||||
|
FreeDestSuffix16:
|
||||||
|
FreePool (DestSuffix16);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Convert select fields of a VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to
|
Convert select fields of a VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to
|
||||||
corresponding fields in EFI_FILE_INFO.
|
corresponding fields in EFI_FILE_INFO.
|
||||||
|
|
|
@ -262,6 +262,14 @@ VirtioFsGetBasename (
|
||||||
IN OUT UINTN *BasenameSize
|
IN OUT UINTN *BasenameSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
VirtioFsComposeRenameDestination (
|
||||||
|
IN CHAR8 *LhsPath8,
|
||||||
|
IN CHAR16 *RhsPath16,
|
||||||
|
OUT CHAR8 **ResultPath8,
|
||||||
|
OUT BOOLEAN *RootEscape
|
||||||
|
);
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
VirtioFsFuseAttrToEfiFileInfo (
|
VirtioFsFuseAttrToEfiFileInfo (
|
||||||
IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr,
|
IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr,
|
||||||
|
|
Loading…
Reference in New Issue