mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Make improvements
- Clean up sigaction() code - Add a port scanner example - Introduce a ParseCidr() API - Clean up our futex abstraction code - Fix a harmless integer overflow in ParseIp() - Use kernel semaphores on NetBSD to make threads much faster
This commit is contained in:
parent
539bddce8c
commit
c995838e5c
107 changed files with 1085 additions and 492 deletions
127
examples/portscan.c
Normal file
127
examples/portscan.c
Normal file
|
@ -0,0 +1,127 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* @fileoverview fast local network port scanner, e.g.
|
||||
*
|
||||
* make -j8 o//examples/portscan.com
|
||||
* o//examples/portscan.com 10.10.10.0/24 22
|
||||
*/
|
||||
|
||||
const char *FormatIp(char buf[16], uint32_t ip) {
|
||||
snprintf(buf, 16, "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define FormatIp(x) FormatIp(alloca(16), x)
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int port;
|
||||
struct Cidr in;
|
||||
uint32_t netmask;
|
||||
const char *status;
|
||||
struct timeval timeout;
|
||||
uint32_t network_address;
|
||||
uint32_t last_host_address;
|
||||
uint32_t first_host_address;
|
||||
|
||||
if (argc != 3) {
|
||||
PrintUsage:
|
||||
fprintf(stderr,
|
||||
"usage: %s IP/CIDR PORT\n"
|
||||
"example: %s 192.168.0.0/24 22\n",
|
||||
argv[0], argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in = ParseCidr(argv[1], -1);
|
||||
if (in.addr == -1) {
|
||||
fprintf(stderr, "error: bad ip/cidr\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
port = atoi(argv[2]);
|
||||
if (!(1 <= port && port <= 65535)) {
|
||||
fprintf(stderr, "error: bad port\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
if (in.cidr > 30) {
|
||||
fprintf(stderr, "error: maximum supported cidr is 30\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
if (in.cidr < 22) {
|
||||
fprintf(stderr, "error: minimum cidr support right now is 22\n");
|
||||
goto PrintUsage;
|
||||
}
|
||||
|
||||
netmask = -1u << (32 - in.cidr);
|
||||
network_address = in.addr & netmask;
|
||||
first_host_address = network_address + 1;
|
||||
last_host_address = (network_address | ~netmask) - 1;
|
||||
|
||||
assert(last_host_address > first_host_address);
|
||||
assert(last_host_address - first_host_address < 1024);
|
||||
|
||||
fprintf(stderr, "scanning %s through %s\n", FormatIp(first_host_address),
|
||||
FormatIp(last_host_address));
|
||||
|
||||
timeout = timeval_frommillis(100);
|
||||
for (int64_t ip = first_host_address; ip <= last_host_address; ++ip) {
|
||||
if (!fork()) {
|
||||
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
if (!connect(3,
|
||||
(struct sockaddr *)&(struct sockaddr_in){
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(ip),
|
||||
.sin_port = htons(port),
|
||||
},
|
||||
sizeof(struct sockaddr_in))) {
|
||||
status = "open";
|
||||
} else if (errno == ECONNREFUSED) {
|
||||
status = "closed";
|
||||
} else if (errno != EINPROGRESS) {
|
||||
status = _strerrno(errno);
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
if (status) {
|
||||
printf("%-15s %s\n", FormatIp(ip), status);
|
||||
}
|
||||
_Exit(0);
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (wait(0) == -1 && errno == ECHILD) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -184,7 +184,10 @@ o/$(MODE)/libc/calls/timespec_tomicros.o \
|
|||
o/$(MODE)/libc/calls/timespec_totimeval.o \
|
||||
o/$(MODE)/libc/calls/timespec_fromnanos.o \
|
||||
o/$(MODE)/libc/calls/timespec_frommillis.o \
|
||||
o/$(MODE)/libc/calls/timespec_frommicros.o: private \
|
||||
o/$(MODE)/libc/calls/timespec_frommicros.o \
|
||||
o/$(MODE)/libc/calls/timeval_tomillis.o \
|
||||
o/$(MODE)/libc/calls/timeval_frommillis.o \
|
||||
o/$(MODE)/libc/calls/timeval_frommicros.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O2
|
||||
|
||||
|
|
|
@ -22,11 +22,6 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/sigaction-linux.internal.h"
|
||||
#include "libc/calls/struct/sigaction-netbsd.h"
|
||||
#include "libc/calls/struct/sigaction-openbsd.internal.h"
|
||||
#include "libc/calls/struct/sigaction-xnu.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigaction.internal.h"
|
||||
#include "libc/calls/struct/siginfo.internal.h"
|
||||
|
@ -46,6 +41,7 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -58,110 +54,111 @@ STATIC_YOINK("strsignal"); // for kprintf()
|
|||
|
||||
#define SA_RESTORER 0x04000000
|
||||
|
||||
#ifndef SWITCHEROO
|
||||
#define SWITCHEROO(S1, S2, A, B, C, D) \
|
||||
do { \
|
||||
autotype((S2).A) a = (typeof((S2).A))(S1).A; \
|
||||
autotype((S2).B) b = (typeof((S2).B))(S1).B; \
|
||||
autotype((S2).C) c = (typeof((S2).C))(S1).C; \
|
||||
typeof((S2).D) d; \
|
||||
bzero(&d, sizeof(d)); \
|
||||
memcpy(&d, &((S1).D), MIN(sizeof(d), sizeof((S1).D))); \
|
||||
(S2).A = a; \
|
||||
(S2).B = b; \
|
||||
(S2).C = c; \
|
||||
bzero(&((S2).D), sizeof((S2).D)); \
|
||||
memcpy(&((S2).D), &d, MIN(sizeof(d), sizeof((S2).D))); \
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
union metasigaction {
|
||||
struct sigaction cosmo;
|
||||
struct sigaction_linux linux;
|
||||
struct sigaction_freebsd freebsd;
|
||||
struct sigaction_openbsd openbsd;
|
||||
struct sigaction_netbsd netbsd;
|
||||
struct sigaction_xnu_in xnu_in;
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
void __sigenter_xnu(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_linux(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_netbsd(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_freebsd(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_openbsd(int, struct siginfo *, void *) hidden;
|
||||
|
||||
static void sigaction_cosmo2native(union metasigaction *sa) {
|
||||
void *handler;
|
||||
uint64_t flags;
|
||||
void *restorer;
|
||||
uint32_t mask[4];
|
||||
if (!sa) return;
|
||||
switch (__hostos) {
|
||||
case _HOSTLINUX:
|
||||
SWITCHEROO(sa->cosmo, sa->linux, sa_handler, sa_flags, sa_restorer,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTXNU:
|
||||
SWITCHEROO(sa->cosmo, sa->xnu_in, sa_handler, sa_flags, sa_restorer,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTFREEBSD:
|
||||
SWITCHEROO(sa->cosmo, sa->freebsd, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTOPENBSD:
|
||||
SWITCHEROO(sa->cosmo, sa->openbsd, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTNETBSD:
|
||||
SWITCHEROO(sa->cosmo, sa->netbsd, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
flags = sa->cosmo.sa_flags;
|
||||
handler = sa->cosmo.sa_handler;
|
||||
restorer = sa->cosmo.sa_restorer;
|
||||
mask[0] = sa->cosmo.sa_mask.__bits[0];
|
||||
mask[1] = sa->cosmo.sa_mask.__bits[0] >> 32;
|
||||
mask[2] = sa->cosmo.sa_mask.__bits[1];
|
||||
mask[3] = sa->cosmo.sa_mask.__bits[1] >> 32;
|
||||
if (IsLinux()) {
|
||||
sa->linux.sa_flags = flags;
|
||||
sa->linux.sa_handler = handler;
|
||||
sa->linux.sa_restorer = restorer;
|
||||
sa->linux.sa_mask[0] = mask[0];
|
||||
sa->linux.sa_mask[1] = mask[1];
|
||||
} else if (IsXnu()) {
|
||||
sa->xnu_in.sa_flags = flags;
|
||||
sa->xnu_in.sa_handler = handler;
|
||||
sa->xnu_in.sa_restorer = restorer;
|
||||
sa->xnu_in.sa_mask[0] = mask[0];
|
||||
} else if (IsFreebsd()) {
|
||||
sa->freebsd.sa_flags = flags;
|
||||
sa->freebsd.sa_handler = handler;
|
||||
sa->freebsd.sa_mask[0] = mask[0];
|
||||
sa->freebsd.sa_mask[1] = mask[1];
|
||||
sa->freebsd.sa_mask[2] = mask[2];
|
||||
sa->freebsd.sa_mask[3] = mask[3];
|
||||
} else if (IsOpenbsd()) {
|
||||
sa->openbsd.sa_flags = flags;
|
||||
sa->openbsd.sa_handler = handler;
|
||||
sa->openbsd.sa_mask[0] = mask[0];
|
||||
} else if (IsNetbsd()) {
|
||||
sa->netbsd.sa_flags = flags;
|
||||
sa->netbsd.sa_handler = handler;
|
||||
sa->netbsd.sa_mask[0] = mask[0];
|
||||
sa->netbsd.sa_mask[1] = mask[1];
|
||||
sa->netbsd.sa_mask[2] = mask[2];
|
||||
sa->netbsd.sa_mask[3] = mask[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void sigaction_native2cosmo(union metasigaction *sa) {
|
||||
void *handler;
|
||||
uint64_t flags;
|
||||
void *restorer = 0;
|
||||
uint32_t mask[4] = {0};
|
||||
if (!sa) return;
|
||||
switch (__hostos) {
|
||||
case _HOSTLINUX:
|
||||
SWITCHEROO(sa->linux, sa->cosmo, sa_handler, sa_flags, sa_restorer,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTXNU:
|
||||
SWITCHEROO(sa->xnu_out, sa->cosmo, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTFREEBSD:
|
||||
SWITCHEROO(sa->freebsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTOPENBSD:
|
||||
SWITCHEROO(sa->openbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
case _HOSTNETBSD:
|
||||
SWITCHEROO(sa->netbsd, sa->cosmo, sa_handler, sa_flags, sa_flags,
|
||||
sa_mask);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (IsLinux()) {
|
||||
flags = sa->linux.sa_flags;
|
||||
handler = sa->linux.sa_handler;
|
||||
restorer = sa->linux.sa_restorer;
|
||||
mask[0] = sa->linux.sa_mask[0];
|
||||
mask[1] = sa->linux.sa_mask[1];
|
||||
} else if (IsXnu()) {
|
||||
flags = sa->xnu_out.sa_flags;
|
||||
handler = sa->xnu_out.sa_handler;
|
||||
mask[0] = sa->xnu_out.sa_mask[0];
|
||||
} else if (IsFreebsd()) {
|
||||
flags = sa->freebsd.sa_flags;
|
||||
handler = sa->freebsd.sa_handler;
|
||||
mask[0] = sa->freebsd.sa_mask[0];
|
||||
mask[1] = sa->freebsd.sa_mask[1];
|
||||
mask[2] = sa->freebsd.sa_mask[2];
|
||||
mask[3] = sa->freebsd.sa_mask[3];
|
||||
} else if (IsOpenbsd()) {
|
||||
flags = sa->openbsd.sa_flags;
|
||||
handler = sa->openbsd.sa_handler;
|
||||
mask[0] = sa->openbsd.sa_mask[0];
|
||||
} else if (IsNetbsd()) {
|
||||
flags = sa->netbsd.sa_flags;
|
||||
handler = sa->netbsd.sa_handler;
|
||||
mask[0] = sa->netbsd.sa_mask[0];
|
||||
mask[1] = sa->netbsd.sa_mask[1];
|
||||
mask[2] = sa->netbsd.sa_mask[2];
|
||||
mask[3] = sa->netbsd.sa_mask[3];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
sa->cosmo.sa_flags = flags;
|
||||
sa->cosmo.sa_handler = handler;
|
||||
sa->cosmo.sa_restorer = restorer;
|
||||
sa->cosmo.sa_mask.__bits[0] = mask[0] | (uint64_t)mask[1] << 32;
|
||||
sa->cosmo.sa_mask.__bits[1] = mask[2] | (uint64_t)mask[3] << 32;
|
||||
}
|
||||
|
||||
static int __sigaction(int sig, const struct sigaction *act,
|
||||
struct sigaction *oldact) {
|
||||
_Static_assert((sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)),
|
||||
"sigaction cosmo abi needs tuning");
|
||||
_Static_assert(
|
||||
(sizeof(struct sigaction) >= sizeof(struct sigaction_linux) &&
|
||||
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_in) &&
|
||||
sizeof(struct sigaction) >= sizeof(struct sigaction_xnu_out) &&
|
||||
sizeof(struct sigaction) >= sizeof(struct sigaction_freebsd) &&
|
||||
sizeof(struct sigaction) >= sizeof(struct sigaction_openbsd) &&
|
||||
sizeof(struct sigaction) >= sizeof(struct sigaction_netbsd)),
|
||||
"sigaction cosmo abi needs tuning");
|
||||
int64_t arg4, arg5;
|
||||
int rc, rva, oldrva;
|
||||
sigaction_f sigenter;
|
||||
struct sigaction *ap, copy;
|
||||
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
|
||||
if (!(0 < sig && sig < NSIG)) return einval();
|
||||
if (!(1 <= sig && sig <= _NSIG)) return einval();
|
||||
if (sig == SIGKILL || sig == SIGSTOP) return einval();
|
||||
if (IsAsan() && ((act && !__asan_is_valid(act, sizeof(*act))) ||
|
||||
(oldact && !__asan_is_valid(oldact, sizeof(*oldact))))) {
|
||||
|
@ -184,18 +181,23 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
if (act) {
|
||||
memcpy(©, act, sizeof(copy));
|
||||
ap = ©
|
||||
if (IsXnu()) {
|
||||
|
||||
if (IsLinux()) {
|
||||
if (!(ap->sa_flags & SA_RESTORER)) {
|
||||
ap->sa_flags |= SA_RESTORER;
|
||||
ap->sa_restorer = &__restore_rt;
|
||||
}
|
||||
if (IsWsl1()) {
|
||||
sigenter = __sigenter_wsl;
|
||||
} else {
|
||||
sigenter = ap->sa_sigaction;
|
||||
}
|
||||
} else if (IsXnu()) {
|
||||
ap->sa_restorer = (void *)&__sigenter_xnu;
|
||||
sigenter = __sigenter_xnu;
|
||||
// mitigate Rosetta signal handling strangeness
|
||||
// https://github.com/jart/cosmopolitan/issues/455
|
||||
ap->sa_flags |= SA_SIGINFO;
|
||||
} else if (IsLinux()) {
|
||||
if (!(ap->sa_flags & SA_RESTORER)) {
|
||||
ap->sa_flags |= SA_RESTORER;
|
||||
ap->sa_restorer = &__restore_rt;
|
||||
}
|
||||
sigenter = __sigenter_linux;
|
||||
} else if (IsNetbsd()) {
|
||||
sigenter = __sigenter_netbsd;
|
||||
} else if (IsFreebsd()) {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo-freebsd.internal.h"
|
||||
#include "libc/calls/struct/siginfo-meta.internal.h"
|
||||
|
@ -51,7 +50,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
|
|||
g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
|
||||
g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
|
||||
g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
|
||||
__repmovsb(&g.uc.uc_sigmask, &ctx->uc_sigmask,
|
||||
__repmovsb(&g.uc.uc_sigmask, ctx->uc_sigmask,
|
||||
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
|
||||
g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
|
||||
g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
|
||||
|
@ -82,7 +81,7 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
|
|||
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
|
||||
ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
|
||||
ctx->uc_flags = g.uc.uc_flags;
|
||||
__repmovsb(&ctx->uc_sigmask, &g.uc.uc_sigmask,
|
||||
__repmovsb(ctx->uc_sigmask, &g.uc.uc_sigmask,
|
||||
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
|
||||
ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi;
|
||||
ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi;
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
||||
privileged void __sigenter_linux(int sig, struct siginfo *info,
|
||||
ucontext_t *ctx) {
|
||||
privileged void __sigenter_wsl(int sig, struct siginfo *info, ucontext_t *ctx) {
|
||||
int i, rva, flags;
|
||||
rva = __sighandrvas[sig & (NSIG - 1)];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo-meta.internal.h"
|
||||
#include "libc/calls/struct/siginfo-netbsd.internal.h"
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo-meta.internal.h"
|
||||
#include "libc/calls/struct/siginfo-openbsd.internal.h"
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct sigset_freebsd {
|
||||
uint32_t sig[4];
|
||||
};
|
||||
|
||||
struct sigaction_freebsd {
|
||||
intptr_t sa_handler;
|
||||
uint32_t sa_flags;
|
||||
struct sigset_freebsd sa_mask;
|
||||
};
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_FREEBSD_H_ */
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct sigset_linux {
|
||||
uint32_t sig[2];
|
||||
};
|
||||
|
||||
struct sigaction_linux {
|
||||
intptr_t sa_handler;
|
||||
uint64_t sa_flags;
|
||||
void (*sa_restorer)(void);
|
||||
struct sigset_linux sa_mask;
|
||||
};
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_LINUX_H_ */
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sigset_netbsd {
|
||||
uint32_t sig[4];
|
||||
};
|
||||
|
||||
struct sigaction_netbsd {
|
||||
intptr_t sa_handler;
|
||||
struct sigset_netbsd sa_mask;
|
||||
uint32_t sa_flags;
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_NETBSD_H_ */
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct sigset_openbsd {
|
||||
uint32_t sig[1];
|
||||
};
|
||||
|
||||
struct sigaction_openbsd {
|
||||
intptr_t sa_handler;
|
||||
struct sigset_openbsd sa_mask;
|
||||
int32_t sa_flags;
|
||||
};
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_OPENBSD_H_ */
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
struct __darwin_ucontext;
|
||||
struct __darwin_siginfo;
|
||||
|
||||
struct sigset_xnu {
|
||||
uint32_t sig[1];
|
||||
};
|
||||
|
||||
struct sigaction_xnu_in {
|
||||
intptr_t sa_handler;
|
||||
void (*sa_restorer)(void *, int, int, const struct __darwin_siginfo *,
|
||||
const struct __darwin_ucontext *);
|
||||
struct sigset_xnu sa_mask;
|
||||
int32_t sa_flags;
|
||||
};
|
||||
|
||||
struct sigaction_xnu_out {
|
||||
intptr_t sa_handler;
|
||||
struct sigset_xnu sa_mask;
|
||||
int32_t sa_flags;
|
||||
};
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_XNU_H_ */
|
|
@ -20,7 +20,6 @@ struct sigaction { /* cosmo abi */
|
|||
uint64_t sa_flags;
|
||||
void (*sa_restorer)(void);
|
||||
struct sigset sa_mask;
|
||||
int64_t __pad;
|
||||
};
|
||||
|
||||
sighandler_t signal(int, sighandler_t);
|
||||
|
|
|
@ -1,10 +1,65 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGACTION_INTERNAL_H_
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sigaction_linux {
|
||||
void *sa_handler;
|
||||
uint64_t sa_flags;
|
||||
void *sa_restorer;
|
||||
uint32_t sa_mask[2];
|
||||
};
|
||||
|
||||
struct sigaction_freebsd {
|
||||
void *sa_handler;
|
||||
uint32_t sa_flags;
|
||||
uint32_t sa_mask[4];
|
||||
};
|
||||
|
||||
struct sigaction_openbsd {
|
||||
void *sa_handler;
|
||||
uint32_t sa_mask[1];
|
||||
uint32_t sa_flags;
|
||||
};
|
||||
|
||||
struct sigaction_netbsd {
|
||||
void *sa_handler;
|
||||
uint32_t sa_mask[4];
|
||||
uint32_t sa_flags;
|
||||
};
|
||||
|
||||
struct sigaction_xnu_in {
|
||||
void *sa_handler;
|
||||
void *sa_restorer;
|
||||
uint32_t sa_mask[1];
|
||||
uint32_t sa_flags;
|
||||
};
|
||||
|
||||
struct sigaction_xnu_out {
|
||||
void *sa_handler;
|
||||
uint32_t sa_mask[1];
|
||||
uint32_t sa_flags;
|
||||
};
|
||||
|
||||
union metasigaction {
|
||||
struct sigaction cosmo;
|
||||
struct sigaction_linux linux;
|
||||
struct sigaction_freebsd freebsd;
|
||||
struct sigaction_openbsd openbsd;
|
||||
struct sigaction_netbsd netbsd;
|
||||
struct sigaction_xnu_in xnu_in;
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
void __sigenter_xnu(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_wsl(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_netbsd(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_freebsd(int, struct siginfo *, void *) hidden;
|
||||
void __sigenter_openbsd(int, struct siginfo *, void *) hidden;
|
||||
|
||||
const char *DescribeSigaction(char[256], int, const struct sigaction *);
|
||||
#define DescribeSigaction(rc, sa) DescribeSigaction(alloca(256), rc, sa)
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SIGINFO_INTERNAL_H_
|
||||
#include "libc/calls/struct/sigaction-xnu.internal.h"
|
||||
#include "libc/calls/struct/siginfo-xnu.internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
|
|
@ -14,12 +14,13 @@ int sys_clock_gettime_nt(int, struct timespec *) hidden;
|
|||
int sys_clock_gettime_xnu(int, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_nt(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_xnu(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_openbsd(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_clock_nanosleep_xnu(int, int, const struct timespec *, struct timespec *) hidden;
|
||||
int sys_futimens(int, const struct timespec[2]) hidden;
|
||||
int sys_nanosleep(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_nanosleep_nt(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
|
||||
int sys_sem_timedwait(int64_t, const struct timespec *) hidden;
|
||||
int sys_utimensat(int, const char *, const struct timespec[2], int) hidden;
|
||||
int sys_utimensat_nt(int, const char *, const struct timespec[2], int) hidden;
|
||||
int sys_utimensat_xnu(int, const char *, const struct timespec[2], int) hidden;
|
||||
|
|
|
@ -17,6 +17,8 @@ int lutimes(const char *, const struct timeval[2]);
|
|||
int utimes(const char *, const struct timeval[2]);
|
||||
|
||||
int timeval_cmp(struct timeval, struct timeval) pureconst;
|
||||
struct timeval timeval_frommicros(int64_t) pureconst;
|
||||
struct timeval timeval_frommillis(int64_t) pureconst;
|
||||
struct timeval timeval_add(struct timeval, struct timeval) pureconst;
|
||||
struct timeval timeval_sub(struct timeval, struct timeval) pureconst;
|
||||
struct timeval timespec_totimeval(struct timespec) pureconst;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
@ -52,7 +51,7 @@ struct mcontext_freebsd {
|
|||
};
|
||||
|
||||
struct ucontext_freebsd {
|
||||
struct sigset_freebsd uc_sigmask;
|
||||
uint32_t uc_sigmask[4];
|
||||
struct mcontext_freebsd uc_mcontext;
|
||||
struct ucontext_freebsd *uc_link;
|
||||
struct stack_freebsd uc_stack;
|
||||
|
|
|
@ -83,6 +83,15 @@ i32 sys_pivot_root(const char *, const char *) hidden;
|
|||
i32 sys_pledge(const char *, const char *) hidden;
|
||||
i32 sys_posix_openpt(i32) hidden;
|
||||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||
i32 sys_sem_close(i64) hidden;
|
||||
i32 sys_sem_destroy(i64) hidden;
|
||||
i32 sys_sem_getvalue(i64, u32 *) hidden;
|
||||
i32 sys_sem_init(u32, i64 *) hidden;
|
||||
i32 sys_sem_open(const char *, int, u32, i64 *) hidden;
|
||||
i32 sys_sem_post(i64) hidden;
|
||||
i32 sys_sem_trywait(i64) hidden;
|
||||
i32 sys_sem_unlink(const char *) hidden;
|
||||
i32 sys_sem_wait(i64) hidden;
|
||||
i32 sys_setfsgid(i32) hidden;
|
||||
i32 sys_setfsuid(i32) hidden;
|
||||
i32 sys_setgid(i32) hidden;
|
||||
|
|
|
@ -22,8 +22,9 @@
|
|||
/**
|
||||
* Converts timespec to scalar.
|
||||
*
|
||||
* This function will detect overflow in which case `INT64_MAX` or
|
||||
* `INT64_MIN` may be returned. The `errno` variable isn't changed.
|
||||
. * This returns the absolute number of nanoseconds in a timespec. If
|
||||
* overflow happens, then `INT64_MAX` or `INT64_MIN` is returned. The
|
||||
* `errno` variable isn't changed.
|
||||
*
|
||||
* @return 64-bit integer holding nanoseconds since epoch
|
||||
*/
|
||||
|
|
29
libc/calls/timeval_frommicros.c
Normal file
29
libc/calls/timeval_frommicros.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2022 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/struct/timeval.h"
|
||||
|
||||
/**
|
||||
* Converts timeval interval from microseconds.
|
||||
*/
|
||||
struct timeval timeval_frommicros(int64_t x) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = x / 1000000;
|
||||
tv.tv_usec = x % 1000000;
|
||||
return tv;
|
||||
}
|
29
libc/calls/timeval_frommillis.c
Normal file
29
libc/calls/timeval_frommillis.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 2022 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/struct/timeval.h"
|
||||
|
||||
/**
|
||||
* Converts timeval interval from milliseconds.
|
||||
*/
|
||||
struct timeval timeval_frommillis(int64_t x) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = x / 1000;
|
||||
tv.tv_usec = x % 1000 * 1000;
|
||||
return tv;
|
||||
}
|
41
libc/calls/timeval_tomicros.c
Normal file
41
libc/calls/timeval_tomicros.c
Normal file
|
@ -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 2022 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/struct/timeval.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Converts timeval to scalar.
|
||||
*
|
||||
* This returns the absolute number of microseconds in a timeval. If
|
||||
* overflow happens, then `INT64_MAX` or `INT64_MIN` is returned. The
|
||||
* `errno` variable isn't changed.
|
||||
*
|
||||
* @return 64-bit integer holding microseconds since epoch
|
||||
*/
|
||||
int64_t timeval_tomicros(struct timeval x) {
|
||||
int64_t ns;
|
||||
if (!__builtin_mul_overflow(x.tv_sec, 1000000ul, &ns) &&
|
||||
!__builtin_add_overflow(ns, x.tv_usec, &ns)) {
|
||||
return ns;
|
||||
} else if (x.tv_sec < 0) {
|
||||
return INT64_MIN;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
}
|
||||
}
|
56
libc/calls/timeval_tomillis.c
Normal file
56
libc/calls/timeval_tomillis.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- 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 2022 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/struct/timeval.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Reduces `ts` from 1e-6 to 1e-3 granularity w/ ceil rounding.
|
||||
*
|
||||
* This function returns the absolute number of milliseconds in a
|
||||
* timeval. Ceiling rounding is used. For example, if `ts` is one
|
||||
* nanosecond, then one millisecond will be returned. Ceil rounding is
|
||||
* needed by many interfaces, e.g. setitimer(), because the zero
|
||||
* timestamp has a valial meaning.
|
||||
*
|
||||
* This function also detects overflow in which case `INT64_MAX` or
|
||||
* `INT64_MIN` may be returned. The `errno` variable isn't changed.
|
||||
*
|
||||
* @return 64-bit scalar milliseconds since epoch
|
||||
*/
|
||||
int64_t timeval_tomillis(struct timeval ts) {
|
||||
int64_t ms;
|
||||
// reduce precision from micros to millis
|
||||
if (ts.tv_usec <= 999000) {
|
||||
ts.tv_usec = (ts.tv_usec + 999) / 1000;
|
||||
} else {
|
||||
ts.tv_usec = 0;
|
||||
if (ts.tv_sec < INT64_MAX) {
|
||||
ts.tv_sec += 1;
|
||||
}
|
||||
}
|
||||
// convert to scalar result
|
||||
if (!__builtin_mul_overflow(ts.tv_sec, 1000ul, &ms) &&
|
||||
!__builtin_add_overflow(ms, ts.tv_usec, &ms)) {
|
||||
return ms;
|
||||
} else if (ts.tv_sec < 0) {
|
||||
return INT64_MIN;
|
||||
} else {
|
||||
return INT64_MAX;
|
||||
}
|
||||
}
|
|
@ -608,10 +608,10 @@ typedef struct {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define notpossible \
|
||||
do { \
|
||||
asm("ud2\n\tnop"); \
|
||||
unreachable; \
|
||||
#define notpossible \
|
||||
do { \
|
||||
asm("nop\n\tud2\n\tnop"); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
#define donothing \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
const char *(DescribeTimespec)(char buf[45], int rc,
|
||||
const struct timespec *ts) {
|
||||
|
@ -30,7 +31,11 @@ const char *(DescribeTimespec)(char buf[45], int rc,
|
|||
(IsAsan() && !__asan_is_valid(ts, sizeof(*ts)))) {
|
||||
ksnprintf(buf, 45, "%p", ts);
|
||||
} else {
|
||||
ksnprintf(buf, 45, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
|
||||
if (!memcmp(ts, ×pec_max, sizeof(*ts))) {
|
||||
strcpy(buf, "timespec_max");
|
||||
} else {
|
||||
ksnprintf(buf, 45, "{%ld, %ld}", ts->tv_sec, ts->tv_nsec);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
/**
|
||||
|
@ -36,9 +37,9 @@
|
|||
*/
|
||||
int gettid(void) {
|
||||
int tid;
|
||||
if (__tls_enabled && !__vforked) {
|
||||
tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_relaxed);
|
||||
if (tid > 0) {
|
||||
if (VERY_LIKELY(__tls_enabled && !__vforked)) {
|
||||
tid = atomic_load_explicit(&__get_tls()->tib_tid, memory_order_acquire);
|
||||
if (VERY_LIKELY(tid > 0)) {
|
||||
return tid;
|
||||
}
|
||||
}
|
||||
|
|
0
libc/intrin/intrin.h
Executable file
0
libc/intrin/intrin.h
Executable file
2
libc/sysv/calls/sys_sem_close.s
Normal file
2
libc/sysv/calls/sys_sem_close.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_close,0x0fafff190210dfff,globl
|
2
libc/sysv/calls/sys_sem_destroy.s
Normal file
2
libc/sysv/calls/sys_sem_destroy.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_destroy,0x0fffff198fffffff,globl
|
2
libc/sysv/calls/sys_sem_getvalue.s
Normal file
2
libc/sysv/calls/sys_sem_getvalue.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_getvalue,0x0fefff197fffffff,globl
|
2
libc/sysv/calls/sys_sem_init.s
Normal file
2
libc/sysv/calls/sys_sem_init.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_init,0x0f7fff194fffffff,globl
|
2
libc/sysv/calls/sys_sem_open.s
Normal file
2
libc/sysv/calls/sys_sem_open.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_open,0x0f8fff195210cfff,globl
|
2
libc/sysv/calls/sys_sem_post.s
Normal file
2
libc/sysv/calls/sys_sem_post.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_post,0x0fbfff1912111fff,globl
|
2
libc/sysv/calls/sys_sem_timedwait.s
Normal file
2
libc/sysv/calls/sys_sem_timedwait.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_timedwait,0x900fff9b9fffffff,globl
|
2
libc/sysv/calls/sys_sem_trywait.s
Normal file
2
libc/sysv/calls/sys_sem_trywait.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_trywait,0x0fdfff1932110fff,globl
|
2
libc/sysv/calls/sys_sem_unlink.s
Normal file
2
libc/sysv/calls/sys_sem_unlink.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_unlink,0x0f9fff196210efff,globl
|
2
libc/sysv/calls/sys_sem_wait.s
Normal file
2
libc/sysv/calls/sys_sem_wait.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_wait,0x8fcfff992290ffff,globl
|
2
libc/sysv/calls/sys_sem_wait_nocancel.s
Normal file
2
libc/sysv/calls/sys_sem_wait_nocancel.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_sem_wait_nocancel,0xfffffffff21a4fff,globl
|
|
@ -2094,44 +2094,44 @@ syscon nr __NR_ktrace 0xfff 0xfff 0x002d 0x002d 0x02d 0xfff
|
|||
# unilateral undocumented errnos
|
||||
#
|
||||
# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon junkerr ECHRNG 44 0 0 0 0 0
|
||||
syscon junkerr EL2NSYNC 45 0 0 0 0 0
|
||||
syscon junkerr EL3HLT 46 0 0 0 0 0
|
||||
syscon junkerr EL3RST 47 0 0 0 0 0
|
||||
syscon junkerr ELNRNG 48 0 0 0 0 0
|
||||
syscon junkerr EUNATCH 49 0 0 0 0 0
|
||||
syscon junkerr ENOCSI 50 0 0 0 0 0
|
||||
syscon junkerr EL2HLT 51 0 0 0 0 0
|
||||
syscon junkerr EBADE 52 0 0 0 0 0
|
||||
syscon junkerr EBADR 53 0 0 0 0 0
|
||||
syscon junkerr EXFULL 54 0 0 0 0 0
|
||||
syscon junkerr ENOANO 55 0 0 0 0 0
|
||||
syscon junkerr EBADRQC 56 0 0 0 0 0
|
||||
syscon junkerr EBADSLT 57 0 0 0 0 0
|
||||
syscon junkerr ENOPKG 65 0 0 0 0 0
|
||||
syscon junkerr EADV 68 0 0 0 0 0
|
||||
syscon junkerr ESRMNT 69 0 0 0 0 0
|
||||
syscon junkerr ECOMM 70 0 0 0 0 0
|
||||
syscon junkerr EDOTDOT 73 0 0 0 0 0
|
||||
syscon junkerr ENOTUNIQ 76 0 0 0 0 0
|
||||
syscon junkerr EREMCHG 78 0 0 0 0 0
|
||||
syscon junkerr ELIBACC 79 0 0 0 0 0
|
||||
syscon junkerr ELIBBAD 80 0 0 0 0 0
|
||||
syscon junkerr ELIBSCN 81 0 0 0 0 0
|
||||
syscon junkerr ELIBMAX 82 0 0 0 0 0
|
||||
syscon junkerr ELIBEXEC 83 0 0 0 0 0
|
||||
syscon junkerr ESTRPIPE 86 0 0 0 0 0
|
||||
syscon junkerr EUCLEAN 117 0 0 0 0 0
|
||||
syscon junkerr ENOTNAM 118 0 0 0 0 0
|
||||
syscon junkerr ENAVAIL 119 0 0 0 0 0
|
||||
syscon junkerr EISNAM 120 0 0 0 0 0
|
||||
syscon junkerr EREMOTEIO 121 0 0 0 0 0
|
||||
syscon junkerr ENOKEY 126 0 0 0 0 0
|
||||
syscon junkerr EKEYEXPIRED 127 0 0 0 0 0
|
||||
syscon junkerr EKEYREVOKED 128 0 0 0 0 0
|
||||
syscon junkerr EKEYREJECTED 129 0 0 0 0 0
|
||||
syscon junkerr ERFKILL 132 0 0 0 0 0
|
||||
syscon junkerr EHWPOISON 133 0 0 0 0 0
|
||||
syscon junkerr ECHRNG 44 -1 -1 -1 -1 -1
|
||||
syscon junkerr EL2NSYNC 45 -1 -1 -1 -1 -1
|
||||
syscon junkerr EL3HLT 46 -1 -1 -1 -1 -1
|
||||
syscon junkerr EL3RST 47 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELNRNG 48 -1 -1 -1 -1 -1
|
||||
syscon junkerr EUNATCH 49 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOCSI 50 -1 -1 -1 -1 -1
|
||||
syscon junkerr EL2HLT 51 -1 -1 -1 -1 -1
|
||||
syscon junkerr EBADE 52 -1 -1 -1 -1 -1
|
||||
syscon junkerr EBADR 53 -1 -1 -1 -1 -1
|
||||
syscon junkerr EXFULL 54 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOANO 55 -1 -1 -1 -1 -1
|
||||
syscon junkerr EBADRQC 56 -1 -1 -1 -1 -1
|
||||
syscon junkerr EBADSLT 57 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOPKG 65 -1 -1 -1 -1 -1
|
||||
syscon junkerr EADV 68 -1 -1 -1 -1 -1
|
||||
syscon junkerr ESRMNT 69 -1 -1 -1 -1 -1
|
||||
syscon junkerr ECOMM 70 -1 -1 -1 -1 -1
|
||||
syscon junkerr EDOTDOT 73 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOTUNIQ 76 -1 -1 -1 -1 -1
|
||||
syscon junkerr EREMCHG 78 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELIBACC 79 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELIBBAD 80 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELIBSCN 81 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELIBMAX 82 -1 -1 -1 -1 -1
|
||||
syscon junkerr ELIBEXEC 83 -1 -1 -1 -1 -1
|
||||
syscon junkerr ESTRPIPE 86 -1 -1 -1 -1 -1
|
||||
syscon junkerr EUCLEAN 117 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOTNAM 118 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENAVAIL 119 -1 -1 -1 -1 -1
|
||||
syscon junkerr EISNAM 120 -1 -1 -1 -1 -1
|
||||
syscon junkerr EREMOTEIO 121 -1 -1 -1 -1 -1
|
||||
syscon junkerr ENOKEY 126 -1 -1 -1 -1 -1
|
||||
syscon junkerr EKEYEXPIRED 127 -1 -1 -1 -1 -1
|
||||
syscon junkerr EKEYREVOKED 128 -1 -1 -1 -1 -1
|
||||
syscon junkerr EKEYREJECTED 129 -1 -1 -1 -1 -1
|
||||
syscon junkerr ERFKILL 132 -1 -1 -1 -1 -1
|
||||
syscon junkerr EHWPOISON 133 -1 -1 -1 -1 -1
|
||||
|
||||
# arpanet fork combating human-induced exhaustion of our ipv4 address space
|
||||
#
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EADV,68,0,0,0,0,0
|
||||
.syscon junkerr,EADV,68,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EBADE,52,0,0,0,0,0
|
||||
.syscon junkerr,EBADE,52,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EBADR,53,0,0,0,0,0
|
||||
.syscon junkerr,EBADR,53,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EBADRQC,56,0,0,0,0,0
|
||||
.syscon junkerr,EBADRQC,56,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EBADSLT,57,0,0,0,0,0
|
||||
.syscon junkerr,EBADSLT,57,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ECHRNG,44,0,0,0,0,0
|
||||
.syscon junkerr,ECHRNG,44,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ECOMM,70,0,0,0,0,0
|
||||
.syscon junkerr,ECOMM,70,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EDOTDOT,73,0,0,0,0,0
|
||||
.syscon junkerr,EDOTDOT,73,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EHWPOISON,133,0,0,0,0,0
|
||||
.syscon junkerr,EHWPOISON,133,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EISNAM,120,0,0,0,0,0
|
||||
.syscon junkerr,EISNAM,120,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EKEYEXPIRED,127,0,0,0,0,0
|
||||
.syscon junkerr,EKEYEXPIRED,127,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EKEYREJECTED,129,0,0,0,0,0
|
||||
.syscon junkerr,EKEYREJECTED,129,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EKEYREVOKED,128,0,0,0,0,0
|
||||
.syscon junkerr,EKEYREVOKED,128,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EL2HLT,51,0,0,0,0,0
|
||||
.syscon junkerr,EL2HLT,51,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EL2NSYNC,45,0,0,0,0,0
|
||||
.syscon junkerr,EL2NSYNC,45,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EL3HLT,46,0,0,0,0,0
|
||||
.syscon junkerr,EL3HLT,46,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EL3RST,47,0,0,0,0,0
|
||||
.syscon junkerr,EL3RST,47,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELIBACC,79,0,0,0,0,0
|
||||
.syscon junkerr,ELIBACC,79,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELIBBAD,80,0,0,0,0,0
|
||||
.syscon junkerr,ELIBBAD,80,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELIBEXEC,83,0,0,0,0,0
|
||||
.syscon junkerr,ELIBEXEC,83,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELIBMAX,82,0,0,0,0,0
|
||||
.syscon junkerr,ELIBMAX,82,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELIBSCN,81,0,0,0,0,0
|
||||
.syscon junkerr,ELIBSCN,81,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ELNRNG,48,0,0,0,0,0
|
||||
.syscon junkerr,ELNRNG,48,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENAVAIL,119,0,0,0,0,0
|
||||
.syscon junkerr,ENAVAIL,119,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOANO,55,0,0,0,0,0
|
||||
.syscon junkerr,ENOANO,55,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOCSI,50,0,0,0,0,0
|
||||
.syscon junkerr,ENOCSI,50,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOKEY,126,0,0,0,0,0
|
||||
.syscon junkerr,ENOKEY,126,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOPKG,65,0,0,0,0,0
|
||||
.syscon junkerr,ENOPKG,65,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOTNAM,118,0,0,0,0,0
|
||||
.syscon junkerr,ENOTNAM,118,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ENOTUNIQ,76,0,0,0,0,0
|
||||
.syscon junkerr,ENOTUNIQ,76,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EREMCHG,78,0,0,0,0,0
|
||||
.syscon junkerr,EREMCHG,78,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EREMOTEIO,121,0,0,0,0,0
|
||||
.syscon junkerr,EREMOTEIO,121,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ERFKILL,132,0,0,0,0,0
|
||||
.syscon junkerr,ERFKILL,132,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ESRMNT,69,0,0,0,0,0
|
||||
.syscon junkerr,ESRMNT,69,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,ESTRPIPE,86,0,0,0,0,0
|
||||
.syscon junkerr,ESTRPIPE,86,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EUCLEAN,117,0,0,0,0,0
|
||||
.syscon junkerr,EUCLEAN,117,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EUNATCH,49,0,0,0,0,0
|
||||
.syscon junkerr,EUNATCH,49,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||
.syscon junkerr,EXFULL,54,0,0,0,0,0
|
||||
.syscon junkerr,EXFULL,54,-1,-1,-1,-1,-1
|
||||
|
|
|
@ -428,6 +428,18 @@ scall sys_issetugid 0xfff0fd0fd2147fff globl hidden
|
|||
scall sys_minherit 0x1110fa0fa20fafff globl # no wrapper
|
||||
scall sys_pathconf 0x0bf0bf0bf20bffff globl # no wrapper
|
||||
scall sys_sysctl 0x0ca0ca0ca20cafff globl # no wrapper
|
||||
#──────────────────XNU & FREEBSD & NETBSD────────────────────
|
||||
scall sys_sem_init 0x0f7fff194fffffff globl
|
||||
scall sys_sem_destroy 0x0fffff198fffffff globl
|
||||
scall sys_sem_open 0x0f8fff195210cfff globl
|
||||
scall sys_sem_close 0x0fafff190210dfff globl
|
||||
scall sys_sem_unlink 0x0f9fff196210efff globl
|
||||
scall sys_sem_post 0x0fbfff1912111fff globl
|
||||
scall sys_sem_wait 0x8fcfff992290ffff globl
|
||||
scall sys_sem_trywait 0x0fdfff1932110fff globl
|
||||
scall sys_sem_timedwait 0x900fff9b9fffffff globl
|
||||
scall sys_sem_wait_nocancel 0xfffffffff21a4fff globl # no wrapper
|
||||
scall sys_sem_getvalue 0x0fefff197fffffff globl
|
||||
#───────────────────────XNU & FREEBSD────────────────────────
|
||||
scall sys_ntp_adjtime 0x0b0fff0b0220ffff globl # no wrapper
|
||||
scall sys_ntp_gettime 0x1c0fff0f82210fff globl # no wrapper
|
||||
|
@ -597,13 +609,6 @@ scall sys_bsdthread_register 0xfffffffff216efff globl hidden
|
|||
#scall renameatx_np 0xfffffffff21e8fff globl
|
||||
#scall searchfs 0xfffffffff20e1fff globl
|
||||
#scall select_nocancel 0xfffffffff2197fff globl
|
||||
#scall sem_close 0xfffffffff210dfff globl
|
||||
#scall sem_open 0xfffffffff210cfff globl
|
||||
#scall sem_post 0xfffffffff2111fff globl
|
||||
#scall sem_trywait 0xfffffffff2110fff globl
|
||||
#scall sem_unlink 0xfffffffff210efff globl
|
||||
#scall sem_wait 0xfffffffff210ffff globl
|
||||
#scall sem_wait_nocancel 0xfffffffff21a4fff globl
|
||||
#scall sendmsg_nocancel 0xfffffffff2192fff globl
|
||||
#scall sendmsg_x 0xfffffffff21e1fff globl
|
||||
#scall sendto_nocancel 0xfffffffff219dfff globl
|
||||
|
@ -711,16 +716,6 @@ scall getpagesize_freebsd 0xffffff040fffffff globl hidden
|
|||
#scall kmq_timedreceive 0xffffff1cbfffffff globl
|
||||
#scall kmq_timedsend 0xffffff1ccfffffff globl
|
||||
#scall kmq_unlink 0xffffff1cefffffff globl
|
||||
#scall ksem_close 0xffffff190fffffff globl
|
||||
#scall ksem_destroy 0xffffff198fffffff globl
|
||||
#scall ksem_getvalue 0xffffff197fffffff globl
|
||||
#scall ksem_init 0xffffff194fffffff globl
|
||||
#scall ksem_open 0xffffff195fffffff globl
|
||||
#scall ksem_post 0xffffff191fffffff globl
|
||||
#scall ksem_timedwait 0xffffff1b9fffffff globl
|
||||
#scall ksem_trywait 0xffffff193fffffff globl
|
||||
#scall ksem_unlink 0xffffff196fffffff globl
|
||||
#scall ksem_wait 0xffffff192fffffff globl
|
||||
#scall lchflags 0x130fff187fffffff globl
|
||||
#scall lchmod 0x112fff112fffffff globl
|
||||
#scall lgetfh 0xffffff0a0fffffff globl
|
||||
|
|
|
@ -51,10 +51,10 @@ int _pthread_cancel_sys(void) {
|
|||
return ecanceled();
|
||||
}
|
||||
|
||||
static void OnSigCancel(int sig, siginfo_t *si, void *ctx) {
|
||||
static void OnSigThr(int sig, siginfo_t *si, void *ctx) {
|
||||
ucontext_t *uc = ctx;
|
||||
struct CosmoTib *tib = __get_tls();
|
||||
struct PosixThread *pt = (struct PosixThread *)tib->tib_pthread;
|
||||
struct CosmoTib *t = __get_tls();
|
||||
struct PosixThread *pt = (struct PosixThread *)t->tib_pthread;
|
||||
if (pt && !(pt->flags & PT_NOCANCEL) &&
|
||||
atomic_load_explicit(&pt->cancelled, memory_order_acquire)) {
|
||||
sigaddset(&uc->uc_sigmask, sig);
|
||||
|
@ -64,15 +64,14 @@ static void OnSigCancel(int sig, siginfo_t *si, void *ctx) {
|
|||
} else if (pt->flags & PT_ASYNC) {
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
} else {
|
||||
__tkill(atomic_load_explicit(&tib->tib_tid, memory_order_relaxed), sig,
|
||||
tib);
|
||||
__tkill(atomic_load_explicit(&t->tib_tid, memory_order_relaxed), sig, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ListenForSigCancel(void) {
|
||||
static void ListenForSigThr(void) {
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = OnSigCancel;
|
||||
sa.sa_sigaction = OnSigThr;
|
||||
sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
|
||||
memset(&sa.sa_mask, -1, sizeof(sa.sa_mask));
|
||||
_npassert(!sigaction(SIGTHR, &sa, 0));
|
||||
|
@ -262,7 +261,7 @@ errno_t pthread_cancel(pthread_t thread) {
|
|||
int e, rc, tid;
|
||||
static bool once;
|
||||
struct PosixThread *pt;
|
||||
if (!once) ListenForSigCancel(), once = true;
|
||||
if (!once) ListenForSigThr(), once = true;
|
||||
pt = (struct PosixThread *)thread;
|
||||
switch (atomic_load_explicit(&pt->status, memory_order_acquire)) {
|
||||
case kPosixThreadZombie:
|
||||
|
|
|
@ -35,13 +35,9 @@
|
|||
* @param value is initial count of semaphore
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `value` exceeds `SEM_VALUE_MAX`
|
||||
* @raise EPERM on OpenBSD if `pshared` is true
|
||||
*/
|
||||
int sem_init(sem_t *sem, int pshared, unsigned value) {
|
||||
if (value > SEM_VALUE_MAX) return einval();
|
||||
// OpenBSD MAP_ANONYMOUS|MAP_SHARED memory is kind of busted.
|
||||
// The OpenBSD implementation of sem_init() also EPERMs here.
|
||||
if (IsOpenbsd() && pshared) return eperm();
|
||||
sem->sem_magic = SEM_MAGIC_UNNAMED;
|
||||
atomic_store_explicit(&sem->sem_value, value, memory_order_relaxed);
|
||||
sem->sem_pshared = !!pshared;
|
||||
|
|
|
@ -209,7 +209,7 @@ sem_t *sem_open(const char *name, int oflag, ...) {
|
|||
sem = SEM_FAILED;
|
||||
} else if (~oflag & O_EXCL) {
|
||||
sem = s->sem;
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acquire);
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel);
|
||||
++s->refs;
|
||||
} else {
|
||||
eexist();
|
||||
|
@ -218,7 +218,7 @@ sem_t *sem_open(const char *name, int oflag, ...) {
|
|||
} else if ((s = calloc(1, sizeof(struct Semaphore)))) {
|
||||
if ((s->path = strdup(path))) {
|
||||
if ((sem = sem_open_impl(path, oflag, mode, value)) != SEM_FAILED) {
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel);
|
||||
s->next = g_semaphores.list;
|
||||
s->sem = sem;
|
||||
s->refs = 1;
|
||||
|
@ -260,7 +260,7 @@ int sem_close(sem_t *sem) {
|
|||
sem_open_init();
|
||||
sem_open_lock();
|
||||
_npassert((s = sem_open_get(sem, &p)));
|
||||
prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_release);
|
||||
prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_acq_rel);
|
||||
_npassert(s->refs > 0);
|
||||
if ((unmap = !--s->refs)) {
|
||||
_npassert(prefs > 0);
|
||||
|
|
|
@ -33,26 +33,6 @@ static void sem_delay(int n) {
|
|||
for (i = 0; i != 1 << n; i++) donothing;
|
||||
}
|
||||
|
||||
// TODO(jart): This should be abstracted by polyfill.
|
||||
static struct timespec *sem_timeout(struct timespec *memory,
|
||||
const struct timespec *abstime) {
|
||||
struct timespec now;
|
||||
if (!abstime) {
|
||||
return 0;
|
||||
} else if (FUTEX_TIMEOUT_IS_ABSOLUTE) {
|
||||
*memory = *abstime;
|
||||
return memory;
|
||||
} else {
|
||||
now = timespec_real();
|
||||
if (timespec_cmp(now, *abstime) > 0) {
|
||||
*memory = (struct timespec){0};
|
||||
} else {
|
||||
*memory = timespec_sub(*abstime, now);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
static void sem_timedwait_cleanup(void *arg) {
|
||||
sem_t *sem = arg;
|
||||
_unassert(atomic_fetch_add_explicit(&sem->sem_waiters, -1,
|
||||
|
@ -95,8 +75,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) {
|
|||
|
||||
do {
|
||||
if (!(v = atomic_load_explicit(&sem->sem_value, memory_order_relaxed))) {
|
||||
rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared,
|
||||
sem_timeout(&ts, abstime));
|
||||
rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared, abstime);
|
||||
if (rc == -EINTR || rc == -ECANCELED) {
|
||||
errno = -rc;
|
||||
rc = -1;
|
||||
|
|
|
@ -209,7 +209,6 @@ bool IsAcceptablePath(const char *, size_t);
|
|||
bool IsAcceptableHost(const char *, size_t);
|
||||
bool IsAcceptablePort(const char *, size_t);
|
||||
bool IsReasonablePath(const char *, size_t);
|
||||
int64_t ParseIp(const char *, size_t);
|
||||
int ParseForwarded(const char *, size_t, uint32_t *, uint16_t *);
|
||||
bool IsMimeType(const char *, size_t, const char *);
|
||||
ssize_t Unchunk(struct HttpUnchunker *, char *, size_t, size_t *);
|
||||
|
|
|
@ -25,6 +25,13 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct Cidr {
|
||||
int64_t addr;
|
||||
int cidr;
|
||||
};
|
||||
|
||||
int64_t ParseIp(const char *, size_t);
|
||||
struct Cidr ParseCidr(const char *, size_t);
|
||||
bool IsDodIp(uint32_t);
|
||||
bool IsArinIp(uint32_t);
|
||||
bool IsRipeIp(uint32_t);
|
||||
|
|
67
net/http/parsecidr.c
Normal file
67
net/http/parsecidr.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- 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 2022 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/ip.h"
|
||||
|
||||
/**
|
||||
* Parse IPv4 network address.
|
||||
*
|
||||
* For example, a router address might be `10.10.10.1/24` in which case
|
||||
* the IP address word `0x0a0a0a01` would be returned, whose CIDR would
|
||||
* be 24. That means your IP address is on a network with 24 bits which
|
||||
* converts to a netmask `0xffffff00` by using `1u << (32 - res.cidr)`.
|
||||
* You may specify the IP address portion as an integer. As an example,
|
||||
* the value `168430081/1` would be the same as `10.10.10.1/1`
|
||||
*
|
||||
* @param n if -1 implies strlen
|
||||
* @return ip is uint32 IPv4 address, or -1 on failure
|
||||
* @return cidr is number of bits in network, on interval [1,32]; it
|
||||
* defaults to 32; if the return ip is -1 then cidr is undefined
|
||||
*/
|
||||
struct Cidr ParseCidr(const char *s, size_t n) {
|
||||
size_t i;
|
||||
const char *p;
|
||||
struct Cidr c;
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
if ((p = strchr(s, '/'))) {
|
||||
if ((c.addr = ParseIp(s, (i = p - s))) != -1) {
|
||||
c.cidr = 0;
|
||||
for (++i; i < n; ++i) {
|
||||
if (isdigit(s[i])) {
|
||||
c.cidr *= 10;
|
||||
c.cidr += s[i] - '0';
|
||||
if (c.cidr > 32) {
|
||||
c.cidr = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
c.cidr = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c.cidr <= 0) {
|
||||
c.addr = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.addr = ParseIp(s, n);
|
||||
c.cidr = 32;
|
||||
}
|
||||
return c;
|
||||
}
|
|
@ -17,27 +17,33 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Parse IPv4 address.
|
||||
* Parse IPv4 host address.
|
||||
*
|
||||
* @param n if -1 implies strlen
|
||||
* @return -1 on failure, otherwise 32-bit host-order unsigned integer
|
||||
* @see ParseCidr()
|
||||
*/
|
||||
int64_t ParseIp(const char *s, size_t n) {
|
||||
int c, j;
|
||||
size_t i;
|
||||
uint32_t x;
|
||||
int b, c, j;
|
||||
unsigned b, x;
|
||||
bool dotted = false;
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
if (!n) return -1;
|
||||
for (b = x = j = i = 0; i < n; ++i) {
|
||||
c = s[i] & 255;
|
||||
if (isdigit(c)) {
|
||||
b *= 10;
|
||||
b += c - '0';
|
||||
if (__builtin_mul_overflow(b, 10, &b) || //
|
||||
__builtin_add_overflow(b, c - '0', &b) || //
|
||||
(b > 255 && dotted)) {
|
||||
return -1;
|
||||
}
|
||||
} else if (c == '.') {
|
||||
if (b > 255) return -1;
|
||||
dotted = true;
|
||||
x <<= 8;
|
||||
x |= b;
|
||||
b = 0;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/ip.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
|
|
|
@ -228,11 +228,13 @@ TEST(uc_sigmask, signalHandlerCanChangeSignalMaskOfTrappedThread) {
|
|||
struct sigaction oldsa;
|
||||
struct sigaction sa = {.sa_sigaction = OnSigMask, .sa_flags = SA_SIGINFO};
|
||||
sigemptyset(&want);
|
||||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &want, 0));
|
||||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, &want, &got));
|
||||
ASSERT_FALSE(sigismember(&got, SIGUSR1));
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &sa, &oldsa));
|
||||
ASSERT_SYS(0, 0, raise(SIGUSR1));
|
||||
ASSERT_TRUE(gotusr1);
|
||||
ASSERT_SYS(0, 0, sigprocmask(SIG_SETMASK, 0, &got));
|
||||
ASSERT_TRUE(sigismember(&got, SIGUSR1));
|
||||
sigaddset(&want, SIGUSR1);
|
||||
ASSERT_STREQ(DescribeSigset(0, &want), DescribeSigset(0, &got));
|
||||
ASSERT_SYS(0, 0, sigaction(SIGUSR1, &oldsa, 0));
|
||||
|
|
|
@ -34,6 +34,7 @@ TEST_LIBC_INTRIN_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_THREAD \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_TINYMATH \
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/gc.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -39,6 +41,23 @@ FILE *f;
|
|||
char buf[32];
|
||||
char testlib_enable_tmp_setup_teardown;
|
||||
|
||||
void CheckForFdLeaks(void) {
|
||||
int rc, i, l = 0, e = errno;
|
||||
for (i = 3; i < 16; ++i) {
|
||||
rc = fcntl(i, F_GETFL);
|
||||
if (rc == -1) {
|
||||
ASSERT_EQ(EBADF, errno);
|
||||
errno = e;
|
||||
} else {
|
||||
kprintf("file descriptor %d leaked!\n", i);
|
||||
++l;
|
||||
}
|
||||
}
|
||||
if (l) {
|
||||
__die();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(popen, command) {
|
||||
char foo[6];
|
||||
testlib_extract("/zip/echo.com", "echo.com", 0755);
|
||||
|
@ -46,6 +65,7 @@ TEST(popen, command) {
|
|||
ASSERT_NE(NULL, fgets(foo, sizeof(foo), f));
|
||||
ASSERT_STREQ("hello", foo);
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
TEST(popen, semicolon) {
|
||||
|
@ -53,6 +73,7 @@ TEST(popen, semicolon) {
|
|||
ASSERT_STREQ("hello\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_STREQ("there\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
TEST(popen, singleQuotes) {
|
||||
|
@ -61,6 +82,7 @@ TEST(popen, singleQuotes) {
|
|||
ASSERT_STREQ("hello $there\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_STREQ("yo\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
TEST(popen, doubleQuotes) {
|
||||
|
@ -68,6 +90,7 @@ TEST(popen, doubleQuotes) {
|
|||
ASSERT_NE(NULL, (f = popen("echo -l \"$hello there\"", "r")));
|
||||
ASSERT_STREQ("a b c there\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
TEST(popen, quoteless) {
|
||||
|
@ -77,6 +100,7 @@ TEST(popen, quoteless) {
|
|||
ASSERT_STREQ("aa b c\n", fgets(buf, sizeof(buf), f)); // mixed feelings
|
||||
ASSERT_STREQ("yo\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
TEST(popen, pipe) {
|
||||
|
@ -84,6 +108,7 @@ TEST(popen, pipe) {
|
|||
ASSERT_NE(NULL, (f = popen("echo hello | toupper", "r")));
|
||||
ASSERT_STREQ("HELLO\n", fgets(buf, sizeof(buf), f));
|
||||
ASSERT_EQ(0, pclose(f));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
sig_atomic_t gotsig;
|
||||
|
@ -102,6 +127,7 @@ TEST(popen, complicated) {
|
|||
ASSERT_EQ(0, pclose(f));
|
||||
ASSERT_EQ(1, gotsig);
|
||||
signal(SIGUSR1, SIG_DFL);
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
||||
void *Worker(void *arg) {
|
||||
|
@ -129,10 +155,10 @@ void *Worker(void *arg) {
|
|||
}
|
||||
|
||||
TEST(popen, torture) {
|
||||
int i, n = 8;
|
||||
int i, n = 4;
|
||||
pthread_t *t = _gc(malloc(sizeof(pthread_t) * n));
|
||||
testlib_extract("/zip/echo.com", "echo.com", 0755);
|
||||
for (i = 0; i < n; ++i) ASSERT_EQ(0, pthread_create(t + i, 0, Worker, 0));
|
||||
for (i = 0; i < n; ++i) ASSERT_EQ(0, pthread_join(t[i], 0));
|
||||
for (i = 3; i < 16; ++i) ASSERT_SYS(EBADF, -1, fcntl(i, F_GETFL));
|
||||
CheckForFdLeaks();
|
||||
}
|
||||
|
|
|
@ -170,12 +170,6 @@ TEST(sem_timedwait, threads) {
|
|||
TEST(sem_timedwait, processes) {
|
||||
int i, r, rc, n = 4, pshared = 1;
|
||||
sem_t *sm = _mapshared(FRAMESIZE), *s[2] = {sm, sm + 1};
|
||||
if (IsOpenbsd()) {
|
||||
// TODO(jart): why?
|
||||
ASSERT_SYS(EPERM, -1, sem_init(s[0], pshared, 0));
|
||||
ASSERT_SYS(0, 0, munmap(sm, FRAMESIZE));
|
||||
return;
|
||||
}
|
||||
ASSERT_SYS(0, 0, sem_init(s[0], pshared, 0));
|
||||
ASSERT_SYS(0, 0, sem_init(s[1], pshared, 0));
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
|
59
test/net/http/parsecidr_test.c
Normal file
59
test/net/http/parsecidr_test.c
Normal file
|
@ -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 2022 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/ip.h"
|
||||
|
||||
TEST(ParseCidr, test) {
|
||||
struct Cidr in;
|
||||
in = ParseCidr("10.10.10.1/24", -1);
|
||||
EXPECT_EQ(0x0a0a0a01, in.addr);
|
||||
EXPECT_EQ(24, in.cidr);
|
||||
in = ParseCidr("168430081/1", -1);
|
||||
EXPECT_EQ(0x0a0a0a01, in.addr);
|
||||
EXPECT_EQ(1, in.cidr);
|
||||
}
|
||||
|
||||
TEST(ParseCidr, noCidr_defaultsTo32) {
|
||||
struct Cidr in;
|
||||
in = ParseCidr("10.10.10.255", -1);
|
||||
EXPECT_EQ(0x0a0a0aff, in.addr);
|
||||
EXPECT_EQ(32, in.cidr);
|
||||
}
|
||||
|
||||
TEST(ParseCidr, badIp_returnsNeg1) {
|
||||
struct Cidr in;
|
||||
in = ParseCidr("10.10.10.a", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
in = ParseCidr("10.10.10.256", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
in = ParseCidr("10.10.10.256/24", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
}
|
||||
|
||||
TEST(ParseCidr, badCidr_returnsNeg1) {
|
||||
struct Cidr in;
|
||||
in = ParseCidr("10.10.10.1/", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
in = ParseCidr("10.10.10.1/a", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
in = ParseCidr("10.10.10.1/0", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
in = ParseCidr("10.10.10.1/33", -1);
|
||||
EXPECT_EQ(-1, in.addr);
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/ip.h"
|
||||
|
||||
TEST(ParseIp, test) {
|
||||
EXPECT_EQ(-1, ParseIp("", -1));
|
||||
|
@ -30,6 +30,8 @@ TEST(ParseIp, test) {
|
|||
EXPECT_EQ(0x00000000, ParseIp("...", -1)); /* meh */
|
||||
EXPECT_EQ(0x80000304, ParseIp("128.0.3.4", -1));
|
||||
EXPECT_EQ(0x80000304, ParseIp("128..3.4", -1));
|
||||
EXPECT_EQ(-1, ParseIp("4294967296", -1));
|
||||
EXPECT_EQ(-1, ParseIp("255.255.255.256", -1));
|
||||
EXPECT_EQ(-1, ParseIp("256.255.255.255", -1));
|
||||
EXPECT_EQ(-1, ParseIp("hello", -1));
|
||||
EXPECT_EQ(-1, ParseIp("hello\177", -1));
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/ip.h"
|
||||
#include "net/http/url.h"
|
||||
|
||||
TEST(ParseUrl, testEmpty) {
|
||||
|
|
8
third_party/lua/lunix.c
vendored
8
third_party/lua/lunix.c
vendored
|
@ -2847,14 +2847,6 @@ static int LuaUnixMemoryWait(lua_State *L) {
|
|||
} else {
|
||||
ts.tv_sec = luaL_checkinteger(L, 4);
|
||||
ts.tv_nsec = luaL_optinteger(L, 5, 0);
|
||||
if (!FUTEX_TIMEOUT_IS_ABSOLUTE) {
|
||||
now = timespec_real();
|
||||
if (timespec_cmp(now, ts) > 0) {
|
||||
ts = (struct timespec){0};
|
||||
} else {
|
||||
ts = timespec_sub(ts, now);
|
||||
}
|
||||
}
|
||||
deadline = &ts;
|
||||
}
|
||||
BEGIN_CANCELLATION_POINT;
|
||||
|
|
3
third_party/mbedtls/x509_crt.c
vendored
3
third_party/mbedtls/x509_crt.c
vendored
|
@ -15,17 +15,18 @@
|
|||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/ip.h"
|
||||
#include "third_party/mbedtls/common.h"
|
||||
#include "third_party/mbedtls/error.h"
|
||||
#include "third_party/mbedtls/oid.h"
|
||||
|
|
50
third_party/nsync/futex.c
vendored
50
third_party/nsync/futex.c
vendored
|
@ -28,7 +28,6 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
|
@ -56,8 +55,8 @@ int sys_futex_cp (atomic_int *, int, int, const struct timespec *, int *, int);
|
|||
|
||||
static int FUTEX_WAIT_;
|
||||
static int FUTEX_PRIVATE_FLAG_;
|
||||
static bool FUTEX_IS_SUPPORTED;
|
||||
bool FUTEX_TIMEOUT_IS_ABSOLUTE;
|
||||
static bool futex_is_supported;
|
||||
static bool futex_timeout_is_relative;
|
||||
|
||||
__attribute__((__constructor__)) static void nsync_futex_init_ (void) {
|
||||
atomic_int x;
|
||||
|
@ -65,20 +64,17 @@ __attribute__((__constructor__)) static void nsync_futex_init_ (void) {
|
|||
FUTEX_WAIT_ = FUTEX_WAIT;
|
||||
|
||||
if (IsWindows ()) {
|
||||
FUTEX_IS_SUPPORTED = true;
|
||||
FUTEX_TIMEOUT_IS_ABSOLUTE = true;
|
||||
futex_is_supported = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsFreebsd ()) {
|
||||
FUTEX_IS_SUPPORTED = true;
|
||||
FUTEX_TIMEOUT_IS_ABSOLUTE = true;
|
||||
futex_is_supported = true;
|
||||
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(FUTEX_IS_SUPPORTED = IsLinux () || IsOpenbsd ())) {
|
||||
FUTEX_TIMEOUT_IS_ABSOLUTE = true;
|
||||
if (!(futex_is_supported = IsLinux () || IsOpenbsd ())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -98,20 +94,20 @@ __attribute__((__constructor__)) static void nsync_futex_init_ (void) {
|
|||
1, 0, 0, FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
|
||||
FUTEX_WAIT_ = FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME;
|
||||
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
FUTEX_TIMEOUT_IS_ABSOLUTE = true;
|
||||
} else if (!IsTiny () && IsLinux () &&
|
||||
_futex (&x, FUTEX_WAIT_BITSET, 1, 0, 0,
|
||||
FUTEX_BITSET_MATCH_ANY) == -EAGAIN) {
|
||||
FUTEX_WAIT_ = FUTEX_WAIT_BITSET;
|
||||
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
FUTEX_TIMEOUT_IS_ABSOLUTE = true;
|
||||
} else if (IsOpenbsd () ||
|
||||
(!IsTiny () && IsLinux () &&
|
||||
!_futex_wake (&x, FUTEX_WAKE_PRIVATE, 1))) {
|
||||
FUTEX_WAIT_ = FUTEX_WAIT;
|
||||
FUTEX_PRIVATE_FLAG_ = FUTEX_PRIVATE_FLAG;
|
||||
futex_timeout_is_relative = true;
|
||||
} else {
|
||||
FUTEX_WAIT_ = FUTEX_WAIT;
|
||||
futex_timeout_is_relative = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,10 +119,8 @@ static int nsync_futex_polyfill_ (atomic_int *w, int expect, struct timespec *ti
|
|||
ts = timespec_real ();
|
||||
if (!timeout) {
|
||||
deadline = timespec_max;
|
||||
} else if (FUTEX_TIMEOUT_IS_ABSOLUTE) {
|
||||
deadline = *timeout;
|
||||
} else {
|
||||
deadline = timespec_add (ts, *timeout);
|
||||
deadline = *timeout;
|
||||
}
|
||||
|
||||
nanos = 100;
|
||||
|
@ -186,9 +180,29 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare, stru
|
|||
return rc;
|
||||
}
|
||||
|
||||
int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *timeout) {
|
||||
static struct timespec *nsync_futex_timeout_ (struct timespec *memory,
|
||||
const struct timespec *abstime) {
|
||||
struct timespec now;
|
||||
if (!abstime) {
|
||||
return 0;
|
||||
} else if (!futex_timeout_is_relative) {
|
||||
*memory = *abstime;
|
||||
return memory;
|
||||
} else {
|
||||
now = timespec_real ();
|
||||
if (timespec_cmp (now, *abstime) > 0) {
|
||||
*memory = (struct timespec){0};
|
||||
} else {
|
||||
*memory = timespec_sub (*abstime, now);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *abstime) {
|
||||
int e, rc, op, fop;
|
||||
struct PosixThread *pt = 0;
|
||||
struct timespec tsmem, *timeout;
|
||||
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
return -EAGAIN;
|
||||
|
@ -199,12 +213,14 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, struct timespec *
|
|||
op |= FUTEX_PRIVATE_FLAG_;
|
||||
}
|
||||
|
||||
timeout = nsync_futex_timeout_ (&tsmem, abstime);
|
||||
|
||||
LOCKTRACE ("futex(%t [%d], %s, %#x, %s) → ...",
|
||||
w, atomic_load_explicit (w, memory_order_relaxed),
|
||||
DescribeFutexOp (op), expect,
|
||||
DescribeTimespec (0, timeout));
|
||||
|
||||
if (FUTEX_IS_SUPPORTED) {
|
||||
if (futex_is_supported) {
|
||||
e = errno;
|
||||
if (IsWindows ()) {
|
||||
// Windows 8 futexes don't support multiple processes :(
|
||||
|
@ -270,7 +286,7 @@ int nsync_futex_wake_ (atomic_int *w, int count, char pshare) {
|
|||
op |= FUTEX_PRIVATE_FLAG_;
|
||||
}
|
||||
|
||||
if (FUTEX_IS_SUPPORTED) {
|
||||
if (futex_is_supported) {
|
||||
if (IsWindows ()) {
|
||||
if (pshare) {
|
||||
goto Polyfill;
|
||||
|
|
2
third_party/nsync/futex.internal.h
vendored
2
third_party/nsync/futex.internal.h
vendored
|
@ -5,8 +5,6 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern bool FUTEX_TIMEOUT_IS_ABSOLUTE;
|
||||
|
||||
int nsync_futex_wake_(_Atomic(int) *, int, char);
|
||||
int nsync_futex_wait_(_Atomic(int) *, int, char, struct timespec *);
|
||||
|
||||
|
|
119
third_party/nsync/mu_semaphore.c
vendored
119
third_party/nsync/mu_semaphore.c
vendored
|
@ -15,16 +15,9 @@
|
|||
│ See the License for the specific language governing permissions and │
|
||||
│ limitations under the License. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/thread.h"
|
||||
#include "third_party/nsync/atomic.h"
|
||||
#include "third_party/nsync/atomic.internal.h"
|
||||
#include "third_party/nsync/futex.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "third_party/nsync/mu_semaphore.h"
|
||||
#include "third_party/nsync/mu_semaphore.internal.h"
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
*NSYNC (Apache 2.0)\\n\
|
||||
|
@ -32,108 +25,40 @@ Copyright 2016 Google, Inc.\\n\
|
|||
https://github.com/google/nsync\"");
|
||||
// clang-format off
|
||||
|
||||
#define ASSERT(x) _npassert(x)
|
||||
|
||||
/* Check that atomic operations on nsync_atomic_uint32_ can be applied to int. */
|
||||
static const int assert_int_size = 1 /
|
||||
(sizeof (assert_int_size) == sizeof (uint32_t) &&
|
||||
sizeof (nsync_atomic_uint32_) == sizeof (uint32_t));
|
||||
|
||||
struct futex {
|
||||
int i; /* lo half=count; hi half=waiter count */
|
||||
};
|
||||
|
||||
static nsync_semaphore *sem_big_enough_for_futex = (nsync_semaphore *) (uintptr_t)(1 /
|
||||
(sizeof (struct futex) <= sizeof (*sem_big_enough_for_futex)));
|
||||
|
||||
/* Initialize *s; the initial value is 0. */
|
||||
void nsync_mu_semaphore_init (nsync_semaphore *s) {
|
||||
struct futex *f = (struct futex *) s;
|
||||
f->i = 0;
|
||||
if (IsNetbsd ()) {
|
||||
return nsync_mu_semaphore_init_sem (s);
|
||||
} else {
|
||||
return nsync_mu_semaphore_init_futex (s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until the count of *s exceeds 0, and decrement it. */
|
||||
errno_t nsync_mu_semaphore_p (nsync_semaphore *s) {
|
||||
struct futex *f = (struct futex *) s;
|
||||
int i;
|
||||
int result = 0;
|
||||
do {
|
||||
i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i);
|
||||
if (i == 0) {
|
||||
int futex_result = nsync_futex_wait_ (
|
||||
(atomic_int *)&f->i, i, PTHREAD_PROCESS_PRIVATE, NULL);
|
||||
ASSERT (futex_result == 0 ||
|
||||
futex_result == -EINTR ||
|
||||
futex_result == -EAGAIN ||
|
||||
futex_result == -ECANCELED ||
|
||||
futex_result == -EWOULDBLOCK);
|
||||
if (futex_result == -ECANCELED) {
|
||||
result = ECANCELED;
|
||||
}
|
||||
}
|
||||
} while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i-1)));
|
||||
return result;
|
||||
if (IsNetbsd ()) {
|
||||
return nsync_mu_semaphore_p_sem (s);
|
||||
} else {
|
||||
return nsync_mu_semaphore_p_futex (s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until one of:
|
||||
the count of *s is non-zero, in which case decrement *s and return 0;
|
||||
or abs_deadline expires, in which case return ETIMEDOUT. */
|
||||
errno_t nsync_mu_semaphore_p_with_deadline (nsync_semaphore *s, nsync_time abs_deadline) {
|
||||
struct futex *f = (struct futex *)s;
|
||||
int i;
|
||||
int result = 0;
|
||||
do {
|
||||
i = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i);
|
||||
if (i == 0) {
|
||||
int futex_result;
|
||||
struct timespec ts_buf;
|
||||
const struct timespec *ts = NULL;
|
||||
if (nsync_time_cmp (abs_deadline, nsync_time_no_deadline) != 0) {
|
||||
memset (&ts_buf, 0, sizeof (ts_buf));
|
||||
if (FUTEX_TIMEOUT_IS_ABSOLUTE) {
|
||||
ts_buf.tv_sec = NSYNC_TIME_SEC (abs_deadline);
|
||||
ts_buf.tv_nsec = NSYNC_TIME_NSEC (abs_deadline);
|
||||
} else {
|
||||
nsync_time now;
|
||||
now = nsync_time_now ();
|
||||
if (nsync_time_cmp (now, abs_deadline) > 0) {
|
||||
ts_buf.tv_sec = 0;
|
||||
ts_buf.tv_nsec = 0;
|
||||
} else {
|
||||
nsync_time rel_deadline;
|
||||
rel_deadline = nsync_time_sub (abs_deadline, now);
|
||||
ts_buf.tv_sec = NSYNC_TIME_SEC (rel_deadline);
|
||||
ts_buf.tv_nsec = NSYNC_TIME_NSEC (rel_deadline);
|
||||
}
|
||||
}
|
||||
ts = &ts_buf;
|
||||
}
|
||||
futex_result = nsync_futex_wait_ ((atomic_int *)&f->i, i, PTHREAD_PROCESS_PRIVATE, ts);
|
||||
ASSERT (futex_result == 0 ||
|
||||
futex_result == -EINTR ||
|
||||
futex_result == -EAGAIN ||
|
||||
futex_result == -ECANCELED ||
|
||||
futex_result == -ETIMEDOUT ||
|
||||
futex_result == -EWOULDBLOCK);
|
||||
/* Some systems don't wait as long as they are told. */
|
||||
if (futex_result == -ETIMEDOUT &&
|
||||
nsync_time_cmp (abs_deadline, nsync_time_now ()) <= 0) {
|
||||
result = ETIMEDOUT;
|
||||
}
|
||||
if (futex_result == -ECANCELED) {
|
||||
result = ECANCELED;
|
||||
}
|
||||
}
|
||||
} while (result == 0 && (i == 0 || !ATM_CAS_ACQ ((nsync_atomic_uint32_ *) &f->i, i, i - 1)));
|
||||
return (result);
|
||||
if (IsNetbsd ()) {
|
||||
return nsync_mu_semaphore_p_with_deadline_sem (s, abs_deadline);
|
||||
} else {
|
||||
return nsync_mu_semaphore_p_with_deadline_futex (s, abs_deadline);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that the count of *s is at least 1. */
|
||||
void nsync_mu_semaphore_v (nsync_semaphore *s) {
|
||||
struct futex *f = (struct futex *) s;
|
||||
uint32_t old_value;
|
||||
do {
|
||||
old_value = ATM_LOAD ((nsync_atomic_uint32_ *) &f->i);
|
||||
} while (!ATM_CAS_REL ((nsync_atomic_uint32_ *) &f->i, old_value, old_value+1));
|
||||
ASSERT (nsync_futex_wake_ ((atomic_int *)&f->i, 1, PTHREAD_PROCESS_PRIVATE) >= 0);
|
||||
if (IsNetbsd ()) {
|
||||
return nsync_mu_semaphore_v_sem (s);
|
||||
} else {
|
||||
return nsync_mu_semaphore_v_futex (s);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue