345 lines
15 KiB
C
345 lines
15 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* Open Watcom Project
|
||
|
*
|
||
|
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* ========================================================================
|
||
|
*
|
||
|
* This file contains Original Code and/or Modifications of Original
|
||
|
* Code as defined in and that are subject to the Sybase Open Watcom
|
||
|
* Public License version 1.0 (the 'License'). You may not use this file
|
||
|
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||
|
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||
|
* provided with the Original Code and Modifications, and is also
|
||
|
* available at www.sybase.com/developer/opensource.
|
||
|
*
|
||
|
* The Original Code and all software distributed under the License are
|
||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||
|
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||
|
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||
|
* NON-INFRINGEMENT. Please see the License for the specific language
|
||
|
* governing rights and limitations under the License.
|
||
|
*
|
||
|
* ========================================================================
|
||
|
*
|
||
|
* Description: Implementation of strerror() function.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
|
||
|
#include "variety.h"
|
||
|
#include "widechar.h"
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include "rtdata.h"
|
||
|
#if defined(__NT__)
|
||
|
#include <windows.h>
|
||
|
#endif
|
||
|
#include "errstr.h"
|
||
|
|
||
|
|
||
|
#ifndef __WIDECHAR__
|
||
|
|
||
|
#ifdef __LINUX__
|
||
|
char *_sys_errlist[] = {
|
||
|
/* 0 EOK */ "No error",
|
||
|
/* 1 EPERM */ "Operation not permitted",
|
||
|
/* 2 ENOENT */ "No such file or directory",
|
||
|
/* 3 ESRCH */ "No such process",
|
||
|
/* 4 EINTR */ "Interrupted system call",
|
||
|
/* 5 EIO */ "I/O error",
|
||
|
/* 6 ENXIO */ "No such device or address",
|
||
|
/* 7 E2BIG */ "Arg list too long",
|
||
|
/* 8 ENOEXEC */ "Exec format error",
|
||
|
/* 9 EBADF */ "Bad file number",
|
||
|
/* 10 ECHILD */ "No child processes",
|
||
|
/* 11 EAGAIN */ "Try again",
|
||
|
/* 12 ENOMEM */ "Out of memory",
|
||
|
/* 13 EACCES */ "Permission denied",
|
||
|
/* 14 EFAULT */ "Bad address",
|
||
|
/* 15 ENOTBLK */ "Block device required",
|
||
|
/* 16 EBUSY */ "Device or resource busy",
|
||
|
/* 17 EEXIST */ "File exists",
|
||
|
/* 18 EXDEV */ "Cross-device link",
|
||
|
/* 19 ENODEV */ "No such device",
|
||
|
/* 20 ENOTDIR */ "Not a directory",
|
||
|
/* 21 EISDIR */ "Is a directory",
|
||
|
/* 22 EINVAL */ "Invalid argument",
|
||
|
/* 23 ENFILE */ "File table overflow",
|
||
|
/* 24 EMFILE */ "Too many open files",
|
||
|
/* 25 ENOTTY */ "Not a typewriter",
|
||
|
/* 26 ETXTBSY */ "Text file busy",
|
||
|
/* 27 EFBIG */ "File too large",
|
||
|
/* 28 ENOSPC */ "No space left on device",
|
||
|
/* 29 ESPIPE */ "Illegal seek",
|
||
|
/* 30 EROFS */ "Read-only file system",
|
||
|
/* 31 EMLINK */ "Too many links",
|
||
|
/* 32 EPIPE */ "Broken pipe",
|
||
|
/* 33 EDOM */ "Math argument out of domain of func",
|
||
|
/* 34 ERANGE */ "Math result not representable",
|
||
|
/* 35 EDEADLK */ "Resource deadlock would occur",
|
||
|
/* 36 ENAMETOOLONG */ "File name too long",
|
||
|
/* 37 ENOLCK */ "No record locks available",
|
||
|
/* 38 ENOSYS */ "Function not implemented",
|
||
|
/* 39 ENOTEMPTY */ "Directory not empty",
|
||
|
/* 40 ELOOP */ "Too many symbolic links encountered",
|
||
|
/* 41 */ "",
|
||
|
/* 42 ENOMSG */ "No message of desired type",
|
||
|
/* 43 EIDRM */ "Identifier removed",
|
||
|
/* 44 ECHRNG */ "Channel number out of range",
|
||
|
/* 45 EL2NSYNC */ "Level 2 not synchronized",
|
||
|
/* 46 EL3HLT */ "Level 3 halted",
|
||
|
/* 47 EL3RST */ "Level 3 reset",
|
||
|
/* 48 ELNRNG */ "Link number out of range",
|
||
|
/* 49 EUNATCH */ "Protocol driver not attached",
|
||
|
/* 50 ENOCSI */ "No CSI structure available",
|
||
|
/* 51 EL2HLT */ "Level 2 halted",
|
||
|
/* 52 EBADE */ "Invalid exchange",
|
||
|
/* 53 EBADR */ "Invalid request descriptor",
|
||
|
/* 54 EXFULL */ "Exchange full",
|
||
|
/* 55 ENOANO */ "No anode",
|
||
|
/* 56 EBADRQC */ "Invalid request code",
|
||
|
/* 57 EBADSLT */ "Invalid slot",
|
||
|
/* 58 */ "",
|
||
|
/* 59 EBFONT */ "Bad font file format",
|
||
|
/* 60 ENOSTR */ "Device not a stream",
|
||
|
/* 61 ENODATA */ "No data available",
|
||
|
/* 62 ETIME */ "Timer expired",
|
||
|
/* 63 ENOSR */ "Out of streams resources",
|
||
|
/* 64 ENONET */ "Machine is not on the network",
|
||
|
/* 65 ENOPKG */ "Package not installed",
|
||
|
/* 66 EREMOTE */ "Object is remote",
|
||
|
/* 67 ENOLINK */ "Link has been severed",
|
||
|
/* 68 EADV */ "Advertise error",
|
||
|
/* 69 ESRMNT */ "Srmount error",
|
||
|
/* 70 ECOMM */ "Communication error on send",
|
||
|
/* 71 EPROTO */ "Protocol error",
|
||
|
/* 72 EMULTIHOP */ "Multihop attempted",
|
||
|
/* 73 EDOTDOT */ "RFS specific error",
|
||
|
/* 74 EBADMSG */ "Not a data message",
|
||
|
/* 75 EOVERFLOW */ "Value too large for defined data type",
|
||
|
/* 76 ENOTUNIQ */ "Name not unique on network",
|
||
|
/* 77 EBADFD */ "File descriptor in bad state",
|
||
|
/* 78 EREMCHG */ "Remote address changed",
|
||
|
/* 79 ELIBACC */ "Can not access a needed shared library",
|
||
|
/* 80 ELIBBAD */ "Accessing a corrupted shared library",
|
||
|
/* 81 ELIBSCN */ ".lib section in a.out corrupted",
|
||
|
/* 82 ELIBMAX */ "Attempting to link in too many shared libraries",
|
||
|
/* 83 ELIBEXEC */ "Cannot exec a shared library directly",
|
||
|
/* 84 EILSEQ */ "Illegal byte sequence",
|
||
|
/* 85 ERESTART */ "Interrupted system call should be restarted",
|
||
|
/* 86 ESTRPIPE */ "Streams pipe error",
|
||
|
/* 87 EUSERS */ "Too many users",
|
||
|
/* 88 ENOTSOCK */ "Socket operation on non-socket",
|
||
|
/* 89 EDESTADDRREQ */ "Destination address required",
|
||
|
/* 90 EMSGSIZE */ "Message too long",
|
||
|
/* 91 EPROTOTYPE */ "Protocol wrong type for socket",
|
||
|
/* 92 ENOPROTOOPT */ "Protocol not available",
|
||
|
/* 93 EPROTONOSUPPORT */ "Protocol not supported",
|
||
|
/* 94 ESOCKTNOSUPPORT */ "Socket type not supported",
|
||
|
/* 95 EOPNOTSUPP */ "Operation not supported on transport endpoint",
|
||
|
/* 96 EPFNOSUPPORT */ "Protocol family not supported",
|
||
|
/* 97 EAFNOSUPPORT */ "Address family not supported by protocol",
|
||
|
/* 98 EADDRINUSE */ "Address already in use",
|
||
|
/* 99 EADDRNOTAVAIL */ "Cannot assign requested address",
|
||
|
/* 100 ENETDOWN */ "Network is down",
|
||
|
/* 101 ENETUNREACH */ "Network is unreachable",
|
||
|
/* 102 ENETRESET */ "Network dropped connection because of reset",
|
||
|
/* 103 ECONNABORTED */ "Software caused connection abort",
|
||
|
/* 104 ECONNRESET */ "Connection reset by peer",
|
||
|
/* 105 ENOBUFS */ "No buffer space available",
|
||
|
/* 106 EISCONN */ "Transport endpoint is already connected",
|
||
|
/* 107 ENOTCONN */ "Transport endpoint is not connected",
|
||
|
/* 108 ESHUTDOWN */ "Cannot send after transport endpoint shutdown",
|
||
|
/* 109 ETOOMANYREFS */ "Too many references: cannot splice",
|
||
|
/* 110 ETIMEDOUT */ "Connection timed out",
|
||
|
/* 111 ECONNREFUSED */ "Connection refused",
|
||
|
/* 112 EHOSTDOWN */ "Host is down",
|
||
|
/* 113 EHOSTUNREACH */ "No route to host",
|
||
|
/* 114 EALREADY */ "Operation already in progress",
|
||
|
/* 115 EINPROGRESS */ "Operation now in progress",
|
||
|
/* 116 ESTALE */ "Stale NFS file handle",
|
||
|
/* 117 EUCLEAN */ "Structure needs cleaning",
|
||
|
/* 118 ENOTNAM */ "Not a XENIX named type file",
|
||
|
/* 119 ENAVAIL */ "No XENIX semaphores available",
|
||
|
/* 120 EISNAM */ "Is a named type file",
|
||
|
/* 121 EREMOTEIO */ "Remote I/O error",
|
||
|
/* 122 EDQUOT */ "Quota exceeded",
|
||
|
/* 121 */ "",
|
||
|
/* 123 ENOMEDIUM */ "No medium found",
|
||
|
/* 124 EMEDIUMTYPE */ "Wrong medium type"
|
||
|
/* if more are added, be sure to update _sys_nerr accordingly */
|
||
|
};
|
||
|
#else
|
||
|
char *_sys_errlist[] = {
|
||
|
/* 0 EZERO */ "No error",
|
||
|
/* 1 ENOENT */ "No such file or directory",
|
||
|
/* 2 E2BIG */ "Arg list too big",
|
||
|
/* 3 ENOEXEC */ "Exec format error",
|
||
|
/* 4 EBADF */ "Bad file number",
|
||
|
/* 5 ENOMEM */ "Not enough memory",
|
||
|
/* 6 EACCES */ "Permission denied",
|
||
|
/* 7 EEXIST */ "File exists",
|
||
|
/* 8 EXDEV */ "Cross-device link",
|
||
|
/* 9 EINVAL */ "Invalid argument",
|
||
|
/* 10 ENFILE */ "File table overflow",
|
||
|
/* 11 EMFILE */ "Too many open files",
|
||
|
/* 12 ENOSPC */ "No space left on device",
|
||
|
/* 13 EDOM */ "Argument too large",
|
||
|
/* 14 ERANGE */ "Result too large",
|
||
|
/* 15 EDEADLK */ "Resource deadlock would occur",
|
||
|
/* 16 EINTR */ "System call interrupted",
|
||
|
/* 17 ECHILD */ "Child does not exist",
|
||
|
/* 18 EAGAIN */ "Resource unavailable, try again",
|
||
|
/* 19 EBUSY */ "Device or resource busy",
|
||
|
/* 20 EFBIG */ "File too large",
|
||
|
/* 21 EIO */ "I/O error",
|
||
|
/* 22 EISDIR */ "Is a directory",
|
||
|
/* 23 ENOTDIR */ "Not a directory",
|
||
|
/* 24 EMLINK */ "Too many links",
|
||
|
/* 25 ENOTBLK */ "Block device required",
|
||
|
/* 26 ENOTTY */ "Not a character device",
|
||
|
/* 27 ENXIO */ "No such device or address",
|
||
|
/* 28 EPERM */ "Not owner",
|
||
|
/* 29 EPIPE */ "Broken pipe",
|
||
|
/* 30 EROFS */ "Read-only file system",
|
||
|
/* 31 ESPIPE */ "Illegal seek",
|
||
|
/* 32 ESRCH */ "No such process",
|
||
|
/* 33 ETXTBSY */ "Text file busy",
|
||
|
/* 34 EFAULT */ "Bad address",
|
||
|
/* 35 ENAMETOOLONG */ "Filename too long",
|
||
|
/* 36 ENODEV */ "No such device",
|
||
|
/* 37 ENOLCK */ "No locks available in system",
|
||
|
/* 38 ENOSYS */ "Unknown system call",
|
||
|
/* 39 ENOTEMPTY */ "Directory not empty",
|
||
|
/* 40 EILSEQ */ "Illegal multibyte sequence"
|
||
|
/* if more are added, be sure to update _sys_nerr accordingly */
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
int _WCNEAR _sys_nerr = ( sizeof( _sys_errlist ) / sizeof( *_sys_errlist ) );
|
||
|
|
||
|
#endif
|
||
|
|
||
|
_WCRTLINK CHAR_TYPE *__F_NAME(strerror,wcserror)( int errnum )
|
||
|
{
|
||
|
#ifdef __WIDECHAR__
|
||
|
static wchar_t Wide_Error_String[40];
|
||
|
#endif
|
||
|
char *msg;
|
||
|
|
||
|
if( errnum < 0 || errnum >= _sys_nerr ) {
|
||
|
msg = UNKNOWN_ERROR;
|
||
|
} else {
|
||
|
msg = _sys_errlist[ errnum ];
|
||
|
}
|
||
|
return( _AToUni( Wide_Error_String, msg ) );
|
||
|
}
|
||
|
|
||
|
// Note: Windows FORMAT_MESSAGE_MAX_WIDTH_MASK is 255
|
||
|
|
||
|
#if !defined(FORMAT_MESSAGE_MAX_WIDTH_MASK)
|
||
|
#define FORMAT_MESSAGE_MAX_WIDTH_MASK 255
|
||
|
#endif
|
||
|
|
||
|
#ifdef __WIDECHAR__
|
||
|
static wchar_t Wide_Error_String[FORMAT_MESSAGE_MAX_WIDTH_MASK+1];
|
||
|
#else
|
||
|
static char Error_String[FORMAT_MESSAGE_MAX_WIDTH_MASK+1];
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
char *_strerror( const char *strErrMsg );
|
||
|
|
||
|
Description from the MSDN:
|
||
|
|
||
|
If strErrMsg is passed as NULL, _strerror returns a pointer to a
|
||
|
string containing the system error message for the last library call
|
||
|
that produced an error. The error-message string is terminated by
|
||
|
the newline character ('\n'). If strErrMsg is not equal to NULL,
|
||
|
then _strerror returns a pointer to a string containing (in order)
|
||
|
your string message, a colon, a space, the system error message for
|
||
|
the last library call producing an error, and a newline character.
|
||
|
Your string message can be, at most, 94 bytes long.
|
||
|
|
||
|
The actual error number for _strerror is stored in the variable
|
||
|
errno. The system error messages are accessed through the variable
|
||
|
_sys_errlist, which is an array of messages ordered by error number.
|
||
|
_strerror accesses the appropriate error message by using the errno
|
||
|
value as an index to the variable _sys_errlist. The value of the
|
||
|
variable _sys_nerr is defined as the maximum number of elements in
|
||
|
the _sys_errlist array. To produce accurate results, call _strerror
|
||
|
immediately after a library routine returns with an error.
|
||
|
Otherwise, subsequent calls to strerror or _strerror can overwrite
|
||
|
the errno value.
|
||
|
|
||
|
_strerror is not part of the ANSI definition but is instead a
|
||
|
Microsoft extension to it. Do not use it where portability is
|
||
|
desired; for ANSI compatibility, use strerror instead.
|
||
|
|
||
|
*/
|
||
|
|
||
|
_WCRTLINK CHAR_TYPE *__F_NAME(_strerror,_wcserror)( const CHAR_TYPE *strErrMsg )
|
||
|
{
|
||
|
int errnum;
|
||
|
|
||
|
errnum = _RWD_errno;
|
||
|
#ifdef __WIDECHAR__
|
||
|
Wide_Error_String[0] = L'\0';
|
||
|
if( strErrMsg != NULL ) {
|
||
|
wcsncpy( Wide_Error_String, strErrMsg, 94 );
|
||
|
Wide_Error_String[94] = L'\0'; // just in case more than 94
|
||
|
wcscat( Wide_Error_String, L": " );
|
||
|
}
|
||
|
wcscat( Wide_Error_String, wcserror( errnum ) );
|
||
|
wcscat( Wide_Error_String, L"\n" );
|
||
|
return( Wide_Error_String );
|
||
|
#else
|
||
|
Error_String[0] = '\0';
|
||
|
if( strErrMsg != NULL ) {
|
||
|
strncpy( Error_String, strErrMsg, 94 );
|
||
|
Error_String[94] = '\0'; // just in case more than 94
|
||
|
strcat( Error_String, ": " );
|
||
|
}
|
||
|
strcat( Error_String, strerror( errnum ) );
|
||
|
strcat( Error_String, "\n" );
|
||
|
return( Error_String );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#if defined(__NT__)
|
||
|
|
||
|
_WCRTLINK CHAR_TYPE *__F_NAME(_doserror,_wdoserror)( int errnum )
|
||
|
{
|
||
|
#ifdef __WIDECHAR__
|
||
|
Wide_Error_String[0] = L'\0';
|
||
|
FormatMessageW( FORMAT_MESSAGE_IGNORE_INSERTS |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||
|
NULL,
|
||
|
errnum,
|
||
|
0,
|
||
|
Wide_Error_String,
|
||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||
|
NULL );
|
||
|
return( Wide_Error_String );
|
||
|
#else
|
||
|
Error_String[0] = '\0';
|
||
|
FormatMessageA( FORMAT_MESSAGE_IGNORE_INSERTS |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||
|
NULL,
|
||
|
errnum,
|
||
|
0,
|
||
|
Error_String,
|
||
|
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||
|
NULL );
|
||
|
return( Error_String );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#endif
|