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