Remove old stack code and improve dirstream

This commit is contained in:
Justine Tunney 2023-08-16 07:54:40 -07:00
parent 74caabb823
commit dc6c67256f
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
61 changed files with 463 additions and 595 deletions

View file

@ -279,8 +279,7 @@ SECTIONS {
}
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
ape_stack_memsz2 = ape_stack_memsz * 2;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
_tls_size = _tbss_end - _tdata_start;
_tdata_size = _tdata_end - _tdata_start;

View file

@ -794,7 +794,7 @@ ape_loader_end:
.stub ape_stack_vaddr,quad // is mmap()'d with MAP_FIXED
.stub ape_stack_paddr,quad // ignored
.stub ape_stack_filesz,quad // ignored
.stub ape_stack_memsz2,quad // is mmap(size) argument
.stub ape_stack_memsz,quad // ignored?
.stub ape_stack_align,quad // must be 16+
#if SupportsOpenbsd() || SupportsNetbsd()
@ -1082,8 +1082,8 @@ ape_pe: .ascin "PE",4
.long 0 // Checksum
.short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console
.short v_ntdllchar // DllCharacteristics
.quad 0x30000 // StackReserve
.quad 0x30000 // StackCommit
.quad 0x10000 // StackReserve
.quad 0x10000 // StackCommit
.quad 0 // HeapReserve
.quad 0 // HeapCommit
.long 0 // LoaderFlags
@ -1735,7 +1735,7 @@ ape_grub_entry:
αcτµαlly pδrταblε εxεcµταblε § cosmopolitan libc runtime runtime
*/
kernel: movabs $ape_stack_vaddr,%rsp
add $ape_stack_memsz2,%rsp
add $ape_stack_memsz,%rsp
movl $0,0x7b000 // unmap null 2mb
#if USE_SYMBOL_HACK
.byte 0x0f,0x1f,0207 // nop rdi binbase

View file

@ -584,8 +584,7 @@ ape_stack_offset = 0;
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
ape_stack_filesz = 0;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
ape_stack_memsz2 = ape_stack_memsz * 2;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
ape_stack_align = 16;
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);

View file

