/**************************************************************************** * * 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 #include #include "rtdata.h" #if defined(__NT__) #include #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