]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VirtioFsDxe: add helper for determining access time updates
authorLaszlo Ersek <lersek@redhat.com>
Wed, 16 Dec 2020 21:11:23 +0000 (22:11 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 21 Dec 2020 17:16:23 +0000 (17:16 +0000)
Add the VirtioFsGetFuseTimeUpdates() function, for determining whether an
EFI_FILE_PROTOCOL.SetInfo() invocation requests access time updates.

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-47-lersek@redhat.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
[lersek@redhat.com: suppress bogus VS2019 warning about lack of
 initialization for ZeroTime]

OvmfPkg/VirtioFsDxe/Helpers.c
OvmfPkg/VirtioFsDxe/VirtioFsDxe.h

index d13bd8c6c9d2a730bc1ee3183f9c3d38ddb7ffcf..c56c60640ad64ac702eade55363f331e91b5c327 100644 (file)
@@ -2213,3 +2213,109 @@ VirtioFsGetFuseSizeUpdate (
   *Update = TRUE;\r
   *Size = NewInfo->FileSize;\r
 }\r
+\r
+/**\r
+  Given an EFI_FILE_INFO object received in an EFI_FILE_PROTOCOL.SetInfo()\r
+  call, determine whether updating the last access time and/or the last\r
+  modification time of the file is necessary, relative to an EFI_FILE_INFO\r
+  object describing the current state of the file.\r
+\r
+  @param[in] Info          The EFI_FILE_INFO describing the current state of\r
+                           the file. The caller is responsible for populating\r
+                           Info on input with VirtioFsFuseAttrToEfiFileInfo(),\r
+                           from the current FUSE attributes of the file. The\r
+                           Info->Size and Info->FileName members are ignored.\r
+\r
+  @param[in] NewInfo       The EFI_FILE_INFO object received in the\r
+                           EFI_FILE_PROTOCOL.SetInfo() call.\r
+\r
+  @param[out] UpdateAtime  Set to TRUE on output if the last access time needs\r
+                           to be updated. Set to FALSE otherwise.\r
+\r
+  @param[out] UpdateMtime  Set to TRUE on output if the last modification time\r
+                           needs to be updated. Set to FALSE otherwise.\r
+\r
+  @param[out] Atime        If UpdateAtime is set to TRUE, then Atime provides\r
+                           the last access timestamp to set (as seconds since\r
+                           the Epoch). Otherwise, Atime is not written to.\r
+\r
+  @param[out] Mtime        If UpdateMtime is set to TRUE, then Mtime provides\r
+                           the last modification timestamp to set (as seconds\r
+                           since the Epoch). Otherwise, Mtime is not written\r
+                           to.\r
+\r
+  @retval EFI_SUCCESS        Output parameters have been set successfully.\r
+\r
+  @retval EFI_ACCESS_DENIED  NewInfo requests changing both CreateTime and\r
+                             ModificationTime, but to values that differ from\r
+                             each other. The Virtio Filesystem device does not\r
+                             support this.\r
+**/\r
+EFI_STATUS\r
+VirtioFsGetFuseTimeUpdates (\r
+  IN     EFI_FILE_INFO *Info,\r
+  IN     EFI_FILE_INFO *NewInfo,\r
+     OUT BOOLEAN       *UpdateAtime,\r
+     OUT BOOLEAN       *UpdateMtime,\r
+     OUT UINT64        *Atime,\r
+     OUT UINT64        *Mtime\r
+  )\r
+{\r
+  EFI_TIME              *Time[3];\r
+  EFI_TIME              *NewTime[ARRAY_SIZE (Time)];\r
+  UINTN                 Idx;\r
+  STATIC CONST EFI_TIME ZeroTime = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\r
+  BOOLEAN               Change[ARRAY_SIZE (Time)];\r
+  UINT64                Seconds[ARRAY_SIZE (Time)];\r
+\r
+  Time[0]    = &Info->CreateTime;\r
+  Time[1]    = &Info->LastAccessTime;\r
+  Time[2]    = &Info->ModificationTime;\r
+  NewTime[0] = &NewInfo->CreateTime;\r
+  NewTime[1] = &NewInfo->LastAccessTime;\r
+  NewTime[2] = &NewInfo->ModificationTime;\r
+\r
+  //\r
+  // Determine which timestamps differ from the current state. (A zero time\r
+  // means "don't update", per UEFI spec.) For each timestamp that's being\r
+  // changed, calculate the seconds since the Epoch.\r
+  //\r
+  for (Idx = 0; Idx < ARRAY_SIZE (Time); Idx++) {\r
+    if (CompareMem (NewTime[Idx], &ZeroTime, sizeof (EFI_TIME)) == 0 ||\r
+        CompareMem (NewTime[Idx], Time[Idx], sizeof (EFI_TIME)) == 0) {\r
+      Change[Idx] = FALSE;\r
+    } else {\r
+      Change[Idx] = TRUE;\r
+      Seconds[Idx] = EfiTimeToEpoch (NewTime[Idx]);\r
+    }\r
+  }\r
+\r
+  //\r
+  // If a change is requested for exactly one of CreateTime and\r
+  // ModificationTime, we'll change the last modification time. If changes are\r
+  // requested for both, and to the same timestamp, we'll similarly update the\r
+  // last modification time. If changes are requested for both, but to\r
+  // different timestamps, we reject the request.\r
+  //\r
+  if (Change[0] && Change[2] && Seconds[0] != Seconds[2]) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  *UpdateAtime = FALSE;\r
+  *UpdateMtime = FALSE;\r
+\r
+  if (Change[0]) {\r
+    *UpdateMtime = TRUE;\r
+    *Mtime = Seconds[0];\r
+  }\r
+  if (Change[1]) {\r
+    *UpdateAtime = TRUE;\r
+    *Atime = Seconds[1];\r
+  }\r
+  if (Change[2]) {\r
+    *UpdateMtime = TRUE;\r
+    *Mtime = Seconds[2];\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
index 0967563029423118eef421cb288ab6998acc84f0..4331cabbd40e7e8c754aa6c5a70633d3deca4ca2 100644 (file)
@@ -290,6 +290,16 @@ VirtioFsGetFuseSizeUpdate (
      OUT UINT64        *Size\r
   );\r
 \r
+EFI_STATUS\r
+VirtioFsGetFuseTimeUpdates (\r
+  IN     EFI_FILE_INFO *Info,\r
+  IN     EFI_FILE_INFO *NewInfo,\r
+     OUT BOOLEAN       *UpdateAtime,\r
+     OUT BOOLEAN       *UpdateMtime,\r
+     OUT UINT64        *Atime,\r
+     OUT UINT64        *Mtime\r
+  );\r
+\r
 //\r
 // Wrapper functions for FUSE commands (primitives).\r
 //\r