]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Dxe/UnixThunk/Bus/SimpleFileSystem/UnixSimpleFileSystem.c
Change many windows references to unix.
[mirror_edk2.git] / EdkUnixPkg / Dxe / UnixThunk / Bus / SimpleFileSystem / UnixSimpleFileSystem.c
CommitLineData
c9093a06 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
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
33 0x10,\r
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
260 INTN i;
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
298 Private->FilePath = NULL;
299 Private->VolumeLabel = NULL;
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
310
311 for (i = 0; UnixIo->EnvString[i] != 0; i++)
312 Private->FilePath[i] = UnixIo->EnvString[i];\r
313 Private->FilePath[i] = 0;
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
352 if (Private->VolumeLabel != NULL)
353 gBS->FreePool (Private->VolumeLabel);
354 if (Private->FilePath != NULL)
355 gBS->FreePool (Private->FilePath);
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
498\r
499 if (This == NULL || Root == NULL) {\r
500 return EFI_INVALID_PARAMETER;\r
501 }\r
502\r
503 Private = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);\r
504\r
505 PrivateFile = NULL;\r
506 Status = gBS->AllocatePool (\r
507 EfiBootServicesData,\r
508 sizeof (UNIX_EFI_FILE_PRIVATE),\r
509 (VOID **)&PrivateFile\r
510 );\r
511 if (EFI_ERROR (Status)) {\r
512 goto Done;\r
513 }\r
514\r
515 PrivateFile->FileName = NULL;\r
516 Status = gBS->AllocatePool (\r
517 EfiBootServicesData,\r
518 AsciiStrSize (Private->FilePath),\r
519 (VOID **)&PrivateFile->FileName\r
520 );\r
521 if (EFI_ERROR (Status)) {\r
522 goto Done;\r
523 }\r
524\r
525 AsciiStrCpy (PrivateFile->FileName, Private->FilePath);\r
526 PrivateFile->Signature = UNIX_EFI_FILE_PRIVATE_SIGNATURE;\r
527 PrivateFile->UnixThunk = Private->UnixThunk;\r
528 PrivateFile->SimpleFileSystem = This;\r
529 PrivateFile->IsRootDirectory = TRUE;\r
530 PrivateFile->IsDirectoryPath = TRUE;\r
531 PrivateFile->IsOpenedByRead = TRUE;\r
532 PrivateFile->EfiFile.Revision = EFI_FILE_HANDLE_REVISION;\r
533 PrivateFile->EfiFile.Open = UnixSimpleFileSystemOpen;\r
534 PrivateFile->EfiFile.Close = UnixSimpleFileSystemClose;\r
535 PrivateFile->EfiFile.Delete = UnixSimpleFileSystemDelete;\r
536 PrivateFile->EfiFile.Read = UnixSimpleFileSystemRead;\r
537 PrivateFile->EfiFile.Write = UnixSimpleFileSystemWrite;\r
538 PrivateFile->EfiFile.GetPosition = UnixSimpleFileSystemGetPosition;\r
539 PrivateFile->EfiFile.SetPosition = UnixSimpleFileSystemSetPosition;\r
540 PrivateFile->EfiFile.GetInfo = UnixSimpleFileSystemGetInfo;\r
541 PrivateFile->EfiFile.SetInfo = UnixSimpleFileSystemSetInfo;\r
542 PrivateFile->EfiFile.Flush = UnixSimpleFileSystemFlush;\r
543 PrivateFile->fd = -1;
544 PrivateFile->Dir = NULL;
545 PrivateFile->Dirent = NULL;
546 \r
547 *Root = &PrivateFile->EfiFile;\r
548\r
549 PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName);
550\r
551 if (PrivateFile->Dir == NULL) {
552 Status = EFI_ACCESS_DENIED;\r
553 }
554 else {
555 Status = EFI_SUCCESS;\r
556 }
557\r
558Done:\r
559 if (EFI_ERROR (Status)) {\r
560 if (PrivateFile) {\r
561 if (PrivateFile->FileName) {\r
562 gBS->FreePool (PrivateFile->FileName);\r
563 }\r
564\r
565 gBS->FreePool (PrivateFile);\r
566 }\r
567 }\r
568\r
569 return Status;\r
570}\r
571\r
572EFI_STATUS\r
573EFIAPI\r
574UnixSimpleFileSystemOpen (\r
575 IN EFI_FILE *This,\r
576 OUT EFI_FILE **NewHandle,\r
577 IN CHAR16 *FileName,\r
578 IN UINT64 OpenMode,\r
579 IN UINT64 Attributes\r
580 )\r
581/*++\r
582\r
583Routine Description:\r
584\r
585 Open a file relative to the source file location.\r
586\r
587Arguments:\r
588\r
589 This - A pointer to the source file location.\r
590\r
591 NewHandle - Pointer to storage for the new file handle.\r
592\r
593 FileName - Pointer to the file name to be opened.\r
594\r
595 OpenMode - File open mode information.\r
596\r
597 Attributes - File creation attributes.\r
598\r
599Returns:\r
600\r
601 EFI_SUCCESS - The file was opened.\r
602\r
603 EFI_NOT_FOUND - The file could not be found in the volume.\r
604\r
605 EFI_NO_MEDIA - The device has no media.\r
606\r
607 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
608\r
609 EFI_DEVICE_ERROR - The device reported an error.\r
610\r
611 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
612\r
613 EFI_WRITE_PROTECTED - The volume or file is write protected.\r
614\r
615 EFI_ACCESS_DENIED - The service denied access to the file.\r
616\r
617 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.\r
618\r
619 EFI_VOLUME_FULL - There is not enough space left to create the new file.\r
620\r
621--*/\r
622// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
623// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
624// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
625// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
626{\r
627 EFI_FILE *Root;\r
628 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
629 UNIX_EFI_FILE_PRIVATE *NewPrivateFile;\r
630 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
631 EFI_STATUS Status;\r
632 CHAR16 *Src;
633 char *Dst;
634 CHAR8 *RealFileName;\r
635 CHAR16 *TempFileName;\r
636 char *ParseFileName;\r
637 char *GuardPointer;\r
638 CHAR8 TempChar;\r
639 UINTN Count;\r
640 BOOLEAN TrailingDash;\r
641 BOOLEAN LoopFinish;\r
642 UINTN InfoSize;\r
643 EFI_FILE_INFO *Info;\r
644\r
645 TrailingDash = FALSE;\r
646\r
647 //\r
648 // Check for obvious invalid parameters.\r
649 //\r
650 if (This == NULL || NewHandle == NULL || FileName == NULL) {\r
651 return EFI_INVALID_PARAMETER;\r
652 }\r
653\r
654 switch (OpenMode) {\r
655 case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
656 if (Attributes &~EFI_FILE_VALID_ATTR) {\r
657 return EFI_INVALID_PARAMETER;\r
658 }\r
659\r
660 if (Attributes & EFI_FILE_READ_ONLY) {\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
664 //\r
665 // fall through\r
666 //\r
667 case EFI_FILE_MODE_READ:\r
668 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
669 break;\r
670\r
671 default:\r
672 return EFI_INVALID_PARAMETER;\r
673 }\r
674\r
675 //\r
676 //\r
677 //\r
678 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
679 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
680 NewPrivateFile = NULL;\r
681\r
682 //\r
683 // BUGBUG: assume an open of root\r
684 // if current location, return current data\r
685 //\r
686 if (StrCmp (FileName, L"\\") == 0
687 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {\r
688 //\r
689 // BUGBUG: assume an open root\r
690 //\r
691OpenRoot:\r
692 Status = UnixSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);\r
693 NewPrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);\r
694 goto Done;\r
695 }\r
696\r
697 if (FileName[StrLen (FileName) - 1] == L'\\') {\r
698 TrailingDash = TRUE;\r
699 FileName[StrLen (FileName) - 1] = 0;\r
700 }\r
701\r
702 //\r
703 // Attempt to open the file\r
704 //\r
705 Status = gBS->AllocatePool (\r
706 EfiBootServicesData,\r
707 sizeof (UNIX_EFI_FILE_PRIVATE),\r
708 (VOID **)&NewPrivateFile\r
709 );\r
710\r
711 if (EFI_ERROR (Status)) {\r
712 goto Done;\r
713 }\r
714\r
715 CopyMem (NewPrivateFile, PrivateFile, sizeof (UNIX_EFI_FILE_PRIVATE));\r
716\r
717 NewPrivateFile->FileName = NULL;\r
718 Status = gBS->AllocatePool (\r
719 EfiBootServicesData,\r
720 AsciiStrSize (PrivateFile->FileName) + 1 + StrLen (FileName) + 1,\r
721 (VOID **)&NewPrivateFile->FileName\r
722 );\r
723\r
724 if (EFI_ERROR (Status)) {\r
725 goto Done;\r
726 }\r
727\r
728 if (*FileName == L'\\') {\r
729 AsciiStrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);\r
730 // Skip first '\'.
731 Src = FileName + 1;
732 } else {\r
733 AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);\r
734 Src = FileName;
735 }\r
736 Dst = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName);
737 GuardPointer = NewPrivateFile->FileName + AsciiStrLen(PrivateRoot->FilePath);
738 *Dst++ = '/';
739 // Convert unicode to ascii and '\' to '/'
740 while (*Src) {
741 if (*Src == '\\')
742 *Dst++ = '/';
743 else
744 *Dst++ = *Src;
745 Src++;
746 }
747 *Dst = 0;
748
749\r
750 //\r
751 // Get rid of . and .., except leading . or ..\r
752 //\r
753\r
754 //\r
755 // GuardPointer protect simplefilesystem root path not be destroyed\r
756 //\r
757\r
758 LoopFinish = FALSE;\r
759\r
760 while (!LoopFinish) {\r
761\r
762 LoopFinish = TRUE;\r
763\r
764 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {\r
765 if (*ParseFileName == '.' &&\r
766 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == '/') &&\r
767 *(ParseFileName - 1) == '/'\r
768 ) {\r
769\r
770 //\r
771 // cut /.\r
772 //\r
773 CutPrefix (ParseFileName - 1, 2);\r
774 LoopFinish = FALSE;\r
775 break;\r
776 }\r
777\r
778 if (*ParseFileName == '.' &&\r
779 *(ParseFileName + 1) == '.' &&\r
780 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == '/') &&\r
781 *(ParseFileName - 1) == '/'\r
782 ) {\r
783\r
784 ParseFileName--;\r
785 Count = 3;\r
786\r
787 while (ParseFileName != GuardPointer) {\r
788 ParseFileName--;\r
789 Count++;\r
790 if (*ParseFileName == '/') {\r
791 break;\r
792 }\r
793 }\r
794\r
795 //\r
796 // cut /.. and its left directory\r
797 //\r
798 CutPrefix (ParseFileName, Count);\r
799 LoopFinish = FALSE;\r
800 break;\r
801 }\r
802 }\r
803 }\r
804\r
805 if (AsciiStrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {\r
806 NewPrivateFile->IsRootDirectory = TRUE;\r
807 gBS->FreePool (NewPrivateFile->FileName);\r
808 gBS->FreePool (NewPrivateFile);\r
809 goto OpenRoot;\r
810 }\r
811\r
812 RealFileName = NewPrivateFile->FileName + AsciiStrLen(NewPrivateFile->FileName) - 1;\r
813 while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')
814 RealFileName--;
815\r
816 TempChar = *(RealFileName - 1);\r
817 *(RealFileName - 1) = 0;\r
818\r
819 *(RealFileName - 1) = TempChar;\r
820\r
821
822
823 //\r
824 // Test whether file or directory\r
825 //\r
826 NewPrivateFile->IsRootDirectory = FALSE;\r
827 NewPrivateFile->fd = -1;
828 NewPrivateFile->Dir = NULL;
829 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
830 if (Attributes & EFI_FILE_DIRECTORY) {\r
831 NewPrivateFile->IsDirectoryPath = TRUE;\r
832 } else {\r
833 NewPrivateFile->IsDirectoryPath = FALSE;\r
834 }\r
835 } else {\r
836 struct stat finfo;
837 int res = NewPrivateFile->UnixThunk->Stat (NewPrivateFile->FileName, &finfo);
838 if (res == 0 && S_ISDIR(finfo.st_mode))
839 NewPrivateFile->IsDirectoryPath = TRUE;\r
840 else
841 NewPrivateFile->IsDirectoryPath = FALSE;\r
842 }\r
843\r
844 if (OpenMode & EFI_FILE_MODE_WRITE) {\r
845 NewPrivateFile->IsOpenedByRead = FALSE;\r
846 } else {\r
847 NewPrivateFile->IsOpenedByRead = TRUE;\r
848 }\r
849\r
850 Status = EFI_SUCCESS;\r
851\r
852 //\r
853 // deal with directory\r
854 //\r
855 if (NewPrivateFile->IsDirectoryPath) {\r
856\r
857 if ((OpenMode & EFI_FILE_MODE_CREATE)) {\r
858 //\r
859 // Create a directory\r
860 //\r
861 if (NewPrivateFile->UnixThunk->MkDir (NewPrivateFile->FileName, 0777) != 0) {\r
862 INTN LastError;
863\r
864 LastError = PrivateFile->UnixThunk->GetErrno ();\r
865 if (LastError != EEXIST) {
866 gBS->FreePool (TempFileName);\r
867 Status = EFI_ACCESS_DENIED;\r
868 goto Done;\r
869 }\r
870 }\r
871 }\r
872\r
873 NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir
874 (NewPrivateFile->FileName);
875\r
876 if (NewPrivateFile->Dir == NULL) {
877 if (PrivateFile->UnixThunk->GetErrno () == EACCES) {
878 Status = EFI_ACCESS_DENIED;\r
879 } else {\r
880 Status = EFI_NOT_FOUND;\r
881 }\r
882\r
883 goto Done;\r
884 }\r
885\r
886 } else {\r
887 //\r
888 // deal with file\r
889 //\r
890 NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open
891 (NewPrivateFile->FileName,\r
892 ((OpenMode & EFI_FILE_MODE_CREATE) ? O_CREAT : 0)
893 | (NewPrivateFile->IsOpenedByRead ? O_RDONLY : O_RDWR),
894 0666);
895 if (NewPrivateFile->fd < 0) {
896 if (PrivateFile->UnixThunk->GetErrno () == ENOENT) {
897 Status = EFI_NOT_FOUND;\r
898 } else {\r
899 Status = EFI_ACCESS_DENIED;\r
900 }\r
901 }\r
902 }\r
903\r
904 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {\r
905 //\r
906 // Set the attribute\r
907 //\r
908 InfoSize = 0;\r
909 Info = NULL;\r
910\r
911 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
912\r
913 if (Status != EFI_BUFFER_TOO_SMALL) {\r
914 Status = EFI_DEVICE_ERROR;\r
915 goto Done;\r
916 }\r
917\r
918 Status = gBS->AllocatePool (\r
919 EfiBootServicesData,\r
920 InfoSize,\r
921 (VOID **)&Info\r
922 );\r
923\r
924 if (EFI_ERROR (Status)) {\r
925 goto Done;\r
926 }\r
927\r
928 Status = UnixSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
929\r
930 if (EFI_ERROR (Status)) {\r
931 goto Done;\r
932 }\r
933\r
934 Info->Attribute = Attributes;\r
935\r
936 UnixSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);\r
937 }\r
938\r
939Done: ;\r
940 if (TrailingDash) {\r
941 FileName[StrLen (FileName) + 1] = 0;\r
942 FileName[StrLen (FileName)] = L'\\';\r
943 }\r
944\r
945 if (EFI_ERROR (Status)) {\r
946 if (NewPrivateFile) {\r
947 if (NewPrivateFile->FileName) {\r
948 gBS->FreePool (NewPrivateFile->FileName);\r
949 }\r
950\r
951 gBS->FreePool (NewPrivateFile);\r
952 }\r
953 } else {\r
954 *NewHandle = &NewPrivateFile->EfiFile;\r
955 }\r
956\r
957 return Status;\r
958}\r
959\r
960EFI_STATUS\r
961EFIAPI\r
962UnixSimpleFileSystemClose (\r
963 IN EFI_FILE *This\r
964 )\r
965/*++\r
966\r
967Routine Description:\r
968\r
969 Close the specified file handle.\r
970\r
971Arguments:\r
972\r
973 This - Pointer to a returned opened file handle.\r
974\r
975Returns:\r
976\r
977 EFI_SUCCESS - The file handle has been closed.\r
978\r
979--*/\r
980// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
981{\r
982 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
983\r
984 if (This == NULL) {\r
985 return EFI_INVALID_PARAMETER;\r
986 }\r
987\r
988 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
989\r
990 if (PrivateFile->fd >= 0) {
991 PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
992 }
993 if (PrivateFile->Dir != NULL) {
994 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
995 }
996\r
997 PrivateFile->fd = -1;
998 PrivateFile->Dir = NULL;
999\r
1000 if (PrivateFile->FileName) {\r
1001 gBS->FreePool (PrivateFile->FileName);\r
1002 }\r
1003\r
1004 gBS->FreePool (PrivateFile);\r
1005 return EFI_SUCCESS;\r
1006}\r
1007\r
1008EFI_STATUS\r
1009EFIAPI\r
1010UnixSimpleFileSystemDelete (\r
1011 IN EFI_FILE *This\r
1012 )\r
1013/*++\r
1014\r
1015Routine Description:\r
1016\r
1017 Close and delete a file.\r
1018\r
1019Arguments:\r
1020\r
1021 This - Pointer to a returned opened file handle.\r
1022\r
1023Returns:\r
1024\r
1025 EFI_SUCCESS - The file handle was closed and deleted.\r
1026\r
1027 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.\r
1028\r
1029--*/\r
1030// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1031{\r
1032 EFI_STATUS Status;\r
1033 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1034\r
1035 if (This == NULL) {\r
1036 return EFI_INVALID_PARAMETER;\r
1037 }\r
1038\r
1039 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1040\r
1041 Status = EFI_WARN_DELETE_FAILURE;\r
1042\r
1043 if (PrivateFile->IsDirectoryPath) {\r
1044 if (PrivateFile->Dir != NULL) {\r
1045 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
1046 PrivateFile->Dir = NULL;
1047 }\r
1048\r
1049 if (PrivateFile->UnixThunk->RmDir (PrivateFile->FileName) == 0) {\r
1050 Status = EFI_SUCCESS;\r
1051 }\r
1052 } else {\r
1053 PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
1054 PrivateFile->fd = -1;
1055\r
1056 if (!PrivateFile->IsOpenedByRead) {\r
1057 if (!PrivateFile->UnixThunk->UnLink (PrivateFile->FileName)) {\r
1058 Status = EFI_SUCCESS;\r
1059 }\r
1060 }\r
1061 }\r
1062\r
1063 gBS->FreePool (PrivateFile->FileName);\r
1064 gBS->FreePool (PrivateFile);\r
1065\r
1066 return Status;\r
1067}\r
1068\r
1069STATIC\r
1070VOID\r
1071UnixSystemTimeToEfiTime (\r
1072 EFI_UNIX_THUNK_PROTOCOL *UnixThunk,\r
1073 IN time_t SystemTime,
1074 OUT EFI_TIME *Time\r
1075 )\r
1076/*++\r
1077\r
1078Routine Description:\r
1079\r
1080 TODO: Add function description\r
1081\r
1082Arguments:\r
1083\r
1084 SystemTime - TODO: add argument description\r
1085 TimeZone - TODO: add argument description\r
1086 Time - TODO: add argument description\r
1087\r
1088Returns:\r
1089\r
1090 TODO: add return values\r
1091\r
1092--*/\r
1093{\r
1094 struct tm *tm;
1095 tm = UnixThunk->GmTime (&SystemTime);
1096 Time->Year = tm->tm_year;
1097 Time->Month = tm->tm_mon;
1098 Time->Day = tm->tm_mday;
1099 Time->Hour = tm->tm_hour;
1100 Time->Minute = tm->tm_min;
1101 Time->Second = tm->tm_sec;
1102 Time->Nanosecond = 0;
1103
1104 Time->TimeZone = UnixThunk->GetTimeZone ();
1105\r
1106 if (UnixThunk->GetDayLight ()) {
1107 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
1108 }\r
1109}\r
1110\r
1111STATIC\r
1112EFI_STATUS\r
1113UnixSimpleFileSystemFileInfo (\r
1114 UNIX_EFI_FILE_PRIVATE *PrivateFile,\r
1115 IN CHAR8 *FileName,
1116 IN OUT UINTN *BufferSize,\r
1117 OUT VOID *Buffer\r
1118 )\r
1119/*++\r
1120\r
1121Routine Description:\r
1122\r
1123 TODO: Add function description\r
1124\r
1125Arguments:\r
1126\r
1127 PrivateFile - TODO: add argument description\r
1128 BufferSize - TODO: add argument description\r
1129 Buffer - TODO: add argument description\r
1130\r
1131Returns:\r
1132\r
1133 TODO: add return values\r
1134\r
1135--*/\r
1136{\r
1137 EFI_STATUS Status;\r
1138 UINTN Size;\r
1139 UINTN NameSize;\r
1140 UINTN ResultSize;\r
1141 EFI_FILE_INFO *Info;\r
1142 CHAR8 *RealFileName;\r
1143 CHAR8 *TempPointer;\r
1144 CHAR16 *BufferFileName;
1145 struct stat buf;
1146\r
1147 if (FileName != NULL) {
1148 RealFileName = FileName;
1149 }
1150 else if (PrivateFile->IsRootDirectory) {\r
1151 RealFileName = "";
1152 } else {\r
1153 RealFileName = PrivateFile->FileName;\r
1154 }
1155
1156 TempPointer = RealFileName;\r
1157 while (*TempPointer) {\r
1158 if (*TempPointer == '/') {\r
1159 RealFileName = TempPointer + 1;\r
1160 }\r
1161\r
1162 TempPointer++;\r
1163 }\r
1164
1165 Size = SIZE_OF_EFI_FILE_INFO;\r
1166 NameSize = AsciiStrSize (RealFileName) * 2;\r
1167 ResultSize = Size + NameSize;\r
1168\r
1169 if (*BufferSize < ResultSize) {\r
1170 *BufferSize = ResultSize;\r
1171 return EFI_BUFFER_TOO_SMALL;\r
1172 }
1173 if (PrivateFile->UnixThunk->Stat (
1174 FileName == NULL ? PrivateFile->FileName : FileName,
1175 &buf) < 0)
1176 return EFI_DEVICE_ERROR;
1177
1178 Status = EFI_SUCCESS;\r
1179\r
1180 Info = Buffer;\r
1181 ZeroMem (Info, ResultSize);\r
1182\r
1183 Info->Size = ResultSize;\r
1184 Info->FileSize = buf.st_size;
1185 Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize);
1186\r
1187 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime);
1188 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime);
1189 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime);
1190
1191 if (!(buf.st_mode & S_IWUSR)) {
1192 Info->Attribute |= EFI_FILE_READ_ONLY;\r
1193 }\r
1194\r
1195 if (S_ISDIR(buf.st_mode)) {
1196 Info->Attribute |= EFI_FILE_DIRECTORY;\r
1197 }\r
1198\r
1199\r
1200 BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size);
1201 while (*RealFileName)
1202 *BufferFileName++ = *RealFileName++;
1203 *BufferFileName = 0;
1204
1205 *BufferSize = ResultSize;\r
1206 return Status;\r
1207}\r
1208\r
1209EFI_STATUS\r
1210EFIAPI\r
1211UnixSimpleFileSystemRead (\r
1212 IN EFI_FILE *This,\r
1213 IN OUT UINTN *BufferSize,\r
1214 OUT VOID *Buffer\r
1215 )\r
1216/*++\r
1217\r
1218Routine Description:\r
1219\r
1220 Read data from a file.\r
1221\r
1222Arguments:\r
1223\r
1224 This - Pointer to a returned open file handle.\r
1225\r
1226 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
1227\r
1228 Buffer - Pointer to the first byte of the read Buffer.\r
1229\r
1230Returns:\r
1231\r
1232 EFI_SUCCESS - The data was read.\r
1233\r
1234 EFI_NO_MEDIA - The device has no media.\r
1235\r
1236 EFI_DEVICE_ERROR - The device reported an error.\r
1237\r
1238 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
1239\r
1240 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
1241 *BufferSize has been updated with the size needed to complete the request.\r
1242\r
1243--*/\r
1244// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1245{\r
1246 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1247 EFI_STATUS Status;\r
1248 INTN Res;
1249 UINTN Size;\r
1250 UINTN NameSize;\r
1251 UINTN ResultSize;\r
1252 CHAR8 *FullFileName;
1253\r
1254 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1255 return EFI_INVALID_PARAMETER;\r
1256 }\r
1257\r
1258 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1259\r
1260 if (!PrivateFile->IsDirectoryPath) {\r
1261\r
1262 if (PrivateFile->fd < 0) {\r
1263 return EFI_DEVICE_ERROR;\r
1264 }\r
1265\r
1266 Res = PrivateFile->UnixThunk->Read (\r
1267 PrivateFile->fd,\r
1268 Buffer,\r
1269 *BufferSize);
1270 if (Res < 0)
1271 return EFI_DEVICE_ERROR;
1272 *BufferSize = Res;
1273 return EFI_SUCCESS;
1274 }\r
1275\r
1276 //\r
1277 // Read on a directory.
1278 //\r
1279 if (PrivateFile->Dir == NULL) {\r
1280 return EFI_DEVICE_ERROR;\r
1281 }\r
1282
1283 if (PrivateFile->Dirent == NULL) {
1284 PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);
1285 if (PrivateFile->Dirent == NULL) {
1286 *BufferSize = 0;\r
1287 return EFI_SUCCESS;\r
1288 }
1289 }
1290
1291 Size = SIZE_OF_EFI_FILE_INFO;\r
1292 NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;
1293 ResultSize = Size + 2 * NameSize;\r
1294\r
1295 if (*BufferSize < ResultSize) {\r
1296 *BufferSize = ResultSize;\r
1297 return EFI_BUFFER_TOO_SMALL;\r
1298 }
1299 Status = EFI_SUCCESS;\r
1300\r
1301 *BufferSize = ResultSize;\r
1302
1303 Status = gBS->AllocatePool (\r
1304 EfiBootServicesData,\r
1305 AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,
1306 (VOID **)&FullFileName
1307 );\r
1308\r
1309 if (EFI_ERROR (Status)) {\r
1310 return Status;
1311 }\r
1312
1313 AsciiStrCpy(FullFileName, PrivateFile->FileName);
1314 AsciiStrCat(FullFileName, "/");
1315 AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);
1316 Status = UnixSimpleFileSystemFileInfo (PrivateFile,
1317 FullFileName,
1318 BufferSize,
1319 Buffer);
1320 gBS->FreePool (FullFileName);
1321\r
1322 PrivateFile->Dirent = NULL;
1323\r
1324 return Status;
1325}\r
1326\r
1327EFI_STATUS\r
1328EFIAPI\r
1329UnixSimpleFileSystemWrite (\r
1330 IN EFI_FILE *This,\r
1331 IN OUT UINTN *BufferSize,\r
1332 IN VOID *Buffer\r
1333 )\r
1334/*++\r
1335\r
1336Routine Description:\r
1337\r
1338 Write data to a file.\r
1339\r
1340Arguments:\r
1341\r
1342 This - Pointer to an opened file handle.\r
1343\r
1344 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
1345 of data written to the file.\r
1346\r
1347 Buffer - Pointer to the first by of data in the buffer to write to the file.\r
1348\r
1349Returns:\r
1350\r
1351 EFI_SUCCESS - The data was written to the file.\r
1352\r
1353 EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
1354\r
1355 EFI_NO_MEDIA - The device has no media.\r
1356\r
1357 EFI_DEVICE_ERROR - The device reported an error.\r
1358\r
1359 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1360\r
1361 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1362\r
1363 EFI_ACCESS_DENIED - The file was opened read-only.\r
1364\r
1365 EFI_VOLUME_FULL - The volume is full.\r
1366\r
1367--*/\r
1368// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1369{\r
1370 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1371 UINTN Res;
1372\r
1373 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1374 return EFI_INVALID_PARAMETER;\r
1375 }\r
1376\r
1377 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1378\r
1379 if (PrivateFile->fd < 0) {\r
1380 return EFI_DEVICE_ERROR;\r
1381 }\r
1382\r
1383 if (PrivateFile->IsDirectoryPath) {\r
1384 return EFI_UNSUPPORTED;\r
1385 }\r
1386\r
1387 if (PrivateFile->IsOpenedByRead) {\r
1388 return EFI_ACCESS_DENIED;\r
1389 }\r
1390\r
1391 Res = PrivateFile->UnixThunk->Write (\r
1392 PrivateFile->fd,\r
1393 Buffer,\r
1394 *BufferSize);
1395 if (Res == (UINTN)-1)
1396 return EFI_DEVICE_ERROR;
1397 *BufferSize = Res;
1398 return EFI_SUCCESS;
1399\r
1400 //\r
377fc2ae 1401 // bugbug: need to access unix error reporting\r
c9093a06 1402 //\r
1403}\r
1404\r
1405EFI_STATUS\r
1406EFIAPI\r
1407UnixSimpleFileSystemSetPosition (\r
1408 IN EFI_FILE *This,\r
1409 IN UINT64 Position\r
1410 )\r
1411/*++\r
1412\r
1413Routine Description:\r
1414\r
1415 Set a file's current position.\r
1416\r
1417Arguments:\r
1418\r
1419 This - Pointer to an opened file handle.\r
1420\r
1421 Position - The byte position from the start of the file to set.\r
1422\r
1423Returns:\r
1424\r
1425 EFI_SUCCESS - The file position has been changed.\r
1426\r
1427 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
1428\r
1429--*/\r
1430// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1431{\r
1432 EFI_STATUS Status;\r
1433 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1434 UINT64 Pos;\r
1435\r
1436 if (This == NULL) {\r
1437 return EFI_INVALID_PARAMETER;\r
1438 }\r
1439\r
1440 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1441\r
1442 if (PrivateFile->IsDirectoryPath) {\r
1443 if (Position != 0) {\r
1444 return EFI_UNSUPPORTED;\r
1445 }\r
1446\r
1447 if (PrivateFile->Dir == NULL) {
1448 return EFI_DEVICE_ERROR;
1449 }
1450 PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);
1451 return EFI_SUCCESS;\r
1452 } else {\r
1453 if (Position == (UINT64) -1) {\r
1454 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);\r
1455 } else {\r
1456 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);\r
1457 }
1458 Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1459\r
1460 return Status;\r
1461 }\r
1462}\r
1463\r
1464EFI_STATUS\r
1465EFIAPI\r
1466UnixSimpleFileSystemGetPosition (\r
1467 IN EFI_FILE *This,\r
1468 OUT UINT64 *Position\r
1469 )\r
1470/*++\r
1471\r
1472Routine Description:\r
1473\r
1474 Get a file's current position.\r
1475\r
1476Arguments:\r
1477\r
1478 This - Pointer to an opened file handle.\r
1479\r
1480 Position - Pointer to storage for the current position.\r
1481\r
1482Returns:\r
1483\r
1484 EFI_SUCCESS - The file position has been reported.\r
1485\r
1486 EFI_UNSUPPORTED - Not valid for directories.\r
1487\r
1488--*/\r
1489// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1490{\r
1491 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1492\r
1493 if (This == NULL || Position == NULL) {\r
1494 return EFI_INVALID_PARAMETER;\r
1495 }\r
1496\r
1497 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1498\r
1499 if (PrivateFile->IsDirectoryPath) {\r
1500 return EFI_UNSUPPORTED;\r
1501 } else {\r
1502 *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);
1503 return (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1504 }\r
1505}\r
1506\r
1507EFI_STATUS\r
1508EFIAPI\r
1509UnixSimpleFileSystemGetInfo (\r
1510 IN EFI_FILE *This,\r
1511 IN EFI_GUID *InformationType,\r
1512 IN OUT UINTN *BufferSize,\r
1513 OUT VOID *Buffer\r
1514 )\r
1515/*++\r
1516\r
1517Routine Description:\r
1518\r
1519 Return information about a file or volume.\r
1520\r
1521Arguments:\r
1522\r
1523 This - Pointer to an opened file handle.\r
1524\r
1525 InformationType - GUID describing the type of information to be returned.\r
1526\r
1527 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
1528 information buffer.\r
1529\r
1530 Buffer - Pointer to the first byte of the information buffer.\r
1531\r
1532Returns:\r
1533\r
1534 EFI_SUCCESS - The requested information has been written into the buffer.\r
1535\r
1536 EFI_UNSUPPORTED - The InformationType is not known.\r
1537\r
1538 EFI_NO_MEDIA - The device has no media.\r
1539\r
1540 EFI_DEVICE_ERROR - The device reported an error.\r
1541\r
1542 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1543\r
1544 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
1545 been updated with the size needed to complete the requested operation.\r
1546\r
1547--*/\r
1548// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1549{\r
1550 EFI_STATUS Status;\r
1551 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1552 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
1553 INTN UnixStatus;\r
1554 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
1555 struct statfs buf;
1556\r
1557 if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
1558 return EFI_INVALID_PARAMETER;\r
1559 }\r
1560\r
1561 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1562 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1563\r
1564 Status = EFI_UNSUPPORTED;\r
1565\r
1566 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1567 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer);\r
1568 }\r
1569 else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1570 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
1571 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1572 return EFI_BUFFER_TOO_SMALL;\r
1573 }\r
1574\r
1575 UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);
1576 if (UnixStatus < 0)
1577 return EFI_DEVICE_ERROR;\r
1578
1579 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1580 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1581 FileSystemInfoBuffer->ReadOnly = FALSE;\r
1582\r
1583 //\r
1584 // Succeeded\r
1585 //\r
1586 FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize);
1587 FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize);
1588 FileSystemInfoBuffer->BlockSize = buf.f_bsize;
1589\r
1590\r
1591 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
1592 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1593 Status = EFI_SUCCESS;\r
1594 }\r
1595\r
1596 else if (CompareGuid (InformationType,
1597 &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1598 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
1599 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
1600 return EFI_BUFFER_TOO_SMALL;\r
1601 }\r
1602\r
1603 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
1604 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
1605 Status = EFI_SUCCESS;\r
1606 }\r
1607\r
1608 return Status;\r
1609}\r
1610\r
1611EFI_STATUS\r
1612EFIAPI\r
1613UnixSimpleFileSystemSetInfo (\r
1614 IN EFI_FILE *This,\r
1615 IN EFI_GUID *InformationType,\r
1616 IN UINTN BufferSize,\r
1617 IN VOID *Buffer\r
1618 )\r
1619/*++\r
1620\r
1621Routine Description:\r
1622\r
1623 Set information about a file or volume.\r
1624\r
1625Arguments:\r
1626\r
1627 This - Pointer to an opened file handle.\r
1628\r
1629 InformationType - GUID identifying the type of information to set.\r
1630\r
1631 BufferSize - Number of bytes of data in the information buffer.\r
1632\r
1633 Buffer - Pointer to the first byte of data in the information buffer.\r
1634\r
1635Returns:\r
1636\r
1637 EFI_SUCCESS - The file or volume information has been updated.\r
1638\r
1639 EFI_UNSUPPORTED - The information identifier is not recognised.\r
1640\r
1641 EFI_NO_MEDIA - The device has no media.\r
1642\r
1643 EFI_DEVICE_ERROR - The device reported an error.\r
1644\r
1645 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1646\r
1647 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1648\r
1649 EFI_ACCESS_DENIED - The file was opened read-only.\r
1650\r
1651 EFI_VOLUME_FULL - The volume is full.\r
1652\r
1653 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
1654\r
1655--*/\r
1656// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1657// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1658{\r
1659 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
1660 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1661 EFI_FILE_INFO *OldFileInfo;\r
1662 EFI_FILE_INFO *NewFileInfo;\r
1663 EFI_STATUS Status;\r
1664 UINTN OldInfoSize;\r
1665 mode_t NewAttr;\r
1666 struct stat OldAttr;\r
1667 CHAR8 *OldFileName;\r
1668 CHAR8 *NewFileName;\r
1669 CHAR8 *CharPointer;\r
1670 BOOLEAN AttrChangeFlag;\r
1671 BOOLEAN NameChangeFlag;\r
1672 BOOLEAN SizeChangeFlag;\r
1673 BOOLEAN TimeChangeFlag;\r
1674 struct tm NewLastAccessSystemTime;\r
1675 struct tm NewLastWriteSystemTime;\r
1676 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
1677 CHAR8 *AsciiFilePtr;
1678 CHAR16 *UnicodeFilePtr;
1679 INTN UnixStatus;
1680\r
1681 //\r
1682 // Check for invalid parameters.\r
1683 //\r
1684 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
1685 return EFI_INVALID_PARAMETER;\r
1686 }\r
1687\r
1688 //\r
1689 // Initialise locals.\r
1690 //\r
1691 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1692 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1693\r
1694 Status = EFI_UNSUPPORTED;\r
1695 OldFileInfo = NewFileInfo = NULL;\r
1696 OldFileName = NewFileName = NULL;\r
1697 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
1698\r
1699 //\r
1700 // Set file system information.\r
1701 //\r
1702 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1703 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
1704 return EFI_BAD_BUFFER_SIZE;\r
1705 }\r
1706\r
1707 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1708\r
1709 gBS->FreePool (PrivateRoot->VolumeLabel);\r
1710\r
1711 PrivateRoot->VolumeLabel = NULL;\r
1712 Status = gBS->AllocatePool (\r
1713 EfiBootServicesData,\r
1714 StrSize (NewFileSystemInfo->VolumeLabel),\r
1715 (VOID **)&PrivateRoot->VolumeLabel\r
1716 );\r
1717\r
1718 if (EFI_ERROR (Status)) {\r
1719 goto Done;\r
1720 }\r
1721\r
1722 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
1723\r
1724 return EFI_SUCCESS;\r
1725 }\r
1726\r
1727 //\r
1728 // Set volume label information.\r
1729 //\r
1730 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1731 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
1732 return EFI_BAD_BUFFER_SIZE;\r
1733 }\r
1734\r
1735 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
1736\r
1737 return EFI_SUCCESS;\r
1738 }\r
1739\r
1740 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1741 return EFI_UNSUPPORTED;\r
1742 }\r
1743\r
1744 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
1745 return EFI_BAD_BUFFER_SIZE;\r
1746 }\r
1747\r
1748 //\r
1749 // Set file/directory information.\r
1750 //\r
1751\r
1752 //\r
1753 // Check for invalid set file information parameters.\r
1754 //\r
1755 NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
1756\r
1757 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||\r
1758 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
1759 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
1760 ) {\r
1761 return EFI_INVALID_PARAMETER;\r
1762 }\r
1763\r
1764 //\r
1765 // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
1766 // that would have an additional parameter that would be the size\r
1767 // of the string array just in case there are no NULL characters in\r
1768 // the string array.\r
1769 //\r
1770 //\r
1771 // Get current file information so we can determine what kind\r
1772 // of change request this is.\r
1773 //\r
1774 OldInfoSize = 0;\r
1775 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);\r
1776\r
1777 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1778 Status = EFI_DEVICE_ERROR;\r
1779 goto Done;\r
1780 }\r
1781\r
1782 Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,
1783 (VOID **)&OldFileInfo);\r
1784\r
1785 if (EFI_ERROR (Status)) {\r
1786 goto Done;\r
1787 }\r
1788\r
1789 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);\r
1790\r
1791 if (EFI_ERROR (Status)) {\r
1792 goto Done;\r
1793 }\r
1794\r
1795 Status = gBS->AllocatePool (\r
1796 EfiBootServicesData,\r
1797 AsciiStrSize (PrivateFile->FileName),\r
1798 (VOID **)&OldFileName\r
1799 );\r
1800\r
1801 if (EFI_ERROR (Status)) {\r
1802 goto Done;\r
1803 }\r
1804\r
1805 AsciiStrCpy (OldFileName, PrivateFile->FileName);\r
1806\r
1807 //\r
1808 // Make full pathname from new filename and rootpath.\r
1809 //\r
1810 if (NewFileInfo->FileName[0] == '\\') {\r
1811 Status = gBS->AllocatePool (\r
1812 EfiBootServicesData,\r
1813 AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1814 (VOID **)&NewFileName\r
1815 );\r
1816\r
1817 if (EFI_ERROR (Status)) {\r
1818 goto Done;\r
1819 }\r
1820\r
1821 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
1822 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);
1823 UnicodeFilePtr = NewFileInfo->FileName + 1;
1824 *AsciiFilePtr++ ='/';
1825 } else {\r
1826 Status = gBS->AllocatePool (\r
1827 EfiBootServicesData,\r
1828 AsciiStrLen (PrivateFile->FileName) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1829 (VOID **)&NewFileName\r
1830 );\r
1831\r
1832 if (EFI_ERROR (Status)) {\r
1833 goto Done;\r
1834 }\r
1835\r
1836 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
1837 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);
1838 while (AsciiFilePtr > NewFileName && AsciiFilePtr[-1] != '/') {
1839 AsciiFilePtr--;
1840 }
1841 UnicodeFilePtr = NewFileInfo->FileName;
1842 }\r
1843 // Convert to ascii.
1844 while (*UnicodeFilePtr) {
1845 *AsciiFilePtr++ = *UnicodeFilePtr++;
1846 }
1847 *AsciiFilePtr = 0;
1848
1849\r
1850 //\r
1851 // Is there an attribute change request?\r
1852 //\r
1853 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
1854 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
1855 Status = EFI_INVALID_PARAMETER;\r
1856 goto Done;\r
1857 }\r
1858\r
1859 AttrChangeFlag = TRUE;\r
1860 }\r
1861\r
1862 //\r
1863 // Is there a name change request?\r
1864 // bugbug: - Need EfiStrCaseCmp()\r
1865 //\r
1866 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
1867 NameChangeFlag = TRUE;\r
1868 }\r
1869\r
1870 //\r
1871 // Is there a size change request?\r
1872 //\r
1873 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
1874 SizeChangeFlag = TRUE;\r
1875 }\r
1876\r
1877 //\r
1878 // Is there a time stamp change request?\r
1879 //\r
1880 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
1881 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
1882 ) {\r
1883 TimeChangeFlag = TRUE;\r
1884 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
1885 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
1886 ) {\r
1887 TimeChangeFlag = TRUE;\r
1888 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
1889 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
1890 ) {\r
1891 TimeChangeFlag = TRUE;\r
1892 }\r
1893\r
1894 //\r
1895 // All done if there are no change requests being made.\r
1896 //\r
1897 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
1898 Status = EFI_SUCCESS;\r
1899 goto Done;\r
1900 }\r
1901\r
1902 //\r
1903 // Set file or directory information.\r
1904 //\r
1905 if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {
1906 Status = EFI_DEVICE_ERROR;
1907 goto Done;
1908 }
1909\r
1910 //\r
1911 // Name change.\r
1912 //\r
1913 if (NameChangeFlag) {\r
1914 //\r
1915 // Close the handles first\r
1916 //\r
1917 if (PrivateFile->IsOpenedByRead) {\r
1918 Status = EFI_ACCESS_DENIED;\r
1919 goto Done;\r
1920 }\r
1921\r
1922 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
1923 }\r
1924\r
1925 if (*CharPointer != 0) {\r
1926 Status = EFI_ACCESS_DENIED;\r
1927 goto Done;\r
1928 }\r
1929\r
1930 UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);\r
1931\r
1932 if (UnixStatus == 0) {\r
1933 //\r
1934 // modify file name\r
1935 //\r
1936 gBS->FreePool (PrivateFile->FileName);\r
1937\r
1938 Status = gBS->AllocatePool (\r
1939 EfiBootServicesData,\r
1940 AsciiStrSize (NewFileName),\r
1941 (VOID **)&PrivateFile->FileName\r
1942 );\r
1943\r
1944 if (EFI_ERROR (Status)) {\r
1945 goto Done;\r
1946 }\r
1947\r
1948 AsciiStrCpy (PrivateFile->FileName, NewFileName);\r
1949 } else {\r
1950 Status = EFI_DEVICE_ERROR;\r
1951 goto Done;\r
1952 }\r
1953 }\r
1954\r
1955 //\r
1956 // Size change\r
1957 //\r
1958 if (SizeChangeFlag) {\r
1959 if (PrivateFile->IsDirectoryPath) {\r
1960 Status = EFI_UNSUPPORTED;\r
1961 goto Done;\r
1962 }\r
1963\r
1964 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
1965 Status = EFI_ACCESS_DENIED;\r
1966 goto Done;\r
1967 }\r
1968\r
1969 if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {\r
1970 Status = EFI_DEVICE_ERROR;\r
1971 goto Done;\r
1972 }\r
1973\r
1974 }\r
1975\r
1976 //\r
1977 // Time change\r
1978 //\r
1979 if (TimeChangeFlag) {\r
1980 struct utimbuf utime;
1981\r
1982 NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year;\r
1983 NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month;\r
1984 NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day;\r
1985 NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour;\r
1986 NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute;\r
1987 NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second;\r
1988 NewLastAccessSystemTime.tm_isdst = 0;
1989\r
1990 utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);
1991
1992 NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year;\r
1993 NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month;\r
1994 NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day;\r
1995 NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour;\r
1996 NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute;\r
1997 NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second;\r
1998 NewLastWriteSystemTime.tm_isdst = 0;
1999\r
2000 utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);
2001
2002 if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {
2003 goto Done;\r
2004 }\r
2005\r
2006 if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {
2007 goto Done;\r
2008 }\r
2009 }\r
2010\r
2011 //\r
2012 // No matter about AttrChangeFlag, Attribute must be set.\r
2013 // Because operation before may cause attribute change.\r
2014 //\r
2015 NewAttr = OldAttr.st_mode;\r
2016\r
2017 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2018 NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);
2019 } else {\r
2020 NewAttr |= S_IRUSR;
2021 }\r
2022\r
2023 UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);\r
2024\r
2025 if (UnixStatus != 0) {\r
2026 Status = EFI_DEVICE_ERROR;\r
2027 }\r
2028\r
2029Done:\r
2030 if (OldFileInfo != NULL) {\r
2031 gBS->FreePool (OldFileInfo);\r
2032 }\r
2033\r
2034 if (OldFileName != NULL) {\r
2035 gBS->FreePool (OldFileName);\r
2036 }\r
2037\r
2038 if (NewFileName != NULL) {\r
2039 gBS->FreePool (NewFileName);\r
2040 }\r
2041\r
2042 return Status;\r
2043}\r
2044\r
2045EFI_STATUS\r
2046EFIAPI\r
2047UnixSimpleFileSystemFlush (\r
2048 IN EFI_FILE *This\r
2049 )\r
2050/*++\r
2051\r
2052Routine Description:\r
2053\r
2054 Flush all modified data to the media.\r
2055\r
2056Arguments:\r
2057\r
2058 This - Pointer to an opened file handle.\r
2059\r
2060Returns:\r
2061\r
2062 EFI_SUCCESS - The data has been flushed.\r
2063\r
2064 EFI_NO_MEDIA - The device has no media.\r
2065\r
2066 EFI_DEVICE_ERROR - The device reported an error.\r
2067\r
2068 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
2069\r
2070 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2071\r
2072 EFI_ACCESS_DENIED - The file was opened read-only.\r
2073\r
2074 EFI_VOLUME_FULL - The volume is full.\r
2075\r
2076--*/\r
2077// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2078{\r
2079 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
2080\r
2081 if (This == NULL) {\r
2082 return EFI_INVALID_PARAMETER;\r
2083 }\r
2084\r
2085 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2086\r
2087\r
2088 if (PrivateFile->IsDirectoryPath) {\r
2089 return EFI_SUCCESS;\r
2090 }\r
2091\r
2092 if (PrivateFile->IsOpenedByRead) {\r
2093 return EFI_ACCESS_DENIED;\r
2094 }\r
2095\r
2096 if (PrivateFile->fd < 0) {
2097 return EFI_DEVICE_ERROR;\r
2098 }\r
2099
2100 return PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
2101\r
2102 //\r
377fc2ae 2103 // bugbug: - Use Unix error reporting.\r
c9093a06 2104 //\r
2105}\r
2106\r