return Status;\r
}\r
\r
+/**\r
+ For a given canonical pathname (as defined at VirtioFsAppendPath()), look up\r
+ the NodeId of the most specific parent directory, plus output a pointer to\r
+ the last pathname component (which is therefore a direct child of said parent\r
+ directory).\r
+\r
+ The function may only be called after VirtioFsFuseInitSession() returns\r
+ successfully and before VirtioFsUninit() is called.\r
+\r
+ @param[in,out] VirtioFs The Virtio Filesystem device to send FUSE_LOOKUP\r
+ and FUSE_FORGET requests to. On output, the FUSE\r
+ request counter "VirtioFs->RequestId" will have\r
+ been incremented several times.\r
+\r
+ @param[in,out] Path The canonical pathname (as defined in the\r
+ description of VirtioFsAppendPath()) to split.\r
+ Path is modified in-place temporarily; however, on\r
+ return (successful or otherwise), Path reassumes\r
+ its original contents.\r
+\r
+ @param[out] DirNodeId The NodeId of the most specific parent directory\r
+ identified by Path. The caller is responsible for\r
+ sending a FUSE_FORGET request to the Virtio\r
+ Filesystem device for DirNodeId -- unless\r
+ DirNodeId equals VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID\r
+ --, when DirNodeId's use ends.\r
+\r
+ @param[out] LastComponent A pointer into Path, pointing at the start of the\r
+ last pathname component.\r
+\r
+ @retval EFI_SUCCESS Splitting successful.\r
+\r
+ @retval EFI_INVALID_PARAMETER Path is "/".\r
+\r
+ @retval EFI_ACCESS_DENIED One of the components on Path before the last\r
+ is not a directory.\r
+\r
+ @return Error codes propagated from\r
+ VirtioFsFuseLookup() and\r
+ VirtioFsFuseAttrToEfiFileInfo().\r
+**/\r
+EFI_STATUS\r
+VirtioFsLookupMostSpecificParentDir (\r
+ IN OUT VIRTIO_FS *VirtioFs,\r
+ IN OUT CHAR8 *Path,\r
+ OUT UINT64 *DirNodeId,\r
+ OUT CHAR8 **LastComponent\r
+ )\r
+{\r
+ UINT64 ParentDirNodeId;\r
+ CHAR8 *Slash;\r
+ EFI_STATUS Status;\r
+ UINT64 NextDirNodeId;\r
+\r
+ if (AsciiStrCmp (Path, "/") == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ParentDirNodeId = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;\r
+ Slash = Path;\r
+ for (;;) {\r
+ CHAR8 *NextSlash;\r
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r
+ EFI_FILE_INFO FileInfo;\r
+\r
+ //\r
+ // Find the slash (if any) that terminates the next pathname component.\r
+ //\r
+ NextSlash = AsciiStrStr (Slash + 1, "/");\r
+ if (NextSlash == NULL) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Temporarily replace the found slash character with a NUL in-place, for\r
+ // easy construction of the single-component filename that we need to look\r
+ // up.\r
+ //\r
+ *NextSlash = '\0';\r
+ Status = VirtioFsFuseLookup (VirtioFs, ParentDirNodeId, Slash + 1,\r
+ &NextDirNodeId, &FuseAttr);\r
+ *NextSlash = '/';\r
+\r
+ //\r
+ // We're done with the directory inode that was the basis for the lookup.\r
+ //\r
+ if (ParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {\r
+ VirtioFsFuseForget (VirtioFs, ParentDirNodeId);\r
+ }\r
+\r
+ //\r
+ // If we couldn't look up the next *non-final* pathname component, bail.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Lookup successful; now check if the next (non-final) component is a\r
+ // directory. If not, bail.\r
+ //\r
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ForgetNextDirNodeId;\r
+ }\r
+ if ((FileInfo.Attribute & EFI_FILE_DIRECTORY) == 0) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ForgetNextDirNodeId;\r
+ }\r
+\r
+ //\r
+ // Advance.\r
+ //\r
+ ParentDirNodeId = NextDirNodeId;\r
+ Slash = NextSlash;\r
+ }\r
+\r
+ //\r
+ // ParentDirNodeId corresponds to the last containing directory. The\r
+ // remaining single-component filename represents a direct child under that\r
+ // directory. Said filename starts at (Slash + 1).\r
+ //\r
+ *DirNodeId = ParentDirNodeId;\r
+ *LastComponent = Slash + 1;\r
+ return EFI_SUCCESS;\r
+\r
+ForgetNextDirNodeId:\r
+ VirtioFsFuseForget (VirtioFs, NextDirNodeId);\r
+ return Status;\r
+}\r
+\r
/**\r
Convert select fields of a VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to\r
corresponding fields in EFI_FILE_INFO.\r