1 | /** @file
|
---|
2 | EFI versions of NetBSD system calls.
|
---|
3 |
|
---|
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.
|
---|
9 |
|
---|
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.
|
---|
12 |
|
---|
13 | **/
|
---|
14 | #include <Uefi.h>
|
---|
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>
|
---|
20 |
|
---|
21 | #include <LibConfig.h>
|
---|
22 | #include <sys/EfiCdefs.h>
|
---|
23 |
|
---|
24 | #include <sys/ansi.h>
|
---|
25 | #include <errno.h>
|
---|
26 | #include <stdarg.h>
|
---|
27 | #include <stdlib.h>
|
---|
28 | #include <string.h>
|
---|
29 | #include <wchar.h>
|
---|
30 | #include <sys/poll.h>
|
---|
31 | #include <sys/fcntl.h>
|
---|
32 | #include <sys/stat.h>
|
---|
33 | #include <sys/syslimits.h>
|
---|
34 | #include <sys/filio.h>
|
---|
35 | #include <Efi/SysEfi.h>
|
---|
36 | #include <unistd.h>
|
---|
37 | #include <kfile.h>
|
---|
38 | #include <Device/Device.h>
|
---|
39 | #include <Device/IIO.h>
|
---|
40 | #include <MainData.h>
|
---|
41 | #include <extern.h>
|
---|
42 |
|
---|
43 | /* EFI versions of BSD system calls used in stdio */
|
---|
44 |
|
---|
45 | /* Validate that fd refers to a valid file descriptor.
|
---|
46 | IsOpen is interpreted as follows:
|
---|
47 | - Positive fd must be OPEN
|
---|
48 | - Zero fd must be CLOSED
|
---|
49 | - Negative fd may be OPEN or CLOSED
|
---|
50 |
|
---|
51 | @retval TRUE fd is VALID
|
---|
52 | @retval FALSE fd is INVALID
|
---|
53 | */
|
---|
54 | BOOLEAN
|
---|
55 | ValidateFD( int fd, int IsOpen)
|
---|
56 | {
|
---|
57 | struct __filedes *filp;
|
---|
58 | BOOLEAN retval = FALSE;
|
---|
59 |
|
---|
60 | if((fd >= 0) && (fd < OPEN_MAX)) {
|
---|
61 | filp = &gMD->fdarray[fd];
|
---|
62 | retval = TRUE;
|
---|
63 | if(IsOpen >= 0) {
|
---|
64 | retval = (BOOLEAN)((filp->f_iflags != 0) && // TRUE if OPEN
|
---|
65 | FILE_IS_USABLE(filp)); // and Usable (not Larval or Closing)
|
---|
66 | if(IsOpen == VALID_CLOSED) {
|
---|
67 | retval = (BOOLEAN)!retval; // We want TRUE if CLOSED
|
---|
68 | }
|
---|
69 | }
|
---|
70 | }
|
---|
71 | return retval;
|
---|
72 | }
|
---|
73 |
|
---|
74 | /* Find and reserve a free File Descriptor.
|
---|
75 |
|
---|
76 | Returns the first free File Descriptor greater than or equal to the,
|
---|
77 | already validated, fd specified by Minfd.
|
---|
78 |
|
---|
79 | @return Returns -1 if there are no free FDs. Otherwise returns the
|
---|
80 | found fd.
|
---|
81 | */
|
---|
82 | int
|
---|
83 | FindFreeFD( int MinFd )
|
---|
84 | {
|
---|
85 | struct __filedes *Mfd;
|
---|
86 | int i;
|
---|
87 | int fd = -1;
|
---|
88 |
|
---|
89 | Mfd = gMD->fdarray;
|
---|
90 |
|
---|
91 | // Get an available fd
|
---|
92 | for(i=MinFd; i < OPEN_MAX; ++i) {
|
---|
93 | if(Mfd[i].f_iflags == 0) {
|
---|
94 | Mfd[i].f_iflags = FIF_LARVAL; // Temporarily mark this fd as reserved
|
---|
95 | fd = i;
|
---|
96 | break;
|
---|
97 | }
|
---|
98 | }
|
---|
99 | return fd;
|
---|
100 | }
|
---|
101 |
|
---|
102 | /* Mark that an open file is to be deleted when closed. */
|
---|
103 | int
|
---|
104 | DeleteOnClose(int fd)
|
---|
105 | {
|
---|
106 | int retval = 0;
|
---|
107 |
|
---|
108 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
109 | gMD->fdarray[fd].f_iflags |= FIF_DELCLOSE;
|
---|
110 | }
|
---|
111 | else {
|
---|
112 | errno = EBADF;
|
---|
113 | retval = -1;
|
---|
114 | }
|
---|
115 | return retval;
|
---|
116 | }
|
---|
117 |
|
---|
118 | /** The isatty() function tests whether fd, an open file descriptor,
|
---|
119 | is associated with a terminal device.
|
---|
120 |
|
---|
121 | @param[in] fd File Descriptor for the file to be examined.
|
---|
122 |
|
---|
123 | @retval 1 fd is associated with a terminal.
|
---|
124 | @retval 0 fd is not associated with a terminal. errno is set to
|
---|
125 | EBADF if fd is not a valid open FD.
|
---|
126 | **/
|
---|
127 | int
|
---|
128 | isatty (int fd)
|
---|
129 | {
|
---|
130 | int retval = 0;
|
---|
131 | struct __filedes *Fp;
|
---|
132 |
|
---|
133 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
134 | Fp = &gMD->fdarray[fd];
|
---|
135 | retval = (Fp->f_iflags & _S_ITTY) ? 1 : 0;
|
---|
136 | }
|
---|
137 | else {
|
---|
138 | errno = EBADF;
|
---|
139 | }
|
---|
140 | return retval;
|
---|
141 | }
|
---|
142 |
|
---|
143 | /** Determine if file descriptor fd is a duplicate of some other fd.
|
---|
144 |
|
---|
145 | @param[in] fd The file descriptor to check.
|
---|
146 |
|
---|
147 | @retval TRUE fd is a duplicate of another fd.
|
---|
148 | @retval FALSE fd is unique.
|
---|
149 | **/
|
---|
150 | static BOOLEAN
|
---|
151 | IsDupFd( int fd)
|
---|
152 | {
|
---|
153 | void * DevData;
|
---|
154 | const struct fileops *FileOps;
|
---|
155 | int i;
|
---|
156 | BOOLEAN Ret = FALSE;
|
---|
157 |
|
---|
158 | if(ValidateFD( fd, VALID_OPEN )) {
|
---|
159 | FileOps = gMD->fdarray[fd].f_ops;
|
---|
160 | DevData = gMD->fdarray[fd].devdata;
|
---|
161 | for(i=0; i < OPEN_MAX; ++i) {
|
---|
162 | if(i == fd) continue;
|
---|
163 | if(ValidateFD( i, VALID_OPEN )) { // TRUE if fd is valid and OPEN
|
---|
164 | if((gMD->fdarray[i].f_ops == FileOps)
|
---|
165 | &&(gMD->fdarray[i].devdata == DevData )) {
|
---|
166 | Ret = TRUE;
|
---|
167 | break;
|
---|
168 | }
|
---|
169 | }
|
---|
170 | }
|
---|
171 | }
|
---|
172 | return Ret;
|
---|
173 | }
|
---|
174 |
|
---|
175 | /** Worker function to Close a file and set its fd to the specified state.
|
---|
176 |
|
---|
177 | @param[in] fd The file descriptor to close.
|
---|
178 | @param[in] NewState State to set the fd to after the file is closed.
|
---|
179 |
|
---|
180 | @retval 0 The operation completed successfully.
|
---|
181 | @retval -1 The operation failed. Further information is in errno.
|
---|
182 | * EBADF fd is not a valid or open file descriptor.
|
---|
183 | **/
|
---|
184 | static int
|
---|
185 | _closeX (int fd, int NewState)
|
---|
186 | {
|
---|
187 | struct __filedes *Fp;
|
---|
188 | int retval = 0;
|
---|
189 |
|
---|
190 | // Verify my pointers and get my FD.
|
---|
191 | if(ValidateFD( fd, VALID_OPEN )) {
|
---|
192 | Fp = &gMD->fdarray[fd];
|
---|
193 | // Check if there are other users of this FileHandle
|
---|
194 | if(Fp->RefCount == 1) { // There should be no other users
|
---|
195 | if(! IsDupFd(fd)) {
|
---|
196 | // Only do the close if no one else is using the FileHandle
|
---|
197 | if(Fp->f_iflags & FIF_DELCLOSE) {
|
---|
198 | /* Handle files marked "Delete on Close". */
|
---|
199 | if(Fp->f_ops->fo_delete != NULL) {
|
---|
200 | retval = Fp->f_ops->fo_delete(Fp);
|
---|
201 | }
|
---|
202 | }
|
---|
203 | else {
|
---|
204 | retval = Fp->f_ops->fo_close( Fp);
|
---|
205 | }
|
---|
206 | }
|
---|
207 | Fp->f_iflags = NewState; // Close this FD or reserve it
|
---|
208 | Fp->RefCount = 0; // No one using this FD
|
---|
209 | }
|
---|
210 | else {
|
---|
211 | --Fp->RefCount; /* One less user of this FD */
|
---|
212 | }
|
---|
213 | }
|
---|
214 | else {
|
---|
215 | // Bad FD
|
---|
216 | retval = -1;
|
---|
217 | errno = EBADF;
|
---|
218 | }
|
---|
219 | return retval;
|
---|
220 | }
|
---|
221 |
|
---|
222 | /** The close() function deallocates the file descriptor indicated by fd.
|
---|
223 | To deallocate means to make the file descriptor available for return by
|
---|
224 | subsequent calls to open() or other functions that allocate file
|
---|
225 | descriptors. All outstanding record locks owned by the process on the file
|
---|
226 | associated with the file descriptor are removed (that is, unlocked).
|
---|
227 |
|
---|
228 | @param[in] fd Descriptor for the File to close.
|
---|
229 |
|
---|
230 | @retval 0 Successful completion.
|
---|
231 | @retval -1 An error occurred and errno is set to identify the error.
|
---|
232 | **/
|
---|
233 | int
|
---|
234 | close (int fd)
|
---|
235 | {
|
---|
236 | return _closeX(fd, 0);
|
---|
237 | }
|
---|
238 |
|
---|
239 | /** Delete the file specified by path.
|
---|
240 |
|
---|
241 | @param[in] path The MBCS path of the file to delete.
|
---|
242 |
|
---|
243 | @retval -1 Unable to open the file specified by path.
|
---|
244 | @retval -1 If (errno == EPERM), unlink is not permited for this file.
|
---|
245 | @retval -1 Low-level delete filed. Reason is in errno.
|
---|
246 | @retval 0 The file was successfully deleted.
|
---|
247 | **/
|
---|
248 | int
|
---|
249 | unlink (const char *path)
|
---|
250 | {
|
---|
251 | struct __filedes *Fp;
|
---|
252 | int fd;
|
---|
253 | int retval = -1;
|
---|
254 |
|
---|
255 | EFIerrno = RETURN_SUCCESS;
|
---|
256 |
|
---|
257 | fd = open(path, O_WRONLY, 0);
|
---|
258 | if(fd >= 0) {
|
---|
259 | Fp = &gMD->fdarray[fd];
|
---|
260 |
|
---|
261 | if(Fp->f_ops->fo_delete != NULL) {
|
---|
262 | retval = Fp->f_ops->fo_delete(Fp);
|
---|
263 | }
|
---|
264 | Fp->f_iflags = 0; // Close this FD
|
---|
265 | Fp->RefCount = 0; // No one using this FD
|
---|
266 | }
|
---|
267 | return retval;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /** The fcntl() function shall perform the operations described below on open
|
---|
271 | files. The fildes argument is a file descriptor.
|
---|
272 |
|
---|
273 | The available values for cmd are defined in <fcntl.h> and are as follows:
|
---|
274 | - F_DUPFD - Return a new file descriptor which shall be the lowest
|
---|
275 | numbered available (that is, not already open) file
|
---|
276 | descriptor greater than or equal to the third argument, arg,
|
---|
277 | taken as an integer of type int. The new file descriptor
|
---|
278 | shall refer to the same open file description as the original
|
---|
279 | file descriptor, and shall share any locks. The FD_CLOEXEC
|
---|
280 | flag associated with the new file descriptor shall be cleared
|
---|
281 | to keep the file open across calls to one of the exec functions.
|
---|
282 | - F_GETFD - Get the file descriptor flags defined in <fcntl.h> that are
|
---|
283 | associated with the file descriptor fildes. File descriptor
|
---|
284 | flags are associated with a single file descriptor and do not
|
---|
285 | affect other file descriptors that refer to the same file.
|
---|
286 | - F_SETFD - Set the file descriptor flags defined in <fcntl.h>, that are
|
---|
287 | associated with fildes, to the third argument, arg, taken
|
---|
288 | as type int. If the FD_CLOEXEC flag in the third argument
|
---|
289 | is 0, the file shall remain open across the exec
|
---|
290 | functions; otherwise, the file shall be closed upon
|
---|
291 | successful execution of one of the exec functions.
|
---|
292 | - F_GETFL - Get the file status flags and file access modes, defined in
|
---|
293 | <fcntl.h>, for the file description associated with fildes.
|
---|
294 | The file access modes can be extracted from the return
|
---|
295 | value using the mask O_ACCMODE, which is defined in
|
---|
296 | <fcntl.h>. File status flags and file access modes are
|
---|
297 | associated with the file description and do not affect
|
---|
298 | other file descriptors that refer to the same file with
|
---|
299 | different open file descriptions.
|
---|
300 | - F_SETFL - Set the file status flags, defined in <fcntl.h>, for the file
|
---|
301 | description associated with fildes from the corresponding
|
---|
302 | bits in the third argument, arg, taken as type int. Bits
|
---|
303 | corresponding to the file access mode and the file creation
|
---|
304 | flags, as defined in <fcntl.h>, that are set in arg shall
|
---|
305 | be ignored. If any bits in arg other than those mentioned
|
---|
306 | here are changed by the application, the result is unspecified.
|
---|
307 | - F_GETOWN - If fildes refers to a socket, get the process or process group
|
---|
308 | ID specified to receive SIGURG signals when out-of-band
|
---|
309 | data is available. Positive values indicate a process ID;
|
---|
310 | negative values, other than -1, indicate a process group
|
---|
311 | ID. If fildes does not refer to a socket, the results are
|
---|
312 | unspecified.
|
---|
313 | - F_SETOWN - If fildes refers to a socket, set the process or process
|
---|
314 | group ID specified to receive SIGURG signals when
|
---|
315 | out-of-band data is available, using the value of the third
|
---|
316 | argument, arg, taken as type int. Positive values indicate
|
---|
317 | a process ID; negative values, other than -1, indicate a
|
---|
318 | process group ID. If fildes does not refer to a socket, the
|
---|
319 | results are unspecified.
|
---|
320 |
|
---|
321 | The fcntl() function shall fail if:
|
---|
322 |
|
---|
323 | [EBADF] The fildes argument is not a valid open file descriptor.
|
---|
324 | [EINVAL] The cmd argument is invalid, or the cmd argument is F_DUPFD
|
---|
325 | and arg is negative or greater than or equal to {OPEN_MAX}.
|
---|
326 | [EMFILE] The argument cmd is F_DUPFD and {OPEN_MAX} file descriptors
|
---|
327 | are currently open in the calling process, or no file
|
---|
328 | descriptors greater than or equal to arg are available.
|
---|
329 | [EOVERFLOW] One of the values to be returned cannot be represented correctly.
|
---|
330 |
|
---|
331 | @param[in] fildes Descriptor for the file to be controlled.
|
---|
332 | @param[in] cmd Command to be acted upon.
|
---|
333 | @param[in,out] ... Optional additional parameters as required by cmd.
|
---|
334 |
|
---|
335 | @return Upon successful completion, the value returned shall depend on
|
---|
336 | cmd as follows:
|
---|
337 | - F_DUPFD - A new file descriptor.
|
---|
338 | - F_GETFD - Value of flags defined in <fcntl.h>. The return value
|
---|
339 | shall not be negative.
|
---|
340 | - F_SETFD - Value other than -1.
|
---|
341 | - F_GETFL - Value of file status flags and access modes. The return
|
---|
342 | value is not negative.
|
---|
343 | - F_SETFL - Value other than -1.
|
---|
344 | - F_GETOWN - Value of the socket owner process or process group;
|
---|
345 | this will not be -1.
|
---|
346 | - F_SETOWN - Value other than -1.
|
---|
347 | Otherwise, -1 shall be returned and errno set to indicate the error.
|
---|
348 |
|
---|
349 | **/
|
---|
350 | int
|
---|
351 | fcntl (int fildes, int cmd, ...)
|
---|
352 | {
|
---|
353 | va_list p3;
|
---|
354 | struct __filedes *MyFd;
|
---|
355 | int retval = -1;
|
---|
356 | int temp;
|
---|
357 |
|
---|
358 | //Print(L"%a( %d, %d, ...)\n", __func__, fildes, cmd);
|
---|
359 | va_start(p3, cmd);
|
---|
360 |
|
---|
361 | if(ValidateFD( fildes, VALID_OPEN )) {
|
---|
362 | MyFd = &gMD->fdarray[fildes];
|
---|
363 |
|
---|
364 | switch(cmd) {
|
---|
365 | case F_DUPFD:
|
---|
366 | temp = va_arg(p3, int);
|
---|
367 | if(ValidateFD( temp, VALID_DONT_CARE )) {
|
---|
368 | temp = FindFreeFD( temp );
|
---|
369 | if(temp < 0) {
|
---|
370 | errno = EMFILE;
|
---|
371 | break;
|
---|
372 | }
|
---|
373 | /* temp is now a valid fd reserved for further use
|
---|
374 | so copy fd into temp.
|
---|
375 | */
|
---|
376 | (void)memcpy(&gMD->fdarray[temp], MyFd, sizeof(struct __filedes));
|
---|
377 | retval = temp;
|
---|
378 | }
|
---|
379 | else {
|
---|
380 | errno = EINVAL;
|
---|
381 | }
|
---|
382 | break;
|
---|
383 |
|
---|
384 | case F_SETFL:
|
---|
385 | retval = MyFd->Oflags; // Get original value
|
---|
386 | temp = va_arg(p3, int);
|
---|
387 | temp &= O_SETMASK; // Only certain bits can be set
|
---|
388 | temp |= retval & O_SETMASK;
|
---|
389 | MyFd->Oflags = temp; // Set new value
|
---|
390 | break;
|
---|
391 |
|
---|
392 | case F_SETFD:
|
---|
393 | retval = MyFd->f_iflags;
|
---|
394 | break;
|
---|
395 | //case F_SETOWN:
|
---|
396 | // retval = MyFd->SocProc;
|
---|
397 | // MyFd->SocProc = va_arg(p3, int);
|
---|
398 | // break;
|
---|
399 | case F_GETFD:
|
---|
400 | retval = MyFd->f_iflags;
|
---|
401 | break;
|
---|
402 | case F_GETFL:
|
---|
403 | retval = MyFd->Oflags;
|
---|
404 | break;
|
---|
405 | //case F_GETOWN:
|
---|
406 | // retval = MyFd->SocProc;
|
---|
407 | // break;
|
---|
408 | default:
|
---|
409 | errno = EINVAL;
|
---|
410 | break;
|
---|
411 | }
|
---|
412 | }
|
---|
413 | else {
|
---|
414 | // Bad FD
|
---|
415 | errno = EBADF;
|
---|
416 | }
|
---|
417 | va_end(p3);
|
---|
418 | return retval;;
|
---|
419 | }
|
---|
420 |
|
---|
421 | /** The dup() function provides an alternative interface to the
|
---|
422 | service provided by fcntl() using the F_DUPFD command. The call:
|
---|
423 | - fid = dup(fildes);
|
---|
424 | shall be equivalent to:
|
---|
425 | - fid = fcntl(fildes, F_DUPFD, 0);
|
---|
426 |
|
---|
427 | @param[in] fildes Descriptor for the file to be examined.
|
---|
428 |
|
---|
429 | @return Upon successful completion a non-negative integer, namely the
|
---|
430 | file descriptor, shall be returned; otherwise, -1 shall be
|
---|
431 | returned and errno set to indicate the error.
|
---|
432 | **/
|
---|
433 | int
|
---|
434 | dup (int fildes)
|
---|
435 | {
|
---|
436 | return fcntl(fildes, F_DUPFD, 0);
|
---|
437 | }
|
---|
438 |
|
---|
439 | /** Make fildes2 refer to a duplicate of fildes.
|
---|
440 |
|
---|
441 | The dup2() function provides an alternative interface to the
|
---|
442 | service provided by fcntl() using the F_DUPFD command. The call:
|
---|
443 | - fid = dup2(fildes, fildes2);
|
---|
444 | shall be equivalent to:
|
---|
445 | - close(fildes2);
|
---|
446 | - fid = fcntl(fildes, F_DUPFD, fildes2);
|
---|
447 | except for the following:
|
---|
448 | - If fildes2 is less than 0 or greater than or equal to {OPEN_MAX},
|
---|
449 | dup2() shall return -1 with errno set to [EBADF].
|
---|
450 | - If fildes is a valid file descriptor and is equal to fildes2, dup2()
|
---|
451 | shall return fildes2 without closing it.
|
---|
452 | - If fildes is not a valid file descriptor, dup2() shall return -1 and
|
---|
453 | shall not close fildes2.
|
---|
454 | - The value returned shall be equal to the value of fildes2 upon
|
---|
455 | successful completion, or -1 upon failure.
|
---|
456 |
|
---|
457 | @param[in] fildes File Descriptor to be duplicated.
|
---|
458 | @param[in] fildes2 File Descriptor to be made a duplicate of fildes.
|
---|
459 |
|
---|
460 | @return Upon successful completion a non-negative integer, namely
|
---|
461 | fildes2, shall be returned; otherwise, -1 shall be
|
---|
462 | returned and errno set to EBADF indicate the error.
|
---|
463 | **/
|
---|
464 | int
|
---|
465 | dup2 (int fildes, int fildes2)
|
---|
466 | {
|
---|
467 | int retval = -1;
|
---|
468 |
|
---|
469 | if(ValidateFD( fildes, VALID_OPEN)) {
|
---|
470 | retval = fildes2;
|
---|
471 | if( fildes != fildes2) {
|
---|
472 | if(ValidateFD( fildes2, VALID_DONT_CARE)) {
|
---|
473 | gMD->fdarray[fildes2].f_iflags = FIF_LARVAL; // Mark the file closed, but reserved
|
---|
474 | (void)memcpy(&gMD->fdarray[fildes2], // Duplicate fildes into fildes2
|
---|
475 | &gMD->fdarray[fildes], sizeof(struct __filedes));
|
---|
476 | gMD->fdarray[fildes2].MyFD = (UINT16)fildes2;
|
---|
477 | }
|
---|
478 | else {
|
---|
479 | errno = EBADF;
|
---|
480 | retval = -1;
|
---|
481 | }
|
---|
482 | }
|
---|
483 | }
|
---|
484 | else {
|
---|
485 | errno = EBADF;
|
---|
486 | }
|
---|
487 | return retval;
|
---|
488 | }
|
---|
489 |
|
---|
490 | /** Reposition a file's read/write offset.
|
---|
491 |
|
---|
492 | The lseek() function repositions the offset of the file descriptor fildes
|
---|
493 | to the argument offset according to the directive how. The argument
|
---|
494 | fildes must be an open file descriptor. lseek() repositions the file
|
---|
495 | pointer fildes as follows:
|
---|
496 |
|
---|
497 | - If how is SEEK_SET, the offset is set to offset bytes.
|
---|
498 |
|
---|
499 | - If how is SEEK_CUR, the offset is set to its current location
|
---|
500 | plus offset bytes.
|
---|
501 |
|
---|
502 | - If how is SEEK_END, the offset is set to the size of the file
|
---|
503 | plus offset bytes.
|
---|
504 |
|
---|
505 | The lseek() function allows the file offset to be set beyond the end of
|
---|
506 | the existing end-of-file of the file. If data is later written at this
|
---|
507 | point, subsequent reads of the data in the gap return bytes of zeros
|
---|
508 | (until data is actually written into the gap).
|
---|
509 |
|
---|
510 | Some devices are incapable of seeking. The value of the pointer associ-
|
---|
511 | ated with such a device is undefined.
|
---|
512 |
|
---|
513 | @param[in] fd Descriptor for the File to be affected.
|
---|
514 | @param[in] offset Value to adjust the file position by.
|
---|
515 | @param[in] how How the file position is to be adjusted.
|
---|
516 |
|
---|
517 | @return Upon successful completion, lseek() returns the resulting offset
|
---|
518 | location as measured in bytes from the beginning of the file.
|
---|
519 | Otherwise, a value of -1 is returned and errno is set to
|
---|
520 | indicate the error.
|
---|
521 | **/
|
---|
522 | __off_t
|
---|
523 | lseek (int fd, __off_t offset, int how)
|
---|
524 | {
|
---|
525 | __off_t CurPos = -1;
|
---|
526 | // RETURN_STATUS Status = RETURN_SUCCESS;
|
---|
527 | struct __filedes *filp;
|
---|
528 |
|
---|
529 | EFIerrno = RETURN_SUCCESS; // In case of error without an EFI call
|
---|
530 |
|
---|
531 | if( how == SEEK_SET || how == SEEK_CUR || how == SEEK_END) {
|
---|
532 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
533 | filp = &gMD->fdarray[fd];
|
---|
534 | // Both of our parameters have been verified as valid
|
---|
535 | CurPos = filp->f_ops->fo_lseek( filp, offset, how);
|
---|
536 | if(CurPos >= 0) {
|
---|
537 | filp->f_offset = CurPos;
|
---|
538 | }
|
---|
539 | }
|
---|
540 | else {
|
---|
541 | errno = EBADF; // Bad File Descriptor
|
---|
542 | }
|
---|
543 | }
|
---|
544 | else {
|
---|
545 | errno = EINVAL; // Invalid how argument
|
---|
546 | }
|
---|
547 | return CurPos;
|
---|
548 | }
|
---|
549 |
|
---|
550 | /** The directory path is created with the access permissions specified by
|
---|
551 | perms.
|
---|
552 |
|
---|
553 | The directory is closed after it is created.
|
---|
554 |
|
---|
555 | @param[in] path The path to a directory to create.
|
---|
556 | @param[in] perms Permissions as defined in <sys/stat.h>
|
---|
557 |
|
---|
558 | @retval 0 The directory was created successfully.
|
---|
559 | @retval -1 An error occurred and error codes are stored in errno and EFIerrno.
|
---|
560 | **/
|
---|
561 | int
|
---|
562 | mkdir (const char *path, __mode_t perms)
|
---|
563 | {
|
---|
564 | wchar_t *NewPath;
|
---|
565 | DeviceNode *Node;
|
---|
566 | char *GenI;
|
---|
567 | RETURN_STATUS Status;
|
---|
568 | int Instance = 0;
|
---|
569 | int retval = 0;
|
---|
570 |
|
---|
571 | Status = ParsePath(path, &NewPath, &Node, &Instance, NULL);
|
---|
572 | if(Status == RETURN_SUCCESS) {
|
---|
573 | GenI = Node->InstanceList;
|
---|
574 | if(GenI == NULL) {
|
---|
575 | errno = EPERM;
|
---|
576 | retval = -1;
|
---|
577 | }
|
---|
578 | else {
|
---|
579 | //GenI += (Instance * Node->InstanceSize);
|
---|
580 | retval = ((GenericInstance *)GenI)->Abstraction.fo_mkdir( path, perms);
|
---|
581 | }
|
---|
582 | free(NewPath);
|
---|
583 | }
|
---|
584 | else {
|
---|
585 | retval = -1;
|
---|
586 | }
|
---|
587 | return retval;
|
---|
588 | }
|
---|
589 |
|
---|
590 | /** Open a file.
|
---|
591 | The open() function establishes the connection between a file and a file
|
---|
592 | descriptor. It creates an open file description that refers to a file
|
---|
593 | and a file descriptor that refers to that open file description. The file
|
---|
594 | descriptor is used by other I/O functions to refer to that file.
|
---|
595 |
|
---|
596 | The open() function returns a file descriptor for the named file that is
|
---|
597 | the lowest file descriptor not currently open for that process. The open
|
---|
598 | file description is new, and therefore the file descriptor shall not
|
---|
599 | share it with any other process in the system.
|
---|
600 |
|
---|
601 | The file offset used to mark the current position within the file is set
|
---|
602 | to the beginning of the file.
|
---|
603 |
|
---|
604 | The EFI ShellOpenFileByName() function is used to perform the low-level
|
---|
605 | file open operation. The primary task of open() is to translate from the
|
---|
606 | flags used in the <stdio.h> environment to those used by the EFI function.
|
---|
607 |
|
---|
608 | The file status flags and file access modes of the open file description
|
---|
609 | are set according to the value of oflags.
|
---|
610 |
|
---|
611 | Values for oflags are constructed by a bitwise-inclusive OR of flags from
|
---|
612 | the following list, defined in <fcntl.h>. Applications shall specify
|
---|
613 | exactly one of { O_RDONLY, O_RDWR, O_WRONLY } in the value of oflags.
|
---|
614 | Any combination of { O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL } may
|
---|
615 | also be specified in oflags.
|
---|
616 |
|
---|
617 | The only valid flag combinations for ShellOpenFileByName() are:
|
---|
618 | - Read
|
---|
619 | - Read/Write
|
---|
620 | - Create/Read/Write
|
---|
621 |
|
---|
622 | Values for mode specify the access permissions for newly created files.
|
---|
623 | The mode value is saved in the FD to indicate permissions for further operations.
|
---|
624 |
|
---|
625 | O_RDONLY -- flags = EFI_FILE_MODE_READ -- this is always done
|
---|
626 | O_WRONLY -- flags |= EFI_FILE_MODE_WRITE
|
---|
627 | O_RDWR -- flags |= EFI_FILE_MODE_WRITE -- READ is already set
|
---|
628 |
|
---|
629 | O_NONBLOCK -- ignored
|
---|
630 | O_APPEND -- Seek to EOF before every write
|
---|
631 | O_CREAT -- flags |= EFI_FILE_MODE_CREATE
|
---|
632 | O_TRUNC -- delete first then create new
|
---|
633 | O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
|
---|
634 |
|
---|
635 | @param[in] Path The path argument points to a pathname naming the
|
---|
636 | object to be opened.
|
---|
637 | @param[in] oflags File status flags and file access modes of the
|
---|
638 | open file description.
|
---|
639 | @param[in] mode File access permission bits as defined in
|
---|
640 | <sys/stat.h>. Only used if a file is created
|
---|
641 | as a result of the open.
|
---|
642 |
|
---|
643 | @return Upon successful completion, open() opens the file and returns
|
---|
644 | a non-negative integer representing the lowest numbered
|
---|
645 | unused file descriptor. Otherwise, open returns -1 and sets
|
---|
646 | errno to indicate the error. If a negative value is
|
---|
647 | returned, no files are created or modified.
|
---|
648 | - EMFILE - No file descriptors available -- Max number already open.
|
---|
649 | - EINVAL - Bad value specified for oflags or mode.
|
---|
650 | - ENOMEM - Failure allocating memory for internal buffers.
|
---|
651 | - EEXIST - File exists and open attempted with (O_EXCL | O_CREAT) set.
|
---|
652 | - EIO - UEFI failure. Check value in EFIerrno.
|
---|
653 | **/
|
---|
654 | int
|
---|
655 | open(
|
---|
656 | const char *path,
|
---|
657 | int oflags,
|
---|
658 | int mode
|
---|
659 | )
|
---|
660 | {
|
---|
661 | wchar_t *NewPath;
|
---|
662 | wchar_t *MPath;
|
---|
663 | DeviceNode *Node;
|
---|
664 | struct __filedes *filp;
|
---|
665 | struct termios *Termio;
|
---|
666 | int Instance = 0;
|
---|
667 | RETURN_STATUS Status;
|
---|
668 | UINT32 OpenMode;
|
---|
669 | int fd = -1;
|
---|
670 | int doresult;
|
---|
671 |
|
---|
672 | Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
|
---|
673 | if(Status == RETURN_SUCCESS) {
|
---|
674 | if((Node == NULL) ||
|
---|
675 | (Node->InstanceList == NULL))
|
---|
676 | {
|
---|
677 | errno = EPERM;
|
---|
678 | }
|
---|
679 | else {
|
---|
680 | // Could add a test to see if the file name begins with a period.
|
---|
681 | // If it does, then add the HIDDEN flag to Attributes.
|
---|
682 |
|
---|
683 | // Get an available fd
|
---|
684 | fd = FindFreeFD( VALID_CLOSED );
|
---|
685 |
|
---|
686 | if( fd < 0 ) {
|
---|
687 | // All available FDs are in use
|
---|
688 | errno = EMFILE;
|
---|
689 | }
|
---|
690 | else {
|
---|
691 | filp = &gMD->fdarray[fd];
|
---|
692 | // Save the flags and mode in the File Descriptor
|
---|
693 | filp->Oflags = oflags;
|
---|
694 | filp->Omode = mode;
|
---|
695 |
|
---|
696 | doresult = Node->OpenFunc(Node, filp, Instance, NewPath, MPath);
|
---|
697 | if(doresult < 0) {
|
---|
698 | filp->f_iflags = 0; // Release this FD
|
---|
699 | fd = -1; // Indicate an error
|
---|
700 | }
|
---|
701 | else {
|
---|
702 | // Build our final f_iflags value
|
---|
703 | OpenMode = ( mode & S_ACC_READ ) ? S_ACC_READ : 0;
|
---|
704 | OpenMode |= ( mode & S_ACC_WRITE ) ? S_ACC_WRITE : 0;
|
---|
705 |
|
---|
706 | filp->f_iflags |= OpenMode;
|
---|
707 |
|
---|
708 | if((oflags & O_TTY_INIT) && (filp->f_iflags & _S_ITTY) && (filp->devdata != NULL)) {
|
---|
709 | // Initialize the device's termios flags to a "sane" value
|
---|
710 | Termio = &((cIIO *)filp->devdata)->Termio;
|
---|
711 | Termio->c_iflag = ICRNL | IGNSPEC;
|
---|
712 | Termio->c_oflag = OPOST | ONLCR | OXTABS | ONOEOT | ONOCR | ONLRET | OCTRL;
|
---|
713 | Termio->c_lflag = ECHO | ECHOE | ECHONL | ICANON;
|
---|
714 | Termio->c_cc[VERASE] = 0x08; // ^H Backspace
|
---|
715 | Termio->c_cc[VKILL] = 0x15; // ^U
|
---|
716 | Termio->c_cc[VINTR] = 0x03; // ^C Interrupt character
|
---|
717 | }
|
---|
718 | ++filp->RefCount;
|
---|
719 | FILE_SET_MATURE(filp);
|
---|
720 | }
|
---|
721 | }
|
---|
722 | }
|
---|
723 | free(NewPath);
|
---|
724 | }
|
---|
725 | free(MPath); // We don't need this any more.
|
---|
726 |
|
---|
727 | // return the fd of our now open file
|
---|
728 | return fd;
|
---|
729 | }
|
---|
730 |
|
---|
731 |
|
---|
732 | /**
|
---|
733 | Poll a list of file descriptors.
|
---|
734 |
|
---|
735 | The ::poll routine waits for up to timeout milliseconds for an event
|
---|
736 | to occur on one or more of the file descriptors listed. The event
|
---|
737 | types of interested are specified for each file descriptor in the events
|
---|
738 | field. The actual event detected is returned in the revents field of
|
---|
739 | the array. The
|
---|
740 | <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html">POSIX</a>
|
---|
741 | documentation is available online.
|
---|
742 |
|
---|
743 | @param[in] pfd Address of an array of pollfd structures.
|
---|
744 |
|
---|
745 | @param[in] nfds Number of elements in the array of pollfd structures.
|
---|
746 |
|
---|
747 | @param[in] timeout Length of time in milliseconds to wait for the event
|
---|
748 |
|
---|
749 | @return The number of file descriptors with detected events. Zero
|
---|
750 | indicates that the call timed out and -1 indicates an error.
|
---|
751 |
|
---|
752 | **/
|
---|
753 | int
|
---|
754 | poll (
|
---|
755 | struct pollfd * pfd,
|
---|
756 | nfds_t nfds,
|
---|
757 | int timeout
|
---|
758 | )
|
---|
759 | {
|
---|
760 | struct __filedes * pDescriptor;
|
---|
761 | struct pollfd * pEnd;
|
---|
762 | struct pollfd * pPollFD;
|
---|
763 | int SelectedFDs;
|
---|
764 | EFI_STATUS Status;
|
---|
765 | EFI_EVENT Timer;
|
---|
766 | UINT64 TimerTicks;
|
---|
767 |
|
---|
768 | //
|
---|
769 | // Create the timer for the timeout
|
---|
770 | //
|
---|
771 | Timer = NULL;
|
---|
772 | Status = EFI_SUCCESS;
|
---|
773 | if ( INFTIM != timeout ) {
|
---|
774 | Status = gBS->CreateEvent ( EVT_TIMER,
|
---|
775 | TPL_NOTIFY,
|
---|
776 | NULL,
|
---|
777 | NULL,
|
---|
778 | &Timer );
|
---|
779 | if ( !EFI_ERROR ( Status )) {
|
---|
780 | //
|
---|
781 | // Start the timeout timer
|
---|
782 | //
|
---|
783 | TimerTicks = timeout;
|
---|
784 | TimerTicks *= 1000 * 10;
|
---|
785 | Status = gBS->SetTimer ( Timer,
|
---|
786 | TimerRelative,
|
---|
787 | TimerTicks );
|
---|
788 | }
|
---|
789 | else {
|
---|
790 | SelectedFDs = -1;
|
---|
791 | errno = ENOMEM;
|
---|
792 | }
|
---|
793 | }
|
---|
794 | if ( !EFI_ERROR ( Status )) {
|
---|
795 | //
|
---|
796 | // Poll until an event is detected or the timer fires
|
---|
797 | //
|
---|
798 | SelectedFDs = 0;
|
---|
799 | errno = 0;
|
---|
800 | do {
|
---|
801 | //
|
---|
802 | // Poll the list of file descriptors
|
---|
803 | //
|
---|
804 | pPollFD = pfd;
|
---|
805 | pEnd = &pPollFD [ nfds ];
|
---|
806 | while ( pEnd > pPollFD ) {
|
---|
807 | //
|
---|
808 | // Validate the file descriptor
|
---|
809 | //
|
---|
810 | if ( !ValidateFD ( pPollFD->fd, VALID_OPEN )) {
|
---|
811 | errno = EINVAL;
|
---|
812 | return -1;
|
---|
813 | }
|
---|
814 |
|
---|
815 | //
|
---|
816 | // Poll the device or file
|
---|
817 | //
|
---|
818 | pDescriptor = &gMD->fdarray [ pPollFD->fd ];
|
---|
819 | pPollFD->revents = pDescriptor->f_ops->fo_poll ( pDescriptor,
|
---|
820 | pPollFD->events );
|
---|
821 |
|
---|
822 | //
|
---|
823 | // Determine if this file descriptor detected an event
|
---|
824 | //
|
---|
825 | if ( 0 != pPollFD->revents ) {
|
---|
826 | //
|
---|
827 | // Select this descriptor
|
---|
828 | //
|
---|
829 | SelectedFDs += 1;
|
---|
830 | }
|
---|
831 |
|
---|
832 | //
|
---|
833 | // Set the next file descriptor
|
---|
834 | //
|
---|
835 | pPollFD += 1;
|
---|
836 | }
|
---|
837 |
|
---|
838 | //
|
---|
839 | // Check for timeout
|
---|
840 | //
|
---|
841 | if ( NULL != Timer ) {
|
---|
842 | Status = gBS->CheckEvent ( Timer );
|
---|
843 | if ( EFI_SUCCESS == Status ) {
|
---|
844 | //
|
---|
845 | // Timeout
|
---|
846 | //
|
---|
847 | break;
|
---|
848 | }
|
---|
849 | else if ( EFI_NOT_READY == Status ) {
|
---|
850 | Status = EFI_SUCCESS;
|
---|
851 | }
|
---|
852 | }
|
---|
853 | } while (( 0 == SelectedFDs )
|
---|
854 | && ( EFI_SUCCESS == Status ));
|
---|
855 |
|
---|
856 | //
|
---|
857 | // Stop the timer
|
---|
858 | //
|
---|
859 | if ( NULL != Timer ) {
|
---|
860 | gBS->SetTimer ( Timer,
|
---|
861 | TimerCancel,
|
---|
862 | 0 );
|
---|
863 | }
|
---|
864 | }
|
---|
865 | else {
|
---|
866 | SelectedFDs = -1;
|
---|
867 | errno = EAGAIN;
|
---|
868 | }
|
---|
869 |
|
---|
870 | //
|
---|
871 | // Release the timer
|
---|
872 | //
|
---|
873 | if ( NULL != Timer ) {
|
---|
874 | gBS->CloseEvent ( Timer );
|
---|
875 | }
|
---|
876 |
|
---|
877 | //
|
---|
878 | // Return the number of selected file system descriptors
|
---|
879 | //
|
---|
880 | return SelectedFDs;
|
---|
881 | }
|
---|
882 |
|
---|
883 |
|
---|
884 | /** The rename() function changes the name of a file.
|
---|
885 | The From argument points to the pathname of the file to be renamed. The To
|
---|
886 | argument points to the new pathname of the file.
|
---|
887 |
|
---|
888 | If the From argument points to the pathname of a file that is not a
|
---|
889 | directory, the To argument shall not point to the pathname of a
|
---|
890 | directory. If the file named by the To argument exists, it shall be
|
---|
891 | removed and From renamed to To. Write access permission is required for
|
---|
892 | both the directory containing old and the directory containing To.
|
---|
893 |
|
---|
894 | If the From argument points to the pathname of a directory, the To
|
---|
895 | argument shall not point to the pathname of a file that is not a
|
---|
896 | directory. If the directory named by the To argument exists, it shall be
|
---|
897 | removed and From renamed to To.
|
---|
898 |
|
---|
899 | The To pathname shall not contain a path prefix that names From. Write
|
---|
900 | access permission is required for the directory containing From and the
|
---|
901 | directory containing To. If the From argument points to the pathname of a
|
---|
902 | directory, write access permission may be required for the directory named
|
---|
903 | by From, and, if it exists, the directory named by To.
|
---|
904 |
|
---|
905 | If the rename() function fails for any reason other than [EIO], any file
|
---|
906 | named by To shall be unaffected.
|
---|
907 |
|
---|
908 | @param[in] From Path to the file to be renamed.
|
---|
909 | @param[in] To The new name of From.
|
---|
910 |
|
---|
911 | @retval 0 Successful completion.
|
---|
912 | @retval -1 An error has occured and errno has been set to further specify the error.
|
---|
913 | Neither the file named by From nor the file named by To are
|
---|
914 | changed or created.
|
---|
915 | - ENXIO: Path specified is not supported by any loaded driver.
|
---|
916 | - ENOMEM: Insufficient memory to calloc a MapName buffer.
|
---|
917 | - EINVAL: The path parameter is not valid.
|
---|
918 | **/
|
---|
919 | int
|
---|
920 | rename(
|
---|
921 | const char *From,
|
---|
922 | const char *To
|
---|
923 | )
|
---|
924 | {
|
---|
925 | wchar_t *FromPath;
|
---|
926 | DeviceNode *FromNode;
|
---|
927 | char *GenI;
|
---|
928 | int Instance = 0;
|
---|
929 | RETURN_STATUS Status;
|
---|
930 | int retval = -1;
|
---|
931 |
|
---|
932 | Status = ParsePath(From, &FromPath, &FromNode, &Instance, NULL);
|
---|
933 | if(Status == RETURN_SUCCESS) {
|
---|
934 | GenI = FromNode->InstanceList;
|
---|
935 | if(GenI == NULL) {
|
---|
936 | errno = EPERM;
|
---|
937 | retval = -1;
|
---|
938 | }
|
---|
939 | else {
|
---|
940 | //GenI += (Instance * FromNode->InstanceSize);
|
---|
941 | retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( From, To);
|
---|
942 | }
|
---|
943 | free(FromPath);
|
---|
944 | }
|
---|
945 | return retval;
|
---|
946 | }
|
---|
947 |
|
---|
948 | /** Delete a specified directory.
|
---|
949 |
|
---|
950 | @param[in] path Path to the directory to delete.
|
---|
951 |
|
---|
952 | @retval -1 The directory couldn't be opened (doesn't exist).
|
---|
953 | @retval -1 The directory wasn't empty or an IO error occured.
|
---|
954 | **/
|
---|
955 | int
|
---|
956 | rmdir(
|
---|
957 | const char *path
|
---|
958 | )
|
---|
959 | {
|
---|
960 | struct __filedes *filp;
|
---|
961 | int fd;
|
---|
962 | int retval = -1;
|
---|
963 |
|
---|
964 | fd = open(path, O_RDWR, 0);
|
---|
965 | if(fd >= 0) {
|
---|
966 | filp = &gMD->fdarray[fd];
|
---|
967 |
|
---|
968 | retval = filp->f_ops->fo_rmdir(filp);
|
---|
969 | filp->f_iflags = 0; // Close this FD
|
---|
970 | filp->RefCount = 0; // No one using this FD
|
---|
971 | }
|
---|
972 | return retval;
|
---|
973 | }
|
---|
974 |
|
---|
975 | /** The fstat() function obtains information about an open file associated
|
---|
976 | with the file descriptor fd, and writes it to the area pointed to
|
---|
977 | by statbuf.
|
---|
978 |
|
---|
979 | The statbuf argument is a pointer to a stat structure, as defined
|
---|
980 | in <sys/stat.h>, into which information is placed concerning the file.
|
---|
981 |
|
---|
982 | The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
|
---|
983 | st_ctime, and st_mtime shall have meaningful values. The value of the
|
---|
984 | member st_nlink shall be set to the number of links to the file.
|
---|
985 |
|
---|
986 | The fstat() function shall update any time-related fields before writing
|
---|
987 | into the stat structure.
|
---|
988 |
|
---|
989 | The fstat() function is implemented using the ShellGetFileInfo()
|
---|
990 | function.
|
---|
991 |
|
---|
992 | The stat structure members which don't have direct analogs to EFI file
|
---|
993 | information are filled in as follows:
|
---|
994 | - st_mode Populated with information from fd
|
---|
995 | - st_ino Set to zero. (inode)
|
---|
996 | - st_dev Set to zero.
|
---|
997 | - st_uid Set to zero.
|
---|
998 | - st_gid Set to zero.
|
---|
999 | - st_nlink Set to one.
|
---|
1000 |
|
---|
1001 | @param[in] fd File descriptor as returned from open().
|
---|
1002 | @param[out] statbuf Buffer in which the file status is put.
|
---|
1003 |
|
---|
1004 | @retval 0 Successful Completion.
|
---|
1005 | @retval -1 An error has occurred and errno has been set to
|
---|
1006 | identify the error.
|
---|
1007 | **/
|
---|
1008 | int
|
---|
1009 | fstat (int fd, struct stat *statbuf)
|
---|
1010 | {
|
---|
1011 | int retval = -1;
|
---|
1012 | struct __filedes *filp;
|
---|
1013 |
|
---|
1014 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
1015 | filp = &gMD->fdarray[fd];
|
---|
1016 | retval = filp->f_ops->fo_stat(filp, statbuf, NULL);
|
---|
1017 | }
|
---|
1018 | else {
|
---|
1019 | errno = EBADF;
|
---|
1020 | }
|
---|
1021 | return retval;
|
---|
1022 | }
|
---|
1023 |
|
---|
1024 | /** Obtains information about the file pointed to by path.
|
---|
1025 |
|
---|
1026 | Opens the file pointed to by path, calls _EFI_FileInfo with the file's handle,
|
---|
1027 | then closes the file.
|
---|
1028 |
|
---|
1029 | @param[in] path Path to the file to obtain information about.
|
---|
1030 | @param[out] statbuf Buffer in which the file status is put.
|
---|
1031 |
|
---|
1032 | @retval 0 Successful Completion.
|
---|
1033 | @retval -1 An error has occurred and errno has been set to
|
---|
1034 | identify the error.
|
---|
1035 | **/
|
---|
1036 | int
|
---|
1037 | stat (const char *path, struct stat *statbuf)
|
---|
1038 | {
|
---|
1039 | int fd;
|
---|
1040 | int retval = -1;
|
---|
1041 | struct __filedes *filp;
|
---|
1042 |
|
---|
1043 | fd = open(path, O_RDONLY, 0);
|
---|
1044 | if(fd >= 0) {
|
---|
1045 | filp = &gMD->fdarray[fd];
|
---|
1046 | retval = filp->f_ops->fo_stat( filp, statbuf, NULL);
|
---|
1047 | close(fd);
|
---|
1048 | }
|
---|
1049 | return retval;
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | /** Same as stat since EFI doesn't have symbolic links.
|
---|
1053 |
|
---|
1054 | @param[in] path Path to the file to obtain information about.
|
---|
1055 | @param[out] statbuf Buffer in which the file status is put.
|
---|
1056 |
|
---|
1057 | @retval 0 Successful Completion.
|
---|
1058 | @retval -1 An error has occurred and errno has been set to
|
---|
1059 | identify the error.
|
---|
1060 | **/
|
---|
1061 | int
|
---|
1062 | lstat (const char *path, struct stat *statbuf)
|
---|
1063 | {
|
---|
1064 | return stat(path, statbuf);
|
---|
1065 | }
|
---|
1066 |
|
---|
1067 | /** Control a device.
|
---|
1068 |
|
---|
1069 | @param[in] fd Descriptor for the file to be acted upon.
|
---|
1070 | @param[in] request Specifies the operation to perform.
|
---|
1071 | @param[in,out] ... Zero or more parameters as required for request.
|
---|
1072 |
|
---|
1073 | @retval >=0 The operation completed successfully.
|
---|
1074 | @retval -1 An error occured. More information is in errno.
|
---|
1075 | **/
|
---|
1076 | int
|
---|
1077 | ioctl(
|
---|
1078 | int fd,
|
---|
1079 | unsigned long request,
|
---|
1080 | ...
|
---|
1081 | )
|
---|
1082 | {
|
---|
1083 | int retval = -1;
|
---|
1084 | struct __filedes *filp;
|
---|
1085 | va_list argp;
|
---|
1086 |
|
---|
1087 | va_start(argp, request);
|
---|
1088 |
|
---|
1089 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
1090 | filp = &gMD->fdarray[fd];
|
---|
1091 |
|
---|
1092 | if(request == FIODLEX) {
|
---|
1093 | /* set Delete-on-Close */
|
---|
1094 | filp->f_iflags |= FIF_DELCLOSE;
|
---|
1095 | retval = 0;
|
---|
1096 | }
|
---|
1097 | else if(request == FIONDLEX) {
|
---|
1098 | /* clear Delete-on-Close */
|
---|
1099 | filp->f_iflags &= ~FIF_DELCLOSE;
|
---|
1100 | retval = 0;
|
---|
1101 | }
|
---|
1102 | else {
|
---|
1103 | /* All other requests. */
|
---|
1104 | retval = filp->f_ops->fo_ioctl(filp, request, argp);
|
---|
1105 | }
|
---|
1106 | }
|
---|
1107 | else {
|
---|
1108 | errno = EBADF;
|
---|
1109 | }
|
---|
1110 | va_end(argp);
|
---|
1111 |
|
---|
1112 | return retval;
|
---|
1113 | }
|
---|
1114 |
|
---|
1115 | /** Read from a file.
|
---|
1116 |
|
---|
1117 | The read() function shall attempt to read nbyte bytes from the file
|
---|
1118 | associated with the open file descriptor, fildes, into the buffer pointed
|
---|
1119 | to by buf.
|
---|
1120 |
|
---|
1121 | Before any action described below is taken, and if nbyte is zero, the
|
---|
1122 | read() function may detect and return errors as described below. In the
|
---|
1123 | absence of errors, or if error detection is not performed, the read()
|
---|
1124 | function shall return zero and have no other results.
|
---|
1125 |
|
---|
1126 | On files that support seeking (for example, a regular file), the read()
|
---|
1127 | shall start at a position in the file given by the file offset associated
|
---|
1128 | with fildes. The file offset shall be incremented by the number of bytes
|
---|
1129 | actually read.
|
---|
1130 |
|
---|
1131 | Files that do not support seeking - for example, terminals - always read
|
---|
1132 | from the current position. The value of a file offset associated with
|
---|
1133 | such a file is undefined.
|
---|
1134 |
|
---|
1135 | No data transfer shall occur past the current end-of-file. If the
|
---|
1136 | starting position is at or after the end-of-file, 0 shall be returned.
|
---|
1137 |
|
---|
1138 | The read() function reads data previously written to a file. If any
|
---|
1139 | portion of a regular file prior to the end-of-file has not been written,
|
---|
1140 | read() shall return bytes with value 0. For example, lseek() allows the
|
---|
1141 | file offset to be set beyond the end of existing data in the file. If data
|
---|
1142 | is later written at this point, subsequent reads in the gap between the
|
---|
1143 | previous end of data and the newly written data shall return bytes with
|
---|
1144 | value 0 until data is written into the gap.
|
---|
1145 |
|
---|
1146 | Upon successful completion, where nbyte is greater than 0, read() shall
|
---|
1147 | mark for update the st_atime field of the file, and shall return the
|
---|
1148 | number of bytes read. This number shall never be greater than nbyte. The
|
---|
1149 | value returned may be less than nbyte if the number of bytes left in the
|
---|
1150 | file is less than nbyte, if the read() request was interrupted by a
|
---|
1151 | signal, or if the file is a pipe or FIFO or special file and has fewer
|
---|
1152 | than nbyte bytes immediately available for reading. For example, a read()
|
---|
1153 | from a file associated with a terminal may return one typed line of data.
|
---|
1154 |
|
---|
1155 | If fildes does not refer to a directory, the function reads the requested
|
---|
1156 | number of bytes from the file at the file's current position and returns
|
---|
1157 | them in buf. If the read goes beyond the end of the file, the read
|
---|
1158 | length is truncated to the end of the file. The file's current position is
|
---|
1159 | increased by the number of bytes returned.
|
---|
1160 |
|
---|
1161 | If fildes refers to a directory, the function reads the directory entry at
|
---|
1162 | the file's current position and returns the entry in buf. If buf
|
---|
1163 | is not large enough to hold the current directory entry, then
|
---|
1164 | errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
|
---|
1165 | current file position is not updated. The size of the buffer needed to read
|
---|
1166 | the entry will be returned as a negative number. On success, the current
|
---|
1167 | position is updated to the next directory entry. If there are no more
|
---|
1168 | directory entries, the read returns a zero-length buffer.
|
---|
1169 | EFI_FILE_INFO is the structure returned as the directory entry.
|
---|
1170 |
|
---|
1171 | @param[in] fildes Descriptor of the file to be read.
|
---|
1172 | @param[out] buf Pointer to location in which to store the read data.
|
---|
1173 | @param[in] nbyte Maximum number of bytes to be read.
|
---|
1174 |
|
---|
1175 | @return Upon successful completion, read() returns a non-negative integer
|
---|
1176 | indicating the number of bytes actually read. Otherwise, the
|
---|
1177 | functions return a negative value and sets errno to indicate the
|
---|
1178 | error. If errno is EBUFSIZE, the absolute value of the
|
---|
1179 | return value indicates the size of the buffer needed to read
|
---|
1180 | the directory entry.
|
---|
1181 | **/
|
---|
1182 | ssize_t
|
---|
1183 | read (int fildes, void *buf, size_t nbyte)
|
---|
1184 | {
|
---|
1185 | struct __filedes *filp;
|
---|
1186 | cIIO *IIO;
|
---|
1187 | ssize_t BufSize;
|
---|
1188 |
|
---|
1189 | BufSize = (ssize_t)nbyte;
|
---|
1190 | if(BufSize > 0) {
|
---|
1191 | if(ValidateFD( fildes, VALID_OPEN)) {
|
---|
1192 | filp = &gMD->fdarray[fildes];
|
---|
1193 |
|
---|
1194 | IIO = filp->devdata;
|
---|
1195 | if(isatty(fildes) && (IIO != NULL)) {
|
---|
1196 | BufSize = IIO->Read(filp, nbyte, buf);
|
---|
1197 | }
|
---|
1198 | else {
|
---|
1199 | BufSize = filp->f_ops->fo_read(filp, &filp->f_offset, nbyte, buf);
|
---|
1200 | }
|
---|
1201 | }
|
---|
1202 | else {
|
---|
1203 | errno = EBADF;
|
---|
1204 | BufSize = -1;
|
---|
1205 | }
|
---|
1206 | }
|
---|
1207 | return BufSize;
|
---|
1208 | }
|
---|
1209 |
|
---|
1210 | /** Write data to a file.
|
---|
1211 |
|
---|
1212 | This function writes the specified number of bytes to the file at the current
|
---|
1213 | file position. The current file position is advanced the actual number of bytes
|
---|
1214 | written, which is returned in BufferSize. Partial writes only occur when there
|
---|
1215 | has been a data error during the write attempt (such as "volume space full").
|
---|
1216 | The file is automatically grown to hold the data if required. Direct writes to
|
---|
1217 | opened directories are not supported.
|
---|
1218 |
|
---|
1219 | If fildes refers to a terminal device, isatty() returns TRUE, a partial write
|
---|
1220 | will occur if a NULL or EOF character is encountered before n characters have
|
---|
1221 | been written. Characters inserted due to line-end translations will not be
|
---|
1222 | counted. Unconvertable characters are translated into the UEFI character
|
---|
1223 | BLOCKELEMENT_LIGHT_SHADE.
|
---|
1224 |
|
---|
1225 | Since the UEFI console device works on wide characters, the buffer is assumed
|
---|
1226 | to contain a single-byte character stream which is then translated to wide
|
---|
1227 | characters using the mbtowc() functions. The resulting wide character stream
|
---|
1228 | is what is actually sent to the UEFI console.
|
---|
1229 |
|
---|
1230 | @param[in] fd Descriptor of file to be written to.
|
---|
1231 | @param[in] buf Pointer to data to write to the file.
|
---|
1232 | @param[in] nbyte Number of bytes to be written to the file.
|
---|
1233 |
|
---|
1234 | @retval >=0 Number of bytes actually written to the file.
|
---|
1235 | @retval <0 An error occurred. More data is provided by errno.
|
---|
1236 | **/
|
---|
1237 | ssize_t
|
---|
1238 | write (int fd, const void *buf, size_t nbyte)
|
---|
1239 | {
|
---|
1240 | struct __filedes *filp;
|
---|
1241 | cIIO *IIO;
|
---|
1242 | ssize_t BufSize;
|
---|
1243 |
|
---|
1244 | BufSize = (ssize_t)nbyte;
|
---|
1245 |
|
---|
1246 | if(ValidateFD( fd, VALID_OPEN)) {
|
---|
1247 | filp = &gMD->fdarray[fd];
|
---|
1248 | if ((filp->Oflags & O_ACCMODE) != 0) {
|
---|
1249 | // File is open for writing
|
---|
1250 | IIO = filp->devdata;
|
---|
1251 | if(isatty(fd) && (IIO != NULL)) {
|
---|
1252 | // Output to an Interactive I/O device
|
---|
1253 | BufSize = IIO->Write(filp, buf, nbyte);
|
---|
1254 | }
|
---|
1255 | else {
|
---|
1256 | // Output to a file, socket, pipe, etc.
|
---|
1257 | BufSize = filp->f_ops->fo_write(filp, &filp->f_offset, nbyte, buf);
|
---|
1258 | }
|
---|
1259 | }
|
---|
1260 | else {
|
---|
1261 | // File is NOT open for writing
|
---|
1262 | errno = EINVAL;
|
---|
1263 | BufSize = -1;
|
---|
1264 | }
|
---|
1265 | }
|
---|
1266 | else {
|
---|
1267 | // fd is not for a valid open file
|
---|
1268 | errno = EBADF;
|
---|
1269 | BufSize = -1;
|
---|
1270 | }
|
---|
1271 | return BufSize;
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | /** Gets the current working directory.
|
---|
1275 |
|
---|
1276 | The getcwd() function shall place an absolute pathname of the current
|
---|
1277 | working directory in the array pointed to by buf, and return buf.The
|
---|
1278 | size argument is the size in bytes of the character array pointed to
|
---|
1279 | by the buf argument.
|
---|
1280 |
|
---|
1281 | @param[in,out] buf The buffer to fill.
|
---|
1282 | @param[in] size The number of bytes in buffer.
|
---|
1283 |
|
---|
1284 | @retval NULL The function failed. The value in errno provides
|
---|
1285 | further information about the cause of the failure.
|
---|
1286 | Values for errno are:
|
---|
1287 | - EINVAL: buf is NULL or size is zero.
|
---|
1288 | - ENOENT: directory does not exist.
|
---|
1289 | - ERANGE: buf size is too small to hold CWD
|
---|
1290 |
|
---|
1291 | @retval buf The function completed successfully.
|
---|
1292 | **/
|
---|
1293 | char
|
---|
1294 | *getcwd (char *buf, size_t size)
|
---|
1295 | {
|
---|
1296 | CONST CHAR16 *Cwd;
|
---|
1297 |
|
---|
1298 | if (size == 0 || buf == NULL) {
|
---|
1299 | errno = EINVAL;
|
---|
1300 | return NULL;
|
---|
1301 | }
|
---|
1302 |
|
---|
1303 | Cwd = ShellGetCurrentDir(NULL);
|
---|
1304 | if (Cwd == NULL) {
|
---|
1305 | errno = ENOENT;
|
---|
1306 | return NULL;
|
---|
1307 | }
|
---|
1308 | if (size < ((StrLen (Cwd) + 1) * sizeof (CHAR8))) {
|
---|
1309 | errno = ERANGE;
|
---|
1310 | return (NULL);
|
---|
1311 | }
|
---|
1312 | return (UnicodeStrToAsciiStr(Cwd, buf));
|
---|
1313 | }
|
---|
1314 |
|
---|
1315 | /** Change the current working directory.
|
---|
1316 |
|
---|
1317 | The chdir() function shall cause the directory named by the pathname
|
---|
1318 | pointed to by the path argument to become the current working directory;
|
---|
1319 | that is, the starting point for path searches for pathnames not beginning
|
---|
1320 | with '/'.
|
---|
1321 |
|
---|
1322 | @param[in] path The new path to set.
|
---|
1323 |
|
---|
1324 | @retval 0 Operation completed successfully.
|
---|
1325 | @retval -1 Function failed. The value in errno provides more
|
---|
1326 | information on the cause of failure:
|
---|
1327 | - EPERM: Operation not supported with this Shell version.
|
---|
1328 | - ENOMEM: Unable to allocate memory.
|
---|
1329 | - ENOENT: Target directory does not exist.
|
---|
1330 |
|
---|
1331 | @todo Add non-NEW-shell CWD changing.
|
---|
1332 | **/
|
---|
1333 | int
|
---|
1334 | chdir (const char *path)
|
---|
1335 | {
|
---|
1336 | CONST CHAR16 *Cwd;
|
---|
1337 | EFI_STATUS Status;
|
---|
1338 | CHAR16 *UnicodePath;
|
---|
1339 |
|
---|
1340 | /* Old Shell does not support Set Current Dir. */
|
---|
1341 | if(gEfiShellProtocol != NULL) {
|
---|
1342 | Cwd = ShellGetCurrentDir(NULL);
|
---|
1343 | if (Cwd != NULL) {
|
---|
1344 | /* We have shell support */
|
---|
1345 | UnicodePath = AllocatePool(((AsciiStrLen (path) + 1) * sizeof (CHAR16)));
|
---|
1346 | if (UnicodePath == NULL) {
|
---|
1347 | errno = ENOMEM;
|
---|
1348 | return -1;
|
---|
1349 | }
|
---|
1350 | AsciiStrToUnicodeStr(path, UnicodePath);
|
---|
1351 | Status = gEfiShellProtocol->SetCurDir(NULL, UnicodePath);
|
---|
1352 | FreePool(UnicodePath);
|
---|
1353 | if (EFI_ERROR(Status)) {
|
---|
1354 | errno = ENOENT;
|
---|
1355 | return -1;
|
---|
1356 | } else {
|
---|
1357 | return 0;
|
---|
1358 | }
|
---|
1359 | }
|
---|
1360 | }
|
---|
1361 | /* Add here for non-shell */
|
---|
1362 | errno = EPERM;
|
---|
1363 | return -1;
|
---|
1364 | }
|
---|
1365 |
|
---|
1366 | /** Get the foreground process group ID associated with a terminal.
|
---|
1367 |
|
---|
1368 | Just returns the Image Handle for the requestor since UEFI does not have
|
---|
1369 | a concept of processes or groups.
|
---|
1370 |
|
---|
1371 | @param[in] x Ignored.
|
---|
1372 |
|
---|
1373 | @return Returns the Image Handle of the application or driver which
|
---|
1374 | called this function.
|
---|
1375 | **/
|
---|
1376 | pid_t tcgetpgrp (int x)
|
---|
1377 | {
|
---|
1378 | return ((pid_t)(UINTN)(gImageHandle));
|
---|
1379 | }
|
---|
1380 |
|
---|
1381 | /** Get the process group ID of the calling process.
|
---|
1382 |
|
---|
1383 | Just returns the Image Handle for the requestor since UEFI does not have
|
---|
1384 | a concept of processes or groups.
|
---|
1385 |
|
---|
1386 | @return Returns the Image Handle of the application or driver which
|
---|
1387 | called this function.
|
---|
1388 | **/
|
---|
1389 | pid_t getpgrp(void)
|
---|
1390 | {
|
---|
1391 | return ((pid_t)(UINTN)(gImageHandle));
|
---|
1392 | }
|
---|
1393 |
|
---|
1394 | /* Internal worker function for utimes.
|
---|
1395 | This works around an error produced by GCC when the va_* macros
|
---|
1396 | are used within a function with a fixed number of arguments.
|
---|
1397 | */
|
---|
1398 | static
|
---|
1399 | int
|
---|
1400 | EFIAPI
|
---|
1401 | va_Utimes(
|
---|
1402 | const char *path,
|
---|
1403 | ...
|
---|
1404 | )
|
---|
1405 | {
|
---|
1406 | struct __filedes *filp;
|
---|
1407 | va_list ap;
|
---|
1408 | int fd;
|
---|
1409 | int retval = -1;
|
---|
1410 |
|
---|
1411 | va_start(ap, path);
|
---|
1412 | fd = open(path, O_RDWR, 0);
|
---|
1413 | if(fd >= 0) {
|
---|
1414 | filp = &gMD->fdarray[fd];
|
---|
1415 | retval = filp->f_ops->fo_ioctl( filp, FIOSETIME, ap);
|
---|
1416 | close(fd);
|
---|
1417 | }
|
---|
1418 | va_end(ap);
|
---|
1419 | return retval;
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 | /** Set file access and modification times.
|
---|
1423 |
|
---|
1424 | @param[in] path Path to the file to be modified.
|
---|
1425 | @param[in] times Pointer to an array of two timeval structures
|
---|
1426 |
|
---|
1427 | @retval 0 File times successfully set.
|
---|
1428 | @retval -1 An error occured. Error type in errno.
|
---|
1429 | **/
|
---|
1430 | int
|
---|
1431 | utimes(
|
---|
1432 | const char *path,
|
---|
1433 | const struct timeval *times
|
---|
1434 | )
|
---|
1435 | {
|
---|
1436 | return va_Utimes(path, times);
|
---|
1437 | }
|
---|