mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 16:30:29 +00:00
Merge branch 'master' of https://github.com/jart/cosmopolitan into FEATURE/ioctl_SIOCGIFCONF
This commit is contained in:
commit
80b14ee951
514 changed files with 12336 additions and 18250 deletions
2
Makefile
2
Makefile
|
@ -137,7 +137,6 @@ include libc/testlib/testlib.mk
|
|||
include tool/viz/lib/vizlib.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include examples/examples.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
|
@ -145,6 +144,7 @@ include third_party/chibicc/test/test.mk
|
|||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include examples/examples.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/hash/hash.mk
|
||||
|
|
76
ape/ape.S
76
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
|
||||
|
||||
/* ▄▄▒▀▀▀▀▒▒▄
|
||||
█████▓▓▄░░░░ ▒▒▄░
|
||||
█████▓▓▄░░░░ ▒▒▄
|
||||
▐█▓▓█▓▄█████▓░ ▀▒▄
|
||||
▓█▓▓▓▓▓▓▓▓▓█▓ ░▀▒░
|
||||
▀▀▓█▓▓▓▓▓▓█▓ ░▀▒▄▄▒▄▄▄▒▒▒▀▀▀▀▀▀▀▀▀▀▀▀▀▀▒▒▄▒
|
||||
|
|
Binary file not shown.
Binary file not shown.
111
examples/curl.c
111
examples/curl.c
|
@ -25,7 +25,8 @@
|
|||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/uri.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/url.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Downloads HTTP URL to stdout.
|
||||
|
@ -35,50 +36,92 @@
|
|||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int sock;
|
||||
ssize_t rc;
|
||||
unsigned long need;
|
||||
struct UriSlice path;
|
||||
size_t i, got, toto, msglen;
|
||||
char buf[1500], host[256], port[7];
|
||||
const char *url, *msg, *pathstr, *crlfcrlf, *contentlength;
|
||||
struct UriSlice us[16];
|
||||
struct Uri u = {.segs.p = us, .segs.n = ARRAYLEN(us)};
|
||||
|
||||
/*
|
||||
* Get argument.
|
||||
*/
|
||||
const char *urlarg;
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "USAGE: %s URL\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
urlarg = argv[1];
|
||||
|
||||
/*
|
||||
* Parse URL.
|
||||
*/
|
||||
struct Url url;
|
||||
char *host, *port;
|
||||
_gc(ParseUrl(urlarg, -1, &url));
|
||||
_gc(url.params.p);
|
||||
if (url.scheme.n &&
|
||||
!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) {
|
||||
fprintf(stderr, "ERROR: NOT AN HTTP URL: %s\n", urlarg);
|
||||
exit(1);
|
||||
}
|
||||
host = firstnonnull(_gc(strndup(url.host.p, url.host.n)), "127.0.0.1");
|
||||
port = url.port.n ? _gc(strndup(url.port.p, url.port.n)) : "80";
|
||||
port = _gc(xasprintf("%hu", atoi(port)));
|
||||
if (!IsAcceptableHost(host, -1)) {
|
||||
fprintf(stderr, "ERROR: INVALID HOST: %s\n", urlarg);
|
||||
exit(1);
|
||||
}
|
||||
url.fragment.p = 0, url.fragment.n = 0;
|
||||
url.scheme.p = 0, url.scheme.n = 0;
|
||||
url.user.p = 0, url.user.n = 0;
|
||||
url.pass.p = 0, url.pass.n = 0;
|
||||
url.host.p = 0, url.host.n = 0;
|
||||
url.port.p = 0, url.port.n = 0;
|
||||
if (!url.path.n || url.path.p[0] != '/') {
|
||||
char *p = _gc(xmalloc(1 + url.path.n));
|
||||
mempcpy(mempcpy(p, "/", 1), url.path.p, url.path.n);
|
||||
url.path.p = p;
|
||||
++url.path.n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create HTTP message.
|
||||
*/
|
||||
const char *msg;
|
||||
msg = _gc(xasprintf("GET %s HTTP/1.1\r\n"
|
||||
"Host: %s:%s\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"Accept: text/plain; */*\r\n"
|
||||
"Accept-Encoding: identity\r\n"
|
||||
"User-Agent: github.com/jart/cosmopolitan\r\n"
|
||||
"\r\n",
|
||||
_gc(EncodeUrl(&url, 0)), host, port));
|
||||
|
||||
/*
|
||||
* Perform DNS lookup.
|
||||
*/
|
||||
struct addrinfo *addr, *addrs;
|
||||
struct addrinfo hints = {.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
.ai_flags = AI_NUMERICSERV};
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "USAGE: %s URL\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
url = argv[1];
|
||||
CHECK_NE(-1, uriparse(&u, url, strlen(url)), "BAD URL: %`'s", url);
|
||||
CHECK_EQ(kUriSchemeHttp, urischeme(u.scheme, url));
|
||||
urislice2cstr(host, sizeof(host), u.host, url, "127.0.0.1");
|
||||
urislice2cstr(port, sizeof(port), u.port, url, "80");
|
||||
path = uripath(&u);
|
||||
pathstr = path.n ? url + path.i : "/";
|
||||
msg = _gc(xstrcat("GET ", pathstr,
|
||||
" HTTP/1.1\r\n"
|
||||
"Host: ",
|
||||
host,
|
||||
"\r\n"
|
||||
"Connection: close\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"Accept: text/plain; */*\r\n"
|
||||
"Accept-Encoding: identity\r\n"
|
||||
"User-Agent: github.com/jart/cosmopolitan\r\n"
|
||||
"\r\n"));
|
||||
msglen = strlen(msg);
|
||||
CHECK_EQ(EAI_SUCCESS, getaddrinfo(host, port, &hints, &addrs));
|
||||
for (addr = addrs; addr; addr = addr->ai_next) {
|
||||
|
||||
/*
|
||||
* Send HTTP Message.
|
||||
*/
|
||||
int sock;
|
||||
CHECK_NE(-1, (sock = socket(addr->ai_family, addr->ai_socktype,
|
||||
addr->ai_protocol)));
|
||||
CHECK_NE(-1, connect(sock, addr->ai_addr, addr->ai_addrlen));
|
||||
CHECK_EQ(msglen, write(sock, msg, msglen));
|
||||
CHECK_EQ(strlen(msg), write(sock, msg, strlen(msg)));
|
||||
shutdown(sock, SHUT_WR);
|
||||
|
||||
/*
|
||||
* Handle response.
|
||||
*/
|
||||
ssize_t rc;
|
||||
char buf[1500];
|
||||
size_t got, toto;
|
||||
unsigned long need;
|
||||
const char *msg, *crlfcrlf;
|
||||
buf[0] = '\0';
|
||||
CHECK_NE(-1, (rc = read(sock, buf, sizeof(buf))));
|
||||
got = rc;
|
||||
|
|
|
@ -74,6 +74,7 @@ EXAMPLES_DIRECTDEPS = \
|
|||
THIRD_PARTY_STB \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_ZLIB \
|
||||
TOOL_BUILD_LIB \
|
||||
TOOL_VIZ_LIB
|
||||
|
||||
EXAMPLES_DEPS := \
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main() {
|
||||
printf("%s \n", "hello world");
|
||||
printf("%`'s\n", "hello\1\2world→→");
|
||||
return errno;
|
||||
}
|
||||
|
|
112
examples/nc.c
Normal file
112
examples/nc.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
#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/calls/calls.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
/**
|
||||
* @fileoverview netcat clone
|
||||
*
|
||||
* Implemented because BusyBox's netcat doesn't detect remote close and
|
||||
* lingers in the CLOSE_WAIT wait possibly due to file descriptor leaks
|
||||
*
|
||||
* Once upon time we called this command "Telnet"
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ssize_t rc;
|
||||
size_t i, got;
|
||||
char buf[1500];
|
||||
int err, toto, sock;
|
||||
struct linger linger = {true, 1};
|
||||
struct sockaddr_in addr = {AF_INET};
|
||||
struct pollfd fds[2] = {{-1, POLLIN}, {-1, POLLIN}};
|
||||
|
||||
if (argc != 3) exit(1);
|
||||
inet_pton(AF_INET, argv[1], &addr.sin_addr);
|
||||
addr.sin_port = htons(atoi(argv[2]));
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == -1) {
|
||||
perror("setsockopt(SO_LINGER)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (connect(sock, &addr, sizeof(addr)) == -1) {
|
||||
perror("connect");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fds[0].fd = 0;
|
||||
fds[1].fd = sock;
|
||||
for (;;) {
|
||||
fds[0].revents = 0;
|
||||
fds[1].revents = 0;
|
||||
if (poll(fds, ARRAYLEN(fds), -1) == -1) {
|
||||
perror("poll");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fds[0].revents & (POLLIN | POLLERR | POLLHUP)) {
|
||||
if ((rc = read(0, buf, 1400)) == -1) {
|
||||
perror("read(stdin)");
|
||||
exit(1);
|
||||
}
|
||||
if (!(got = rc)) {
|
||||
shutdown(sock, SHUT_WR);
|
||||
fds[0].fd = -1;
|
||||
}
|
||||
for (i = 0; i < got; i += rc) {
|
||||
if ((rc = write(sock, buf + i, got - i)) == -1) {
|
||||
perror("write(sock)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fds[1].revents & (POLLIN | POLLERR | POLLHUP)) {
|
||||
if ((rc = read(sock, buf, 1500)) == -1) {
|
||||
perror("read(sock)");
|
||||
exit(1);
|
||||
}
|
||||
if (!(got = rc)) {
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < got; i += rc) {
|
||||
if ((rc = write(1, buf + i, got - i)) == -1) {
|
||||
perror("write(stdout)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (close(sock) == -1) {
|
||||
perror("close");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
175
examples/panels.c
Normal file
175
examples/panels.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
#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/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "tool/build/lib/panel.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Paneling Demo.
|
||||
*
|
||||
* This is useful for creating terminal user interfaces. We take the
|
||||
* simplest approach possible. The main thing we abstract is like,
|
||||
* truncating the lines that overflow within a panel. In order to do
|
||||
* that, we abstract the ANSI parsing and the implementation is able to
|
||||
* tell how many cells wide each UNICODE character is.
|
||||
*
|
||||
* There are smarter ways for Cosmopolitan to do this. For example, it'd
|
||||
* be great to have automatic flex boxes. It'd also be nice to be able
|
||||
* to use dynamic programming for low bandwidth display updates, like
|
||||
* Emacs does, but that's less of an issue these days and can actually
|
||||
* make things slower, since for heavy workloads like printing videos,
|
||||
* having ANSI codes bouncing around the display actually goes slower.
|
||||
*
|
||||
* Beyond basic paneling, a message box widget is also provided, which
|
||||
* makes it easier to do modal dialogs.
|
||||
*/
|
||||
|
||||
struct Panels {
|
||||
union {
|
||||
struct {
|
||||
struct Panel left;
|
||||
struct Panel right;
|
||||
};
|
||||
struct Panel p[2];
|
||||
};
|
||||
} pan;
|
||||
|
||||
long tyn;
|
||||
long txn;
|
||||
char key[8];
|
||||
bool shutdown;
|
||||
bool invalidated;
|
||||
struct termios oldterm;
|
||||
|
||||
void OnShutdown(int sig) {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
void OnInvalidate(int sig) {
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
void GetTtySize(void) {
|
||||
struct winsize wsize;
|
||||
wsize.ws_row = tyn;
|
||||
wsize.ws_col = txn;
|
||||
getttysize(1, &wsize);
|
||||
tyn = wsize.ws_row;
|
||||
txn = wsize.ws_col;
|
||||
}
|
||||
|
||||
int Write(const char *s) {
|
||||
return write(1, s, strlen(s));
|
||||
}
|
||||
|
||||
void Setup(void) {
|
||||
CHECK_NE(-1, ioctl(1, TCGETS, &oldterm));
|
||||
}
|
||||
|
||||
void Enter(void) {
|
||||
struct termios term;
|
||||
memcpy(&term, &oldterm, sizeof(term));
|
||||
term.c_cc[VMIN] = 1;
|
||||
term.c_cc[VTIME] = 1;
|
||||
term.c_iflag &= ~(INPCK | ISTRIP | PARMRK | INLCR | IGNCR | ICRNL | IXON);
|
||||
term.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHONL);
|
||||
term.c_cflag &= ~(CSIZE | PARENB);
|
||||
term.c_cflag |= CS8;
|
||||
term.c_iflag |= IUTF8;
|
||||
CHECK_NE(-1, ioctl(1, TCSETS, &term));
|
||||
Write("\e[?25l");
|
||||
}
|
||||
|
||||
void Leave(void) {
|
||||
Write(gc(xasprintf("\e[?25h\e[%d;%dH\e[S\r\n", tyn, txn)));
|
||||
ioctl(1, TCSETS, &oldterm);
|
||||
}
|
||||
|
||||
void Clear(void) {
|
||||
long i, j;
|
||||
for (i = 0; i < ARRAYLEN(pan.p); ++i) {
|
||||
for (j = 0; j < pan.p[i].n; ++j) {
|
||||
free(pan.p[i].lines[j].p);
|
||||
}
|
||||
free(pan.p[i].lines);
|
||||
pan.p[i].lines = 0;
|
||||
pan.p[i].n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Layout(void) {
|
||||
long i, j;
|
||||
i = txn >> 1;
|
||||
pan.left.top = 0;
|
||||
pan.left.left = 0;
|
||||
pan.left.bottom = tyn;
|
||||
pan.left.right = i;
|
||||
pan.right.top = 0;
|
||||
pan.right.left = i + 1;
|
||||
pan.right.bottom = tyn;
|
||||
pan.right.right = txn;
|
||||
pan.left.n = pan.left.bottom - pan.left.top;
|
||||
pan.left.lines = xcalloc(pan.left.n, sizeof(*pan.left.lines));
|
||||
pan.right.n = pan.right.bottom - pan.right.top;
|
||||
pan.right.lines = xcalloc(pan.right.n, sizeof(*pan.right.lines));
|
||||
}
|
||||
|
||||
void Append(struct Panel *p, int i, const char *s) {
|
||||
if (i >= p->n) return;
|
||||
AppendStr(p->lines + i, s);
|
||||
}
|
||||
|
||||
void Draw(void) {
|
||||
Append(&pan.left, 0, gc(xasprintf("you typed %`'s", key)));
|
||||
Append(&pan.left, ((tyn + 1) >> 1) + 0, "hello left 1 𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷");
|
||||
Append(&pan.left, ((tyn + 1) >> 1) + 1, "hello left 2 (╯°□°)╯");
|
||||
Append(&pan.right, ((tyn + 1) >> 1) + 0, "hello right 1");
|
||||
Append(&pan.right, ((tyn + 1) >> 1) + 1, "hello right 2");
|
||||
PrintPanels(1, ARRAYLEN(pan.p), pan.p, tyn, txn);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sigaction sa[2] = {{.sa_handler = OnShutdown},
|
||||
{.sa_handler = OnInvalidate}};
|
||||
showcrashreports();
|
||||
Setup();
|
||||
Enter();
|
||||
GetTtySize();
|
||||
sigaction(SIGINT, &sa[0], 0);
|
||||
sigaction(SIGCONT, &sa[1], 0);
|
||||
sigaction(SIGWINCH, &sa[1], 0);
|
||||
atexit(Leave);
|
||||
do {
|
||||
Clear();
|
||||
Layout();
|
||||
Draw();
|
||||
if (invalidated) {
|
||||
Enter();
|
||||
GetTtySize();
|
||||
invalidated = false;
|
||||
} else {
|
||||
readansi(0, key, sizeof(key));
|
||||
}
|
||||
} while (!shutdown);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
198
libc/bits/bits.h
198
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 ─╬─│┼
|
||||
|
|
|
@ -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"
|
||||
|
@ -29,7 +30,7 @@
|
|||
#define SIG_DFL ((void *)0)
|
||||
#define SIG_IGN ((void *)1)
|
||||
|
||||
#define MAP_FAILED ((void *)__SIZE_MAX__)
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_SET_FS 0x1002
|
||||
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -39,22 +39,24 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
memset(st, 0, sizeof(*st));
|
||||
switch (filetype) {
|
||||
case kNtFileTypeChar:
|
||||
st->st_mode = S_IFCHR | 0600;
|
||||
st->st_mode = S_IFCHR | 0644;
|
||||
break;
|
||||
case kNtFileTypePipe:
|
||||
st->st_mode = S_IFIFO | 0600;
|
||||
st->st_mode = S_IFIFO | 0644;
|
||||
break;
|
||||
case kNtFileTypeDisk:
|
||||
if (GetFileInformationByHandle(handle, &wst)) {
|
||||
st->st_mode =
|
||||
(S_IRUSR | S_IXUSR |
|
||||
(!(wst.dwFileAttributes & kNtFileAttributeReadonly) ? S_IWUSR
|
||||
: 0) |
|
||||
((wst.dwFileAttributes & kNtFileAttributeNormal) ? S_IFREG : 0) |
|
||||
((wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) ? S_IFLNK
|
||||
: 0) |
|
||||
((wst.dwFileAttributes & kNtFileAttributeDirectory) ? S_IFDIR
|
||||
: 0));
|
||||
st->st_mode = 0555;
|
||||
if (!(wst.dwFileAttributes & kNtFileAttributeReadonly)) {
|
||||
st->st_mode |= 0200;
|
||||
}
|
||||
if (wst.dwFileAttributes & kNtFileAttributeDirectory) {
|
||||
st->st_mode |= S_IFDIR;
|
||||
} else if (wst.dwFileAttributes & kNtFileFlagOpenReparsePoint) {
|
||||
st->st_mode |= S_IFLNK;
|
||||
} else {
|
||||
st->st_mode |= S_IFREG;
|
||||
}
|
||||
st->st_atim = FileTimeToTimeSpec(wst.ftLastAccessFileTime);
|
||||
st->st_mtim = FileTimeToTimeSpec(wst.ftLastWriteFileTime);
|
||||
st->st_ctim = FileTimeToTimeSpec(wst.ftCreationFileTime);
|
||||
|
|
|
@ -16,18 +16,20 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "net/http/http.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
unsigned ParseHttpVersion(const char *p, size_t n) {
|
||||
unsigned x;
|
||||
if (!n) return 9;
|
||||
if (n >= 8 && READ32LE(p) == ('H' | 'T' << 8 | 'T' << 16 | 'P' << 24)) {
|
||||
if (READ32LE(p + 4) == ('/' | '1' << 8 | '.' << 16 | '1' << 24)) {
|
||||
return 101;
|
||||
} else if (READ32LE(p + 4) == ('/' | '1' << 8 | '.' << 16 | '0' << 24)) {
|
||||
return 100;
|
||||
}
|
||||
/**
|
||||
* 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 -1;
|
||||
return rc;
|
||||
}
|
|
@ -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,8 @@ 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;
|
||||
ssize_t WritevUninterruptible(int, struct iovec *, int);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » windows nt » veneers ─╬─│┼
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -56,7 +56,7 @@ static long double MeasureNanosPerCycle(void) {
|
|||
return avg;
|
||||
}
|
||||
|
||||
static void InitTime(void) {
|
||||
void RefreshTime(void) {
|
||||
struct Now now;
|
||||
now.cpn = MeasureNanosPerCycle();
|
||||
now.r0 = dtime(CLOCK_REALTIME);
|
||||
|
@ -66,21 +66,17 @@ static void InitTime(void) {
|
|||
}
|
||||
|
||||
long double ConvertTicksToNanos(uint64_t ticks) {
|
||||
if (!g_now.once) InitTime();
|
||||
if (!g_now.once) RefreshTime();
|
||||
return ticks * g_now.cpn; /* pico scale */
|
||||
}
|
||||
|
||||
static long double ConvertTicksToSeconds(uint64_t ticks) {
|
||||
return 1 / 1e9 * ConvertTicksToNanos(ticks);
|
||||
}
|
||||
|
||||
long double nowl_sys(void) {
|
||||
return dtime(CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
long double nowl_art(void) {
|
||||
uint64_t ticks;
|
||||
if (!g_now.once) InitTime();
|
||||
if (!g_now.once) RefreshTime();
|
||||
ticks = unsignedsubtract(rdtsc(), g_now.k0);
|
||||
return g_now.r0 + ConvertTicksToSeconds(ticks);
|
||||
return g_now.r0 + (1 / 1e9L * (ticks * g_now.cpn));
|
||||
}
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 { \
|
||||
|
|
59
libc/calls/sigqueue.c
Normal file
59
libc/calls/sigqueue.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 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);
|
||||
}
|
||||
}
|
|
@ -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) */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,43 +22,55 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
struct VdprintfState {
|
||||
int n;
|
||||
int fd;
|
||||
unsigned char buf[1024];
|
||||
int n, t, fd;
|
||||
char b[1024];
|
||||
};
|
||||
|
||||
static int vdprintf_flush(struct VdprintfState *df, int n) {
|
||||
int i, rc;
|
||||
for (i = 0; i < n; i += rc) {
|
||||
if ((rc = write(df->fd, df->buf + i, n - i)) == -1) {
|
||||
return -1;
|
||||
static int vdprintf_putc(const char *s, struct VdprintfState *t, size_t n) {
|
||||
struct iovec iov[2];
|
||||
if (n) {
|
||||
if (t->n + n < sizeof(t->b)) {
|
||||
memcpy(t->b + t->n, s, n);
|
||||
t->n += n;
|
||||
} else {
|
||||
iov[0].iov_base = t->b;
|
||||
iov[0].iov_len = t->n;
|
||||
iov[1].iov_base = s;
|
||||
iov[1].iov_len = n;
|
||||
if (WritevUninterruptible(t->fd, iov, 2) == -1) {
|
||||
return -1;
|
||||
}
|
||||
t->t += t->n;
|
||||
t->n = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vdprintf_putc(int c, struct VdprintfState *df) {
|
||||
df->buf[df->n++ & (ARRAYLEN(df->buf) - 1)] = c & 0xff;
|
||||
if ((df->n & (ARRAYLEN(df->buf) - 1))) {
|
||||
return 0;
|
||||
} else {
|
||||
return vdprintf_flush(df, ARRAYLEN(df->buf));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats string directly to system i/o device.
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int(vdprintf)(int fd, const char *fmt, va_list va) {
|
||||
struct VdprintfState df;
|
||||
df.n = 0;
|
||||
df.fd = fd;
|
||||
if (__fmt(vdprintf_putc, &df, fmt, va) == -1) return -1;
|
||||
if (vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) == -1) return -1;
|
||||
return df.n;
|
||||
struct iovec iov[1];
|
||||
struct VdprintfState t;
|
||||
t.n = 0;
|
||||
t.t = 0;
|
||||
t.fd = fd;
|
||||
if (__fmt(vdprintf_putc, &t, fmt, va) == -1) return -1;
|
||||
if (t.n) {
|
||||
iov[0].iov_base = t.b;
|
||||
iov[0].iov_len = t.n;
|
||||
if (WritevUninterruptible(t.fd, iov, 1) == -1) {
|
||||
return -1;
|
||||
}
|
||||
t.t += t.n;
|
||||
}
|
||||
return t.t;
|
||||
}
|
||||
|
|
31
libc/calls/wait4-sysv.c
Normal file
31
libc/calls/wait4-sysv.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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__
|
||||
|
|
45
libc/calls/writevuninterruptible.c
Normal file
45
libc/calls/writevuninterruptible.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- 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/internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
||||
ssize_t WritevUninterruptible(int fd, struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
size_t wrote;
|
||||
do {
|
||||
if ((rc = writev(fd, iov, iovlen)) != -1) {
|
||||
wrote = rc;
|
||||
do {
|
||||
if (wrote >= iov->iov_len) {
|
||||
wrote -= iov->iov_len;
|
||||
++iov;
|
||||
--iovlen;
|
||||
} else {
|
||||
iov->iov_base = (char *)iov->iov_base + wrote;
|
||||
iov->iov_len -= wrote;
|
||||
wrote = 0;
|
||||
}
|
||||
} while (wrote);
|
||||
} else if (errno != EINTR) {
|
||||
return -1;
|
||||
}
|
||||
} while (iovlen);
|
||||
return 0;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
|
@ -31,11 +32,12 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
#define PUT(C) \
|
||||
do { \
|
||||
if (out(C, arg) == -1) { \
|
||||
return -1; \
|
||||
} \
|
||||
#define PUT(C) \
|
||||
do { \
|
||||
char Buf[1] = {C}; \
|
||||
if (out(Buf, arg, 1) == -1) { \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static const char kSpecialFloats[2][2][4] = {{"INF", "inf"}, {"NAN", "nan"}};
|
||||
|
@ -121,14 +123,18 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
uint32_t u[2];
|
||||
uint64_t q;
|
||||
} pun;
|
||||
long ld;
|
||||
void *p;
|
||||
unsigned u;
|
||||
char ibuf[21];
|
||||
bool longdouble;
|
||||
long double ldbl;
|
||||
unsigned long lu;
|
||||
wchar_t charbuf[1];
|
||||
const char *alphabet;
|
||||
int (*out)(long, void *);
|
||||
int (*out)(const char *, void *, size_t);
|
||||
unsigned char signbit, log2base;
|
||||
int c, d, k, w, i1, ui, bw, bex;
|
||||
int c, d, k, w, n, i1, ui, bw, bex;
|
||||
char *s, *q, *se, qchar, special[8];
|
||||
int sgn, alt, sign, prec, prec1, flags, width, decpt, lasterr;
|
||||
|
||||
|
@ -136,18 +142,64 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
|
|||
out = fn ? fn : (void *)missingno;
|
||||
|
||||
while (*format) {
|
||||
/* %[flags][width][.prec][length] */
|
||||
if (*format != '%') {
|
||||
/* no */
|
||||
PUT(*format);
|
||||
format++;
|
||||
for (n = 1; format[n]; ++n) {
|
||||
if (format[n] == '%') break;
|
||||
}
|
||||
if (out(format, arg, n) == -1) return -1;
|
||||
format += n;
|
||||
continue;
|
||||
} else {
|
||||
/* yes, evaluate it */
|
||||
format++;
|
||||
}
|
||||
|
||||
/* evaluate flags */
|
||||
if (!IsTiny()) {
|
||||
if (format[1] == 's') { /* FAST PATH: PLAIN STRING */
|
||||
s = va_arg(va, char *);
|
||||
if (!s) s = "(null)";
|
||||
if (out(s, arg, strlen(s)) == -1) return -1;
|
||||
format += 2;
|
||||
continue;
|
||||
} else if (format[1] == 'd') { /* FAST PATH: PLAIN INTEGER */
|
||||
d = va_arg(va, int);
|
||||
if (out(ibuf, arg, int64toarray_radix10(d, ibuf)) == -1) return -1;
|
||||
format += 2;
|
||||
continue;
|
||||
} else if (format[1] == 'u') { /* FAST PATH: PLAIN UNSIGNED */
|
||||
u = va_arg(va, unsigned);
|
||||
if (out(ibuf, arg, uint64toarray_radix10(u, ibuf)) == -1) return -1;
|
||||
format += 2;
|
||||
continue;
|
||||
} else if (format[1] == 'x') { /* FAST PATH: PLAIN HEX */
|
||||
u = va_arg(va, unsigned);
|
||||
if (out(ibuf, arg, uint64toarray_radix16(u, ibuf)) == -1) return -1;
|
||||
format += 2;
|
||||
continue;
|
||||
} else if (format[1] == 'l' && format[2] == 'x') {
|
||||
lu = va_arg(va, unsigned long); /* FAST PATH: PLAIN LONG HEX */
|
||||
if (out(ibuf, arg, uint64toarray_radix16(lu, ibuf)) == -1) return -1;
|
||||
format += 3;
|
||||
continue;
|
||||
} else if (format[1] == 'l' && format[2] == 'd') {
|
||||
ld = va_arg(va, long); /* FAST PATH: PLAIN LONG */
|
||||
if (out(ibuf, arg, int64toarray_radix10(ld, ibuf)) == -1) return -1;
|
||||
format += 3;
|
||||
continue;
|
||||
} else if (format[1] == 'l' && format[2] == 'u') {
|
||||
lu = va_arg(va, unsigned long); /* FAST PATH: PLAIN UNSIGNED LONG */
|
||||
if (out(ibuf, arg, int64toarray_radix10(lu, ibuf)) == -1) return -1;
|
||||
format += 3;
|
||||
continue;
|
||||
} else if (format[1] == '.' && format[2] == '*' && format[3] == 's') {
|
||||
n = va_arg(va, unsigned); /* FAST PATH: PRECISION STRING */
|
||||
s = va_arg(va, const char *);
|
||||
if (!s) s = "(null)", n = MIN(6, n);
|
||||
if (out(s, arg, n) == -1) return -1;
|
||||
format += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* GENERAL PATH */
|
||||
format++;
|
||||
sign = 0;
|
||||
flags = 0;
|
||||
getflag:
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int __fmt_pad(int (*)(long, void *), void *, unsigned long) hidden;
|
||||
int __fmt_stoa(int (*)(long, void *), void *, void *, unsigned long,
|
||||
unsigned long, unsigned long, unsigned char,
|
||||
unsigned char) hidden;
|
||||
int __fmt_ntoa(int (*)(long, void *), void *, va_list, unsigned char,
|
||||
int __fmt_pad(int (*)(const char *, void *, size_t), void *,
|
||||
unsigned long) hidden;
|
||||
int __fmt_stoa(int (*)(const char *, void *, size_t), void *, void *,
|
||||
unsigned long, unsigned long, unsigned long, unsigned char,
|
||||
const char *) hidden;
|
||||
unsigned char) hidden;
|
||||
int __fmt_ntoa(int (*)(const char *, void *, size_t), void *, va_list,
|
||||
unsigned char, unsigned long, unsigned long, unsigned long,
|
||||
unsigned char, const char *) hidden;
|
||||
char *__fmt_dtoa(double, int, int, int *, int *, char **) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/reverse.internal.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
|
@ -25,12 +26,11 @@
|
|||
|
||||
uintmax_t __udivmodti4(uintmax_t, uintmax_t, uintmax_t *);
|
||||
|
||||
static int __fmt_ntoa_format(int out(long, void *), void *arg, char *buf,
|
||||
unsigned len, bool negative, unsigned log2base,
|
||||
unsigned prec, unsigned width,
|
||||
static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg,
|
||||
char *buf, unsigned len, bool negative,
|
||||
unsigned log2base, unsigned prec, unsigned width,
|
||||
unsigned char flags) {
|
||||
unsigned i, idx;
|
||||
idx = 0;
|
||||
unsigned i;
|
||||
|
||||
/* pad leading zeros */
|
||||
if (!(flags & FLAGS_LEFT)) {
|
||||
|
@ -82,24 +82,21 @@ static int __fmt_ntoa_format(int out(long, void *), void *arg, char *buf,
|
|||
}
|
||||
}
|
||||
|
||||
/* reverse string */
|
||||
for (i = 0U; i < len; i++) {
|
||||
if (out(buf[len - i - 1], arg) == -1) return -1;
|
||||
idx++;
|
||||
}
|
||||
reverse(buf, len);
|
||||
if (out(buf, arg, len) == -1) return -1;
|
||||
|
||||
/* append pad spaces up to given width */
|
||||
if (flags & FLAGS_LEFT) {
|
||||
if (idx < width) {
|
||||
if (__fmt_pad(out, arg, width - idx) == -1) return -1;
|
||||
if (len < width) {
|
||||
if (__fmt_pad(out, arg, width - len) == -1) return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __fmt_ntoa2(int out(long, void *), void *arg, uintmax_t value, bool neg,
|
||||
unsigned log2base, unsigned prec, unsigned width,
|
||||
unsigned flags, const char *alphabet) {
|
||||
int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg,
|
||||
uintmax_t value, bool neg, unsigned log2base, unsigned prec,
|
||||
unsigned width, unsigned flags, const char *alphabet) {
|
||||
uintmax_t remainder;
|
||||
unsigned len, count, digit;
|
||||
char buf[BUFFER_SIZE];
|
||||
|
@ -130,7 +127,7 @@ int __fmt_ntoa2(int out(long, void *), void *arg, uintmax_t value, bool neg,
|
|||
flags);
|
||||
}
|
||||
|
||||
int __fmt_ntoa(int out(long, void *), void *arg, va_list va,
|
||||
int __fmt_ntoa(int out(const char *, void *, size_t), void *arg, va_list va,
|
||||
unsigned char signbit, unsigned long log2base,
|
||||
unsigned long prec, unsigned long width, unsigned char flags,
|
||||
const char *lang) {
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmts.h"
|
||||
|
||||
int __fmt_pad(int out(long, void *), void *arg, unsigned long n) {
|
||||
int __fmt_pad(int out(const char *, void *, size_t), void *arg,
|
||||
unsigned long n) {
|
||||
int i, rc;
|
||||
for (rc = i = 0; i < n; ++i) rc |= out(' ', arg);
|
||||
for (rc = i = 0; i < n; ++i) rc |= out(" ", arg, 1);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/fmt/fmts.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/tinystrlen.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
|
@ -26,56 +29,48 @@
|
|||
#include "libc/str/utf16.h"
|
||||
#include "libc/unicode/unicode.h"
|
||||
|
||||
typedef int (*emit_f)(int (*)(long, void *), void *, wint_t);
|
||||
typedef int (*out_f)(const char *, void *, size_t);
|
||||
typedef int (*emit_f)(out_f, void *, uint64_t);
|
||||
|
||||
static noinstrument int __fmt_stoa_byte(int f(long, void *), void *a,
|
||||
wint_t c) {
|
||||
return f(c, a);
|
||||
static int __fmt_stoa_byte(out_f out, void *a, uint64_t c) {
|
||||
char buf[1] = {c};
|
||||
return out(buf, a, 1);
|
||||
}
|
||||
|
||||
static noinstrument int __fmt_stoa_word(int f(long, void *), void *a,
|
||||
uint64_t w) {
|
||||
do {
|
||||
if (f(w & 0xff, a) == -1) {
|
||||
return -1;
|
||||
}
|
||||
} while ((w >>= 8));
|
||||
return 0;
|
||||
static int __fmt_stoa_wide(out_f out, void *a, uint64_t w) {
|
||||
char buf[8];
|
||||
if (!isascii(w)) w = tpenc(w);
|
||||
WRITE64LE(buf, w);
|
||||
return out(buf, a, w ? (bsr(w) >> 3) + 1 : 1);
|
||||
}
|
||||
|
||||
static noinstrument int __fmt_stoa_wide(int f(long, void *), void *a,
|
||||
wint_t c) {
|
||||
if (isascii(c)) {
|
||||
return f(c, a);
|
||||
static int __fmt_stoa_bing(out_f out, void *a, uint64_t w) {
|
||||
char buf[8];
|
||||
w = tpenc((*weaken(kCp437))[w & 0xFF]);
|
||||
WRITE64LE(buf, w);
|
||||
return out(buf, a, w ? (bsr(w) >> 3) + 1 : 1);
|
||||
}
|
||||
|
||||
static int __fmt_stoa_quoted(out_f out, void *a, uint64_t w) {
|
||||
char buf[8];
|
||||
if (isascii(w)) {
|
||||
w = cescapec(w);
|
||||
} else {
|
||||
return __fmt_stoa_word(f, a, tpenc(c));
|
||||
w = tpenc(w);
|
||||
}
|
||||
WRITE64LE(buf, w);
|
||||
return out(buf, a, w ? (bsr(w) >> 3) + 1 : 1);
|
||||
}
|
||||
|
||||
static noinstrument int __fmt_stoa_bing(int f(long, void *), void *a,
|
||||
wint_t c) {
|
||||
return __fmt_stoa_wide(f, a, (*weaken(kCp437))[c]);
|
||||
}
|
||||
|
||||
static noinstrument int __fmt_stoa_quoted(int f(long, void *), void *a,
|
||||
wint_t c) {
|
||||
if (isascii(c)) {
|
||||
return __fmt_stoa_word(f, a, cescapec(c));
|
||||
} else {
|
||||
return __fmt_stoa_word(f, a, tpenc(c));
|
||||
}
|
||||
}
|
||||
|
||||
static noinstrument int __fmt_stoa_quote(int out(long, void *), void *arg,
|
||||
unsigned flags, char ch,
|
||||
unsigned char signbit) {
|
||||
static int __fmt_stoa_quote(out_f out, void *arg, unsigned flags, char ch,
|
||||
unsigned char signbit) {
|
||||
if (flags & FLAGS_REPR) {
|
||||
if (signbit == 63) {
|
||||
if (out('L', arg) == -1) return -1;
|
||||
if (out("L", arg, 1) == -1) return -1;
|
||||
} else if (signbit == 15) {
|
||||
if (out('u', arg) == -1) return -1;
|
||||
if (out("u", arg, 1) == -1) return -1;
|
||||
}
|
||||
if (out(ch, arg) == -1) return -1;
|
||||
if (out(&ch, arg, 1) == -1) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -89,23 +84,25 @@ static noinstrument int __fmt_stoa_quote(int out(long, void *), void *arg,
|
|||
*
|
||||
* @see __fmt()
|
||||
*/
|
||||
int __fmt_stoa(int out(long, void *), void *arg, void *data,
|
||||
int __fmt_stoa(int out(const char *, void *, size_t), void *arg, void *data,
|
||||
unsigned long flags, unsigned long precision,
|
||||
unsigned long width, unsigned char signbit,
|
||||
unsigned char qchar) {
|
||||
char *p;
|
||||
wint_t wc;
|
||||
unsigned n;
|
||||
emit_f emit;
|
||||
char *p, buf[1];
|
||||
unsigned w, c, pad;
|
||||
bool justdobytes, ignorenul;
|
||||
|
||||
p = data;
|
||||
if (!p) {
|
||||
p = ((flags & FLAGS_REPR) ? "NULL" : "(null)");
|
||||
flags &= ~FLAGS_PRECISION;
|
||||
flags |= FLAGS_NOQUOTE;
|
||||
signbit = 0;
|
||||
flags |= FLAGS_NOQUOTE;
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
precision = min(strlen(p), precision);
|
||||
}
|
||||
} else {
|
||||
if (__fmt_stoa_quote(out, arg, flags, qchar, signbit) == -1) return -1;
|
||||
}
|
||||
|
@ -215,7 +212,8 @@ int __fmt_stoa(int out(long, void *), void *arg, void *data,
|
|||
}
|
||||
|
||||
if (!(flags & FLAGS_NOQUOTE) && (flags & FLAGS_REPR)) {
|
||||
if (out(qchar, arg) == -1) return -1;
|
||||
buf[0] = qchar;
|
||||
if (out(buf, arg, 1) == -1) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -20,291 +20,160 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
STATIC_YOINK("E2BIG");
|
||||
STATIC_YOINK("EACCES");
|
||||
STATIC_YOINK("EADDRINUSE");
|
||||
STATIC_YOINK("EADDRNOTAVAIL");
|
||||
STATIC_YOINK("EADV");
|
||||
STATIC_YOINK("EAFNOSUPPORT");
|
||||
STATIC_YOINK("EAGAIN");
|
||||
STATIC_YOINK("EALREADY");
|
||||
STATIC_YOINK("EBADE");
|
||||
STATIC_YOINK("EBADF");
|
||||
STATIC_YOINK("EBADFD");
|
||||
STATIC_YOINK("EBADMSG");
|
||||
STATIC_YOINK("EBADR");
|
||||
STATIC_YOINK("EBADRQC");
|
||||
STATIC_YOINK("EBADSLT");
|
||||
STATIC_YOINK("EBFONT");
|
||||
STATIC_YOINK("EBUSY");
|
||||
STATIC_YOINK("ECANCELED");
|
||||
STATIC_YOINK("ECHILD");
|
||||
STATIC_YOINK("ECHRNG");
|
||||
STATIC_YOINK("ECOMM");
|
||||
STATIC_YOINK("ECONNABORTED");
|
||||
STATIC_YOINK("ECONNREFUSED");
|
||||
STATIC_YOINK("ECONNRESET");
|
||||
STATIC_YOINK("EDEADLK");
|
||||
STATIC_YOINK("EDESTADDRREQ");
|
||||
STATIC_YOINK("EDOM");
|
||||
STATIC_YOINK("EDOTDOT");
|
||||
STATIC_YOINK("EDQUOT");
|
||||
STATIC_YOINK("EEXIST");
|
||||
STATIC_YOINK("EFAULT");
|
||||
STATIC_YOINK("EFBIG");
|
||||
STATIC_YOINK("EHOSTDOWN");
|
||||
STATIC_YOINK("EHOSTUNREACH");
|
||||
STATIC_YOINK("EHWPOISON");
|
||||
STATIC_YOINK("EIDRM");
|
||||
STATIC_YOINK("EILSEQ");
|
||||
STATIC_YOINK("EINPROGRESS");
|
||||
STATIC_YOINK("EINTR");
|
||||
STATIC_YOINK("EINVAL");
|
||||
STATIC_YOINK("EIO");
|
||||
STATIC_YOINK("EISCONN");
|
||||
STATIC_YOINK("EISDIR");
|
||||
STATIC_YOINK("EISNAM");
|
||||
STATIC_YOINK("EKEYEXPIRED");
|
||||
STATIC_YOINK("EKEYREJECTED");
|
||||
STATIC_YOINK("EKEYREVOKED");
|
||||
STATIC_YOINK("EL2HLT");
|
||||
STATIC_YOINK("EL2NSYNC");
|
||||
STATIC_YOINK("EL3HLT");
|
||||
STATIC_YOINK("EL3RST");
|
||||
STATIC_YOINK("ELIBACC");
|
||||
STATIC_YOINK("ELIBBAD");
|
||||
STATIC_YOINK("ELIBEXEC");
|
||||
STATIC_YOINK("ELIBMAX");
|
||||
STATIC_YOINK("ELIBSCN");
|
||||
STATIC_YOINK("ELNRNG");
|
||||
STATIC_YOINK("ELOOP");
|
||||
STATIC_YOINK("EMEDIUMTYPE");
|
||||
STATIC_YOINK("EMFILE");
|
||||
STATIC_YOINK("EMLINK");
|
||||
STATIC_YOINK("EMSGSIZE");
|
||||
STATIC_YOINK("EMULTIHOP");
|
||||
STATIC_YOINK("ENAMETOOLONG");
|
||||
STATIC_YOINK("ENAVAIL");
|
||||
STATIC_YOINK("ENETDOWN");
|
||||
STATIC_YOINK("ENETRESET");
|
||||
STATIC_YOINK("ENETUNREACH");
|
||||
STATIC_YOINK("ENFILE");
|
||||
STATIC_YOINK("ENOANO");
|
||||
STATIC_YOINK("ENOBUFS");
|
||||
STATIC_YOINK("ENOCSI");
|
||||
STATIC_YOINK("ENODATA");
|
||||
STATIC_YOINK("ENODEV");
|
||||
STATIC_YOINK("ENOENT");
|
||||
STATIC_YOINK("ENOEXEC");
|
||||
STATIC_YOINK("ENOKEY");
|
||||
STATIC_YOINK("ENOLCK");
|
||||
STATIC_YOINK("ENOLINK");
|
||||
STATIC_YOINK("ENOMEDIUM");
|
||||
STATIC_YOINK("ENOMEM");
|
||||
STATIC_YOINK("ENOMSG");
|
||||
STATIC_YOINK("ENONET");
|
||||
STATIC_YOINK("ENOPKG");
|
||||
STATIC_YOINK("ENOPROTOOPT");
|
||||
STATIC_YOINK("ENOSPC");
|
||||
STATIC_YOINK("ENOSR");
|
||||
STATIC_YOINK("ENOSTR");
|
||||
STATIC_YOINK("ENOSYS");
|
||||
STATIC_YOINK("ENOTBLK");
|
||||
STATIC_YOINK("ENOTCONN");
|
||||
STATIC_YOINK("ENOTDIR");
|
||||
STATIC_YOINK("ENOTEMPTY");
|
||||
STATIC_YOINK("ENOTNAM");
|
||||
STATIC_YOINK("ENOTRECOVERABLE");
|
||||
STATIC_YOINK("ENOTSOCK");
|
||||
STATIC_YOINK("ENOTSUP");
|
||||
STATIC_YOINK("ENOTTY");
|
||||
STATIC_YOINK("ENOTUNIQ");
|
||||
STATIC_YOINK("ENXIO");
|
||||
STATIC_YOINK("EOPNOTSUPP");
|
||||
STATIC_YOINK("EOVERFLOW");
|
||||
STATIC_YOINK("EOWNERDEAD");
|
||||
STATIC_YOINK("EPERM");
|
||||
STATIC_YOINK("EPFNOSUPPORT");
|
||||
STATIC_YOINK("EPIPE");
|
||||
STATIC_YOINK("EPROTO");
|
||||
STATIC_YOINK("EPROTONOSUPPORT");
|
||||
STATIC_YOINK("EPROTOTYPE");
|
||||
STATIC_YOINK("ERANGE");
|
||||
STATIC_YOINK("EREMCHG");
|
||||
STATIC_YOINK("EREMOTE");
|
||||
STATIC_YOINK("EREMOTEIO");
|
||||
STATIC_YOINK("ERESTART");
|
||||
STATIC_YOINK("ERFKILL");
|
||||
STATIC_YOINK("EROFS");
|
||||
STATIC_YOINK("ESHUTDOWN");
|
||||
STATIC_YOINK("ESOCKTNOSUPPORT");
|
||||
STATIC_YOINK("ESPIPE");
|
||||
STATIC_YOINK("ESRCH");
|
||||
STATIC_YOINK("ESRMNT");
|
||||
STATIC_YOINK("ESTALE");
|
||||
STATIC_YOINK("ESTRPIPE");
|
||||
STATIC_YOINK("ETIME");
|
||||
STATIC_YOINK("ETIMEDOUT");
|
||||
STATIC_YOINK("ETOOMANYREFS");
|
||||
STATIC_YOINK("ETXTBSY");
|
||||
STATIC_YOINK("EUCLEAN");
|
||||
STATIC_YOINK("EUNATCH");
|
||||
STATIC_YOINK("EUSERS");
|
||||
STATIC_YOINK("EXDEV");
|
||||
STATIC_YOINK("EXFULL");
|
||||
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 (x) {
|
||||
for (i = 0; i < ARRAYLEN(kErrors); ++i) {
|
||||
if (x == *kErrors[i].x) {
|
||||
return kErrors[i].s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return "EUNKNOWN";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,28 +181,19 @@ static const char *geterrname(long code) {
|
|||
* @return 0 on success, or error code
|
||||
*/
|
||||
int strerror_r(int err, char *buf, size_t size) {
|
||||
char *p;
|
||||
const char *s;
|
||||
char16_t buf16[100];
|
||||
int winstate, sysvstate;
|
||||
if (!err || IsTiny()) {
|
||||
s = "?";
|
||||
} else {
|
||||
s = firstnonnull(geterrname(err), "?");
|
||||
err &= 0xFFFF;
|
||||
s = geterrname(err);
|
||||
p = buf;
|
||||
if (strlen(s) + 1 + 5 + 1 + 1 <= size) {
|
||||
p = stpcpy(p, s);
|
||||
*p++ = '[';
|
||||
p += uint64toarray_radix10(err, p);
|
||||
*p++ = ']';
|
||||
}
|
||||
if (!SupportsWindows()) {
|
||||
(snprintf)(buf, size, "E%s[%d]", s, err);
|
||||
} else {
|
||||
winstate = GetLastError();
|
||||
sysvstate = errno;
|
||||
if (FormatMessage(
|
||||
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL,
|
||||
err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) {
|
||||
chomp16(buf16);
|
||||
} else {
|
||||
buf16[0] = u'\0';
|
||||
}
|
||||
(snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
|
||||
sysvstate, winstate, buf16[0] ? " " : "", buf16);
|
||||
if (p - buf < size) {
|
||||
*p++ = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
struct SprintfStr {
|
||||
|
@ -28,10 +28,13 @@ struct SprintfStr {
|
|||
size_t n;
|
||||
};
|
||||
|
||||
static noinstrument int vsnprintfputchar(unsigned char c,
|
||||
struct SprintfStr *str) {
|
||||
if (str->i < str->n) str->p[str->i] = c;
|
||||
str->i++;
|
||||
static int vsnprintfputchar(const char *s, struct SprintfStr *t, size_t n) {
|
||||
if (t->i + n <= t->n) {
|
||||
memcpy(t->p + t->i, s, n);
|
||||
} else if (t->i < t->n) {
|
||||
memcpy(t->p + t->i, s, t->n - t->i);
|
||||
}
|
||||
t->i += n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -51,6 +54,6 @@ static noinstrument int vsnprintfputchar(unsigned char c,
|
|||
int(vsnprintf)(char *buf, size_t size, const char *fmt, va_list va) {
|
||||
struct SprintfStr str = {buf, 0, size};
|
||||
__fmt(vsnprintfputchar, &str, fmt, va);
|
||||
if (str.n) str.p[min(str.i, str.n - 1)] = '\0';
|
||||
if (str.n) str.p[MIN(str.i, str.n - 1)] = '\0';
|
||||
return str.i;
|
||||
}
|
||||
|
|
|
@ -659,6 +659,7 @@ typedef uint64_t uintmax_t;
|
|||
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
|
||||
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
|
||||
#pragma GCC diagnostic ignored "-Wunused-const-variable" /* let me dce */
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
|
||||
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
|
||||
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
@ -43,17 +46,8 @@
|
|||
bool cancolor(void) {
|
||||
static bool once;
|
||||
static bool result;
|
||||
const char *term;
|
||||
if (!once) {
|
||||
if (!result) {
|
||||
if ((term = getenv("TERM"))) {
|
||||
/* anything but emacs basically */
|
||||
result = strcmp(term, "dumb") != 0;
|
||||
} else {
|
||||
/* TODO(jart): Why does Mac bash login shell exec nuke TERM? */
|
||||
result = IsXnu();
|
||||
}
|
||||
}
|
||||
result = !!strcmp(nulltoempty(getenv("DONTANSIMEBRO")), "1");
|
||||
once = true;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -21,9 +21,6 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Checks if we're probably running inside Emacs.
|
||||
*/
|
||||
bool IsTerminalInarticulate(void) {
|
||||
return strcmp(nulltoempty(getenv("TERM")), "dumb") == 0;
|
||||
return !strcmp(nulltoempty(getenv("TERM")), "dumb");
|
||||
}
|
||||
|
|
|
@ -232,8 +232,6 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
|||
err = errno;
|
||||
if (once) _exit(119);
|
||||
once = true;
|
||||
/* TODO(jart): Needs translation for ucontext_t and possibly siginfo_t. */
|
||||
if (IsFreebsd() || IsOpenbsd()) ctx = NULL;
|
||||
rip = ctx ? ctx->uc_mcontext.rip : 0;
|
||||
if ((gdbpid = IsDebuggerPresent(true))) {
|
||||
DebugBreak();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,26 +29,26 @@
|
|||
* @see xasprintf() for a better API
|
||||
*/
|
||||
int(vasprintf)(char **strp, const char *fmt, va_list va) {
|
||||
int wrote;
|
||||
char *p;
|
||||
size_t size;
|
||||
va_list va2;
|
||||
va_list vb;
|
||||
int wrote, rc = -1;
|
||||
if ((*strp = malloc((size = 512)))) {
|
||||
va_copy(va2, va);
|
||||
va_copy(vb, va);
|
||||
wrote = (vsnprintf)(*strp, size, fmt, va);
|
||||
if (wrote == -1) return -1;
|
||||
if (wrote < size) {
|
||||
if ((p = realloc(*strp, wrote + 1))) *strp = p;
|
||||
return wrote;
|
||||
rc = wrote;
|
||||
} else {
|
||||
size = wrote + 1;
|
||||
if ((p = realloc(*strp, size))) {
|
||||
*strp = p;
|
||||
wrote = (vsnprintf)(*strp, size, fmt, va2);
|
||||
wrote = (vsnprintf)(*strp, size, fmt, vb);
|
||||
assert(wrote == size - 1);
|
||||
return wrote;
|
||||
rc = wrote;
|
||||
}
|
||||
}
|
||||
va_end(vb);
|
||||
}
|
||||
return -1;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
// @param dil contains byte to escape
|
||||
// @see libc/nexgen32e/cescapec.c
|
||||
cescapec:
|
||||
.leafprologue
|
||||
.profilable
|
||||
movzbl %dil,%edi
|
||||
lea -7(%rdi),%ecx
|
||||
cmp $85,%cl
|
||||
|
@ -36,28 +38,28 @@ cescapec:
|
|||
jmp *cescapectab(,%rcx,8)
|
||||
.Lanchorpoint:
|
||||
.LBEL: mov $'a',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LBS: mov $'b',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LHT: mov $'t',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LLF: mov $'n',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LVT: mov $'v',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LFF: mov $'f',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LCR: mov $'r',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LDQ: mov $'\"',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LSQ: mov $'\'',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
.LBSL: mov $'\\',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
#ifdef __STRICT_ANSI__
|
||||
.LQM: mov $'?',%ah
|
||||
ret
|
||||
.leafepilogue
|
||||
#else
|
||||
.LQM:
|
||||
#endif
|
||||
|
@ -65,7 +67,7 @@ cescapec:
|
|||
lea -0x20(%rax),%ecx
|
||||
cmp $0x5E,%ecx
|
||||
ja 2f
|
||||
ret
|
||||
.leafepilogue
|
||||
2: and $-64,%eax
|
||||
mov %edi,%ecx
|
||||
and $56,%ecx
|
||||
|
@ -75,7 +77,7 @@ cescapec:
|
|||
or %ecx,%edi
|
||||
lea (%rdi,%rax,4),%eax
|
||||
add $'0'<<030|'0'<<020|'0'<<010|'\\',%eax
|
||||
ret
|
||||
.leafepilogue
|
||||
.endfn cescapec,globl
|
||||
|
||||
.initro 300,_init_cescapec
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const uint32_t kCrc32cTab[256];
|
||||
|
||||
void crc32init(uint32_t[hasatleast 256], uint32_t);
|
||||
uint32_t crc32c(uint32_t, const void *, size_t);
|
||||
uint32_t crc32_z(uint32_t, const void *, size_t);
|
||||
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t);
|
||||
uint32_t crc32c_pure(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32c_sse42(uint32_t, const void *, size_t) strlenesque hidden;
|
||||
uint32_t crc32_pclmul(uint32_t, const void *, size_t) hidden;
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
// @return rax is address of last %sil in %rdi, or NULL
|
||||
// @note AVX2 requires Haswell (2014+) or Excavator (2015+)
|
||||
// @asyncsignalsafe
|
||||
memrchr:.leafprologue
|
||||
memrchr:
|
||||
.leafprologue
|
||||
.profilable
|
||||
#if !IsTiny()
|
||||
cmp $32,%rdx
|
||||
|
|
75
libc/runtime/clktck.c
Normal file
75
libc/runtime/clktck.c
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
12
libc/runtime/clktck.h
Normal file
12
libc/runtime/clktck.h
Normal file
|
@ -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_ */
|
|
@ -29,40 +29,28 @@
|
|||
/**
|
||||
* Returns path of binary with the debug information, or null.
|
||||
*
|
||||
* @return path to debug binary, or -1 w/ errno
|
||||
* @return path to debug binary, or NULL
|
||||
*/
|
||||
const char *FindDebugBinary(void) {
|
||||
unsigned i, len;
|
||||
char buf[2][PATH_MAX];
|
||||
static char res[PATH_MAX];
|
||||
const char *bins[4], *pwd, *comdbg;
|
||||
if (res[0]) return res;
|
||||
if ((comdbg = emptytonull(getenv("COMDBG")))) return comdbg;
|
||||
if (res[0]) return res;
|
||||
bins[0] = program_invocation_name;
|
||||
bins[1] = (const char *)getauxval(AT_EXECFN);
|
||||
pwd = emptytonull(getenv("PWD"));
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (pwd && bins[i] && bins[i][0] != '/' && bins[i][0] != '\\' &&
|
||||
strlen(pwd) + 1 + strlen(bins[i]) + 1 <= ARRAYLEN(buf[0])) {
|
||||
strcpy(buf[i], pwd);
|
||||
strcat(buf[i], "/");
|
||||
strcat(buf[i], bins[i]);
|
||||
bins[i + 2] = buf[i];
|
||||
static bool once;
|
||||
static char *res;
|
||||
static char buf[PATH_MAX + 1];
|
||||
char *p;
|
||||
size_t n;
|
||||
if (!once) {
|
||||
if (!(res = getenv("COMDBG"))) {
|
||||
p = (char *)getauxval(AT_EXECFN);
|
||||
n = strlen(p);
|
||||
if (n > 4 && !memcmp(p + n - 4, ".dbg", 4)) {
|
||||
res = p;
|
||||
} else if (n + 4 <= PATH_MAX) {
|
||||
mempcpy(mempcpy(buf, p, n), ".dbg", 5);
|
||||
if (fileexists(buf)) {
|
||||
res = buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
once = true;
|
||||
}
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (!bins[i]) continue;
|
||||
len = strlen(bins[i]);
|
||||
memcpy(res, bins[i], len + 1);
|
||||
if (!endswith(res, ".dbg") && len + 3 + 1 <= ARRAYLEN(res)) {
|
||||
strcat(res, ".dbg");
|
||||
}
|
||||
if (fileexists(res)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
res[0] = '\0';
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -106,42 +106,12 @@ privileged noasan void ftrace(void) {
|
|||
noreentry = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables plaintext function tracing if `--ftrace` flag is passed.
|
||||
*
|
||||
* The `--ftrace` CLI arg is removed before main() is called. This code
|
||||
* is intended for diagnostic purposes and assumes binaries are
|
||||
* trustworthy and stack isn't corrupted. Logging plain text allows
|
||||
* program structure to easily be visualized and hotspots identified w/
|
||||
* `sed | sort | uniq -c | sort`. A compressed trace can be made by
|
||||
* appending `--ftrace 2>&1 | gzip -4 >trace.gz` to the CLI arguments.
|
||||
*
|
||||
* @see libc/runtime/_init.S for documentation
|
||||
*/
|
||||
textstartup int ftrace_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
bool foundflag;
|
||||
foundflag = false;
|
||||
for (i = 1; i <= argc; ++i) {
|
||||
if (!foundflag) {
|
||||
if (argv[i]) {
|
||||
if (strcmp(argv[i], "--ftrace") == 0) {
|
||||
foundflag = true;
|
||||
} else if (strcmp(argv[i], "----ftrace") == 0) {
|
||||
strcpy(argv[i], "--ftrace");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
argv[i - 1] = argv[i];
|
||||
}
|
||||
textstartup void ftrace_install(void) {
|
||||
g_buf[0] = '+';
|
||||
g_buf[1] = ' ';
|
||||
if ((g_symbols = OpenSymbolTable(FindDebugBinary()))) {
|
||||
__hook(ftrace_hook, g_symbols);
|
||||
} else {
|
||||
write(2, "error: --ftrace needs the concomitant .com.dbg binary\n", 54);
|
||||
}
|
||||
if (foundflag) {
|
||||
--argc;
|
||||
g_buf[0] = '+';
|
||||
g_buf[1] = ' ';
|
||||
if ((g_symbols = OpenSymbolTable(FindDebugBinary()))) {
|
||||
__hook(ftrace_hook, g_symbols);
|
||||
}
|
||||
}
|
||||
return argc;
|
||||
}
|
||||
|
|
56
libc/runtime/ftraceinit.c
Normal file
56
libc/runtime/ftraceinit.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 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/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Enables plaintext function tracing if `--ftrace` flag is passed.
|
||||
*
|
||||
* The `--ftrace` CLI arg is removed before main() is called. This code
|
||||
* is intended for diagnostic purposes and assumes binaries are
|
||||
* trustworthy and stack isn't corrupted. Logging plain text allows
|
||||
* program structure to easily be visualized and hotspots identified w/
|
||||
* `sed | sort | uniq -c | sort`. A compressed trace can be made by
|
||||
* appending `--ftrace 2>&1 | gzip -4 >trace.gz` to the CLI arguments.
|
||||
*
|
||||
* @see libc/runtime/_init.S for documentation
|
||||
*/
|
||||
textstartup int ftrace_init(int argc, char *argv[]) {
|
||||
int i;
|
||||
bool foundflag;
|
||||
foundflag = false;
|
||||
for (i = 1; i <= argc; ++i) {
|
||||
if (!foundflag) {
|
||||
if (argv[i]) {
|
||||
if (strcmp(argv[i], "--ftrace") == 0) {
|
||||
foundflag = true;
|
||||
} else if (strcmp(argv[i], "----ftrace") == 0) {
|
||||
strcpy(argv[i], "--ftrace");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
argv[i - 1] = argv[i];
|
||||
}
|
||||
}
|
||||
if (foundflag) {
|
||||
--argc;
|
||||
ftrace_install();
|
||||
}
|
||||
return argc;
|
||||
}
|
|
@ -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 > 0x0000010000000000ull) 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;
|
||||
}
|
||||
|
|
|
@ -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,55 +16,40 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#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"
|
||||
#include "net/http/uri.h"
|
||||
|
||||
/* TODO(jart): Rewrite in C */
|
||||
|
||||
#define static
|
||||
|
||||
/* clang-format off */
|
||||
%% machine uricspn;
|
||||
%% write data;
|
||||
/* clang-format on */
|
||||
|
||||
int uricspn(const char *data, size_t size) {
|
||||
int uricspn$avx(const char *, size_t) hidden;
|
||||
const char *p, *pe;
|
||||
int cs;
|
||||
|
||||
assert(data || !size);
|
||||
assert(size <= 0x7ffff000);
|
||||
assert(size <= 0x7ffff000);
|
||||
|
||||
if (X86_HAVE(AVX)) {
|
||||
return uricspn$avx(data, size);
|
||||
}
|
||||
|
||||
p = data;
|
||||
pe = data + size;
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
%%{
|
||||
mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")";
|
||||
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",";
|
||||
unreserved = alnum | mark;
|
||||
uric = reserved | unreserved | "%";
|
||||
machina := uric*;
|
||||
}%%
|
||||
|
||||
%% write init;
|
||||
cs = uricspn_en_machina;
|
||||
%% write exec;
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
if (cs >= uricspn_first_final) {
|
||||
return p - data;
|
||||
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 {
|
||||
return einval();
|
||||
rax = enosys();
|
||||
}
|
||||
return (void *)rax;
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
198
libc/runtime/openexecutable.S
Normal file
198
libc/runtime/openexecutable.S
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*-*- 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)
|
||||
pushq __NR_mprotect(%rip) # -0x48(%rbp)
|
||||
pushq __NR_mprotect(%rip) # -0x50(%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,%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
|
||||
|
||||
// Change protection.
|
||||
mov -0x48(%rbp),%eax # __NR_mprotect
|
||||
mov %rbx,%rdi
|
||||
mov $PAGESIZE,%esi
|
||||
mov $PROT_READ|PROT_EXEC,%edx
|
||||
syscall
|
||||
|
||||
jmp *%rbx
|
||||
|
||||
// <LIMBO>
|
||||
|
||||
// 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
|
||||
mov %r12,%rsi
|
||||
mov $ape_ram_filesz,%ecx
|
||||
rep movsb
|
||||
|
||||
// Jump back.
|
||||
mov $9f,%eax
|
||||
jmp *%rax
|
||||
|
||||
// </LIMBO>
|
||||
|
||||
// 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
|
|
@ -35,7 +35,7 @@ extern uint8_t __zip_end[]; /* αpε */
|
|||
|
||||
void mcount(void);
|
||||
unsigned long getauxval(unsigned long);
|
||||
void *mapanon(size_t) vallocesque attributeallocsize((1));
|
||||
void *mapanon(size_t) attributeallocsize((1));
|
||||
int setjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
void longjmp(jmp_buf, int) libcesque wontreturn paramsnonnull();
|
||||
int _setjmp(jmp_buf) libcesque returnstwice paramsnonnull();
|
||||
|
@ -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,8 @@ void _savexmm(void *);
|
|||
void _weakfree(void *);
|
||||
void free_s(void *) paramsnonnull() libcesque;
|
||||
int close_s(int *) paramsnonnull() libcesque;
|
||||
int OpenExecutable(void);
|
||||
void ftrace_install(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/inaddr.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Converts internet address string to binary.
|
||||
|
@ -32,16 +32,23 @@
|
|||
* @return 1 on success, 0 on src malformed, or -1 w/ errno
|
||||
*/
|
||||
int inet_pton(int af, const char *src, void *dst) {
|
||||
if (af == AF_INET) {
|
||||
unsigned char *p = (unsigned char *)dst;
|
||||
if (sscanf(src, "%hhu.%hhu.%hhu.%hhu", &p[0], &p[1], &p[2], &p[3]) == 4) {
|
||||
return 1;
|
||||
uint8_t *p;
|
||||
int b, c, j;
|
||||
if (af != AF_INET) return eafnosupport();
|
||||
j = 0;
|
||||
p = dst;
|
||||
p[0] = 0;
|
||||
while ((c = *src++)) {
|
||||
if (isdigit(c)) {
|
||||
b = c - '0' + p[j] * 10;
|
||||
p[j] = MIN(255, b);
|
||||
if (b > 255) return 0;
|
||||
} else if (c == '.') {
|
||||
if (++j == 4) return 0;
|
||||
p[j] = 0;
|
||||
} else {
|
||||
*(uint32_t *)dst = htonl(INADDR_TESTNET3);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
*(uint32_t *)dst = htonl(INADDR_TESTNET3);
|
||||
return eafnosupport();
|
||||
}
|
||||
return j == 3 ? 1 : 0;
|
||||
}
|
||||
|
|
|
@ -47,9 +47,10 @@ struct msghdr_bsd {
|
|||
};
|
||||
|
||||
struct sockaddr_un_bsd {
|
||||
uint8_t sun_len; /* sockaddr len including NUL on freebsd but excluding it on openbsd/xnu */
|
||||
uint8_t sun_len; /* sockaddr len including NUL on freebsd but excluding it on
|
||||
openbsd/xnu */
|
||||
uint8_t sun_family;
|
||||
char sun_path[108];
|
||||
char sun_path[108];
|
||||
};
|
||||
|
||||
struct SockFd {
|
||||
|
@ -121,6 +122,7 @@ int sys_socketpair_nt_dgram(int, int, int, int[2]) hidden;
|
|||
int sys_socketpair_nt(int, int, int, int[2]) hidden;
|
||||
int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *) hidden;
|
||||
int sys_shutdown_nt(struct Fd *, int) hidden;
|
||||
int sys_setsockopt_nt(struct Fd *, int, int, const void *, uint32_t) hidden;
|
||||
|
||||
size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *,
|
||||
size_t) hidden;
|
||||
|
|
60
libc/sock/setsockopt-nt.c
Normal file
60
libc/sock/setsockopt-nt.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- 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/struct/timeval.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
struct linger_nt { /* Linux+XNU+BSD ABI */
|
||||
uint16_t l_onoff; /* on/off */
|
||||
uint16_t l_linger; /* seconds */
|
||||
};
|
||||
|
||||
textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
|
||||
const void *optval, uint32_t optlen) {
|
||||
struct timeval *tv;
|
||||
struct linger *linger;
|
||||
union {
|
||||
uint32_t millis;
|
||||
struct linger_nt linger;
|
||||
} nt;
|
||||
|
||||
if (optname == SO_LINGER && optval && optlen == sizeof(struct linger)) {
|
||||
linger = optval;
|
||||
nt.linger.l_onoff = linger->l_onoff;
|
||||
nt.linger.l_linger = MIN(0xFFFF, MAX(0, linger->l_linger));
|
||||
optval = &nt.linger;
|
||||
optlen = sizeof(nt.linger);
|
||||
}
|
||||
|
||||
if ((optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) && optval &&
|
||||
optlen == sizeof(struct timeval)) {
|
||||
tv = optval;
|
||||
nt.millis = MIN(0xFFFFFFFF, MAX(0, tv->tv_sec * 1000 + tv->tv_usec / 1000));
|
||||
optval = &nt.millis;
|
||||
optlen = sizeof(nt.millis);
|
||||
}
|
||||
|
||||
if (__sys_setsockopt_nt(fd->handle, level, optname, optval, optlen) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winsockerr();
|
||||
}
|
||||
}
|
|
@ -33,15 +33,6 @@ static bool setsockopt_polyfill(int *optname) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static textwindows int sys_setsockopt_nt(struct Fd *fd, int level, int optname,
|
||||
const void *optval, uint32_t optlen) {
|
||||
if (__sys_setsockopt_nt(fd->handle, level, optname, optval, optlen) != -1) {
|
||||
return 0;
|
||||
} else {
|
||||
return __winsockerr();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies socket settings.
|
||||
*
|
||||
|
|
|
@ -41,8 +41,8 @@ struct sockaddr_in { /* Linux+NT ABI */
|
|||
};
|
||||
|
||||
struct sockaddr_un {
|
||||
uint16_t sun_family; /* AF_UNIX */
|
||||
char sun_path[108];/* path */
|
||||
uint16_t sun_family; /* AF_UNIX */
|
||||
char sun_path[108]; /* path */
|
||||
};
|
||||
|
||||
struct sockaddr_storage {
|
||||
|
@ -53,11 +53,15 @@ struct sockaddr_storage {
|
|||
};
|
||||
};
|
||||
|
||||
struct ip_mreq {
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
struct ip_mreq {
|
||||
struct in_addr imr_multiaddr; /* IP multicast address of group */
|
||||
struct in_addr imr_interface; /* local IP address of interface */
|
||||
};
|
||||
|
||||
struct linger { /* Linux+XNU+BSD ABI */
|
||||
int32_t l_onoff; /* on/off */
|
||||
int32_t l_linger; /* seconds */
|
||||
};
|
||||
|
||||
struct pollfd {
|
||||
int32_t fd;
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
*/
|
||||
int fflush(FILE *f) {
|
||||
size_t i;
|
||||
ssize_t rc;
|
||||
if (!f) {
|
||||
for (i = __fflush.handles.i; i; --i) {
|
||||
if ((f = __fflush.handles.p[i - 1])) {
|
||||
|
@ -45,14 +44,7 @@ int fflush(FILE *f) {
|
|||
}
|
||||
}
|
||||
} else if (f->fd != -1) {
|
||||
while (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
if (rc != f->beg) abort();
|
||||
f->beg = 0;
|
||||
}
|
||||
if (__fflush_impl(f) == -1) return -1;
|
||||
} else if (f->beg && f->beg < f->size) {
|
||||
f->buf[f->beg] = 0;
|
||||
}
|
||||
|
|
37
libc/stdio/fflushimpl.c
Normal file
37
libc/stdio/fflushimpl.c
Normal file
|
@ -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/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
int __fflush_impl(FILE *f) {
|
||||
size_t i;
|
||||
ssize_t rc;
|
||||
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
for (i = 0; i < f->beg; i += rc) {
|
||||
if ((rc = write(f->fd, f->buf + i, f->beg - i)) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
f->beg = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
|
@ -38,14 +39,7 @@ int fseeko(FILE *f, int64_t offset, int whence) {
|
|||
ssize_t rc;
|
||||
int64_t pos;
|
||||
if (f->fd != -1) {
|
||||
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
if (rc != f->beg) abort();
|
||||
f->beg = 0;
|
||||
}
|
||||
if (__fflush_impl(f) == -1) return -1;
|
||||
if (whence == SEEK_CUR && f->beg < f->end) {
|
||||
offset -= f->end - f->beg;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
|
@ -29,18 +30,10 @@
|
|||
* @returns current byte offset from beginning, or -1 w/ errno
|
||||
*/
|
||||
int64_t ftello(FILE *f) {
|
||||
ssize_t rc;
|
||||
int64_t pos;
|
||||
uint32_t skew;
|
||||
if (f->fd != -1) {
|
||||
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
|
||||
if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
|
||||
f->state = errno;
|
||||
return -1;
|
||||
}
|
||||
if (rc != f->beg) abort();
|
||||
f->beg = 0;
|
||||
}
|
||||
if (__fflush_impl(f) == -1) return -1;
|
||||
if ((pos = lseek(f->fd, 0, SEEK_CUR)) != -1) {
|
||||
if (f->beg < f->end) pos -= f->end - f->beg;
|
||||
return pos;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
@ -78,12 +79,10 @@ size_t fwrite(const void *data, size_t stride, size_t count, FILE *f) {
|
|||
iov[1].iov_base = data;
|
||||
iov[1].iov_len = n;
|
||||
n += f->beg;
|
||||
if ((rc = writev(f->fd, iov, 2)) == -1) {
|
||||
if (WritevUninterruptible(f->fd, iov, 2) == -1) {
|
||||
f->state = errno;
|
||||
return 0;
|
||||
}
|
||||
m = rc;
|
||||
if (n != m) abort();
|
||||
f->beg = 0;
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ extern char g_stdinbuf[BUFSIZ];
|
|||
extern char g_stdoutbuf[BUFSIZ];
|
||||
extern char g_stderrbuf[BUFSIZ];
|
||||
|
||||
int __fflush_impl(FILE *) hidden;
|
||||
int __fflush_register(FILE *) hidden;
|
||||
void __fflush_unregister(FILE *) hidden;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
@ -26,9 +27,17 @@ struct state {
|
|||
int n;
|
||||
};
|
||||
|
||||
static noinstrument int vfprintfputchar(int c, struct state *st) {
|
||||
st->n++;
|
||||
return fputc(c, st->f);
|
||||
static int vfprintfputchar(const char *s, struct state *t, size_t n) {
|
||||
if (n) {
|
||||
if (n == 1 && *s != '\n' && t->f->beg < t->f->size &&
|
||||
t->f->bufmode != _IONBF) {
|
||||
t->f->buf[t->f->beg++] = *s;
|
||||
} else if (!fwrite(s, 1, n, t->f)) {
|
||||
return -1;
|
||||
}
|
||||
t->n += n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int(vfprintf)(FILE *f, const char *fmt, va_list va) {
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
/*-*- 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/nexgen32e/crc32.h"
|
||||
|
||||
extern const uint32_t kCrc32cTab[256];
|
||||
|
||||
/**
|
||||
* Computes Castagnoli CRC-32 on old computers.
|
||||
*/
|
||||
uint32_t crc32c_pure(uint32_t init, const void *data, size_t size) {
|
||||
const unsigned char *p = data;
|
||||
uint32_t h = init ^ 0xffffffff;
|
||||
unsigned i;
|
||||
for (i = 0; i < size; i++) {
|
||||
h = h >> 8 ^ kCrc32cTab[(h & 0xff) ^ p[i]];
|
||||
}
|
||||
return h ^ 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
bench_crc32c_pure for #c per n where c ≈ 0.293ns
|
||||
N x1 x8 x64 mBps
|
||||
------------------------------------------------------------
|
||||
1 4305.000 91.375 44.203 74
|
||||
1 75.000 55.875 44.703 73
|
||||
2 46.500 35.188 24.617 132
|
||||
3 40.333 26.625 19.193 169
|
||||
4 32.250 19.969 16.215 200
|
||||
7 18.429 15.089 12.033 270
|
||||
8 20.625 13.547 11.607 280
|
||||
15 15.667 10.775 9.589 339
|
||||
16 17.562 10.695 9.419 345
|
||||
31 12.226 8.891 8.317 391
|
||||
32 13.219 8.480 8.078 402
|
||||
63 9.571 8.065 7.731 420
|
||||
64 9.672 7.955 7.633 426
|
||||
127 8.433 7.548 7.329 443
|
||||
128 8.492 7.528 7.352 442
|
||||
255 7.557 7.366 7.239 449
|
||||
256 7.699 7.342 7.305 445
|
||||
511 7.376 7.243 7.223 450
|
||||
512 7.408 7.233 7.225 450
|
||||
1023 7.188 7.192 7.098 458
|
||||
1024 7.171 7.194 7.097 458
|
||||
2047 7.130 7.172 7.085 459
|
||||
2048 7.117 7.170 7.169 453
|
||||
4095 7.063 7.076 7.085 459
|
||||
4096 7.078 7.161 7.081 459
|
||||
8191 7.041 7.095 7.055 461
|
||||
8192 7.051 7.098 7.087 459
|
||||
16383 7.039 7.114 7.067 460
|
||||
16384 6.876 6.931 7.133 456
|
||||
32767 7.055 7.108 7.290 446
|
||||
32768 6.868 6.887 6.974 466
|
||||
65535 6.984 6.885 6.967 467
|
||||
65536 6.877 6.924 10.994 296
|
||||
131071 7.166 7.141 7.011 464
|
||||
131072 6.853 6.971 7.694 422
|
||||
262143 6.853 7.213 7.406 439
|
||||
262144 6.852 6.968 7.290 446
|
||||
524287 7.398 7.389 7.166 454
|
||||
524288 6.851 7.094 7.159 454
|
||||
*/
|
|
@ -1,95 +0,0 @@
|
|||
/*-*- 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/str/internal.h"
|
||||
|
||||
/**
|
||||
* Hashes data with hardware acceleration at 10GBps.
|
||||
* @note needs Nehalem+ c. 2008 or Bulldozer+ c. 2011
|
||||
*/
|
||||
optimizespeed uint32_t crc32c_sse42(uint32_t init, const void *data, size_t n) {
|
||||
const unsigned char *p = (const unsigned char *)data;
|
||||
const unsigned char *pe = (const unsigned char *)data + n;
|
||||
uint32_t h = init ^ 0xffffffff;
|
||||
if (n >= 16 + 8) {
|
||||
while ((uintptr_t)p & 7) asm("crc32b\t%1,%0" : "+r"(h) : "rm"(*p++));
|
||||
uint64_t hl = h;
|
||||
while (p < pe - 16ul) {
|
||||
asm("crc32q\t%1,%0" : "+r"(hl) : "rm"(*(const uint64_t *)p));
|
||||
p += 8;
|
||||
asm("crc32q\t%1,%0" : "+r"(hl) : "rm"(*(const uint64_t *)p));
|
||||
p += 8;
|
||||
}
|
||||
h = (uint32_t)hl;
|
||||
}
|
||||
while (p < pe) asm("crc32b\t%1,%0" : "+r"(h) : "rm"(*p++));
|
||||
return h ^ 0xffffffff;
|
||||
}
|
||||
|
||||
/*
|
||||
bench_crc32c_sse42 for #c per n where c ≈ 0.293ns
|
||||
N x1 x8 x64 mBps
|
||||
------------------------------------------------------------
|
||||
1 877.000 43.375 40.359 81
|
||||
1 45.000 39.625 40.484 80
|
||||
2 34.500 27.562 20.461 159
|
||||
3 23.000 16.708 14.245 228
|
||||
4 18.250 13.094 11.449 284
|
||||
7 10.429 8.339 8.185 397
|
||||
8 42.125 8.734 6.850 475
|
||||
15 9.400 5.375 4.884 665
|
||||
16 7.312 5.070 4.882 666
|
||||
31 5.258 2.923 2.680 1213
|
||||
32 3.969 2.676 2.562 1269
|
||||
63 3.095 1.581 1.428 2276
|
||||
64 2.234 1.623 1.478 2199
|
||||
127 1.205 0.901 0.900 3610
|
||||
128 1.164 0.960 0.915 3552
|
||||
255 0.922 0.651 0.618 5260
|
||||
256 0.715 0.650 0.609 5341
|
||||
511 0.558 0.482 0.477 6819
|
||||
512 0.529 0.475 0.469 6932
|
||||
1023 0.425 0.400 0.396 8204
|
||||
1024 0.417 0.392 0.388 8383
|
||||
2047 0.367 0.355 0.353 9199
|
||||
2048 0.374 0.366 0.364 8929
|
||||
4095 0.351 0.338 0.337 9644
|
||||
4096 0.353 0.338 0.338 9624
|
||||
8191 0.335 0.338 0.337 9641
|
||||
8192 0.335 0.329 0.329 9870
|
||||
16383 0.336 0.325 0.325 10011
|
||||
16384 0.336 0.326 0.375 8666
|
||||
32767 0.329 0.323 0.323 10070
|
||||
32768 0.327 0.324 0.323 10062
|
||||
65535 0.322 0.322 0.322 10103
|
||||
65536 0.321 0.322 0.322 10102
|
||||
131071 0.322 0.321 0.321 10125
|
||||
131072 0.321 0.321 0.321 10124
|
||||
262143 0.322 0.321 0.335 9699
|
||||
262144 0.321 0.321 0.321 10134
|
||||
524287 0.321 0.321 0.499 6516
|
||||
524288 0.321 0.321 0.339 9575
|
||||
1048575 0.322 0.321 0.322 10095
|
||||
1048576 0.320 1.001 0.323 10048
|
||||
2097151 0.325 0.321 0.322 10086
|
||||
2097152 0.330 0.320 0.323 10076
|
||||
4194303 0.331 0.322 0.321 10128
|
||||
4194304 0.332 0.321 0.325 10004
|
||||
8388607 0.334 0.332 0.331 9829
|
||||
8388608 0.334 0.329 0.327 9934
|
||||
*/
|
|
@ -1,43 +0,0 @@
|
|||
/*-*- 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 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/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
// Computes 32-bit Castagnoli Cyclic Redundancy Check.
|
||||
//
|
||||
// @param edi is the initial hash value (0 is fine)
|
||||
// @param rsi points to the data
|
||||
// @param rdx is the byte size of data
|
||||
// @return eax is the new hash value
|
||||
// @note Used by ISCSI, TensorFlow, etc.
|
||||
.initbss 300,_init_crc32c
|
||||
crc32c: .quad 0
|
||||
.endobj crc32c,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init_crc32c
|
||||
ezlea crc32c_pure,ax
|
||||
ezlea crc32c_sse42,cx
|
||||
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
||||
cmovnz %rcx,%rax
|
||||
stosq
|
||||
.init.end 300,_init_crc32c
|
||||
.source __FILE__
|
50
libc/str/crc32c.c
Normal file
50
libc/str/crc32c.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- 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/nexgen32e/crc32.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
|
||||
/**
|
||||
* Computes 32-bit Castagnoli Cyclic Redundancy Check.
|
||||
*
|
||||
* @param init is the initial hash value
|
||||
* @param data points to the data
|
||||
* @param size is the byte size of data
|
||||
* @return eax is the new hash value
|
||||
* @note Used by ISCSI, TensorFlow, etc.
|
||||
*/
|
||||
uint32_t crc32c(uint32_t init, const void *data, size_t size) {
|
||||
uint64_t h;
|
||||
const unsigned char *p, *pe;
|
||||
p = data;
|
||||
pe = p + size;
|
||||
h = init ^ 0xffffffff;
|
||||
if (X86_HAVE(SSE4_2)) {
|
||||
for (; p + 8 <= pe; p += 8) {
|
||||
asm("crc32q\t%1,%0" : "+r"(h) : "rm"(*(const uint64_t *)p));
|
||||
}
|
||||
while (p < pe) {
|
||||
asm("crc32b\t%1,%0" : "+r"(h) : "rm"(*p++));
|
||||
}
|
||||
} else {
|
||||
while (p < pe) {
|
||||
h = h >> 8 ^ kCrc32cTab[(h & 0xff) ^ *p++];
|
||||
}
|
||||
}
|
||||
return h ^ 0xffffffff;
|
||||
}
|
53
libc/str/getzipcdir.c
Normal file
53
libc/str/getzipcdir.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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,14 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "net/http/uri.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
TEST(urischeme, test) {
|
||||
EXPECT_EQ(kUriSchemeSip, urischeme((struct UriSlice){0, 3}, "sips"));
|
||||
}
|
||||
|
||||
BENCH(urischeme, bench) {
|
||||
EZBENCH(donothing, urischeme((struct UriSlice){0, 3}, "sips"));
|
||||
/**
|
||||
* Returns comment of zip central directory.
|
||||
*/
|
||||
void *GetZipCdirComment(const uint8_t *eocd) {
|
||||
if (READ32LE(eocd) == kZipCdir64HdrMagic) {
|
||||
return ZIP_CDIR64_COMMENT(eocd);
|
||||
} else {
|
||||
return ZIP_CDIR_COMMENT(eocd);
|
||||
}
|
||||
}
|
|
@ -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,15 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "net/http/uri.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
struct UriSlice uripath(const struct Uri *uri) {
|
||||
if (uri->segs.i) {
|
||||
return (struct UriSlice){
|
||||
uri->segs.p[0].i,
|
||||
(uri->segs.p[uri->segs.i - 1].n +
|
||||
(uri->segs.p[uri->segs.i - 1].i - uri->segs.p[0].i))};
|
||||
/**
|
||||
* Returns comment of zip central directory.
|
||||
*/
|
||||
uint64_t GetZipCdirCommentSize(const uint8_t *eocd) {
|
||||
if (READ32LE(eocd) == kZipCdir64HdrMagic) {
|
||||
return ZIP_CDIR64_COMMENTSIZE(eocd);
|
||||
} else {
|
||||
return (struct UriSlice){0, 0};
|
||||
return ZIP_CDIR_COMMENTSIZE(eocd);
|
||||
}
|
||||
}
|
|
@ -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,20 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "net/http/geturischeme.inc"
|
||||
#include "net/http/uri.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
/**
|
||||
* Returns nonzero numeric code for resource paradigms we like.
|
||||
*
|
||||
* Lookups are case-insensitive and performed using a hash table that's
|
||||
* literally perfect.
|
||||
* Returns offset of zip central directory.
|
||||
*/
|
||||
enum UriScheme urischeme(struct UriSlice scheme, const char *str) {
|
||||
const struct UriSchemeSlot *slot;
|
||||
if ((slot = in_word_set(str + scheme.i, scheme.n))) {
|
||||
return slot->code;
|
||||
uint64_t GetZipCdirOffset(const uint8_t *eocd) {
|
||||
if (READ32LE(eocd) == kZipCdir64HdrMagic) {
|
||||
return ZIP_CDIR64_OFFSET(eocd);
|
||||
} else {
|
||||
return 0;
|
||||
return ZIP_CDIR_OFFSET(eocd);
|
||||
}
|
||||
}
|
30
libc/str/getzipcdirrecords.c
Normal file
30
libc/str/getzipcdirrecords.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
37
libc/str/getzipcfilecompressedsize.c
Normal file
37
libc/str/getzipcfilecompressedsize.c
Normal file
|
@ -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;
|
||||
}
|
47
libc/str/getzipcfilemode.c
Normal file
47
libc/str/getzipcfilemode.c
Normal file
|
@ -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));
|
||||
}
|
||||
}
|
37
libc/str/getzipcfileoffset.c
Normal file
37
libc/str/getzipcfileoffset.c
Normal file
|
@ -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;
|
||||
}
|
37
libc/str/getzipcfileuncompressedsize.c
Normal file
37
libc/str/getzipcfileuncompressedsize.c
Normal file
|
@ -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;
|
||||
}
|
37
libc/str/getziplfilecompressedsize.c
Normal file
37
libc/str/getziplfilecompressedsize.c
Normal file
|
@ -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;
|
||||
}
|
38
libc/str/getziplfileuncompressedsize.c
Normal file
38
libc/str/getziplfileuncompressedsize.c
Normal file
|
@ -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;
|
||||
}
|
38
libc/str/iszipcdir32.c
Normal file
38
libc/str/iszipcdir32.c
Normal file
|
@ -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;
|
||||
}
|
41
libc/str/iszipcdir64.c
Normal file
41
libc/str/iszipcdir64.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 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan size_t stpcpy_sse2(char *d, const char *s, size_t i) {
|
||||
static inline noasan size_t stpcpy_sse2(char *d, const char *s, size_t i) {
|
||||
uint8_t v1[16], v2[16], vz[16];
|
||||
for (;;) {
|
||||
memset(vz, 0, 16);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § characters » asa x3.4-1967 ─╬─│┼
|
||||
│ cosmopolitan § characters » usas x3.4-1967 ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│─╝
|
||||
fourth age telecommunications */
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue