]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Dxe/UnixThunk/Bus/SimpleFileSystem/UnixSimpleFileSystem.c
remove unnecessary check for NULL pointer.
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / SimpleFileSystem / UnixSimpleFileSystem.c
CommitLineData
c9093a06 1/*++\r
2\r
ac10bddd 3Copyright (c) 2006 - 2007, Intel Corporation \r
c9093a06 4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 UnixSimpleFileSystem.c\r
15\r
16Abstract:\r
17\r
377fc2ae 18 Produce Simple File System abstractions for directories on your PC using Posix APIs.\r
19 The configuration of what devices to mount or emulate comes from UNIX \r
c9093a06 20 environment variables. The variables must be visible to the Microsoft* \r
21 Developer Studio for them to work.\r
22\r
23 * Other names and brands may be claimed as the property of others.\r
24\r
25--*/\r
26\r
27#include "UnixSimpleFileSystem.h"\r
28\r
29EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding = {\r
30 UnixSimpleFileSystemDriverBindingSupported,\r
31 UnixSimpleFileSystemDriverBindingStart,\r
32 UnixSimpleFileSystemDriverBindingStop,\r
caea5554 33 0xa,\r
c9093a06 34 NULL,\r
35 NULL\r
36};\r
37\r
38\r
39CHAR16 *\r
40EfiStrChr (\r
41 IN CHAR16 *Str,\r
42 IN CHAR16 Chr\r
43 )\r
44/*++\r
45\r
46Routine Description:\r
47\r
48 Locate the first occurance of a character in a string.\r
49\r
50Arguments:\r
51\r
52 Str - Pointer to NULL terminated unicode string.\r
53 Chr - Character to locate.\r
54\r
55Returns:\r
56\r
57 If Str is NULL, then NULL is returned.\r
58 If Chr is not contained in Str, then NULL is returned.\r
59 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.\r
60\r
61--*/\r
62{\r
63 if (Str == NULL) {\r
64 return Str;\r
65 }\r
66\r
67 while (*Str != '\0' && *Str != Chr) {\r
68 ++Str;\r
69 }\r
70\r
71 return (*Str == Chr) ? Str : NULL;\r
72}\r
73\r
74BOOLEAN\r
75IsZero (\r
76 IN VOID *Buffer,\r
77 IN UINTN Length\r
78 )\r
79/*++\r
80\r
81Routine Description:\r
82\r
83 TODO: Add function description\r
84\r
85Arguments:\r
86\r
87 Buffer - TODO: add argument description\r
88 Length - TODO: add argument description\r
89\r
90Returns:\r
91\r
92 TODO: add return values\r
93\r
94--*/\r
95{\r
96 if (Buffer == NULL || Length == 0) {\r
97 return FALSE;\r
98 }\r
99\r
100 if (*(UINT8 *) Buffer != 0) {\r
101 return FALSE;\r
102 }\r
103\r
104 if (Length > 1) {\r
105 if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {\r
106 return FALSE;\r
107 }\r
108 }\r
109\r
110 return TRUE;\r
111}\r
112\r
113VOID\r
114CutPrefix (\r
115 IN CHAR8 *Str,\r
116 IN UINTN Count\r
117 )\r
118/*++\r
119\r
120Routine Description:\r
121\r
122 TODO: Add function description\r
123\r
124Arguments:\r
125\r
126 Str - TODO: add argument description\r
127 Count - TODO: add argument description\r
128\r
129Returns:\r
130\r
131 TODO: add return values\r
132\r
133--*/\r
134{\r
135 CHAR8 *Pointer;\r
136\r
137 if (AsciiStrLen (Str) < Count) {\r
138 ASSERT (0);\r
139 }\r
140\r
141 for (Pointer = Str; *(Pointer + Count); Pointer++) {\r
142 *Pointer = *(Pointer + Count);\r
143 }\r
144\r
145 *Pointer = *(Pointer + Count);\r
146}\r
147\r
148\r
149\r
150EFI_STATUS\r
151EFIAPI\r
152UnixSimpleFileSystemDriverBindingSupported (\r
153 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
154 IN EFI_HANDLE ControllerHandle,\r
155 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
156 )\r
157/*++\r
158\r
159Routine Description:\r
160\r
161 Check to see if the driver supports a given controller.\r
162\r
163Arguments:\r
164\r
165 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
166\r
167 ControllerHandle - EFI handle of the controller to test.\r
168\r
169 RemainingDevicePath - Pointer to remaining portion of a device path.\r
170\r
171Returns:\r
172\r
173 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver\r
174 specified by This.\r
175\r
176 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
177 the driver specified by This.\r
178\r
179 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
180 a different driver or an application that requires exclusive access.\r
181\r
182 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the\r
183 driver specified by This.\r
184\r
185--*/\r
186{\r
187 EFI_STATUS Status;\r
188 EFI_UNIX_IO_PROTOCOL *UnixIo;\r
189\r
190 //\r
191 // Open the IO Abstraction(s) needed to perform the supported test\r
192 //\r
193 Status = gBS->OpenProtocol (\r
194 ControllerHandle,\r
195 &gEfiUnixIoProtocolGuid,\r
196 (VOID **)&UnixIo,\r
197 This->DriverBindingHandle,\r
198 ControllerHandle,\r
199 EFI_OPEN_PROTOCOL_BY_DRIVER\r
200 );\r
201 if (EFI_ERROR (Status)) {\r
202 return Status;\r
203 }\r
204\r
205 //\r
206 // Make sure GUID is for a File System handle.\r
207 //\r
208 Status = EFI_UNSUPPORTED;\r
209 if (CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {\r
210 Status = EFI_SUCCESS;\r
211 }\r
212\r
213 //\r
214 // Close the I/O Abstraction(s) used to perform the supported test\r
215 //\r
216 gBS->CloseProtocol (\r
217 ControllerHandle,\r
218 &gEfiUnixIoProtocolGuid,\r
219 This->DriverBindingHandle,\r
220 ControllerHandle\r
221 );\r
222\r
223 return Status;\r
224}\r
225\r
226EFI_STATUS\r
227EFIAPI\r
228UnixSimpleFileSystemDriverBindingStart (\r
229 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
230 IN EFI_HANDLE ControllerHandle,\r
231 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
232 )\r
233/*++\r
234\r
235Routine Description:\r
236\r
237 Starts a device controller or a bus controller.\r
238\r
239Arguments:\r
240\r
241 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
242\r
243 ControllerHandle - EFI handle of the controller to start.\r
244\r
245 RemainingDevicePath - Pointer to remaining portion of a device path.\r
246\r
247Returns:\r
248\r
249 EFI_SUCCESS - The device or bus controller has been started.\r
250\r
251 EFI_DEVICE_ERROR - The device could not be started due to a device failure.\r
252\r
253 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
254\r
255--*/\r
256{\r
257 EFI_STATUS Status;\r
258 EFI_UNIX_IO_PROTOCOL *UnixIo;\r
259 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
caea5554 260 INTN i;\r
c9093a06 261\r
262 Private = NULL;\r
263\r
264 //\r
265 // Open the IO Abstraction(s) needed\r
266 //\r
267 Status = gBS->OpenProtocol (\r
268 ControllerHandle,\r
269 &gEfiUnixIoProtocolGuid,\r
270 (VOID **)&UnixIo,\r
271 This->DriverBindingHandle,\r
272 ControllerHandle,\r
273 EFI_OPEN_PROTOCOL_BY_DRIVER\r
274 );\r
275 if (EFI_ERROR (Status)) {\r
276 return Status;\r
277 }\r
278\r
279 //\r
280 // Validate GUID\r
281 //\r
282 if (!CompareGuid (UnixIo->TypeGuid, &gEfiUnixFileSystemGuid)) {\r
283 Status = EFI_UNSUPPORTED;\r
284 goto Done;\r
285 }\r
286\r
287 Status = gBS->AllocatePool (\r
288 EfiBootServicesData,\r
289 sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE),\r
290 (VOID **)&Private\r
291 );\r
292 if (EFI_ERROR (Status)) {\r
293 goto Done;\r
294 }\r
295\r
296 Private->Signature = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;\r
297 Private->UnixThunk = UnixIo->UnixThunk;\r
caea5554 298 Private->FilePath = NULL;\r
299 Private->VolumeLabel = NULL;\r
c9093a06 300\r
301 Status = gBS->AllocatePool (\r
302 EfiBootServicesData,\r
303 StrLen (UnixIo->EnvString) + 1,\r
304 (VOID **)&Private->FilePath\r
305 );\r
306\r
307 if (EFI_ERROR (Status)) {\r
308 goto Done;\r
309 }\r
caea5554 310\r
311 for (i = 0; UnixIo->EnvString[i] != 0; i++)\r
c9093a06 312 Private->FilePath[i] = UnixIo->EnvString[i];\r
caea5554 313 Private->FilePath[i] = 0;\r
c9093a06 314\r
315 Private->VolumeLabel = NULL;\r
316 Status = gBS->AllocatePool (\r
317 EfiBootServicesData,\r
318 StrSize (L"EFI_EMULATED"),\r
319 (VOID **)&Private->VolumeLabel\r
320 );\r
321\r
322 if (EFI_ERROR (Status)) {\r
323 goto Done;\r
324 }\r
325\r
326 StrCpy (Private->VolumeLabel, L"EFI_EMULATED");\r
327\r
328 Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
329 Private->SimpleFileSystem.OpenVolume = UnixSimpleFileSystemOpenVolume;\r
330\r
331 Private->ControllerNameTable = NULL;\r
332\r
333 AddUnicodeString (\r
334 "eng",\r
335 gUnixSimpleFileSystemComponentName.SupportedLanguages,\r
336 &Private->ControllerNameTable,\r
337 UnixIo->EnvString\r
338 );\r
339\r
340 Status = gBS->InstallMultipleProtocolInterfaces (\r
341 &ControllerHandle,\r
342 &gEfiSimpleFileSystemProtocolGuid,\r
343 &Private->SimpleFileSystem,\r
344 NULL\r
345 );\r
346\r
347Done:\r
348 if (EFI_ERROR (Status)) {\r
349\r
350 if (Private != NULL) {\r
351\r
caea5554 352 if (Private->VolumeLabel != NULL)\r
353 gBS->FreePool (Private->VolumeLabel);\r
354 if (Private->FilePath != NULL)\r
355 gBS->FreePool (Private->FilePath);\r
c9093a06 356 FreeUnicodeStringTable (Private->ControllerNameTable);\r
357\r
358 gBS->FreePool (Private);\r
359 }\r
360\r
361 gBS->CloseProtocol (\r
362 ControllerHandle,\r
363 &gEfiUnixIoProtocolGuid,\r
364 This->DriverBindingHandle,\r
365 ControllerHandle\r
366 );\r
367 }\r
368\r
369 return Status;\r
370}\r
371\r
372EFI_STATUS\r
373EFIAPI\r
374UnixSimpleFileSystemDriverBindingStop (\r
375 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
376 IN EFI_HANDLE ControllerHandle,\r
377 IN UINTN NumberOfChildren,\r
378 IN EFI_HANDLE *ChildHandleBuffer\r
379 )\r
380/*++\r
381\r
382Routine Description:\r
383\r
384 TODO: Add function description\r
385\r
386Arguments:\r
387\r
388 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
389\r
390 ControllerHandle - A handle to the device to be stopped.\r
391\r
392 NumberOfChildren - The number of child device handles in ChildHandleBuffer.\r
393\r
394 ChildHandleBuffer - An array of child device handles to be freed.\r
395\r
396Returns:\r
397\r
398 EFI_SUCCESS - The device has been stopped.\r
399\r
400 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.\r
401\r
402--*/\r
403// TODO: EFI_UNSUPPORTED - add return value to function comment\r
404{\r
405 EFI_STATUS Status;\r
406 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;\r
407 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
408\r
409 //\r
410 // Get our context back\r
411 //\r
412 Status = gBS->OpenProtocol (\r
413 ControllerHandle,\r
414 &gEfiSimpleFileSystemProtocolGuid,\r
415 (VOID **)&SimpleFileSystem,\r
416 This->DriverBindingHandle,\r
417 ControllerHandle,\r
418 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
419 );\r
420 if (EFI_ERROR (Status)) {\r
421 return EFI_UNSUPPORTED;\r
422 }\r
423\r
424 Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);\r
425\r
426 //\r
427 // Uninstall the Simple File System Protocol from ControllerHandle\r
428 //\r
429 Status = gBS->UninstallMultipleProtocolInterfaces (\r
430 ControllerHandle,\r
431 &gEfiSimpleFileSystemProtocolGuid,\r
432 &Private->SimpleFileSystem,\r
433 NULL\r
434 );\r
435 if (!EFI_ERROR (Status)) {\r
436 Status = gBS->CloseProtocol (\r
437 ControllerHandle,\r
438 &gEfiUnixIoProtocolGuid,\r
439 This->DriverBindingHandle,\r
440 ControllerHandle\r
441 );\r
442 }\r
443\r
444 if (!EFI_ERROR (Status)) {\r
445 //\r
446 // Free our instance data\r
447 //\r
448 FreeUnicodeStringTable (Private->ControllerNameTable);\r
449\r
450 gBS->FreePool (Private);\r
451 }\r
452\r
453 return Status;\r
454}\r
455\r
456EFI_STATUS\r
457EFIAPI\r
458UnixSimpleFileSystemOpenVolume (\r
459 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
460 OUT EFI_FILE **Root\r
461 )\r
462/*++\r
463\r
464Routine Description:\r
465\r
466 Open the root directory on a volume.\r
467\r
468Arguments:\r
469\r
470 This - A pointer to the volume to open.\r
471\r
472 Root - A pointer to storage for the returned opened file handle of the root directory.\r
473\r
474Returns:\r
475\r
476 EFI_SUCCESS - The volume was opened.\r
477\r
478 EFI_UNSUPPORTED - The volume does not support the requested file system type.\r
479\r
480 EFI_NO_MEDIA - The device has no media.\r
481\r
482 EFI_DEVICE_ERROR - The device reported an error.\r
483\r
484 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
485\r
486 EFI_ACCESS_DENIED - The service denied access to the file.\r
487\r
488 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.\r
489\r
490 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
491\r
492--*/\r
493// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
494{\r
495 EFI_STATUS Status;\r
496 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
497 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
4825e9d8 498 EFI_TPL OldTpl;\r
c9093a06 499\r
500 if (This == NULL || Root == NULL) {\r
501 return EFI_INVALID_PARAMETER;\r
502 }\r
93b0fbc8 503 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
c9093a06 504\r
505 Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);\r
506\r
507 PrivateFile = NULL;\r
508 Status = gBS->AllocatePool (\r
509 EfiBootServicesData,\r
510 sizeof (UNIX_EFI_FILE_PRIVATE),\r
511 (VOID **)&PrivateFile\r
512 );\r
513 if (EFI_ERROR (Status)) {\r
514 goto Done;\r
515 }\r
516\r
517 PrivateFile->FileName = NULL;\r
518 Status = gBS->AllocatePool (\r
519 EfiBootServicesData,\r
520 AsciiStrSize (Private->FilePath),\r
521 (VOID **)&PrivateFile->FileName\r
522 );\r
523 if (EFI_ERROR (Status)) {\r
524 goto Done;\r
525 }\r
526\r
527 AsciiStrCpy (PrivateFile->FileName, Private->FilePath);\r
528 PrivateFile->Signature = UNIX_EFI_FILE_PRIVATE_SIGNATURE;\r
529 PrivateFile->UnixThunk = Private->UnixThunk;\r
530 PrivateFile->SimpleFileSystem = This;\r
531 PrivateFile->IsRootDirectory = TRUE;\r
532 PrivateFile->IsDirectoryPath = TRUE;\r
533 PrivateFile->IsOpenedByRead = TRUE;\r
534 PrivateFile->EfiFile.Revision = EFI_FILE_HANDLE_REVISION;\r
535 PrivateFile->EfiFile.Open = UnixSimpleFileSystemOpen;\r
536 PrivateFile->EfiFile.Close = UnixSimpleFileSystemClose;\r
537 PrivateFile->EfiFile.Delete = UnixSimpleFileSystemDelete;\r
538 PrivateFile->EfiFile.Read = UnixSimpleFileSystemRead;\r
539 PrivateFile->EfiFile.Write = UnixSimpleFileSystemWrite;\r
540 PrivateFile->EfiFile.GetPosition = UnixSimpleFileSystemGetPosition;\r
541 PrivateFile->EfiFile.SetPosition = UnixSimpleFileSystemSetPosition;\r
542 PrivateFile->EfiFile.GetInfo = UnixSimpleFileSystemGetInfo;\r
543 PrivateFile->EfiFile.SetInfo = UnixSimpleFileSystemSetInfo;\r
544 PrivateFile->EfiFile.Flush = UnixSimpleFileSystemFlush;\r
caea5554 545 PrivateFile->fd = -1;\r
546 PrivateFile->Dir = NULL;\r
547 PrivateFile->Dirent = NULL;\r
c9093a06 548 \r
549 *Root = &PrivateFile->EfiFile;\r
550\r
caea5554 551 PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName);\r
c9093a06 552\r
caea5554 553 if (PrivateFile->Dir == NULL) {\r
c9093a06 554 Status = EFI_ACCESS_DENIED;\r
caea5554 555 }\r
556 else {\r
c9093a06 557 Status = EFI_SUCCESS;\r
caea5554 558 }\r
c9093a06 559\r
560Done:\r
561 if (EFI_ERROR (Status)) {\r
562 if (PrivateFile) {\r
563 if (PrivateFile->FileName) {\r
564 gBS->FreePool (PrivateFile->FileName);\r
565 }\r
566\r
567 gBS->FreePool (PrivateFile);\r
568 }\r
569 }\r
570\r
4825e9d8 571 gBS->RestoreTPL (OldTpl);\r
572\r
c9093a06 573 return Status;\r
574}\r
575\r
576EFI_STATUS\r
577EFIAPI\r
578UnixSimpleFileSystemOpen (\r
579 IN EFI_FILE *This,\r
580 OUT EFI_FILE **NewHandle,\r
581 IN CHAR16 *FileName,\r
582 IN UINT64 OpenMode,\r
583 IN UINT64 Attributes\r
584 )\r
585/*++\r
586\r
587Routine Description:\r
588\r
589 Open a file relative to the source file location.\r
590\r
591Arguments:\r
592\r
593 This - A pointer to the source file location.\r
594\r
595 NewHandle - Pointer to storage for the new file handle.\r
596\r
597 FileName - Pointer to the file name to be opened.\r
598\r
599 OpenMode - File open mode information.\r
600\r
601 Attributes - File creation attributes.\r
602\r
603Returns:\r
604\r
605 EFI_SUCCESS - The file was opened.\r
606\r
607 EFI_NOT_FOUND - The file could not be found in the volume.\r
608\r
609 EFI_NO_MEDIA - The device has no media.\r
610\r
611 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
612\r
613 EFI_DEVICE_ERROR - The device reported an error.\r
614\r
615 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
616\r
617 EFI_WRITE_PROTECTED - The volume or file is write protected.\r
618\r
619 EFI_ACCESS_DENIED - The service denied access to the file.\r
620\r
621 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.\r
622\r
623 EFI_VOLUME_FULL - There is not enough space left to create the new file.\r
624\r
625--*/\r
626// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
627// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
628// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
629// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
630{\r
631 EFI_FILE *Root;\r
632 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
633 UNIX_EFI_FILE_PRIVATE *NewPrivateFile;\r
634 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
635 EFI_STATUS Status;\r
caea5554 636 CHAR16 *Src;\r
637 char *Dst;\r
c9093a06 638 CHAR8 *RealFileName;\r
c9093a06 639 char *ParseFileName;\r
640 char *GuardPointer;\r
641 CHAR8 TempChar;\r
642 UINTN Count;\r
643 BOOLEAN TrailingDash;\r
644 BOOLEAN LoopFinish;\r
645 UINTN InfoSize;\r
646 EFI_FILE_INFO *Info;\r
647\r
648 TrailingDash = FALSE;\r
649\r
650 //\r
651 // Check for obvious invalid parameters.\r
652 //\r
653 if (This == NULL || NewHandle == NULL || FileName == NULL) {\r
654 return EFI_INVALID_PARAMETER;\r
655 }\r
656\r
657 switch (OpenMode) {\r
658 case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
659 if (Attributes &~EFI_FILE_VALID_ATTR) {\r
660 return EFI_INVALID_PARAMETER;\r
661 }\r
662\r
663 if (Attributes & EFI_FILE_READ_ONLY) {\r
664 return EFI_INVALID_PARAMETER;\r
665 }\r
666\r
667 //\r
668 // fall through\r
669 //\r
670 case EFI_FILE_MODE_READ:\r
671 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
672 break;\r
673\r
674 default:\r
675 return EFI_INVALID_PARAMETER;\r
676 }\r
677\r
ac10bddd 678\r
c9093a06 679 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
680 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
681 NewPrivateFile = NULL;\r
682\r
683 //\r
684 // BUGBUG: assume an open of root\r
685 // if current location, return current data\r
686 //\r
caea5554 687 if (StrCmp (FileName, L"\\") == 0\r
c9093a06 688 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {\r
689 //\r
690 // BUGBUG: assume an open root\r
691 //\r
692OpenRoot:\r
693 Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);\r
694 NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);\r
695 goto Done;\r
696 }\r
697\r
698 if (FileName[StrLen (FileName) - 1] == L'\\') {\r
699 TrailingDash = TRUE;\r
700 FileName[StrLen (FileName) - 1] = 0;\r
701 }\r
702\r
703 //\r
704 // Attempt to open the file\r
705 //\r
706 Status = gBS->AllocatePool (\r
707 EfiBootServicesData,\r
708 sizeof (UNIX_EFI_FILE_PRIVATE),\r
709 (VOID **)&NewPrivateFile\r
710 );\r
711\r
712 if (EFI_ERROR (Status)) {\r
713 goto Done;\r
714 }\r
715\r
716 CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE));\r
717\r
718 NewPrivateFile->FileName = NULL;\r
719 Status = gBS->AllocatePool (\r
720 EfiBootServicesData,\r
721 AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1,\r
722 (VOID **)&NewPrivateFile->FileName\r
723 );\r
724\r
725 if (EFI_ERROR (Status)) {\r
726 goto Done;\r
727 }\r
728\r
729 if (*FileName == L'\\') {\r
730 AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);\r
caea5554 731 // Skip first '\'.\r
732 Src = FileName + 1;\r
c9093a06 733 } else {\r
734 AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);\r
caea5554 735 Src = FileName;\r
736 }\r
737 Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName);\r
738 GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath);\r
739 *Dst++ = '/';\r
740 // Convert unicode to ascii and '\' to '/'\r
741 while (*Src) {\r
742 if (*Src == '\\')\r
743 *Dst++ = '/';\r
744 else\r
745 *Dst++ = *Src;\r
746 Src++;\r
747 }\r
748 *Dst = 0;\r
749 \r
c9093a06 750\r
751 //\r
752 // Get rid of . and .., except leading . or ..\r
753 //\r
754\r
755 //\r
756 // GuardPointer protect simplefilesystem root path not be destroyed\r
757 //\r
758\r
759 LoopFinish = FALSE;\r
760\r
761 while (!LoopFinish) {\r
762\r
763 LoopFinish = TRUE;\r
764\r
765 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {\r
766 if (*ParseFileName == '.' &&\r
767 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') &&\r
768 *(ParseFileName - 1) == '/'\r
769 ) {\r
770\r
771 //\r
772 // cut /.\r
773 //\r
774 CutPrefix (ParseFileName - 1, 2);\r
775 LoopFinish = FALSE;\r
776 break;\r
777 }\r
778\r
779 if (*ParseFileName == '.' &&\r
780 *(ParseFileName + 1) == '.' &&\r
781 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') &&\r
782 *(ParseFileName - 1) == '/'\r
783 ) {\r
784\r
785 ParseFileName--;\r
786 Count = 3;\r
787\r
788 while (ParseFileName != GuardPointer) {\r
789 ParseFileName--;\r
790 Count++;\r
791 if (*ParseFileName == '/') {\r
792 break;\r
793 }\r
794 }\r
795\r
796 //\r
797 // cut /.. and its left directory\r
798 //\r
799 CutPrefix (ParseFileName, Count);\r
800 LoopFinish = FALSE;\r
801 break;\r
802 }\r
803 }\r
804 }\r
805\r
806 if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {\r
807 NewPrivateFile->IsRootDirectory = TRUE;\r
808 gBS->FreePool (NewPrivateFile->FileName);\r
809 gBS->FreePool (NewPrivateFile);\r
810 goto OpenRoot;\r
811 }\r
812\r
813 RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1;\r
caea5554 814 while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')\r
815 RealFileName--;\r
c9093a06 816\r
817 TempChar = *(RealFileName - 1);\r
818 *(RealFileName - 1) = 0;\r
819\r
820 *(RealFileName - 1) = TempChar;\r
821\r
caea5554 822\r
823\r
c9093a06 824 //\r
825 // Test whether file or directory\r
826 //\r
827 NewPrivateFile->IsRootDirectory = FALSE;\r
caea5554 828 NewPrivateFile->fd = -1;\r
829 NewPrivateFile->Dir = NULL;\r
c9093a06 830 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
831 if (Attributes & EFI_FILE_DIRECTORY) {\r
832 NewPrivateFile->IsDirectoryPath = TRUE;\r
833 } else {\r
834 NewPrivateFile->IsDirectoryPath = FALSE;\r
835 }\r
836 } else {\r
caea5554 837 struct stat finfo;\r
838 int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo);\r
839 if (res == 0 && S_ISDIR(finfo.st_mode))\r
c9093a06 840 NewPrivateFile->IsDirectoryPath = TRUE;\r
caea5554 841 else\r
c9093a06 842 NewPrivateFile->IsDirectoryPath = FALSE;\r
843 }\r
844\r
845 if (OpenMode & EFI_FILE_MODE_WRITE) {\r
846 NewPrivateFile->IsOpenedByRead = FALSE;\r
847 } else {\r
848 NewPrivateFile->IsOpenedByRead = TRUE;\r
849 }\r
850\r
851 Status = EFI_SUCCESS;\r
852\r
853 //\r
854 // deal with directory\r
855 //\r
856 if (NewPrivateFile->IsDirectoryPath) {\r
857\r
858 if ((OpenMode & EFI_FILE_MODE_CREATE)) {\r
859 //\r
860 // Create a directory\r
861 //\r
862 if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) {\r
caea5554 863 INTN LastError;\r
c9093a06 864\r
865 LastError = PrivateFile->UnixThunk->GetErrno ();\r
caea5554 866 if (LastError != EEXIST) {\r
8ef571df 867 //gBS->FreePool (TempFileName);\r
c9093a06 868 Status = EFI_ACCESS_DENIED;\r
869 goto Done;\r
870 }\r
871 }\r
872 }\r
873\r
caea5554 874 NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir\r
875 (NewPrivateFile->FileName);\r
c9093a06 876\r
caea5554 877 if (NewPrivateFile->Dir == NULL) {\r
878 if (PrivateFile->UnixThunk->GetErrno () == EACCES) {\r
c9093a06 879 Status = EFI_ACCESS_DENIED;\r
880 } else {\r
881 Status = EFI_NOT_FOUND;\r
882 }\r
883\r
884 goto Done;\r
885 }\r
886\r
887 } else {\r
888 //\r
889 // deal with file\r
890 //\r
caea5554 891 NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open\r
c9093a06 892 (NewPrivateFile->FileName,\r
caea5554 893 ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0)\r
894 | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR),\r
895 0666);\r
896 if (NewPrivateFile->fd < 0) {\r
897 if (PrivateFile->UnixThunk->GetErrno () == ENOENT) {\r
c9093a06 898 Status = EFI_NOT_FOUND;\r
899 } else {\r
900 Status = EFI_ACCESS_DENIED;\r
901 }\r
902 }\r
903 }\r
904\r
905 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {\r
906 //\r
907 // Set the attribute\r
908 //\r
909 InfoSize = 0;\r
910 Info = NULL;\r
911\r
912 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
913\r
914 if (Status != EFI_BUFFER_TOO_SMALL) {\r
915 Status = EFI_DEVICE_ERROR;\r
916 goto Done;\r
917 }\r
918\r
919 Status = gBS->AllocatePool (\r
920 EfiBootServicesData,\r
921 InfoSize,\r
922 (VOID **)&Info\r
923 );\r
924\r
925 if (EFI_ERROR (Status)) {\r
926 goto Done;\r
927 }\r
928\r
929 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
930\r
931 if (EFI_ERROR (Status)) {\r
932 goto Done;\r
933 }\r
934\r
935 Info->Attribute = Attributes;\r
936\r
937 UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);\r
938 }\r
939\r
940Done: ;\r
941 if (TrailingDash) {\r
942 FileName[StrLen (FileName) + 1] = 0;\r
943 FileName[StrLen (FileName)] = L'\\';\r
944 }\r
945\r
946 if (EFI_ERROR (Status)) {\r
947 if (NewPrivateFile) {\r
948 if (NewPrivateFile->FileName) {\r
949 gBS->FreePool (NewPrivateFile->FileName);\r
950 }\r
951\r
952 gBS->FreePool (NewPrivateFile);\r
953 }\r
954 } else {\r
955 *NewHandle = &NewPrivateFile->EfiFile;\r
956 }\r
957\r
958 return Status;\r
959}\r
960\r
961EFI_STATUS\r
962EFIAPI\r
963UnixSimpleFileSystemClose (\r
964 IN EFI_FILE *This\r
965 )\r
966/*++\r
967\r
968Routine Description:\r
969\r
970 Close the specified file handle.\r
971\r
972Arguments:\r
973\r
974 This - Pointer to a returned opened file handle.\r
975\r
976Returns:\r
977\r
978 EFI_SUCCESS - The file handle has been closed.\r
979\r
980--*/\r
981// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
982{\r
983 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
ebc5b955 984 EFI_TPL OldTpl;\r
c9093a06 985\r
986 if (This == NULL) {\r
987 return EFI_INVALID_PARAMETER;\r
988 }\r
989\r
990 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
991\r
93b0fbc8 992 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 993\r
caea5554 994 if (PrivateFile->fd >= 0) {\r
c9093a06 995 PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
caea5554 996 }\r
997 if (PrivateFile->Dir != NULL) {\r
c9093a06 998 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
caea5554 999 }\r
c9093a06 1000\r
caea5554 1001 PrivateFile->fd = -1;\r
1002 PrivateFile->Dir = NULL;\r
c9093a06 1003\r
1004 if (PrivateFile->FileName) {\r
1005 gBS->FreePool (PrivateFile->FileName);\r
1006 }\r
1007\r
1008 gBS->FreePool (PrivateFile);\r
ac10bddd 1009\r
1010 gBS->RestoreTPL (OldTpl);\r
1011 \r
c9093a06 1012 return EFI_SUCCESS;\r
1013}\r
1014\r
1015EFI_STATUS\r
1016EFIAPI\r
1017UnixSimpleFileSystemDelete (\r
1018 IN EFI_FILE *This\r
1019 )\r
1020/*++\r
1021\r
1022Routine Description:\r
1023\r
1024 Close and delete a file.\r
1025\r
1026Arguments:\r
1027\r
1028 This - Pointer to a returned opened file handle.\r
1029\r
1030Returns:\r
1031\r
1032 EFI_SUCCESS - The file handle was closed and deleted.\r
1033\r
1034 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.\r
1035\r
1036--*/\r
1037// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1038{\r
1039 EFI_STATUS Status;\r
ac10bddd 1040 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1041 EFI_TPL OldTpl;\r
c9093a06 1042\r
1043 if (This == NULL) {\r
1044 return EFI_INVALID_PARAMETER;\r
1045 }\r
1046\r
93b0fbc8 1047 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1048 \r
c9093a06 1049 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1050\r
1051 Status = EFI_WARN_DELETE_FAILURE;\r
1052\r
1053 if (PrivateFile->IsDirectoryPath) {\r
1054 if (PrivateFile->Dir != NULL) {\r
1055 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
caea5554 1056 PrivateFile->Dir = NULL;\r
c9093a06 1057 }\r
1058\r
1059 if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) {\r
1060 Status = EFI_SUCCESS;\r
1061 }\r
1062 } else {\r
1063 PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
caea5554 1064 PrivateFile->fd = -1;\r
c9093a06 1065\r
1066 if (!PrivateFile->IsOpenedByRead) {\r
1067 if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) {\r
1068 Status = EFI_SUCCESS;\r
1069 }\r
1070 }\r
1071 }\r
1072\r
1073 gBS->FreePool (PrivateFile->FileName);\r
1074 gBS->FreePool (PrivateFile);\r
1075\r
4825e9d8 1076 gBS->RestoreTPL (OldTpl);\r
1077\r
c9093a06 1078 return Status;\r
1079}\r
1080\r
1081STATIC\r
1082VOID\r
1083UnixSystemTimeToEfiTime (\r
1084 EFI_UNIX_THUNK_PROTOCOL *UnixThunk,\r
caea5554 1085 IN time_t SystemTime,\r
c9093a06 1086 OUT EFI_TIME *Time\r
1087 )\r
1088/*++\r
1089\r
1090Routine Description:\r
1091\r
1092 TODO: Add function description\r
1093\r
1094Arguments:\r
1095\r
1096 SystemTime - TODO: add argument description\r
1097 TimeZone - TODO: add argument description\r
1098 Time - TODO: add argument description\r
1099\r
1100Returns:\r
1101\r
1102 TODO: add return values\r
1103\r
1104--*/\r
1105{\r
caea5554 1106 struct tm *tm;\r
1107 tm = UnixThunk->GmTime (&SystemTime);\r
1108 Time->Year = tm->tm_year;\r
1109 Time->Month = tm->tm_mon;\r
1110 Time->Day = tm->tm_mday;\r
1111 Time->Hour = tm->tm_hour;\r
1112 Time->Minute = tm->tm_min;\r
1113 Time->Second = tm->tm_sec;\r
1114 Time->Nanosecond = 0;\r
1115\r
1116 Time->TimeZone = UnixThunk->GetTimeZone ();\r
1117\r
1118 if (UnixThunk->GetDayLight ()) {\r
c9093a06 1119 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
1120 }\r
1121}\r
1122\r
1123STATIC\r
1124EFI_STATUS\r
1125UnixSimpleFileSystemFileInfo (\r
1126 UNIX_EFI_FILE_PRIVATE *PrivateFile,\r
caea5554 1127 IN CHAR8 *FileName,\r
c9093a06 1128 IN OUT UINTN *BufferSize,\r
1129 OUT VOID *Buffer\r
1130 )\r
1131/*++\r
1132\r
1133Routine Description:\r
1134\r
1135 TODO: Add function description\r
1136\r
1137Arguments:\r
1138\r
1139 PrivateFile - TODO: add argument description\r
1140 BufferSize - TODO: add argument description\r
1141 Buffer - TODO: add argument description\r
1142\r
1143Returns:\r
1144\r
1145 TODO: add return values\r
1146\r
1147--*/\r
1148{\r
1149 EFI_STATUS Status;\r
1150 UINTN Size;\r
1151 UINTN NameSize;\r
1152 UINTN ResultSize;\r
1153 EFI_FILE_INFO *Info;\r
1154 CHAR8 *RealFileName;\r
1155 CHAR8 *TempPointer;\r
caea5554 1156 CHAR16 *BufferFileName;\r
1157 struct stat buf;\r
c9093a06 1158\r
caea5554 1159 if (FileName != NULL) {\r
1160 RealFileName = FileName;\r
1161 }\r
c9093a06 1162 else if (PrivateFile->IsRootDirectory) {\r
caea5554 1163 RealFileName = "";\r
c9093a06 1164 } else {\r
1165 RealFileName = PrivateFile->FileName;\r
caea5554 1166 }\r
1167\r
c9093a06 1168 TempPointer = RealFileName;\r
1169 while (*TempPointer) {\r
1170 if (*TempPointer == '/') {\r
1171 RealFileName = TempPointer + 1;\r
1172 }\r
1173\r
1174 TempPointer++;\r
1175 }\r
caea5554 1176\r
c9093a06 1177 Size = SIZE_OF_EFI_FILE_INFO;\r
1178 NameSize = AsciiStrSize (RealFileName) * 2;\r
1179 ResultSize = Size + NameSize;\r
1180\r
1181 if (*BufferSize < ResultSize) {\r
1182 *BufferSize = ResultSize;\r
1183 return EFI_BUFFER_TOO_SMALL;\r
caea5554 1184 }\r
1185 if (PrivateFile->UnixThunk->Stat (\r
1186 FileName == NULL ? PrivateFile->FileName : FileName,\r
1187 &buf) < 0)\r
1188 return EFI_DEVICE_ERROR;\r
1189\r
c9093a06 1190 Status = EFI_SUCCESS;\r
1191\r
1192 Info = Buffer;\r
1193 ZeroMem (Info, ResultSize);\r
1194\r
1195 Info->Size = ResultSize;\r
caea5554 1196 Info->FileSize = buf.st_size;\r
1197 Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize);\r
1198\r
1199 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime);\r
1200 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime);\r
1201 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime);\r
1202\r
1203 if (!(buf.st_mode & S_IWUSR)) {\r
c9093a06 1204 Info->Attribute |= EFI_FILE_READ_ONLY;\r
1205 }\r
1206\r
caea5554 1207 if (S_ISDIR(buf.st_mode)) {\r
c9093a06 1208 Info->Attribute |= EFI_FILE_DIRECTORY;\r
1209 }\r
1210\r
1211\r
caea5554 1212 BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size);\r
1213 while (*RealFileName)\r
1214 *BufferFileName++ = *RealFileName++;\r
1215 *BufferFileName = 0;\r
1216\r
c9093a06 1217 *BufferSize = ResultSize;\r
1218 return Status;\r
1219}\r
1220\r
1221EFI_STATUS\r
1222EFIAPI\r
1223UnixSimpleFileSystemRead (\r
1224 IN EFI_FILE *This,\r
1225 IN OUT UINTN *BufferSize,\r
1226 OUT VOID *Buffer\r
1227 )\r
1228/*++\r
1229\r
1230Routine Description:\r
1231\r
1232 Read data from a file.\r
1233\r
1234Arguments:\r
1235\r
1236 This - Pointer to a returned open file handle.\r
1237\r
1238 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
1239\r
1240 Buffer - Pointer to the first byte of the read Buffer.\r
1241\r
1242Returns:\r
1243\r
1244 EFI_SUCCESS - The data was read.\r
1245\r
1246 EFI_NO_MEDIA - The device has no media.\r
1247\r
1248 EFI_DEVICE_ERROR - The device reported an error.\r
1249\r
1250 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
1251\r
1252 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
1253 *BufferSize has been updated with the size needed to complete the request.\r
1254\r
1255--*/\r
1256// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1257{\r
1258 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1259 EFI_STATUS Status;\r
caea5554 1260 INTN Res;\r
c9093a06 1261 UINTN Size;\r
1262 UINTN NameSize;\r
1263 UINTN ResultSize;\r
caea5554 1264 CHAR8 *FullFileName;\r
ac10bddd 1265 EFI_TPL OldTpl;\r
c9093a06 1266\r
1267 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1268 return EFI_INVALID_PARAMETER;\r
1269 }\r
1270\r
93b0fbc8 1271 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1272 \r
c9093a06 1273 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1274\r
1275 if (!PrivateFile->IsDirectoryPath) {\r
1276\r
1277 if (PrivateFile->fd < 0) {\r
4825e9d8 1278 Status = EFI_DEVICE_ERROR;\r
1279 goto Done;\r
c9093a06 1280 }\r
1281\r
1282 Res = PrivateFile->UnixThunk->Read (\r
1283 PrivateFile->fd,\r
1284 Buffer,\r
caea5554 1285 *BufferSize);\r
4825e9d8 1286 if (Res < 0) {\r
1287 Status = EFI_DEVICE_ERROR;\r
1288 goto Done;\r
1289 }\r
caea5554 1290 *BufferSize = Res;\r
4825e9d8 1291 Status = EFI_SUCCESS;\r
1292 goto Done;\r
c9093a06 1293 }\r
1294\r
1295 //\r
caea5554 1296 // Read on a directory.\r
c9093a06 1297 //\r
1298 if (PrivateFile->Dir == NULL) {\r
4825e9d8 1299 Status = EFI_DEVICE_ERROR;\r
1300 goto Done;\r
c9093a06 1301 }\r
caea5554 1302\r
1303 if (PrivateFile->Dirent == NULL) {\r
1304 PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);\r
1305 if (PrivateFile->Dirent == NULL) {\r
c9093a06 1306 *BufferSize = 0;\r
4825e9d8 1307 Status = EFI_SUCCESS;\r
1308 goto Done;\r
caea5554 1309 }\r
1310 }\r
1311\r
c9093a06 1312 Size = SIZE_OF_EFI_FILE_INFO;\r
caea5554 1313 NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;\r
c9093a06 1314 ResultSize = Size + 2 * NameSize;\r
1315\r
1316 if (*BufferSize < ResultSize) {\r
1317 *BufferSize = ResultSize;\r
4825e9d8 1318 Status = EFI_BUFFER_TOO_SMALL;\r
1319 goto Done;\r
caea5554 1320 }\r
c9093a06 1321 Status = EFI_SUCCESS;\r
1322\r
1323 *BufferSize = ResultSize;\r
caea5554 1324\r
c9093a06 1325 Status = gBS->AllocatePool (\r
1326 EfiBootServicesData,\r
caea5554 1327 AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,\r
1328 (VOID **)&FullFileName\r
c9093a06 1329 );\r
1330\r
1331 if (EFI_ERROR (Status)) {\r
4825e9d8 1332 goto Done;\r
c9093a06 1333 }\r
caea5554 1334 \r
1335 AsciiStrCpy(FullFileName, PrivateFile->FileName);\r
1336 AsciiStrCat(FullFileName, "/");\r
1337 AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);\r
1338 Status = UnixSimpleFileSystemFileInfo (PrivateFile,\r
1339 FullFileName,\r
1340 BufferSize,\r
1341 Buffer);\r
1342 gBS->FreePool (FullFileName);\r
c9093a06 1343\r
caea5554 1344 PrivateFile->Dirent = NULL;\r
c9093a06 1345\r
4825e9d8 1346Done:\r
1347 gBS->RestoreTPL (OldTpl);\r
1348\r
caea5554 1349 return Status;\r
c9093a06 1350}\r
1351\r
1352EFI_STATUS\r
1353EFIAPI\r
1354UnixSimpleFileSystemWrite (\r
1355 IN EFI_FILE *This,\r
1356 IN OUT UINTN *BufferSize,\r
1357 IN VOID *Buffer\r
1358 )\r
1359/*++\r
1360\r
1361Routine Description:\r
1362\r
1363 Write data to a file.\r
1364\r
1365Arguments:\r
1366\r
1367 This - Pointer to an opened file handle.\r
1368\r
1369 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
1370 of data written to the file.\r
1371\r
1372 Buffer - Pointer to the first by of data in the buffer to write to the file.\r
1373\r
1374Returns:\r
1375\r
1376 EFI_SUCCESS - The data was written to the file.\r
1377\r
1378 EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
1379\r
1380 EFI_NO_MEDIA - The device has no media.\r
1381\r
1382 EFI_DEVICE_ERROR - The device reported an error.\r
1383\r
1384 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1385\r
1386 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1387\r
1388 EFI_ACCESS_DENIED - The file was opened read-only.\r
1389\r
1390 EFI_VOLUME_FULL - The volume is full.\r
1391\r
1392--*/\r
1393// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1394{\r
1395 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
ac10bddd 1396 UINTN Res;\r
1397 EFI_STATUS Status;\r
1398 EFI_TPL OldTpl;\r
c9093a06 1399\r
1400 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1401 return EFI_INVALID_PARAMETER;\r
1402 }\r
1403\r
93b0fbc8 1404 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
4825e9d8 1405\r
c9093a06 1406 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1407\r
1408 if (PrivateFile->fd < 0) {\r
1409 return EFI_DEVICE_ERROR;\r
1410 }\r
1411\r
1412 if (PrivateFile->IsDirectoryPath) {\r
1413 return EFI_UNSUPPORTED;\r
1414 }\r
1415\r
1416 if (PrivateFile->IsOpenedByRead) {\r
1417 return EFI_ACCESS_DENIED;\r
1418 }\r
1419\r
1420 Res = PrivateFile->UnixThunk->Write (\r
1421 PrivateFile->fd,\r
1422 Buffer,\r
caea5554 1423 *BufferSize);\r
ac10bddd 1424 if (Res == (UINTN)-1) {\r
1425 Status = EFI_DEVICE_ERROR;\r
1426 goto Done;\r
1427 }\r
caea5554 1428 *BufferSize = Res;\r
ac10bddd 1429 Status = EFI_SUCCESS;\r
1430\r
1431Done:\r
1432 gBS->RestoreTPL (OldTpl);\r
1433 return Status;\r
c9093a06 1434\r
1435 //\r
377fc2ae 1436 // bugbug: need to access unix error reporting\r
c9093a06 1437 //\r
1438}\r
1439\r
1440EFI_STATUS\r
1441EFIAPI\r
1442UnixSimpleFileSystemSetPosition (\r
1443 IN EFI_FILE *This,\r
1444 IN UINT64 Position\r
1445 )\r
1446/*++\r
1447\r
1448Routine Description:\r
1449\r
1450 Set a file's current position.\r
1451\r
1452Arguments:\r
1453\r
1454 This - Pointer to an opened file handle.\r
1455\r
1456 Position - The byte position from the start of the file to set.\r
1457\r
1458Returns:\r
1459\r
1460 EFI_SUCCESS - The file position has been changed.\r
1461\r
1462 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
1463\r
1464--*/\r
1465// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1466{\r
1467 EFI_STATUS Status;\r
1468 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1469 UINT64 Pos;\r
ac10bddd 1470 EFI_TPL OldTpl;\r
c9093a06 1471\r
1472 if (This == NULL) {\r
1473 return EFI_INVALID_PARAMETER;\r
1474 }\r
1475\r
93b0fbc8 1476 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1477 \r
c9093a06 1478 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1479\r
1480 if (PrivateFile->IsDirectoryPath) {\r
1481 if (Position != 0) {\r
ac10bddd 1482 Status = EFI_UNSUPPORTED;\r
1483 goto Done;\r
c9093a06 1484 }\r
1485\r
caea5554 1486 if (PrivateFile->Dir == NULL) {\r
ac10bddd 1487 Status = EFI_DEVICE_ERROR;\r
1488 goto Done;\r
caea5554 1489 }\r
1490 PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);\r
ac10bddd 1491 Status = EFI_SUCCESS;\r
1492 goto Done;\r
c9093a06 1493 } else {\r
1494 if (Position == (UINT64) -1) {\r
1495 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);\r
1496 } else {\r
1497 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);\r
caea5554 1498 }\r
c9093a06 1499 Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
ac10bddd 1500 }\r
c9093a06 1501\r
ac10bddd 1502Done:\r
1503 gBS->RestoreTPL (OldTpl);\r
c9093a06 1504 return Status;\r
c9093a06 1505}\r
1506\r
1507EFI_STATUS\r
1508EFIAPI\r
1509UnixSimpleFileSystemGetPosition (\r
1510 IN EFI_FILE *This,\r
1511 OUT UINT64 *Position\r
1512 )\r
1513/*++\r
1514\r
1515Routine Description:\r
1516\r
1517 Get a file's current position.\r
1518\r
1519Arguments:\r
1520\r
1521 This - Pointer to an opened file handle.\r
1522\r
1523 Position - Pointer to storage for the current position.\r
1524\r
1525Returns:\r
1526\r
1527 EFI_SUCCESS - The file position has been reported.\r
1528\r
1529 EFI_UNSUPPORTED - Not valid for directories.\r
1530\r
1531--*/\r
1532// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1533{\r
ac10bddd 1534 EFI_STATUS Status;\r
c9093a06 1535 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
ac10bddd 1536 EFI_TPL OldTpl;\r
c9093a06 1537\r
1538 if (This == NULL || Position == NULL) {\r
1539 return EFI_INVALID_PARAMETER;\r
1540 }\r
1541\r
93b0fbc8 1542 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1543 \r
c9093a06 1544 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1545\r
1546 if (PrivateFile->IsDirectoryPath) {\r
ac10bddd 1547 Status = EFI_UNSUPPORTED;\r
c9093a06 1548 } else {\r
caea5554 1549 *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);\r
ac10bddd 1550 Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
c9093a06 1551 }\r
ac10bddd 1552\r
5db2b1e1 1553 gBS->RestoreTPL (OldTpl);\r
ac10bddd 1554 return Status;\r
c9093a06 1555}\r
1556\r
1557EFI_STATUS\r
1558EFIAPI\r
1559UnixSimpleFileSystemGetInfo (\r
1560 IN EFI_FILE *This,\r
1561 IN EFI_GUID *InformationType,\r
1562 IN OUT UINTN *BufferSize,\r
1563 OUT VOID *Buffer\r
1564 )\r
1565/*++\r
1566\r
1567Routine Description:\r
1568\r
1569 Return information about a file or volume.\r
1570\r
1571Arguments:\r
1572\r
1573 This - Pointer to an opened file handle.\r
1574\r
1575 InformationType - GUID describing the type of information to be returned.\r
1576\r
1577 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
1578 information buffer.\r
1579\r
1580 Buffer - Pointer to the first byte of the information buffer.\r
1581\r
1582Returns:\r
1583\r
1584 EFI_SUCCESS - The requested information has been written into the buffer.\r
1585\r
1586 EFI_UNSUPPORTED - The InformationType is not known.\r
1587\r
1588 EFI_NO_MEDIA - The device has no media.\r
1589\r
1590 EFI_DEVICE_ERROR - The device reported an error.\r
1591\r
1592 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1593\r
1594 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
1595 been updated with the size needed to complete the requested operation.\r
1596\r
1597--*/\r
1598// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1599{\r
1600 EFI_STATUS Status;\r
1601 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1602 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
1603 INTN UnixStatus;\r
1604 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
caea5554 1605 struct statfs buf;\r
ac10bddd 1606 EFI_TPL OldTpl;\r
c9093a06 1607\r
1608 if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
1609 return EFI_INVALID_PARAMETER;\r
1610 }\r
1611\r
93b0fbc8 1612 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1613 \r
c9093a06 1614 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1615 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1616\r
1617 Status = EFI_UNSUPPORTED;\r
1618\r
1619 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1620 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer);\r
ac10bddd 1621 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
c9093a06 1622 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
1623 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
ac10bddd 1624 Status = EFI_BUFFER_TOO_SMALL;\r
1625 goto Done;\r
c9093a06 1626 }\r
1627\r
caea5554 1628 UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);\r
ac10bddd 1629 if (UnixStatus < 0) {\r
1630 Status = EFI_DEVICE_ERROR;\r
1631 goto Done;\r
1632 }\r
caea5554 1633\r
c9093a06 1634 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1635 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1636 FileSystemInfoBuffer->ReadOnly = FALSE;\r
1637\r
1638 //\r
1639 // Succeeded\r
1640 //\r
caea5554 1641 FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize);\r
1642 FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize);\r
1643 FileSystemInfoBuffer->BlockSize = buf.f_bsize;\r
c9093a06 1644\r
1645\r
1646 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
1647 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1648 Status = EFI_SUCCESS;\r
ebc5b955 1649 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
c9093a06 1650 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
1651 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
ac10bddd 1652 Status = EFI_BUFFER_TOO_SMALL;\r
1653 goto Done;\r
c9093a06 1654 }\r
1655\r
1656 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
1657 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
1658 Status = EFI_SUCCESS;\r
1659 }\r
1660\r
ac10bddd 1661Done:\r
1662 gBS->RestoreTPL (OldTpl);\r
c9093a06 1663 return Status;\r
1664}\r
1665\r
1666EFI_STATUS\r
1667EFIAPI\r
1668UnixSimpleFileSystemSetInfo (\r
1669 IN EFI_FILE *This,\r
1670 IN EFI_GUID *InformationType,\r
1671 IN UINTN BufferSize,\r
1672 IN VOID *Buffer\r
1673 )\r
1674/*++\r
1675\r
1676Routine Description:\r
1677\r
1678 Set information about a file or volume.\r
1679\r
1680Arguments:\r
1681\r
1682 This - Pointer to an opened file handle.\r
1683\r
1684 InformationType - GUID identifying the type of information to set.\r
1685\r
1686 BufferSize - Number of bytes of data in the information buffer.\r
1687\r
1688 Buffer - Pointer to the first byte of data in the information buffer.\r
1689\r
1690Returns:\r
1691\r
1692 EFI_SUCCESS - The file or volume information has been updated.\r
1693\r
1694 EFI_UNSUPPORTED - The information identifier is not recognised.\r
1695\r
1696 EFI_NO_MEDIA - The device has no media.\r
1697\r
1698 EFI_DEVICE_ERROR - The device reported an error.\r
1699\r
1700 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1701\r
1702 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1703\r
1704 EFI_ACCESS_DENIED - The file was opened read-only.\r
1705\r
1706 EFI_VOLUME_FULL - The volume is full.\r
1707\r
1708 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
1709\r
1710--*/\r
1711// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1712// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1713{\r
1714 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
1715 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1716 EFI_FILE_INFO *OldFileInfo;\r
1717 EFI_FILE_INFO *NewFileInfo;\r
1718 EFI_STATUS Status;\r
1719 UINTN OldInfoSize;\r
ac10bddd 1720 EFI_TPL OldTpl;\r
c9093a06 1721 mode_t NewAttr;\r
1722 struct stat OldAttr;\r
1723 CHAR8 *OldFileName;\r
1724 CHAR8 *NewFileName;\r
1725 CHAR8 *CharPointer;\r
1726 BOOLEAN AttrChangeFlag;\r
1727 BOOLEAN NameChangeFlag;\r
1728 BOOLEAN SizeChangeFlag;\r
1729 BOOLEAN TimeChangeFlag;\r
1730 struct tm NewLastAccessSystemTime;\r
1731 struct tm NewLastWriteSystemTime;\r
1732 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
caea5554 1733 CHAR8 *AsciiFilePtr;\r
1734 CHAR16 *UnicodeFilePtr;\r
1735 INTN UnixStatus;\r
c9093a06 1736\r
1737 //\r
1738 // Check for invalid parameters.\r
1739 //\r
1740 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
1741 return EFI_INVALID_PARAMETER;\r
1742 }\r
1743\r
93b0fbc8 1744 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 1745 \r
c9093a06 1746 //\r
1747 // Initialise locals.\r
1748 //\r
1749 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1750 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1751\r
1752 Status = EFI_UNSUPPORTED;\r
1753 OldFileInfo = NewFileInfo = NULL;\r
1754 OldFileName = NewFileName = NULL;\r
1755 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
1756\r
1757 //\r
1758 // Set file system information.\r
1759 //\r
1760 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1761 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
ac10bddd 1762 Status = EFI_BAD_BUFFER_SIZE;\r
1763 goto Done;\r
c9093a06 1764 }\r
1765\r
1766 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1767\r
1768 gBS->FreePool (PrivateRoot->VolumeLabel);\r
1769\r
1770 PrivateRoot->VolumeLabel = NULL;\r
1771 Status = gBS->AllocatePool (\r
1772 EfiBootServicesData,\r
1773 StrSize (NewFileSystemInfo->VolumeLabel),\r
1774 (VOID **)&PrivateRoot->VolumeLabel\r
1775 );\r
1776\r
1777 if (EFI_ERROR (Status)) {\r
1778 goto Done;\r
1779 }\r
1780\r
1781 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
1782\r
ac10bddd 1783 Status = EFI_SUCCESS;\r
1784 goto Done;\r
c9093a06 1785 }\r
1786\r
1787 //\r
1788 // Set volume label information.\r
1789 //\r
1790 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1791 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
ac10bddd 1792 Status = EFI_BAD_BUFFER_SIZE;\r
1793 goto Done;\r
c9093a06 1794 }\r
1795\r
1796 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
1797\r
ac10bddd 1798 Status = EFI_SUCCESS;\r
1799 goto Done;\r
c9093a06 1800 }\r
1801\r
1802 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
ac10bddd 1803 Status = EFI_UNSUPPORTED;\r
1804 goto Done;\r
c9093a06 1805 }\r
1806\r
1807 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
ac10bddd 1808 Status = EFI_BAD_BUFFER_SIZE;\r
1809 goto Done;\r
c9093a06 1810 }\r
1811\r
1812 //\r
1813 // Set file/directory information.\r
1814 //\r
1815\r
1816 //\r
1817 // Check for invalid set file information parameters.\r
1818 //\r
1819 NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
1820\r
1821 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||\r
1822 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
1823 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
1824 ) {\r
ac10bddd 1825 Status = EFI_INVALID_PARAMETER;\r
1826 goto Done;\r
c9093a06 1827 }\r
1828\r
1829 //\r
1830 // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
1831 // that would have an additional parameter that would be the size\r
1832 // of the string array just in case there are no NULL characters in\r
1833 // the string array.\r
1834 //\r
1835 //\r
1836 // Get current file information so we can determine what kind\r
1837 // of change request this is.\r
1838 //\r
1839 OldInfoSize = 0;\r
1840 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);\r
1841\r
1842 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1843 Status = EFI_DEVICE_ERROR;\r
1844 goto Done;\r
1845 }\r
1846\r
caea5554 1847 Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,\r
c9093a06 1848 (VOID **)&OldFileInfo);\r
1849\r
1850 if (EFI_ERROR (Status)) {\r
1851 goto Done;\r
1852 }\r
1853\r
1854 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);\r
1855\r
1856 if (EFI_ERROR (Status)) {\r
1857 goto Done;\r
1858 }\r
1859\r
1860 Status = gBS->AllocatePool (\r
1861 EfiBootServicesData,\r
1862 AsciiStrSize (PrivateFile->FileName),\r
1863 (VOID **)&OldFileName\r
1864 );\r
1865\r
1866 if (EFI_ERROR (Status)) {\r
1867 goto Done;\r
1868 }\r
1869\r
1870 AsciiStrCpy (OldFileName, PrivateFile->FileName);\r
1871\r
1872 //\r
1873 // Make full pathname from new filename and rootpath.\r
1874 //\r
1875 if (NewFileInfo->FileName[0] == '\\') {\r
1876 Status = gBS->AllocatePool (\r
1877 EfiBootServicesData,\r
1878 AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1879 (VOID **)&NewFileName\r
1880 );\r
1881\r
1882 if (EFI_ERROR (Status)) {\r
1883 goto Done;\r
1884 }\r
1885\r
1886 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
caea5554 1887 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
1888 UnicodeFilePtr = NewFileInfo->FileName + 1;\r
1889 *AsciiFilePtr++ ='/';\r
c9093a06 1890 } else {\r
1891 Status = gBS->AllocatePool (\r
1892 EfiBootServicesData,\r
1893 AsciiStrLen (PrivateFile->FileName) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1894 (VOID **)&NewFileName\r
1895 );\r
1896\r
1897 if (EFI_ERROR (Status)) {\r
1898 goto Done;\r
1899 }\r
1900\r
1901 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
caea5554 1902 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
1903 while (AsciiFilePtr > NewFileName && AsciiFilePtr[-1] != '/') {\r
1904 AsciiFilePtr--;\r
1905 }\r
1906 UnicodeFilePtr = NewFileInfo->FileName;\r
1907 }\r
1908 // Convert to ascii.\r
1909 while (*UnicodeFilePtr) {\r
1910 *AsciiFilePtr++ = *UnicodeFilePtr++;\r
c9093a06 1911 }\r
caea5554 1912 *AsciiFilePtr = 0;\r
1913\r
c9093a06 1914\r
1915 //\r
1916 // Is there an attribute change request?\r
1917 //\r
1918 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
1919 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
1920 Status = EFI_INVALID_PARAMETER;\r
1921 goto Done;\r
1922 }\r
1923\r
1924 AttrChangeFlag = TRUE;\r
1925 }\r
1926\r
1927 //\r
1928 // Is there a name change request?\r
1929 // bugbug: - Need EfiStrCaseCmp()\r
1930 //\r
1931 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
1932 NameChangeFlag = TRUE;\r
1933 }\r
1934\r
1935 //\r
1936 // Is there a size change request?\r
1937 //\r
1938 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
1939 SizeChangeFlag = TRUE;\r
1940 }\r
1941\r
1942 //\r
1943 // Is there a time stamp change request?\r
1944 //\r
1945 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
1946 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
1947 ) {\r
1948 TimeChangeFlag = TRUE;\r
1949 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
1950 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
1951 ) {\r
1952 TimeChangeFlag = TRUE;\r
1953 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
1954 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
1955 ) {\r
1956 TimeChangeFlag = TRUE;\r
1957 }\r
1958\r
1959 //\r
1960 // All done if there are no change requests being made.\r
1961 //\r
1962 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
1963 Status = EFI_SUCCESS;\r
1964 goto Done;\r
1965 }\r
1966\r
1967 //\r
1968 // Set file or directory information.\r
1969 //\r
caea5554 1970 if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {\r
1971 Status = EFI_DEVICE_ERROR;\r
1972 goto Done;\r
1973 }\r
c9093a06 1974\r
1975 //\r
1976 // Name change.\r
1977 //\r
1978 if (NameChangeFlag) {\r
1979 //\r
1980 // Close the handles first\r
1981 //\r
1982 if (PrivateFile->IsOpenedByRead) {\r
1983 Status = EFI_ACCESS_DENIED;\r
1984 goto Done;\r
1985 }\r
1986\r
1987 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
1988 }\r
1989\r
1990 if (*CharPointer != 0) {\r
1991 Status = EFI_ACCESS_DENIED;\r
1992 goto Done;\r
1993 }\r
1994\r
1995 UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);\r
1996\r
1997 if (UnixStatus == 0) {\r
1998 //\r
1999 // modify file name\r
2000 //\r
2001 gBS->FreePool (PrivateFile->FileName);\r
2002\r
2003 Status = gBS->AllocatePool (\r
2004 EfiBootServicesData,\r
2005 AsciiStrSize (NewFileName),\r
2006 (VOID **)&PrivateFile->FileName\r
2007 );\r
2008\r
2009 if (EFI_ERROR (Status)) {\r
2010 goto Done;\r
2011 }\r
2012\r
2013 AsciiStrCpy (PrivateFile->FileName, NewFileName);\r
2014 } else {\r
2015 Status = EFI_DEVICE_ERROR;\r
2016 goto Done;\r
2017 }\r
2018 }\r
2019\r
2020 //\r
2021 // Size change\r
2022 //\r
2023 if (SizeChangeFlag) {\r
2024 if (PrivateFile->IsDirectoryPath) {\r
2025 Status = EFI_UNSUPPORTED;\r
2026 goto Done;\r
2027 }\r
2028\r
2029 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2030 Status = EFI_ACCESS_DENIED;\r
2031 goto Done;\r
2032 }\r
2033\r
2034 if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {\r
2035 Status = EFI_DEVICE_ERROR;\r
2036 goto Done;\r
2037 }\r
2038\r
2039 }\r
2040\r
2041 //\r
2042 // Time change\r
2043 //\r
2044 if (TimeChangeFlag) {\r
caea5554 2045 struct utimbuf utime;\r
c9093a06 2046\r
2047 NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year;\r
2048 NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month;\r
2049 NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day;\r
2050 NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour;\r
2051 NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute;\r
2052 NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second;\r
caea5554 2053 NewLastAccessSystemTime.tm_isdst = 0;\r
2054\r
2055 utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);\r
c9093a06 2056\r
c9093a06 2057 NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year;\r
2058 NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month;\r
2059 NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day;\r
2060 NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour;\r
2061 NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute;\r
2062 NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second;\r
caea5554 2063 NewLastWriteSystemTime.tm_isdst = 0;\r
2064\r
2065 utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);\r
c9093a06 2066\r
caea5554 2067 if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {\r
c9093a06 2068 goto Done;\r
2069 }\r
2070\r
caea5554 2071 if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {\r
c9093a06 2072 goto Done;\r
2073 }\r
2074 }\r
2075\r
2076 //\r
2077 // No matter about AttrChangeFlag, Attribute must be set.\r
2078 // Because operation before may cause attribute change.\r
2079 //\r
2080 NewAttr = OldAttr.st_mode;\r
2081\r
2082 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
caea5554 2083 NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);\r
c9093a06 2084 } else {\r
caea5554 2085 NewAttr |= S_IRUSR;\r
c9093a06 2086 }\r
2087\r
2088 UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);\r
2089\r
2090 if (UnixStatus != 0) {\r
2091 Status = EFI_DEVICE_ERROR;\r
2092 }\r
2093\r
2094Done:\r
2095 if (OldFileInfo != NULL) {\r
2096 gBS->FreePool (OldFileInfo);\r
2097 }\r
2098\r
2099 if (OldFileName != NULL) {\r
2100 gBS->FreePool (OldFileName);\r
2101 }\r
2102\r
2103 if (NewFileName != NULL) {\r
2104 gBS->FreePool (NewFileName);\r
2105 }\r
2106\r
ac10bddd 2107 gBS->RestoreTPL (OldTpl);\r
2108 \r
c9093a06 2109 return Status;\r
2110}\r
2111\r
2112EFI_STATUS\r
2113EFIAPI\r
2114UnixSimpleFileSystemFlush (\r
2115 IN EFI_FILE *This\r
2116 )\r
2117/*++\r
2118\r
2119Routine Description:\r
2120\r
2121 Flush all modified data to the media.\r
2122\r
2123Arguments:\r
2124\r
2125 This - Pointer to an opened file handle.\r
2126\r
2127Returns:\r
2128\r
2129 EFI_SUCCESS - The data has been flushed.\r
2130\r
2131 EFI_NO_MEDIA - The device has no media.\r
2132\r
2133 EFI_DEVICE_ERROR - The device reported an error.\r
2134\r
2135 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
2136\r
2137 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2138\r
2139 EFI_ACCESS_DENIED - The file was opened read-only.\r
2140\r
2141 EFI_VOLUME_FULL - The volume is full.\r
2142\r
2143--*/\r
2144// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2145{\r
2146 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
ac10bddd 2147 EFI_STATUS Status;\r
2148 EFI_TPL OldTpl;\r
c9093a06 2149\r
2150 if (This == NULL) {\r
2151 return EFI_INVALID_PARAMETER;\r
2152 }\r
2153\r
95122138 2154 Status = EFI_SUCCESS;\r
93b0fbc8 2155 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
ac10bddd 2156 \r
c9093a06 2157 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2158\r
2159\r
2160 if (PrivateFile->IsDirectoryPath) {\r
ac10bddd 2161 goto Done;\r
c9093a06 2162 }\r
2163\r
2164 if (PrivateFile->IsOpenedByRead) {\r
ac10bddd 2165 Status = EFI_ACCESS_DENIED;\r
2166 goto Done;\r
c9093a06 2167 }\r
2168\r
caea5554 2169 if (PrivateFile->fd < 0) {\r
ac10bddd 2170 Status = EFI_DEVICE_ERROR;\r
2171 goto Done;\r
c9093a06 2172 }\r
caea5554 2173\r
ac10bddd 2174 PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
2175\r
2176Done:\r
2177 gBS->RestoreTPL (OldTpl);\r
2178\r
2179 return Status;\r
c9093a06 2180\r
2181 //\r
377fc2ae 2182 // bugbug: - Use Unix error reporting.\r
c9093a06 2183 //\r
2184}\r
2185\r
ac10bddd 2186\r