Make improvements for Actually Portable Emacs

- Get SIGWINCH working again on the New Technology
- Correctly handle O_NOFOLLOW in open() on Windows
- Implement synthetic umask() functionality on Windows
- Do a better job managing file execute access on Windows
- Fill in `st_uid` and `st_gid` with username hash on Windows
- Munge UNICODE control pictures into control codes on Windows
- Do a better job ensuring Windows console settings are restored
- Introduce KPRINTF_LOG environment variable to log kprintf to a file
This commit is contained in:
Justine Tunney 2023-08-19 06:41:06 -07:00
parent 9c7b81ee0f
commit 965516e313
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
108 changed files with 1126 additions and 807 deletions

View file

@ -67,11 +67,6 @@ extern char ape_stack_prot[] __attribute__((__weak__));
extern pthread_mutex_t __mmi_lock_obj;
extern int hostos asm("__hostos");
void cosmo2(int, char **, char **, unsigned long *) wontreturn;
void __switch_stacks(int, char **, char **, unsigned long *,
void (*)(int, char **, char **, unsigned long *),
void *) wontreturn;
static const char *DecodeMagnum(const char *p, long *r) {
int k = 0;
unsigned long c, x = 0;
@ -96,6 +91,15 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
unsigned long *auxv = (unsigned long *)(sp + 1 + argc + 1);
while (*auxv++) donothing;
// set helpful globals
__argc = argc;
__argv = argv;
__envp = envp;
__auxv = auxv;
environ = envp;
program_invocation_name = argv[0];
__oldstack = (intptr_t)sp;
// detect apple m1 environment
char *magnums;
if (SupportsXnu() && (__syslib = m1)) {
@ -134,16 +138,7 @@ wontreturn textstartup void cosmo(long *sp, struct Syslib *m1) {
sys_sigaction(SIGSYS, act, 0, 8, 0);
}
// set helpful globals
__argc = argc;
__argv = argv;
__envp = envp;
__auxv = auxv;
environ = envp;
program_invocation_name = argv[0];
// needed by kisdangerous()
__oldstack = (intptr_t)sp;
__pid = sys_getpid().ax;
// initialize memory manager

View file

@ -16,11 +16,9 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
/**
* Exits process with grace.
@ -45,9 +43,5 @@ wontreturn void exit(int exitcode) {
for (p = __fini_array_end; p > __fini_array_start;) {
((void (*)(void))(*--p))();
}
#if SupportsWindows()
_Exitr(exitcode);
#else
_Exit(exitcode);
#endif
}

View file

@ -42,6 +42,7 @@
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/errors.h"
#include "libc/nt/ipc.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
@ -145,18 +146,38 @@ static textwindows dontinline void ReadOrDie(int64_t h, void *buf, size_t n) {
static textwindows int64_t MapOrDie(uint32_t prot, uint64_t size) {
int64_t h;
if ((h = CreateFileMapping(-1, 0, prot, size >> 32, size, 0))) {
return h;
} else {
for (;;) {
if ((h = CreateFileMapping(-1, 0, prot, size >> 32, size, 0))) {
return h;
}
if (GetLastError() == kNtErrorAccessDenied) {
switch (prot) {
case kNtPageExecuteWritecopy:
prot = kNtPageWritecopy;
continue;
case kNtPageExecuteReadwrite:
prot = kNtPageReadwrite;
continue;
case kNtPageExecuteRead:
prot = kNtPageReadonly;
continue;
default:
break;
}
}
AbortFork("MapOrDie");
}
}
static textwindows void ViewOrDie(int64_t h, uint32_t access, size_t pos,
size_t size, void *base) {
void *got;
got = MapViewOfFileEx(h, access, pos >> 32, pos, size, base);
if (!got || (base && got != base)) {
TryAgain:
if (!MapViewOfFileEx(h, access, pos >> 32, pos, size, base)) {
if ((access & kNtFileMapExecute) &&
GetLastError() == kNtErrorAccessDenied) {
access &= ~kNtFileMapExecute;
goto TryAgain;
}
AbortFork("ViewOrDie");
}
}

View file

@ -16,7 +16,6 @@ COSMOPOLITAN_C_START_
extern int __pid;
extern char __runlevel;
extern int ftrace_stackdigs;
extern uint32_t __ntconsolemode[3];
extern const char v_ntsubsystem[] __attribute__((__weak__));
extern const uintptr_t __fini_array_end[] __attribute__((__weak__));
extern const uintptr_t __fini_array_start[] __attribute__((__weak__));
@ -38,6 +37,7 @@ void __morph_tls(void);
void __enable_tls(void);
void __enable_threads(void);
void *__cxa_finalize(void *);
void __restore_console_win32(void);
void __stack_chk_fail(void) wontreturn relegated;
void __stack_chk_fail_local(void) wontreturn relegated;
void __asan_init(int, char **, char **, intptr_t *);

View file

@ -74,7 +74,7 @@ static inline pureconst unsigned long __rounddown2pow(unsigned long x) {
static wontreturn void __mmap_die(const char *s) {
if (_weaken(__die)) _weaken(__die)();
STRACE("%s %m", s);
_Exitr(199);
_Exit(199);
}
static dontasan inline bool __overlaps_existing_mapping(char *p, size_t n) {

View file

@ -480,13 +480,15 @@ dontasan textstartup void __printargs(const char *prologue) {
} else {
PRINT(" - stderr");
}
kprintf(prologue);
errno = 0;
kprintf(" isatty = %d% m\n", isatty(i));
PRINT(" isatty = %d% m", isatty(i));
if (!tcgetwinsize(i, &ws)) {
kprintf(" ws_row = %d\n", ws.ws_row);
kprintf(" ws_col = %d\n", ws.ws_col);
PRINT(" ws_row = %d", ws.ws_row);
PRINT(" ws_col = %d", ws.ws_col);
} else {
PRINT(" tcgetwinsize = %s", strerror(errno));
}
kprintf(prologue);
kprintf(" c_iflag =");
if (termios.c_iflag & IGNBRK) kprintf(" IGNBRK");
if (termios.c_iflag & BRKINT) kprintf(" BRKINT");

View file

@ -110,9 +110,7 @@ axdx_t setlongerjmp(jmp_buf)
libcesque returnstwice paramsnonnull();
void longerjmp(jmp_buf, intptr_t) libcesque wontreturn paramsnonnull();
void __warn_if_powersave(void);
void _Exitr(int) libcesque wontreturn;
void _Exit1(int) libcesque wontreturn;
void _restorewintty(void);
void __paginate(int, const char *);
/* memory management */
void _weakfree(void *);

View file

@ -22,6 +22,7 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/getenv.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
@ -59,6 +60,7 @@
// clang-format off
__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;
@ -71,11 +73,17 @@ __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
extern const signed char kNtConsoleHandles[3];
extern void cosmo(int, char **, char **, long (*)[2]) wontreturn;
static const signed char kNtStdio[3] = {
(signed char)kNtStdInputHandle,
(signed char)kNtStdOutputHandle,
(signed char)kNtStdErrorHandle,
};
static const short kConsoleModes[3] = {
kNtEnableProcessedInput | kNtEnableLineInput | kNtEnableEchoInput |
kNtEnableMouseInput | kNtEnableQuickEditMode | kNtEnableExtendedFlags |
@ -87,12 +95,25 @@ static const short kConsoleModes[3] = {
kNtEnableVirtualTerminalProcessing,
};
static uint32_t __init_pid;
static uint32_t __console_mode[3];
// implements all win32 apis on non-windows hosts
__msabi long __win32_oops(void) {
__msabi long __oops_win32(void) {
assert(!"win32 api called on non-windows host");
return 0;
}
// called by _exit to undo our config changes to cmd.exe
// it must never ever be called from forked subprocesses
void __restore_console_win32(void) {
if (__imp_GetCurrentProcessId() == __init_pid) {
for (int i = 0; i < 3; ++i) {
__imp_SetConsoleMode(__imp_GetStdHandle(kNtStdio[i]), __console_mode[i]);
}
}
}
// https://nullprogram.com/blog/2022/02/18/
__msabi static inline char16_t *MyCommandLine(void) {
void *cmd;
@ -106,14 +127,14 @@ __msabi static inline char16_t *MyCommandLine(void) {
// this ensures close(1) won't accidentally close(2) for example
__msabi static textwindows void DeduplicateStdioHandles(void) {
for (long i = 0; i < 3; ++i) {
int64_t h1 = __imp_GetStdHandle(kNtConsoleHandles[i]);
int64_t h1 = __imp_GetStdHandle(kNtStdio[i]);
for (long j = i + 1; j < 3; ++j) {
int64_t h2 = __imp_GetStdHandle(kNtConsoleHandles[j]);
int64_t h2 = __imp_GetStdHandle(kNtStdio[j]);
if (h1 == h2) {
int64_t h3, proc = __imp_GetCurrentProcess();
__imp_DuplicateHandle(proc, h2, proc, &h3, 0, true,
kNtDuplicateSameAccess);
__imp_SetStdHandle(kNtConsoleHandles[j], h3);
__imp_SetStdHandle(kNtStdio[j], h3);
}
}
}
@ -123,14 +144,15 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
size_t stacksize;
struct WinArgs *wa;
uintptr_t stackaddr;
__init_pid = __pid;
__oldstack = (intptr_t)__builtin_frame_address(0);
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);
int64_t hand = __imp_GetStdHandle(kNtStdio[i]);
__imp_GetConsoleMode(hand, __console_mode + i);
__imp_SetConsoleMode(hand, kConsoleModes[i]);
}
}
@ -167,6 +189,7 @@ __msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
GetDosEnviron(env16, wa->envblock, ARRAYLEN(wa->envblock) - 8, wa->envp,
ARRAYLEN(wa->envp) - 1);
__imp_FreeEnvironmentStringsW(env16);
__envp = &wa->envp[0];
_jmpstack((char *)(stackaddr + (stacksize - sizeof(struct WinArgs))), cosmo,
count, wa->argv, wa->envp, wa->auxv);
}
@ -175,8 +198,9 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int64_t nCmdShow) {
const char16_t *cmdline;
extern char os asm("__hostos");
os = _HOSTWINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
os = _HOSTWINDOWS; // madness https://news.ycombinator.com/item?id=21019722
kStartTsc = rdtsc();
__umask = 077;
__pid = __imp_GetCurrentProcessId();
DeduplicateStdioHandles();
if (_weaken(WinMainStdin)) {
@ -184,7 +208,7 @@ __msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
}
cmdline = MyCommandLine();
#ifdef SYSDEBUG
/* sloppy flag-only check for early initialization */
// sloppy flag-only check for early initialization
if (__strstr16(cmdline, u"--strace")) ++__strace;
#endif
if (_weaken(WinSockInit)) {

View file

@ -16,9 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/cosmo.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/kmalloc.h"
@ -28,9 +30,11 @@
#include "libc/mem/alg.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/posix.h"
#include "libc/sysv/consts/prot.h"
#include "libc/thread/thread.h"
#include "libc/zip.internal.h"
@ -39,23 +43,33 @@
__static_yoink(APE_COM_NAME);
#endif
static uint64_t __zipos_get_min_offset(const uint8_t *map,
const uint8_t *cdir) {
uint64_t i, n, c, r, o;
static struct Zipos __zipos;
static atomic_uint __zipos_once;
static void __zipos_dismiss(const uint8_t *map, const uint8_t *cdir, long pg) {
uint64_t i, n, c, ef, lf, mo, lo, hi;
// determine the byte range of zip file content (excluding central dir)
c = GetZipCdirOffset(cdir);
n = GetZipCdirRecords(cdir);
for (r = c, i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(map + c)) {
o = GetZipCfileOffset(map + c);
if (o < r) r = o;
for (lo = c, hi = i = 0; i < n; ++i, c += ZIP_CFILE_HDRSIZE(map + c)) {
lf = GetZipCfileOffset(map + c);
if (lf < lo) lo = lf;
ef = lf + ZIP_LFILE_HDRSIZE(map + lf) + GetZipLfileCompressedSize(map + lf);
if (ef > hi) hi = ef;
}
return r;
}
static void __zipos_munmap_unneeded(const uint8_t *map, const uint8_t *cdir) {
uint64_t n;
n = __zipos_get_min_offset(map, cdir);
n = ROUNDDOWN(n, FRAMESIZE);
if (n) munmap(map, n);
// unmap the executable portion beneath the local files
mo = ROUNDDOWN(lo, FRAMESIZE);
if (mo) munmap(map, mo);
// this is supposed to reduce our rss usage but does it
pg = getauxval(AT_PAGESZ);
lo = ROUNDDOWN(lo, pg);
hi = MIN(ROUNDUP(hi, pg), ROUNDDOWN(c, pg));
if (hi > lo) {
posix_madvise(map + lo, hi - lo, POSIX_MADV_DONTNEED);
}
}
static int __zipos_compare_names(const void *a, const void *b, void *c) {
@ -88,75 +102,67 @@ static void __zipos_generate_index(struct Zipos *zipos) {
__zipos_compare_names, zipos);
}
static void __zipos_init(void) {
char *endptr;
const char *s;
struct stat st;
int x, fd, err, msg;
uint8_t *map, *cdir;
const char *progpath;
if (!(s = getenv("COSMOPOLITAN_DISABLE_ZIPOS"))) {
// 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;
}
if (fd != -1 || PLEDGED(RPATH)) {
if (fd == -1) {
if (!progpath) {
progpath = GetProgramExecutableName();
}
fd = open(progpath, O_RDONLY);
}
if (fd != -1) {
if (!fstat(fd, &st) && (map = mmap(0, st.st_size, PROT_READ, MAP_SHARED,
fd, 0)) != MAP_FAILED) {
if ((cdir = GetZipEocd(map, st.st_size, &err))) {
long pagesz = getauxval(AT_PAGESZ);
__zipos_dismiss(map, cdir, pagesz);
__zipos.map = map;
__zipos.cdir = cdir;
__zipos.dev = st.st_ino;
__zipos.pagesz = pagesz;
__zipos_generate_index(&__zipos);
msg = kZipOk;
} else {
munmap(map, st.st_size);
msg = !cdir ? err : kZipErrorRaceCondition;
}
} else {
msg = kZipErrorMapFailed;
}
close(fd);
} else {
msg = kZipErrorOpenFailed;
}
} else {
msg = -666;
}
} else {
progpath = 0;
msg = -777;
}
STRACE("__zipos_get(%#s) → %d% m", progpath, msg);
}
/**
* Returns pointer to zip central directory of current executable.
* @asyncsignalsafe
* @threadsafe
*/
struct Zipos *__zipos_get(void) {
char *endptr;
const char *s;
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) {
if (!(s = getenv("COSMOPOLITAN_DISABLE_ZIPOS"))) {
// 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;
}
if (fd != -1 || PLEDGED(RPATH)) {
if (fd == -1) {
if (!progpath) {
progpath = GetProgramExecutableName();
}
fd = open(progpath, O_RDONLY);
}
if (fd != -1) {
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);
zipos.map = map;
zipos.cdir = cdir;
zipos.dev = st.st_ino;
__zipos_generate_index(&zipos);
msg = kZipOk;
} else {
munmap(map, st.st_size);
msg = !cdir ? err : kZipErrorRaceCondition;
}
} else {
msg = kZipErrorMapFailed;
}
close(fd);
} else {
msg = kZipErrorOpenFailed;
}
} else {
msg = -666;
}
} else {
progpath = 0;
msg = -777;
}
STRACE("__zipos_get(%#s) → %d% m", progpath, msg);
once = true;
}
__zipos_unlock();
if (zipos.cdir) {
res = &zipos;
} else {
res = 0;
}
return res;
cosmo_once(&__zipos_once, __zipos_init);
return __zipos.cdir ? &__zipos : 0;
}