@ -21,7 +21,9 @@
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/errfuns.h"
/**
@ -30,14 +32,27 @@
* This does *not* update the `PWD` environment variable.
*
* @return 0 on success, or -1 w/ errno
* @raise ELOOP if a loop was detected resolving components of `path`
* @raise EACCES if search permission was denied on directory
* @raise ENOTDIR if component of `path` isn't a directory
* @raise ENOMEM if insufficient memory was available
* @raise EFAULT if `path` points to invalid memory
* @raise ENOTSUP if `path` is a `/zip/...` file
* @raise ENAMETOOLONG if `path` was too long
* @raise ENOENT if `path` doesn't exist
* @raise EIO if an i/o error happened
* @asyncsignalsafe
* @see fchdir()
*/
int chdir(const char *path) {
int rc;
struct ZiposUri zipname;
GetProgramExecutableName(); // XXX: ugly workaround
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
rc = efault();
} else if (_weaken(__zipos_parseuri) &&
_weaken(__zipos_parseuri)(path, &zipname) != -1) {
rc = enotsup();
} else if (!IsWindows()) {
rc = sys_chdir(path);
} else {

View file

@ -17,22 +17,30 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Sets current directory based on file descriptor.
*
* This does *not* update the `PWD` environment variable.
*
* @raise EACCES if search permission was denied on directory
* @raise ENOTDIR if `dirfd` doesn't refer to a directory
* @raise EBADF if `dirfd` isn't a valid file descriptor
* @raise ENOTSUP if `dirfd` refers to `/zip/...` file
* @see open(path, O_DIRECTORY)
* @asyncsignalsafe
*/
int fchdir(int dirfd) {
int rc;
if (!IsWindows()) {
if (__isfdkind(dirfd, kFdZip)) {
rc = enotsup();
} else if (!IsWindows()) {
rc = sys_fchdir(dirfd);
} else {
rc = sys_fchdir_nt(dirfd);

View file

@ -22,6 +22,7 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/stack.h"
#include "libc/sysv/consts/rlimit.h"
#include "libc/sysv/errfuns.h"
@ -41,6 +42,10 @@ int getrlimit(int resource, struct rlimit *rlim) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_getrlimit(resource, rlim);
} else if (resource == RLIMIT_STACK) {
rlim->rlim_cur = (uintptr_t)ape_stack_memsz;
rlim->rlim_max = (uintptr_t)ape_stack_memsz;
rc = 0;
} else if (resource == RLIMIT_AS) {
rlim->rlim_cur = __virtualmax;
rlim->rlim_max = __virtualmax;

View file

@ -78,6 +78,8 @@ int setrlimit(int resource, const struct rlimit *rlim) {
// TODO(jart): What's up with XNU and NetBSD?
__virtualmax = rlim->rlim_cur;
}
} else if (resource == RLIMIT_STACK) {
rc = enotsup();
} else if (resource == RLIMIT_AS) {
__virtualmax = rlim->rlim_cur;
rc = 0;

View file

@ -78,6 +78,7 @@ unsigned __wincrash(struct NtExceptionPointers *ep) {
break;
case kNtSignalGuardPage:
case kNtSignalInPageError:
case kNtStatusStackOverflow:
code = SEGV_MAPERR;
sig = SIGSEGV;
break;
@ -128,7 +129,9 @@ unsigned __wincrash(struct NtExceptionPointers *ep) {
sig = SIGSYS;
break;
default:
return kNtExceptionContinueSearch;
code = ep->ExceptionRecord->ExceptionCode;
sig = SIGSEGV;
break;
}
rip = ep->ContextRecord->Rip;

View file

@ -153,9 +153,8 @@ typedef struct {
#define libcesque dontthrow nocallback
#define memcpyesque libcesque
#define strlenesque libcesque nosideeffect paramsnonnull()
#define vallocesque \
libcesque dontdiscard returnsaligned((APE_PAGESIZE)) \
returnspointerwithnoaliases
#define vallocesque \
libcesque dontdiscard returnsaligned((65536)) returnspointerwithnoaliases
#define reallocesque libcesque returnsaligned((16))
#define mallocesque reallocesque returnspointerwithnoaliases
#define interruptfn nocallersavedregisters forcealignargpointer

View file

@ -74,8 +74,6 @@
#define __BIGGEST_ALIGNMENT__ 16
#endif
#define APE_STACKSIZE 8388608
#define APE_PAGESIZE 65536
#ifdef _COSMO_SOURCE
#define FRAMESIZE 65536
#define _PAGESIZE 4096

View file

@ -20,7 +20,7 @@ char *critbit0_get(struct critbit0 *, const char *);
intptr_t critbit0_allprefixed(struct critbit0 *, const char *,
intptr_t (*)(const char *, void *), void *)
paramsnonnull((1, 2, 3)) dontthrow;
int critbit0_emplace(struct critbit0 *, char *, size_t) paramsnonnull();
int critbit0_emplace(struct critbit0 *, const void *, size_t) paramsnonnull();
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -21,23 +21,35 @@
#include "libc/mem/mem.h"
#include "libc/str/str.h"
static void *critbit0_dup(const void *u, size_t ulen) {
char *res;
if ((res = malloc(ulen + 1))) {
if (ulen) {
memcpy(res, u, ulen);
}
res[ulen] = 0;
}
return res;
}
/**
* Inserts 𝑢 into 𝑡 without copying.
*
* @param t is critical bit tree
* @param u is nul-terminated string which must be 8+ byte aligned
* and becomes owned by the tree afterwards
* @return true if 𝑡 was mutated, or -1 w/ errno
* @return 1 if 𝑡 was mutated, 0 if present, or -1 w/ errno
* @note h/t djb and agl
*/
int critbit0_emplace(struct critbit0 *t, char *u, size_t ulen) {
int critbit0_emplace(struct critbit0 *t, const void *u, size_t ulen) {
unsigned char *p = t->root;
if (!p) {
t->root = u;
t->count = 1;
return 1;
if ((u = critbit0_dup(u, ulen))) {
t->root = u;
t->count = 1;
return 1;
} else {
return -1;
}
}
const unsigned char *const ubytes = (void *)u;
const unsigned char *ubytes = (void *)u;
while (1 & (intptr_t)p) {
struct CritbitNode *q = (void *)(p - 1);
unsigned char c = 0;
@ -66,7 +78,8 @@ DifferentByteFound:
unsigned char c = p[newbyte];
int newdirection = (1 + (newotherbits | c)) >> 8;
struct CritbitNode *newnode;
if ((newnode = malloc(sizeof(struct CritbitNode)))) {
if ((newnode = malloc(sizeof(struct CritbitNode))) &&
(ubytes = critbit0_dup(ubytes, ulen))) {
newnode->byte = newbyte;
newnode->otherbits = newotherbits;
newnode->child[1 - newdirection] = (void *)ubytes;
@ -87,6 +100,7 @@ DifferentByteFound:
t->count++;
return 1;
} else {
free(newnode);
return -1;
}
}

View file

@ -25,15 +25,9 @@
* Inserts 𝑢 into 𝑡.
* @param t tree
* @param u NUL-terminated string
* @return true if 𝑡 was mutated, or -1 w/ errno
* @return 1 if 𝑡 was mutated, 0 if present, or -1 w/ errno
* @note h/t djb and agl
*/
int critbit0_insert(struct critbit0 *t, const char *u) {
char *p;
size_t n;
if ((p = malloc((n = strlen(u)) + 1))) {
return critbit0_emplace(t, memcpy(p, u, n + 1), n);
} else {
return -1;
}
return critbit0_emplace(t, u, strlen(u));
}

View file

@ -123,66 +123,6 @@ cosmo: push %rbp
pop %rdi
.init.end 304,_init_tls
#if !IsTiny()
// Creates deterministically addressed stack we can use
//
// This helps debugging be more comprehensible, because
// when diagnosing low-level problems when error report
// isn't working, sometimes numbers are all you have to
// go on, and we can't use them if kernel hardening has
// configured that meaningful data to be randomized.
//
// Having deterministic addresses is also key to ensure
// builds, execution, and other things are reproducible
.init.start 304,_init_stack
testb IsWindows()
jnz 9f
testb IsMetal()
jnz 9f
push %rdi
push %rsi
// allocate stack
movabs $ape_stack_vaddr,%rdi
mov $ape_stack_memsz,%esi
mov $ape_stack_prot,%edx
mov $MAP_STACK,%ecx
or MAP_ANONYMOUS,%ecx
or $-1,%r8
xor %r9d,%r9d
push %rsi
push %rsi
call mmap
pop %r8
pop %r8
pop %rsi
pop %rdi
cmp $-1,%rax
je 9f
// switch stacks
//
// we subtract 8 because the openbsd kernel always checks rsp
// is on a MAP_STACK interval non-inclusively of stack + size
leave
pop %rcx // return address
sub $8,%r8d // openbsd:stackbound
lea (%rax,%r8),%rsp
mov $ape_stack_align,%eax
neg %rax
and %rax,%rsp
push %rcx
push %rbp
mov %rsp,%rbp
9: nop
.init.end 304,_init_stack
.weak ape_stack_prot
.weak ape_stack_vaddr
.weak ape_stack_memsz
.weak ape_stack_align
#endif
#if IsAsan()
.init.start 305,_init_symbols
push %rdi

View file

@ -64,8 +64,6 @@ extern init_f *__preinit_array_start[] __attribute__((__weak__));
extern init_f *__preinit_array_end[] __attribute__((__weak__));
extern init_f *__init_array_start[] __attribute__((__weak__));
extern init_f *__init_array_end[] __attribute__((__weak__));
extern char ape_stack_vaddr[] __attribute__((__weak__));
extern char ape_stack_memsz[] __attribute__((__weak__));
extern char ape_stack_prot[] __attribute__((__weak__));
extern pthread_mutex_t __mmi_lock_obj;
extern int hostos asm("__hostos");
@ -161,16 +159,6 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
__enable_tls();
__switch_stacks(argc, argv, envp, auxv, cosmo2,
(char *)mmap(ape_stack_vaddr, (uintptr_t)ape_stack_memsz,
MAP_FIXED | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) +
(uintptr_t)ape_stack_memsz);
}
wontreturn textstartup void cosmo2(int argc, char **argv, char **envp,
unsigned long *auxv) {
#if 0
#if IsAsan()
// TODO(jart): Figure out ASAN data model on AARCH64.

View file

@ -453,9 +453,11 @@ dontasan textstartup void __printargs(const char *prologue) {
PRINT(" ☼ %s = %#s", "GetInterpreterExecutableName",
GetInterpreterExecutableName(u.path, sizeof(u.path)));
PRINT(" ☼ %s = %p", "RSP", __builtin_frame_address(0));
PRINT(" ☼ %s = %p", "GetStackAddr()", GetStackAddr());
PRINT(" ☼ %s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
PRINT(" ☼ %s = %p", "GetStackSize()", GetStackSize());
PRINT(" ☼ %s = %p", "GetGuardSize()", GetGuardSize());
PRINT(" ☼ %s = %p", "GetStackAddr()", GetStackAddr());
PRINT(" ☼ %s = %p", "GetStaticStackSize()", GetStaticStackSize());
PRINT(" ☼ %s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
PRINT("");
PRINT("MEMTRACK");

View file

@ -3,6 +3,20 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#ifdef _COSMO_SOURCE
/**
* Returns preferred size and alignment of thread stack.
*
* This will always be equal to `PTHREAD_STACK_MIN`.
*/
#define GetStackSize() 262144
/**
* Returns preferred stack guard size.
*
* This is the max cpu page size of supported architectures.
*/
#define GetGuardSize() 16384
/**
* Tunes APE stack maximum size.
*
@ -80,20 +94,6 @@ extern char ape_stack_prot[] __attribute__((__weak__));
extern char ape_stack_memsz[] __attribute__((__weak__));
extern char ape_stack_align[] __attribute__((__weak__));
/**
* Returns preferred size and alignment of thread stack.
*
* This will always be equal to `PTHREAD_STACK_MIN`.
*/
#define GetStackSize() 262144
/**
* Returns preferred stack guard size.
*
* This is the max cpu page size of supported architectures.
*/
#define GetGuardSize() 16384
/**
* Returns address of bottom of stack.
*
@ -107,6 +107,8 @@ extern char ape_stack_align[] __attribute__((__weak__));
#define GetStackAddr() \
(((intptr_t)__builtin_frame_address(0) - 1) & -GetStackSize())
#define GetStaticStackSize() ((uintptr_t)ape_stack_memsz)
#ifdef __x86_64__
/**
* Returns preferred bottom address of stack.

View file

@ -1,31 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
__switch_stacks:
#ifdef __x86_64__
int3
#elif defined(__aarch64__)
mov x29,0
mov sp,x5
br x4
#else
#error "unsupported architecture"
#endif
.endfn __switch_stacks,globl

View file

@ -22,14 +22,11 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nt/console.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/creationdisposition.h"
@ -59,12 +56,8 @@
#ifdef __x86_64__
// clang-format off
__msabi extern typeof(AddVectoredExceptionHandler) *const __imp_AddVectoredExceptionHandler;
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
__msabi extern typeof(CreateFileMapping) *const __imp_CreateFileMappingW;
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
__msabi extern typeof(ExitProcess) *const __imp_ExitProcess;
__msabi extern typeof(FreeEnvironmentStrings) *const __imp_FreeEnvironmentStringsW;
__msabi extern typeof(GetConsoleMode) *const __imp_GetConsoleMode;
__msabi extern typeof(GetCurrentProcess) *const __imp_GetCurrentProcess;
@ -72,21 +65,13 @@ __msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId;
__msabi extern typeof(GetEnvironmentStrings) *const __imp_GetEnvironmentStringsW;
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
__msabi extern typeof(ReadFile) *const __imp_ReadFile;
__msabi extern typeof(SetConsoleCP) *const __imp_SetConsoleCP;
__msabi extern typeof(SetConsoleMode) *const __imp_SetConsoleMode;
__msabi extern typeof(SetConsoleOutputCP) *const __imp_SetConsoleOutputCP;
__msabi extern typeof(SetStdHandle) *const __imp_SetStdHandle;
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
// clang-format on
/*
* TODO: Why can't we allocate addresses above 4GB on Windows 7 x64?
* TODO: How can we ensure we never overlap with KERNEL32.DLL?
*/
extern int64_t __wincrashearly;
extern const signed char kNtConsoleHandles[3];
extern void cosmo(int, char **, char **, long (*)[2]) wontreturn;
@ -117,55 +102,15 @@ __msabi static inline char16_t *MyCommandLine(void) {
return cmd;
}
__msabi static inline size_t StrLen16(const char16_t *s) {
size_t n;
for (n = 0;; ++n) {
if (!s[n]) {
return n;
}
}
}
__msabi static textwindows int OnEarlyWinCrash(struct NtExceptionPointers *ep) {
uint32_t wrote;
char buf[64], *p = buf;
*p++ = 'c';
*p++ = 'r';
*p++ = 'a';
*p++ = 's';
*p++ = 'h';
*p++ = ' ';
*p++ = '0';
*p++ = 'x';
p = __fixcpy(p, ep->ExceptionRecord->ExceptionCode, 32);
*p++ = ' ';
*p++ = 'r';
*p++ = 'i';
*p++ = 'p';
*p++ = ' ';
p = __fixcpy(p, ep->ContextRecord ? ep->ContextRecord->Rip : -1, 32);
*p++ = '\r';
*p++ = '\n';
__imp_WriteFile(__imp_GetStdHandle(kNtStdErrorHandle), buf, p - buf, &wrote,
0);
__imp_ExitProcess(11);
__builtin_unreachable();
}
__msabi static textwindows bool ProxyStdin(void) {
return true;
}
// this ensures close(1) won't accidentally close(2) for example
__msabi static textwindows void DeduplicateStdioHandles(void) {
long i, j;
int64_t h1, h2, h3, proc;
for (i = 0; i < 3; ++i) {
h1 = __imp_GetStdHandle(kNtConsoleHandles[i]);
for (j = i + 1; j < 3; ++j) {
h3 = h2 = __imp_GetStdHandle(kNtConsoleHandles[j]);
for (long i = 0; i < 3; ++i) {
int64_t h1 = __imp_GetStdHandle(kNtConsoleHandles[i]);
for (long j = i + 1; j < 3; ++j) {
int64_t h2 = __imp_GetStdHandle(kNtConsoleHandles[j]);
if (h1 == h2) {
proc = __imp_GetCurrentProcess();
int64_t h3, proc = __imp_GetCurrentProcess();
__imp_DuplicateHandle(proc, h2, proc, &h3, 0, true,
kNtDuplicateSameAccess);
__imp_SetStdHandle(kNtConsoleHandles[j], h3);
@ -175,53 +120,35 @@ __msabi static textwindows void DeduplicateStdioHandles(void) {
}
__msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
bool32 rc;
int64_t h, hand;
uint32_t oldprot;
struct WinArgs *wa;
char inflagsbuf[256];
char outflagsbuf[128];
const char16_t *env16;
int i, prot, count, version;
size_t allocsize, stacksize;
intptr_t stackaddr, allocaddr;
version = NtGetPeb()->OSMajorVersion;
uintptr_t stackaddr, allocaddr;
__oldstack = (intptr_t)__builtin_frame_address(0);
if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) {
rc = __imp_SetConsoleCP(kNtCpUtf8);
NTTRACE("SetConsoleCP(kNtCpUtf8) → %hhhd", rc);
rc = __imp_SetConsoleOutputCP(kNtCpUtf8);
NTTRACE("SetConsoleOutputCP(kNtCpUtf8) → %hhhd", rc);
for (i = 0; i < 3; ++i) {
hand = __imp_GetStdHandle(kNtConsoleHandles[i]);
rc = __imp_GetConsoleMode(hand, __ntconsolemode + i);
NTTRACE("GetConsoleMode(%p, [%s]) → %hhhd", hand,
i ? (DescribeNtConsoleOutFlags)(outflagsbuf, __ntconsolemode[i])
: (DescribeNtConsoleInFlags)(inflagsbuf, __ntconsolemode[i]),
rc);
rc = __imp_SetConsoleMode(hand, kConsoleModes[i]);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", hand,
i ? (DescribeNtConsoleOutFlags)(outflagsbuf, kConsoleModes[i])
: (DescribeNtConsoleInFlags)(inflagsbuf, kConsoleModes[i]),
rc);
if (NtGetPeb()->OSMajorVersion >= 10 &&
(intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui) {
__imp_SetConsoleCP(kNtCpUtf8);
__imp_SetConsoleOutputCP(kNtCpUtf8);
for (int i = 0; i < 3; ++i) {
int64_t hand = __imp_GetStdHandle(kNtConsoleHandles[i]);
__imp_GetConsoleMode(hand, __ntconsolemode + i);
__imp_SetConsoleMode(hand, kConsoleModes[i]);
}
(void)rc;
}
_Static_assert(sizeof(struct WinArgs) % FRAMESIZE == 0, "");
_mmi.p = _mmi.s;
_mmi.n = ARRAYLEN(_mmi.s);
stackaddr = GetStaticStackAddr(0);
stacksize = GetStackSize();
stacksize = GetStaticStackSize();
allocaddr = stackaddr;
allocsize = stacksize + sizeof(struct WinArgs);
NTTRACE("WinMainNew() mapping %'zu byte stack at %p", allocsize, allocaddr);
__imp_MapViewOfFileEx((_mmi.p[0].h = __imp_CreateFileMappingW(
-1, &kNtIsInheritable, kNtPageExecuteReadwrite,
allocsize >> 32, allocsize, NULL)),
kNtFileMapWrite | kNtFileMapExecute, 0, 0, allocsize,
(void *)allocaddr);
prot = (intptr_t)ape_stack_prot;
int prot = (intptr_t)ape_stack_prot;
if (~prot & PROT_EXEC) {
uint32_t oldprot;
__imp_VirtualProtect((void *)allocaddr, allocsize, kNtPageReadwrite,
&oldprot);
}
@ -232,20 +159,17 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
_mmi.p[0].size = allocsize;
_mmi.i = 1;
wa = (struct WinArgs *)(allocaddr + stacksize);
NTTRACE("WinMainNew() loading arg block");
count = GetDosArgv(cmdline, wa->argblock, ARRAYLEN(wa->argblock), wa->argv,
ARRAYLEN(wa->argv));
for (i = 0; wa->argv[0][i]; ++i) {
int count = GetDosArgv(cmdline, wa->argblock, ARRAYLEN(wa->argblock),
wa->argv, ARRAYLEN(wa->argv));
for (int i = 0; wa->argv[0][i]; ++i) {
if (wa->argv[0][i] == '\\') {
wa->argv[0][i] = '/';
}
}
env16 = __imp_GetEnvironmentStringsW();
NTTRACE("WinMainNew() loading environment");
const char16_t *env16 = __imp_GetEnvironmentStringsW();
GetDosEnviron(env16, wa->envblock, ARRAYLEN(wa->envblock) - 8, wa->envp,
ARRAYLEN(wa->envp) - 1);
__imp_FreeEnvironmentStringsW(env16);
NTTRACE("WinMainNew() switching stacks");
_jmpstack((char *)(stackaddr + stacksize - (intptr_t)ape_stack_align), cosmo,
count, wa->argv, wa->envp, wa->auxv);
}
@ -261,16 +185,11 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
if (_weaken(WinMainStdin)) {
_weaken(WinMainStdin)();
}
#if !IsTiny()
__wincrashearly =
__imp_AddVectoredExceptionHandler(1, (void *)OnEarlyWinCrash);
#endif
cmdline = MyCommandLine();
#ifdef SYSDEBUG
/* sloppy flag-only check for early initialization */
if (__strstr16(cmdline, u"--strace")) ++__strace;
#endif
NTTRACE("WinMain()");
if (_weaken(WinSockInit)) {
_weaken(WinSockInit)();
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kprintf.h"
@ -26,6 +27,7 @@
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
@ -64,19 +66,19 @@ static void __zipos_munmap_unneeded(const uint8_t *base, const uint8_t *cdir,
*/
struct Zipos *__zipos_get(void) {
char *endptr;
ssize_t size;
int fd, err, msg;
struct stat st;
static bool once;
struct Zipos *res;
int x, fd, err, msg;
uint8_t *map, *cdir;
const char *progpath;
static struct Zipos zipos;
__zipos_lock();
if (!once) {
progpath = getenv("COSMOPOLITAN_INIT_ZIPOS");
if (progpath) {
fd = strtol(progpath, &endptr, 10);
if (*endptr) fd = -1;
// this environment variable may be a filename or file descriptor
if ((progpath = getenv("COSMOPOLITAN_INIT_ZIPOS")) &&
(x = strtol(progpath, &endptr, 10)) >= 0 && !*endptr) {
fd = x;
} else {
fd = -1;
}
@ -88,16 +90,16 @@ struct Zipos *__zipos_get(void) {
fd = open(progpath, O_RDONLY);
}
if (fd != -1) {
if ((size = lseek(fd, 0, SEEK_END)) != -1 &&
(map = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) !=
MAP_FAILED) {
if ((cdir = GetZipEocd(map, size, &err))) {
if (!fstat(fd, &st) && (map = mmap(0, st.st_size, PROT_READ,
MAP_PRIVATE, fd, 0)) != MAP_FAILED) {
if ((cdir = GetZipEocd(map, st.st_size, &err))) {
__zipos_munmap_unneeded(map, cdir, map);
zipos.map = map;
zipos.cdir = cdir;
zipos.dev = st.st_ino;
msg = kZipOk;
} else {
munmap(map, size);
munmap(map, st.st_size);
msg = !cdir ? err : kZipErrorRaceCondition;
}
} else {

View file

@ -21,27 +21,26 @@
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#include "libc/zip.internal.h"
int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
size_t lf;
if (zipos && st) {
bzero(st, sizeof(*st));
if (cf == ZIPOS_SYNTHETIC_DIRECTORY) {
st->st_mode = S_IFDIR | 0555;
} else {
lf = GetZipCfileOffset(zipos->map + cf);
st->st_mode = GetZipCfileMode(zipos->map + cf);
st->st_size = GetZipLfileUncompressedSize(zipos->map + lf);
st->st_blocks =
roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512;
GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim,
&st->st_ctim, 0);
st->st_birthtim = st->st_ctim;
}
return 0;
bzero(st, sizeof(*st));
st->st_ino = cf;
st->st_nlink = 1;
st->st_dev = zipos->dev;
st->st_blksize = FRAMESIZE;
if (cf == ZIPOS_SYNTHETIC_DIRECTORY) {
st->st_mode = S_IFDIR | 0555;
} else {
return einval();
lf = GetZipCfileOffset(zipos->map + cf);
st->st_mode = GetZipCfileMode(zipos->map + cf);
st->st_size = GetZipLfileUncompressedSize(zipos->map + lf);
st->st_blocks =
roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512;
GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim,
&st->st_ctim, 0);
st->st_birthtim = st->st_ctim;
}
return 0;
}

View file

@ -34,6 +34,7 @@ struct ZiposHandle {
struct Zipos {
uint8_t *map;
uint8_t *cdir;
uint64_t dev;
struct ZiposHandle *freelist;
};

View file

@ -25,13 +25,19 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/nopl.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/macros.internal.h"
#include "libc/mem/critbit0.h"
#include "libc/mem/mem.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/filetype.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/win32finddata.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
@ -60,18 +66,20 @@ int sys_getdents(unsigned, void *, unsigned, long *);
struct dirstream {
int fd;
bool iszip;
long tell;
int64_t hand;
int64_t tell;
char16_t *name;
pthread_mutex_t lock;
struct {
uint64_t offset;
uint64_t records;
size_t prefixlen;
uint8_t prefix[ZIPOS_PATH_MAX];
} zip;
struct dirent ent;
union {
struct {
struct Zipos *zipos;
uint64_t inode;
uint64_t offset;
uint64_t records;
size_t prefixlen;
uint8_t prefix[ZIPOS_PATH_MAX];
struct critbit0 found;
} zip;
struct {
unsigned buf_pos;
unsigned buf_end;
@ -80,6 +88,8 @@ struct dirstream {
struct {
bool isdone;
struct NtWin32FindData windata;
char16_t name16[PATH_MAX];
uint32_t name16len;
};
};
};
@ -119,69 +129,40 @@ struct dirent_netbsd {
char d_name[512];
};
// TODO(jart): wipe these locks when forking
void _lockdir(DIR *dir) {
pthread_mutex_lock(&dir->lock);
}
void _unlockdir(DIR *dir) {
pthread_mutex_unlock(&dir->lock);
}
#ifdef _NOPL1
#define _lockdir(d) _NOPL1("__threadcalls", _lockdir, d)
#define _unlockdir(d) _NOPL1("__threadcalls", _unlockdir, d)
#else
#define _lockdir(d) (__threaded ? _lockdir(d) : 0)
#define _unlockdir(d) (__threaded ? _unlockdir(d) : 0)
#endif
static textwindows DIR *opendir_nt_impl(char16_t *name, size_t len) {
DIR *res;
if (len + 2 + 1 <= PATH_MAX) {
if (len == 1 && name[0] == '.') {
name[0] = '*';
} else {
if (len > 1 && name[len - 1] != u'\\') {
name[len++] = u'\\';
}
name[len++] = u'*';
}
name[len] = u'\0';
if ((res = calloc(1, sizeof(DIR)))) {
if ((res->hand = FindFirstFile(name, &res->windata)) != -1) {
return res;
}
__fix_enotdir(-1, name);
free(res);
}
} else {
enametoolong();
static void _lockdir(DIR *dir) {
if (__threaded) {
pthread_mutex_lock(&dir->lock);
}
return NULL;
}
static textwindows dontinline DIR *fdopendir_nt(int fd) {
DIR *res;
char16_t *name;
if (__isfdkind(fd, kFdFile)) {
if ((name = calloc(1, PATH_MAX * 2))) {
if ((res = opendir_nt_impl(
name, GetFinalPathNameByHandle(
g_fds.p[fd].handle, name, PATH_MAX,
kNtFileNameNormalized | kNtVolumeNameDos)))) {
res->name = name;
res->fd = -1;
close(fd);
return res;
}
free(name);
}
} else {
ebadf();
static void _unlockdir(DIR *dir) {
if (__threaded) {
pthread_mutex_unlock(&dir->lock);
}
return NULL;
}
static textwindows dontinline int fdopendir_nt(DIR *res, int fd) {
if (!__isfdkind(fd, kFdFile)) {
return ebadf();
}
res->name16len = GetFinalPathNameByHandle(
g_fds.p[fd].handle, res->name16, ARRAYLEN(res->name16),
kNtFileNameNormalized | kNtVolumeNameDos);
if (!res->name16len) {
return __winerr();
}
if (res->name16len + 2 + 1 > ARRAYLEN(res->name16)) {
return enametoolong();
}
if (res->name16len > 1 && res->name16[res->name16len - 1] != u'\\') {
res->name16[res->name16len++] = u'\\';
}
res->name16[res->name16len++] = u'*';
res->name16[res->name16len] = u'\0';
if ((res->hand = FindFirstFile(res->name16, &res->windata)) == -1) {
return __fix_enotdir(-1, res->name16);
}
return 0;
}
static textwindows uint8_t GetNtDirentType(struct NtWin32FindData *w) {
@ -204,26 +185,57 @@ static textwindows uint8_t GetNtDirentType(struct NtWin32FindData *w) {
}
static textwindows dontinline struct dirent *readdir_nt(DIR *dir) {
size_t i;
if (!dir->isdone) {
bzero(&dir->ent, sizeof(dir->ent));
dir->ent.d_ino++;
dir->ent.d_off = dir->tell++;
dir->ent.d_reclen =
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name) - 2,
dir->windata.cFileName)
.ax;
for (i = 0; i < dir->ent.d_reclen; ++i) {
if (dir->ent.d_name[i] == '\\') {
dir->ent.d_name[i] = '/';
}
}
dir->ent.d_type = GetNtDirentType(&dir->windata);
dir->isdone = !FindNextFile(dir->hand, &dir->windata);
return &dir->ent;
} else {
if (dir->isdone) {
return NULL;
}
// join absolute path
uint64_t ino = 0;
size_t i = dir->name16len - 1;
char16_t *p = dir->windata.cFileName;
while (*p) {
if (i + 1 < ARRAYLEN(dir->name16)) {
dir->name16[i++] = *p++;
} else {
// ignore errors and set inode to zero
goto GiveUpOnGettingInode;
}
}
dir->name16[i] = u'\0';
// get inode that's consistent with stat()
int e = errno;
int64_t fh =
CreateFile(dir->name16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,
kNtFileAttributeNormal | kNtFileFlagBackupSemantics |
kNtFileFlagOpenReparsePoint,
0);
if (fh != -1) {
struct NtByHandleFileInformation wst;
if (GetFileInformationByHandle(fh, &wst)) {
ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
}
CloseHandle(fh);
} else {
// ignore errors and set inode to zero
// TODO(jart): How do we handle "." and ".."?
errno = e;
}
GiveUpOnGettingInode:
// restore original directory search path
dir->name16[dir->name16len - 1] = u'*';
dir->name16[dir->name16len] = u'\0';
// create result object
bzero(&dir->ent, sizeof(dir->ent));
dir->ent.d_ino = ino;
dir->ent.d_off = dir->tell++;
tprecode16to8(dir->ent.d_name, sizeof(dir->ent.d_name),
dir->windata.cFileName);
dir->ent.d_type = GetNtDirentType(&dir->windata);
dir->isdone = !FindNextFile(dir->hand, &dir->windata);
return &dir->ent;
}
/**
@ -246,8 +258,12 @@ DIR *fdopendir(int fd) {
dir->fd = fd;
if (!__isfdkind(fd, kFdZip)) {
if (IsWindows()) {
free(dir);
return fdopendir_nt(fd);
if (!fdopendir_nt(dir, fd)) {
return dir;
} else {
free(dir);
return 0;
}
}
return dir;
}
@ -285,6 +301,8 @@ DIR *fdopendir(int fd) {
dir->zip.prefixlen = len;
// setup state values for directory iterator
dir->zip.zipos = h->zipos;
dir->zip.inode = h->cfile;
dir->zip.offset = GetZipCdirOffset(h->zipos->cdir);
dir->zip.records = GetZipCdirRecords(h->zipos->cdir);
@ -325,124 +343,123 @@ DIR *opendir(const char *name) {
return res;
}
static struct dirent *readdir_impl(DIR *dir) {
size_t n;
int rc, mode;
uint8_t *s, *p;
struct Zipos *zip;
struct dirent *ent;
struct dirent *lastent;
struct dirent_bsd *bsd;
struct dirent_netbsd *nbsd;
struct dirent_openbsd *obsd;
if (dir->iszip) {
ent = 0;
zip = _weaken(__zipos_get)();
while (!ent && dir->tell < dir->zip.records + 2) {
if (!dir->tell) {
ent = (struct dirent *)dir->buf;
ent->d_ino++;
ent->d_off = dir->tell;
ent->d_reclen = 1;
ent->d_type = DT_DIR;
strcpy(ent->d_name, ".");
} else if (dir->tell == 1) {
ent = (struct dirent *)dir->buf;
ent->d_ino++;
ent->d_off = dir->tell;
ent->d_reclen = 2;
ent->d_type = DT_DIR;
strcpy(ent->d_name, "..");
} else {
s = ZIP_CFILE_NAME(zip->map + dir->zip.offset);
n = ZIP_CFILE_NAMESIZE(zip->map + dir->zip.offset);
if (dir->zip.prefixlen < n &&
!memcmp(dir->zip.prefix, s, dir->zip.prefixlen)) {
s += dir->zip.prefixlen;
n -= dir->zip.prefixlen;
p = memchr(s, '/', n);
if (!p || p + 1 - s == n) {
if (p + 1 - s == n) --n;
mode = GetZipCfileMode(zip->map + dir->zip.offset);
ent = (struct dirent *)dir->buf;
ent->d_ino++;
ent->d_off = dir->tell;
ent->d_reclen = MIN(n, 255);
ent->d_type = S_ISDIR(mode) ? DT_DIR : DT_REG;
if (ent->d_reclen) {
memcpy(ent->d_name, s, ent->d_reclen);
}
ent->d_name[ent->d_reclen] = 0;
} else {
lastent = (struct dirent *)dir->buf;
n = p - s;
n = MIN(n, 255);
if (!lastent->d_ino || (n != lastent->d_reclen) ||
memcmp(lastent->d_name, s, n)) {
ent = lastent;
mode = GetZipCfileMode(zip->map + dir->zip.offset);
ent->d_ino++;
ent->d_off = dir->tell;
ent->d_reclen = n;
ent->d_type = S_ISDIR(mode) ? DT_DIR : DT_REG;
if (ent->d_reclen) {
memcpy(ent->d_name, s, ent->d_reclen);
}
ent->d_name[ent->d_reclen] = 0;
}
}
}
dir->zip.offset += ZIP_CFILE_HDRSIZE(zip->map + dir->zip.offset);
}
dir->tell++;
}
return ent;
} else if (!IsWindows()) {
if (dir->buf_pos >= dir->buf_end) {
long basep = dir->tell;
rc = sys_getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep);
STRACE("sys_getdents(%d) → %d% m", dir->fd, rc);
if (!rc || rc == -1) return NULL;
dir->buf_pos = 0;
dir->buf_end = rc;
}
if (IsLinux()) {
ent = (struct dirent *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += ent->d_reclen;
dir->tell = ent->d_off;
} else if (IsOpenbsd()) {
obsd = (struct dirent_openbsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += obsd->d_reclen;
dir->tell = obsd->d_off;
static struct dirent *readdir_zipos(DIR *dir) {
struct dirent *ent = 0;
while (!ent && dir->tell < dir->zip.records + 2) {
size_t n;
if (!dir->tell) {
ent = &dir->ent;
ent->d_ino = obsd->d_fileno;
ent->d_off = obsd->d_off;
ent->d_reclen = obsd->d_reclen;
ent->d_type = obsd->d_type;
memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1);
} else if (IsNetbsd()) {
nbsd = (struct dirent_netbsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += nbsd->d_reclen;
ent->d_off = dir->tell;
ent->d_ino = dir->zip.inode;
ent->d_type = DT_DIR;
ent->d_name[0] = '.';
ent->d_name[1] = 0;
n = 1;
} else if (dir->tell == 1) {
ent = &dir->ent;
ent->d_ino = nbsd->d_fileno;
ent->d_off = (dir->tell += nbsd->d_reclen);
ent->d_reclen = nbsd->d_reclen;
ent->d_type = nbsd->d_type;
memcpy(ent->d_name, nbsd->d_name, MAX(256, nbsd->d_namlen + 1));
ent->d_off = dir->tell;
ent->d_ino = 0; // TODO
ent->d_type = DT_DIR;
ent->d_name[0] = '.';
ent->d_name[1] = '.';
ent->d_name[2] = 0;
n = 2;
} else {
bsd = (struct dirent_bsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += bsd->d_reclen;
ent = &dir->ent;
ent->d_ino = bsd->d_fileno;
ent->d_off = dir->tell++;
ent->d_reclen = bsd->d_reclen;
ent->d_type = bsd->d_type;
memcpy(ent->d_name, bsd->d_name, bsd->d_namlen + 1);
uint8_t *s = ZIP_CFILE_NAME(dir->zip.zipos->map + dir->zip.offset);
n = ZIP_CFILE_NAMESIZE(dir->zip.zipos->map + dir->zip.offset);
if (n > dir->zip.prefixlen &&
!memcmp(dir->zip.prefix, s, dir->zip.prefixlen)) {
s += dir->zip.prefixlen;
n -= dir->zip.prefixlen;
uint8_t *p = memchr(s, '/', n);
if (p) n = p - s;
if ((n = MIN(n, sizeof(ent->d_name) - 1)) &&
critbit0_emplace(&dir->zip.found, s, n) == 1) {
ent = &dir->ent;
ent->d_ino = dir->zip.offset;
ent->d_off = dir->tell;
ent->d_type =
S_ISDIR(GetZipCfileMode(dir->zip.zipos->map + dir->zip.offset))
? DT_DIR
: DT_REG;
memcpy(ent->d_name, s, n);
ent->d_name[n] = 0;
}
}
dir->zip.offset +=
ZIP_CFILE_HDRSIZE(dir->zip.zipos->map + dir->zip.offset);
}
return ent;
dir->tell++;
}
return ent;
}
static struct dirent *readdir_unix(DIR *dir) {
if (dir->buf_pos >= dir->buf_end) {
long basep = dir->tell;
int rc = sys_getdents(dir->fd, dir->buf, sizeof(dir->buf) - 256, &basep);
STRACE("sys_getdents(%d) → %d% m", dir->fd, rc);
if (!rc || rc == -1) {
return NULL;
}
dir->buf_pos = 0;
dir->buf_end = rc;
}
struct dirent *ent;
if (IsLinux()) {
ent = (struct dirent *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += ent->d_reclen;
dir->tell = ent->d_off;
} else if (IsOpenbsd()) {
struct dirent_openbsd *obsd =
(struct dirent_openbsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += obsd->d_reclen;
dir->tell = obsd->d_off;
ent = &dir->ent;
ent->d_ino = obsd->d_fileno;
ent->d_off = obsd->d_off;
ent->d_reclen = obsd->d_reclen;
ent->d_type = obsd->d_type;
memcpy(ent->d_name, obsd->d_name, obsd->d_namlen + 1);
} else if (IsNetbsd()) {
struct dirent_netbsd *nbsd =
(struct dirent_netbsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += nbsd->d_reclen;
ent = &dir->ent;
ent->d_ino = nbsd->d_fileno;
ent->d_off = (dir->tell += nbsd->d_reclen);
ent->d_reclen = nbsd->d_reclen;
ent->d_type = nbsd->d_type;
size_t n =
MIN(nbsd->d_namlen, MIN(sizeof(ent->d_name) - 1, sizeof(nbsd->d_name)));
memcpy(ent->d_name, nbsd->d_name, n);
ent->d_name[n] = 0;
} else {
struct dirent_bsd *bsd =
(struct dirent_bsd *)((char *)dir->buf + dir->buf_pos);
dir->buf_pos += bsd->d_reclen;
ent = &dir->ent;
ent->d_ino = bsd->d_fileno;
ent->d_off = dir->tell++;
ent->d_reclen = bsd->d_reclen;
ent->d_type = bsd->d_type;
memcpy(ent->d_name, bsd->d_name, bsd->d_namlen + 1);
}
if (ent) {
ent->d_reclen =
ROUNDUP(offsetof(struct dirent, d_name) + strlen(ent->d_name) + 1, 8);
}
return ent;
}
static struct dirent *readdir_impl(DIR *dir) {
if (dir->iszip) {
return readdir_zipos(dir);
}
if (IsWindows()) {
return readdir_nt(dir);
}
return readdir_unix(dir);
}
/**
@ -509,10 +526,12 @@ errno_t readdir_r(DIR *dir, struct dirent *output, struct dirent **result) {
int closedir(DIR *dir) {
int rc = 0;
if (dir) {
if (dir->iszip) {
critbit0_clear(&dir->zip.found);
}
if (dir->fd != -1) {
rc |= close(dir->fd);
}
free(dir->name);
if (IsWindows() && !dir->iszip) {
if (!FindClose(dir->hand)) {
rc = __winerr();
@ -540,11 +559,7 @@ long telldir(DIR *dir) {
* @threadsafe
*/
int dirfd(DIR *dir) {
int rc;
_lockdir(dir);
rc = dir->fd;
_unlockdir(dir);
return rc;
return dir->fd;
}
/**
@ -554,8 +569,9 @@ int dirfd(DIR *dir) {
void rewinddir(DIR *dir) {
_lockdir(dir);
if (dir->iszip) {
critbit0_clear(&dir->zip.found);
dir->tell = 0;
dir->zip.offset = GetZipCdirOffset(_weaken(__zipos_get)()->cdir);
dir->zip.offset = GetZipCdirOffset(dir->zip.zipos->cdir);
} else if (!IsWindows()) {
if (!lseek(dir->fd, 0, SEEK_SET)) {
dir->buf_pos = dir->buf_end = 0;
@ -563,7 +579,7 @@ void rewinddir(DIR *dir) {
}
} else {
FindClose(dir->hand);
if ((dir->hand = FindFirstFile(dir->name, &dir->windata)) != -1) {
if ((dir->hand = FindFirstFile(dir->name16, &dir->windata)) != -1) {
dir->isdone = false;
dir->tell = 0;
} else {
@ -577,27 +593,26 @@ void rewinddir(DIR *dir) {
* Seeks in directory stream.
* @threadsafe
*/
void seekdir(DIR *dir, long off) {
long i;
struct Zipos *zip;
void seekdir(DIR *dir, long tell) {
_lockdir(dir);
zip = _weaken(__zipos_get)();
if (dir->iszip) {
dir->zip.offset = GetZipCdirOffset(_weaken(__zipos_get)()->cdir);
for (i = 0; i < off && i < dir->zip.records; ++i) {
if (i >= 2) {
dir->zip.offset += ZIP_CFILE_HDRSIZE(zip->map + dir->zip.offset);
critbit0_clear(&dir->zip.found);
dir->tell = 0;
dir->zip.offset = GetZipCdirOffset(dir->zip.zipos->cdir);
while (dir->tell < tell) {
if (!readdir_zipos(dir)) {
break;
}
}
} else if (!IsWindows()) {
i = lseek(dir->fd, off, SEEK_SET);
dir->tell = lseek(dir->fd, tell, SEEK_SET);
dir->buf_pos = dir->buf_end = 0;
} else {
i = 0;
dir->tell = 0;
dir->isdone = false;
FindClose(dir->hand);
if ((dir->hand = FindFirstFile(dir->name, &dir->windata)) != -1) {
for (; i < off; ++i) {
if ((dir->hand = FindFirstFile(dir->name16, &dir->windata)) != -1) {
for (; dir->tell < tell; ++dir->tell) {
if (!FindNextFile(dir->hand, &dir->windata)) {
dir->isdone = true;
break;
@ -607,7 +622,6 @@ void seekdir(DIR *dir, long off) {
dir->isdone = true;
}
}
dir->tell = i;
_unlockdir(dir);
}

View file

@ -56,6 +56,7 @@ o//libc/stdio/appendw.o: private \
CFLAGS += \
-Os
o/$(MODE)/libc/stdio/dirstream.o \
o/$(MODE)/libc/stdio/posix_spawnattr.o \
o/$(MODE)/libc/stdio/posix_spawn_file_actions.o \
o/$(MODE)/libc/stdio/mt19937.o: private \

View file

@ -458,7 +458,7 @@ syscon auxv AT_NO_AUTOMOUNT 0x0800 0x0800 0 0 0 0x0800 0 0x0800
syscon rlimit RLIMIT_CPU 0 0 0 0 0 0 0 127 # max cpu time in seconds; see SIGXCPU; unix consensus
syscon rlimit RLIMIT_FSIZE 1 1 1 1 1 1 1 127 # max file size in bytes; unix consensus
syscon rlimit RLIMIT_DATA 2 2 2 2 2 2 2 127 # max mmap() / brk() / sbrk() size in bytes; unix consensus
syscon rlimit RLIMIT_STACK 3 3 3 3 3 3 3 127 # max stack size in bytes; see SIGXFSZ; unix consensus
syscon rlimit RLIMIT_STACK 3 3 3 3 3 3 3 1 # max stack size in bytes; see SIGXFSZ; unix consensus
syscon rlimit RLIMIT_CORE 4 4 4 4 4 4 4 127 # max core file size in bytes; unix consensus
syscon rlimit RLIMIT_RSS 5 5 5 5 5 5 5 127 # max physical memory size in bytes; see mmap()→ENOMEM; unix consensus
syscon rlimit RLIMIT_NPROC 6 6 7 7 7 7 7 127 # max number of processes; see fork()→EAGAIN; bsd consensus
@ -479,7 +479,7 @@ syscon compat RLIMIT_VMEM 9 9 5 5 10 127 10 127 # same as RLI
# resource limit special values
#
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
syscon rlim RLIM_NLIMITS 16 16 9 9 15 9 12 1
syscon rlim RLIM_NLIMITS 16 16 9 9 15 9 12 2
syscon rlim RLIM_INFINITY 0xffffffffffffffff 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0xffffffffffffffff
syscon rlim RLIM_SAVED_CUR 0xffffffffffffffff 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0xffffffffffffffff
syscon rlim RLIM_SAVED_MAX 0xffffffffffffffff 0xffffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0x7fffffffffffffff 0xffffffffffffffff

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon rlimit,RLIMIT_STACK,3,3,3,3,3,3,3,127
.syscon rlimit,RLIMIT_STACK,3,3,3,3,3,3,3,1

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon rlim,RLIM_NLIMITS,16,16,9,9,15,9,12,1
.syscon rlim,RLIM_NLIMITS,16,16,9,9,15,9,12,2

View file

@ -52,7 +52,7 @@ void *xrealloc(void *, size_t)
attributeallocsize((2)) dontthrow nocallback dontdiscard;
void *xcalloc(size_t, size_t) attributeallocsize((1, 2))
returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull;
void *xvalloc(size_t) attributeallocsize((1)) returnsaligned((APE_PAGESIZE))
void *xvalloc(size_t) attributeallocsize((1)) returnsaligned((65536))
returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull;
void *xmemalign(size_t, size_t) attributeallocalign((1)) attributeallocsize((2))
returnspointerwithnoaliases dontthrow nocallback dontdiscard returnsnonnull;

View file

@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.internal.h"

View file

@ -20,7 +20,6 @@
#include "libc/calls/struct/flock.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/f.h"

View file

@ -29,7 +29,6 @@
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/internal.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/stdio/rand.h"
#include "libc/testlib/testlib.h"

View file

@ -19,7 +19,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/dos2errno.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/errors.h"
#include "libc/sock/internal.h"
#include "libc/str/str.h"

View file

@ -19,7 +19,6 @@
#include "libc/atomic.h"
#include "libc/calls/struct/timespec.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
#include "third_party/zip/zip.h"

View file

@ -22,7 +22,6 @@
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/critbit0.h"
#include "libc/intrin/bits.h"
#include "libc/mem/critbit0.h"
#include "libc/mem/mem.h"
@ -128,3 +129,10 @@ TEST(critbit0, testAllPrefixed_haltOnNonzero) {
critbit0_clear(tree);
FreeBog(&a);
}
TEST(critbit0, duplicate) {
struct critbit0 tree = {0};
ASSERT_TRUE(critbit0_insert(&tree, "hi"));
ASSERT_FALSE(critbit0_insert(&tree, "hi"));
critbit0_clear(&tree);
}

View file

@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"

View file

@ -23,7 +23,6 @@
#include "libc/calls/struct/timespec.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"

View file

@ -25,7 +25,6 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/intrin/xchg.internal.h"
#include "libc/log/log.h"

View file

@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/syslib.internal.h"

View file

@ -20,7 +20,6 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"

View file

@ -21,7 +21,7 @@
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/gc.h"
#include "libc/mem/gc.internal.h"
#include "libc/runtime/runtime.h"
@ -35,6 +35,7 @@
#include "libc/x/xiso8601.h"
__static_yoink("zipos");
__static_yoink("usr/share/zoneinfo/");
__static_yoink("usr/share/zoneinfo/New_York");
char testlib_enable_tmp_setup_teardown;
@ -248,5 +249,75 @@ TEST(dirstream, seek) {
ASSERT_NE(NULL, (ent = readdir(dir))); // #3
ASSERT_NE(NULL, (ent = readdir(dir))); // #4
ASSERT_EQ(NULL, (ent = readdir(dir))); // eod
ASSERT_EQ(NULL, (ent = readdir(dir))); // eod
ASSERT_SYS(0, 0, closedir(dir));
}
TEST(dirstream, ino) {
if (IsNetbsd()) return; // omg
ASSERT_SYS(0, 0, mkdir("boop", 0755));
EXPECT_SYS(0, 0, touch("boop/a", 0644));
EXPECT_SYS(0, 0, touch("boop/b", 0644));
EXPECT_SYS(0, 0, touch("boop/c", 0644));
ASSERT_NE(NULL, (dir = opendir("boop")));
ASSERT_NE(NULL, (ent = readdir(dir))); // #1
ASSERT_NE(NULL, (ent = readdir(dir))); // #2
long pos = telldir(dir);
ASSERT_NE(NULL, (ent = readdir(dir))); // #3
char name[32];
strlcpy(name, ent->d_name, sizeof(name));
ASSERT_NE(NULL, (ent = readdir(dir))); // #4
ASSERT_NE(NULL, (ent = readdir(dir))); // #5
ASSERT_EQ(NULL, (ent = readdir(dir))); // eod
seekdir(dir, pos);
ASSERT_NE(NULL, (ent = readdir(dir))); // #2
ASSERT_STREQ(name, ent->d_name);
ASSERT_NE(NULL, (ent = readdir(dir))); // #3
ASSERT_NE(NULL, (ent = readdir(dir))); // #4
ASSERT_EQ(NULL, (ent = readdir(dir))); // eod
ASSERT_EQ(NULL, (ent = readdir(dir))); // eod
ASSERT_SYS(0, 0, closedir(dir));
}
TEST(dirstream, dots) {
bool got_dot = false;
bool got_dot_dot = false;
ASSERT_NE(NULL, (dir = opendir(".")));
while ((ent = readdir(dir))) {
got_dot |= !strcmp(ent->d_name, ".");
got_dot_dot |= !strcmp(ent->d_name, "..");
}
ASSERT_SYS(0, 0, closedir(dir));
ASSERT_TRUE(got_dot_dot);
ASSERT_TRUE(got_dot);
}
TEST(dirstream, inoFile_isConsistentWithStat) {
struct stat st;
bool gotsome = false;
EXPECT_SYS(0, 0, touch("foo", 0644));
EXPECT_SYS(0, 0, stat("foo", &st));
ASSERT_NE(NULL, (dir = opendir(".")));
while ((ent = readdir(dir))) {
if (!strcmp(ent->d_name, "foo")) {
ASSERT_EQ(st.st_ino, ent->d_ino);
gotsome = true;
}
}
ASSERT_SYS(0, 0, closedir(dir));
ASSERT_TRUE(gotsome);
}
TEST(dirstream_zipos, inoFile_isConsistentWithStat) {
struct stat st;
const char *dirpath;
char filename[PATH_MAX];
dirpath = "/zip/usr/share/zoneinfo";
ASSERT_NE(NULL, (dir = opendir(dirpath)));
while ((ent = readdir(dir))) {
snprintf(filename, sizeof(filename), "%s/%s", dirpath, ent->d_name);
EXPECT_SYS(0, 0, stat(filename, &st));
ASSERT_EQ(st.st_ino, ent->d_ino);
}
ASSERT_SYS(0, 0, closedir(dir));
}

View file

@ -23,7 +23,6 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"

View file

@ -54,6 +54,7 @@ TEST(zipdir, test) {
ASSERT_EQ(0, strcmp(ent->d_name, "moby.txt"));
ASSERT_EQ(DT_REG, ent->d_type);
ASSERT_EQ(NULL, (ent = readdir(dir)));
ASSERT_EQ(NULL, (ent = readdir(dir)));
ASSERT_SYS(0, 0, closedir(dir));
}

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/testlib/testlib.h"

View file

@ -23,7 +23,6 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"

View file

@ -1,56 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/spawn.h"
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/internal.h"
#include "libc/testlib/testlib.h"
atomic_int itworked;
_Thread_local int var;
void SetUpOnce(void) {
__enable_threads();
ASSERT_SYS(0, 0, pledge("stdio", 0));
}
int Worker(void *arg, int tid) {
int i = (long)arg;
ASSERT_EQ(0, var++);
ASSERT_EQ(gettid(), tid);
ASSERT_EQ(1, var++);
ASSERT_EQ(sys_gettid(), tid);
ASSERT_EQ(2, var++);
itworked++;
return 0;
}
TEST(_spawn, test) {
long i, n = 64;
struct spawn *t = gc(malloc(sizeof(struct spawn) * n));
for (i = 0; i < n; ++i) ASSERT_SYS(0, 0, _spawn(Worker, (void *)i, t + i));
for (i = 0; i < n; ++i) EXPECT_SYS(0, 0, _join(t + i));
EXPECT_EQ(n, itworked);
}

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/tinymath/magicu.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"

View file

@ -18,7 +18,6 @@
*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"

1
third_party/tr/tr.c vendored
View file

@ -34,7 +34,6 @@
*/
#include "libc/calls/calls.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/bsd.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"

View file

@ -28,7 +28,6 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macho.internal.h"
#include "libc/macros.internal.h"

View file

@ -31,7 +31,6 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/bsr.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"

View file

@ -24,7 +24,6 @@
#include "libc/fmt/fmt.h"
#include "libc/fmt/libgen.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/mem/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/ftw.h"

View file

@ -27,7 +27,6 @@
#include "libc/intrin/bits.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/dll.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"

View file

@ -30,7 +30,6 @@
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"

View file

@ -20,14 +20,13 @@
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/ftw.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/s.h"
#include "third_party/getopt/getopt.internal.h"
#include "libc/stdio/ftw.h"
#define USAGE \
" FILE...\n\

View file

@ -15,7 +15,6 @@
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"

View file

@ -179,7 +179,6 @@
(defconst cosmo-cpp-constants-cosmopolitan
'("__SAUCE__"
"APE_STACKSIZE"
"FRAMESIZE"
"ARG_MAX"
"PATH_MAX"