blob: ed80a3bdb7c2186e7285cb7ccfb34d8dea29c66f [file] [log] [blame] [raw]
/* A part of the Native C Library for Windows NT
Copyright 2007-2015 PC GO Ld.
Copyright 2026 Rivoreo
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
*/
#include <string.h>
#include <errno.h>
#include <stdio.h>
static const char *get_static_error_message(int e) {
switch(e) {
case 0: return "Success";
case EPERM: return "Operation not permitted";
case ENOENT: return "No such file or directory";
case ESRCH: return "No such process";
case EINTR: return "Interrupted call";
case EIO: return "Input/output error";
case ENXIO: return "Device not configured";
case E2BIG: return "Argument list too long";
case ENOEXEC: return "Exec format error";
case EBADF: return "Bad file descriptor";
case ECHILD: return "No child processes";
case EAGAIN: return "Resource temporarily unavailable";
case ENOMEM: return "Cannot allocate memory";
case EACCES: return "Permission denied";
case EFAULT: return "Bad address";
case EBUSY: return "Device or resource busy";
case EEXIST: return "File exists";
case EXDEV: return "Cross-device link";
case ENODEV: return "No such device";
case ENOTDIR: return "Not a directory";
case EISDIR: return "Is a directory";
case EINVAL: return "Invalid argument";
case ENFILE: return "Too many open files in system";
case EMFILE: return "Too many open files";
case ENOTTY: return "Inappropriate ioctl for device";
case ETXTBSY: return "Text file busy";
case EFBIG: return "File too large";
case ENOSPC: return "No space left on device";
case ESPIPE: return "Illegal seek";
case EROFS: return "Read-only file system";
case EMLINK: return "Too many links";
case EPIPE: return "Broken pipe";
case EDOM: return "Numerical argument out of domain";
case ERANGE: return "Result too large";
case EDEADLK: return "Resource deadlock avoided";
case EINPROGRESS: return "Operation now in progress";
case EALREADY: return "Operation already in progress";
case ENOTSOCK: return "Socket operation on non-socket";
case EDESTADDRREQ: return "Destination address required";
case EMSGSIZE: return "Message too long";
case EPROTOTYPE: return "Protocol wrong type for socket";
case ENOPROTOOPT: return "Protocol not available";
case EPROTONOSUPPORT: return "Protocol not supported";
case ESOCKTNOSUPPORT: return "Socket type not supported";
case EOPNOTSUPP: return "Operation not supported";
case EPFNOSUPPORT: return "Protocol family not supported";
case EADDRINUSE: return "Address already in use";
case EADDRNOTAVAIL: return "Can't assign requested address";
case ENETDOWN: return "Network is down";
case ENETUNREACH: return "Network is unreachable";
case ENETRESET: return "Network dropped connection on reset";
case ECONNABORTED: return "Software caused connection abort";
case ECONNRESET: return "Connection reset by peer";
case ENOBUFS: return "No buffer space available";
case EISCONN: return "Socket is already connected";
case ENOTCONN: return "Socket is not connected";
case ESHUTDOWN: return "Can't send after socket shutdown";
case ETOOMANYREFS: return "Too many references: can't splice";
case ETIMEDOUT: return "Operation timed out";
case ECONNREFUSED: return "Connection refused";
case ELOOP: return "Too many levels of symbolic links";
case ENAMETOOLONG: return "File name too long";
case EHOSTDOWN: return "Host is down";
case EHOSTUNREACH: return "No route to host";
case ENOTEMPTY: return "Directory not empty";
case EPROCLIM: return "Too many processes";
case EUSERS: return "Too many users";
case EDQUOT: return "Disc quota exceeded";
case ESTALE: return "Stale NFS file handle";
case EREMOTE: return "Too many levels of remote in path";
case EBADRPC: return "RPC struct is bad";
case ERPCMISMATCH: return "RPC version wrong";
case EPROGUNAVAIL: return "RPC prog. not avail";
case EPROGMISMATCH: return "Program version wrong";
case EPROCUNAVAIL: return "Bad procedure for program";
case ENOLCK: return "No locks available";
case ENOSYS: return "Function not implemented";
case EFTYPE: return "Inappropriate file type or format";
case EAUTH: return "Authentication error";
case ENEEDAUTH: return "Need authenticator";
case EIDRM: return "Identifier removed";
case ENOMSG: return "No message of desired type";
case EOVERFLOW: return "Value too large to be stored in data type";
case ECANCELED: return "Operation canceled";
case EILSEQ: return "Illegal byte sequence";
case ENOATTR: return "Attribute not found";
case EBADMSG: return "Bad message";
case EMULTIHOP: return "Multihop attempted";
case ENOLINK: return "Link has been severed";
case EPROTO: return "Protocol error";
case ENOTRECOVERABLE: return "State not recoverable";
case EOWNERDEAD: return "Previous owner died";
case ENODATA: return "No data available";
case ETIME: return "Timer expired";
case ENOTUNIQ: return "Name not unique on network";
case ELIBBAD: return "Accessing a corrupted shared library";
case EUCLEAN: return "Structure needs cleaning";
case EREMOTEIO: return "Remote I/O error";
case ENOMEDIUM: return "No medium found";
case EMEDIUMTYPE: return "Wrong medium type";
}
return NULL;
}
#define MAKE_UNKNOWN_ERROR_MESSAGE(N,MSG) \
do { \
if((N) & 0x80000000) sprintf((MSG), "Unmapped NT status 0x%lx", (long int)((((N) << 4) & 0xf0000000) | ((N) & 0xffffff))); \
else sprintf((MSG), "Unknown error %d", (N)); \
} while(0)
char *strerror(int e) {
const char *static_msg = get_static_error_message(e);
if(static_msg) return (char *)static_msg;
static char msg[512];
MAKE_UNKNOWN_ERROR_MESSAGE(e, msg);
errno = EINVAL;
return msg;
}
char *_gnu_strerror_r(int number, char *buffer, size_t size) {
if(!size) {
errno = ERANGE;
return buffer;
}
char unknown_error_message[512];
const char *message = get_static_error_message(number);
if(!message) {
MAKE_UNKNOWN_ERROR_MESSAGE(number, unknown_error_message);
message = unknown_error_message;
errno = EINVAL;
}
size_t len = strlen(message);
if(len > size - 1) {
len = size - 1;
errno = ERANGE;
}
buffer[len] = 0;
return memcpy(buffer, message, len);
}
int _xpg_strerror_r(int number, char *buffer, size_t size) {
if(!size) return ERANGE;
//int orig_errno = errno;
int r = 0;
char unknown_error_message[512];
const char *message = get_static_error_message(number);
if(!message) {
MAKE_UNKNOWN_ERROR_MESSAGE(number, unknown_error_message);
message = unknown_error_message;
r = EINVAL;
}
size_t len = strlen(message);
if(len > size - 1) {
len = size - 1;
r = ERANGE;
}
memcpy(buffer, message, len);
buffer[len] = 0;
//errno = orig_errno;
return r;
}