3 Copyright (c) 2006 - 2007, 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
;
639 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
;
675 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
677 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
678 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
679 NewPrivateFile
= NULL
;
682 // BUGBUG: assume an open of root
683 // if current location, return current data
685 if (StrCmp (FileName
, L
"\\") == 0
686 || (StrCmp (FileName
, L
".") == 0 && PrivateFile
->IsRootDirectory
)) {
688 // BUGBUG: assume an open root
691 Status
= UnixSimpleFileSystemOpenVolume (PrivateFile
->SimpleFileSystem
, &Root
);
692 NewPrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root
);
696 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
698 FileName
[StrLen (FileName
) - 1] = 0;
702 // Attempt to open the file
704 Status
= gBS
->AllocatePool (
706 sizeof (UNIX_EFI_FILE_PRIVATE
),
707 (VOID
**)&NewPrivateFile
710 if (EFI_ERROR (Status
)) {
714 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (UNIX_EFI_FILE_PRIVATE
));
716 NewPrivateFile
->FileName
= NULL
;
717 Status
= gBS
->AllocatePool (
719 AsciiStrSize (PrivateFile
->FileName
) + 1 + StrLen (FileName
) + 1,
720 (VOID
**)&NewPrivateFile
->FileName
723 if (EFI_ERROR (Status
)) {
727 if (*FileName
== L
'\\') {
728 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
732 AsciiStrCpy (NewPrivateFile
->FileName
, PrivateFile
->FileName
);
735 Dst
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
);
736 GuardPointer
= NewPrivateFile
->FileName
+ AsciiStrLen(PrivateRoot
->FilePath
);
738 // Convert unicode to ascii and '\' to '/'
750 // Get rid of . and .., except leading . or ..
754 // GuardPointer protect simplefilesystem root path not be destroyed
759 while (!LoopFinish
) {
763 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
764 if (*ParseFileName
== '.' &&
765 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == '/') &&
766 *(ParseFileName
- 1) == '/'
772 CutPrefix (ParseFileName
- 1, 2);
777 if (*ParseFileName
== '.' &&
778 *(ParseFileName
+ 1) == '.' &&
779 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == '/') &&
780 *(ParseFileName
- 1) == '/'
786 while (ParseFileName
!= GuardPointer
) {
789 if (*ParseFileName
== '/') {
795 // cut /.. and its left directory
797 CutPrefix (ParseFileName
, Count
);
804 if (AsciiStrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
805 NewPrivateFile
->IsRootDirectory
= TRUE
;
806 gBS
->FreePool (NewPrivateFile
->FileName
);
807 gBS
->FreePool (NewPrivateFile
);
811 RealFileName
= NewPrivateFile
->FileName
+ AsciiStrLen(NewPrivateFile
->FileName
) - 1;
812 while (RealFileName
> NewPrivateFile
->FileName
&& *RealFileName
!= '/')
815 TempChar
= *(RealFileName
- 1);
816 *(RealFileName
- 1) = 0;
818 *(RealFileName
- 1) = TempChar
;
823 // Test whether file or directory
825 NewPrivateFile
->IsRootDirectory
= FALSE
;
826 NewPrivateFile
->fd
= -1;
827 NewPrivateFile
->Dir
= NULL
;
828 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
829 if (Attributes
& EFI_FILE_DIRECTORY
) {
830 NewPrivateFile
->IsDirectoryPath
= TRUE
;
832 NewPrivateFile
->IsDirectoryPath
= FALSE
;
836 int res
= NewPrivateFile
->UnixThunk
->Stat (NewPrivateFile
->FileName
, &finfo
);
837 if (res
== 0 && S_ISDIR(finfo
.st_mode
))
838 NewPrivateFile
->IsDirectoryPath
= TRUE
;
840 NewPrivateFile
->IsDirectoryPath
= FALSE
;
843 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
844 NewPrivateFile
->IsOpenedByRead
= FALSE
;
846 NewPrivateFile
->IsOpenedByRead
= TRUE
;
849 Status
= EFI_SUCCESS
;
852 // deal with directory
854 if (NewPrivateFile
->IsDirectoryPath
) {
856 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
858 // Create a directory
860 if (NewPrivateFile
->UnixThunk
->MkDir (NewPrivateFile
->FileName
, 0777) != 0) {
863 LastError
= PrivateFile
->UnixThunk
->GetErrno ();
864 if (LastError
!= EEXIST
) {
865 //gBS->FreePool (TempFileName);
866 Status
= EFI_ACCESS_DENIED
;
872 NewPrivateFile
->Dir
= NewPrivateFile
->UnixThunk
->OpenDir
873 (NewPrivateFile
->FileName
);
875 if (NewPrivateFile
->Dir
== NULL
) {
876 if (PrivateFile
->UnixThunk
->GetErrno () == EACCES
) {
877 Status
= EFI_ACCESS_DENIED
;
879 Status
= EFI_NOT_FOUND
;
889 NewPrivateFile
->fd
= NewPrivateFile
->UnixThunk
->Open
890 (NewPrivateFile
->FileName
,
891 ((OpenMode
& EFI_FILE_MODE_CREATE
) ? O_CREAT
: 0)
892 | (NewPrivateFile
->IsOpenedByRead
? O_RDONLY
: O_RDWR
),
894 if (NewPrivateFile
->fd
< 0) {
895 if (PrivateFile
->UnixThunk
->GetErrno () == ENOENT
) {
896 Status
= EFI_NOT_FOUND
;
898 Status
= EFI_ACCESS_DENIED
;
903 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
910 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
912 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
913 Status
= EFI_DEVICE_ERROR
;
917 Status
= gBS
->AllocatePool (
923 if (EFI_ERROR (Status
)) {
927 Status
= UnixSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
929 if (EFI_ERROR (Status
)) {
933 Info
->Attribute
= Attributes
;
935 UnixSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
940 FileName
[StrLen (FileName
) + 1] = 0;
941 FileName
[StrLen (FileName
)] = L
'\\';
944 if (EFI_ERROR (Status
)) {
945 if (NewPrivateFile
) {
946 if (NewPrivateFile
->FileName
) {
947 gBS
->FreePool (NewPrivateFile
->FileName
);
950 gBS
->FreePool (NewPrivateFile
);
953 *NewHandle
= &NewPrivateFile
->EfiFile
;
956 gBS
->RestoreTPL (OldTpl
);
963 UnixSimpleFileSystemClose (
970 Close the specified file handle.
974 This - Pointer to a returned opened file handle.
978 EFI_SUCCESS - The file handle has been closed.
981 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
983 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
987 return EFI_INVALID_PARAMETER
;
990 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
992 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
994 if (PrivateFile
->fd
>= 0) {
995 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
997 if (PrivateFile
->Dir
!= NULL
) {
998 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
1001 PrivateFile
->fd
= -1;
1002 PrivateFile
->Dir
= NULL
;
1004 if (PrivateFile
->FileName
) {
1005 gBS
->FreePool (PrivateFile
->FileName
);
1008 gBS
->FreePool (PrivateFile
);
1010 gBS
->RestoreTPL (OldTpl
);
1017 UnixSimpleFileSystemDelete (
1022 Routine Description:
1024 Close and delete a file.
1028 This - Pointer to a returned opened file handle.
1032 EFI_SUCCESS - The file handle was closed and deleted.
1034 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1037 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1040 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1044 return EFI_INVALID_PARAMETER
;
1047 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1049 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1051 Status
= EFI_WARN_DELETE_FAILURE
;
1053 if (PrivateFile
->IsDirectoryPath
) {
1054 if (PrivateFile
->Dir
!= NULL
) {
1055 PrivateFile
->UnixThunk
->CloseDir (PrivateFile
->Dir
);
1056 PrivateFile
->Dir
= NULL
;
1059 if (PrivateFile
->UnixThunk
->RmDir (PrivateFile
->FileName
) == 0) {
1060 Status
= EFI_SUCCESS
;
1063 PrivateFile
->UnixThunk
->Close (PrivateFile
->fd
);
1064 PrivateFile
->fd
= -1;
1066 if (!PrivateFile
->IsOpenedByRead
) {
1067 if (!PrivateFile
->UnixThunk
->UnLink (PrivateFile
->FileName
)) {
1068 Status
= EFI_SUCCESS
;
1073 gBS
->FreePool (PrivateFile
->FileName
);
1074 gBS
->FreePool (PrivateFile
);
1081 UnixSystemTimeToEfiTime (
1082 EFI_UNIX_THUNK_PROTOCOL
*UnixThunk
,
1083 IN
time_t SystemTime
,
1088 Routine Description:
1090 TODO: Add function description
1094 SystemTime - TODO: add argument description
1095 TimeZone - TODO: add argument description
1096 Time - TODO: add argument description
1100 TODO: add return values
1105 tm
= UnixThunk
->GmTime (&SystemTime
);
1106 Time
->Year
= tm
->tm_year
;
1107 Time
->Month
= tm
->tm_mon
;
1108 Time
->Day
= tm
->tm_mday
;
1109 Time
->Hour
= tm
->tm_hour
;
1110 Time
->Minute
= tm
->tm_min
;
1111 Time
->Second
= tm
->tm_sec
;
1112 Time
->Nanosecond
= 0;
1114 Time
->TimeZone
= UnixThunk
->GetTimeZone ();
1116 if (UnixThunk
->GetDayLight ()) {
1117 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1123 UnixSimpleFileSystemFileInfo (
1124 UNIX_EFI_FILE_PRIVATE
*PrivateFile
,
1126 IN OUT UINTN
*BufferSize
,
1131 Routine Description:
1133 TODO: Add function description
1137 PrivateFile - TODO: add argument description
1138 BufferSize - TODO: add argument description
1139 Buffer - TODO: add argument description
1143 TODO: add return values
1151 EFI_FILE_INFO
*Info
;
1152 CHAR8
*RealFileName
;
1154 CHAR16
*BufferFileName
;
1157 if (FileName
!= NULL
) {
1158 RealFileName
= FileName
;
1160 else if (PrivateFile
->IsRootDirectory
) {
1163 RealFileName
= PrivateFile
->FileName
;
1166 TempPointer
= RealFileName
;
1167 while (*TempPointer
) {
1168 if (*TempPointer
== '/') {
1169 RealFileName
= TempPointer
+ 1;
1175 Size
= SIZE_OF_EFI_FILE_INFO
;
1176 NameSize
= AsciiStrSize (RealFileName
) * 2;
1177 ResultSize
= Size
+ NameSize
;
1179 if (*BufferSize
< ResultSize
) {
1180 *BufferSize
= ResultSize
;
1181 return EFI_BUFFER_TOO_SMALL
;
1183 if (PrivateFile
->UnixThunk
->Stat (
1184 FileName
== NULL
? PrivateFile
->FileName
: FileName
,
1186 return EFI_DEVICE_ERROR
;
1188 Status
= EFI_SUCCESS
;
1191 ZeroMem (Info
, ResultSize
);
1193 Info
->Size
= ResultSize
;
1194 Info
->FileSize
= buf
.st_size
;
1195 Info
->PhysicalSize
= MultU64x32 (buf
.st_blocks
, buf
.st_blksize
);
1197 UnixSystemTimeToEfiTime (PrivateFile
->UnixThunk
, buf
.st_ctime
, &Info
->CreateTime
);
1198 UnixSystemTimeToEfiTime (PrivateFile
->UnixThunk
, buf
.st_atime
, &Info
->LastAccessTime
);
1199 UnixSystemTimeToEfiTime (PrivateFile
->UnixThunk
, buf
.st_mtime
, &Info
->ModificationTime
);
1201 if (!(buf
.st_mode
& S_IWUSR
)) {
1202 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1205 if (S_ISDIR(buf
.st_mode
)) {
1206 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1210 BufferFileName
= (CHAR16
*)((CHAR8
*) Buffer
+ Size
);
1211 while (*RealFileName
)
1212 *BufferFileName
++ = *RealFileName
++;
1213 *BufferFileName
= 0;
1215 *BufferSize
= ResultSize
;
1221 UnixSimpleFileSystemRead (
1223 IN OUT UINTN
*BufferSize
,
1228 Routine Description:
1230 Read data from a file.
1234 This - Pointer to a returned open file handle.
1236 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1238 Buffer - Pointer to the first byte of the read Buffer.
1242 EFI_SUCCESS - The data was read.
1244 EFI_NO_MEDIA - The device has no media.
1246 EFI_DEVICE_ERROR - The device reported an error.
1248 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1250 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1251 *BufferSize has been updated with the size needed to complete the request.
1254 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1256 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1262 CHAR8
*FullFileName
;
1265 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1266 return EFI_INVALID_PARAMETER
;
1269 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1271 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1273 if (!PrivateFile
->IsDirectoryPath
) {
1275 if (PrivateFile
->fd
< 0) {
1276 return EFI_DEVICE_ERROR
;
1279 Res
= PrivateFile
->UnixThunk
->Read (
1284 return EFI_DEVICE_ERROR
;
1290 // Read on a directory.
1292 if (PrivateFile
->Dir
== NULL
) {
1293 return EFI_DEVICE_ERROR
;
1296 if (PrivateFile
->Dirent
== NULL
) {
1297 PrivateFile
->Dirent
= PrivateFile
->UnixThunk
->ReadDir (PrivateFile
->Dir
);
1298 if (PrivateFile
->Dirent
== NULL
) {
1304 Size
= SIZE_OF_EFI_FILE_INFO
;
1305 NameSize
= AsciiStrLen (PrivateFile
->Dirent
->d_name
) + 1;
1306 ResultSize
= Size
+ 2 * NameSize
;
1308 if (*BufferSize
< ResultSize
) {
1309 *BufferSize
= ResultSize
;
1310 return EFI_BUFFER_TOO_SMALL
;
1312 Status
= EFI_SUCCESS
;
1314 *BufferSize
= ResultSize
;
1316 Status
= gBS
->AllocatePool (
1317 EfiBootServicesData
,
1318 AsciiStrLen(PrivateFile
->FileName
) + 1 + NameSize
,
1319 (VOID
**)&FullFileName
1322 if (EFI_ERROR (Status
)) {
1326 AsciiStrCpy(FullFileName
, PrivateFile
->FileName
);
1327 AsciiStrCat(FullFileName
, "/");
1328 AsciiStrCat(FullFileName
, PrivateFile
->Dirent
->d_name
);
1329 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
,
1333 gBS
->FreePool (FullFileName
);
1335 PrivateFile
->Dirent
= NULL
;
1342 UnixSimpleFileSystemWrite (
1344 IN OUT UINTN
*BufferSize
,
1349 Routine Description:
1351 Write data to a file.
1355 This - Pointer to an opened file handle.
1357 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1358 of data written to the file.
1360 Buffer - Pointer to the first by of data in the buffer to write to the file.
1364 EFI_SUCCESS - The data was written to the file.
1366 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1368 EFI_NO_MEDIA - The device has no media.
1370 EFI_DEVICE_ERROR - The device reported an error.
1372 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1374 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1376 EFI_ACCESS_DENIED - The file was opened read-only.
1378 EFI_VOLUME_FULL - The volume is full.
1381 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1383 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1388 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1389 return EFI_INVALID_PARAMETER
;
1392 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1394 if (PrivateFile
->fd
< 0) {
1395 return EFI_DEVICE_ERROR
;
1398 if (PrivateFile
->IsDirectoryPath
) {
1399 return EFI_UNSUPPORTED
;
1402 if (PrivateFile
->IsOpenedByRead
) {
1403 return EFI_ACCESS_DENIED
;
1406 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1408 Res
= PrivateFile
->UnixThunk
->Write (
1412 if (Res
== (UINTN
)-1) {
1413 Status
= EFI_DEVICE_ERROR
;
1417 Status
= EFI_SUCCESS
;
1420 gBS
->RestoreTPL (OldTpl
);
1424 // bugbug: need to access unix error reporting
1430 UnixSimpleFileSystemSetPosition (
1436 Routine Description:
1438 Set a file's current position.
1442 This - Pointer to an opened file handle.
1444 Position - The byte position from the start of the file to set.
1448 EFI_SUCCESS - The file position has been changed.
1450 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1453 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1456 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1461 return EFI_INVALID_PARAMETER
;
1464 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1466 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1468 if (PrivateFile
->IsDirectoryPath
) {
1469 if (Position
!= 0) {
1470 Status
= EFI_UNSUPPORTED
;
1474 if (PrivateFile
->Dir
== NULL
) {
1475 Status
= EFI_DEVICE_ERROR
;
1478 PrivateFile
->UnixThunk
->RewindDir (PrivateFile
->Dir
);
1479 Status
= EFI_SUCCESS
;
1482 if (Position
== (UINT64
) -1) {
1483 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_END
);
1485 Pos
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, Position
, SEEK_SET
);
1487 Status
= (Pos
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1491 gBS
->RestoreTPL (OldTpl
);
1497 UnixSimpleFileSystemGetPosition (
1499 OUT UINT64
*Position
1503 Routine Description:
1505 Get a file's current position.
1509 This - Pointer to an opened file handle.
1511 Position - Pointer to storage for the current position.
1515 EFI_SUCCESS - The file position has been reported.
1517 EFI_UNSUPPORTED - Not valid for directories.
1520 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1523 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1526 if (This
== NULL
|| Position
== NULL
) {
1527 return EFI_INVALID_PARAMETER
;
1530 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1532 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1534 if (PrivateFile
->IsDirectoryPath
) {
1535 Status
= EFI_UNSUPPORTED
;
1537 *Position
= PrivateFile
->UnixThunk
->Lseek (PrivateFile
->fd
, 0, SEEK_CUR
);
1538 Status
= (*Position
== (UINT64
) -1) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1541 gBS
->RestoreTPL (OldTpl
);
1547 UnixSimpleFileSystemGetInfo (
1549 IN EFI_GUID
*InformationType
,
1550 IN OUT UINTN
*BufferSize
,
1555 Routine Description:
1557 Return information about a file or volume.
1561 This - Pointer to an opened file handle.
1563 InformationType - GUID describing the type of information to be returned.
1565 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1568 Buffer - Pointer to the first byte of the information buffer.
1572 EFI_SUCCESS - The requested information has been written into the buffer.
1574 EFI_UNSUPPORTED - The InformationType is not known.
1576 EFI_NO_MEDIA - The device has no media.
1578 EFI_DEVICE_ERROR - The device reported an error.
1580 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1582 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
1583 been updated with the size needed to complete the requested operation.
1586 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1589 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1590 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1592 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1596 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1597 return EFI_INVALID_PARAMETER
;
1600 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1602 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1603 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1605 Status
= EFI_UNSUPPORTED
;
1607 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1608 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, BufferSize
, Buffer
);
1609 } else if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1610 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1611 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1612 Status
= EFI_BUFFER_TOO_SMALL
;
1616 UnixStatus
= PrivateFile
->UnixThunk
->StatFs (PrivateFile
->FileName
, &buf
);
1617 if (UnixStatus
< 0) {
1618 Status
= EFI_DEVICE_ERROR
;
1622 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1623 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1624 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
1629 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (buf
.f_blocks
, buf
.f_bsize
);
1630 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (buf
.f_bavail
, buf
.f_bsize
);
1631 FileSystemInfoBuffer
->BlockSize
= buf
.f_bsize
;
1634 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
1635 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1636 Status
= EFI_SUCCESS
;
1637 } else if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1638 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1639 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1640 Status
= EFI_BUFFER_TOO_SMALL
;
1644 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
1645 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1646 Status
= EFI_SUCCESS
;
1650 gBS
->RestoreTPL (OldTpl
);
1656 UnixSimpleFileSystemSetInfo (
1658 IN EFI_GUID
*InformationType
,
1659 IN UINTN BufferSize
,
1664 Routine Description:
1666 Set information about a file or volume.
1670 This - Pointer to an opened file handle.
1672 InformationType - GUID identifying the type of information to set.
1674 BufferSize - Number of bytes of data in the information buffer.
1676 Buffer - Pointer to the first byte of data in the information buffer.
1680 EFI_SUCCESS - The file or volume information has been updated.
1682 EFI_UNSUPPORTED - The information identifier is not recognised.
1684 EFI_NO_MEDIA - The device has no media.
1686 EFI_DEVICE_ERROR - The device reported an error.
1688 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1690 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1692 EFI_ACCESS_DENIED - The file was opened read-only.
1694 EFI_VOLUME_FULL - The volume is full.
1696 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
1699 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1700 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1702 UNIX_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1703 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
1704 EFI_FILE_INFO
*OldFileInfo
;
1705 EFI_FILE_INFO
*NewFileInfo
;
1710 struct stat OldAttr
;
1714 BOOLEAN AttrChangeFlag
;
1715 BOOLEAN NameChangeFlag
;
1716 BOOLEAN SizeChangeFlag
;
1717 BOOLEAN TimeChangeFlag
;
1718 struct tm NewLastAccessSystemTime
;
1719 struct tm NewLastWriteSystemTime
;
1720 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1721 CHAR8
*AsciiFilePtr
;
1722 CHAR16
*UnicodeFilePtr
;
1726 // Check for invalid parameters.
1728 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
1729 return EFI_INVALID_PARAMETER
;
1732 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
1735 // Initialise locals.
1737 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1738 PrivateRoot
= UNIX_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1740 Status
= EFI_UNSUPPORTED
;
1741 OldFileInfo
= NewFileInfo
= NULL
;
1742 OldFileName
= NewFileName
= NULL
;
1743 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1746 // Set file system information.
1748 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1749 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1750 Status
= EFI_BAD_BUFFER_SIZE
;
1754 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
1756 gBS
->FreePool (PrivateRoot
->VolumeLabel
);
1758 PrivateRoot
->VolumeLabel
= NULL
;
1759 Status
= gBS
->AllocatePool (
1760 EfiBootServicesData
,
1761 StrSize (NewFileSystemInfo
->VolumeLabel
),
1762 (VOID
**)&PrivateRoot
->VolumeLabel
1765 if (EFI_ERROR (Status
)) {
1769 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
1771 Status
= EFI_SUCCESS
;
1776 // Set volume label information.
1778 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1779 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1780 Status
= EFI_BAD_BUFFER_SIZE
;
1784 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
1786 Status
= EFI_SUCCESS
;
1790 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1791 Status
= EFI_UNSUPPORTED
;
1795 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1796 Status
= EFI_BAD_BUFFER_SIZE
;
1801 // Set file/directory information.
1805 // Check for invalid set file information parameters.
1807 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
1809 if (NewFileInfo
->Size
<= sizeof (EFI_FILE_INFO
) ||
1810 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1811 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1813 Status
= EFI_INVALID_PARAMETER
;
1818 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1819 // that would have an additional parameter that would be the size
1820 // of the string array just in case there are no NULL characters in
1821 // the string array.
1824 // Get current file information so we can determine what kind
1825 // of change request this is.
1828 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, NULL
);
1830 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1831 Status
= EFI_DEVICE_ERROR
;
1835 Status
= gBS
->AllocatePool (EfiBootServicesData
, OldInfoSize
,
1836 (VOID
**)&OldFileInfo
);
1838 if (EFI_ERROR (Status
)) {
1842 Status
= UnixSimpleFileSystemFileInfo (PrivateFile
, NULL
, &OldInfoSize
, OldFileInfo
);
1844 if (EFI_ERROR (Status
)) {
1848 Status
= gBS
->AllocatePool (
1849 EfiBootServicesData
,
1850 AsciiStrSize (PrivateFile
->FileName
),
1851 (VOID
**)&OldFileName
1854 if (EFI_ERROR (Status
)) {
1858 AsciiStrCpy (OldFileName
, PrivateFile
->FileName
);
1861 // Make full pathname from new filename and rootpath.
1863 if (NewFileInfo
->FileName
[0] == '\\') {
1864 Status
= gBS
->AllocatePool (
1865 EfiBootServicesData
,
1866 AsciiStrLen (PrivateRoot
->FilePath
) + 1 + StrLen (NewFileInfo
->FileName
) + 1,
1867 (VOID
**)&NewFileName
1870 if (EFI_ERROR (Status
)) {
1874 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1875 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1876 UnicodeFilePtr
= NewFileInfo
->FileName
+ 1;
1877 *AsciiFilePtr
++ ='/';
1879 Status
= gBS
->AllocatePool (
1880 EfiBootServicesData
,
1881 AsciiStrLen (PrivateFile
->FileName
) + 1 + StrLen (NewFileInfo
->FileName
) + 1,
1882 (VOID
**)&NewFileName
1885 if (EFI_ERROR (Status
)) {
1889 AsciiStrCpy (NewFileName
, PrivateRoot
->FilePath
);
1890 AsciiFilePtr
= NewFileName
+ AsciiStrLen(NewFileName
);
1891 while (AsciiFilePtr
> NewFileName
&& AsciiFilePtr
[-1] != '/') {
1894 UnicodeFilePtr
= NewFileInfo
->FileName
;
1896 // Convert to ascii.
1897 while (*UnicodeFilePtr
) {
1898 *AsciiFilePtr
++ = *UnicodeFilePtr
++;
1904 // Is there an attribute change request?
1906 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1907 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1908 Status
= EFI_INVALID_PARAMETER
;
1912 AttrChangeFlag
= TRUE
;
1916 // Is there a name change request?
1917 // bugbug: - Need EfiStrCaseCmp()
1919 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1920 NameChangeFlag
= TRUE
;
1924 // Is there a size change request?
1926 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1927 SizeChangeFlag
= TRUE
;
1931 // Is there a time stamp change request?
1933 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1934 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1936 TimeChangeFlag
= TRUE
;
1937 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1938 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1940 TimeChangeFlag
= TRUE
;
1941 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1942 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1944 TimeChangeFlag
= TRUE
;
1948 // All done if there are no change requests being made.
1950 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1951 Status
= EFI_SUCCESS
;
1956 // Set file or directory information.
1958 if (PrivateFile
->UnixThunk
->Stat (OldFileName
, &OldAttr
) != 0) {
1959 Status
= EFI_DEVICE_ERROR
;
1966 if (NameChangeFlag
) {
1968 // Close the handles first
1970 if (PrivateFile
->IsOpenedByRead
) {
1971 Status
= EFI_ACCESS_DENIED
;
1975 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
1978 if (*CharPointer
!= 0) {
1979 Status
= EFI_ACCESS_DENIED
;
1983 UnixStatus
= PrivateFile
->UnixThunk
->Rename (OldFileName
, NewFileName
);
1985 if (UnixStatus
== 0) {
1989 gBS
->FreePool (PrivateFile
->FileName
);
1991 Status
= gBS
->AllocatePool (
1992 EfiBootServicesData
,
1993 AsciiStrSize (NewFileName
),
1994 (VOID
**)&PrivateFile
->FileName
1997 if (EFI_ERROR (Status
)) {
2001 AsciiStrCpy (PrivateFile
->FileName
, NewFileName
);
2003 Status
= EFI_DEVICE_ERROR
;
2011 if (SizeChangeFlag
) {
2012 if (PrivateFile
->IsDirectoryPath
) {
2013 Status
= EFI_UNSUPPORTED
;
2017 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2018 Status
= EFI_ACCESS_DENIED
;
2022 if (PrivateFile
->UnixThunk
->FTruncate (PrivateFile
->fd
, NewFileInfo
->FileSize
) != 0) {
2023 Status
= EFI_DEVICE_ERROR
;
2032 if (TimeChangeFlag
) {
2033 struct utimbuf utime
;
2035 NewLastAccessSystemTime
.tm_year
= NewFileInfo
->LastAccessTime
.Year
;
2036 NewLastAccessSystemTime
.tm_mon
= NewFileInfo
->LastAccessTime
.Month
;
2037 NewLastAccessSystemTime
.tm_mday
= NewFileInfo
->LastAccessTime
.Day
;
2038 NewLastAccessSystemTime
.tm_hour
= NewFileInfo
->LastAccessTime
.Hour
;
2039 NewLastAccessSystemTime
.tm_min
= NewFileInfo
->LastAccessTime
.Minute
;
2040 NewLastAccessSystemTime
.tm_sec
= NewFileInfo
->LastAccessTime
.Second
;
2041 NewLastAccessSystemTime
.tm_isdst
= 0;
2043 utime
.actime
= PrivateFile
->UnixThunk
->MkTime (&NewLastAccessSystemTime
);
2045 NewLastWriteSystemTime
.tm_year
= NewFileInfo
->ModificationTime
.Year
;
2046 NewLastWriteSystemTime
.tm_mon
= NewFileInfo
->ModificationTime
.Month
;
2047 NewLastWriteSystemTime
.tm_mday
= NewFileInfo
->ModificationTime
.Day
;
2048 NewLastWriteSystemTime
.tm_hour
= NewFileInfo
->ModificationTime
.Hour
;
2049 NewLastWriteSystemTime
.tm_min
= NewFileInfo
->ModificationTime
.Minute
;
2050 NewLastWriteSystemTime
.tm_sec
= NewFileInfo
->ModificationTime
.Second
;
2051 NewLastWriteSystemTime
.tm_isdst
= 0;
2053 utime
.modtime
= PrivateFile
->UnixThunk
->MkTime (&NewLastWriteSystemTime
);
2055 if (utime
.actime
== (time_t)-1 || utime
.modtime
== (time_t)-1) {
2059 if (PrivateFile
->UnixThunk
->UTime (PrivateFile
->FileName
, &utime
) == -1) {
2065 // No matter about AttrChangeFlag, Attribute must be set.
2066 // Because operation before may cause attribute change.
2068 NewAttr
= OldAttr
.st_mode
;
2070 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2071 NewAttr
&= ~(S_IRUSR
| S_IRGRP
| S_IROTH
);
2076 UnixStatus
= PrivateFile
->UnixThunk
->Chmod (NewFileName
, NewAttr
);
2078 if (UnixStatus
!= 0) {
2079 Status
= EFI_DEVICE_ERROR
;
2083 if (OldFileInfo
!= NULL
) {
2084 gBS
->FreePool (OldFileInfo
);
2087 if (OldFileName
!= NULL
) {
2088 gBS
->FreePool (OldFileName
);
2091 if (NewFileName
!= NULL
) {
2092 gBS
->FreePool (NewFileName
);
2095 gBS
->RestoreTPL (OldTpl
);
2102 UnixSimpleFileSystemFlush (
2107 Routine Description:
2109 Flush all modified data to the media.
2113 This - Pointer to an opened file handle.
2117 EFI_SUCCESS - The data has been flushed.
2119 EFI_NO_MEDIA - The device has no media.
2121 EFI_DEVICE_ERROR - The device reported an error.
2123 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2125 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2127 EFI_ACCESS_DENIED - The file was opened read-only.
2129 EFI_VOLUME_FULL - The volume is full.
2132 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2134 UNIX_EFI_FILE_PRIVATE
*PrivateFile
;
2139 return EFI_INVALID_PARAMETER
;
2142 OldTpl
= gBS
->RaiseTPL (EFI_TPL_CALLBACK
);
2144 PrivateFile
= UNIX_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2147 if (PrivateFile
->IsDirectoryPath
) {
2148 Status
= EFI_SUCCESS
;
2152 if (PrivateFile
->IsOpenedByRead
) {
2153 Status
= EFI_ACCESS_DENIED
;
2157 if (PrivateFile
->fd
< 0) {
2158 Status
= EFI_DEVICE_ERROR
;
2162 PrivateFile
->UnixThunk
->FSync (PrivateFile
->fd
) == 0 ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2165 gBS
->RestoreTPL (OldTpl
);
2170 // bugbug: - Use Unix error reporting.