]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/UdfDxe/File.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / UdfDxe / File.c
CommitLineData
99c9b949
PA
1/** @file\r
2 Handle operations in files and directories from UDF/ECMA-167 file systems.\r
3\r
4 Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>\r
b9ae1705 5 Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
99c9b949 6\r
9d510e61 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
99c9b949
PA
8**/\r
9\r
10#include "Udf.h"\r
11\r
1436aea4 12EFI_FILE_PROTOCOL gUdfFileIoOps = {\r
99c9b949
PA
13 EFI_FILE_PROTOCOL_REVISION,\r
14 UdfOpen,\r
15 UdfClose,\r
16 UdfDelete,\r
17 UdfRead,\r
18 UdfWrite,\r
19 UdfGetPosition,\r
20 UdfSetPosition,\r
21 UdfGetInfo,\r
22 UdfSetInfo,\r
23 UdfFlush,\r
24 NULL,\r
25 NULL,\r
26 NULL,\r
27 NULL\r
28};\r
29\r
1436aea4 30#define _ROOT_FILE(_PrivData) (_PrivData)->Root\r
99c9b949
PA
31#define _PARENT_FILE(_PrivData) \\r
32 ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)\r
1436aea4 33#define _FILE(_PrivData) _PARENT_FILE(_PrivData)\r
99c9b949
PA
34\r
35/**\r
36 Open the root directory on a volume.\r
37\r
38 @param This Protocol instance pointer.\r
39 @param Root Returns an Open file handle for the root directory\r
40\r
41 @retval EFI_SUCCESS The device was opened.\r
42 @retval EFI_UNSUPPORTED This volume does not support the file system.\r
43 @retval EFI_NO_MEDIA The device has no media.\r
44 @retval EFI_DEVICE_ERROR The device reported an error.\r
45 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
46 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
47 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
48 resources.\r
49\r
50**/\r
51EFI_STATUS\r
52EFIAPI\r
53UdfOpenVolume (\r
54 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
55 OUT EFI_FILE_PROTOCOL **Root\r
56 )\r
57{\r
58 EFI_TPL OldTpl;\r
59 EFI_STATUS Status;\r
60 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
61 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
62\r
63 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
64\r
1436aea4 65 if ((This == NULL) || (Root == NULL)) {\r
99c9b949
PA
66 Status = EFI_INVALID_PARAMETER;\r
67 goto Error_Invalid_Params;\r
68 }\r
69\r
70 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This);\r
71\r
72 if (PrivFsData->OpenFiles == 0) {\r
73 //\r
74 // There is no more open files. Read volume information again since it was\r
75 // cleaned up on the last UdfClose() call.\r
76 //\r
77 Status = ReadUdfVolumeInformation (\r
1436aea4
MK
78 PrivFsData->BlockIo,\r
79 PrivFsData->DiskIo,\r
80 &PrivFsData->Volume\r
81 );\r
99c9b949
PA
82 if (EFI_ERROR (Status)) {\r
83 goto Error_Read_Udf_Volume;\r
84 }\r
85 }\r
86\r
87 CleanupFileInformation (&PrivFsData->Root);\r
88\r
89 //\r
90 // Find root directory file.\r
91 //\r
92 Status = FindRootDirectory (\r
1436aea4
MK
93 PrivFsData->BlockIo,\r
94 PrivFsData->DiskIo,\r
95 &PrivFsData->Volume,\r
96 &PrivFsData->Root\r
97 );\r
99c9b949
PA
98 if (EFI_ERROR (Status)) {\r
99 goto Error_Find_Root_Dir;\r
100 }\r
101\r
102 PrivFileData =\r
1436aea4 103 (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));\r
99c9b949
PA
104 if (PrivFileData == NULL) {\r
105 Status = EFI_OUT_OF_RESOURCES;\r
106 goto Error_Alloc_Priv_File_Data;\r
107 }\r
108\r
1436aea4
MK
109 PrivFileData->Signature = PRIVATE_UDF_FILE_DATA_SIGNATURE;\r
110 PrivFileData->SimpleFs = This;\r
111 PrivFileData->Root = &PrivFsData->Root;\r
112 PrivFileData->IsRootDirectory = TRUE;\r
99c9b949 113\r
1436aea4
MK
114 CopyMem (\r
115 (VOID *)&PrivFileData->FileIo,\r
116 (VOID *)&gUdfFileIoOps,\r
117 sizeof (EFI_FILE_PROTOCOL)\r
118 );\r
99c9b949
PA
119\r
120 *Root = &PrivFileData->FileIo;\r
121\r
122 PrivFsData->OpenFiles++;\r
123\r
124 gBS->RestoreTPL (OldTpl);\r
125\r
126 return EFI_SUCCESS;\r
127\r
128Error_Alloc_Priv_File_Data:\r
129 CleanupFileInformation (&PrivFsData->Root);\r
130\r
131Error_Find_Root_Dir:\r
99c9b949
PA
132\r
133Error_Read_Udf_Volume:\r
134Error_Invalid_Params:\r
135 gBS->RestoreTPL (OldTpl);\r
136\r
137 return Status;\r
138}\r
139\r
140/**\r
141 Opens a new file relative to the source file's location.\r
142\r
143 @param This The protocol instance pointer.\r
144 @param NewHandle Returns File Handle for FileName.\r
145 @param FileName Null terminated string. "\", ".", and ".." are supported.\r
146 @param OpenMode Open mode for file.\r
147 @param Attributes Only used for EFI_FILE_MODE_CREATE.\r
148\r
149 @retval EFI_SUCCESS The device was opened.\r
150 @retval EFI_NOT_FOUND The specified file could not be found on the\r
151 device.\r
152 @retval EFI_NO_MEDIA The device has no media.\r
153 @retval EFI_MEDIA_CHANGED The media has changed.\r
154 @retval EFI_DEVICE_ERROR The device reported an error.\r
155 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
156 @retval EFI_ACCESS_DENIED The service denied access to the file.\r
157 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
158 resources.\r
159 @retval EFI_VOLUME_FULL The volume is full.\r
160\r
161**/\r
162EFI_STATUS\r
163EFIAPI\r
164UdfOpen (\r
165 IN EFI_FILE_PROTOCOL *This,\r
166 OUT EFI_FILE_PROTOCOL **NewHandle,\r
167 IN CHAR16 *FileName,\r
168 IN UINT64 OpenMode,\r
169 IN UINT64 Attributes\r
170 )\r
171{\r
172 EFI_TPL OldTpl;\r
173 EFI_STATUS Status;\r
174 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
175 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
eb928b17 176 CHAR16 FilePath[UDF_PATH_LENGTH];\r
99c9b949
PA
177 UDF_FILE_INFO File;\r
178 PRIVATE_UDF_FILE_DATA *NewPrivFileData;\r
179 CHAR16 *TempFileName;\r
180\r
eb928b17 181 ZeroMem (FilePath, sizeof FilePath);\r
99c9b949
PA
182 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
183\r
1436aea4 184 if ((This == NULL) || (NewHandle == NULL) || (FileName == NULL)) {\r
99c9b949
PA
185 Status = EFI_INVALID_PARAMETER;\r
186 goto Error_Invalid_Params;\r
187 }\r
188\r
189 if (OpenMode != EFI_FILE_MODE_READ) {\r
190 Status = EFI_WRITE_PROTECTED;\r
191 goto Error_Invalid_Params;\r
192 }\r
193\r
194 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
195\r
196 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
197\r
198 //\r
199 // Build full path\r
200 //\r
201 if (*FileName == L'\\') {\r
202 StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);\r
203 } else {\r
204 StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);\r
205 StrCatS (FilePath, UDF_PATH_LENGTH, L"\\");\r
206 StrCatS (FilePath, UDF_PATH_LENGTH, FileName);\r
207 }\r
208\r
209 MangleFileName (FilePath);\r
210 if (FilePath[0] == L'\0') {\r
211 Status = EFI_NOT_FOUND;\r
212 goto Error_Bad_FileName;\r
213 }\r
214\r
215 Status = FindFile (\r
1436aea4
MK
216 PrivFsData->BlockIo,\r
217 PrivFsData->DiskIo,\r
218 &PrivFsData->Volume,\r
219 FilePath,\r
220 _ROOT_FILE (PrivFileData),\r
221 _PARENT_FILE (PrivFileData),\r
222 &_PARENT_FILE (PrivFileData)->FileIdentifierDesc->Icb,\r
223 &File\r
224 );\r
99c9b949
PA
225 if (EFI_ERROR (Status)) {\r
226 goto Error_Find_File;\r
227 }\r
228\r
229 NewPrivFileData =\r
230 (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));\r
231 if (NewPrivFileData == NULL) {\r
232 Status = EFI_OUT_OF_RESOURCES;\r
233 goto Error_Alloc_New_Priv_File_Data;\r
234 }\r
235\r
1436aea4
MK
236 CopyMem (\r
237 (VOID *)NewPrivFileData,\r
238 (VOID *)PrivFileData,\r
239 sizeof (PRIVATE_UDF_FILE_DATA)\r
240 );\r
99c9b949
PA
241 CopyMem ((VOID *)&NewPrivFileData->File, &File, sizeof (UDF_FILE_INFO));\r
242\r
243 NewPrivFileData->IsRootDirectory = FALSE;\r
244\r
245 StrCpyS (NewPrivFileData->AbsoluteFileName, UDF_PATH_LENGTH, FilePath);\r
246 FileName = NewPrivFileData->AbsoluteFileName;\r
247\r
248 while ((TempFileName = StrStr (FileName, L"\\")) != NULL) {\r
249 FileName = TempFileName + 1;\r
250 }\r
251\r
b9ae1705 252 StrCpyS (NewPrivFileData->FileName, UDF_FILENAME_LENGTH, FileName);\r
99c9b949
PA
253\r
254 Status = GetFileSize (\r
1436aea4
MK
255 PrivFsData->BlockIo,\r
256 PrivFsData->DiskIo,\r
257 &PrivFsData->Volume,\r
258 &NewPrivFileData->File,\r
259 &NewPrivFileData->FileSize\r
260 );\r
99c9b949 261 if (EFI_ERROR (Status)) {\r
f355dd34
HW
262 DEBUG ((\r
263 DEBUG_ERROR,\r
264 "%a: GetFileSize() fails with status - %r.\n",\r
1436aea4
MK
265 __FUNCTION__,\r
266 Status\r
f355dd34 267 ));\r
99c9b949
PA
268 goto Error_Get_File_Size;\r
269 }\r
270\r
271 NewPrivFileData->FilePosition = 0;\r
1436aea4
MK
272 ZeroMem (\r
273 (VOID *)&NewPrivFileData->ReadDirInfo,\r
274 sizeof (UDF_READ_DIRECTORY_INFO)\r
275 );\r
99c9b949
PA
276\r
277 *NewHandle = &NewPrivFileData->FileIo;\r
278\r
279 PrivFsData->OpenFiles++;\r
280\r
281 gBS->RestoreTPL (OldTpl);\r
282\r
283 return Status;\r
284\r
285Error_Get_File_Size:\r
286 FreePool ((VOID *)NewPrivFileData);\r
287\r
288Error_Alloc_New_Priv_File_Data:\r
289 CleanupFileInformation (&File);\r
290\r
291Error_Find_File:\r
292Error_Bad_FileName:\r
293Error_Invalid_Params:\r
294 gBS->RestoreTPL (OldTpl);\r
295\r
296 return Status;\r
297}\r
298\r
299/**\r
300 Read data from the file.\r
301\r
302 @param This Protocol instance pointer.\r
303 @param BufferSize On input size of buffer, on output amount of data in\r
304 buffer.\r
305 @param Buffer The buffer in which data is read.\r
306\r
307 @retval EFI_SUCCESS Data was read.\r
308 @retval EFI_NO_MEDIA The device has no media.\r
309 @retval EFI_DEVICE_ERROR The device reported an error.\r
310 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
311 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains\r
312 required size.\r
313\r
314**/\r
315EFI_STATUS\r
316EFIAPI\r
317UdfRead (\r
318 IN EFI_FILE_PROTOCOL *This,\r
319 IN OUT UINTN *BufferSize,\r
320 OUT VOID *Buffer\r
321 )\r
322{\r
323 EFI_TPL OldTpl;\r
324 EFI_STATUS Status;\r
325 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
326 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
327 UDF_VOLUME_INFO *Volume;\r
328 UDF_FILE_INFO *Parent;\r
329 UDF_READ_DIRECTORY_INFO *ReadDirInfo;\r
330 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
331 EFI_DISK_IO_PROTOCOL *DiskIo;\r
332 UDF_FILE_INFO FoundFile;\r
333 UDF_FILE_IDENTIFIER_DESCRIPTOR *NewFileIdentifierDesc;\r
334 VOID *NewFileEntryData;\r
eb928b17 335 CHAR16 FileName[UDF_FILENAME_LENGTH];\r
99c9b949
PA
336 UINT64 FileSize;\r
337 UINT64 BufferSizeUint64;\r
338\r
eb928b17 339 ZeroMem (FileName, sizeof FileName);\r
99c9b949
PA
340 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
341\r
1436aea4
MK
342 if ((This == NULL) || (BufferSize == NULL) || ((*BufferSize != 0) &&\r
343 (Buffer == NULL)))\r
344 {\r
99c9b949
PA
345 Status = EFI_INVALID_PARAMETER;\r
346 goto Error_Invalid_Params;\r
347 }\r
348\r
349 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
1436aea4 350 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
99c9b949 351\r
1436aea4
MK
352 BlockIo = PrivFsData->BlockIo;\r
353 DiskIo = PrivFsData->DiskIo;\r
354 Volume = &PrivFsData->Volume;\r
355 ReadDirInfo = &PrivFileData->ReadDirInfo;\r
356 NewFileIdentifierDesc = NULL;\r
357 NewFileEntryData = NULL;\r
99c9b949
PA
358\r
359 Parent = _PARENT_FILE (PrivFileData);\r
360\r
361 Status = EFI_VOLUME_CORRUPTED;\r
362\r
363 if (IS_FID_NORMAL_FILE (Parent->FileIdentifierDesc)) {\r
364 if (PrivFileData->FilePosition > PrivFileData->FileSize) {\r
365 //\r
366 // File's position is beyond the EOF\r
367 //\r
368 Status = EFI_DEVICE_ERROR;\r
369 goto Error_File_Beyond_The_Eof;\r
370 }\r
371\r
372 if (PrivFileData->FilePosition == PrivFileData->FileSize) {\r
373 *BufferSize = 0;\r
1436aea4 374 Status = EFI_SUCCESS;\r
99c9b949
PA
375 goto Done;\r
376 }\r
377\r
378 BufferSizeUint64 = *BufferSize;\r
379\r
380 Status = ReadFileData (\r
1436aea4
MK
381 BlockIo,\r
382 DiskIo,\r
383 Volume,\r
384 Parent,\r
385 PrivFileData->FileSize,\r
386 &PrivFileData->FilePosition,\r
387 Buffer,\r
388 &BufferSizeUint64\r
389 );\r
99c9b949
PA
390 ASSERT (BufferSizeUint64 <= MAX_UINTN);\r
391 *BufferSize = (UINTN)BufferSizeUint64;\r
392 } else if (IS_FID_DIRECTORY_FILE (Parent->FileIdentifierDesc)) {\r
1436aea4
MK
393 if ((ReadDirInfo->FidOffset == 0) && (PrivFileData->FilePosition > 0)) {\r
394 Status = EFI_DEVICE_ERROR;\r
99c9b949
PA
395 *BufferSize = 0;\r
396 goto Done;\r
397 }\r
398\r
1436aea4 399 for ( ; ;) {\r
99c9b949 400 Status = ReadDirectoryEntry (\r
1436aea4
MK
401 BlockIo,\r
402 DiskIo,\r
403 Volume,\r
404 &Parent->FileIdentifierDesc->Icb,\r
405 Parent->FileEntry,\r
406 ReadDirInfo,\r
407 &NewFileIdentifierDesc\r
408 );\r
99c9b949
PA
409 if (EFI_ERROR (Status)) {\r
410 if (Status == EFI_DEVICE_ERROR) {\r
411 FreePool (ReadDirInfo->DirectoryData);\r
412 ZeroMem ((VOID *)ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));\r
413\r
414 *BufferSize = 0;\r
1436aea4 415 Status = EFI_SUCCESS;\r
99c9b949
PA
416 }\r
417\r
418 goto Done;\r
419 }\r
1436aea4 420\r
5fb22f59
HW
421 //\r
422 // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'\r
423 // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the\r
424 // code reaches here, 'NewFileIdentifierDesc' must be not NULL.\r
425 //\r
426 // The ASSERT here is for addressing a false positive NULL pointer\r
427 // dereference issue raised from static analysis.\r
428 //\r
429 ASSERT (NewFileIdentifierDesc != NULL);\r
99c9b949
PA
430\r
431 if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc)) {\r
432 break;\r
433 }\r
434\r
435 FreePool ((VOID *)NewFileIdentifierDesc);\r
436 }\r
437\r
438 Status = FindFileEntry (\r
1436aea4
MK
439 BlockIo,\r
440 DiskIo,\r
441 Volume,\r
442 &NewFileIdentifierDesc->Icb,\r
443 &NewFileEntryData\r
444 );\r
99c9b949
PA
445 if (EFI_ERROR (Status)) {\r
446 goto Error_Find_Fe;\r
447 }\r
1436aea4 448\r
3fa40d58 449 ASSERT (NewFileEntryData != NULL);\r
99c9b949 450\r
baaa3cee 451 if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {\r
99c9b949 452 Status = ResolveSymlink (\r
1436aea4
MK
453 BlockIo,\r
454 DiskIo,\r
455 Volume,\r
456 Parent,\r
457 NewFileEntryData,\r
458 &FoundFile\r
459 );\r
99c9b949
PA
460 if (EFI_ERROR (Status)) {\r
461 goto Error_Resolve_Symlink;\r
462 }\r
463\r
464 FreePool ((VOID *)NewFileEntryData);\r
465 NewFileEntryData = FoundFile.FileEntry;\r
466\r
b9ae1705 467 Status = GetFileNameFromFid (NewFileIdentifierDesc, ARRAY_SIZE (FileName), FileName);\r
99c9b949
PA
468 if (EFI_ERROR (Status)) {\r
469 FreePool ((VOID *)FoundFile.FileIdentifierDesc);\r
470 goto Error_Get_FileName;\r
471 }\r
472\r
473 FreePool ((VOID *)NewFileIdentifierDesc);\r
474 NewFileIdentifierDesc = FoundFile.FileIdentifierDesc;\r
475 } else {\r
1436aea4
MK
476 FoundFile.FileIdentifierDesc = NewFileIdentifierDesc;\r
477 FoundFile.FileEntry = NewFileEntryData;\r
99c9b949 478\r
b9ae1705 479 Status = GetFileNameFromFid (FoundFile.FileIdentifierDesc, ARRAY_SIZE (FileName), FileName);\r
99c9b949
PA
480 if (EFI_ERROR (Status)) {\r
481 goto Error_Get_FileName;\r
482 }\r
483 }\r
484\r
485 Status = GetFileSize (\r
1436aea4
MK
486 BlockIo,\r
487 DiskIo,\r
488 Volume,\r
489 &FoundFile,\r
490 &FileSize\r
491 );\r
99c9b949
PA
492 if (EFI_ERROR (Status)) {\r
493 goto Error_Get_File_Size;\r
494 }\r
495\r
496 Status = SetFileInfo (\r
1436aea4
MK
497 &FoundFile,\r
498 FileSize,\r
499 FileName,\r
500 BufferSize,\r
501 Buffer\r
502 );\r
99c9b949
PA
503 if (EFI_ERROR (Status)) {\r
504 goto Error_Set_File_Info;\r
505 }\r
506\r
507 PrivFileData->FilePosition++;\r
508 Status = EFI_SUCCESS;\r
509 } else if (IS_FID_DELETED_FILE (Parent->FileIdentifierDesc)) {\r
11941d3b
HW
510 //\r
511 // Code should never reach here.\r
512 //\r
513 ASSERT (FALSE);\r
99c9b949
PA
514 Status = EFI_DEVICE_ERROR;\r
515 }\r
516\r
517Error_Set_File_Info:\r
518Error_Get_File_Size:\r
519Error_Get_FileName:\r
520Error_Resolve_Symlink:\r
521 if (NewFileEntryData != NULL) {\r
522 FreePool (NewFileEntryData);\r
523 }\r
524\r
525Error_Find_Fe:\r
526 if (NewFileIdentifierDesc != NULL) {\r
527 FreePool ((VOID *)NewFileIdentifierDesc);\r
528 }\r
529\r
530Done:\r
531Error_File_Beyond_The_Eof:\r
532Error_Invalid_Params:\r
533 gBS->RestoreTPL (OldTpl);\r
534\r
535 return Status;\r
536}\r
537\r
538/**\r
539 Close the file handle.\r
540\r
541 @param This Protocol instance pointer.\r
542\r
543 @retval EFI_SUCCESS The file was closed.\r
544\r
545**/\r
546EFI_STATUS\r
547EFIAPI\r
548UdfClose (\r
1436aea4 549 IN EFI_FILE_PROTOCOL *This\r
99c9b949
PA
550 )\r
551{\r
1436aea4
MK
552 EFI_TPL OldTpl;\r
553 EFI_STATUS Status;\r
554 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
99c9b949
PA
555\r
556 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
557\r
558 Status = EFI_SUCCESS;\r
559\r
560 if (This == NULL) {\r
561 Status = EFI_INVALID_PARAMETER;\r
562 goto Exit;\r
563 }\r
564\r
565 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
566\r
99c9b949
PA
567 if (!PrivFileData->IsRootDirectory) {\r
568 CleanupFileInformation (&PrivFileData->File);\r
569\r
570 if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {\r
571 FreePool (PrivFileData->ReadDirInfo.DirectoryData);\r
572 }\r
573 }\r
574\r
99c9b949
PA
575 FreePool ((VOID *)PrivFileData);\r
576\r
577Exit:\r
578 gBS->RestoreTPL (OldTpl);\r
579\r
580 return Status;\r
581}\r
582\r
583/**\r
584 Close and delete the file handle.\r
585\r
586 @param This Protocol instance pointer.\r
587\r
588 @retval EFI_SUCCESS The file was closed and deleted.\r
589 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not\r
590 deleted.\r
591\r
592**/\r
593EFI_STATUS\r
594EFIAPI\r
595UdfDelete (\r
596 IN EFI_FILE_PROTOCOL *This\r
597 )\r
598{\r
1436aea4 599 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
99c9b949
PA
600\r
601 if (This == NULL) {\r
602 return EFI_INVALID_PARAMETER;\r
603 }\r
604\r
605 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
606\r
1436aea4 607 (VOID)PrivFileData->FileIo.Close (This);\r
99c9b949
PA
608\r
609 return EFI_WARN_DELETE_FAILURE;\r
610}\r
611\r
612/**\r
613 Write data to a file.\r
614\r
615 @param This Protocol instance pointer.\r
616 @param BufferSize On input size of buffer, on output amount of data in\r
617 buffer.\r
618 @param Buffer The buffer in which data to write.\r
619\r
620 @retval EFI_SUCCESS Data was written.\r
621 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.\r
622 @retval EFI_NO_MEDIA The device has no media.\r
623 @retval EFI_DEVICE_ERROR The device reported an error.\r
624 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.\r
625 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
626 @retval EFI_WRITE_PROTECTED The device is write protected.\r
627 @retval EFI_ACCESS_DENIED The file was open for read only.\r
628 @retval EFI_VOLUME_FULL The volume is full.\r
629\r
630**/\r
631EFI_STATUS\r
632EFIAPI\r
633UdfWrite (\r
634 IN EFI_FILE_PROTOCOL *This,\r
635 IN OUT UINTN *BufferSize,\r
636 IN VOID *Buffer\r
637 )\r
638{\r
639 return EFI_UNSUPPORTED;\r
640}\r
641\r
642/**\r
643 Get file's current position.\r
644\r
645 @param This Protocol instance pointer.\r
646 @param Position Byte position from the start of the file.\r
647\r
648 @retval EFI_SUCCESS Position was updated.\r
649 @retval EFI_UNSUPPORTED Seek request for directories is not valid.\r
650\r
651**/\r
652EFI_STATUS\r
653EFIAPI\r
654UdfGetPosition (\r
655 IN EFI_FILE_PROTOCOL *This,\r
656 OUT UINT64 *Position\r
657 )\r
658{\r
1436aea4 659 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
99c9b949 660\r
1436aea4 661 if ((This == NULL) || (Position == NULL)) {\r
99c9b949
PA
662 return EFI_INVALID_PARAMETER;\r
663 }\r
664\r
665 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
666\r
667 //\r
668 // As per UEFI spec, if the file handle is a directory, then the current file\r
669 // position has no meaning and the operation is not supported.\r
670 //\r
baaa3cee 671 if (IS_FID_DIRECTORY_FILE (PrivFileData->File.FileIdentifierDesc)) {\r
1436aea4 672 return EFI_UNSUPPORTED;\r
99c9b949
PA
673 }\r
674\r
675 //\r
676 // The file is not a directory. So, return its position.\r
677 //\r
678 *Position = PrivFileData->FilePosition;\r
679\r
680 return EFI_SUCCESS;\r
681}\r
682\r
683/**\r
684 Set file's current position.\r
685\r
686 @param This Protocol instance pointer.\r
687 @param Position Byte position from the start of the file.\r
688\r
689 @retval EFI_SUCCESS Position was updated.\r
690 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.\r
691\r
692**/\r
693EFI_STATUS\r
694EFIAPI\r
695UdfSetPosition (\r
696 IN EFI_FILE_PROTOCOL *This,\r
697 IN UINT64 Position\r
698 )\r
699{\r
700 EFI_STATUS Status;\r
701 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
702 UDF_FILE_IDENTIFIER_DESCRIPTOR *FileIdentifierDesc;\r
703\r
704 if (This == NULL) {\r
705 return EFI_INVALID_PARAMETER;\r
706 }\r
707\r
708 Status = EFI_UNSUPPORTED;\r
709\r
710 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
711\r
11b4463e
PA
712 FileIdentifierDesc = _FILE (PrivFileData)->FileIdentifierDesc;\r
713 ASSERT (FileIdentifierDesc != NULL);\r
99c9b949
PA
714 if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) {\r
715 //\r
716 // If the file handle is a directory, the _only_ position that may be set is\r
717 // zero. This has no effect of starting the read proccess of the directory\r
718 // entries over.\r
719 //\r
720 if (Position == 0) {\r
1436aea4 721 PrivFileData->FilePosition = Position;\r
99c9b949 722 PrivFileData->ReadDirInfo.FidOffset = 0;\r
1436aea4 723 Status = EFI_SUCCESS;\r
99c9b949
PA
724 }\r
725 } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc)) {\r
726 //\r
727 // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be\r
728 // set to the EOF.\r
729 //\r
730 if (Position == 0xFFFFFFFFFFFFFFFF) {\r
6df465b2 731 PrivFileData->FilePosition = PrivFileData->FileSize;\r
99c9b949
PA
732 } else {\r
733 PrivFileData->FilePosition = Position;\r
734 }\r
735\r
736 Status = EFI_SUCCESS;\r
737 }\r
738\r
739 return Status;\r
740}\r
741\r
742/**\r
743 Get information about a file.\r
744\r
745 @param This Protocol instance pointer.\r
746 @param InformationType Type of information to return in Buffer.\r
747 @param BufferSize On input size of buffer, on output amount of data in\r
748 buffer.\r
749 @param Buffer The buffer to return data.\r
750\r
751 @retval EFI_SUCCESS Data was returned.\r
752 @retval EFI_UNSUPPORTED InformationType is not supported.\r
753 @retval EFI_NO_MEDIA The device has no media.\r
754 @retval EFI_DEVICE_ERROR The device reported an error.\r
755 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
756 @retval EFI_WRITE_PROTECTED The device is write protected.\r
757 @retval EFI_ACCESS_DENIED The file was open for read only.\r
758 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in\r
759 BufferSize.\r
760\r
761**/\r
762EFI_STATUS\r
763EFIAPI\r
764UdfGetInfo (\r
765 IN EFI_FILE_PROTOCOL *This,\r
766 IN EFI_GUID *InformationType,\r
767 IN OUT UINTN *BufferSize,\r
768 OUT VOID *Buffer\r
769 )\r
770{\r
32698a8f
HW
771 EFI_STATUS Status;\r
772 PRIVATE_UDF_FILE_DATA *PrivFileData;\r
773 PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData;\r
774 EFI_FILE_SYSTEM_INFO *FileSystemInfo;\r
775 UINTN FileSystemInfoLength;\r
776 UINT64 VolumeSize;\r
777 UINT64 FreeSpaceSize;\r
778 EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;\r
779 UINTN FileSystemVolumeLabelLength;\r
780 CHAR16 VolumeLabel[64];\r
99c9b949 781\r
1436aea4
MK
782 if ((This == NULL) || (InformationType == NULL) || (BufferSize == NULL) ||\r
783 ((*BufferSize != 0) && (Buffer == NULL)))\r
784 {\r
99c9b949
PA
785 return EFI_INVALID_PARAMETER;\r
786 }\r
787\r
788 PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);\r
789\r
790 PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);\r
791\r
792 Status = EFI_UNSUPPORTED;\r
793\r
794 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
795 Status = SetFileInfo (\r
1436aea4
MK
796 _FILE (PrivFileData),\r
797 PrivFileData->FileSize,\r
798 PrivFileData->FileName,\r
799 BufferSize,\r
800 Buffer\r
801 );\r
99c9b949 802 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
32698a8f
HW
803 Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);\r
804 if (EFI_ERROR (Status)) {\r
805 return Status;\r
b9ae1705 806 }\r
99c9b949
PA
807\r
808 FileSystemInfoLength = StrSize (VolumeLabel) +\r
809 sizeof (EFI_FILE_SYSTEM_INFO);\r
810 if (*BufferSize < FileSystemInfoLength) {\r
811 *BufferSize = FileSystemInfoLength;\r
812 return EFI_BUFFER_TOO_SMALL;\r
813 }\r
814\r
815 FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
b9ae1705
HW
816 StrCpyS (\r
817 FileSystemInfo->VolumeLabel,\r
32698a8f 818 (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),\r
b9ae1705
HW
819 VolumeLabel\r
820 );\r
99c9b949 821 Status = GetVolumeSize (\r
1436aea4
MK
822 PrivFsData->BlockIo,\r
823 PrivFsData->DiskIo,\r
824 &PrivFsData->Volume,\r
825 &VolumeSize,\r
826 &FreeSpaceSize\r
827 );\r
99c9b949
PA
828 if (EFI_ERROR (Status)) {\r
829 return Status;\r
830 }\r
831\r
1436aea4
MK
832 FileSystemInfo->Size = FileSystemInfoLength;\r
833 FileSystemInfo->ReadOnly = TRUE;\r
834 FileSystemInfo->BlockSize =\r
baaa3cee 835 PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;\r
1436aea4
MK
836 FileSystemInfo->VolumeSize = VolumeSize;\r
837 FileSystemInfo->FreeSpace = FreeSpaceSize;\r
99c9b949
PA
838\r
839 *BufferSize = FileSystemInfoLength;\r
1436aea4 840 Status = EFI_SUCCESS;\r
32698a8f
HW
841 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
842 Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);\r
843 if (EFI_ERROR (Status)) {\r
844 return Status;\r
845 }\r
846\r
847 FileSystemVolumeLabelLength = StrSize (VolumeLabel) +\r
848 sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL);\r
849 if (*BufferSize < FileSystemVolumeLabelLength) {\r
850 *BufferSize = FileSystemVolumeLabelLength;\r
851 return EFI_BUFFER_TOO_SMALL;\r
852 }\r
853\r
854 FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;\r
855 StrCpyS (\r
856 FileSystemVolumeLabel->VolumeLabel,\r
857 (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL) / sizeof (CHAR16),\r
858 VolumeLabel\r
859 );\r
860 Status = EFI_SUCCESS;\r
99c9b949
PA
861 }\r
862\r
863 return Status;\r
864}\r
865\r
866/**\r
867 Set information about a file.\r
868\r
077f8c43 869 @param This Protocol instance pointer.\r
99c9b949
PA
870 @param InformationType Type of information in Buffer.\r
871 @param BufferSize Size of buffer.\r
872 @param Buffer The data to write.\r
873\r
874 @retval EFI_SUCCESS Data was set.\r
875 @retval EFI_UNSUPPORTED InformationType is not supported.\r
876 @retval EFI_NO_MEDIA The device has no media.\r
877 @retval EFI_DEVICE_ERROR The device reported an error.\r
878 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
879 @retval EFI_WRITE_PROTECTED The device is write protected.\r
880 @retval EFI_ACCESS_DENIED The file was open for read only.\r
881\r
882**/\r
883EFI_STATUS\r
884EFIAPI\r
885UdfSetInfo (\r
886 IN EFI_FILE_PROTOCOL *This,\r
887 IN EFI_GUID *InformationType,\r
888 IN UINTN BufferSize,\r
889 IN VOID *Buffer\r
890 )\r
891{\r
892 return EFI_WRITE_PROTECTED;\r
893}\r
894\r
895/**\r
896 Flush data back for the file handle.\r
897\r
898 @param This Protocol instance pointer.\r
899\r
900 @retval EFI_SUCCESS Data was flushed.\r
901 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.\r
902 @retval EFI_NO_MEDIA The device has no media.\r
903 @retval EFI_DEVICE_ERROR The device reported an error.\r
904 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
905 @retval EFI_WRITE_PROTECTED The device is write protected.\r
906 @retval EFI_ACCESS_DENIED The file was open for read only.\r
907 @retval EFI_VOLUME_FULL The volume is full.\r
908\r
909**/\r
910EFI_STATUS\r
911EFIAPI\r
912UdfFlush (\r
1436aea4 913 IN EFI_FILE_PROTOCOL *This\r
99c9b949
PA
914 )\r
915{\r
916 return EFI_WRITE_PROTECTED;\r
917}\r