]> git.proxmox.com Git - mirror_edk2.git/blame - UnixPkg/UnixSimpleFileSystemDxe/UnixSimpleFileSystem.c
Fix file headers
[mirror_edk2.git] / UnixPkg / UnixSimpleFileSystemDxe / UnixSimpleFileSystem.c
CommitLineData
804405e7 1/*++\r
2\r
3Copyright (c) 2006 - 2007, 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
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
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 0xa,\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;\r
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;\r
299 Private->VolumeLabel = NULL;\r
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\r
311 for (i = 0; UnixIo->EnvString[i] != 0; i++)\r
312 Private->FilePath[i] = UnixIo->EnvString[i];\r
313 Private->FilePath[i] = 0;\r
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)\r
353 gBS->FreePool (Private->VolumeLabel);\r
354 if (Private->FilePath != NULL)\r
355 gBS->FreePool (Private->FilePath);\r
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 EFI_TPL OldTpl;\r
499\r
500 if (This == NULL || Root == NULL) {\r
501 return EFI_INVALID_PARAMETER;\r
502 }\r
503 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
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_SIMPLE_FILE_SYSTEM_PROTOCOL_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
545 PrivateFile->fd = -1;\r
546 PrivateFile->Dir = NULL;\r
547 PrivateFile->Dirent = NULL;\r
548 \r
549 *Root = &PrivateFile->EfiFile;\r
550\r
551 PrivateFile->Dir = PrivateFile->UnixThunk->OpenDir(PrivateFile->FileName);\r
552\r
553 if (PrivateFile->Dir == NULL) {\r
554 Status = EFI_ACCESS_DENIED;\r
555 }\r
556 else {\r
557 Status = EFI_SUCCESS;\r
558 }\r
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
571 gBS->RestoreTPL (OldTpl);\r
572\r
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
636 CHAR16 *Src;\r
637 char *Dst;\r
638 CHAR8 *RealFileName;\r
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
678\r
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
687 if (StrCmp (FileName, L"\\") == 0\r
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
731 // Skip first '\'.\r
732 Src = FileName + 1;\r
733 } else {\r
734 AsciiStrCpy (NewPrivateFile->FileName, PrivateFile->FileName);\r
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
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
814 while (RealFileName > NewPrivateFile->FileName && *RealFileName != '/')\r
815 RealFileName--;\r
816\r
817 TempChar = *(RealFileName - 1);\r
818 *(RealFileName - 1) = 0;\r
819\r
820 *(RealFileName - 1) = TempChar;\r
821\r
822\r
823\r
824 //\r
825 // Test whether file or directory\r
826 //\r
827 NewPrivateFile->IsRootDirectory = FALSE;\r
828 NewPrivateFile->fd = -1;\r
829 NewPrivateFile->Dir = NULL;\r
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
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
840 NewPrivateFile->IsDirectoryPath = TRUE;\r
841 else\r
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
863 INTN LastError;\r
864\r
865 LastError = PrivateFile->UnixThunk->GetErrno ();\r
866 if (LastError != EEXIST) {\r
867 //gBS->FreePool (TempFileName);\r
868 Status = EFI_ACCESS_DENIED;\r
869 goto Done;\r
870 }\r
871 }\r
872 }\r
873\r
874 NewPrivateFile->Dir = NewPrivateFile->UnixThunk->OpenDir\r
875 (NewPrivateFile->FileName);\r
876\r
877 if (NewPrivateFile->Dir == NULL) {\r
878 if (PrivateFile->UnixThunk->GetErrno () == EACCES) {\r
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
891 NewPrivateFile->fd = NewPrivateFile->UnixThunk->Open\r
892 (NewPrivateFile->FileName,\r
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
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
984 EFI_TPL OldTpl;\r
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
992 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
993\r
994 if (PrivateFile->fd >= 0) {\r
995 PrivateFile->UnixThunk->Close (PrivateFile->fd);\r
996 }\r
997 if (PrivateFile->Dir != NULL) {\r
998 PrivateFile->UnixThunk->CloseDir (PrivateFile->Dir);\r
999 }\r
1000\r
1001 PrivateFile->fd = -1;\r
1002 PrivateFile->Dir = NULL;\r
1003\r
1004 if (PrivateFile->FileName) {\r
1005 gBS->FreePool (PrivateFile->FileName);\r
1006 }\r
1007\r
1008 gBS->FreePool (PrivateFile);\r
1009\r
1010 gBS->RestoreTPL (OldTpl);\r
1011 \r
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
1040 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1041 EFI_TPL OldTpl;\r
1042\r
1043 if (This == NULL) {\r
1044 return EFI_INVALID_PARAMETER;\r
1045 }\r
1046\r
1047 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1048 \r
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
1056 PrivateFile->Dir = NULL;\r
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
1064 PrivateFile->fd = -1;\r
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
1076 gBS->RestoreTPL (OldTpl);\r
1077\r
1078 return Status;\r
1079}\r
1080\r
804405e7 1081VOID\r
1082UnixSystemTimeToEfiTime (\r
1083 EFI_UNIX_THUNK_PROTOCOL *UnixThunk,\r
1084 IN time_t SystemTime,\r
1085 OUT EFI_TIME *Time\r
1086 )\r
1087/*++\r
1088\r
1089Routine Description:\r
1090\r
1091 TODO: Add function description\r
1092\r
1093Arguments:\r
1094\r
1095 SystemTime - TODO: add argument description\r
1096 TimeZone - TODO: add argument description\r
1097 Time - TODO: add argument description\r
1098\r
1099Returns:\r
1100\r
1101 TODO: add return values\r
1102\r
1103--*/\r
1104{\r
1105 struct tm *tm;\r
1106 tm = UnixThunk->GmTime (&SystemTime);\r
1107 Time->Year = tm->tm_year;\r
1108 Time->Month = tm->tm_mon;\r
1109 Time->Day = tm->tm_mday;\r
1110 Time->Hour = tm->tm_hour;\r
1111 Time->Minute = tm->tm_min;\r
1112 Time->Second = tm->tm_sec;\r
1113 Time->Nanosecond = 0;\r
1114\r
1115 Time->TimeZone = UnixThunk->GetTimeZone ();\r
1116\r
1117 if (UnixThunk->GetDayLight ()) {\r
1118 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
1119 }\r
1120}\r
1121\r
804405e7 1122EFI_STATUS\r
1123UnixSimpleFileSystemFileInfo (\r
1124 UNIX_EFI_FILE_PRIVATE *PrivateFile,\r
1125 IN CHAR8 *FileName,\r
1126 IN OUT UINTN *BufferSize,\r
1127 OUT VOID *Buffer\r
1128 )\r
1129/*++\r
1130\r
1131Routine Description:\r
1132\r
1133 TODO: Add function description\r
1134\r
1135Arguments:\r
1136\r
1137 PrivateFile - TODO: add argument description\r
1138 BufferSize - TODO: add argument description\r
1139 Buffer - TODO: add argument description\r
1140\r
1141Returns:\r
1142\r
1143 TODO: add return values\r
1144\r
1145--*/\r
1146{\r
1147 EFI_STATUS Status;\r
1148 UINTN Size;\r
1149 UINTN NameSize;\r
1150 UINTN ResultSize;\r
1151 EFI_FILE_INFO *Info;\r
1152 CHAR8 *RealFileName;\r
1153 CHAR8 *TempPointer;\r
1154 CHAR16 *BufferFileName;\r
1155 struct stat buf;\r
1156\r
1157 if (FileName != NULL) {\r
1158 RealFileName = FileName;\r
1159 }\r
1160 else if (PrivateFile->IsRootDirectory) {\r
1161 RealFileName = "";\r
1162 } else {\r
1163 RealFileName = PrivateFile->FileName;\r
1164 }\r
1165\r
1166 TempPointer = RealFileName;\r
1167 while (*TempPointer) {\r
1168 if (*TempPointer == '/') {\r
1169 RealFileName = TempPointer + 1;\r
1170 }\r
1171\r
1172 TempPointer++;\r
1173 }\r
1174\r
1175 Size = SIZE_OF_EFI_FILE_INFO;\r
1176 NameSize = AsciiStrSize (RealFileName) * 2;\r
1177 ResultSize = Size + NameSize;\r
1178\r
1179 if (*BufferSize < ResultSize) {\r
1180 *BufferSize = ResultSize;\r
1181 return EFI_BUFFER_TOO_SMALL;\r
1182 }\r
1183 if (PrivateFile->UnixThunk->Stat (\r
1184 FileName == NULL ? PrivateFile->FileName : FileName,\r
1185 &buf) < 0)\r
1186 return EFI_DEVICE_ERROR;\r
1187\r
1188 Status = EFI_SUCCESS;\r
1189\r
1190 Info = Buffer;\r
1191 ZeroMem (Info, ResultSize);\r
1192\r
1193 Info->Size = ResultSize;\r
1194 Info->FileSize = buf.st_size;\r
1195 Info->PhysicalSize = MultU64x32 (buf.st_blocks, buf.st_blksize);\r
1196\r
1197 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_ctime, &Info->CreateTime);\r
1198 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_atime, &Info->LastAccessTime);\r
1199 UnixSystemTimeToEfiTime (PrivateFile->UnixThunk, buf.st_mtime, &Info->ModificationTime);\r
1200\r
1201 if (!(buf.st_mode & S_IWUSR)) {\r
1202 Info->Attribute |= EFI_FILE_READ_ONLY;\r
1203 }\r
1204\r
1205 if (S_ISDIR(buf.st_mode)) {\r
1206 Info->Attribute |= EFI_FILE_DIRECTORY;\r
1207 }\r
1208\r
1209\r
1210 BufferFileName = (CHAR16 *)((CHAR8 *) Buffer + Size);\r
1211 while (*RealFileName)\r
1212 *BufferFileName++ = *RealFileName++;\r
1213 *BufferFileName = 0;\r
1214\r
1215 *BufferSize = ResultSize;\r
1216 return Status;\r
1217}\r
1218\r
1219EFI_STATUS\r
1220EFIAPI\r
1221UnixSimpleFileSystemRead (\r
1222 IN EFI_FILE *This,\r
1223 IN OUT UINTN *BufferSize,\r
1224 OUT VOID *Buffer\r
1225 )\r
1226/*++\r
1227\r
1228Routine Description:\r
1229\r
1230 Read data from a file.\r
1231\r
1232Arguments:\r
1233\r
1234 This - Pointer to a returned open file handle.\r
1235\r
1236 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
1237\r
1238 Buffer - Pointer to the first byte of the read Buffer.\r
1239\r
1240Returns:\r
1241\r
1242 EFI_SUCCESS - The data was read.\r
1243\r
1244 EFI_NO_MEDIA - The device has no media.\r
1245\r
1246 EFI_DEVICE_ERROR - The device reported an error.\r
1247\r
1248 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
1249\r
1250 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
1251 *BufferSize has been updated with the size needed to complete the request.\r
1252\r
1253--*/\r
1254// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1255{\r
1256 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1257 EFI_STATUS Status;\r
1258 INTN Res;\r
1259 UINTN Size;\r
1260 UINTN NameSize;\r
1261 UINTN ResultSize;\r
1262 CHAR8 *FullFileName;\r
1263 EFI_TPL OldTpl;\r
1264\r
1265 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1266 return EFI_INVALID_PARAMETER;\r
1267 }\r
1268\r
1269 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1270 \r
1271 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1272\r
1273 if (!PrivateFile->IsDirectoryPath) {\r
1274\r
1275 if (PrivateFile->fd < 0) {\r
1276 Status = EFI_DEVICE_ERROR;\r
1277 goto Done;\r
1278 }\r
1279\r
1280 Res = PrivateFile->UnixThunk->Read (\r
1281 PrivateFile->fd,\r
1282 Buffer,\r
1283 *BufferSize);\r
1284 if (Res < 0) {\r
1285 Status = EFI_DEVICE_ERROR;\r
1286 goto Done;\r
1287 }\r
1288 *BufferSize = Res;\r
1289 Status = EFI_SUCCESS;\r
1290 goto Done;\r
1291 }\r
1292\r
1293 //\r
1294 // Read on a directory.\r
1295 //\r
1296 if (PrivateFile->Dir == NULL) {\r
1297 Status = EFI_DEVICE_ERROR;\r
1298 goto Done;\r
1299 }\r
1300\r
1301 if (PrivateFile->Dirent == NULL) {\r
1302 PrivateFile->Dirent = PrivateFile->UnixThunk->ReadDir (PrivateFile->Dir);\r
1303 if (PrivateFile->Dirent == NULL) {\r
1304 *BufferSize = 0;\r
1305 Status = EFI_SUCCESS;\r
1306 goto Done;\r
1307 }\r
1308 }\r
1309\r
1310 Size = SIZE_OF_EFI_FILE_INFO;\r
1311 NameSize = AsciiStrLen (PrivateFile->Dirent->d_name) + 1;\r
1312 ResultSize = Size + 2 * NameSize;\r
1313\r
1314 if (*BufferSize < ResultSize) {\r
1315 *BufferSize = ResultSize;\r
1316 Status = EFI_BUFFER_TOO_SMALL;\r
1317 goto Done;\r
1318 }\r
1319 Status = EFI_SUCCESS;\r
1320\r
1321 *BufferSize = ResultSize;\r
1322\r
1323 Status = gBS->AllocatePool (\r
1324 EfiBootServicesData,\r
1325 AsciiStrLen(PrivateFile->FileName) + 1 + NameSize,\r
1326 (VOID **)&FullFileName\r
1327 );\r
1328\r
1329 if (EFI_ERROR (Status)) {\r
1330 goto Done;\r
1331 }\r
1332 \r
1333 AsciiStrCpy(FullFileName, PrivateFile->FileName);\r
1334 AsciiStrCat(FullFileName, "/");\r
1335 AsciiStrCat(FullFileName, PrivateFile->Dirent->d_name);\r
1336 Status = UnixSimpleFileSystemFileInfo (PrivateFile,\r
1337 FullFileName,\r
1338 BufferSize,\r
1339 Buffer);\r
1340 gBS->FreePool (FullFileName);\r
1341\r
1342 PrivateFile->Dirent = NULL;\r
1343\r
1344Done:\r
1345 gBS->RestoreTPL (OldTpl);\r
1346\r
1347 return Status;\r
1348}\r
1349\r
1350EFI_STATUS\r
1351EFIAPI\r
1352UnixSimpleFileSystemWrite (\r
1353 IN EFI_FILE *This,\r
1354 IN OUT UINTN *BufferSize,\r
1355 IN VOID *Buffer\r
1356 )\r
1357/*++\r
1358\r
1359Routine Description:\r
1360\r
1361 Write data to a file.\r
1362\r
1363Arguments:\r
1364\r
1365 This - Pointer to an opened file handle.\r
1366\r
1367 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
1368 of data written to the file.\r
1369\r
1370 Buffer - Pointer to the first by of data in the buffer to write to the file.\r
1371\r
1372Returns:\r
1373\r
1374 EFI_SUCCESS - The data was written to the file.\r
1375\r
1376 EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
1377\r
1378 EFI_NO_MEDIA - The device has no media.\r
1379\r
1380 EFI_DEVICE_ERROR - The device reported an error.\r
1381\r
1382 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1383\r
1384 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1385\r
1386 EFI_ACCESS_DENIED - The file was opened read-only.\r
1387\r
1388 EFI_VOLUME_FULL - The volume is full.\r
1389\r
1390--*/\r
1391// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1392{\r
1393 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1394 UINTN Res;\r
1395 EFI_STATUS Status;\r
1396 EFI_TPL OldTpl;\r
1397\r
1398 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1399 return EFI_INVALID_PARAMETER;\r
1400 }\r
1401\r
1402 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1403\r
1404 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1405\r
1406 if (PrivateFile->fd < 0) {\r
1407 return EFI_DEVICE_ERROR;\r
1408 }\r
1409\r
1410 if (PrivateFile->IsDirectoryPath) {\r
1411 return EFI_UNSUPPORTED;\r
1412 }\r
1413\r
1414 if (PrivateFile->IsOpenedByRead) {\r
1415 return EFI_ACCESS_DENIED;\r
1416 }\r
1417\r
1418 Res = PrivateFile->UnixThunk->Write (\r
1419 PrivateFile->fd,\r
1420 Buffer,\r
1421 *BufferSize);\r
1422 if (Res == (UINTN)-1) {\r
1423 Status = EFI_DEVICE_ERROR;\r
1424 goto Done;\r
1425 }\r
1426 *BufferSize = Res;\r
1427 Status = EFI_SUCCESS;\r
1428\r
1429Done:\r
1430 gBS->RestoreTPL (OldTpl);\r
1431 return Status;\r
1432\r
1433 //\r
1434 // bugbug: need to access unix error reporting\r
1435 //\r
1436}\r
1437\r
1438EFI_STATUS\r
1439EFIAPI\r
1440UnixSimpleFileSystemSetPosition (\r
1441 IN EFI_FILE *This,\r
1442 IN UINT64 Position\r
1443 )\r
1444/*++\r
1445\r
1446Routine Description:\r
1447\r
1448 Set a file's current position.\r
1449\r
1450Arguments:\r
1451\r
1452 This - Pointer to an opened file handle.\r
1453\r
1454 Position - The byte position from the start of the file to set.\r
1455\r
1456Returns:\r
1457\r
1458 EFI_SUCCESS - The file position has been changed.\r
1459\r
1460 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
1461\r
1462--*/\r
1463// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1464{\r
1465 EFI_STATUS Status;\r
1466 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1467 UINT64 Pos;\r
1468 EFI_TPL OldTpl;\r
1469\r
1470 if (This == NULL) {\r
1471 return EFI_INVALID_PARAMETER;\r
1472 }\r
1473\r
1474 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1475 \r
1476 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1477\r
1478 if (PrivateFile->IsDirectoryPath) {\r
1479 if (Position != 0) {\r
1480 Status = EFI_UNSUPPORTED;\r
1481 goto Done;\r
1482 }\r
1483\r
1484 if (PrivateFile->Dir == NULL) {\r
1485 Status = EFI_DEVICE_ERROR;\r
1486 goto Done;\r
1487 }\r
1488 PrivateFile->UnixThunk->RewindDir (PrivateFile->Dir);\r
1489 Status = EFI_SUCCESS;\r
1490 goto Done;\r
1491 } else {\r
1492 if (Position == (UINT64) -1) {\r
1493 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_END);\r
1494 } else {\r
1495 Pos = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, Position, SEEK_SET);\r
1496 }\r
1497 Status = (Pos == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1498 }\r
1499\r
1500Done:\r
1501 gBS->RestoreTPL (OldTpl);\r
1502 return Status;\r
1503}\r
1504\r
1505EFI_STATUS\r
1506EFIAPI\r
1507UnixSimpleFileSystemGetPosition (\r
1508 IN EFI_FILE *This,\r
1509 OUT UINT64 *Position\r
1510 )\r
1511/*++\r
1512\r
1513Routine Description:\r
1514\r
1515 Get a file's current position.\r
1516\r
1517Arguments:\r
1518\r
1519 This - Pointer to an opened file handle.\r
1520\r
1521 Position - Pointer to storage for the current position.\r
1522\r
1523Returns:\r
1524\r
1525 EFI_SUCCESS - The file position has been reported.\r
1526\r
1527 EFI_UNSUPPORTED - Not valid for directories.\r
1528\r
1529--*/\r
1530// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1531{\r
1532 EFI_STATUS Status;\r
1533 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1534 EFI_TPL OldTpl;\r
1535\r
1536 if (This == NULL || Position == NULL) {\r
1537 return EFI_INVALID_PARAMETER;\r
1538 }\r
1539\r
1540 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1541 \r
1542 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1543\r
1544 if (PrivateFile->IsDirectoryPath) {\r
1545 Status = EFI_UNSUPPORTED;\r
1546 } else {\r
1547 *Position = PrivateFile->UnixThunk->Lseek (PrivateFile->fd, 0, SEEK_CUR);\r
1548 Status = (*Position == (UINT64) -1) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1549 }\r
1550\r
1551 gBS->RestoreTPL (OldTpl);\r
1552 return Status;\r
1553}\r
1554\r
1555EFI_STATUS\r
1556EFIAPI\r
1557UnixSimpleFileSystemGetInfo (\r
1558 IN EFI_FILE *This,\r
1559 IN EFI_GUID *InformationType,\r
1560 IN OUT UINTN *BufferSize,\r
1561 OUT VOID *Buffer\r
1562 )\r
1563/*++\r
1564\r
1565Routine Description:\r
1566\r
1567 Return information about a file or volume.\r
1568\r
1569Arguments:\r
1570\r
1571 This - Pointer to an opened file handle.\r
1572\r
1573 InformationType - GUID describing the type of information to be returned.\r
1574\r
1575 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
1576 information buffer.\r
1577\r
1578 Buffer - Pointer to the first byte of the information buffer.\r
1579\r
1580Returns:\r
1581\r
1582 EFI_SUCCESS - The requested information has been written into the buffer.\r
1583\r
1584 EFI_UNSUPPORTED - The InformationType is not known.\r
1585\r
1586 EFI_NO_MEDIA - The device has no media.\r
1587\r
1588 EFI_DEVICE_ERROR - The device reported an error.\r
1589\r
1590 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1591\r
1592 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
1593 been updated with the size needed to complete the requested operation.\r
1594\r
1595--*/\r
1596// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1597{\r
1598 EFI_STATUS Status;\r
1599 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1600 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
1601 INTN UnixStatus;\r
1602 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
1603 struct statfs buf;\r
1604 EFI_TPL OldTpl;\r
1605\r
1606 if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
1607 return EFI_INVALID_PARAMETER;\r
1608 }\r
1609\r
1610 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1611 \r
1612 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1613 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1614\r
1615 Status = EFI_UNSUPPORTED;\r
1616\r
1617 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1618 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, BufferSize, Buffer);\r
1619 } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1620 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
1621 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1622 Status = EFI_BUFFER_TOO_SMALL;\r
1623 goto Done;\r
1624 }\r
1625\r
1626 UnixStatus = PrivateFile->UnixThunk->StatFs (PrivateFile->FileName, &buf);\r
1627 if (UnixStatus < 0) {\r
1628 Status = EFI_DEVICE_ERROR;\r
1629 goto Done;\r
1630 }\r
1631\r
1632 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1633 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1634 FileSystemInfoBuffer->ReadOnly = FALSE;\r
1635\r
1636 //\r
1637 // Succeeded\r
1638 //\r
1639 FileSystemInfoBuffer->VolumeSize = MultU64x32 (buf.f_blocks, buf.f_bsize);\r
1640 FileSystemInfoBuffer->FreeSpace = MultU64x32 (buf.f_bavail, buf.f_bsize);\r
1641 FileSystemInfoBuffer->BlockSize = buf.f_bsize;\r
1642\r
1643\r
1644 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
1645 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
1646 Status = EFI_SUCCESS;\r
1647 } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1648 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
1649 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
1650 Status = EFI_BUFFER_TOO_SMALL;\r
1651 goto Done;\r
1652 }\r
1653\r
1654 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
1655 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
1656 Status = EFI_SUCCESS;\r
1657 }\r
1658\r
1659Done:\r
1660 gBS->RestoreTPL (OldTpl);\r
1661 return Status;\r
1662}\r
1663\r
1664EFI_STATUS\r
1665EFIAPI\r
1666UnixSimpleFileSystemSetInfo (\r
1667 IN EFI_FILE *This,\r
1668 IN EFI_GUID *InformationType,\r
1669 IN UINTN BufferSize,\r
1670 IN VOID *Buffer\r
1671 )\r
1672/*++\r
1673\r
1674Routine Description:\r
1675\r
1676 Set information about a file or volume.\r
1677\r
1678Arguments:\r
1679\r
1680 This - Pointer to an opened file handle.\r
1681\r
1682 InformationType - GUID identifying the type of information to set.\r
1683\r
1684 BufferSize - Number of bytes of data in the information buffer.\r
1685\r
1686 Buffer - Pointer to the first byte of data in the information buffer.\r
1687\r
1688Returns:\r
1689\r
1690 EFI_SUCCESS - The file or volume information has been updated.\r
1691\r
1692 EFI_UNSUPPORTED - The information identifier is not recognised.\r
1693\r
1694 EFI_NO_MEDIA - The device has no media.\r
1695\r
1696 EFI_DEVICE_ERROR - The device reported an error.\r
1697\r
1698 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1699\r
1700 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1701\r
1702 EFI_ACCESS_DENIED - The file was opened read-only.\r
1703\r
1704 EFI_VOLUME_FULL - The volume is full.\r
1705\r
1706 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
1707\r
1708--*/\r
1709// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1710// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1711{\r
1712 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
1713 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
1714 EFI_FILE_INFO *OldFileInfo;\r
1715 EFI_FILE_INFO *NewFileInfo;\r
1716 EFI_STATUS Status;\r
1717 UINTN OldInfoSize;\r
1718 EFI_TPL OldTpl;\r
1719 mode_t NewAttr;\r
1720 struct stat OldAttr;\r
1721 CHAR8 *OldFileName;\r
1722 CHAR8 *NewFileName;\r
1723 CHAR8 *CharPointer;\r
1724 BOOLEAN AttrChangeFlag;\r
1725 BOOLEAN NameChangeFlag;\r
1726 BOOLEAN SizeChangeFlag;\r
1727 BOOLEAN TimeChangeFlag;\r
1728 struct tm NewLastAccessSystemTime;\r
1729 struct tm NewLastWriteSystemTime;\r
1730 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
1731 CHAR8 *AsciiFilePtr;\r
1732 CHAR16 *UnicodeFilePtr;\r
1733 INTN UnixStatus;\r
1734\r
1735 //\r
1736 // Check for invalid parameters.\r
1737 //\r
1738 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
1739 return EFI_INVALID_PARAMETER;\r
1740 }\r
1741\r
1742 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1743 \r
1744 //\r
1745 // Initialise locals.\r
1746 //\r
1747 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1748 PrivateRoot = UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
1749\r
1750 Status = EFI_UNSUPPORTED;\r
1751 OldFileInfo = NewFileInfo = NULL;\r
1752 OldFileName = NewFileName = NULL;\r
1753 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
1754\r
1755 //\r
1756 // Set file system information.\r
1757 //\r
1758 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
1759 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
1760 Status = EFI_BAD_BUFFER_SIZE;\r
1761 goto Done;\r
1762 }\r
1763\r
1764 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
1765\r
1766 gBS->FreePool (PrivateRoot->VolumeLabel);\r
1767\r
1768 PrivateRoot->VolumeLabel = NULL;\r
1769 Status = gBS->AllocatePool (\r
1770 EfiBootServicesData,\r
1771 StrSize (NewFileSystemInfo->VolumeLabel),\r
1772 (VOID **)&PrivateRoot->VolumeLabel\r
1773 );\r
1774\r
1775 if (EFI_ERROR (Status)) {\r
1776 goto Done;\r
1777 }\r
1778\r
1779 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
1780\r
1781 Status = EFI_SUCCESS;\r
1782 goto Done;\r
1783 }\r
1784\r
1785 //\r
1786 // Set volume label information.\r
1787 //\r
1788 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
1789 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
1790 Status = EFI_BAD_BUFFER_SIZE;\r
1791 goto Done;\r
1792 }\r
1793\r
1794 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
1795\r
1796 Status = EFI_SUCCESS;\r
1797 goto Done;\r
1798 }\r
1799\r
1800 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
1801 Status = EFI_UNSUPPORTED;\r
1802 goto Done;\r
1803 }\r
1804\r
1805 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
1806 Status = EFI_BAD_BUFFER_SIZE;\r
1807 goto Done;\r
1808 }\r
1809\r
1810 //\r
1811 // Set file/directory information.\r
1812 //\r
1813\r
1814 //\r
1815 // Check for invalid set file information parameters.\r
1816 //\r
1817 NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
1818\r
1819 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||\r
1820 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
1821 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
1822 ) {\r
1823 Status = EFI_INVALID_PARAMETER;\r
1824 goto Done;\r
1825 }\r
1826\r
1827 //\r
1828 // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
1829 // that would have an additional parameter that would be the size\r
1830 // of the string array just in case there are no NULL characters in\r
1831 // the string array.\r
1832 //\r
1833 //\r
1834 // Get current file information so we can determine what kind\r
1835 // of change request this is.\r
1836 //\r
1837 OldInfoSize = 0;\r
1838 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, NULL);\r
1839\r
1840 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1841 Status = EFI_DEVICE_ERROR;\r
1842 goto Done;\r
1843 }\r
1844\r
1845 Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize,\r
1846 (VOID **)&OldFileInfo);\r
1847\r
1848 if (EFI_ERROR (Status)) {\r
1849 goto Done;\r
1850 }\r
1851\r
1852 Status = UnixSimpleFileSystemFileInfo (PrivateFile, NULL, &OldInfoSize, OldFileInfo);\r
1853\r
1854 if (EFI_ERROR (Status)) {\r
1855 goto Done;\r
1856 }\r
1857\r
1858 Status = gBS->AllocatePool (\r
1859 EfiBootServicesData,\r
1860 AsciiStrSize (PrivateFile->FileName),\r
1861 (VOID **)&OldFileName\r
1862 );\r
1863\r
1864 if (EFI_ERROR (Status)) {\r
1865 goto Done;\r
1866 }\r
1867\r
1868 AsciiStrCpy (OldFileName, PrivateFile->FileName);\r
1869\r
1870 //\r
1871 // Make full pathname from new filename and rootpath.\r
1872 //\r
1873 if (NewFileInfo->FileName[0] == '\\') {\r
1874 Status = gBS->AllocatePool (\r
1875 EfiBootServicesData,\r
1876 AsciiStrLen (PrivateRoot->FilePath) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1877 (VOID **)&NewFileName\r
1878 );\r
1879\r
1880 if (EFI_ERROR (Status)) {\r
1881 goto Done;\r
1882 }\r
1883\r
1884 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
1885 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
1886 UnicodeFilePtr = NewFileInfo->FileName + 1;\r
1887 *AsciiFilePtr++ ='/';\r
1888 } else {\r
1889 Status = gBS->AllocatePool (\r
1890 EfiBootServicesData,\r
1891 AsciiStrLen (PrivateFile->FileName) + 1 + StrLen (NewFileInfo->FileName) + 1,\r
1892 (VOID **)&NewFileName\r
1893 );\r
1894\r
1895 if (EFI_ERROR (Status)) {\r
1896 goto Done;\r
1897 }\r
1898\r
1899 AsciiStrCpy (NewFileName, PrivateRoot->FilePath);\r
1900 AsciiFilePtr = NewFileName + AsciiStrLen(NewFileName);\r
1901 while (AsciiFilePtr > NewFileName && AsciiFilePtr[-1] != '/') {\r
1902 AsciiFilePtr--;\r
1903 }\r
1904 UnicodeFilePtr = NewFileInfo->FileName;\r
1905 }\r
1906 // Convert to ascii.\r
1907 while (*UnicodeFilePtr) {\r
1908 *AsciiFilePtr++ = *UnicodeFilePtr++;\r
1909 }\r
1910 *AsciiFilePtr = 0;\r
1911\r
1912\r
1913 //\r
1914 // Is there an attribute change request?\r
1915 //\r
1916 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
1917 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
1918 Status = EFI_INVALID_PARAMETER;\r
1919 goto Done;\r
1920 }\r
1921\r
1922 AttrChangeFlag = TRUE;\r
1923 }\r
1924\r
1925 //\r
1926 // Is there a name change request?\r
1927 // bugbug: - Need EfiStrCaseCmp()\r
1928 //\r
1929 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
1930 NameChangeFlag = TRUE;\r
1931 }\r
1932\r
1933 //\r
1934 // Is there a size change request?\r
1935 //\r
1936 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
1937 SizeChangeFlag = TRUE;\r
1938 }\r
1939\r
1940 //\r
1941 // Is there a time stamp change request?\r
1942 //\r
1943 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
1944 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
1945 ) {\r
1946 TimeChangeFlag = TRUE;\r
1947 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
1948 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
1949 ) {\r
1950 TimeChangeFlag = TRUE;\r
1951 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
1952 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
1953 ) {\r
1954 TimeChangeFlag = TRUE;\r
1955 }\r
1956\r
1957 //\r
1958 // All done if there are no change requests being made.\r
1959 //\r
1960 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
1961 Status = EFI_SUCCESS;\r
1962 goto Done;\r
1963 }\r
1964\r
1965 //\r
1966 // Set file or directory information.\r
1967 //\r
1968 if (PrivateFile->UnixThunk->Stat (OldFileName, &OldAttr) != 0) {\r
1969 Status = EFI_DEVICE_ERROR;\r
1970 goto Done;\r
1971 }\r
1972\r
1973 //\r
1974 // Name change.\r
1975 //\r
1976 if (NameChangeFlag) {\r
1977 //\r
1978 // Close the handles first\r
1979 //\r
1980 if (PrivateFile->IsOpenedByRead) {\r
1981 Status = EFI_ACCESS_DENIED;\r
1982 goto Done;\r
1983 }\r
1984\r
1985 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
1986 }\r
1987\r
1988 if (*CharPointer != 0) {\r
1989 Status = EFI_ACCESS_DENIED;\r
1990 goto Done;\r
1991 }\r
1992\r
1993 UnixStatus = PrivateFile->UnixThunk->Rename (OldFileName, NewFileName);\r
1994\r
1995 if (UnixStatus == 0) {\r
1996 //\r
1997 // modify file name\r
1998 //\r
1999 gBS->FreePool (PrivateFile->FileName);\r
2000\r
2001 Status = gBS->AllocatePool (\r
2002 EfiBootServicesData,\r
2003 AsciiStrSize (NewFileName),\r
2004 (VOID **)&PrivateFile->FileName\r
2005 );\r
2006\r
2007 if (EFI_ERROR (Status)) {\r
2008 goto Done;\r
2009 }\r
2010\r
2011 AsciiStrCpy (PrivateFile->FileName, NewFileName);\r
2012 } else {\r
2013 Status = EFI_DEVICE_ERROR;\r
2014 goto Done;\r
2015 }\r
2016 }\r
2017\r
2018 //\r
2019 // Size change\r
2020 //\r
2021 if (SizeChangeFlag) {\r
2022 if (PrivateFile->IsDirectoryPath) {\r
2023 Status = EFI_UNSUPPORTED;\r
2024 goto Done;\r
2025 }\r
2026\r
2027 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2028 Status = EFI_ACCESS_DENIED;\r
2029 goto Done;\r
2030 }\r
2031\r
2032 if (PrivateFile->UnixThunk->FTruncate (PrivateFile->fd, NewFileInfo->FileSize) != 0) {\r
2033 Status = EFI_DEVICE_ERROR;\r
2034 goto Done;\r
2035 }\r
2036\r
2037 }\r
2038\r
2039 //\r
2040 // Time change\r
2041 //\r
2042 if (TimeChangeFlag) {\r
2043 struct utimbuf utime;\r
2044\r
2045 NewLastAccessSystemTime.tm_year = NewFileInfo->LastAccessTime.Year;\r
2046 NewLastAccessSystemTime.tm_mon = NewFileInfo->LastAccessTime.Month;\r
2047 NewLastAccessSystemTime.tm_mday = NewFileInfo->LastAccessTime.Day;\r
2048 NewLastAccessSystemTime.tm_hour = NewFileInfo->LastAccessTime.Hour;\r
2049 NewLastAccessSystemTime.tm_min = NewFileInfo->LastAccessTime.Minute;\r
2050 NewLastAccessSystemTime.tm_sec = NewFileInfo->LastAccessTime.Second;\r
2051 NewLastAccessSystemTime.tm_isdst = 0;\r
2052\r
2053 utime.actime = PrivateFile->UnixThunk->MkTime (&NewLastAccessSystemTime);\r
2054\r
2055 NewLastWriteSystemTime.tm_year = NewFileInfo->ModificationTime.Year;\r
2056 NewLastWriteSystemTime.tm_mon = NewFileInfo->ModificationTime.Month;\r
2057 NewLastWriteSystemTime.tm_mday = NewFileInfo->ModificationTime.Day;\r
2058 NewLastWriteSystemTime.tm_hour = NewFileInfo->ModificationTime.Hour;\r
2059 NewLastWriteSystemTime.tm_min = NewFileInfo->ModificationTime.Minute;\r
2060 NewLastWriteSystemTime.tm_sec = NewFileInfo->ModificationTime.Second;\r
2061 NewLastWriteSystemTime.tm_isdst = 0;\r
2062\r
2063 utime.modtime = PrivateFile->UnixThunk->MkTime (&NewLastWriteSystemTime);\r
2064\r
2065 if (utime.actime == (time_t)-1 || utime.modtime == (time_t)-1) {\r
2066 goto Done;\r
2067 }\r
2068\r
2069 if (PrivateFile->UnixThunk->UTime (PrivateFile->FileName, &utime) == -1) {\r
2070 goto Done;\r
2071 }\r
2072 }\r
2073\r
2074 //\r
2075 // No matter about AttrChangeFlag, Attribute must be set.\r
2076 // Because operation before may cause attribute change.\r
2077 //\r
2078 NewAttr = OldAttr.st_mode;\r
2079\r
2080 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2081 NewAttr &= ~(S_IRUSR | S_IRGRP | S_IROTH);\r
2082 } else {\r
2083 NewAttr |= S_IRUSR;\r
2084 }\r
2085\r
2086 UnixStatus = PrivateFile->UnixThunk->Chmod (NewFileName, NewAttr);\r
2087\r
2088 if (UnixStatus != 0) {\r
2089 Status = EFI_DEVICE_ERROR;\r
2090 }\r
2091\r
2092Done:\r
2093 if (OldFileInfo != NULL) {\r
2094 gBS->FreePool (OldFileInfo);\r
2095 }\r
2096\r
2097 if (OldFileName != NULL) {\r
2098 gBS->FreePool (OldFileName);\r
2099 }\r
2100\r
2101 if (NewFileName != NULL) {\r
2102 gBS->FreePool (NewFileName);\r
2103 }\r
2104\r
2105 gBS->RestoreTPL (OldTpl);\r
2106 \r
2107 return Status;\r
2108}\r
2109\r
2110EFI_STATUS\r
2111EFIAPI\r
2112UnixSimpleFileSystemFlush (\r
2113 IN EFI_FILE *This\r
2114 )\r
2115/*++\r
2116\r
2117Routine Description:\r
2118\r
2119 Flush all modified data to the media.\r
2120\r
2121Arguments:\r
2122\r
2123 This - Pointer to an opened file handle.\r
2124\r
2125Returns:\r
2126\r
2127 EFI_SUCCESS - The data has been flushed.\r
2128\r
2129 EFI_NO_MEDIA - The device has no media.\r
2130\r
2131 EFI_DEVICE_ERROR - The device reported an error.\r
2132\r
2133 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
2134\r
2135 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2136\r
2137 EFI_ACCESS_DENIED - The file was opened read-only.\r
2138\r
2139 EFI_VOLUME_FULL - The volume is full.\r
2140\r
2141--*/\r
2142// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2143{\r
2144 UNIX_EFI_FILE_PRIVATE *PrivateFile;\r
2145 EFI_STATUS Status;\r
2146 EFI_TPL OldTpl;\r
2147\r
2148 if (This == NULL) {\r
2149 return EFI_INVALID_PARAMETER;\r
2150 }\r
2151\r
2152 Status = EFI_SUCCESS;\r
2153 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2154 \r
2155 PrivateFile = UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2156\r
2157\r
2158 if (PrivateFile->IsDirectoryPath) {\r
2159 goto Done;\r
2160 }\r
2161\r
2162 if (PrivateFile->IsOpenedByRead) {\r
2163 Status = EFI_ACCESS_DENIED;\r
2164 goto Done;\r
2165 }\r
2166\r
2167 if (PrivateFile->fd < 0) {\r
2168 Status = EFI_DEVICE_ERROR;\r
2169 goto Done;\r
2170 }\r
2171\r
2172 PrivateFile->UnixThunk->FSync (PrivateFile->fd) == 0 ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
2173\r
2174Done:\r
2175 gBS->RestoreTPL (OldTpl);\r
2176\r
2177 return Status;\r
2178\r
2179 //\r
2180 // bugbug: - Use Unix error reporting.\r
2181 //\r
2182}\r
2183\r
2184\r