return Status;\r
}\r
\r
+/**\r
+ Update the attributes of a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.\r
+\r
+ @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to update the attributes of.\r
+\r
+ @param[in] NewFileInfo The new attributes requested by\r
+ EFI_FILE_PROTOCOL.SetInfo(). NewFileInfo->Size\r
+ and NewFileInfo->FileName are ignored.\r
+\r
+ @retval EFI_SUCCESS No attributes had to be updated.\r
+\r
+ @retval EFI_SUCCESS The required set of attribute updates has been\r
+ determined and performed successfully.\r
+\r
+ @retval EFI_ACCESS_DENIED NewFileInfo requests an update to a property\r
+ different from the EFI_FILE_READ_ONLY bit in the\r
+ Attribute field, but VirtioFsFile is not open for\r
+ writing.\r
+\r
+ @return Error codes propagated from underlying functions.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+UpdateAttributes (\r
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,\r
+ IN EFI_FILE_INFO *NewFileInfo\r
+ )\r
+{\r
+ VIRTIO_FS *VirtioFs;\r
+ EFI_STATUS Status;\r
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
+ EFI_FILE_INFO FileInfo;\r
+ BOOLEAN UpdateFileSize;\r
+ UINT64 FileSize;\r
+ BOOLEAN UpdateAtime;\r
+ BOOLEAN UpdateMtime;\r
+ UINT64 Atime;\r
+ UINT64 Mtime;\r
+ BOOLEAN UpdateMode;\r
+ UINT32 Mode;\r
+\r
+ VirtioFs = VirtioFsFile->OwnerFs;\r
+\r
+ //\r
+ // Fetch the current attributes first, so we can build the difference between\r
+ // them and NewFileInfo.\r
+ //\r
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Collect the updates.\r
+ //\r
+ if (VirtioFsFile->IsDirectory) {\r
+ UpdateFileSize = FALSE;\r
+ } else {\r
+ VirtioFsGetFuseSizeUpdate (&FileInfo, NewFileInfo, &UpdateFileSize,\r
+ &FileSize);\r
+ }\r
+\r
+ Status = VirtioFsGetFuseTimeUpdates (&FileInfo, NewFileInfo, &UpdateAtime,\r
+ &UpdateMtime, &Atime, &Mtime);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = VirtioFsGetFuseModeUpdate (&FileInfo, NewFileInfo, &UpdateMode,\r
+ &Mode);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // If no attribute updates are necessary, we're done.\r
+ //\r
+ if (!UpdateFileSize && !UpdateAtime && !UpdateMtime && !UpdateMode) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // If the file is not open for writing, then only Mode may be updated (for\r
+ // toggling EFI_FILE_READ_ONLY).\r
+ //\r
+ if (!VirtioFsFile->IsOpenForWriting &&\r
+ (UpdateFileSize || UpdateAtime || UpdateMtime)) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ //\r
+ // Send the FUSE_SETATTR request now.\r
+ //\r
+ Status = VirtioFsFuseSetAttr (\r
+ VirtioFs,\r
+ VirtioFsFile->NodeId,\r
+ UpdateFileSize ? &FileSize : NULL,\r
+ UpdateAtime ? &Atime : NULL,\r
+ UpdateMtime ? &Mtime : NULL,\r
+ UpdateMode ? &Mode : NULL\r
+ );\r
+ return Status;\r
+}\r
+\r
/**\r
Process an EFI_FILE_INFO setting request.\r
**/\r
//\r
// Update any attributes requested.\r
//\r
- Status = EFI_UNSUPPORTED;\r
+ Status = UpdateAttributes (VirtioFsFile, FileInfo);\r
//\r
// The UEFI spec does not speak about partial failure in\r
// EFI_FILE_PROTOCOL.SetInfo(); we won't try to roll back the rename (if\r