diff options
author | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-07-30 00:30:44 +0000 |
---|---|---|
committer | darylm503 <darylm503@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-07-30 00:30:44 +0000 |
commit | d7ce700605e1af0e455e31ec11f19ff21d26b525 (patch) | |
tree | 243b582ac3350e8c6ce6ca96fff13805318fd65c /StdLib/LibC | |
parent | f766dd76fde231ecd4f2e9faf99293e90902cebb (diff) | |
download | edk2-platforms-d7ce700605e1af0e455e31ec11f19ff21d26b525.tar.xz |
Add Socket Libraries.
Add Posix functions for porting compatibility.
Fix compliance issues with ISO/IEC 9899:199409
New Functions:
setenv(), fparseln(), GetFileNameFromPath(), rename(),
realpath(), setprogname(), getprogname(), strlcat(), strlcpy(),
strsep(), setitimer(), getitimer(), timegm(), getopt(), basename(),
mkstemp(), ffs(), vsnprintf(), snprintf(), getpass(), usleep(), select(),
writev(), strcasecmp(), getcwd(), chdir(), tcgetpgrp(), getpgrp(), gettimeofday(),
bcopy(),
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12061 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'StdLib/LibC')
55 files changed, 2773 insertions, 350 deletions
diff --git a/StdLib/LibC/Locale/Locale.inf b/StdLib/LibC/Locale/Locale.inf index 5fee723f85..c891e3bfaf 100644 --- a/StdLib/LibC/Locale/Locale.inf +++ b/StdLib/LibC/Locale/Locale.inf @@ -63,12 +63,3 @@ [LibraryClasses]
LibC
LibCType
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-[BuildOptions]
- GCC:*_*_*_CC_FLAGS = -fno-builtin
diff --git a/StdLib/LibC/Locale/_wcstoul.h b/StdLib/LibC/Locale/_wcstoul.h index ebfc330fe9..2131d4b5c1 100644 --- a/StdLib/LibC/Locale/_wcstoul.h +++ b/StdLib/LibC/Locale/_wcstoul.h @@ -42,6 +42,8 @@ NetBSD: _wcstoul.h,v 1.3 2005/11/29 03:11:59 christos Exp
*/
+#include <Library/BaseLib.h>
+
/*
* function template for wcstoul, wcstoull and wcstoumax.
*
@@ -102,8 +104,8 @@ _FUNCNAME( /*
* See strtoul for comments as to the logic used.
*/
- cutoff = __wUINT_MAX / (__wUINT)base;
- cutlim = (int)(__wUINT_MAX % (__wUINT)base);
+ cutoff = (__wUINT)DivU64x32 ((UINT64) __wUINT_MAX, (UINT32) base);
+ cutlim = (int) ModU64x32 ((UINT64) __wUINT_MAX, (UINT32) base);
for (acc = 0, any = 0;; wc = (wint_t) *s++) {
i = __wctoint((wchar_t)wc);
if (i == -1) {
diff --git a/StdLib/LibC/Locale/multibyte_sb.c b/StdLib/LibC/Locale/multibyte_sb.c index 6d57cd6c09..0a73898e61 100644 --- a/StdLib/LibC/Locale/multibyte_sb.c +++ b/StdLib/LibC/Locale/multibyte_sb.c @@ -137,7 +137,7 @@ wcrtomb( /* ps appears to be unused */
if (s == NULL)
- return 0;
+ return 1; /* Spec. says this should be 1. */
*s = (char) wchar;
return 1;
@@ -150,7 +150,12 @@ wctomb( )
{
- /* s may be NULL */
+ /*
+ If s is NULL just return if MB Characters have state
+ dependent encodings.
+ */
+ if (s == NULL)
+ return 0;
return (int)wcrtomb(s, wchar, NULL);
}
@@ -176,8 +181,10 @@ mbsrtowcs( if (n != 0) {
if (pwcs != NULL) {
do {
- if ((*pwcs++ = (wchar_t) *(*s)++) == 0)
+ if ((*pwcs++ = (wchar_t) *(*s)++) == 0) {
+ *s = NULL;
break;
+ }
count++;
} while (--n != 0);
} else {
@@ -232,8 +239,10 @@ wcsrtombs( if (n != 0) {
do {
- if ((*s++ = (char) *(*pwcs)++) == 0)
+ if ((*s++ = (char) *(*pwcs)++) == 0) {
+ *pwcs = NULL;
break;
+ }
count++;
} while (--n != 0);
}
@@ -266,7 +275,13 @@ btowc(int c) int
wctob(wint_t c)
{
- if (c == WEOF || c & ~0xFF)
+ /* wctob needs to be consistent with wcrtomb.
+ if wcrtomb says that a character is representable in 1 byte,
+ which this implementation always says, then wctob needs to
+ also represent the character as 1 byte.
+ */
+ if (c == WEOF) {
return EOF;
- return (int)c;
+ }
+ return (int)(c & 0xFF);
}
diff --git a/StdLib/LibC/Main/Main.c b/StdLib/LibC/Main/Main.c index 47103ce388..3a5cca5b24 100644 --- a/StdLib/LibC/Main/Main.c +++ b/StdLib/LibC/Main/Main.c @@ -8,13 +8,14 @@ This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
+ http://opensource.org/licenses/bsd-license.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -40,23 +41,30 @@ void __main() ;
}
-static
+/** Clean up data as required by the exit() function.
+
+**/
void
-FinalCleanup( void )
+exitCleanup(INTN ExitVal)
{
+ void (*CleanUp)(void); // Pointer to Cleanup Function
int i;
- /* Close any open files */
- for(i = OPEN_MAX - 1; i >= 0; --i) {
- (void)close(i); // Close properly handles closing a closed file.
+ if(gMD != NULL) {
+ gMD->ExitValue = (int)ExitVal;
+ CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
+
+ // Call all registered atexit functions in reverse order
+ i = gMD->num_atexit;
+ if( i > 0) {
+ do {
+ (gMD->atexit_handler[--i])();
+ } while( i > 0);
}
- /* Free the global MainData structure */
- if(gMD != NULL) {
- if(gMD->NCmdLine != NULL) {
- FreePool( gMD->NCmdLine );
+ if (CleanUp != NULL) {
+ CleanUp();
}
- FreePool( gMD );
}
}
@@ -71,6 +79,13 @@ ArgvConvert(UINTN Argc, CHAR16 **Argv) char *string;
INTN nArgvSize; /* Cumulative size of narrow Argv[i] */
+DEBUG_CODE_BEGIN();
+ Print(L"ArgvConvert called with %d arguments.\n", Argc);
+ for(count = 0; count < ((Argc > 5)? 5: Argc); ++count) {
+ Print(L"Argument[%d] = \"%s\".\n", count, Argv[count]);
+ }
+DEBUG_CODE_END();
+
nArgvSize = Argc;
/* Determine space needed for narrow Argv strings. */
for(count = 0; count < Argc; ++count) {
@@ -98,6 +113,7 @@ ArgvConvert(UINTN Argc, CHAR16 **Argv) nArgv[count] = string;
AVsz = wcstombs(string, Argv[count], nArgvSize);
string[AVsz] = 0; /* NULL terminate the argument */
+ DEBUG((DEBUG_INFO, "Cvt[%d] %d \"%s\" --> \"%a\"\n", (INT32)count, (INT32)AVsz, Argv[count], nArgv[count]));
string += AVsz + 1;
nArgvSize -= AVsz + 1;
if(nArgvSize < 0) {
@@ -119,7 +135,7 @@ ShellAppMain ( struct __filedes *mfd;
char **nArgv;
INTN ExitVal;
- INTN i;
+ int i;
ExitVal = (INTN)RETURN_SUCCESS;
gMD = AllocateZeroPool(sizeof(struct __MainData));
@@ -132,7 +148,6 @@ ShellAppMain ( _fltused = 1;
errno = 0;
EFIerrno = 0;
- gMD->FinalCleanup = &FinalCleanup;
#ifdef NT32dvm
gMD->ClocksPerSecond = 1; // For NT32 only
@@ -166,10 +181,33 @@ ShellAppMain ( ExitVal = (INTN)RETURN_INVALID_PARAMETER;
}
else {
- ExitVal = (INTN)main( (int)Argc, nArgv);
+ if( setjmp(gMD->MainExit) == 0) {
+ ExitVal = (INTN)main( (int)Argc, gMD->NArgV);
+ exitCleanup(ExitVal);
+ }
+ /* You reach here if:
+ * normal return from main()
+ * call to _Exit(), either directly or through exit().
+ */
+ ExitVal = (INTN)gMD->ExitValue;
+ }
+
+ if( ExitVal == EXIT_FAILURE) {
+ ExitVal = RETURN_ABORTED;
+ }
+
+ /* Close any open files */
+ for(i = OPEN_MAX - 1; i >= 0; --i) {
+ (void)close(i); // Close properly handles closing a closed file.
+ }
+
+ /* Free the global MainData structure */
+ if(gMD != NULL) {
+ if(gMD->NCmdLine != NULL) {
+ FreePool( gMD->NCmdLine );
+ }
+ FreePool( gMD );
}
}
- exit((int)ExitVal);
- /* Not Reached */
return ExitVal;
}
diff --git a/StdLib/LibC/Main/assert.c b/StdLib/LibC/Main/assert.c index 6bb53d6abd..a20a656ef0 100644 --- a/StdLib/LibC/Main/assert.c +++ b/StdLib/LibC/Main/assert.c @@ -18,7 +18,6 @@ #include <stdlib.h>
void
-EFIAPI
__assert(const char *func, const char *file, int line, const char *failedexpr)
{
if (func == NULL)
diff --git a/StdLib/LibC/Main/x86flt_rounds.c b/StdLib/LibC/Main/x86flt_rounds.c index d0478e2c1b..86b4846098 100644 --- a/StdLib/LibC/Main/x86flt_rounds.c +++ b/StdLib/LibC/Main/x86flt_rounds.c @@ -16,7 +16,6 @@ extern int internal_FPU_rmode( void ); static INT8 rmode[] = { 1, 3, 2, 0 };
int
-EFIAPI
__flt_rounds ( void )
{
return rmode[ internal_FPU_rmode() ];
diff --git a/StdLib/LibC/NetUtil/NetUtil.inf b/StdLib/LibC/NetUtil/NetUtil.inf index 537fe9cd42..9fc6b9b7be 100644 --- a/StdLib/LibC/NetUtil/NetUtil.inf +++ b/StdLib/LibC/NetUtil/NetUtil.inf @@ -48,12 +48,3 @@ LibStdLib
LibStdio
LibString
-
-################################################################
-#
-# The Build Options, below, are only used when building the Socket library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-#[BuildOptions]
-# MSFT:*_*_IA32_CC_FLAGS = /GL-
diff --git a/StdLib/LibC/StdLib/Environs.c b/StdLib/LibC/StdLib/Environs.c index 8472d0ef4c..40807279c9 100644 --- a/StdLib/LibC/StdLib/Environs.c +++ b/StdLib/LibC/StdLib/Environs.c @@ -29,6 +29,10 @@ #include <stdlib.h>
#include <MainData.h>
+/** Internal worker function used by exit().
+**/
+void exitCleanup(INTN ExitVal);
+
/* ################# Public Functions ################################### */
/** The abort function causes abnormal program termination to occur, unless
@@ -92,24 +96,7 @@ atexit(void (*handler)(void)) void
exit(int status)
{
- void (*CleanUp)(void); // Pointer to Cleanup Function
- int i;
-
- if(gMD != NULL) {
- CleanUp = gMD->cleanup; // Preserve the pointer to the Cleanup Function
-
- // Call all registered atexit functions in reverse order
- i = gMD->num_atexit;
- if( i > 0) {
- do {
- (gMD->atexit_handler[--i])();
- } while( i > 0);
- }
-
- if (CleanUp != NULL) {
- CleanUp();
- }
- }
+ exitCleanup((INTN) status);
_Exit(status);
}
@@ -129,17 +116,12 @@ exit(int status) void
_Exit(int status)
{
- RETURN_STATUS ExitVal = (RETURN_STATUS)status;
-
- if( ExitVal == EXIT_FAILURE) {
- ExitVal = RETURN_ABORTED;
- }
-
- if(gMD->FinalCleanup != NULL) {
- gMD->FinalCleanup(); // gMD does not exist when this returns.
- }
+ gMD->ExitValue = status; // Save our exit status. Allows a status of 0.
+ longjmp(gMD->MainExit, 0x55); // Get out of here. longjmp can't return 0. Use 0x55 for a non-zero value.
- gBS->Exit(gImageHandle, ExitVal, 0, NULL); /* abort() */
+#ifdef __GNUC__
+ __builtin__Exit(status); /* Keep GCC happy - never reached */
+#endif
}
/** If string is a null pointer, the system function determines whether the
diff --git a/StdLib/LibC/StdLib/NumericInt.c b/StdLib/LibC/StdLib/NumericInt.c index 058ad04959..97e52eb1bd 100644 --- a/StdLib/LibC/StdLib/NumericInt.c +++ b/StdLib/LibC/StdLib/NumericInt.c @@ -8,7 +8,7 @@ - atol: strtol(nptr, (char **)NULL, 10)
- atoll: strtoll(nptr, (char **)NULL, 10)
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -120,7 +120,7 @@ atoll(const char *nptr) static int
Digit2Val( int c)
{
- if(__isHexLetter(c)) { /* If c is one of [A-Fa-f]... */
+ if(isalpha(c)) { /* If c is one of [A-Za-z]... */
c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
}
return c - '0'; // Value returned is between 0 and 35, inclusive.
@@ -183,13 +183,18 @@ Digit2Val( int c) long
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
long Result = 0;
long Previous;
int temp;
BOOLEAN Negative = FALSE;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -204,9 +209,29 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) Negative = TRUE;
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long int)temp;
@@ -221,15 +246,15 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -247,12 +272,17 @@ strtol(const char * __restrict nptr, char ** __restrict endptr, int base) unsigned long
strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
unsigned long Result = 0;
unsigned long Previous;
int temp;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -262,9 +292,29 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) if(*nptr == '+') {
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long)temp;
@@ -273,12 +323,12 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -297,13 +347,18 @@ strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) long long
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
long long Result = 0;
long long Previous;
int temp;
BOOLEAN Negative = FALSE;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -318,9 +373,29 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) Negative = TRUE;
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (long long int)temp;
@@ -335,15 +410,15 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
if(Negative) {
Result = -Result;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
@@ -361,12 +436,17 @@ strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) unsigned long long
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
{
+ const char *pEnd;
unsigned long long Result = 0;
unsigned long long Previous;
int temp;
+ pEnd = nptr;
+
if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
*endptr = NULL;
+ }
return 0;
}
// Skip leading spaces.
@@ -376,9 +456,29 @@ strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) if(*nptr == '+') {
++nptr;
}
- if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
- nptr += 2;
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
}
+
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
Previous = Result;
Result = (Result * base) + (unsigned long long)temp;
@@ -387,12 +487,12 @@ strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) errno = ERANGE;
break;
}
- ++nptr;
+ pEnd = ++nptr;
}
// Save pointer to final sequence
- if( endptr != NULL) {
- *endptr = (char *)nptr;
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
}
return Result;
}
diff --git a/StdLib/LibC/StdLib/StdLib.inf b/StdLib/LibC/StdLib/StdLib.inf index 21d1c1f4aa..ce1c3052cb 100644 --- a/StdLib/LibC/StdLib/StdLib.inf +++ b/StdLib/LibC/StdLib/StdLib.inf @@ -1,7 +1,7 @@ ## @file
# Standard C library: StdLib implementations.
#
-# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -36,6 +36,8 @@ strtoumax.c
Xabs.c
Xdiv.c
+ realpath.c
+ setprogname.c
[Packages]
StdLib/StdLib.dec
@@ -53,6 +55,7 @@ LibC
LibCType
LibSignal
+ PathLib
################################################################
#
diff --git a/StdLib/LibC/StdLib/realpath.c b/StdLib/LibC/StdLib/realpath.c new file mode 100644 index 0000000000..b9f674dbce --- /dev/null +++ b/StdLib/LibC/StdLib/realpath.c @@ -0,0 +1,57 @@ +/** @file
+ Implement the realpath function.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <LibConfig.h>
+#include <Library/BaseLib.h>
+#include <Library/PathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <errno.h>
+
+/**
+ The realpath() function shall derive, from the pathname pointed to by
+ file_name, an absolute pathname that names the same file, whose resolution
+ does not involve '.', '..', or symbolic links. The generated pathname shall
+ be stored as a null-terminated string, up to a maximum of {PATH_MAX} bytes,
+ in the buffer pointed to by resolved_name.
+
+ If resolved_name is a null pointer, the behavior of realpath() is
+ implementation-defined.
+
+ @param[in] file_name The filename to convert.
+ @param[in,out] resolved_name The resultant name.
+
+ @retval NULL An error occured.
+ @return resolved_name.
+**/
+char *
+realpath(
+ char *file_name,
+ char *resolved_name
+ )
+{
+ CHAR16 *Temp;
+ if (file_name == NULL || resolved_name == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ Temp = AllocateZeroPool((1+AsciiStrLen(file_name))*sizeof(CHAR16));
+ if (Temp == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ AsciiStrToUnicodeStr(file_name, Temp);
+ PathCleanUpDirectories(Temp);
+ UnicodeStrToAsciiStr(Temp, resolved_name);
+ return (resolved_name);
+}
\ No newline at end of file diff --git a/StdLib/LibC/StdLib/setprogname.c b/StdLib/LibC/StdLib/setprogname.c new file mode 100644 index 0000000000..3f2bc53cd5 --- /dev/null +++ b/StdLib/LibC/StdLib/setprogname.c @@ -0,0 +1,64 @@ +/** @file setprogname and getprogname
+
+ $NetBSD: setprogname.c,v 1.5 2008/04/28 20:24:12 martin Exp $
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Todd Vierling.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <LibConfig.h>
+
+#ifndef HAVE_SETPROGNAME
+#include <string.h>
+
+static const char *__progname = NULL;
+
+void
+setprogname(const char *progname)
+{
+ __progname = strrchr(progname, '/');
+ if (__progname == NULL)
+ __progname = progname;
+ else
+ __progname++;
+}
+
+const char *
+getprogname(void)
+{
+ return __progname;
+}
+
+#endif
diff --git a/StdLib/LibC/StdLib/strtoumax.c b/StdLib/LibC/StdLib/strtoumax.c index 5bf64383d4..15658002a9 100644 --- a/StdLib/LibC/StdLib/strtoumax.c +++ b/StdLib/LibC/StdLib/strtoumax.c @@ -48,6 +48,8 @@ __RCSID("$NetBSD: strtoumax.c,v 1.1 2006/04/22 15:33:33 thorpej Exp $"); #include <inttypes.h>
#include <stddef.h>
+#include <Library/BaseLib.h>
+
#ifdef __weak_alias
__weak_alias(strtoumax, _strtoumax)
#endif
@@ -98,8 +100,8 @@ strtoumax(const char *nptr, char **endptr, int base) if (base == 0)
base = c == '0' ? 8 : 10;
- cutoff = UINTMAX_MAX / (uintmax_t)base;
- cutlim = (int)(UINTMAX_MAX % (uintmax_t)base);
+ cutoff = DivU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
+ cutlim = (int) ModU64x32 ((UINT64) UINTMAX_MAX, (UINT32) base);
for (acc = 0, any = 0;; c = (unsigned char) *s++) {
if (isdigit(c))
c -= '0';
diff --git a/StdLib/LibC/Stdio/Stdio.inf b/StdLib/LibC/Stdio/Stdio.inf index 9d2adef1f6..6edc8867e8 100644 --- a/StdLib/LibC/Stdio/Stdio.inf +++ b/StdLib/LibC/Stdio/Stdio.inf @@ -72,6 +72,7 @@ snprintf.c
vsnprintf.c
+ fparseln.c
# Wide character functions
fgetwc.c #
diff --git a/StdLib/LibC/Stdio/freopen.c b/StdLib/LibC/Stdio/freopen.c index 4d34497317..75a086b84b 100644 --- a/StdLib/LibC/Stdio/freopen.c +++ b/StdLib/LibC/Stdio/freopen.c @@ -104,7 +104,7 @@ freopen(const char *file, const char *mode, FILE *fp) (void) __sflush(fp);
/* if close is NULL, closing is a no-op, hence pointless */
isopen = fp->_close != NULL;
- if ((wantfd = fp->_file) < 0 && isopen) {
+ if (((wantfd = fp->_file) >= 0) && isopen) {
(void) (*fp->_close)(fp->_cookie);
isopen = 0;
}
@@ -127,7 +127,7 @@ freopen(const char *file, const char *mode, FILE *fp) * keep fp->_base: it may be the wrong size. This loses the effect
* of any setbuffer calls, but stdio has always done this before.
*/
- if (isopen && f != wantfd)
+ if (isopen && (f != wantfd))
(void) (*fp->_close)(fp->_cookie);
if (fp->_flags & __SMBF)
free((char *)fp->_bf._base);
diff --git a/StdLib/LibC/Stdio/fseeko.c b/StdLib/LibC/Stdio/fseeko.c index 7fc7e42661..662d25f91a 100644 --- a/StdLib/LibC/Stdio/fseeko.c +++ b/StdLib/LibC/Stdio/fseeko.c @@ -238,6 +238,7 @@ fseeko(FILE *fp, off_t offset, int whence) fp->_r = (int)(n - o);
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_flags &= ~__SEOF;
FUNLOCKFILE(fp);
return (0);
@@ -261,6 +262,7 @@ fseeko(FILE *fp, off_t offset, int whence) fp->_p = fp->_bf._base;
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_flags &= ~__SEOF;
n = (int)(target - curoff);
if (n) {
@@ -290,9 +292,10 @@ dumb: /* success: clear EOF indicator and discard ungetc() data */
if (HASUB(fp))
FREEUB(fp);
+ WCIO_FREE(fp); /* Should this really be unconditional??? */
fp->_p = fp->_bf._base;
fp->_r = 0;
- /* fp->_w = 0; */ /* unnecessary (I think...) */
+ fp->_w = 0;
fp->_flags &= ~__SEOF;
FUNLOCKFILE(fp);
//Print(L"%a: %d\n", __func__, __LINE__);
diff --git a/StdLib/LibC/Stdio/gettemp.c b/StdLib/LibC/Stdio/gettemp.c index 1bd7dd3924..7b1c564c9a 100644 --- a/StdLib/LibC/Stdio/gettemp.c +++ b/StdLib/LibC/Stdio/gettemp.c @@ -45,7 +45,7 @@ #include "nbtool_config.h"
#endif
-#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP || !HAVE_MKDTEMP
+#if !defined(HAVE_NBTOOL_CONFIG_H) || !defined(HAVE_MKSTEMP) || !defined(HAVE_MKDTEMP)
#include <sys/EfiCdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
diff --git a/StdLib/LibC/Stdio/local.h b/StdLib/LibC/Stdio/local.h index f9eaba9989..262deb3611 100644 --- a/StdLib/LibC/Stdio/local.h +++ b/StdLib/LibC/Stdio/local.h @@ -64,11 +64,11 @@ extern int _fwalk(int (*)(FILE *)); extern char *_mktemp(char *);
extern int __swsetup(FILE *);
extern int __sflags(const char *, int *);
-extern int __svfscanf(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_)
+extern int __svfscanf(FILE * __restrict, const char * __restrict, va_list)
__attribute__((__format__(__scanf__, 2, 0)));
-extern int __svfscanf_unlocked(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_)
+extern int __svfscanf_unlocked(FILE * __restrict, const char * __restrict, va_list)
__attribute__((__format__(__scanf__, 2, 0)));
-extern int __vfprintf_unlocked(FILE * __restrict, const char * __restrict, _BSD_VA_LIST_);
+extern int __vfprintf_unlocked(FILE * __restrict, const char * __restrict, va_list);
extern int __sdidinit;
@@ -80,8 +80,8 @@ extern wint_t __fputwc_unlock(wchar_t, FILE *); extern char *__fgetstr(FILE * __restrict, size_t * __restrict, int);
extern int __slbexpand(FILE *, size_t);
-extern int __vfwprintf_unlocked(FILE *, const wchar_t *, _BSD_VA_LIST_);
-extern int __vfwscanf_unlocked(FILE * __restrict, const wchar_t * __restrict, _BSD_VA_LIST_);
+extern int __vfwprintf_unlocked(FILE *, const wchar_t *, va_list);
+extern int __vfwscanf_unlocked(FILE * __restrict, const wchar_t * __restrict, va_list);
/*
* Return true iff the given FILE cannot be written now.
diff --git a/StdLib/LibC/Stdio/mkstemp.c b/StdLib/LibC/Stdio/mkstemp.c index 7ea578ce4a..d2962214dd 100644 --- a/StdLib/LibC/Stdio/mkstemp.c +++ b/StdLib/LibC/Stdio/mkstemp.c @@ -34,7 +34,7 @@ #include "nbtool_config.h"
#endif
-#if !HAVE_NBTOOL_CONFIG_H || !HAVE_MKSTEMP
+#if !defined(HAVE_NBTOOL_CONFIG_H) || !defined(HAVE_MKSTEMP)
#include <sys/EfiCdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
diff --git a/StdLib/LibC/Stdio/setbuffer.c b/StdLib/LibC/Stdio/setbuffer.c index 9527a4b3f6..761f67f88c 100644 --- a/StdLib/LibC/Stdio/setbuffer.c +++ b/StdLib/LibC/Stdio/setbuffer.c @@ -1,6 +1,13 @@ -/* $NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp $ */
+/*
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -30,16 +37,12 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- */
+
+ NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp
+ setbuffer.c 8.1 (Berkeley) 6/4/93
+*/
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
-#if defined(LIBC_SCCS) && !defined(lint)
-#if 0
-static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: setbuffer.c,v 1.10 2003/08/07 16:43:31 agc Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
#include <assert.h>
#include <errno.h>
diff --git a/StdLib/LibC/Stdio/vfwprintf.c b/StdLib/LibC/Stdio/vfwprintf.c index 3c5332ac4a..0554edb645 100644 --- a/StdLib/LibC/Stdio/vfwprintf.c +++ b/StdLib/LibC/Stdio/vfwprintf.c @@ -1056,8 +1056,6 @@ reswitch: switch (ch) { xdigs = xdigs_upper;
expchar = 'P';
}
- if (prec >= 0)
- prec++;
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
dtoaresult =
@@ -1092,10 +1090,8 @@ reswitch: switch (ch) { case 'e':
case 'E':
expchar = ch;
- if (prec < 0) /* account for digit before decpt */
- prec = DEFPREC + 1;
- else
- prec++;
+ if (prec < 0)
+ prec = DEFPREC;
goto fp_begin;
case 'f':
case 'F':
@@ -1165,10 +1161,8 @@ fp_common: case 'e':
case 'E':
expchar = ch;
- if (prec < 0) /* account for digit before decpt */
- prec = DEFPREC /* + 1*/ ;
- else
- prec++;
+ if (prec < 0)
+ prec = DEFPREC;
goto fp_begin;
case 'f':
case 'F':
@@ -1242,16 +1236,21 @@ fp_begin: /*
* Make %[gG] smell like %[eE], but
* trim trailing zeroes if no # flag.
+ *
+ * Note: The precision field used with [gG] is the number significant
+ * digits to print. When converting to [eE] the digit before the
+ * decimal must not be included in the precision value.
*/
if (!(flags & ALT))
- prec = ndig;
+ prec = ndig - 1;
}
}
if (expchar) {
+ dprec = prec; /* In some cases dprec will not be set. Make sure it is set now */
expsize = exponent(expstr, expt - 1, expchar);
- size = expsize + prec;
- if (prec > 1 || flags & ALT)
- ++size;
+ size = expsize + prec + 1; /* Leading digit + exponent string + precision */
+ if (prec >= 1 || flags & ALT)
+ ++size; /* Decimal point is added to character count */
} else {
/* space for digits before decimal point */
if (expt > 0)
@@ -1322,7 +1321,7 @@ fp_begin: * defined manner.''
* -- ANSI X3J11
*/
- ujval = (uintmax_t)GETARG(void *);
+ ujval = (uintmax_t) (UINTN) GETARG(void *);
base = 16;
xdigs = xdigs_lower;
flags = flags | INTMAXT;
@@ -1332,7 +1331,7 @@ fp_begin: flags |= LONGINT;
/*FALLTHROUGH*/
case 's':
- if ((flags & LONGINT) != MULTI) {
+ if (((flags & LONGINT) ? 1:0) != MULTI) {
if ((result = GETARG(CHAR_T *)) == NULL)
result = STRCONST("(null)");
} else {
@@ -1538,7 +1537,7 @@ number: if ((dprec = prec) >= 0) PRINTANDPAD(result, convbuf + ndig, prec,
zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
- if (prec > 1 || flags & ALT) {
+ if (prec >= 1 || flags & ALT) {
buf[0] = *result++;
buf[1] = *decimal_point;
PRINT(buf, 2);
@@ -2003,8 +2002,6 @@ cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, *decpt = -ndigits + 1;
bp += *decpt;
}
- if (value == 0) /* kludge for __dtoa irregularity */
- rve = bp;
while (rve < bp)
*rve++ = '0';
}
diff --git a/StdLib/LibC/Stdio/vfwscanf.c b/StdLib/LibC/Stdio/vfwscanf.c index 3d7404171b..7bf3f66690 100644 --- a/StdLib/LibC/Stdio/vfwscanf.c +++ b/StdLib/LibC/Stdio/vfwscanf.c @@ -198,7 +198,7 @@ literal: goto input_failure;
if (wi != c) {
ungetwc(wi, fp);
- goto input_failure;
+ goto match_failure;
}
nread++;
continue;
@@ -721,20 +721,19 @@ literal: if ((width = parsefloat(fp, buf, buf + width)) == 0)
goto match_failure;
if ((flags & SUPPRESS) == 0) {
-#ifdef notyet
+#ifdef REAL_LONG_DOUBLE_SUPPORT
if (flags & LONGDBL) {
long double res = wcstold(buf, &p);
*va_arg(ap, long double *) = res;
} else
#endif
- if (flags & LONG) {
+ if (flags & (LONG | LONGDBL)) {
double res = wcstod(buf, &p);
*va_arg(ap, double *) = res;
-#ifdef notyet
- } else {
+ }
+ else {
float res = wcstof(buf, &p);
*va_arg(ap, float *) = res;
-#endif
}
#ifdef DEBUG
if (p - buf != width)
diff --git a/StdLib/LibC/Stdio/vprintf.c b/StdLib/LibC/Stdio/vprintf.c index 96d43ee7a0..46ebf32970 100644 --- a/StdLib/LibC/Stdio/vprintf.c +++ b/StdLib/LibC/Stdio/vprintf.c @@ -50,7 +50,7 @@ #include <stdio.h>
int
-vprintf(char const *fmt, _BSD_VA_LIST_ ap)
+vprintf(char const *fmt, va_list ap)
{
_DIAGASSERT(fmt != NULL);
diff --git a/StdLib/LibC/Stdio/vsnprintf.c b/StdLib/LibC/Stdio/vsnprintf.c index 23385ba0d8..16e06667bc 100644 --- a/StdLib/LibC/Stdio/vsnprintf.c +++ b/StdLib/LibC/Stdio/vsnprintf.c @@ -54,7 +54,7 @@ __weak_alias(vsnprintf,_vsnprintf) #endif
int
-vsnprintf(char *str, size_t n, const char *fmt, _BSD_VA_LIST_ ap)
+vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
int ret;
FILE f;
diff --git a/StdLib/LibC/Stdio/vsnprintf_ss.c b/StdLib/LibC/Stdio/vsnprintf_ss.c index 77a2887ea6..a71dd6d3e5 100644 --- a/StdLib/LibC/Stdio/vsnprintf_ss.c +++ b/StdLib/LibC/Stdio/vsnprintf_ss.c @@ -117,7 +117,7 @@ __weak_alias(vsnprintf_ss,_vsnprintf_ss) } while (/*CONSTCOND*/0)
int
-vsnprintf_ss(char *sbuf, size_t slen, const char *fmt0, _BSD_VA_LIST_ ap)
+vsnprintf_ss(char *sbuf, size_t slen, const char *fmt0, va_list ap)
{
const char *fmt; /* format string */
int ch; /* character from fmt */
diff --git a/StdLib/LibC/Stdio/vsprintf.c b/StdLib/LibC/Stdio/vsprintf.c index 4fb8d28155..9534d95e1b 100644 --- a/StdLib/LibC/Stdio/vsprintf.c +++ b/StdLib/LibC/Stdio/vsprintf.c @@ -53,7 +53,7 @@ #include "local.h"
int
-vsprintf(char *str, const char *fmt, _BSD_VA_LIST_ ap)
+vsprintf(char *str, const char *fmt, va_list ap)
{
int ret;
FILE f;
diff --git a/StdLib/LibC/String/Comparison.c b/StdLib/LibC/String/Comparison.c index e656fe73f5..b4980c7c1e 100644 --- a/StdLib/LibC/String/Comparison.c +++ b/StdLib/LibC/String/Comparison.c @@ -109,10 +109,15 @@ strcasecmp(const char *s1, const char *s2) {
const unsigned char *us1 = (const unsigned char *)s1,
*us2 = (const unsigned char *)s2;
+ int Difference;
- while (tolower(*us1) == tolower(*us2++))
- if (*us1++ == '\0')
+ while ( 0 == ( Difference = tolower(*us1) - tolower(*us2))) {
+ if (*us1 == 0) {
return (0);
- return (tolower(*us1) - tolower(*--us2));
+ }
+ us1 += 1;
+ us2 += 1;
+ }
+ return Difference;
}
diff --git a/StdLib/LibC/String/String.inf b/StdLib/LibC/String/String.inf index b6ab660051..62db60e6a5 100644 --- a/StdLib/LibC/String/String.inf +++ b/StdLib/LibC/String/String.inf @@ -33,6 +33,9 @@ Searching.c
ErrorList.c
strncasecmp.c
+ strlcpy.c
+ strlcat.c
+ strsep.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/String/strlcat.c b/StdLib/LibC/String/strlcat.c new file mode 100644 index 0000000000..fc9aba7b12 --- /dev/null +++ b/StdLib/LibC/String/strlcat.c @@ -0,0 +1,86 @@ +/* $NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */
+/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <LibConfig.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcat, _strlcat)
+# endif
+#endif
+
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+#ifndef HAVE_STRLCAT
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
+#endif
diff --git a/StdLib/LibC/String/strlcpy.c b/StdLib/LibC/String/strlcpy.c new file mode 100644 index 0000000000..5631e255d5 --- /dev/null +++ b/StdLib/LibC/String/strlcpy.c @@ -0,0 +1,82 @@ +/* $NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */
+/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <LibConfig.h>
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef _LIBC
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strlcpy, _strlcpy)
+# endif
+#endif
+#else
+#include <lib/libkern/libkern.h>
+#endif /* !_KERNEL && !_STANDALONE */
+
+
+#if !HAVE_STRLCPY
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ _DIAGASSERT(dst != NULL);
+ _DIAGASSERT(src != NULL);
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+#endif
diff --git a/StdLib/LibC/String/strncasecmp.c b/StdLib/LibC/String/strncasecmp.c index 2519df94e4..b3f6d05965 100644 --- a/StdLib/LibC/String/strncasecmp.c +++ b/StdLib/LibC/String/strncasecmp.c @@ -40,7 +40,6 @@ $NetBSD: strncasecmp.c,v 1.2 2007/06/04 18:19:27 christos Exp $
strcasecmp.c 8.1 (Berkeley) 6/4/93
**/
-
#include <LibConfig.h>
#include <sys/cdefs.h>
diff --git a/StdLib/LibC/String/strsep.c b/StdLib/LibC/String/strsep.c new file mode 100644 index 0000000000..234b0cabd6 --- /dev/null +++ b/StdLib/LibC/String/strsep.c @@ -0,0 +1,82 @@ +/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <LibConfig.h>
+
+#include <sys/cdefs.h>
+#include <string.h>
+#include <stdio.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(
+ register char **stringp,
+ register const char *delim
+ )
+{
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/StdLib/LibC/Time/Time.c b/StdLib/LibC/Time/Time.c index 5cb9347752..e3eccb593b 100644 --- a/StdLib/LibC/Time/Time.c +++ b/StdLib/LibC/Time/Time.c @@ -82,7 +82,6 @@ static void localsub(const time_t * const timep, const long offset, struct tm * const tmp);
clock_t
-EFIAPI
__getCPS(void)
{
return gMD->ClocksPerSecond;
@@ -183,7 +182,7 @@ timesub( /** The clock function determines the processor time used.
- @return The clock function returns the implementation’s best
+ @return The clock function returns the implementation's best
approximation to the processor time used by the program since the
beginning of an implementation-defined era related only to the
program invocation. To determine the time in seconds, the value
@@ -196,7 +195,6 @@ timesub( CPU TimeStamp Counter ticks since the appliation started.
**/
clock_t
-EFIAPI
clock(void)
{
#ifndef NT32dvm
@@ -213,7 +211,6 @@ clock(void) /**
**/
double
-EFIAPI
difftime(time_t time1, time_t time0)
{
return (double)(time1 - time0);
@@ -429,7 +426,7 @@ time2sub( return t;
}
-static time_t
+time_t
time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
const long offset, int * const okayp)
{
@@ -542,7 +539,6 @@ time1( represented, the function returns the value (time_t)(-1).
**/
time_t
-EFIAPI
mktime(struct tm *timeptr)
{
/* From NetBSD */
@@ -558,14 +554,13 @@ mktime(struct tm *timeptr) /** The time function determines the current calendar time. The encoding of
the value is unspecified.
- @return The time function returns the implementation’s best approximation
+ @return The time function returns the implementation's best approximation
to the current calendar time. The value (time_t)(-1) is returned
if the calendar time is not available. If timer is not a null
pointer, the return value is also assigned to the object it
points to.
**/
time_t
-EFIAPI
time(time_t *timer)
{
time_t CalTime;
@@ -633,7 +628,6 @@ time(time_t *timer) @return The asctime function returns a pointer to the string.
**/
char *
-EFIAPI
asctime(const struct tm *timeptr)
{
register const char * wn;
@@ -663,7 +657,6 @@ asctime(const struct tm *timeptr) /**
**/
char *
-EFIAPI
ctime(const time_t *timer)
{
return asctime(localtime(timer));
@@ -672,7 +665,7 @@ ctime(const time_t *timer) /*
** gmtsub is to gmtime as localsub is to localtime.
*/
-static void
+void
gmtsub(
const time_t * const timep,
const long offset,
@@ -718,7 +711,6 @@ gmtsub( /**
**/
struct tm *
-EFIAPI
gmtime(const time_t *timer)
{
gmtsub(timer, 0L, &gMD->BDTime);
@@ -771,7 +763,6 @@ localsub(const time_t * const timep, const long offset, struct tm * const tmp) /**
**/
struct tm *
-EFIAPI
localtime(const time_t *timer)
{
tzset();
diff --git a/StdLib/LibC/Time/Time.inf b/StdLib/LibC/Time/Time.inf index 6de494f8d4..3ad226951d 100644 --- a/StdLib/LibC/Time/Time.inf +++ b/StdLib/LibC/Time/Time.inf @@ -32,6 +32,8 @@ strptime.c
TimeEfi.c
gettimeofday.c
+ timegm.c
+ itimer.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/Time/TimeEfi.c b/StdLib/LibC/Time/TimeEfi.c index 7b062c917b..8c033fd7d9 100644 --- a/StdLib/LibC/Time/TimeEfi.c +++ b/StdLib/LibC/Time/TimeEfi.c @@ -21,7 +21,6 @@ /* Convert an EFI_TIME structure into a C Standard tm structure. */
void
-EFIAPI
Efi2Tm( EFI_TIME *ET, struct tm *BT)
{
// Convert EFI time to broken-down time.
@@ -39,7 +38,6 @@ Efi2Tm( EFI_TIME *ET, struct tm *BT) /* Convert an EFI_TIME structure into a time_t value. */
time_t
-EFIAPI
Efi2Time( EFI_TIME *EfiBDtime)
{
Efi2Tm( EfiBDtime, &gMD->BDTime);
diff --git a/StdLib/LibC/Time/TimeVals.h b/StdLib/LibC/Time/TimeVals.h index 72827f9a91..f84f4f612a 100644 --- a/StdLib/LibC/Time/TimeVals.h +++ b/StdLib/LibC/Time/TimeVals.h @@ -110,8 +110,8 @@ struct rule { #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
__BEGIN_DECLS
-extern void EFIAPI gmtload(struct state * const sp);
-extern void EFIAPI tzset(void);
+extern void gmtload(struct state * const sp);
+extern void tzset(void);
__END_DECLS
#endif /* _TIMEVAL_H */
diff --git a/StdLib/LibC/Time/ZoneProc.c b/StdLib/LibC/Time/ZoneProc.c index e33b99ed68..a7b589b7df 100644 --- a/StdLib/LibC/Time/ZoneProc.c +++ b/StdLib/LibC/Time/ZoneProc.c @@ -761,7 +761,6 @@ tzparse( }
void
-EFIAPI
gmtload(struct state * const sp)
{
if (tzload(gmt, sp) != 0)
@@ -788,7 +787,6 @@ tzsetwall(void) }
void
-EFIAPI
tzset(void)
{
register const char * name;
diff --git a/StdLib/LibC/Time/gettimeofday.c b/StdLib/LibC/Time/gettimeofday.c index 1c379a6b97..b26d157684 100644 --- a/StdLib/LibC/Time/gettimeofday.c +++ b/StdLib/LibC/Time/gettimeofday.c @@ -44,7 +44,6 @@ Heimdal: gettimeofday.c 14773 2005-04-12 11:29:18Z lha $
NetBSD: gettimeofday.c,v 1.2 2008/03/22 08:37:21 mlelstv Exp $
**/
-
#include <LibConfig.h>
#include <sys/EfiCdefs.h>
#include <sys/time.h>
diff --git a/StdLib/LibC/Time/itimer.c b/StdLib/LibC/Time/itimer.c new file mode 100644 index 0000000000..d6f6ab44c0 --- /dev/null +++ b/StdLib/LibC/Time/itimer.c @@ -0,0 +1,277 @@ +/** @file
+ setitimer and getitimer functions.
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <LibConfig.h>
+#include <sys/EfiSysCall.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/signal.h>
+#include <signal.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiLib.h>
+
+STATIC EFI_EVENT RealTimer = NULL;
+STATIC EFI_EVENT VirtualTimer = NULL;
+STATIC EFI_EVENT ProfTimer = NULL;
+
+STATIC struct itimerval RealTimerInfo = {{0,0},{0,0}};
+STATIC struct itimerval VirtualTimerInfo = {{0,0},{0,0}};
+STATIC struct itimerval ProfTimerInfo = {{0,0},{0,0}};
+
+/**
+ Function to queue the next iteration of the timer.
+
+ This will copy the interval part of the struct into the value and (if
+ non-zero), then queue the next timer event.
+
+ @param[in] TimerInfo The timer info structure.
+ @param[in] Event The EFI timer event.
+**/
+VOID
+EFIAPI
+SetNext (
+ IN struct itimerval *TimerInfo,
+ IN EFI_EVENT Event
+ )
+{
+ EFI_STATUS Status;
+
+ CopyMem(&(TimerInfo->it_value), &(TimerInfo->it_interval), sizeof(struct timeval));
+
+ //
+ // If now zero then close and be done.
+ //
+ if (TimerInfo->it_value.tv_sec+TimerInfo->it_value.tv_usec == 0) {
+ if (Event != NULL) {
+ gBS->CloseEvent(Event);
+ Event = NULL;
+ }
+ return;
+ }
+
+ //
+ // Set up for the next loop.
+ //
+ Status = gBS->SetTimer (
+ Event,
+ TimerRelative,
+ TimerInfo->it_value.tv_sec*10000000+TimerInfo->it_value.tv_usec*1000);
+
+ if (EFI_ERROR(Status)) {
+ gBS->CloseEvent(Event);
+ Event = NULL;
+ }
+}
+
+/**
+ Notification function for real timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerRealNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGALRM);
+ SetNext(&RealTimerInfo, RealTimer);
+}
+
+/**
+ Notification function for virtual timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerVirtualNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGVTALRM);
+ SetNext(&VirtualTimerInfo, VirtualTimer);
+}
+
+/**
+ Notification function for prof timer.
+
+ @param[in] Event The event.
+ @param[in] Context Ignored.
+**/
+VOID
+EFIAPI
+iTimerProfNotifyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ raise(SIGPROF);
+ SetNext(&ProfTimerInfo, ProfTimer);
+}
+
+/**
+ The setitimer() function sets the timer specified by which to the value
+ specified in the structure pointed to by value, and if ovalue is not a null
+ pointer, stores the previous value of the timer in the structure pointed to
+ by ovalue.
+
+ A timer value is defined by the itimerval structure. If it_value is non-zero,
+ it indicates the time to the next timer expiration. If it_interval is
+ non-zero, it specifies a value to be used in reloading it_value when the
+ timer expires. Setting it_value to 0 disables a timer, regardless of the
+ value of it_interval. Setting it_interval to 0 disables a timer after its
+ next expiration (assuming it_value is non-zero).
+
+ ITIMER_REAL
+ Decrements in real time. A SIGALRM signal is delivered when this timer
+ expires.
+
+ ITIMER_VIRTUAL
+ Decrements in process virtual time. It runs only when the process is
+ executing. A SIGVTALRM signal is delivered when it expires.
+
+ ITIMER_PROF
+ Decrements both in process virtual time and when the system is running on
+ behalf of the process. It is designed to be used by interpreters in
+ statistically profiling the execution of interpreted programs. Each time
+ the ITIMER_PROF timer expires, the SIGPROF signal is delivered.
+
+ @param[in] which Which timer to set. Possible values are described above.
+ @param[in] value The new value for this timer.
+ @param[out] ovalue The old value for this timer.
+
+ @retval 0 The operation was successful.
+ @retval -1 The operation failed. see errno for more details.
+**/
+
+int setitimer(
+ int which,
+ const struct itimerval *value,
+ struct itimerval *ovalue
+ )
+{
+ EFI_EVENT *EventPointer;
+ EFI_EVENT_NOTIFY NotifyFunction;
+ EFI_STATUS Status;
+
+ if (value == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (which == ITIMER_REAL) {
+ EventPointer = &RealTimer;
+ NotifyFunction = iTimerRealNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &RealTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&RealTimerInfo, value, sizeof(struct itimerval));
+ } else if (which == ITIMER_VIRTUAL) {
+ EventPointer = &VirtualTimer;
+ NotifyFunction = iTimerVirtualNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &VirtualTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&VirtualTimerInfo, value, sizeof(struct itimerval));
+ } else if (which == ITIMER_PROF) {
+ EventPointer = &ProfTimer;
+ NotifyFunction = iTimerProfNotifyFunction;
+ if (ovalue != NULL) {
+ CopyMem(ovalue, &ProfTimerInfo, sizeof(struct itimerval));
+ }
+ CopyMem(&ProfTimerInfo, value, sizeof(struct itimerval));
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*EventPointer != NULL) {
+ gBS->CloseEvent(*EventPointer);
+ *EventPointer = NULL;
+ }
+
+ //
+ // This was a 'please cancel me' request.
+ //
+ if (value->it_value.tv_sec+value->it_value.tv_usec == 0) {
+ return 0;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER|EVT_NOTIFY_SIGNAL,
+ EfiGetCurrentTpl(),
+ NotifyFunction,
+ NULL, // no context
+ EventPointer);
+
+ if (EFI_ERROR(Status)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ Status = gBS->SetTimer (
+ *EventPointer,
+ TimerRelative,
+ value->it_value.tv_sec*10000000+value->it_value.tv_usec*1000);
+
+ if (EFI_ERROR(Status)) {
+ gBS->CloseEvent(*EventPointer);
+ *EventPointer = NULL;
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return 0;
+}
+
+/**
+ Function to get the current state of a timer.
+
+ @param[in] which The identifier of the timer to get. See setitimer for
+ details.
+ @param[in] value The pointer to populate. must be pre-allocated to size.
+
+ @return 0 The operation was successful.
+ @return -1 The operation failed.
+ This means that value or which had an invalid value.
+**/
+int getitimer(
+ int which,
+ struct itimerval *value
+ )
+{
+
+ if (value == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (which == ITIMER_REAL) {
+ CopyMem(value, &RealTimerInfo, sizeof(struct itimerval));
+ } else if (which == ITIMER_VIRTUAL) {
+ CopyMem(value, &VirtualTimerInfo, sizeof(struct itimerval));
+ } else if (which == ITIMER_PROF) {
+ CopyMem(value, &ProfTimerInfo, sizeof(struct itimerval));
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return 0;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Time/strftime.c b/StdLib/LibC/Time/strftime.c index 6a5e2a34af..11757b6129 100644 --- a/StdLib/LibC/Time/strftime.c +++ b/StdLib/LibC/Time/strftime.c @@ -72,9 +72,9 @@ #define Locale _CurrentTimeLocale
-static char * EFIAPI _add(const char *, char *, const char * const);
-static char * EFIAPI _conv(const int, const char * const, char * const, const char * const);
-static char * EFIAPI _fmt(const char *, const struct tm * const, char *, const char * const, int *);
+static char * _add(const char *, char *, const char * const);
+static char * _conv(const int, const char * const, char * const, const char * const);
+static char * _fmt(const char *, const struct tm * const, char *, const char * const, int *);
#define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
@@ -89,7 +89,6 @@ static char * EFIAPI _fmt(const char *, const struct tm * const, char *, const c #define IN_ALL 3
size_t
-EFIAPI
strftime(
char * __restrict s,
size_t maxsize,
@@ -128,7 +127,6 @@ strftime( }
static char *
-EFIAPI
_fmt(
const char * format,
const struct tm * const t,
@@ -574,7 +572,6 @@ label: }
static char *
-EFIAPI
_conv(
const int n,
const char * const format,
@@ -589,7 +586,6 @@ _conv( }
static char *
-EFIAPI
_add(
const char * str,
char * pt,
diff --git a/StdLib/LibC/Time/timegm.c b/StdLib/LibC/Time/timegm.c new file mode 100644 index 0000000000..a672dc8da1 --- /dev/null +++ b/StdLib/LibC/Time/timegm.c @@ -0,0 +1,113 @@ +/** @file
+ timegm implementation
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License that accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ * Copyright (c) 1987, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Arthur David Olson of the National Cancer Institute.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+static char *sccsid = "from: @(#)ctime.c 5.26 (Berkeley) 2/23/91";
+
+
+ * This implementation of mktime is lifted straight from the NetBSD (BSD 4.4)
+ * version. I modified it slightly to divorce it from the internals of the
+ * ctime library. Thus this version can't use details of the internal
+ * timezone state file to figure out strange unnormalized struct tm values,
+ * as might result from someone doing date math on the tm struct then passing
+ * it to mktime.
+ *
+ * It just does as well as it can at normalizing the tm input, then does a
+ * binary search of the time space using the system's localtime() function.
+ *
+ * The original binary search was defective in that it didn't consider the
+ * setting of tm_isdst when comparing tm values, causing the search to be
+ * flubbed for times near the dst/standard time changeover. The original
+ * code seems to make up for this by grubbing through the timezone info
+ * whenever the binary search barfed. Since I don't have that luxury in
+ * portable code, I have to take care of tm_isdst in the comparison routine.
+ * This requires knowing how many minutes offset dst is from standard time.
+ *
+ * So, if you live somewhere in the world where dst is not 60 minutes offset,
+ * and your vendor doesn't supply mktime(), you'll have to edit this variable
+ * by hand. Sorry about that.
+
+ $NetBSD: mktime.c,v 1.4 2006/06/11 19:34:10 kardel Exp $
+**/
+
+#include <LibConfig.h>
+#include <time.h>
+
+/*
+ This funciton is in Time.c, which has a different license than timegm.
+*/
+time_t
+time2(struct tm * const tmp, void (* const funcp)(const time_t*, long, struct tm*),
+ const long offset, int * const okayp);
+
+/*
+ This funciton is in Time.c, which has a different license than timegm.
+*/
+void
+gmtsub(
+ const time_t * const timep,
+ const long offset,
+ struct tm * const tmp
+ );
+
+#ifndef WRONG
+#define WRONG (-1)
+#endif /* !defined WRONG */
+
+/*
+ Convert a tm structure to a GMT based time_t.
+*/
+time_t timegm( struct tm * tmp )
+{
+ register time_t t;
+ int okay;
+
+ tmp->tm_isdst = 0;
+ t = time2(tmp, gmtsub, 0, &okay);
+ if (okay || tmp->tm_isdst < 0)
+ return t;
+
+ return WRONG;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Uefi/Devices/Console/daConsole.c b/StdLib/LibC/Uefi/Devices/Console/daConsole.c index c579959081..5dfc18acb4 100644 --- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c +++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c @@ -45,6 +45,12 @@ static const int stdioFlags[NUM_SPECIAL] = { static DeviceNode *ConNode[NUM_SPECIAL];
static ConInstance *ConInstanceList;
+static wchar_t *ConReadBuf;
+
+/* Flags settable by Ioctl */
+static BOOLEAN TtyCooked;
+static BOOLEAN TtyEcho;
+
ssize_t
WideTtyCvt( CHAR16 *dest, const char *buf, size_t n)
{
@@ -127,74 +133,6 @@ da_ConSeek( }
}
-static
-ssize_t
-EFIAPI
-da_ConRead(
- IN OUT struct __filedes *filp,
- IN OUT off_t *offset, // Console ignores this
- IN size_t BufferSize,
- OUT VOID *Buffer
-)
-{
- EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
- ConInstance *Stream;
- CHAR16 *OutPtr;
- EFI_INPUT_KEY Key;
- UINTN NumChar;
- UINTN Edex;
- EFI_STATUS Status = RETURN_SUCCESS;
- UINTN i;
-
- Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
- // Quick check to see if Stream looks reasonable
- if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
- EFIerrno = RETURN_INVALID_PARAMETER;
- return -1; // Looks like a bad This pointer
- }
- if(Stream->InstanceNum != STDIN_FILENO) {
- // Read only valid for stdin
- EFIerrno = RETURN_UNSUPPORTED;
- return -1;
- }
- // It looks like things are OK for trying to read
- // We will accumulate *BufferSize characters or until we encounter
- // an "activation" character. Currently any control character.
- Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
- OutPtr = Buffer;
- NumChar = (BufferSize - 1) / sizeof(CHAR16);
- i = 0;
- do {
- if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
- Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
- if(Status != RETURN_SUCCESS) {
- break;
- }
- Status = Proto->ReadKeyStroke(Proto, &Key);
- if(Status != RETURN_SUCCESS) {
- break;
- }
- }
- else {
- Key.ScanCode = Stream->UnGetKey.ScanCode;
- Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
- Stream->UnGetKey.ScanCode = SCAN_NULL;
- Stream->UnGetKey.UnicodeChar = CHAR_NULL;
- }
- if(Key.ScanCode == SCAN_NULL) {
- *OutPtr++ = Key.UnicodeChar;
- ++i;
- }
- if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
- break;
- }
- } while(i < NumChar);
-
- *OutPtr = L'\0'; // Terminate the input buffer
- EFIerrno = Status;
- return (ssize_t)(i * sizeof(CHAR16)); // Will be 0 if we didn't get a key
-}
-
/* Write a NULL terminated WCS to the EFI console.
@param[in,out] BufferSize Number of bytes in Buffer. Set to zero if
@@ -265,6 +203,109 @@ da_ConWrite( return BufferSize;
}
+/** Read characters from the console input device.
+
+ @param[in,out] filp Pointer to file descriptor for this file.
+ @param[in,out] offset Ignored.
+ @param[in] BufferSize Buffer size, in bytes.
+ @param[out] Buffer Buffer in which to place the read characters.
+
+ @return Number of bytes actually placed into Buffer.
+
+ @todo Handle encodings other than ASCII-7 and UEFI.
+**/
+static
+ssize_t
+EFIAPI
+da_ConRead(
+ IN OUT struct __filedes *filp,
+ IN OUT off_t *offset, // Console ignores this
+ IN size_t BufferSize,
+ OUT VOID *Buffer
+)
+{
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Proto;
+ ConInstance *Stream;
+ wchar_t *OutPtr;
+ EFI_INPUT_KEY Key;
+ UINTN NumChar;
+ UINTN Edex;
+ EFI_STATUS Status = RETURN_SUCCESS;
+ UINTN i;
+ char EchoBuff[MB_CUR_MAX + 1];
+ int NumEcho;
+
+ Stream = BASE_CR(filp->f_ops, ConInstance, Abstraction);
+ // Quick check to see if Stream looks reasonable
+ if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
+ EFIerrno = RETURN_INVALID_PARAMETER;
+ return -1; // Looks like a bad This pointer
+ }
+ if(Stream->InstanceNum != STDIN_FILENO) {
+ // Read only valid for stdin
+ EFIerrno = RETURN_UNSUPPORTED;
+ return -1;
+ }
+ // It looks like things are OK for trying to read
+ // We will accumulate *BufferSize characters or until we encounter
+ // an "activation" character. Currently any control character.
+ Proto = (EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Stream->Dev;
+ OutPtr = ConReadBuf;
+ NumChar = (BufferSize > MAX_INPUT)? MAX_INPUT : BufferSize;
+ i = 0;
+ do {
+ if((Stream->UnGetKey.UnicodeChar == CHAR_NULL) && (Stream->UnGetKey.ScanCode == SCAN_NULL)) {
+ Status = gBS->WaitForEvent( 1, &Proto->WaitForKey, &Edex);
+ if(Status != RETURN_SUCCESS) {
+ break;
+ }
+ Status = Proto->ReadKeyStroke(Proto, &Key);
+ if(Status != RETURN_SUCCESS) {
+ break;
+ }
+ }
+ else {
+ Key.ScanCode = Stream->UnGetKey.ScanCode;
+ Key.UnicodeChar = Stream->UnGetKey.UnicodeChar;
+ Stream->UnGetKey.ScanCode = SCAN_NULL;
+ Stream->UnGetKey.UnicodeChar = CHAR_NULL;
+ }
+ if(Key.ScanCode == SCAN_NULL) {
+ NumEcho = 0;
+ if(TtyCooked && (Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
+ *OutPtr++ = CHAR_LINEFEED;
+ NumEcho = wctomb(EchoBuff, CHAR_LINEFEED);
+ }
+ else {
+ *OutPtr++ = Key.UnicodeChar;
+ NumEcho = wctomb(EchoBuff, Key.UnicodeChar);
+ }
+ ++i;
+ EchoBuff[NumEcho] = 0; /* Terminate the Echo buffer */
+ if(TtyEcho) {
+ /* Echo the character just input */
+ da_ConWrite(&gMD->fdarray[STDOUT_FILENO], NULL, 2, EchoBuff);
+ }
+ }
+ if(iswcntrl(Key.UnicodeChar)) { // If a control character, or a scan code
+ break;
+ }
+ } while(i < NumChar);
+
+ *OutPtr = L'\0'; // Terminate the input buffer
+
+ /* Convert the input buffer and place in Buffer.
+ If the fully converted input buffer won't fit, write what will and
+ leave the rest in ConReadBuf with ConReadLeft indicating how many
+ unconverted characters remain in ConReadBuf.
+ */
+ NumEcho = (int)wcstombs(Buffer, ConReadBuf, BufferSize); /* Re-use NumEcho to hold number of bytes in Buffer */
+ /* More work needs to be done before locales other than C can be supported. */
+
+ EFIerrno = Status;
+ return (ssize_t)NumEcho; // Will be 0 if we didn't get a key
+}
+
/** Console-specific helper function for the fstat() function.
st_size Set to number of characters read for stdin and number written for stdout and stderr.
@@ -347,27 +388,28 @@ da_ConIoctl( int
EFIAPI
da_ConOpen(
+ DeviceNode *DevNode,
struct __filedes *filp,
- void *DevInstance,
+ int DevInstance, // Not used for console devices
wchar_t *Path, // Not used for console devices
- wchar_t *Flags // Not used for console devices
+ wchar_t *MPath // Not used for console devices
)
{
ConInstance *Stream;
if((filp == NULL) ||
- (DevInstance == NULL))
+ (DevNode == NULL))
{
EFIerrno = RETURN_INVALID_PARAMETER;
return -1;
}
- Stream = (ConInstance *)DevInstance;
+ Stream = (ConInstance *)DevNode->InstanceList;
// Quick check to see if Stream looks reasonable
if(Stream->Cookie != CON_COOKIE) { // Cookie == 'IoAb'
EFIerrno = RETURN_INVALID_PARAMETER;
return -1; // Looks like a bad This pointer
}
- gMD->StdIo[Stream->InstanceNum] = (ConInstance *)DevInstance;
+ gMD->StdIo[Stream->InstanceNum] = Stream;
filp->f_iflags |= (S_IFREG | _S_IFCHR | _S_ICONSOLE);
filp->f_offset = 0;
filp->f_ops = &Stream->Abstraction;
@@ -448,7 +490,8 @@ __Cons_construct( int i;
ConInstanceList = (ConInstance *)AllocateZeroPool(NUM_SPECIAL * sizeof(ConInstance));
- if(ConInstanceList == NULL) {
+ ConReadBuf = (wchar_t *)AllocateZeroPool((MAX_INPUT + 1) * sizeof(wchar_t));
+ if((ConInstanceList == NULL) || (ConReadBuf == NULL)) {
return RETURN_OUT_OF_RESOURCES;
}
@@ -507,6 +550,10 @@ __Cons_construct( }
Stream->Parent = ConNode[i];
}
+ /* Initialize Ioctl flags until Ioctl is really implemented. */
+ TtyCooked = TRUE;
+ TtyEcho = TRUE;
+
return Status;
}
@@ -527,6 +574,9 @@ __Cons_deconstruct( if(ConInstanceList != NULL) {
FreePool(ConInstanceList);
}
+ if(ConReadBuf != NULL) {
+ FreePool(ConReadBuf);
+ }
return RETURN_SUCCESS;
}
diff --git a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c index 37870e8384..d56db49159 100644 --- a/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c +++ b/StdLib/LibC/Uefi/Devices/UefiShell/daShell.c @@ -29,6 +29,7 @@ #include <wctype.h>
#include <wchar.h>
#include <sys/fcntl.h>
+#include <sys/syslimits.h>
#include <kfile.h>
#include <Device/Device.h>
#include <MainData.h>
@@ -321,7 +322,7 @@ da_ShellIoctl( void *argp ///< May be a pointer or a value
)
{
- return 0;
+ return -EPERM;
}
/** Open an abstract Shell File.
@@ -329,10 +330,11 @@ da_ShellIoctl( int
EFIAPI
da_ShellOpen(
+ DeviceNode *DevNode,
struct __filedes *filp,
- void *DevInstance,
+ int DevInstance, /* Not used by Shell */
wchar_t *Path,
- wchar_t *Flags
+ wchar_t *MPath
)
{
UINT64 OpenMode;
@@ -340,8 +342,10 @@ da_ShellOpen( SHELL_FILE_HANDLE FileHandle;
GenericInstance *Gip;
char *NPath;
+ wchar_t *WPath;
RETURN_STATUS Status;
int oflags;
+ int retval;
EFIerrno = RETURN_SUCCESS;
@@ -356,6 +360,23 @@ da_ShellOpen( return -1;
}
+ /* Re-create the full mapped path for the shell. */
+ if(MPath != NULL) {
+ WPath = AllocateZeroPool(PATH_MAX * sizeof(wchar_t) + 1);
+ if(WPath == NULL) {
+ errno = ENOMEM;
+ EFIerrno = RETURN_OUT_OF_RESOURCES;
+ return -1;
+ }
+ wcsncpy(WPath, MPath, NAME_MAX); /* Get the Map Name */
+ wcsncat(WPath, Path, (PATH_MAX - NAME_MAX)); /* Append the path */
+ }
+ else {
+ WPath = Path;
+ }
+
+ retval = -1; /* Initially assume failure. */
+
/* Do we care if the file already exists?
If O_TRUNC, then delete the file. It will be created anew subsequently.
If O_EXCL, then error if the file exists and O_CREAT is set.
@@ -363,23 +384,24 @@ da_ShellOpen( !!!!!!!!! Change this to use ShellSetFileInfo() to actually truncate the file
!!!!!!!!! instead of deleting and re-creating it.
*/
+ do { /* Do fake exception handling */
if((oflags & O_TRUNC) || ((oflags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
- Status = ShellIsFile( Path );
+ Status = ShellIsFile( WPath );
if(Status == RETURN_SUCCESS) {
// The file exists
if(oflags & O_TRUNC) {
- NPath = AllocateZeroPool(1024);
+ NPath = AllocateZeroPool(PATH_MAX);
if(NPath == NULL) {
errno = ENOMEM;
EFIerrno = RETURN_OUT_OF_RESOURCES;
- return -1;
+ break;
}
- wcstombs(NPath, Path, 1024);
+ wcstombs(NPath, WPath, PATH_MAX);
// We do a truncate by deleting the existing file and creating a new one.
if(unlink(NPath) != 0) {
filp->f_iflags = 0; // Release our reservation on this FD
FreePool(NPath);
- return -1; // errno and EFIerrno are already set.
+ break;
}
FreePool(NPath);
}
@@ -387,32 +409,40 @@ da_ShellOpen( errno = EEXIST;
EFIerrno = RETURN_ACCESS_DENIED;
filp->f_iflags = 0; // Release our reservation on this FD
- return -1;
+ break;
}
}
}
// Call the EFI Shell's Open function
- Status = ShellOpenFileByName( Path, &FileHandle, OpenMode, Attributes);
+ Status = ShellOpenFileByName( WPath, &FileHandle, OpenMode, Attributes);
if(RETURN_ERROR(Status)) {
filp->f_iflags = 0; // Release our reservation on this FD
// Set errno based upon Status
errno = EFI2errno(Status);
EFIerrno = Status;
- return -1;
+ break;
}
+ retval = 0;
// Successfully got a regular File
filp->f_iflags |= S_IFREG;
// Update the info in the fd
filp->devdata = (void *)FileHandle;
- Gip = (GenericInstance *)DevInstance;
+ Gip = (GenericInstance *)DevNode->InstanceList;
filp->f_offset = 0;
filp->f_ops = &Gip->Abstraction;
-// filp->devdata = FileHandle;
+ // filp->devdata = FileHandle;
+ } while(FALSE);
- return 0;
+ /* If we get this far, WPath is not NULL.
+ If MPath is not NULL, then WPath was allocated so we need to free it.
+ */
+ if(MPath != NULL) {
+ FreePool(WPath);
+ }
+ return retval;
}
#include <sys/poll.h>
@@ -468,9 +498,10 @@ da_ShellRename( RETURN_STATUS Status;
EFI_FILE_INFO *NewFileInfo;
EFI_FILE_INFO *OldFileInfo;
- char *NewFn;
+ wchar_t *NewFn;
int OldFd;
SHELL_FILE_HANDLE FileHandle;
+ wchar_t *NormalizedPath;
// Open old file
OldFd = open(from, O_RDWR, 0);
@@ -482,22 +513,20 @@ da_ShellRename( OldFileInfo = ShellGetFileInfo( FileHandle);
if(OldFileInfo != NULL) {
// Copy the Old file info into our new buffer, and free the old.
- memcpy(OldFileInfo, NewFileInfo, sizeof(EFI_FILE_INFO));
+ memcpy(NewFileInfo, OldFileInfo, sizeof(EFI_FILE_INFO));
FreePool(OldFileInfo);
+ // Normalize path and convert to WCS.
+ NormalizedPath = NormalizePath(to);
+ if (NormalizedPath != NULL) {
// Strip off all but the file name portion of new
- NewFn = strrchr(to, '/');
- if(NewFn == NULL) {
- NewFn = strrchr(to, '\\');
- if(NewFn == NULL) {
- NewFn = (char *)to;
- }
- }
- // Convert new name from MBCS to WCS
- (void)AsciiStrToUnicodeStr( NewFn, gMD->UString);
+ NewFn = GetFileNameFromPath(NormalizedPath);
// Copy the new file name into our new file info buffer
- wcsncpy(NewFileInfo->FileName, gMD->UString, wcslen(gMD->UString)+1);
+ wcsncpy(NewFileInfo->FileName, NewFn, wcslen(NewFn) + 1);
+ // Update the size of the structure.
+ NewFileInfo->Size = sizeof(EFI_FILE_INFO) + StrSize(NewFn);
// Apply the new file name
Status = ShellSetFileInfo(FileHandle, NewFileInfo);
+ free(NormalizedPath);
free(NewFileInfo);
if(Status == EFI_SUCCESS) {
// File has been successfully renamed. We are DONE!
@@ -507,6 +536,12 @@ da_ShellRename( EFIerrno = Status;
}
else {
+ free(NewFileInfo);
+ errno = ENOMEM;
+ }
+ }
+ else {
+ free(NewFileInfo);
errno = EIO;
}
}
@@ -619,7 +654,7 @@ __ctor_DevShell( Stream->Abstraction.fo_poll = &da_ShellPoll;
Stream->Abstraction.fo_flush = &fnullop_flush;
Stream->Abstraction.fo_stat = &da_ShellStat;
- Stream->Abstraction.fo_ioctl = &fbadop_ioctl;
+ Stream->Abstraction.fo_ioctl = &da_ShellIoctl;
Stream->Abstraction.fo_delete = &da_ShellDelete;
Stream->Abstraction.fo_rmdir = &da_ShellRmdir;
Stream->Abstraction.fo_mkdir = &da_ShellMkdir;
diff --git a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c index 2bdb33ac53..6510ce7747 100644 --- a/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c +++ b/StdLib/LibC/Uefi/Devices/Utility/DevGenisis.c @@ -31,33 +31,33 @@ DeviceNode *daCurrentDevice = NULL; ///< Device currently being accessed fnullop_* Does nothing and returns success.
fbadop_* Does nothing and returns EPERM
*/
-int fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
+int EFIAPI fnullop_fcntl (struct __filedes *filp, UINT32 Cmd, void *p3, void *p4)
{ return 0; }
-short fnullop_poll (struct __filedes *filp, short Events)
+short EFIAPI fnullop_poll (struct __filedes *filp, short Events)
{
return ((POLLIN | POLLRDNORM | POLLOUT) & Events);
}
-int fnullop_flush (struct __filedes *filp)
+int EFIAPI fnullop_flush (struct __filedes *filp)
{ return 0; }
-int fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
+int EFIAPI fbadop_stat (struct __filedes *filp, struct stat *StatBuf, void *Buf)
{ return -EPERM; }
-int fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
+int EFIAPI fbadop_ioctl (struct __filedes *filp, ULONGN Cmd, void *argp)
{ return -EPERM; }
-int fbadop_delete (struct __filedes *filp)
+int EFIAPI fbadop_delete (struct __filedes *filp)
{ return -EPERM; }
-int fbadop_mkdir (const char *path, __mode_t perms)
+int EFIAPI fbadop_mkdir (const char *path, __mode_t perms)
{ return -EPERM; }
-int fbadop_rename (const char *from, const char *to)
+int EFIAPI fbadop_rename (const char *from, const char *to)
{ return -EPERM; }
-int fbadop_rmdir (struct __filedes *filp)
+int EFIAPI fbadop_rmdir (struct __filedes *filp)
{ return -EPERM; }
/** Add a new device to the device list.
diff --git a/StdLib/LibC/Uefi/Devices/Utility/Path.c b/StdLib/LibC/Uefi/Devices/Utility/Path.c index 92bb1a20b7..96392e018d 100644 --- a/StdLib/LibC/Uefi/Devices/Utility/Path.c +++ b/StdLib/LibC/Uefi/Devices/Utility/Path.c @@ -248,10 +248,16 @@ PathAlias( /** Parse a path producing the target device, device instance, and file path.
+ It is the caller's responsibility to free() FullPath and MapPath when they
+ are no longer needed.
+
@param[in] path
@param[out] FullPath
@param[out] DevNode
@param[out] Which
+ @param[out] MapPath OPTIONAL. If not NULL, it points to the place to save a pointer
+ to the extracted map name. If the path didn't have a map name,
+ then *MapPath is set to NULL.
@retval RETURN_SUCCESS The path was parsed successfully.
@retval RETURN_NOT_FOUND The path does not map to a valid device.
@@ -266,7 +272,8 @@ ParsePath( IN const char *path,
OUT wchar_t **FullPath,
OUT DeviceNode **DevNode,
- OUT int *Which
+ OUT int *Which,
+ OUT wchar_t **MapPath
)
{
int MapLen;
@@ -301,7 +308,7 @@ reclassify: // Get the Map Name, including the trailing ':'. */
MPath = calloc(MapLen+2, sizeof(wchar_t));
if(MPath != NULL) {
- wmemcpy(MPath, WPath, MapLen+2);
+ wmemcpy(MPath, WPath, MapLen+1);
}
else {
errno = ENOMEM;
@@ -346,6 +353,12 @@ reclassify: if(!RETURN_ERROR(Status)) {
*FullPath = WPath;
*Which = Instance;
+ if(MapPath != NULL) {
+ *MapPath = MPath;
+ }
+ else if(MPath != NULL) {
+ free(MPath); /* Caller doesn't want it so let MPath go free */
+ }
/* At this point, WPath is an absolute path,
MPath is either NULL or points to the Map Name,
@@ -359,6 +372,9 @@ reclassify: if(Node != NULL) {
Status = RETURN_SUCCESS;
}
+ else {
+ Status = RETURN_NOT_FOUND;
+ }
}
else {
/* This is a mapped path. */
@@ -375,8 +391,41 @@ reclassify: *DevNode = Node;
}
}
- if(MPath != NULL) {
- free(MPath); // We don't need this any more.
- }
return Status;
}
+
+/**
+ Parses a normalized wide character path and returns a pointer to the entry
+ following the last \. If a \ is not found in the path the return value will
+ be the same as the input value. All error conditions return NULL.
+
+ The behavior when passing in a path that has not been normalized is undefined.
+
+ @param Path - A pointer to a wide character string containing a path to a
+ directory or a file.
+
+ @return Pointer to the file name or terminal directory. NULL if an error is
+ detected.
+**/
+wchar_t *
+EFIAPI
+GetFileNameFromPath (
+ const wchar_t *Path
+ )
+{
+ wchar_t *Tail;
+
+ if (Path == NULL) {
+ return NULL;
+ }
+
+ Tail = wcsrchr(Path, L'\\');
+ if(Tail == NULL) {
+ Tail = (wchar_t *) Path;
+ } else {
+ // Move to the next character after the '\\' to get the file name.
+ Tail++;
+ }
+
+ return Tail;
+}
diff --git a/StdLib/LibC/Uefi/Devices/daConsole.inf b/StdLib/LibC/Uefi/Devices/daConsole.inf index 17865e4fec..802c6eb13c 100644 --- a/StdLib/LibC/Uefi/Devices/daConsole.inf +++ b/StdLib/LibC/Uefi/Devices/daConsole.inf @@ -16,7 +16,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevConsole
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = f6937495-1f44-4a8a-8a1b-5a669f9396f6
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevConsole
@@ -49,15 +49,3 @@ [Protocols]
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/Devices/daShell.inf b/StdLib/LibC/Uefi/Devices/daShell.inf index 7b56f37363..56710259b6 100644 --- a/StdLib/LibC/Uefi/Devices/daShell.inf +++ b/StdLib/LibC/Uefi/Devices/daShell.inf @@ -19,7 +19,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevShell
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = 0a1d4fd8-4704-4501-85eb-93399492cbed
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevShell
@@ -49,15 +49,3 @@ LibWchar
LibUefi
DevUtility
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/Devices/daUtility.inf b/StdLib/LibC/Uefi/Devices/daUtility.inf index 53daad28ac..6bdc1eead9 100644 --- a/StdLib/LibC/Uefi/Devices/daUtility.inf +++ b/StdLib/LibC/Uefi/Devices/daUtility.inf @@ -15,7 +15,7 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = DevUtility
- FILE_GUID = 42c078ef-14a8-4e30-9329-6f12d796e54a
+ FILE_GUID = d6a9928c-3397-4dd1-818f-c664ba6dcaaf
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = DevUtility
@@ -42,15 +42,3 @@ LibC
LibWchar
LibUefi
-
-################################################################
-#
-# The Build Options, below, are only used when building the C library.
-# DO NOT use them when building your application!
-# Nasty things could happen if you do.
-#
-# /Oi- is required for Microsoft VC++ to allow "intrinsic" functions to be
-# defined in this library.
-#
-#[BuildOptions]
-# MSFT:*_*_*_CC_FLAGS = /Oi-
diff --git a/StdLib/LibC/Uefi/GetPass.c b/StdLib/LibC/Uefi/GetPass.c new file mode 100644 index 0000000000..9c0c1f4116 --- /dev/null +++ b/StdLib/LibC/Uefi/GetPass.c @@ -0,0 +1,57 @@ +/** @file Implement the getpass function.
+
+ Copyright (c) 2011, Intel Corporation <BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/ShellLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+
+static CHAR8 *ReturnStringAscii = NULL;
+
+char *getpass(const char *Prompt)
+{
+ BOOLEAN Ascii;
+ CHAR16 *ReturnString;
+
+ Ascii = FALSE;
+
+ Print(L"%a", Prompt);
+
+ ReturnString = ShellFileHandleReturnLine (gEfiShellParametersProtocol->StdIn, &Ascii);
+ if (ReturnString == NULL) {
+ return (NULL);
+ }
+
+ ReturnStringAscii = AllocateZeroPool((StrLen(ReturnString)+1)*sizeof(CHAR8));
+ if (ReturnStringAscii == NULL) {
+ return (NULL);
+ }
+
+ UnicodeStrToAsciiStr(ReturnString, ReturnStringAscii);
+
+ FreePool(ReturnString);
+
+ return (ReturnStringAscii);
+}
+
+EFI_STATUS
+EFIAPI
+DestructMePlease (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_FREE_NON_NULL(ReturnStringAscii);
+
+ return EFI_SUCCESS;
+}
\ No newline at end of file diff --git a/StdLib/LibC/Uefi/StubFunctions.c b/StdLib/LibC/Uefi/StubFunctions.c new file mode 100644 index 0000000000..da2eaf9148 --- /dev/null +++ b/StdLib/LibC/Uefi/StubFunctions.c @@ -0,0 +1,79 @@ +/** @file
+ Implement the invalid functions to return failures.
+
+ Copyright (c) 2011, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <sys/EfiCdefs.h>
+#include <sys/featuretest.h>
+#include <namespace.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <errno.h>
+
+struct passwd *
+getpwuid (uid_t uid)
+{
+ uid;
+ errno = EPERM;
+ return NULL;
+}
+
+char *getlogin (void)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+struct passwd *
+getpwnam (const char *name)
+{
+ name;
+ errno = EPERM;
+ return NULL;
+}
+
+uid_t getuid (void)
+{
+ return 0;
+}
+
+pid_t fork (void)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+int chmod (const char *c, mode_t m)
+{
+ errno = EPERM;
+ return (-1);
+}
+
+pid_t wait(int *stat_loc) {
+ return 0;
+}
+
+FILE *popen (const char *cmd, const char *type)
+{
+ errno = EPERM;
+ return NULL;
+}
+
+int pclose (FILE *stream)
+{
+ errno = EPERM;
+ return -1;
+}
+
+int access (const char *path, int amode)
+{
+ return 0;
+}
diff --git a/StdLib/LibC/Uefi/SysCalls.c b/StdLib/LibC/Uefi/SysCalls.c index b3ca5b89b4..d2fb0c6af6 100644 --- a/StdLib/LibC/Uefi/SysCalls.c +++ b/StdLib/LibC/Uefi/SysCalls.c @@ -524,7 +524,7 @@ mkdir (const char *path, __mode_t perms) int Instance = 0;
int retval = 0;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = Node->InstanceList;
if(GenI == NULL) {
@@ -532,7 +532,7 @@ mkdir (const char *path, __mode_t perms) retval = -1;
}
else {
- GenI += (Instance * Node->InstanceSize);
+ //GenI += (Instance * Node->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_mkdir( path, perms);
}
free(NewPath);
@@ -567,11 +567,15 @@ mkdir (const char *path, __mode_t perms) O_EXCL -- if O_CREAT is also set, open will fail if the file already exists.
**/
int
-open (const char *path, int oflags, int mode)
+open(
+ const char *path,
+ int oflags,
+ int mode
+ )
{
wchar_t *NewPath;
+ wchar_t *MPath;
DeviceNode *Node;
- char *GenI = NULL;
struct __filedes *filp;
int Instance = 0;
RETURN_STATUS Status;
@@ -579,10 +583,10 @@ open (const char *path, int oflags, int mode) int fd = -1;
int doresult;
- Status = ParsePath(path, &NewPath, &Node, &Instance);
+ Status = ParsePath(path, &NewPath, &Node, &Instance, &MPath);
if(Status == RETURN_SUCCESS) {
- if((Node != NULL) &&
- ((GenI = Node->InstanceList) == NULL)) {
+ if((Node == NULL) ||
+ (Node->InstanceList == NULL)) {
errno = EPERM;
}
else {
@@ -595,15 +599,14 @@ open (const char *path, int oflags, int mode) if( fd < 0 ) {
// All available FDs are in use
errno = EMFILE;
- return -1;
}
+ else {
filp = &gMD->fdarray[fd];
// Save the flags and mode in the File Descriptor
filp->Oflags = oflags;
filp->Omode = mode;
- GenI += (Instance * Node->InstanceSize);
- doresult = Node->OpenFunc(filp, GenI, NewPath, NULL);
+ doresult = Node->OpenFunc(Node, filp, Instance, NewPath, MPath);
if(doresult < 0) {
filp->f_iflags = 0; // Release this FD
fd = -1; // Indicate an error
@@ -618,8 +621,14 @@ open (const char *path, int oflags, int mode) FILE_SET_MATURE(filp);
}
}
+ }
+ if(NewPath != NULL) {
free(NewPath);
}
+ }
+ if(MPath != NULL) {
+ free(MPath); // We don't need this any more.
+ }
// return the fd of our now open file
return fd;
}
@@ -748,6 +757,7 @@ poll ( }
} while (( 0 == SelectedFDs )
&& ( EFI_SUCCESS == Status ));
+
//
// Stop the timer
//
@@ -776,7 +786,6 @@ poll ( }
-
/** The rename() function changes the name of a file.
The old argument points to the pathname of the file to be renamed. The new
argument points to the new pathname of the file.
@@ -807,7 +816,6 @@ poll ( shall be changed or created.
**/
int
-EFIAPI
rename(
const char *from,
const char *to
@@ -820,7 +828,7 @@ rename( RETURN_STATUS Status;
int retval = -1;
- Status = ParsePath(from, &FromPath, &FromNode, &Instance);
+ Status = ParsePath(from, &FromPath, &FromNode, &Instance, NULL);
if(Status == RETURN_SUCCESS) {
GenI = FromNode->InstanceList;
if(GenI == NULL) {
@@ -828,7 +836,7 @@ rename( retval = -1;
}
else {
- GenI += (Instance * FromNode->InstanceSize);
+ //GenI += (Instance * FromNode->InstanceSize);
retval = ((GenericInstance *)GenI)->Abstraction.fo_rename( from, to);
}
free(FromPath);
@@ -839,7 +847,6 @@ rename( /**
**/
int
-EFIAPI
rmdir(
const char *path
)
@@ -1006,13 +1013,13 @@ ioctl( from a file associated with a terminal may return one typed line of data.
If fildes does not refer to a directory, the function reads the requested
- number of bytes from the file at the file’s current position and returns
+ number of bytes from the file at the file's current position and returns
them in buf. If the read goes beyond the end of the file, the read
- length is truncated to the end of the file. The file’s current position is
+ length is truncated to the end of the file. The file's current position is
increased by the number of bytes returned.
If fildes refers to a directory, the function reads the directory entry at
- the file’s current position and returns the entry in buf. If buf
+ the file's current position and returns the entry in buf. If buf
is not large enough to hold the current directory entry, then
errno is set to EBUFSIZE, EFIerrno is set to EFI_BUFFER_TOO_SMALL, and the
current file position is not updated. The size of the buffer needed to read
@@ -1129,3 +1136,56 @@ char return (UnicodeStrToAsciiStr(Cwd, buf));
}
+
+/** Change the current working directory.
+
+ The chdir() function shall cause the directory named by the pathname
+ pointed to by the path argument to become the current working directory;
+ that is, the starting point for path searches for pathnames not beginning
+ with '/'.
+
+ @param[in] path The new path to set.
+
+ @todo Add non-shell CWD changing.
+**/
+int
+chdir (const char *path)
+{
+ CONST CHAR16 *Cwd;
+ EFI_STATUS Status;
+ CHAR16 *UnicodePath;
+
+ Cwd = ShellGetCurrentDir(NULL);
+ if (Cwd != NULL) {
+ /* We have shell support */
+ UnicodePath = AllocatePool(((AsciiStrLen (path) + 1) * sizeof (CHAR16)));
+ if (UnicodePath == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ AsciiStrToUnicodeStr(path, UnicodePath);
+ Status = gEfiShellProtocol->SetCurDir(NULL, UnicodePath);
+ FreePool(UnicodePath);
+ if (EFI_ERROR(Status)) {
+ errno = EACCES;
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Add here for non-shell */
+ errno = EACCES;
+ return -1;
+}
+
+pid_t tcgetpgrp (int x)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
+pid_t getpgrp(void)
+{
+ return ((pid_t)(UINTN)(gImageHandle));
+}
+
diff --git a/StdLib/LibC/Uefi/Uefi.inf b/StdLib/LibC/Uefi/Uefi.inf index 084d6c4fc3..30b619b409 100644 --- a/StdLib/LibC/Uefi/Uefi.inf +++ b/StdLib/LibC/Uefi/Uefi.inf @@ -16,18 +16,24 @@ [Defines]
INF_VERSION = 0x00010005
BASE_NAME = LibUefi
- FILE_GUID = 39356e02-26bf-4cfb-9564-378ce25e702f
+ FILE_GUID = 1dcff17c-aa53-4b78-b234-864027555035
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
LIBRARY_CLASS = LibUefi
+ LIBRARY_CONSTRUCTOR = DestructMePlease
#
# VALID_ARCHITECTURES = IA32 X64 IPF
#
[Sources]
+ select.c
SysCalls.c
+ writev.c
Xform.c
+ compat.c
+ GetPass.c
+ StubFunctions.c
[Packages]
StdLib/StdLib.dec
diff --git a/StdLib/LibC/Uefi/compat.c b/StdLib/LibC/Uefi/compat.c new file mode 100644 index 0000000000..7f250d15ff --- /dev/null +++ b/StdLib/LibC/Uefi/compat.c @@ -0,0 +1,847 @@ +/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein and Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
+ */
+#include <LibConfig.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifndef HAVE_GETOPT
+char *optarg;
+int optind = 1;
+int
+getopt(int argc, char **argv, char *args)
+{
+ size_t n;
+ size_t nlen = strlen(args);
+ char cmd;
+ char rv;
+
+ if (argv[optind] && *argv[optind] == '-') {
+ cmd = *(argv[optind] + 1);
+
+ for (n = 0; n < nlen; n++) {
+ if (args[n] == ':')
+ continue;
+ if (args[n] == cmd) {
+ rv = *(argv[optind] + 1);
+ if (args[n+1] == ':') {
+ if (*(argv[optind] + 2) != '\0') {
+ optarg = argv[optind] + 2;
+ optind += 1;
+ } else {
+ optarg = argv[optind + 1];
+ optind += 2;
+ }
+ if (!optarg)
+ optarg="";
+ return rv;
+ } else {
+ optarg = NULL;
+ optind += 1;
+ return rv;
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+#endif
+
+#ifdef WIN32
+#define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
+#else
+#define ISPATHSEPARATOR(x) (x == '/')
+#endif
+
+#ifndef HAVE_BASENAME
+#ifndef PATH_MAX
+#define PATH_MAX 5000
+#endif
+
+char *
+basename(char *path)
+{
+ static char singledot[] = ".";
+ static char result[PATH_MAX];
+ char *p, *lastp;
+ size_t len;
+
+ /*
+ * If `path' is a null pointer or points to an empty string,
+ * return a pointer to the string ".".
+ */
+ if ((path == NULL) || (*path == '\0'))
+ return (singledot);
+
+ /* Strip trailing slashes, if any. */
+ lastp = path + strlen(path) - 1;
+ while (lastp != path && ISPATHSEPARATOR(*lastp))
+ lastp--;
+
+ /* Now find the beginning of this (final) component. */
+ p = lastp;
+ while (p != path && !ISPATHSEPARATOR(*(p - 1)))
+ p--;
+
+ /* ...and copy the result into the result buffer. */
+ len = (lastp - p) + 1 /* last char */;
+ if (len > (PATH_MAX - 1))
+ len = PATH_MAX - 1;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+ return (result);
+}
+#endif
+
+#if !defined(HAVE_MKSTEMP) && !defined(WIN32)
+int
+mkstemp(char *path)
+{
+ char *start, *trv;
+ unsigned int pid;
+
+ /* To guarantee multiple calls generate unique names even if
+ the file is not created. 676 different possibilities with 7
+ or more X's, 26 with 6 or less. */
+ static char xtra[2] = "aa";
+ int xcnt = 0;
+
+ pid = getpid();
+
+ /* Move to end of path and count trailing X's. */
+ for (trv = path; *trv; ++trv)
+ if (*trv == 'X')
+ xcnt++;
+ else
+ xcnt = 0;
+
+ /* Use at least one from xtra. Use 2 if more than 6 X's. */
+ if (*(trv - 1) == 'X')
+ *--trv = xtra[0];
+ if (xcnt > 6 && *(trv - 1) == 'X')
+ *--trv = xtra[1];
+
+ /* Set remaining X's to pid digits with 0's to the left. */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+
+ /* update xtra for next call. */
+ if (xtra[0] != 'z')
+ xtra[0]++;
+ else {
+ xtra[0] = 'a';
+ if (xtra[1] != 'z')
+ xtra[1]++;
+ else
+ xtra[1] = 'a';
+ }
+
+ return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
+}
+#endif
+
+#ifndef HAVE_FFS
+int
+ffs(int x)
+{
+ int r = 1;
+ if (!x) return 0;
+ if (!(x & 0xffff)) { x >>= 16; r += 16; }
+ if (!(x & 0xff)) { x >>= 8; r += 8; }
+ if (!(x & 0xf)) { x >>= 4; r += 4; }
+ if (!(x & 3)) { x >>= 2; r += 2; }
+ if (!(x & 1)) { x >>= 1; r += 1; }
+
+ return r;
+}
+#endif
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args);
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
+ int min, int max);
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
+ int min, int max, int flags);
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags);
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LONG_LONG 4
+
+#define char_to_int(p) (p - '0')
+#define abs_val(p) (p < 0 ? -p : p)
+
+
+static void
+dopr(char *buffer, size_t maxlen, const char *format, va_list args)
+{
+ char *strvalue, ch;
+ long value;
+ long double fvalue;
+ int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
+ size_t currlen = 0;
+
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if ((ch == '\0') || (currlen >= maxlen))
+ state = DP_S_DONE;
+
+ switch(state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit((unsigned char)ch)) {
+ min = 10 * min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else
+ state = DP_S_DOT;
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MAX:
+ if (isdigit((unsigned char)ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10 * max + char_to_int(ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else
+ state = DP_S_MOD;
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ if (ch == 'l') {
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ }
+ break;
+ case 'q':
+ cflags = DP_C_LONG_LONG;
+ ch = *format++;
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg (args, long long);
+ else
+ value = va_arg (args, int);
+ fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg(args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg(args, unsigned long int);
+ else if (cflags == DP_C_LONG_LONG)
+ value = va_arg(args, unsigned long long);
+ else
+ value = va_arg(args, unsigned int);
+ fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ /* um, floating point? */
+ fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg(args, long double);
+ else
+ fvalue = va_arg(args, double);
+ break;
+ case 'c':
+ dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
+ break;
+ case 's':
+ strvalue = va_arg(args, char *);
+ if (max < 0)
+ max = maxlen; /* ie, no max */
+ fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = va_arg(args, void *);
+ fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg(args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg(args, long int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG_LONG) {
+ long long *num;
+ num = va_arg(args, long long *);
+ *num = currlen;
+ } else {
+ int *num;
+ num = va_arg(args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch(buffer, &currlen, maxlen, ch);
+ break;
+ case 'w': /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default: /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default: /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else
+ buffer[maxlen - 1] = '\0';
+}
+
+static void
+fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int cnt = 0, padlen, strln; /* amount to pad */
+
+ if (value == 0)
+ value = "<NULL>";
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+ while (*value && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void
+fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ unsigned long uvalue;
+ char convert[20];
+ int signvalue = 0, place = 0, caps = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+
+#define PADMAX(x,y) ((x) > (y) ? (x) : (y))
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if (!(flags & DP_F_UNSIGNED)) {
+ if (value < 0) {
+ signvalue = '-';
+ uvalue = -value;
+ } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+
+ if (flags & DP_F_UP)
+ caps = 1; /* Should characters be upper case? */
+ do {
+ convert[place++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [uvalue % (unsigned)base];
+ uvalue = (uvalue / (unsigned)base );
+ } while (uvalue && (place < 20));
+ if (place == 20)
+ place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (spadlen < 0)
+ spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = PADMAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch(buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static long double
+pow10(int exp)
+{
+ long double result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static long
+round(long double value)
+{
+ long intpart = value;
+
+ value -= intpart;
+ if (value >= 0.5)
+ intpart++;
+
+ return intpart;
+}
+
+static void
+fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
+ int min, int max, int flags)
+{
+ char iconvert[20], fconvert[20];
+ int signvalue = 0, iplace = 0, fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0, caps = 0;
+ long intpart, fracpart;
+ long double ufvalue;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val(fvalue);
+
+ if (fvalue < 0)
+ signvalue = '-';
+ else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+
+ intpart = ufvalue;
+
+ /*
+ * Sorry, we only support 9 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 9)
+ max = 9;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+ fracpart = round((pow10 (max)) * (ufvalue - intpart));
+
+ if (fracpart >= pow10 (max)) {
+ intpart++;
+ fracpart -= pow10 (max);
+ }
+
+ /* Convert integer part */
+ do {
+ iconvert[iplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [intpart % 10];
+ intpart = (intpart / 10);
+ } while(intpart && (iplace < 20));
+ if (iplace == 20)
+ iplace--;
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ do {
+ fconvert[fplace++] =
+ (caps ? "0123456789ABCDEF" : "0123456789abcdef")
+ [fracpart % 10];
+ fracpart = (fracpart / 10);
+ } while(fracpart && (fplace < 20));
+ if (fplace == 20)
+ fplace--;
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+ if (zpadlen < 0)
+ zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+ if (signvalue)
+ dopr_outch(buffer, currlen, maxlen, signvalue);
+
+ while (iplace > 0)
+ dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
+
+ /*
+ * Decimal point. This should probably use locale to find the
+ * correct char to print out.
+ */
+ dopr_outch(buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
+
+ while (zpadlen > 0) {
+ dopr_outch(buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch(buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void
+dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+ if (*currlen < maxlen)
+ buffer[(*currlen)++] = c;
+}
+#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ str[0] = 0;
+ dopr(str, count, fmt, args);
+
+ return(strlen(str));
+}
+#endif /* !HAVE_VSNPRINTF */
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf(char *str,size_t count,const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+
+ return(strlen(str));
+}
+
+#endif /* !HAVE_SNPRINTF */
diff --git a/StdLib/LibC/Uefi/select.c b/StdLib/LibC/Uefi/select.c new file mode 100644 index 0000000000..8da03e65d0 --- /dev/null +++ b/StdLib/LibC/Uefi/select.c @@ -0,0 +1,256 @@ +/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Portions copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ *
+ * This product includes software developed by the University of
+ * California, Berkeley, Intel Corporation, and its contributors.
+ *
+ * 4. Neither the name of University, Intel Corporation, or their respective
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS,
+ * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
+ * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $
+ */
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <LibConfig.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <extern.h> /* For ffs() */
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+#ifdef EFI_NT_EMULATOR
+#define _SELECT_DELAY_ 10000
+#else
+#define _SELECT_DELAY_ 1000
+#endif
+
+#define MAX_SLEEP_DELAY 0xfffffffe
+
+//
+// Name:
+// usleep
+//
+// Description:
+// Implement usleep(3) function.
+//
+// Arguments:
+// Microseconds to sleep.
+//
+// Returns:
+// 0
+//
+int
+usleep( useconds_t Microseconds )
+{
+ while ( MAX_SLEEP_DELAY < Microseconds ) {
+ gBS->Stall ( MAX_SLEEP_DELAY );
+ Microseconds -= MAX_SLEEP_DELAY;
+ }
+ gBS->Stall((UINTN)Microseconds );
+ return (0);
+}
+
+static int
+selscan(
+ fd_mask **ibits,
+ fd_mask **obits,
+ int nfd,
+ int *nselected
+ )
+{
+ int msk;
+ int i;
+ int j;
+ int fd;
+ int n;
+ struct pollfd pfd;
+ int FdCount;
+ fd_mask bits;
+ /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
+ static int16_t flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
+
+ for (msk = 0, n = 0; msk < 3; msk++) {
+ if (ibits[msk] == NULL)
+ continue;
+ for (i = 0; i < nfd; i += NFDBITS) {
+ bits = ibits[ msk ][ i / NFDBITS ];
+ while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {
+ bits &= ~(1 << j);
+
+ pfd.fd = fd;
+ pfd.events = flag[msk];
+ pfd.revents = 0;
+ FdCount = poll ( &pfd, 1, 0 );
+ if ( -1 == FdCount ) {
+ return errno;
+ }
+ if ( 0 != FdCount ) {
+ obits[msk][(fd)/NFDBITS] |=
+ (1 << ((fd) % NFDBITS));
+ n++;
+ break;
+ }
+ }
+ }
+ }
+ *nselected = n;
+ return (0);
+}
+
+int
+select(
+ int nd,
+ fd_set *in,
+ fd_set *ou,
+ fd_set *ex,
+ struct timeval *tv
+ )
+{
+ fd_mask *ibits[3], *obits[3], *selbits, *sbp;
+ int error, forever, nselected;
+ u_int nbufbytes, ncpbytes, nfdbits;
+ int64_t timo;
+
+ if (nd < 0)
+ return (EINVAL);
+
+ /*
+ * Allocate just enough bits for the non-null fd_sets. Use the
+ * preallocated auto buffer if possible.
+ */
+ nfdbits = roundup(nd, NFDBITS);
+ ncpbytes = nfdbits / NBBY;
+ nbufbytes = 0;
+ if (in != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ou != NULL)
+ nbufbytes += 2 * ncpbytes;
+ if (ex != NULL)
+ nbufbytes += 2 * ncpbytes;
+ selbits = malloc(nbufbytes);
+
+ /*
+ * Assign pointers into the bit buffers and fetch the input bits.
+ * Put the output buffers together so that they can be bzeroed
+ * together.
+ */
+ sbp = selbits;
+#define getbits(name, x) \
+ do { \
+ if (name == NULL) \
+ ibits[x] = NULL; \
+ else { \
+ ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
+ obits[x] = sbp; \
+ sbp += ncpbytes / sizeof *sbp; \
+ bcopy(name, ibits[x], ncpbytes); \
+ } \
+ } while (0)
+ getbits(in, 0);
+ getbits(ou, 1);
+ getbits(ex, 2);
+#undef getbits
+ if (nbufbytes != 0)
+ memset(selbits, 0, nbufbytes / 2);
+
+ if (tv) {
+ timo = tv->tv_usec + (tv->tv_sec * 1000000);
+ forever = 0;
+ } else {
+ timo = 0;
+ forever = 1;
+ }
+
+ /*
+ * Poll for I/O events
+ */
+ nselected = 0;
+ do {
+ /*
+ * Scan for pending I/O
+ */
+ error = selscan(ibits, obits, nd, &nselected);
+ if (error || nselected)
+ break;
+
+ /*
+ * Adjust timeout is needed
+ */
+ if (timo) {
+ /*
+ * Give it a rest
+ */
+ usleep( _SELECT_DELAY_ );
+ timo -= _SELECT_DELAY_;
+ }
+
+ } while (timo > 0 || forever);
+
+ /* select is not restarted after signals... */
+ if (error == ERESTART)
+ error = EINTR;
+ else if (error == EWOULDBLOCK)
+ error = 0;
+
+#define putbits(name, x) if (name) bcopy(obits[x], name, ncpbytes)
+ if (error == 0) {
+ putbits(in, 0);
+ putbits(ou, 1);
+ putbits(ex, 2);
+#undef putbits
+ } else {
+ errno = error;
+ nselected = -1;
+ }
+
+ free( selbits );
+ return ( nselected );
+}
diff --git a/StdLib/LibC/Uefi/writev.c b/StdLib/LibC/Uefi/writev.c new file mode 100644 index 0000000000..9cff086c6a --- /dev/null +++ b/StdLib/LibC/Uefi/writev.c @@ -0,0 +1,143 @@ +/*
+ * Copyright (c) 1999, 2000
+ * Intel Corporation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software must
+ * display the following acknowledgement:
+ *
+ * This product includes software developed by Intel Corporation and its
+ * contributors.
+ *
+ * 4. Neither the name of Intel Corporation or its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*++
+
+Module Name:
+
+ writev.c
+
+Abstract:
+
+ Functions implementing the standard "writev" system call interface
+
+
+Revision History
+
+--*/
+#include <LibConfig.h>
+
+#ifdef foo
+#include <efi_interface.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#include "./filedesc.h"
+
+#include <libc_debug.h>
+#include <assert.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <string.h>
+#ifndef KERNEL
+#define KERNEL
+#include <errno.h>
+#undef KERNEL
+#else
+#include <errno.h>
+#endif
+
+//
+// Name:
+// writev
+//
+// Description:
+// BSD writev interface for libc
+//
+// Arguments:
+// File Descriptor (index into file descriptor table)
+// iovec pointer
+// size of iovec array
+//
+// Returns:
+// number of bytes written
+//
+
+ssize_t
+writev(
+ int fd,
+ const struct iovec *iov,
+ int iovcnt
+ )
+{
+ const struct iovec *pVecTmp;
+ char *pBuf, *pBufTmp;
+ size_t TotalBytes, i, ret;
+
+ //
+ // See how much memory we'll need
+ //
+
+ for (i = 0, TotalBytes = 0, pVecTmp = iov; i < (size_t)iovcnt; i++, pVecTmp++) {
+ TotalBytes += pVecTmp->iov_len;
+ }
+
+ //
+ // Allocate a contiguous buffer
+ //
+
+ pBuf = (char*)malloc (TotalBytes);
+ if (pBuf == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ //
+ // Copy vectors to the buffer
+ //
+
+ for (pBufTmp = pBuf; iovcnt; iovcnt--) {
+ bcopy(iov->iov_base, pBuf, iov->iov_len);
+ pBuf += iov->iov_len;
+ iov++;
+ }
+
+ //
+ // Use standard write(2) then free buffer
+ //
+
+ ret = write (fd, pBuf, TotalBytes);
+ free (pBuf);
+
+ return (ret);
+}
|