mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-10 10:41:27 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce9aeb2aed | ||
|
|
ed93fc3dd7 | ||
|
|
5f61d273e4 | ||
|
|
bf3531de81 | ||
|
|
3b0ea2db4d | ||
|
|
f029375d39 | ||
|
|
9b87dd2b87 | ||
|
|
787b04f752 | ||
|
|
0768807935 | ||
|
|
0b59f01b43 | ||
|
|
cf70a44756 | ||
|
|
a52792c59f | ||
|
|
65c9b28e99 | ||
|
|
4292348707 | ||
|
|
2ec20b6c4c | ||
|
|
47183551d6 | ||
|
|
42891e82bb | ||
|
|
624119ea38 | ||
|
|
2f3c6e7cc3 | ||
|
|
13b9ecd537 | ||
|
|
6659981457 | ||
|
|
ae2a7ac844 | ||
|
|
793393a341 | ||
|
|
952b9009e8 | ||
|
|
8f18b3ad65 | ||
|
|
56e0fd9d1d |
No files matched your search
@@ -149,9 +149,9 @@ export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
COSMOCC = .cosmocc/3.3.3
|
||||
COSMOCC = .cosmocc/3.3.5
|
||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.3 e4d0fa63cd79cc3bfff6c2d015f1776db081409907625aea8ad40cefc1996d08)
|
||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.3.5 db78fd8d3f8706e9dff4be72bf71d37a3f12062f212f407e1c33bc4af3780dd0)
|
||||
|
||||
AS = $(TOOLCHAIN)as
|
||||
CC = $(TOOLCHAIN)gcc
|
||||
|
||||
+18
-1
@@ -254,7 +254,24 @@ o/$(MODE)/ape: $(APE_CHECKS) \
|
||||
endif
|
||||
|
||||
# these assembly files are safe to build on aarch64
|
||||
o/$(MODE)/ape/ape.o: ape/ape.S
|
||||
o/$(MODE)/ape/ape.o: \
|
||||
ape/ape.S \
|
||||
ape/ape.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
ape/relocations.h \
|
||||
libc/thread/tls.h \
|
||||
ape/ape.internal.h \
|
||||
ape/macros.internal.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
libc/calls/metalfile.internal.h
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
|
||||
+3
-4
@@ -293,7 +293,6 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
+3
-1
@@ -553,7 +553,9 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tls_align = 1;
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
|
||||
+11
-4
@@ -137,13 +137,20 @@ if [ x"$(uname -s)" = xLinux ]; then
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
uname_r="$(uname -r)"
|
||||
if printf '%s\n%s\n' 5.12 "$uname_r" | sort -CV; then
|
||||
FLAGS=FP
|
||||
else
|
||||
FLAGS=F
|
||||
fi
|
||||
|
||||
echo >&2
|
||||
echo registering APE with binfmt_misc >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
|
||||
@@ -16,6 +16,8 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_align[] __attribute__((__weak__));
|
||||
extern unsigned char _tbss_align[] __attribute__((__weak__));
|
||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||
extern unsigned char __ro[] __attribute__((__weak__));
|
||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
||||
|
||||
@@ -63,10 +63,6 @@ BACKTRACES = \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
ifneq ($(ARCH), aarch64)
|
||||
BACKTRACES += -fno-schedule-insns2
|
||||
endif
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
__static_yoink("__die");
|
||||
__static_yoink("GetSymbolByAddr");
|
||||
__static_yoink("malloc_inspect_all");
|
||||
|
||||
char *lol(int n) {
|
||||
return malloc(n);
|
||||
}
|
||||
|
||||
char *(*pLol)(int) = lol;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *s = pLol(4);
|
||||
s[4] = 1;
|
||||
}
|
||||
+18
-21
@@ -23,6 +23,7 @@
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/utf16.h"
|
||||
@@ -31,16 +32,14 @@
|
||||
|
||||
#define APPEND(c) \
|
||||
do { \
|
||||
if (k == 32766) { \
|
||||
return e2big(); \
|
||||
} \
|
||||
cmdline[k++] = c; \
|
||||
if (k < size) \
|
||||
cmdline[k] = c; \
|
||||
++k; \
|
||||
} while (0)
|
||||
|
||||
static bool NeedsQuotes(const char *s) {
|
||||
if (!*s) {
|
||||
static textwindows bool NeedsQuotes(const char *s) {
|
||||
if (!*s)
|
||||
return true;
|
||||
}
|
||||
do {
|
||||
switch (*s) {
|
||||
case '"':
|
||||
@@ -60,7 +59,7 @@ static inline int IsAlpha(int c) {
|
||||
return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
|
||||
}
|
||||
|
||||
static bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
static textwindows bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
return s[0] == '/' && //
|
||||
IsAlpha(s[1]) && //
|
||||
s[2] == '/';
|
||||
@@ -74,12 +73,13 @@ static bool LooksLikeCosmoDrivePath(const char *s) {
|
||||
//
|
||||
// @param cmdline is output buffer
|
||||
// @param argv is an a NULL-terminated array of UTF-8 strings
|
||||
// @return 0 on success, or -1 w/ errno
|
||||
// @raise E2BIG if everything is too huge
|
||||
// @param size is number of characters in cmdline buffer
|
||||
// @return length on success, which is >=size on truncation
|
||||
// @see "Everyone quotes command line arguments the wrong way" MSDN
|
||||
// @see libc/runtime/getdosargv.c
|
||||
// @asyncsignalsafe
|
||||
textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
textwindows size_t mkntcmdline(char16_t *cmdline, char *const argv[],
|
||||
size_t size) {
|
||||
char *arg;
|
||||
int slashes, n;
|
||||
bool needsquote;
|
||||
@@ -95,9 +95,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
} else {
|
||||
arg = argv[i];
|
||||
}
|
||||
if ((needsquote = NeedsQuotes(arg))) {
|
||||
if ((needsquote = NeedsQuotes(arg)))
|
||||
APPEND(u'"');
|
||||
}
|
||||
for (slashes = j = 0;;) {
|
||||
wint_t x = arg[j++] & 255;
|
||||
if (x >= 0300) {
|
||||
@@ -122,9 +121,8 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
APPEND(u'"');
|
||||
APPEND(u'"');
|
||||
} else {
|
||||
for (s = 0; s < slashes; ++s) {
|
||||
for (s = 0; s < slashes; ++s)
|
||||
APPEND(u'\\');
|
||||
}
|
||||
slashes = 0;
|
||||
uint32_t w = EncodeUtf16(x);
|
||||
do
|
||||
@@ -132,13 +130,12 @@ textwindows int mkntcmdline(char16_t cmdline[32767], char *const argv[]) {
|
||||
while ((w >>= 16));
|
||||
}
|
||||
}
|
||||
for (s = 0; s < (slashes << needsquote); ++s) {
|
||||
for (s = 0; s < (slashes << needsquote); ++s)
|
||||
APPEND(u'\\');
|
||||
}
|
||||
if (needsquote) {
|
||||
if (needsquote)
|
||||
APPEND(u'"');
|
||||
}
|
||||
}
|
||||
cmdline[k] = 0;
|
||||
return 0;
|
||||
if (size)
|
||||
cmdline[MIN(k, size - 1)] = 0;
|
||||
return k;
|
||||
}
|
||||
+168
-86
@@ -20,9 +20,15 @@
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/enum/processaccess.h"
|
||||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/events.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
@@ -33,6 +39,7 @@
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/nt/struct/startupinfoex.h"
|
||||
#include "libc/proc/ntspawn.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#ifdef __x86_64__
|
||||
@@ -44,14 +51,167 @@ struct SpawnBlock {
|
||||
char envbuf[32767];
|
||||
};
|
||||
|
||||
static void *ntspawn_malloc(size_t size) {
|
||||
static textwindows void *ntspawn_malloc(size_t size) {
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
}
|
||||
|
||||
static void ntspawn_free(void *ptr) {
|
||||
static textwindows void ntspawn_free(void *ptr) {
|
||||
HeapFree(GetProcessHeap(), 0, ptr);
|
||||
}
|
||||
|
||||
static textwindows ssize_t ntspawn_read(intptr_t fh, char *buf, size_t len) {
|
||||
bool ok;
|
||||
uint32_t got;
|
||||
struct NtOverlapped overlap = {.hEvent = CreateEvent(0, 0, 0, 0)};
|
||||
ok = (ReadFile(fh, buf, len, 0, &overlap) ||
|
||||
GetLastError() == kNtErrorIoPending) &&
|
||||
GetOverlappedResult(fh, &overlap, &got, true);
|
||||
CloseHandle(overlap.hEvent);
|
||||
return ok ? got : -1;
|
||||
}
|
||||
|
||||
static textwindows int ntspawn2(struct NtSpawnArgs *a, struct SpawnBlock *sb) {
|
||||
|
||||
// make executable path
|
||||
if (__mkntpathath(a->dirhand, a->prog, 0, sb->path) == -1)
|
||||
return -1;
|
||||
|
||||
// open executable
|
||||
char *p = sb->envbuf;
|
||||
char *pe = p + sizeof(sb->envbuf);
|
||||
intptr_t fh = CreateFile(
|
||||
sb->path, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting, kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0);
|
||||
if (fh == -1)
|
||||
return -1;
|
||||
ssize_t got = ntspawn_read(fh, p, pe - p);
|
||||
CloseHandle(fh);
|
||||
if (got < 3)
|
||||
return enoexec();
|
||||
pe = p + got;
|
||||
|
||||
// handle shebang
|
||||
size_t i = 0; // represents space of sb->cmdline consumed
|
||||
if (p[0] == 'M' && p[1] == 'Z') {
|
||||
// it's a windows executable
|
||||
} else if (p[0] == '#' && p[1] == '!') {
|
||||
p += 2;
|
||||
// make sure we got a complete first line
|
||||
pe = memchr(p, '\n', pe - p);
|
||||
if (!pe)
|
||||
return enoexec();
|
||||
*pe = 0;
|
||||
int argc = 0;
|
||||
char *argv[4];
|
||||
// it's legal to say "#! /bin/sh"
|
||||
while (p < pe && (*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p == pe)
|
||||
return enoexec();
|
||||
argv[argc++] = p;
|
||||
// find the optional argument
|
||||
while (p < pe && !(*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p < pe) {
|
||||
*p++ = 0;
|
||||
while (p < pe && (*p == ' ' || *p == '\t'))
|
||||
++p;
|
||||
if (p < pe) {
|
||||
argv[argc++] = p;
|
||||
}
|
||||
}
|
||||
// now add the prog
|
||||
argv[argc++] = (char *)a->prog;
|
||||
argv[argc] = 0;
|
||||
// ignore argv[0]
|
||||
if (*a->argv)
|
||||
++a->argv;
|
||||
// prepend arguments
|
||||
if ((i += mkntcmdline(sb->cmdline + i, argv, 32767 - i)) >= 32767 - 1)
|
||||
return e2big();
|
||||
sb->cmdline[i++] = ' ';
|
||||
sb->cmdline[i] = 0;
|
||||
// setup the true executable path
|
||||
if (__mkntpathath(a->dirhand, argv[0], 0, sb->path) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
// it's something else
|
||||
return enoexec();
|
||||
}
|
||||
|
||||
// setup arguments and environment
|
||||
if ((i += mkntcmdline(sb->cmdline + i, a->argv, 32767 - i)) >= 32767)
|
||||
return e2big();
|
||||
if (mkntenvblock(sb->envblock, a->envp, a->extravars, sb->envbuf) == -1)
|
||||
return -1;
|
||||
|
||||
// create attribute list
|
||||
// this code won't call malloc in practice
|
||||
bool32 ok;
|
||||
void *freeme = 0;
|
||||
alignas(16) char memory[128];
|
||||
size_t size = sizeof(memory);
|
||||
struct NtProcThreadAttributeList *alist = (void *)memory;
|
||||
uint32_t items = !!a->opt_hParentProcess + !!a->opt_lpExplicitHandleList;
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
|
||||
ok = !!(alist = freeme = ntspawn_malloc(size));
|
||||
if (ok) {
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
}
|
||||
}
|
||||
if (ok && a->opt_hParentProcess) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeParentProcess, &a->opt_hParentProcess,
|
||||
sizeof(a->opt_hParentProcess), 0, 0);
|
||||
}
|
||||
if (ok && a->opt_lpExplicitHandleList) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeHandleList, a->opt_lpExplicitHandleList,
|
||||
a->dwExplicitHandleCount * sizeof(*a->opt_lpExplicitHandleList), 0, 0);
|
||||
}
|
||||
|
||||
// create the process
|
||||
int rc;
|
||||
if (ok) {
|
||||
struct NtStartupInfoEx info = {
|
||||
.StartupInfo = *a->lpStartupInfo,
|
||||
.StartupInfo.cb = sizeof(info),
|
||||
.lpAttributeList = alist,
|
||||
};
|
||||
if (ok) {
|
||||
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
|
||||
a->dwCreationFlags | kNtCreateUnicodeEnvironment |
|
||||
kNtExtendedStartupinfoPresent |
|
||||
kNtInheritParentAffinity |
|
||||
GetPriorityClass(GetCurrentProcess()),
|
||||
sb->envblock, a->opt_lpCurrentDirectory,
|
||||
&info.StartupInfo, a->opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
STRACE("CreateProcess() failed w/ %d", GetLastError());
|
||||
if (GetLastError() == kNtErrorSharingViolation) {
|
||||
etxtbsy();
|
||||
} else if (GetLastError() == kNtErrorInvalidName) {
|
||||
enoent();
|
||||
}
|
||||
}
|
||||
rc = __fix_enotdir(rc, sb->path);
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
|
||||
// clean up resources
|
||||
if (alist)
|
||||
DeleteProcThreadAttributeList(alist);
|
||||
if (freeme)
|
||||
ntspawn_free(freeme);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawns process on Windows NT.
|
||||
*
|
||||
@@ -72,93 +232,15 @@ static void ntspawn_free(void *ptr) {
|
||||
* @see spawnve() which abstracts this function
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
textwindows int ntspawn(
|
||||
int64_t dirhand, const char *prog, char *const argv[], char *const envp[],
|
||||
char *const extravars[], uint32_t dwCreationFlags,
|
||||
const char16_t *opt_lpCurrentDirectory, int64_t opt_hParentProcess,
|
||||
int64_t *opt_lpExplicitHandleList, uint32_t dwExplicitHandleCount,
|
||||
const struct NtStartupInfo *lpStartupInfo,
|
||||
struct NtProcessInformation *opt_out_lpProcessInformation) {
|
||||
int rc = -1;
|
||||
textwindows int ntspawn(struct NtSpawnArgs *args) {
|
||||
int rc;
|
||||
struct SpawnBlock *sb;
|
||||
BLOCK_SIGNALS;
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb))) &&
|
||||
__mkntpathath(dirhand, prog, 0, sb->path) != -1) {
|
||||
if (!mkntcmdline(sb->cmdline, argv) &&
|
||||
!mkntenvblock(sb->envblock, envp, extravars, sb->envbuf)) {
|
||||
bool32 ok;
|
||||
int64_t dp = GetCurrentProcess();
|
||||
|
||||
// create attribute list
|
||||
// this code won't call malloc in practice
|
||||
void *freeme = 0;
|
||||
_Alignas(16) char memory[128];
|
||||
size_t size = sizeof(memory);
|
||||
struct NtProcThreadAttributeList *alist = (void *)memory;
|
||||
uint32_t items = !!opt_hParentProcess + !!opt_lpExplicitHandleList;
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
if (!ok && GetLastError() == kNtErrorInsufficientBuffer) {
|
||||
ok = !!(alist = freeme = ntspawn_malloc(size));
|
||||
if (ok) {
|
||||
ok = InitializeProcThreadAttributeList(alist, items, 0, &size);
|
||||
}
|
||||
}
|
||||
if (ok && opt_hParentProcess) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeParentProcess, &opt_hParentProcess,
|
||||
sizeof(opt_hParentProcess), 0, 0);
|
||||
}
|
||||
if (ok && opt_lpExplicitHandleList) {
|
||||
ok = UpdateProcThreadAttribute(
|
||||
alist, 0, kNtProcThreadAttributeHandleList,
|
||||
opt_lpExplicitHandleList,
|
||||
dwExplicitHandleCount * sizeof(*opt_lpExplicitHandleList), 0, 0);
|
||||
}
|
||||
|
||||
// create the process
|
||||
if (ok) {
|
||||
struct NtStartupInfoEx info;
|
||||
bzero(&info, sizeof(info));
|
||||
info.StartupInfo = *lpStartupInfo;
|
||||
info.StartupInfo.cb = sizeof(info);
|
||||
info.lpAttributeList = alist;
|
||||
if (ok) {
|
||||
if (CreateProcess(sb->path, sb->cmdline, 0, 0, true,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment |
|
||||
kNtExtendedStartupinfoPresent |
|
||||
kNtInheritParentAffinity |
|
||||
GetPriorityClass(GetCurrentProcess()),
|
||||
sb->envblock, opt_lpCurrentDirectory,
|
||||
&info.StartupInfo, opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
STRACE("CreateProcess() failed w/ %d", GetLastError());
|
||||
if (GetLastError() == kNtErrorSharingViolation) {
|
||||
etxtbsy();
|
||||
} else if (GetLastError() == kNtErrorInvalidName) {
|
||||
enoent();
|
||||
}
|
||||
}
|
||||
rc = __fix_enotdir(rc, sb->path);
|
||||
}
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
|
||||
// clean up resources
|
||||
if (alist) {
|
||||
DeleteProcThreadAttributeList(alist);
|
||||
}
|
||||
if (freeme) {
|
||||
ntspawn_free(freeme);
|
||||
}
|
||||
if (dp && dp != GetCurrentProcess()) {
|
||||
CloseHandle(dp);
|
||||
}
|
||||
}
|
||||
if ((sb = ntspawn_malloc(sizeof(*sb)))) {
|
||||
rc = ntspawn2(args, sb);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
if (sb)
|
||||
ntspawn_free(sb);
|
||||
ALLOW_SIGNALS;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1641,7 +1641,6 @@ static privileged void AllowMmapExec(struct Filter *f) {
|
||||
//
|
||||
// - MAP_LOCKED (0x02000)
|
||||
// - MAP_NONBLOCK (0x10000)
|
||||
// - MAP_HUGETLB (0x40000)
|
||||
//
|
||||
static privileged void AllowMmapNoexec(struct Filter *f) {
|
||||
static const struct sock_filter fragment[] = {
|
||||
@@ -1650,7 +1649,7 @@ static privileged void AllowMmapNoexec(struct Filter *f) {
|
||||
/*L2*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~(PROT_READ | PROT_WRITE)),
|
||||
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 8 - 4),
|
||||
/*L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[3])), // flags
|
||||
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x52000),
|
||||
/*L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x12000),
|
||||
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 0, 1),
|
||||
/*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
/*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||
|
||||
@@ -252,6 +252,12 @@ static int __sigaction(int sig, const struct sigaction *act,
|
||||
rc = sys_sigaction(sig, ap, oldact, arg4, arg5);
|
||||
} else {
|
||||
rc = _sysret(__syslib->__sigaction(sig, ap, oldact));
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (!rc && oldact &&
|
||||
(((struct sigaction_silicon *)oldact)->sa_flags & SA_RESETHAND)) {
|
||||
((struct sigaction_silicon *)oldact)->sa_flags |= SA_RESETHAND;
|
||||
}
|
||||
}
|
||||
if (rc != -1) {
|
||||
sigaction_native2cosmo((union metasigaction *)oldact);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
||||
@@ -494,6 +495,8 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||
privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
struct __darwin_ucontext *xnuctx) {
|
||||
#endif
|
||||
|
||||
// allocate signal frame on stack
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Wframe-larger-than="
|
||||
struct Goodies {
|
||||
@@ -502,10 +505,24 @@ privileged void __sigenter_xnu(int sig, struct siginfo_xnu *xnuinfo,
|
||||
} g;
|
||||
CheckLargeStackAllocation(&g, sizeof(g));
|
||||
#pragma GCC pop_options
|
||||
|
||||
// handle signal
|
||||
int rva, flags;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
flags = __sighandflags[sig];
|
||||
|
||||
#ifdef __aarch64__
|
||||
// xnu silicon claims to support sa_resethand but it does nothing
|
||||
// this can be tested, since it clears the bit from flags as well
|
||||
if (flags & SA_RESETHAND) {
|
||||
struct sigaction sa = {0};
|
||||
__syslib->__sigaction(sig, &sa, 0);
|
||||
__sighandflags[sig] = 0;
|
||||
__sighandrvas[sig] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (~flags & SA_SIGINFO) {
|
||||
((sigaction_f)(__executable_start + rva))(sig, 0, 0);
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "libc/mem/alloca.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
ssize_t __robust_writev(int, struct iovec *, int);
|
||||
int64_t sys_preadv(int, struct iovec *, int, int64_t, int64_t);
|
||||
int64_t sys_pwritev(int, const struct iovec *, int, int64_t, int64_t);
|
||||
int64_t sys_readv(int32_t, const struct iovec *, int32_t);
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ char *sleb64(char *p, int64_t x) {
|
||||
*p++ = c;
|
||||
return p;
|
||||
} else {
|
||||
*p++ = c | 64;
|
||||
*p++ = c | 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define __COSMOPOLITAN_MAJOR__ 3
|
||||
#define __COSMOPOLITAN_MINOR__ 3
|
||||
#define __COSMOPOLITAN_PATCH__ 5
|
||||
#define __COSMOPOLITAN_PATCH__ 7
|
||||
#define __COSMOPOLITAN__ \
|
||||
(100000000 * __COSMOPOLITAN_MAJOR__ + 1000000 * __COSMOPOLITAN_MINOR__ + \
|
||||
__COSMOPOLITAN_PATCH__)
|
||||
|
||||
+10
-1
@@ -82,7 +82,16 @@ o//libc/intrin/memcmp.o \
|
||||
o//libc/intrin/memset.o \
|
||||
o//libc/intrin/memmove.o: private \
|
||||
CFLAGS += \
|
||||
-O2 -finline -foptimize-sibling-calls
|
||||
-O2 \
|
||||
-finline \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
# make asan stack traces shorter
|
||||
o/$(MODE)/libc/intrin/asanthunk.o: private \
|
||||
CFLAGS += \
|
||||
-Os \
|
||||
$(NO_MAGIC) \
|
||||
-foptimize-sibling-calls
|
||||
|
||||
o/$(MODE)/libc/intrin/bzero.o \
|
||||
o/$(MODE)/libc/intrin/memcmp.o \
|
||||
|
||||
@@ -30,6 +30,7 @@ const char *(DescribeMapFlags)(char buf[64], int x) {
|
||||
{MAP_SHARED, "SHARED"}, //
|
||||
{MAP_FIXED, "FIXED"}, //
|
||||
{MAP_FIXED_NOREPLACE, "FIXED_NOREPLACE"}, //
|
||||
{MAP_HUGETLB, "HUGETLB"}, //
|
||||
{MAP_CONCEAL, "CONCEAL"}, //
|
||||
{MAP_LOCKED, "LOCKED"}, //
|
||||
{MAP_NORESERVE, "NORESERVE"}, //
|
||||
|
||||
@@ -78,17 +78,14 @@ int feenableexcept(int excepts) {
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
unsigned fpcr;
|
||||
unsigned fpcr2;
|
||||
unsigned updated_fpcr;
|
||||
fpcr = __builtin_aarch64_get_fpcr();
|
||||
fpcr2 = fpcr | (excepts << 8);
|
||||
unsigned fpcr = __builtin_aarch64_get_fpcr();
|
||||
unsigned want = excepts << 8;
|
||||
unsigned fpcr2 = fpcr | want;
|
||||
if (fpcr != fpcr2) {
|
||||
__builtin_aarch64_set_fpcr(fpcr2);
|
||||
// floating point exception trapping is optional in aarch64
|
||||
updated_fpcr = __builtin_aarch64_get_fpsr();
|
||||
if (fpcr2 & ~updated_fpcr)
|
||||
return -1;
|
||||
fpcr2 = __builtin_aarch64_get_fpsr();
|
||||
if ((fpcr2 & want) != want)
|
||||
return -1; // not supported by cpu
|
||||
}
|
||||
return (fpcr >> 8) & FE_ALL_EXCEPT;
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
_Alignas(1) static char strerror_buf[128];
|
||||
alignas(1) static char strerror_buf[128];
|
||||
|
||||
/**
|
||||
* Returns string describing `err`.
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
#define COSMOPOLITAN_LIBC_ISYSTEM_SYS_AUXV_H_
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/hwcap.h"
|
||||
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYS_AUXV_H_ */
|
||||
@@ -192,6 +192,8 @@ void ShowCrashReportHook(int, int, int, struct siginfo *, ucontext_t *);
|
||||
|
||||
static relegated void ShowCrashReport(int err, int sig, struct siginfo *si,
|
||||
ucontext_t *ctx) {
|
||||
if (sig != SIGTRAP && sig != SIGQUIT)
|
||||
sigaddset(&ctx->uc_sigmask, sig);
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
long size = __get_safe_size(8192, 4096);
|
||||
|
||||
@@ -191,6 +191,8 @@ static relegated char *GetSymbolName(struct SymbolTable *st, int symbol) {
|
||||
|
||||
static relegated void __oncrash_impl(int sig, struct siginfo *si,
|
||||
ucontext_t *ctx) {
|
||||
if (sig != SIGTRAP && sig != SIGQUIT)
|
||||
sigaddset(&ctx->uc_sigmask, sig);
|
||||
#pragma GCC push_options
|
||||
#pragma GCC diagnostic ignored "-Walloca-larger-than="
|
||||
long size = __get_safe_size(10000, 4096);
|
||||
|
||||
@@ -85,13 +85,13 @@ void ShowCrashReports(void) {
|
||||
#ifdef __x86_64__
|
||||
InstallCrashHandler(SIGTRAP, 0);
|
||||
#else
|
||||
InstallCrashHandler(SIGTRAP, SA_RESETHAND);
|
||||
InstallCrashHandler(SIGTRAP, 0);
|
||||
#endif
|
||||
InstallCrashHandler(SIGFPE, SA_RESETHAND);
|
||||
InstallCrashHandler(SIGILL, SA_RESETHAND);
|
||||
InstallCrashHandler(SIGBUS, SA_RESETHAND);
|
||||
InstallCrashHandler(SIGABRT, SA_RESETHAND);
|
||||
InstallCrashHandler(SIGSEGV, SA_RESETHAND | SA_ONSTACK);
|
||||
InstallCrashHandler(SIGFPE, 0);
|
||||
InstallCrashHandler(SIGILL, 0);
|
||||
InstallCrashHandler(SIGBUS, 0);
|
||||
InstallCrashHandler(SIGABRT, 0);
|
||||
InstallCrashHandler(SIGSEGV, SA_ONSTACK);
|
||||
}
|
||||
|
||||
IGNORE_LEAKS(ShowCrashReports)
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/stdckdint.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
@@ -29,7 +30,7 @@
|
||||
|
||||
#ifndef MODE_DBG /* don't interfere with asan dlmalloc hooking */
|
||||
|
||||
_Alignas(TINYMALLOC_MAX_ALIGN) static struct {
|
||||
alignas(TINYMALLOC_MAX_ALIGN) static struct {
|
||||
char memory[TINYMALLOC_MAX_BYTES];
|
||||
unsigned used, last, free;
|
||||
} heap;
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
_Alignas(uint8_t) const uint8_t kBase36[256] = {
|
||||
alignas(uint8_t) const uint8_t kBase36[256] = {
|
||||
['0'] = 1, //
|
||||
['1'] = 2, //
|
||||
['2'] = 3, //
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
_Alignas(uint8_t) const uint8_t kToLower[256] = {
|
||||
alignas(uint8_t) const uint8_t kToLower[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 30, 31, ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')',
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
_Alignas(uint8_t) const uint8_t kToUpper[256] = {
|
||||
alignas(uint8_t) const uint8_t kToUpper[256] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
|
||||
28, 29, 30, 31, ' ', '!', '\"', '#', '$', '%', '&', '\'', '(', ')',
|
||||
|
||||
@@ -91,9 +91,9 @@ textwindows int sys_execve_nt(const char *program, char *const argv[],
|
||||
|
||||
// launch the process
|
||||
struct NtProcessInformation pi;
|
||||
int rc = ntspawn(AT_FDCWD, program, argv, envp,
|
||||
(char *[]){fdspec, maskvar, 0}, 0, 0, hParentProcess,
|
||||
lpExplicitHandles, dwExplicitHandleCount, &si, &pi);
|
||||
int rc = ntspawn(&(struct NtSpawnArgs){
|
||||
AT_FDCWD, program, argv, envp, (char *[]){fdspec, maskvar, 0}, 0, 0,
|
||||
hParentProcess, lpExplicitHandles, dwExplicitHandleCount, &si, &pi});
|
||||
__undescribe_fds(hParentProcess, lpExplicitHandles, dwExplicitHandleCount);
|
||||
if (rc == -1) {
|
||||
free(fdspec);
|
||||
|
||||
+4
-3
@@ -344,9 +344,10 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
||||
}
|
||||
#endif
|
||||
NTTRACE("STARTING SPAWN");
|
||||
int spawnrc = ntspawn(AT_FDCWD, GetProgramExecutableName(), args, environ,
|
||||
(char *[]){forkvar, 0}, dwCreationFlags, 0, 0, 0, 0,
|
||||
&startinfo, &procinfo);
|
||||
int spawnrc = ntspawn(&(struct NtSpawnArgs){
|
||||
AT_FDCWD, GetProgramExecutableName(), args, environ,
|
||||
(char *[]){forkvar, 0}, dwCreationFlags, 0, 0, 0, 0, &startinfo,
|
||||
&procinfo});
|
||||
if (spawnrc != -1) {
|
||||
CloseHandle(procinfo.hThread);
|
||||
ok = WriteAll(writer, jb, sizeof(jb)) &&
|
||||
|
||||
+18
-5
@@ -4,12 +4,25 @@
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void mungentpath(char *);
|
||||
int mkntcmdline(char16_t[32767], char *const[]);
|
||||
struct NtSpawnArgs {
|
||||
int64_t dirhand;
|
||||
const char *prog;
|
||||
char *const *argv;
|
||||
char *const *envp;
|
||||
char *const *extravars;
|
||||
uint32_t dwCreationFlags;
|
||||
const char16_t *opt_lpCurrentDirectory;
|
||||
int64_t opt_hParentProcess;
|
||||
int64_t *opt_lpExplicitHandleList;
|
||||
uint32_t dwExplicitHandleCount;
|
||||
const struct NtStartupInfo *lpStartupInfo;
|
||||
struct NtProcessInformation *opt_out_lpProcessInformation;
|
||||
};
|
||||
|
||||
int mkntenvblock(char16_t[32767], char *const[], char *const[], char[32767]);
|
||||
int ntspawn(int64_t, const char *, char *const[], char *const[], char *const[],
|
||||
uint32_t, const char16_t *, int64_t, int64_t *, uint32_t,
|
||||
const struct NtStartupInfo *, struct NtProcessInformation *);
|
||||
int ntspawn(struct NtSpawnArgs *);
|
||||
size_t mkntcmdline(char16_t *, char *const[], size_t);
|
||||
void mungentpath(char *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_NTSPAWN_H_ */
|
||||
@@ -382,9 +382,10 @@ static textwindows errno_t posix_spawn_nt_impl(
|
||||
envp = environ;
|
||||
if ((fdspec = __describe_fds(fds.p, fds.n, &startinfo, hCreatorProcess,
|
||||
&lpExplicitHandles, &dwExplicitHandleCount))) {
|
||||
rc = ntspawn(dirhand, path, argv, envp, (char *[]){fdspec, maskvar, 0},
|
||||
dwCreationFlags, lpCurrentDirectory, 0, lpExplicitHandles,
|
||||
dwExplicitHandleCount, &startinfo, &procinfo);
|
||||
rc = ntspawn(&(struct NtSpawnArgs){
|
||||
dirhand, path, argv, envp, (char *[]){fdspec, maskvar, 0},
|
||||
dwCreationFlags, lpCurrentDirectory, 0, lpExplicitHandles,
|
||||
dwExplicitHandleCount, &startinfo, &procinfo});
|
||||
}
|
||||
if (rc == -1) {
|
||||
err = errno;
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
#define LWP_SUSPENDED 0x00000080
|
||||
|
||||
struct CloneArgs {
|
||||
_Alignas(16) union {
|
||||
alignas(16) union {
|
||||
struct {
|
||||
int tid;
|
||||
int this;
|
||||
|
||||
+40
-33
@@ -35,6 +35,7 @@
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
@@ -47,7 +48,7 @@
|
||||
extern unsigned char __tls_mov_nt_rax[];
|
||||
extern unsigned char __tls_add_nt_rax[];
|
||||
|
||||
_Alignas(TLS_ALIGNMENT) static char __static_tls[6016];
|
||||
alignas(TLS_ALIGNMENT) static char __static_tls[6016];
|
||||
|
||||
static unsigned long ParseMask(const char *str) {
|
||||
int c;
|
||||
@@ -68,13 +69,13 @@ static unsigned long ParseMask(const char *str) {
|
||||
*
|
||||
* __get_tls()
|
||||
* │
|
||||
* %fs Linux/BSDs
|
||||
* %fs OpenBSD/NetBSD
|
||||
* _Thread_local │
|
||||
* ┌───┬──────────┬──────────┼───┐
|
||||
* │pad│ .tdata │ .tbss │tib│
|
||||
* └───┴──────────┴──────────┼───┘
|
||||
* │
|
||||
* Windows/Mac %gs
|
||||
* Linux/FreeBSD/Windows/Mac %gs
|
||||
*
|
||||
* Here's the TLS memory layout on aarch64:
|
||||
*
|
||||
@@ -112,10 +113,6 @@ static unsigned long ParseMask(const char *str) {
|
||||
* and your `errno` variable also won't be thread safe anymore.
|
||||
*/
|
||||
textstartup void __enable_tls(void) {
|
||||
int tid;
|
||||
size_t siz;
|
||||
char *mem, *tls;
|
||||
struct CosmoTib *tib;
|
||||
|
||||
// Here's the layout we're currently using:
|
||||
//
|
||||
@@ -138,7 +135,8 @@ textstartup void __enable_tls(void) {
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
siz = ROUNDUP(I(_tls_size) + sizeof(*tib), TLS_ALIGNMENT);
|
||||
char *mem;
|
||||
size_t siz = ROUNDUP(I(_tls_size) + sizeof(struct CosmoTib), TLS_ALIGNMENT);
|
||||
if (siz <= sizeof(__static_tls)) {
|
||||
// if tls requirement is small then use the static tls block
|
||||
// which helps avoid a system call for appes with little tls
|
||||
@@ -158,28 +156,44 @@ textstartup void __enable_tls(void) {
|
||||
kAsanProtected);
|
||||
}
|
||||
|
||||
tib = (struct CosmoTib *)(mem + siz - sizeof(*tib));
|
||||
tls = mem + siz - sizeof(*tib) - I(_tls_size);
|
||||
struct CosmoTib *tib = (struct CosmoTib *)(mem + siz - sizeof(*tib));
|
||||
char *tls = mem + siz - sizeof(*tib) - I(_tls_size);
|
||||
|
||||
// copy in initialized data section
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
size_t hiz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *), I(_tls_align));
|
||||
siz = hiz + I(_tls_size);
|
||||
if (siz <= sizeof(__static_tls)) {
|
||||
uintptr_t size = ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) + //
|
||||
ROUNDUP(sizeof(uintptr_t) * 2, I(_tdata_align)) + //
|
||||
ROUNDUP(I(_tdata_size), I(_tbss_align)) + //
|
||||
I(_tbss_size);
|
||||
|
||||
char *mem;
|
||||
if (I(_tls_align) <= TLS_ALIGNMENT && size <= sizeof(__static_tls)) {
|
||||
mem = __static_tls;
|
||||
} else {
|
||||
mem = _weaken(_mapanon)(siz);
|
||||
mem = _weaken(_mapanon)(size);
|
||||
}
|
||||
|
||||
if (IsAsan()) {
|
||||
// there's a roundup(pagesize) gap between .tdata and .tbss
|
||||
// poison that empty space
|
||||
__asan_poison(mem + hiz + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
|
||||
kAsanProtected);
|
||||
}
|
||||
struct CosmoTib *tib =
|
||||
(struct CosmoTib *)(mem +
|
||||
ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) -
|
||||
sizeof(struct CosmoTib));
|
||||
|
||||
tib = (struct CosmoTib *)mem;
|
||||
tls = mem + hiz;
|
||||
uintptr_t *dtv = (uintptr_t *)(tib + 1);
|
||||
size_t dtv_size = sizeof(uintptr_t) * 2;
|
||||
|
||||
char *tdata = (char *)dtv + ROUNDUP(dtv_size, I(_tdata_align));
|
||||
if (I(_tdata_size)) {
|
||||
memmove(tdata, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
|
||||
// Set the DTV.
|
||||
//
|
||||
@@ -189,8 +203,8 @@ textstartup void __enable_tls(void) {
|
||||
//
|
||||
// @see musl/src/env/__init_tls.c
|
||||
// @see https://chao-tic.github.io/blog/2018/12/25/tls
|
||||
((uintptr_t *)tls)[-2] = 1;
|
||||
((void **)tls)[-1] = tls;
|
||||
dtv[0] = 1;
|
||||
dtv[1] = (uintptr_t)tdata;
|
||||
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
@@ -213,6 +227,8 @@ textstartup void __enable_tls(void) {
|
||||
} else if (IsXnuSilicon()) {
|
||||
tib->tib_syshand = __syslib->__pthread_self();
|
||||
}
|
||||
|
||||
int tid;
|
||||
if (IsLinux() || IsXnuSilicon()) {
|
||||
// gnu/systemd guarantees pid==tid for the main thread so we can
|
||||
// avoid issuing a superfluous system call at startup in program
|
||||
@@ -237,15 +253,6 @@ textstartup void __enable_tls(void) {
|
||||
_pthread_list = &_pthread_static.list;
|
||||
atomic_store_explicit(&_pthread_static.ptid, tid, memory_order_relaxed);
|
||||
|
||||
// copy in initialized data section
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
}
|
||||
|
||||
// ask the operating system to change the x86 segment register
|
||||
__set_tls(tib);
|
||||
|
||||
|
||||
@@ -87,10 +87,6 @@ static int sys_accept_nt_start(int64_t handle, struct NtOverlapped *overlap,
|
||||
if (g_acceptex.lpAcceptEx(args->listensock, handle, args->buffer, 0,
|
||||
sizeof(args->buffer->local),
|
||||
sizeof(args->buffer->remote), 0, overlap)) {
|
||||
// inherit properties of listening socket
|
||||
unassert(!__imp_setsockopt(args->listensock, SOL_SOCKET,
|
||||
kNtSoUpdateAcceptContext, &handle,
|
||||
sizeof(handle)));
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
@@ -123,6 +119,13 @@ textwindows int sys_accept_nt(struct Fd *f, struct sockaddr_storage *addr,
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
// inherit properties of listening socket
|
||||
// errors ignored as if f->handle was created before forking
|
||||
// this fails with WSAENOTSOCK, see
|
||||
// https://github.com/jart/cosmopolitan/issues/1174
|
||||
__imp_setsockopt(resources.handle, SOL_SOCKET, kNtSoUpdateAcceptContext,
|
||||
&f->handle, sizeof(f->handle));
|
||||
|
||||
// create file descriptor for new socket
|
||||
// don't inherit the file open mode bits
|
||||
int oflags = 0;
|
||||
|
||||
+10
-1
@@ -35,11 +35,14 @@
|
||||
#include "libc/sock/syscall_fd.internal.h"
|
||||
#include "libc/sock/wsaid.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
#include "libc/sock/yoink.inc"
|
||||
|
||||
__msabi extern typeof(__sys_setsockopt_nt) *const __imp_setsockopt;
|
||||
|
||||
struct ConnectArgs {
|
||||
const void *addr;
|
||||
uint32_t addrsize;
|
||||
@@ -113,6 +116,8 @@ static textwindows int sys_connect_nt_impl(struct Fd *f, const void *addr,
|
||||
// return ETIMEDOUT if SO_SNDTIMEO elapsed
|
||||
// note that Linux will return EINPROGRESS
|
||||
errno = etimedout();
|
||||
} else if (!rc) {
|
||||
__imp_setsockopt(f->handle, SOL_SOCKET, kNtSoUpdateConnectContext, 0, 0);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -131,7 +136,11 @@ static textwindows int sys_connect_nt_impl(struct Fd *f, const void *addr,
|
||||
ok = WSAGetOverlappedResult(f->handle, overlap, &dwBytes, false, &dwFlags);
|
||||
WSACloseEvent(overlap->hEvent);
|
||||
free(overlap);
|
||||
return ok ? 0 : __winsockerr();
|
||||
if (!ok) {
|
||||
return __winsockerr();
|
||||
}
|
||||
__imp_setsockopt(f->handle, SOL_SOCKET, kNtSoUpdateConnectContext, 0, 0);
|
||||
return 0;
|
||||
} else if (WSAGetLastError() == kNtErrorIoPending) {
|
||||
f->connect_op = overlap;
|
||||
return einprogress();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/paths.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/unistd.h"
|
||||
|
||||
+89
-32
@@ -16,6 +16,7 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/errno.h"
|
||||
@@ -25,6 +26,41 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static ssize_t readvall(int fd, struct iovec *iov, int iovlen) {
|
||||
int olde;
|
||||
ssize_t rc;
|
||||
size_t got, toto;
|
||||
toto = 0;
|
||||
olde = errno;
|
||||
do {
|
||||
if ((rc = readv(fd, iov, iovlen)) == -1) {
|
||||
if (toto && errno == EINTR) {
|
||||
errno = olde;
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
got = rc;
|
||||
toto += got;
|
||||
for (;;) {
|
||||
if (!iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
} else if (got >= iov->iov_len) {
|
||||
got -= iov->iov_len;
|
||||
--iovlen;
|
||||
++iov;
|
||||
} else {
|
||||
iov->iov_base += got;
|
||||
iov->iov_len -= got;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (got && iovlen);
|
||||
return toto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from stream.
|
||||
@@ -36,11 +72,10 @@
|
||||
size_t fread_unlocked(void *buf, size_t stride, size_t count, FILE *f) {
|
||||
char *p;
|
||||
ssize_t rc;
|
||||
size_t n, m;
|
||||
struct iovec iov[2];
|
||||
if (!stride) {
|
||||
return 0;
|
||||
}
|
||||
size_t n, m, got, need;
|
||||
|
||||
// check state and parameters
|
||||
if ((f->iomode & O_ACCMODE) == O_WRONLY) {
|
||||
f->state = errno = EBADF;
|
||||
return 0;
|
||||
@@ -53,52 +88,74 @@ size_t fread_unlocked(void *buf, size_t stride, size_t count, FILE *f) {
|
||||
f->state = errno = EOVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
// try to fulfill request from buffer if possible
|
||||
p = buf;
|
||||
m = f->end - f->beg;
|
||||
if (MIN(n, m)) {
|
||||
memcpy(p, f->buf + f->beg, MIN(n, m));
|
||||
}
|
||||
if (n < m) {
|
||||
f->beg += n;
|
||||
return count;
|
||||
}
|
||||
if (n == m) {
|
||||
f->beg = f->end = 0;
|
||||
if (n <= m) {
|
||||
memcpy(p, f->buf + f->beg, n);
|
||||
if ((f->beg += n) == f->end) {
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// handle end-of-file condition in fileless mode
|
||||
if (f->fd == -1) {
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
f->state = -1;
|
||||
m /= stride;
|
||||
m *= stride;
|
||||
if (m)
|
||||
memcpy(p, f->buf + f->beg, m);
|
||||
if ((f->beg += m) == f->end) {
|
||||
f->state = EOF;
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
}
|
||||
return m / stride;
|
||||
}
|
||||
|
||||
// `n` is number of bytes requested by caller
|
||||
// `m` is how much of `n` came from existing buffer
|
||||
// `iov[0]` reads remainder of the caller request
|
||||
// `iov[1]` reads ahead extra content into buffer
|
||||
if (m)
|
||||
memcpy(p, f->buf + f->beg, m);
|
||||
iov[0].iov_base = p + m;
|
||||
iov[0].iov_len = n - m;
|
||||
iov[0].iov_len = need = n - m;
|
||||
if (f->bufmode != _IONBF && n < f->size) {
|
||||
iov[1].iov_base = f->buf;
|
||||
if (f->size > PUSHBACK) {
|
||||
if (f->size > PUSHBACK)
|
||||
iov[1].iov_len = f->size - PUSHBACK;
|
||||
} else {
|
||||
else
|
||||
iov[1].iov_len = f->size;
|
||||
}
|
||||
} else {
|
||||
iov[1].iov_base = NULL;
|
||||
iov[1].iov_len = 0;
|
||||
}
|
||||
if ((rc = readv(f->fd, iov, 2)) == -1) {
|
||||
if ((rc = readvall(f->fd, iov, 2)) == -1) {
|
||||
f->state = errno;
|
||||
return 0;
|
||||
}
|
||||
n = rc;
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
if (n > iov[0].iov_len) {
|
||||
f->end += n - iov[0].iov_len;
|
||||
return count;
|
||||
} else {
|
||||
n = (m + n) / stride;
|
||||
if (n < count)
|
||||
f->state = -1;
|
||||
return n;
|
||||
got = rc;
|
||||
|
||||
// handle partial fulfillment
|
||||
if (got < need) {
|
||||
got += m;
|
||||
if (got % stride) {
|
||||
f->state = eio();
|
||||
return 0;
|
||||
}
|
||||
f->beg = 0;
|
||||
f->end = 0;
|
||||
f->state = EOF;
|
||||
return got / stride;
|
||||
}
|
||||
|
||||
// handle overfulfillment
|
||||
f->beg = 0;
|
||||
f->end = got - need;
|
||||
return count;
|
||||
}
|
||||
@@ -27,6 +27,40 @@
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
static ssize_t writevall(int fd, struct iovec *iov, int iovlen) {
|
||||
int olde;
|
||||
ssize_t rc;
|
||||
size_t got, toto;
|
||||
toto = 0;
|
||||
olde = errno;
|
||||
do {
|
||||
if ((rc = writev(fd, iov, iovlen)) == -1) {
|
||||
if (toto && errno == EINTR) {
|
||||
errno = olde;
|
||||
continue;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
got = rc;
|
||||
toto += got;
|
||||
for (;;) {
|
||||
if (!iov->iov_len) {
|
||||
--iovlen;
|
||||
++iov;
|
||||
} else if (got >= iov->iov_len) {
|
||||
got -= iov->iov_len;
|
||||
--iovlen;
|
||||
++iov;
|
||||
} else {
|
||||
iov->iov_base += got;
|
||||
iov->iov_len -= got;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (got && iovlen);
|
||||
return toto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data to stream.
|
||||
*
|
||||
@@ -104,7 +138,7 @@ size_t fwrite_unlocked(const void *data, size_t stride, size_t count, FILE *f) {
|
||||
iov[1].iov_base = (void *)data;
|
||||
iov[1].iov_len = n;
|
||||
n += f->beg;
|
||||
if (__robust_writev(f->fd, iov, 2) == -1) {
|
||||
if ((rc = writevall(f->fd, iov, 2)) == -1) {
|
||||
f->state = errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set noet ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ │
|
||||
│ │
|
||||
│ Copyright (c) 2000-2002, 2007, 2010 │
|
||||
│ Todd C. Miller <[email protected]> │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and 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. │
|
||||
│ │
|
||||
│ Sponsored in part by the Defense Advanced Research Projects │
|
||||
│ Agency (DARPA) and Air Force Research Laboratory, Air Force │
|
||||
│ Materiel Command, USAF, under agreement number F39502-99-1-0512. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/readpassphrase.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/unistd.h"
|
||||
|
||||
__notice(readpassphrase_notice, "\
|
||||
libbsd readpassphrase (ISC)\n\
|
||||
Copyright (c) 2000-2002, 2007, 2010 Todd C. Miller <[email protected]>");
|
||||
// clang-format off
|
||||
|
||||
#ifndef TCSASOFT
|
||||
#define TCSASOFT 0
|
||||
#endif
|
||||
|
||||
#ifndef _NSIG
|
||||
#if defined(NSIG)
|
||||
#define _NSIG NSIG
|
||||
#else
|
||||
/* The SIGRTMAX define might be set to a function such as sysconf(). */
|
||||
#define _NSIG (SIGRTMAX + 1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static volatile sig_atomic_t signo[_NSIG];
|
||||
|
||||
static void handler(int);
|
||||
|
||||
char *
|
||||
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
|
||||
{
|
||||
ssize_t nr;
|
||||
int input, output, save_errno, i, need_restart;
|
||||
char ch, *p, *end;
|
||||
struct termios term, oterm;
|
||||
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
|
||||
struct sigaction savetstp, savettin, savettou, savepipe;
|
||||
|
||||
/* I suppose we could alloc on demand in this case (XXX). */
|
||||
if (bufsiz == 0) {
|
||||
errno = EINVAL;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
restart:
|
||||
for (i = 0; i < _NSIG; i++)
|
||||
signo[i] = 0;
|
||||
nr = -1;
|
||||
save_errno = 0;
|
||||
need_restart = 0;
|
||||
/*
|
||||
* Read and write to /dev/tty if available. If not, read from
|
||||
* stdin and write to stderr unless a tty is required.
|
||||
*/
|
||||
if ((flags & RPP_STDIN) ||
|
||||
(input = output = open(_PATH_TTY, O_RDWR)) == -1) {
|
||||
if (flags & RPP_REQUIRE_TTY) {
|
||||
errno = ENOTTY;
|
||||
return(NULL);
|
||||
}
|
||||
input = STDIN_FILENO;
|
||||
output = STDERR_FILENO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn off echo if possible.
|
||||
* If we are using a tty but are not the foreground pgrp this will
|
||||
* generate SIGTTOU, so do it *before* installing the signal handlers.
|
||||
*/
|
||||
if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
|
||||
memcpy(&term, &oterm, sizeof(term));
|
||||
if (!(flags & RPP_ECHO_ON))
|
||||
term.c_lflag &= ~(ECHO | ECHONL);
|
||||
#ifdef VSTATUS
|
||||
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
|
||||
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
(void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
|
||||
} else {
|
||||
memset(&term, 0, sizeof(term));
|
||||
term.c_lflag |= ECHO;
|
||||
memset(&oterm, 0, sizeof(oterm));
|
||||
oterm.c_lflag |= ECHO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Catch signals that would otherwise cause the user to end
|
||||
* up with echo turned off in the shell. Don't worry about
|
||||
* things like SIGXCPU and SIGVTALRM for now.
|
||||
*/
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0; /* don't restart system calls */
|
||||
sa.sa_handler = handler;
|
||||
(void)sigaction(SIGALRM, &sa, &savealrm);
|
||||
(void)sigaction(SIGHUP, &sa, &savehup);
|
||||
(void)sigaction(SIGINT, &sa, &saveint);
|
||||
(void)sigaction(SIGPIPE, &sa, &savepipe);
|
||||
(void)sigaction(SIGQUIT, &sa, &savequit);
|
||||
(void)sigaction(SIGTERM, &sa, &saveterm);
|
||||
(void)sigaction(SIGTSTP, &sa, &savetstp);
|
||||
(void)sigaction(SIGTTIN, &sa, &savettin);
|
||||
(void)sigaction(SIGTTOU, &sa, &savettou);
|
||||
|
||||
if (!(flags & RPP_STDIN))
|
||||
(void)write(output, prompt, strlen(prompt));
|
||||
end = buf + bufsiz - 1;
|
||||
p = buf;
|
||||
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
|
||||
if (p < end) {
|
||||
if ((flags & RPP_SEVENBIT))
|
||||
ch &= 0x7f;
|
||||
if (isalpha((unsigned char)ch)) {
|
||||
if ((flags & RPP_FORCELOWER))
|
||||
ch = (char)tolower((unsigned char)ch);
|
||||
if ((flags & RPP_FORCEUPPER))
|
||||
ch = (char)toupper((unsigned char)ch);
|
||||
}
|
||||
*p++ = ch;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
save_errno = errno;
|
||||
if (!(term.c_lflag & ECHO))
|
||||
(void)write(output, "\n", 1);
|
||||
|
||||
/* Restore old terminal settings and signals. */
|
||||
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
|
||||
const int sigttou = signo[SIGTTOU];
|
||||
|
||||
/* Ignore SIGTTOU generated when we are not the fg pgrp. */
|
||||
while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
|
||||
errno == EINTR && !signo[SIGTTOU])
|
||||
continue;
|
||||
signo[SIGTTOU] = sigttou;
|
||||
}
|
||||
(void)sigaction(SIGALRM, &savealrm, NULL);
|
||||
(void)sigaction(SIGHUP, &savehup, NULL);
|
||||
(void)sigaction(SIGINT, &saveint, NULL);
|
||||
(void)sigaction(SIGQUIT, &savequit, NULL);
|
||||
(void)sigaction(SIGPIPE, &savepipe, NULL);
|
||||
(void)sigaction(SIGTERM, &saveterm, NULL);
|
||||
(void)sigaction(SIGTSTP, &savetstp, NULL);
|
||||
(void)sigaction(SIGTTIN, &savettin, NULL);
|
||||
(void)sigaction(SIGTTOU, &savettou, NULL);
|
||||
if (input != STDIN_FILENO)
|
||||
(void)close(input);
|
||||
|
||||
/*
|
||||
* If we were interrupted by a signal, resend it to ourselves
|
||||
* now that we have restored the signal handlers.
|
||||
*/
|
||||
for (i = 0; i < _NSIG; i++) {
|
||||
if (signo[i]) {
|
||||
kill(getpid(), i);
|
||||
if (i == SIGTSTP || i == SIGTTIN || i == SIGTTOU) {
|
||||
need_restart = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_restart)
|
||||
goto restart;
|
||||
|
||||
if (save_errno)
|
||||
errno = save_errno;
|
||||
return(nr == -1 ? NULL : buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *
|
||||
getpass(const char *prompt)
|
||||
{
|
||||
static char buf[_PASSWORD_LEN + 1];
|
||||
|
||||
return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void handler(int s)
|
||||
{
|
||||
signo[s] = 1;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_STDIO_READPASSPHRASE_H_
|
||||
#define COSMOPOLITAN_LIBC_STDIO_READPASSPHRASE_H_
|
||||
|
||||
#define RPP_ECHO_OFF 0x00
|
||||
#define RPP_ECHO_ON 0x01
|
||||
#define RPP_REQUIRE_TTY 0x02
|
||||
#define RPP_FORCELOWER 0x04
|
||||
#define RPP_FORCEUPPER 0x08
|
||||
#define RPP_SEVENBIT 0x10
|
||||
#define RPP_STDIN 0x20
|
||||
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
char *readpassphrase(const char *, char *, size_t, int) libcesque;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_STDIO_READPASSPHRASE_H_ */
|
||||
@@ -79,7 +79,6 @@ int setvbuf(FILE *, char *, int, size_t) libcesque;
|
||||
int pclose(FILE *) libcesque;
|
||||
char *ctermid(char *) libcesque;
|
||||
void perror(const char *) libcesque relegated;
|
||||
size_t confstr(int, char *, size_t) libcesque;
|
||||
|
||||
typedef uint64_t fpos_t;
|
||||
char *gets(char *) libcesque paramsnonnull();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/limits.h"
|
||||
@@ -42,7 +42,7 @@ static int vdprintf_putc(const char *s, struct VdprintfState *t, size_t n) {
|
||||
iov[0].iov_len = t->n;
|
||||
iov[1].iov_base = (void *)s;
|
||||
iov[1].iov_len = n;
|
||||
if (__robust_writev(t->fd, iov, 2) == -1) {
|
||||
if (writev(t->fd, iov, 2) == -1) {
|
||||
return -1;
|
||||
}
|
||||
t->t += t->n;
|
||||
@@ -68,7 +68,7 @@ int vdprintf(int fd, const char *fmt, va_list va) {
|
||||
if (t.n) {
|
||||
iov[0].iov_base = t.b;
|
||||
iov[0].iov_len = t.n;
|
||||
if (__robust_writev(t.fd, iov, 1) == -1) {
|
||||
if (writev(t.fd, iov, 1) == -1) {
|
||||
return -1;
|
||||
}
|
||||
t.t += t.n;
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdalign.internal.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
|
||||
_Alignas(int8_t) const int8_t kHexToInt[256] = {
|
||||
alignas(int8_t) const int8_t kHexToInt[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x20
|
||||
|
||||
@@ -230,6 +230,7 @@ syscon mmap MAP_NORESERVE 0x00004000 0x00004000 0x00000040 0x00000040 0
|
||||
syscon mmap MAP_POPULATE 0x00008000 0x00008000 0 0 0x00040000 0 0 0 # MAP_PREFAULT_READ on FreeBSD; can avoid madvise(MADV_WILLNEED) on private file mapping
|
||||
syscon mmap MAP_NONBLOCK 0x00010000 0x00010000 0 0 0 0 0 0
|
||||
syscon mmap MAP_SYNC 0x00080000 0x00080000 0 0 0 0 0 0 # perform synchronous page faults for mapping (Linux 4.15+)
|
||||
syscon mmap MAP_HUGETLB 0x00040000 -1 -1 -1 -1 -1 -1 -1 # make it inherit across execve()
|
||||
syscon mmap MAP_INHERIT -1 -1 -1 -1 -1 -1 0x00000080 -1 # make it inherit across execve()
|
||||
syscon mmap MAP_HASSEMAPHORE 0 0 0x00000200 0x00000200 0x00000200 0 0x00000200 0 # does it matter on x86?
|
||||
syscon mmap MAP_NOSYNC 0 0 0 0 0x00000800 0 0 0 # flush to physical media only when necessary rather than gratuitously; be sure to use write() rather than ftruncate() with this!
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon mmap,MAP_HUGETLB,0x00040000,-1,-1,-1,-1,-1,-1,-1
|
||||
@@ -13,6 +13,7 @@ extern const int MAP_FILE;
|
||||
extern const int MAP_FIXED;
|
||||
extern const int MAP_FIXED_NOREPLACE;
|
||||
extern const int MAP_HASSEMAPHORE;
|
||||
extern const int MAP_HUGETLB;
|
||||
extern const int MAP_INHERIT;
|
||||
extern const int MAP_JIT;
|
||||
extern const int MAP_LOCKED;
|
||||
|
||||
@@ -13,6 +13,7 @@ LIBC_TESTLIB_A = o/$(MODE)/libc/testlib/testlib.a
|
||||
LIBC_TESTLIB_A_CHECKS = $(LIBC_TESTLIB_A).pkg
|
||||
|
||||
LIBC_TESTLIB_A_ASSETS = \
|
||||
libc/testlib/blake2b256_tests.txt \
|
||||
libc/testlib/blocktronics.txt \
|
||||
libc/testlib/viewables.txt \
|
||||
libc/testlib/hyperion.txt \
|
||||
@@ -32,6 +33,7 @@ LIBC_TESTLIB_A_HDRS = \
|
||||
|
||||
LIBC_TESTLIB_A_SRCS_S = \
|
||||
libc/testlib/bench.S \
|
||||
libc/testlib/blake2b256_tests.S \
|
||||
libc/testlib/blocktronics.S \
|
||||
libc/testlib/fixture.S \
|
||||
libc/testlib/hyperion.S \
|
||||
@@ -124,6 +126,7 @@ $(LIBC_TESTLIB_A).pkg: \
|
||||
$(LIBC_TESTLIB_A_OBJS) \
|
||||
$(foreach x,$(LIBC_TESTLIB_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/testlib/blake2b256_tests.o: libc/testlib/blake2b256_tests.txt
|
||||
o/$(MODE)/libc/testlib/blocktronics.o: libc/testlib/blocktronics.txt
|
||||
o/$(MODE)/libc/testlib/viewables.o: libc/testlib/viewables.txt
|
||||
o/$(MODE)/libc/testlib/hyperion.o: libc/testlib/hyperion.txt
|
||||
@@ -132,6 +135,8 @@ o/$(MODE)/libc/testlib/moby.o: libc/testlib/moby.txt
|
||||
# these assembly files are safe to build on aarch64
|
||||
o/$(MODE)/libc/testlib/bench.o: libc/testlib/bench.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/libc/testlib/blake2b256_tests.o: libc/testlib/blake2b256_tests.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/libc/testlib/blocktronics.o: libc/testlib/blocktronics.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||
o/$(MODE)/libc/testlib/fixture.o: libc/testlib/fixture.S
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2024 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,30 +16,18 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/iovec.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/macros.internal.h"
|
||||
.rodata
|
||||
|
||||
ssize_t __robust_writev(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;
|
||||
}
|
||||
// Blake2B256 test vectors.
|
||||
.underrun
|
||||
kBlake2b256Tests:
|
||||
0: .incbin "libc/testlib/blake2b256_tests.txt"
|
||||
1: .byte 0
|
||||
.endobj kBlake2b256Tests,globl
|
||||
.overrun
|
||||
|
||||
.balign 8
|
||||
kBlake2b256TestsSize:
|
||||
.quad 1b-0b
|
||||
.endobj kBlake2b256TestsSize,globl
|
||||
File renamed without changes.
@@ -17,6 +17,7 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
@@ -32,7 +33,7 @@ void __testlib_ezbenchreport_n(const char *form, char z, size_t n, double c) {
|
||||
char msg[128];
|
||||
__warn_if_powersave();
|
||||
ksnprintf(msg, sizeof(msg), "%s %c=%d", form, z, n);
|
||||
cn = lrint(c / 3);
|
||||
cn = max(lrint(c / 3), 1);
|
||||
if (!n) {
|
||||
kprintf("\n");
|
||||
kprintf(" * %-28s", msg);
|
||||
|
||||
+48
-29
@@ -25,6 +25,7 @@
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/sysparam.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/tls.h"
|
||||
@@ -54,6 +55,19 @@ static char *_mktls_below(struct CosmoTib **out_tib) {
|
||||
char *mem, *tls;
|
||||
struct CosmoTib *tib;
|
||||
|
||||
// Here's the TLS memory layout on x86_64
|
||||
//
|
||||
// __get_tls()
|
||||
// │
|
||||
// %fs OpenBSD/NetBSD
|
||||
// _Thread_local │
|
||||
// ┌───┬──────────┬──────────┼───┐
|
||||
// │pad│ .tdata │ .tbss │tib│
|
||||
// └───┴──────────┴──────────┼───┘
|
||||
// │
|
||||
// Linux/FreeBSD/Windows/Mac %gs
|
||||
//
|
||||
|
||||
siz = ROUNDUP(I(_tls_size) + sizeof(*tib), _Alignof(struct CosmoTib));
|
||||
siz = ROUNDUP(siz, _Alignof(struct CosmoTib));
|
||||
mem = memalign(_Alignof(struct CosmoTib), siz);
|
||||
@@ -77,53 +91,58 @@ static char *_mktls_below(struct CosmoTib **out_tib) {
|
||||
}
|
||||
|
||||
// clear .tbss
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
if (I(_tbss_size))
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
|
||||
// set up thread information block
|
||||
return _mktls_finish(out_tib, mem, tib);
|
||||
}
|
||||
|
||||
static char *_mktls_above(struct CosmoTib **out_tib) {
|
||||
size_t hiz, siz;
|
||||
struct CosmoTib *tib;
|
||||
char *mem, *dtv, *tls;
|
||||
|
||||
// allocate memory for tdata, tbss, and tib
|
||||
hiz = ROUNDUP(sizeof(*tib) + 2 * sizeof(void *), I(_tls_align));
|
||||
siz = hiz + I(_tls_size);
|
||||
mem = memalign(TLS_ALIGNMENT, siz);
|
||||
// Here's the TLS memory layout on aarch64
|
||||
//
|
||||
// x28
|
||||
// %tpidr_el0
|
||||
// │
|
||||
// │ _Thread_local
|
||||
// ┌───┼───┬──────────┬──────────┐
|
||||
// │tib│dtv│ .tdata │ .tbss │
|
||||
// ├───┴───┴──────────┴──────────┘
|
||||
// │
|
||||
// __get_tls()
|
||||
//
|
||||
|
||||
size_t size = ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) + //
|
||||
ROUNDUP(sizeof(uintptr_t) * 2, I(_tdata_align)) + //
|
||||
ROUNDUP(I(_tdata_size), I(_tbss_align)) + //
|
||||
I(_tbss_size);
|
||||
|
||||
char *mem = memalign(I(_tls_align), size);
|
||||
if (!mem)
|
||||
return 0;
|
||||
|
||||
// poison memory between tdata and tbss
|
||||
if (IsAsan()) {
|
||||
__asan_poison(mem + hiz + I(_tdata_size), I(_tbss_offset) - I(_tdata_size),
|
||||
kAsanProtected);
|
||||
}
|
||||
struct CosmoTib *tib =
|
||||
(struct CosmoTib *)(mem +
|
||||
ROUNDUP(sizeof(struct CosmoTib), I(_tls_align)) -
|
||||
sizeof(struct CosmoTib));
|
||||
|
||||
tib = (struct CosmoTib *)mem;
|
||||
dtv = mem + sizeof(*tib);
|
||||
tls = mem + hiz;
|
||||
uintptr_t *dtv = (uintptr_t *)(tib + 1);
|
||||
size_t dtv_size = sizeof(uintptr_t) * 2;
|
||||
|
||||
// set dtv
|
||||
((uintptr_t *)dtv)[0] = 1;
|
||||
((void **)dtv)[1] = tls;
|
||||
|
||||
// initialize .tdata
|
||||
char *tdata = (char *)dtv + ROUNDUP(dtv_size, I(_tdata_align));
|
||||
if (I(_tdata_size)) {
|
||||
if (IsAsan()) {
|
||||
__asan_memcpy(tls, _tdata_start, I(_tdata_size));
|
||||
} else {
|
||||
memmove(tls, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
memmove(tdata, _tdata_start, I(_tdata_size));
|
||||
}
|
||||
|
||||
// clear .tbss
|
||||
char *tbss = tdata + ROUNDUP(I(_tdata_size), I(_tbss_align));
|
||||
if (I(_tbss_size)) {
|
||||
bzero(tls + I(_tbss_offset), I(_tbss_size));
|
||||
bzero(tbss, I(_tbss_size));
|
||||
}
|
||||
|
||||
// set up thread information block
|
||||
dtv[0] = 1;
|
||||
dtv[1] = (uintptr_t)tdata;
|
||||
|
||||
return _mktls_finish(out_tib, mem, tib);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ COSMOPOLITAN_C_START_
|
||||
|
||||
#define _CS_PATH 0
|
||||
|
||||
size_t confstr(int, char *, size_t) libcesque;
|
||||
|
||||
#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || \
|
||||
defined(_COSMO_SOURCE)
|
||||
void encrypt(char *, int) libcesque;
|
||||
|
||||
@@ -1817,7 +1817,6 @@ StartOver:
|
||||
CHECK_DB(sqlite3_bind_int64(stmt, 1, v[i].ip));
|
||||
CHECK_DB(sqlite3_bind_text(stmt, 2, v[i].name, -1, SQLITE_TRANSIENT));
|
||||
CHECK_DB(sqlite3_bind_int64(stmt, 3, v[i].created));
|
||||
CHECK_DB(sqlite3_bind_int64(stmt, 3, v[i].created));
|
||||
CHECK_DB((rc = DbStep(stmt)) == SQLITE_DONE ? SQLITE_OK : rc);
|
||||
CHECK_DB(sqlite3_reset(stmt));
|
||||
++processed;
|
||||
|
||||
@@ -27,39 +27,53 @@
|
||||
|
||||
char16_t cmdline[32767];
|
||||
|
||||
TEST(mkntcmdline, empty) {
|
||||
char16_t buf2[2];
|
||||
EXPECT_EQ(0, mkntcmdline(buf2, (char *[]){0}, 2));
|
||||
EXPECT_STREQ(u"", buf2);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, truncation) {
|
||||
char *argv[] = {"foo", NULL};
|
||||
EXPECT_EQ(3, mkntcmdline(0, argv, 0));
|
||||
char16_t buf2[2];
|
||||
EXPECT_EQ(3, mkntcmdline(buf2, argv, 2));
|
||||
EXPECT_STREQ(u"f", buf2);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, emptyArgvList_cantBeEmptyOnWindows) {
|
||||
char *argv[] = {"foo", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"foo", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, emptyArgvListWithProg_isEmpty) {
|
||||
char *argv[] = {NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, emptyArg_getsQuoted) {
|
||||
char *argv[] = {"", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"\"\"", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, ignoranceIsBliss) {
|
||||
char *argv[] = {"echo", "hello", "world", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"echo hello world", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, spaceInArgument_getQuotesWrappedAround) {
|
||||
char *argv[] = {"echo", "hello there", "world", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"echo \"hello there\" world", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, justSlash) {
|
||||
char *argv[] = {"\\", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"\\", cmdline);
|
||||
}
|
||||
|
||||
@@ -69,7 +83,7 @@ TEST(mkntcmdline, testUnicode) {
|
||||
gc(strdup("要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非")),
|
||||
NULL,
|
||||
};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv1));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv1, 32767));
|
||||
EXPECT_STREQ(u"(╯°□°)╯ \"要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非\"",
|
||||
cmdline);
|
||||
}
|
||||
@@ -80,13 +94,13 @@ TEST(mkntcmdline, fixit) {
|
||||
"--version",
|
||||
NULL,
|
||||
};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv1));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv1, 32767));
|
||||
EXPECT_STREQ(u"\"C:\\Program Files\\doom\\doom.exe\" --version", cmdline);
|
||||
}
|
||||
|
||||
TEST(mkntcmdline, testWut) {
|
||||
char *argv[] = {"C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛", "--strace", NULL};
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv));
|
||||
EXPECT_NE(-1, mkntcmdline(cmdline, argv, 32767));
|
||||
EXPECT_STREQ(u"C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛 --strace", cmdline);
|
||||
}
|
||||
|
||||
@@ -95,5 +109,5 @@ BENCH(mkntcmdline, lotsOfArgs) {
|
||||
for (int i = 0; i < 999; ++i) {
|
||||
argv[i] = "hello there hello there";
|
||||
}
|
||||
EZBENCH2("mkntcmdline", donothing, unassert(!mkntcmdline(cmdline, argv)));
|
||||
EZBENCH2("mkntcmdline", donothing, mkntcmdline(cmdline, argv, 32767));
|
||||
}
|
||||
@@ -33,9 +33,9 @@
|
||||
|
||||
__static_yoink("zipos");
|
||||
__static_yoink("libc/testlib/hyperion.txt");
|
||||
__static_yoink("inflate");
|
||||
__static_yoink("inflateInit2");
|
||||
__static_yoink("inflateEnd");
|
||||
__static_yoink("_Cz_inflate");
|
||||
__static_yoink("_Cz_inflateInit2");
|
||||
__static_yoink("_Cz_inflateEnd");
|
||||
|
||||
void *Worker(void *arg) {
|
||||
int i, fd;
|
||||
|
||||
@@ -68,7 +68,8 @@ o/$(MODE)/test/libc/sock/shutdown_test.runs \
|
||||
o/$(MODE)/test/libc/sock/setsockopt_test.runs \
|
||||
o/$(MODE)/test/libc/sock/sendfile_test.runs \
|
||||
o/$(MODE)/test/libc/sock/poll_test.runs \
|
||||
o/$(MODE)/test/libc/sock/pollfd_test.runs: \
|
||||
o/$(MODE)/test/libc/sock/pollfd_test.runs \
|
||||
o/$(MODE)/test/libc/sock/getpeername_test.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
o/$(MODE)/test/libc/sock/sendrecvmsg_test.runs: \
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Gavin Arthur Hayes │
|
||||
│ │
|
||||
│ 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/sock/sock.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(getpeername, worksAfterAcceptingOnFork) {
|
||||
// https://github.com/jart/cosmopolitan/issues/1174
|
||||
if (IsWindows()) {
|
||||
return;
|
||||
}
|
||||
char buf[16] = {0};
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(0x7f000001),
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 4, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||
struct sockaddr_storage out = {0};
|
||||
uint32_t out_size = sizeof(out);
|
||||
ASSERT_SYS(0, 0, getpeername(4, (struct sockaddr *)&out, &out_size));
|
||||
EXPECT_GE(sizeof(struct sockaddr_in), out_size);
|
||||
EXPECT_EQ(AF_INET, ((struct sockaddr_in *)&out)->sin_family);
|
||||
EXPECT_EQ(htonl(0x7f000001), ((struct sockaddr_in *)&out)->sin_addr.s_addr);
|
||||
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 5, read(3, buf, 16));
|
||||
ASSERT_STREQ("hello", buf);
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
WAIT(exit, 0);
|
||||
}
|
||||
|
||||
TEST(getpeername, worksAfterAcceptingOnParent) {
|
||||
char buf[16] = {0};
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(0x7f000001),
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 5, read(3, buf, 16));
|
||||
ASSERT_STREQ("hello", buf);
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 4, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||
struct sockaddr_storage out = {0};
|
||||
uint32_t out_size = sizeof(out);
|
||||
ASSERT_SYS(0, 0, getpeername(4, (struct sockaddr *)&out, &out_size));
|
||||
EXPECT_GE(sizeof(struct sockaddr_in), out_size);
|
||||
EXPECT_EQ(AF_INET, ((struct sockaddr_in *)&out)->sin_family);
|
||||
EXPECT_EQ(htonl(0x7f000001), ((struct sockaddr_in *)&out)->sin_addr.s_addr);
|
||||
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
WAIT(exit, 0);
|
||||
}
|
||||
|
||||
TEST(getpeername, worksAfterConnectingOnFork) {
|
||||
char buf[16] = {0};
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(0x7f000001),
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||
ASSERT_SYS(0, 4, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 0, connect(4, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
struct sockaddr_storage out = {0};
|
||||
uint32_t out_size = sizeof(out);
|
||||
ASSERT_SYS(0, 0, getpeername(4, (struct sockaddr *)&out, &out_size));
|
||||
EXPECT_GE(sizeof(struct sockaddr_in), out_size);
|
||||
EXPECT_EQ(AF_INET, ((struct sockaddr_in *)&out)->sin_family);
|
||||
EXPECT_EQ(htonl(0x7f000001), ((struct sockaddr_in *)&out)->sin_addr.s_addr);
|
||||
ASSERT_SYS(0, 5, send(4, "hello", 5, 0));
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 4, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 5, read(4, buf, 16));
|
||||
ASSERT_STREQ("hello", buf);
|
||||
ASSERT_SYS(0, 0, close(4));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
WAIT(exit, 0);
|
||||
}
|
||||
|
||||
TEST(getpeername, worksAfterConnectingOnParent) {
|
||||
char buf[16] = {0};
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_addr.s_addr = htonl(0x7f000001),
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0, getsockname(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 0, listen(3, SOMAXCONN));
|
||||
SPAWN(fork);
|
||||
ASSERT_SYS(0, 4, accept(3, (struct sockaddr *)&addr, &addrsize));
|
||||
ASSERT_SYS(0, 5, read(4, buf, 16));
|
||||
ASSERT_STREQ("hello", buf);
|
||||
PARENT();
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
|
||||
ASSERT_SYS(0, 0, connect(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
struct sockaddr_storage out = {0};
|
||||
uint32_t out_size = sizeof(out);
|
||||
ASSERT_SYS(0, 0, getpeername(3, (struct sockaddr *)&out, &out_size));
|
||||
EXPECT_GE(sizeof(struct sockaddr_in), out_size);
|
||||
EXPECT_EQ(AF_INET, ((struct sockaddr_in *)&out)->sin_family);
|
||||
EXPECT_EQ(htonl(0x7f000001), ((struct sockaddr_in *)&out)->sin_addr.s_addr);
|
||||
ASSERT_SYS(0, 5, send(3, "hello", 5, 0));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
WAIT(exit, 0);
|
||||
}
|
||||
@@ -152,8 +152,6 @@ __attribute__((__constructor__)) static void StdioPro(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
TEST(socket, canBeUsedAsExecutedStdio) {
|
||||
if (IsWindows())
|
||||
return; // TODO(jart): What broke this?
|
||||
char buf[16] = {0};
|
||||
const char *prog;
|
||||
uint32_t addrsize = sizeof(struct sockaddr_in);
|
||||
|
||||
@@ -16,53 +16,67 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* This test was contributed by @ahgamut
|
||||
* https://github.com/jart/cosmopolitan/issues/61#issuecomment-792214575
|
||||
*/
|
||||
|
||||
void SetUpOnce(void) {
|
||||
testlib_enable_tmp_setup_teardown();
|
||||
char path[PATH_MAX];
|
||||
|
||||
void teardown(void) {
|
||||
unlink(path);
|
||||
}
|
||||
|
||||
int writefile(const char* filename) {
|
||||
int stat = 0;
|
||||
FILE* fp = fopen(filename, "w");
|
||||
stat = fputs("cosmopolitan libc\n", fp);
|
||||
fclose(fp);
|
||||
return stat;
|
||||
}
|
||||
|
||||
int readfile(const char* filename) {
|
||||
int stat = 0;
|
||||
char buf1[30];
|
||||
char buf2[30];
|
||||
FILE *fp1, *fp2;
|
||||
fp1 = fopen(filename, "r");
|
||||
if (!fp1) {
|
||||
printf("failed to read %s in r\n", filename);
|
||||
int setup(void) {
|
||||
int fd;
|
||||
const char* tmpdir;
|
||||
if ((tmpdir = getenv("TMPDIR")))
|
||||
strlcpy(path, tmpdir, sizeof(path));
|
||||
else
|
||||
strlcpy(path, "/tmp", sizeof(path));
|
||||
strlcat(path, "/freopen_test.XXXXXX", sizeof(path));
|
||||
if ((fd = mkstemp(path)) == -1)
|
||||
return 1;
|
||||
}
|
||||
buf1[0] = fgetc(fp1);
|
||||
buf1[1] = '\0';
|
||||
fp2 = freopen(filename, "rb", fp1);
|
||||
if (!fp2) {
|
||||
printf("failed to read %s in rb\n", filename);
|
||||
return 1;
|
||||
}
|
||||
stat = fread(buf2, sizeof(buf2[0]), 20, fp2);
|
||||
ASSERT_EQ(18, stat);
|
||||
buf2[stat] = '\0';
|
||||
fclose(fp2);
|
||||
ASSERT_STREQ("c", buf1);
|
||||
ASSERT_STREQ("cosmopolitan libc\n", buf2);
|
||||
if (write(fd, "cosmopolitan libc\n", 18) != 18)
|
||||
return 2;
|
||||
if (close(fd))
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(freopen, test) {
|
||||
writefile("file.txt");
|
||||
readfile("file.txt");
|
||||
int test(void) {
|
||||
FILE* fp;
|
||||
char buf[20];
|
||||
if (!(fp = fopen(path, "r")))
|
||||
return 4;
|
||||
if (fgetc(fp) != 'c')
|
||||
return 5;
|
||||
if (!(fp = freopen(path, "rb", fp)))
|
||||
return 6;
|
||||
if (fread(buf, 1, 20, fp) != 18)
|
||||
return 7;
|
||||
if (memcmp(buf, "cosmopolitan libc\n", 18))
|
||||
return 8;
|
||||
if (fclose(fp))
|
||||
return 9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int rc;
|
||||
if ((rc = setup())) {
|
||||
perror(path);
|
||||
teardown();
|
||||
return rc;
|
||||
}
|
||||
rc = test();
|
||||
teardown();
|
||||
return rc;
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/blake2.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/mem/mem.h"
|
||||
@@ -26,6 +27,9 @@
|
||||
#include "libc/testlib/hyperion.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
__static_yoink("libc/testlib/blake2b256_tests.txt");
|
||||
__static_yoink("zipos");
|
||||
|
||||
uint8_t *EZBLAKE2B256(const char *s, size_t n) {
|
||||
static uint8_t digest[BLAKE2B256_DIGEST_LENGTH];
|
||||
BLAKE2B256(s, n, digest);
|
||||
@@ -63,7 +67,27 @@ TEST(BLAKE2B256Test, ABC) {
|
||||
EXPECT_BINEQ(
|
||||
"03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314",
|
||||
HEXBLAKE2B256("00"));
|
||||
/* TODO(jart): do rest */
|
||||
}
|
||||
|
||||
TEST(BLAKE2B256Test, vectors) {
|
||||
char *line = NULL;
|
||||
size_t cap = 0;
|
||||
ssize_t n;
|
||||
FILE *f = fopen("/zip/libc/testlib/blake2b256_tests.txt", "r");
|
||||
uint8_t *digest = 0;
|
||||
while ((n = getline(&line, &cap, f)) != -1) {
|
||||
if (n < 2 || line[0] == '#')
|
||||
continue;
|
||||
line[n - 1] = 0;
|
||||
if (!strncmp(line, "IN:", 3)) {
|
||||
digest = HEXBLAKE2B256(line + 4);
|
||||
}
|
||||
if (!strncmp(line, "HASH: ", 6)) {
|
||||
EXPECT_BINEQ(line + 6, digest);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
free(line);
|
||||
}
|
||||
|
||||
BENCH(blake2, bench) {
|
||||
|
||||
@@ -52,6 +52,9 @@ o/$(MODE)/test/posix/%.dbg: \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/test/posix/fread3gb_test.runs: \
|
||||
private QUOTA += -F5gb -M5gb
|
||||
|
||||
.PHONY: o/$(MODE)/test/posix
|
||||
o/$(MODE)/test/posix: \
|
||||
$(TEST_POSIX_BINS) \
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SIZE ((size_t)2 * 1024 * 1024 * 1024 + 13)
|
||||
|
||||
char path[PATH_MAX];
|
||||
|
||||
void teardown(void) {
|
||||
unlink(path);
|
||||
}
|
||||
|
||||
int setup(void) {
|
||||
int fd;
|
||||
struct stat st;
|
||||
const char *tmpdir;
|
||||
if (!stat("/dev/shm", &st))
|
||||
strlcpy(path, "/dev/shm", sizeof(path));
|
||||
else if ((tmpdir = getenv("TMPDIR")))
|
||||
strlcpy(path, tmpdir, sizeof(path));
|
||||
else
|
||||
strlcpy(path, "/tmp", sizeof(path));
|
||||
strlcat(path, "/fread3gb.XXXXXX", sizeof(path));
|
||||
if ((fd = mkstemp(path)) == -1)
|
||||
return 1;
|
||||
if (ftruncate(fd, SIZE))
|
||||
return 2;
|
||||
if (pwrite(fd, "a", 1, 0) != 1)
|
||||
return 3;
|
||||
if (pwrite(fd, "z", 1, SIZE - 1) != 1)
|
||||
return 4;
|
||||
if (close(fd))
|
||||
return 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test(void) {
|
||||
FILE *f;
|
||||
char *buf;
|
||||
size_t rc;
|
||||
if (!(f = fopen(path, "r")))
|
||||
return 6;
|
||||
if (!(buf = malloc(SIZE)))
|
||||
return 7;
|
||||
if ((rc = fread(buf, SIZE, 1, f)) != 1)
|
||||
return 8;
|
||||
if (buf[0] != 'a')
|
||||
return 9;
|
||||
if (buf[SIZE - 1] != 'z')
|
||||
return 10;
|
||||
if (fclose(f))
|
||||
return 11;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc;
|
||||
if ((rc = setup())) {
|
||||
perror(path);
|
||||
teardown();
|
||||
return rc;
|
||||
}
|
||||
rc = test();
|
||||
teardown();
|
||||
return rc;
|
||||
}
|
||||
Vendored
+1
-1
@@ -111,7 +111,7 @@
|
||||
#if (MORECORE_CONTIGUOUS || defined(WIN32))
|
||||
#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */
|
||||
#else /* MORECORE_CONTIGUOUS */
|
||||
#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U)
|
||||
#define DEFAULT_GRANULARITY ((size_t)256U * (size_t)1024U)
|
||||
#endif /* MORECORE_CONTIGUOUS */
|
||||
#endif /* DEFAULT_GRANULARITY */
|
||||
#ifndef DEFAULT_TRIM_THRESHOLD
|
||||
|
||||
Vendored
+2
@@ -36,3 +36,5 @@ LOCAL MODIFICATIONS
|
||||
Added Python-like printf modulus operator for strings.
|
||||
|
||||
Added Python-like printf multiply operator for strings.
|
||||
|
||||
Fixed a buffer overflow in os.tmpname
|
||||
Vendored
+4
-4
@@ -133,12 +133,12 @@ __static_yoink("lua_notice");
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#define LUA_TMPNAMBUFSIZE 32
|
||||
#define LUA_TMPNAMBUFSIZE 128
|
||||
|
||||
#define lua_tmpnam(b,e) { \
|
||||
strcpy(b, __get_tmpdir()); \
|
||||
strcat(b, "lua_XXXXXX"); \
|
||||
e = mkstemp(b); \
|
||||
strlcpy(b, __get_tmpdir(), LUA_TMPNAMBUFSIZE); \
|
||||
e = strlcat(b, "lua_XXXXXX", LUA_TMPNAMBUFSIZE) >= LUA_TMPNAMBUFSIZE; \
|
||||
e = e ? -1 : mkstemp(b); \
|
||||
if (e != -1) close(e); \
|
||||
e = (e == -1); }
|
||||
|
||||
|
||||
Vendored
+3
-3
@@ -45,9 +45,9 @@ __static_yoink("musl_libc_notice");
|
||||
// something as substantive as this library, then we shall assume the
|
||||
// application is meaty enough to benefit from the performance of the
|
||||
// chromium zlib library (costs ~40kb binary) versus just having puff
|
||||
__static_yoink("inflateInit2");
|
||||
__static_yoink("inflate");
|
||||
__static_yoink("inflateEnd");
|
||||
__static_yoink("_Cz_inflateInit2");
|
||||
__static_yoink("_Cz_inflate");
|
||||
__static_yoink("_Cz_inflateEnd");
|
||||
#endif
|
||||
|
||||
static char *
|
||||
|
||||
Vendored
+16
-16
@@ -7,7 +7,7 @@ THIRD_PARTY_PYTHON_ARTIFACTS = \
|
||||
THIRD_PARTY_PYTHON_STAGE1_A \
|
||||
THIRD_PARTY_PYTHON_STAGE2_A \
|
||||
THIRD_PARTY_PYTHON_PYTEST_A \
|
||||
THIRD_PARTY_PYTHON_PYTHON \
|
||||
THIRD_PARTY_PYTHON_PYTHON3 \
|
||||
THIRD_PARTY_PYTHON_FREEZE
|
||||
|
||||
THIRD_PARTY_PYTHON_BINS = \
|
||||
@@ -17,7 +17,7 @@ THIRD_PARTY_PYTHON_BINS = \
|
||||
THIRD_PARTY_PYTHON_COMS = \
|
||||
o/$(MODE)/third_party/python/Parser/asdl_c \
|
||||
o/$(MODE)/third_party/python/pystone \
|
||||
o/$(MODE)/third_party/python/python \
|
||||
o/$(MODE)/third_party/python/python3 \
|
||||
o/$(MODE)/third_party/python/freeze \
|
||||
o/$(MODE)/third_party/python/pycomp \
|
||||
o/$(MODE)/third_party/python/pyobj \
|
||||
@@ -29,7 +29,7 @@ THIRD_PARTY_PYTHON_CHECKS = \
|
||||
$(THIRD_PARTY_PYTHON_STAGE2_A).pkg \
|
||||
$(THIRD_PARTY_PYTHON_PYTEST_A).pkg \
|
||||
$(THIRD_PARTY_PYTHON_HDRS:%=o/$(MODE)/%.ok) \
|
||||
o/$(MODE)/third_party/python/python.pkg \
|
||||
o/$(MODE)/third_party/python/python3.pkg \
|
||||
o/$(MODE)/third_party/python/freeze.pkg
|
||||
|
||||
# TODO: Deal with aarch64 under qemu not making execve() easy.
|
||||
@@ -3980,12 +3980,12 @@ THIRD_PARTY_PYTHON_SRCS = \
|
||||
################################################################################
|
||||
# PYTHON
|
||||
|
||||
THIRD_PARTY_PYTHON_PYTHON_SRCS = third_party/python/python.c
|
||||
THIRD_PARTY_PYTHON_PYTHON_OBJS = o/$(MODE)/third_party/python/python.o
|
||||
THIRD_PARTY_PYTHON_PYTHON_COMS = o/$(MODE)/third_party/python/python
|
||||
THIRD_PARTY_PYTHON_PYTHON_BINS = $(THIRD_PARTY_PYTHON_PYTHON_COMS) $(THIRD_PARTY_PYTHON_PYTHON_COMS:%=%.dbg)
|
||||
THIRD_PARTY_PYTHON_PYTHON_DEPS = $(call uniq,$(foreach x,$(THIRD_PARTY_PYTHON_PYTHON_DIRECTDEPS),$($(x))))
|
||||
THIRD_PARTY_PYTHON_PYTHON_DIRECTDEPS = \
|
||||
THIRD_PARTY_PYTHON_PYTHON3_SRCS = third_party/python/python3.c
|
||||
THIRD_PARTY_PYTHON_PYTHON3_OBJS = o/$(MODE)/third_party/python/python3.o
|
||||
THIRD_PARTY_PYTHON_PYTHON3_COMS = o/$(MODE)/third_party/python/python3
|
||||
THIRD_PARTY_PYTHON_PYTHON3_BINS = $(THIRD_PARTY_PYTHON_PYTHON3_COMS) $(THIRD_PARTY_PYTHON_PYTHON3_COMS:%=%.dbg)
|
||||
THIRD_PARTY_PYTHON_PYTHON3_DEPS = $(call uniq,$(foreach x,$(THIRD_PARTY_PYTHON_PYTHON3_DIRECTDEPS),$($(x))))
|
||||
THIRD_PARTY_PYTHON_PYTHON3_DIRECTDEPS = \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
@@ -4005,14 +4005,14 @@ THIRD_PARTY_PYTHON_PYTHON_DIRECTDEPS = \
|
||||
THIRD_PARTY_XED \
|
||||
TOOL_ARGS
|
||||
|
||||
o/$(MODE)/third_party/python/python.pkg: \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_PYTHON_PYTHON_DIRECTDEPS),$($(x)_A).pkg)
|
||||
o/$(MODE)/third_party/python/python3.pkg: \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON3_OBJS) \
|
||||
$(foreach x,$(THIRD_PARTY_PYTHON_PYTHON3_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/third_party/python/python.dbg: \
|
||||
o/$(MODE)/third_party/python/python.pkg \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON_DEPS) \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON_OBJS) \
|
||||
o/$(MODE)/third_party/python/python3.dbg: \
|
||||
o/$(MODE)/third_party/python/python3.pkg \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON3_DEPS) \
|
||||
$(THIRD_PARTY_PYTHON_PYTHON3_OBJS) \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
File renamed without changes.
Vendored
+1
-1
@@ -31,7 +31,7 @@
|
||||
#ifndef USE_ZLIB
|
||||
ZCONST ulg near *get_crc_table OF((void));
|
||||
#endif
|
||||
#if (1 || defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))
|
||||
#if (defined(USE_ZLIB) || defined(CRC_TABLE_ONLY))
|
||||
# ifdef IZ_CRC_BE_OPTIMIZ
|
||||
# undef IZ_CRC_BE_OPTIMIZ
|
||||
# endif
|
||||
|
||||
Vendored
+5
-5
@@ -72,7 +72,7 @@
|
||||
#include "libc/nt/winsock.h"
|
||||
#endif
|
||||
|
||||
unsigned crc32(unsigned crc, const unsigned char *buf, unsigned len);
|
||||
unsigned _Cz_crc32(unsigned crc, const unsigned char *buf, unsigned len);
|
||||
|
||||
/*
|
||||
* XXX start of zipfile.h
|
||||
@@ -867,7 +867,7 @@ local void read_Unicode_Path_entry(pZipListEntry)
|
||||
}
|
||||
strcpy(iname, pZipListEntry->iname);
|
||||
|
||||
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
chksum = _Cz_crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
|
||||
free(iname);
|
||||
|
||||
@@ -972,7 +972,7 @@ local void read_Unicode_Path_local_entry(pZipListEntry)
|
||||
}
|
||||
strcpy(iname, pZipListEntry->iname);
|
||||
|
||||
chksum = crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
chksum = _Cz_crc32(chksum, (uch *)(iname), strlen(iname));
|
||||
|
||||
free(iname);
|
||||
|
||||
@@ -1558,7 +1558,7 @@ local int add_Unicode_Path_local_extra_field(pZEntry)
|
||||
# define inameLocal (pZEntry->iname)
|
||||
#endif
|
||||
|
||||
chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
chksum = _Cz_crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
|
||||
#ifdef WIN32_OEM
|
||||
free(inameLocal);
|
||||
@@ -1685,7 +1685,7 @@ local int add_Unicode_Path_cen_extra_field(pZEntry)
|
||||
# define inameLocal (pZEntry->iname)
|
||||
#endif
|
||||
|
||||
chksum = crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
chksum = _Cz_crc32(chksum, (uch *)(inameLocal), strlen(inameLocal));
|
||||
|
||||
#ifdef WIN32_OEM
|
||||
free(inameLocal);
|
||||
|
||||
Vendored
-4
@@ -13,7 +13,6 @@
|
||||
|
||||
#define z_const const
|
||||
|
||||
#if 0
|
||||
#define Z_COSMO_PREFIX_SET
|
||||
|
||||
#define Bytef _Cz_Bytef
|
||||
@@ -163,9 +162,6 @@
|
||||
#define zlibCompileFlags _Cz_zlibCompileFlags
|
||||
#define zlibVersion _Cz_zlibVersion
|
||||
|
||||
#pragma message "zconf is included, so zlibVersion should be renamed"
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
|
||||
@@ -15,7 +15,7 @@ $PROG (GCC) $GCC_VERSION
|
||||
Copyright (c) 2024 Justine Alexandra Roberts Tunney
|
||||
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
|
||||
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
|
||||
our copyright notices. This toolchain is configured to do so default.
|
||||
our copyright notices. This toolchain is configured to do so by default.
|
||||
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
|
||||
For more information, see the Cosmopolitan LICENSE files.
|
||||
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
@@ -184,11 +184,6 @@ for x; do
|
||||
# no support for position independent executables
|
||||
# https://github.com/jart/cosmopolitan/issues/1126
|
||||
continue
|
||||
elif [ x"$x" = x"-Werror" ] || \
|
||||
[ x"$x" = x"-pedantic-errors" ]; then
|
||||
# this toolchain is intended for building other people's code
|
||||
# elevating warnings into errors, should only be done by devs
|
||||
continue
|
||||
elif [ x"$x" = x"-static-libgcc" ] || \
|
||||
[ x"$x" = x"-shared-libgcc" ]; then
|
||||
# cosmopolitan.a always has llvm compiler runtime static code
|
||||
|
||||
@@ -165,11 +165,6 @@ for x; do
|
||||
# information."
|
||||
set -- "$@" -momit-leaf-frame-pointer -foptimize-sibling-calls
|
||||
continue
|
||||
elif [ x"$x" != x"${x#-Werror}" ] || \
|
||||
[ x"$x" = x"-pedantic-errors" ]; then
|
||||
# this toolchain is intended for building other people's code
|
||||
# elevating warnings into errors, should only be done by devs
|
||||
continue
|
||||
elif [ x"$x" = x"-dumpversion" ]; then
|
||||
echo $GCC_VERSION
|
||||
exit 0
|
||||
|
||||
Reference in new issue
Block a user