mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-01 03:53:33 +00:00
f064183646
See #61 See #104
339 lines
8 KiB
C
339 lines
8 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ Permission to use, copy, modify, and/or 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 THE AUTHOR DISCLAIMS ALL │
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
│ AUTHOR 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 "libc/bits/safemacros.internal.h"
|
|
#include "libc/dce.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/fmt/fmt.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/nt/enum/formatmessageflags.h"
|
|
#include "libc/nt/process.h"
|
|
#include "libc/nt/runtime.h"
|
|
#include "libc/str/str.h"
|
|
|
|
STATIC_YOINK("E2BIG");
|
|
STATIC_YOINK("EACCES");
|
|
STATIC_YOINK("EADDRINUSE");
|
|
STATIC_YOINK("EADDRNOTAVAIL");
|
|
STATIC_YOINK("EADV");
|
|
STATIC_YOINK("EAFNOSUPPORT");
|
|
STATIC_YOINK("EAGAIN");
|
|
STATIC_YOINK("EALREADY");
|
|
STATIC_YOINK("EBADE");
|
|
STATIC_YOINK("EBADF");
|
|
STATIC_YOINK("EBADFD");
|
|
STATIC_YOINK("EBADMSG");
|
|
STATIC_YOINK("EBADR");
|
|
STATIC_YOINK("EBADRQC");
|
|
STATIC_YOINK("EBADSLT");
|
|
STATIC_YOINK("EBFONT");
|
|
STATIC_YOINK("EBUSY");
|
|
STATIC_YOINK("ECANCELED");
|
|
STATIC_YOINK("ECHILD");
|
|
STATIC_YOINK("ECHRNG");
|
|
STATIC_YOINK("ECOMM");
|
|
STATIC_YOINK("ECONNABORTED");
|
|
STATIC_YOINK("ECONNREFUSED");
|
|
STATIC_YOINK("ECONNRESET");
|
|
STATIC_YOINK("EDEADLK");
|
|
STATIC_YOINK("EDESTADDRREQ");
|
|
STATIC_YOINK("EDOM");
|
|
STATIC_YOINK("EDOTDOT");
|
|
STATIC_YOINK("EDQUOT");
|
|
STATIC_YOINK("EEXIST");
|
|
STATIC_YOINK("EFAULT");
|
|
STATIC_YOINK("EFBIG");
|
|
STATIC_YOINK("EHOSTDOWN");
|
|
STATIC_YOINK("EHOSTUNREACH");
|
|
STATIC_YOINK("EHWPOISON");
|
|
STATIC_YOINK("EIDRM");
|
|
STATIC_YOINK("EILSEQ");
|
|
STATIC_YOINK("EINPROGRESS");
|
|
STATIC_YOINK("EINTR");
|
|
STATIC_YOINK("EINVAL");
|
|
STATIC_YOINK("EIO");
|
|
STATIC_YOINK("EISCONN");
|
|
STATIC_YOINK("EISDIR");
|
|
STATIC_YOINK("EISNAM");
|
|
STATIC_YOINK("EKEYEXPIRED");
|
|
STATIC_YOINK("EKEYREJECTED");
|
|
STATIC_YOINK("EKEYREVOKED");
|
|
STATIC_YOINK("EL2HLT");
|
|
STATIC_YOINK("EL2NSYNC");
|
|
STATIC_YOINK("EL3HLT");
|
|
STATIC_YOINK("EL3RST");
|
|
STATIC_YOINK("ELIBACC");
|
|
STATIC_YOINK("ELIBBAD");
|
|
STATIC_YOINK("ELIBEXEC");
|
|
STATIC_YOINK("ELIBMAX");
|
|
STATIC_YOINK("ELIBSCN");
|
|
STATIC_YOINK("ELNRNG");
|
|
STATIC_YOINK("ELOOP");
|
|
STATIC_YOINK("EMEDIUMTYPE");
|
|
STATIC_YOINK("EMFILE");
|
|
STATIC_YOINK("EMLINK");
|
|
STATIC_YOINK("EMSGSIZE");
|
|
STATIC_YOINK("EMULTIHOP");
|
|
STATIC_YOINK("ENAMETOOLONG");
|
|
STATIC_YOINK("ENAVAIL");
|
|
STATIC_YOINK("ENETDOWN");
|
|
STATIC_YOINK("ENETRESET");
|
|
STATIC_YOINK("ENETUNREACH");
|
|
STATIC_YOINK("ENFILE");
|
|
STATIC_YOINK("ENOANO");
|
|
STATIC_YOINK("ENOBUFS");
|
|
STATIC_YOINK("ENOCSI");
|
|
STATIC_YOINK("ENODATA");
|
|
STATIC_YOINK("ENODEV");
|
|
STATIC_YOINK("ENOENT");
|
|
STATIC_YOINK("ENOEXEC");
|
|
STATIC_YOINK("ENOKEY");
|
|
STATIC_YOINK("ENOLCK");
|
|
STATIC_YOINK("ENOLINK");
|
|
STATIC_YOINK("ENOMEDIUM");
|
|
STATIC_YOINK("ENOMEM");
|
|
STATIC_YOINK("ENOMSG");
|
|
STATIC_YOINK("ENONET");
|
|
STATIC_YOINK("ENOPKG");
|
|
STATIC_YOINK("ENOPROTOOPT");
|
|
STATIC_YOINK("ENOSPC");
|
|
STATIC_YOINK("ENOSR");
|
|
STATIC_YOINK("ENOSTR");
|
|
STATIC_YOINK("ENOSYS");
|
|
STATIC_YOINK("ENOTBLK");
|
|
STATIC_YOINK("ENOTCONN");
|
|
STATIC_YOINK("ENOTDIR");
|
|
STATIC_YOINK("ENOTEMPTY");
|
|
STATIC_YOINK("ENOTNAM");
|
|
STATIC_YOINK("ENOTRECOVERABLE");
|
|
STATIC_YOINK("ENOTSOCK");
|
|
STATIC_YOINK("ENOTSUP");
|
|
STATIC_YOINK("ENOTTY");
|
|
STATIC_YOINK("ENOTUNIQ");
|
|
STATIC_YOINK("ENXIO");
|
|
STATIC_YOINK("EOPNOTSUPP");
|
|
STATIC_YOINK("EOVERFLOW");
|
|
STATIC_YOINK("EOWNERDEAD");
|
|
STATIC_YOINK("EPERM");
|
|
STATIC_YOINK("EPFNOSUPPORT");
|
|
STATIC_YOINK("EPIPE");
|
|
STATIC_YOINK("EPROTO");
|
|
STATIC_YOINK("EPROTONOSUPPORT");
|
|
STATIC_YOINK("EPROTOTYPE");
|
|
STATIC_YOINK("ERANGE");
|
|
STATIC_YOINK("EREMCHG");
|
|
STATIC_YOINK("EREMOTE");
|
|
STATIC_YOINK("EREMOTEIO");
|
|
STATIC_YOINK("ERESTART");
|
|
STATIC_YOINK("ERFKILL");
|
|
STATIC_YOINK("EROFS");
|
|
STATIC_YOINK("ESHUTDOWN");
|
|
STATIC_YOINK("ESOCKTNOSUPPORT");
|
|
STATIC_YOINK("ESPIPE");
|
|
STATIC_YOINK("ESRCH");
|
|
STATIC_YOINK("ESRMNT");
|
|
STATIC_YOINK("ESTALE");
|
|
STATIC_YOINK("ESTRPIPE");
|
|
STATIC_YOINK("ETIME");
|
|
STATIC_YOINK("ETIMEDOUT");
|
|
STATIC_YOINK("ETOOMANYREFS");
|
|
STATIC_YOINK("ETXTBSY");
|
|
STATIC_YOINK("EUCLEAN");
|
|
STATIC_YOINK("EUNATCH");
|
|
STATIC_YOINK("EUSERS");
|
|
STATIC_YOINK("EXDEV");
|
|
STATIC_YOINK("EXFULL");
|
|
|
|
_Alignas(char) static const char kErrnoNames[] = "\
|
|
2BIG\000\
|
|
ACCES\000\
|
|
ADDRINUSE\000\
|
|
ADDRNOTAVAIL\000\
|
|
ADV\000\
|
|
AFNOSUPPORT\000\
|
|
AGAIN\000\
|
|
ALREADY\000\
|
|
BADE\000\
|
|
BADF\000\
|
|
BADFD\000\
|
|
BADMSG\000\
|
|
BADR\000\
|
|
BADRQC\000\
|
|
BADSLT\000\
|
|
BFONT\000\
|
|
BUSY\000\
|
|
CANCELED\000\
|
|
CHILD\000\
|
|
CHRNG\000\
|
|
COMM\000\
|
|
CONNABORTED\000\
|
|
CONNREFUSED\000\
|
|
CONNRESET\000\
|
|
DEADLK\000\
|
|
DESTADDRREQ\000\
|
|
DOM\000\
|
|
DOTDOT\000\
|
|
DQUOT\000\
|
|
EXIST\000\
|
|
FAULT\000\
|
|
FBIG\000\
|
|
HOSTDOWN\000\
|
|
HOSTUNREACH\000\
|
|
HWPOISON\000\
|
|
IDRM\000\
|
|
ILSEQ\000\
|
|
INPROGRESS\000\
|
|
INTR\000\
|
|
INVAL\000\
|
|
IO\000\
|
|
ISCONN\000\
|
|
ISDIR\000\
|
|
ISNAM\000\
|
|
KEYEXPIRED\000\
|
|
KEYREJECTED\000\
|
|
KEYREVOKED\000\
|
|
L2HLT\000\
|
|
L2NSYNC\000\
|
|
L3HLT\000\
|
|
L3RST\000\
|
|
LIBACC\000\
|
|
LIBBAD\000\
|
|
LIBEXEC\000\
|
|
LIBMAX\000\
|
|
LIBSCN\000\
|
|
LNRNG\000\
|
|
LOOP\000\
|
|
MEDIUMTYPE\000\
|
|
MFILE\000\
|
|
MLINK\000\
|
|
MSGSIZE\000\
|
|
MULTIHOP\000\
|
|
NAMETOOLONG\000\
|
|
NAVAIL\000\
|
|
NETDOWN\000\
|
|
NETRESET\000\
|
|
NETUNREACH\000\
|
|
NFILE\000\
|
|
NOANO\000\
|
|
NOBUFS\000\
|
|
NOCSI\000\
|
|
NODATA\000\
|
|
NODEV\000\
|
|
NOENT\000\
|
|
NOEXEC\000\
|
|
NOKEY\000\
|
|
NOLCK\000\
|
|
NOLINK\000\
|
|
NOMEDIUM\000\
|
|
NOMEM\000\
|
|
NOMSG\000\
|
|
NONET\000\
|
|
NOPKG\000\
|
|
NOPROTOOPT\000\
|
|
NOSPC\000\
|
|
NOSR\000\
|
|
NOSTR\000\
|
|
NOSYS\000\
|
|
NOTBLK\000\
|
|
NOTCONN\000\
|
|
NOTDIR\000\
|
|
NOTEMPTY\000\
|
|
NOTNAM\000\
|
|
NOTRECOVERABLE\000\
|
|
NOTSOCK\000\
|
|
NOTSUP\000\
|
|
NOTTY\000\
|
|
NOTUNIQ\000\
|
|
NXIO\000\
|
|
OPNOTSUPP\000\
|
|
OVERFLOW\000\
|
|
OWNERDEAD\000\
|
|
PERM\000\
|
|
PFNOSUPPORT\000\
|
|
PIPE\000\
|
|
PROTO\000\
|
|
PROTONOSUPPORT\000\
|
|
PROTOTYPE\000\
|
|
RANGE\000\
|
|
REMCHG\000\
|
|
REMOTE\000\
|
|
REMOTEIO\000\
|
|
RESTART\000\
|
|
RFKILL\000\
|
|
ROFS\000\
|
|
SHUTDOWN\000\
|
|
SOCKTNOSUPPORT\000\
|
|
SPIPE\000\
|
|
SRCH\000\
|
|
SRMNT\000\
|
|
STALE\000\
|
|
STRPIPE\000\
|
|
TIME\000\
|
|
TIMEDOUT\000\
|
|
TOOMANYREFS\000\
|
|
TXTBSY\000\
|
|
UCLEAN\000\
|
|
UNATCH\000\
|
|
USERS\000\
|
|
XDEV\000\
|
|
XFULL\000\
|
|
\000";
|
|
|
|
static const char *geterrname(long code) {
|
|
const long *e;
|
|
size_t i, n;
|
|
e = &E2BIG;
|
|
n = &EXFULL + 1 - e;
|
|
for (i = 0; i < n; ++i) {
|
|
if (code == e[i]) {
|
|
return IndexDoubleNulString(kErrnoNames, i);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* Converts errno value to string.
|
|
* @return 0 on success, or error code
|
|
*/
|
|
int strerror_r(int err, char *buf, size_t size) {
|
|
const char *s;
|
|
char16_t buf16[100];
|
|
int winstate, sysvstate;
|
|
if (!err || IsTiny()) {
|
|
s = "?";
|
|
} else {
|
|
s = firstnonnull(geterrname(err), "?");
|
|
}
|
|
if (!SupportsWindows()) {
|
|
(snprintf)(buf, size, "E%s[%d]", s, err);
|
|
} else {
|
|
winstate = GetLastError();
|
|
sysvstate = errno;
|
|
if (FormatMessage(
|
|
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL,
|
|
err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) {
|
|
chomp16(buf16);
|
|
} else {
|
|
buf16[0] = u'\0';
|
|
}
|
|
(snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
|
|
sysvstate, winstate, buf16[0] ? " " : "", buf16);
|
|
}
|
|
return 0;
|
|
}
|