]>
Commit | Line | Data |
---|---|---|
334c13e1 LE |
1 | /** @file\r |
2 | EFI_FILE_PROTOCOL.Open() member function for the Virtio Filesystem driver.\r | |
3 | \r | |
4 | Copyright (C) 2020, Red Hat, Inc.\r | |
5 | \r | |
6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r | |
7 | **/\r | |
8 | \r | |
de0e1190 LE |
9 | #include <Library/BaseLib.h> // AsciiStrCmp()\r |
10 | #include <Library/MemoryAllocationLib.h> // AllocatePool()\r | |
11 | \r | |
334c13e1 LE |
12 | #include "VirtioFsDxe.h"\r |
13 | \r | |
de0e1190 LE |
14 | /**\r |
15 | Open the root directory, possibly for writing.\r | |
16 | \r | |
17 | @param[in,out] VirtioFs The Virtio Filesystem device whose root directory\r | |
18 | should be opened.\r | |
19 | \r | |
20 | @param[out] NewHandle The new EFI_FILE_PROTOCOL instance through which\r | |
21 | the root directory can be accessed.\r | |
22 | \r | |
23 | @param[in] OpenForWriting TRUE if the root directory should be opened for\r | |
24 | read-write access. FALSE if the root directory\r | |
25 | should be opened for read-only access. Opening the\r | |
26 | root directory for read-write access is useful for\r | |
27 | calling EFI_FILE_PROTOCOL.Flush() or\r | |
28 | EFI_FILE_PROTOCOL.SetInfo() later, for syncing or\r | |
29 | touching the root directory, respectively.\r | |
30 | \r | |
31 | @retval EFI_SUCCESS The root directory has been opened successfully.\r | |
32 | \r | |
33 | @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the root directory is\r | |
34 | marked as read-only.\r | |
35 | \r | |
36 | @return Error codes propagated from underlying functions.\r | |
37 | **/\r | |
38 | STATIC\r | |
39 | EFI_STATUS\r | |
40 | OpenRootDirectory (\r | |
ac0a286f MK |
41 | IN OUT VIRTIO_FS *VirtioFs,\r |
42 | OUT EFI_FILE_PROTOCOL **NewHandle,\r | |
43 | IN BOOLEAN OpenForWriting\r | |
de0e1190 LE |
44 | )\r |
45 | {\r | |
ac0a286f MK |
46 | EFI_STATUS Status;\r |
47 | VIRTIO_FS_FILE *NewVirtioFsFile;\r | |
de0e1190 LE |
48 | \r |
49 | //\r | |
50 | // VirtioFsOpenVolume() opens the root directory for read-only access. If the\r | |
51 | // current request is to open the root directory for read-write access, so\r | |
52 | // that EFI_FILE_PROTOCOL.Flush() or EFI_FILE_PROTOCOL.SetInfo()+timestamps\r | |
53 | // can be used on the root directory later, then we have to check for write\r | |
54 | // permission first.\r | |
55 | //\r | |
56 | if (OpenForWriting) {\r | |
ac0a286f MK |
57 | VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r |
58 | EFI_FILE_INFO FileInfo;\r | |
59 | \r | |
60 | Status = VirtioFsFuseGetAttr (\r | |
61 | VirtioFs,\r | |
62 | VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID,\r | |
63 | &FuseAttr\r | |
64 | );\r | |
de0e1190 LE |
65 | if (EFI_ERROR (Status)) {\r |
66 | return Status;\r | |
67 | }\r | |
ac0a286f | 68 | \r |
de0e1190 LE |
69 | Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r |
70 | if (EFI_ERROR (Status)) {\r | |
71 | return Status;\r | |
72 | }\r | |
ac0a286f | 73 | \r |
de0e1190 LE |
74 | if ((FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0) {\r |
75 | return EFI_ACCESS_DENIED;\r | |
76 | }\r | |
77 | }\r | |
78 | \r | |
79 | Status = VirtioFsOpenVolume (&VirtioFs->SimpleFs, NewHandle);\r | |
80 | if (EFI_ERROR (Status)) {\r | |
81 | return Status;\r | |
82 | }\r | |
83 | \r | |
ac0a286f | 84 | NewVirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (*NewHandle);\r |
de0e1190 LE |
85 | NewVirtioFsFile->IsOpenForWriting = OpenForWriting;\r |
86 | return EFI_SUCCESS;\r | |
87 | }\r | |
88 | \r | |
89 | /**\r | |
90 | Open an existent regular file or non-root directory.\r | |
91 | \r | |
92 | @param[in,out] VirtioFs The Virtio Filesystem device on which the\r | |
93 | regular file or directory should be opened.\r | |
94 | \r | |
95 | @param[in] DirNodeId The inode number of the immediate parent\r | |
96 | directory of the regular file or directory to\r | |
97 | open.\r | |
98 | \r | |
99 | @param[in] Name The single-component filename of the regular\r | |
100 | file or directory to open, under the immediate\r | |
101 | parent directory identified by DirNodeId.\r | |
102 | \r | |
103 | @param[in] OpenForWriting TRUE if the regular file or directory should be\r | |
104 | opened for read-write access. FALSE if the\r | |
105 | regular file or directory should be opened for\r | |
106 | read-only access. Opening a directory for\r | |
107 | read-write access is useful for deleting,\r | |
108 | renaming, syncing or touching the directory\r | |
109 | later.\r | |
110 | \r | |
111 | @param[out] NodeId The inode number of the regular file or\r | |
112 | directory, returned by the Virtio Filesystem\r | |
113 | device.\r | |
114 | \r | |
115 | @param[out] FuseHandle The open handle to the regular file or\r | |
116 | directory, returned by the Virtio Filesystem\r | |
117 | device.\r | |
118 | \r | |
119 | @param[out] NodeIsDirectory Set to TRUE on output if Name was found to refer\r | |
120 | to a directory. Set to FALSE if Name was found\r | |
121 | to refer to a regular file.\r | |
122 | \r | |
123 | @retval EFI_SUCCESS The regular file or directory has been looked up\r | |
124 | and opened successfully.\r | |
125 | \r | |
126 | @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the regular file or\r | |
127 | directory is marked read-only.\r | |
128 | \r | |
129 | @retval EFI_NOT_FOUND A directory entry called Name was not found in the\r | |
130 | directory identified by DirNodeId. (EFI_NOT_FOUND\r | |
131 | is not returned for any other condition.)\r | |
132 | \r | |
133 | @return Errors propagated from underlying functions. If\r | |
134 | the error code to propagate were EFI_NOT_FOUND, it\r | |
135 | is remapped to EFI_DEVICE_ERROR.\r | |
136 | **/\r | |
137 | STATIC\r | |
138 | EFI_STATUS\r | |
139 | OpenExistentFileOrDirectory (\r | |
ac0a286f MK |
140 | IN OUT VIRTIO_FS *VirtioFs,\r |
141 | IN UINT64 DirNodeId,\r | |
142 | IN CHAR8 *Name,\r | |
143 | IN BOOLEAN OpenForWriting,\r | |
144 | OUT UINT64 *NodeId,\r | |
145 | OUT UINT64 *FuseHandle,\r | |
146 | OUT BOOLEAN *NodeIsDirectory\r | |
de0e1190 LE |
147 | )\r |
148 | {\r | |
ac0a286f MK |
149 | EFI_STATUS Status;\r |
150 | UINT64 ResolvedNodeId;\r | |
151 | VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;\r | |
152 | EFI_FILE_INFO FileInfo;\r | |
153 | BOOLEAN IsDirectory;\r | |
154 | UINT64 NewFuseHandle;\r | |
155 | \r | |
156 | Status = VirtioFsFuseLookup (\r | |
157 | VirtioFs,\r | |
158 | DirNodeId,\r | |
159 | Name,\r | |
160 | &ResolvedNodeId,\r | |
161 | &FuseAttr\r | |
162 | );\r | |
de0e1190 LE |
163 | if (EFI_ERROR (Status)) {\r |
164 | return Status;\r | |
165 | }\r | |
ac0a286f | 166 | \r |
de0e1190 LE |
167 | Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);\r |
168 | if (EFI_ERROR (Status)) {\r | |
169 | goto ForgetResolvedNodeId;\r | |
170 | }\r | |
171 | \r | |
ac0a286f | 172 | if (OpenForWriting && ((FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0)) {\r |
de0e1190 LE |
173 | Status = EFI_ACCESS_DENIED;\r |
174 | goto ForgetResolvedNodeId;\r | |
175 | }\r | |
176 | \r | |
177 | IsDirectory = (BOOLEAN)((FileInfo.Attribute & EFI_FILE_DIRECTORY) != 0);\r | |
178 | if (IsDirectory) {\r | |
179 | //\r | |
180 | // If OpenForWriting is TRUE here, that's not passed to\r | |
181 | // VirtioFsFuseOpenDir(); it does not affect the FUSE_OPENDIR request we\r | |
182 | // send. OpenForWriting=TRUE will only permit attempts to delete, rename,\r | |
183 | // flush (sync), and touch the directory.\r | |
184 | //\r | |
185 | Status = VirtioFsFuseOpenDir (VirtioFs, ResolvedNodeId, &NewFuseHandle);\r | |
186 | } else {\r | |
ac0a286f MK |
187 | Status = VirtioFsFuseOpen (\r |
188 | VirtioFs,\r | |
189 | ResolvedNodeId,\r | |
190 | OpenForWriting,\r | |
191 | &NewFuseHandle\r | |
192 | );\r | |
de0e1190 | 193 | }\r |
ac0a286f | 194 | \r |
de0e1190 LE |
195 | if (EFI_ERROR (Status)) {\r |
196 | goto ForgetResolvedNodeId;\r | |
197 | }\r | |
198 | \r | |
199 | *NodeId = ResolvedNodeId;\r | |
200 | *FuseHandle = NewFuseHandle;\r | |
201 | *NodeIsDirectory = IsDirectory;\r | |
202 | return EFI_SUCCESS;\r | |
203 | \r | |
204 | ForgetResolvedNodeId:\r | |
205 | VirtioFsFuseForget (VirtioFs, ResolvedNodeId);\r | |
206 | return (Status == EFI_NOT_FOUND) ? EFI_DEVICE_ERROR : Status;\r | |
207 | }\r | |
208 | \r | |
209 | /**\r | |
210 | Create a directory.\r | |
211 | \r | |
212 | @param[in,out] VirtioFs The Virtio Filesystem device on which the directory\r | |
213 | should be created.\r | |
214 | \r | |
215 | @param[in] DirNodeId The inode number of the immediate parent directory\r | |
216 | of the directory to create.\r | |
217 | \r | |
218 | @param[in] Name The single-component filename of the directory to\r | |
219 | create, under the immediate parent directory\r | |
220 | identified by DirNodeId.\r | |
221 | \r | |
222 | @param[out] NodeId The inode number of the directory created, returned\r | |
223 | by the Virtio Filesystem device.\r | |
224 | \r | |
225 | @param[out] FuseHandle The open handle to the directory created, returned\r | |
226 | by the Virtio Filesystem device.\r | |
227 | \r | |
228 | @retval EFI_SUCCESS The directory has been created successfully.\r | |
229 | \r | |
230 | @return Errors propagated from underlying functions.\r | |
231 | **/\r | |
232 | STATIC\r | |
233 | EFI_STATUS\r | |
234 | CreateDirectory (\r | |
ac0a286f MK |
235 | IN OUT VIRTIO_FS *VirtioFs,\r |
236 | IN UINT64 DirNodeId,\r | |
237 | IN CHAR8 *Name,\r | |
238 | OUT UINT64 *NodeId,\r | |
239 | OUT UINT64 *FuseHandle\r | |
de0e1190 LE |
240 | )\r |
241 | {\r | |
ac0a286f MK |
242 | EFI_STATUS Status;\r |
243 | UINT64 NewChildDirNodeId;\r | |
244 | UINT64 NewFuseHandle;\r | |
de0e1190 LE |
245 | \r |
246 | Status = VirtioFsFuseMkDir (VirtioFs, DirNodeId, Name, &NewChildDirNodeId);\r | |
247 | if (EFI_ERROR (Status)) {\r | |
248 | return Status;\r | |
249 | }\r | |
250 | \r | |
251 | Status = VirtioFsFuseOpenDir (VirtioFs, NewChildDirNodeId, &NewFuseHandle);\r | |
252 | if (EFI_ERROR (Status)) {\r | |
253 | goto RemoveNewChildDir;\r | |
254 | }\r | |
255 | \r | |
256 | *NodeId = NewChildDirNodeId;\r | |
257 | *FuseHandle = NewFuseHandle;\r | |
258 | return EFI_SUCCESS;\r | |
259 | \r | |
260 | RemoveNewChildDir:\r | |
261 | VirtioFsFuseRemoveFileOrDir (VirtioFs, DirNodeId, Name, TRUE /* IsDir */);\r | |
262 | VirtioFsFuseForget (VirtioFs, NewChildDirNodeId);\r | |
263 | return Status;\r | |
264 | }\r | |
265 | \r | |
266 | /**\r | |
267 | Create a regular file.\r | |
268 | \r | |
269 | @param[in,out] VirtioFs The Virtio Filesystem device on which the regular\r | |
270 | file should be created.\r | |
271 | \r | |
272 | @param[in] DirNodeId The inode number of the immediate parent directory\r | |
273 | of the regular file to create.\r | |
274 | \r | |
275 | @param[in] Name The single-component filename of the regular file to\r | |
276 | create, under the immediate parent directory\r | |
277 | identified by DirNodeId.\r | |
278 | \r | |
279 | @param[out] NodeId The inode number of the regular file created,\r | |
280 | returned by the Virtio Filesystem device.\r | |
281 | \r | |
282 | @param[out] FuseHandle The open handle to the regular file created,\r | |
283 | returned by the Virtio Filesystem device.\r | |
284 | \r | |
285 | @retval EFI_SUCCESS The regular file has been created successfully.\r | |
286 | \r | |
287 | @return Errors propagated from underlying functions.\r | |
288 | **/\r | |
289 | STATIC\r | |
290 | EFI_STATUS\r | |
291 | CreateRegularFile (\r | |
ac0a286f MK |
292 | IN OUT VIRTIO_FS *VirtioFs,\r |
293 | IN UINT64 DirNodeId,\r | |
294 | IN CHAR8 *Name,\r | |
295 | OUT UINT64 *NodeId,\r | |
296 | OUT UINT64 *FuseHandle\r | |
de0e1190 LE |
297 | )\r |
298 | {\r | |
ac0a286f MK |
299 | return VirtioFsFuseOpenOrCreate (\r |
300 | VirtioFs,\r | |
301 | DirNodeId,\r | |
302 | Name,\r | |
303 | NodeId,\r | |
304 | FuseHandle\r | |
305 | );\r | |
de0e1190 LE |
306 | }\r |
307 | \r | |
334c13e1 LE |
308 | EFI_STATUS\r |
309 | EFIAPI\r | |
310 | VirtioFsSimpleFileOpen (\r | |
ac0a286f MK |
311 | IN EFI_FILE_PROTOCOL *This,\r |
312 | OUT EFI_FILE_PROTOCOL **NewHandle,\r | |
313 | IN CHAR16 *FileName,\r | |
314 | IN UINT64 OpenMode,\r | |
315 | IN UINT64 Attributes\r | |
334c13e1 LE |
316 | )\r |
317 | {\r | |
ac0a286f MK |
318 | VIRTIO_FS_FILE *VirtioFsFile;\r |
319 | VIRTIO_FS *VirtioFs;\r | |
320 | BOOLEAN OpenForWriting;\r | |
321 | BOOLEAN PermitCreation;\r | |
322 | BOOLEAN CreateDirectoryIfCreating;\r | |
323 | VIRTIO_FS_FILE *NewVirtioFsFile;\r | |
324 | EFI_STATUS Status;\r | |
325 | CHAR8 *NewCanonicalPath;\r | |
326 | BOOLEAN RootEscape;\r | |
327 | UINT64 DirNodeId;\r | |
328 | CHAR8 *LastComponent;\r | |
329 | UINT64 NewNodeId;\r | |
330 | UINT64 NewFuseHandle;\r | |
331 | BOOLEAN NewNodeIsDirectory;\r | |
de0e1190 LE |
332 | \r |
333 | VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);\r | |
334 | VirtioFs = VirtioFsFile->OwnerFs;\r | |
335 | \r | |
336 | //\r | |
337 | // Validate OpenMode.\r | |
338 | //\r | |
339 | switch (OpenMode) {\r | |
ac0a286f MK |
340 | case EFI_FILE_MODE_READ:\r |
341 | OpenForWriting = FALSE;\r | |
342 | PermitCreation = FALSE;\r | |
343 | break;\r | |
344 | case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r | |
345 | OpenForWriting = TRUE;\r | |
346 | PermitCreation = FALSE;\r | |
347 | break;\r | |
348 | case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r | |
349 | OpenForWriting = TRUE;\r | |
350 | PermitCreation = TRUE;\r | |
351 | break;\r | |
352 | default:\r | |
353 | return EFI_INVALID_PARAMETER;\r | |
de0e1190 LE |
354 | }\r |
355 | \r | |
d82c4693 SD |
356 | //\r |
357 | // Set CreateDirectoryIfCreating to suppress incorrect compiler/analyzer\r | |
358 | // warnings.\r | |
359 | //\r | |
360 | CreateDirectoryIfCreating = FALSE;\r | |
361 | \r | |
de0e1190 LE |
362 | //\r |
363 | // Validate the Attributes requested for the case when the file ends up being\r | |
364 | // created, provided creation is permitted.\r | |
365 | //\r | |
366 | if (PermitCreation) {\r | |
367 | if ((Attributes & ~EFI_FILE_VALID_ATTR) != 0) {\r | |
368 | //\r | |
369 | // Unknown attribute requested.\r | |
370 | //\r | |
371 | return EFI_INVALID_PARAMETER;\r | |
372 | }\r | |
373 | \r | |
374 | ASSERT (OpenForWriting);\r | |
375 | if ((Attributes & EFI_FILE_READ_ONLY) != 0) {\r | |
376 | DEBUG ((\r | |
377 | DEBUG_ERROR,\r | |
378 | ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\" "\r | |
379 | "OpenMode=0x%Lx Attributes=0x%Lx: nonsensical request to possibly "\r | |
380 | "create a file marked read-only, for read-write access\n"),\r | |
381 | __FUNCTION__,\r | |
382 | VirtioFs->Label,\r | |
383 | VirtioFsFile->CanonicalPathname,\r | |
384 | FileName,\r | |
385 | OpenMode,\r | |
386 | Attributes\r | |
387 | ));\r | |
388 | return EFI_INVALID_PARAMETER;\r | |
389 | }\r | |
ac0a286f | 390 | \r |
de0e1190 LE |
391 | CreateDirectoryIfCreating = (BOOLEAN)((Attributes &\r |
392 | EFI_FILE_DIRECTORY) != 0);\r | |
393 | }\r | |
394 | \r | |
395 | //\r | |
396 | // Referring to a file relative to a regular file makes no sense (or at least\r | |
397 | // it cannot be implemented consistently with how a file is referred to\r | |
398 | // relative to a directory).\r | |
399 | //\r | |
400 | if (!VirtioFsFile->IsDirectory) {\r | |
401 | DEBUG ((\r | |
402 | DEBUG_ERROR,\r | |
403 | ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\": "\r | |
404 | "nonsensical request to open a file or directory relative to a regular "\r | |
405 | "file\n"),\r | |
406 | __FUNCTION__,\r | |
407 | VirtioFs->Label,\r | |
408 | VirtioFsFile->CanonicalPathname,\r | |
409 | FileName\r | |
410 | ));\r | |
411 | return EFI_INVALID_PARAMETER;\r | |
412 | }\r | |
413 | \r | |
414 | //\r | |
415 | // Allocate the new VIRTIO_FS_FILE object.\r | |
416 | //\r | |
417 | NewVirtioFsFile = AllocatePool (sizeof *NewVirtioFsFile);\r | |
418 | if (NewVirtioFsFile == NULL) {\r | |
419 | return EFI_OUT_OF_RESOURCES;\r | |
420 | }\r | |
421 | \r | |
422 | //\r | |
423 | // Create the canonical pathname at which the desired file is expected to\r | |
424 | // exist.\r | |
425 | //\r | |
ac0a286f MK |
426 | Status = VirtioFsAppendPath (\r |
427 | VirtioFsFile->CanonicalPathname,\r | |
428 | FileName,\r | |
429 | &NewCanonicalPath,\r | |
430 | &RootEscape\r | |
431 | );\r | |
de0e1190 LE |
432 | if (EFI_ERROR (Status)) {\r |
433 | goto FreeNewVirtioFsFile;\r | |
434 | }\r | |
ac0a286f | 435 | \r |
de0e1190 LE |
436 | if (RootEscape) {\r |
437 | Status = EFI_ACCESS_DENIED;\r | |
438 | goto FreeNewCanonicalPath;\r | |
439 | }\r | |
440 | \r | |
441 | //\r | |
442 | // If the desired file is the root directory, just open the volume one more\r | |
443 | // time, without looking up anything.\r | |
444 | //\r | |
445 | if (AsciiStrCmp (NewCanonicalPath, "/") == 0) {\r | |
446 | FreePool (NewCanonicalPath);\r | |
447 | FreePool (NewVirtioFsFile);\r | |
448 | return OpenRootDirectory (VirtioFs, NewHandle, OpenForWriting);\r | |
449 | }\r | |
450 | \r | |
451 | //\r | |
452 | // Split the new canonical pathname into most specific parent directory\r | |
453 | // (given by DirNodeId) and last pathname component (i.e., immediate child\r | |
454 | // within that parent directory).\r | |
455 | //\r | |
ac0a286f MK |
456 | Status = VirtioFsLookupMostSpecificParentDir (\r |
457 | VirtioFs,\r | |
458 | NewCanonicalPath,\r | |
459 | &DirNodeId,\r | |
460 | &LastComponent\r | |
461 | );\r | |
de0e1190 LE |
462 | if (EFI_ERROR (Status)) {\r |
463 | goto FreeNewCanonicalPath;\r | |
464 | }\r | |
465 | \r | |
d82c4693 SD |
466 | //\r |
467 | // Set NewNodeIsDirectory to suppress incorrect compiler/analyzer warnings.\r | |
468 | //\r | |
469 | NewNodeIsDirectory = FALSE;\r | |
470 | \r | |
de0e1190 LE |
471 | //\r |
472 | // Try to open LastComponent directly under DirNodeId, as an existent regular\r | |
473 | // file or directory.\r | |
474 | //\r | |
ac0a286f MK |
475 | Status = OpenExistentFileOrDirectory (\r |
476 | VirtioFs,\r | |
477 | DirNodeId,\r | |
478 | LastComponent,\r | |
479 | OpenForWriting,\r | |
480 | &NewNodeId,\r | |
481 | &NewFuseHandle,\r | |
482 | &NewNodeIsDirectory\r | |
483 | );\r | |
de0e1190 LE |
484 | //\r |
485 | // If LastComponent could not be found under DirNodeId, but the request\r | |
486 | // allows us to create a new entry, attempt creating the requested regular\r | |
487 | // file or directory.\r | |
488 | //\r | |
ac0a286f | 489 | if ((Status == EFI_NOT_FOUND) && PermitCreation) {\r |
de0e1190 LE |
490 | ASSERT (OpenForWriting);\r |
491 | if (CreateDirectoryIfCreating) {\r | |
ac0a286f MK |
492 | Status = CreateDirectory (\r |
493 | VirtioFs,\r | |
494 | DirNodeId,\r | |
495 | LastComponent,\r | |
496 | &NewNodeId,\r | |
497 | &NewFuseHandle\r | |
498 | );\r | |
de0e1190 | 499 | } else {\r |
ac0a286f MK |
500 | Status = CreateRegularFile (\r |
501 | VirtioFs,\r | |
502 | DirNodeId,\r | |
503 | LastComponent,\r | |
504 | &NewNodeId,\r | |
505 | &NewFuseHandle\r | |
506 | );\r | |
de0e1190 | 507 | }\r |
ac0a286f | 508 | \r |
de0e1190 LE |
509 | NewNodeIsDirectory = CreateDirectoryIfCreating;\r |
510 | }\r | |
511 | \r | |
512 | //\r | |
513 | // Regardless of the branch taken, we're done with DirNodeId.\r | |
514 | //\r | |
515 | if (DirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {\r | |
516 | VirtioFsFuseForget (VirtioFs, DirNodeId);\r | |
517 | }\r | |
518 | \r | |
519 | if (EFI_ERROR (Status)) {\r | |
520 | goto FreeNewCanonicalPath;\r | |
521 | }\r | |
522 | \r | |
523 | //\r | |
524 | // Populate the new VIRTIO_FS_FILE object.\r | |
525 | //\r | |
526 | NewVirtioFsFile->Signature = VIRTIO_FS_FILE_SIG;\r | |
527 | NewVirtioFsFile->SimpleFile.Revision = EFI_FILE_PROTOCOL_REVISION;\r | |
528 | NewVirtioFsFile->SimpleFile.Open = VirtioFsSimpleFileOpen;\r | |
529 | NewVirtioFsFile->SimpleFile.Close = VirtioFsSimpleFileClose;\r | |
530 | NewVirtioFsFile->SimpleFile.Delete = VirtioFsSimpleFileDelete;\r | |
531 | NewVirtioFsFile->SimpleFile.Read = VirtioFsSimpleFileRead;\r | |
532 | NewVirtioFsFile->SimpleFile.Write = VirtioFsSimpleFileWrite;\r | |
533 | NewVirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;\r | |
534 | NewVirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;\r | |
535 | NewVirtioFsFile->SimpleFile.GetInfo = VirtioFsSimpleFileGetInfo;\r | |
536 | NewVirtioFsFile->SimpleFile.SetInfo = VirtioFsSimpleFileSetInfo;\r | |
537 | NewVirtioFsFile->SimpleFile.Flush = VirtioFsSimpleFileFlush;\r | |
538 | NewVirtioFsFile->IsDirectory = NewNodeIsDirectory;\r | |
539 | NewVirtioFsFile->IsOpenForWriting = OpenForWriting;\r | |
540 | NewVirtioFsFile->OwnerFs = VirtioFs;\r | |
541 | NewVirtioFsFile->CanonicalPathname = NewCanonicalPath;\r | |
c4edb49b | 542 | NewVirtioFsFile->FilePosition = 0;\r |
de0e1190 LE |
543 | NewVirtioFsFile->NodeId = NewNodeId;\r |
544 | NewVirtioFsFile->FuseHandle = NewFuseHandle;\r | |
b845de89 LE |
545 | NewVirtioFsFile->FileInfoArray = NULL;\r |
546 | NewVirtioFsFile->SingleFileInfoSize = 0;\r | |
547 | NewVirtioFsFile->NumFileInfo = 0;\r | |
548 | NewVirtioFsFile->NextFileInfo = 0;\r | |
de0e1190 LE |
549 | \r |
550 | //\r | |
551 | // One more file is now open for the filesystem.\r | |
552 | //\r | |
553 | InsertTailList (&VirtioFs->OpenFiles, &NewVirtioFsFile->OpenFilesEntry);\r | |
554 | \r | |
555 | *NewHandle = &NewVirtioFsFile->SimpleFile;\r | |
556 | return EFI_SUCCESS;\r | |
557 | \r | |
558 | FreeNewCanonicalPath:\r | |
559 | FreePool (NewCanonicalPath);\r | |
560 | \r | |
561 | FreeNewVirtioFsFile:\r | |
562 | FreePool (NewVirtioFsFile);\r | |
563 | \r | |
564 | return Status;\r | |
334c13e1 | 565 | }\r |