3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 UnixSimpleFileSystem.c
18 Produce Simple File System abstractions for directories on your PC using Posix APIs.
19 The configuration of what devices to mount or emulate comes from UNIX
20 environment variables. The variables must be visible to the Microsoft*
21 Developer Studio for them to work.
23 * Other names and brands may be claimed as the property of others.
27 #include "UnixSimpleFileSystem.h"
29 EFI_DRIVER_BINDING_PROTOCOL gUnixSimpleFileSystemDriverBinding
= {
30 UnixSimpleFileSystemDriverBindingSupported
,
31 UnixSimpleFileSystemDriverBindingStart
,
32 UnixSimpleFileSystemDriverBindingStop
,
48 Locate the first occurance of a character in a string.
52 Str - Pointer to NULL terminated unicode string.
53 Chr - Character to locate.
57 If Str is NULL, then NULL is returned.
58 If Chr is not contained in Str, then NULL is returned.
59 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
67 while (*Str
!= '\0' && *Str
!= Chr
) {
71 return (*Str
== Chr
) ? Str
: NULL
;
83 TODO: Add function description
87 Buffer - TODO: add argument description
88 Length - TODO: add argument description
92 TODO: add return values
96 if (Buffer
== NULL
|| Length
== 0) {
100 if (*(UINT8
*) Buffer
!= 0) {
105 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
122 TODO: Add function description
126 Str - TODO: add argument description
127 Count - TODO: add argument description
131 TODO: add return values
137 if (AsciiStrLen (Str
) < Count
) {
141 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
142 *Pointer
= *(Pointer
+ Count
);
145 *Pointer
= *(Pointer
+ Count
);
152 UnixSimpleFileSystemDriverBindingSupported (
153 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
154 IN EFI_HANDLE ControllerHandle
,
155 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
161 Check to see if the driver supports a given controller.
165 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
167 ControllerHandle - EFI handle of the controller to test.
169 RemainingDevicePath - Pointer to remaining portion of a device path.
173 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
176 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
177 the driver specified by This.
179 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
180 a different driver or an application that requires exclusive access.
182 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
183 driver specified by This.
188 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
191 // Open the IO Abstraction(s) needed to perform the supported test
193 Status
= gBS
->OpenProtocol (
195 &gEfiUnixIoProtocolGuid
,
197 This
->DriverBindingHandle
,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
201 if (EFI_ERROR (Status
)) {
206 // Make sure GUID is for a File System handle.
208 Status
= EFI_UNSUPPORTED
;
209 if (CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixFileSystemGuid
)) {
210 Status
= EFI_SUCCESS
;
214 // Close the I/O Abstraction(s) used to perform the supported test
218 &gEfiUnixIoProtocolGuid
,
219 This
->DriverBindingHandle
,
228 UnixSimpleFileSystemDriverBindingStart (
229 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
230 IN EFI_HANDLE ControllerHandle
,
231 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
237 Starts a device controller or a bus controller.
241 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
243 ControllerHandle - EFI handle of the controller to start.
245 RemainingDevicePath - Pointer to remaining portion of a device path.
249 EFI_SUCCESS - The device or bus controller has been started.
251 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
253 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
258 EFI_UNIX_IO_PROTOCOL
*UnixIo
;
259 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
265 // Open the IO Abstraction(s) needed
267 Status
= gBS
->OpenProtocol (
269 &gEfiUnixIoProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
275 if (EFI_ERROR (Status
)) {
282 if (!CompareGuid (UnixIo
->TypeGuid
, &gEfiUnixFileSystemGuid
)) {
283 Status
= EFI_UNSUPPORTED
;
287 Status
= gBS
->AllocatePool (
289 sizeof (UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
),
292 if (EFI_ERROR (Status
)) {
296 Private
->Signature
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
297 Private
->UnixThunk
= UnixIo
->UnixThunk
;
298 Private
->FilePath
= NULL
;
299 Private
->VolumeLabel
= NULL
;
301 Status
= gBS
->AllocatePool (
303 StrLen (UnixIo
->EnvString
) + 1,
304 (VOID
**)&Private
->FilePath
307 if (EFI_ERROR (Status
)) {
311 for (i
= 0; UnixIo
->EnvString
[i
] != 0; i
++)
312 Private
->FilePath
[i
] = UnixIo
->EnvString
[i
];
313 Private
->FilePath
[i
] = 0;
315 Private
->VolumeLabel
= NULL
;
316 Status
= gBS
->AllocatePool (
318 StrSize (L
"EFI_EMULATED"),
319 (VOID
**)&Private
->VolumeLabel
322 if (EFI_ERROR (Status
)) {
326 StrCpy (Private
->VolumeLabel
, L
"EFI_EMULATED");
328 Private
->SimpleFileSystem
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
329 Private
->SimpleFileSystem
.OpenVolume
= UnixSimpleFileSystemOpenVolume
;
331 Private
->ControllerNameTable
= NULL
;
335 gUnixSimpleFileSystemComponentName
.SupportedLanguages
,
336 &Private
->ControllerNameTable
,
340 Status
= gBS
->InstallMultipleProtocolInterfaces (
342 &gEfiSimpleFileSystemProtocolGuid
,
343 &Private
->SimpleFileSystem
,
348 if (EFI_ERROR (Status
)) {
350 if (Private
!= NULL
) {
352 if (Private
->VolumeLabel
!= NULL
)
353 gBS
->FreePool (Private
->VolumeLabel
);
354 if (Private
->FilePath
!= NULL
)
355 gBS
->FreePool (Private
->FilePath
);
356 FreeUnicodeStringTable (Private
->ControllerNameTable
);
358 gBS
->FreePool (Private
);
363 &gEfiUnixIoProtocolGuid
,
364 This
->DriverBindingHandle
,
374 UnixSimpleFileSystemDriverBindingStop (
375 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
376 IN EFI_HANDLE ControllerHandle
,
377 IN UINTN NumberOfChildren
,
378 IN EFI_HANDLE
*ChildHandleBuffer
384 TODO: Add function description
388 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
390 ControllerHandle - A handle to the device to be stopped.
392 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
394 ChildHandleBuffer - An array of child device handles to be freed.
398 EFI_SUCCESS - The device has been stopped.
400 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
403 // TODO: EFI_UNSUPPORTED - add return value to function comment
406 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
407 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
410 // Get our context back
412 Status
= gBS
->OpenProtocol (
414 &gEfiSimpleFileSystemProtocolGuid
,
415 (VOID
**)&SimpleFileSystem
,
416 This
->DriverBindingHandle
,
418 EFI_OPEN_PROTOCOL_GET_PROTOCOL
420 if (EFI_ERROR (Status
)) {
421 return EFI_UNSUPPORTED
;
424 Private
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem
);
427 // Uninstall the Simple File System Protocol from ControllerHandle
429 Status
= gBS
->UninstallMultipleProtocolInterfaces (
431 &gEfiSimpleFileSystemProtocolGuid
,
432 &Private
->SimpleFileSystem
,
435 if (!EFI_ERROR (Status
)) {
436 Status
= gBS
->CloseProtocol (
438 &gEfiUnixIoProtocolGuid
,
439 This
->DriverBindingHandle
,
444 if (!EFI_ERROR (Status
)) {
446 // Free our instance data
448 FreeUnicodeStringTable (Private
->ControllerNameTable
);
450 gBS
->FreePool (Private
);
458 UnixSimpleFileSystemOpenVolume (
459 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
466 Open the root directory on a volume.
470 This - A pointer to the volume to open.
472 Root - A pointer to storage for the returned opened file handle of the root directory.
476 EFI_SUCCESS - The volume was opened.
478 EFI_UNSUPPORTED - The volume does not support the requested file system type.
480 EFI_NO_MEDIA - The device has no media.
482 EFI_DEVICE_ERROR - The device reported an error.
484 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
486 EFI_ACCESS_DENIED - The service denied access to the file.
488 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
490 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
493 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
496 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
497 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
499 if (This
== NULL
|| Root
== NULL
) {
500 return EFI_INVALID_PARAMETER
;
503 Private
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
506 Status
= gBS
->AllocatePool (
508 sizeof (UNIX_EFI_FILE_PRIVATE
),
509 (VOID
**)&PrivateFile
511 if (EFI_ERROR (Status
)) {
515 PrivateFile
->FileName
= NULL
;
516 Status
= gBS
->AllocatePool (
518 AsciiStrSize (Private
->FilePath
),
519 (VOID
**)&PrivateFile
->FileName
521 if (EFI_ERROR (Status
)) {
525 AsciiStrCpy (PrivateFile
->FileName
, Private
->FilePath
);
526 PrivateFile
->Signature
= UNIX_EFI_FILE_PRIVATE_SIGNATURE
;
527 PrivateFile
->UnixThunk
= Private
->UnixThunk
;
528 PrivateFile
->SimpleFileSystem
= This
;
529 PrivateFile
->IsRootDirectory
= TRUE
;
530 PrivateFile
->IsDirectoryPath
= TRUE
;
531 PrivateFile
->IsOpenedByRead
= TRUE
;
532 PrivateFile
->EfiFile
.Revision
= EFI_FILE_HANDLE_REVISION
;
533 PrivateFile
->EfiFile
.Open
= UnixSimpleFileSystemOpen
;
534 PrivateFile
->EfiFile
.Close
= UnixSimpleFileSystemClose
;
535 PrivateFile
->EfiFile
.Delete
= UnixSimpleFileSystemDelete
;
536 PrivateFile
->EfiFile
.Read
= UnixSimpleFileSystemRead
;
537 PrivateFile
->EfiFile
.Write
= UnixSimpleFileSystemWrite
;
538 PrivateFile
->EfiFile
.GetPosition
= UnixSimpleFileSystemGetPosition
;
539 PrivateFile
->EfiFile
.SetPosition
= UnixSimpleFileSystemSetPosition
;
540 PrivateFile
->EfiFile
.GetInfo
= UnixSimpleFileSystemGetInfo
;
541 PrivateFile
->EfiFile
.SetInfo
= UnixSimpleFileSystemSetInfo
;
542 PrivateFile
->EfiFile
.Flush
= UnixSimpleFileSystemFlush
;
543 PrivateFile
->fd
= -1;
544 PrivateFile
->Dir
= NULL
;
545 PrivateFile
->Dirent
= NULL
;
547 *Root
= &PrivateFile
->EfiFile
;
549 PrivateFile
->Dir
= PrivateFile
->UnixThunk
->OpenDir(PrivateFile
->FileName
);
551 if (PrivateFile
->Dir
== NULL
) {
552 Status
= EFI_ACCESS_DENIED
;
555 Status
= EFI_SUCCESS
;
559 if (EFI_ERROR (Status
)) {
561 if (PrivateFile
->FileName
) {
562 gBS
->FreePool (PrivateFile
->FileName
);
565 gBS
->FreePool (PrivateFile
);
574 UnixSimpleFileSystemOpen (
576 OUT EFI_FILE
**NewHandle
,
585 Open a file relative to the source file location.
589 This - A pointer to the source file location.
591 NewHandle - Pointer to storage for the new file handle.
593 FileName - Pointer to the file name to be opened.
595 OpenMode - File open mode information.
597 Attributes - File creation attributes.
601 EFI_SUCCESS - The file was opened.
603 EFI_NOT_FOUND - The file could not be found in the volume.
605 EFI_NO_MEDIA - The device has no media.
607 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
609 EFI_DEVICE_ERROR - The device reported an error.
611 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
613 EFI_WRITE_PROTECTED - The volume or file is write protected.
615 EFI_ACCESS_DENIED - The service denied access to the file.
617 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
619 EFI_VOLUME_FULL - There is not enough space left to create the new file.
622 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
623 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
624 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
625 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
628 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
629 UNIX_EFI_FILE_PRIVATE
*NewPrivateFile
;
630 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
635 //CHAR16 *TempFileName;
640 BOOLEAN TrailingDash
;
645 TrailingDash
= FALSE
;
648 // Check for obvious invalid parameters.
650 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
651 return EFI_INVALID_PARAMETER
;
655 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
656 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
657 return EFI_INVALID_PARAMETER
;
660 if (Attributes
& EFI_FILE_READ_ONLY
) {
661 return EFI_INVALID_PARAMETER
;
667 case EFI_FILE_MODE_READ
:
668 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
672 return EFI_INVALID_PARAMETER
;
678 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
679 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
680 NewPrivateFile
= NULL
;
683 // BUGBUG: assume an open of root
684 // if current location, return current data
686 if (StrCmp (FileName
, L
"\\") == 0
687 || (StrCmp (FileName
, L
".") == 0 && PrivateFile
->IsRootDirectory
)) {
689 // BUGBUG: assume an open root
692 Status
= UnixSimpleFileSystemOpenVolume (PrivateFile
->SimpleFileSystem
, &Root
);
693 NewPrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root
);
697 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
699 FileName
[StrLen (FileName
) - 1] = 0;
703 // Attempt to open the file
705 Status
= gBS
->AllocatePool (
707 sizeof (UNIX_EFI_FILE_PRIVATE
),
708 (VOID
**)&NewPrivateFile
711 if (EFI_ERROR (Status
)) {
715 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (UNIX_EFI_FILE_PRIVATE
));
717 NewPrivateFile
->FileName
= NULL
;
718 Status
= gBS
->AllocatePool (
720 AsciiStrSize (PrivateFile
->FileName
) + 1 + StrLen (FileName
) + 1,
721 (VOID
**)&NewPrivateFile
->FileName
724 if (EFI_ERROR (Status
)) {
728 if (*FileName
== L
'\\') {
729 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
733 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateFile
->FileName
);
736 Dst
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
);
737 GuardPointer
= NewPrivateFile
->FileName
+ AsciiStrLen(PrivateRoot
->FilePath
);
739 // Convert unicode to ascii and '\' to '/'
751 // Get rid of . and .., except leading . or ..
755 // GuardPointer protect simplefilesystem root path not be destroyed
760 while (!LoopFinish
) {
764 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
765 if (*ParseFileName
== '.' &&
766 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == '/') &&
767 *(ParseFileName
- 1) == '/'
773 CutPrefix (ParseFileName
- 1, 2);
778 if (*ParseFileName
== '.' &&
779 *(ParseFileName
+ 1) == '.' &&
780 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == '/') &&
781 *(ParseFileName
- 1) == '/'
787 while (ParseFileName
!= GuardPointer
) {
790 if (*ParseFileName
== '/') {
796 // cut /.. and its left directory
798 CutPrefix (ParseFileName
, Count
);
805 if (AsciiStrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
806 NewPrivateFile
->IsRootDirectory
= TRUE
;
807 gBS
->FreePool (NewPrivateFile
->FileName
);
808 gBS
->FreePool (NewPrivateFile
);
812 RealFileName
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
) - 1;
813 while (RealFileName
> NewPrivateFile
->FileName
&& *RealFileName
!= '/')
816 TempChar
= *(RealFileName
- 1);
817 *(RealFileName
- 1) = 0;
819 *(RealFileName
- 1) = TempChar
;
824 // Test whether file or directory
826 NewPrivateFile
->IsRootDirectory
= FALSE
;
827 NewPrivateFile
->fd
= -1;
828 NewPrivateFile
->Dir
= NULL
;
829 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
830 if (Attributes
& EFI_FILE_DIRECTORY
) {
831 NewPrivateFile
->IsDirectoryPath
= TRUE
;
833 NewPrivateFile
->IsDirectoryPath
= FALSE
;
837 int res
= NewPrivateFile
->UnixThunk
->Stat (NewPrivateFile
->FileName
, &finfo
);
838 if (res
== 0 && S_ISDIR(finfo
.st_mode
))
839 NewPrivateFile
->IsDirectoryPath
= TRUE
;
841 NewPrivateFile
->IsDirectoryPath
= FALSE
;
844 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
845 NewPrivateFile
->IsOpenedByRead
= FALSE
;
847 NewPrivateFile
->IsOpenedByRead
= TRUE
;
850 Status
= EFI_SUCCESS
;
853 // deal with directory
855 if (NewPrivateFile
->IsDirectoryPath
) {
857 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
859 // Create a directory
861 if (NewPrivateFile
->UnixThunk
->MkDir (NewPrivateFile
->FileName
, 0777) != 0) {
864 LastError
= PrivateFile
->UnixThunk
->GetErrno ();
865 if (LastError
!= EEXIST
) {
866 //gBS->FreePool (TempFileName);
867 Status
= EFI_ACCESS_DENIED
;
873 NewPrivateFile
->Dir
= NewPrivateFile
->UnixThunk
->OpenDir
874 (NewPrivateFile
->FileName
);
876 if (NewPrivateFile
->Dir
== NULL
) {
877 if (PrivateFile
->UnixThunk
->GetErrno () == EACCES
) {
878 Status
= EFI_ACCESS_DENIED
;
880 Status
= EFI_NOT_FOUND
;
890 NewPrivateFile
->fd
= NewPrivateFile
->UnixThunk
->Open
891 (NewPrivateFile
->FileName
,
892 ((OpenMode
& EFI_FILE_MODE_CREATE
) ? O_CREAT
: 0)
893 | (NewPrivateFile
->IsOpenedByRead
? O_RDONLY
: O_RDWR
),
895 if (NewPrivateFile
->fd
< 0) {
896 if (PrivateFile
->UnixThunk
->GetErrno () == ENOENT
) {
897 Status
= EFI_NOT_FOUND
;
899 Status
= EFI_ACCESS_DENIED
;
904 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
911 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
913 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
914 Status
= EFI_DEVICE_ERROR
;
918 Status
= gBS
->AllocatePool (
924 if (EFI_ERROR (Status
)) {
928 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
930 if (EFI_ERROR (Status
)) {
934 Info
->Attribute
= Attributes
;
936 UnixSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
941 FileName
[StrLen (FileName
) + 1] = 0;
942 FileName
[StrLen (FileName
)] = L
'\\';
945 if (EFI_ERROR (Status
)) {
946 if (NewPrivateFile
) {
947 if (NewPrivateFile
->FileName
) {
948 gBS
->FreePool (NewPrivateFile
->FileName
);
951 gBS
->FreePool (NewPrivateFile
);
954 *NewHandle
= &NewPrivateFile
->EfiFile
;
962 UnixSimpleFileSystemClose (
969 Close the specified file handle.
973 This - Pointer to a returned opened file handle.
977 EFI_SUCCESS - The file handle has been closed.
980 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
982 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
985 return EFI_INVALID_PARAMETER
;
988 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
990 if (PrivateFile
->fd
>= 0) {
991 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
993 if (PrivateFile
->Dir
!= NULL
) {
994 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
997 PrivateFile
->fd
= -1;
998 PrivateFile
->Dir
= NULL
;
1000 if (PrivateFile
->FileName
) {
1001 gBS
->FreePool (PrivateFile
->FileName
);
1004 gBS
->FreePool (PrivateFile
);
1010 UnixSimpleFileSystemDelete (
1015 Routine Description:
1017 Close and delete a file.
1021 This - Pointer to a returned opened file handle.
1025 EFI_SUCCESS - The file handle was closed and deleted.
1027 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1030 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1033 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1036 return EFI_INVALID_PARAMETER
;
1039 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1041 Status
= EFI_WARN_DELETE_FAILURE
;
1043 if (PrivateFile
->IsDirectoryPath
) {
1044 if (PrivateFile
->Dir
!= NULL
) {
1045 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
1046 PrivateFile
->Dir
= NULL
;
1049 if (PrivateFile
->UnixThunk
->RmDir (PrivateFile
->FileName
) == 0) {
1050 Status
= EFI_SUCCESS
;
1053 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
1054 PrivateFile
->fd
= -1;
1056 if (!PrivateFile
->IsOpenedByRead
) {
1057 if (!PrivateFile
->UnixThunk
->UnLink (PrivateFile
->FileName
)) {
1058 Status
= EFI_SUCCESS
;
1063 gBS
->FreePool (PrivateFile
->FileName
);
1064 gBS
->FreePool (PrivateFile
);
1071 UnixSystemTimeToEfiTime (
1072 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
,
1073 IN
time_t SystemTime
,
1078 Routine Description:
1080 TODO: Add function description
1084 SystemTime - TODO: add argument description
1085 TimeZone - TODO: add argument description
1086 Time - TODO: add argument description
1090 TODO: add return values
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;
1104 Time
->TimeZone
= UnixThunk
->GetTimeZone ();
1106 if (UnixThunk
->GetDayLight ()) {
1107 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1113 UnixSimpleFileSystemFileInfo (
1114 UNIX_EFI_FILE_PRIVATE
*PrivateFile
,
1116 IN OUT UINTN
*BufferSize
,
1121 Routine Description:
1123 TODO: Add function description
1127 PrivateFile - TODO: add argument description
1128 BufferSize - TODO: add argument description
1129 Buffer - TODO: add argument description
1133 TODO: add return values
1141 EFI_FILE_INFO
*Info
;
1142 CHAR8
*RealFileName
;
1144 CHAR16
*BufferFileName
;
1147 if (FileName
!= NULL
) {
1148 RealFileName
= FileName
;
1150 else if (PrivateFile
->IsRootDirectory
) {
1153 RealFileName
= PrivateFile
->FileName
;
1156 TempPointer
= RealFileName
;
1157 while (*TempPointer
) {
1158 if (*TempPointer
== '/') {
1159 RealFileName
= TempPointer
+ 1;
1165 Size
= SIZE_OF_EFI_FILE_INFO
;
1166 NameSize
= AsciiStrSize (RealFileName
) * 2;
1167 ResultSize
= Size
+ NameSize
;
1169 if (*BufferSize
< ResultSize
) {
1170 *BufferSize
= ResultSize
;
1171 return EFI_BUFFER_TOO_SMALL
;
1173 if (PrivateFile
->UnixThunk
->Stat (
1174 FileName
== NULL
? PrivateFile
->FileName
: FileName
,
1176 return EFI_DEVICE_ERROR
;
1178 Status
= EFI_SUCCESS
;
1181 ZeroMem (Info
, ResultSize
);
1183 Info
->Size
= ResultSize
;
1184 Info
->FileSize
= buf
.st_size
;
1185 Info
->PhysicalSize
= MultU64x32 (buf
.st_blocks
, buf
.st_blksize
);
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
);
1191 if (!(buf
.st_mode
& S_IWUSR
)) {
1192 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1195 if (S_ISDIR(buf
.st_mode
)) {
1196 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1200 BufferFileName
= (CHAR16
*)((CHAR8
*) Buffer
+ Size
);
1201 while (*RealFileName
)
1202 *BufferFileName
++ = *RealFileName
++;
1203 *BufferFileName
= 0;
1205 *BufferSize
= ResultSize
;
1211 UnixSimpleFileSystemRead (
1213 IN OUT UINTN
*BufferSize
,
1218 Routine Description:
1220 Read data from a file.
1224 This - Pointer to a returned open file handle.
1226 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1228 Buffer - Pointer to the first byte of the read Buffer.
1232 EFI_SUCCESS - The data was read.
1234 EFI_NO_MEDIA - The device has no media.
1236 EFI_DEVICE_ERROR - The device reported an error.
1238 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1240 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1241 *BufferSize has been updated with the size needed to complete the request.
1244 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1246 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1252 CHAR8
*FullFileName
;
1254 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1255 return EFI_INVALID_PARAMETER
;
1258 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1260 if (!PrivateFile
->IsDirectoryPath
) {
1262 if (PrivateFile
->fd
< 0) {
1263 return EFI_DEVICE_ERROR
;
1266 Res
= PrivateFile
->UnixThunk
->Read (
1271 return EFI_DEVICE_ERROR
;
1277 // Read on a directory.
1279 if (PrivateFile
->Dir
== NULL
) {
1280 return EFI_DEVICE_ERROR
;
1283 if (PrivateFile
->Dirent
== NULL
) {
1284 PrivateFile
->Dirent
= PrivateFile
->UnixThunk
->ReadDir (PrivateFile
->Dir
);
1285 if (PrivateFile
->Dirent
== NULL
) {
1291 Size
= SIZE_OF_EFI_FILE_INFO
;
1292 NameSize
= AsciiStrLen (PrivateFile
->Dirent
->d_name
) + 1;
1293 ResultSize
= Size
+ 2 * NameSize
;
1295 if (*BufferSize
< ResultSize
) {
1296 *BufferSize
= ResultSize
;
1297 return EFI_BUFFER_TOO_SMALL
;
1299 Status
= EFI_SUCCESS
;
1301 *BufferSize
= ResultSize
;
1303 Status
= gBS
->AllocatePool (
1304 EfiBootServicesData
,
1305 AsciiStrLen(PrivateFile
->FileName
) + 1 + NameSize
,
1306 (VOID
**)&FullFileName
1309 if (EFI_ERROR (Status
)) {
1313 AsciiStrCpy(FullFileName
, PrivateFile
->FileName
);
1314 AsciiStrCat(FullFileName
, "/");
1315 AsciiStrCat(FullFileName
, PrivateFile
->Dirent
->d_name
);
1316 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
,
1320 gBS
->FreePool (FullFileName
);
1322 PrivateFile
->Dirent
= NULL
;
1329 UnixSimpleFileSystemWrite (
1331 IN OUT UINTN
*BufferSize
,
1336 Routine Description:
1338 Write data to a file.
1342 This - Pointer to an opened file handle.
1344 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1345 of data written to the file.
1347 Buffer - Pointer to the first by of data in the buffer to write to the file.
1351 EFI_SUCCESS - The data was written to the file.
1353 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1355 EFI_NO_MEDIA - The device has no media.
1357 EFI_DEVICE_ERROR - The device reported an error.
1359 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1361 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1363 EFI_ACCESS_DENIED - The file was opened read-only.
1365 EFI_VOLUME_FULL - The volume is full.
1368 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1370 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1373 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1374 return EFI_INVALID_PARAMETER
;
1377 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1379 if (PrivateFile
->fd
< 0) {
1380 return EFI_DEVICE_ERROR
;
1383 if (PrivateFile
->IsDirectoryPath
) {
1384 return EFI_UNSUPPORTED
;
1387 if (PrivateFile
->IsOpenedByRead
) {
1388 return EFI_ACCESS_DENIED
;
1391 Res
= PrivateFile
->UnixThunk
->Write (
1395 if (Res
== (UINTN
)-1)
1396 return EFI_DEVICE_ERROR
;
1401 // bugbug: need to access unix error reporting
1407 UnixSimpleFileSystemSetPosition (
1413 Routine Description:
1415 Set a file's current position.
1419 This - Pointer to an opened file handle.
1421 Position - The byte position from the start of the file to set.
1425 EFI_SUCCESS - The file position has been changed.
1427 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1430 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1433 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1437 return EFI_INVALID_PARAMETER
;
1440 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1442 if (PrivateFile
->IsDirectoryPath
) {
1443 if (Position
!= 0) {
1444 return EFI_UNSUPPORTED
;
1447 if (PrivateFile
->Dir
== NULL
) {
1448 return EFI_DEVICE_ERROR
;
1450 PrivateFile
->UnixThunk
->RewindDir (PrivateFile
->Dir
);
1453 if (Position
== (UINT64
) -1) {
1454 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_END
);
1456 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, Position
, SEEK_SET
);
1458 Status
= (Pos
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1466 UnixSimpleFileSystemGetPosition (
1468 OUT UINT64
*Position
1472 Routine Description:
1474 Get a file's current position.
1478 This - Pointer to an opened file handle.
1480 Position - Pointer to storage for the current position.
1484 EFI_SUCCESS - The file position has been reported.
1486 EFI_UNSUPPORTED - Not valid for directories.
1489 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1491 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1493 if (This
== NULL
|| Position
== NULL
) {
1494 return EFI_INVALID_PARAMETER
;
1497 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1499 if (PrivateFile
->IsDirectoryPath
) {
1500 return EFI_UNSUPPORTED
;
1502 *Position
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_CUR
);
1503 return (*Position
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1509 UnixSimpleFileSystemGetInfo (
1511 IN EFI_GUID
*InformationType
,
1512 IN OUT UINTN
*BufferSize
,
1517 Routine Description:
1519 Return information about a file or volume.
1523 This - Pointer to an opened file handle.
1525 InformationType - GUID describing the type of information to be returned.
1527 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1530 Buffer - Pointer to the first byte of the information buffer.
1534 EFI_SUCCESS - The requested information has been written into the buffer.
1536 EFI_UNSUPPORTED - The InformationType is not known.
1538 EFI_NO_MEDIA - The device has no media.
1540 EFI_DEVICE_ERROR - The device reported an error.
1542 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1544 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
1545 been updated with the size needed to complete the requested operation.
1548 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1551 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1552 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1554 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1557 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1558 return EFI_INVALID_PARAMETER
;
1561 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1562 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1564 Status
= EFI_UNSUPPORTED
;
1566 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1567 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, BufferSize
, Buffer
);
1569 else if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1570 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1571 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1572 return EFI_BUFFER_TOO_SMALL
;
1575 UnixStatus
= PrivateFile
->UnixThunk
->StatFs (PrivateFile
->FileName
, &buf
);
1577 return EFI_DEVICE_ERROR
;
1579 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1580 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1581 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
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
;
1591 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
1592 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1593 Status
= EFI_SUCCESS
;
1596 else if (CompareGuid (InformationType
,
1597 &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1598 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1599 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1600 return EFI_BUFFER_TOO_SMALL
;
1603 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
1604 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1605 Status
= EFI_SUCCESS
;
1613 UnixSimpleFileSystemSetInfo (
1615 IN EFI_GUID
*InformationType
,
1616 IN UINTN BufferSize
,
1621 Routine Description:
1623 Set information about a file or volume.
1627 This - Pointer to an opened file handle.
1629 InformationType - GUID identifying the type of information to set.
1631 BufferSize - Number of bytes of data in the information buffer.
1633 Buffer - Pointer to the first byte of data in the information buffer.
1637 EFI_SUCCESS - The file or volume information has been updated.
1639 EFI_UNSUPPORTED - The information identifier is not recognised.
1641 EFI_NO_MEDIA - The device has no media.
1643 EFI_DEVICE_ERROR - The device reported an error.
1645 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1647 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1649 EFI_ACCESS_DENIED - The file was opened read-only.
1651 EFI_VOLUME_FULL - The volume is full.
1653 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
1656 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1657 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1659 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1660 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1661 EFI_FILE_INFO
*OldFileInfo
;
1662 EFI_FILE_INFO
*NewFileInfo
;
1666 struct stat OldAttr
;
1670 BOOLEAN AttrChangeFlag
;
1671 BOOLEAN NameChangeFlag
;
1672 BOOLEAN SizeChangeFlag
;
1673 BOOLEAN TimeChangeFlag
;
1674 struct tm NewLastAccessSystemTime
;
1675 struct tm NewLastWriteSystemTime
;
1676 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1677 CHAR8
*AsciiFilePtr
;
1678 CHAR16
*UnicodeFilePtr
;
1682 // Check for invalid parameters.
1684 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
1685 return EFI_INVALID_PARAMETER
;
1689 // Initialise locals.
1691 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1692 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1694 Status
= EFI_UNSUPPORTED
;
1695 OldFileInfo
= NewFileInfo
= NULL
;
1696 OldFileName
= NewFileName
= NULL
;
1697 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1700 // Set file system information.
1702 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1703 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1704 return EFI_BAD_BUFFER_SIZE
;
1707 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1709 gBS
->FreePool (PrivateRoot
->VolumeLabel
);
1711 PrivateRoot
->VolumeLabel
= NULL
;
1712 Status
= gBS
->AllocatePool (
1713 EfiBootServicesData
,
1714 StrSize (NewFileSystemInfo
->VolumeLabel
),
1715 (VOID
**)&PrivateRoot
->VolumeLabel
1718 if (EFI_ERROR (Status
)) {
1722 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
1728 // Set volume label information.
1730 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1731 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1732 return EFI_BAD_BUFFER_SIZE
;
1735 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
1740 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1741 return EFI_UNSUPPORTED
;
1744 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1745 return EFI_BAD_BUFFER_SIZE
;
1749 // Set file/directory information.
1753 // Check for invalid set file information parameters.
1755 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
1757 if (NewFileInfo
->Size
<= sizeof (EFI_FILE_INFO
) ||
1758 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1759 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1761 return EFI_INVALID_PARAMETER
;
1765 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1766 // that would have an additional parameter that would be the size
1767 // of the string array just in case there are no NULL characters in
1768 // the string array.
1771 // Get current file information so we can determine what kind
1772 // of change request this is.
1775 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, NULL
);
1777 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1778 Status
= EFI_DEVICE_ERROR
;
1782 Status
= gBS
->AllocatePool (EfiBootServicesData
, OldInfoSize
,
1783 (VOID
**)&OldFileInfo
);
1785 if (EFI_ERROR (Status
)) {
1789 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, OldFileInfo
);
1791 if (EFI_ERROR (Status
)) {
1795 Status
= gBS
->AllocatePool (
1796 EfiBootServicesData
,
1797 AsciiStrSize (PrivateFile
->FileName
),
1798 (VOID
**)&OldFileName
1801 if (EFI_ERROR (Status
)) {
1805 AsciiStrCpy (OldFileName
, PrivateFile
->FileName
);
1808 // Make full pathname from new filename and rootpath.
1810 if (NewFileInfo
->FileName
[0] == '\\') {
1811 Status
= gBS
->AllocatePool (
1812 EfiBootServicesData
,
1813 AsciiStrLen (PrivateRoot
->FilePath
) + 1 + StrLen (NewFileInfo
->FileName
) + 1,
1814 (VOID
**)&NewFileName
1817 if (EFI_ERROR (Status
)) {
1821 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1822 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1823 UnicodeFilePtr
= NewFileInfo
->FileName
+ 1;
1824 *AsciiFilePtr
++ ='/';
1826 Status
= gBS
->AllocatePool (
1827 EfiBootServicesData
,
1828 AsciiStrLen (PrivateFile
->FileName
) + 1 + StrLen (NewFileInfo
->FileName
) + 1,
1829 (VOID
**)&NewFileName
1832 if (EFI_ERROR (Status
)) {
1836 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1837 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1838 while (AsciiFilePtr
> NewFileName
&& AsciiFilePtr
[-1] != '/') {
1841 UnicodeFilePtr
= NewFileInfo
->FileName
;
1843 // Convert to ascii.
1844 while (*UnicodeFilePtr
) {
1845 *AsciiFilePtr
++ = *UnicodeFilePtr
++;
1851 // Is there an attribute change request?
1853 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1854 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1855 Status
= EFI_INVALID_PARAMETER
;
1859 AttrChangeFlag
= TRUE
;
1863 // Is there a name change request?
1864 // bugbug: - Need EfiStrCaseCmp()
1866 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1867 NameChangeFlag
= TRUE
;
1871 // Is there a size change request?
1873 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1874 SizeChangeFlag
= TRUE
;
1878 // Is there a time stamp change request?
1880 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1881 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1883 TimeChangeFlag
= TRUE
;
1884 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1885 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1887 TimeChangeFlag
= TRUE
;
1888 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1889 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1891 TimeChangeFlag
= TRUE
;
1895 // All done if there are no change requests being made.
1897 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1898 Status
= EFI_SUCCESS
;
1903 // Set file or directory information.
1905 if (PrivateFile
->UnixThunk
->Stat (OldFileName
, &OldAttr
) != 0) {
1906 Status
= EFI_DEVICE_ERROR
;
1913 if (NameChangeFlag
) {
1915 // Close the handles first
1917 if (PrivateFile
->IsOpenedByRead
) {
1918 Status
= EFI_ACCESS_DENIED
;
1922 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
1925 if (*CharPointer
!= 0) {
1926 Status
= EFI_ACCESS_DENIED
;
1930 UnixStatus
= PrivateFile
->UnixThunk
->Rename (OldFileName
, NewFileName
);
1932 if (UnixStatus
== 0) {
1936 gBS
->FreePool (PrivateFile
->FileName
);
1938 Status
= gBS
->AllocatePool (
1939 EfiBootServicesData
,
1940 AsciiStrSize (NewFileName
),
1941 (VOID
**)&PrivateFile
->FileName
1944 if (EFI_ERROR (Status
)) {
1948 AsciiStrCpy (PrivateFile
->FileName
, NewFileName
);
1950 Status
= EFI_DEVICE_ERROR
;
1958 if (SizeChangeFlag
) {
1959 if (PrivateFile
->IsDirectoryPath
) {
1960 Status
= EFI_UNSUPPORTED
;
1964 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
1965 Status
= EFI_ACCESS_DENIED
;
1969 if (PrivateFile
->UnixThunk
->FTruncate (PrivateFile
->fd
, NewFileInfo
->FileSize
) != 0) {
1970 Status
= EFI_DEVICE_ERROR
;
1979 if (TimeChangeFlag
) {
1980 struct utimbuf utime
;
1982 NewLastAccessSystemTime
.tm_year
= NewFileInfo
->LastAccessTime
.Year
;
1983 NewLastAccessSystemTime
.tm_mon
= NewFileInfo
->LastAccessTime
.Month
;
1984 NewLastAccessSystemTime
.tm_mday
= NewFileInfo
->LastAccessTime
.Day
;
1985 NewLastAccessSystemTime
.tm_hour
= NewFileInfo
->LastAccessTime
.Hour
;
1986 NewLastAccessSystemTime
.tm_min
= NewFileInfo
->LastAccessTime
.Minute
;
1987 NewLastAccessSystemTime
.tm_sec
= NewFileInfo
->LastAccessTime
.Second
;
1988 NewLastAccessSystemTime
.tm_isdst
= 0;
1990 utime
.actime
= PrivateFile
->UnixThunk
->MkTime (&NewLastAccessSystemTime
);
1992 NewLastWriteSystemTime
.tm_year
= NewFileInfo
->ModificationTime
.Year
;
1993 NewLastWriteSystemTime
.tm_mon
= NewFileInfo
->ModificationTime
.Month
;
1994 NewLastWriteSystemTime
.tm_mday
= NewFileInfo
->ModificationTime
.Day
;
1995 NewLastWriteSystemTime
.tm_hour
= NewFileInfo
->ModificationTime
.Hour
;
1996 NewLastWriteSystemTime
.tm_min
= NewFileInfo
->ModificationTime
.Minute
;
1997 NewLastWriteSystemTime
.tm_sec
= NewFileInfo
->ModificationTime
.Second
;
1998 NewLastWriteSystemTime
.tm_isdst
= 0;
2000 utime
.modtime
= PrivateFile
->UnixThunk
->MkTime (&NewLastWriteSystemTime
);
2002 if (utime
.actime
== (time_t)-1 || utime
.modtime
== (time_t)-1) {
2006 if (PrivateFile
->UnixThunk
->UTime (PrivateFile
->FileName
, &utime
) == -1) {
2012 // No matter about AttrChangeFlag, Attribute must be set.
2013 // Because operation before may cause attribute change.
2015 NewAttr
= OldAttr
.st_mode
;
2017 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2018 NewAttr
&= ~(S_IRUSR
| S_IRGRP
| S_IROTH
);
2023 UnixStatus
= PrivateFile
->UnixThunk
->Chmod (NewFileName
, NewAttr
);
2025 if (UnixStatus
!= 0) {
2026 Status
= EFI_DEVICE_ERROR
;
2030 if (OldFileInfo
!= NULL
) {
2031 gBS
->FreePool (OldFileInfo
);
2034 if (OldFileName
!= NULL
) {
2035 gBS
->FreePool (OldFileName
);
2038 if (NewFileName
!= NULL
) {
2039 gBS
->FreePool (NewFileName
);
2047 UnixSimpleFileSystemFlush (
2052 Routine Description:
2054 Flush all modified data to the media.
2058 This - Pointer to an opened file handle.
2062 EFI_SUCCESS - The data has been flushed.
2064 EFI_NO_MEDIA - The device has no media.
2066 EFI_DEVICE_ERROR - The device reported an error.
2068 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2070 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2072 EFI_ACCESS_DENIED - The file was opened read-only.
2074 EFI_VOLUME_FULL - The volume is full.
2077 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2079 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
2082 return EFI_INVALID_PARAMETER
;
2085 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2088 if (PrivateFile
->IsDirectoryPath
) {
2092 if (PrivateFile
->IsOpenedByRead
) {
2093 return EFI_ACCESS_DENIED
;
2096 if (PrivateFile
->fd
< 0) {
2097 return EFI_DEVICE_ERROR
;
2100 return PrivateFile
->UnixThunk
->FSync (PrivateFile
->fd
) == 0 ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2103 // bugbug: - Use Unix error reporting.