FuseMkDir.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /** @file
  2. FUSE_MKDIR wrapper for the Virtio Filesystem device.
  3. Copyright (C) 2020, Red Hat, Inc.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/BaseLib.h> // AsciiStrSize()
  7. #include "VirtioFsDxe.h"
  8. /**
  9. Send a FUSE_MKDIR request to the Virtio Filesystem device, for creating a
  10. directory.
  11. The function may only be called after VirtioFsFuseInitSession() returns
  12. successfully and before VirtioFsUninit() is called.
  13. @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_MKDIR
  14. request to. On output, the FUSE request counter
  15. "VirtioFs->RequestId" will have been incremented.
  16. @param[in] ParentNodeId The inode number of the direct parent directory of
  17. the directory to create.
  18. @param[in] Name The single-component filename of the directory to
  19. create, under the parent directory identified by
  20. ParentNodeId.
  21. @param[out] NodeId The inode number of the new directory.
  22. @retval EFI_SUCCESS The directory has been created.
  23. @return The "errno" value mapped to an EFI_STATUS code, if the
  24. Virtio Filesystem device explicitly reported an error.
  25. @return Error codes propagated from VirtioFsSgListsValidate(),
  26. VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
  27. VirtioFsFuseCheckResponse().
  28. **/
  29. EFI_STATUS
  30. VirtioFsFuseMkDir (
  31. IN OUT VIRTIO_FS *VirtioFs,
  32. IN UINT64 ParentNodeId,
  33. IN CHAR8 *Name,
  34. OUT UINT64 *NodeId
  35. )
  36. {
  37. VIRTIO_FS_FUSE_REQUEST CommonReq;
  38. VIRTIO_FS_FUSE_MKDIR_REQUEST MkDirReq;
  39. VIRTIO_FS_IO_VECTOR ReqIoVec[3];
  40. VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
  41. VIRTIO_FS_FUSE_RESPONSE CommonResp;
  42. VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
  43. VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
  44. VIRTIO_FS_IO_VECTOR RespIoVec[3];
  45. VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
  46. EFI_STATUS Status;
  47. //
  48. // Set up the scatter-gather lists.
  49. //
  50. ReqIoVec[0].Buffer = &CommonReq;
  51. ReqIoVec[0].Size = sizeof CommonReq;
  52. ReqIoVec[1].Buffer = &MkDirReq;
  53. ReqIoVec[1].Size = sizeof MkDirReq;
  54. ReqIoVec[2].Buffer = Name;
  55. ReqIoVec[2].Size = AsciiStrSize (Name);
  56. ReqSgList.IoVec = ReqIoVec;
  57. ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
  58. RespIoVec[0].Buffer = &CommonResp;
  59. RespIoVec[0].Size = sizeof CommonResp;
  60. RespIoVec[1].Buffer = &NodeResp;
  61. RespIoVec[1].Size = sizeof NodeResp;
  62. RespIoVec[2].Buffer = &AttrResp;
  63. RespIoVec[2].Size = sizeof AttrResp;
  64. RespSgList.IoVec = RespIoVec;
  65. RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
  66. //
  67. // Validate the scatter-gather lists; calculate the total transfer sizes.
  68. //
  69. Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
  70. if (EFI_ERROR (Status)) {
  71. return Status;
  72. }
  73. //
  74. // Populate the common request header.
  75. //
  76. Status = VirtioFsFuseNewRequest (
  77. VirtioFs,
  78. &CommonReq,
  79. ReqSgList.TotalSize,
  80. VirtioFsFuseOpMkDir,
  81. ParentNodeId
  82. );
  83. if (EFI_ERROR (Status)) {
  84. return Status;
  85. }
  86. //
  87. // Populate the FUSE_MKDIR-specific fields.
  88. //
  89. MkDirReq.Mode = (VIRTIO_FS_FUSE_MODE_PERM_RWXU |
  90. VIRTIO_FS_FUSE_MODE_PERM_RWXG |
  91. VIRTIO_FS_FUSE_MODE_PERM_RWXO);
  92. MkDirReq.Umask = 0;
  93. //
  94. // Submit the request.
  95. //
  96. Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
  97. if (EFI_ERROR (Status)) {
  98. return Status;
  99. }
  100. //
  101. // Verify the response (all response buffers are fixed size).
  102. //
  103. Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
  104. if (EFI_ERROR (Status)) {
  105. if (Status == EFI_DEVICE_ERROR) {
  106. DEBUG ((
  107. DEBUG_ERROR,
  108. "%a: Label=\"%s\" ParentNodeId=%Lu Name=\"%a\" "
  109. "Errno=%d\n",
  110. __FUNCTION__,
  111. VirtioFs->Label,
  112. ParentNodeId,
  113. Name,
  114. CommonResp.Error
  115. ));
  116. Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
  117. }
  118. return Status;
  119. }
  120. //
  121. // Output the NodeId of the new directory.
  122. //
  123. *NodeId = NodeResp.NodeId;
  124. return EFI_SUCCESS;
  125. }