]>
git.proxmox.com Git - mirror_edk2.git/blob - StdLib/LibC/Uefi/SysCalls.c
2 EFI versions of NetBSD system calls.
4 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Library/UefiLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/BaseLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/ShellLib.h>
21 #include <LibConfig.h>
22 #include <sys/EfiCdefs.h>
31 #include <sys/fcntl.h>
33 #include <sys/syslimits.h>
34 #include <sys/filio.h>
35 #include <Efi/SysEfi.h>
38 #include <Device/Device.h>
42 /* EFI versions of BSD system calls used in stdio */
44 /* Validate that fd refers to a valid file descriptor.
45 IsOpen is interpreted as follows:
46 - Positive fd must be OPEN
47 - Zero fd must be CLOSED
48 - Negative fd may be OPEN or CLOSED
50 @retval TRUE fd is VALID
51 @retval FALSE fd is INVALID
54 ValidateFD( int fd
, int IsOpen
)
56 struct __filedes
*filp
;
57 BOOLEAN retval
= FALSE
;
59 if((fd
>= 0) && (fd
< OPEN_MAX
)) {
60 filp
= &gMD
->fdarray
[fd
];
63 retval
= (BOOLEAN
)((filp
->f_iflags
!= 0) && // TRUE if OPEN
64 FILE_IS_USABLE(filp
)); // and Usable (not Larval or Closing)
65 if(IsOpen
== VALID_CLOSED
) {
66 retval
= (BOOLEAN
)!retval
; // We want TRUE if CLOSED
73 /* Find and reserve a free File Descriptor.
75 Returns the first free File Descriptor greater than or equal to the,
76 already validated, fd specified by Minfd.
78 @return Returns -1 if there are no free FDs. Otherwise returns the
82 FindFreeFD( int MinFd
)
84 struct __filedes
*Mfd
;
90 // Get an available fd
91 for(i
=MinFd
; i
< OPEN_MAX
; ++i
) {
92 if(Mfd
[i
].f_iflags
== 0) {
93 Mfd
[i
].f_iflags
= FIF_LARVAL
; // Temporarily mark this fd as reserved
101 /* Mark that an open file is to be deleted when closed. */
103 DeleteOnClose(int fd
)
107 if(ValidateFD( fd
, VALID_OPEN
)) {
108 gMD
->fdarray
[fd
].f_iflags
|= FIF_DELCLOSE
;
117 /** The isatty() function tests whether fildes, an open file descriptor,
118 is associated with a terminal device.
120 @retval 1 fildes is associated with a terminal.
121 @retval 0 fildes is not associated with a terminal. errno is set to
122 EBADF if fildes is not a valid open FD.
128 struct __filedes
*Fp
;
130 if(ValidateFD( fd
, VALID_OPEN
)) {
131 Fp
= &gMD
->fdarray
[fd
];
132 retval
= Fp
->f_iflags
& _S_ITTY
;
140 /** Determine if file descriptor fd is a duplicate of some other fd.
142 @param[in] fd The file descriptor to check.
144 @retval TRUE fd is a duplicate of another fd.
145 @retval FALSE fd is unique.
151 const struct fileops
*FileOps
;
155 if(ValidateFD( fd
, VALID_OPEN
)) {
156 FileOps
= gMD
->fdarray
[fd
].f_ops
;
157 DevData
= gMD
->fdarray
[fd
].devdata
;
158 for(i
=0; i
< OPEN_MAX
; ++i
) {
159 if(i
== fd
) continue;
160 if(ValidateFD( i
, VALID_OPEN
)) { // TRUE if fd is valid and OPEN
161 if((gMD
->fdarray
[i
].f_ops
== FileOps
)
162 &&(gMD
->fdarray
[i
].devdata
== DevData
)) {
172 /** Close a file and set its fd to the specified state.
174 @param[in] fd The file descriptor to close.
175 @param[in] NewState State to set the fd to after the file is closed.
177 @retval 0 The operation completed successfully.
178 @retval -1 The operation failed. Further information is in errno.
181 _closeX (int fd
, int NewState
)
183 struct __filedes
*Fp
;
186 // Verify my pointers and get my FD.
187 if(ValidateFD( fd
, VALID_OPEN
)) {
188 Fp
= &gMD
->fdarray
[fd
];
189 // Check if there are other users of this FileHandle
190 if(Fp
->RefCount
== 1) { // There should be no other users
192 // Only do the close if no one else is using the FileHandle
193 if(Fp
->f_iflags
& FIF_DELCLOSE
) {
194 /* Handle files marked "Delete on Close". */
195 if(Fp
->f_ops
->fo_delete
!= NULL
) {
196 retval
= Fp
->f_ops
->fo_delete(Fp
);
200 retval
= Fp
->f_ops
->fo_close( Fp
);
203 Fp
->f_iflags
= NewState
; // Close this FD or reserve it
204 Fp
->RefCount
= 0; // No one using this FD
207 --Fp
->RefCount
; /* One less user of this FD */
218 /** The close() function deallocates the file descriptor indicated by fd.
219 To deallocate means to make the file descriptor available for return by
220 subsequent calls to open() or other functions that allocate file
221 descriptors. All outstanding record locks owned by the process on the file
222 associated with the file descriptor are removed (that is, unlocked).
224 @retval 0 Successful completion.
225 @retval -1 An error occurred and errno is set to identify the error.
230 return _closeX(fd
, 0);
236 unlink (const char *path
)
238 struct __filedes
*Fp
;
242 EFIerrno
= RETURN_SUCCESS
;
244 fd
= open(path
, O_WRONLY
, 0);
246 Fp
= &gMD
->fdarray
[fd
];
248 if(Fp
->f_ops
->fo_delete
!= NULL
) {
249 retval
= Fp
->f_ops
->fo_delete(Fp
);
251 Fp
->f_iflags
= 0; // Close this FD
252 Fp
->RefCount
= 0; // No one using this FD
257 /** The fcntl() function shall perform the operations described below on open
258 files. The fildes argument is a file descriptor.
260 The available values for cmd are defined in <fcntl.h> and are as follows:
261 - F_DUPFD - Return a new file descriptor which shall be the lowest
262 numbered available (that is, not already open) file
263 descriptor greater than or equal to the third argument, arg,
264 taken as an integer of type int. The new file descriptor
265 shall refer to the same open file description as the original
266 file descriptor, and shall share any locks. The FD_CLOEXEC
267 flag associated with the new file descriptor shall be cleared
268 to keep the file open across calls to one of the exec functions.
269 - F_GETFD - Get the file descriptor flags defined in <fcntl.h> that are
270 associated with the file descriptor fildes. File descriptor
271 flags are associated with a single file descriptor and do not
272 affect other file descriptors that refer to the same file.
273 - F_SETFD - Set the file descriptor flags defined in <fcntl.h>, that are
274 associated with fildes, to the third argument, arg, taken
275 as type int. If the FD_CLOEXEC flag in the third argument
276 is 0, the file shall remain open across the exec
277 functions; otherwise, the file shall be closed upon
278 successful execution of one of the exec functions.
279 - F_GETFL - Get the file status flags and file access modes, defined in
280 <fcntl.h>, for the file description associated with fildes.
281 The file access modes can be extracted from the return
282 value using the mask O_ACCMODE, which is defined in
283 <fcntl.h>. File status flags and file access modes are
284 associated with the file description and do not affect
285 other file descriptors that refer to the same file with
286 different open file descriptions.
287 - F_SETFL - Set the file status flags, defined in <fcntl.h>, for the file
288 description associated with fildes from the corresponding
289 bits in the third argument, arg, taken as type int. Bits
290 corresponding to the file access mode and the file creation
291 flags, as defined in <fcntl.h>, that are set in arg shall
292 be ignored. If any bits in arg other than those mentioned
293 here are changed by the application, the result is unspecified.
294 - F_GETOWN - If fildes refers to a socket, get the process or process group
295 ID specified to receive SIGURG signals when out-of-band
296 data is available. Positive values indicate a process ID;
297 negative values, other than -1, indicate a process group
298 ID. If fildes does not refer to a socket, the results are
300 - F_SETOWN - If fildes refers to a socket, set the process or process
301 group ID specified to receive SIGURG signals when
302 out-of-band data is available, using the value of the third
303 argument, arg, taken as type int. Positive values indicate
304 a process ID; negative values, other than -1, indicate a
305 process group ID. If fildes does not refer to a socket, the
306 results are unspecified.
308 The fcntl() function shall fail if:
310 [EBADF] The fildes argument is not a valid open file descriptor.
311 [EINVAL] The cmd argument is invalid, or the cmd argument is F_DUPFD
312 and arg is negative or greater than or equal to {OPEN_MAX}.
313 [EMFILE] The argument cmd is F_DUPFD and {OPEN_MAX} file descriptors
314 are currently open in the calling process, or no file
315 descriptors greater than or equal to arg are available.
316 [EOVERFLOW] One of the values to be returned cannot be represented correctly.
318 @return Upon successful completion, the value returned shall depend on
320 - F_DUPFD - A new file descriptor.
321 - F_GETFD - Value of flags defined in <fcntl.h>. The return value
322 shall not be negative.
323 - F_SETFD - Value other than -1.
324 - F_GETFL - Value of file status flags and access modes. The return
325 value is not negative.
326 - F_SETFL - Value other than -1.
327 - F_GETOWN - Value of the socket owner process or process group;
329 - F_SETOWN - Value other than -1.
330 Otherwise, -1 shall be returned and errno set to indicate the error.
334 fcntl (int fildes
, int cmd
, ...)
337 struct __filedes
*MyFd
;
341 //Print(L"%a( %d, %d, ...)\n", __func__, fildes, cmd);
344 if(ValidateFD( fildes
, VALID_OPEN
)) {
345 MyFd
= &gMD
->fdarray
[fildes
];
349 temp
= va_arg(p3
, int);
350 if(ValidateFD( temp
, VALID_DONT_CARE
)) {
351 temp
= FindFreeFD( temp
);
356 /* temp is now a valid fd reserved for further use
357 so copy fd into temp.
359 (void)memcpy(&gMD
->fdarray
[temp
], MyFd
, sizeof(struct __filedes
));
368 retval
= MyFd
->Oflags
; // Get original value
369 temp
= va_arg(p3
, int);
370 temp
&= O_SETMASK
; // Only certain bits can be set
371 temp
|= retval
& O_SETMASK
;
372 MyFd
->Oflags
= temp
; // Set new value
376 retval
= MyFd
->f_iflags
;
379 // retval = MyFd->SocProc;
380 // MyFd->SocProc = va_arg(p3, int);
383 retval
= MyFd
->f_iflags
;
386 retval
= MyFd
->Oflags
;
389 // retval = MyFd->SocProc;
404 /** The dup() function provides an alternative interface to the
405 service provided by fcntl() using the F_DUPFD command. The call:
407 shall be equivalent to:
408 - fid = fcntl(fildes, F_DUPFD, 0);
410 @return Upon successful completion a non-negative integer, namely the
411 file descriptor, shall be returned; otherwise, -1 shall be
412 returned and errno set to indicate the error.
417 return fcntl(fildes
, F_DUPFD
, 0);
420 /** The dup2() function provides an alternative interface to the
421 service provided by fcntl() using the F_DUPFD command. The call:
422 - fid = dup2(fildes, fildes2);
423 shall be equivalent to:
425 - fid = fcntl(fildes, F_DUPFD, fildes2);
426 except for the following:
427 - If fildes2 is less than 0 or greater than or equal to {OPEN_MAX},
428 dup2() shall return -1 with errno set to [EBADF].
429 - If fildes is a valid file descriptor and is equal to fildes2, dup2()
430 shall return fildes2 without closing it.
431 - If fildes is not a valid file descriptor, dup2() shall return -1 and
432 shall not close fildes2.
433 - The value returned shall be equal to the value of fildes2 upon
434 successful completion, or -1 upon failure.
436 @return Upon successful completion a non-negative integer, namely
437 fildes2, shall be returned; otherwise, -1 shall be
438 returned and errno set to EBADF indicate the error.
441 dup2 (int fildes
, int fildes2
)
445 if(ValidateFD( fildes
, VALID_OPEN
)) {
447 if( fildes
!= fildes2
) {
448 if(ValidateFD( fildes2
, VALID_DONT_CARE
)) {
449 gMD
->fdarray
[fildes2
].f_iflags
= FIF_LARVAL
; // Mark the file closed, but reserved
450 (void)memcpy(&gMD
->fdarray
[fildes2
], // Duplicate fildes into fildes2
451 &gMD
->fdarray
[fildes
], sizeof(struct __filedes
));
452 gMD
->fdarray
[fildes2
].MyFD
= (UINT16
)fildes2
;
466 /** Reposition a file's read/write offset.
468 The lseek() function repositions the offset of the file descriptor fildes
469 to the argument offset according to the directive how. The argument
470 fildes must be an open file descriptor. lseek() repositions the file
471 pointer fildes as follows:
473 If how is SEEK_SET, the offset is set to offset bytes.
475 If how is SEEK_CUR, the offset is set to its current location
478 If how is SEEK_END, the offset is set to the size of the file
481 The lseek() function allows the file offset to be set beyond the end of
482 the existing end-of-file of the file. If data is later written at this
483 point, subsequent reads of the data in the gap return bytes of zeros
484 (until data is actually written into the gap).
486 Some devices are incapable of seeking. The value of the pointer associ-
487 ated with such a device is undefined.
489 @return Upon successful completion, lseek() returns the resulting offset
490 location as measured in bytes from the beginning of the file.
491 Otherwise, a value of -1 is returned and errno is set to
495 lseek (int fd
, __off_t offset
, int how
)
498 // RETURN_STATUS Status = RETURN_SUCCESS;
499 struct __filedes
*filp
;
501 EFIerrno
= RETURN_SUCCESS
; // In case of error without an EFI call
503 if( how
== SEEK_SET
|| how
== SEEK_CUR
|| how
== SEEK_END
) {
504 if(ValidateFD( fd
, VALID_OPEN
)) {
505 filp
= &gMD
->fdarray
[fd
];
506 // Both of our parameters have been verified as valid
507 CurPos
= filp
->f_ops
->fo_lseek( filp
, offset
, how
);
509 filp
->f_offset
= CurPos
;
513 errno
= EBADF
; // Bad File Descriptor
517 errno
= EINVAL
; // Invalid how argument
522 /** The directory path is created with the access permissions specified by
525 The directory is closed after it is created.
527 @retval 0 The directory was created successfully.
528 @retval -1 An error occurred and error codes are stored in errno and EFIerrno.
531 mkdir (const char *path
, __mode_t perms
)
536 RETURN_STATUS Status
;
540 Status
= ParsePath(path
, &NewPath
, &Node
, &Instance
, NULL
);
541 if(Status
== RETURN_SUCCESS
) {
542 GenI
= Node
->InstanceList
;
548 //GenI += (Instance * Node->InstanceSize);
549 retval
= ((GenericInstance
*)GenI
)->Abstraction
.fo_mkdir( path
, perms
);
560 The open() function establishes the connection between a file and a file
561 descriptor. It creates an open file description that refers to a file
562 and a file descriptor that refers to that open file description. The file
563 descriptor is used by other I/O functions to refer to that file.
565 The open() function returns a file descriptor for the named file that is
566 the lowest file descriptor not currently open for that process. The open
567 file description is new, and therefore the file descriptor shall not
568 share it with any other process in the system.
570 The file offset used to mark the current position within the file is set
571 to the beginning of the file.
573 The EFI ShellOpenFileByName() function is used to perform the low-level
574 file open operation. The primary task of open() is to translate from the
575 flags used in the <stdio.h> environment to those used by the EFI function.
577 The file status flags and file access modes of the open file description
578 are set according to the value of oflags.
580 Values for oflags are constructed by a bitwise-inclusive OR of flags from
581 the following list, defined in <fcntl.h>. Applications shall specify
582 exactly one of { O_RDONLY, O_RDWR, O_WRONLY } in the value of oflags.
583 Any combination of { O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL } may
584 also be specified in oflags.
586 The only valid flag combinations for ShellOpenFileByName() are:
591 Values for mode specify the access permissions for newly created files.
592 The mode value is saved in the FD to indicate permissions for further operations.
594 O_RDONLY -- flags = EFI_FILE_MODE_READ -- this is always done
595 O_WRONLY -- flags |= EFI_FILE_MODE_WRITE
596 O_RDWR -- flags |= EFI_FILE_MODE_WRITE -- READ is already set
598 O_NONBLOCK -- ignored
599 O_APPEND -- Seek to EOF before every write
600 O_CREAT -- flags |= EFI_FILE_MODE_CREATE
601 O_TRUNC -- delete first then create new
602 O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
604 @param[in] Path The path argument points to a pathname naming the
606 @param[in] oflags File status flags and file access modes of the
607 open file description.
608 @param[in] mode File access permission bits as defined in
611 @return Upon successful completion, open() opens the file and returns
612 a non-negative integer representing the lowest numbered
613 unused file descriptor. Otherwise, open returns -1 and sets
614 errno to indicate the error. If a negative value is
615 returned, no files are created or modified.
617 @retval EMFILE No file descriptors available -- Max number already open.
618 @retval EINVAL Bad value specified for oflags or mode.
619 @retval ENOMEM Failure allocating memory for internal buffers.
620 @retval EEXIST File exists and open attempted with (O_EXCL | O_CREAT) set.
621 @retval EIO UEFI failure. Check value in EFIerrno.
633 struct __filedes
*filp
;
635 RETURN_STATUS Status
;
640 Status
= ParsePath(path
, &NewPath
, &Node
, &Instance
, &MPath
);
641 if(Status
== RETURN_SUCCESS
) {
643 (Node
->InstanceList
== NULL
)) {
647 // Could add a test to see if the file name begins with a period.
648 // If it does, then add the HIDDEN flag to Attributes.
650 // Get an available fd
651 fd
= FindFreeFD( VALID_CLOSED
);
654 // All available FDs are in use
658 filp
= &gMD
->fdarray
[fd
];
659 // Save the flags and mode in the File Descriptor
660 filp
->Oflags
= oflags
;
663 doresult
= Node
->OpenFunc(Node
, filp
, Instance
, NewPath
, MPath
);
665 filp
->f_iflags
= 0; // Release this FD
666 fd
= -1; // Indicate an error
669 // Re-use OpenMode in order to build our final f_iflags value
670 OpenMode
= ( mode
& S_ACC_READ
) ? S_ACC_READ
: 0;
671 OpenMode
|= ( mode
& S_ACC_WRITE
) ? S_ACC_WRITE
: 0;
673 filp
->f_iflags
|= (UINT32
)OpenMode
;
675 FILE_SET_MATURE(filp
);
679 if(NewPath
!= NULL
) {
684 free(MPath
); // We don't need this any more.
686 // return the fd of our now open file
692 Poll a list of file descriptors.
694 The ::poll routine waits for up to timeout milliseconds for an event
695 to occur on one or more of the file descriptors listed. The event
696 types of interested are specified for each file descriptor in the events
697 field. The actual event detected is returned in the revents field of
699 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">POSIX</a>
700 documentation is available online.
702 @param [in] pfd Address of an array of pollfd structures.
704 @param [in] nfds Number of elements in the array of pollfd structures.
706 @param [in] timeout Length of time in milliseconds to wait for the event
708 @return The number of file descriptors with detected events. Zero
709 indicates that the call timed out and -1 indicates an error.
719 struct __filedes
* pDescriptor
;
720 struct pollfd
* pEnd
;
721 struct pollfd
* pPollFD
;
728 // Create the timer for the timeout
731 Status
= EFI_SUCCESS
;
732 if ( INFTIM
!= timeout
) {
733 Status
= gBS
->CreateEvent ( EVT_TIMER
,
738 if ( !EFI_ERROR ( Status
)) {
740 // Start the timeout timer
742 TimerTicks
= timeout
;
743 TimerTicks
*= 1000 * 10;
744 Status
= gBS
->SetTimer ( Timer
,
753 if ( !EFI_ERROR ( Status
)) {
755 // Poll until an event is detected or the timer fires
761 // Poll the list of file descriptors
764 pEnd
= &pPollFD
[ nfds
];
765 while ( pEnd
> pPollFD
) {
767 // Validate the file descriptor
769 if ( !ValidateFD ( pPollFD
->fd
, VALID_OPEN
)) {
775 // Poll the device or file
777 pDescriptor
= &gMD
->fdarray
[ pPollFD
->fd
];
778 pPollFD
->revents
= pDescriptor
->f_ops
->fo_poll ( pDescriptor
,
782 // Determine if this file descriptor detected an event
784 if ( 0 != pPollFD
->revents
) {
786 // Select this descriptor
792 // Set the next file descriptor
800 if ( NULL
!= Timer
) {
801 Status
= gBS
->CheckEvent ( Timer
);
802 if ( EFI_SUCCESS
== Status
) {
808 else if ( EFI_NOT_READY
== Status
) {
809 Status
= EFI_SUCCESS
;
812 } while (( 0 == SelectedFDs
)
813 && ( EFI_SUCCESS
== Status
));
818 if ( NULL
!= Timer
) {
819 gBS
->SetTimer ( Timer
,
832 if ( NULL
!= Timer
) {
833 gBS
->CloseEvent ( Timer
);
837 // Return the number of selected file system descriptors
843 /** The rename() function changes the name of a file.
844 The old argument points to the pathname of the file to be renamed. The new
845 argument points to the new pathname of the file.
847 If the old argument points to the pathname of a file that is not a
848 directory, the new argument shall not point to the pathname of a
849 directory. If the file named by the new argument exists, it shall be
850 removed and old renamed to new. Write access permission is required for
851 both the directory containing old and the directory containing new.
853 If the old argument points to the pathname of a directory, the new
854 argument shall not point to the pathname of a file that is not a
855 directory. If the directory named by the new argument exists, it shall be
856 removed and old renamed to new.
858 The new pathname shall not contain a path prefix that names old. Write
859 access permission is required for the directory containing old and the
860 directory containing new. If the old argument points to the pathname of a
861 directory, write access permission may be required for the directory named
862 by old, and, if it exists, the directory named by new.
864 If the rename() function fails for any reason other than [EIO], any file
865 named by new shall be unaffected.
867 @return Upon successful completion, rename() shall return 0; otherwise,
868 -1 shall be returned, errno shall be set to indicate the error,
869 and neither the file named by old nor the file named by new
870 shall be changed or created.
879 DeviceNode
*FromNode
;
882 RETURN_STATUS Status
;
885 Status
= ParsePath(from
, &FromPath
, &FromNode
, &Instance
, NULL
);
886 if(Status
== RETURN_SUCCESS
) {
887 GenI
= FromNode
->InstanceList
;
893 //GenI += (Instance * FromNode->InstanceSize);
894 retval
= ((GenericInstance
*)GenI
)->Abstraction
.fo_rename( from
, to
);
908 struct __filedes
*filp
;
912 fd
= open(path
, O_RDWR
, 0);
914 filp
= &gMD
->fdarray
[fd
];
916 retval
= filp
->f_ops
->fo_rmdir(filp
);
917 filp
->f_iflags
= 0; // Close this FD
918 filp
->RefCount
= 0; // No one using this FD
923 /** The fstat() function obtains information about an open file associated
924 with the file descriptor fildes, and shall write it to the area pointed to
927 The buf argument is a pointer to a stat structure, as defined
928 in <sys/stat.h>, into which information is placed concerning the file.
930 The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
931 st_ctime, and st_mtime shall have meaningful values. The value of the
932 member st_nlink shall be set to the number of links to the file.
934 The fstat() function shall update any time-related fields before writing
935 into the stat structure.
937 The fstat() function is implemented using the ShellGetFileInfo()
940 The stat structure members which don't have direct analogs to EFI file
941 information are filled in as follows:
942 - st_mode Populated with information from fildes
943 - st_ino Set to zero. (inode)
944 - st_dev Set to zero.
945 - st_uid Set to zero.
946 - st_gid Set to zero.
947 - st_nlink Set to one.
949 @param[in] fd File descriptor as returned from open().
950 @param[out] statbuf Buffer in which the file status is put.
952 @retval 0 Successful Completion.
953 @retval -1 An error has occurred and errno has been set to
957 fstat (int fd
, struct stat
*statbuf
)
960 struct __filedes
*filp
;
962 if(ValidateFD( fd
, VALID_OPEN
)) {
963 filp
= &gMD
->fdarray
[fd
];
964 retval
= filp
->f_ops
->fo_stat(filp
, statbuf
, NULL
);
972 /** Obtains information about the file pointed to by path.
974 Opens the file pointed to by path, calls _EFI_FileInfo with the file's handle,
975 then closes the file.
977 @retval 0 Successful Completion.
978 @retval -1 An error has occurred and errno has been set to
982 stat (const char *path
, struct stat
*statbuf
)
986 struct __filedes
*filp
;
988 fd
= open(path
, O_RDONLY
, 0);
990 filp
= &gMD
->fdarray
[fd
];
991 retval
= filp
->f_ops
->fo_stat( filp
, statbuf
, NULL
);
997 /** Same as stat since EFI doesn't have symbolic links. **/
999 lstat (const char *path
, struct stat
*statbuf
)
1001 return stat(path
, statbuf
);
1004 /** Control a device.
1009 unsigned long request
,
1014 struct __filedes
*filp
;
1017 va_start(argp
, request
);
1019 if(ValidateFD( fd
, VALID_OPEN
)) {
1020 filp
= &gMD
->fdarray
[fd
];
1022 if(request
== FIODLEX
) {
1023 /* set Delete-on-Close */
1024 filp
->f_iflags
|= FIF_DELCLOSE
;
1027 else if(request
== FIONDLEX
) {
1028 /* clear Delete-on-Close */
1029 filp
->f_iflags
&= ~FIF_DELCLOSE
;
1033 /* All other requests. */
1034 retval
= filp
->f_ops
->fo_ioctl(filp
, request
, argp
);
1045 /** Read from a file.
1047 The read() function shall attempt to read nbyte bytes from the file
1048 associated with the open file descriptor, fildes, into the buffer pointed
1051 Before any action described below is taken, and if nbyte is zero, the
1052 read() function may detect and return errors as described below. In the
1053 absence of errors, or if error detection is not performed, the read()
1054 function shall return zero and have no other results.
1056 On files that support seeking (for example, a regular file), the read()
1057 shall start at a position in the file given by the file offset associated
1058 with fildes. The file offset shall be incremented by the number of bytes
1061 Files that do not support seeking - for example, terminals - always read
1062 from the current position. The value of a file offset associated with
1063 such a file is undefined.
1065 No data transfer shall occur past the current end-of-file. If the
1066 starting position is at or after the end-of-file, 0 shall be returned.
1068 The read() function reads data previously written to a file. If any
1069 portion of a regular file prior to the end-of-file has not been written,
1070 read() shall return bytes with value 0. For example, lseek() allows the
1071 file offset to be set beyond the end of existing data in the file. If data
1072 is later written at this point, subsequent reads in the gap between the
1073 previous end of data and the newly written data shall return bytes with
1074 value 0 until data is written into the gap.
1076 Upon successful completion, where nbyte is greater than 0, read() shall
1077 mark for update the st_atime field of the file, and shall return the
1078 number of bytes read. This number shall never be greater than nbyte. The
1079 value returned may be less than nbyte if the number of bytes left in the
1080 file is less than nbyte, if the read() request was interrupted by a
1081 signal, or if the file is a pipe or FIFO or special file and has fewer
1082 than nbyte bytes immediately available for reading. For example, a read()
1083 from a file associated with a terminal may return one typed line of data.
1085 If fildes does not refer to a directory, the function reads the requested
1086 number of bytes from the file at the file's current position and returns
1087 them in buf. If the read goes beyond the end of the file, the read
1088 length is truncated to the end of the file. The file's current position is
1089 increased by the number of bytes returned.
1091 If fildes refers to a directory, the function reads the directory entry at
1092 the file's current position and returns the entry in buf. If buf
1093 is not large enough to hold the current directory entry, then
1094 errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
1095 current file position is not updated. The size of the buffer needed to read
1096 the entry will be returned as a negative number. On success, the current
1097 position is updated to the next directory entry. If there are no more
1098 directory entries, the read returns a zero-length buffer.
1099 EFI_FILE_INFO is the structure returned as the directory entry.
1101 @return Upon successful completion, read() returns a non-negative integer
1102 indicating the number of bytes actually read. Otherwise, the
1103 functions return a negative value and sets errno to indicate the
1104 error. If errno is EBUFSIZE, the absolute value of the
1105 return value indicates the size of the buffer needed to read
1106 the directory entry.
1109 read (int fildes
, void *buf
, size_t nbyte
)
1111 struct __filedes
*filp
;
1114 BufSize
= (ssize_t
)nbyte
;
1115 if(ValidateFD( fildes
, VALID_OPEN
)) {
1116 filp
= &gMD
->fdarray
[fildes
];
1118 BufSize
= filp
->f_ops
->fo_read(filp
, &filp
->f_offset
, nbyte
, buf
);
1127 /** Write data to a file.
1129 This function writes the specified number of bytes to the file at the current
1130 file position. The current file position is advanced the actual number of bytes
1131 written, which is returned in BufferSize. Partial writes only occur when there
1132 has been a data error during the write attempt (such as "volume space full").
1133 The file is automatically grown to hold the data if required. Direct writes to
1134 opened directories are not supported.
1136 If fildes refers to a terminal device, isatty() returns TRUE, a partial write
1137 will occur if a NULL or EOF character is encountered before n characters have
1138 been written. Characters inserted due to line-end translations will not be
1139 counted. Unconvertable characters are translated into the UEFI character
1140 BLOCKELEMENT_LIGHT_SHADE.
1142 Since the UEFI console device works on wide characters, the buffer is assumed
1143 to contain a single-byte character stream which is then translated to wide
1144 characters using the btowc() functions. The resulting wide character stream
1145 is what is actually sent to the UEFI console.
1147 QUESTION: Should writes to stdout or stderr always succeed?
1150 write (int fd
, const void *buf
, size_t nbyte
)
1152 struct __filedes
*filp
;
1154 // EFI_FILE_HANDLE FileHandle;
1155 // RETURN_STATUS Status = RETURN_SUCCESS;
1157 BufSize
= (ssize_t
)nbyte
;
1159 if(ValidateFD( fd
, VALID_OPEN
)) {
1160 filp
= &gMD
->fdarray
[fd
];
1162 BufSize
= filp
->f_ops
->fo_write(filp
, &filp
->f_offset
, nbyte
, buf
);
1171 /** Gets the current working directory.
1173 The getcwd() function shall place an absolute pathname of the current
1174 working directory in the array pointed to by buf, and return buf.The
1175 size argument is the size in bytes of the character array pointed to
1176 by the buf argument.
1178 @param[in,out] buf The buffer to fill.
1179 @param[in] size The number of bytes in buffer.
1181 @retval NULL The function failed. The value in errno provides
1182 further information about the cause of the failure.
1183 Values for errno are:
1184 - EINVAL: buf is NULL or size is zero.
1185 - ENOENT: directory does not exist.
1186 - ERANGE: buf size is too small to hold CWD
1188 @retval buf The function completed successfully.
1191 *getcwd (char *buf
, size_t size
)
1195 if (size
== 0 || buf
== NULL
) {
1200 Cwd
= ShellGetCurrentDir(NULL
);
1205 if (size
< ((StrLen (Cwd
) + 1) * sizeof (CHAR8
))) {
1209 return (UnicodeStrToAsciiStr(Cwd
, buf
));
1212 /** Change the current working directory.
1214 The chdir() function shall cause the directory named by the pathname
1215 pointed to by the path argument to become the current working directory;
1216 that is, the starting point for path searches for pathnames not beginning
1219 @param[in] path The new path to set.
1221 @retval 0 Operation completed successfully.
1222 @retval -1 Function failed. The value in errno provides more
1223 information on the cause of failure:
1224 - EPERM: Operation not supported with this Shell version.
1225 - ENOMEM: Unable to allocate memory.
1226 - ENOENT: Target directory does not exist.
1228 @todo Add non-NEW-shell CWD changing.
1231 chdir (const char *path
)
1235 CHAR16
*UnicodePath
;
1237 /* Old Shell does not support Set Current Dir. */
1238 if(gEfiShellProtocol
!= NULL
) {
1239 Cwd
= ShellGetCurrentDir(NULL
);
1241 /* We have shell support */
1242 UnicodePath
= AllocatePool(((AsciiStrLen (path
) + 1) * sizeof (CHAR16
)));
1243 if (UnicodePath
== NULL
) {
1247 AsciiStrToUnicodeStr(path
, UnicodePath
);
1248 Status
= gEfiShellProtocol
->SetCurDir(NULL
, UnicodePath
);
1249 FreePool(UnicodePath
);
1250 if (EFI_ERROR(Status
)) {
1258 /* Add here for non-shell */
1263 pid_t
tcgetpgrp (int x
)
1265 return ((pid_t
)(UINTN
)(gImageHandle
));
1270 return ((pid_t
)(UINTN
)(gImageHandle
));
1273 /* Internal worker function for utimes.
1274 This works around an error produced by GCC when the va_* macros
1275 are used within a function with a fixed number of arguments.
1285 struct __filedes
*filp
;
1291 fd
= open(path
, O_RDWR
, 0);
1293 filp
= &gMD
->fdarray
[fd
];
1294 retval
= filp
->f_ops
->fo_ioctl( filp
, FIOSETIME
, ap
);
1301 /** Set file access and modification times.
1311 const struct timeval
*times
1314 return va_Utimes(path
, times
);