View file

@ -1,39 +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/thread.h"
#include "libc/runtime/zipos.internal.h"
static pthread_mutex_t __zipos_lock_obj;
void(__zipos_lock)(void) {
pthread_mutex_lock(&__zipos_lock_obj);
}
void(__zipos_unlock)(void) {
pthread_mutex_unlock(&__zipos_lock_obj);
}
void __zipos_funlock(void) {
pthread_mutex_init(&__zipos_lock_obj, 0);
}
__attribute__((__constructor__)) static void __zipos_init(void) {
__zipos_funlock();
pthread_atfork(__zipos_lock, __zipos_unlock, __zipos_funlock);
}

View file

@ -45,21 +45,39 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/zip.internal.h"
static char *mapend;
static size_t maptotal;
static char *__zipos_mapend;
static size_t __zipos_maptotal;
static pthread_mutex_t __zipos_lock_obj;
static void __zipos_lock(void) {
if (__threaded) {
pthread_mutex_lock(&__zipos_lock_obj);
}
}
static void __zipos_unlock(void) {
if (__threaded) {
pthread_mutex_unlock(&__zipos_lock_obj);
}
}
static void __zipos_funlock(void) {
pthread_mutex_init(&__zipos_lock_obj, 0);
}
static void *__zipos_mmap_space(size_t mapsize) {
char *start;
size_t offset;
unassert(mapsize);
offset = maptotal;
maptotal += mapsize;
offset = __zipos_maptotal;
__zipos_maptotal += mapsize;
start = (char *)kMemtrackZiposStart;
if (!mapend) mapend = start;
mapend = _extend(start, maptotal, mapend, MAP_PRIVATE,
kMemtrackZiposStart + kMemtrackZiposSize);
if (!__zipos_mapend) __zipos_mapend = start;
__zipos_mapend = _extend(start, __zipos_maptotal, __zipos_mapend, MAP_PRIVATE,
kMemtrackZiposStart + kMemtrackZiposSize);
return start + offset;
}
@ -68,7 +86,6 @@ void __zipos_free(struct ZiposHandle *h) {
__asan_poison((char *)h + sizeof(struct ZiposHandle),
h->mapsize - sizeof(struct ZiposHandle), kAsanHeapFree);
}
pthread_mutex_destroy(&h->lock);
__zipos_lock();
do h->next = h->zipos->freelist;
while (!_cmpxchg(&h->zipos->freelist, h->next, h));
@ -105,7 +122,6 @@ StartOver:
h->size = size;
h->zipos = zipos;
h->mapsize = mapsize;
pthread_mutex_init(&h->lock, 0);
}
return h;
}
@ -197,16 +213,40 @@ static int __zipos_load(struct Zipos *zipos, size_t cf, int flags,
return -1;
}
static int __zipos_open_impl(struct ZiposUri *name, int flags) {
struct Zipos *zipos;
/**
* Loads compressed file from αcτµαlly pδrταblε εxεcµταblε object store.
*
* @param uri is obtained via __zipos_parseuri()
* @asyncsignalsafe
* @threadsafe
*/
int __zipos_open(struct ZiposUri *name, int flags) {
// check if this thread is cancelled
int rc;
if (_weaken(pthread_testcancel_np) &&
(rc = _weaken(pthread_testcancel_np)())) {
errno = rc;
return -1;
}
// validate api usage
if ((flags & O_CREAT) || //
(flags & O_TRUNC) || //
(flags & O_ACCMODE) != O_RDONLY) {
return erofs();
}
// get the zipos global singleton
struct Zipos *zipos;
if (!(zipos = __zipos_get())) {
return enoexec();
}
// most open() calls are due to languages path searching assets. the
// majority of these calls will return ENOENT or ENOTDIR. we need to
// perform two extremely costly sigprocmask() calls below. thanks to
// zipos being a read-only filesystem, we can avoid it in many cases
ssize_t cf;
if ((cf = __zipos_find(zipos, name)) == -1) {
return -1;
@ -223,25 +263,14 @@ static int __zipos_open_impl(struct ZiposUri *name, int flags) {
return eacces();
}
}
return __zipos_load(zipos, cf, flags, name);
}
/**
* Loads compressed file from αcτµαlly pδrταblε εxεcµταblε object store.
*
* @param uri is obtained via __zipos_parseuri()
* @asyncsignalsafe
* @threadsafe
*/
int __zipos_open(struct ZiposUri *name, int flags) {
int rc;
if (_weaken(pthread_testcancel_np) &&
(rc = _weaken(pthread_testcancel_np)())) {
errno = rc;
return -1;
}
// now do the heavy lifting
BLOCK_SIGNALS;
rc = __zipos_open_impl(name, flags);
rc = __zipos_load(zipos, cf, flags, name);
ALLOW_SIGNALS;
return rc;
}
__attribute__((__constructor__)) static void __zipos_ctor(void) {
pthread_atfork(__zipos_lock, __zipos_unlock, __zipos_funlock);
}

View file

@ -21,14 +21,9 @@
#include "libc/runtime/zipos.internal.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h"
#include "libc/zip.internal.h"
static size_t GetIovSize(const struct iovec *iov, size_t iovlen) {
size_t i, r;
for (r = i = 0; i < iovlen; ++i) r += iov[i].iov_len;
return r;
}
static ssize_t __zipos_read_impl(struct ZiposHandle *h, const struct iovec *iov,
size_t iovlen, ssize_t opt_offset) {
int i;
@ -61,10 +56,6 @@ static ssize_t __zipos_read_impl(struct ZiposHandle *h, const struct iovec *iov,
*/
ssize_t __zipos_read(struct ZiposHandle *h, const struct iovec *iov,
size_t iovlen, ssize_t opt_offset) {
ssize_t rc;
unassert(opt_offset >= 0 || opt_offset == -1);
pthread_mutex_lock(&h->lock);
rc = __zipos_read_impl(h, iov, iovlen, opt_offset);
pthread_mutex_unlock(&h->lock);
return rc;
return __zipos_read_impl(h, iov, iovlen, opt_offset);
}

View file

@ -22,10 +22,11 @@
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/zip.internal.h"
static int64_t __zipos_lseek_impl(struct ZiposHandle *h, int64_t offset,
unsigned whence) {
static int64_t __zipos_seek_impl(struct ZiposHandle *h, int64_t offset,
unsigned whence) {
int64_t pos;
if (h->cfile == ZIPOS_SYNTHETIC_DIRECTORY ||
S_ISDIR(GetZipCfileMode(h->zipos->map + h->cfile))) {
@ -71,12 +72,10 @@ static int64_t __zipos_lseek_impl(struct ZiposHandle *h, int64_t offset,
* @return new position relative to beginning, or -1 on error
* @asyncsignalsafe
*/
int64_t __zipos_lseek(struct ZiposHandle *h, int64_t offset, unsigned whence) {
int64_t __zipos_seek(struct ZiposHandle *h, int64_t offset, unsigned whence) {
int64_t pos;
pthread_mutex_lock(&h->lock);
if ((pos = __zipos_lseek_impl(h, offset, whence)) != -1) {
if ((pos = __zipos_seek_impl(h, offset, whence)) != -1) {
h->pos = pos;
}
pthread_mutex_unlock(&h->lock);
return pos;
}

View file

@ -16,7 +16,9 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/runtime/zipos.internal.h"
#include "libc/str/str.h"
@ -30,7 +32,8 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
st->st_dev = zipos->dev;
st->st_blksize = FRAMESIZE;
if (cf == ZIPOS_SYNTHETIC_DIRECTORY) {
st->st_mode = S_IFDIR | 0555;
st->st_mode = S_IFDIR | (0555 & ~atomic_load_explicit(
&__umask, memory_order_acquire));
} else {
lf = GetZipCfileOffset(zipos->map + cf);
st->st_mode = GetZipCfileMode(zipos->map + cf);

View file

@ -26,7 +26,7 @@
.yoink __zipos_fcntl
.yoink __zipos_fstat
.yoink __zipos_access
.yoink __zipos_lseek
.yoink __zipos_seek
.yoink __zipos_open
.yoink __zipos_parseuri
.yoink __zipos_read

View file

@ -1,8 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
#define COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_
#include "libc/intrin/nopl.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -21,7 +18,6 @@ struct ZiposUri {
struct ZiposHandle {
struct ZiposHandle *next;
pthread_mutex_t lock;
struct Zipos *zipos;
size_t size;
size_t mapsize;
@ -32,6 +28,7 @@ struct ZiposHandle {
};
struct Zipos {
long pagesz;
uint8_t *map;
uint8_t *cdir;
uint64_t dev;
@ -41,8 +38,6 @@ struct Zipos {
};
int __zipos_close(int);
void __zipos_lock(void);
void __zipos_unlock(void);
void __zipos_free(struct ZiposHandle *);
struct Zipos *__zipos_get(void) pureconst;
size_t __zipos_normpath(char *, const char *, size_t);
@ -57,20 +52,12 @@ int __zipos_fstat(struct ZiposHandle *, struct stat *);
int __zipos_stat_impl(struct Zipos *, size_t, struct stat *);
ssize_t __zipos_read(struct ZiposHandle *, const struct iovec *, size_t,
ssize_t);
int64_t __zipos_lseek(struct ZiposHandle *, int64_t, unsigned);
int64_t __zipos_seek(struct ZiposHandle *, int64_t, unsigned);
int __zipos_fcntl(int, int, uintptr_t);
int __zipos_notat(int, const char *);
void *__zipos_mmap(void *, uint64_t, int32_t, int32_t, struct ZiposHandle *,
int64_t) dontasan;
#ifdef _NOPL0
#define __zipos_lock() _NOPL0("__threadcalls", __zipos_lock)
#define __zipos_unlock() _NOPL0("__threadcalls", __zipos_unlock)
#else
#define __zipos_lock() (__threaded ? __zipos_lock() : 0)
#define __zipos_unlock() (__threaded ? __zipos_unlock() : 0)
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ZIPOS_ZIPOS_H_ */