diff --git a/ape/ape.S b/ape/ape.S index ad4986203..e355ae632 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -865,48 +865,48 @@ ape_macho: @see "The Portable Executable File Format from Top to Bottom", Randy Kath, Microsoft Developer Network Technology Group. */ -// ┌14:Uniprocessor Machine ┌─────────────────────────┐ -// │┌13:DLL │ PE File Characteristics │ -// ││┌12:System ├─────────────────────────┤ -// │││┌11:If Net Run From Swap │ r │ reserved │ -// ││││┌10:If Removable Run From Swap │ d │ deprecated │ -// │││││┌9:Debug Stripped │ D │ deprecated with │ -// ││││││┌8:32bit Machine │ │ extreme prejudice │ -// │││││││ ┌5:Large Address Aware └───┴─────────────────────┘ -// │││││││ │ ┌1:Executable -// │││││││ │ │┌0:Relocs Stripped -// d│││││││dr│Ddd││ -PEEXE = 0b0000001000100011 +// ┌14:Uniprocessor Machine ┌─────────────────────────┐ +// │┌13:DLL │ PE File Characteristics │ +// ││┌12:System ├─────────────────────────┤ +// │││┌11:If Net Run From Swap │ r │ reserved │ +// ││││┌10:If Removable Run From Swap │ d │ deprecated │ +// │││││┌9:Debug Stripped │ D │ deprecated with │ +// ││││││┌8:32bit Machine │ │ extreme prejudice │ +// │││││││ ┌5:Large Address Aware └───┴─────────────────────┘ +// │││││││ │ ┌1:Executable +// │││││││ │ │┌0:Relocs Stripped +// d│││││││dr│Ddd││ +PEEXE = 0b00000001000100011 -// ┌15:TERMINAL_SERVER_AWARE ┌─────────────────────────┐ -// │┌14:GUARD_CF │ PE DLL Characteristics │ -// ││┌13:WDM_DRIVER ├─────────────────────────┤ -// │││┌12:APPCONTAINER │ r │ reserved │ -// ││││┌11:NO_BIND └───┴─────────────────────┘ -// │││││┌10:NO_SEH -// ││││││┌9:NO_ISOLATION -// │││││││┌8:NX_COMPAT -// ││││││││┌7:FORCE_INTEGRITY -// │││││││││┌6:DYNAMIC_BASE -// ││││││││││┌5:HIGH_ENTROPY_VA -// │││││││││││rrrrr +// ┌15:TERMINAL_SERVER_AWARE ┌─────────────────────────┐ +// │┌14:GUARD_CF │ PE DLL Characteristics │ +// ││┌13:WDM_DRIVER ├─────────────────────────┤ +// │││┌12:APPCONTAINER │ r │ reserved │ +// ││││┌11:NO_BIND └───┴─────────────────────┘ +// │││││┌10:NO_SEH +// ││││││┌9:NO_ISOLATION +// │││││││┌8:NX_COMPAT +// ││││││││┌7:FORCE_INTEGRITY +// │││││││││┌6:DYNAMIC_BASE +// ││││││││││┌5:HIGH_ENTROPY_VA +// │││││││││││rrrrr DLLSTD = 0b0000000100100000 DLLPIE = 0b0000000001100000 DLLEXE = DLLSTD -// ┌31:Writeable ┌─────────────────────────┐ -// │┌30:Readable │ PE Section Flags │ -// ││┌29:Executable ├─────────────────────────┤ -// │││┌28:Shareable │ o │ for object files │ -// ││││┌27:Unpageable │ r │ reserved │ -// │││││┌26:Uncacheable └───┴─────────────────────┘ -// ││││││┌25:Discardable -// │││││││┌24:Contains Extended Relocations -// ││││││││ ┌15:Contains Global Pointer (GP) Relative Data -// ││││││││ │ ┌7:Contains Uninitialized Data -// ││││││││ │ │┌6:Contains Initialized Data -// ││││││││ o │ ││┌5:Contains Code -// ││││││││┌┴─┐rrrr│ ooror│││rorrr +// ┌31:Writeable ┌─────────────────────────┐ +// │┌30:Readable │ PE Section Flags │ +// ││┌29:Executable ├─────────────────────────┤ +// │││┌28:Shareable │ o │ for object files │ +// ││││┌27:Unpageable │ r │ reserved │ +// │││││┌26:Uncacheable └───┴─────────────────────┘ +// ││││││┌25:Discardable +// │││││││┌24:Contains Extended Relocations +// ││││││││ ┌15:Contains Global Pointer (GP) Relative Data +// ││││││││ │ ┌7:Contains Uninitialized Data +// ││││││││ │ │┌6:Contains Initialized Data +// ││││││││ o │ ││┌5:Contains Code +// ││││││││┌┴─┐rrrr│ ooror│││rorrr PETEXT = 0b01110000000000000000000001100000 PEDATA = 0b11000000000000000000000011000000 PEIMPS = 0b11000000000000000000000001000000 @@ -1437,7 +1437,7 @@ long: push $GDT_LONG_DATA .endfn long /* ▄▄▒▀▀▀▀▒▒▄ -█████▓▓▄░░░░ ▒▒▄░ +█████▓▓▄░░░░ ▒▒▄ ▐█▓▓█▓▄█████▓░ ▀▒▄ ▓█▓▓▓▓▓▓▓▓▓█▓ ░▀▒░ ▀▀▓█▓▓▓▓▓▓█▓ ░▀▒▄▄▒▄▄▄▒▒▒▀▀▀▀▀▀▀▀▀▀▀▀▀▀▒▒▄▒ diff --git a/build/bootstrap/package.com b/build/bootstrap/package.com index c166f1018..4266ab544 100755 Binary files a/build/bootstrap/package.com and b/build/bootstrap/package.com differ diff --git a/build/bootstrap/zipobj.com b/build/bootstrap/zipobj.com index d148bd22d..bbe95476f 100755 Binary files a/build/bootstrap/zipobj.com and b/build/bootstrap/zipobj.com differ diff --git a/libc/alg/bisect.internal.h b/libc/alg/bisect.internal.h index beaa9be7b..242d50668 100644 --- a/libc/alg/bisect.internal.h +++ b/libc/alg/bisect.internal.h @@ -6,19 +6,23 @@ COSMOPOLITAN_C_START_ forceinline void *bisect(const void *k, const void *data, size_t n, size_t size, int cmp(const void *a, const void *b, void *arg), void *arg) { - int dir; - const char *p, *pos; - p = data; - while (n > 0) { - pos = p + size * (n / 2); - dir = cmp(k, pos, arg); - if (dir < 0) { - n /= 2; - } else if (dir > 0) { - p = pos + size; - n -= n / 2 + 1; - } else { - return (void *)pos; + int c; + const char *p; + ssize_t m, l, r; + if (n) { + l = 0; + r = n - 1; + p = data; + while (l <= r) { + m = (l + r) >> 1; + c = cmp(k, p + m * size, arg); + if (c > 0) { + l = m + 1; + } else if (c < 0) { + r = m - 1; + } else { + return p + m * size; + } } } return NULL; diff --git a/libc/bits/bitreverse16.c b/libc/bits/bitreverse16.c index c3a8058a7..7769ec82c 100644 --- a/libc/bits/bitreverse16.c +++ b/libc/bits/bitreverse16.c @@ -21,6 +21,6 @@ /** * Reverses bits in 16-bit word. */ -uint16_t(bitreverse16)(uint16_t x) { - return kReverseBits[x & 0x00FF] << 8 | kReverseBits[(x & 0xFF00) >> 8]; +int bitreverse16(int x) { + return BITREVERSE16(x); } diff --git a/libc/bits/bitreverse32.c b/libc/bits/bitreverse32.c index 405068a13..126e5403a 100644 --- a/libc/bits/bitreverse32.c +++ b/libc/bits/bitreverse32.c @@ -22,10 +22,10 @@ /** * Reverses bits in 32-bit word. */ -uint32_t(bitreverse32)(uint32_t x) { +uint32_t bitreverse32(uint32_t x) { x = bswap_32(x); - x = ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1); - x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2); - x = ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4); + x = (x & 0xaaaaaaaa) >> 1 | (x & 0x55555555) << 1; + x = (x & 0xcccccccc) >> 2 | (x & 0x33333333) << 2; + x = (x & 0xf0f0f0f0) >> 4 | (x & 0x0f0f0f0f) << 4; return x; } diff --git a/libc/bits/bitreverse64.c b/libc/bits/bitreverse64.c index be0abb1fe..4bacc907e 100644 --- a/libc/bits/bitreverse64.c +++ b/libc/bits/bitreverse64.c @@ -24,8 +24,8 @@ */ uint64_t bitreverse64(uint64_t x) { x = bswap_64(x); - x = ((x & 0xaaaaaaaaaaaaaaaa) >> 1) | ((x & 0x5555555555555555) << 1); - x = ((x & 0xcccccccccccccccc) >> 2) | ((x & 0x3333333333333333) << 2); - x = ((x & 0xf0f0f0f0f0f0f0f0) >> 4) | ((x & 0x0f0f0f0f0f0f0f0f) << 4); + x = (x & 0xaaaaaaaaaaaaaaaa) >> 1 | (x & 0x5555555555555555) << 1; + x = (x & 0xcccccccccccccccc) >> 2 | (x & 0x3333333333333333) << 2; + x = (x & 0xf0f0f0f0f0f0f0f0) >> 4 | (x & 0x0f0f0f0f0f0f0f0f) << 4; return x; } diff --git a/libc/bits/bitreverse8.c b/libc/bits/bitreverse8.c index 5ce08fc45..e9788f47b 100644 --- a/libc/bits/bitreverse8.c +++ b/libc/bits/bitreverse8.c @@ -21,6 +21,6 @@ /** * Reverses bits in 8-bit word. */ -uint8_t(bitreverse8)(uint8_t x) { - return kReverseBits[x]; +int bitreverse8(int x) { + return BITREVERSE8(x); } diff --git a/libc/bits/bits.h b/libc/bits/bits.h index 4b2a2ee6a..d4a4c5b4f 100644 --- a/libc/bits/bits.h +++ b/libc/bits/bits.h @@ -13,8 +13,8 @@ extern const uint8_t kReverseBits[256]; uint32_t gray(uint32_t) pureconst; uint32_t ungray(uint32_t) pureconst; -uint8_t bitreverse8(uint8_t) libcesque pureconst; -uint16_t bitreverse16(uint16_t) libcesque pureconst; +int bitreverse8(int) libcesque pureconst; +int bitreverse16(int) libcesque pureconst; uint32_t bitreverse32(uint32_t) libcesque pureconst; uint64_t bitreverse64(uint64_t) libcesque pureconst; unsigned long roundup2pow(unsigned long) libcesque pureconst; @@ -31,106 +31,104 @@ intptr_t atomic_store(void *, intptr_t, size_t); │ cosmopolitan § bits » no assembly required ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ -#define bitreverse8(X) (kReverseBits[(uint8_t)(X)]) -#define bitreverse16(X) \ - ((uint16_t)kReverseBits[(uint8_t)(X)] << 010 | \ - kReverseBits[((uint16_t)(X) >> 010) & 0xff]) +#define BITREVERSE8(X) (kReverseBits[255 & (X)]) +#define BITREVERSE16(X) \ + (kReverseBits[0x00FF & (X)] << 8 | kReverseBits[(0xFF00 & (X)) >> 8]) -#define READ16LE(S) \ - ((uint16_t)((unsigned char *)(S))[1] << 010 | \ - (uint16_t)((unsigned char *)(S))[0] << 000) -#define READ32LE(S) \ - ((uint32_t)((unsigned char *)(S))[3] << 030 | \ - (uint32_t)((unsigned char *)(S))[2] << 020 | \ - (uint32_t)((unsigned char *)(S))[1] << 010 | \ - (uint32_t)((unsigned char *)(S))[0] << 000) -#define READ64LE(S) \ - ((uint64_t)((unsigned char *)(S))[7] << 070 | \ - (uint64_t)((unsigned char *)(S))[6] << 060 | \ - (uint64_t)((unsigned char *)(S))[5] << 050 | \ - (uint64_t)((unsigned char *)(S))[4] << 040 | \ - (uint64_t)((unsigned char *)(S))[3] << 030 | \ - (uint64_t)((unsigned char *)(S))[2] << 020 | \ - (uint64_t)((unsigned char *)(S))[1] << 010 | \ - (uint64_t)((unsigned char *)(S))[0] << 000) +#ifdef __STRICT_ANSI__ +#define READ16LE(S) ((255 & (S)[1]) << 8 | (255 & (S)[0])) +#define READ16BE(S) ((255 & (S)[0]) << 8 | (255 & (S)[1])) +#define READ32LE(S) \ + ((uint32_t)(255 & (S)[3]) << 030 | (uint32_t)(255 & (S)[2]) << 020 | \ + (uint32_t)(255 & (S)[1]) << 010 | (uint32_t)(255 & (S)[0]) << 000) +#define READ32BE(S) \ + ((uint32_t)(255 & (S)[0]) << 030 | (uint32_t)(255 & (S)[1]) << 020 | \ + (uint32_t)(255 & (S)[2]) << 010 | (uint32_t)(255 & (S)[3]) << 000) +#define READ64LE(S) \ + ((uint64_t)(255 & (S)[7]) << 070 | (uint64_t)(255 & (S)[6]) << 060 | \ + (uint64_t)(255 & (S)[5]) << 050 | (uint64_t)(255 & (S)[4]) << 040 | \ + (uint64_t)(255 & (S)[3]) << 030 | (uint64_t)(255 & (S)[2]) << 020 | \ + (uint64_t)(255 & (S)[1]) << 010 | (uint64_t)(255 & (S)[0]) << 000) +#define READ64BE(S) \ + ((uint64_t)(255 & (S)[0]) << 070 | (uint64_t)(255 & (S)[1]) << 060 | \ + (uint64_t)(255 & (S)[2]) << 050 | (uint64_t)(255 & (S)[3]) << 040 | \ + (uint64_t)(255 & (S)[4]) << 030 | (uint64_t)(255 & (S)[5]) << 020 | \ + (uint64_t)(255 & (S)[6]) << 010 | (uint64_t)(255 & (S)[7]) << 000) +#else /* gcc needs help knowing above are mov if s isn't a variable */ +#define READ16LE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + Ptr[1] << 8 | Ptr[0]; \ + }) +#define READ16BE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + Ptr[0] << 8 | Ptr[1]; \ + }) +#define READ32LE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + ((uint32_t)Ptr[3] << 030 | (uint32_t)Ptr[2] << 020 | \ + (uint32_t)Ptr[1] << 010 | (uint32_t)Ptr[0] << 000); \ + }) +#define READ32BE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + ((uint32_t)Ptr[0] << 030 | (uint32_t)Ptr[1] << 020 | \ + (uint32_t)Ptr[2] << 010 | (uint32_t)Ptr[3] << 000); \ + }) +#define READ64LE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + ((uint64_t)Ptr[7] << 070 | (uint64_t)Ptr[6] << 060 | \ + (uint64_t)Ptr[5] << 050 | (uint64_t)Ptr[4] << 040 | \ + (uint64_t)Ptr[3] << 030 | (uint64_t)Ptr[2] << 020 | \ + (uint64_t)Ptr[1] << 010 | (uint64_t)Ptr[0] << 000); \ + }) +#define READ64BE(S) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(S); \ + ((uint64_t)Ptr[0] << 070 | (uint64_t)Ptr[1] << 060 | \ + (uint64_t)Ptr[2] << 050 | (uint64_t)Ptr[3] << 040 | \ + (uint64_t)Ptr[4] << 030 | (uint64_t)Ptr[5] << 020 | \ + (uint64_t)Ptr[6] << 010 | (uint64_t)Ptr[7] << 000); \ + }) +#endif -#define READ16BE(S) \ - ((uint16_t)((unsigned char *)(S))[0] << 010 | \ - (uint16_t)((unsigned char *)(S))[1] << 000) -#define READ32BE(S) \ - ((uint32_t)((unsigned char *)(S))[0] << 030 | \ - (uint32_t)((unsigned char *)(S))[1] << 020 | \ - (uint32_t)((unsigned char *)(S))[2] << 010 | \ - (uint32_t)((unsigned char *)(S))[3] << 000) -#define READ64BE(S) \ - ((uint64_t)((unsigned char *)(S))[0] << 070 | \ - (uint64_t)((unsigned char *)(S))[1] << 060 | \ - (uint64_t)((unsigned char *)(S))[2] << 050 | \ - (uint64_t)((unsigned char *)(S))[3] << 040 | \ - (uint64_t)((unsigned char *)(S))[4] << 030 | \ - (uint64_t)((unsigned char *)(S))[5] << 020 | \ - (uint64_t)((unsigned char *)(S))[6] << 010 | \ - (uint64_t)((unsigned char *)(S))[7] << 000) - -#define WRITE16LE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint16_t Vle = (V); \ - Ple[0] = (uint8_t)(Vle >> 000); \ - Ple[1] = (uint8_t)(Vle >> 010); \ - } while (0) -#define WRITE32LE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint32_t Vle = (V); \ - Ple[0] = (uint8_t)(Vle >> 000); \ - Ple[1] = (uint8_t)(Vle >> 010); \ - Ple[2] = (uint8_t)(Vle >> 020); \ - Ple[3] = (uint8_t)(Vle >> 030); \ - } while (0) -#define WRITE64LE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint64_t Vle = (V); \ - Ple[0] = (uint8_t)(Vle >> 000); \ - Ple[1] = (uint8_t)(Vle >> 010); \ - Ple[2] = (uint8_t)(Vle >> 020); \ - Ple[3] = (uint8_t)(Vle >> 030); \ - Ple[4] = (uint8_t)(Vle >> 040); \ - Ple[5] = (uint8_t)(Vle >> 050); \ - Ple[6] = (uint8_t)(Vle >> 060); \ - Ple[7] = (uint8_t)(Vle >> 070); \ - } while (0) - -#define WRITE16BE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint16_t Vle = (V); \ - Ple[1] = (uint8_t)(Vle >> 000); \ - Ple[0] = (uint8_t)(Vle >> 010); \ - } while (0) -#define WRITE32BE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint32_t Vle = (V); \ - Ple[3] = (uint8_t)(Vle >> 000); \ - Ple[2] = (uint8_t)(Vle >> 010); \ - Ple[1] = (uint8_t)(Vle >> 020); \ - Ple[0] = (uint8_t)(Vle >> 030); \ - } while (0) -#define WRITE64BE(P, V) \ - do { \ - uint8_t *Ple = (uint8_t *)(P); \ - uint64_t Vle = (V); \ - Ple[7] = (uint8_t)(Vle >> 000); \ - Ple[6] = (uint8_t)(Vle >> 010); \ - Ple[5] = (uint8_t)(Vle >> 020); \ - Ple[4] = (uint8_t)(Vle >> 030); \ - Ple[3] = (uint8_t)(Vle >> 040); \ - Ple[2] = (uint8_t)(Vle >> 050); \ - Ple[1] = (uint8_t)(Vle >> 060); \ - Ple[0] = (uint8_t)(Vle >> 070); \ - } while (0) +#define WRITE16LE(P, V) \ + ((P)[0] = (0x00000000000000FF & (V)) >> 000, \ + (P)[1] = (0x000000000000FF00 & (V)) >> 010, (P) + 2) +#define WRITE16BE(P, V) \ + ((P)[0] = (0x000000000000FF00 & (V)) >> 010, \ + (P)[1] = (0x00000000000000FF & (V)) >> 000, (P) + 2) +#define WRITE32LE(P, V) \ + ((P)[0] = (0x00000000000000FF & (V)) >> 000, \ + (P)[1] = (0x000000000000FF00 & (V)) >> 010, \ + (P)[2] = (0x0000000000FF0000 & (V)) >> 020, \ + (P)[3] = (0x00000000FF000000 & (V)) >> 030, (P) + 4) +#define WRITE32BE(P, V) \ + ((P)[0] = (0x00000000FF000000 & (V)) >> 030, \ + (P)[1] = (0x0000000000FF0000 & (V)) >> 020, \ + (P)[2] = (0x000000000000FF00 & (V)) >> 010, \ + (P)[3] = (0x00000000000000FF & (V)) >> 000, (P) + 4) +#define WRITE64LE(P, V) \ + ((P)[0] = (0x00000000000000FF & (V)) >> 000, \ + (P)[1] = (0x000000000000FF00 & (V)) >> 010, \ + (P)[2] = (0x0000000000FF0000 & (V)) >> 020, \ + (P)[3] = (0x00000000FF000000 & (V)) >> 030, \ + (P)[4] = (0x000000FF00000000 & (V)) >> 040, \ + (P)[5] = (0x0000FF0000000000 & (V)) >> 050, \ + (P)[6] = (0x00FF000000000000 & (V)) >> 060, \ + (P)[7] = (0xFF00000000000000 & (V)) >> 070, (P) + 8) +#define WRITE64BE(P, V) \ + ((P)[0] = (0xFF00000000000000 & (V)) >> 070, \ + (P)[1] = (0x00FF000000000000 & (V)) >> 060, \ + (P)[2] = (0x0000FF0000000000 & (V)) >> 050, \ + (P)[3] = (0x000000FF00000000 & (V)) >> 040, \ + (P)[4] = (0x00000000FF000000 & (V)) >> 030, \ + (P)[5] = (0x0000000000FF0000 & (V)) >> 020, \ + (P)[6] = (0x000000000000FF00 & (V)) >> 010, \ + (P)[7] = (0x00000000000000FF & (V)) >> 000, (P) + 8) /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § bits » some assembly required ─╬─│┼ diff --git a/libc/calls/calls.h b/libc/calls/calls.h index 19e188607..20d0a80e8 100644 --- a/libc/calls/calls.h +++ b/libc/calls/calls.h @@ -5,6 +5,7 @@ #include "libc/calls/struct/rlimit.h" #include "libc/calls/struct/rusage.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/sigval.h" #include "libc/calls/struct/stat.h" #include "libc/calls/struct/sysinfo.h" #include "libc/calls/struct/timespec.h" @@ -120,6 +121,7 @@ int getrlimit(int, struct rlimit *); int getrusage(int, struct rusage *); int kill(int, int); int killpg(int, int); +int sigqueue(int, int, const union sigval); int link(const char *, const char *) nothrow; int linkat(int, const char *, int, const char *, uint32_t); int lstat(const char *, struct stat *); diff --git a/libc/calls/clock_gettime.c b/libc/calls/clock_gettime.c index 336fe2f13..e9e3e975c 100644 --- a/libc/calls/clock_gettime.c +++ b/libc/calls/clock_gettime.c @@ -30,14 +30,10 @@ * time. Among the more popular is CLOCK_MONOTONIC. This function has a * zero syscall implementation of that on modern x86. * - * @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. noting - * that on Linux CLOCK_MONOTONIC is redefined to use the monotonic - * clock that's actually monotonic lool + * @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. * @param ts is where the result is stored * @return 0 on success, or -1 w/ errno - * @error ENOSYS if clockid isn't available; in which case this function - * guarantees an ordinary timestamp is still stored to ts; and - * errno isn't restored to its original value, to detect prec. loss + * @error EINVAL if clockid isn't supported on this system * @see strftime(), gettimeofday() * @asyncsignalsafe */ @@ -46,6 +42,7 @@ int clock_gettime(int clockid, struct timespec *ts) { axdx_t ad; struct NtFileTime ft; if (!ts) return efault(); + if (clockid == -1) return einval(); if (!IsWindows()) { if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) { ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL); diff --git a/libc/calls/getrusage-sysv.c b/libc/calls/getrusage-sysv.c new file mode 100644 index 000000000..4e3261c5e --- /dev/null +++ b/libc/calls/getrusage-sysv.c @@ -0,0 +1,35 @@ +/*-*- 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/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/sysv/errfuns.h" + +/** + * Returns resource usage statistics. + * + * @param who can be RUSAGE_{SELF,CHILDREN,THREAD} + * @return 0 on success, or -1 w/ errno + */ +int sys_getrusage(int who, struct rusage *usage) { + int rc; + if ((rc = __sys_getrusage(who, usage)) != -1) { + __rusage2linux(usage); + } + return rc; +} diff --git a/libc/calls/internal.h b/libc/calls/internal.h index 32e057289..d523e8e44 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -4,7 +4,10 @@ #include "libc/calls/internal.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/itimerval.h" +#include "libc/calls/struct/rusage.h" #include "libc/calls/struct/sigaction-xnu.internal.h" +#include "libc/calls/struct/siginfo.h" +#include "libc/calls/struct/sigval.h" #include "libc/calls/struct/timespec.h" #include "libc/calls/struct/timeval.h" #include "libc/dce.h" @@ -108,9 +111,11 @@ i32 __sys_dup3(i32, i32, i32) hidden; i32 __sys_execve(const char *, char *const[], char *const[]) hidden; i32 __sys_fstat(i32, struct stat *) hidden; i32 __sys_fstatat(i32, const char *, struct stat *, i32) hidden; +i32 __sys_getrusage(i32, struct rusage *) hidden; i32 __sys_openat(i32, const char *, i32, u32) hidden; i32 __sys_pipe2(i32[hasatleast 2], u32) hidden; i32 __sys_utimensat(i32, const char *, const struct timespec *, i32) hidden; +i32 __sys_wait4(i32, i32 *, i32, struct rusage *) hidden; i32 getdents(i32, char *, u32, i64 *) hidden; i32 sys_chdir(const char *) hidden; i32 sys_clock_gettime(i32, struct timespec *) hidden; @@ -170,6 +175,8 @@ i32 sys_setrlimit(i32, const struct rlimit *) hidden; i32 sys_setsid(void) hidden; i32 sys_sigaction(i32, const void *, void *, i64, i64) hidden; i32 sys_sigprocmask(i32, const sigset *, sigset *, u64) hidden; +i32 sys_sigqueue(i32, i32, const union sigval) hidden; +i32 sys_sigqueueinfo(i32, const siginfo_t *) hidden; i32 sys_sigsuspend(const sigset *, u64) hidden; i32 sys_symlinkat(const char *, i32, const char *) hidden; i32 sys_sync(void) hidden; @@ -220,6 +227,7 @@ int gethostname_linux(char *, size_t) hidden; int gethostname_bsd(char *, size_t) hidden; int gethostname_nt(char *, size_t) hidden; size_t __iovec_size(const struct iovec *, size_t) hidden; +void __rusage2linux(struct rusage *) hidden; /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼ diff --git a/libc/calls/kill.c b/libc/calls/kill.c index f72bab6e4..26b9f0c84 100644 --- a/libc/calls/kill.c +++ b/libc/calls/kill.c @@ -33,7 +33,7 @@ * <-1 signals all processes in -pid process group * @param sig can be: * >0 can be SIGINT, SIGTERM, SIGKILL, SIGUSR1, etc. - * =0 is for error checking + * =0 checks both if pid exists and we can signal it * @return 0 if something was accomplished, or -1 w/ errno * @asyncsignalsafe */ diff --git a/libc/calls/mprotect.greg.c b/libc/calls/mprotect.greg.c index f2ff0b7fc..dedc7a909 100644 --- a/libc/calls/mprotect.greg.c +++ b/libc/calls/mprotect.greg.c @@ -39,12 +39,12 @@ privileged int mprotect(void *addr, uint64_t len, int prot) { int64_t rc; uint32_t oldprot; if (!IsWindows()) { - asm volatile(CFLAG_ASM("syscall") + asm volatile(CFLAG_ASM("clc\n\tsyscall") : CFLAG_CONSTRAINT(cf), "=a"(rc) : "1"(__NR_mprotect), "D"(addr), "S"(len), "d"(prot) : "rcx", "r11", "memory", "cc"); if (cf) { - rc = -rc; + errno = rc; rc = -1; } else if (rc > -4096ul) { errno = -rc; diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c index b29e70871..819256869 100644 --- a/libc/calls/open-nt.c +++ b/libc/calls/open-nt.c @@ -47,14 +47,11 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path, ? kNtFileShareExclusive : kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, &kNtIsInheritable, - (flags & O_CREAT) && (flags & O_EXCL) - ? kNtCreateNew - : (flags & O_CREAT) && (flags & O_TRUNC) - ? kNtCreateAlways - : (flags & O_CREAT) - ? kNtOpenAlways - : (flags & O_TRUNC) ? kNtTruncateExisting - : kNtOpenExisting, + (flags & O_CREAT) && (flags & O_EXCL) ? kNtCreateNew + : (flags & O_CREAT) && (flags & O_TRUNC) ? kNtCreateAlways + : (flags & O_CREAT) ? kNtOpenAlways + : (flags & O_TRUNC) ? kNtTruncateExisting + : kNtOpenExisting, /* TODO(jart): Should we just always set overlapped? */ (/* note: content indexer demolishes unix-ey i/o performance */ kNtFileAttributeNotContentIndexed | kNtFileAttributeNormal | diff --git a/test/tool/build/lib/wut_test.c b/libc/calls/rusage2linux.c similarity index 83% rename from test/tool/build/lib/wut_test.c rename to libc/calls/rusage2linux.c index 1359316a0..855fd8dbe 100644 --- a/test/tool/build/lib/wut_test.c +++ b/libc/calls/rusage2linux.c @@ -1,7 +1,7 @@ /*-*- 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 │ +│ Copyright 2021 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 │ @@ -16,16 +16,10 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" +#include "libc/calls/internal.h" -TEST(memcpy, testBackwardsOverlap3) { - volatile char *c; - c = malloc(3); - memcpy(c, "\e[C", 3); - memcpy(c, c + 1, VEIL("r", 3) - 1); - EXPECT_EQ('[', c[0]); - EXPECT_EQ('C', c[1]); - free(c); +void __rusage2linux(struct rusage *ru) { + if (IsXnu()) { + ru->ru_maxrss /= 1024; + } } diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index ac36db971..eeb16c371 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -39,6 +39,8 @@ #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" +#define SA_RESTORER 0x04000000 + #ifndef SWITCHEROO #define SWITCHEROO(S1, S2, A, B, C, D) \ do { \ diff --git a/libc/calls/sigqueue.c b/libc/calls/sigqueue.c new file mode 100644 index 000000000..d0171e66c --- /dev/null +++ b/libc/calls/sigqueue.c @@ -0,0 +1,59 @@ +/*-*- 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 2021 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/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/struct/siginfo.h" +#include "libc/calls/struct/sigval.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/sicode.h" + +/* TODO(jart): XNU */ + +/** + * Sends signal to process, with data. + * + * The impact of this action can be terminating the process, or + * interrupting it to request something happen. + * + * @param pid can be: + * >0 signals one process by id + * =0 signals all processes in current process group + * -1 signals all processes possible (except init) + * <-1 signals all processes in -pid process group + * @param sig can be: + * >0 can be SIGINT, SIGTERM, SIGKILL, SIGUSR1, etc. + * =0 checks both if pid exists and we can signal it + * @return 0 if something was accomplished, or -1 w/ errno + * @note this isn't supported on OpenBSD + * @asyncsignalsafe + */ +int sigqueue(int pid, int sig, const union sigval value) { + siginfo_t info; + if (IsFreebsd()) { + return sys_sigqueue(pid, sig, value); + } else { + memset(&info, 0, sizeof(info)); + info.si_signo = sig; + info.si_code = SI_QUEUE; + info.si_pid = getpid(); + info.si_uid = geteuid(); + info.si_value = value; + return sys_sigqueueinfo(pid, &info); + } +} diff --git a/libc/calls/struct/rlimit.h b/libc/calls/struct/rlimit.h index a52e5cdc0..edbe0dfb5 100644 --- a/libc/calls/struct/rlimit.h +++ b/libc/calls/struct/rlimit.h @@ -3,8 +3,8 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) struct rlimit { - int64_t rlim_cur; - int64_t rlim_max; + uint64_t rlim_cur; /* current (soft) limit in bytes */ + uint64_t rlim_max; /* maximum limit in bytes */ }; #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/calls/struct/rusage.h b/libc/calls/struct/rusage.h index 32d3207ce..ed08ebc71 100644 --- a/libc/calls/struct/rusage.h +++ b/libc/calls/struct/rusage.h @@ -8,12 +8,12 @@ struct rusage { struct { struct timeval ru_utime; /* user CPU time used */ struct timeval ru_stime; /* system CPU time used */ - int64_t ru_maxrss; /* maximum resident set size */ - int64_t ru_ixrss; /* integral shared memory size */ - int64_t ru_idrss; /* integral unshared data size */ - int64_t ru_isrss; /* integral unshared stack size */ - int64_t ru_minflt; /* page reclaims (soft page faults) */ - int64_t ru_majflt; /* page faults (hard page faults) */ + int64_t ru_maxrss; /* maximum resident set size in (kb) */ + int64_t ru_ixrss; /* shared memory size (integral kb CLK_TCK) */ + int64_t ru_idrss; /* unshared data size (integral kb CLK_TCK) */ + int64_t ru_isrss; /* unshared stack size (integral kb CLK_TCK) */ + int64_t ru_minflt; /* page reclaims */ + int64_t ru_majflt; /* page faults */ int64_t ru_nswap; /* swaps */ int64_t ru_inblock; /* block input operations */ int64_t ru_oublock; /* block output operations */ diff --git a/libc/calls/struct/siginfo.h b/libc/calls/struct/siginfo.h index 72ca1d1d4..105ad24c5 100644 --- a/libc/calls/struct/siginfo.h +++ b/libc/calls/struct/siginfo.h @@ -6,7 +6,7 @@ struct siginfo { int32_t si_signo; int32_t si_errno; - int32_t si_code; + int32_t si_code; /* {SICODE,SEGV,ILL,FPE,POLL}_xxx */ union { struct { union { @@ -20,7 +20,7 @@ struct siginfo { }; }; union { - union sigval si_value; + union sigval si_value; /* provided by third arg of sigqueue(2) */ struct { int32_t si_status; int64_t si_utime, si_stime; diff --git a/libc/calls/wait4-sysv.c b/libc/calls/wait4-sysv.c new file mode 100644 index 000000000..7e1ebccf8 --- /dev/null +++ b/libc/calls/wait4-sysv.c @@ -0,0 +1,31 @@ +/*-*- 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 2021 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/calls/calls.h" +#include "libc/calls/internal.h" + +int sys_wait4(int pid, int *opt_out_wstatus, int options, + struct rusage *opt_out_rusage) { + int rc; + if ((rc = __sys_wait4(pid, opt_out_wstatus, options, opt_out_rusage)) != -1) { + if (opt_out_rusage) { + __rusage2linux(opt_out_rusage); + } + } + return rc; +} diff --git a/libc/calls/weirdtypes.h b/libc/calls/weirdtypes.h index f23cad207..bd7c7fe70 100644 --- a/libc/calls/weirdtypes.h +++ b/libc/calls/weirdtypes.h @@ -37,6 +37,7 @@ #define time_t int64_t #define timer_t void* #define uid_t uint32_t +#define rlim_t uint64_t /* int64_t on bsd */ #define int_fast8_t __INT_FAST8_TYPE__ #define uint_fast8_t __UINT_FAST8_TYPE__ diff --git a/libc/dce.h b/libc/dce.h index e100c4da0..73cde783f 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -45,12 +45,6 @@ #define IsTrustworthy() 0 #endif -#ifdef SECURITY_BLANKETS -#define UseSecurityBlankets() 1 -#else -#define UseSecurityBlankets() 0 -#endif - #ifdef TINY #define IsTiny() 1 #else diff --git a/libc/fmt/strerror_r.c b/libc/fmt/strerror_r.c index 4efb8b872..dbd893fc8 100644 --- a/libc/fmt/strerror_r.c +++ b/libc/fmt/strerror_r.c @@ -26,285 +26,153 @@ #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"); +const struct Error { + const long *x; + const char *s; +} kErrors[] = { + {&ENOSYS, "ENOSYS"}, + {&EPERM, "EPERM"}, + {&ENOENT, "ENOENT"}, + {&ESRCH, "ESRCH"}, + {&EINTR, "EINTR"}, + {&EIO, "EIO"}, + {&ENXIO, "ENXIO"}, + {&E2BIG, "E2BIG"}, + {&ENOEXEC, "ENOEXEC"}, + {&EBADF, "EBADF"}, + {&ECHILD, "ECHILD"}, + {&EAGAIN, "EAGAIN"}, + {&ENOMEM, "ENOMEM"}, + {&EACCES, "EACCES"}, + {&EFAULT, "EFAULT"}, + {&ENOTBLK, "ENOTBLK"}, + {&EBUSY, "EBUSY"}, + {&EEXIST, "EEXIST"}, + {&EXDEV, "EXDEV"}, + {&ENODEV, "ENODEV"}, + {&ENOTDIR, "ENOTDIR"}, + {&EISDIR, "EISDIR"}, + {&EINVAL, "EINVAL"}, + {&ENFILE, "ENFILE"}, + {&EMFILE, "EMFILE"}, + {&ENOTTY, "ENOTTY"}, + {&ETXTBSY, "ETXTBSY"}, + {&EFBIG, "EFBIG"}, + {&ENOSPC, "ENOSPC"}, + {&EDQUOT, "EDQUOT"}, + {&ESPIPE, "ESPIPE"}, + {&EROFS, "EROFS"}, + {&EMLINK, "EMLINK"}, + {&EPIPE, "EPIPE"}, + {&EDOM, "EDOM"}, + {&ERANGE, "ERANGE"}, + {&EDEADLK, "EDEADLK"}, + {&ENAMETOOLONG, "ENAMETOOLONG"}, + {&ENOLCK, "ENOLCK"}, + {&ENOTEMPTY, "ENOTEMPTY"}, + {&ELOOP, "ELOOP"}, + {&ENOMSG, "ENOMSG"}, + {&EIDRM, "EIDRM"}, + {&ETIME, "ETIME"}, + {&EPROTO, "EPROTO"}, + {&EOVERFLOW, "EOVERFLOW"}, + {&EILSEQ, "EILSEQ"}, + {&EUSERS, "EUSERS"}, + {&ENOTSOCK, "ENOTSOCK"}, + {&EDESTADDRREQ, "EDESTADDRREQ"}, + {&EMSGSIZE, "EMSGSIZE"}, + {&EPROTOTYPE, "EPROTOTYPE"}, + {&ENOPROTOOPT, "ENOPROTOOPT"}, + {&EPROTONOSUPPORT, "EPROTONOSUPPORT"}, + {&ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT"}, + {&ENOTSUP, "ENOTSUP"}, + {&EOPNOTSUPP, "EOPNOTSUPP"}, + {&EPFNOSUPPORT, "EPFNOSUPPORT"}, + {&EAFNOSUPPORT, "EAFNOSUPPORT"}, + {&EADDRINUSE, "EADDRINUSE"}, + {&EADDRNOTAVAIL, "EADDRNOTAVAIL"}, + {&ENETDOWN, "ENETDOWN"}, + {&ENETUNREACH, "ENETUNREACH"}, + {&ENETRESET, "ENETRESET"}, + {&ECONNABORTED, "ECONNABORTED"}, + {&ECONNRESET, "ECONNRESET"}, + {&ENOBUFS, "ENOBUFS"}, + {&EISCONN, "EISCONN"}, + {&ENOTCONN, "ENOTCONN"}, + {&ESHUTDOWN, "ESHUTDOWN"}, + {&ETOOMANYREFS, "ETOOMANYREFS"}, + {&ETIMEDOUT, "ETIMEDOUT"}, + {&ECONNREFUSED, "ECONNREFUSED"}, + {&EHOSTDOWN, "EHOSTDOWN"}, + {&EHOSTUNREACH, "EHOSTUNREACH"}, + {&EALREADY, "EALREADY"}, + {&EINPROGRESS, "EINPROGRESS"}, + {&ESTALE, "ESTALE"}, + {&EREMOTE, "EREMOTE"}, + {&EBADMSG, "EBADMSG"}, + {&ECANCELED, "ECANCELED"}, + {&EOWNERDEAD, "EOWNERDEAD"}, + {&ENOTRECOVERABLE, "ENOTRECOVERABLE"}, + {&ENONET, "ENONET"}, + {&ERESTART, "ERESTART"}, + {&ECHRNG, "ECHRNG"}, + {&EL2NSYNC, "EL2NSYNC"}, + {&EL3HLT, "EL3HLT"}, + {&EL3RST, "EL3RST"}, + {&ELNRNG, "ELNRNG"}, + {&EUNATCH, "EUNATCH"}, + {&ENOCSI, "ENOCSI"}, + {&EL2HLT, "EL2HLT"}, + {&EBADE, "EBADE"}, + {&EBADR, "EBADR"}, + {&EXFULL, "EXFULL"}, + {&ENOANO, "ENOANO"}, + {&EBADRQC, "EBADRQC"}, + {&EBADSLT, "EBADSLT"}, + {&ENOSTR, "ENOSTR"}, + {&ENODATA, "ENODATA"}, + {&ENOSR, "ENOSR"}, + {&ENOPKG, "ENOPKG"}, + {&ENOLINK, "ENOLINK"}, + {&EADV, "EADV"}, + {&ESRMNT, "ESRMNT"}, + {&ECOMM, "ECOMM"}, + {&EMULTIHOP, "EMULTIHOP"}, + {&EDOTDOT, "EDOTDOT"}, + {&ENOTUNIQ, "ENOTUNIQ"}, + {&EBADFD, "EBADFD"}, + {&EREMCHG, "EREMCHG"}, + {&ELIBACC, "ELIBACC"}, + {&ELIBBAD, "ELIBBAD"}, + {&ELIBSCN, "ELIBSCN"}, + {&ELIBMAX, "ELIBMAX"}, + {&ELIBEXEC, "ELIBEXEC"}, + {&ESTRPIPE, "ESTRPIPE"}, + {&EUCLEAN, "EUCLEAN"}, + {&ENOTNAM, "ENOTNAM"}, + {&ENAVAIL, "ENAVAIL"}, + {&EISNAM, "EISNAM"}, + {&EREMOTEIO, "EREMOTEIO"}, + {&ENOMEDIUM, "ENOMEDIUM"}, + {&EMEDIUMTYPE, "EMEDIUMTYPE"}, + {&ENOKEY, "ENOKEY"}, + {&EKEYEXPIRED, "EKEYEXPIRED"}, + {&EKEYREVOKED, "EKEYREVOKED"}, + {&EKEYREJECTED, "EKEYREJECTED"}, + {&ERFKILL, "ERFKILL"}, + {&EHWPOISON, "EHWPOISON"}, +}; -_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); +static const char *geterrname(long x) { + int i; + if (!IsTiny() && x) { + for (i = 0; i < ARRAYLEN(kErrors); ++i) { + if (x == *kErrors[i].x) { + return kErrors[i].s; + } } } - return NULL; + return "EUNKNOWN"; } /** @@ -315,13 +183,9 @@ 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), "?"); - } + s = geterrname(err); if (!SupportsWindows()) { - (snprintf)(buf, size, "E%s[%d]", s, err); + (snprintf)(buf, size, "%s[%d]", s, err); } else { winstate = GetLastError(); sysvstate = errno; @@ -332,7 +196,7 @@ int strerror_r(int err, char *buf, size_t size) { } else { buf16[0] = u'\0'; } - (snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err, + (snprintf)(buf, size, "%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err, sysvstate, winstate, buf16[0] ? " " : "", buf16); } return 0; diff --git a/libc/log/gdbexec.c b/libc/log/gdbexec.c index fc781f4ed..13a345c9c 100644 --- a/libc/log/gdbexec.c +++ b/libc/log/gdbexec.c @@ -28,7 +28,7 @@ /** * Attachs GDB temporarilly, to do something like print a variable. */ -int(gdbexec)(const char *cmd) { +privileged int(gdbexec)(const char *cmd) { struct StackFrame *bp; int pid, ttyin, ttyout; intptr_t continuetoaddr; diff --git a/libc/mem/reallocarray.c b/libc/mem/reallocarray.c index a7cb94c1b..0c1c5750b 100644 --- a/libc/mem/reallocarray.c +++ b/libc/mem/reallocarray.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/errno.h" #include "libc/fmt/conv.h" #include "libc/mem/mem.h" @@ -27,5 +28,11 @@ * @return new address or NULL w/ errno and ptr is NOT free()'d */ void *reallocarray(void *ptr, size_t nmemb, size_t itemsize) { - return realloc(ptr, nmemb * itemsize); + size_t n; + if (!__builtin_mul_overflow(nmemb, itemsize, &n)) { + return realloc(ptr, n); + } else { + errno = ENOMEM; + return NULL; + } } diff --git a/libc/runtime/clktck.c b/libc/runtime/clktck.c new file mode 100644 index 000000000..8fe9f3fa6 --- /dev/null +++ b/libc/runtime/clktck.c @@ -0,0 +1,75 @@ +/*-*- 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 2021 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/calls/calls.h" +#include "libc/dce.h" +#include "libc/runtime/clktck.h" +#include "libc/sysv/consts/auxv.h" + +struct clockinfo_netbsd { + int32_t hz; // number of clock ticks per second + int32_t tick; // µs per tick + int32_t tickadj; // skew rate for adjtime() + int32_t stathz; // statistics clock frequency + int32_t profhz; // profiling clock frequency +}; + +static int clk_tck; + +static noinline int __clk_tck_init(void) { + int x; + int cmd[2]; + size_t len; + struct clockinfo_netbsd clock; + if (IsXnu() || IsOpenbsd()) { + x = 100; + } else if (IsFreebsd()) { + x = 128; + } else if (IsNetbsd()) { + cmd[0] = 1; // CTL_KERN + cmd[1] = 12; // KERN_CLOCKRATE + len = sizeof(clock); + if (sysctl(cmd, 2, &clock, &len, NULL, 0) != -1) { + x = clock.hz; + } else { + x = -1; + } + } else { + x = getauxval(AT_CLKTCK); + } + if (x < 1) x = 100; + clk_tck = x; + return x; +} + +/** + * Returns system clock ticks per second. + * + * The returned value is memoized. This function is intended to be + * used via the `CLK_TCK` macro wrapper. + * + * The returned value is always greater than zero. It's usually 100 + * hertz which means each clock tick is 10 milliseconds long. + */ +int __clk_tck(void) { + if (clk_tck) { + return clk_tck; + } else { + return __clk_tck_init(); + } +} diff --git a/libc/runtime/clktck.h b/libc/runtime/clktck.h new file mode 100644 index 000000000..3ab13648a --- /dev/null +++ b/libc/runtime/clktck.h @@ -0,0 +1,12 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_CLKTCK_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_CLKTCK_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +#define CLK_TCK (__clk_tck()) + +int __clk_tck(void) pureconst; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_CLKTCK_H_ */ diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index 3992db5c1..0d507e953 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -59,8 +59,9 @@ */ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { struct DirectMap dm; - int i, x, n, a, b, f; + int i, x, n, m, a, b, f; if (!size) return VIP(einval()); + if (size > 0x0000010000000000) return VIP(enomem()); if (!ALIGNED(off)) return VIP(einval()); if (!ALIGNED(addr)) return VIP(einval()); if (!CANONICAL(addr)) return VIP(einval()); @@ -77,6 +78,7 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { n = ROUNDUP(size, FRAMESIZE) >> 16; for (i = 0; i < _mmi.i; ++i) { if (_mmi.p[i].y < x) continue; + if (__builtin_add_overflow(_mmi.p[i].y, n, &m)) return VIP(enomem()); if (_mmi.p[i].x > x + n - 1) break; x = _mmi.p[i].y + 1; } diff --git a/libc/runtime/mremap-sysv.c b/libc/runtime/mremap-sysv.c new file mode 100644 index 000000000..76303f161 --- /dev/null +++ b/libc/runtime/mremap-sysv.c @@ -0,0 +1,55 @@ +/*-*- 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 2021 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/bits.h" +#include "libc/calls/calls.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/mremap.h" +#include "libc/sysv/errfuns.h" + +privileged void *sys_mremap(void *p, size_t n, size_t m, int f, void *q) { + bool cf; + uintptr_t rax, rdi, rsi, rdx; + register uintptr_t r8 asm("r8"); + register uintptr_t r10 asm("r10"); + if (IsLinux()) { + r10 = f; + r8 = (uintptr_t)q; + asm("syscall" + : "=a"(rax) + : "0"(0x019), "D"(p), "S"(n), "d"(m), "r"(r10), "r"(r8) + : "rcx", "r11", "memory", "cc"); + if (rax > -4096ul) errno = -rax, rax = -1; + } else if (IsNetbsd()) { + if (f & MREMAP_MAYMOVE) { + rax = 0x19B; + r10 = m; + r8 = (f & MREMAP_FIXED) ? MAP_FIXED : 0; + asm(CFLAG_ASM("syscall") + : CFLAG_CONSTRAINT(cf), "+a"(rax) + : "D"(p), "S"(n), "d"(q), "r"(r10), "r"(r8) + : "rcx", "r11", "memory", "cc"); + if (cf) errno = rax, rax = -1; + } else { + rax = einval(); + } + } else { + rax = enosys(); + } + return (void *)rax; +} diff --git a/libc/runtime/mremap.c b/libc/runtime/mremap.c index cd4133c95..e7fbd0b5b 100644 --- a/libc/runtime/mremap.c +++ b/libc/runtime/mremap.c @@ -17,9 +17,46 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/dce.h" +#include "libc/macros.internal.h" +#include "libc/sysv/consts/mremap.h" #include "libc/sysv/errfuns.h" -void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, - void *new_address) { - return (void *)(intptr_t)enosys(); +#define IP(X) (intptr_t)(X) +#define VIP(X) (void *)IP(X) +#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) + +/** + * Relocates mapping. + * + * @param p is old address + * @param n is old size + * @param m is new size + * @param f should have MREMAP_MAYMOVE and may have MAP_FIXED + * @param q is new address + */ +void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) { + return VIP(enosys()); /* TODO: Implement Me! */ + void *q; + va_list va; + if (!IsWindows()) { + if (!n) return VIP(einval()); + if (!m) return VIP(einval()); + if (!ALIGNED(p)) return VIP(einval()); + n = ROUNDUP(n, FRAMESIZE); + m = ROUNDUP(m, FRAMESIZE); + if (f & MREMAP_FIXED) { + va_start(va, f); + q = va_arg(va, void *); + va_end(va); + if (!ALIGNED(q)) return VIP(einval()); + } else { + q = NULL; + if (!(f & MREMAP_MAYMOVE)) { + } + } + return VIP(enosys()); + } else { + return VIP(enosys()); + } } diff --git a/libc/runtime/openexecutable.S b/libc/runtime/openexecutable.S new file mode 100644 index 000000000..b3dde6bc1 --- /dev/null +++ b/libc/runtime/openexecutable.S @@ -0,0 +1,188 @@ +/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ +│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 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/dce.h" +#include "libc/macros.internal.h" +#include "libc/sysv/consts/auxv.h" +#include "libc/sysv/consts/prot.h" +.privileged + +// Opens executable in O_RDWR mode. +// +// To avoid ETXTBSY we need to unmap the running executable first, +// then open the file, and finally load the code back into memory. +// +// @return file descriptor +// @note only works on .com binary (not .com.dbg) +// @note only supports linux, freebsd, openbsd, and netbsd +OpenExecutable: + push %rbp + mov %rsp,%rbp + pushq __NR_open(%rip) # -0x08(%rbp) + pushq __NR_mmap(%rip) # -0x10(%rbp) + pushq __NR_munmap(%rip) # -0x18(%rbp) + pushq O_RDWR(%rip) # -0x20(%rbp) + pushq MAP_ANONYMOUS(%rip) # -0x28(%rbp) + pushq MAP_PRIVATE(%rip) # -0x30(%rbp) + pushq MAP_FIXED(%rip) # -0x38(%rbp) + pushq MAP_SHARED(%rip) # -0x40(%rbp) + push %rbx # code buffer + push %r12 # data buffer + push %r14 # filename + push %r15 # fd + +// Get filename. + mov AT_EXECFN,%edi + call getauxval + mov %rax,%r14 + +// Allocate code buffer. + mov -0x10(%rbp),%eax # __NR_mmap + xor %edi,%edi + mov $PAGESIZE,%esi + mov $PROT_READ|PROT_WRITE|PROT_EXEC,%edx + mov -0x28(%rbp),%r10d # MAP_ANONYMOUS + or -0x30(%rbp),%r10d # MAP_PRIVATE + mov $-1,%r8 + mov $0,%r9 + push %r9 # openbsd:pad + push %r9 # openbsd:align + syscall + pop %r9 + pop %r9 + mov %rax,%rbx + +// Allocate data buffer. + mov -0x10(%rbp),%eax # __NR_mmap + xor %edi,%edi + mov $ape_ram_filesz,%esi + mov $PROT_READ|PROT_WRITE,%edx + mov -0x28(%rbp),%r10d # MAP_ANONYMOUS + or -0x30(%rbp),%r10d # MAP_PRIVATE + mov $-1,%r8 + mov $0,%r9 + push %r9 # openbsd:pad + push %r9 # openbsd:align + syscall + pop %r9 + pop %r9 + mov %rax,%r12 + +// Move data. + mov %r12,%rdi + mov $ape_ram_vaddr,%esi + mov $ape_ram_filesz,%ecx + rep movsb + +// Move code. + mov %rbx,%rdi + mov $8f,%esi + mov $9f-8f,%ecx + rep movsb + jmp *%rbx + +// + +// Unmap code segment. +8: mov -0x18(%rbp),%eax # __NR_munmap + mov $ape_rom_vaddr,%edi + mov $ape_rom_filesz,%esi + syscall + +// Unmap data segment. + mov -0x18(%rbp),%eax # __NR_munmap + mov $ape_ram_vaddr,%edi + mov $ape_ram_filesz,%esi + syscall + +// Open executable in read-write mode. + mov -0x08(%rbp),%eax # __NR_open + mov %r14,%rdi + mov -0x20(%rbp),%esi # O_RDWR + syscall + mov %eax,%r15d + +// Map code segment. + mov -0x10(%rbp),%eax # __NR_mmap + mov $ape_rom_vaddr,%edi + mov $ape_rom_filesz,%esi + mov $PROT_READ|PROT_EXEC,%edx + mov -0x38(%rbp),%r10d # MAP_FIXED + or -0x40(%rbp),%r10d # MAP_SHARED + mov %r15d,%r8d + mov $ape_rom_offset,%r9d + push %r9 # openbsd:pad + push %r9 # openbsd:align + syscall + pop %r9 + pop %r9 + +// Allocate data segment. + mov -0x10(%rbp),%eax # __NR_mmap + mov $ape_ram_vaddr,%edi + mov $ape_ram_filesz,%esi + mov $PROT_READ|PROT_WRITE,%edx + mov -0x38(%rbp),%r10d # MAP_FIXED + or -0x30(%rbp),%r10d # MAP_PRIVATE + or -0x28(%rbp),%r10d # MAP_ANONYMOUS + mov $-1,%r8 + mov $0,%r9 + push %r9 # openbsd:pad + push %r9 # openbsd:align + syscall + pop %r9 + pop %r9 + +// Put data back. + mov $ape_ram_vaddr,%edi + xchg %eax,%esi + mov $ape_ram_filesz,%ecx + rep movsb + +// Jump back. + mov $9f,%eax + jmp *%rax + +// + +// Deallocate code buffer. +9: mov __NR_munmap,%eax + mov %rbx,%rdi + mov $PAGESIZE,%esi + syscall + +// Deallocate data buffer. + mov __NR_munmap,%eax + mov %r12,%rdi + mov $ape_ram_filesz,%esi + syscall + + mov %r15d,%eax + pop %r15 + pop %r14 + pop %r12 + pop %rbx + leave + ret +9: .endfn OpenExecutable,globl + + .weak ape_rom_vaddr + .weak ape_rom_filesz + .weak ape_rom_offset + .weak ape_ram_vaddr + .weak ape_ram_filesz diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index ef34b22ff..3cc0faed5 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -55,7 +55,7 @@ int clearenv(void); void fpreset(void); int issetugid(void); void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t); -void *mremap(void *, uint64_t, uint64_t, int32_t, void *); +void *mremap(void *, size_t, size_t, int, ...); int munmap(void *, uint64_t); int mprotect(void *, uint64_t, int) privileged; int msync(void *, size_t, int); @@ -87,6 +87,7 @@ void _savexmm(void *); void _weakfree(void *); void free_s(void *) paramsnonnull() libcesque; int close_s(int *) paramsnonnull() libcesque; +int OpenExecutable(void); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/runtime/sysconf.c b/libc/runtime/sysconf.c index fbfc8fbf8..3fd5699aa 100644 --- a/libc/runtime/sysconf.c +++ b/libc/runtime/sysconf.c @@ -16,10 +16,32 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/clktck.h" #include "libc/runtime/sysconf.h" /** * Returns configuration value about system. - * @param thing can be _SC_XXX + * + * The following parameters are supported: + * + * - `_SC_CLK_TCK` returns number of clock ticks per second + * - `_SC_ARG_MAX` currently always returns 32768 due to Windows + * - `_SC_PAGESIZE` currently always returns 65536 due to Windows + * + * You are encouraged to undiamond calls to this API as follows: + * + * - Use `CLK_TCK` instead of `getconf(_SC_CLK_TCK)` + * - Use `PAGESIZE` or `FRAMESIZE` instead of `getconf(_SC_PAGESIZE)` */ -long(sysconf)(int thing) { return __sysconf(thing); } +long sysconf(int name) { + switch (name) { + case _SC_ARG_MAX: + return ARG_MAX; + case _SC_CLK_TCK: + return CLK_TCK; + case _SC_PAGESIZE: + return FRAMESIZE; + default: + return -1; + } +} diff --git a/libc/runtime/sysconf.h b/libc/runtime/sysconf.h index 0afd83eaf..465ece060 100644 --- a/libc/runtime/sysconf.h +++ b/libc/runtime/sysconf.h @@ -1,7 +1,5 @@ #ifndef COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_ #define COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_ -#include "libc/runtime/runtime.h" -#include "libc/sysv/consts/auxv.h" #define _SC_ARG_MAX 0 #define _SC_CLK_TCK 2 @@ -13,26 +11,6 @@ COSMOPOLITAN_C_START_ long sysconf(int); -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -#define sysconf(X) __sysconf(X) -forceinline long __sysconf(int thing) { - switch (thing) { - case _SC_ARG_MAX: - return ARG_MAX; - case _SC_CLK_TCK: { - extern const long __AT_CLKTCK asm("AT_CLKTCK"); - long res = getauxval(__AT_CLKTCK); - if (!res) res = 100; - return res; - } - case _SC_PAGESIZE: - return FRAMESIZE; - default: - return -1; - } -} -#endif /* GNU && !ANSI */ - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_RUNTIME_SYSCONF_H_ */ diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index 77844de97..2adfc81f7 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -160,17 +160,15 @@ static noasan textwindows wontreturn void WinMainNew(void) { * able to assume that stack addresses are located at higher * addresses than heap and program memory. * - * 5. Windows users are afraid of "drive-by downloads" where someone - * might accidentally an evil DLL to their Downloads folder which - * then overrides the behavior of a legitimate EXE being run from - * the downloads folder. Since we don't even use dynamic linking, - * we've cargo culted some API calls, that may harden against it. + * 5. Reconfigure x87 FPU so long double is actually long (80 bits). * - * 6. Reconfigure x87 FPU so long double is actually long (80 bits). - * - * 7. Finally, we need fork. Microsoft designed Windows to prevent us - * from having fork() so we pass pipe handles in an environment - * variable literally copy all the memory. + * 6. Finally, we need fork. Since disagreeing with fork is axiomatic to + * Microsoft's engineering culture, we need to go to great lengths to + * have it anyway without breaking Microsoft's rules: using the WIN32 + * API (i.e. not NTDLL) to copy MAP_PRIVATE pages via a pipe. It'd go + * faster if the COW pages CreateFileMappingNuma claims to have turns + * out to be true. Until then we have a "PC Scale" and entirely legal + * workaround that they hopefully won't block using Windows Defender. * * @param hInstance call GetModuleHandle(NULL) from main if you need it */ diff --git a/libc/stdio/system.c b/libc/stdio/system.c index ef58b0fc3..dd1fee19b 100644 --- a/libc/stdio/system.c +++ b/libc/stdio/system.c @@ -42,7 +42,7 @@ int system(const char *cmdline) { struct sigaction ignore, saveint, savequit; if (!cmdline) { if (IsWindows()) return 1; - if (access(_PATH_BSHELL, X_OK) == 0) return 1; + if (!access(_PATH_BSHELL, X_OK)) return 1; return 0; } ignore.sa_flags = 0; @@ -54,13 +54,13 @@ int system(const char *cmdline) { sigaddset(&chldmask, SIGCHLD); sigprocmask(SIG_BLOCK, &chldmask, &savemask); if (!(pid = fork())) { - sigaction(SIGINT, &saveint, NULL); - sigaction(SIGQUIT, &savequit, NULL); - sigprocmask(SIG_SETMASK, &savemask, NULL); + sigaction(SIGINT, &saveint, 0); + sigaction(SIGQUIT, &savequit, 0); + sigprocmask(SIG_SETMASK, &savemask, 0); systemexec(cmdline); _exit(127); } else if (pid != -1) { - while (wait4(pid, &wstatus, 0, NULL) == -1) { + while (wait4(pid, &wstatus, 0, 0) == -1) { if (errno != EINTR) { wstatus = -1; break; @@ -69,8 +69,8 @@ int system(const char *cmdline) { } else { wstatus = -1; } - sigaction(SIGINT, &saveint, NULL); - sigaction(SIGQUIT, &savequit, NULL); - sigprocmask(SIG_SETMASK, &savemask, NULL); + sigaction(SIGINT, &saveint, 0); + sigaction(SIGQUIT, &savequit, 0); + sigprocmask(SIG_SETMASK, &savemask, 0); return wstatus; } diff --git a/libc/stdio/systemexec.c b/libc/stdio/systemexec.c index cb9b3fd76..70134991a 100644 --- a/libc/stdio/systemexec.c +++ b/libc/stdio/systemexec.c @@ -20,19 +20,28 @@ #include "libc/dce.h" #include "libc/paths.h" #include "libc/runtime/runtime.h" -#include "libc/stdio/stdio.h" #include "libc/str/str.h" +#include "libc/sysv/errfuns.h" /** * Executes system command replacing current process. * @vforksafe */ int systemexec(const char *cmdline) { - char comspec[128]; - const char *prog, *arg; - strcpy(comspec, kNtSystemDirectory); - strcat(comspec, "cmd.exe"); - prog = !IsWindows() ? _PATH_BSHELL : comspec; - arg = !IsWindows() ? "-c" : "/C"; - return execv(prog, (char *const[]){prog, arg, cmdline, NULL}); + size_t n, m; + char *a, *b, *argv[4], comspec[PATH_MAX + 1]; + if (!IsWindows()) { + argv[0] = _PATH_BSHELL; + argv[1] = "-c"; + } else { + b = "cmd.exe"; + a = kNtSystemDirectory; + if ((n = strlen(a)) + (m = strlen(b)) > PATH_MAX) return enametoolong(); + memcpy(mempcpy(comspec, a, n), b, m + 1); + argv[0] = comspec; + argv[1] = "/C"; + } + argv[2] = cmdline; + argv[3] = NULL; + return execv(argv[0], argv); } diff --git a/libc/str/getzipcdir.c b/libc/str/getzipcdir.c new file mode 100644 index 000000000..18d1d956e --- /dev/null +++ b/libc/str/getzipcdir.c @@ -0,0 +1,53 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Locates End Of Central Directory record in ZIP file. + * + * The ZIP spec says this header can be anywhere in the last 64kb. + * We search it backwards for the ZIP-64 "PK♠♠" magic number. If that's + * not found, then we search again for the original "PK♣♠" magnum. The + * caller needs to check the first four bytes of the returned value to + * determine whether to use ZIP_CDIR_xxx() or ZIP_CDIR64_xxx() macros. + * + * @param p points to file memory + * @param n is byte size of file + * @return pointer to EOCD64 or EOCD, or NULL if not found + */ +uint8_t *GetZipCdir(const uint8_t *p, size_t n) { + size_t i, j; + if (n >= kZipCdirHdrMinSize) { + i = n - kZipCdirHdrMinSize; + do { + if (READ32LE(p + i) == kZipCdir64HdrMagic && IsZipCdir64(p, n, i)) { + return (/*unconst*/ uint8_t *)(p + i); + } else if (READ32LE(p + i) == kZipCdirHdrMagic && IsZipCdir32(p, n, i)) { + j = i; + do { + if (READ32LE(p + j) == kZipCdir64HdrMagic && IsZipCdir64(p, n, j)) { + return (/*unconst*/ uint8_t *)(p + j); + } + } while (j-- && i - j < 64 * 1024); + return (/*unconst*/ uint8_t *)(p + i); + } + } while (i--); + } + return NULL; +} diff --git a/libc/str/getzipcdiroffset.c b/libc/str/getzipcdiroffset.c new file mode 100644 index 000000000..c50ff6d7a --- /dev/null +++ b/libc/str/getzipcdiroffset.c @@ -0,0 +1,30 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns offset of zip central directory. + */ +uint64_t GetZipCdirOffset(const uint8_t *eocd) { + if (READ32LE(eocd) == kZipCdir64HdrMagic) { + return ZIP_CDIR64_OFFSET(eocd); + } else { + return ZIP_CDIR_OFFSET(eocd); + } +} diff --git a/libc/str/getzipcdirrecords.c b/libc/str/getzipcdirrecords.c new file mode 100644 index 000000000..722bd31d8 --- /dev/null +++ b/libc/str/getzipcdirrecords.c @@ -0,0 +1,30 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns number of records in zip central directory. + */ +uint64_t GetZipCdirRecords(const uint8_t *eocd) { + if (READ32LE(eocd) == kZipCdir64HdrMagic) { + return ZIP_CDIR64_RECORDS(eocd); + } else { + return ZIP_CDIR_RECORDS(eocd); + } +} diff --git a/libc/str/getzipcfilecompressedsize.c b/libc/str/getzipcfilecompressedsize.c new file mode 100644 index 000000000..9391bcce7 --- /dev/null +++ b/libc/str/getzipcfilecompressedsize.c @@ -0,0 +1,37 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns compressed size in bytes from zip central directory header. + */ +uint64_t GetZipCfileCompressedSize(const uint8_t *z) { + uint64_t x; + const uint8_t *p, *pe; + if ((x = ZIP_CFILE_COMPRESSEDSIZE(z)) == 0xFFFFFFFF) { + for (p = ZIP_CFILE_EXTRA(z), pe = p + ZIP_CFILE_EXTRASIZE(z); p < pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64 && + 8 + 8 <= ZIP_EXTRA_CONTENTSIZE(p)) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 8); + } + } + } + return x; +} diff --git a/libc/str/getzipcfilemode.c b/libc/str/getzipcfilemode.c new file mode 100644 index 000000000..7a51b551d --- /dev/null +++ b/libc/str/getzipcfilemode.c @@ -0,0 +1,47 @@ +/*-*- 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 2021 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/nt/enum/fileflagandattributes.h" +#include "libc/sysv/consts/s.h" +#include "libc/zip.h" + +static int ConvertWindowsToUnixMode(int x) { + int m; + if (x & kNtFileAttributeReadonly) { + m = 0444; + } else { + m = 0644; + } + if (x & kNtFileAttributeDirectory) { + m |= S_IFDIR | 0111; + } else { + m |= S_IFREG; + } + return m; +} + +/** + * Returns st_mode from ZIP central directory record. + */ +int GetZipCfileMode(const uint8_t *p) { + if (ZIP_CFILE_FILEATTRCOMPAT(p) == kZipOsUnix) { + return ZIP_CFILE_EXTERNALATTRIBUTES(p) >> 16; + } else { + return ConvertWindowsToUnixMode(ZIP_CFILE_EXTERNALATTRIBUTES(p)); + } +} diff --git a/libc/str/getzipcfileoffset.c b/libc/str/getzipcfileoffset.c new file mode 100644 index 000000000..59f519fb3 --- /dev/null +++ b/libc/str/getzipcfileoffset.c @@ -0,0 +1,37 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns offset of local file header. + */ +uint64_t GetZipCfileOffset(const uint8_t *z) { + uint64_t x; + const uint8_t *p, *pe; + if ((x = ZIP_CFILE_OFFSET(z)) == 0xFFFFFFFF) { + for (p = ZIP_CFILE_EXTRA(z), pe = p + ZIP_CFILE_EXTRASIZE(z); p < pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64 && + 16 + 8 <= ZIP_EXTRA_CONTENTSIZE(p)) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 16); + } + } + } + return x; +} diff --git a/libc/str/getzipcfileuncompressedsize.c b/libc/str/getzipcfileuncompressedsize.c new file mode 100644 index 000000000..0db56764b --- /dev/null +++ b/libc/str/getzipcfileuncompressedsize.c @@ -0,0 +1,37 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns uncompressed size in bytes from zip central directory header. + */ +uint64_t GetZipCfileUncompressedSize(const uint8_t *z) { + uint64_t x; + const uint8_t *p, *pe; + if ((x = ZIP_CFILE_UNCOMPRESSEDSIZE(z)) == 0xFFFFFFFF) { + for (p = ZIP_CFILE_EXTRA(z), pe = p + ZIP_CFILE_EXTRASIZE(z); p < pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64 && + 0 + 8 <= ZIP_EXTRA_CONTENTSIZE(p)) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 0); + } + } + } + return x; +} diff --git a/libc/str/getziplfilecompressedsize.c b/libc/str/getziplfilecompressedsize.c new file mode 100644 index 000000000..e2b978333 --- /dev/null +++ b/libc/str/getziplfilecompressedsize.c @@ -0,0 +1,37 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns compressed size in bytes from zip local file header. + */ +uint64_t GetZipLfileCompressedSize(const uint8_t *z) { + uint64_t x; + const uint8_t *p, *pe; + if ((x = ZIP_LFILE_COMPRESSEDSIZE(z)) == 0xFFFFFFFF) { + for (p = ZIP_LFILE_EXTRA(z), pe = p + ZIP_LFILE_EXTRASIZE(z); p < pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64 && + 8 + 8 <= ZIP_EXTRA_CONTENTSIZE(p)) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 8); + } + } + } + return x; +} diff --git a/libc/str/getziplfileuncompressedsize.c b/libc/str/getziplfileuncompressedsize.c new file mode 100644 index 000000000..2afb9deea --- /dev/null +++ b/libc/str/getziplfileuncompressedsize.c @@ -0,0 +1,38 @@ +/*-*- 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 2021 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/zip.h" + +/** + * Returns uncompressed size in bytes from zip local file header. + */ +uint64_t GetZipLfileUncompressedSize(const uint8_t *z) { + uint64_t x; + const uint8_t *p, *pe; + x = ZIP_LFILE_UNCOMPRESSEDSIZE(z); + if (x == 0xFFFFFFFF) { + for (p = ZIP_LFILE_EXTRA(z), pe = p + ZIP_LFILE_EXTRASIZE(z); p < pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraZip64 && + 0 + 8 <= ZIP_EXTRA_CONTENTSIZE(p)) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 0); + } + } + } + return x; +} diff --git a/libc/str/iszipcdir32.c b/libc/str/iszipcdir32.c new file mode 100644 index 000000000..27382a230 --- /dev/null +++ b/libc/str/iszipcdir32.c @@ -0,0 +1,38 @@ +/*-*- 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 2021 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/bits.h" +#include "libc/zip.h" + +/** + * Returns true if zip end of central directory header seems legit. + */ +bool IsZipCdir32(const uint8_t *p, size_t n, size_t i) { + if (i > n || n - i < kZipCdirHdrMinSize) return false; + if (READ32LE(p + i) != kZipCdirHdrMagic) return false; + if (i + ZIP_CDIR_HDRSIZE(p + i) > n) return false; + if (ZIP_CDIR_DISK(p + i) != ZIP_CDIR_STARTINGDISK(p + i)) return false; + if (ZIP_CDIR_RECORDSONDISK(p + i) != ZIP_CDIR_RECORDS(p + i)) return false; + if (ZIP_CDIR_RECORDS(p + i) * kZipCfileHdrMinSize > ZIP_CDIR_SIZE(p + i)) { + return false; + } + if (ZIP_CDIR_OFFSET(p + i) + ZIP_CDIR_SIZE(p + i) > i) { + return false; + } + return true; +} diff --git a/libc/str/iszipcdir64.c b/libc/str/iszipcdir64.c new file mode 100644 index 000000000..ca18dcee2 --- /dev/null +++ b/libc/str/iszipcdir64.c @@ -0,0 +1,41 @@ +/*-*- 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 2021 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/bits.h" +#include "libc/zip.h" + +/** + * Returns true if zip64 end of central directory header seems legit. + */ +bool IsZipCdir64(const uint8_t *p, size_t n, size_t i) { + if (i > n || n - i < kZipCdir64HdrMinSize) return false; + if (READ32LE(p + i) != kZipCdir64HdrMagic) return false; + if (i + ZIP_CDIR64_HDRSIZE(p + i) > n) return false; + if (ZIP_CDIR64_DISK(p + i) != ZIP_CDIR64_STARTINGDISK(p + i)) return false; + if (ZIP_CDIR64_RECORDSONDISK(p + i) != ZIP_CDIR64_RECORDS(p + i)) { + return false; + } + if (ZIP_CDIR64_RECORDS(p + i) * kZipCfileHdrMinSize > + ZIP_CDIR64_SIZE(p + i)) { + return false; + } + if (ZIP_CDIR64_OFFSET(p + i) + ZIP_CDIR64_SIZE(p + i) > i) { + return false; + } + return true; +} diff --git a/libc/str/memccpy.c b/libc/str/memccpy.c index adcd21eec..708a85fe5 100644 --- a/libc/str/memccpy.c +++ b/libc/str/memccpy.c @@ -16,12 +16,14 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" #include "libc/str/str.h" static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) { - return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 | - (uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 | - (uint64_t)p[1] << 010 | (uint64_t)p[0] << 000; + return (uint64_t)(255 & p[7]) << 070 | (uint64_t)(255 & p[6]) << 060 | + (uint64_t)(255 & p[5]) << 050 | (uint64_t)(255 & p[4]) << 040 | + (uint64_t)(255 & p[3]) << 030 | (uint64_t)(255 & p[2]) << 020 | + (uint64_t)(255 & p[1]) << 010 | (uint64_t)(255 & p[0]) << 000; } /** diff --git a/libc/str/strcasecmp16.c b/libc/str/strcasecmp16.c index 663265ba6..5f3869e69 100644 --- a/libc/str/strcasecmp16.c +++ b/libc/str/strcasecmp16.c @@ -29,6 +29,6 @@ int strcasecmp16(const char16_t *l, const char16_t *r) { int x, y; size_t i = 0; - while ((x = tolower(l[i])) == (y = tolower(r[i])) && r[i]) ++i; + while ((x = towlower(l[i])) == (y = towlower(r[i])) && r[i]) ++i; return x - y; } diff --git a/libc/str/strchrnul.c b/libc/str/strchrnul.c index 09c4f738b..cde51302f 100644 --- a/libc/str/strchrnul.c +++ b/libc/str/strchrnul.c @@ -19,14 +19,14 @@ #include "libc/assert.h" #include "libc/str/str.h" -noasan static const unsigned char *strchrnul_x64(const unsigned char *p, - uint64_t c) { +noasan static const char *strchrnul_x64(const char *p, uint64_t c) { unsigned a, b; uint64_t w, x, y; for (c *= 0x0101010101010101;; p += 8) { - w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 | - (uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 | - (uint64_t)p[1] << 010 | (uint64_t)p[0] << 000; + w = (uint64_t)(255 & p[7]) << 070 | (uint64_t)(255 & p[6]) << 060 | + (uint64_t)(255 & p[5]) << 050 | (uint64_t)(255 & p[4]) << 040 | + (uint64_t)(255 & p[3]) << 030 | (uint64_t)(255 & p[2]) << 020 | + (uint64_t)(255 & p[1]) << 010 | (uint64_t)(255 & p[0]) << 000; if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) | (y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) { if (x) { @@ -59,11 +59,11 @@ noasan static const unsigned char *strchrnul_x64(const unsigned char *p, */ char *strchrnul(const char *s, int c) { char *r; - for (c &= 0xff; (uintptr_t)s & 7; ++s) { + for (c &= 255; (uintptr_t)s & 7; ++s) { if ((*s & 0xff) == c) return s; if (!*s) return s; } - r = (char *)strchrnul_x64((const unsigned char *)s, c); - assert((*r & 0xff) == c || !*r); + r = strchrnul_x64(s, c); + assert((*r & 255) == c || !*r); return r; } diff --git a/libc/str/strcmp.c b/libc/str/strcmp.c index 53cc44cf5..0917ecac2 100644 --- a/libc/str/strcmp.c +++ b/libc/str/strcmp.c @@ -18,10 +18,11 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/str/str.h" -static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) { - return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 | - (uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 | - (uint64_t)p[1] << 010 | (uint64_t)p[0] << 000; +static inline noasan uint64_t UncheckedAlignedRead64(const char *p) { + return (uint64_t)(255 & p[7]) << 070 | (uint64_t)(255 & p[6]) << 060 | + (uint64_t)(255 & p[5]) << 050 | (uint64_t)(255 & p[4]) << 040 | + (uint64_t)(255 & p[3]) << 030 | (uint64_t)(255 & p[2]) << 020 | + (uint64_t)(255 & p[1]) << 010 | (uint64_t)(255 & p[0]) << 000; } /** diff --git a/libc/str/strlen-pure.c b/libc/str/strlen-pure.c index 6df045f16..8463fce55 100644 --- a/libc/str/strlen-pure.c +++ b/libc/str/strlen-pure.c @@ -17,20 +17,15 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/bits.h" #include "libc/str/str.h" static noasan size_t strlen_pure_x64(const char *s, size_t i) { uint64_t w; - const unsigned char *p; - for (;;) { - p = (const unsigned char *)s + i; - w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 | - (uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 | - (uint64_t)p[1] << 010 | (uint64_t)p[0] << 000; + for (;; i += 8) { + w = READ64LE(s + i); if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) { return i + ((unsigned)__builtin_ctzll(w) >> 3); - } else { - i += 8; } } } diff --git a/libc/str/strnlen.c b/libc/str/strnlen.c index 61b326f18..f07286a36 100644 --- a/libc/str/strnlen.c +++ b/libc/str/strnlen.c @@ -17,16 +17,13 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" +#include "libc/bits/bits.h" #include "libc/str/str.h" static noasan size_t strnlen_x64(const char *s, size_t n, size_t i) { uint64_t w; - const unsigned char *p; for (; i + 8 < n; i += 8) { - p = (const unsigned char *)s + i; - w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 | - (uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 | - (uint64_t)p[1] << 010 | (uint64_t)p[0] << 000; + w = READ64LE(s + i); if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) { i += (unsigned)__builtin_ctzll(w) >> 3; break; diff --git a/libc/str/tprecode8to16.c b/libc/str/tprecode8to16.c index 7d9956659..f06e7d104 100644 --- a/libc/str/tprecode8to16.c +++ b/libc/str/tprecode8to16.c @@ -25,8 +25,8 @@ #include "libc/str/utf16.h" /* 34x speedup for ascii */ -static noasan axdx_t tprecode8to16_sse2(char16_t *dst, size_t dstsize, - const char *src, axdx_t r) { +static inline noasan axdx_t tprecode8to16_sse2(char16_t *dst, size_t dstsize, + const char *src, axdx_t r) { uint8_t v1[16], v2[16], vz[16]; memset(vz, 0, 16); while (r.ax + 16 < dstsize) { @@ -54,26 +54,25 @@ static noasan axdx_t tprecode8to16_sse2(char16_t *dst, size_t dstsize, */ axdx_t tprecode8to16(char16_t *dst, size_t dstsize, const char *src) { axdx_t r; - unsigned n; - uint64_t w; - wint_t x, y; + unsigned w; + int x, y, a, b, i, n; r.ax = 0; r.dx = 0; for (;;) { - /* TODO(jart): Why is it now so much slower refactored? */ - /* if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) { */ - /* tprecode8to16_sse2(dst, dstsize, src, r); */ - /* } */ - x = src[r.dx++] & 0xff; - if (ThomPikeCont(x)) continue; - if (!isascii(x)) { - n = ThomPikeLen(x); - x = ThomPikeByte(x); - while (--n) { - if ((y = src[r.dx++] & 0xff)) { - x = ThomPikeMerge(x, y); - } else { - x = 0; + if (!IsTiny() && !((uintptr_t)(src + r.dx) & 15)) { + r = tprecode8to16_sse2(dst, dstsize, src, r); + } + x = src[r.dx++] & 0377; + if (x >= 0300) { + a = ThomPikeByte(x); + n = ThomPikeLen(x) - 1; + for (i = 0;;) { + if (!(b = src[r.dx + i] & 0377)) break; + if (!ThomPikeCont(b)) break; + a = ThomPikeMerge(a, b); + if (++i == n) { + r.dx += i; + x = a; break; } } @@ -81,7 +80,7 @@ axdx_t tprecode8to16(char16_t *dst, size_t dstsize, const char *src) { if (!x) break; w = EncodeUtf16(x); while (w && r.ax + 1 < dstsize) { - dst[r.ax++] = w & 0xFFFF; + dst[r.ax++] = w; w >>= 16; } } diff --git a/libc/str/undeflate.c b/libc/str/undeflate.c index d849417d2..60b165efa 100644 --- a/libc/str/undeflate.c +++ b/libc/str/undeflate.c @@ -104,7 +104,7 @@ static struct DeflateHold undeflatesymbol(struct DeflateHold hold, uint32_t search, key; left = 0; right = treecount; - search = bitreverse16(hold.word); + search = BITREVERSE16(hold.word); search <<= 16; search |= 0xffff; while (left < right) { /* TODO(jart): Make this O(1) like Zlib. */ diff --git a/libc/str/utf16.h b/libc/str/utf16.h index 7bc999f7d..0e8e391d7 100644 --- a/libc/str/utf16.h +++ b/libc/str/utf16.h @@ -11,15 +11,15 @@ COSMOPOLITAN_C_START_ #define IsUcs2(wc) (((wc)&UTF16_MASK) != UTF16_MOAR) #define IsUtf16Cont(wc) (((wc)&UTF16_MASK) == UTF16_CONT) #define MergeUtf16(lo, hi) ((((lo)-0xD800) << 10) + ((hi)-0xDC00) + 0x10000) -#define EncodeUtf16(wc) \ - (__builtin_expect(((0x0000 <= (wc) && (wc) <= 0xFFFF) || \ - (0xE000 <= (wc) && (wc) <= 0xFFFF)), \ - 1) \ - ? (wc) \ - : 0x10000 <= (wc) && (wc) <= 0x10FFFF \ - ? (((((wc)-0x10000) >> 10) + 0xD800) | \ - ((((wc)-0x10000) & 1023) + 0xDC00) << 16) \ - : 0xFFFD) +#define EncodeUtf16(wc) \ + (__builtin_expect(((0x0000 <= (wc) && (wc) <= 0xFFFF) || \ + (0xE000 <= (wc) && (wc) <= 0xFFFF)), \ + 1) \ + ? (wc) \ + : 0x10000 <= (wc) && (wc) <= 0x10FFFF \ + ? (((((wc)-0x10000) >> 10) + 0xD800) | \ + (unsigned)((((wc)-0x10000) & 1023) + 0xDC00) << 16) \ + : 0xFFFD) COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/str/zipfindcentraldir.c b/libc/str/zipfindcentraldir.c index 431a75ea1..42a966d66 100644 --- a/libc/str/zipfindcentraldir.c +++ b/libc/str/zipfindcentraldir.c @@ -18,6 +18,8 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/zip.h" +/* TODO(jart): DELETE */ + /** * Locates End Of Central Directory record in ZIP file. * @@ -36,13 +38,7 @@ uint8_t *zipfindcentraldir(const uint8_t *p, size_t n) { if (n >= kZipCdirHdrMinSize) { i = n - kZipCdirHdrMinSize; do { - if (ZIP_CDIR_MAGIC(p + i) == kZipCdirHdrMagic && - i + ZIP_CDIR_HDRSIZE(p + i) <= n && - ZIP_CDIR_DISK(p + i) == ZIP_CDIR_STARTINGDISK(p + i) && - ZIP_CDIR_RECORDSONDISK(p + i) == ZIP_CDIR_RECORDS(p + i) && - ZIP_CDIR_RECORDS(p + i) * kZipCdirHdrMinSize <= - ZIP_CDIR_SIZE(p + i) && - ZIP_CDIR_OFFSET(p + i) + ZIP_CDIR_SIZE(p + i) <= i) { + if (ZIP_CDIR_MAGIC(p + i) == kZipCdirHdrMagic && IsZipCdir32(p, n, i)) { return (/*unconst*/ uint8_t *)(p + i); } } while (i--); diff --git a/libc/sysv/calls/__sys_getrusage.s b/libc/sysv/calls/__sys_getrusage.s new file mode 100644 index 000000000..49b33c68d --- /dev/null +++ b/libc/sysv/calls/__sys_getrusage.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_getrusage,0x1bd0130752075062,globl,hidden diff --git a/libc/sysv/calls/__sys_mremap.s b/libc/sysv/calls/__sys_mremap.s new file mode 100644 index 000000000..9e32e0e10 --- /dev/null +++ b/libc/sysv/calls/__sys_mremap.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_mremap,0x19bffffffffff019,globl,hidden diff --git a/libc/sysv/calls/__sys_wait4.s b/libc/sysv/calls/__sys_wait4.s new file mode 100644 index 000000000..15180408c --- /dev/null +++ b/libc/sysv/calls/__sys_wait4.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_wait4,0x1c100b007200703d,globl,hidden diff --git a/libc/sysv/calls/rt_sigqueueinfo.s b/libc/sysv/calls/rt_sigqueueinfo.s deleted file mode 100644 index 0b821b76e..000000000 --- a/libc/sysv/calls/rt_sigqueueinfo.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall rt_sigqueueinfo,0xfffffffffffff081,globl diff --git a/libc/sysv/calls/sigqueue.s b/libc/sysv/calls/sigqueue.s deleted file mode 100644 index 7f813ba9e..000000000 --- a/libc/sysv/calls/sigqueue.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sigqueue,0xffffff1c8fffffff,globl diff --git a/libc/sysv/calls/sys_getrusage.s b/libc/sysv/calls/sys_getrusage.s deleted file mode 100644 index a59cee99c..000000000 --- a/libc/sysv/calls/sys_getrusage.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_getrusage,0x1bd0130752075062,globl,hidden diff --git a/libc/sysv/calls/sys_mremap.s b/libc/sysv/calls/sys_mremap.s deleted file mode 100644 index 759973cd9..000000000 --- a/libc/sysv/calls/sys_mremap.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_mremap,0x19bffffffffff019,globl,hidden diff --git a/libc/sysv/calls/sys_sigqueue.s b/libc/sysv/calls/sys_sigqueue.s new file mode 100644 index 000000000..5faa160bf --- /dev/null +++ b/libc/sysv/calls/sys_sigqueue.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sigqueue,0xffffff1c8fffffff,globl diff --git a/libc/sysv/calls/sys_sigqueueinfo.s b/libc/sysv/calls/sys_sigqueueinfo.s new file mode 100644 index 000000000..4e521ca9f --- /dev/null +++ b/libc/sysv/calls/sys_sigqueueinfo.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall sys_sigqueueinfo,0x0f5ffffffffff081,globl diff --git a/libc/sysv/calls/sys_wait4.s b/libc/sysv/calls/sys_wait4.s deleted file mode 100644 index 4a1674eee..000000000 --- a/libc/sysv/calls/sys_wait4.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_wait4,0x1c100b007200703d,globl,hidden diff --git a/libc/sysv/consensus.py b/libc/sysv/consensus.py deleted file mode 100755 index fbd61bfd5..000000000 --- a/libc/sysv/consensus.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import sys - -lineno = 0 - -def atoi(s): - try: - if s == '0': - return 0 - elif s.startswith('0x'): - return int(s[2:], 16) - elif s.startswith('0b'): - return int(s[2:], 2) - elif s.startswith('0'): - return int(s[1:], 8) - return int(s) - except ValueError: - sys.stderr.write('error: %s on line %d\n' % (s, lineno)) - sys.exit(1) - -for line in open('consts.sh'): - f = line.split() - lineno = lineno + 1 - if len(f) >= 8 and f[0] == 'syscon': - linux = atoi(f[3]) - xnu = atoi(f[4]) - freebsd = atoi(f[5]) - openbsd = atoi(f[6]) - windows = atoi(f[7]) - if linux == xnu and xnu == freebsd and freebsd == openbsd and openbsd == windows: - sys.stdout.write('%s\t%s\n' % (f[1], f[2])) diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 80e50605e..665f3afdc 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -23,180 +23,176 @@ dir=libc/sysv/consts # » catalogue of carnage # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD Windows Commentary -syscon errno ENOSYS 38 78 78 78 78 1 # bsd consensus & kNtErrorInvalidFunction -syscon errno EPERM 1 1 1 1 1 12 # unix consensus & kNtErrorInvalidAccess (should be kNtErrorNotOwner but is that mutex only??) -syscon errno ENOENT 2 2 2 2 2 2 # unix consensus & kNtErrorFileNotFound -syscon errno ESRCH 3 3 3 3 3 566 # "no such process" & kNtErrorThreadNotInProcess (cf. kNtErrorInvalidHandle) -syscon errno EINTR 4 4 4 4 4 10004 # unix consensus & WSAEINTR -syscon errno EIO 5 5 5 5 5 1117 # unix consensus & kNtErrorIoDevice -syscon errno ENXIO 6 6 6 6 6 1112 # unix consensus & kNtErrorNoMediaInDrive -syscon errno E2BIG 7 7 7 7 7 1639 # unix consensus & kNtErrorInvalidCommandLine -syscon errno ENOEXEC 8 8 8 8 8 193 # unix consensus & kNtErrorBadExeFormat -syscon errno EBADF 9 9 9 9 9 6 # bad file descriptor; cf. EBADFD; unix consensus & kNtErrorInvalidHandle -syscon errno ECHILD 10 10 10 10 10 128 # unix consensus & kNtErrorWaitNoChildren -syscon errno EAGAIN 11 35 35 35 35 0x2733 # bsd consensus & WSAEWOULDBLOCK -syscon errno EWOULDBLOCK 11 35 35 35 35 0x2733 # bsd consensus & WSAEWOULDBLOCK -syscon errno ENOMEM 12 12 12 12 12 14 # unix consensus & kNtErrorOutofmemory -syscon errno EACCES 13 13 13 13 13 5 # unix consensus & kNtErrorAccessDenied -syscon errno EFAULT 14 14 14 14 14 487 # unix consensus & kNtErrorInvalidAddress -syscon errno ENOTBLK 15 15 15 15 15 26 # unix consensus & kNtErrorNotDosDisk -syscon errno EBUSY 16 16 16 16 16 170 # unix consensus & kNtErrorBusy -syscon errno EEXIST 17 17 17 17 17 183 # unix consensus & kNtErrorAlreadyExists (should be kNtErrorFileExists too) -syscon errno EXDEV 18 18 18 18 18 17 # unix consensus & kNtErrorNotSameDevice -syscon errno ENODEV 19 19 19 19 19 1200 # unix consensus & kNtErrorBadDevice -syscon errno ENOTDIR 20 20 20 20 20 3 # unix consensus & kNtErrorPathNotFound -syscon errno EISDIR 21 21 21 21 21 267 # unix consensus & kNtErrorDirectoryNotSupported -syscon errno EINVAL 22 22 22 22 22 87 # unix consensus & kNtErrorInvalidParameter -syscon errno ENFILE 23 23 23 23 23 331 # unix consensus & kNtErrorTooManyDescriptors -syscon errno EMFILE 24 24 24 24 24 336 # unix consensus & kNtErrorTooManyOpenFiles -syscon errno ENOTTY 25 25 25 25 25 1118 # unix consensus & kNtErrorSerialNoDevice -syscon errno ETXTBSY 26 26 26 26 26 148 # unix consensus & kNtErrorPathBusy -syscon errno EFBIG 27 27 27 27 27 223 # unix consensus & kNtErrorFileTooLarge -syscon errno ENOSPC 28 28 28 28 28 39 # unix consensus & kNtErrorDiskFull -syscon errno EDQUOT 122 69 69 69 69 0x2755 # bsd consensus -syscon errno ESPIPE 29 29 29 29 29 25 # unix consensus & kNtErrorSeek -syscon errno EROFS 30 30 30 30 30 6009 # unix consensus & kNtErrorFileReadOnly -syscon errno EMLINK 31 31 31 31 31 4 # unix consensus & kNtErrorTooManyLinks -syscon errno EPIPE 32 32 32 32 32 109 # unix consensus & kNtErrorBrokenPipe -syscon errno EDOM 33 33 33 33 33 33 # bsd consensus & fudged on NT -syscon errno ERANGE 34 34 34 34 34 34 # bsd consensus & fudged on NT -syscon errno EDEADLK 35 11 11 11 11 1131 # bsd consensus & kNtErrorPossibleDeadlock -syscon errno ENAMETOOLONG 36 63 63 63 63 0x274f # bsd consensus & WSAENAMETOOLONG -syscon errno ENOLCK 37 77 77 77 77 0 # bsd consensus -syscon errno ENOTEMPTY 39 66 66 66 66 145 # bsd consensus & kNtErrorDirNotEmpty (TODO: What is WSAENOTEMPTY? 0x2752) -syscon errno ELOOP 40 62 62 62 62 0x274e # bsd consensus & WSAELOOP -syscon errno ENOMSG 42 91 83 90 83 0 -syscon errno EIDRM 43 90 82 89 82 0 -syscon errno EUSERS 87 68 68 68 68 0x2754 # bsd consensus & WSAEUSERS -syscon errno ENOTSOCK 88 38 38 38 38 0x2736 # bsd consensus & WSAENOTSOCK -syscon errno EDESTADDRREQ 89 39 39 39 39 0x2737 # bsd consensus & WSAEDESTADDRREQ -syscon errno EMSGSIZE 90 40 40 40 40 0x2738 # bsd consensus & WSAEMSGSIZE -syscon errno EPROTOTYPE 91 41 41 41 41 0x2739 # bsd consensus & WSAEPROTOTYPE -syscon errno ENOPROTOOPT 92 42 42 42 42 0x273a # bsd consensus & WSAENOPROTOOPT -syscon errno EPROTONOSUPPORT 93 43 43 43 43 0x273b # bsd consensus & WSAEPROTONOSUPPORT -syscon errno ESOCKTNOSUPPORT 94 44 44 44 44 0x273c # bsd consensus & WSAESOCKTNOSUPPORT -syscon errno ENOTSUP 95 45 45 91 86 0x273d -syscon errno EOPNOTSUPP 95 102 45 45 45 0x273d -syscon errno EPFNOSUPPORT 96 46 46 46 46 0x273e # bsd consensus & WSAEPFNOSUPPORT -syscon errno EAFNOSUPPORT 97 47 47 47 47 0x273f # bsd consensus & WSAEAFNOSUPPORT -syscon errno EADDRINUSE 98 48 48 48 48 0x2740 # bsd consensus & WSAEADDRINUSE -syscon errno EADDRNOTAVAIL 99 49 49 49 49 0x2741 # bsd consensus & WSAEADDRNOTAVAIL -syscon errno ENETDOWN 100 50 50 50 50 0x2742 # bsd consensus & WSAENETDOWN -syscon errno ENETUNREACH 101 51 51 51 51 0x2743 # bsd consensus & WSAENETUNREACH -syscon errno ENETRESET 102 52 52 52 52 0x2744 # bsd consensus & WSAENETRESET -syscon errno ECONNABORTED 103 53 53 53 53 0x2745 # bsd consensus & WSAECONNABORTED -syscon errno ECONNRESET 104 54 54 54 54 0x2746 # bsd consensus & WSAECONNRESET -syscon errno ENOBUFS 105 55 55 55 55 0x2747 # bsd consensus & WSAENOBUFS -syscon errno EISCONN 106 56 56 56 56 0x2748 # bsd consensus & WSAEISCONN -syscon errno ENOTCONN 107 57 57 57 57 0x2749 # bsd consensus & WSAENOTCONN -syscon errno ESHUTDOWN 108 58 58 58 58 0x274a # bsd consensus & WSAESHUTDOWN -syscon errno ETOOMANYREFS 109 59 59 59 59 0x274b # bsd consensus & WSAETOOMANYREFS -syscon errno ETIMEDOUT 110 60 60 60 60 0x274c # bsd consensus & WSAETIMEDOUT -syscon errno ECONNREFUSED 111 61 61 61 61 0x274d # bsd consensus & WSAECONNREFUSED -syscon errno EHOSTDOWN 112 64 64 64 64 0x2750 # bsd consensus & WSAEHOSTDOWN -syscon errno EHOSTUNREACH 113 65 65 65 65 0x2751 # bsd consensus & WSAEHOSTUNREACH -syscon errno EALREADY 114 37 37 37 37 0x2735 # bsd consensus & WSAEALREADY -syscon errno EINPROGRESS 115 36 36 36 36 0x2734 # bsd consensus & WSAEINPROGRESS -syscon errno ESTALE 116 70 70 70 70 0x2756 # bsd consensus & WSAESTALE -syscon errno ECHRNG 44 0 0 0 0 0 # bsd consensus -syscon errno EL2NSYNC 45 0 0 0 0 0 # bsd consensus -syscon errno EL3HLT 46 0 0 0 0 0 # bsd consensus -syscon errno EL3RST 47 0 0 0 0 0 # bsd consensus -syscon errno ELNRNG 48 0 0 0 0 0 # bsd consensus -syscon errno EUNATCH 49 0 0 0 0 0 # bsd consensus -syscon errno ENOCSI 50 0 0 0 0 0 # bsd consensus -syscon errno EL2HLT 51 0 0 0 0 0 # bsd consensus -syscon errno EBADE 52 0 0 0 0 0 # bsd consensus -syscon errno EBADR 53 0 0 0 0 0 # bsd consensus -syscon errno EXFULL 54 0 0 0 0 0 # bsd consensus -syscon errno ENOANO 55 0 0 0 0 0 # bsd consensus -syscon errno EBADRQC 56 0 0 0 0 0 # bsd consensus -syscon errno EBADSLT 57 0 0 0 0 0 # bsd consensus -syscon errno EBFONT 59 0 0 0 0 0 # bsd consensus -syscon errno ENOSTR 60 99 0 0 91 0 -syscon errno ENODATA 61 96 0 0 89 0 -syscon errno ETIME 62 101 0 0 92 0 -syscon errno ENOSR 63 98 0 0 90 0 -syscon errno ENONET 64 0 0 0 0 0 # bsd consensus -syscon errno ENOPKG 65 0 0 0 0 0 # bsd consensus +syscon errno ENOSYS 38 78 78 78 78 1 # system call unavailable; bsd consensus; kNtErrorInvalidFunction +syscon errno EPERM 1 1 1 1 1 12 # operation not permitted; unix consensus; kNtErrorInvalidAccess (should be kNtErrorNotOwner but is that mutex only??); raised by accept(2), acct(2), add_key(2), adjtimex(2), arch_prctl(2), bdflush(2), bpf(2), capget(2), chmod(2), chown(2), chroot(2), clock_getres(2), clone(2), copy_file_range(2), create_module(2), delete_module(2), epoll_ctl(2), execve(2), fallocate(2), fanotify_init(2), fcntl(2), futex(2), get_robust_list(2), getdomainname(2), getgroups(2), gethostname(2), getpriority(2), getrlimit(2), getsid(2), gettimeofday(2), idle(2), init_module(2), io_submit(2), ioctl_console(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_ns(2), ioctl_tty(2), ioperm(2), iopl(2), ioprio_set(2), kcmp(2), kexec_load(2), keyctl(2), kill(2), link(2), lookup_dcookie(2), madvise(2), mbind(2), membarrier(2), migrate_pages(2), mkdir(2), mknod(2), mlock(2), mmap(2), mount(2), move_pages(2), msgctl(2), nice(2), open(2), open_by_handle_at(2), pciconfig_read(2), perf_event_open(2), pidfd_getfd(2), pidfd_send_signal(2), pivot_root(2), prctl(2), process_vm_readv(2), ptrace(2), quotactl(2), reboot(2), rename(2), request_key(2), rmdir(2), rt_sigqueueinfo(2), sched_setaffinity(2), sched_setattr(2), sched_setparam(2), sched_setscheduler(2), semctl(2), seteuid(2), setfsgid(2), setfsuid(2), setgid(2), setns(2), setpgid(2), setresuid(2), setreuid(2), setsid(2), setuid(2), setup(2), setxattr(2), shmctl(2), shmget(2), sigaltstack(2), spu_create(2), stime(2), swapon(2), symlink(2), syslog(2), timer_create(2), timerfd_create(2), tkill(2), truncate(2), umount(2), unlink(2), unshare(2), utime(2), utimensat(2), vhangup(2), vm86(2), write(2), unix(7), ip(7) +syscon errno ENOENT 2 2 2 2 2 2 # no such file or directory; unix consensus; kNtErrorFileNotFound; raised by access(2), acct(2), alloc_hugepages(2), bind(2), bpf(2), chdir(2), chmod(2), chown(2), chroot(2), clock_getres(2), delete_module(2), epoll_ctl(2), execve(2), execveat(2), fanotify_mark(2), getdents(2), inotify_add_watch(2), ioctl_fat(2), kcmp(2), keyctl(2), link(2), mkdir(2), mknod(2), mount(2), msgget(2), open(2), open_by_handle_at(2), perf_event_open(2), query_module(2), quotactl(2), readdir(2), readlink(2), rename(2), rmdir(2), semget(2), shmget(2), spu_create(2), stat(2), statfs(2), statx(2), swapon(2), symlink(2), truncate(2), umount(2), unlink(2), utime(2), utimensat(2), unix(7), ip(7) +syscon errno ESRCH 3 3 3 3 3 566 # no such process; kNtErrorThreadNotInProcess (cf. kNtErrorInvalidHandle); raised by capget(2), get_robust_list(2), getpriority(2), getrlimit(2), getsid(2), ioprio_set(2), kcmp(2), kill(2), migrate_pages(2), move_pages(2), perf_event_open(2), pidfd_getfd(2), pidfd_open(2), pidfd_send_signal(2), process_vm_readv(2), ptrace(2), quotactl(2), rt_sigqueueinfo(2), sched_rr_get_interval(2), sched_setaffinity(2), sched_setattr(2), sched_setparam(2), sched_setscheduler(2), set_thread_area(2), setpgid(2), tkill(2), utimensat(2), unix(7) +syscon errno EINTR 4 4 4 4 4 10004 # crucial for building real time reliable software; unix consensus; WSAEINTR; raised by accept(2), clock_nanosleep(2), close(2), connect(2), dup(2), epoll_wait(2), fallocate(2), fcntl(2), flock(2), futex(2), getrandom(2), io_getevents(2), msgop(2), nanosleep(2), open(2), pause(2), perf_event_open(2), poll(2), ptrace(2), read(2), recv(2), request_key(2), select(2), semop(2), send(2), sigsuspend(2), sigwaitinfo(2), spu_run(2), statfs(2), truncate(2), wait(2), write(2), +syscon errno EIO 5 5 5 5 5 1117 # unix consensus; kNtErrorIoDevice; raised by access(2) acct(2) chdir(2) chmod(2) chown(2) chroot(2) close(2) copy_file_range(2) execve(2) fallocate(2) fsync(2) ioperm(2) link(2) madvise(2) mbind(2) pciconfig_read(2) ptrace(2) read(2) readlink(2) sendfile(2) statfs(2) symlink(2) sync_file_range(2) truncate(2) unlink(2) write(2) +syscon errno ENXIO 6 6 6 6 6 1112 # no such device or address; unix consensus; kNtErrorNoMediaInDrive; raised by lseek(2), mount(2), open(2), prctl(2) +syscon errno E2BIG 7 7 7 7 7 1639 # argument list too long; unix consensus; kNtErrorInvalidCommandLine; raised by bpf(2), execve(2), getxattr(2), listxattr(2), move_pages(2), msgop(2), openat2(2), perf_event_open(2), sched_setattr(2), semop(2), +syscon errno ENOEXEC 8 8 8 8 8 193 # exec format error; unix consensus; kNtErrorBadExeFormat; raised by execve(2), init_module(2), kexec_load(2), uselib(2) +syscon errno EBADF 9 9 9 9 9 6 # bad file descriptor; cf. EBADFD; unix consensus; kNtErrorInvalidHandle; raised by accept(2), access(2), bind(2), bpf(2), chdir(2), chmod(2), chown(2), close(2), connect(2), copy_file_range(2), dup(2), epoll_ctl(2), epoll_wait(2), execveat(2), fallocate(2), fanotify_mark(2), fcntl(2), flock(2), fsync(2), futimesat(2), getdents(2), getpeername(2), getsockname(2), getsockopt(2), init_module(2), inotify_add_watch(2), inotify_rm_watch(2), io_submit(2), ioctl(2), ioctl_console(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_getfsmap(2), kcmp(2), kexec_load(2), link(2), listen(2), llseek(2), lseek(2), madvise(2), mkdir(2), mknod(2), mmap(2), open(2), open_by_handle_at(2), perf_event_open(2), pidfd_getfd(2), pidfd_send_signal(2), posix_fadvise(2), prctl(2), read(2), readahead(2), readdir(2), readlink(2), recv(2), rename(2), select(2), send(2), sendfile(2), setns(2), shutdown(2), signalfd(2), splice(2), spu_run(2), stat(2), statfs(2), statx(2), symlink(2), sync(2), sync_file_range(2), timerfd_create(2), truncate(2), unlink(2), utimensat(2), vmsplice(2), write(2), unix(7) +syscon errno ECHILD 10 10 10 10 10 128 # no child process; unix consensus; kNtErrorWaitNoChildren; raised by wait(2), waitpid(2), waitid(2), wait3(2), wait4(2) +syscon errno EAGAIN 11 35 35 35 35 0x2733 # resource temporarily unavailable (e.g. too many processes, read or write with O_NONBLOCK needs polling, too much memory locked, etc.); bsd consensus; WSAEWOULDBLOCK; raised by accept(2), clone(2), connect(2), eventfd(2), fcntl(2), fork(2), futex(2), getrandom(2), io_cancel(2), io_setup(2), io_submit(2), ioctl_userfaultfd(2), keyctl(2), madvise(2), mincore(2), mlock(2), mmap(2), mremap(2), msgop(2), openat2(2), poll(2), read(2), rt_sigqueueinfo(2), select(2), semop(2), send(2), sendfile(2), setresuid(2), setreuid(2), setuid(2), signalfd(2), sigwaitinfo(2), splice(2), tee(2), timer_create(2), timerfd_create(2), tkill(2), umount(2), vmsplice(2), write(2), ip(7) +syscon errno ENOMEM 12 12 12 12 12 14 # we require more vespene gas; unix consensus; kNtErrorOutofmemory; raised by access(2), acct(2), add_key(2), bind(2), bpf(2), chdir(2), chmod(2), chown(2), chroot(2), clone(2), copy_file_range(2), create_module(2), epoll_create(2), epoll_ctl(2), eventfd(2), execve(2), fanotify_init(2), fanotify_mark(2), fork(2), getgroups(2), getrlimit(2), init_module(2), inotify_add_watch(2), inotify_init(2), io_setup(2), ioctl_fideduperange(2), ioctl_getfsmap(2), ioperm(2), kexec_load(2), keyctl(2), link(2), lookup_dcookie(2), madvise(2), mbind(2), memfd_create(2), mincore(2), mkdir(2), mknod(2), mlock(2), mmap(2), mount(2), mprotect(2), mremap(2), msgget(2), msgop(2), msync(2), open(2), pidfd_open(2), poll(2), process_vm_readv(2), readlink(2), recv(2), rename(2), request_key(2), rmdir(2), s390_guarded_storage(2), s390_pci_mmio_write(2), s390_runtime_instr(2), s390_sthyi(2), select(2), semget(2), semop(2), send(2), sendfile(2), set_mempolicy(2), setns(2), shmctl(2), shmget(2), shmop(2), sigaltstack(2), signalfd(2), splice(2), spu_create(2), spu_run(2), stat(2), statfs(2), statx(2), subpage_prot(2), swapon(2), symlink(2), sync_file_range(2), tee(2), timer_create(2), timerfd_create(2), umount(2), unlink(2), unshare(2), userfaultfd(2), vmsplice(2), unix(7), ip(7) +syscon errno EACCES 13 13 13 13 13 5 # permission denied; unix consensus; kNtErrorAccessDenied; raised by access(2), acct(2), add_key(2), bind(2), bpf(2), chdir(2), chmod(2), chown(2), chroot(2), clock_getres(2), connect(2), execve(2), fcntl(2), futex(2), getpriority(2), inotify_add_watch(2), keyctl(2), link(2), madvise(2), mkdir(2), mknod(2), mmap(2), mount(2), move_pages(2), mprotect(2), msgctl(2), msgget(2), msgop(2), open(2), perf_event_open(2), prctl(2), ptrace(2), quotactl(2), readlink(2), rename(2), request_key(2), rmdir(2), semctl(2), semget(2), semop(2), send(2), setpgid(2), shmctl(2), shmget(2), shmop(2), socket(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), unlink(2), uselib(2), utime(2), utimensat(2), ip(7) +syscon errno EFAULT 14 14 14 14 14 487 # pointer passed to system call that would otherwise segfault; unix consensus; kNtErrorInvalidAddress; raised by accept(2), access(2), acct(2), add_key(2), adjtimex(2), arch_prctl(2), bdflush(2), bind(2), bpf(2), cacheflush(2), capget(2), chdir(2), chmod(2), chown(2), chroot(2), clock_getres(2), clock_nanosleep(2), connect(2), create_module(2), delete_module(2), epoll_wait(2), execve(2), fcntl(2), futex(2), get_mempolicy(2), get_robust_list(2), getcpu(2), getdents(2), getdomainname(2), getgroups(2), gethostname(2), getitimer(2), getpeername(2), getrandom(2), getresuid(2), getrlimit(2), getrusage(2), getsockname(2), getsockopt(2), gettimeofday(2), getunwind(2), init_module(2), inotify_add_watch(2), io_cancel(2), io_destroy(2), io_getevents(2), io_setup(2), io_submit(2), ioctl(2), ioctl_getfsmap(2), ioctl_userfaultfd(2), kcmp(2), keyctl(2), link(2), llseek(2), lookup_dcookie(2), mbind(2), memfd_create(2), migrate_pages(2), mincore(2), mkdir(2), mknod(2), mmap2(2), modify_ldt(2), mount(2), move_pages(2), mremap(2), msgctl(2), msgop(2), msync(2), nanosleep(2), open(2), open_by_handle_at(2), perf_event_open(2), pipe(2), poll(2), prctl(2), process_vm_readv(2), ptrace(2), query_module(2), quotactl(2), read(2), readdir(2), readlink(2), reboot(2), recv(2), rename(2), request_key(2), rmdir(2), s390_guarded_storage(2), s390_pci_mmio_write(2), s390_sthyi(2), sched_rr_get_interval(2), sched_setaffinity(2), semctl(2), semop(2), send(2), sendfile(2), set_mempolicy(2), set_thread_area(2), shmctl(2), sigaction(2), sigaltstack(2), sigpending(2), sigprocmask(2), sigsuspend(2), socketpair(2), spu_create(2), spu_run(2), stat(2), statfs(2), statx(2), stime(2), subpage_prot(2), symlink(2), sysctl(2), sysfs(2), sysinfo(2), time(2), timer_settime(2), timerfd_create(2), times(2), truncate(2), umount(2), uname(2), unlink(2), ustat(2), utimensat(2), vm86(2), write(2), unix(7) +syscon errno ENOTBLK 15 15 15 15 15 26 # block device required; unix consensus; kNtErrorNotDosDisk; raised by mount(2), quotactl(2), umount(2) +syscon errno EBUSY 16 16 16 16 16 170 # device or resource busy; unix consensus; kNtErrorBusy; raised by bdflush(2), delete_module(2), dup(2), fcntl(2), init_module(2), ioctl_tty(2), ioctl_userfaultfd(2), kexec_load(2), mount(2), msync(2), pivot_root(2), prctl(2), ptrace(2), quotactl(2), rename(2), rmdir(2), sched_setattr(2), swapon(2), umount(2) +syscon errno EEXIST 17 17 17 17 17 183 # file exists; unix consensus; kNtErrorAlreadyExists (should be kNtErrorFileExists too); raised by bpf(2), create_module(2), epoll_ctl(2), init_module(2), inotify_add_watch(2), keyctl(2), link(2), mkdir(2), mknod(2), mmap(2), msgget(2), open(2), rename(2), rmdir(2), semget(2), setxattr(2), shmget(2), spu_create(2), symlink(2) +syscon errno EXDEV 18 18 18 18 18 17 # improper link; unix consensus; kNtErrorNotSameDevice; raised by copy_file_range(2), fanotify_mark(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), link(2), openat2(2), rename(2) +syscon errno ENODEV 19 19 19 19 19 1200 # no such device; unix consensus; kNtErrorBadDevice; raised by arch_prctl(2), eventfd(2), fallocate(2), fanotify_mark(2), mmap(2), mount(2), move_pages(2), open(2), pciconfig_read(2), perf_event_open(2), pidfd_open(2), prctl(2), s390_pci_mmio_write(2), signalfd(2), spu_create(2), timerfd_create(2) +syscon errno ENOTDIR 20 20 20 20 20 3 # not a directory; unix consensus; kNtErrorPathNotFound; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), execve(2), execveat(2), fanotify_mark(2), fcntl(2), futimesat(2), getdents(2), inotify_add_watch(2), ioctl_fat(2), keyctl(2), link(2), mkdir(2), mknod(2), mount(2), open(2), open_by_handle_at(2), pivot_root(2), readdir(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), sysctl(2), truncate(2), unlink(2), utimensat(2) +syscon errno EISDIR 21 21 21 21 21 267 # is a a directory; unix consensus; kNtErrorDirectoryNotSupported; raised by acct(2), copy_file_range(2), execve(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), open(2), read(2), rename(2), truncate(2), unlink(2) +syscon errno EINVAL 22 22 22 22 22 87 # invalid argument; unix consensus; kNtErrorInvalidParameter; raised by accept(2), access(2), add_key(2), adjtimex(2), arch_prctl(2), bdflush(2), bind(2), bpf(2), cacheflush(2), capget(2), chmod(2), chown(2), clock_getres(2), clock_nanosleep(2), clone(2), copy_file_range(2), create_module(2), dup(2), epoll_create(2), epoll_ctl(2), epoll_wait(2), eventfd(2), execve(2), execveat(2), fallocate(2), fanotify_init(2), fanotify_mark(2), fcntl(2), flock(2), futex(2), get_mempolicy(2), get_robust_list(2), getdents(2), getdomainname(2), getgroups(2), gethostname(2), getitimer(2), getpeername(2), getpriority(2), getrandom(2), getrlimit(2), getrusage(2), getsockname(2), getsockopt(2), gettimeofday(2), init_module(2), inotify_add_watch(2), inotify_init(2), inotify_rm_watch(2), io_cancel(2), io_destroy(2), io_getevents(2), io_setup(2), io_submit(2), ioctl(2), ioctl_console(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_getfsmap(2), ioctl_ns(2), ioctl_tty(2), ioctl_userfaultfd(2), ioperm(2), iopl(2), ioprio_set(2), kcmp(2), kexec_load(2), keyctl(2), kill(2), link(2), llseek(2), lookup_dcookie(2), lseek(2), madvise(2), mbind(2), membarrier(2), memfd_create(2), migrate_pages(2), mincore(2), mkdir(2), mknod(2), mlock(2), mmap(2), mmap2(2), modify_ldt(2), mount(2), move_pages(2), mprotect(2), mremap(2), msgctl(2), msgop(2), msync(2), nanosleep(2), open(2), open_by_handle_at(2), openat2(2), pciconfig_read(2), perf_event_open(2), personality(2), pidfd_getfd(2), pidfd_open(2), pidfd_send_signal(2), pipe(2), pivot_root(2), pkey_alloc(2), poll(2), posix_fadvise(2), prctl(2), process_vm_readv(2), ptrace(2), query_module(2), quotactl(2), read(2), readahead(2), readdir(2), readlink(2), readv(2), reboot(2), recv(2), recvmmsg(2), remap_file_pages(2), rename(2), request_key(2), rmdir(2), rt_sigqueueinfo(2), s390_guarded_storage(2), s390_pci_mmio_write(2), s390_runtime_instr(2), s390_sthyi(2), sched_get_priority_max(2), sched_rr_get_interval(2), sched_setaffinity(2), sched_setattr(2), sched_setparam(2), sched_setscheduler(2), seccomp(2), select(2), semctl(2), semget(2), semop(2), send(2), sendfile(2), set_mempolicy(2), set_thread_area(2), seteuid(2), setfsgid(2), setfsuid(2), setgid(2), setns(2), setpgid(2), setresuid(2), setreuid(2), setuid(2), shmctl(2), shmget(2), shmop(2), shutdown(2), sigaction(2), sigaltstack(2), signal(2), signalfd(2), sigprocmask(2), sigsuspend(2), sigwaitinfo(2), socket(2), splice(2), spu_create(2), spu_run(2), stat(2), statx(2), subpage_prot(2), swapon(2), sync_file_range(2), sysfs(2), syslog(2), tee(2), timer_create(2), timer_delete(2), timer_getoverrun(2), timer_settime(2), timerfd_create(2), tkill(2), truncate(2), umount(2), unlink(2), unshare(2), userfaultfd(2), ustat(2), utimensat(2), vmsplice(2), wait(2), write(2), unix(7), ip(7) +syscon errno ENFILE 23 23 23 23 23 331 # too many open files in system; unix consensus; kNtErrorTooManyDescriptors; raised by accept(2), acct(2), epoll_create(2), eventfd(2), execve(2), futex(2), inotify_init(2), memfd_create(2), mmap(2), open(2), pidfd_getfd(2), pidfd_open(2), pipe(2), shmget(2), signalfd(2), socket(2), socketpair(2), spu_create(2), swapon(2), timerfd_create(2), uselib(2), userfaultfd(2) +syscon errno EMFILE 24 24 24 24 24 336 # too many open files; unix consensus; kNtErrorTooManyOpenFiles; raised by accept(2), dup(2), epoll_create(2), eventfd(2), execve(2), fanotify_init(2), fcntl(2), inotify_init(2), memfd_create(2), mount(2), open(2), perf_event_open(2), pidfd_getfd(2), pidfd_open(2), pipe(2), signalfd(2), socket(2), socketpair(2), spu_create(2), timerfd_create(2) +syscon errno ENOTTY 25 25 25 25 25 1118 # inappropriate i/o control operation; unix consensus; kNtErrorSerialNoDevice; raised by ioctl(2), ioctl_console(2), ioctl_fat(2), ioctl_ns(2), ioctl_tty(2) +syscon errno ETXTBSY 26 26 26 26 26 148 # won't open executable that's executing in write mode; try UnlockExecutable(); unix consensus; kNtErrorPathBusy; raised by access(2), copy_file_range(2), execve(2), fallocate(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), mmap(2), open(2), truncate(2) +syscon errno EFBIG 27 27 27 27 27 223 # file too large; unix consensus; kNtErrorFileTooLarge; raised by copy_file_range(2), fallocate(2), init_module(2), open(2), semop(2), truncate(2), write(2) +syscon errno ENOSPC 28 28 28 28 28 39 # no space left on device; unix consensus; kNtErrorDiskFull; raised by copy_file_range(2), epoll_ctl(2), fallocate(2), fanotify_mark(2), fsync(2), inotify_add_watch(2), link(2), mkdir(2), mknod(2), msgget(2), open(2), perf_event_open(2), pkey_alloc(2), query_module(2), rename(2), semget(2), setxattr(2), shmget(2), spu_create(2), symlink(2), sync_file_range(2), write(2) +syscon errno EDQUOT 122 69 69 69 69 0x2755 # disk quota exceeded; bsd consensus; raised by add_key(2), keyctl(2), link(2), mkdir(2), mknod(2), open(2), rename(2), request_key(2), setxattr(2), symlink(2), write(2) +syscon errno ESPIPE 29 29 29 29 29 25 # invalid seek; unix consensus; kNtErrorSeek; raised by fallocate(2), lseek(2), posix_fadvise(2), sendfile(2), splice(2), sync_file_range(2) +syscon errno EROFS 30 30 30 30 30 6009 # read-only filesystem; unix consensus; kNtErrorFileReadOnly; raised by access(2), acct(2), bind(2), chmod(2), chown(2), link(2), mkdir(2), mknod(2), mount(2), open(2), rename(2), rmdir(2), symlink(2), truncate(2), unlink(2), utime(2), utimensat(2) +syscon errno EMLINK 31 31 31 31 31 4 # too many links; unix consensus; kNtErrorTooManyLinks; raised by link(2), mkdir(2), rename(2) +syscon errno EPIPE 32 32 32 32 32 109 # broken pipe; unix consensus; kNtErrorBrokenPipe; raised by send(2), write(2), tcp(7), unix(7), ip(7) +syscon errno EDOM 33 33 33 33 33 33 # mathematics argument out of domain of function; bsd consensus; fudged on NT; returned by cos(3), fmod(3), log1p(3), sin(3), tan(3), tgamma(3) +syscon errno ERANGE 34 34 34 34 34 34 # result too large; bsd consensus; fudged on NT; raised by getxattr(2), listxattr(2), lookup_dcookie(2), prctl(2), quotactl(2), semctl(2), semop(2), setxattr(2) +syscon errno EDEADLK 35 11 11 11 11 1131 # resource deadlock avoided; bsd consensus; kNtErrorPossibleDeadlock; raised by fcntl(2), keyctl(2) +syscon errno ENAMETOOLONG 36 63 63 63 63 0x274f # filename too long; bsd consensus; WSAENAMETOOLONG; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), execve(2), gethostname(2), inotify_add_watch(2), link(2), lookup_dcookie(2), mkdir(2), mknod(2), mount(2), open(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), umount(2), unlink(2), utimensat(2) +syscon errno ENOLCK 37 77 77 77 77 0 # no locks available; bsd consensus; raised by fcntl(2), flock(2) +syscon errno ENOTEMPTY 39 66 66 66 66 145 # directory not empty; bsd consensus; kNtErrorDirNotEmpty (TODO: What is WSAENOTEMPTY? 0x2752); raised by rmdir(2) +syscon errno ELOOP 40 62 62 62 62 0x274e # too many levels of symbolic links; bsd consensus; WSAELOOP; raised by access(2), acct(2), bind(2), chdir(2), chmod(2), chown(2), chroot(2), epoll_ctl(2), execve(2), execveat(2), keyctl(2), link(2), mkdir(2), mknod(2), mount(2), open(2), open_by_handle_at(2), openat2(2), readlink(2), rename(2), rmdir(2), spu_create(2), stat(2), statfs(2), statx(2), symlink(2), truncate(2), unlink(2), utimensat(2) +syscon errno ENOMSG 42 91 83 90 83 0 # raised by msgop(2) +syscon errno EIDRM 43 90 82 89 82 0 # identifier removed; raised by msgctl(2), msgget(2), msgop(2), semctl(2), semop(2), shmctl(2), shmget(2), shmop(2) +syscon errno ETIME 62 101 60 60 92 0 # timer expired; timer expired; raised by connect(2), futex(2), keyctl(2), mq_receive(2), mq_send(2), rtime(2), sem_wait(2) +syscon errno EPROTO 71 100 92 95 96 0 # raised by accept(2), connect(2), socket(2), socketpair(2) +syscon errno EOVERFLOW 75 84 84 87 84 0 # raised by aio_read(2), copy_file_range(2), ctime(2), fanotify_init(2), lseek(2), mmap(2), open(2), open_by_handle_at(2), sem_post(2), sendfile(2), shmctl(2), stat(2), statfs(2), statvfs(2), time(2), timegm(2) +syscon errno EILSEQ 84 92 86 84 85 0 # returned by fgetwc(3), fputwc(3), getwchar(3), putwchar(3), scanf(3), ungetwc(3) +syscon errno EUSERS 87 68 68 68 68 0x2754 # too many users; bsd consensus; WSAEUSERS; raised by acct(2) +syscon errno ENOTSOCK 88 38 38 38 38 0x2736 # not a socket; bsd consensus; WSAENOTSOCK; raised by accept(2), bind(2), connect(2), getpeername(2), getsockname(2), getsockopt(2), listen(2), recv(2), send(2), shutdown(2) +syscon errno EDESTADDRREQ 89 39 39 39 39 0x2737 # destination address required; bsd consensus; WSAEDESTADDRREQ; raised by send(2), write(2) +syscon errno EMSGSIZE 90 40 40 40 40 0x2738 # message too long; bsd consensus; WSAEMSGSIZE; raised by keyctl(2), send(2), ip(7) +syscon errno EPROTOTYPE 91 41 41 41 41 0x2739 # protocol wrong type for socket; bsd consensus; WSAEPROTOTYPE; raised by connect(2), unix(7) +syscon errno ENOPROTOOPT 92 42 42 42 42 0x273a # protocol not available; bsd consensus; WSAENOPROTOOPT; raised by getsockopt(2), accept(2), ip(7) +syscon errno EPROTONOSUPPORT 93 43 43 43 43 0x273b # protocol not supported; bsd consensus; WSAEPROTONOSUPPORT; raised by socket(2), socketpair(2), unix(7) +syscon errno ESOCKTNOSUPPORT 94 44 44 44 44 0x273c # socket type not supported; bsd consensus; WSAESOCKTNOSUPPORT; raised by unix(7), ip(7) +syscon errno ENOTSUP 95 45 45 91 86 0x273d # operation not supported; raised by chmod(2), clock_getres(2), clock_nanosleep(2), getxattr(2), listxattr(2), removexattr(2), setxattr(2), timer_create(2) +syscon errno EOPNOTSUPP 95 102 45 45 45 0x273d # socket operation not supported; raised by accept(2), fallocate(2), fanotify_mark(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_getfsmap(2), keyctl(2), listen(2), mmap(2), open_by_handle_at(2), pciconfig_read(2), perf_event_open(2), prctl(2), readv(2), s390_guarded_storage(2), s390_runtime_instr(2), s390_sthyi(2), send(2), socketpair(2), unix(7), ip(7) +syscon errno EPFNOSUPPORT 96 46 46 46 46 0x273e # protocol family not supported; bsd consensus; WSAEPFNOSUPPORT +syscon errno EAFNOSUPPORT 97 47 47 47 47 0x273f # address family not supported; bsd consensus; WSAEAFNOSUPPORT; raised by connect(2), socket(2), socketpair(2), tcp(7) +syscon errno EADDRINUSE 98 48 48 48 48 0x2740 # address already in use; bsd consensus; WSAEADDRINUSE; raised by bind(2), connect(2), listen(2), unix(7), ip(7) +syscon errno EADDRNOTAVAIL 99 49 49 49 49 0x2741 # address not available; bsd consensus; WSAEADDRNOTAVAIL; raised by bind(2), connect(2), kexec_load(2), ip(7) +syscon errno ENETDOWN 100 50 50 50 50 0x2742 # network is down; bsd consensus; WSAENETDOWN; raised by accept(2) +syscon errno ENETUNREACH 101 51 51 51 51 0x2743 # host is unreachable; bsd consensus; WSAENETUNREACH; raised by accept(2), connect(2) +syscon errno ENETRESET 102 52 52 52 52 0x2744 # connection reset by network; bsd consensus; WSAENETRESET +syscon errno ECONNABORTED 103 53 53 53 53 0x2745 # connection reset before accept; bsd consensus; WSAECONNABORTED; raised by accept(2) +syscon errno ECONNRESET 104 54 54 54 54 0x2746 # connection reset by client; bsd consensus; WSAECONNRESET; raised by send(2), unix(7) +syscon errno ENOBUFS 105 55 55 55 55 0x2747 # no buffer space available; bsd consensus; WSAENOBUFS; raised by getpeername(2), getsockname(2), send(2), ip(7) +syscon errno EISCONN 106 56 56 56 56 0x2748 # socket is connected; bsd consensus; WSAEISCONN; raised by connect(2), send(2), unix(7), ip(7) +syscon errno ENOTCONN 107 57 57 57 57 0x2749 # socket is not connected; bsd consensus; WSAENOTCONN; raised by getpeername(2), recv(2), send(2), shutdown(2), ip(7) +syscon errno ESHUTDOWN 108 58 58 58 58 0x274a # cannot send after transport endpoint shutdown; note that shutdown write is an EPIPE; bsd consensus; WSAESHUTDOWN +syscon errno ETOOMANYREFS 109 59 59 59 59 0x274b # too many references: cannot splice; bsd consensus; WSAETOOMANYREFS; raised by sendmsg(2), unix(7) +syscon errno ETIMEDOUT 110 60 60 60 60 0x274c # connection timed out; bsd consensus; WSAETIMEDOUT; raised by connect(2), futex(2), keyctl(2), tcp(7) +syscon errno ECONNREFUSED 111 61 61 61 61 0x274d # bsd consensus; WSAECONNREFUSED; raised by connect(2), listen(2), recv(2), unix(7), udp(7)system-imposed limit on the number of threads was encountered. +syscon errno EHOSTDOWN 112 64 64 64 64 0x2750 # bsd consensus; WSAEHOSTDOWN; raised by accept(2) +syscon errno EHOSTUNREACH 113 65 65 65 65 0x2751 # bsd consensus; WSAEHOSTUNREACH; raised by accept(2), ip(7) +syscon errno EALREADY 114 37 37 37 37 0x2735 # connection already in progress; bsd consensus; WSAEALREADY; raised by connect(2), send(2), ip(7) +syscon errno EINPROGRESS 115 36 36 36 36 0x2734 # bsd consensus; WSAEINPROGRESS; raised by connect(2) w/ O_NONBLOCK +syscon errno ESTALE 116 70 70 70 70 0x2756 # bsd consensus; WSAESTALE; raised by open_by_handle_at(2) syscon errno EREMOTE 66 71 71 71 71 0x2757 # bsd consensus -syscon errno ENOLINK 67 97 91 0 95 0 -syscon errno EADV 68 0 0 0 0 0 # bsd consensus -syscon errno ESRMNT 69 0 0 0 0 0 # bsd consensus -syscon errno ECOMM 70 0 0 0 0 0 # bsd consensus -syscon errno EPROTO 71 100 92 95 96 0 -syscon errno EMULTIHOP 72 95 90 0 94 0 -syscon errno EDOTDOT 73 0 0 0 0 0 # bsd consensus -syscon errno EBADMSG 74 94 89 92 88 0 -syscon errno EOVERFLOW 75 84 84 87 84 0 -syscon errno ENOTUNIQ 76 0 0 0 0 0 # bsd consensus -syscon errno EBADFD 77 9 9 9 9 6 # file descriptor in bad state; cf. EBADF; fudged on non-Linux -syscon errno EREMCHG 78 0 0 0 0 0 # bsd consensus -syscon errno ELIBACC 79 0 0 0 0 0 # bsd consensus -syscon errno ELIBBAD 80 0 0 0 0 0 # bsd consensus -syscon errno ELIBSCN 81 0 0 0 0 0 # bsd consensus -syscon errno ELIBMAX 82 0 0 0 0 0 # bsd consensus -syscon errno ELIBEXEC 83 0 0 0 0 0 # bsd consensus -syscon errno EILSEQ 84 92 86 84 85 0 -syscon errno ERESTART 85 0 0 0 -3 0 # bsd consensus -syscon errno ESTRPIPE 86 0 0 0 0 0 # bsd consensus -syscon errno EUCLEAN 117 0 0 0 0 0 # bsd consensus -syscon errno ENOTNAM 118 0 0 0 0 0 # bsd consensus -syscon errno ENAVAIL 119 0 0 0 0 0 # bsd consensus -syscon errno EISNAM 120 0 0 0 0 0 # bsd consensus -syscon errno EREMOTEIO 121 0 0 0 0 0 # bsd consensus -syscon errno ENOMEDIUM 123 0 0 85 85 0 -syscon errno EMEDIUMTYPE 124 0 0 86 86 0 -syscon errno ECANCELED 125 89 85 88 87 0 -syscon errno ENOKEY 126 0 0 0 0 0 # bsd consensus -syscon errno EKEYEXPIRED 127 0 0 0 0 0 # bsd consensus -syscon errno EKEYREVOKED 128 0 0 0 0 0 # bsd consensus -syscon errno EKEYREJECTED 129 0 0 0 0 0 # bsd consensus -syscon errno EOWNERDEAD 130 105 96 94 97 0 -syscon errno ENOTRECOVERABLE 131 104 95 93 98 0 -syscon errno ERFKILL 132 0 0 0 0 0 # bsd consensus -syscon errno EHWPOISON 133 0 0 0 0 0 # bsd consensus +syscon errno EBADMSG 74 94 89 92 88 0 # raised by ioctl_getfsmap(2) +syscon errno ECANCELED 125 89 85 88 87 0 # raised by timerfd_create(2) +syscon errno EOWNERDEAD 130 105 96 94 97 0 # raised by pthread_cond_timedwait(3), pthread_mutex_consistent(3), pthread_mutex_getprioceiling(3), pthread_mutex_lock(3), pthread_mutex_timedlock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3) +syscon errno ENOTRECOVERABLE 131 104 95 93 98 0 # raised by pthread_cond_timedwait(3), pthread_mutex_consistent(3), pthread_mutex_getprioceiling(3), pthread_mutex_lock(3), pthread_mutex_timedlock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3) +syscon errno ENONET 64 0 0 0 0 0 # bsd consensus; raised by accept(2) +syscon errno ERESTART 85 0 0 0 -3 0 # bsd consensus; should only be seen in ptrace() +syscon junkerr ECHRNG 44 0 0 0 0 0 # bsd consensus +syscon junkerr EL2NSYNC 45 0 0 0 0 0 # bsd consensus +syscon junkerr EL3HLT 46 0 0 0 0 0 # bsd consensus +syscon junkerr EL3RST 47 0 0 0 0 0 # bsd consensus +syscon junkerr ELNRNG 48 0 0 0 0 0 # bsd consensus +syscon junkerr EUNATCH 49 0 0 0 0 0 # bsd consensus +syscon junkerr ENOCSI 50 0 0 0 0 0 # bsd consensus +syscon junkerr EL2HLT 51 0 0 0 0 0 # bsd consensus +syscon junkerr EBADE 52 0 0 0 0 0 # bsd consensus +syscon junkerr EBADR 53 0 0 0 0 0 # bsd consensus +syscon junkerr EXFULL 54 0 0 0 0 0 # bsd consensus +syscon junkerr ENOANO 55 0 0 0 0 0 # bsd consensus +syscon junkerr EBADRQC 56 0 0 0 0 0 # bsd consensus +syscon junkerr EBADSLT 57 0 0 0 0 0 # bsd consensus +syscon junkerr ENOSTR 60 99 0 0 91 0 # +syscon junkerr ENODATA 61 96 0 0 89 0 # raised by getxattr(2), removexattr(2), setxattr(2) +syscon junkerr ENOSR 63 98 0 0 90 0 # +syscon junkerr ENOPKG 65 0 0 0 0 0 # bsd consensus, ip(7) +syscon junkerr ENOLINK 67 97 91 0 95 0 # +syscon junkerr EADV 68 0 0 0 0 0 # bsd consensus +syscon junkerr ESRMNT 69 0 0 0 0 0 # bsd consensus +syscon junkerr ECOMM 70 0 0 0 0 0 # bsd consensus +syscon junkerr EMULTIHOP 72 95 90 0 94 0 # +syscon junkerr EDOTDOT 73 0 0 0 0 0 # bsd consensus +syscon junkerr ENOTUNIQ 76 0 0 0 0 0 # bsd consensus +syscon junkerr EREMCHG 78 0 0 0 0 0 # bsd consensus +syscon junkerr ELIBACC 79 0 0 0 0 0 # bsd consensus +syscon junkerr ELIBBAD 80 0 0 0 0 0 # bsd consensus +syscon junkerr ELIBSCN 81 0 0 0 0 0 # bsd consensus +syscon junkerr ELIBMAX 82 0 0 0 0 0 # bsd consensus +syscon junkerr ELIBEXEC 83 0 0 0 0 0 # bsd consensus +syscon junkerr ESTRPIPE 86 0 0 0 0 0 # bsd consensus +syscon junkerr EUCLEAN 117 0 0 0 0 0 # bsd consensus +syscon junkerr ENOTNAM 118 0 0 0 0 0 # bsd consensus +syscon junkerr ENAVAIL 119 0 0 0 0 0 # bsd consensus +syscon junkerr EISNAM 120 0 0 0 0 0 # bsd consensus +syscon junkerr EREMOTEIO 121 0 0 0 0 0 # bsd consensus +syscon junkerr ENOMEDIUM 123 0 0 85 85 0 # +syscon junkerr EMEDIUMTYPE 124 0 0 86 86 0 # +syscon junkerr ENOKEY 126 0 0 0 0 0 # bsd consensus +syscon junkerr EKEYEXPIRED 127 0 0 0 0 0 # bsd consensus +syscon junkerr EKEYREVOKED 128 0 0 0 0 0 # bsd consensus +syscon junkerr EKEYREJECTED 129 0 0 0 0 0 # bsd consensus +syscon junkerr ERFKILL 132 0 0 0 0 0 # bsd consensus +syscon junkerr EHWPOISON 133 0 0 0 0 0 # bsd consensus +syscon junkerr EBADFD 77 9 9 9 9 6 # file descriptor in bad state; cf. EBADF; fudged on non-Linux +syscon compat EWOULDBLOCK 11 35 35 35 35 0x2733 # same as EWOULDBLOCK # signals # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon sig SIGHUP 1 1 1 1 1 1 # unix consensus & faked on nt -syscon sig SIGINT 2 2 2 2 2 2 # unix consensus & faked on nt -syscon sig SIGQUIT 3 3 3 3 3 3 # unix consensus & faked on nt -syscon sig SIGILL 4 4 4 4 4 4 # unix consensus & faked on nt -syscon sig SIGTRAP 5 5 5 5 5 5 # unix consensus & faked on nt -syscon sig SIGABRT 6 6 6 6 6 6 # unix consensus & faked on nt -syscon sig SIGIOT 6 6 6 6 6 6 # unix consensus & faked on nt -syscon sig SIGFPE 8 8 8 8 8 8 # unix consensus & faked on nt -syscon sig SIGKILL 9 9 9 9 9 9 # unix consensus & faked on nt -syscon sig SIGSEGV 11 11 11 11 11 11 # unix consensus & faked on nt -syscon sig SIGPIPE 13 13 13 13 13 13 # unix consensus & faked on nt -syscon sig SIGALRM 14 14 14 14 14 14 # unix consensus & faked on nt -syscon sig SIGTERM 15 15 15 15 15 15 # unix consensus & faked on nt -syscon sig SIGTTIN 21 21 21 21 21 21 # unix consensus & faked on nt -syscon sig SIGTTOU 22 22 22 22 22 22 # unix consensus & faked on nt -syscon sig SIGXCPU 24 24 24 24 24 24 # unix consensus & faked on nt -syscon sig SIGXFSZ 25 25 25 25 25 25 # unix consensus & faked on nt -syscon sig SIGVTALRM 26 26 26 26 26 26 # unix consensus & faked on nt -syscon sig SIGPROF 27 27 27 27 27 27 # unix consensus & faked on nt -syscon sig SIGWINCH 28 28 28 28 28 28 # unix consensus & faked on nt -syscon sig SIGBUS 7 10 10 10 10 7 # bsd consensus -syscon sig SIGUSR1 10 30 30 30 30 10 # bsd consensus -syscon sig SIGCHLD 17 20 20 20 20 17 # bsd consensus -syscon sig SIGCONT 18 19 19 19 19 18 # bsd consensus +syscon sig SIGHUP 1 1 1 1 1 1 # terminal hangup or daemon reload; resumable; auto-broadcasted to process group; unix consensus & faked on nt +syscon sig SIGINT 2 2 2 2 2 2 # terminal ctrl-c keystroke; resumable; auto-broadcasted to process group; unix consensus & faked on nt +syscon sig SIGQUIT 3 3 3 3 3 3 # terminal ctrl-\ keystroke; resumable; unix consensus & faked on nt +syscon sig SIGILL 4 4 4 4 4 4 # illegal instruction; unresumable (unless you longjmp() or edit ucontex->rip+=ild(ucontex->rip)); unix consensus & faked on nt +syscon sig SIGTRAP 5 5 5 5 5 5 # int3 instruction; resumable; unix consensus & faked on nt +syscon sig SIGABRT 6 6 6 6 6 6 # process aborted; resumable; unix consensus & faked on nt +syscon sig SIGBUS 7 10 10 10 10 7 # valid memory access that went beyond underlying end of file; bsd consensus +syscon sig SIGFPE 8 8 8 8 8 8 # illegal math; unresumable (unless you longjmp() or edit ucontex->rip+=ild(ucontex->rip)); unix consensus & faked on nt +syscon sig SIGKILL 9 9 9 9 9 9 # terminate with extreme prejudice; unreceivable; unix consensus & faked on nt +syscon sig SIGUSR1 10 30 30 30 30 10 # do whatever you want; bsd consensus +syscon sig SIGSEGV 11 11 11 11 11 11 # invalid memory access; unresumable (unless you longjmp() or edit ucontex->rip+=ild(ucontex->rip)); unix consensus & faked on nt +syscon sig SIGUSR2 12 31 31 31 31 12 # do whatever you want; bsd consensus +syscon sig SIGPIPE 13 13 13 13 13 13 # write to closed file descriptor; unix consensus & faked on nt +syscon sig SIGALRM 14 14 14 14 14 14 # sent by setitimer(2) or timer_settime(2); unix consensus & faked on nt +syscon sig SIGTERM 15 15 15 15 15 15 # terminate; resumable; unix consensus & faked on nt +syscon sig SIGCHLD 17 20 20 20 20 17 # child process exited or terminated and is now a zombie (unless this is SIG_IGN or SA_NOCLDWAIT) or child process stopped due to terminal i/o or profiling/debugging (unless you used SA_NOCLDSTOP); bsd consensus +syscon sig SIGCONT 18 19 19 19 19 18 # child process resumed from profiling/debugging; bsd consensus +syscon sig SIGSTOP 19 17 17 17 17 19 # child process stopped due to profiling/debugging; bsd consensus +syscon sig SIGTSTP 20 18 18 18 18 20 # terminal ctrl-z keystroke; bsd consensus +syscon sig SIGTTIN 21 21 21 21 21 21 # terminal input for background process; resumable; unix consensus & faked on nt +syscon sig SIGTTOU 22 22 22 22 22 22 # terminal output for background process; resumable; unix consensus & faked on nt +syscon sig SIGURG 23 16 16 16 16 23 # bsd consensus +syscon sig SIGXCPU 24 24 24 24 24 24 # cpu time limit exceeded; unix consensus & faked on nt +syscon sig SIGXFSZ 25 25 25 25 25 25 # file size limit exceeded; unix consensus & faked on nt +syscon sig SIGVTALRM 26 26 26 26 26 26 # virtual alarm clock; wut; unix consensus & faked on nt +syscon sig SIGPROF 27 27 27 27 27 27 # profiling timer expired; unix consensus & faked on nt +syscon sig SIGWINCH 28 28 28 28 28 28 # terminal resized; unix consensus & faked on nt syscon sig SIGIO 29 23 23 23 23 29 # bsd consensus -syscon sig SIGSTOP 19 17 17 17 17 19 # bsd consensus -syscon sig SIGSYS 31 12 12 12 12 31 # bsd consensus -syscon sig SIGTSTP 20 18 18 18 18 20 # bsd consensus -syscon sig SIGURG 23 0x10 0x10 0x10 0x10 23 # bsd consensus -syscon sig SIGUSR2 12 31 31 31 31 12 # bsd consensus -syscon sig SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x7000 0x2000 -syscon sig SIGPOLL 29 0 0 0 0 29 -syscon sig SIGPWR 30 0 0 0 32 30 -syscon sig SIGSTKFLT 0x10 0 0 0 0 0x10 -syscon sig SIGUNUSED 31 0 0 0 0 31 +syscon sig SIGSYS 31 12 12 12 12 31 # wut; bsd consensus syscon sig SIGRTMAX 0 0 126 0 63 0 syscon sig SIGRTMIN 0 0 65 0 33 0 +syscon compat SIGPOLL 29 23 23 23 23 29 # same as SIGIO +syscon compat SIGIOT 6 6 6 6 6 6 # PDP-11 feature; same as SIGABRT +syscon compat SIGPWR 30 30 30 30 32 30 # not implemented in most community editions of system five; consider doing this using SIGUSR1 or SIGUSR2 instead # open() flags ┌──────hoo boy # ┌──────┐ @@ -232,6 +228,10 @@ syscon open O_EXEC 0 0 0x040000 0 0x4000000 0 syscon open O_TTY_INIT 0 0 0x080000 0 0 0 syscon compat O_LARGEFILE 0 0 0 0 0 0 +# mmap() flags +# the revolutionary praxis of malloc() +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon compat MAP_FILE 0 0 0 0 0 0 # consensus syscon mmap MAP_SHARED 1 1 1 1 1 1 # forced consensus & faked nt syscon mmap MAP_PRIVATE 2 2 2 2 2 2 # forced consensus & faked nt @@ -254,6 +254,10 @@ syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 0 # ignored syscon compat MAP_DENYWRITE 0x0800 0 0 0 0 0 syscon compat MAP_32BIT 0x40 0 0x080000 0 0 0 # iffy +# madvise() flags +# beneath the iceberg memory management +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon madv MADV_NORMAL 0 0 0 0 0 0x00000080 # consensus & kNtFileAttributeNormal syscon compat POSIX_FADV_NORMAL 0 0 0 0 0 0x00000080 # consensus & kNtFileAttributeNormal syscon compat POSIX_MADV_NORMAL 0 0 0 0 0 0x00000080 # consensus & kNtFileAttributeNormal @@ -276,7 +280,7 @@ syscon madv MADV_HUGEPAGE 14 0 0 0 0 0 # TODO(jart): why would we syscon madv MADV_NOHUGEPAGE 15 0 0 0 0 0 # TODO(jart): why would we need it? syscon madv MADV_DODUMP 17 0 0 0 0 0 # TODO(jart): what is it? syscon madv MADV_DOFORK 11 0 0 0 0 0 # TODO(jart): what is it? -syscon madv MADV_DONTDUMP 0x10 0 0 0 0 0 # TODO(jart): what is it? +syscon madv MADV_DONTDUMP 16 0 0 0 0 0 # TODO(jart): what is it? syscon madv MADV_DONTFORK 10 0 0 0 0 0 # TODO(jart): what is it? syscon madv MADV_HWPOISON 100 0 0 0 0 0 # TODO(jart): what is it? syscon madv MADV_REMOVE 9 0 0 0 0 0 # TODO(jart): what is it? @@ -293,9 +297,16 @@ syscon mprot PROT_EXEC 4 4 4 4 4 4 # mmap, mprotect, unix consens syscon mprot PROT_GROWSDOWN 0x01000000 0 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap() (todo: what was 0x01000000 on nt) syscon mprot PROT_GROWSUP 0x02000000 0 0 0 0 0 # intended for mprotect; see MAP_GROWSDOWN for mmap() +# mremap() flags +# the revolutionary praxis of realloc() +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon mremap MREMAP_MAYMOVE 1 1 1 1 1 1 # faked non-linux (b/c linux only) syscon mremap MREMAP_FIXED 2 2 2 2 2 2 # faked non-linux (b/c linux only) +# splice() flags +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon splice SPLICE_F_MOVE 1 0 0 0 0 0 # can be safely ignored by polyfill; it's a hint syscon splice SPLICE_F_NONBLOCK 2 0 0 0 0 0 # can be safely ignored by polyfill, since linux says it doesn't apply to underlying FDs syscon splice SPLICE_F_MORE 4 0 0 0 0 0 # can be safely ignored by polyfill; it's a hint @@ -320,7 +331,7 @@ syscon lock LOCK_UN 8 8 8 8 8 8 # unlock [unix consensus & faked # waitpid() / wait4() options # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon waitpid WNOHANG 1 1 1 1 1 0 # unix consensus +syscon waitpid WNOHANG 1 1 1 1 1 0 # helps you reap zombies; unix consensus syscon waitpid WUNTRACED 2 2 2 2 2 0 # unix consensus syscon waitpid WCONTINUED 8 0x10 4 8 16 0 @@ -334,41 +345,32 @@ syscon waitid WNOWAIT 0x01000000 0x20 8 0 0x10000 0 # stat::st_mode constants # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon stat S_IFREG 0100000 0100000 0100000 0100000 0100000 0100000 -syscon stat S_IFBLK 0060000 0060000 0060000 0060000 0060000 0060000 -syscon stat S_IFCHR 0020000 0020000 0020000 0020000 0020000 0020000 -syscon stat S_IFDIR 0040000 0040000 0040000 0040000 0040000 0040000 -syscon stat S_IFIFO 0010000 0010000 0010000 0010000 0010000 0010000 -syscon stat S_IFMT 0170000 0170000 0170000 0170000 0170000 0170000 -syscon stat S_IFLNK 0120000 0120000 0120000 0120000 0120000 0120000 -syscon stat S_IFSOCK 0140000 0140000 0140000 0140000 0140000 0140000 - -# chmod() permission flag constants -# consider just typing the octal codes -# -# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon stat S_ISVTX 01000 01000 01000 01000 01000 01000 # unix consensus STICKY BIT -syscon stat S_ISGID 02000 02000 02000 02000 02000 02000 # unix consensus a.k.a. setgid bit -syscon stat S_ISUID 04000 04000 04000 04000 04000 04000 # unix consensus a.k.a. setuid bit - -syscon stat S_IEXEC 00100 00100 00100 00100 00100 00100 # unix consensus -syscon stat S_IWRITE 00200 00200 00200 00200 00200 00200 # unix consensus -syscon stat S_IREAD 00400 00400 00400 00400 00400 00400 # unix consensus - -syscon stat S_IXUSR 00100 00100 00100 00100 00100 00100 # unix consensus -syscon stat S_IWUSR 00200 00200 00200 00200 00200 00200 # unix consensus -syscon stat S_IRUSR 00400 00400 00400 00400 00400 00400 # unix consensus -syscon stat S_IRWXU 00700 00700 00700 00700 00700 00700 # unix consensus - -syscon stat S_IXGRP 00010 00010 00010 00010 00010 00010 # unix consensus -syscon stat S_IWGRP 00020 00020 00020 00020 00020 00020 # unix consensus -syscon stat S_IRGRP 00040 00040 00040 00040 00040 00040 # unix consensus -syscon stat S_IRWXG 00070 00070 00070 00070 00070 00070 # unix consensus - -syscon stat S_IXOTH 00001 00001 00001 00001 00001 00001 # unix consensus -syscon stat S_IWOTH 00002 00002 00002 00002 00002 00002 # unix consensus -syscon stat S_IROTH 00004 00004 00004 00004 00004 00004 # unix consensus -syscon stat S_IRWXO 00007 00007 00007 00007 00007 00007 # unix consensus +syscon stat S_IFREG 0100000 0100000 0100000 0100000 0100000 0100000 # regular file (unix consensus; faked nt) +syscon stat S_IFBLK 0060000 0060000 0060000 0060000 0060000 0060000 # block device (unix consensus; faked nt) +syscon stat S_IFCHR 0020000 0020000 0020000 0020000 0020000 0020000 # character device (unix consensus; faked nt) +syscon stat S_IFDIR 0040000 0040000 0040000 0040000 0040000 0040000 # directory (unix consensus; faked nt) +syscon stat S_IFIFO 0010000 0010000 0010000 0010000 0010000 0010000 # pipe (unix consensus; faked nt) +syscon stat S_IFLNK 0120000 0120000 0120000 0120000 0120000 0120000 # symbolic link (unix consensus; faked nt) +syscon stat S_IFSOCK 0140000 0140000 0140000 0140000 0140000 0140000 # socket (unix consensus; faked nt) +syscon stat S_IFMT 0170000 0170000 0170000 0170000 0170000 0170000 # FILE TYPE MASK (unix consensus; faked nt) +syscon stat S_ISVTX 0001000 0001000 0001000 0001000 0001000 0001000 # THE STICKY BIT (unix consensus; faked nt) +syscon stat S_ISGID 0002000 0002000 0002000 0002000 0002000 0002000 # the setgid bit (unix consensus; faked nt) +syscon stat S_ISUID 0004000 0004000 0004000 0004000 0004000 0004000 # the setuid bit (unix consensus; faked nt) +syscon stat S_IEXEC 0000100 0000100 0000100 0000100 0000100 0000100 # just use octal (unix consensus; faked nt) +syscon stat S_IWRITE 0000200 0000200 0000200 0000200 0000200 0000200 # just use octal (unix consensus; faked nt) +syscon stat S_IREAD 0000400 0000400 0000400 0000400 0000400 0000400 # just use octal (unix consensus; faked nt) +syscon stat S_IXUSR 0000100 0000100 0000100 0000100 0000100 0000100 # just use octal (unix consensus; faked nt) +syscon stat S_IWUSR 0000200 0000200 0000200 0000200 0000200 0000200 # just use octal (unix consensus; faked nt) +syscon stat S_IRUSR 0000400 0000400 0000400 0000400 0000400 0000400 # just use octal (unix consensus; faked nt) +syscon stat S_IRWXU 0000700 0000700 0000700 0000700 0000700 0000700 # just use octal (unix consensus; faked nt) +syscon stat S_IXGRP 0000010 0000010 0000010 0000010 0000010 0000010 # just use octal (unix consensus; faked nt) +syscon stat S_IWGRP 0000020 0000020 0000020 0000020 0000020 0000020 # just use octal (unix consensus; faked nt) +syscon stat S_IRGRP 0000040 0000040 0000040 0000040 0000040 0000040 # just use octal (unix consensus; faked nt) +syscon stat S_IRWXG 0000070 0000070 0000070 0000070 0000070 0000070 # just use octal (unix consensus; faked nt) +syscon stat S_IXOTH 0000001 0000001 0000001 0000001 0000001 0000001 # just use octal (unix consensus; faked nt) +syscon stat S_IWOTH 0000002 0000002 0000002 0000002 0000002 0000002 # just use octal (unix consensus; faked nt) +syscon stat S_IROTH 0000004 0000004 0000004 0000004 0000004 0000004 # just use octal (unix consensus; faked nt) +syscon stat S_IRWXO 0000007 0000007 0000007 0000007 0000007 0000007 # just use octal (unix consensus; faked nt) # fcntl() # @@ -428,17 +430,24 @@ syscon at AT_EACCESS 0x0200 0x10 0x0100 1 0x100 0 syscon at AT_SYMLINK_FOLLOW 0x0400 0x40 0x0400 4 4 0 syscon at AT_EMPTY_PATH 0x1000 0 0 0 0 0 # linux 2.6.39+; see unlink, O_TMPFILE, etc. +# memfd_create() flags +# +# Unsupported flags are encoded as 0. +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon memfd MFD_CLOEXEC 1 0 0 0 0 0 syscon memfd MFD_ALLOW_SEALING 2 0 0 0 0 0 -# utimensat() +# utimensat() special values # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon utime UTIME_NOW 0x3fffffff 0x3fffffff -1 -2 0x3fffffff -2 # polyfilled xnu/nt -syscon utime UTIME_OMIT 0x3ffffffe 0x3ffffffe -2 -1 0x3ffffffe -1 # polyfilled xnu/nt +syscon utime UTIME_NOW 0x3fffffff 0x3fffffff -1 -2 0x3fffffff -2 # timespec::tv_sec may be this; polyfilled xnu/nt +syscon utime UTIME_OMIT 0x3ffffffe 0x3ffffffe -2 -1 0x3ffffffe -1 # timespec::tv_nsec may be this; polyfilled xnu/nt # getauxval() keys # +# Unsupported values are encoded as 0. +# # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon auxv AT_EXECFD 2 0 2 0 2 0 # file descriptor of program syscon auxv AT_PHDR 3 0 3 0 3 0 # address of program headers of executable @@ -468,81 +477,121 @@ syscon auxv AT_EXECFN 31 31 999 999 2014 31 # address of string c syscon auxv AT_SYSINFO_EHDR 33 0 0 0 0 0 syscon auxv AT_NO_AUTOMOUNT 0x0800 0 0 0 0 0 -# ptrace() codes +# getrlimit() / setrlimit() resource parameter +# +# Unsupported values are encoded as 127. # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon ptrace PTRACE_TRACEME 0 0 0 0 -1 -1 # unix consensus a.k.a. PT_TRACE_ME -syscon ptrace PTRACE_PEEKTEXT 1 1 1 1 -1 -1 # unix consensus a.k.a. PT_READ_I -syscon ptrace PTRACE_PEEKDATA 2 2 2 2 -1 -1 # unix consensus a.k.a. PT_READ_D -syscon ptrace PTRACE_PEEKUSER 3 3 -1 -1 -1 -1 # a.k.a. PT_READ_U -syscon ptrace PTRACE_POKETEXT 4 4 4 4 -1 -1 # unix consensus a.k.a. PT_WRITE_I -syscon ptrace PTRACE_POKEDATA 5 5 5 5 -1 -1 # unix consensus a.k.a. PT_WRITE_D -syscon ptrace PTRACE_POKEUSER 6 6 -1 -1 -1 -1 # a.k.a. PT_WRITE_U -syscon ptrace PTRACE_CONT 7 7 7 7 -1 -1 # unix consensus a.k.a. PT_CONTINUE -syscon ptrace PTRACE_KILL 8 8 8 8 -1 -1 # unix consensus a.k.a. PT_KILL -syscon ptrace PTRACE_SINGLESTEP 9 9 9 32 -1 -1 # a.k.a. PT_STEP -syscon ptrace PTRACE_GETREGS 12 -1 33 33 -1 -1 # a.k.a. PT_GETREGS -syscon ptrace PTRACE_SETREGS 13 -1 34 34 -1 -1 # a.k.a. PT_SETREGS -syscon ptrace PTRACE_GETFPREGS 14 -1 35 35 -1 -1 # a.k.a. PT_GETFPREGS -syscon ptrace PTRACE_SETFPREGS 15 -1 36 36 -1 -1 # a.k.a. PT_SETFPREGS -syscon ptrace PTRACE_ATTACH 16 10 10 9 -1 -1 # a.k.a. PT_ATTACH -syscon ptrace PTRACE_DETACH 17 11 11 10 -1 -1 # a.k.a. PT_DETACH -syscon ptrace PTRACE_GETFPXREGS 18 -1 -1 -1 -1 -1 # a.k.a. PT_GETFPXREGS -syscon ptrace PTRACE_SETFPXREGS 19 -1 -1 -1 -1 -1 # a.k.a. PT_SETFPXREGS -syscon ptrace PTRACE_SYSCALL 24 -1 22 -1 -1 -1 # a.k.a. PT_SYSCALL -syscon ptrace PTRACE_GETEVENTMSG 0x4201 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_GETSIGINFO 0x4202 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SETOPTIONS 0x4200 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SETSIGINFO 0x4203 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_GETREGSET 0x4204 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_GETSIGMASK 0x420a -1 -1 -1 -1 -1 -syscon ptrace PTRACE_INTERRUPT 0x4207 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_LISTEN 0x4208 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_PEEKSIGINFO 0x4209 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SECCOMP_GET_FILTER 0x420c -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SEIZE 0x4206 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SETREGSET 0x4205 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_SETSIGMASK 0x420b -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACESYSGOOD 0x0001 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACEFORK 0x0002 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACEVFORK 0x0004 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACECLONE 0x0008 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACEEXEC 0x0010 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACEVFORKDONE 0x0020 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_TRACEEXIT 0x0040 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_O_MASK 0x007f -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_FORK 1 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_VFORK 2 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_CLONE 3 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_EXEC 4 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_VFORK_DONE 5 -1 -1 -1 -1 -1 -syscon ptrace PTRACE_EVENT_EXIT 6 -1 -1 -1 -1 -1 +syscon rlimit RLIMIT_CPU 0 0 0 0 0 127 # max cpu time in seconds; see SIGXCPU; unix consensus +syscon rlimit RLIMIT_FSIZE 1 1 1 1 1 127 # max file size in bytes; unix consensus +syscon rlimit RLIMIT_DATA 2 2 2 2 2 127 # max mmap() / brk() / sbrk() size in bytes; unix consensus +syscon rlimit RLIMIT_STACK 3 3 3 3 3 127 # max stack size in bytes; see SIGXFSZ; unix consensus +syscon rlimit RLIMIT_CORE 4 4 4 4 4 127 # max core file size in bytes; unix consensus +syscon rlimit RLIMIT_RSS 5 5 5 5 5 127 # max physical memory size in bytes; see mmap()→ENOMEM; unix consensus +syscon rlimit RLIMIT_NPROC 6 7 7 7 7 127 # max number of processes; see fork()→EAGAIN; bsd consensus +syscon rlimit RLIMIT_NOFILE 7 8 8 8 8 127 # max number of open files; see accept()→EMFILE/ENFILE; bsd consensus +syscon rlimit RLIMIT_MEMLOCK 8 6 6 6 6 127 # max locked-in-memory address space; bsd consensus +syscon rlimit RLIMIT_AS 9 5 10 127 10 127 # max virtual memory size in bytes +syscon rlimit RLIMIT_LOCKS 10 127 127 127 127 127 # max flock() / fcntl() locks; bsd consensus +syscon rlimit RLIMIT_SIGPENDING 11 127 127 127 127 127 # max sigqueue() can enqueue; bsd consensus +syscon rlimit RLIMIT_MSGQUEUE 12 127 127 127 127 127 # meh posix message queues; bsd consensus +syscon rlimit RLIMIT_NICE 13 127 127 127 127 127 # max scheduling priority; 𝑥 ∈ [1,40]; niceness is traditionally displayed as as 𝟸𝟶-𝑥, therefore 𝑥=1 (lowest priority) prints as 19 and 𝑥=40 (highest priority) prints as -20; bsd consensus +syscon rlimit RLIMIT_RTPRIO 14 127 127 127 127 127 # bsd consensus +syscon compat RLIMIT_VMEM 9 5 10 127 10 127 # same as RLIMIT_AS + +# resource limit special values +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary +syscon rlim RLIM_NLIMITS 16 9 15 9 12 0 # no clue why we need it +syscon rlim RLIM_INFINITY 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0 +syscon rlim RLIM_SAVED_CUR 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0 +syscon rlim RLIM_SAVED_MAX 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0 # sigaction() codes # # group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary -syscon sigact SA_RESTORER 0x04000000 0 0 0 0 0 -syscon sigact SA_ONSTACK 0x08000000 1 1 1 1 0 # bsd consensus -syscon sigact SA_RESTART 0x10000000 2 2 2 2 0 # bsd consensus -syscon sigact SA_NOCLDSTOP 1 8 8 8 8 0 # bsd consensus -syscon sigact SA_NOCLDWAIT 2 0x20 0x20 0x20 0x20 0 # bsd consensus -syscon sigact SA_SIGINFO 4 0x40 0x40 0x40 0x40 0 # bsd consensus -syscon sigact SA_NODEFER 0x40000000 0x10 0x10 0x10 0x10 0 # bsd consensus -syscon sigact SA_NOMASK 0x40000000 0x10 0x10 0x10 0x10 0 # linux/obsolete -syscon sigact SA_RESETHAND 0x80000000 4 4 4 4 0 # bsd consensus -syscon sigact SA_ONESHOT 0x80000000 0 0 0 0 0 +syscon sigact SA_NOCLDSTOP 1 8 8 8 8 1 # lets you set SIGCHLD handler that's only notified on exit/termination and not notified on SIGSTOP/SIGTSTP/SIGTTIN/SIGTTOU/SIGCONT lool; bsd consensus +syscon sigact SA_NOCLDWAIT 2 32 32 32 32 2 # changes SIGCHLD so the zombie is gone and you can't call wait(2) anymore; similar to SIGCHLD+SIG_IGN but may still deliver the SIGCHLD; bsd consensus +syscon sigact SA_SIGINFO 4 64 64 64 64 4 # asks kernel to provide ucontext_t argument, which has mutable cpu/fpu state of signalled process; and it is polyfilled by cosmopolitan; bsd consensus +syscon sigact SA_ONSTACK 0x08000000 1 1 1 1 0x08000000 # causes signal handler to be called on stack provided by sigaltstack(2); bsd consensus +syscon sigact SA_RESTART 0x10000000 2 2 2 2 0x10000000 # prevents signal delivery from triggering EINTR on i/o calls (e.g. read/write/open/wait/accept) but doesn't impact non-i/o blocking calls (e.g. poll, sigsuspend, nanosleep) which will still EINTR; bsd consensus +syscon sigact SA_NODEFER 0x40000000 16 16 16 16 0x40000000 # blocks signal delivery during signal handling (i.e. lets you use longjmp() in the signal handler); bsd consensus +syscon sigact SA_RESETHAND 0x80000000 4 4 4 4 0x80000000 # causes signal handler to be called at most once and then set to SIG_DFL automatically; bsd consensus +syscon compat SA_NOMASK 0x40000000 16 16 16 16 0x40000000 # same as SA_NODEFER +syscon compat SA_ONESHOT 0x80000000 4 4 4 4 0x80000000 # same as SA_RESETHAND +# siginfo::si_code values +# +# Windows NT is polyfilled as Linux. +# Unsupported values are encoded as 0x80000000. +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary +syscon sicode SI_USER 0 0x010001 0x010001 0 0 0 # sent by kill(2); openbsd defines si_code<=0 as originating from user +syscon sicode SI_QUEUE -1 0x010002 0x010002 -2 -1 -1 # sent by sigqueue(2) +syscon sicode SI_TIMER -2 0x010003 0x010003 -3 -2 -2 # sent by setitimer(2) or clock_settime(2) +syscon sicode SI_TKILL -6 0x80000000 0x010007 -1 -5 -6 # sent by tkill(2) or tgkill(2) or thr_kill(2) or lwp_kill(2) or _lwp_kill(2); cries +syscon sicode SI_MESGQ -3 0x010005 0x010005 0x80000000 -4 -3 # sent by mq_notify(2); lool +syscon sicode SI_ASYNCIO -4 0x010004 0x010004 0x80000000 -3 -4 # aio completion; no thank you +syscon sicode SI_ASYNCNL -60 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 # aio completion for dns; the horror +syscon sicode SI_KERNEL 0x80 0x80000000 0x010006 0x80000000 0x80000000 0x80 # wut; openbsd defines as si_code>0 +syscon sicode SI_NOINFO 32767 0x80000000 0 32767 32767 32767 # no signal specific info available +syscon sicode CLD_EXITED 1 1 1 1 1 1 # SIGCHLD; child exited; unix consensus +syscon sicode CLD_KILLED 2 2 2 2 2 2 # SIGCHLD; child terminated w/o core; unix consensus +syscon sicode CLD_DUMPED 3 3 3 3 3 3 # SIGCHLD; child terminated w/ core; unix consensus +syscon sicode CLD_TRAPPED 4 4 4 4 4 4 # SIGCHLD; traced child trapped; unix consensus +syscon sicode CLD_STOPPED 5 5 5 5 5 5 # SIGCHLD; child stopped; unix consensus +syscon sicode CLD_CONTINUED 6 6 6 6 6 6 # SIGCHLD; stopped child continued; unix consensus +syscon sicode TRAP_BRKPT 1 1 1 1 1 1 # SIGTRAP; unix consensus +syscon sicode TRAP_TRACE 2 2 2 2 2 2 # SIGTRAP; unix consensus +syscon sicode SEGV_MAPERR 1 1 1 1 1 1 # SIGSEGV; unix consensus +syscon sicode SEGV_ACCERR 2 2 2 2 2 2 # SIGSEGV; unix consensus +syscon sicode FPE_INTDIV 1 7 2 1 1 1 # SIGFPE; integer divide by zero +syscon sicode FPE_INTOVF 2 8 1 2 2 2 # SIGFPE; integer overflow +syscon sicode FPE_FLTDIV 3 1 3 3 3 3 # SIGFPE; floating point divide by zero +syscon sicode FPE_FLTOVF 4 2 4 4 4 4 # SIGFPE; floating point overflow +syscon sicode FPE_FLTUND 5 3 5 5 5 5 # SIGFPE; floating point underflow +syscon sicode FPE_FLTRES 6 4 6 6 6 6 # SIGFPE; floating point inexact +syscon sicode FPE_FLTINV 7 5 7 7 7 7 # SIGFPE; invalid floating point operation +syscon sicode FPE_FLTSUB 8 6 8 8 8 8 # SIGFPE; subscript out of range +syscon sicode ILL_ILLOPC 1 1 1 1 1 1 # SIGILL; illegal opcode; unix consensus +syscon sicode ILL_ILLOPN 2 4 2 2 2 2 # SIGILL; illegal operand +syscon sicode ILL_ILLADR 3 5 3 3 3 3 # SIGILL; illegal addressing mode +syscon sicode ILL_ILLTRP 4 2 4 4 4 4 # SIGILL; illegal trap +syscon sicode ILL_PRVOPC 5 3 5 5 5 5 # SIGILL; privileged opcode +syscon sicode ILL_PRVREG 6 6 6 6 6 6 # SIGILL; privileged register; unix consensus +syscon sicode ILL_COPROC 7 7 7 7 7 7 # SIGILL; coprocessor error; unix consensus +syscon sicode ILL_BADSTK 8 8 8 8 8 8 # SIGILL; internal stack error; unix consensus +syscon sicode BUS_ADRALN 1 1 1 1 1 1 # SIGBUS; invalid address alignment; unix consensus +syscon sicode BUS_ADRERR 2 2 2 2 2 2 # SIGBUS; non-existent physical address; unix consensus +syscon sicode BUS_OBJERR 3 3 3 3 3 3 # SIGBUS; object specific hardware error; unix consensus +syscon sicode BUS_MCEERR_AR 4 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 # SIGBUS; Linux 2.6.32+ +syscon sicode BUS_MCEERR_AO 5 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 # SIGBUS; Linux 2.6.32+ +syscon sicode POLL_IN 1 1 1 1 1 1 # SIGIO; data input available; unix consensus +syscon sicode POLL_OUT 2 2 2 2 2 2 # SIGIO; output buffer available; unix consensus +syscon sicode POLL_MSG 3 3 3 3 3 3 # SIGIO; input message available; unix consensus +syscon sicode POLL_ERR 4 4 4 4 4 4 # SIGIO; i/o error; unix consensus +syscon sicode POLL_PRI 5 5 5 5 5 5 # SIGIO; high priority input available; unix consensus +syscon sicode POLL_HUP 6 6 6 6 6 6 # SIGIO; device disconnected; unix consensus + +# sigalstack() values +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary +syscon ss SIGSTKSZ 0x2000 0x020000 0x8800 0x7000 0x7000 0x2000 + +# clock_{gettime,settime} timers +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary syscon clock CLOCK_REALTIME 0 0 0 0 0 0 # consensus -syscon clock CLOCK_MONOTONIC 1 1 4 3 3 1 # XNU/NT faked -syscon clock CLOCK_PROCESS_CPUTIME_ID 2 0 15 2 0x40000000 0 -syscon clock CLOCK_THREAD_CPUTIME_ID 3 0 14 4 0x20000000 0 -syscon clock CLOCK_MONOTONIC_RAW 4 4 0x4000 0x4000 0x4000 4 # XNU/NT/FreeBSD/OpenBSD faked, not available on RHEL5 -syscon clock CLOCK_REALTIME_COARSE 5 0 0 0 0 0 # bsd consensus -syscon clock CLOCK_MONOTONIC_COARSE 6 0 0 0 0 0 # bsd consensus -syscon clock CLOCK_BOOTTIME 7 0 0 6 6 0 -syscon clock CLOCK_REALTIME_ALARM 8 0 0 0 0 0 # bsd consensus -syscon clock CLOCK_BOOTTIME_ALARM 9 0 0 0 0 0 # bsd consensus -syscon clock CLOCK_TAI 11 0 0 0 0 0 # bsd consensus +syscon clock CLOCK_MONOTONIC 1 1 4 3 3 1 # XNU/NT faked; could move backwards if NTP introduces negative leap second +syscon clock CLOCK_PROCESS_CPUTIME_ID 2 -1 15 2 0x40000000 -1 +syscon clock CLOCK_THREAD_CPUTIME_ID 3 -1 14 4 0x20000000 -1 +syscon clock CLOCK_MONOTONIC_RAW 4 4 0x4000 0x4000 0x4000 4 # actually monotonic; not subject to NTP adjustments; Linux 2.6.28+; XNU/NT/FreeBSD/OpenBSD faked; not available on RHEL5 +syscon clock CLOCK_REALTIME_COARSE 5 -1 -1 -1 -1 -1 # Linux 2.6.32+; bsd consensus; not available on RHEL5 +syscon clock CLOCK_MONOTONIC_COARSE 6 -1 -1 -1 -1 -1 # Linux 2.6.32+; bsd consensus; not available on RHEL5 +syscon clock CLOCK_BOOTTIME 7 -1 -1 6 6 -1 +syscon clock CLOCK_REALTIME_ALARM 8 -1 -1 -1 -1 -1 # bsd consensus +syscon clock CLOCK_BOOTTIME_ALARM 9 -1 -1 -1 -1 -1 # bsd consensus +syscon clock CLOCK_TAI 11 -1 -1 -1 -1 -1 # bsd consensus # epoll # @@ -586,7 +635,7 @@ syscon so SO_OOBINLINE 10 0x0100 0x0100 0x0100 0x0100 0x0100 # bs syscon so SO_SNDBUF 7 0x1001 0x1001 0x1001 0x1001 0x1001 # bsd consensus syscon so SO_RCVBUF 8 0x1002 0x1002 0x1002 0x1002 0x1002 # bsd consensus syscon so SO_RCVLOWAT 18 0x1004 0x1004 0x1004 0x1004 0x1004 # bsd consensus -syscon so SO_RCVTIMEO 20 0x1006 0x1006 0x1006 0x100c 0x1006 # bsd consensus +syscon so SO_RCVTIMEO 20 0x1006 0x1006 0x1006 0x100c 0x1006 # overrides SA_RESTART restoring EINTR behavior on recv/send/connect/accept/etc.; bsd consensus syscon so SO_EXCLUSIVEADDRUSE 0 0 0 0 0 0xfffffffb # hoo boy syscon so SO_SNDLOWAT 19 0x1003 0x1003 0x1003 0x1003 0x1003 # bsd consensus syscon so SO_SNDTIMEO 21 0x1005 0x1005 0x1005 0x100b 0x1005 # bsd consensus @@ -699,6 +748,56 @@ syscon tcp TCP_REPAIR_OPTIONS 22 0 0 0 0 0 # what is it syscon tcp TCP_REPAIR_QUEUE 20 0 0 0 0 0 # what is it syscon tcp TCP_THIN_LINEAR_TIMEOUTS 16 0 0 0 0 0 # what is it +# ptrace() codes +# +# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary +syscon ptrace PTRACE_TRACEME 0 0 0 0 -1 -1 # unix consensus a.k.a. PT_TRACE_ME +syscon ptrace PTRACE_PEEKTEXT 1 1 1 1 -1 -1 # unix consensus a.k.a. PT_READ_I +syscon ptrace PTRACE_PEEKDATA 2 2 2 2 -1 -1 # unix consensus a.k.a. PT_READ_D +syscon ptrace PTRACE_PEEKUSER 3 3 -1 -1 -1 -1 # a.k.a. PT_READ_U +syscon ptrace PTRACE_POKETEXT 4 4 4 4 -1 -1 # unix consensus a.k.a. PT_WRITE_I +syscon ptrace PTRACE_POKEDATA 5 5 5 5 -1 -1 # unix consensus a.k.a. PT_WRITE_D +syscon ptrace PTRACE_POKEUSER 6 6 -1 -1 -1 -1 # a.k.a. PT_WRITE_U +syscon ptrace PTRACE_CONT 7 7 7 7 -1 -1 # unix consensus a.k.a. PT_CONTINUE +syscon ptrace PTRACE_KILL 8 8 8 8 -1 -1 # unix consensus a.k.a. PT_KILL +syscon ptrace PTRACE_SINGLESTEP 9 9 9 32 -1 -1 # a.k.a. PT_STEP +syscon ptrace PTRACE_GETREGS 12 -1 33 33 -1 -1 # a.k.a. PT_GETREGS +syscon ptrace PTRACE_SETREGS 13 -1 34 34 -1 -1 # a.k.a. PT_SETREGS +syscon ptrace PTRACE_GETFPREGS 14 -1 35 35 -1 -1 # a.k.a. PT_GETFPREGS +syscon ptrace PTRACE_SETFPREGS 15 -1 36 36 -1 -1 # a.k.a. PT_SETFPREGS +syscon ptrace PTRACE_ATTACH 16 10 10 9 -1 -1 # a.k.a. PT_ATTACH +syscon ptrace PTRACE_DETACH 17 11 11 10 -1 -1 # a.k.a. PT_DETACH +syscon ptrace PTRACE_GETFPXREGS 18 -1 -1 -1 -1 -1 # a.k.a. PT_GETFPXREGS +syscon ptrace PTRACE_SETFPXREGS 19 -1 -1 -1 -1 -1 # a.k.a. PT_SETFPXREGS +syscon ptrace PTRACE_SYSCALL 24 -1 22 -1 -1 -1 # a.k.a. PT_SYSCALL +syscon ptrace PTRACE_GETEVENTMSG 0x4201 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_GETSIGINFO 0x4202 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SETOPTIONS 0x4200 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SETSIGINFO 0x4203 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_GETREGSET 0x4204 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_GETSIGMASK 0x420a -1 -1 -1 -1 -1 +syscon ptrace PTRACE_INTERRUPT 0x4207 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_LISTEN 0x4208 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_PEEKSIGINFO 0x4209 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SECCOMP_GET_FILTER 0x420c -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SEIZE 0x4206 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SETREGSET 0x4205 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_SETSIGMASK 0x420b -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACESYSGOOD 0x0001 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACEFORK 0x0002 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACEVFORK 0x0004 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACECLONE 0x0008 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACEEXEC 0x0010 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACEVFORKDONE 0x0020 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_TRACEEXIT 0x0040 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_O_MASK 0x007f -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_FORK 1 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_VFORK 2 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_CLONE 3 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_EXEC 4 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_VFORK_DONE 5 -1 -1 -1 -1 -1 +syscon ptrace PTRACE_EVENT_EXIT 6 -1 -1 -1 -1 -1 + syscon iproto IPPROTO_IP 0 0 0 0 0 0 # consensus syscon iproto IPPROTO_ICMP 1 1 1 1 1 1 # consensus syscon iproto IPPROTO_TCP 6 6 6 6 6 6 # consensus @@ -1318,13 +1417,6 @@ syscon poll POLLWRBAND 0x0200 0x0100 0x0100 0x0100 0x0100 0x20 # syscon poll POLLWRNORM 0x0100 4 4 4 4 0x10 # bsd consensus syscon poll POLLRDHUP 0x2000 0x10 0x10 0x10 0x10 2 # bsd consensus (POLLHUP on non-Linux) -syscon sigpoll POLL_ERR 4 4 4 0 0 0 -syscon sigpoll POLL_HUP 6 6 6 0 0 0 -syscon sigpoll POLL_IN 1 1 1 0 0 0 -syscon sigpoll POLL_MSG 3 3 3 0 0 0 -syscon sigpoll POLL_OUT 2 2 2 0 0 0 -syscon sigpoll POLL_PRI 5 5 5 0 0 0 - syscon c C_IXOTH 0000001 0000001 0000001 0000001 0000001 0 # unix consensus syscon c C_IWOTH 0000002 0000002 0000002 0000002 0000002 0 # unix consensus syscon c C_IROTH 0000004 0000004 0000004 0000004 0000004 0 # unix consensus @@ -1547,23 +1639,6 @@ syscon nd ND_ROUTER_ADVERT 134 134 134 134 134 0 # unix consensus syscon nd ND_ROUTER_SOLICIT 133 133 133 133 133 0 # unix consensus syscon nd ND_RA_FLAG_HOME_AGENT 0x20 0 0 0 0 0x20 # bsd consensus -syscon rlim RLIMIT_CPU 0 0 0 0 0 127 # unix consensus -syscon rlim RLIMIT_FSIZE 1 1 1 1 1 127 # unix consensus -syscon rlim RLIMIT_DATA 2 2 2 2 2 127 # unix consensus -syscon rlim RLIMIT_STACK 3 3 3 3 3 127 # unix consensus -syscon rlim RLIMIT_CORE 4 4 4 4 4 127 # unix consensus -syscon rlim RLIMIT_RSS 5 5 5 5 5 127 # unix consensus -syscon rlim RLIMIT_NPROC 6 7 7 7 7 127 # bsd consensus -syscon rlim RLIMIT_NOFILE 7 8 8 8 8 127 # bsd consensus -syscon rlim RLIMIT_MEMLOCK 8 6 6 6 6 127 # bsd consensus -syscon rlim RLIMIT_AS 9 5 10 127 127 127 -syscon rlim RLIMIT_LOCKS 10 127 127 127 127 127 # bsd consensus -syscon rlim RLIMIT_SIGPENDING 11 127 127 127 127 127 # bsd consensus -syscon rlim RLIMIT_MSGQUEUE 12 127 127 127 127 127 # bsd consensus -syscon rlim RLIMIT_NICE 13 127 127 127 127 127 # bsd consensus -syscon rlim RLIMIT_RTPRIO 14 127 127 127 127 127 # bsd consensus -syscon rlim RLIMIT_NLIMITS 16 127 127 127 127 127 # bsd consensus - syscon misc TCFLSH 0x540b 0 0 0 0 0 syscon misc TCIFLUSH 0 1 1 1 1 0 # bsd consensus syscon misc TCIOFF 2 3 3 3 3 0 # bsd consensus @@ -1771,13 +1846,7 @@ syscon misc SCSI_IOCTL_SYNC 4 0 0 0 0 0 syscon misc SCSI_IOCTL_TAGGED_DISABLE 0x5384 0 0 0 0 0 syscon misc SCSI_IOCTL_TAGGED_ENABLE 0x5383 0 0 0 0 0 syscon misc SCSI_IOCTL_TEST_UNIT_READY 2 0 0 0 0 0 - -syscon misc CLD_CONTINUED 6 6 6 6 6 6 # unix consensus -syscon misc CLD_DUMPED 3 3 3 3 3 3 # unix consensus -syscon misc CLD_EXITED 1 1 1 1 1 1 # unix consensus -syscon misc CLD_KILLED 2 2 2 2 2 2 # unix consensus -syscon misc CLD_STOPPED 5 5 5 5 5 5 # unix consensus -syscon misc CLD_TRAPPED 4 4 4 4 4 4 # unix consensus +syscon misc BUS_DEVICE_RESET 12 0 0 0 0 0 # SIGBUS; syscon misc READ_10 40 0 0 0 0 0 syscon misc READ_12 168 0 0 0 0 0 @@ -1838,15 +1907,6 @@ syscon misc WRITE_SAME 65 0 0 0 0 0 syscon misc WRITE_VERIFY 46 0 0 0 0 0 syscon misc WRITE_VERIFY_12 174 0 0 0 0 0 -syscon misc ILL_BADSTK 8 8 8 8 8 0 # unix consensus -syscon misc ILL_COPROC 7 7 7 7 7 0 # unix consensus -syscon misc ILL_ILLOPC 1 1 1 1 1 0 # unix consensus -syscon misc ILL_PRVREG 6 6 6 6 6 0 # unix consensus -syscon misc ILL_ILLADR 3 5 3 3 3 0 -syscon misc ILL_ILLOPN 2 4 2 2 2 0 -syscon misc ILL_ILLTRP 4 2 4 4 4 0 -syscon misc ILL_PRVOPC 5 3 5 5 5 0 - syscon lock LOCK_UNLOCK_CACHE 54 0 0 0 0 0 # wut syscon misc ARPHRD_ETHER 1 1 1 1 1 0 # unix consensus @@ -1858,13 +1918,6 @@ syscon misc ARPHRD_IEEE802154 804 0 0 0 0 0 syscon misc ARPHRD_IEEE802_TR 800 0 0 0 0 0 syscon misc ARPHRD_LOCALTLK 773 0 0 0 0 0 -syscon misc BUS_ADRALN 1 1 1 1 1 0 # unix consensus -syscon misc BUS_ADRERR 2 2 2 2 2 0 # unix consensus -syscon misc BUS_OBJERR 3 3 3 3 3 0 # unix consensus -syscon misc BUS_DEVICE_RESET 12 0 0 0 0 0 -syscon misc BUS_MCEERR_AO 5 0 0 0 0 0 -syscon misc BUS_MCEERR_AR 4 0 0 0 0 0 - syscon misc IP6F_MORE_FRAG 0x0100 0x0100 0x0100 0x0100 0x0100 0x0100 # consensus syscon misc IP6F_OFF_MASK 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff 0xf8ff # consensus syscon misc IP6F_RESERVED_MASK 0x0600 0x0600 0x0600 0x0600 0x0600 0x0600 # consensus @@ -1954,17 +2007,6 @@ syscon misc SEARCH_HIGH_12 176 0 0 0 0 0 syscon misc SEARCH_LOW 50 0 0 0 0 0 syscon misc SEARCH_LOW_12 178 0 0 0 0 0 -syscon misc SI_QUEUE -1 0x010002 0x010002 -2 -2 0 -syscon misc SI_TIMER -2 0x010003 0x010003 -3 -3 0 -syscon misc SI_ASYNCIO -4 0x010004 0x010004 0 0 0 -syscon misc SI_MESGQ -3 0x010005 0x010005 0 0 0 -syscon misc SI_KERNEL 0x80 0 0x010006 0 0 0 -syscon misc SI_USER 0 0x010001 0x010001 0 0 0 -syscon misc SI_ASYNCNL -60 0 0 0 0 0 -syscon misc SI_LOAD_SHIFT 0x10 0 0 0 0 0 -syscon misc SI_SIGIO -5 0 0 0 0 0 -syscon misc SI_TKILL -6 0 0 0 0 0 - syscon misc STRU_F 1 1 1 1 1 0 # unix consensus syscon misc STRU_P 3 3 3 3 3 0 # unix consensus syscon misc STRU_R 2 2 2 2 2 0 # unix consensus @@ -2050,12 +2092,6 @@ syscon misc SCHED_BATCH 3 0 0 0 0 0 syscon misc SCHED_IDLE 5 0 0 0 0 0 syscon misc SCHED_RESET_ON_FORK 0x40000000 0 0 0 0 0 -syscon misc SEGV_ACCERR 2 2 2 2 2 0 # unix consensus -syscon misc SEGV_MAPERR 1 1 1 1 1 0 # unix consensus - -syscon misc TRAP_BRKPT 1 1 1 1 1 0 # unix consensus -syscon misc TRAP_TRACE 2 2 2 2 2 0 # unix consensus - syscon misc WRDE_APPEND 0 1 1 0 0 0 syscon misc WRDE_BADCHAR 0 1 1 0 0 0 syscon misc WRDE_BADVAL 0 2 2 0 0 0 @@ -2112,14 +2148,6 @@ syscon misc TFD_NONBLOCK 0x0800 0 0 0 0 0 syscon misc TFD_TIMER_ABSTIME 1 0 0 0 0 0 syscon misc USRQUOTA 0 0 0 0 0 0 -syscon misc FPE_FLTDIV 3 1 3 3 3 0 -syscon misc FPE_FLTINV 7 5 7 7 7 0 -syscon misc FPE_FLTOVF 4 2 4 4 4 0 -syscon misc FPE_FLTRES 6 4 6 6 6 0 -syscon misc FPE_FLTSUB 8 6 8 8 8 0 -syscon misc FPE_FLTUND 5 3 5 5 5 0 -syscon misc FPE_INTDIV 1 7 2 1 1 0 -syscon misc FPE_INTOVF 2 8 1 2 2 0 syscon misc ABDAY_1 0x020000 14 14 13 13 0 syscon misc ABDAY_2 0x020001 15 15 14 14 0 @@ -2287,11 +2315,6 @@ syscon misc BC_DIM_MAX 0x0800 0x0800 0x0800 0xffff 0xffff 0 syscon misc BC_SCALE_MAX 99 99 99 0x7fffffff 0x7fffffff 0 syscon misc BC_STRING_MAX 0x03e8 0x03e8 0x03e8 0x7fffffff 0x7fffffff 0 -syscon misc RLIM_NLIMITS 0x10 9 15 9 9 0 -syscon misc RLIM_INFINITY -1 0 0x7fffffffffffffff 0 0 0 -syscon misc RLIM_SAVED_CUR -1 0 0x7fffffffffffffff 0 0 0 -syscon misc RLIM_SAVED_MAX -1 0 0x7fffffffffffffff 0 0 0 - syscon misc ABORTED_COMMAND 11 0 0 0 0 0 syscon misc ACORE 0 8 8 8 8 0 # bsd consensus syscon misc AFORK 0 1 1 1 1 0 # bsd consensus @@ -2512,22 +2535,22 @@ syscon termios VDISCARD 13 15 15 15 15 0 # termios.c_cc[VDISCARD] syscon termios VWERASE 14 4 4 4 4 0 # termios.c_cc[VWERASE]=𝑥 syscon termios VLNEXT 15 14 14 14 14 0 # termios.c_cc[VLNEXT]=𝑥 -syscon termios TIOCSERGETLSR 0x5459 0 0 0 0 0 # -syscon termios TIOCSERGETMULTI 0x545a 0 0 0 0 0 # -syscon termios TIOCSERSETMULTI 0x545b 0 0 0 0 0 # -syscon termios TIOCSER_TEMT 1 0 0 0 0 0 # +syscon termios TIOCSERGETLSR 0x5459 0 0 0 0 0 # +syscon termios TIOCSERGETMULTI 0x545a 0 0 0 0 0 # +syscon termios TIOCSERSETMULTI 0x545b 0 0 0 0 0 # +syscon termios TIOCSER_TEMT 1 0 0 0 0 0 # syscon termios VERIFY 47 0 0 0 0 0 -syscon termios PARENB 0x0100 0x1000 0x1000 0x1000 0x1000 0 # -syscon termios PARODD 0x0200 0x2000 0x2000 0x2000 0x2000 0 # +syscon termios PARENB 0x0100 0x1000 0x1000 0x1000 0x1000 0 # +syscon termios PARODD 0x0200 0x2000 0x2000 0x2000 0x2000 0 # syscon termios CIBAUD 0x100f0000 0 0 0 0 0 -syscon termios CLOCAL 0x0800 0x8000 0x8000 0x8000 0x8000 0 # +syscon termios CLOCAL 0x0800 0x8000 0x8000 0x8000 0x8000 0 # syscon termios CMSPAR 0x40000000 0 0 0 0 0 syscon termios BUSY 4 0 0 0 0 0 syscon termios CANBSIZ 255 0 0 0 0 0 syscon termios CBAUD 0x100f 0 0 0 0 0 syscon termios CBAUDEX 0x1000 0 0 0 0 0 -syscon termios CBRK 0 255 255 255 255 0 # -syscon termios CEOL 0 255 255 255 255 0 # +syscon termios CBRK 0 255 255 255 255 0 # +syscon termios CEOL 0 255 255 255 255 0 # # Pseudoteletypewriter Control # diff --git a/libc/sysv/consts/BUS_ADRALN.S b/libc/sysv/consts/BUS_ADRALN.S index f5c0c5e04..1ef06bbbc 100644 --- a/libc/sysv/consts/BUS_ADRALN.S +++ b/libc/sysv/consts/BUS_ADRALN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,BUS_ADRALN,1,1,1,1,1,0 +.syscon sicode,BUS_ADRALN,1,1,1,1,1,1 diff --git a/libc/sysv/consts/BUS_ADRERR.S b/libc/sysv/consts/BUS_ADRERR.S index b51d4eab4..67cd338da 100644 --- a/libc/sysv/consts/BUS_ADRERR.S +++ b/libc/sysv/consts/BUS_ADRERR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,BUS_ADRERR,2,2,2,2,2,0 +.syscon sicode,BUS_ADRERR,2,2,2,2,2,2 diff --git a/libc/sysv/consts/BUS_MCEERR_AO.S b/libc/sysv/consts/BUS_MCEERR_AO.S index ba125b0fa..6da2b9896 100644 --- a/libc/sysv/consts/BUS_MCEERR_AO.S +++ b/libc/sysv/consts/BUS_MCEERR_AO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,BUS_MCEERR_AO,5,0,0,0,0,0 +.syscon sicode,BUS_MCEERR_AO,5,0x80000000,0x80000000,0x80000000,0x80000000,0x80000000 diff --git a/libc/sysv/consts/BUS_MCEERR_AR.S b/libc/sysv/consts/BUS_MCEERR_AR.S index 1ed98654b..45e32fdbe 100644 --- a/libc/sysv/consts/BUS_MCEERR_AR.S +++ b/libc/sysv/consts/BUS_MCEERR_AR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,BUS_MCEERR_AR,4,0,0,0,0,0 +.syscon sicode,BUS_MCEERR_AR,4,0x80000000,0x80000000,0x80000000,0x80000000,0x80000000 diff --git a/libc/sysv/consts/BUS_OBJERR.S b/libc/sysv/consts/BUS_OBJERR.S index 160ad33bb..96dc0771c 100644 --- a/libc/sysv/consts/BUS_OBJERR.S +++ b/libc/sysv/consts/BUS_OBJERR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,BUS_OBJERR,3,3,3,3,3,0 +.syscon sicode,BUS_OBJERR,3,3,3,3,3,3 diff --git a/libc/sysv/consts/CLD_CONTINUED.S b/libc/sysv/consts/CLD_CONTINUED.S index 556196233..3665d1432 100644 --- a/libc/sysv/consts/CLD_CONTINUED.S +++ b/libc/sysv/consts/CLD_CONTINUED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_CONTINUED,6,6,6,6,6,6 +.syscon sicode,CLD_CONTINUED,6,6,6,6,6,6 diff --git a/libc/sysv/consts/CLD_DUMPED.S b/libc/sysv/consts/CLD_DUMPED.S index 1edbbadfa..5dbe99925 100644 --- a/libc/sysv/consts/CLD_DUMPED.S +++ b/libc/sysv/consts/CLD_DUMPED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_DUMPED,3,3,3,3,3,3 +.syscon sicode,CLD_DUMPED,3,3,3,3,3,3 diff --git a/libc/sysv/consts/CLD_EXITED.S b/libc/sysv/consts/CLD_EXITED.S index d6b6c972f..ff63e185d 100644 --- a/libc/sysv/consts/CLD_EXITED.S +++ b/libc/sysv/consts/CLD_EXITED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_EXITED,1,1,1,1,1,1 +.syscon sicode,CLD_EXITED,1,1,1,1,1,1 diff --git a/libc/sysv/consts/CLD_KILLED.S b/libc/sysv/consts/CLD_KILLED.S index 04d2a2f0f..3453b6985 100644 --- a/libc/sysv/consts/CLD_KILLED.S +++ b/libc/sysv/consts/CLD_KILLED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_KILLED,2,2,2,2,2,2 +.syscon sicode,CLD_KILLED,2,2,2,2,2,2 diff --git a/libc/sysv/consts/CLD_STOPPED.S b/libc/sysv/consts/CLD_STOPPED.S index 0dc66af27..2ec88545d 100644 --- a/libc/sysv/consts/CLD_STOPPED.S +++ b/libc/sysv/consts/CLD_STOPPED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_STOPPED,5,5,5,5,5,5 +.syscon sicode,CLD_STOPPED,5,5,5,5,5,5 diff --git a/libc/sysv/consts/CLD_TRAPPED.S b/libc/sysv/consts/CLD_TRAPPED.S index 7b027f015..35f858ef6 100644 --- a/libc/sysv/consts/CLD_TRAPPED.S +++ b/libc/sysv/consts/CLD_TRAPPED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,CLD_TRAPPED,4,4,4,4,4,4 +.syscon sicode,CLD_TRAPPED,4,4,4,4,4,4 diff --git a/libc/sysv/consts/CLOCK_BOOTTIME.S b/libc/sysv/consts/CLOCK_BOOTTIME.S index 6093b3969..4a093dab4 100644 --- a/libc/sysv/consts/CLOCK_BOOTTIME.S +++ b/libc/sysv/consts/CLOCK_BOOTTIME.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_BOOTTIME,7,0,0,6,6,0 +.syscon clock,CLOCK_BOOTTIME,7,-1,-1,6,6,-1 diff --git a/libc/sysv/consts/CLOCK_BOOTTIME_ALARM.S b/libc/sysv/consts/CLOCK_BOOTTIME_ALARM.S index 1c510dc53..aa660bfd3 100644 --- a/libc/sysv/consts/CLOCK_BOOTTIME_ALARM.S +++ b/libc/sysv/consts/CLOCK_BOOTTIME_ALARM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_BOOTTIME_ALARM,9,0,0,0,0,0 +.syscon clock,CLOCK_BOOTTIME_ALARM,9,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/CLOCK_MONOTONIC_COARSE.S b/libc/sysv/consts/CLOCK_MONOTONIC_COARSE.S index 431a181a0..d12e8ec95 100644 --- a/libc/sysv/consts/CLOCK_MONOTONIC_COARSE.S +++ b/libc/sysv/consts/CLOCK_MONOTONIC_COARSE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_MONOTONIC_COARSE,6,0,0,0,0,0 +.syscon clock,CLOCK_MONOTONIC_COARSE,6,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/CLOCK_PROCESS_CPUTIME_ID.S b/libc/sysv/consts/CLOCK_PROCESS_CPUTIME_ID.S index 507a56999..5a080feb2 100644 --- a/libc/sysv/consts/CLOCK_PROCESS_CPUTIME_ID.S +++ b/libc/sysv/consts/CLOCK_PROCESS_CPUTIME_ID.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_PROCESS_CPUTIME_ID,2,0,15,2,0x40000000,0 +.syscon clock,CLOCK_PROCESS_CPUTIME_ID,2,-1,15,2,0x40000000,-1 diff --git a/libc/sysv/consts/CLOCK_REALTIME_ALARM.S b/libc/sysv/consts/CLOCK_REALTIME_ALARM.S index 4845de579..795e372e4 100644 --- a/libc/sysv/consts/CLOCK_REALTIME_ALARM.S +++ b/libc/sysv/consts/CLOCK_REALTIME_ALARM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_REALTIME_ALARM,8,0,0,0,0,0 +.syscon clock,CLOCK_REALTIME_ALARM,8,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/CLOCK_REALTIME_COARSE.S b/libc/sysv/consts/CLOCK_REALTIME_COARSE.S index cb2e53004..7f40a4d9e 100644 --- a/libc/sysv/consts/CLOCK_REALTIME_COARSE.S +++ b/libc/sysv/consts/CLOCK_REALTIME_COARSE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_REALTIME_COARSE,5,0,0,0,0,0 +.syscon clock,CLOCK_REALTIME_COARSE,5,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/CLOCK_TAI.S b/libc/sysv/consts/CLOCK_TAI.S index 144ee41e5..0925bb74a 100644 --- a/libc/sysv/consts/CLOCK_TAI.S +++ b/libc/sysv/consts/CLOCK_TAI.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_TAI,11,0,0,0,0,0 +.syscon clock,CLOCK_TAI,11,-1,-1,-1,-1,-1 diff --git a/libc/sysv/consts/CLOCK_THREAD_CPUTIME_ID.S b/libc/sysv/consts/CLOCK_THREAD_CPUTIME_ID.S index 59a0db26f..d7358df70 100644 --- a/libc/sysv/consts/CLOCK_THREAD_CPUTIME_ID.S +++ b/libc/sysv/consts/CLOCK_THREAD_CPUTIME_ID.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon clock,CLOCK_THREAD_CPUTIME_ID,3,0,14,4,0x20000000,0 +.syscon clock,CLOCK_THREAD_CPUTIME_ID,3,-1,14,4,0x20000000,-1 diff --git a/libc/sysv/consts/EADV.S b/libc/sysv/consts/EADV.S index 08cbe9082..aa434b681 100644 --- a/libc/sysv/consts/EADV.S +++ b/libc/sysv/consts/EADV.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EADV,68,0,0,0,0,0 +.syscon junkerr,EADV,68,0,0,0,0,0 diff --git a/libc/sysv/consts/EBADE.S b/libc/sysv/consts/EBADE.S index ecaf458fc..74b94ea93 100644 --- a/libc/sysv/consts/EBADE.S +++ b/libc/sysv/consts/EBADE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBADE,52,0,0,0,0,0 +.syscon junkerr,EBADE,52,0,0,0,0,0 diff --git a/libc/sysv/consts/EBADFD.S b/libc/sysv/consts/EBADFD.S index 71f5f1687..3d23845e6 100644 --- a/libc/sysv/consts/EBADFD.S +++ b/libc/sysv/consts/EBADFD.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBADFD,77,9,9,9,9,6 +.syscon junkerr,EBADFD,77,9,9,9,9,6 diff --git a/libc/sysv/consts/EBADR.S b/libc/sysv/consts/EBADR.S index b1375b239..c63e4745e 100644 --- a/libc/sysv/consts/EBADR.S +++ b/libc/sysv/consts/EBADR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBADR,53,0,0,0,0,0 +.syscon junkerr,EBADR,53,0,0,0,0,0 diff --git a/libc/sysv/consts/EBADRQC.S b/libc/sysv/consts/EBADRQC.S index 134bfb5af..da7aa46d1 100644 --- a/libc/sysv/consts/EBADRQC.S +++ b/libc/sysv/consts/EBADRQC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBADRQC,56,0,0,0,0,0 +.syscon junkerr,EBADRQC,56,0,0,0,0,0 diff --git a/libc/sysv/consts/EBADSLT.S b/libc/sysv/consts/EBADSLT.S index fb1bff43d..da3094623 100644 --- a/libc/sysv/consts/EBADSLT.S +++ b/libc/sysv/consts/EBADSLT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBADSLT,57,0,0,0,0,0 +.syscon junkerr,EBADSLT,57,0,0,0,0,0 diff --git a/libc/sysv/consts/ECHRNG.S b/libc/sysv/consts/ECHRNG.S index 861ee6ebd..53c7a71ce 100644 --- a/libc/sysv/consts/ECHRNG.S +++ b/libc/sysv/consts/ECHRNG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ECHRNG,44,0,0,0,0,0 +.syscon junkerr,ECHRNG,44,0,0,0,0,0 diff --git a/libc/sysv/consts/ECOMM.S b/libc/sysv/consts/ECOMM.S index f84f311a4..4b86f5212 100644 --- a/libc/sysv/consts/ECOMM.S +++ b/libc/sysv/consts/ECOMM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ECOMM,70,0,0,0,0,0 +.syscon junkerr,ECOMM,70,0,0,0,0,0 diff --git a/libc/sysv/consts/EDOTDOT.S b/libc/sysv/consts/EDOTDOT.S index 8329e10d7..743fbc8ed 100644 --- a/libc/sysv/consts/EDOTDOT.S +++ b/libc/sysv/consts/EDOTDOT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EDOTDOT,73,0,0,0,0,0 +.syscon junkerr,EDOTDOT,73,0,0,0,0,0 diff --git a/libc/sysv/consts/EHWPOISON.S b/libc/sysv/consts/EHWPOISON.S index 7c94d3942..ff444df5f 100644 --- a/libc/sysv/consts/EHWPOISON.S +++ b/libc/sysv/consts/EHWPOISON.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EHWPOISON,133,0,0,0,0,0 +.syscon junkerr,EHWPOISON,133,0,0,0,0,0 diff --git a/libc/sysv/consts/EISNAM.S b/libc/sysv/consts/EISNAM.S index 12029e087..bdcc5c3e9 100644 --- a/libc/sysv/consts/EISNAM.S +++ b/libc/sysv/consts/EISNAM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EISNAM,120,0,0,0,0,0 +.syscon junkerr,EISNAM,120,0,0,0,0,0 diff --git a/libc/sysv/consts/EKEYEXPIRED.S b/libc/sysv/consts/EKEYEXPIRED.S index 161ed2852..fd5498a77 100644 --- a/libc/sysv/consts/EKEYEXPIRED.S +++ b/libc/sysv/consts/EKEYEXPIRED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EKEYEXPIRED,127,0,0,0,0,0 +.syscon junkerr,EKEYEXPIRED,127,0,0,0,0,0 diff --git a/libc/sysv/consts/EKEYREJECTED.S b/libc/sysv/consts/EKEYREJECTED.S index e8f1fb54a..c9e5d2225 100644 --- a/libc/sysv/consts/EKEYREJECTED.S +++ b/libc/sysv/consts/EKEYREJECTED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EKEYREJECTED,129,0,0,0,0,0 +.syscon junkerr,EKEYREJECTED,129,0,0,0,0,0 diff --git a/libc/sysv/consts/EKEYREVOKED.S b/libc/sysv/consts/EKEYREVOKED.S index beb4031f6..be58ba181 100644 --- a/libc/sysv/consts/EKEYREVOKED.S +++ b/libc/sysv/consts/EKEYREVOKED.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EKEYREVOKED,128,0,0,0,0,0 +.syscon junkerr,EKEYREVOKED,128,0,0,0,0,0 diff --git a/libc/sysv/consts/EL2HLT.S b/libc/sysv/consts/EL2HLT.S index 0415c820d..e55005ac5 100644 --- a/libc/sysv/consts/EL2HLT.S +++ b/libc/sysv/consts/EL2HLT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EL2HLT,51,0,0,0,0,0 +.syscon junkerr,EL2HLT,51,0,0,0,0,0 diff --git a/libc/sysv/consts/EL2NSYNC.S b/libc/sysv/consts/EL2NSYNC.S index 31ddd4a99..4da833ae8 100644 --- a/libc/sysv/consts/EL2NSYNC.S +++ b/libc/sysv/consts/EL2NSYNC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EL2NSYNC,45,0,0,0,0,0 +.syscon junkerr,EL2NSYNC,45,0,0,0,0,0 diff --git a/libc/sysv/consts/EL3HLT.S b/libc/sysv/consts/EL3HLT.S index c0e150d1c..607b6f6a6 100644 --- a/libc/sysv/consts/EL3HLT.S +++ b/libc/sysv/consts/EL3HLT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EL3HLT,46,0,0,0,0,0 +.syscon junkerr,EL3HLT,46,0,0,0,0,0 diff --git a/libc/sysv/consts/EL3RST.S b/libc/sysv/consts/EL3RST.S index 96e3fa638..0b5ea0c3c 100644 --- a/libc/sysv/consts/EL3RST.S +++ b/libc/sysv/consts/EL3RST.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EL3RST,47,0,0,0,0,0 +.syscon junkerr,EL3RST,47,0,0,0,0,0 diff --git a/libc/sysv/consts/ELIBACC.S b/libc/sysv/consts/ELIBACC.S index 76c50141b..97fe15688 100644 --- a/libc/sysv/consts/ELIBACC.S +++ b/libc/sysv/consts/ELIBACC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELIBACC,79,0,0,0,0,0 +.syscon junkerr,ELIBACC,79,0,0,0,0,0 diff --git a/libc/sysv/consts/ELIBBAD.S b/libc/sysv/consts/ELIBBAD.S index 9596cc363..6622fadb0 100644 --- a/libc/sysv/consts/ELIBBAD.S +++ b/libc/sysv/consts/ELIBBAD.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELIBBAD,80,0,0,0,0,0 +.syscon junkerr,ELIBBAD,80,0,0,0,0,0 diff --git a/libc/sysv/consts/ELIBEXEC.S b/libc/sysv/consts/ELIBEXEC.S index cd9ae7540..3245cdf4f 100644 --- a/libc/sysv/consts/ELIBEXEC.S +++ b/libc/sysv/consts/ELIBEXEC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELIBEXEC,83,0,0,0,0,0 +.syscon junkerr,ELIBEXEC,83,0,0,0,0,0 diff --git a/libc/sysv/consts/ELIBMAX.S b/libc/sysv/consts/ELIBMAX.S index 2f18e3b08..b319adea2 100644 --- a/libc/sysv/consts/ELIBMAX.S +++ b/libc/sysv/consts/ELIBMAX.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELIBMAX,82,0,0,0,0,0 +.syscon junkerr,ELIBMAX,82,0,0,0,0,0 diff --git a/libc/sysv/consts/ELIBSCN.S b/libc/sysv/consts/ELIBSCN.S index 680f8da4d..3776c44d9 100644 --- a/libc/sysv/consts/ELIBSCN.S +++ b/libc/sysv/consts/ELIBSCN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELIBSCN,81,0,0,0,0,0 +.syscon junkerr,ELIBSCN,81,0,0,0,0,0 diff --git a/libc/sysv/consts/ELNRNG.S b/libc/sysv/consts/ELNRNG.S index bda2fc53d..236df0e89 100644 --- a/libc/sysv/consts/ELNRNG.S +++ b/libc/sysv/consts/ELNRNG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ELNRNG,48,0,0,0,0,0 +.syscon junkerr,ELNRNG,48,0,0,0,0,0 diff --git a/libc/sysv/consts/EMEDIUMTYPE.S b/libc/sysv/consts/EMEDIUMTYPE.S index ba830f328..488841a65 100644 --- a/libc/sysv/consts/EMEDIUMTYPE.S +++ b/libc/sysv/consts/EMEDIUMTYPE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EMEDIUMTYPE,124,0,0,86,86,0 +.syscon junkerr,EMEDIUMTYPE,124,0,0,86,86,0 diff --git a/libc/sysv/consts/EMULTIHOP.S b/libc/sysv/consts/EMULTIHOP.S index 434e78754..cfff27b7d 100644 --- a/libc/sysv/consts/EMULTIHOP.S +++ b/libc/sysv/consts/EMULTIHOP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EMULTIHOP,72,95,90,0,94,0 +.syscon junkerr,EMULTIHOP,72,95,90,0,94,0 diff --git a/libc/sysv/consts/ENAVAIL.S b/libc/sysv/consts/ENAVAIL.S index 5cbd8fda4..2b89fb282 100644 --- a/libc/sysv/consts/ENAVAIL.S +++ b/libc/sysv/consts/ENAVAIL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENAVAIL,119,0,0,0,0,0 +.syscon junkerr,ENAVAIL,119,0,0,0,0,0 diff --git a/libc/sysv/consts/ENOANO.S b/libc/sysv/consts/ENOANO.S index 235babdad..2ecd8abe2 100644 --- a/libc/sysv/consts/ENOANO.S +++ b/libc/sysv/consts/ENOANO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOANO,55,0,0,0,0,0 +.syscon junkerr,ENOANO,55,0,0,0,0,0 diff --git a/libc/sysv/consts/ENOCSI.S b/libc/sysv/consts/ENOCSI.S index 9c5de5dd5..29453b515 100644 --- a/libc/sysv/consts/ENOCSI.S +++ b/libc/sysv/consts/ENOCSI.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOCSI,50,0,0,0,0,0 +.syscon junkerr,ENOCSI,50,0,0,0,0,0 diff --git a/libc/sysv/consts/ENODATA.S b/libc/sysv/consts/ENODATA.S index e9b938bbb..c406f9ae6 100644 --- a/libc/sysv/consts/ENODATA.S +++ b/libc/sysv/consts/ENODATA.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENODATA,61,96,0,0,89,0 +.syscon junkerr,ENODATA,61,96,0,0,89,0 diff --git a/libc/sysv/consts/ENOKEY.S b/libc/sysv/consts/ENOKEY.S index bc11fdebf..46c2fc42a 100644 --- a/libc/sysv/consts/ENOKEY.S +++ b/libc/sysv/consts/ENOKEY.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOKEY,126,0,0,0,0,0 +.syscon junkerr,ENOKEY,126,0,0,0,0,0 diff --git a/libc/sysv/consts/ENOLINK.S b/libc/sysv/consts/ENOLINK.S index 875ea6b1b..9d890098e 100644 --- a/libc/sysv/consts/ENOLINK.S +++ b/libc/sysv/consts/ENOLINK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOLINK,67,97,91,0,95,0 +.syscon junkerr,ENOLINK,67,97,91,0,95,0 diff --git a/libc/sysv/consts/ENOMEDIUM.S b/libc/sysv/consts/ENOMEDIUM.S index 0c9a5d03a..7243999b8 100644 --- a/libc/sysv/consts/ENOMEDIUM.S +++ b/libc/sysv/consts/ENOMEDIUM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOMEDIUM,123,0,0,85,85,0 +.syscon junkerr,ENOMEDIUM,123,0,0,85,85,0 diff --git a/libc/sysv/consts/ENOPKG.S b/libc/sysv/consts/ENOPKG.S index d05ef3a03..e2580a4ab 100644 --- a/libc/sysv/consts/ENOPKG.S +++ b/libc/sysv/consts/ENOPKG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOPKG,65,0,0,0,0,0 +.syscon junkerr,ENOPKG,65,0,0,0,0,0 diff --git a/libc/sysv/consts/ENOSR.S b/libc/sysv/consts/ENOSR.S index 86ff4c52b..ea4d91cf0 100644 --- a/libc/sysv/consts/ENOSR.S +++ b/libc/sysv/consts/ENOSR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOSR,63,98,0,0,90,0 +.syscon junkerr,ENOSR,63,98,0,0,90,0 diff --git a/libc/sysv/consts/ENOSTR.S b/libc/sysv/consts/ENOSTR.S index 749624fa4..9dde57279 100644 --- a/libc/sysv/consts/ENOSTR.S +++ b/libc/sysv/consts/ENOSTR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOSTR,60,99,0,0,91,0 +.syscon junkerr,ENOSTR,60,99,0,0,91,0 diff --git a/libc/sysv/consts/ENOTNAM.S b/libc/sysv/consts/ENOTNAM.S index b1b4db47e..94e0ff0d3 100644 --- a/libc/sysv/consts/ENOTNAM.S +++ b/libc/sysv/consts/ENOTNAM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOTNAM,118,0,0,0,0,0 +.syscon junkerr,ENOTNAM,118,0,0,0,0,0 diff --git a/libc/sysv/consts/ENOTUNIQ.S b/libc/sysv/consts/ENOTUNIQ.S index 3212f49c8..a4b4922f9 100644 --- a/libc/sysv/consts/ENOTUNIQ.S +++ b/libc/sysv/consts/ENOTUNIQ.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ENOTUNIQ,76,0,0,0,0,0 +.syscon junkerr,ENOTUNIQ,76,0,0,0,0,0 diff --git a/libc/sysv/consts/EREMCHG.S b/libc/sysv/consts/EREMCHG.S index 0097bc85d..40c2b77fb 100644 --- a/libc/sysv/consts/EREMCHG.S +++ b/libc/sysv/consts/EREMCHG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EREMCHG,78,0,0,0,0,0 +.syscon junkerr,EREMCHG,78,0,0,0,0,0 diff --git a/libc/sysv/consts/EREMOTEIO.S b/libc/sysv/consts/EREMOTEIO.S index 99326c177..274433d49 100644 --- a/libc/sysv/consts/EREMOTEIO.S +++ b/libc/sysv/consts/EREMOTEIO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EREMOTEIO,121,0,0,0,0,0 +.syscon junkerr,EREMOTEIO,121,0,0,0,0,0 diff --git a/libc/sysv/consts/ERFKILL.S b/libc/sysv/consts/ERFKILL.S index 2f331d26e..fb48e5305 100644 --- a/libc/sysv/consts/ERFKILL.S +++ b/libc/sysv/consts/ERFKILL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ERFKILL,132,0,0,0,0,0 +.syscon junkerr,ERFKILL,132,0,0,0,0,0 diff --git a/libc/sysv/consts/ESRMNT.S b/libc/sysv/consts/ESRMNT.S index 99b5f9605..7c3147570 100644 --- a/libc/sysv/consts/ESRMNT.S +++ b/libc/sysv/consts/ESRMNT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ESRMNT,69,0,0,0,0,0 +.syscon junkerr,ESRMNT,69,0,0,0,0,0 diff --git a/libc/sysv/consts/ESTRPIPE.S b/libc/sysv/consts/ESTRPIPE.S index 8892e8b26..f89d8fa13 100644 --- a/libc/sysv/consts/ESTRPIPE.S +++ b/libc/sysv/consts/ESTRPIPE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ESTRPIPE,86,0,0,0,0,0 +.syscon junkerr,ESTRPIPE,86,0,0,0,0,0 diff --git a/libc/sysv/consts/ETIME.S b/libc/sysv/consts/ETIME.S index e338e9f62..38366adf2 100644 --- a/libc/sysv/consts/ETIME.S +++ b/libc/sysv/consts/ETIME.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,ETIME,62,101,0,0,92,0 +.syscon errno,ETIME,62,101,60,60,92,0 diff --git a/libc/sysv/consts/EUCLEAN.S b/libc/sysv/consts/EUCLEAN.S index a827c02e0..a0eecf2db 100644 --- a/libc/sysv/consts/EUCLEAN.S +++ b/libc/sysv/consts/EUCLEAN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EUCLEAN,117,0,0,0,0,0 +.syscon junkerr,EUCLEAN,117,0,0,0,0,0 diff --git a/libc/sysv/consts/EUNATCH.S b/libc/sysv/consts/EUNATCH.S index 5595e478a..679c2a8fc 100644 --- a/libc/sysv/consts/EUNATCH.S +++ b/libc/sysv/consts/EUNATCH.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EUNATCH,49,0,0,0,0,0 +.syscon junkerr,EUNATCH,49,0,0,0,0,0 diff --git a/libc/sysv/consts/EWOULDBLOCK.S b/libc/sysv/consts/EWOULDBLOCK.S index 91f2f0ba8..16f6e6d55 100644 --- a/libc/sysv/consts/EWOULDBLOCK.S +++ b/libc/sysv/consts/EWOULDBLOCK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EWOULDBLOCK,11,35,35,35,35,0x2733 +.syscon compat,EWOULDBLOCK,11,35,35,35,35,0x2733 diff --git a/libc/sysv/consts/EXFULL.S b/libc/sysv/consts/EXFULL.S index 0c0aad1d2..bd1fd87c3 100644 --- a/libc/sysv/consts/EXFULL.S +++ b/libc/sysv/consts/EXFULL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EXFULL,54,0,0,0,0,0 +.syscon junkerr,EXFULL,54,0,0,0,0,0 diff --git a/libc/sysv/consts/FPE_FLTDIV.S b/libc/sysv/consts/FPE_FLTDIV.S index 3390eed37..779be8461 100644 --- a/libc/sysv/consts/FPE_FLTDIV.S +++ b/libc/sysv/consts/FPE_FLTDIV.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTDIV,3,1,3,3,3,0 +.syscon sicode,FPE_FLTDIV,3,1,3,3,3,3 diff --git a/libc/sysv/consts/FPE_FLTINV.S b/libc/sysv/consts/FPE_FLTINV.S index 24a2d9b9d..efd268e49 100644 --- a/libc/sysv/consts/FPE_FLTINV.S +++ b/libc/sysv/consts/FPE_FLTINV.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTINV,7,5,7,7,7,0 +.syscon sicode,FPE_FLTINV,7,5,7,7,7,7 diff --git a/libc/sysv/consts/FPE_FLTOVF.S b/libc/sysv/consts/FPE_FLTOVF.S index 6ccf5937c..ff290e423 100644 --- a/libc/sysv/consts/FPE_FLTOVF.S +++ b/libc/sysv/consts/FPE_FLTOVF.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTOVF,4,2,4,4,4,0 +.syscon sicode,FPE_FLTOVF,4,2,4,4,4,4 diff --git a/libc/sysv/consts/FPE_FLTRES.S b/libc/sysv/consts/FPE_FLTRES.S index 7d4881f0b..8dcf2076d 100644 --- a/libc/sysv/consts/FPE_FLTRES.S +++ b/libc/sysv/consts/FPE_FLTRES.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTRES,6,4,6,6,6,0 +.syscon sicode,FPE_FLTRES,6,4,6,6,6,6 diff --git a/libc/sysv/consts/FPE_FLTSUB.S b/libc/sysv/consts/FPE_FLTSUB.S index f17fa18c1..1c16c937e 100644 --- a/libc/sysv/consts/FPE_FLTSUB.S +++ b/libc/sysv/consts/FPE_FLTSUB.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTSUB,8,6,8,8,8,0 +.syscon sicode,FPE_FLTSUB,8,6,8,8,8,8 diff --git a/libc/sysv/consts/FPE_FLTUND.S b/libc/sysv/consts/FPE_FLTUND.S index 7556e5724..9a93a8dd8 100644 --- a/libc/sysv/consts/FPE_FLTUND.S +++ b/libc/sysv/consts/FPE_FLTUND.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_FLTUND,5,3,5,5,5,0 +.syscon sicode,FPE_FLTUND,5,3,5,5,5,5 diff --git a/libc/sysv/consts/FPE_INTDIV.S b/libc/sysv/consts/FPE_INTDIV.S index 87d9e0340..23ea84b2a 100644 --- a/libc/sysv/consts/FPE_INTDIV.S +++ b/libc/sysv/consts/FPE_INTDIV.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_INTDIV,1,7,2,1,1,0 +.syscon sicode,FPE_INTDIV,1,7,2,1,1,1 diff --git a/libc/sysv/consts/FPE_INTOVF.S b/libc/sysv/consts/FPE_INTOVF.S index dfcfe321c..dd44f7bbc 100644 --- a/libc/sysv/consts/FPE_INTOVF.S +++ b/libc/sysv/consts/FPE_INTOVF.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,FPE_INTOVF,2,8,1,2,2,0 +.syscon sicode,FPE_INTOVF,2,8,1,2,2,2 diff --git a/libc/sysv/consts/ILL_BADSTK.S b/libc/sysv/consts/ILL_BADSTK.S index 0dbf521d0..296262949 100644 --- a/libc/sysv/consts/ILL_BADSTK.S +++ b/libc/sysv/consts/ILL_BADSTK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_BADSTK,8,8,8,8,8,0 +.syscon sicode,ILL_BADSTK,8,8,8,8,8,8 diff --git a/libc/sysv/consts/ILL_COPROC.S b/libc/sysv/consts/ILL_COPROC.S index 3c7d9a3a3..220f3d6ba 100644 --- a/libc/sysv/consts/ILL_COPROC.S +++ b/libc/sysv/consts/ILL_COPROC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_COPROC,7,7,7,7,7,0 +.syscon sicode,ILL_COPROC,7,7,7,7,7,7 diff --git a/libc/sysv/consts/ILL_ILLADR.S b/libc/sysv/consts/ILL_ILLADR.S index f7bd4dd40..7aff4a492 100644 --- a/libc/sysv/consts/ILL_ILLADR.S +++ b/libc/sysv/consts/ILL_ILLADR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_ILLADR,3,5,3,3,3,0 +.syscon sicode,ILL_ILLADR,3,5,3,3,3,3 diff --git a/libc/sysv/consts/ILL_ILLOPC.S b/libc/sysv/consts/ILL_ILLOPC.S index f3cc6c998..9343caf39 100644 --- a/libc/sysv/consts/ILL_ILLOPC.S +++ b/libc/sysv/consts/ILL_ILLOPC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_ILLOPC,1,1,1,1,1,0 +.syscon sicode,ILL_ILLOPC,1,1,1,1,1,1 diff --git a/libc/sysv/consts/ILL_ILLOPN.S b/libc/sysv/consts/ILL_ILLOPN.S index 802e290fe..ad757bc07 100644 --- a/libc/sysv/consts/ILL_ILLOPN.S +++ b/libc/sysv/consts/ILL_ILLOPN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_ILLOPN,2,4,2,2,2,0 +.syscon sicode,ILL_ILLOPN,2,4,2,2,2,2 diff --git a/libc/sysv/consts/ILL_ILLTRP.S b/libc/sysv/consts/ILL_ILLTRP.S index 8dde415d1..722e291f4 100644 --- a/libc/sysv/consts/ILL_ILLTRP.S +++ b/libc/sysv/consts/ILL_ILLTRP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_ILLTRP,4,2,4,4,4,0 +.syscon sicode,ILL_ILLTRP,4,2,4,4,4,4 diff --git a/libc/sysv/consts/ILL_PRVOPC.S b/libc/sysv/consts/ILL_PRVOPC.S index a3ea0bcc2..438b12a21 100644 --- a/libc/sysv/consts/ILL_PRVOPC.S +++ b/libc/sysv/consts/ILL_PRVOPC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_PRVOPC,5,3,5,5,5,0 +.syscon sicode,ILL_PRVOPC,5,3,5,5,5,5 diff --git a/libc/sysv/consts/ILL_PRVREG.S b/libc/sysv/consts/ILL_PRVREG.S index c80307d9c..bfbb3b56a 100644 --- a/libc/sysv/consts/ILL_PRVREG.S +++ b/libc/sysv/consts/ILL_PRVREG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,ILL_PRVREG,6,6,6,6,6,0 +.syscon sicode,ILL_PRVREG,6,6,6,6,6,6 diff --git a/libc/sysv/consts/MADV_DONTDUMP.S b/libc/sysv/consts/MADV_DONTDUMP.S index c24e42a02..feba10977 100644 --- a/libc/sysv/consts/MADV_DONTDUMP.S +++ b/libc/sysv/consts/MADV_DONTDUMP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon madv,MADV_DONTDUMP,0x10,0,0,0,0,0 +.syscon madv,MADV_DONTDUMP,16,0,0,0,0,0 diff --git a/libc/sysv/consts/POLL_ERR.S b/libc/sysv/consts/POLL_ERR.S index 8f6024588..1c0e2ffd5 100644 --- a/libc/sysv/consts/POLL_ERR.S +++ b/libc/sysv/consts/POLL_ERR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_ERR,4,4,4,0,0,0 +.syscon sicode,POLL_ERR,4,4,4,4,4,4 diff --git a/libc/sysv/consts/POLL_HUP.S b/libc/sysv/consts/POLL_HUP.S index 5c4abccf5..514a3cef2 100644 --- a/libc/sysv/consts/POLL_HUP.S +++ b/libc/sysv/consts/POLL_HUP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_HUP,6,6,6,0,0,0 +.syscon sicode,POLL_HUP,6,6,6,6,6,6 diff --git a/libc/sysv/consts/POLL_IN.S b/libc/sysv/consts/POLL_IN.S index edb282b17..1c2be195e 100644 --- a/libc/sysv/consts/POLL_IN.S +++ b/libc/sysv/consts/POLL_IN.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_IN,1,1,1,0,0,0 +.syscon sicode,POLL_IN,1,1,1,1,1,1 diff --git a/libc/sysv/consts/POLL_MSG.S b/libc/sysv/consts/POLL_MSG.S index 326e10ceb..acd5a6183 100644 --- a/libc/sysv/consts/POLL_MSG.S +++ b/libc/sysv/consts/POLL_MSG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_MSG,3,3,3,0,0,0 +.syscon sicode,POLL_MSG,3,3,3,3,3,3 diff --git a/libc/sysv/consts/POLL_OUT.S b/libc/sysv/consts/POLL_OUT.S index 9aede8bb9..5b9eb0746 100644 --- a/libc/sysv/consts/POLL_OUT.S +++ b/libc/sysv/consts/POLL_OUT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_OUT,2,2,2,0,0,0 +.syscon sicode,POLL_OUT,2,2,2,2,2,2 diff --git a/libc/sysv/consts/POLL_PRI.S b/libc/sysv/consts/POLL_PRI.S index 4c8e61db9..13d080839 100644 --- a/libc/sysv/consts/POLL_PRI.S +++ b/libc/sysv/consts/POLL_PRI.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigpoll,POLL_PRI,5,5,5,0,0,0 +.syscon sicode,POLL_PRI,5,5,5,5,5,5 diff --git a/libc/sysv/consts/RLIMIT_AS.S b/libc/sysv/consts/RLIMIT_AS.S index 98cade3b7..00f1f8ea2 100644 --- a/libc/sysv/consts/RLIMIT_AS.S +++ b/libc/sysv/consts/RLIMIT_AS.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_AS,9,5,10,127,127,127 +.syscon rlimit,RLIMIT_AS,9,5,10,127,10,127 diff --git a/libc/sysv/consts/RLIMIT_CORE.S b/libc/sysv/consts/RLIMIT_CORE.S index 5901b08f7..0b70c7a64 100644 --- a/libc/sysv/consts/RLIMIT_CORE.S +++ b/libc/sysv/consts/RLIMIT_CORE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_CORE,4,4,4,4,4,127 +.syscon rlimit,RLIMIT_CORE,4,4,4,4,4,127 diff --git a/libc/sysv/consts/RLIMIT_CPU.S b/libc/sysv/consts/RLIMIT_CPU.S index 5acec12a7..3c722caf1 100644 --- a/libc/sysv/consts/RLIMIT_CPU.S +++ b/libc/sysv/consts/RLIMIT_CPU.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_CPU,0,0,0,0,0,127 +.syscon rlimit,RLIMIT_CPU,0,0,0,0,0,127 diff --git a/libc/sysv/consts/RLIMIT_DATA.S b/libc/sysv/consts/RLIMIT_DATA.S index dded0c054..492ee8dcc 100644 --- a/libc/sysv/consts/RLIMIT_DATA.S +++ b/libc/sysv/consts/RLIMIT_DATA.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_DATA,2,2,2,2,2,127 +.syscon rlimit,RLIMIT_DATA,2,2,2,2,2,127 diff --git a/libc/sysv/consts/RLIMIT_FSIZE.S b/libc/sysv/consts/RLIMIT_FSIZE.S index 8e1daa55b..1ba468e45 100644 --- a/libc/sysv/consts/RLIMIT_FSIZE.S +++ b/libc/sysv/consts/RLIMIT_FSIZE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_FSIZE,1,1,1,1,1,127 +.syscon rlimit,RLIMIT_FSIZE,1,1,1,1,1,127 diff --git a/libc/sysv/consts/RLIMIT_LOCKS.S b/libc/sysv/consts/RLIMIT_LOCKS.S index 3656d1bd6..fc4b768f1 100644 --- a/libc/sysv/consts/RLIMIT_LOCKS.S +++ b/libc/sysv/consts/RLIMIT_LOCKS.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_LOCKS,10,127,127,127,127,127 +.syscon rlimit,RLIMIT_LOCKS,10,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_MEMLOCK.S b/libc/sysv/consts/RLIMIT_MEMLOCK.S index 9b7e9e9a6..1b6453b6b 100644 --- a/libc/sysv/consts/RLIMIT_MEMLOCK.S +++ b/libc/sysv/consts/RLIMIT_MEMLOCK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_MEMLOCK,8,6,6,6,6,127 +.syscon rlimit,RLIMIT_MEMLOCK,8,6,6,6,6,127 diff --git a/libc/sysv/consts/RLIMIT_MSGQUEUE.S b/libc/sysv/consts/RLIMIT_MSGQUEUE.S index 6b5265367..5f5b72750 100644 --- a/libc/sysv/consts/RLIMIT_MSGQUEUE.S +++ b/libc/sysv/consts/RLIMIT_MSGQUEUE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_MSGQUEUE,12,127,127,127,127,127 +.syscon rlimit,RLIMIT_MSGQUEUE,12,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_NICE.S b/libc/sysv/consts/RLIMIT_NICE.S index 0e023da20..96ce1be85 100644 --- a/libc/sysv/consts/RLIMIT_NICE.S +++ b/libc/sysv/consts/RLIMIT_NICE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_NICE,13,127,127,127,127,127 +.syscon rlimit,RLIMIT_NICE,13,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_NLIMITS.S b/libc/sysv/consts/RLIMIT_NLIMITS.S deleted file mode 100644 index 841045785..000000000 --- a/libc/sysv/consts/RLIMIT_NLIMITS.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_NLIMITS,16,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_NOFILE.S b/libc/sysv/consts/RLIMIT_NOFILE.S index 2708a6cd5..264b45dce 100644 --- a/libc/sysv/consts/RLIMIT_NOFILE.S +++ b/libc/sysv/consts/RLIMIT_NOFILE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_NOFILE,7,8,8,8,8,127 +.syscon rlimit,RLIMIT_NOFILE,7,8,8,8,8,127 diff --git a/libc/sysv/consts/RLIMIT_NPROC.S b/libc/sysv/consts/RLIMIT_NPROC.S index a4bb784eb..060763a46 100644 --- a/libc/sysv/consts/RLIMIT_NPROC.S +++ b/libc/sysv/consts/RLIMIT_NPROC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_NPROC,6,7,7,7,7,127 +.syscon rlimit,RLIMIT_NPROC,6,7,7,7,7,127 diff --git a/libc/sysv/consts/RLIMIT_RSS.S b/libc/sysv/consts/RLIMIT_RSS.S index 2ab654e5b..552e12ba5 100644 --- a/libc/sysv/consts/RLIMIT_RSS.S +++ b/libc/sysv/consts/RLIMIT_RSS.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_RSS,5,5,5,5,5,127 +.syscon rlimit,RLIMIT_RSS,5,5,5,5,5,127 diff --git a/libc/sysv/consts/RLIMIT_RTPRIO.S b/libc/sysv/consts/RLIMIT_RTPRIO.S index c6c036385..d1b418404 100644 --- a/libc/sysv/consts/RLIMIT_RTPRIO.S +++ b/libc/sysv/consts/RLIMIT_RTPRIO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_RTPRIO,14,127,127,127,127,127 +.syscon rlimit,RLIMIT_RTPRIO,14,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_SIGPENDING.S b/libc/sysv/consts/RLIMIT_SIGPENDING.S index f3c872177..7e8014a74 100644 --- a/libc/sysv/consts/RLIMIT_SIGPENDING.S +++ b/libc/sysv/consts/RLIMIT_SIGPENDING.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_SIGPENDING,11,127,127,127,127,127 +.syscon rlimit,RLIMIT_SIGPENDING,11,127,127,127,127,127 diff --git a/libc/sysv/consts/RLIMIT_STACK.S b/libc/sysv/consts/RLIMIT_STACK.S index e4bde29ac..ca5899cad 100644 --- a/libc/sysv/consts/RLIMIT_STACK.S +++ b/libc/sysv/consts/RLIMIT_STACK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon rlim,RLIMIT_STACK,3,3,3,3,3,127 +.syscon rlimit,RLIMIT_STACK,3,3,3,3,3,127 diff --git a/libc/sysv/consts/EBFONT.S b/libc/sysv/consts/RLIMIT_VMEM.S similarity index 50% rename from libc/sysv/consts/EBFONT.S rename to libc/sysv/consts/RLIMIT_VMEM.S index 4ddb766ff..30017ab72 100644 --- a/libc/sysv/consts/EBFONT.S +++ b/libc/sysv/consts/RLIMIT_VMEM.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon errno,EBFONT,59,0,0,0,0,0 +.syscon compat,RLIMIT_VMEM,9,5,10,127,10,127 diff --git a/libc/sysv/consts/RLIM_INFINITY.S b/libc/sysv/consts/RLIM_INFINITY.S index 9f0fbfef5..422e8ccc7 100644 --- a/libc/sysv/consts/RLIM_INFINITY.S +++ b/libc/sysv/consts/RLIM_INFINITY.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,RLIM_INFINITY,-1,0,0x7fffffffffffffff,0,0,0 +.syscon rlim,RLIM_INFINITY,0xffffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0 diff --git a/libc/sysv/consts/RLIM_NLIMITS.S b/libc/sysv/consts/RLIM_NLIMITS.S index 6de03aefe..ca3b0635d 100644 --- a/libc/sysv/consts/RLIM_NLIMITS.S +++ b/libc/sysv/consts/RLIM_NLIMITS.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,RLIM_NLIMITS,0x10,9,15,9,9,0 +.syscon rlim,RLIM_NLIMITS,16,9,15,9,12,0 diff --git a/libc/sysv/consts/RLIM_SAVED_CUR.S b/libc/sysv/consts/RLIM_SAVED_CUR.S index be886de01..78d294007 100644 --- a/libc/sysv/consts/RLIM_SAVED_CUR.S +++ b/libc/sysv/consts/RLIM_SAVED_CUR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,RLIM_SAVED_CUR,-1,0,0x7fffffffffffffff,0,0,0 +.syscon rlim,RLIM_SAVED_CUR,0xffffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0 diff --git a/libc/sysv/consts/RLIM_SAVED_MAX.S b/libc/sysv/consts/RLIM_SAVED_MAX.S index 312626bed..67b4fc5d6 100644 --- a/libc/sysv/consts/RLIM_SAVED_MAX.S +++ b/libc/sysv/consts/RLIM_SAVED_MAX.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,RLIM_SAVED_MAX,-1,0,0x7fffffffffffffff,0,0,0 +.syscon rlim,RLIM_SAVED_MAX,0xffffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0x7fffffffffffffff,0 diff --git a/libc/sysv/consts/SA_NOCLDSTOP.S b/libc/sysv/consts/SA_NOCLDSTOP.S index b31167ec4..01f482ea8 100644 --- a/libc/sysv/consts/SA_NOCLDSTOP.S +++ b/libc/sysv/consts/SA_NOCLDSTOP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_NOCLDSTOP,1,8,8,8,8,0 +.syscon sigact,SA_NOCLDSTOP,1,8,8,8,8,1 diff --git a/libc/sysv/consts/SA_NOCLDWAIT.S b/libc/sysv/consts/SA_NOCLDWAIT.S index 71708bee5..921c1c347 100644 --- a/libc/sysv/consts/SA_NOCLDWAIT.S +++ b/libc/sysv/consts/SA_NOCLDWAIT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_NOCLDWAIT,2,0x20,0x20,0x20,0x20,0 +.syscon sigact,SA_NOCLDWAIT,2,32,32,32,32,2 diff --git a/libc/sysv/consts/SA_NODEFER.S b/libc/sysv/consts/SA_NODEFER.S index e6da9b8d5..785678705 100644 --- a/libc/sysv/consts/SA_NODEFER.S +++ b/libc/sysv/consts/SA_NODEFER.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_NODEFER,0x40000000,0x10,0x10,0x10,0x10,0 +.syscon sigact,SA_NODEFER,0x40000000,16,16,16,16,0x40000000 diff --git a/libc/sysv/consts/SA_NOMASK.S b/libc/sysv/consts/SA_NOMASK.S index f3ebc2b4c..77d364345 100644 --- a/libc/sysv/consts/SA_NOMASK.S +++ b/libc/sysv/consts/SA_NOMASK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_NOMASK,0x40000000,0x10,0x10,0x10,0x10,0 +.syscon compat,SA_NOMASK,0x40000000,16,16,16,16,0x40000000 diff --git a/libc/sysv/consts/SA_ONESHOT.S b/libc/sysv/consts/SA_ONESHOT.S index b408be2c0..f719357fc 100644 --- a/libc/sysv/consts/SA_ONESHOT.S +++ b/libc/sysv/consts/SA_ONESHOT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_ONESHOT,0x80000000,0,0,0,0,0 +.syscon compat,SA_ONESHOT,0x80000000,4,4,4,4,0x80000000 diff --git a/libc/sysv/consts/SA_ONSTACK.S b/libc/sysv/consts/SA_ONSTACK.S index 7c461f57b..10237f767 100644 --- a/libc/sysv/consts/SA_ONSTACK.S +++ b/libc/sysv/consts/SA_ONSTACK.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_ONSTACK,0x08000000,1,1,1,1,0 +.syscon sigact,SA_ONSTACK,0x08000000,1,1,1,1,0x08000000 diff --git a/libc/sysv/consts/SA_RESETHAND.S b/libc/sysv/consts/SA_RESETHAND.S index 9c697d4a8..57447ed2e 100644 --- a/libc/sysv/consts/SA_RESETHAND.S +++ b/libc/sysv/consts/SA_RESETHAND.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_RESETHAND,0x80000000,4,4,4,4,0 +.syscon sigact,SA_RESETHAND,0x80000000,4,4,4,4,0x80000000 diff --git a/libc/sysv/consts/SA_RESTART.S b/libc/sysv/consts/SA_RESTART.S index 0f36b4a49..4d55eea7e 100644 --- a/libc/sysv/consts/SA_RESTART.S +++ b/libc/sysv/consts/SA_RESTART.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_RESTART,0x10000000,2,2,2,2,0 +.syscon sigact,SA_RESTART,0x10000000,2,2,2,2,0x10000000 diff --git a/libc/sysv/consts/SA_RESTORER.S b/libc/sysv/consts/SA_RESTORER.S deleted file mode 100644 index 7f9491980..000000000 --- a/libc/sysv/consts/SA_RESTORER.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_RESTORER,0x04000000,0,0,0,0,0 diff --git a/libc/sysv/consts/SA_SIGINFO.S b/libc/sysv/consts/SA_SIGINFO.S index 4f1b53071..46ca4be61 100644 --- a/libc/sysv/consts/SA_SIGINFO.S +++ b/libc/sysv/consts/SA_SIGINFO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sigact,SA_SIGINFO,4,0x40,0x40,0x40,0x40,0 +.syscon sigact,SA_SIGINFO,4,64,64,64,64,4 diff --git a/libc/sysv/consts/SEGV_ACCERR.S b/libc/sysv/consts/SEGV_ACCERR.S index cc37aade6..bafc738d8 100644 --- a/libc/sysv/consts/SEGV_ACCERR.S +++ b/libc/sysv/consts/SEGV_ACCERR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SEGV_ACCERR,2,2,2,2,2,0 +.syscon sicode,SEGV_ACCERR,2,2,2,2,2,2 diff --git a/libc/sysv/consts/SEGV_MAPERR.S b/libc/sysv/consts/SEGV_MAPERR.S index f6025fdd4..3f77bd82c 100644 --- a/libc/sysv/consts/SEGV_MAPERR.S +++ b/libc/sysv/consts/SEGV_MAPERR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SEGV_MAPERR,1,1,1,1,1,0 +.syscon sicode,SEGV_MAPERR,1,1,1,1,1,1 diff --git a/libc/sysv/consts/SIGIOT.S b/libc/sysv/consts/SIGIOT.S index b8c19047f..0da16e1b9 100644 --- a/libc/sysv/consts/SIGIOT.S +++ b/libc/sysv/consts/SIGIOT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGIOT,6,6,6,6,6,6 +.syscon compat,SIGIOT,6,6,6,6,6,6 diff --git a/libc/sysv/consts/SIGPOLL.S b/libc/sysv/consts/SIGPOLL.S index 1bdcef26a..9fc61e573 100644 --- a/libc/sysv/consts/SIGPOLL.S +++ b/libc/sysv/consts/SIGPOLL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGPOLL,29,0,0,0,0,29 +.syscon compat,SIGPOLL,29,23,23,23,23,29 diff --git a/libc/sysv/consts/SIGPWR.S b/libc/sysv/consts/SIGPWR.S index 0adb12f32..5d15017a3 100644 --- a/libc/sysv/consts/SIGPWR.S +++ b/libc/sysv/consts/SIGPWR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGPWR,30,0,0,0,32,30 +.syscon compat,SIGPWR,30,30,30,30,32,30 diff --git a/libc/sysv/consts/SIGSTKFLT.S b/libc/sysv/consts/SIGSTKFLT.S deleted file mode 100644 index 7c26a6b74..000000000 --- a/libc/sysv/consts/SIGSTKFLT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGSTKFLT,0x10,0,0,0,0,0x10 diff --git a/libc/sysv/consts/SIGSTKSZ.S b/libc/sysv/consts/SIGSTKSZ.S index 652bf9c05..1a557a4b5 100644 --- a/libc/sysv/consts/SIGSTKSZ.S +++ b/libc/sysv/consts/SIGSTKSZ.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGSTKSZ,0x2000,0x020000,0x8800,0x7000,0x7000,0x2000 +.syscon ss,SIGSTKSZ,0x2000,0x020000,0x8800,0x7000,0x7000,0x2000 diff --git a/libc/sysv/consts/SIGUNUSED.S b/libc/sysv/consts/SIGUNUSED.S deleted file mode 100644 index 9ef68febf..000000000 --- a/libc/sysv/consts/SIGUNUSED.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGUNUSED,31,0,0,0,0,31 diff --git a/libc/sysv/consts/SIGURG.S b/libc/sysv/consts/SIGURG.S index a9c7cc2e1..9dbe9cb7e 100644 --- a/libc/sysv/consts/SIGURG.S +++ b/libc/sysv/consts/SIGURG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon sig,SIGURG,23,0x10,0x10,0x10,0x10,23 +.syscon sig,SIGURG,23,16,16,16,16,23 diff --git a/libc/sysv/consts/SI_ASYNCIO.S b/libc/sysv/consts/SI_ASYNCIO.S index d2782fb59..bc1cfc07d 100644 --- a/libc/sysv/consts/SI_ASYNCIO.S +++ b/libc/sysv/consts/SI_ASYNCIO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_ASYNCIO,-4,0x010004,0x010004,0,0,0 +.syscon sicode,SI_ASYNCIO,-4,0x010004,0x010004,0x80000000,-3,-4 diff --git a/libc/sysv/consts/SI_ASYNCNL.S b/libc/sysv/consts/SI_ASYNCNL.S index b6c952205..090ab2518 100644 --- a/libc/sysv/consts/SI_ASYNCNL.S +++ b/libc/sysv/consts/SI_ASYNCNL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_ASYNCNL,-60,0,0,0,0,0 +.syscon sicode,SI_ASYNCNL,-60,0x80000000,0x80000000,0x80000000,0x80000000,0x80000000 diff --git a/libc/sysv/consts/SI_KERNEL.S b/libc/sysv/consts/SI_KERNEL.S index db6a4ca4c..63c917744 100644 --- a/libc/sysv/consts/SI_KERNEL.S +++ b/libc/sysv/consts/SI_KERNEL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_KERNEL,0x80,0,0x010006,0,0,0 +.syscon sicode,SI_KERNEL,0x80,0x80000000,0x010006,0x80000000,0x80000000,0x80 diff --git a/libc/sysv/consts/SI_LOAD_SHIFT.S b/libc/sysv/consts/SI_LOAD_SHIFT.S deleted file mode 100644 index 1efc6e161..000000000 --- a/libc/sysv/consts/SI_LOAD_SHIFT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_LOAD_SHIFT,0x10,0,0,0,0,0 diff --git a/libc/sysv/consts/SI_MESGQ.S b/libc/sysv/consts/SI_MESGQ.S index b6e439c31..7021509b3 100644 --- a/libc/sysv/consts/SI_MESGQ.S +++ b/libc/sysv/consts/SI_MESGQ.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_MESGQ,-3,0x010005,0x010005,0,0,0 +.syscon sicode,SI_MESGQ,-3,0x010005,0x010005,0x80000000,-4,-3 diff --git a/libc/sysv/consts/SI_NOINFO.S b/libc/sysv/consts/SI_NOINFO.S new file mode 100644 index 000000000..be65136ff --- /dev/null +++ b/libc/sysv/consts/SI_NOINFO.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon sicode,SI_NOINFO,32767,0x80000000,0,32767,32767,32767 diff --git a/libc/sysv/consts/SI_QUEUE.S b/libc/sysv/consts/SI_QUEUE.S index ec9ce4e06..2379cf591 100644 --- a/libc/sysv/consts/SI_QUEUE.S +++ b/libc/sysv/consts/SI_QUEUE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_QUEUE,-1,0x010002,0x010002,-2,-2,0 +.syscon sicode,SI_QUEUE,-1,0x010002,0x010002,-2,-1,-1 diff --git a/libc/sysv/consts/SI_SIGIO.S b/libc/sysv/consts/SI_SIGIO.S deleted file mode 100644 index 6f9717af5..000000000 --- a/libc/sysv/consts/SI_SIGIO.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_SIGIO,-5,0,0,0,0,0 diff --git a/libc/sysv/consts/SI_TIMER.S b/libc/sysv/consts/SI_TIMER.S index 64c46cd1a..bd9120da4 100644 --- a/libc/sysv/consts/SI_TIMER.S +++ b/libc/sysv/consts/SI_TIMER.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_TIMER,-2,0x010003,0x010003,-3,-3,0 +.syscon sicode,SI_TIMER,-2,0x010003,0x010003,-3,-2,-2 diff --git a/libc/sysv/consts/SI_TKILL.S b/libc/sysv/consts/SI_TKILL.S index 6f59973a4..b9802a707 100644 --- a/libc/sysv/consts/SI_TKILL.S +++ b/libc/sysv/consts/SI_TKILL.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_TKILL,-6,0,0,0,0,0 +.syscon sicode,SI_TKILL,-6,0x80000000,0x010007,-1,-5,-6 diff --git a/libc/sysv/consts/SI_USER.S b/libc/sysv/consts/SI_USER.S index d97a740b4..ffc2deea0 100644 --- a/libc/sysv/consts/SI_USER.S +++ b/libc/sysv/consts/SI_USER.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,SI_USER,0,0x010001,0x010001,0,0,0 +.syscon sicode,SI_USER,0,0x010001,0x010001,0,0,0 diff --git a/libc/sysv/consts/S_IEXEC.S b/libc/sysv/consts/S_IEXEC.S index 5e8189256..cec133e38 100644 --- a/libc/sysv/consts/S_IEXEC.S +++ b/libc/sysv/consts/S_IEXEC.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IEXEC,00100,00100,00100,00100,00100,00100 +.syscon stat,S_IEXEC,0000100,0000100,0000100,0000100,0000100,0000100 diff --git a/libc/sysv/consts/S_IREAD.S b/libc/sysv/consts/S_IREAD.S index d42eeedff..5e0bee1c4 100644 --- a/libc/sysv/consts/S_IREAD.S +++ b/libc/sysv/consts/S_IREAD.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IREAD,00400,00400,00400,00400,00400,00400 +.syscon stat,S_IREAD,0000400,0000400,0000400,0000400,0000400,0000400 diff --git a/libc/sysv/consts/S_IRGRP.S b/libc/sysv/consts/S_IRGRP.S index d29b91cae..ad9f3a6f8 100644 --- a/libc/sysv/consts/S_IRGRP.S +++ b/libc/sysv/consts/S_IRGRP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRGRP,00040,00040,00040,00040,00040,00040 +.syscon stat,S_IRGRP,0000040,0000040,0000040,0000040,0000040,0000040 diff --git a/libc/sysv/consts/S_IROTH.S b/libc/sysv/consts/S_IROTH.S index 1492a931b..6179fbf38 100644 --- a/libc/sysv/consts/S_IROTH.S +++ b/libc/sysv/consts/S_IROTH.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IROTH,00004,00004,00004,00004,00004,00004 +.syscon stat,S_IROTH,0000004,0000004,0000004,0000004,0000004,0000004 diff --git a/libc/sysv/consts/S_IRUSR.S b/libc/sysv/consts/S_IRUSR.S index 69802c4cf..7720d0f60 100644 --- a/libc/sysv/consts/S_IRUSR.S +++ b/libc/sysv/consts/S_IRUSR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRUSR,00400,00400,00400,00400,00400,00400 +.syscon stat,S_IRUSR,0000400,0000400,0000400,0000400,0000400,0000400 diff --git a/libc/sysv/consts/S_IRWXG.S b/libc/sysv/consts/S_IRWXG.S index dd2f6f755..e35589566 100644 --- a/libc/sysv/consts/S_IRWXG.S +++ b/libc/sysv/consts/S_IRWXG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXG,00070,00070,00070,00070,00070,00070 +.syscon stat,S_IRWXG,0000070,0000070,0000070,0000070,0000070,0000070 diff --git a/libc/sysv/consts/S_IRWXO.S b/libc/sysv/consts/S_IRWXO.S index 17fb95261..c9a4db418 100644 --- a/libc/sysv/consts/S_IRWXO.S +++ b/libc/sysv/consts/S_IRWXO.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXO,00007,00007,00007,00007,00007,00007 +.syscon stat,S_IRWXO,0000007,0000007,0000007,0000007,0000007,0000007 diff --git a/libc/sysv/consts/S_IRWXU.S b/libc/sysv/consts/S_IRWXU.S index 3be366d68..3a291a499 100644 --- a/libc/sysv/consts/S_IRWXU.S +++ b/libc/sysv/consts/S_IRWXU.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IRWXU,00700,00700,00700,00700,00700,00700 +.syscon stat,S_IRWXU,0000700,0000700,0000700,0000700,0000700,0000700 diff --git a/libc/sysv/consts/S_ISGID.S b/libc/sysv/consts/S_ISGID.S index 3b5294408..108508726 100644 --- a/libc/sysv/consts/S_ISGID.S +++ b/libc/sysv/consts/S_ISGID.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISGID,02000,02000,02000,02000,02000,02000 +.syscon stat,S_ISGID,0002000,0002000,0002000,0002000,0002000,0002000 diff --git a/libc/sysv/consts/S_ISUID.S b/libc/sysv/consts/S_ISUID.S index 796799484..170183946 100644 --- a/libc/sysv/consts/S_ISUID.S +++ b/libc/sysv/consts/S_ISUID.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISUID,04000,04000,04000,04000,04000,04000 +.syscon stat,S_ISUID,0004000,0004000,0004000,0004000,0004000,0004000 diff --git a/libc/sysv/consts/S_ISVTX.S b/libc/sysv/consts/S_ISVTX.S index 5f1251d1c..33636aff5 100644 --- a/libc/sysv/consts/S_ISVTX.S +++ b/libc/sysv/consts/S_ISVTX.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_ISVTX,01000,01000,01000,01000,01000,01000 +.syscon stat,S_ISVTX,0001000,0001000,0001000,0001000,0001000,0001000 diff --git a/libc/sysv/consts/S_IWGRP.S b/libc/sysv/consts/S_IWGRP.S index 22defc1eb..27dd51e4c 100644 --- a/libc/sysv/consts/S_IWGRP.S +++ b/libc/sysv/consts/S_IWGRP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWGRP,00020,00020,00020,00020,00020,00020 +.syscon stat,S_IWGRP,0000020,0000020,0000020,0000020,0000020,0000020 diff --git a/libc/sysv/consts/S_IWOTH.S b/libc/sysv/consts/S_IWOTH.S index c760e0098..61e7b7ae8 100644 --- a/libc/sysv/consts/S_IWOTH.S +++ b/libc/sysv/consts/S_IWOTH.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWOTH,00002,00002,00002,00002,00002,00002 +.syscon stat,S_IWOTH,0000002,0000002,0000002,0000002,0000002,0000002 diff --git a/libc/sysv/consts/S_IWRITE.S b/libc/sysv/consts/S_IWRITE.S index 9663e1a6f..df2360188 100644 --- a/libc/sysv/consts/S_IWRITE.S +++ b/libc/sysv/consts/S_IWRITE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWRITE,00200,00200,00200,00200,00200,00200 +.syscon stat,S_IWRITE,0000200,0000200,0000200,0000200,0000200,0000200 diff --git a/libc/sysv/consts/S_IWUSR.S b/libc/sysv/consts/S_IWUSR.S index e6493ff0b..7df8df706 100644 --- a/libc/sysv/consts/S_IWUSR.S +++ b/libc/sysv/consts/S_IWUSR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IWUSR,00200,00200,00200,00200,00200,00200 +.syscon stat,S_IWUSR,0000200,0000200,0000200,0000200,0000200,0000200 diff --git a/libc/sysv/consts/S_IXGRP.S b/libc/sysv/consts/S_IXGRP.S index 9db4c424b..f23c82907 100644 --- a/libc/sysv/consts/S_IXGRP.S +++ b/libc/sysv/consts/S_IXGRP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXGRP,00010,00010,00010,00010,00010,00010 +.syscon stat,S_IXGRP,0000010,0000010,0000010,0000010,0000010,0000010 diff --git a/libc/sysv/consts/S_IXOTH.S b/libc/sysv/consts/S_IXOTH.S index 74329aeef..ff3cc2474 100644 --- a/libc/sysv/consts/S_IXOTH.S +++ b/libc/sysv/consts/S_IXOTH.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXOTH,00001,00001,00001,00001,00001,00001 +.syscon stat,S_IXOTH,0000001,0000001,0000001,0000001,0000001,0000001 diff --git a/libc/sysv/consts/S_IXUSR.S b/libc/sysv/consts/S_IXUSR.S index d91c11525..fb7f231b5 100644 --- a/libc/sysv/consts/S_IXUSR.S +++ b/libc/sysv/consts/S_IXUSR.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon stat,S_IXUSR,00100,00100,00100,00100,00100,00100 +.syscon stat,S_IXUSR,0000100,0000100,0000100,0000100,0000100,0000100 diff --git a/libc/sysv/consts/TRAP_BRKPT.S b/libc/sysv/consts/TRAP_BRKPT.S index 3dc73994e..a2a5e7b4d 100644 --- a/libc/sysv/consts/TRAP_BRKPT.S +++ b/libc/sysv/consts/TRAP_BRKPT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,TRAP_BRKPT,1,1,1,1,1,0 +.syscon sicode,TRAP_BRKPT,1,1,1,1,1,1 diff --git a/libc/sysv/consts/TRAP_TRACE.S b/libc/sysv/consts/TRAP_TRACE.S index a2b0c356c..1daca2f96 100644 --- a/libc/sysv/consts/TRAP_TRACE.S +++ b/libc/sysv/consts/TRAP_TRACE.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon misc,TRAP_TRACE,2,2,2,2,2,0 +.syscon sicode,TRAP_TRACE,2,2,2,2,2,2 diff --git a/libc/sysv/consts/bus.h b/libc/sysv/consts/bus.h deleted file mode 100644 index e6f9dddac..000000000 --- a/libc/sysv/consts/bus.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_BUS_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_BUS_H_ -#include "libc/runtime/symbolic.h" - -#define BUS_ADRALN SYMBOLIC(BUS_ADRALN) -#define BUS_ADRERR SYMBOLIC(BUS_ADRERR) -#define BUS_DEVICE_RESET SYMBOLIC(BUS_DEVICE_RESET) -#define BUS_MCEERR_AO SYMBOLIC(BUS_MCEERR_AO) -#define BUS_MCEERR_AR SYMBOLIC(BUS_MCEERR_AR) -#define BUS_OBJERR SYMBOLIC(BUS_OBJERR) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long BUS_ADRALN; -extern const long BUS_ADRERR; -extern const long BUS_DEVICE_RESET; -extern const long BUS_MCEERR_AO; -extern const long BUS_MCEERR_AR; -extern const long BUS_OBJERR; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_BUS_H_ */ diff --git a/libc/sysv/consts/cld.h b/libc/sysv/consts/cld.h deleted file mode 100644 index 9dd866ea9..000000000 --- a/libc/sysv/consts/cld.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_ - -#define CLD_CONTINUED 6 -#define CLD_DUMPED 3 -#define CLD_EXITED 1 -#define CLD_KILLED 2 -#define CLD_STOPPED 5 -#define CLD_TRAPPED 4 - -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_ */ diff --git a/libc/sysv/consts/ill.h b/libc/sysv/consts/ill.h deleted file mode 100644 index 141f3e391..000000000 --- a/libc/sysv/consts/ill.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_ILL_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_ILL_H_ -#include "libc/runtime/symbolic.h" - -#define ILL_BADSTK SYMBOLIC(ILL_BADSTK) -#define ILL_COPROC SYMBOLIC(ILL_COPROC) -#define ILL_ILLADR SYMBOLIC(ILL_ILLADR) -#define ILL_ILLOPC SYMBOLIC(ILL_ILLOPC) -#define ILL_ILLOPN SYMBOLIC(ILL_ILLOPN) -#define ILL_ILLTRP SYMBOLIC(ILL_ILLTRP) -#define ILL_PRVOPC SYMBOLIC(ILL_PRVOPC) -#define ILL_PRVREG SYMBOLIC(ILL_PRVREG) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long ILL_BADSTK; -extern const long ILL_COPROC; -extern const long ILL_ILLADR; -extern const long ILL_ILLOPC; -extern const long ILL_ILLOPN; -extern const long ILL_ILLTRP; -extern const long ILL_PRVOPC; -extern const long ILL_PRVREG; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_ILL_H_ */ diff --git a/libc/sysv/consts/rlimit.h b/libc/sysv/consts/rlimit.h index 1ab7163ac..c847974e4 100644 --- a/libc/sysv/consts/rlimit.h +++ b/libc/sysv/consts/rlimit.h @@ -2,22 +2,22 @@ #define COSMOPOLITAN_LIBC_SYSV_CONSTS_RLIMIT_H_ #include "libc/runtime/symbolic.h" -#define RLIMIT_AS SYMBOLIC(RLIMIT_AS) -#define RLIMIT_CORE SYMBOLIC(RLIMIT_CORE) -#define RLIMIT_CPU SYMBOLIC(RLIMIT_CPU) -#define RLIMIT_DATA SYMBOLIC(RLIMIT_DATA) -#define RLIMIT_FSIZE SYMBOLIC(RLIMIT_FSIZE) -#define RLIMIT_LOCKS SYMBOLIC(RLIMIT_LOCKS) -#define RLIMIT_MEMLOCK SYMBOLIC(RLIMIT_MEMLOCK) -#define RLIMIT_MSGQUEUE SYMBOLIC(RLIMIT_MSGQUEUE) -#define RLIMIT_NICE SYMBOLIC(RLIMIT_NICE) -#define RLIMIT_NLIMITS SYMBOLIC(RLIMIT_NLIMITS) -#define RLIMIT_NOFILE SYMBOLIC(RLIMIT_NOFILE) -#define RLIMIT_NPROC SYMBOLIC(RLIMIT_NPROC) -#define RLIMIT_RSS SYMBOLIC(RLIMIT_RSS) -#define RLIMIT_RTPRIO SYMBOLIC(RLIMIT_RTPRIO) +#define RLIMIT_AS SYMBOLIC(RLIMIT_AS) +#define RLIMIT_CORE SYMBOLIC(RLIMIT_CORE) +#define RLIMIT_CPU SYMBOLIC(RLIMIT_CPU) +#define RLIMIT_DATA SYMBOLIC(RLIMIT_DATA) +#define RLIMIT_FSIZE SYMBOLIC(RLIMIT_FSIZE) +#define RLIMIT_LOCKS SYMBOLIC(RLIMIT_LOCKS) +#define RLIMIT_MEMLOCK SYMBOLIC(RLIMIT_MEMLOCK) +#define RLIMIT_MSGQUEUE SYMBOLIC(RLIMIT_MSGQUEUE) +#define RLIMIT_NICE SYMBOLIC(RLIMIT_NICE) +#define RLIMIT_NOFILE SYMBOLIC(RLIMIT_NOFILE) +#define RLIMIT_NPROC SYMBOLIC(RLIMIT_NPROC) +#define RLIMIT_RSS SYMBOLIC(RLIMIT_RSS) +#define RLIMIT_RTPRIO SYMBOLIC(RLIMIT_RTPRIO) #define RLIMIT_SIGPENDING SYMBOLIC(RLIMIT_SIGPENDING) -#define RLIMIT_STACK SYMBOLIC(RLIMIT_STACK) +#define RLIMIT_STACK SYMBOLIC(RLIMIT_STACK) +#define RLIMIT_VMEM SYMBOLIC(RLIMIT_VMEM) #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -31,13 +31,13 @@ extern const long RLIMIT_LOCKS; extern const long RLIMIT_MEMLOCK; extern const long RLIMIT_MSGQUEUE; extern const long RLIMIT_NICE; -extern const long RLIMIT_NLIMITS; extern const long RLIMIT_NOFILE; extern const long RLIMIT_NPROC; extern const long RLIMIT_RSS; extern const long RLIMIT_RTPRIO; extern const long RLIMIT_SIGPENDING; extern const long RLIMIT_STACK; +extern const long RLIMIT_VMEM; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/sysv/consts/s.h b/libc/sysv/consts/s.h index e1ac2f0c2..07b2ae6bc 100644 --- a/libc/sysv/consts/s.h +++ b/libc/sysv/consts/s.h @@ -1,64 +1,32 @@ #ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_ #define COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_ -#include "libc/runtime/symbolic.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ -extern const long S_IEXEC; -extern const long S_IFBLK; -extern const long S_IFCHR; -extern const long S_IFDIR; -extern const long S_IFIFO; -extern const long S_IFLNK; -extern const long S_IFMT; -extern const long S_IFREG; -extern const long S_IFSOCK; -extern const long S_IREAD; -extern const long S_IRGRP; -extern const long S_IROTH; -extern const long S_IRUSR; -extern const long S_IRWXG; -extern const long S_IRWXO; -extern const long S_IRWXU; -extern const long S_ISGID; -extern const long S_ISUID; -extern const long S_ISVTX; -extern const long S_IWGRP; -extern const long S_IWOTH; -extern const long S_IWRITE; -extern const long S_IWUSR; -extern const long S_IXGRP; -extern const long S_IXOTH; -extern const long S_IXUSR; +#define S_ISVTX 01000 /* THE STICKY BIT */ +#define S_ISGID 02000 /* the setgid bit */ +#define S_ISUID 04000 /* the setuid bit */ +#define S_IXUSR 00100 /* user --x; just use octal */ +#define S_IWUSR 00200 /* user -w-; just use octal */ +#define S_IRUSR 00400 /* user r--; just use octal */ +#define S_IRWXU 00700 /* user rwx; just use octal */ +#define S_IXGRP 00010 /* group --x; just use octal */ +#define S_IWGRP 00020 /* group -w-; just use octal */ +#define S_IRGRP 00040 /* group r--; just use octal */ +#define S_IRWXG 00070 /* group rwx; just use octal */ +#define S_IXOTH 00001 /* other --x; just use octal */ +#define S_IWOTH 00002 /* other -w-; just use octal */ +#define S_IROTH 00004 /* other r--; just use octal */ +#define S_IRWXO 00007 /* other rwx; just use octal */ +#define S_IREAD 00400 /* just use octal */ +#define S_IEXEC 00100 /* just use octal */ +#define S_IWRITE 00200 /* just use octal */ -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ - -#define S_IFREG LITERALLY(0100000) -#define S_IFBLK LITERALLY(0060000) -#define S_IFCHR LITERALLY(0020000) -#define S_IFDIR LITERALLY(0040000) -#define S_IFIFO LITERALLY(0010000) -#define S_IFMT LITERALLY(0170000) -#define S_IFLNK LITERALLY(0120000) -#define S_IFSOCK LITERALLY(0140000) -#define S_ISVTX LITERALLY(01000) -#define S_ISGID LITERALLY(02000) -#define S_ISUID LITERALLY(04000) -#define S_IEXEC LITERALLY(00100) -#define S_IWRITE LITERALLY(00200) -#define S_IREAD LITERALLY(00400) -#define S_IXUSR LITERALLY(00100) -#define S_IWUSR LITERALLY(00200) -#define S_IRUSR LITERALLY(00400) -#define S_IRWXU LITERALLY(00700) -#define S_IXGRP LITERALLY(00010) -#define S_IWGRP LITERALLY(00020) -#define S_IRGRP LITERALLY(00040) -#define S_IRWXG LITERALLY(00070) -#define S_IXOTH LITERALLY(00001) -#define S_IWOTH LITERALLY(00002) -#define S_IROTH LITERALLY(00004) -#define S_IRWXO LITERALLY(00007) +#define S_IFIFO (1 << 12) /* pipe */ +#define S_IFCHR (2 << 12) /* character device */ +#define S_IFDIR (4 << 12) /* directory */ +#define S_IFBLK (6 << 12) /* block device */ +#define S_IFREG (8 << 12) /* regular file */ +#define S_IFLNK (10 << 12) /* symbolic link */ +#define S_IFSOCK (12 << 12) /* socket */ +#define S_IFMT (15 << 12) /* mask of file types above */ #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_S_H_ */ diff --git a/libc/sysv/consts/sa.h b/libc/sysv/consts/sa.h index b175276b4..aa85f7660 100644 --- a/libc/sysv/consts/sa.h +++ b/libc/sysv/consts/sa.h @@ -4,14 +4,13 @@ #define SA_NOCLDSTOP SYMBOLIC(SA_NOCLDSTOP) #define SA_NOCLDWAIT SYMBOLIC(SA_NOCLDWAIT) -#define SA_NODEFER SYMBOLIC(SA_NODEFER) -#define SA_NOMASK SYMBOLIC(SA_NOMASK) -#define SA_ONESHOT SYMBOLIC(SA_ONESHOT) -#define SA_ONSTACK SYMBOLIC(SA_ONSTACK) +#define SA_NODEFER SYMBOLIC(SA_NODEFER) +#define SA_NOMASK SYMBOLIC(SA_NOMASK) +#define SA_ONESHOT SYMBOLIC(SA_ONESHOT) +#define SA_ONSTACK SYMBOLIC(SA_ONSTACK) #define SA_RESETHAND SYMBOLIC(SA_RESETHAND) -#define SA_RESTART SYMBOLIC(SA_RESTART) -#define SA_RESTORER SYMBOLIC(SA_RESTORER) -#define SA_SIGINFO SYMBOLIC(SA_SIGINFO) +#define SA_RESTART SYMBOLIC(SA_RESTART) +#define SA_SIGINFO SYMBOLIC(SA_SIGINFO) #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ @@ -24,7 +23,6 @@ extern const long SA_ONESHOT; extern const long SA_ONSTACK; extern const long SA_RESETHAND; extern const long SA_RESTART; -extern const long SA_RESTORER; extern const long SA_SIGINFO; COSMOPOLITAN_C_END_ diff --git a/libc/sysv/consts/segv.h b/libc/sysv/consts/segv.h deleted file mode 100644 index 711fb69fd..000000000 --- a/libc/sysv/consts/segv.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_SEGV_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_SEGV_H_ -#include "libc/runtime/symbolic.h" - -#define SEGV_ACCERR SYMBOLIC(SEGV_ACCERR) -#define SEGV_MAPERR SYMBOLIC(SEGV_MAPERR) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long SEGV_ACCERR; -extern const long SEGV_MAPERR; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_SEGV_H_ */ diff --git a/libc/sysv/consts/sicode.h b/libc/sysv/consts/sicode.h new file mode 100644 index 000000000..11922b88d --- /dev/null +++ b/libc/sysv/consts/sicode.h @@ -0,0 +1,105 @@ +#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_SICODE_H_ +#define COSMOPOLITAN_LIBC_SYSV_CONSTS_SICODE_H_ +#include "libc/runtime/symbolic.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +extern const long SI_USER; +extern const long SI_QUEUE; +extern const long SI_TIMER; +extern const long SI_MESGQ; +extern const long SI_ASYNCIO; +extern const long SI_TKILL; +extern const long SI_ASYNCNL; +extern const long SI_KERNEL; +extern const long SI_NOINFO; +extern const long CLD_EXITED; +extern const long CLD_KILLED; +extern const long CLD_DUMPED; +extern const long CLD_TRAPPED; +extern const long CLD_STOPPED; +extern const long CLD_CONTINUED; +extern const long TRAP_BRKPT; +extern const long TRAP_TRACE; +extern const long SEGV_MAPERR; +extern const long SEGV_ACCERR; +extern const long FPE_INTDIV; +extern const long FPE_INTOVF; +extern const long FPE_FLTDIV; +extern const long FPE_FLTOVF; +extern const long FPE_FLTUND; +extern const long FPE_FLTRES; +extern const long FPE_FLTINV; +extern const long FPE_FLTSUB; +extern const long ILL_ILLOPC; +extern const long ILL_ILLOPN; +extern const long ILL_ILLADR; +extern const long ILL_ILLTRP; +extern const long ILL_PRVOPC; +extern const long ILL_PRVREG; +extern const long ILL_COPROC; +extern const long ILL_BADSTK; +extern const long BUS_ADRALN; +extern const long BUS_ADRERR; +extern const long BUS_OBJERR; +extern const long BUS_MCEERR_AR; +extern const long BUS_MCEERR_AO; +extern const long POLL_IN; +extern const long POLL_OUT; +extern const long POLL_MSG; +extern const long POLL_ERR; +extern const long POLL_PRI; +extern const long POLL_HUP; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ + +#define CLD_EXITED LITERALLY(1) +#define CLD_KILLED LITERALLY(2) +#define CLD_DUMPED LITERALLY(3) +#define CLD_TRAPPED LITERALLY(4) +#define CLD_STOPPED LITERALLY(5) +#define CLD_CONTINUED LITERALLY(6) +#define TRAP_BRKPT LITERALLY(1) +#define TRAP_TRACE LITERALLY(2) +#define SEGV_MAPERR LITERALLY(1) +#define SEGV_ACCERR LITERALLY(2) +#define ILL_ILLOPC LITERALLY(1) +#define ILL_PRVREG LITERALLY(6) +#define ILL_COPROC LITERALLY(7) +#define ILL_BADSTK LITERALLY(8) +#define BUS_ADRALN LITERALLY(1) +#define BUS_ADRERR LITERALLY(2) +#define BUS_OBJERR LITERALLY(3) +#define POLL_IN LITERALLY(1) +#define POLL_OUT LITERALLY(2) +#define POLL_MSG LITERALLY(3) +#define POLL_ERR LITERALLY(4) +#define POLL_PRI LITERALLY(5) +#define POLL_HUP LITERALLY(6) + +#define SI_USER SYMBOLIC(SI_USER) +#define SI_QUEUE SYMBOLIC(SI_QUEUE) +#define SI_TIMER SYMBOLIC(SI_TIMER) +#define SI_MESGQ SYMBOLIC(SI_MESGQ) +#define SI_ASYNCIO SYMBOLIC(SI_ASYNCIO) +#define SI_TKILL SYMBOLIC(SI_TKILL) +#define SI_ASYNCNL SYMBOLIC(SI_ASYNCNL) +#define SI_KERNEL SYMBOLIC(SI_KERNEL) +#define SI_NOINFO SYMBOLIC(SI_NOINFO) +#define FPE_INTDIV SYMBOLIC(FPE_INTDIV) +#define FPE_INTOVF SYMBOLIC(FPE_INTOVF) +#define FPE_FLTDIV SYMBOLIC(FPE_FLTDIV) +#define FPE_FLTOVF SYMBOLIC(FPE_FLTOVF) +#define FPE_FLTUND SYMBOLIC(FPE_FLTUND) +#define FPE_FLTRES SYMBOLIC(FPE_FLTRES) +#define FPE_FLTINV SYMBOLIC(FPE_FLTINV) +#define FPE_FLTSUB SYMBOLIC(FPE_FLTSUB) +#define ILL_ILLOPN SYMBOLIC(ILL_ILLOPN) +#define ILL_ILLADR SYMBOLIC(ILL_ILLADR) +#define ILL_ILLTRP SYMBOLIC(ILL_ILLTRP) +#define ILL_PRVOPC SYMBOLIC(ILL_PRVOPC) +#define BUS_MCEERR_AR SYMBOLIC(BUS_MCEERR_AR) +#define BUS_MCEERR_AO SYMBOLIC(BUS_MCEERR_AO) + +#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_SICODE_H_ */ diff --git a/libc/sysv/consts/sigpoll.h b/libc/sysv/consts/sigpoll.h deleted file mode 100644 index 8c4258648..000000000 --- a/libc/sysv/consts/sigpoll.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_POLL_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_POLL_H_ -#include "libc/runtime/symbolic.h" - -#define POLL_ERR SYMBOLIC(POLL_ERR) -#define POLL_HUP SYMBOLIC(POLL_HUP) -#define POLL_IN SYMBOLIC(POLL_IN) -#define POLL_MSG SYMBOLIC(POLL_MSG) -#define POLL_OUT SYMBOLIC(POLL_OUT) -#define POLL_PRI SYMBOLIC(POLL_PRI) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long POLL_ERR; -extern const long POLL_HUP; -extern const long POLL_IN; -extern const long POLL_MSG; -extern const long POLL_OUT; -extern const long POLL_PRI; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_POLL_H_ */ diff --git a/libc/sysv/consts/trap.h b/libc/sysv/consts/trap.h deleted file mode 100644 index b0f6d8fca..000000000 --- a/libc/sysv/consts/trap.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_TRAP_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_TRAP_H_ -#include "libc/runtime/symbolic.h" - -#define TRAP_BRKPT SYMBOLIC(TRAP_BRKPT) -#define TRAP_TRACE SYMBOLIC(TRAP_TRACE) - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long TRAP_BRKPT; -extern const long TRAP_TRACE; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_TRAP_H_ */ diff --git a/libc/sysv/netbsd.py b/libc/sysv/netbsd.py deleted file mode 100644 index cb97b60a5..000000000 --- a/libc/sysv/netbsd.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import re -import sys -NETBSD = {} -MAXBIT = 0 - -def bsr(x): - r = -1 - while x: - r += 1 - x >>= 1 - return r - -def binify(x): - return "%016x" % (x) - -lines = open('libc/sysv/netbsd.txt').read().split('\n') -for line in lines: - if 'STD' not in line: continue - m = re.search(r'^(\d+).*?([_0-9A-Za-z]+)\(', line) - if not m: continue - NETBSD[m.group(2)] = int(m.group(1)) - -lines = open('libc/sysv/syscalls.sh').read().split('\n') -for line in lines: - if line.startswith('scall'): - fields = line.split() - name = fields[1] - if name.startswith("'"): name = name[1:] - if name.endswith("'"): name = name[:-1] - if name.startswith("__"): name = name[2:] - if name.startswith("sys_"): name = name[4:] - if name.endswith("_bsd"): name = name[:-4] - if name.endswith("_freebsd"): name = name[:-8] - numbas = fields[2][2:] - numbers = int(numbas, 16) - systemd = (numbers >> 000) & 0xffff - xnu = (numbers >> 020) & 0x0fff - xnukind = (numbers >> 034) & 0xf - freebsd = (numbers >> 040) & 0xffff - openbsd = (numbers >> 060) & 0xffff - netbsd = NETBSD.get(name, 0xffff) - com = "" - if netbsd != 0xffff: - if netbsd == systemd: com += " SYSTEMD" - if netbsd == xnu: com += " xnu" - if netbsd == freebsd: com += " freebsd" - if netbsd == openbsd: com += " openbsd" - getbit = lambda x: 0 if x == 0xffff else bsr(x) - maxbit = max([getbit(systemd), getbit(xnu), getbit(freebsd), getbit(openbsd), getbit(netbsd)]) - MAXBIT = max(maxbit, MAXBIT) - # print "%-30s %04x %04x %04x %04x %04x %3d %3d %s" % (name, systemd, xnu, freebsd, openbsd, netbsd, maxbit, MAXBIT, com) - systemd &= 0b111111111111 - xnu &= 0b111111111111 - freebsd &= 0b111111111111 - openbsd &= 0b111111111111 - netbsd &= 0b111111111111 - numba = netbsd << (4*13) | openbsd << (4*10) | freebsd << (4*7) | xnukind << (4*6) | xnu << (4*3) | systemd - assert numbas in line - line = line.replace(numbas, binify(numba)) - print line diff --git a/libc/sysv/newconsts.py b/libc/sysv/newconsts.py deleted file mode 100644 index 7285ef653..000000000 --- a/libc/sysv/newconsts.py +++ /dev/null @@ -1,74 +0,0 @@ -import sys - -H = '/home/jart/vendor/netbsd/sys/sys/spawn.h' -G = 'errno' - -MAGNUMS = {} - -def ParseInt(x): - s = 1 - if x.startswith('-'): - x = x[1:] - s = -1 - if x.startswith('0x'): - x = int(x[2:], 16) - elif x.startswith('0b'): - x = int(x[2:], 2) - elif x.startswith('0'): - x = int(x, 8) - else: - x = int(x, 10) - return x * s - -def FormatInt(x): - if x == -1: - return "-1" - if -128 <= x < 128: - return "%d" % (x) - else: - return "%#x" % (x) - -for line in open(H): - if line.startswith('#define'): - a = line.split() - if len(a) >= 3: - try: - MAGNUMS[a[1]] = ParseInt(a[2]) - except ValueError: - pass - -GROUP_COLUMN = 2 -NAME_COLUMN = 4 -SYSTEMD_COLUMN = 6 -XNU_COLUMN = 8 -FREEBSD_COLUMN = 10 -OPENBSD_COLUMN = 12 -NETBSD_COLUMN = 14 - -print """\ -# The Fifth Bell System, Community Edition -# > catalogue of carnage -# -# group name GNU/Systemd XNU's Not UNIX FreeBSD OpenBSD NetBSD XENIX Commentary""" - -for line in open('libc/sysv/consts.sh'): - if not line.startswith('syscon'): continue - fields = [""] - i = 0 - t = 0 - for i in range(len(line)): - if t == 0: - if line[i] == '\t': - fields.append("") - t = 1 - elif t == 1: - if line[i] != '\t': - fields.append("") - t = 0 - fields[-1] = fields[-1] + line[i] - k = fields[NAME_COLUMN] - v = ParseInt(fields[NETBSD_COLUMN]) - if k in MAGNUMS and MAGNUMS[k] != v: - fields[NETBSD_COLUMN] = FormatInt(MAGNUMS[k]) - # if fields[GROUP_COLUMN] == G: - sys.stdout.write("".join(fields)) diff --git a/libc/sysv/nr.py b/libc/sysv/nr.py deleted file mode 100644 index 138b11798..000000000 --- a/libc/sysv/nr.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -lines = open('libc/sysv/syscalls.sh').read().split('\n') -for line in lines: - if not line.startswith('scall'): - continue - fields = line.split() - name = fields[1] - if name.startswith("'"): name = name[1:] - if name.endswith("'"): name = name[:-1] - if name.startswith("__"): name = name[2:] - if name.startswith("sys_"): name = name[4:] - if name.endswith("_bsd"): name = name[:-4] - if name.endswith("_freebsd"): name = name[:-8] - numbers = int(fields[2][2:], 16) - systemd = (numbers >> 000) & 0xffff - xnu = (numbers >> 020) & 0x0fff | ((numbers >> 28) & 0xf) << 20 - freebsd = (numbers >> 040) & 0xffff - openbsd = (numbers >> 060) & 0xffff - print "syscon\tnr\t__NR_%s\t\t\t\t0x%04x\t\t\t0x%07x\t\t0x%04x\t\t\t0x%04x\t\t\t-1" % (name, systemd, xnu, freebsd, openbsd) diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index fd9ac3c22..09976ccae 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -61,7 +61,7 @@ scall sys_select 0x1a104705d205d017 globl hidden scall pselect 0x1b406e20a218afff globl scall pselect6 0xfffffffffffff10e globl scall sys_sched_yield 0x15e12a14b103c018 globl hidden # swtch() on xnu -scall sys_mremap 0x19bffffffffff019 globl hidden +scall __sys_mremap 0x19bffffffffff019 globl hidden scall mincore 0x04e04e04e204e01b globl scall sys_madvise 0x04b04b04b204b01c globl hidden scall shmget 0x0e71210e7210901d globl # consider mmap @@ -95,7 +95,7 @@ scall sys_fork 0x0020020022002039 globl hidden # xnu needs eax&=~-edx bc eax al #scall vfork 0x042042042204203a globl # this syscall is from the moon so we implement it by hand in libc/calls/hefty/vfork.S scall sys_posix_spawn 0xfffffffff20f4fff globl hidden # good luck figuring out how xnu defines this scall __sys_execve 0x03b03b03b203b03b globl hidden -scall sys_wait4 0x1c100b007200703d globl hidden +scall __sys_wait4 0x1c100b007200703d globl hidden scall sys_kill 0x02507a025202503e globl hidden # kill(pid, sig, 1) b/c xnu scall sys_killpg 0xffffff092fffffff globl hidden scall clone 0xfffffffffffff038 globl @@ -137,7 +137,7 @@ scall sys_lchown 0x1130fe0fe216c05e globl hidden # impl. w/ fchownat() scall umask 0x03c03c03c203c05f globl scall sys_gettimeofday 0x1a20430742074060 globl hidden # xnu esi/edx=0 scall sys_getrlimit 0x0c20c20c220c2061 globl hidden -scall sys_getrusage 0x1bd0130752075062 globl hidden +scall __sys_getrusage 0x1bd0130752075062 globl hidden scall sys_sysinfo 0xfffffffffffff063 globl hidden scall sys_times 0xfffffffffffff064 globl hidden scall sys_ptrace 0x01a01a01a201a065 globl hidden @@ -190,7 +190,8 @@ scall setfsgid 0xfffffffffffff07b globl scall capget 0xfffffffffffff07d globl scall capset 0xfffffffffffff07e globl scall sigtimedwait 0xffffff159ffff080 globl -scall rt_sigqueueinfo 0xfffffffffffff081 globl +scall sys_sigqueue 0xffffff1c8fffffff globl +scall sys_sigqueueinfo 0x0f5ffffffffff081 globl # rt_sigqueueinfo on linux scall personality 0xfffffffffffff087 globl scall ustat 0xfffffffffffff088 globl scall sysfs 0xfffffffffffff08b globl @@ -254,6 +255,11 @@ scall timer_settime 0x1beffffffffff0df globl scall timer_gettime 0x1bfffffffffff0e0 globl scall timer_getoverrun 0x0efffffffffff0e1 globl scall timer_delete 0x0ecffffffffff0e2 globl +scall ktimer_create 0xffffff0ebfffffff globl +scall ktimer_delete 0xffffff0ecfffffff globl +scall ktimer_getoverrun 0xffffff0effffffff globl +scall ktimer_gettime 0xffffff0eefffffff globl +scall ktimer_settime 0xffffff0edfffffff globl scall clock_settime 0x1ac0580e9ffff0e3 globl scall sys_clock_gettime 0x1ab0570e8ffff0e4 globl hidden # Linux 2.6+ (c. 2003); XNU uses magic address scall clock_getres 0x1ad0590eaffff0e5 globl @@ -690,11 +696,6 @@ scall ksem_timedwait 0xffffff1b9fffffff globl scall ksem_trywait 0xffffff193fffffff globl scall ksem_unlink 0xffffff196fffffff globl scall ksem_wait 0xffffff192fffffff globl -scall ktimer_create 0xffffff0ebfffffff globl -scall ktimer_delete 0xffffff0ecfffffff globl -scall ktimer_getoverrun 0xffffff0effffffff globl -scall ktimer_gettime 0xffffff0eefffffff globl -scall ktimer_settime 0xffffff0edfffffff globl scall lchflags 0x130fff187fffffff globl scall lchmod 0x112fff112fffffff globl scall lgetfh 0xffffff0a0fffffff globl @@ -734,7 +735,6 @@ scall setfib 0xffffff0affffffff globl scall sethostid 0xffffff08ffffffff globl scall setloginclass 0xffffff20cfffffff globl scall sigblock 0xffffff06dfffffff globl -scall sigqueue 0xffffff1c8fffffff globl scall sigsetmask 0xffffff06efffffff globl scall sigstack 0xffffff070fffffff globl scall sigvec 0xffffff06cfffffff globl diff --git a/libc/sysv/versions.txt b/libc/sysv/versions.txt deleted file mode 100644 index a99dd23e9..000000000 --- a/libc/sysv/versions.txt +++ /dev/null @@ -1,12 +0,0 @@ -1993 FreeBSD 1.o -1994 FreeBSD 2 -1998 FreeBSD 3 -2000 FreeBSD 4 (EOL 2007) -2003 FreeBSD 5 -2005 FreeBSD 6 -2008 FreeBSD 7 (EOL 2013) -2009 FreeBSD 8 (EOL 2015) -2012 FreeBSD 9 (EOL 2016) -2014 FreeBSD 10 (EOL 2018) -2016 FreeBSD 11 -2018 FreeBSD 12 diff --git a/libc/x/x.h b/libc/x/x.h index a5b6199a9..dd359878f 100644 --- a/libc/x/x.h +++ b/libc/x/x.h @@ -36,7 +36,8 @@ char *xasprintf(const char *, ...) printfesque(1) paramsnonnull((1)) _XMAL; char *xvasprintf(const char *, va_list) _XPNN _XMAL; char *xgetline(struct FILE *) _XPNN mallocesque; void *xmalloc(size_t) attributeallocsize((1)) _XMAL; -void *xrealloc(void *, size_t) attributeallocsize((2)) _XRET; +void *xrealloc(void *, size_t) + attributeallocsize((2)) nothrow nocallback nodiscard; void *xcalloc(size_t, size_t) attributeallocsize((1, 2)) _XMAL; void *xvalloc(size_t) attributeallocsize((1)) _XMALPG; void *xmemalign(size_t, size_t) attributeallocalign((1)) diff --git a/libc/x/xrealloc.c b/libc/x/xrealloc.c index 4318b43bc..f61cace06 100644 --- a/libc/x/xrealloc.c +++ b/libc/x/xrealloc.c @@ -21,13 +21,23 @@ #include "libc/x/x.h" /** - * Relocates, extends, and/or shrinks memory──or die. + * Allocates/expands/shrinks/frees memory, or die. * - * This API is fabulous since it categorically eliminates an extremely - * common type of memory bug, by simply redefining it as a crash. + * This API enables you to do the following: + * + * p = xrealloc(p, n) + * + * The standard behaviors for realloc() still apply: + * + * - `!p` means xmalloc (returns non-NULL) + * - `p && n` means resize (returns non-NULL) + * - `p && !n` means free (returns NULL) + * + * The complexity of resizing is guaranteed to be amortized. */ -void *xrealloc(void *p1, size_t newsize) { - void *p2 = realloc(p1, newsize); - if (!p2) xdie(); - return p2; +void *xrealloc(void *p, size_t n) { + void *q; + q = realloc(p, n); + if (!q && !(p && !n)) xdie(); + return q; } diff --git a/libc/zip.h b/libc/zip.h index 619dfcf3b..4c999ecb0 100644 --- a/libc/zip.h +++ b/libc/zip.h @@ -10,7 +10,7 @@ #define kZipAlign 2 -#define kZipCosmopolitanVersion 20 +#define kZipCosmopolitanVersion kZipEra2001 #define kZipOsDos 0 #define kZipOsAmiga 1 @@ -37,8 +37,8 @@ #define kZipEra1993 20 /* PKZIP 2.0: deflate/subdir/etc. support */ #define kZipEra2001 45 /* PKZIP 4.5: kZipExtraZip64 support */ -#define kZipIattrBinary 0 -#define kZipIattrAscii 1 +#define kZipIattrBinary 0 /* first bit not set */ +#define kZipIattrText 1 /* first bit set */ #define kZipCompressionNone 0 #define kZipCompressionDeflate 8 @@ -49,6 +49,9 @@ #define kZipCdirHdrLinkableSize \ ROUNDUP(kZipCfileHdrMinSize + PATH_MAX, kZipCdirAlign) +#define kZipCdir64HdrMagic 0x06064b50 /* PK♣♠ "PK\6\6" */ +#define kZipCdir64HdrMinSize 56 + #define kZipCfileHdrMagic 0x02014b50 /* PK☺☻ "PK\1\2" */ #define kZipCfileHdrMinSize 46 #define kZipCfileOffsetGeneralflag 8 @@ -73,10 +76,12 @@ #define kZipGflagUtf8 0x800 -#define kZipExtraHdrSize 4 -#define kZipExtraZip64 0x0001 -#define kZipExtraNtfs 0x000a -#define kZipExtraExtendedTimestamp 0x5455 +#define kZipExtraHdrSize 4 +#define kZipExtraZip64 0x0001 +#define kZipExtraNtfs 0x000a +#define kZipExtraUnix 0x000d +#define kZipExtraExtendedTimestamp 0x5455 +#define kZipExtraInfoZipNewUnixExtra 0x7875 #define kZipCfileMagic "PK\001\002" @@ -91,15 +96,30 @@ #define ZIP_CDIR_SIZE(P) READ32LE((P) + 12) #define ZIP_CDIR_OFFSET(P) READ32LE((P) + 16) #define ZIP_CDIR_COMMENTSIZE(P) READ16LE((P) + 20) -#define ZIP_CDIR_COMMENT(P) (&(P)[22]) +#define ZIP_CDIR_COMMENT(P) ((P) + 22) /* recommend stopping at nul */ #define ZIP_CDIR_HDRSIZE(P) (ZIP_CDIR_COMMENTSIZE(P) + kZipCdirHdrMinSize) +/* zip64 end of central directory record */ +#define ZIP_CDIR64_MAGIC(P) READ32LE(P) +#define ZIP_CDIR64_HDRSIZE(P) (READ64LE((P) + 4) + 12) +#define ZIP_CDIR64_VERSIONMADE(P) READ16LE((P) + 12) +#define ZIP_CDIR64_VERSIONNEED(P) READ16LE((P) + 14) +#define ZIP_CDIR64_DISK(P) READ32LE((P) + 16) +#define ZIP_CDIR64_STARTINGDISK(P) READ32LE((P) + 20) +#define ZIP_CDIR64_RECORDSONDISK(P) READ64LE((P) + 24) +#define ZIP_CDIR64_RECORDS(P) READ64LE((P) + 32) +#define ZIP_CDIR64_SIZE(P) READ64LE((P) + 40) +#define ZIP_CDIR64_OFFSET(P) READ64LE((P) + 48) +#define ZIP_CDIR64_COMMENTSIZE(P) \ + (ZIP_CDIR64_HDRSIZE(P) >= 56 ? ZIP_CDIR64_HDRSIZE(P) - 56 : 0) +#define ZIP_CDIR64_COMMENT(P) ((P) + 56) /* recommend stopping at nul */ + /* central directory file header */ #define ZIP_CFILE_MAGIC(P) READ32LE(P) -#define ZIP_CFILE_VERSIONMADE(P) ((P)[4]) -#define ZIP_CFILE_FILEATTRCOMPAT(P) ((P)[5]) -#define ZIP_CFILE_VERSIONNEED(P) ((P)[6]) -#define ZIP_CFILE_OSNEED(P) ((P)[7]) +#define ZIP_CFILE_VERSIONMADE(P) (255 & (P)[4]) +#define ZIP_CFILE_FILEATTRCOMPAT(P) (255 & (P)[5]) +#define ZIP_CFILE_VERSIONNEED(P) (255 & (P)[6]) +#define ZIP_CFILE_OSNEED(P) (255 & (P)[7]) #define ZIP_CFILE_GENERALFLAG(P) READ16LE((P) + kZipCfileOffsetGeneralflag) #define ZIP_CFILE_COMPRESSIONMETHOD(P) \ READ16LE((P) + kZipCfileOffsetCompressionmethod) @@ -119,18 +139,19 @@ #define ZIP_CFILE_EXTERNALATTRIBUTES(P) \ READ32LE((P) + kZipCfileOffsetExternalattributes) #define ZIP_CFILE_OFFSET(P) READ32LE((P) + kZipCfileOffsetOffset) -#define ZIP_CFILE_NAME(P) ((const char *)(&(P)[46])) /* not nul-terminated */ -#define ZIP_CFILE_EXTRA(P) (&(P)[46 + ZIP_CFILE_NAMESIZE(P)]) -#define ZIP_CFILE_COMMENT(P) \ - (&(P)[46 + ZIP_CFILE_NAMESIZE(P) + ZIP_CFILE_EXTRASIZE(P)]) +#define ZIP_CFILE_NAME(P) ((const char *)((P) + 46)) /* not nul-terminated */ +#define ZIP_CFILE_EXTRA(P) ((P) + 46 + ZIP_CFILE_NAMESIZE(P)) +#define ZIP_CFILE_COMMENT(P) \ + ((const char *)((P) + 46 + ZIP_CFILE_NAMESIZE(P) + \ + ZIP_CFILE_EXTRASIZE(P))) /* recommend stopping at nul */ #define ZIP_CFILE_HDRSIZE(P) \ (ZIP_CFILE_NAMESIZE(P) + ZIP_CFILE_EXTRASIZE(P) + ZIP_CFILE_COMMENTSIZE(P) + \ kZipCfileHdrMinSize) /* local file header */ #define ZIP_LFILE_MAGIC(P) READ32LE(P) -#define ZIP_LFILE_VERSIONNEED(P) ((P)[4]) -#define ZIP_LFILE_OSNEED(P) ((P)[5]) +#define ZIP_LFILE_VERSIONNEED(P) (255 & (P)[4]) +#define ZIP_LFILE_OSNEED(P) (255 & (P)[5]) #define ZIP_LFILE_GENERALFLAG(P) READ16LE((P) + kZipLfileOffsetGeneralflag) #define ZIP_LFILE_COMPRESSIONMETHOD(P) \ READ16LE((P) + kZipLfileOffsetCompressionmethod) @@ -145,8 +166,8 @@ READ32LE((P) + kZipLfileOffsetUncompressedsize) #define ZIP_LFILE_NAMESIZE(P) READ16LE((P) + 26) #define ZIP_LFILE_EXTRASIZE(P) READ16LE((P) + 28) -#define ZIP_LFILE_NAME(P) ((const char *)(&(P)[30])) -#define ZIP_LFILE_EXTRA(P) (&(P)[30 + ZIP_LFILE_NAMESIZE(P)]) +#define ZIP_LFILE_NAME(P) ((const char *)((P) + 30)) +#define ZIP_LFILE_EXTRA(P) ((P) + 30 + ZIP_LFILE_NAMESIZE(P)) #define ZIP_LFILE_HDRSIZE(P) \ (ZIP_LFILE_NAMESIZE(P) + ZIP_LFILE_EXTRASIZE(P) + kZipLfileHdrMinSize) #define ZIP_LFILE_CONTENT(P) ((P) + ZIP_LFILE_HDRSIZE(P)) @@ -154,9 +175,20 @@ #define ZIP_EXTRA_HEADERID(P) READ16LE(P) #define ZIP_EXTRA_CONTENTSIZE(P) READ16LE((P) + 2) -#define ZIP_EXTRA_CONTENT(P) (&(P)[4]) +#define ZIP_EXTRA_CONTENT(P) ((P) + 4) #define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize) +uint8_t *GetZipCdir(const uint8_t *, size_t); +bool IsZipCdir32(const uint8_t *, size_t, size_t); +bool IsZipCdir64(const uint8_t *, size_t, size_t); +int GetZipCfileMode(const uint8_t *); +uint64_t GetZipCdirOffset(const uint8_t *); +uint64_t GetZipCdirRecords(const uint8_t *); +uint64_t GetZipCfileUncompressedSize(const uint8_t *); +uint64_t GetZipCfileCompressedSize(const uint8_t *); +uint64_t GetZipCfileOffset(const uint8_t *); +uint64_t GetZipLfileUncompressedSize(const uint8_t *); +uint64_t GetZipLfileCompressedSize(const uint8_t *); uint8_t *zipfindcentraldir(const uint8_t *, size_t); #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/zipos/find.c b/libc/zipos/find.c index e38571305..9263bbd00 100644 --- a/libc/zipos/find.c +++ b/libc/zipos/find.c @@ -24,15 +24,14 @@ #include "libc/zipos/zipos.internal.h" ssize_t __zipos_find(struct Zipos *zipos, const struct ZiposUri *name) { - size_t i, cf; - assert(ZIP_CDIR_MAGIC(zipos->cdir) == kZipCdirHdrMagic); - for (i = 0, cf = ZIP_CDIR_OFFSET(zipos->cdir); - i < ZIP_CDIR_RECORDS(zipos->cdir); - ++i, cf += ZIP_CFILE_HDRSIZE(zipos->map + cf)) { - assert(ZIP_CFILE_MAGIC(zipos->map + cf) == kZipCfileHdrMagic); - if (name->len == ZIP_CFILE_NAMESIZE(zipos->map + cf) && - memcmp(name->path, ZIP_CFILE_NAME(zipos->map + cf), name->len) == 0) { - return cf; + size_t i, n, c; + c = GetZipCdirOffset(zipos->cdir); + n = GetZipCdirRecords(zipos->cdir); + for (i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(zipos->map + c)) { + assert(ZIP_CFILE_MAGIC(zipos->map + c) == kZipCfileHdrMagic); + if (name->len == ZIP_CFILE_NAMESIZE(zipos->map + c) && + memcmp(name->path, ZIP_CFILE_NAME(zipos->map + c), name->len) == 0) { + return c; } } return -1; diff --git a/libc/zipos/get.c b/libc/zipos/get.c index 985ef310b..af443f8ab 100644 --- a/libc/zipos/get.c +++ b/libc/zipos/get.c @@ -59,7 +59,7 @@ struct Zipos *__zipos_get(void) { } else { base = map; } - if ((cdir = zipfindcentraldir(base, size))) { + if ((cdir = GetZipCdir(base, size))) { zipos.map = base; zipos.cdir = cdir; } else { diff --git a/libc/zipos/open.c b/libc/zipos/open.c index 3847a5c9b..e4e4705b9 100644 --- a/libc/zipos/open.c +++ b/libc/zipos/open.c @@ -87,20 +87,20 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, unsigned flags, int fd; size_t lf; struct ZiposHandle *h; - lf = ZIP_CFILE_OFFSET(zipos->map + cf); + lf = GetZipCfileOffset(zipos->map + cf); assert(ZIP_LFILE_MAGIC(zipos->map + lf) == kZipLfileHdrMagic); assert(ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf) == kZipCompressionNone || ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf) == kZipCompressionDeflate); if (!(h = calloc(1, sizeof(*h)))) return -1; h->cfile = cf; - if ((h->size = ZIP_LFILE_UNCOMPRESSEDSIZE(zipos->map + lf))) { + if ((h->size = GetZipLfileUncompressedSize(zipos->map + lf))) { if (ZIP_LFILE_COMPRESSIONMETHOD(zipos->map + lf)) { - assert(ZIP_LFILE_COMPRESSEDSIZE(zipos->map + lf)); + assert(GetZipLfileCompressedSize(zipos->map + lf)); if ((h->freeme = malloc(h->size)) && (IsTiny() ? __zipos_inflate_tiny : __zipos_inflate_fast)( h, ZIP_LFILE_CONTENT(zipos->map + lf), - ZIP_LFILE_COMPRESSEDSIZE(zipos->map + lf)) != -1) { + GetZipLfileCompressedSize(zipos->map + lf)) != -1) { h->mem = h->freeme; } } else { diff --git a/libc/zipos/stat-impl.c b/libc/zipos/stat-impl.c index 170eb1b52..8bb989b6d 100644 --- a/libc/zipos/stat-impl.c +++ b/libc/zipos/stat-impl.c @@ -25,6 +25,7 @@ #include "libc/zipos/zipos.internal.h" int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) { + size_t lf; if (zipos && st) { memset(st, 0, sizeof(*st)); if (ZIP_CFILE_FILEATTRCOMPAT(zipos->map + cf) == kZipOsUnix) { @@ -32,9 +33,10 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) { } else { st->st_mode = 0100644; } - st->st_size = ZIP_CFILE_UNCOMPRESSEDSIZE(zipos->map + cf); + lf = GetZipCfileOffset(zipos->map + cf); + st->st_size = GetZipLfileUncompressedSize(zipos->map + lf); st->st_blocks = - roundup(ZIP_CFILE_COMPRESSEDSIZE(zipos->map + cf), 512) / 512; + roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512; return 0; } else { return einval(); diff --git a/net/http/decodebase64.c b/net/http/decodebase64.c index 7a8a1a72d..5932e8e56 100644 --- a/net/http/decodebase64.c +++ b/net/http/decodebase64.c @@ -41,13 +41,18 @@ static const signed char kBase64[256] = { /** * Decodes base64 ascii representation to binary. + * + * @param data is input value + * @param size if -1 implies strlen + * @param out_size if non-NULL receives output length + * @return allocated NUL-terminated buffer, or NULL w/ errno */ void *DecodeBase64(const char *data, size_t size, size_t *out_size) { - unsigned w; + size_t n; char *r, *q; - int a, b, c, d; + int a, b, c, d, w; const char *p, *pe; - if (size == -1) size = strlen(data); + if (size == -1) size = data ? strlen(data) : 0; if ((r = malloc(size / 4 * 3 + 1))) { q = r; p = data; @@ -77,9 +82,14 @@ void *DecodeBase64(const char *data, size_t size, size_t *out_size) { if (d != -2) *q++ = (w & 0x0000FF) >> 000; } Done: - if (out_size) *out_size = q - r; + n = q - r; *q++ = '\0'; if ((q = realloc(r, q - r))) r = q; + } else { + n = 0; + } + if (out_size) { + *out_size = n; } return r; } diff --git a/net/http/decodelatin1.c b/net/http/decodelatin1.c index aef372ccd..d3d86ef72 100644 --- a/net/http/decodelatin1.c +++ b/net/http/decodelatin1.c @@ -16,6 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/pcmpgtb.h" +#include "libc/intrin/pmovmskb.h" #include "libc/mem/mem.h" #include "libc/str/str.h" #include "net/http/http.h" @@ -25,14 +27,15 @@ * * @param data is input value * @param size if -1 implies strlen - * @param out_size if non-NULL receives output length on success + * @param out_size if non-NULL receives output length * @return allocated NUL-terminated buffer, or NULL w/ errno */ char *DecodeLatin1(const char *data, size_t size, size_t *out_size) { int c; + size_t n; char *r, *q; const char *p, *e; - if (size == -1) size = strlen(data); + if (size == -1) size = data ? strlen(data) : 0; if ((r = malloc(size * 2 + 1))) { q = r; p = data; @@ -46,9 +49,14 @@ char *DecodeLatin1(const char *data, size_t size, size_t *out_size) { *q++ = 0200 | c & 077; } } - if (out_size) *out_size = q - r; + n = q - r; *q++ = '\0'; - if ((q = realloc(r, q - r))) r = q; + if ((q = realloc(r, n + 1))) r = q; + } else { + n = 0; + } + if (out_size) { + *out_size = n; } return r; } diff --git a/net/http/encodebase64.c b/net/http/encodebase64.c index 1515bdfd0..f7543a9cb 100644 --- a/net/http/encodebase64.c +++ b/net/http/encodebase64.c @@ -17,22 +17,28 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/mem/mem.h" +#include "libc/str/str.h" #include "net/http/base64.h" #define CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" /** * Encodes binary to base64 ascii representation. + * + * @param data is input value + * @param size if -1 implies strlen + * @param out_size if non-NULL receives output length + * @return allocated NUL-terminated buffer, or NULL w/ errno */ char *EncodeBase64(const void *data, size_t size, size_t *out_size) { size_t n; unsigned w; char *r, *q; const unsigned char *p, *pe; + if (size == -1) size = data ? strlen(data) : 0; if ((n = size) % 3) n += 3 - size % 3; n /= 3, n *= 4; if ((r = malloc(n + 1))) { - if (out_size) *out_size = n; for (q = r, p = data, pe = p + size; p < pe; p += 3) { w = p[0] << 020; if (p + 1 < pe) w |= p[1] << 010; @@ -43,6 +49,11 @@ char *EncodeBase64(const void *data, size_t size, size_t *out_size) { *q++ = p + 2 < pe ? CHARS[w & 077] : '='; } *q++ = '\0'; + } else { + n = 0; + } + if (out_size) { + *out_size = n; } return r; } diff --git a/net/http/encodehttpheadervalue.c b/net/http/encodehttpheadervalue.c index ee5829e10..03b8b91ec 100644 --- a/net/http/encodehttpheadervalue.c +++ b/net/http/encodehttpheadervalue.c @@ -42,9 +42,10 @@ char *EncodeHttpHeaderValue(const char *data, size_t size, size_t *out_size) { bool t; wint_t x; + size_t n; char *r, *q; const char *p, *e; - if (size == -1) size = strlen(data); + if (size == -1) size = data ? strlen(data) : 0; if ((r = malloc(size + 1))) { t = 0; q = r; @@ -77,9 +78,14 @@ char *EncodeHttpHeaderValue(const char *data, size_t size, size_t *out_size) { } } while (q > r && (q[-1] == ' ' || q[-1] == '\t')) --q; - if (out_size) *out_size = q - r; + n = q - r; *q++ = '\0'; if ((q = realloc(r, q - r))) r = q; + } else { + n = 0; + } + if (out_size) { + *out_size = n; } return r; } diff --git a/net/http/escapeurl.c b/net/http/escapeurl.c index 09dfddb1e..0b7615cce 100644 --- a/net/http/escapeurl.c +++ b/net/http/escapeurl.c @@ -25,6 +25,7 @@ * This function is agnostic to the underlying charset. * Always using UTF-8 is a good idea. * + * @param size if -1 implies strlen * @see EscapeUrlParam * @see EscapeUrlFragment * @see EscapeUrlPathSegment @@ -35,6 +36,7 @@ struct EscapeResult EscapeUrl(const char *data, size_t size, char *p; size_t i; struct EscapeResult r; + if (size == -1) size = data ? strlen(data) : 0; p = r.data = xmalloc(size * 6 + 1); for (i = 0; i < size; ++i) { if (!xlat[(c = data[i] & 0xff)]) { diff --git a/net/http/escapeurlfragment.c b/net/http/escapeurlfragment.c index a03406b82..ef5b1e204 100644 --- a/net/http/escapeurlfragment.c +++ b/net/http/escapeurlfragment.c @@ -46,6 +46,8 @@ static const char kEscapeUrlFragment[256] = { /** * Escapes URL fragment. + * + * @param size if -1 implies strlen */ struct EscapeResult EscapeUrlFragment(const char *data, size_t size) { return EscapeUrl(data, size, kEscapeUrlFragment); diff --git a/net/http/escapeurlparam.c b/net/http/escapeurlparam.c index 88b2ab672..cc20b06c2 100644 --- a/net/http/escapeurlparam.c +++ b/net/http/escapeurlparam.c @@ -44,6 +44,8 @@ static const char kEscapeUrlParam[256] = { /** * Escapes query/form name/parameter. + * + * @param size if -1 implies strlen */ struct EscapeResult EscapeUrlParam(const char *data, size_t size) { return EscapeUrl(data, size, kEscapeUrlParam); diff --git a/net/http/escapeurlpath.c b/net/http/escapeurlpath.c index 55789eb47..9a3afda23 100644 --- a/net/http/escapeurlpath.c +++ b/net/http/escapeurlpath.c @@ -48,6 +48,8 @@ static const char kEscapeUrlPath[256] = { * Escapes URL path. * * This is the same as EscapeUrlPathSegment() except slash is allowed. + * + * @param size if -1 implies strlen */ struct EscapeResult EscapeUrlPath(const char *data, size_t size) { return EscapeUrl(data, size, kEscapeUrlPath); diff --git a/net/http/escapeurlpathsegment.c b/net/http/escapeurlpathsegment.c index 47667ec0a..c878f1f58 100644 --- a/net/http/escapeurlpathsegment.c +++ b/net/http/escapeurlpathsegment.c @@ -49,6 +49,8 @@ static const char kEscapeUrlPathSegment[256] = { * * Please note this will URI encode the slash character. That's because * segments are the labels between the slashes in a path. + * + * @param size if -1 implies strlen */ struct EscapeResult EscapeUrlPathSegment(const char *data, size_t size) { return EscapeUrl(data, size, kEscapeUrlPathSegment); diff --git a/net/http/http.h b/net/http/http.h index 79766d17a..12464ab24 100644 --- a/net/http/http.h +++ b/net/http/http.h @@ -125,7 +125,8 @@ bool IsValidHttpToken(const char *, size_t); char *EncodeHttpHeaderValue(const char *, size_t, size_t *); char *VisualizeControlCodes(const char *, size_t, size_t *); char *IndentLines(const char *, size_t, size_t *, size_t); -bool IsAcceptableHttpRequestPath(const char *, size_t); +bool IsAcceptablePath(const char *, size_t); +bool IsAcceptableHostPort(const char *, size_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/net/http/indentlines.c b/net/http/indentlines.c index 2bd9aa1fa..580074153 100644 --- a/net/http/indentlines.c +++ b/net/http/indentlines.c @@ -25,7 +25,7 @@ * * @param data is input value * @param size if -1 implies strlen - * @param out_size if non-NULL receives output length on success + * @param out_size if non-NULL receives output length * @param amt is number of spaces to use * @return allocated NUL-terminated buffer, or NULL w/ errno */ @@ -33,7 +33,7 @@ char *IndentLines(const char *data, size_t size, size_t *out_size, size_t amt) { char *r; const char *p; size_t i, n, m, a; - if (size == -1) size = strlen(data); + if (size == -1) size = data ? strlen(data) : 0; r = 0; n = 0; do { @@ -51,7 +51,9 @@ char *IndentLines(const char *data, size_t size, size_t *out_size, size_t amt) { data += m; size -= m; } while (p); - if (out_size) *out_size = n; + if (out_size) { + *out_size = n; + } r[n] = '\0'; return r; } diff --git a/net/http/isacceptablehostport.c b/net/http/isacceptablehostport.c new file mode 100644 index 000000000..3313c688c --- /dev/null +++ b/net/http/isacceptablehostport.c @@ -0,0 +1,106 @@ +/*-*- 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 2021 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/str/str.h" +#include "net/http/http.h" + +/** + * Returns true if HOST[:PORT] seems legit. + * + * This parser is permissive and imposes the subset of restrictions + * that'll make things easier for the caller. For example, only one + * colon is allowed to appear, which makes memchr() so much easier. + * + * Here's examples of permitted inputs: + * + * - 1.2.3.4 + * - 1.2.3.4.arpa + * - 1.2.3.4:8080 + * - localservice + * - hello.example + * - _hello.example + * - -hello.example + * - hi-there.example + * - hello.example:443 + * + * Here's some examples of forbidden inputs: + * + * - :443 + * - 1.2.3 + * - 1.2.3.4.5 + * - [::1]:8080 + * - .hi.example + * - hi..example + * - hi.example::80 + * - hi.example:-80 + * - hi.example:65536 + * + * @param n if -1 implies strlen + */ +bool IsAcceptableHostPort(const char *s, size_t n) { + size_t i; + bool isip; + int c, t, p, b, j; + if (n == -1) n = s ? strlen(s) : 0; + if (!n) return false; + for (isip = true, b = j = p = t = i = 0; i < n; ++i) { + c = s[i] & 255; + if (!t) { + if (c == ':') { + if (!i || s[i - 1] == '.') { + return false; + } else { + t = 1; + } + } else if (c == '.' && (!i || s[i - 1] == '.')) { + return false; + } else if (!(isalnum(c) || c == '-' || c == '_' || c == '.')) { + return false; + } + if (isip) { + if (isdigit(c)) { + b *= 10; + b += c - '0'; + if (b > 255) { + return false; + } + } else if (c == '.') { + b = 0; + ++j; + } else { + isip = false; + } + } + } else { + if (c == ':') { + return false; + } else if ('0' <= c && c <= '9') { + p *= 10; + p += c - '0'; + if (p > 65535) { + return false; + } + } else { + return false; + } + } + } + if (isip && j != 3) return false; + if (!t && s[i - 1] == '.') return false; + return true; +} diff --git a/net/http/isacceptablehttprequestpath.c b/net/http/isacceptablepath.c similarity index 84% rename from net/http/isacceptablehttprequestpath.c rename to net/http/isacceptablepath.c index c093a7b89..8ff2b7903 100644 --- a/net/http/isacceptablehttprequestpath.c +++ b/net/http/isacceptablepath.c @@ -16,29 +16,29 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/str/str.h" #include "libc/str/thompike.h" #include "net/http/http.h" /** * Returns true if request path seems legit. * - * 1. Request path must start with '/'. - * 2. The substring "//" is disallowed. - * 3. We won't serve hidden files (segment starts with '.'). - * 4. We won't serve paths with segments equal to "." or "..". + * 1. The substring "//" is disallowed. + * 2. We won't serve hidden files (segment starts with '.'). + * 3. We won't serve paths with segments equal to "." or "..". * * It is assumed that the URI parser already took care of percent * escape decoding as well as ISO-8859-1 decoding. The input needs * to be a UTF-8 string. + * + * @param size if -1 implies strlen */ -bool IsAcceptableHttpRequestPath(const char *data, size_t size) { - bool t; - size_t i; - unsigned n; - wint_t x, y, a, b; +bool IsAcceptablePath(const char *data, size_t size) { const char *p, *e; - if (!size || *data != '/') return false; + int x, y, a, b, t, i, n; + if (size == -1) size = data ? strlen(data) : 0; t = 0; + y = '/'; p = data; e = p + size; while (p < e) { @@ -62,14 +62,12 @@ bool IsAcceptableHttpRequestPath(const char *data, size_t size) { if (x == '\\') { x = '/'; } - if (!t) { - t = true; - } else { - if ((x == '/' || x == '.') && y == '/') { - return false; - } + if (y == '/') { + if (x == '.') return false; + if (x == '/' && t) return false; } y = x; + t = 1; } return true; } diff --git a/net/http/isvalidhttptoken.c b/net/http/isvalidhttptoken.c index b3e61791b..e82994ffa 100644 --- a/net/http/isvalidhttptoken.c +++ b/net/http/isvalidhttptoken.c @@ -21,7 +21,7 @@ // http/1.1 token dispatch // 0 is CTLs, SP, ()<>@,;:\"/[]?={} -// 1 is legal ascii +// 1 is what remains of ascii static const char kHttpToken[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 @@ -41,10 +41,15 @@ static const char kHttpToken[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0 }; +/** + * Returns true if string is ASCII without delimiters. + * + * @param n if -1 implies strlen + */ bool IsValidHttpToken(const char *s, size_t n) { size_t i; if (!n) return false; - if (n == -1) n = strlen(s); + if (n == -1) n = s ? strlen(s) : 0; for (i = 0; i < n; ++i) { if (!kHttpToken[s[i] & 0xff]) { return false; diff --git a/net/http/parseurl.c b/net/http/parseurl.c new file mode 100644 index 000000000..786ed90e9 --- /dev/null +++ b/net/http/parseurl.c @@ -0,0 +1,346 @@ +/*-*- 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 2021 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/likely.h" +#include "libc/limits.h" +#include "libc/str/str.h" +#include "libc/x/x.h" +#include "net/http/url.h" + +struct UrlParser { + int i; + int c; + const char *data; + int size; + bool isform; + bool islatin1; + char *p; + char *q; +}; + +static const signed char kHexToInt[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x20 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 0x30 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x40 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x50 + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x60 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x70 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x80 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x90 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xa0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xb0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xc0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xd0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xe0 + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xf0 +}; + +static void EmitLatin1(struct UrlParser *u, int c) { + u->p[0] = 0300 | c >> 6; + u->p[1] = 0200 | c & 077; + u->p += 2; +} + +static void EmitKey(struct UrlParser *u, struct UrlParams *h) { + h->p = xrealloc(h->p, ++h->n * sizeof(*h->p)); + h->p[h->n - 1].key.p = u->q; + h->p[h->n - 1].key.n = u->p - u->q; + u->q = u->p; +} + +static void EmitVal(struct UrlParser *u, struct UrlParams *h, bool t) { + if (!t) { + if (u->p > u->q) { + EmitKey(u, h); + h->p[h->n - 1].val.p = NULL; + h->p[h->n - 1].val.n = SIZE_MAX; + } + } else { + h->p[h->n - 1].val.p = u->q; + h->p[h->n - 1].val.n = u->p - u->q; + u->q = u->p; + } +} + +static void ParseEscape(struct UrlParser *u) { + int a, b; + if (u->i + 2 <= u->size && + ((a = kHexToInt[u->data[u->i + 0] & 0xff]) != -1 && + (b = kHexToInt[u->data[u->i + 1] & 0xff]) != -1)) { + u->c = a << 4 | b; + u->i += 2; + } + *u->p++ = u->c; +} + +static bool ParseScheme(struct UrlParser *u, struct Url *h) { + while (u->i < u->size) { + u->c = u->data[u->i++] & 0xff; + if (u->c == '/') { + if (u->i == 1 && u->i < u->size && u->data[u->i] == '/') { + ++u->i; + return true; + } else { + *u->p++ = u->c; + return false; + } + } else if (u->c == ':') { + h->scheme.p = u->q; + h->scheme.n = u->p - u->q; + u->q = u->p; + if (u->i + 2 <= u->size && + (u->data[u->i + 1] == '/' && u->data[u->i + 1] == '/')) { + u->i += 2; + return true; + } else { + return false; + } + } else if (u->c == '#' || u->c == '?') { + h->path.p = u->q; + h->path.n = u->p - u->q; + u->q = u->p; + return false; + } else if (u->c == '%') { + ParseEscape(u); + } else if (u->c >= 0200 && u->islatin1) { + EmitLatin1(u, u->c); + } else { + *u->p++ = u->c; + } + } + return false; +} + +static void ParseAuthority(struct UrlParser *u, struct Url *h) { + bool b = false; + const char *c = NULL; + while (u->i < u->size) { + u->c = u->data[u->i++] & 0xff; + if (u->c == '/' || u->c == '#' || u->c == '?') { + break; + } else if (u->c == '[') { + b = true; + } else if (u->c == ']') { + b = false; + } else if (u->c == ':' && !b) { + c = u->p; + } else if (u->c == '@') { + if (c) { + h->user.p = u->q; + h->user.n = c - u->q; + h->pass.p = c; + h->pass.n = u->p - c; + c = NULL; + } else { + h->user.p = u->q; + h->user.n = u->p - u->q; + } + u->q = u->p; + } else if (u->c == '%') { + ParseEscape(u); + } else if (u->c >= 0200 && u->islatin1) { + EmitLatin1(u, u->c); + } else { + *u->p++ = u->c; + } + } + if (c) { + h->host.p = u->q; + h->host.n = c - u->q; + h->port.p = c; + h->port.n = u->p - c; + c = NULL; + } else { + h->host.p = u->q; + h->host.n = u->p - u->q; + } + u->q = u->p; + if (u->c == '/') { + *u->p++ = u->c; + } +} + +static void ParsePath(struct UrlParser *u, struct UrlView *h) { + while (u->i < u->size) { + u->c = u->data[u->i++] & 0xff; + if (u->c == '#' || u->c == '?') { + break; + } else if (u->c == '%') { + ParseEscape(u); + } else if (u->c >= 0200 && u->islatin1) { + EmitLatin1(u, u->c); + } else { + *u->p++ = u->c; + } + } + h->p = u->q; + h->n = u->p - u->q; + u->q = u->p; +} + +static void ParseKeyValues(struct UrlParser *u, struct UrlParams *h) { + bool t = false; + while (u->i < u->size) { + u->c = u->data[u->i++] & 0xff; + if (u->c == '#') { + break; + } else if (u->c == '%') { + ParseEscape(u); + } else if (u->c == '+') { + *u->p++ = u->isform ? ' ' : '+'; + } else if (u->c == '&') { + EmitVal(u, h, t); + t = false; + } else if (u->c == '=') { + if (!t) { + if (u->p > u->q) { + EmitKey(u, h); + t = true; + } + } else { + *u->p++ = '='; + } + } else if (u->c >= 0200 && u->islatin1) { + EmitLatin1(u, u->c); + } else { + *u->p++ = u->c; + } + } + EmitVal(u, h, t); +} + +static void ParseFragment(struct UrlParser *u, struct UrlView *h) { + while (u->i < u->size) { + u->c = u->data[u->i++] & 0xff; + if (u->c == '%') { + ParseEscape(u); + } else if (u->c >= 0200 && u->islatin1) { + EmitLatin1(u, u->c); + } else { + *u->p++ = u->c; + } + } + h->p = u->q; + h->n = u->p - u->q; + u->q = u->p; +} + +static char *ParseUrlImpl(const char *data, size_t size, struct Url *h, + bool latin1) { + char *m; + struct UrlParser u; + if (size == -1) size = data ? strlen(data) : 0; + u.i = 0; + u.c = 0; + u.isform = false; + u.islatin1 = latin1; + u.data = data; + u.size = size; + memset(h, 0, sizeof(*h)); + u.q = u.p = m = xmalloc(u.size * 2); + if (ParseScheme(&u, h)) ParseAuthority(&u, h); + if (u.c != '#' && u.c != '?') ParsePath(&u, &h->path); + if (u.c == '?') ParseKeyValues(&u, &h->params); + if (u.c == '#') ParseFragment(&u, &h->fragment); + return xrealloc(m, u.p - m); +} + +/** + * Parses URL. + * + * There's no failure condition for this routine. This is a permissive + * parser that doesn't impose character restrictions beyond what is + * necessary for parsing. This doesn't normalize path segments like `.` + * or `..`. Use IsAcceptablePath() to check for those. + * + * This parser is charset agnostic. Returned values might contain things + * like NUL characters, control codes, and non-canonical encodings. + * + * This parser doesn't support the ability to accurately parse path + * segments which contain percent-encoded slash. There's also no support + * for semicolon parameters at the moment. + * + * @param data is value like `/hi?x=y&z` or `http://a.example/hi#x` + * @param size is byte length and -1 implies strlen + * @param h is assumed to be uninitialized + * @return memory backing UrlView needing free (and h.params.p too) + */ +char *ParseUrl(const char *data, size_t size, struct Url *h) { + return ParseUrlImpl(data, size, h, false); +} + +/** + * Parses HTTP Request-URI. + * + * The input is ISO-8859-1 which is transcoded to UTF-8. Therefore we + * assume percent-encoded bytes are expressed as UTF-8. Returned values + * might contain things like NUL characters, C0, and C1 control codes. + * UTF-8 isn't checked for validity and may contain overlong values. + * + * There's no failure condition for this routine. This is a permissive + * parser that doesn't impose character restrictions beyond what is + * necessary for parsing. This doesn't normalize path segments like `.` + * or `..`. Use IsAcceptablePath() to check for those. + * + * This parser doesn't support the ability to accurately parse path + * segments which contain percent-encoded slash. + * + * @param data is value like `/hi?x=y&z` or `http://a.example/hi#x` + * @param size is byte length and -1 implies strlen + * @param h is assumed to be uninitialized + * @return memory backing UrlView needing free (and h.params.p too) + */ +char *ParseRequestUri(const char *data, size_t size, struct Url *h) { + return ParseUrlImpl(data, size, h, true); +} + +/** + * Parses HTTP POST key-value params. + * + * These are similar to the parameters found in a Request-URI. The main + * difference is that `+` is translated into space here. The mime type + * for this is application/x-www-form-urlencoded. + * + * This parser is charset agnostic. Returned values might contain things + * like NUL characters, control codes, and non-canonical encodings. + * + * There's no failure condition for this routine. This is a permissive + * parser that doesn't impose character restrictions beyond what is + * necessary for parsing. + * + * @param data is value like `foo=bar&x=y&z` + * @param size is byte length and -1 implies strlen + * @param h must be zeroed by caller and this appends if reused + * @return UrlView memory with same size needing free (h.p needs free too) + */ +char *ParseParams(const char *data, size_t size, struct UrlParams *h) { + char *m; + struct UrlParser u; + if (size == -1) size = data ? strlen(data) : 0; + u.i = 0; + u.c = 0; + u.isform = true; + u.islatin1 = false; + u.data = data; + u.size = size; + u.q = u.p = m = xmalloc(u.size); + ParseKeyValues(&u, h); + return m; +} diff --git a/net/http/url.h b/net/http/url.h new file mode 100644 index 000000000..c0fdda679 --- /dev/null +++ b/net/http/url.h @@ -0,0 +1,36 @@ +#ifndef COSMOPOLITAN_NET_HTTP_URL_H_ +#define COSMOPOLITAN_NET_HTTP_URL_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct UrlView { + size_t n; + char *p; /* not allocated; not nul terminated */ +}; + +struct UrlParams { + size_t n; + struct Param { + struct UrlView key; + struct UrlView val; /* val.n may be SIZE_MAX */ + } * p; +}; + +struct Url { + struct UrlView scheme; + struct UrlView user; + struct UrlView pass; + struct UrlView host; + struct UrlView port; + struct UrlView path; + struct UrlParams params; + struct UrlView fragment; +}; + +char *ParseUrl(const char *, size_t, struct Url *); +char *ParseParams(const char *, size_t, struct UrlParams *); +char *ParseRequestUri(const char *, size_t, struct Url *); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_NET_HTTP_URL_H_ */ diff --git a/net/http/visualizecontrolcodes.c b/net/http/visualizecontrolcodes.c index d1049731d..42efb54d7 100644 --- a/net/http/visualizecontrolcodes.c +++ b/net/http/visualizecontrolcodes.c @@ -31,7 +31,7 @@ * * @param data is input value * @param size if -1 implies strlen - * @param out_size if non-NULL receives output length on success + * @param out_size if non-NULL receives output length * @return allocated NUL-terminated buffer, or NULL w/ errno */ char *VisualizeControlCodes(const char *data, size_t size, size_t *out_size) { @@ -40,7 +40,7 @@ char *VisualizeControlCodes(const char *data, size_t size, size_t *out_size) { unsigned i, n; wint_t x, a, b; const char *p, *e; - if (size == -1) size = strlen(data); + if (size == -1) size = data ? strlen(data) : 0; if ((r = malloc(size * 6 + 1))) { q = r; p = data; @@ -85,9 +85,14 @@ char *VisualizeControlCodes(const char *data, size_t size, size_t *out_size) { } while ((w >>= 8)); } } - if (out_size) *out_size = q - r; + n = q - r; *q++ = '\0'; if ((q = realloc(r, q - r))) r = q; + } else { + n = 0; + } + if (out_size) { + *out_size = n; } return r; } diff --git a/test/libc/bits/bitreverse_test.c b/test/libc/bits/bitreverse_test.c index ae2a8014a..acd47ae28 100644 --- a/test/libc/bits/bitreverse_test.c +++ b/test/libc/bits/bitreverse_test.c @@ -21,29 +21,24 @@ #include "libc/testlib/testlib.h" TEST(bitreverse, test) { + EXPECT_EQ(0xde, BITREVERSE8(123)); EXPECT_EQ(0xde, bitreverse8(123)); - EXPECT_EQ(0xde, (bitreverse8)(123)); + EXPECT_EQ(0xde00, BITREVERSE16(123)); EXPECT_EQ(0xde00, bitreverse16(123)); - EXPECT_EQ(0xde00, (bitreverse16)(123)); EXPECT_EQ(0xde000000u, bitreverse32(123)); - EXPECT_EQ(0xde000000u, (bitreverse32)(123)); EXPECT_EQ(0xde00000000000000ul, bitreverse64(123)); - EXPECT_EQ(0xde00000000000000ul, (bitreverse64)(123)); EXPECT_EQ(0x482d96c305f7c697ul, bitreverse64(0xe963efa0c369b412)); - EXPECT_EQ(0x482d96c305f7c697ul, (bitreverse64)(0xe963efa0c369b412)); } BENCH(bitreverse, bench) { - EZBENCH2("bitreverse8 mac", donothing, + EZBENCH2("BITREVERSE8", donothing, + EXPROPRIATE(BITREVERSE8(CONCEAL("r", 123)))); + EZBENCH2("bitreverse8", donothing, EXPROPRIATE(bitreverse8(CONCEAL("r", 123)))); - EZBENCH2("bitreverse8 fun", donothing, - EXPROPRIATE((bitreverse8)(CONCEAL("r", 123)))); - EZBENCH2("bitreverse16 mac", donothing, - EXPROPRIATE(bitreverse16(CONCEAL("r", 123)))); - EZBENCH2("bitreverse16 fun", donothing, - EXPROPRIATE((bitreverse16)(CONCEAL("r", 123)))); - EZBENCH2("bitreverse32 mac", donothing, + EZBENCH2("BITREVERSE16", donothing, + EXPROPRIATE(BITREVERSE16(CONCEAL("r", 123)))); + EZBENCH2("bitreverse32", donothing, EXPROPRIATE(bitreverse32(CONCEAL("r", 123)))); - EZBENCH2("bitreverse32 fun", donothing, - EXPROPRIATE((bitreverse32)(CONCEAL("r", (123))))); + EZBENCH2("bitreverse64", donothing, + EXPROPRIATE(bitreverse64(CONCEAL("r", 123)))); } diff --git a/test/net/http/isacceptablehttprequestpath_test.c b/test/libc/calls/mprotect_test.c similarity index 54% rename from test/net/http/isacceptablehttprequestpath_test.c rename to test/libc/calls/mprotect_test.c index a256bdf55..7857f1066 100644 --- a/test/net/http/isacceptablehttprequestpath_test.c +++ b/test/libc/calls/mprotect_test.c @@ -16,46 +16,51 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/runtime/gc.internal.h" -#include "libc/testlib/ezbench.h" +#include "libc/calls/calls.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/sa.h" #include "libc/testlib/testlib.h" -#include "net/http/escape.h" -#include "net/http/http.h" -TEST(IsAcceptableHttpRequestPath, test) { - EXPECT_TRUE(IsAcceptableHttpRequestPath("/", 1)); - EXPECT_TRUE(IsAcceptableHttpRequestPath("/index.html", 11)); +jmp_buf jb; +bool gotsegv; +struct sigaction old[2]; + +void OnSigSegv(int sig) { + gotsegv = true; + longjmp(jb, 1); } -TEST(IsAcceptableHttpRequestPath, testDoubleSlash_notAllowed) { - EXPECT_FALSE(IsAcceptableHttpRequestPath("//", 2)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("/foo//bar", 9)); +void SetUp(void) { + sigaction(SIGBUS, NULL, &old[0]); + sigaction(SIGSEGV, NULL, &old[1]); } -TEST(IsAcceptableHttpRequestPath, testDoesntStartWithSlash_notAllowed) { - EXPECT_FALSE(IsAcceptableHttpRequestPath(NULL, 0)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("*", 1)); +void TearDown(void) { + sigaction(SIGBUS, &old[0], NULL); + sigaction(SIGSEGV, &old[1], NULL); } -TEST(IsAcceptableHttpRequestPath, testNoncanonicalDirectories_areForbidden) { - EXPECT_FALSE(IsAcceptableHttpRequestPath("/.", 2)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("/./", 3)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("/../", 4)); +TEST(mprotect, test) { + char *p = gc(memalign(PAGESIZE, PAGESIZE)); + p[0] = 0; + ASSERT_NE(-1, mprotect(p, PAGESIZE, PROT_READ | PROT_WRITE)); + p[0] = 1; + EXPECT_EQ(1, p[0]); } -TEST(IsAcceptableHttpRequestPath, testNoncanonicalWindowsDirs_areForbidden) { - EXPECT_FALSE(IsAcceptableHttpRequestPath("\\.", 2)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("\\.\\", 3)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("\\..\\", 4)); -} - -TEST(IsAcceptableHttpRequestPath, testOverlongSlashDot_isDetected) { - EXPECT_FALSE(IsAcceptableHttpRequestPath("/\300\256", 3)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("/\300\257", 3)); - EXPECT_FALSE(IsAcceptableHttpRequestPath("\300\256\300\256", 4)); -} - -BENCH(IsAcceptableHttpRequestPath, bench) { - EZBENCH2("IsAcceptableHttpRequestPath", donothing, - IsAcceptableHttpRequestPath("/index.html", 11)); +TEST(mprotect, testSegfault) { + char *p; + struct sigaction ss = {.sa_handler = OnSigSegv, .sa_flags = SA_NODEFER}; + if (IsWindows()) return; /* TODO */ + p = gc(memalign(PAGESIZE, PAGESIZE)); + EXPECT_NE(-1, sigaction(SIGBUS, &ss, NULL)); + EXPECT_NE(-1, sigaction(SIGSEGV, &ss, NULL)); + if (!setjmp(jb)) p[0] = 1; + EXPECT_FALSE(gotsegv); + EXPECT_NE(-1, mprotect(p, sizeof(p), PROT_READ)); + if (!setjmp(jb)) p[0] = 2; + EXPECT_TRUE(gotsegv); + EXPECT_EQ(1, p[0]); + EXPECT_NE(-1, mprotect(p, sizeof(p), PROT_READ | PROT_WRITE)); } diff --git a/test/libc/fmt/strerror_test.c b/test/libc/fmt/strerror_test.c index b6b607136..331f49008 100644 --- a/test/libc/fmt/strerror_test.c +++ b/test/libc/fmt/strerror_test.c @@ -45,8 +45,8 @@ TEST(strerror, einval) { } TEST(strerror, symbolizingTheseNumbersAsErrorsIsHeresyInUnixStyle) { - EXPECT_STARTSWITH("E?", strerror(0)); - EXPECT_STARTSWITH("E?", strerror(-1)); + EXPECT_STARTSWITH("EUNKNOWN", strerror(0)); + EXPECT_STARTSWITH("EUNKNOWN", strerror(-1)); } TEST(strerror, enotconn_orLinkerIsntUsingLocaleC_orCodeIsOutOfSync) { @@ -55,9 +55,9 @@ TEST(strerror, enotconn_orLinkerIsntUsingLocaleC_orCodeIsOutOfSync) { } TEST(strerror, exfull_orLinkerIsntUsingLocaleC_orCodeIsOutOfSync) { - if (IsLinux() && !IsTiny()) { - EXPECT_STARTSWITH("EXFULL", strerror(EXFULL)); + if (!IsTiny()) { + EXPECT_STARTSWITH("ETXTBSY", strerror(ETXTBSY)); } else { - EXPECT_STARTSWITH("E?", strerror(EXFULL)); + EXPECT_STARTSWITH("EUNKNOWN", strerror(ETXTBSY)); } } diff --git a/test/libc/release/test.mk b/test/libc/release/test.mk index 01aac0224..872f9395d 100644 --- a/test/libc/release/test.mk +++ b/test/libc/release/test.mk @@ -8,7 +8,7 @@ o/$(MODE)/test/libc/release/cosmopolitan.zip: \ o/$(MODE)/ape/ape.o \ o/$(MODE)/ape/ape-no-modify-self.o \ o/$(MODE)/cosmopolitan.a - @$(COMPILE) -AZIP -T$@ zip -j $@ $^ + @$(COMPILE) -AZIP -T$@ zip -qj $@ $^ o/$(MODE)/test/libc/release/smoke.com: \ o/$(MODE)/test/libc/release/smoke.com.dbg diff --git a/test/net/http/decodelatin1_test.c b/test/net/http/decodelatin1_test.c index ccb507181..f1a86e0cf 100644 --- a/test/net/http/decodelatin1_test.c +++ b/test/net/http/decodelatin1_test.c @@ -16,6 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/testlib/ezbench.h" +#include "libc/testlib/hyperion.h" #include "libc/testlib/testlib.h" #include "net/http/http.h" @@ -26,3 +28,14 @@ TEST(DecodeLatin1, test) { EXPECT_STREQ("¥atta", DecodeLatin1("\245atta", -1, &n)); EXPECT_EQ(6, n); } + +TEST(DecodeLatin1, testOom_returnsNullAndSetsSizeToZero) { + n = 31337; + EXPECT_EQ(NULL, DecodeLatin1("hello", 0x1000000000000, &n)); + EXPECT_EQ(0, n); +} + +BENCH(DecodeLatin1, bench) { + EZBENCH2("DecodeLatin1", donothing, + DecodeLatin1(kHyperion, kHyperionSize, 0)); +} diff --git a/test/net/http/encodebase64_test.c b/test/net/http/encodebase64_test.c index 4e4f23a30..3af1b5091 100644 --- a/test/net/http/encodebase64_test.c +++ b/test/net/http/encodebase64_test.c @@ -126,6 +126,18 @@ TEST(DecodeBase64, testInvalidSequences_skipsOverThem) { EXPECT_BINEQ(u"♦ ", gc(DecodeBase64("====BB==", 8, 0))); } +TEST(DecodeBase64, testOom_returnsNullAndSetsSizeToZero) { + n = 31337; + EXPECT_EQ(NULL, DecodeBase64("hello", 0x1000000000000, &n)); + EXPECT_EQ(0, n); +} + +TEST(EncodeBase64, testOom_returnsNullAndSetsSizeToZero) { + n = 31337; + EXPECT_EQ(NULL, EncodeBase64("hello", 0x1000000000000, &n)); + EXPECT_EQ(0, n); +} + TEST(Base64, RoundTrip) { for (i = 0; i < 1000; ++i) { n = rand() % 32; diff --git a/test/net/http/encodehttpheadervalue_test.c b/test/net/http/encodehttpheadervalue_test.c index 9df05d12b..c3f9dc996 100644 --- a/test/net/http/encodehttpheadervalue_test.c +++ b/test/net/http/encodehttpheadervalue_test.c @@ -70,6 +70,12 @@ TEST(EncodeHttpHeaderValue, testC1_isForbidden) { EXPECT_EQ(NULL, gc(EncodeHttpHeaderValue("\302\205", 2, 0))); } +TEST(EncodeHttpHeaderValue, testOom_returnsNullAndSetsSizeToZero) { + n = 31337; + EXPECT_EQ(NULL, EncodeHttpHeaderValue("hello", 0x1000000000000, &n)); + EXPECT_EQ(0, n); +} + BENCH(EncodeHttpHeaderValue, bench) { n = 22851; p = gc(malloc(n)); diff --git a/test/net/http/escapeurlparam_test.c b/test/net/http/escapeurlparam_test.c index c7469c700..2bb7745c8 100644 --- a/test/net/http/escapeurlparam_test.c +++ b/test/net/http/escapeurlparam_test.c @@ -25,29 +25,29 @@ char *escapeparam(const char *s) { struct EscapeResult r; - r = EscapeUrlParam(s, strlen(s)); + r = EscapeUrlParam(s, -1); ASSERT_EQ(strlen(r.data), r.size); return r.data; } -TEST(escapeparam, test) { +TEST(EscapeUrlParam, test) { EXPECT_STREQ("abc%20%26%3C%3E%22%27%01%02", gc(escapeparam("abc &<>\"'\1\2"))); } -TEST(escapeparam, testLargeGrowth) { +TEST(EscapeUrlParam, testLargeGrowth) { EXPECT_STREQ("%22%22%22", gc(escapeparam("\"\"\""))); } -TEST(escapeparam, testEmpty) { +TEST(EscapeUrlParam, testEmpty) { EXPECT_STREQ("", gc(escapeparam(""))); } -TEST(escapeparam, testAstralPlanes_usesUtf8HexEncoding) { +TEST(EscapeUrlParam, testAstralPlanes_usesUtf8HexEncoding) { EXPECT_STREQ("%F0%90%8C%B0", escapeparam("𐌰")); } -BENCH(escapeparam, bench) { - EZBENCH2("escapeparam", donothing, +BENCH(EscapeUrlParam, bench) { + EZBENCH2("EscapeUrlParam", donothing, free(EscapeUrlParam(kHyperion, kHyperionSize).data)); } diff --git a/test/net/http/isacceptablehostport_test.c b/test/net/http/isacceptablehostport_test.c new file mode 100644 index 000000000..7d392dba5 --- /dev/null +++ b/test/net/http/isacceptablehostport_test.c @@ -0,0 +1,59 @@ +/*-*- 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 2021 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/testlib/testlib.h" +#include "net/http/http.h" + +TEST(IsAcceptableHostPort, test) { + EXPECT_FALSE(IsAcceptableHostPort("", -1)); + EXPECT_FALSE(IsAcceptableHostPort(":", -1)); + EXPECT_FALSE(IsAcceptableHostPort(":80", -1)); + EXPECT_TRUE(IsAcceptableHostPort("0.0.0.0", -1)); + EXPECT_FALSE(IsAcceptableHostPort("1.2.3", -1)); + EXPECT_TRUE(IsAcceptableHostPort("1.2.3.4", -1)); + EXPECT_FALSE(IsAcceptableHostPort("1.2.3.4.5", -1)); + EXPECT_TRUE(IsAcceptableHostPort("1.2.3.4.5.arpa", -1)); + EXPECT_TRUE(IsAcceptableHostPort("255.255.255.255", -1)); + EXPECT_FALSE(IsAcceptableHostPort("255.255.255", -1)); + EXPECT_FALSE(IsAcceptableHostPort("256.255.255.255", -1)); + EXPECT_TRUE(IsAcceptableHostPort("hello.example", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello..example", -1)); + EXPECT_TRUE(IsAcceptableHostPort("hello.example:80", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example:80:", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example::80", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example:-80", -1)); + EXPECT_FALSE(IsAcceptableHostPort(":80", -1)); + EXPECT_TRUE(IsAcceptableHostPort("hello.example:65535", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example:65536", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example:-80", -1)); + EXPECT_FALSE(IsAcceptableHostPort(" hello .example:80", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example:80h", -1)); + EXPECT_TRUE(IsAcceptableHostPort("hello", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello\177", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hello.example\300\200:80", -1)); + EXPECT_FALSE(IsAcceptableHostPort(".", -1)); + EXPECT_FALSE(IsAcceptableHostPort(".e", -1)); + EXPECT_FALSE(IsAcceptableHostPort("e.", -1)); + EXPECT_FALSE(IsAcceptableHostPort(".hi.example", -1)); + EXPECT_FALSE(IsAcceptableHostPort("hi..example", -1)); + EXPECT_TRUE(IsAcceptableHostPort("hi-there.example", -1)); + EXPECT_TRUE(IsAcceptableHostPort("_there.example", -1)); + EXPECT_TRUE(IsAcceptableHostPort("-there.example", -1)); + EXPECT_TRUE(IsAcceptableHostPort("there-.example", -1)); + EXPECT_FALSE(IsAcceptableHostPort("ther#e.example", -1)); +} diff --git a/test/net/http/isacceptablepath_test.c b/test/net/http/isacceptablepath_test.c new file mode 100644 index 000000000..4472b9f7e --- /dev/null +++ b/test/net/http/isacceptablepath_test.c @@ -0,0 +1,92 @@ +/*-*- 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 2021 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/runtime/gc.internal.h" +#include "libc/testlib/ezbench.h" +#include "libc/testlib/testlib.h" +#include "net/http/escape.h" +#include "net/http/http.h" + +TEST(IsAcceptablePath, test) { + EXPECT_TRUE(IsAcceptablePath("/", 1)); + EXPECT_TRUE(IsAcceptablePath("index.html", 10)); + EXPECT_TRUE(IsAcceptablePath("/index.html", 11)); + EXPECT_TRUE(IsAcceptablePath("/index.html", -1)); +} + +TEST(IsAcceptablePath, testEmptyString_allowedIfYouLikeImplicitLeadingSlash) { + EXPECT_TRUE(IsAcceptablePath(0, 0)); + EXPECT_TRUE(IsAcceptablePath(0, -1)); + EXPECT_TRUE(IsAcceptablePath("", 0)); +} + +TEST(IsAcceptablePath, testHiddenFiles_notAllowed) { + EXPECT_FALSE(IsAcceptablePath("/.index.html", 12)); + EXPECT_FALSE(IsAcceptablePath("/x/.index.html", 14)); +} + +TEST(IsAcceptablePath, testDoubleSlash_notAllowed) { + EXPECT_FALSE(IsAcceptablePath("//", 2)); + EXPECT_FALSE(IsAcceptablePath("foo//", 5)); + EXPECT_FALSE(IsAcceptablePath("/foo//", 6)); + EXPECT_FALSE(IsAcceptablePath("/foo//bar", 9)); +} + +TEST(IsAcceptablePath, testNoncanonicalDirectories_areForbidden) { + EXPECT_FALSE(IsAcceptablePath(".", 1)); + EXPECT_FALSE(IsAcceptablePath("..", 2)); + EXPECT_FALSE(IsAcceptablePath("/.", 2)); + EXPECT_FALSE(IsAcceptablePath("/..", 3)); + EXPECT_FALSE(IsAcceptablePath("./", 2)); + EXPECT_FALSE(IsAcceptablePath("../", 3)); + EXPECT_FALSE(IsAcceptablePath("/./", 3)); + EXPECT_FALSE(IsAcceptablePath("/../", 4)); + EXPECT_FALSE(IsAcceptablePath("x/.", 3)); + EXPECT_FALSE(IsAcceptablePath("x/..", 4)); + EXPECT_FALSE(IsAcceptablePath("x/./", 4)); + EXPECT_FALSE(IsAcceptablePath("x/../", 5)); + EXPECT_FALSE(IsAcceptablePath("/x/./", 5)); + EXPECT_FALSE(IsAcceptablePath("/x/../", 6)); +} + +TEST(IsAcceptablePath, testNoncanonicalWindowsDirs_areForbidden) { + EXPECT_FALSE(IsAcceptablePath(".", 1)); + EXPECT_FALSE(IsAcceptablePath("..", 2)); + EXPECT_FALSE(IsAcceptablePath("\\.", 2)); + EXPECT_FALSE(IsAcceptablePath("\\..", 3)); + EXPECT_FALSE(IsAcceptablePath(".\\", 2)); + EXPECT_FALSE(IsAcceptablePath("..\\", 3)); + EXPECT_FALSE(IsAcceptablePath("\\.\\", 3)); + EXPECT_FALSE(IsAcceptablePath("\\..\\", 4)); + EXPECT_FALSE(IsAcceptablePath("x\\.", 3)); + EXPECT_FALSE(IsAcceptablePath("x\\..", 4)); + EXPECT_FALSE(IsAcceptablePath("x\\.\\", 4)); + EXPECT_FALSE(IsAcceptablePath("x\\..\\", 5)); + EXPECT_FALSE(IsAcceptablePath("\\x\\.\\", 5)); + EXPECT_FALSE(IsAcceptablePath("\\x\\..\\", 6)); +} + +TEST(IsAcceptablePath, testOverlongSlashDot_isDetected) { + EXPECT_FALSE(IsAcceptablePath("/\300\256", 3)); + EXPECT_FALSE(IsAcceptablePath("/\300\257", 3)); + EXPECT_FALSE(IsAcceptablePath("\300\256\300\256", 4)); +} + +BENCH(IsAcceptablePath, bench) { + EZBENCH2("IsAcceptablePath", donothing, IsAcceptablePath("/index.html", 11)); +} diff --git a/test/net/http/parsehttprequest_test.c b/test/net/http/parsehttprequest_test.c index 5047fa829..3aec4789e 100644 --- a/test/net/http/parsehttprequest_test.c +++ b/test/net/http/parsehttprequest_test.c @@ -202,6 +202,35 @@ User-Agent: \t hi there \t \r\n\ EXPECT_STREQ("hi there", gc(slice(m, req->headers[kHttpUserAgent]))); } +TEST(ParseHttpRequest, testAbsentHost_setsSliceToZero) { + static const char m[] = "\ +GET / HTTP/1.1\r\n\ +\r\n"; + EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m))); + EXPECT_EQ(0, req->headers[kHttpHost].a); + EXPECT_EQ(0, req->headers[kHttpHost].b); +} + +TEST(ParseHttpRequest, testEmptyHost_setsSliceToNonzeroValue) { + static const char m[] = "\ +GET / HTTP/1.1\r\n\ +Host:\r\n\ +\r\n"; + EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m))); + EXPECT_NE(0, req->headers[kHttpHost].a); + EXPECT_EQ(req->headers[kHttpHost].a, req->headers[kHttpHost].b); +} + +TEST(ParseHttpRequest, testEmptyHost2_setsSliceToNonzeroValue) { + static const char m[] = "\ +GET / HTTP/1.1\r\n\ +Host: \r\n\ +\r\n"; + EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m))); + EXPECT_NE(0, req->headers[kHttpHost].a); + EXPECT_EQ(req->headers[kHttpHost].a, req->headers[kHttpHost].b); +} + void DoTiniestHttpRequest(void) { static const char m[] = "\ GET /\r\n\ diff --git a/test/net/http/parseurl_test.c b/test/net/http/parseurl_test.c new file mode 100644 index 000000000..219ae77aa --- /dev/null +++ b/test/net/http/parseurl_test.c @@ -0,0 +1,357 @@ +/*-*- 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 2021 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/limits.h" +#include "libc/mem/mem.h" +#include "libc/rand/rand.h" +#include "libc/testlib/ezbench.h" +#include "libc/testlib/hyperion.h" +#include "libc/testlib/testlib.h" +#include "net/http/url.h" + +TEST(ParseRequestUri, testEmpty) { + struct Url h; + gc(ParseRequestUri(0, 0, &h)); + gc(h.params.p); + ASSERT_EQ(0, h.params.n); +} + +TEST(ParseRequestUri, testFragment) { + struct Url h; + gc(ParseRequestUri("#x", -1, &h)); + gc(h.params.p); + ASSERT_EQ(0, h.path.n); + ASSERT_EQ(1, h.fragment.n); + ASSERT_BINEQ(u"x", h.fragment.p); +} + +TEST(ParseRequestUri, testFragmentAbsent_isNull) { + struct Url h; + gc(ParseRequestUri("", -1, &h)); + gc(h.params.p); + ASSERT_EQ(0, h.fragment.p); + ASSERT_EQ(0, h.fragment.n); +} + +TEST(ParseRequestUri, testFragmentEmpty_isNonNull) { + struct Url h; + gc(ParseRequestUri("#", -1, &h)); + gc(h.params.p); + ASSERT_NE(0, h.fragment.p); + ASSERT_EQ(0, h.fragment.n); +} + +TEST(ParseRequestUri, testPathFragment) { + struct Url h; + gc(ParseRequestUri("x#y", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ('x', h.path.p[0]); + ASSERT_EQ(1, h.fragment.n); + ASSERT_EQ('y', h.fragment.p[0]); +} + +TEST(ParseRequestUri, testAbsolutePath) { + struct Url h; + gc(ParseRequestUri("/x/y", -1, &h)); + gc(h.params.p); + ASSERT_EQ(4, h.path.n); + ASSERT_BINEQ(u"/x/y", h.path.p); +} + +TEST(ParseRequestUri, testRelativePath1) { + struct Url h; + gc(ParseRequestUri("x", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ('x', h.path.p[0]); +} + +TEST(ParseRequestUri, testOptions) { + struct Url h; + gc(ParseRequestUri("*", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ('*', h.path.p[0]); +} + +TEST(ParseRequestUri, testRelativePath2) { + struct Url h; + gc(ParseRequestUri("x/y", -1, &h)); + gc(h.params.p); + ASSERT_EQ(3, h.path.n); + ASSERT_BINEQ(u"x/y", h.path.p); +} + +TEST(ParseRequestUri, testRoot) { + struct Url h; + gc(ParseRequestUri("/", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ('/', h.path.p[0]); +} + +TEST(ParseRequestUri, testSchemePath) { + struct Url h; + gc(ParseRequestUri("x:y", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.scheme.n); + ASSERT_BINEQ(u"x", h.scheme.p); + ASSERT_EQ(1, h.path.n); + ASSERT_BINEQ(u"y", h.path.p); +} + +TEST(ParseRequestUri, testSchemeAuthority) { + struct Url h; + gc(ParseRequestUri("x://y", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.scheme.n); + ASSERT_EQ('x', h.scheme.p[0]); + ASSERT_EQ(1, h.host.n); + ASSERT_EQ('y', h.host.p[0]); +} + +TEST(ParseRequestUri, testParamsQuestion_doesntTurnIntoSpace) { + struct Url h; + gc(ParseRequestUri("x?+", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_BINEQ(u"x", h.path.p); + ASSERT_EQ(1, h.params.n); + ASSERT_EQ(1, h.params.p[0].key.n); + ASSERT_EQ('+', h.params.p[0].key.p[0]); +} + +TEST(ParseRequestUri, testUrl) { + struct Url h; + gc(ParseRequestUri("a://b:B@c:C/d?e#f", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.scheme.n); + ASSERT_EQ('a', h.scheme.p[0]); + ASSERT_EQ(1, h.user.n); + ASSERT_EQ('b', h.user.p[0]); + ASSERT_EQ(1, h.pass.n); + ASSERT_EQ('B', h.pass.p[0]); + ASSERT_EQ(1, h.host.n); + ASSERT_EQ('c', h.host.p[0]); + ASSERT_EQ(1, h.port.n); + ASSERT_EQ('C', h.port.p[0]); + ASSERT_EQ(2, h.path.n); + ASSERT_BINEQ(u"/d", h.path.p); + ASSERT_EQ(1, h.params.n); + ASSERT_EQ(1, h.params.p[0].key.n); + ASSERT_BINEQ(u"e", h.params.p[0].key.p); + ASSERT_EQ(SIZE_MAX, h.params.p[0].val.n); + ASSERT_EQ(1, h.fragment.n); + ASSERT_BINEQ(u"f", h.fragment.p); +} + +TEST(ParseRequestUri, testUrlWithoutScheme) { + struct Url h; + gc(ParseRequestUri("//b@c/d?e#f", -1, &h)); + gc(h.params.p); + ASSERT_EQ(0, h.scheme.n); + ASSERT_EQ(1, h.user.n); + ASSERT_EQ('b', h.user.p[0]); + ASSERT_EQ(1, h.host.n); + ASSERT_EQ('c', h.host.p[0]); + ASSERT_EQ(2, h.path.n); + ASSERT_BINEQ(u"/d", h.path.p); + ASSERT_EQ(1, h.params.n); + ASSERT_EQ(1, h.params.p[0].key.n); + ASSERT_BINEQ(u"e", h.params.p[0].key.p); + ASSERT_EQ(SIZE_MAX, h.params.p[0].val.n); + ASSERT_EQ(1, h.fragment.n); + ASSERT_BINEQ(u"f", h.fragment.p); +} + +TEST(ParseRequestUri, testUrlWithoutUser) { + struct Url h; + gc(ParseRequestUri("a://c/d?e#f", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.scheme.n); + ASSERT_EQ('a', h.scheme.p[0]); + ASSERT_EQ(0, h.user.n); + ASSERT_EQ(0, h.pass.n); + ASSERT_EQ(1, h.host.n); + ASSERT_EQ('c', h.host.p[0]); + ASSERT_EQ(0, h.port.n); + ASSERT_EQ(2, h.path.n); + ASSERT_BINEQ(u"/d", h.path.p); + ASSERT_EQ(1, h.params.n); + ASSERT_EQ(1, h.params.p[0].key.n); + ASSERT_EQ('e', h.params.p[0].key.p[0]); + ASSERT_EQ(SIZE_MAX, h.params.p[0].val.n); + ASSERT_EQ(1, h.fragment.n); + ASSERT_EQ('f', h.fragment.p[0]); +} + +TEST(ParseRequestUri, testLolv6) { + struct Url h; + gc(ParseRequestUri("//[::1]:31337", -1, &h)); + gc(h.params.p); + ASSERT_EQ(3, h.host.n); + ASSERT_BINEQ(u"::1", h.host.p); + ASSERT_EQ(5, h.port.n); + ASSERT_BINEQ(u"31337", h.port.p); +} + +TEST(ParseRequestUri, testUrlWithoutParams) { + struct Url h; + gc(ParseRequestUri("a://b@c/d#f", -1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.scheme.n); + ASSERT_EQ('a', h.scheme.p[0]); + ASSERT_EQ(1, h.user.n); + ASSERT_EQ('b', h.user.p[0]); + ASSERT_EQ(1, h.host.n); + ASSERT_EQ('c', h.host.p[0]); + ASSERT_EQ(2, h.path.n); + ASSERT_BINEQ(u"/d", h.path.p); + ASSERT_EQ(0, h.params.n); + ASSERT_EQ(1, h.fragment.n); + ASSERT_EQ('f', h.fragment.p[0]); +} + +TEST(ParseUrl, testLatin1_doesNothing) { + struct Url h; + const char b[1] = {0377}; + gc(ParseUrl(b, 1, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ(0, memcmp("\377", h.path.p, 1)); +} + +TEST(ParseRequestUri, testLatin1_expandsMemoryToUtf8) { + struct Url h; + const char b[1] = {0377}; + gc(ParseRequestUri(b, 1, &h)); + gc(h.params.p); + ASSERT_EQ(2, h.path.n); + ASSERT_EQ(0, memcmp("\303\277", h.path.p, 2)); +} + +TEST(ParseRequestUri, testPercentShrinkingMemory) { + struct Url h; + gc(ParseRequestUri("%Ff", 3, &h)); + gc(h.params.p); + ASSERT_EQ(1, h.path.n); + ASSERT_EQ(0, memcmp("\377", h.path.p, 1)); +} + +TEST(ParseRequestUri, testBadPercent_getsIgnored) { + struct Url h; + gc(ParseRequestUri("%FZ", 3, &h)); + gc(h.params.p); + ASSERT_EQ(3, h.path.n); + ASSERT_EQ(0, memcmp("%FZ", h.path.p, 3)); +} + +TEST(ParseRequestUri, testFileUrl) { + struct Url h; + gc(ParseRequestUri("file:///etc/passwd", -1, &h)); + gc(h.params.p); + ASSERT_EQ(4, h.scheme.n); + ASSERT_BINEQ(u"file", h.scheme.p); + ASSERT_EQ(11, h.path.n); + ASSERT_BINEQ(u"/etc/passwd", h.path.p); +} + +TEST(ParseRequestUri, testZipUri2) { + struct Url h; + gc(ParseRequestUri("zip:etc/passwd", -1, &h)); + gc(h.params.p); + ASSERT_EQ(3, h.scheme.n); + ASSERT_BINEQ(u"zip", h.scheme.p); + ASSERT_EQ(10, h.path.n); + ASSERT_BINEQ(u"etc/passwd", h.path.p); +} + +TEST(ParseParams, testEmpty) { + struct UrlParams h = {0}; + gc(ParseParams(0, 0, &h)); + gc(h.p); + ASSERT_EQ(0, h.n); +} + +TEST(ParseParams, test) { + struct UrlParams h = {0}; + gc(ParseParams("a=b&c&x+y%7A=", -1, &h)); + gc(h.p); + ASSERT_EQ(3, h.n); + ASSERT_EQ(1, h.p[0].key.n); + ASSERT_EQ(1, h.p[0].val.n); + ASSERT_EQ(1, h.p[1].key.n); + ASSERT_EQ(SIZE_MAX, h.p[1].val.n); + ASSERT_EQ(4, h.p[2].key.n); + ASSERT_EQ(0, h.p[2].val.n); + EXPECT_EQ('a', h.p[0].key.p[0]); + EXPECT_EQ('b', h.p[0].val.p[0]); + EXPECT_EQ('c', h.p[1].key.p[0]); + EXPECT_BINEQ(u"x yz", h.p[2].key.p); +} + +TEST(ParseParams, testLatin1_doesNothing) { + struct UrlParams h = {0}; + gc(ParseParams("\200", -1, &h)); + gc(h.p); + ASSERT_EQ(1, h.n); + ASSERT_EQ(1, h.p[0].key.n); + ASSERT_EQ(0200, h.p[0].key.p[0] & 255); +} + +TEST(ParseParams, testUtf8_doesNothing) { + struct UrlParams h = {0}; + gc(ParseParams("\300\200", -1, &h)); + gc(h.p); + ASSERT_EQ(1, h.n); + ASSERT_EQ(2, h.p[0].key.n); + ASSERT_EQ(0300, h.p[0].key.p[0] & 255); + ASSERT_EQ(0200, h.p[0].key.p[1] & 255); +} + +TEST(ParseRequestUri, fuzz) { + int i, j; + struct Url h; + char B[13], C[] = "/:#?%[]:@&=abc123xyz\200\300"; + for (i = 0; i < 1024; ++i) { + for (j = 0; j < sizeof(B); ++j) { + B[j] = C[rand() % sizeof(C)]; + } + free(ParseRequestUri(B, 8, &h)); + free(h.params.p); + } +} + +void A(void) { + struct UrlParams h = {0}; + free(ParseParams(kHyperion, kHyperionSize, &h)); + free(h.p); +} + +BENCH(url, bench) { + struct Url h; + EZBENCH2("ParseParams", donothing, A()); + EZBENCH2("URI a", donothing, free(ParseRequestUri("a", -1, &h))); + EZBENCH2("URI a://b@c/d#f", donothing, + free(ParseRequestUri("a://b@c/d#f", -1, &h))); + EZBENCH2("URI a://b@c/d?z#f", donothing, ({ + free(ParseRequestUri("a://b@c/?zd#f", -1, &h)); + free(h.params.p); + })); +} diff --git a/test/net/http/visualizecontrolcodes_test.c b/test/net/http/visualizecontrolcodes_test.c index b307f0b4d..8c33ccd37 100644 --- a/test/net/http/visualizecontrolcodes_test.c +++ b/test/net/http/visualizecontrolcodes_test.c @@ -28,6 +28,12 @@ TEST(VisualizeControlCodes, test) { EXPECT_STREQ("hello\\u0085", VisualizeControlCodes("hello\302\205", -1, 0)); } +TEST(VisualizeControlCodes, testOom_returnsNullAndSetsSizeToZero) { + size_t n = 31337; + EXPECT_EQ(NULL, VisualizeControlCodes("hello", 0x1000000000000, &n)); + EXPECT_EQ(0, n); +} + BENCH(VisualizeControlCodes, bench) { EZBENCH2("VisualizeControlCodes", donothing, free(VisualizeControlCodes(kHyperion, kHyperionSize, 0))); diff --git a/third_party/chibicc/as.c b/third_party/chibicc/as.c index 8d59d04a6..88c430b49 100644 --- a/third_party/chibicc/as.c +++ b/third_party/chibicc/as.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" #include "libc/elf/def.h" @@ -138,16 +139,7 @@ #define APPEND(L) L.p = realloc(L.p, ++L.n * sizeof(*L.p)) #define IS(P, N, S) (N == sizeof(S) - 1 && !strncasecmp(P, S, sizeof(S) - 1)) #define MAX(X, Y) ((Y) < (X) ? (X) : (Y)) -#define LOAD128BE(S) ((unsigned __int128)LOAD64BE(S) << 64 | LOAD64BE((S) + 8)) -#define LOAD64BE(S) \ - ((unsigned long)((unsigned char *)(S))[0] << 070 | \ - (unsigned long)((unsigned char *)(S))[1] << 060 | \ - (unsigned long)((unsigned char *)(S))[2] << 050 | \ - (unsigned long)((unsigned char *)(S))[3] << 040 | \ - (unsigned long)((unsigned char *)(S))[4] << 030 | \ - (unsigned long)((unsigned char *)(S))[5] << 020 | \ - (unsigned long)((unsigned char *)(S))[6] << 010 | \ - (unsigned long)((unsigned char *)(S))[7] << 000) +#define READ128BE(S) ((unsigned __int128)READ64BE(S) << 64 | READ64BE((S) + 8)) struct As { int i; // things @@ -1911,13 +1903,13 @@ static void CopyLower(char *k, const char *p, int n) { static unsigned long MakeKey64(const char *p, int n) { char k[8] = {0}; CopyLower(k, p, n); - return LOAD64BE(k); + return READ64BE(k); } static unsigned __int128 MakeKey128(const char *p, int n) { char k[16] = {0}; CopyLower(k, p, n); - return LOAD128BE(k); + return READ128BE(k); } static bool Prefix(struct As *a, const char *p, int n) { @@ -1929,7 +1921,7 @@ static bool Prefix(struct As *a, const char *p, int n) { r = ARRAYLEN(kPrefix) - 1; while (l <= r) { m = (l + r) >> 1; - y = LOAD64BE(kPrefix[m]); + y = READ64BE(kPrefix[m]); if (x < y) { r = m - 1; } else if (x > y) { @@ -1954,7 +1946,7 @@ static bool FindReg(const char *p, int n, struct Reg *out_reg) { r = ARRAYLEN(kRegs) - 1; while (l <= r) { m = (l + r) >> 1; - y = LOAD64BE(kRegs[m].s); + y = READ64BE(kRegs[m].s); if (x < y) { r = m - 1; } else if (x > y) { @@ -3710,7 +3702,7 @@ static bool OnDirective8(struct As *a, struct Slice s) { r = ARRAYLEN(kDirective8) - 1; while (l <= r) { m = (l + r) >> 1; - y = LOAD64BE(kDirective8[m].s); + y = READ64BE(kDirective8[m].s); if (x < y) { r = m - 1; } else if (x > y) { @@ -3733,7 +3725,7 @@ static bool OnDirective16(struct As *a, struct Slice s) { r = ARRAYLEN(kDirective16) - 1; while (l <= r) { m = (l + r) >> 1; - y = LOAD128BE(kDirective16[m].s); + y = READ128BE(kDirective16[m].s); if (x < y) { r = m - 1; } else if (x > y) { diff --git a/third_party/dlmalloc/dlmalloc.c b/third_party/dlmalloc/dlmalloc.c index 4bf1b9810..4b33edc6c 100644 --- a/third_party/dlmalloc/dlmalloc.c +++ b/third_party/dlmalloc/dlmalloc.c @@ -37,9 +37,10 @@ hidden struct MallocParams g_mparams; */ static void *dlmalloc_requires_more_vespene_gas(size_t size) { char *p; - p = mapanon(size); - if (weaken(__asan_poison)) { - weaken(__asan_poison)((uintptr_t)p, size, kAsanHeapFree); + if ((p = mapanon(size)) != MAP_FAILED) { + if (weaken(__asan_poison)) { + weaken(__asan_poison)((uintptr_t)p, size, kAsanHeapFree); + } } return p; } @@ -836,7 +837,7 @@ textstartup void dlmalloc_init(void) { if (g_mparams.magic == 0) { size_t magic; size_t psize = PAGESIZE; - size_t gsize = FRAMESIZE; + size_t gsize = DEFAULT_GRANULARITY; /* Sanity-check configuration: size_t must be unsigned and as wide as pointer type. ints must be at least 4 bytes. diff --git a/third_party/dlmalloc/dlmalloc.internal.h b/third_party/dlmalloc/dlmalloc.internal.h index a88b8000d..5be234213 100644 --- a/third_party/dlmalloc/dlmalloc.internal.h +++ b/third_party/dlmalloc/dlmalloc.internal.h @@ -907,7 +907,7 @@ extern struct MallocParams g_mparams; #else /* GNUC */ #define RTCHECK(e) (e) #endif /* GNUC */ -#else /* !IsTrustworthy() */ +#else /* !IsTrustworthy() */ #define RTCHECK(e) (1) #endif /* !IsTrustworthy() */ diff --git a/tool/build/lib/cvt.c b/tool/build/lib/cvt.c index 7a85bb262..04f4373dc 100644 --- a/tool/build/lib/cvt.c +++ b/tool/build/lib/cvt.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/macros.internal.h" #include "libc/math.h" +#include "libc/str/str.h" #include "tool/build/lib/cvt.h" #include "tool/build/lib/endian.h" #include "tool/build/lib/machine.h" diff --git a/tool/build/lib/endian.h b/tool/build/lib/endian.h index da716f707..f23d1d39b 100644 --- a/tool/build/lib/endian.h +++ b/tool/build/lib/endian.h @@ -1,116 +1,53 @@ #ifndef COSMOPOLITAN_TOOL_BUILD_LIB_ENDIAN_H_ #define COSMOPOLITAN_TOOL_BUILD_LIB_ENDIAN_H_ -#include "libc/dce.h" -#include "libc/str/str.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -#if __BYTE_ORDER__ + 0 == 1234 +#include "libc/bits/bits.h" -#define Read8(P) \ - ({ \ - uint8_t *Ptr = (P); \ - *Ptr; \ +#define Read8(P) (*(const uint8_t *)(P)) + +#define Read16(P) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(P); \ + READ16LE(P); \ }) -#define Read16(P) \ - ({ \ - uint16_t Res; \ - uint8_t *Ptr = (P); \ - memcpy(&Res, Ptr, 2); \ - Res; \ +#define Read32(P) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(P); \ + READ32LE(P); \ }) -#define Read32(P) \ - ({ \ - uint32_t Res; \ - uint8_t *Ptr = (P); \ - memcpy(&Res, Ptr, 4); \ - Res; \ +#define Read64(P) \ + ({ \ + const uint8_t *Ptr = (const uint8_t *)(P); \ + READ64LE(P); \ }) -#define Read64(P) \ - ({ \ - uint64_t Res; \ - uint8_t *Ptr = (P); \ - memcpy(&Res, Ptr, 8); \ - Res; \ - }) - -#define Write8(P, B) \ +#define Write8(P, V) \ do { \ + uint8_t Val = (V); \ uint8_t *Ptr = (P); \ - *Ptr = (B); \ + *Ptr = Val; \ } while (0) -#define Write16(P, V) \ - do { \ - uint16_t Val = (V); \ - uint8_t *Ptr = (P); \ - memcpy(Ptr, &Val, 2); \ +#define Write16(P, V) \ + do { \ + uint16_t Val = (V); \ + uint8_t *Ptr = (P); \ + WRITE16LE(Ptr, Val); \ } while (0) -#define Write32(P, V) \ - do { \ - uint32_t Val = (V); \ - uint8_t *Ptr = (P); \ - memcpy(Ptr, &Val, 4); \ +#define Write32(P, V) \ + do { \ + uint32_t Val = (V); \ + uint8_t *Ptr = (P); \ + WRITE32LE(Ptr, Val); \ } while (0) -#define Write64(P, V) \ - do { \ - uint64_t Val = (V); \ - uint8_t *Ptr = (P); \ - memcpy(Ptr, &Val, 8); \ +#define Write64(P, V) \ + do { \ + uint64_t Val = (V); \ + uint8_t *Ptr = (P); \ + WRITE64LE(Ptr, Val); \ } while (0) -#else - -forceinline uint16_t Read8(const uint8_t p[hasatleast 1]) { - return p[0]; -} - -forceinline uint16_t Read16(const uint8_t p[hasatleast 2]) { - return p[0] | p[1] << 010; -} - -forceinline uint32_t Read32(const uint8_t bytes[hasatleast 4]) { - return (uint32_t)bytes[0] << 000 | (uint32_t)bytes[1] << 010 | - (uint32_t)bytes[2] << 020 | (uint32_t)bytes[3] << 030; -} - -forceinline uint64_t Read64(const uint8_t bytes[hasatleast 8]) { - return (uint64_t)bytes[0] << 000 | (uint64_t)bytes[1] << 010 | - (uint64_t)bytes[2] << 020 | (uint64_t)bytes[3] << 030 | - (uint64_t)bytes[4] << 040 | (uint64_t)bytes[5] << 050 | - (uint64_t)bytes[6] << 060 | (uint64_t)bytes[7] << 070; -} - -forceinline void Write8(unsigned char p[hasatleast 1], uint8_t x) { - p[0] = x >> 000; -} - -forceinline void Write16(unsigned char p[hasatleast 2], uint16_t x) { - p[0] = x >> 000; - p[1] = x >> 010; -} - -forceinline void Write32(unsigned char p[hasatleast 4], uint64_t x) { - p[0] = x >> 000; - p[1] = x >> 010; - p[2] = x >> 020; - p[3] = x >> 030; -} - -forceinline void Write64(unsigned char p[hasatleast 8], uint64_t x) { - p[0] = x >> 000; - p[1] = x >> 010; - p[2] = x >> 020; - p[3] = x >> 030; - p[4] = x >> 040; - p[5] = x >> 050; - p[6] = x >> 060; - p[7] = x >> 070; -} - -#endif /* ENDIAN */ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_TOOL_BUILD_LIB_ENDIAN_H_ */ diff --git a/tool/build/lib/machine.c b/tool/build/lib/machine.c index c6478ce4b..72a42522a 100644 --- a/tool/build/lib/machine.c +++ b/tool/build/lib/machine.c @@ -20,6 +20,7 @@ #include "libc/macros.internal.h" #include "libc/rand/rand.h" #include "libc/runtime/runtime.h" +#include "libc/str/str.h" #include "tool/build/lib/abp.h" #include "tool/build/lib/address.h" #include "tool/build/lib/alu.h" @@ -1568,7 +1569,11 @@ static void Op1ae(struct Machine *m, uint32_t rde) { } static void OpSalc(struct Machine *m, uint32_t rde) { - Write8(m->ax, GetFlag(m->flags, FLAGS_CF)); + if (GetFlag(m->flags, FLAGS_CF)) { + m->ax[0] = 255; + } else { + m->ax[0] = 0; + } } static void OpBofram(struct Machine *m, uint32_t rde) { diff --git a/tool/build/lib/stack.c b/tool/build/lib/stack.c index 0ebe775dc..b646183a5 100644 --- a/tool/build/lib/stack.c +++ b/tool/build/lib/stack.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/log/check.h" #include "libc/macros.internal.h" +#include "libc/str/str.h" #include "tool/build/lib/address.h" #include "tool/build/lib/endian.h" #include "tool/build/lib/memory.h" diff --git a/tool/build/lib/syscall.c b/tool/build/lib/syscall.c index e22a07d0e..9ffd239f8 100644 --- a/tool/build/lib/syscall.c +++ b/tool/build/lib/syscall.c @@ -77,6 +77,8 @@ #include "tool/build/lib/throw.h" #include "tool/build/lib/xlaterrno.h" +#define SA_RESTORER 0x04000000 + #define AT_FDCWD_LINUX -100 #define TIOCGWINSZ_LINUX 0x5413 #define TCGETS_LINUX 0x5401 diff --git a/tool/build/lib/word.c b/tool/build/lib/word.c index f77df94b1..fd5d0ab8e 100644 --- a/tool/build/lib/word.c +++ b/tool/build/lib/word.c @@ -16,6 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/str/str.h" #include "tool/build/lib/endian.h" #include "tool/build/lib/memory.h" #include "tool/build/lib/word.h" diff --git a/tool/build/package.c b/tool/build/package.c index b9d1bbe49..a6c1f8184 100644 --- a/tool/build/package.c +++ b/tool/build/package.c @@ -25,6 +25,7 @@ #include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" #include "libc/calls/struct/stat.h" +#include "libc/dce.h" #include "libc/elf/def.h" #include "libc/elf/elf.h" #include "libc/elf/struct/rela.h" @@ -165,8 +166,8 @@ struct Packages { }; int CompareSymbolName(const struct Symbol *a, const struct Symbol *b, - const char *strs[hasatleast 2]) { - return strcmp(&strs[0][a->name], &strs[1][b->name]); + const char *tab) { + return strcmp(tab + a->name, tab + b->name); } struct Package *LoadPackage(const char *path) { @@ -189,6 +190,7 @@ struct Package *LoadPackage(const char *path) { pkg->strings.p); pkg->addr = pkg; pkg->size = st.st_size; + CHECK_NE(-1, mprotect(pkg, st.st_size, PROT_READ)); return pkg; } @@ -378,37 +380,48 @@ void LoadObjects(struct Package *pkg) { size_t i; struct Object *obj; for (i = 0; i < pkg->objects.i; ++i) { - obj = &pkg->objects.p[i]; + obj = pkg->objects.p + i; OpenObject(pkg, obj, O_RDONLY, PROT_READ, MAP_SHARED); LoadSymbols(pkg, i); CloseObject(obj); } - qsort_r(&pkg->symbols.p[0], pkg->symbols.i, sizeof(pkg->symbols.p[0]), - (void *)CompareSymbolName, - (const char *[2]){pkg->strings.p, pkg->strings.p}); + qsort_r(pkg->symbols.p, pkg->symbols.i, sizeof(*pkg->symbols.p), + (void *)CompareSymbolName, pkg->strings.p); +} + +struct Symbol *BisectSymbol(struct Package *pkg, const char *name) { + int c; + long m, l, r; + l = 0; + r = pkg->symbols.i - 1; + while (l <= r) { + m = (l + r) >> 1; + c = strcmp(pkg->strings.p + pkg->symbols.p[m].name, name); + if (c < 0) { + l = m + 1; + } else if (c > 0) { + r = m - 1; + } else { + return pkg->symbols.p + m; + } + } + return NULL; } bool FindSymbol(const char *name, struct Package *pkg, struct Packages *directdeps, struct Package **out_pkg, struct Symbol **out_sym) { - size_t i; - struct Package *dep; - struct Symbol key, *sym; - key.name = 0; - if ((sym = bisect(&key, &pkg->symbols.p[0], pkg->symbols.i, - sizeof(pkg->symbols.p[0]), (void *)CompareSymbolName, - (const char *[2]){name, pkg->strings.p}))) { - if (out_pkg) *out_pkg = pkg; + size_t i, j; + struct Symbol *sym; + if ((sym = BisectSymbol(pkg, name))) { if (out_sym) *out_sym = sym; + if (out_pkg) *out_pkg = pkg; return true; } for (i = 0; i < directdeps->i; ++i) { - dep = directdeps->p[i]; - if ((sym = bisect(&key, &dep->symbols.p[0], dep->symbols.i, - sizeof(dep->symbols.p[0]), (void *)CompareSymbolName, - (const char *[2]){name, dep->strings.p}))) { - if (out_pkg) *out_pkg = dep; + if ((sym = BisectSymbol(directdeps->p[i], name))) { if (out_sym) *out_sym = sym; + if (out_pkg) *out_pkg = directdeps->p[i]; return true; } } @@ -422,15 +435,15 @@ void CheckStrictDeps(struct Package *pkg, struct Packages *deps) { for (i = 0; i < pkg->undefs.i; ++i) { undef = &pkg->undefs.p[i]; if (undef->bind == STB_WEAK) continue; - if (!FindSymbol(&pkg->strings.p[undef->name], pkg, deps, NULL, NULL)) { - fprintf(stderr, "%s: %s (%s) %s %s\n", "error", - &pkg->strings.p[undef->name], - &pkg->strings.p[pkg->objects.p[undef->object].path], - "not defined by direct deps of", &pkg->strings.p[pkg->path]); + if (!FindSymbol(pkg->strings.p + undef->name, pkg, deps, NULL, NULL)) { + fprintf(stderr, "%s: %`'s (%s) %s %s\n", "error", + pkg->strings.p + undef->name, + pkg->strings.p + pkg->objects.p[undef->object].path, + "not defined by direct deps of", pkg->strings.p + pkg->path); for (j = 0; j < deps->i; ++j) { dep = deps->p[j]; fputc('\t', stderr); - fputs(&dep->strings.p[dep->path], stderr); + fputs(dep->strings.p + dep->path, stderr); fputc('\n', stderr); } exit(1); diff --git a/tool/build/zipobj.c b/tool/build/zipobj.c index 5804775c6..3b6f21186 100644 --- a/tool/build/zipobj.c +++ b/tool/build/zipobj.c @@ -55,16 +55,6 @@ #define ZIP_LOCALFILE_SECTION ".zip.2." #define ZIP_DIRECTORY_SECTION ".zip.4." -#define PUT8(P, V) *P++ = V -#define PUT16(P, V) P[0] = V & 0xff, P[1] = V >> 010 & 0xff, P += 2 -#define PUT32(P, V) \ - P[0] = V & 0xff, P[1] = V >> 010 & 0xff, P[2] = V >> 020 & 0xff, \ - P[3] = V >> 030 & 0xff, P += 4 -#define PUT64(P, V) \ - P[0] = V & 0xff, P[1] = V >> 010 & 0xff, P[2] = V >> 020 & 0xff, \ - P[3] = V >> 030 & 0xff, P[4] = V >> 040 & 0xff, P[5] = V >> 050 & 0xff, \ - P[6] = V >> 060 & 0xff, P[7] = V >> 070 & 0xff, P += 8 - #define DOS_DATE(YEAR, MONTH_IDX1, DAY_IDX1) \ (((YEAR)-1980) << 9 | (MONTH_IDX1) << 5 | (DAY_IDX1)) #define DOS_TIME(HOUR, MINUTE, SECOND) \ @@ -116,10 +106,24 @@ void GetOpts(int *argc, char ***argv) { CHECK_NOTNULL(outpath_); } -bool IsPureAscii(const void *data, size_t size) { +bool IsUtf8(const void *data, size_t size) { + const unsigned char *p, *pe; + for (p = data, pe = p + size; p + 2 <= pe; ++p) { + if (*p >= 0300) { + if (*p >= 0200 && *p < 0300) { + return true; + } else { + return false; + } + } + } + return false; +} + +bool IsText(const void *data, size_t size) { const unsigned char *p, *pe; for (p = data, pe = p + size; p < pe; ++p) { - if (!*p || *p >= 0x80) { + if (*p <= 3) { return false; } } @@ -146,86 +150,81 @@ void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time, *out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1); } -static unsigned char *EmitZipLfileHdr(unsigned char *op, const void *name, +static int DetermineVersionNeededToExtract(int method) { + if (method == kZipCompressionDeflate) { + return kZipEra1993; + } else { + return kZipEra1989; + } +} + +static unsigned char *EmitZipLfileHdr(unsigned char *p, const void *name, size_t namesize, uint32_t crc, uint8_t era, uint16_t gflags, uint16_t method, uint16_t mtime, uint16_t mdate, size_t compsize, size_t uncompsize) { - PUT32(op, kZipLfileHdrMagic); - PUT8(op, kZipEra1993); - PUT8(op, kZipOsDos); - PUT16(op, gflags); - PUT16(op, method); - PUT16(op, mtime); - PUT16(op, mdate); - PUT32(op, crc); - PUT32(op, compsize); - PUT32(op, uncompsize); - PUT16(op, namesize); - PUT16(op, 0); /* extra */ - return mempcpy(op, name, namesize); + p = WRITE32LE(p, kZipLfileHdrMagic); + *p++ = era; + *p++ = kZipOsDos; + p = WRITE16LE(p, gflags); + p = WRITE16LE(p, method); + p = WRITE16LE(p, mtime); + p = WRITE16LE(p, mdate); + p = WRITE32LE(p, crc); + p = WRITE32LE(p, compsize); + p = WRITE32LE(p, uncompsize); + p = WRITE16LE(p, namesize); + p = WRITE16LE(p, 0); /* extra */ + return mempcpy(p, name, namesize); } -static void EmitZipCdirHdr(unsigned char *op, const void *name, size_t namesize, +static void EmitZipCdirHdr(unsigned char *p, const void *name, size_t namesize, uint32_t crc, uint8_t era, uint16_t gflags, uint16_t method, uint16_t mtime, uint16_t mdate, uint16_t iattrs, uint16_t dosmode, uint16_t unixmode, size_t compsize, size_t uncompsize, size_t commentsize, struct stat *st) { uint64_t mt, at, ct; - PUT32(op, kZipCfileHdrMagic); - PUT8(op, 20); - PUT8(op, kZipOsDos); - PUT8(op, kZipEra1993); - PUT8(op, kZipOsDos); - PUT16(op, gflags); - PUT16(op, method); - PUT16(op, mtime); - PUT16(op, mdate); + p = WRITE32LE(p, kZipCfileHdrMagic); + *p++ = kZipCosmopolitanVersion; + *p++ = kZipOsUnix; + *p++ = era; + *p++ = kZipOsDos; + p = WRITE16LE(p, gflags); + p = WRITE16LE(p, method); + p = WRITE16LE(p, mtime); + p = WRITE16LE(p, mdate); /* 16 */ - PUT32(op, crc); - PUT32(op, compsize); - PUT32(op, uncompsize); - PUT16(op, namesize); -#if 0 -#define CFILE_HDR_SIZE kZipCfileHdrMinSize - PUT16(op, 0); /* extra size */ - /* 32 */ - PUT16(op, commentsize); - PUT16(op, 0); /* disk */ - PUT16(op, iattrs); - PUT16(op, dosmode); - PUT16(op, unixmode); - PUT32(op, 0); /* RELOCATE ME (kZipCfileOffsetOffset) */ - /* 46 */ - memcpy(op, name, namesize); -#else + p = WRITE32LE(p, crc); + p = WRITE32LE(p, compsize); + p = WRITE32LE(p, uncompsize); + p = WRITE16LE(p, namesize); #define CFILE_HDR_SIZE (kZipCfileHdrMinSize + 36) - PUT16(op, 36); /* extra size */ + p = WRITE16LE(p, 36); /* extra size */ /* 32 */ - PUT16(op, commentsize); - PUT16(op, 0); /* disk */ - PUT16(op, iattrs); - PUT32(op, dosmode); - PUT32(op, 0); /* RELOCATE ME (kZipCfileOffsetOffset) */ + p = WRITE16LE(p, commentsize); + p = WRITE16LE(p, 0); /* disk */ + p = WRITE16LE(p, iattrs); + p = WRITE16LE(p, dosmode); + p = WRITE16LE(p, unixmode); + p = WRITE32LE(p, 0); /* RELOCATE ME (kZipCfileOffsetOffset) */ /* 46 */ - memcpy(op, name, namesize); - op += namesize; - PUT16(op, kZipExtraNtfs); - PUT16(op, 32); - PUT32(op, 0); - PUT16(op, 1); - PUT16(op, 24); + memcpy(p, name, namesize); + p += namesize; + p = WRITE16LE(p, kZipExtraNtfs); + p = WRITE16LE(p, 32); + p = WRITE32LE(p, 0); + p = WRITE16LE(p, 1); + p = WRITE16LE(p, 24); #define NTTIME(t) \ (t.tv_sec + MODERNITYSECONDS) * HECTONANOSECONDS + t.tv_nsec / 100 mt = NTTIME(st->st_mtim); at = NTTIME(st->st_atim); ct = NTTIME(st->st_ctim); - PUT64(op, mt); - PUT64(op, at); - PUT64(op, ct); -#endif + p = WRITE64LE(p, mt); + p = WRITE64LE(p, at); + p = WRITE64LE(p, ct); } void EmitZip(struct ElfWriter *elf, const char *name, size_t namesize, @@ -238,15 +237,17 @@ void EmitZip(struct ElfWriter *elf, const char *name, size_t namesize, size_t lfilehdrsize, uncompsize, compsize, commentsize; uint16_t method, gflags, mtime, mdate, iattrs, dosmode; + gflags = 0; + iattrs = 0; compsize = st->st_size; uncompsize = st->st_size; CHECK_LE(uncompsize, UINT32_MAX); lfilehdrsize = kZipLfileHdrMinSize + namesize; crc = crc32_z(0, data, uncompsize); GetDosLocalTime(st->st_mtim.tv_sec, &mtime, &mdate); - gflags = IsPureAscii(name, namesize) ? 0 : kZipGflagUtf8; + if (IsUtf8(name, namesize)) gflags |= kZipGflagUtf8; + if (IsText(data, st->st_size)) iattrs |= kZipIattrText; commentsize = kZipCdirHdrLinkableSize - (CFILE_HDR_SIZE + namesize); - iattrs = IsPureAscii(data, st->st_size) ? kZipIattrAscii : kZipIattrBinary; dosmode = !(st->st_mode & 0200) ? kNtFileAttributeReadonly : 0; method = (st->st_size >= kMinCompressSize && ShouldCompress(name, namesize)) ? kZipCompressionDeflate @@ -280,7 +281,7 @@ void EmitZip(struct ElfWriter *elf, const char *name, size_t namesize, if (method == kZipCompressionNone) { memcpy(lfile + lfilehdrsize, data, uncompsize); } - era = (gflags || method) ? kZipEra1993 : kZipEra1989; + era = method ? kZipEra1993 : kZipEra1989; EmitZipLfileHdr(lfile, name, namesize, crc, era, gflags, method, mtime, mdate, compsize, uncompsize); elfwriter_commit(elf, lfilehdrsize + compsize); diff --git a/tool/decode/lib/zipnames.c b/tool/decode/lib/zipnames.c index 23bb65d28..39f028f7d 100644 --- a/tool/decode/lib/zipnames.c +++ b/tool/decode/lib/zipnames.c @@ -29,13 +29,15 @@ const struct IdName kZipCompressionNames[] = { const struct IdName kZipExtraNames[] = { {kZipExtraZip64, "kZipExtraZip64"}, {kZipExtraNtfs, "kZipExtraNtfs"}, + {kZipExtraUnix, "kZipExtraUnix"}, {kZipExtraExtendedTimestamp, "kZipExtraExtendedTimestamp"}, + {kZipExtraInfoZipNewUnixExtra, "kZipExtraInfoZipNewUnixExtra"}, {0, 0}, }; const struct IdName kZipIattrNames[] = { {kZipIattrBinary, "kZipIattrBinary"}, - {kZipIattrAscii, "kZipIattrAscii"}, + {kZipIattrText, "kZipIattrText"}, {0, 0}, }; diff --git a/tool/decode/zip.c b/tool/decode/zip.c index 3ee9bcb1c..151f74bd6 100644 --- a/tool/decode/zip.c +++ b/tool/decode/zip.c @@ -22,6 +22,7 @@ #include "libc/calls/struct/stat.h" #include "libc/fmt/conv.h" #include "libc/log/check.h" +#include "libc/log/log.h" #include "libc/mem/mem.h" #include "libc/nexgen32e/crc32.h" #include "libc/nt/struct/filetime.h" @@ -45,17 +46,17 @@ * @fileoverview Zip File Disassembler. */ -nodiscard char *formatdosdate(uint16_t dosdate) { +nodiscard char *FormatDosDate(uint16_t dosdate) { return xasprintf("%04u-%02u-%02u", ((dosdate >> 9) & 0b1111111) + 1980, (dosdate >> 5) & 0b1111, dosdate & 0b11111); } -nodiscard char *formatdostime(uint16_t dostime) { +nodiscard char *FormatDosTime(uint16_t dostime) { return xasprintf("%02u:%02u:%02u", (dostime >> 11) & 0b11111, (dostime >> 5) & 0b111111, (dostime << 1) & 0b111110); } -void advancepos(uint8_t *map, size_t *pos, size_t off) { +void AdvancePosition(uint8_t *map, size_t *pos, size_t off) { CHECK_GE(off, *pos); if (off > *pos) { printf("\n/\t<%s>\n", "LIMBO"); @@ -65,7 +66,7 @@ void advancepos(uint8_t *map, size_t *pos, size_t off) { *pos = off; } -void showgeneralflag(uint16_t generalflag) { +void ShowGeneralFlag(uint16_t generalflag) { puts("\ / ┌─utf8\n\ / │ ┌─strong encryption\n\ @@ -77,21 +78,21 @@ void showgeneralflag(uint16_t generalflag) { show(".short", format(b1, "0b%016b", generalflag), "generalflag"); } -void showtimestamp(uint16_t time, uint16_t date) { +void ShowTimestamp(uint16_t time, uint16_t date) { show(".short", format(b1, "%#04hx", time), - gc(xasprintf("%s (%s)", "lastmodifiedtime", gc(formatdostime(time))))); + gc(xasprintf("%s (%s)", "lastmodifiedtime", gc(FormatDosTime(time))))); show(".short", format(b1, "%#04hx", date), - gc(xasprintf("%s (%s)", "lastmodifieddate", gc(formatdosdate(date))))); + gc(xasprintf("%s (%s)", "lastmodifieddate", gc(FormatDosDate(date))))); } -void showcompressmethod(uint16_t compressmethod) { +void ShowCompressionMethod(uint16_t compressmethod) { show(".short", firstnonnull(findnamebyid(kZipCompressionNames, compressmethod), format(b1, "%hu", compressmethod)), "compressionmethod"); } -void showextrantfs(uint8_t *ntfs) { +void ShowNtfs(uint8_t *ntfs, size_t n) { struct timespec mtime, atime, ctime; mtime = FileTimeToTimeSpec( (struct NtFileTime){READ32LE(ntfs + 8), READ32LE(ntfs + 12)}); @@ -115,47 +116,85 @@ void showextrantfs(uint8_t *ntfs) { void ShowExtendedTimestamp(uint8_t *p, size_t n, bool islocal) { int flag; - int64_t x; - struct timespec ts; - flag = *p++; - show(".byte", gc(xasprintf("0b%03hhb", flag)), "fields present in local"); - if (!islocal) { - show(".quad", gc(xasprintf("%u", READ32LE(p))), - gc(xasprintf("%s (%s)", "last modified", gc(xiso8601(&ts))))); - } else { - if (flag & 1) { - ts = (struct timespec){READ32LE(p)}; - show(".quad", gc(xasprintf("%u", READ32LE(p))), - gc(xasprintf("%s (%s)", "last modified", gc(xiso8601(&ts))))); + if (n) { + --n; + flag = *p++; + show(".byte", gc(xasprintf("0b%03hhb", flag)), "fields present in local"); + if ((flag & 1) && n >= 4) { + show(".long", gc(xasprintf("%u", READ32LE(p))), + gc(xasprintf("%s (%s)", "last modified", + gc(xiso8601(&(struct timespec){READ32LE(p)}))))); p += 4; + n -= 4; } flag >>= 1; - if (flag & 1) { - ts = (struct timespec){READ32LE(p)}; - show(".quad", gc(xasprintf("%u", READ32LE(p))), - gc(xasprintf("%s (%s)", "access time", gc(xiso8601(&ts))))); - p += 4; - } - flag >>= 1; - if (flag & 1) { - ts = (struct timespec){READ32LE(p)}; - show(".quad", gc(xasprintf("%u", READ32LE(p))), - gc(xasprintf("%s (%s)", "creation time", gc(xiso8601(&ts))))); + if (islocal) { + if ((flag & 1) && n >= 4) { + show(".long", gc(xasprintf("%u", READ32LE(p))), + gc(xasprintf("%s (%s)", "access time", + gc(xiso8601(&(struct timespec){READ32LE(p)}))))); + p += 4; + n -= 4; + } + flag >>= 1; + if ((flag & 1) && n >= 4) { + show(".long", gc(xasprintf("%u", READ32LE(p))), + gc(xasprintf("%s (%s)", "creation time", + gc(xiso8601(&(struct timespec){READ32LE(p)}))))); + p += 4; + n -= 4; + } } } } -void showextra(uint8_t *extra, bool islocal) { +void ShowZip64(uint8_t *p, size_t n, bool islocal) { + if (n >= 8) { + show(".quad", gc(xasprintf("%lu", READ64LE(p))), + gc(xasprintf("uncompressed size (%,ld)", READ64LE(p)))); + } + if (n >= 16) { + show(".quad", gc(xasprintf("%lu", READ64LE(p + 8))), + gc(xasprintf("compressed size (%,ld)", READ64LE(p + 8)))); + } + if (n >= 24) { + show(".quad", gc(xasprintf("%lu", READ64LE(p + 16))), + gc(xasprintf("lfile hdr offset (%,ld)", READ64LE(p + 16)))); + } + if (n >= 28) { + show(".long", gc(xasprintf("%u", READ32LE(p + 24))), "disk number"); + } +} + +void ShowInfoZipNewUnixExtra(uint8_t *p, size_t n, bool islocal) { + if (p[0] == 1 && p[1] == 4 && p[6] == 4) { + show(".byte", "1", "version"); + show(".byte", "4", "uid length"); + show(".long", gc(xasprintf("%u", READ32LE(p + 2))), "uid"); + show(".byte", "4", "gid length"); + show(".long", gc(xasprintf("%u", READ32LE(p + 7))), "gid"); + } else { + disassemblehex(p, n, stdout); + } +} + +void ShowExtra(uint8_t *extra, bool islocal) { switch (ZIP_EXTRA_HEADERID(extra)) { case kZipExtraNtfs: - showextrantfs(ZIP_EXTRA_CONTENT(extra)); + ShowNtfs(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra)); break; case kZipExtraExtendedTimestamp: ShowExtendedTimestamp(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), islocal); break; case kZipExtraZip64: - /* TODO */ + ShowZip64(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), + islocal); + break; + case kZipExtraInfoZipNewUnixExtra: + ShowInfoZipNewUnixExtra(ZIP_EXTRA_CONTENT(extra), + ZIP_EXTRA_CONTENTSIZE(extra), islocal); + break; default: disassemblehex(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra), stdout); @@ -163,7 +202,7 @@ void showextra(uint8_t *extra, bool islocal) { } } -void showexternalattributes(uint8_t *cf) { +void ShowExternalAttributes(uint8_t *cf) { uint32_t ea; ea = ZIP_CFILE_EXTERNALATTRIBUTES(cf); if (ZIP_CFILE_FILEATTRCOMPAT(cf) == kZipOsUnix) { @@ -175,7 +214,7 @@ void showexternalattributes(uint8_t *cf) { } } -void showextras(uint8_t *extras, uint16_t extrassize, bool islocal) { +void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) { int i; bool first; uint8_t *p, *pe; @@ -194,14 +233,14 @@ void showextras(uint8_t *extras, uint16_t extrassize, bool islocal) { first = false; printf("%d:", (i + 1) * 10); } - showextra(p, islocal); + ShowExtra(p, islocal); printf("%d:", (i + 2) * 10); } } putchar('\n'); } -void showlocalfileheader(uint8_t *lf, uint16_t idx) { +void ShowLocalFileHeader(uint8_t *lf, uint16_t idx) { printf("\n/\t%s #%hu (%zu %s)\n", "local file", idx + 1, ZIP_LFILE_HDRSIZE(lf), "bytes"); show(".ascii", format(b1, "%`'.*s", 4, lf), "magic"); @@ -213,17 +252,23 @@ void showlocalfileheader(uint8_t *lf, uint16_t idx) { firstnonnull(findnamebyid(kZipOsNames, ZIP_LFILE_OSNEED(lf)), gc(xasprintf("%d", ZIP_LFILE_OSNEED(lf)))), "os need"); - showgeneralflag(ZIP_LFILE_GENERALFLAG(lf)); - showcompressmethod(ZIP_LFILE_COMPRESSIONMETHOD(lf)); - showtimestamp(ZIP_LFILE_LASTMODIFIEDTIME(lf), ZIP_LFILE_LASTMODIFIEDDATE(lf)); - show(".long", format(b1, "%#x", ZIP_LFILE_CRC32(lf)), - gc(xasprintf( - "%s (%#x)", "crc32z", - crc32_z(0, ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf))))); - show(".long", "3f-2f", - format(b1, "%s (%u %s)", "compressedsize", ZIP_LFILE_COMPRESSEDSIZE(lf), - "bytes")); - show(".long", format(b1, "%u", ZIP_LFILE_UNCOMPRESSEDSIZE(lf)), + ShowGeneralFlag(ZIP_LFILE_GENERALFLAG(lf)); + ShowCompressionMethod(ZIP_LFILE_COMPRESSIONMETHOD(lf)); + ShowTimestamp(ZIP_LFILE_LASTMODIFIEDTIME(lf), ZIP_LFILE_LASTMODIFIEDDATE(lf)); + show( + ".long", + format(b1, "%#x", ZIP_LFILE_CRC32(lf)), gc(xasprintf("%s (%#x)", "crc32z", GetZipLfileCompressedSize(lf) /* crc32_z(0, ZIP_LFILE_CONTENT(lf), GetZipLfileCompressedSize(lf)) */))); + if (ZIP_LFILE_COMPRESSEDSIZE(lf) == 0xFFFFFFFF) { + show(".long", "0xFFFFFFFF", "compressedsize (zip64)"); + } else { + show(".long", "3f-2f", + format(b1, "%s (%u %s)", "compressedsize", + ZIP_LFILE_COMPRESSEDSIZE(lf), "bytes")); + } + show(".long", + ZIP_LFILE_UNCOMPRESSEDSIZE(lf) == 0xFFFFFFFF + ? "0xFFFFFFFF" + : format(b1, "%u", ZIP_LFILE_UNCOMPRESSEDSIZE(lf)), "uncompressedsize"); show(".short", "1f-0f", format(b1, "%s (%hu %s)", "namesize", ZIP_LFILE_NAMESIZE(lf), "bytes")); @@ -236,17 +281,19 @@ void showlocalfileheader(uint8_t *lf, uint16_t idx) { gc(strndup(ZIP_LFILE_NAME(lf), ZIP_LFILE_NAMESIZE(lf)))), "name"); printf("1:"); - showextras(ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true); + ShowExtras(ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true); printf("2:"); - disassemblehex(ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf), stdout); + /* disassemblehex(ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf), + * stdout); */ printf("3:\n"); } -void showcentralfileheader(uint8_t *cf) { +void ShowCentralFileHeader(uint8_t *cf) { printf("\n/\t%s (%zu %s)\n", "central directory file header", ZIP_CFILE_HDRSIZE(cf), "bytes"); show(".ascii", format(b1, "%`'.*s", 4, cf), "magic"); - show(".byte", gc(xasprintf("%d", ZIP_CFILE_VERSIONMADE(cf))), "version made"); + show(".byte", gc(xasprintf("%d", ZIP_CFILE_VERSIONMADE(cf))), + "zip version made"); show(".byte", firstnonnull(findnamebyid(kZipOsNames, ZIP_CFILE_FILEATTRCOMPAT(cf)), gc(xasprintf("%d", ZIP_CFILE_FILEATTRCOMPAT(cf)))), @@ -259,14 +306,22 @@ void showcentralfileheader(uint8_t *cf) { firstnonnull(findnamebyid(kZipOsNames, ZIP_CFILE_OSNEED(cf)), gc(xasprintf("%d", ZIP_CFILE_OSNEED(cf)))), "os need"); - showgeneralflag(ZIP_CFILE_GENERALFLAG(cf)); - showcompressmethod(ZIP_CFILE_COMPRESSIONMETHOD(cf)); - showtimestamp(ZIP_CFILE_LASTMODIFIEDTIME(cf), ZIP_CFILE_LASTMODIFIEDDATE(cf)); + ShowGeneralFlag(ZIP_CFILE_GENERALFLAG(cf)); + ShowCompressionMethod(ZIP_CFILE_COMPRESSIONMETHOD(cf)); + ShowTimestamp(ZIP_CFILE_LASTMODIFIEDTIME(cf), ZIP_CFILE_LASTMODIFIEDDATE(cf)); show(".long", format(b1, "%#x", ZIP_CFILE_CRC32(cf)), "crc32z"); - show(".long", format(b1, "%u", ZIP_CFILE_COMPRESSEDSIZE(cf)), - "compressedsize"); - show(".long", format(b1, "%u", ZIP_CFILE_UNCOMPRESSEDSIZE(cf)), - "uncompressedsize"); + if (ZIP_CFILE_COMPRESSEDSIZE(cf) == 0xFFFFFFFF) { + show(".long", "0xFFFFFFFF", "compressedsize (zip64)"); + } else { + show(".long", format(b1, "%u", ZIP_CFILE_COMPRESSEDSIZE(cf)), + "compressedsize"); + } + if (ZIP_CFILE_UNCOMPRESSEDSIZE(cf) == 0xFFFFFFFF) { + show(".long", "0xFFFFFFFF", "compressedsize (zip64)"); + } else { + show(".long", format(b1, "%u", ZIP_CFILE_UNCOMPRESSEDSIZE(cf)), + "uncompressedsize"); + } show(".short", "1f-0f", format(b1, "%s (%hu %s)", "namesize", ZIP_CFILE_NAMESIZE(cf), "bytes")); show( @@ -277,23 +332,29 @@ void showcentralfileheader(uint8_t *cf) { "bytes")); show(".short", format(b1, "%hu", ZIP_CFILE_DISK(cf)), "disk"); show(".short", - RecreateFlags(kZipIattrNames, ZIP_CFILE_INTERNALATTRIBUTES(cf)), + RecreateFlags(kZipIattrNames, ZIP_CFILE_INTERNALATTRIBUTES(cf) & 1), "internalattributes"); - showexternalattributes(cf); - show(".long", format(b1, "%u", ZIP_CFILE_OFFSET(cf)), "lfile hdr offset"); + ShowExternalAttributes(cf); + if (ZIP_CFILE_OFFSET(cf) == 0xFFFFFFFF) { + show(".long", "0xFFFFFFFF", "lfile hdr offset (zip64)"); + } else { + show(".long", format(b1, "%u", ZIP_CFILE_OFFSET(cf)), "lfile hdr offset"); + } printf("0:"); show(".ascii", format(b1, "%`'s", gc(strndup(ZIP_CFILE_NAME(cf), ZIP_CFILE_NAMESIZE(cf)))), "name"); printf("1:"); - showextras(ZIP_CFILE_EXTRA(cf), ZIP_CFILE_EXTRASIZE(cf), false); + ShowExtras(ZIP_CFILE_EXTRA(cf), ZIP_CFILE_EXTRASIZE(cf), false); printf("2:"); - disassemblehex(ZIP_CFILE_COMMENT(cf), ZIP_CFILE_COMMENTSIZE(cf), stdout); + show(".ascii", + format(b1, "%`'.*s", ZIP_CFILE_COMMENTSIZE(cf), ZIP_CFILE_COMMENT(cf)), + "comment"); printf("3:\n"); } -void showcentraldirheader(uint8_t *cd) { +void ShowCentralDirHeader32(uint8_t *cd) { printf("\n/\t%s (%zu %s)\n", "end of central directory header", ZIP_CDIR_HDRSIZE(cd), "bytes"); show(".ascii", format(b1, "%`'.*s", 4, cd), "magic"); @@ -312,39 +373,116 @@ void showcentraldirheader(uint8_t *cd) { printf("1:\n"); } -void disassemblezip(uint8_t *map, size_t mapsize) { +void ShowCentralDirHeader64(uint8_t *cd) { + printf("\n/\t%s (%zu %s)\n", "zip64 end of central directory header", + ZIP_CDIR64_HDRSIZE(cd), "bytes"); + show(".ascii", format(b1, "%`'.*s", 4, cd), "magic"); + show(".quad", format(b1, "%lu", ZIP_CDIR64_HDRSIZE(cd) - 12), "hdr size"); + show(".short", format(b1, "%hd", ZIP_CDIR64_VERSIONMADE(cd)), "version made"); + show(".short", format(b1, "%hd", ZIP_CDIR64_VERSIONNEED(cd)), "version need"); + show(".long", format(b1, "%d", ZIP_CDIR64_DISK(cd)), "disk"); + show(".long", format(b1, "%d", ZIP_CDIR64_STARTINGDISK(cd)), "startingdisk"); + show(".quad", format(b1, "%lu", ZIP_CDIR64_RECORDSONDISK(cd)), + "recordsondisk"); + show(".quad", format(b1, "%lu", ZIP_CDIR64_RECORDS(cd)), "records"); + show(".quad", format(b1, "%lu", ZIP_CDIR64_SIZE(cd)), "cdir size"); + show(".quad", format(b1, "%lu", ZIP_CDIR64_OFFSET(cd)), "cdir offset"); + printf("0:"); + disassemblehex(ZIP_CDIR64_COMMENT(cd), ZIP_CDIR64_COMMENTSIZE(cd), stdout); + printf("1:\n"); +} + +uint8_t *GetZipCdir32(const uint8_t *p, size_t n) { + size_t i; + if (n >= kZipCdirHdrMinSize) { + i = n - kZipCdirHdrMinSize; + do { + if (READ32LE(p + i) == kZipCdirHdrMagic && IsZipCdir32(p, n, i)) { + return (/*unconst*/ uint8_t *)(p + i); + } + } while (i--); + } + return NULL; +} + +uint8_t *GetZipCdir64(const uint8_t *p, size_t n) { + size_t i; + if (n >= kZipCdir64HdrMinSize) { + i = n - kZipCdir64HdrMinSize; + do { + if (READ32LE(p + i) == kZipCdir64HdrMagic && IsZipCdir64(p, n, i)) { + return (/*unconst*/ uint8_t *)(p + i); + } + } while (i--); + } + return NULL; +} + +void DisassembleZip(const char *path, uint8_t *p, size_t n) { size_t pos; uint16_t i; static int records; - uint8_t *cd, *cf, *lf; - CHECK_NOTNULL((cd = zipfindcentraldir(map, mapsize))); + uint8_t *eocd32, *eocd64, *cdir, *cf, *lf, *q; + if (endswith(path, ".com.dbg") && (q = memmem(p, n, "MZqFpD", 6))) { + n -= q - p; + p += q - p; + } + eocd32 = GetZipCdir32(p, n); + eocd64 = GetZipCdir64(p, n); + CHECK(eocd32 || eocd64); pos = 0; - records = ZIP_CDIR_RECORDS(cd); - for (i = 0, cf = map + ZIP_CDIR_OFFSET(cd); i < records; - ++i, cf += ZIP_CFILE_HDRSIZE(cf)) { - lf = map + ZIP_CFILE_OFFSET(cf); + if (eocd64) { + records = ZIP_CDIR64_RECORDS(eocd64); + cdir = p + ZIP_CDIR64_OFFSET(eocd64); + } else { + records = ZIP_CDIR_RECORDS(eocd32); + cdir = p + ZIP_CDIR_OFFSET(eocd32); + } + for (i = 0, cf = cdir; i < records; ++i, cf += ZIP_CFILE_HDRSIZE(cf)) { + lf = p + GetZipCfileOffset(cf); CHECK_EQ(kZipLfileHdrMagic, ZIP_LFILE_MAGIC(lf)); - advancepos(map, &pos, lf - map); - showlocalfileheader(lf, i); - pos = (lf - map) + ZIP_LFILE_SIZE(lf); + AdvancePosition(p, &pos, lf - p); + ShowLocalFileHeader(lf, i); + pos = (lf - p) + ZIP_LFILE_SIZE(lf); } - for (i = 0, cf = map + ZIP_CDIR_OFFSET(cd); i < records; - ++i, cf += ZIP_CFILE_HDRSIZE(cf)) { + for (i = 0, cf = cdir; i < records; ++i, cf += ZIP_CFILE_HDRSIZE(cf)) { CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(cf)); - advancepos(map, &pos, cf - map); - showcentralfileheader(cf); - pos = (cf - map) + ZIP_CFILE_HDRSIZE(cf); + AdvancePosition(p, &pos, cf - p); + ShowCentralFileHeader(cf); + pos = (cf - p) + ZIP_CFILE_HDRSIZE(cf); } - advancepos(map, &pos, cd - map); - showcentraldirheader(cd); - pos = (cd - map) + ZIP_CDIR_HDRSIZE(cd); - advancepos(map, &pos, mapsize); + if (eocd32 && eocd64) { + if (eocd32 < eocd64) { + ShowCentralDirHeader32(eocd32); + AdvancePosition(p, &pos, eocd32 - p); + ShowCentralDirHeader64(eocd64); + AdvancePosition(p, &pos, eocd64 - p); + } else { + ShowCentralDirHeader64(eocd64); + AdvancePosition(p, &pos, eocd64 - p); + ShowCentralDirHeader32(eocd32); + AdvancePosition(p, &pos, eocd32 - p); + } + } else if (eocd32) { + ShowCentralDirHeader32(eocd32); + AdvancePosition(p, &pos, eocd32 - p); + } else { + ShowCentralDirHeader64(eocd64); + AdvancePosition(p, &pos, eocd64 - p); + } + if (!eocd64 || eocd32 > eocd64) { + pos = eocd32 - p + ZIP_CDIR_HDRSIZE(eocd32); + } else { + pos = eocd64 - p + ZIP_CDIR_HDRSIZE(eocd64); + } + AdvancePosition(p, &pos, n); } int main(int argc, char *argv[]) { int fd; uint8_t *map; struct stat st; + showcrashreports(); CHECK_EQ(2, argc); CHECK_NE(-1, (fd = open(argv[1], O_RDONLY))); CHECK_NE(-1, fstat(fd, &st)); @@ -353,7 +491,7 @@ int main(int argc, char *argv[]) { (map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0))); showtitle("αcτµαlly pδrταblε εxεcµταblε", "tool/decode/zip", basename(argv[1]), NULL, &kModelineAsm); - disassemblezip(map, st.st_size); + DisassembleZip(argv[1], map, st.st_size); CHECK_NE(-1, munmap(map, st.st_size)); CHECK_NE(-1, close(fd)); return 0; diff --git a/tool/net/.init.lua b/tool/net/.init.lua index 080402535..778f344ec 100644 --- a/tool/net/.init.lua +++ b/tool/net/.init.lua @@ -1,3 +1,2 @@ -- special script called by main redbean process at startup -ProgramRedirect(0, '/favicon.ico', '/tool/net/redbean.ico') HidePath('/usr/share/zoneinfo/') diff --git a/tool/net/redbean.ico b/tool/net/favicon.ico similarity index 100% rename from tool/net/redbean.ico rename to tool/net/favicon.ico diff --git a/tool/net/redbean.html b/tool/net/index.html similarity index 86% rename from tool/net/redbean.html rename to tool/net/index.html index c7f6fe5b8..8cca37ed7 100644 --- a/tool/net/redbean.html +++ b/tool/net/index.html @@ -1,8 +1,8 @@ redbean - - + +

redbean
diff --git a/tool/net/net.mk b/tool/net/net.mk index 8bd0dd324..a7385f5b7 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -63,20 +63,35 @@ o/$(MODE)/tool/net/%.com.dbg: \ o/$(MODE)/tool/net/redbean.com.dbg: \ $(TOOL_NET_DEPS) \ o/$(MODE)/tool/net/redbean.o \ - o/$(MODE)/tool/net/redbean.ico.zip.o \ - o/$(MODE)/tool/net/redbean.png.zip.o \ - o/$(MODE)/tool/net/redbean.css.zip.o \ - o/$(MODE)/tool/net/redbean.html.zip.o \ - o/$(MODE)/tool/net/redbean.lua.zip.o \ - o/$(MODE)/tool/net/redbean-form.lua.zip.o \ - o/$(MODE)/tool/net/redbean-xhr.lua.zip.o \ - o/$(MODE)/tool/net/.init.lua.zip.o \ - o/$(MODE)/tool/net/.reload.lua.zip.o \ o/$(MODE)/tool/net/net.pkg \ $(CRT) \ $(APE) @$(APELINK) +o/$(MODE)/tool/net/redbean.com: \ + o/$(MODE)/tool/net/redbean.com.dbg \ + tool/net/favicon.ico \ + tool/net/redbean.png \ + tool/net/.init.lua \ + tool/net/.reload.lua + @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@ + @$(COMPILE) -ADD -T$@ dd if=$@ of=o/$(MODE)/tool/net/.ape bs=64 count=11 conv=notrunc 2>/dev/null + @$(COMPILE) -AZIP -T$@ zip -qj $@ o/$(MODE)/tool/net/.ape tool/net/.init.lua tool/net/.reload.lua tool/net/favicon.ico tool/net/redbean.png + +o/$(MODE)/tool/net/redbean-demo.com: \ + o/$(MODE)/tool/net/redbean.com \ + tool/net/redbean.mk \ + tool/net/index.html \ + tool/net/redbean.css \ + tool/net/redbean.lua \ + tool/net/redbean-form.lua \ + tool/net/redbean-xhr.lua \ + $(TOOL_NET_HDRS) \ + $(TOOL_NET_SRCS) + @$(COMPILE) -ACP -T$@ cp $< $@ + @$(COMPILE) -AZIP -T$@ zip -qj $@ tool/net/redbean.lua tool/net/redbean-form.lua tool/net/redbean-xhr.lua + @$(COMPILE) -AZIP -T$@ zip -q $@ tool/net tool/net/index.html tool/net/redbean.css $(TOOL_NET_HDRS) $(TOOL_NET_SRCS) + .PHONY: o/$(MODE)/tool/net o/$(MODE)/tool/net: \ $(TOOL_NET_BINS) \ diff --git a/tool/net/redbean-form.lua b/tool/net/redbean-form.lua index 5b8f03855..257df6b1c 100644 --- a/tool/net/redbean-form.lua +++ b/tool/net/redbean-form.lua @@ -63,7 +63,7 @@ local function main() Write('\n') Write('

') - Write('Click here ') + Write('Click here ') Write('to return to the previous page.\n') end diff --git a/tool/net/redbean-xhr.lua b/tool/net/redbean-xhr.lua index cd93d5d4e..a2daf44d1 100644 --- a/tool/net/redbean-xhr.lua +++ b/tool/net/redbean-xhr.lua @@ -1,3 +1,8 @@ -- redbean xhr handler demo -SetHeader('Vary', 'X-Custom-Header') -SetHeader('X-Custom-Header', 'hello ' .. GetHeader('x-custom-header')) +hdr = GetHeader('x-custom-header') +if hdr then + SetHeader('Vary', 'X-Custom-Header') + SetHeader('X-Custom-Header', 'hello ' .. hdr) +else + ServeError(400) +end diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 8d91e634c..9fefc6111 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -23,6 +23,7 @@ #include "libc/calls/calls.h" #include "libc/calls/struct/iovec.h" #include "libc/calls/struct/itimerval.h" +#include "libc/calls/struct/rusage.h" #include "libc/calls/struct/stat.h" #include "libc/calls/weirdtypes.h" #include "libc/dce.h" @@ -39,7 +40,9 @@ #include "libc/nexgen32e/bsf.h" #include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/crc32.h" +#include "libc/nt/synchronization.h" #include "libc/rand/rand.h" +#include "libc/runtime/clktck.h" #include "libc/runtime/runtime.h" #include "libc/sock/sock.h" #include "libc/stdio/stdio.h" @@ -58,8 +61,11 @@ #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/itimer.h" #include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/mlock.h" +#include "libc/sysv/consts/msync.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/prot.h" +#include "libc/sysv/consts/s.h" #include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/shut.h" #include "libc/sysv/consts/sig.h" @@ -77,6 +83,7 @@ #include "net/http/base64.h" #include "net/http/escape.h" #include "net/http/http.h" +#include "net/http/url.h" #include "third_party/getopt/getopt.h" #include "third_party/lua/lauxlib.h" #include "third_party/lua/ltests.h" @@ -151,12 +158,19 @@ USAGE\n\ redbean imposes a 32kb limit on requests to limit the memory of\n\ connection processes, which grow to whatever number your system\n\ limits and tcp stack configuration allow. If fork() should fail\n\ - then redbean starts shutting idle connections down.\n\ + or accept runs out of file descriptors, then redbean will react\n\ + by closing idle connections, while sending out 503 responses in\n\ + the meantime from the main process. That way if you have a load\n\ + balancer with multiple instances, failover will happen quickly.\n\ \n" #define HASH_LOAD_FACTOR /* 1. / */ 4 #define DEFAULT_PORT 8080 +#define HeaderEqual(H, S) \ + SlicesEqual(S, strlen(S), inbuf.p + msg.headers[H].a, \ + msg.headers[H].b - msg.headers[H].a) + static const struct itimerval kHeartbeat = { {0, 500000}, {0, 500000}, @@ -175,25 +189,6 @@ static const uint8_t kGzipHeader[] = { kZipOsUnix, // OS }; -static const char kHexToInt[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // 0x30 - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50 - 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xc0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xd0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0 -}; - static const struct ContentTypeExtension { unsigned char ext[8]; const char *mime; @@ -245,33 +240,8 @@ struct Strings { char **p; }; -struct Parser { - int i; - int c; - const char *data; - int size; - bool isform; - bool islatin1; - char *p; - char *q; -}; - -struct Params { - size_t n; - struct Param { - struct Buffer key; - struct Buffer val; // val.n may be SIZE_MAX - } * p; -}; - -struct Request { - struct Buffer path; - struct Params params; - struct Buffer fragment; -}; - static struct Freelist { - size_t n; + size_t n, c; void **p; } freelist; @@ -288,8 +258,10 @@ static struct Redirects { static struct Assets { uint32_t n; struct Asset { - uint32_t lf; + bool istext; uint32_t hash; + uint64_t cf; + uint64_t lf; int64_t lastmodified; char *lastmodifiedstr; struct File { @@ -300,7 +272,8 @@ static struct Assets { } assets; static struct Shared { - int workers; // + int workers; + long requestshandled; } * shared; static bool killed; @@ -309,7 +282,6 @@ static bool zombied; static bool gzipped; static bool branded; static bool meltdown; -static bool unbranded; static bool heartless; static bool printport; static bool heartbeat; @@ -331,13 +303,14 @@ static int client; static int daemonuid; static int daemongid; static int statuscode; -static unsigned httpversion; +static int httpversion; +static int requestshandled; static uint32_t clientaddrsize; static lua_State *L; static size_t zsize; static void *content; -static uint8_t *zdir; +static uint8_t *cdir; static uint8_t *zmap; static size_t hdrsize; static size_t msgsize; @@ -355,14 +328,14 @@ static const char *serverheader; static struct Strings stagedirs; static struct Strings hidepaths; -static struct Buffer logo; +static struct Url request; static struct Buffer inbuf; static struct Buffer hdrbuf; static struct Buffer outbuf; -static struct Request request; static long double nowish; static long double startread; +static long double startserver; static long double lastmeltdown; static long double startrequest; static long double startconnection; @@ -427,6 +400,14 @@ static int CompareSlicesCase(const char *a, size_t n, const char *b, size_t m) { return 0; } +static bool SlicesEqual(const char *a, size_t n, const char *b, size_t m) { + return n == m && !CompareSlices(a, n, b, m); +} + +static bool SlicesEqualCase(const char *a, size_t n, const char *b, size_t m) { + return n == m && !CompareSlicesCase(a, n, b, m); +} + static long FindRedirect(const char *path, size_t n) { int c, m, l, r, z; l = 0; @@ -489,7 +470,7 @@ static int CompareInts(const uint64_t x, uint64_t y) { return x > y ? 1 : x < y ? -1 : 0; } -static const char *FindContentType(uint64_t ext) { +static const char *BisectContentType(uint64_t ext) { int c, m, l, r; l = 0; r = ARRAYLEN(kContentTypeExtension) - 1; @@ -507,7 +488,7 @@ static const char *FindContentType(uint64_t ext) { return NULL; } -static const char *GetContentType2(const char *path, size_t n) { +static const char *FindContentType(const char *path, size_t n) { size_t i; uint64_t x; const char *p, *r; @@ -516,7 +497,7 @@ static const char *GetContentType2(const char *path, size_t n) { x <<= 8; x |= path[i] & 0xFF; } - if ((r = FindContentType(bswap_64(x)))) { + if ((r = BisectContentType(bswap_64(x)))) { return r; } } @@ -525,14 +506,14 @@ static const char *GetContentType2(const char *path, size_t n) { static const char *GetContentType(struct Asset *a, const char *path, size_t n) { const char *r; - if (a->file && (r = GetContentType2(a->file->path, strlen(a->file->path)))) { + if (a->file && (r = FindContentType(a->file->path, strlen(a->file->path)))) { return r; } return firstnonnull( - GetContentType2(path, n), - firstnonnull(GetContentType2(ZIP_LFILE_NAME(zmap + a->lf), + FindContentType(path, n), + firstnonnull(FindContentType(ZIP_LFILE_NAME(zmap + a->lf), ZIP_LFILE_NAMESIZE(zmap + a->lf)), - "application/octet-stream")); + a->istext ? "text/plain" : "application/octet-stream")); } static void DescribeAddress(char buf[32], const struct sockaddr_in *addr) { @@ -550,7 +531,6 @@ static void ProgramBrand(const char *s) { free(brand); free(serverheader); brand = strdup(s); - if (!strstr(s, "redbean")) unbranded = true; if (!(serverheader = EncodeHttpHeaderValue(brand, -1, 0))) { fprintf(stderr, "error: brand isn't latin1 encodable: %`'s", brand); exit(1); @@ -566,7 +546,7 @@ static void ProgramPort(long x) { } static void SetDefaults(void) { - ProgramBrand("redbean/0.3"); + ProgramBrand("redbean/0.4"); ProgramCache(-1); ProgramPort(DEFAULT_PORT); serveraddr.sin_family = AF_INET; @@ -594,8 +574,8 @@ static void AddString(struct Strings *l, char *s) { static void AddStagingDirectory(const char *dirpath) { char *s; s = RemoveTrailingSlashes(strdup(dirpath)); - if (!isdirectory(s)) { - fprintf(stderr, "error: not a directory: %s\n", s); + if (!*s || !isdirectory(s)) { + fprintf(stderr, "error: not a directory: %`'s\n", s); exit(1); } AddString(&stagedirs, s); @@ -691,27 +671,85 @@ static void Daemonize(void) { LOGIFNEG1(setgid(daemongid)); } -static void OnWorkerExit(int pid, int ws) { - int w; - w = --shared->workers; +static void ReportWorkerExit(int pid, int ws) { + --shared->workers; if (WIFEXITED(ws)) { if (WEXITSTATUS(ws)) { - WARNF("worker %d exited with %d (%,d workers remain)", pid, - WEXITSTATUS(ws), w); + WARNF("%d exited with %d (%,d workers remain)", pid, WEXITSTATUS(ws), + shared->workers); } else { - DEBUGF("worker %d exited (%,d workers remain)", pid, w); + DEBUGF("%d exited (%,d workers remain)", pid, shared->workers); } } else { - WARNF("worker %d terminated with %s (%,d workers remain)", pid, - strsignal(WTERMSIG(ws)), w); + WARNF("%d terminated with %s (%,d workers remain)", pid, + strsignal(WTERMSIG(ws)), shared->workers); + } +} + +static void ReportWorkerResources(int pid, struct rusage *ru) { + long utime, stime; + long double ticks; + /* + * NetBSD accounting literally uses calculus. + * OpenBSD and XNU are pretty good. + * Linux and FreeBSD track less. + */ + if (ru->ru_maxrss) { + DEBUGF("%d ballooned to %,ldkb of memory", pid, ru->ru_maxrss); + } + if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) | + (stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) { + ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK)); + DEBUGF("%d needed %,ldµs of cpu (%d%% kernel)", pid, utime + stime, + (int)((long double)utime / (utime + stime) * 100)); + if (ru->ru_idrss) { + DEBUGF("%d needed %,ldkb of memory on average", pid, + lroundl(ru->ru_idrss / ticks)); + } + if (ru->ru_isrss) { + DEBUGF("%d needed %,ldkb of stack memory on average", pid, + lroundl(ru->ru_isrss / ticks)); + } + if (ru->ru_ixrss) { + DEBUGF("%d mapped %,ldkb of shared memory on average", pid, + lroundl(ru->ru_ixrss / ticks)); + } + } + if (ru->ru_minflt || ru->ru_majflt) { + DEBUGF("%d caused %,ld page faults (%d%% memcpy)", pid, + ru->ru_minflt + ru->ru_majflt, + (int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) * + 100)); + } + if (ru->ru_nvcsw + ru->ru_nivcsw > 1) { + DEBUGF("%d triggered %,ld context switches (%d%% consensual)", pid, + ru->ru_nvcsw + ru->ru_nivcsw, + (int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) * + 100)); + } + if (ru->ru_inblock || ru->ru_oublock) { + DEBUGF("%d performed %,ld read and %,ld write i/o operations", pid, + ru->ru_inblock, ru->ru_oublock); + } + if (ru->ru_msgrcv || ru->ru_msgsnd) { + DEBUGF("%d received %,ld message and sent %,ld", pid, ru->ru_msgrcv, + ru->ru_msgsnd); + } + if (ru->ru_nsignals) { + DEBUGF("%d received %,ld signals", pid, ru->ru_nsignals); + } + if (ru->ru_nswap) { + DEBUGF("%d got swapped %,ld times", pid, ru->ru_nswap); } } static void WaitAll(void) { int ws, pid; + struct rusage ru; for (;;) { - if ((pid = wait(&ws)) != -1) { - OnWorkerExit(pid, ws); + if ((pid = wait4(-1, &ws, 0, &ru)) != -1) { + ReportWorkerExit(pid, ws); + ReportWorkerResources(pid, &ru); } else { if (errno == ECHILD) break; if (errno == EINTR) { @@ -730,11 +768,13 @@ static void WaitAll(void) { static void ReapZombies(void) { int ws, pid; - zombied = false; + struct rusage ru; do { - if ((pid = waitpid(-1, &ws, WNOHANG)) != -1) { + zombied = false; + if ((pid = wait4(-1, &ws, WNOHANG, &ru)) != -1) { if (pid) { - OnWorkerExit(pid, ws); + ReportWorkerExit(pid, ws); + ReportWorkerResources(pid, &ru); } else { break; } @@ -782,16 +822,7 @@ static uint32_t Hash(const void *data, size_t size) { } static bool HasHeader(int h) { - return msg.headers[h].b > msg.headers[h].a; -} - -static int CompareHeader(int h, const char *s) { - return CompareSlices(s, strlen(s), inbuf.p + msg.headers[h].a, - msg.headers[h].b - msg.headers[h].a); -} - -static bool HeaderEquals(int h, const char *s) { - return !CompareHeader(h, s); + return !!msg.headers[h].a; } static bool ClientAcceptsGzip(void) { @@ -822,20 +853,34 @@ static int64_t LocoTimeToZulu(int64_t x) { return x - gmtoff; } -static int64_t GetLastModifiedZip(const uint8_t *cfile) { +static int64_t GetZipCfileLastModified(const uint8_t *zcf) { const uint8_t *p, *pe; - for (p = ZIP_CFILE_EXTRA(cfile), pe = p + ZIP_CFILE_EXTRASIZE(cfile); p < pe; + for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe; p += ZIP_EXTRA_SIZE(p)) { - if (ZIP_EXTRA_HEADERID(p) == kZipExtraNtfs) { - return LocoTimeToZulu(READ64LE(ZIP_EXTRA_CONTENT(p) + 8) / - HECTONANOSECONDS - - MODERNITYSECONDS); - } else if (ZIP_EXTRA_HEADERID(p) == kZipExtraExtendedTimestamp) { - return READ32LE(ZIP_EXTRA_CONTENT(p) + 1); + if (ZIP_EXTRA_HEADERID(p) == kZipExtraNtfs && + ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 3 && + READ16LE(ZIP_EXTRA_CONTENT(p) + 4) == 1 && + READ16LE(ZIP_EXTRA_CONTENT(p) + 6) == 24) { + return READ64LE(ZIP_EXTRA_CONTENT(p) + 8) / HECTONANOSECONDS - + MODERNITYSECONDS; } } - return LocoTimeToZulu(DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(cfile), - ZIP_CFILE_LASTMODIFIEDTIME(cfile))); + for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraExtendedTimestamp && + ZIP_EXTRA_CONTENTSIZE(p) >= 1 + 4 && (*ZIP_EXTRA_CONTENT(p) & 1)) { + return (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1); + } + } + for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe; + p += ZIP_EXTRA_SIZE(p)) { + if (ZIP_EXTRA_HEADERID(p) == kZipExtraUnix && + ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4) { + return (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 4); + } + } + return LocoTimeToZulu(DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(zcf), + ZIP_CFILE_LASTMODIFIEDTIME(zcf))); } static bool IsCompressed(struct Asset *a) { @@ -861,21 +906,21 @@ static char *FormatUnixHttpDateTime(char *s, int64_t t) { static void *FreeLater(void *p) { if (p) { - freelist.p = xrealloc(freelist.p, ++freelist.n * sizeof(*freelist.p)); + if (++freelist.n > freelist.c) { + freelist.c = freelist.n + 2; + freelist.c += freelist.c >> 1; + freelist.p = xrealloc(freelist.p, freelist.c * sizeof(*freelist.p)); + } freelist.p[freelist.n - 1] = p; } return p; } static void CollectGarbage(void) { - size_t i; - for (i = 0; i < freelist.n; ++i) free(freelist.p[i]); - free(freelist.p); - freelist.p = 0; - freelist.n = 0; - free(outbuf.p); - free(request.params.p); DestroyHttpRequest(&msg); + while (freelist.n) { + free(freelist.p[--freelist.n]); + } } static bool IsCompressionMethodSupported(int method) { @@ -884,24 +929,27 @@ static bool IsCompressionMethodSupported(int method) { static void IndexAssets(void) { int64_t lm; + uint64_t cf, lf; struct Asset *p; - uint32_t i, n, m, cf, step, hash; + uint32_t i, n, m, step, hash; CHECK_GE(HASH_LOAD_FACTOR, 2); - n = ZIP_CDIR_RECORDS(zdir); + CHECK(READ32LE(cdir) == kZipCdir64HdrMagic || + READ32LE(cdir) == kZipCdirHdrMagic); + n = GetZipCdirRecords(cdir); m = roundup2pow(MAX(1, n) * HASH_LOAD_FACTOR); p = xcalloc(m, sizeof(struct Asset)); - CHECK_EQ(kZipCdirHdrMagic, ZIP_CDIR_MAGIC(zdir)); - for (cf = ZIP_CDIR_OFFSET(zdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { + for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); - if (!IsCompressionMethodSupported(ZIP_CFILE_COMPRESSIONMETHOD(zmap + cf))) { + lf = GetZipCfileOffset(zmap + cf); + if (!IsCompressionMethodSupported(ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf))) { WARNF("don't understand zip compression method %d used by %`'.*s", - ZIP_CFILE_COMPRESSIONMETHOD(zmap + cf), + ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf), ZIP_CFILE_NAMESIZE(zmap + cf), ZIP_CFILE_NAME(zmap + cf)); continue; } if (ZIP_CFILE_NAMESIZE(zmap + cf) > 1 && ZIP_CFILE_NAME(zmap + cf)[ZIP_CFILE_NAMESIZE(zmap + cf) - 1] == '/' && - !ZIP_CFILE_UNCOMPRESSEDSIZE(zmap + cf)) { + !GetZipLfileUncompressedSize(zmap + lf)) { continue; } hash = Hash(ZIP_CFILE_NAME(zmap + cf), ZIP_CFILE_NAMESIZE(zmap + cf)); @@ -910,9 +958,11 @@ static void IndexAssets(void) { i = (hash + (step * (step + 1)) >> 1) & (m - 1); ++step; } while (p[i].hash); - lm = GetLastModifiedZip(zmap + cf); + lm = GetZipCfileLastModified(zmap + cf); p[i].hash = hash; - p[i].lf = ZIP_CFILE_OFFSET(zmap + cf); + p[i].lf = lf; + p[i].cf = cf; + p[i].istext = !!(ZIP_CFILE_INTERNALATTRIBUTES(zmap + cf) & kZipIattrText); p[i].lastmodified = lm; p[i].lastmodifiedstr = FormatUnixHttpDateTime(xmalloc(30), lm); } @@ -929,7 +979,7 @@ static void OpenZip(const char *path) { CHECK((zsize = st.st_size)); CHECK_NE(MAP_FAILED, (zmap = mmap(NULL, zsize, PROT_READ, MAP_SHARED, fd, 0))); - CHECK_NOTNULL((zdir = zipfindcentraldir(zmap, zsize))); + CHECK_NOTNULL((cdir = GetZipCdir(zmap, zsize))); if (endswith(path, ".com.dbg") && (p = memmem(zmap, zsize, "MZqFpD", 6))) { zsize -= p - zmap; zmap = p; @@ -937,7 +987,7 @@ static void OpenZip(const char *path) { close(fd); } -static struct Asset *FindAsset(const char *path, size_t pathlen) { +static struct Asset *GetAsset(const char *path, size_t pathlen) { uint32_t i, step, hash; hash = Hash(path, pathlen); for (step = 0;; ++step) { @@ -954,14 +1004,14 @@ static struct Asset *FindAsset(const char *path, size_t pathlen) { static struct Asset *LocateAssetZip(const char *path, size_t pathlen) { char *p2, *p3, *p4; struct Asset *a; - if (pathlen && path[0] == '/') ++path, --pathlen; - if (!(a = FindAsset(path, pathlen)) && + if (pathlen > 1 && path[0] == '/') ++path, --pathlen; + if (!(a = GetAsset(path, pathlen)) && (!pathlen || (pathlen && path[pathlen - 1] == '/'))) { - p2 = strndup(path, pathlen); + p2 = xstrndup(path, pathlen); p3 = xjoinpaths(p2, "index.lua"); - if (!(a = FindAsset(p3, strlen(p3)))) { + if (!(a = GetAsset(p3, strlen(p3)))) { p4 = xjoinpaths(p2, "index.html"); - a = FindAsset(p4, strlen(p4)); + a = GetAsset(p4, strlen(p4)); free(p4); } free(p3); @@ -1007,144 +1057,6 @@ static struct Asset *LocateAsset(const char *path, size_t pathlen) { return a; } -static void EmitParamKey(struct Parser *u, struct Params *h) { - h->p = xrealloc(h->p, ++h->n * sizeof(*h->p)); - h->p[h->n - 1].key.p = u->q; - h->p[h->n - 1].key.n = u->p - u->q; - u->q = u->p; -} - -static void EmitParamVal(struct Parser *u, struct Params *h, bool t) { - if (!t) { - if (u->p > u->q) { - EmitParamKey(u, h); - h->p[h->n - 1].val.p = NULL; - h->p[h->n - 1].val.n = SIZE_MAX; - } - } else { - h->p[h->n - 1].val.p = u->q; - h->p[h->n - 1].val.n = u->p - u->q; - u->q = u->p; - } -} - -static void ParseLatin1(struct Parser *u) { - *u->p++ = 0300 | u->c >> 6; - *u->p++ = 0200 | u->c & 077; -} - -static void ParseEscape(struct Parser *u) { - int a, b; - a = u->i < u->size ? u->data[u->i++] & 0xff : 0; - b = u->i < u->size ? u->data[u->i++] & 0xff : 0; - *u->p++ = kHexToInt[a] << 4 | kHexToInt[b]; -} - -static void ParsePath(struct Parser *u, struct Buffer *h) { - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; - if (u->c == '#' || u->c == '?') { - break; - } else if (u->c == '%') { - ParseEscape(u); - } else if (u->c >= 0200 && u->islatin1) { - ParseLatin1(u); - } else { - *u->p++ = u->c; - } - } - h->p = u->q; - h->n = u->p - u->q; - u->q = u->p; -} - -static void ParseParams(struct Parser *u, struct Params *h) { - bool t = false; - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; - if (u->c == '#') { - break; - } else if (u->c == '%') { - ParseEscape(u); - } else if (u->c == '+') { - *u->p++ = u->isform ? ' ' : '+'; - } else if (u->c == '&') { - EmitParamVal(u, h, t); - t = false; - } else if (u->c == '=') { - if (!t) { - if (u->p > u->q) { - EmitParamKey(u, h); - t = true; - } - } else { - *u->p++ = '='; - } - } else if (u->c >= 0200 && u->islatin1) { - ParseLatin1(u); - } else { - *u->p++ = u->c; - } - } - EmitParamVal(u, h, t); -} - -static void ParseFragment(struct Parser *u, struct Buffer *h) { - while (u->i < u->size) { - u->c = u->data[u->i++] & 0xff; - if (u->c == '%') { - ParseEscape(u); - } else if (u->c >= 0200 && u->islatin1) { - ParseLatin1(u); - } else { - *u->p++ = u->c; - } - } - h->p = u->q; - h->n = u->p - u->q; - u->q = u->p; -} - -static void ParseRequestUri(void) { - struct Parser u; - u.i = 0; - u.c = 0; - u.isform = false; - u.islatin1 = true; - u.data = inbuf.p + msg.uri.a; - u.size = msg.uri.b - msg.uri.a; - memset(&request, 0, sizeof(request)); - if (u.size > 8 && !memcmp(u.data, "http", 4)) { - /* - * convert http://www.foo.com/index.html -> /www.foo.com/index.html - */ - if (u.data[4] == ':' && u.data[5] == '/' && u.data[6] == '/') { - u.data += 6; - u.size -= 6; - } else if (u.data[4] == 's' && u.data[5] == ':' && u.data[6] == '/' && - u.data[7] == '/') { - u.data += 7; - u.size -= 7; - } - } - u.q = u.p = FreeLater(xmalloc(u.size * 2)); - ParsePath(&u, &request.path); - if (u.c == '?') ParseParams(&u, &request.params); - if (u.c == '#') ParseFragment(&u, &request.fragment); -} - -static void ParseFormParams(void) { - struct Parser u; - u.i = 0; - u.c = 0; - u.isform = true; - u.islatin1 = false; - u.data = inbuf.p + hdrsize; - u.size = msgsize - hdrsize; - u.q = u.p = FreeLater(xmalloc(u.size)); - ParseParams(&u, &request.params); -} - static void *AddRange(char *content, long start, long length) { intptr_t mend, mstart; if (!__builtin_add_overflow((intptr_t)content, start, &mstart) || @@ -1168,17 +1080,14 @@ static bool MustNotIncludeMessageBody(void) { /* RFC2616 § 4.4 */ statuscode == 204 || statuscode == 304; } -static char *SetStatus(int code, const char *reason) { - char *p; +char *SetStatus(unsigned code, const char *reason) { statuscode = code; - p = hdrbuf.p; - p = stpcpy(p, "HTTP/1."); - *p++ = httpversion == 100 ? '0' : '1'; - *p++ = ' '; - p += uint64toarray_radix10(code, p); - *p++ = ' '; - p = stpcpy(p, reason); - return AppendCrlf(p); + stpcpy(hdrbuf.p, "HTTP/1.1 000 "); + if (httpversion == 100) hdrbuf.p[7] = '0'; + hdrbuf.p[9] += code / 100; + hdrbuf.p[10] += code / 10 % 10; + hdrbuf.p[11] += code % 10; + return AppendCrlf(stpcpy(hdrbuf.p + 13, reason)); } static char *AppendHeader(char *p, const char *k, const char *v) { @@ -1189,14 +1098,16 @@ static char *AppendHeader(char *p, const char *k, const char *v) { static char *AppendContentType(char *p, const char *ct) { p = stpcpy(p, "Content-Type: "); p = stpcpy(p, ct); - if (startswith(ct, "text/") && !strchr(ct, ';')) { - p = stpcpy(p, "; charset=utf-8"); + if (startswith(ct, "text/")) { istext = true; + if (!strchr(ct, ';')) { + p = stpcpy(p, "; charset=utf-8"); + } } return AppendCrlf(p); } -static char *ServeError(int code, const char *reason) { +static char *ServeError(unsigned code, const char *reason) { char *p; size_t reasonlen; reasonlen = strlen(reason); @@ -1204,7 +1115,7 @@ static char *ServeError(int code, const char *reason) { p = AppendContentType(p, "text/plain"); content = FreeLater(xmalloc(reasonlen + 3)); contentlength = reasonlen + 2; - stpcpy(stpcpy(content, reason), "\r\n"); + AppendCrlf(stpcpy(content, reason)); WARNF("%s %s %`'.*s %d %s", clientaddrstr, kHttpMethod[msg.method], msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a, code, reason); return p; @@ -1219,12 +1130,14 @@ static char *AppendExpires(char *p, int64_t t) { } static char *AppendCache(char *p, int64_t seconds) { - struct tm tm; if (seconds < 0) return p; - p = stpcpy(p, "Cache-Control: "); - p = stpcpy(p, "max-age="); + p = stpcpy(p, "Cache-Control: max-age="); p += uint64toarray_radix10(seconds, p); - if (seconds) p = stpcpy(p, ", public"); + if (seconds) { + p = stpcpy(p, ", public"); + } else { + p = stpcpy(p, ", no-store"); + } p = AppendCrlf(p); return AppendExpires(p, (int64_t)nowish + seconds); } @@ -1251,10 +1164,8 @@ static char *AppendContentRange(char *p, long rangestart, long rangelength, return AppendCrlf(p); } -static bool Inflate(uint8_t *dp, size_t dn, const uint8_t *sp, size_t sn) { - bool ok; +static bool Inflate(void *dp, size_t dn, const void *sp, size_t sn) { z_stream zs; - ok = false; zs.next_in = sp; zs.avail_in = sn; zs.total_in = sn; @@ -1263,26 +1174,35 @@ static bool Inflate(uint8_t *dp, size_t dn, const uint8_t *sp, size_t sn) { zs.total_out = dn; zs.zfree = Z_NULL; zs.zalloc = Z_NULL; - if (inflateInit2(&zs, -MAX_WBITS) == Z_OK) { - switch (inflate(&zs, Z_NO_FLUSH)) { - case Z_STREAM_END: - ok = true; - break; - case Z_MEM_ERROR: - WARNF("Z_MEM_ERROR"); - break; - case Z_DATA_ERROR: - WARNF("Z_DATA_ERROR"); - break; - case Z_NEED_DICT: - WARNF("Z_NEED_DICT"); - break; - default: - abort(); - } - inflateEnd(&zs); + CHECK_EQ(Z_OK, inflateInit2(&zs, -MAX_WBITS)); + switch (inflate(&zs, Z_NO_FLUSH)) { + case Z_STREAM_END: + CHECK_EQ(Z_OK, inflateEnd(&zs)); + return true; + case Z_DATA_ERROR: + inflateEnd(&zs); + WARNF("Z_DATA_ERROR"); + return false; + case Z_NEED_DICT: + inflateEnd(&zs); + WARNF("Z_NEED_DICT"); + return false; + case Z_MEM_ERROR: + FATALF("Z_MEM_ERROR"); + default: + abort(); + } +} + +static bool Verify(void *data, size_t size, uint32_t crc) { + uint32_t got; + if (crc == (got = crc32_z(0, data, size))) { + return true; + } else { + WARNF("corrupt zip file at %`'.*s had crc 0x%08x but expected 0x%08x", + msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a, got, crc); + return false; } - return ok; } static void *Deflate(const void *data, size_t size, size_t *out_size) { @@ -1303,12 +1223,12 @@ static void *Deflate(const void *data, size_t size, size_t *out_size) { static void *LoadAsset(struct Asset *a, size_t *out_size) { size_t size; uint8_t *data; - if (a->file) return FreeLater(xslurp(a->file->path, out_size)); - size = ZIP_LFILE_UNCOMPRESSEDSIZE(zmap + a->lf); + if (a->file) return xslurp(a->file->path, out_size); + size = GetZipLfileUncompressedSize(zmap + a->lf); data = xmalloc(size + 1); if (ZIP_LFILE_COMPRESSIONMETHOD(zmap + a->lf) == kZipCompressionDeflate) { - CHECK(Inflate(data, size, ZIP_LFILE_CONTENT(zmap + a->lf), - ZIP_LFILE_COMPRESSEDSIZE(zmap + a->lf))); + Inflate(data, size, ZIP_LFILE_CONTENT(zmap + a->lf), + GetZipLfileCompressedSize(zmap + a->lf)); } else { memcpy(data, ZIP_LFILE_CONTENT(zmap + a->lf), size); } @@ -1331,36 +1251,48 @@ static ssize_t Send(struct iovec *iov, int iovlen) { } static char *ServeAsset(struct Asset *a, const char *path, size_t pathlen) { - char *p; + size_t size; + uint32_t crc; + char *p, *buf; long rangestart, rangelength; if (IsNotModified(a)) { DEBUGF("%s %s %`'.*s not modified", clientaddrstr, kHttpMethod[msg.method], pathlen, path); p = SetStatus(304, "Not Modified"); } else { - if (!a->file) { + if (a->file) { + if (a->file->st.st_mode & 0004) { + content = FreeLater(xslurp(a->file->path, &contentlength)); + } else { + WARNF("local file lacks st_mode read bit for other users %`'.*s", + msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a); + return ServeError(403, "Forbidden"); + } + } else if (GetZipCfileMode(zmap + a->cf) & 0004) { content = ZIP_LFILE_CONTENT(zmap + a->lf); - contentlength = ZIP_LFILE_COMPRESSEDSIZE(zmap + a->lf); + contentlength = GetZipLfileCompressedSize(zmap + a->lf); } else { - /* TODO(jart): Use sendfile(). */ - content = FreeLater(xslurp(a->file->path, &contentlength)); + WARNF("zip file lacks st_mode read bit for other users %`'.*s", + msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a); + return ServeError(403, "Forbidden"); } - if (IsCompressed(a)) { + if (!a->file && IsCompressed(a)) { + crc = ZIP_LFILE_CRC32(zmap + a->lf); + size = GetZipLfileUncompressedSize(zmap + a->lf); if (ClientAcceptsGzip()) { gzipped = true; - memcpy(gzip_footer + 0, zmap + a->lf + kZipLfileOffsetCrc32, 4); - memcpy(gzip_footer + 4, zmap + a->lf + kZipLfileOffsetUncompressedsize, - 4); + WRITE32LE(gzip_footer + 0, crc); + WRITE32LE(gzip_footer + 4, size); p = SetStatus(200, "OK"); - p = AppendHeader(p, "Content-Encoding", "gzip"); + p = stpcpy(p, "Content-Encoding: gzip\r\n"); + } else if ((buf = FreeLater(malloc(size))) && + Inflate(buf, size, content, contentlength) && + Verify(buf, size, crc)) { + p = SetStatus(200, "OK"); + content = buf; + contentlength = size; } else { - CHECK(Inflate( - (content = - FreeLater(xmalloc(ZIP_LFILE_UNCOMPRESSEDSIZE(zmap + a->lf)))), - (contentlength = ZIP_LFILE_UNCOMPRESSEDSIZE(zmap + a->lf)), - ZIP_LFILE_CONTENT(zmap + a->lf), - ZIP_LFILE_COMPRESSEDSIZE(zmap + a->lf))); - p = SetStatus(200, "OK"); + return ServeError(500, "Internal Server Error"); } } else if (httpversion >= 101 && HasHeader(kHttpRange)) { if (ParseHttpRange(inbuf.p + msg.headers[kHttpRange].a, @@ -1381,20 +1313,32 @@ static char *ServeAsset(struct Asset *a, const char *path, size_t pathlen) { content = ""; contentlength = 0; } + } else if (a->file && ClientAcceptsGzip()) { + gzipped = true; + p = SetStatus(200, "OK"); + p = stpcpy(p, "Content-Encoding: gzip\r\n"); + crc = crc32_z(0, content, contentlength); + WRITE32LE(gzip_footer + 0, crc); + WRITE32LE(gzip_footer + 4, contentlength); + content = FreeLater(Deflate(content, contentlength, &contentlength)); + } else if (!a->file && ZIP_LFILE_COMPRESSIONMETHOD(zmap + a->lf) == + kZipCompressionNone) { + if (Verify(content, contentlength, ZIP_LFILE_CRC32(zmap + a->lf))) { + p = SetStatus(200, "OK"); + } else { + return ServeError(500, "Internal Server Error"); + } } else { p = SetStatus(200, "OK"); } } - if (httpversion >= 100) { - p = AppendHeader(p, "Last-Modified", a->lastmodifiedstr); - p = AppendContentType(p, GetContentType(a, path, pathlen)); - if (httpversion >= 101) { - p = AppendCache(p, cacheseconds); - if (!IsCompressed(a)) { - p = AppendHeader(p, "Accept-Ranges", "bytes"); - } else { - p = AppendHeader(p, "Vary", "Accept-Encoding"); - } + p = stpcpy(p, "Vary: Accept-Encoding\r\n"); + p = AppendHeader(p, "Last-Modified", a->lastmodifiedstr); + p = AppendContentType(p, GetContentType(a, path, pathlen)); + if (httpversion >= 101) { + p = AppendCache(p, cacheseconds); + if (a->file || !IsCompressed(a)) { + p = stpcpy(p, "Accept-Ranges: bytes\r\n"); } } return p; @@ -1411,38 +1355,43 @@ static void AppendString(const char *s) { } static void AppendFmt(const char *fmt, ...) { - int size; - char *data; + int n; + char *p; va_list va; - data = NULL; va_start(va, fmt); - CHECK_NE(-1, (size = vasprintf(&data, fmt, va))); + n = vasprintf(&p, fmt, va); va_end(va); - AppendData(data, size); - free(data); + CHECK_NE(-1, n); + AppendData(p, n); + free(p); } static char *CommitOutput(char *p) { + uint32_t crc; + p = stpcpy(p, "Vary: Accept-Encoding\r\n"); if (istext && outbuf.n >= 100 && ClientAcceptsGzip()) { gzipped = true; - p = AppendHeader(p, "Content-Encoding", "gzip"); - p = AppendHeader(p, "Vary", "Accept-Encoding"); - WRITE32LE(gzip_footer + 0, crc32_z(0, outbuf.p, outbuf.n)); + p = stpcpy(p, "Content-Encoding: gzip\r\n"); + crc = crc32_z(0, outbuf.p, outbuf.n); + WRITE32LE(gzip_footer + 0, crc); WRITE32LE(gzip_footer + 4, outbuf.n); content = FreeLater(Deflate(outbuf.p, outbuf.n, &contentlength)); + free(outbuf.p); } else { - content = outbuf.p; + content = FreeLater(outbuf.p); contentlength = outbuf.n; } + outbuf.p = 0; + outbuf.n = 0; return p; } -static char *GetAssetPath(uint32_t cf, size_t *out_size) { +static char *GetAssetPath(uint64_t cf, size_t *out_size) { char *p1, *p2; size_t n1, n2; p1 = ZIP_CFILE_NAME(zmap + cf); n1 = ZIP_CFILE_NAMESIZE(zmap + cf); - p2 = malloc(1 + n1 + 1); + p2 = xmalloc(1 + n1 + 1); n2 = 1 + n1 + 1; p2[0] = '/'; memcpy(p2 + 1, p1, n1); @@ -1491,7 +1440,7 @@ static int LuaServeAsset(lua_State *L) { return 0; } -static int LuaRespond(lua_State *L, char *respond(int, const char *)) { +static int LuaRespond(lua_State *L, char *respond(unsigned, const char *)) { char *p; int code; size_t reasonlen; @@ -1606,19 +1555,22 @@ static int LuaGetHeader(lua_State *L) { size_t i, keylen; key = luaL_checklstring(L, 1, &keylen); if ((h = GetHttpHeader(key, keylen)) != -1) { - LuaPushLatin1(L, inbuf.p + msg.headers[h].a, - msg.headers[h].b - msg.headers[h].a); - return 1; - } - for (i = 0; i < msg.xheaders.n; ++i) { - if (!CompareSlicesCase(key, keylen, inbuf.p + msg.xheaders.p[i].k.a, - msg.xheaders.p[i].k.b - msg.xheaders.p[i].k.a)) { - LuaPushLatin1(L, inbuf.p + msg.xheaders.p[i].v.a, - msg.xheaders.p[i].v.b - msg.xheaders.p[i].v.a); + if (msg.headers[h].a) { + LuaPushLatin1(L, inbuf.p + msg.headers[h].a, + msg.headers[h].b - msg.headers[h].a); return 1; } + } else { + for (i = 0; i < msg.xheaders.n; ++i) { + if (SlicesEqualCase(key, keylen, inbuf.p + msg.xheaders.p[i].k.a, + msg.xheaders.p[i].k.b - msg.xheaders.p[i].k.a)) { + LuaPushLatin1(L, inbuf.p + msg.xheaders.p[i].v.a, + msg.xheaders.p[i].v.b - msg.xheaders.p[i].v.a); + return 1; + } + } } - lua_pushstring(L, ""); + lua_pushnil(L); return 1; } @@ -1627,7 +1579,7 @@ static int LuaGetHeaders(lua_State *L) { char *name; lua_newtable(L); for (i = 0; i < kHttpHeadersMax; ++i) { - if (msg.headers[i].b - msg.headers[i].a) { + if (msg.headers[i].a) { LuaPushLatin1(L, inbuf.p + msg.headers[i].a, msg.headers[i].b - msg.headers[i].a); lua_setfield(L, -2, GetHttpHeaderName(i)); @@ -1673,11 +1625,6 @@ static int LuaSetHeader(lua_State *L) { p = luaheaderp; } switch (h) { - case kHttpDate: - case kHttpContentRange: - case kHttpContentLength: - case kHttpContentEncoding: - return luaL_argerror(L, 1, "abstracted"); case kHttpConnection: if (evallen != 5 || memcmp(eval, "close", 5)) { return luaL_argerror(L, 2, "unsupported"); @@ -1731,19 +1678,72 @@ static int LuaGetParam(lua_State *L) { return 1; } -static int LuaGetParams(lua_State *L) { +static void LuaPushParams(lua_State *L, struct UrlParams *h) { size_t i; lua_newtable(L); - for (i = 0; i < request.params.n; ++i) { + for (i = 0; i < h->n; ++i) { lua_newtable(L); - lua_pushlstring(L, request.params.p[i].key.p, request.params.p[i].key.n); + lua_pushlstring(L, h->p[i].key.p, h->p[i].key.n); lua_seti(L, -2, 1); - if (request.params.p[i].val.n != SIZE_MAX) { - lua_pushlstring(L, request.params.p[i].val.p, request.params.p[i].val.n); + if (h->p[i].val.n != SIZE_MAX) { + lua_pushlstring(L, h->p[i].val.p, h->p[i].val.n); lua_seti(L, -2, 2); } lua_seti(L, -2, i + 1); } +} + +static int LuaGetParams(lua_State *L) { + LuaPushParams(L, &request.params); + return 1; +} + +static int LuaParseParams(lua_State *L) { + void *m; + size_t size; + const char *data; + struct UrlParams h; + data = luaL_checklstring(L, 1, &size); + memset(&h, 0, sizeof(h)); + m = ParseParams(data, size, &h); + LuaPushParams(L, &h); + free(h.p); + free(m); + return 1; +} + +static void LuaPushUrlView(lua_State *L, struct UrlView *v) { + if (v->p) { + lua_pushlstring(L, v->p, v->n); + } else { + lua_pushnil(L); + } +} + +static void LuaSetUrlView(lua_State *L, struct UrlView *v, const char *k) { + LuaPushUrlView(L, v); + lua_setfield(L, -2, k); +} + +static int LuaParseUrl(lua_State *L) { + void *m; + size_t size; + struct Url h; + const char *data; + data = luaL_checklstring(L, 1, &size); + m = ParseUrl(data, size, &h); + lua_newtable(L); + LuaSetUrlView(L, &h.user, "user"); + LuaSetUrlView(L, &h.pass, "pass"); + LuaSetUrlView(L, &h.host, "host"); + LuaSetUrlView(L, &h.port, "port"); + LuaSetUrlView(L, &h.path, "path"); + LuaSetUrlView(L, &h.scheme, "scheme"); + LuaSetUrlView(L, &h.fragment, "fragment"); + LuaPushParams(L, &h.params); + lua_setfield(L, -2, "params"); + free(h.params.p); + free(m); return 1; } @@ -1756,6 +1756,30 @@ static int LuaWrite(lua_State *L) { return 0; } +static int LuaIsValidHttpToken(lua_State *L) { + size_t size; + const char *data; + data = luaL_checklstring(L, 1, &size); + lua_pushboolean(L, IsValidHttpToken(data, size)); + return 1; +} + +static int LuaIsAcceptablePath(lua_State *L) { + size_t size; + const char *data; + data = luaL_checklstring(L, 1, &size); + lua_pushboolean(L, IsAcceptablePath(data, size)); + return 1; +} + +static int LuaIsAcceptableHostPort(lua_State *L) { + size_t size; + const char *data; + data = luaL_checklstring(L, 1, &size); + lua_pushboolean(L, IsAcceptableHostPort(data, size)); + return 1; +} + static int LuaEscaper(lua_State *L, struct EscapeResult escape(const char *, size_t)) { size_t size; @@ -1891,7 +1915,10 @@ static int LuaSetLogLevel(lua_State *L) { } static int LuaHidePath(lua_State *L) { - AddString(&hidepaths, strdup(luaL_checkstring(L, 1))); + size_t pathlen; + const char *path; + path = luaL_checklstring(L, 1, &pathlen); + AddString(&hidepaths, strndup(path, pathlen)); return 0; } @@ -1917,13 +1944,12 @@ static int LuaIsHiddenPath(lua_State *L) { static int LuaGetZipPaths(lua_State *L) { char *path; - uint32_t cf; + uint64_t cf; size_t i, n, pathlen; lua_newtable(L); i = 0; - n = ZIP_CDIR_RECORDS(zdir); - CHECK_EQ(kZipCdirHdrMagic, ZIP_CDIR_MAGIC(zdir)); - for (cf = ZIP_CDIR_OFFSET(zdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { + n = GetZipCdirRecords(cdir); + for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) { CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf)); path = GetAssetPath(cf, &pathlen); lua_pushlstring(L, path, pathlen); @@ -1954,50 +1980,55 @@ static void LuaRun(const char *path) { } static const luaL_Reg kLuaFuncs[] = { - {"DecodeBase64", LuaDecodeBase64}, // - {"EncodeBase64", LuaEncodeBase64}, // - {"EscapeFragment", LuaEscapeFragment}, // - {"EscapeHtml", LuaEscapeHtml}, // - {"EscapeLiteral", LuaEscapeLiteral}, // - {"EscapeParam", LuaEscapeParam}, // - {"EscapePath", LuaEscapePath}, // - {"EscapeSegment", LuaEscapeSegment}, // - {"FormatHttpDateTime", LuaFormatHttpDateTime}, // - {"GetClientAddr", LuaGetClientAddr}, // - {"GetDate", LuaGetDate}, // - {"GetHeader", LuaGetHeader}, // - {"GetHeaders", LuaGetHeaders}, // - {"GetLogLevel", LuaGetLogLevel}, // - {"GetMethod", LuaGetMethod}, // - {"GetParam", LuaGetParam}, // - {"GetParams", LuaGetParams}, // - {"GetPath", LuaGetPath}, // - {"GetPayload", LuaGetPayload}, // - {"GetServerAddr", LuaGetServerAddr}, // - {"GetUri", LuaGetUri}, // - {"GetVersion", LuaGetVersion}, // - {"GetZipPaths", LuaGetZipPaths}, // - {"LaunchBrowser", LuaLaunchBrowser}, // - {"HasParam", LuaHasParam}, // - {"HidePath", LuaHidePath}, // - {"LoadAsset", LuaLoadAsset}, // - {"Log", LuaLog}, // - {"ParseHttpDateTime", LuaParseHttpDateTime}, // - {"ProgramBrand", LuaProgramBrand}, // - {"ProgramCache", LuaProgramCache}, // - {"ProgramPort", LuaProgramPort}, // - {"ProgramRedirect", LuaProgramRedirect}, // - {"ServeAsset", LuaServeAsset}, // - {"ServeError", LuaServeError}, // - {"SetHeader", LuaSetHeader}, // - {"SetLogLevel", LuaSetLogLevel}, // - {"SetStatus", LuaSetStatus}, // - {"Write", LuaWrite}, // - {"bsf", LuaBsf}, // - {"bsr", LuaBsr}, // - {"crc32", LuaCrc32}, // - {"crc32c", LuaCrc32c}, // - {"popcnt", LuaPopcnt}, // + {"DecodeBase64", LuaDecodeBase64}, // + {"EncodeBase64", LuaEncodeBase64}, // + {"EscapeFragment", LuaEscapeFragment}, // + {"EscapeHtml", LuaEscapeHtml}, // + {"EscapeLiteral", LuaEscapeLiteral}, // + {"EscapeParam", LuaEscapeParam}, // + {"EscapePath", LuaEscapePath}, // + {"EscapeSegment", LuaEscapeSegment}, // + {"FormatHttpDateTime", LuaFormatHttpDateTime}, // + {"GetClientAddr", LuaGetClientAddr}, // + {"GetDate", LuaGetDate}, // + {"GetHeader", LuaGetHeader}, // + {"GetHeaders", LuaGetHeaders}, // + {"GetLogLevel", LuaGetLogLevel}, // + {"GetMethod", LuaGetMethod}, // + {"GetParam", LuaGetParam}, // + {"GetParams", LuaGetParams}, // + {"GetPath", LuaGetPath}, // + {"GetPayload", LuaGetPayload}, // + {"GetServerAddr", LuaGetServerAddr}, // + {"GetUri", LuaGetUri}, // + {"GetVersion", LuaGetVersion}, // + {"GetZipPaths", LuaGetZipPaths}, // + {"HasParam", LuaHasParam}, // + {"HidePath", LuaHidePath}, // + {"IsAcceptableHostPort", LuaIsAcceptableHostPort}, // + {"IsAcceptablePath", LuaIsAcceptablePath}, // + {"IsValidHttpToken", LuaIsValidHttpToken}, // + {"LaunchBrowser", LuaLaunchBrowser}, // + {"LoadAsset", LuaLoadAsset}, // + {"Log", LuaLog}, // + {"ParseHttpDateTime", LuaParseHttpDateTime}, // + {"ParseParams", LuaParseParams}, // + {"ParseUrl", LuaParseUrl}, // + {"ProgramBrand", LuaProgramBrand}, // + {"ProgramCache", LuaProgramCache}, // + {"ProgramPort", LuaProgramPort}, // + {"ProgramRedirect", LuaProgramRedirect}, // + {"ServeAsset", LuaServeAsset}, // + {"ServeError", LuaServeError}, // + {"SetHeader", LuaSetHeader}, // + {"SetLogLevel", LuaSetLogLevel}, // + {"SetStatus", LuaSetStatus}, // + {"Write", LuaWrite}, // + {"bsf", LuaBsf}, // + {"bsr", LuaBsr}, // + {"crc32", LuaCrc32}, // + {"crc32c", LuaCrc32c}, // + {"popcnt", LuaPopcnt}, // }; static void LuaSetArgv(lua_State *L) { @@ -2030,11 +2061,11 @@ static void LuaInit(void) { LuaSetConstant(L, "kLogWarn", kLogWarn); LuaSetConstant(L, "kLogError", kLogError); LuaSetConstant(L, "kLogFatal", kLogFatal); - LuaRun("/tool/net/.init.lua"); + LuaRun(".init.lua"); } static void LuaReload(void) { - LuaRun("/tool/net/.reload.lua"); + LuaRun(".reload.lua"); } static char *ServeLua(struct Asset *a) { @@ -2046,10 +2077,7 @@ static char *ServeLua(struct Asset *a) { p = SetStatus(200, "OK"); p = AppendContentType(p, "text/html"); } - if (outbuf.n) { - p = CommitOutput(p); - } - return p; + return CommitOutput(p); } else { WARNF("%s %s", clientaddrstr, lua_tostring(L, -1)); lua_pop(L, 1); /* remove message */ @@ -2080,23 +2108,22 @@ static char *HandleAsset(struct Asset *a, const char *path, size_t pathlen) { } static char *HandleRedirect(struct Redirect *r) { + int code; struct Asset *a; - if (!r->code) { - if ((a = LocateAsset(r->location, strlen(r->location)))) { - DEBUGF("%s %s %`'.*s rewritten %`'s", clientaddrstr, - kHttpMethod[msg.method], request.path.n, request.path.p, - r->location); - return HandleAsset(a, r->location, strlen(r->location)); - } else { - return ServeError(505, "HTTP Version Not Supported"); - } + if (!r->code && (a = LocateAsset(r->location, strlen(r->location)))) { + DEBUGF("%s %s %`'.*s rewritten %`'s", clientaddrstr, + kHttpMethod[msg.method], request.path.n, request.path.p, + r->location); + return HandleAsset(a, r->location, strlen(r->location)); } else if (httpversion == 9) { return ServeError(505, "HTTP Version Not Supported"); } else { + code = r->code; + if (!code) code = 307; DEBUGF("%s %s %`'.*s %d redirecting %`'s", clientaddrstr, - kHttpMethod[msg.method], request.path.n, request.path.p, r->code, + kHttpMethod[msg.method], request.path.n, request.path.p, code, r->location); - return AppendHeader(SetStatus(r->code, GetHttpReason(r->code)), "Location", + return AppendHeader(SetStatus(code, GetHttpReason(code)), "Location", FreeLater(EncodeHttpHeaderValue(r->location, -1, 0))); } } @@ -2104,31 +2131,33 @@ static char *HandleRedirect(struct Redirect *r) { static void LogMessage(const char *d, const char *s, size_t n) { size_t n2, n3, n4; char *s2, *s3, *s4; - if (!logmessages) return; - while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; - if ((s2 = DecodeLatin1(s, n, &n2))) { - if ((s3 = VisualizeControlCodes(s2, n2, &n3))) { - if ((s4 = IndentLines(s3, n3, &n4, 1))) { - LOGF("%s %s %,ld byte message\n%.*s", clientaddrstr, d, n, n4, s4); - free(s4); + if (logmessages) { + while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; + if ((s2 = DecodeLatin1(s, n, &n2))) { + if ((s3 = VisualizeControlCodes(s2, n2, &n3))) { + if ((s4 = IndentLines(s3, n3, &n4, 1))) { + LOGF("%s %s %,ld byte message\n%.*s", clientaddrstr, d, n, n4, s4); + free(s4); + } + free(s3); } - free(s3); + free(s2); } - free(s2); } } static void LogBody(const char *d, const char *s, size_t n) { char *s2, *s3; size_t n2, n3; - if (!n || !logbodies) return; - while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; - if ((s2 = VisualizeControlCodes(s, n, &n2))) { - if ((s3 = IndentLines(s2, n2, &n3, 1))) { - LOGF("%s %s %,ld byte payload\n%.*s", clientaddrstr, d, n, n3, s3); - free(s3); + if (n && logbodies) { + while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; + if ((s2 = VisualizeControlCodes(s, n, &n2))) { + if ((s3 = IndentLines(s2, n2, &n3, 1))) { + LOGF("%s %s %,ld byte payload\n%.*s", clientaddrstr, d, n, n3, s3); + free(s3); + } + free(s2); } - free(s2); } } @@ -2169,9 +2198,11 @@ Content-Length: 0\r\n\ static void LogClose(const char *reason) { if (amtread) { - WARNF("%s %s with %,ld bytes unprocessed", clientaddrstr, reason, amtread); + WARNF("%s %s with %,ld bytes unprocessed and %,d requests handled", + clientaddrstr, reason, amtread, requestshandled); } else { - DEBUGF("%s %s", clientaddrstr, reason); + DEBUGF("%s %s with %,d requests handled", clientaddrstr, reason, + requestshandled); } } @@ -2183,41 +2214,41 @@ static const char *DescribeClose(void) { return "destroyed"; } -static const char *DescribeCompressionRatio(char rb[8], uint32_t cf) { +static const char *DescribeCompressionRatio(char rb[8], uint64_t lf) { long percent; - if (ZIP_CFILE_COMPRESSIONMETHOD(zmap + cf) == kZipCompressionNone) { + if (ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf) == kZipCompressionNone) { return "n/a"; } else { - percent = lround(100 - (double)ZIP_CFILE_COMPRESSEDSIZE(zmap + cf) / - ZIP_CFILE_UNCOMPRESSEDSIZE(zmap + cf) * 100); + percent = lround(100 - (double)GetZipLfileCompressedSize(zmap + lf) / + GetZipLfileUncompressedSize(zmap + lf) * 100); sprintf(rb, "%ld%%", MIN(999, MAX(-999, percent))); return rb; } } -static void LoadLogo(void) { - char *p; - size_t n; - struct Asset *a; - const char *logopath; - logopath = "/tool/net/redbean.png"; - if ((a = LocateAsset(logopath, strlen(logopath)))) { - p = LoadAsset(a, &n); - logo.p = EncodeBase64(p, n, &logo.n); - free(p); - } +static int GetDecimalWidth(int x) { + int w = x ? ceil(log10(x)) : 1; + return w + (w - 1) / 3; +} + +static int GetOctalWidth(int x) { + return !x ? 1 : x < 8 ? 2 : 1 + bsr(x) / 3; } static char *ServeListing(void) { + long x; + ldiv_t y; + int w[3]; char rb[8]; char tb[64]; - int w, x, y; struct tm tm; - char *p, *path; + const char *and; int64_t lastmod; - uint32_t cf, lf; + uint64_t cf, lf; + struct Asset *a; + char *p, *q, *path; size_t i, n, pathlen; - struct EscapeResult r[3]; + struct EscapeResult r[4]; AppendString("\ \n\ \n\ @@ -2238,51 +2269,60 @@ footer {\n\ }\n\ \n\

\n"); - if (logo.n) { + if ((a = LocateAsset("redbean.png", 11))) { + p = LoadAsset(a, &n); + q = EncodeBase64(p, n, &n); AppendString("\n"); + free(q); + free(p); } r[0] = EscapeHtml(brand, strlen(brand)); AppendData(r[0].data, r[0].size); free(r[0].data); AppendString("


\n");
-  w = x = 0;
-  n = ZIP_CDIR_RECORDS(zdir);
-  CHECK_EQ(kZipCdirHdrMagic, ZIP_CDIR_MAGIC(zdir));
-  for (cf = ZIP_CDIR_OFFSET(zdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
+  memset(w, 0, sizeof(w));
+  n = GetZipCdirRecords(cdir);
+  for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
     CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
-    if (!IsHiddenPath((path = GetAssetPath(cf, &pathlen)))) {
-      y = strwidth(path, 0);
-      w = MIN(80, MAX(w, y + 2));
-      y = ZIP_CFILE_UNCOMPRESSEDSIZE(zmap + cf);
-      y = y ? llog10(y) : 1;
-      x = MIN(80, MAX(x, y + (y - 1) / 3 + 2));
+    lf = GetZipCfileOffset(zmap + cf);
+    path = GetAssetPath(cf, &pathlen);
+    if (!IsHiddenPath(path)) {
+      w[0] = min(80, max(w[0], strwidth(path, 0) + 2));
+      w[1] = max(w[1], GetOctalWidth(GetZipCfileMode(zmap + cf)));
+      w[2] = max(w[2], GetDecimalWidth(GetZipLfileUncompressedSize(zmap + lf)));
     }
+    free(path);
   }
-  n = ZIP_CDIR_RECORDS(zdir);
-  for (cf = ZIP_CDIR_OFFSET(zdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
+  n = GetZipCdirRecords(cdir);
+  for (cf = GetZipCdirOffset(cdir); n--; cf += ZIP_CFILE_HDRSIZE(zmap + cf)) {
     CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(zmap + cf));
+    lf = GetZipCfileOffset(zmap + cf);
     path = GetAssetPath(cf, &pathlen);
     if (!IsHiddenPath(path)) {
       r[0] = EscapeHtml(path, pathlen);
       r[1] = EscapeUrlPath(path, pathlen);
       r[2] = EscapeHtml(r[1].data, r[1].size);
-      lastmod = GetLastModifiedZip(zmap + cf);
+      r[3] = EscapeHtml(ZIP_CFILE_COMMENT(zmap + cf),
+                        ZIP_CFILE_COMMENTSIZE(zmap + cf));
+      lastmod = GetZipCfileLastModified(zmap + cf);
       localtime_r(&lastmod, &tm);
-      strftime(tb, sizeof(tb), "%Y-%m-%d %H:%M:%S", &tm);
+      strftime(tb, sizeof(tb), "%Y-%m-%d %H:%M:%S %Z", &tm);
       if (IsCompressionMethodSupported(
-              ZIP_CFILE_COMPRESSIONMETHOD(zmap + cf)) &&
-          IsAcceptableHttpRequestPath(path, pathlen)) {
-        AppendFmt("%-*.*s %s %4s %,*ld\n", r[2].size,
-                  r[2].data, w, r[0].size, r[0].data, tb,
-                  DescribeCompressionRatio(rb, cf), x,
-                  ZIP_CFILE_UNCOMPRESSEDSIZE(zmap + cf));
+              ZIP_LFILE_COMPRESSIONMETHOD(zmap + lf)) &&
+          IsAcceptablePath(path, pathlen)) {
+        AppendFmt("%-*.*s %s  %0*o %4s  %,*ld  %'s\n",
+                  r[2].size, r[2].data, w[0], r[0].size, r[0].data, tb, w[1],
+                  GetZipCfileMode(zmap + cf), DescribeCompressionRatio(rb, lf),
+                  w[2], GetZipLfileUncompressedSize(zmap + lf), r[3].data);
       } else {
-        AppendFmt("%-*.*s %s %4s %,*ld\n", w, r[0].size, r[0].data, tb,
-                  DescribeCompressionRatio(rb, cf), x,
-                  ZIP_CFILE_UNCOMPRESSEDSIZE(zmap + cf));
+        AppendFmt("%-*.*s %s  %0*o %4s  %,*ld  %'s\n", w[0], r[0].size,
+                  r[0].data, tb, w[1], GetZipCfileMode(zmap + cf),
+                  DescribeCompressionRatio(rb, lf), w[2],
+                  GetZipLfileUncompressedSize(zmap + lf), r[3].data);
       }
+      free(r[3].data);
       free(r[2].data);
       free(r[1].data);
       free(r[0].data);
@@ -2290,21 +2330,29 @@ footer {\n\
     free(path);
   }
   AppendString("
\n"); p = SetStatus(200, "OK"); p = AppendCache(p, 0); @@ -2321,24 +2369,30 @@ static char *ServeServerOptions(void) { return p; } -static char *HandleMessage(void) { +static char *TryPath(const char *path, size_t pathlen) { long r; - ssize_t cl, rc; struct Asset *a; - size_t got, need; + if ((a = LocateAsset(path, pathlen))) { + return HandleAsset(a, path, pathlen); + } else if ((r = FindRedirect(path, pathlen)) != -1) { + return HandleRedirect(redirects.p + r); + } else if (SlicesEqual(path, pathlen, "/", 1)) { + return ServeListing(); + } else { + return NULL; + } +} + +static char *HandleMessage(void) { + char *p, *path; + ssize_t cl, rc; + const char *host; + size_t got, need, pathlen, hostlen; httpversion = ParseHttpVersion(inbuf.p + msg.version.a, msg.version.b - msg.version.a); if (httpversion > 101) { return ServeError(505, "HTTP Version Not Supported"); } - if (HasHeader(kHttpExpect) && !HeaderEquals(kHttpExpect, "100-continue")) { - return ServeError(417, "Expectation Failed"); - } - if (msg.method == kHttpConnect || - (HasHeader(kHttpTransferEncoding) && - !HeaderEquals(kHttpTransferEncoding, "identity"))) { - return ServeError(501, "Not Implemented"); - } if (!HasHeader(kHttpContentLength) && (msg.method == kHttpPost || msg.method == kHttpPut)) { return ServeError(411, "Length Required"); @@ -2352,7 +2406,7 @@ static char *HandleMessage(void) { if (need > inbuf.n) { return ServeError(413, "Payload Too Large"); } - if (HeaderEquals(kHttpExpect, "100-continue") && httpversion >= 101) { + if (HeaderEqual(kHttpExpect, "100-continue") && httpversion >= 101) { SendContinue(); } while (amtread < need) { @@ -2381,36 +2435,84 @@ static char *HandleMessage(void) { } msgsize = need; /* we are now synchronized */ LogBody("received", inbuf.p + hdrsize, msgsize - hdrsize); - if (httpversion != 101 || !CompareHeader(kHttpConnection, "close")) { + if (httpversion != 101 || HeaderEqual(kHttpConnection, "close")) { connectionclose = true; } - ParseRequestUri(); + if (HasHeader(kHttpExpect) && !HeaderEqual(kHttpExpect, "100-continue")) { + return ServeError(417, "Expectation Failed"); + } + if (msg.method == kHttpConnect || + (HasHeader(kHttpTransferEncoding) && + !HeaderEqual(kHttpTransferEncoding, "identity"))) { + return ServeError(501, "Not Implemented"); + } + FreeLater( + ParseRequestUri(inbuf.p + msg.uri.a, msg.uri.b - msg.uri.a, &request)); + if (HeaderEqual(kHttpContentType, "application/x-www-form-urlencoded")) { + FreeLater( + ParseParams(inbuf.p + hdrsize, msgsize - hdrsize, &request.params)); + } + FreeLater(request.params.p); + if ((httpversion >= 101 && !HasHeader(kHttpHost)) || + (request.scheme.n && + !SlicesEqualCase(request.scheme.p, request.scheme.n, "http", 4) && + !SlicesEqualCase(request.scheme.p, request.scheme.n, "https", 5))) { + return ServeError(400, "Bad Request"); + } if (msg.method == kHttpOptions && !CompareSlices(request.path.p, request.path.n, "*", 1)) { return ServeServerOptions(); } - if (!IsAcceptableHttpRequestPath(request.path.p, request.path.n)) { - WARNF("%s could not parse request %`'.*s", clientaddrstr, - msg.uri.b - msg.uri.a, inbuf.p + msg.uri.a); + if (!request.path.n || request.path.p[0] != '/' || + !IsAcceptablePath(request.path.p, request.path.n)) { + WARNF("%s refusing path %`'.*s", clientaddrstr, msg.uri.b - msg.uri.a, + inbuf.p + msg.uri.a); connectionclose = true; return ServeError(400, "Bad Request"); } - if (HeaderEquals(kHttpContentType, "application/x-www-form-urlencoded")) { - ParseFormParams(); + if (!request.path.n || request.path.p[0] != '/' || + !IsAcceptablePath(request.path.p, request.path.n)) { + WARNF("%s refusing path %`'.*s", clientaddrstr, msg.uri.b - msg.uri.a, + inbuf.p + msg.uri.a); + return ServeError(400, "Bad Request"); } - VERBOSEF("%s %s %`'.*s referrer %`'.*s", clientaddrstr, - kHttpMethod[msg.method], request.path.n, request.path.p, - msg.headers[kHttpReferer].b - msg.headers[kHttpReferer].a, - inbuf.p + msg.headers[kHttpReferer].a); - if ((a = LocateAsset(request.path.p, request.path.n))) { - return HandleAsset(a, request.path.p, request.path.n); - } else if ((r = FindRedirect(request.path.p, request.path.n)) != -1) { - return HandleRedirect(redirects.p + r); - } else if (!CompareSlices(request.path.p, request.path.n, "/", 1)) { - return ServeListing(); + if (request.host.n) { + host = request.host.p; + hostlen = request.host.n; } else { - return ServeError(404, "Not Found"); + host = inbuf.p + msg.headers[kHttpHost].a; + hostlen = msg.headers[kHttpHost].b - msg.headers[kHttpHost].a; } + if (!IsAcceptableHostPort(host, hostlen)) { + WARNF("%s refusing host %`'.*s", clientaddrstr, hostlen, host); + return ServeError(400, "Bad Request"); + } + VERBOSEF("%s %s %`'.*s %`'.*s referrer %`'.*s from %`'.*s", clientaddrstr, + kHttpMethod[msg.method], hostlen, host, msg.uri.b - msg.uri.a, + inbuf.p + msg.uri.a, + msg.headers[kHttpReferer].b - msg.headers[kHttpReferer].a, + inbuf.p + msg.headers[kHttpReferer].a, + msg.headers[kHttpUserAgent].b - msg.headers[kHttpUserAgent].a, + inbuf.p + msg.headers[kHttpUserAgent].a); + if (hostlen) { + if ((p = memchr(host, ':', hostlen))) hostlen = p - host; + pathlen = 1 + hostlen + request.path.n; + path = FreeLater(xmalloc(pathlen + 4)); + path[0] = '/'; + mempcpy(mempcpy(path + 1, host, hostlen), request.path.p, request.path.n); + if ((p = TryPath(path, pathlen))) return p; + if (hostlen > 4 && !memcmp(host, "www.", 4)) { + mempcpy(mempcpy(path + 1, host + 4, hostlen - 4), request.path.p, + request.path.n); + if ((p = TryPath(path, pathlen))) return p; + } else { + mempcpy(mempcpy(mempcpy(path + 1, "www.", 4), host, hostlen), + request.path.p, request.path.n); + if ((p = TryPath(path, pathlen))) return p; + } + } + if ((p = TryPath(request.path.p, request.path.n))) return p; + return ServeError(404, "Not Found"); } static bool HandleRequest(void) { @@ -2483,15 +2585,14 @@ static bool HandleRequest(void) { iovlen = 1; } Send(iov, iovlen); - CollectGarbage(); + InterlockedAdd(&shared->requestshandled, 1); + ++requestshandled; return true; } static void InitRequest(void) { frags = 0; msgsize = 0; - outbuf.p = 0; - outbuf.n = 0; content = NULL; gzipped = false; branded = false; @@ -2499,7 +2600,7 @@ static void InitRequest(void) { InitHttpRequest(&msg); } -static void ProcessRequests(void) { +static void HandleRequests(void) { ssize_t rc; size_t got; long double now; @@ -2549,17 +2650,18 @@ static void ProcessRequests(void) { LogClose(DescribeClose()); return; } + CollectGarbage(); } } static void EnterMeltdownMode(void) { if (lastmeltdown && nowl() - lastmeltdown < 1) return; - WARNF("redbean is entering meltdown mode with %,d workers", shared->workers); + WARNF("redbean is melting down (%,d workers)", shared->workers); LOGIFNEG1(kill(0, SIGUSR2)); lastmeltdown = nowl(); } -static void ProcessConnection(void) { +static void HandleConnection(void) { int pid; clientaddrsize = sizeof(clientaddr); if ((client = accept4(server, &clientaddr, &clientaddrsize, SOCK_CLOEXEC)) != @@ -2567,6 +2669,7 @@ static void ProcessConnection(void) { startconnection = nowl(); if (uniprocess) { pid = -1; + requestshandled = 0; connectionclose = true; } else { switch ((pid = fork())) { @@ -2575,6 +2678,7 @@ static void ProcessConnection(void) { connectionclose = false; break; case -1: + WARNF("%s too man processes %s", serveraddrstr, strerror(errno)); EnterMeltdownMode(); SendServiceUnavailable(); /* fallthrough */ @@ -2586,33 +2690,82 @@ static void ProcessConnection(void) { } DescribeAddress(clientaddrstr, &clientaddr); DEBUGF("%s accept", clientaddrstr); - ProcessRequests(); + HandleRequests(); LOGIFNEG1(close(client)); - if (!pid) _exit(0); + if (!pid) { + _exit(0); + } else { + CollectGarbage(); + } } else if (errno != EINTR) { - FATALF("%s accept error %s", serveraddrstr, strerror(errno)); + if (errno == ENFILE) { + WARNF("%s too many open files", serveraddrstr); + EnterMeltdownMode(); + } else if (errno == EMFILE) { + WARNF("%s ran out of open file quota", serveraddrstr); + EnterMeltdownMode(); + } else if (errno == ENOMEM || errno == ENOBUFS) { + WARNF("%s ran out of memory"); + EnterMeltdownMode(); + } else if (errno == ENONET) { + WARNF("%s network gone", serveraddrstr); + sleep(1); + } else if (errno == ENETDOWN) { + WARNF("%s network down", serveraddrstr); + sleep(1); + } else if (errno == ECONNABORTED) { + WARNF("%s connection reset before accept"); + } else if (errno == ENETUNREACH || errno == EHOSTUNREACH || + errno == EOPNOTSUPP || errno == ENOPROTOOPT || errno == EPROTO) { + WARNF("%s ephemeral accept error %s", serveraddrstr, strerror(errno)); + } else { + FATALF("%s accept error %s", serveraddrstr, strerror(errno)); + } } } +static void HandleHeartbeat(void) { + UpdateCurrentDate(nowl()); +} + static void TuneServerSocket(void) { int yes = 1; - LOGIFNEG1(setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes))); - LOGIFNEG1(setsockopt(server, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))); - LOGIFNEG1(setsockopt(server, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes))); - LOGIFNEG1(setsockopt(server, IPPROTO_TCP, TCP_FASTOPEN, &yes, sizeof(yes))); - LOGIFNEG1(setsockopt(server, IPPROTO_TCP, TCP_QUICKACK, &yes, sizeof(yes))); + setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + setsockopt(server, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); + setsockopt(server, IPPROTO_TCP, TCP_FASTOPEN, &yes, sizeof(yes)); + setsockopt(server, IPPROTO_TCP, TCP_QUICKACK, &yes, sizeof(yes)); } -void RedBean(int argc, char *argv[]) { +static void RestoreApe(const char *prog) { + char *p; + size_t n; + struct Asset *a; + extern char ape_rom_vaddr[] __attribute__((__weak__)); + if (IsWindows()) return; + if (endswith(prog, ".com.dbg")) return; + close(OpenExecutable()); + if ((a = GetAsset(".ape", 4))) { + p = LoadAsset(a, &n); + mprotect(ape_rom_vaddr, PAGESIZE, PROT_READ | PROT_WRITE); + memcpy(ape_rom_vaddr, p, MIN(n, PAGESIZE)); + msync(ape_rom_vaddr, PAGESIZE, MS_ASYNC); + mprotect(ape_rom_vaddr, PAGESIZE, PROT_NONE); + free(p); + } +} + +void RedBean(int argc, char *argv[], const char *prog) { uint32_t addrsize; + startserver = nowl(); gmtoff = GetGmtOffset(); + CHECK_GT(CLK_TCK, 0); CHECK_NE(MAP_FAILED, (shared = mmap(NULL, ROUNDUP(sizeof(struct Shared), FRAMESIZE), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0))); - OpenZip((const char *)getauxval(AT_EXECFN)); + OpenZip(prog); IndexAssets(); - LoadLogo(); + RestoreApe(prog); SetDefaults(); GetOpts(argc, argv); LuaInit(); @@ -2662,13 +2815,11 @@ void RedBean(int argc, char *argv[]) { LuaReload(); invalidated = false; } else if (heartbeat) { - UpdateCurrentDate(nowl()); + HandleHeartbeat(); heartbeat = false; } else { - if (heartless) { - UpdateCurrentDate(nowl()); - } - ProcessConnection(); + if (heartless) HandleHeartbeat(); + HandleConnection(); } } VERBOSEF("%s shutting down", serveraddrstr); @@ -2684,6 +2835,6 @@ void RedBean(int argc, char *argv[]) { int main(int argc, char *argv[]) { showcrashreports(); - RedBean(argc, argv); + RedBean(argc, argv, (const char *)getauxval(AT_EXECFN)); return 0; } diff --git a/tool/net/redbean.lua b/tool/net/redbean.lua index ec8716733..fe186327c 100644 --- a/tool/net/redbean.lua +++ b/tool/net/redbean.lua @@ -69,7 +69,7 @@ local function main() Write([[

post request html form demo

-
+
@@ -92,7 +92,7 @@ local function main() r.onload = function() { document.getElementById("result").innerText = this.getResponseHeader('X-Custom-Header'); }; - r.open('POST', '/tool/net/redbean-xhr.lua'); + r.open('POST', 'redbean-xhr.lua'); r.setRequestHeader('X-Custom-Header', document.getElementById('x').value); r.send(); }