Compare commits

...
22 Commits
Author SHA1 Message Date
Justine Tunney 5e60e5ad10 Release redbean v2.2 2022-11-02 09:52:54 -07:00
Justine Tunney 6b06a8176d Fix some glitches in redbean
This change includes a fix to Fetch() where an out of bounds memory read
could happen, when the reverse proxied endpoint omits the content-length
header. This caused a bunch of NUL chars to appear on TurfWar's /statusz
since it wouldn't actually overrun the buffer, and if it did it would've
been caught by MODE=asan builds.
2022-11-02 09:46:34 -07:00
Justine Tunney 14d036b68d Add WSL to test fleet
All tests pass now under WSL2. They should pass under WSL1 too, but only
WSL2 is integrated into the test fleet right now. This change also fills
in some gaps in the error numbers.

Fixes #665
2022-11-02 06:49:42 -07:00
Justine Tunney fae0c0286f Workaround WSL not supporting x87 in ucontext_t 2022-11-02 03:20:39 -07:00
Justine Tunney d6ff4c754e Workaround WSL misconfiguring the x87 FPU 2022-11-02 02:17:14 -07:00
Justine Tunney f44d88707e Workaround sendfile() bug in WSL 2022-11-02 02:17:03 -07:00
Justine Tunney fc96af058b Workaround MAP_GROWSDOWN unavailability on WSL 2022-11-02 01:38:06 -07:00
Justine Tunney bd6069deb5 Remove old code from Landlock Make 2022-11-02 00:55:05 -07:00
Justine Tunney e9735a7738 Release landlock make 1.5 2022-11-01 23:52:38 -07:00
Stephen M. Cameron 0ea10c8631 Add useconds_t type to weirdtypes.h 2022-11-01 23:28:26 -07:00
Justine Tunney e522aa3a07 Make more threading improvements
- ASAN memory morgue is now lockless
- Make C11 atomics header more portable
- Rewrote pthread keys support to be lockless
- Simplify Python's unicode table unpacking code
- Make crash report write(2) closer to being atomic
- Make it possible to strace/ftrace a single thread
- ASAN now checks nul-terminated strings fast and properly
- Windows fork() now restores TLS memory of calling thread
2022-11-01 23:28:26 -07:00
Paul Kulchenko d7b88734cd Make redbean compress w/o explicit content-type (#671) 2022-11-01 23:15:20 -07:00
Gavin Hayes da8f5009fd Make Windows fcntl() and lseek() fixes (#668)
* F_SETFD should always return 0 on success
* F_SETFL is not implemented on nt
* nt lseek, error with ESPIPE when attempting on socket
2022-11-01 23:14:14 -07:00
mattx ef9776755e blackholed: allow changing iptables chain (#670)
* Make blackholed use its own chain

This makes blackholed interfere less with any existing iptables raw table configurations.

* Allow specifying iptables chain at runtime

blackholed will now insert blocks to the PREROUTING chain by default,
with a runtime switch to change it to another chain
2022-10-20 10:19:27 -07:00
Justine Tunney da336b3ea8 Make some more fixes to prod 2022-10-19 13:10:24 -07:00
Justine Tunney 69bee64a59 Make some last minute production changes 2022-10-19 10:00:29 -07:00
Justine Tunney f7ff77d865 Make fixes and improvements
- Invent iso8601us() for faster timestamps
- Improve --strace descriptions of sigset_t
- Rebuild the Landlock Make bootstrap binary
- Introduce MODE=sysv for non-Windows builds
- Permit OFD fcntl() locks under pledge(flock)
- redbean can now protect your kernel from ddos
- Have vfork() fallback to sys_fork() not fork()
- Change kmalloc() to not die when out of memory
- Improve documentation for some termios functions
- Rewrite putenv() and friends to conform to POSIX
- Fix linenoise + strace verbosity issue on Windows
- Fix regressions in our ability to show backtraces
- Change redbean SetHeader() to no-op if value is nil
- Improve fcntl() so SQLite locks work in non-WAL mode
- Remove some unnecessary work during fork() on Windows
- Create redbean-based SSL reverse proxy for IPv4 TurfWar
- Fix ape/apeinstall.sh warning when using non-bash shells
- Add ProgramTrustedIp(), and IsTrustedIp() APIs to redbean
- Support $PWD, $UID, $GID, and $EUID in command interpreter
- Introduce experimental JTqFpD APE prefix for non-Windows builds
- Invent blackhole daemon for firewalling IP addresses via UNIX named socket
- Add ProgramTokenBucket(), AcquireToken(), and CountTokens() APIs to redbean
2022-10-19 07:19:19 -07:00
Justine Tunney 648bf6555c Reimport zip into third party 2022-10-16 13:39:41 -07:00
Justine Tunney 60cb435cb4 Implement pthread_atfork()
If threads are being used, then fork() will now acquire and release and
runtime locks so that fork() may be safely used from threads. This also
makes vfork() thread safe, because pthread mutexes will do nothing when
the process is a child of vfork(). More torture tests have been written
to confirm this all works like a charm. Additionally:

- Invent hexpcpy() api
- Rename nsync_malloc_() to kmalloc()
- Complete posix named semaphore implementation
- Make pthread_create() asynchronous signal safe
- Add rm, rmdir, and touch to command interpreter builtins
- Invent sigisprecious() and modify sigset functions to use it
- Add unit tests for posix_spawn() attributes and fix its bugs

One unresolved problem is the reclaiming of *NSYNC waiter memory in the
forked child processes, within apps which have threads waiting on locks
2022-10-16 12:25:13 -07:00
Justine Tunney 64c284003d Fix MODE=opt build 2022-10-14 16:49:16 -07:00
Justine Tunney 3d2d04b25e Make cli commands yoinkable into cosmo shell
This lets our system() and popen() commands function sort of like
BusyBox and ToyBox. By default the Cosmopolitan Shell is lightweight.
But if you use STATIC_YOINK then you can pull the individual commands
you want into the linkage, and they'll be included in a single binary.
For example the demo binary embeds `tr` and `sed` and ends up ~140kb.
2022-10-14 16:37:29 -07:00
Justine Tunney 5af19b7eed Make some foss compatibility improvements 2022-10-14 13:59:34 -07:00
578 changed files with 13050 additions and 3878 deletions

No files matched your search

+4 -2
View File
@@ -60,7 +60,7 @@
# build/config.mk
SHELL = build/bootstrap/cocmd.com
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10 win10:31336
MAKEFLAGS += -j --no-builtin-rules
.SUFFIXES:
@@ -92,6 +92,7 @@ o/$(MODE): \
.UNVEIL = \
libc/integral \
libc/disclaimer.inc \
rwc:/dev/shm \
rx:build/bootstrap \
rx:o/third_party/gcc \
/proc/stat \
@@ -127,6 +128,7 @@ include ape/ape.mk # │
include libc/fmt/fmt.mk # │
include libc/vga/vga.mk #─┘
include libc/calls/calls.mk #─┐
include third_party/getopt/getopt.mk # │
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
include libc/crt/crt.mk # │ You can issue system calls
include third_party/nsync/nsync.mk # │
@@ -150,7 +152,6 @@ include dsp/mpeg/mpeg.mk # │
include dsp/dsp.mk # │
include third_party/zlib/gz/gz.mk # │
include third_party/musl/musl.mk # │
include third_party/getopt/getopt.mk # │
include libc/libc.mk #─┘
include libc/sock/sock.mk #─┐
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
@@ -171,6 +172,7 @@ include third_party/maxmind/maxmind.mk
include net/finger/finger.mk
include third_party/double-conversion/test/test.mk
include third_party/lua/lua.mk
include third_party/tr/tr.mk
include third_party/sed/sed.mk
include third_party/awk/awk.mk
include third_party/make/make.mk
+5 -1
View File
@@ -246,12 +246,16 @@ gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
| AMD | K8 Venus | 2005 |
| Intel | Core | 2006 |
| Linux | 2.6.18 | 2007 |
| Windows | 8 | 2012 |
| Windows | 8 [1] | 2012 |
| Mac OS X | 15.6 | 2018 |
| OpenBSD | 6.4 | 2018 |
| FreeBSD | 13 | 2020 |
| NetBSD | 9.2 | 2021 |
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
for a community supported version of Cosmopolitan that works on Windows
Vista and Windows 7.
## Special Thanks
Funding for this project is crowdsourced using
+9 -1
View File
@@ -112,7 +112,15 @@ cstr: .endobj cstr,globl,hidden # ←for gdb readability
//
// @param dl is drive number
// @noreturn
ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
ape_mz:
#if SupportsWindows() || SupportsMetal()
.asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
#else
// Avoid virus scanner reputation damage when targeting System Five.
// WARNING: This prefix is experimental; it may be removed sometime.
// TODO(jart): Find another prefix that will work with BIOS loading.
.asciz "JTqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
#endif
.short 0x1000 # MZ: lowers upper bound load / 16
.short 0xf800 # MZ: roll greed on bss
.short 0 # MZ: lower bound on stack segment
+3 -1
View File
@@ -1,6 +1,6 @@
#!/bin/sh
if [ $UID -eq 0 ]; then
if [ "$(id -u)" -eq 0 ]; then
SUDO=
else
SUDO=sudo
@@ -97,6 +97,8 @@ if [ x"$(uname -s)" = xLinux ]; then
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-sysv:M::JTqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
$SUDO sh -c "echo ':APE-sysv:M::JTqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
echo done >&2
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
+4
View File
@@ -11,6 +11,7 @@ fi
echo "APE Uninstaller intends to run"
echo
echo " $SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE'"
echo " $SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE-sysv'"
echo " $SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
echo
echo "You may then use ape/apeinstall.sh to reinstall it"
@@ -21,4 +22,7 @@ set -ex
if [ -f /proc/sys/fs/binfmt_misc/APE ]; then
$SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE' || exit
fi
if [ -f /proc/sys/fs/binfmt_misc/APE-sysv ]; then
$SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE-sysv' || exit
fi
$SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape o/tmp/ape /tmp/.ape /tmp/ape || exit
+30
View File
@@ -0,0 +1,30 @@
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern unsigned char _base[];
extern unsigned char _ehead[];
extern unsigned char _etext[];
extern unsigned char _edata[];
extern unsigned char _ezip[];
extern unsigned char _end[];
extern unsigned char _ereal[];
extern unsigned char __privileged_start[];
extern unsigned char __privileged_addr[];
extern unsigned char __privileged_size[];
extern unsigned char __privileged_end[];
extern unsigned char __test_start[];
extern unsigned char __ro[];
extern unsigned char *__relo_start[];
extern unsigned char *__relo_end[];
extern uint8_t __zip_start[];
extern uint8_t __zip_end[];
extern uint8_t __data_start[];
extern uint8_t __data_end[];
extern uint8_t __bss_start[];
extern uint8_t __bss_end[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
Binary file not shown.
Binary file not shown.
+27 -6
View File
@@ -29,7 +29,7 @@ endif
#
ifeq ($(MODE),fastbuild)
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O
CONFIG_CPPFLAGS += -DSYSDEBUG
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
CONFIG_OFLAGS += -g0
CONFIG_LDFLAGS += -S
TARGET_ARCH ?= -msse3
@@ -125,6 +125,22 @@ TARGET_ARCH ?= -msse3
OVERRIDE_CCFLAGS += -fno-pie
endif
# System Five Mode
#
# - `make MODE=sysv`
# - Optimized
# - Backtraces
# - Debuggable
# - Syscall tracing
# - Function tracing
# - No Windows bloat!
#
ifeq ($(MODE), sysv)
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
TARGET_ARCH ?= -msse3
endif
# Tiny Mode
#
# - `make MODE=tiny`
@@ -151,7 +167,8 @@ CONFIG_CCFLAGS += \
-fschedule-insns2 \
-fomit-frame-pointer \
-momit-leaf-frame-pointer \
-foptimize-sibling-calls
-foptimize-sibling-calls \
-DDWARFLESS
CONFIG_OFLAGS += \
-g0
CONFIG_LDFLAGS += \
@@ -181,7 +198,8 @@ CONFIG_CPPFLAGS += \
-DTINY \
-DNDEBUG \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=1
-DSUPPORT_VECTOR=1 \
-DDWARFLESS
DEFAULT_COPTS += \
-mred-zone
CONFIG_OFLAGS += \
@@ -217,7 +235,8 @@ CONFIG_CPPFLAGS += \
-DTINY \
-DNDEBUG \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=113
-DSUPPORT_VECTOR=113 \
-DDWARFLESS
DEFAULT_COPTS += \
-mred-zone
CONFIG_OFLAGS += \
@@ -252,7 +271,8 @@ CONFIG_CPPFLAGS += \
-DTINY \
-DNDEBUG \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=121
-DSUPPORT_VECTOR=121 \
-DDWARFLESS
DEFAULT_COPTS += \
-mred-zone
CONFIG_CCFLAGS += \
@@ -287,7 +307,8 @@ CONFIG_CPPFLAGS += \
-DTINY \
-DNDEBUG \
-DTRUSTWORTHY \
-DSUPPORT_VECTOR=251
-DSUPPORT_VECTOR=251 \
-DDWARFLESS
CONFIG_CCFLAGS += \
-Os \
-fno-align-functions \
+9 -3
View File
@@ -7,12 +7,12 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/bits.h"
#include "libc/dce.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
@@ -59,9 +59,15 @@
int main(int argc, char *argv[]) {
if (!IsAsan()) {
printf("this example is intended for MODE=asan or MODE=dbg\n");
kprintf("this example is intended for MODE=asan or MODE=dbg\n");
exit(1);
}
kprintf("----------------\n");
kprintf(" THIS IS A TEST \n");
kprintf("SIMULATING CRASH\n");
kprintf("----------------\n");
char *buffer;
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
buffer = malloc(13);
+7
View File
@@ -7,6 +7,7 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/runtime/symbols.internal.h"
@@ -24,6 +25,12 @@
*/
noubsan int main(int argc, char *argv[]) {
kprintf("----------------\n");
kprintf(" THIS IS A TEST \n");
kprintf("SIMULATING CRASH\n");
kprintf("----------------\n");
volatile int64_t x;
ShowCrashReports();
return 1 / (x = 0);
+23 -1
View File
@@ -49,12 +49,12 @@ EXAMPLES_DIRECTDEPS = \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_NT_IPHLPAPI \
LIBC_NT_KERNEL32 \
LIBC_NT_NTDLL \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_NT_ADVAPI32 \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
@@ -71,6 +71,7 @@ EXAMPLES_DIRECTDEPS = \
LIBC_ZIPOS \
NET_HTTP \
NET_HTTPS \
THIRD_PARTY_AWK \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_DOUBLECONVERSION \
@@ -84,7 +85,9 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_NSYNC \
THIRD_PARTY_NSYNC_MEM \
THIRD_PARTY_QUICKJS \
THIRD_PARTY_SED \
THIRD_PARTY_STB \
THIRD_PARTY_TR \
THIRD_PARTY_XED \
THIRD_PARTY_ZLIB \
TOOL_BUILD_LIB \
@@ -143,6 +146,25 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
$(EXAMPLES_BOOTLOADER)
@$(APELINK)
# # force symtab.com to be a zip file, by pulling a zip asset into linkage
# # we wouldn't need to do this if we depended on functions like localtime
# o/$(MODE)/examples/symtab.com.dbg: \
# $(EXAMPLES_DEPS) \
# o/$(MODE)/examples/symtab.o \
# o/$(MODE)/examples/symtab.c.zip.o \
# o/$(MODE)/examples/examples.pkg \
# $(EXAMPLES_BOOTLOADER)
# @$(APELINK)
# modify .com so it can read the symbol table without needing the .com.dbg file
o/$(MODE)/examples/symtab.com: \
o/$(MODE)/examples/symtab.com.dbg \
o/$(MODE)/third_party/zip/zip.com \
o/$(MODE)/tool/build/symtab.com
@$(MAKE_OBJCOPY)
@$(MAKE_SYMTAB_CREATE)
@$(MAKE_SYMTAB_ZIP)
o/$(MODE)/examples/picol.o: private \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
+1
View File
@@ -7,6 +7,7 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
+1 -1
View File
@@ -47,7 +47,7 @@
#include "third_party/libcxx/vector"
#include "tool/viz/lib/knobs.h"
STATIC_YOINK("zip_uri_support");
STATIC_YOINK("zipos");
#define USAGE \
" [ROM] [FMV]\n\
+1
View File
@@ -7,6 +7,7 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "ape/sections.internal.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
+42
View File
@@ -0,0 +1,42 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
/**
* @fileoverview example of how to embed symbol table in .com file
*
* # build our binary
* make -j16 o//examples/symtab.com
*
* # move binary somewhere else
* # so it can't find the .com.dbg binary
* cp o//examples/symtab.com /tmp
*
* # run program
* # notice that it has a symbolic backtrace
* /tmp/symtab.com
*
* @see examples/examples.mk
*/
int main(int argc, char *argv[]) {
// this links all the debugging and zip functionality
ShowCrashReports();
kprintf("----------------\n");
kprintf(" THIS IS A TEST \n");
kprintf("SIMULATING CRASH\n");
kprintf("----------------\n");
volatile int64_t x;
return 1 / (x = 0);
}
+13 -6
View File
@@ -7,13 +7,20 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/**
* @fileoverview Cosmopolitan Command Interpreter Demo
* Yes this works on Windows.
*/
STATIC_YOINK("_tr");
STATIC_YOINK("_sed");
int main(int argc, char *argv[]) {
if (IsWindows()) {
system("notepad");
} else {
system("ls | tr a-z A-Z");
}
system("x=world\n"
"echo hello $x |\n"
" tr a-z A-Z |\n"
" sed 's/\\(.\\)/\\1 /g'");
}
+3 -3
View File
@@ -17,7 +17,7 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
#endif
#ifdef __GNUC__
#ifndef TINY
#if !defined(TINY) && !defined(MODE_DBG)
/**
* Specifies expression can't possibly be false.
*
@@ -36,7 +36,7 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
* In `MODE=tiny` these assertions are redefined as undefined behavior.
*/
#define _npassert(x) \
({ \
__extension__({ \
if (__builtin_expect(!(x), 0)) { \
notpossible; \
} \
@@ -63,7 +63,7 @@ void __assert_fail(const char *, const char *, int) hidden relegated;
* that's capable of debugging this macro.
*/
#define _unassert(x) \
({ \
__extension__({ \
if (__builtin_expect(!(x), 0)) { \
unreachable; \
} \
+3 -6
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/sig.internal.h"
@@ -107,7 +108,6 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
STRACE("delivering %G", sig);
// enter the signal
__sig_lock();
rva = __sighandrvas[sig];
flags = __sighandflags[sig];
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
@@ -118,7 +118,6 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
// signal handler. in that case you must use SA_NODEFER.
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
}
__sig_unlock();
// setup the somewhat expensive information args
// only if they're requested by the user in sigaction()
@@ -140,11 +139,9 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
// since sigaction() is @asyncsignalsafe we only restore it if the
// user didn't change it during the signal handler. we also don't
// need to do anything if this was a oneshot signal or nodefer.
__sig_lock();
if (__sighandrvas[sig] == (int32_t)(intptr_t)SIG_DFL) {
__sighandrvas[sig] = rva;
}
__sig_unlock();
}
if (!restartable) {
@@ -227,12 +224,12 @@ textwindows int __sig_add(int tid, int sig, int si_code) {
int rc;
struct Signal *mem;
if (1 <= sig && sig <= 64) {
__sig_lock();
if (__sighandrvas[sig] == (unsigned)(intptr_t)SIG_IGN) {
STRACE("ignoring %G", sig);
rc = 0;
} else {
STRACE("enqueuing %G", sig);
__sig_lock();
++__sig_count;
if ((mem = __sig_alloc())) {
mem->tid = tid;
@@ -244,8 +241,8 @@ textwindows int __sig_add(int tid, int sig, int si_code) {
} else {
rc = enomem();
}
__sig_unlock();
}
__sig_unlock();
} else {
rc = einval();
}
+6 -1
View File
@@ -16,7 +16,9 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h"
@@ -45,7 +47,10 @@ textwindows int __sig_mask(int how, const sigset_t *neu, sigset_t *old) {
} else {
x = y;
}
x &= ~(GetSigBit(SIGKILL) | GetSigBit(SIGSTOP) | GetSigBit(SIGABRT));
x &= ~(0
#define M(x) | GetSigBit(x)
#include "libc/intrin/sigisprecious.inc"
);
*mask = x;
}
return 0;
+19
View File
@@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_INTERNAL_H_
#define COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_INTERNAL_H_
#include "libc/calls/struct/sigset.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define BLOCK_SIGNALS \
do { \
sigset_t _SigMask; \
_SigMask = _sigblockall()
#define ALLOW_SIGNALS \
_sigsetmask(_SigMask); \
} \
while (0)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_BLOCKSIGS_INTERNAL_H_ */
+42 -42
View File
@@ -65,13 +65,13 @@ char *ttyname(int);
int access(const char *, int) dontthrow;
int arch_prctl();
int chdir(const char *);
int chmod(const char *, uint32_t);
int chown(const char *, uint32_t, uint32_t);
int chmod(const char *, unsigned);
int chown(const char *, unsigned, unsigned);
int chroot(const char *);
int close(int);
int close_range(unsigned, unsigned, unsigned);
int closefrom(int);
int creat(const char *, uint32_t);
int creat(const char *, unsigned);
int dup(int);
int dup2(int, int);
int dup3(int, int, int);
@@ -84,25 +84,22 @@ int execv(const char *, char *const[]);
int execve(const char *, char *const[], char *const[]);
int execvp(const char *, char *const[]);
int execvpe(const char *, char *const[], char *const[]);
int fexecve(int, char *const[], char *const[]);
int faccessat(int, const char *, int, int);
int fadvise(int, uint64_t, uint64_t, int);
int fchdir(int);
int fchmod(int, uint32_t) dontthrow;
int fchmodat(int, const char *, uint32_t, int);
int fchown(int, uint32_t, uint32_t);
int fchownat(int, const char *, uint32_t, uint32_t, int);
int fchmod(int, unsigned) dontthrow;
int fchmodat(int, const char *, unsigned, int);
int fchown(int, unsigned, unsigned);
int fchownat(int, const char *, unsigned, unsigned, int);
int fcntl(int, int, ...);
int fdatasync(int);
int fexecve(int, char *const[], char *const[]);
int flock(int, int);
int fork(void);
int fsync(int);
int ftruncate(int, int64_t);
int getdomainname(char *, size_t);
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
int getgroups(int size, uint32_t list[]);
int getgroups(int, unsigned[]);
int gethostname(char *, size_t);
int getloadavg(double *, int);
int getpgid(int) libcesque;
@@ -110,36 +107,29 @@ int getpgrp(void) nosideeffect;
int getpid(void) nosideeffect libcesque;
int getppid(void);
int getpriority(int, unsigned);
int getresgid(uint32_t *, uint32_t *, uint32_t *);
int getresuid(uint32_t *, uint32_t *, uint32_t *);
int getresgid(unsigned *, unsigned *, unsigned *);
int getresuid(unsigned *, unsigned *, unsigned *);
int getsid(int) nosideeffect libcesque;
int gettid(void) libcesque;
uint32_t getuid(void) libcesque;
int sys_iopl(int);
int ioprio_get(int, int);
int ioprio_set(int, int, int);
int issetugid(void);
int kill(int, int);
int killpg(int, int);
int lchmod(const char *, uint32_t);
int lchown(const char *, uint32_t, uint32_t);
int lchmod(const char *, unsigned);
int lchown(const char *, unsigned, unsigned);
int link(const char *, const char *) dontthrow;
int linkat(int, const char *, int, const char *, int);
int madvise(void *, uint64_t, int);
int makedirs(const char *, unsigned);
int memfd_create(const char *, unsigned int);
int mincore(void *, size_t, unsigned char *);
int mkdir(const char *, unsigned);
int mkdirat(int, const char *, unsigned);
int makedirs(const char *, unsigned);
int mkfifo(const char *, uint32_t);
int mkfifoat(int, const char *, uint32_t);
int mknod(const char *, uint32_t, uint64_t);
int mknodat(int, const char *, int32_t, uint64_t);
int sys_mlock(const void *, size_t);
int sys_mlock2(const void *, size_t, int);
int sys_mlockall(int);
int sys_munlock(const void *, size_t);
int sys_munlockall(void);
int mkfifo(const char *, unsigned);
int mkfifoat(int, const char *, unsigned);
int mknod(const char *, unsigned, uint64_t);
int mknodat(int, const char *, int, uint64_t);
int nice(int);
int open(const char *, int, ...);
int openat(int, const char *, int, ...);
@@ -161,19 +151,19 @@ int renameat2(long, const char *, long, const char *, int);
int rmdir(const char *);
int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(uint32_t);
int seteuid(uint32_t);
int setegid(unsigned);
int seteuid(unsigned);
int setfsgid(unsigned);
int setfsuid(unsigned);
int setgid(unsigned);
int setgroups(size_t, const uint32_t[]);
int setgroups(size_t, const unsigned[]);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int setreuid(uint32_t, uint32_t);
int setregid(unsigned, unsigned);
int setresgid(unsigned, unsigned, unsigned);
int setresuid(unsigned, unsigned, unsigned);
int setreuid(unsigned, unsigned);
int setsid(void);
int setuid(unsigned);
int sigignore(int);
@@ -181,16 +171,22 @@ int siginterrupt(int, int);
int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *);
int sync_file_range(int, int64_t, int64_t, unsigned);
int sys_iopl(int);
int sys_mlock(const void *, size_t);
int sys_mlock2(const void *, size_t, int);
int sys_mlockall(int);
int sys_munlock(const void *, size_t);
int sys_munlockall(void);
int sys_ptrace(int, ...);
int sys_sysctl(const int *, unsigned, void *, size_t *, void *, size_t);
int tcsetpgrp(int, int32_t);
int tcgetpgrp(int);
int tcsetpgrp(int, int);
int tgkill(int, int, int);
int tkill(int, int);
int tmpfd(void);
int touch(const char *, uint32_t);
int touch(const char *, unsigned);
int truncate(const char *, int64_t);
int ttyname_r(int, char *, size_t);
unsigned umask(unsigned);
int unlink(const char *);
int unlink_s(const char **);
int unlinkat(int, const char *, int);
@@ -199,11 +195,10 @@ int usleep(unsigned);
int vfork(void) returnstwice;
int wait(int *);
int waitpid(int, int *, int);
int32_t tcgetpgrp(int);
intptr_t syscall(int, ...);
long ptrace(int, ...);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t copy_file_range(int, long *, int, long *, size_t, unsigned);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, unsigned);
ssize_t getfiledescriptorsize(int);
ssize_t lseek(int, int64_t, int);
ssize_t pread(int, void *, size_t, int64_t);
@@ -212,8 +207,13 @@ ssize_t read(int, void *, size_t);
ssize_t readansi(int, char *, size_t);
ssize_t readlink(const char *, char *, size_t);
ssize_t readlinkat(int, const char *, char *, size_t);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t splice(int, int64_t *, int, int64_t *, size_t, unsigned);
ssize_t write(int, const void *, size_t);
unsigned getegid(void) nosideeffect;
unsigned geteuid(void) nosideeffect;
unsigned getgid(void) nosideeffect;
unsigned getuid(void) libcesque;
unsigned umask(unsigned);
void sync(void);
COSMOPOLITAN_C_END_
@@ -20,6 +20,58 @@
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
/**
* Returns input baud rate.
* @asyncsignalsafe
*/
uint32_t cfgetispeed(const struct termios *t) {
if (CBAUD) {
return t->c_cflag & CBAUD;
} else {
return t->c_ispeed;
}
}
/**
* Returns output baud rate.
* @asyncsignalsafe
*/
uint32_t cfgetospeed(const struct termios *t) {
if (CBAUD) {
return t->c_cflag & CBAUD;
} else {
return t->c_ospeed;
}
}
/**
* Sets input baud rate.
*
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int cfsetispeed(struct termios *t, unsigned speed) {
if (speed) {
if (CBAUD) {
if (!(speed & ~CBAUD)) {
t->c_cflag &= ~CBAUD;
t->c_cflag |= speed;
} else {
return einval();
}
} else {
t->c_ispeed = speed;
}
}
return 0;
}
/**
* Sets output baud rate.
*
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
*/
int cfsetospeed(struct termios *t, unsigned speed) {
if (CBAUD) {
if (!(speed & ~CBAUD)) {
+1 -1
View File
@@ -36,7 +36,7 @@
int chdir(const char *path) {
int rc;
GetProgramExecutableName(); // XXX: ugly workaround
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
rc = efault();
} else if (!IsWindows()) {
rc = sys_chdir(path);
+1 -1
View File
@@ -49,7 +49,7 @@
*/
int chroot(const char *path) {
int rc;
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
rc = efault();
} else {
rc = sys_chroot(path);
+1 -1
View File
@@ -84,7 +84,7 @@ int clock_gettime(int clock, struct timespec *ts) {
rc = __clock_gettime(clock, ts);
}
#if SYSDEBUG
if (!(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (__tls_enabled && !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
STRACE("clock_gettime(%s, [%s]) → %d% m", DescribeClockName(clock),
DescribeTimespec(rc, ts), rc);
}
+1 -1
View File
@@ -113,7 +113,7 @@ errno_t clock_nanosleep(int clock, int flags, const struct timespec *req,
}
#if SYSDEBUG
if (!(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (__tls_enabled && !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
STRACE("clock_nanosleep(%s, %s, %s, [%s]) → %s", DescribeClockName(clock),
DescribeSleepFlags(flags), DescribeTimespec(0, req),
DescribeTimespec(rc, rem), DescribeErrnoResult(rc));
+8 -1
View File
@@ -18,15 +18,22 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/fd.internal.h"
#include "libc/errno.h"
#include "libc/intrin/weaken.h"
#include "libc/nt/enum/filetype.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/o.h"
textwindows int sys_close_nt(struct Fd *fd) {
void sys_fcntl_nt_lock_cleanup(int) hidden;
textwindows int sys_close_nt(struct Fd *fd, int fildes) {
int e;
bool ok = true;
if (_weaken(sys_fcntl_nt_lock_cleanup)) {
_weaken(sys_fcntl_nt_lock_cleanup)(fildes);
}
if (fd->kind == kFdFile && ((fd->flags & O_ACCMODE) != O_RDONLY &&
GetFileType(fd->handle) == kNtFileTypeDisk)) {
// Like Linux, closing a file on Windows doesn't guarantee it's
+2 -2
View File
@@ -16,10 +16,10 @@
│ 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/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
@@ -81,7 +81,7 @@ int close(int fd) {
} else if (__isfdkind(fd, kFdFile) || //
__isfdkind(fd, kFdConsole) || //
__isfdkind(fd, kFdProcess)) { //
rc = sys_close_nt(g_fds.p + fd);
rc = sys_close_nt(g_fds.p + fd, fd);
} else {
rc = eio();
}
+2 -5
View File
@@ -27,12 +27,9 @@
/**
* Closes extra file descriptors, e.g.
*
* // close all non-stdio file descriptors
* if (closefrom(3) == -1) {
* for (int i = 3; i < 256; ++i) {
* if (closefrom(3))
* for (int i = 3; i < 256; ++i)
* close(i);
* }
* }
*
* @return 0 on success, or -1 w/ errno
* @raise EBADF if `first` is negative
+13 -22
View File
@@ -45,27 +45,18 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
}
// allocate a new file descriptor
for (;;) {
if (newfd == -1) {
if ((newfd = __reservefd_unlocked(start)) == -1) {
__fds_unlock();
return -1;
}
break;
} else {
if (__ensurefds_unlocked(newfd) == -1) {
__fds_unlock();
return -1;
}
if (g_fds.p[newfd].kind) {
__fds_unlock();
close(newfd);
__fds_lock();
}
if (!g_fds.p[newfd].kind) {
g_fds.p[newfd].kind = kFdReserved;
break;
}
if (newfd == -1) {
if ((newfd = __reservefd_unlocked(start)) == -1) {
__fds_unlock();
return -1;
}
} else {
if (__ensurefds_unlocked(newfd) == -1) {
__fds_unlock();
return -1;
}
if (g_fds.p[newfd].kind) {
sys_close_nt(g_fds.p + newfd, newfd);
}
}
@@ -86,7 +77,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
}
rc = newfd;
} else {
__releasefd_unlocked(newfd);
__releasefd(newfd);
rc = __winerr();
}
+33 -24
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/blocksigs.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
@@ -40,7 +41,9 @@ static bool IsApeBinary(const char *path) {
char buf[8];
bool res = false;
if ((fd = sys_open(path, O_RDONLY, 0)) != -1) {
if (sys_read(fd, buf, 8) == 8 && READ64LE(buf) == READ64LE("MZqFpD='")) {
if (sys_read(fd, buf, 8) == 8 && //
(READ64LE(buf) == READ64LE("MZqFpD='") ||
READ64LE(buf) == READ64LE("JTqFpD='"))) {
res = true;
}
sys_close(fd);
@@ -61,35 +64,41 @@ static const char *Join(const char *a, const char *b, char buf[PATH_MAX]) {
}
int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
int e;
size_t i;
int e, rc;
char *buf;
char **shargs;
const char *ape;
e = errno;
__sys_execve(prog, argv, envp);
if (errno != ENOEXEC) return -1;
for (i = 0; argv[i];) ++i;
buf = alloca(PATH_MAX);
shargs = alloca((i + 4) * sizeof(char *));
if (IsApeBinary(prog) &&
(CanExecute((ape = "/usr/bin/ape")) ||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
firstnonnull(getenv("HOME"), ".")),
".ape", buf))) ||
CanExecute(
(ape = Join(firstnonnull(getenv("HOME"), "."), ".ape", buf))))) {
shargs[0] = ape;
shargs[1] = "-";
shargs[2] = prog;
memcpy(shargs + 3, argv, (i + 1) * sizeof(char *));
} else if (CanExecute(prog)) {
shargs[0] = _PATH_BSHELL;
shargs[1] = prog;
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
if (errno == ENOEXEC) {
for (i = 0; argv[i];) ++i;
buf = alloca(PATH_MAX);
shargs = alloca((i + 4) * sizeof(char *));
if (IsApeBinary(prog) &&
(CanExecute((ape = "/usr/bin/ape")) ||
CanExecute((ape = Join(firstnonnull(getenv("TMPDIR"),
firstnonnull(getenv("HOME"), ".")),
".ape", buf))) ||
CanExecute(
(ape = Join(firstnonnull(getenv("HOME"), "."), ".ape", buf))))) {
shargs[0] = ape;
shargs[1] = "-";
shargs[2] = prog;
memcpy(shargs + 3, argv, (i + 1) * sizeof(char *));
errno = e;
rc = __sys_execve(shargs[0], shargs, envp);
} else if (CanExecute(prog)) {
shargs[0] = _PATH_BSHELL;
shargs[1] = prog;
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
errno = e;
rc = __sys_execve(shargs[0], shargs, envp);
} else {
rc = enoexec();
}
} else {
return enoexec();
rc = -1;
}
errno = e;
return __sys_execve(shargs[0], shargs, envp);
return rc;
}
+6 -18
View File
@@ -23,6 +23,7 @@
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/promises.internal.h"
@@ -53,26 +54,13 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
int rc;
size_t i;
if (!prog || !argv || !envp ||
(IsAsan() &&
(!__asan_is_valid(prog, 1) || !__asan_is_valid_strlist(argv) ||
!__asan_is_valid_strlist(envp)))) {
(IsAsan() && (!__asan_is_valid_str(prog) || //
!__asan_is_valid_strlist(argv) || //
!__asan_is_valid_strlist(envp)))) {
rc = efault();
} else {
#ifdef SYSDEBUG
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "execve(%#s, {", prog);
for (i = 0; argv[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", argv[i]);
}
kprintf("}, {");
for (i = 0; envp[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", envp[i]);
}
kprintf("})\n");
}
#endif
STRACE("execve(%#s, %s, %s) → ...", prog, DescribeStringList(argv),
DescribeStringList(envp));
if (!IsWindows()) {
rc = 0;
if (IsLinux() && __execpromises && _weaken(sys_pledge_linux)) {
+1 -1
View File
@@ -37,7 +37,7 @@
int execvpe(const char *prog, char *const argv[], char *const *envp) {
char *exe;
char pathbuf[PATH_MAX];
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
if (IsAsan() && !__asan_is_valid_str(prog)) return efault();
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
return execve(exe, argv, envp);
}
+1 -1
View File
@@ -51,7 +51,7 @@
int faccessat(int dirfd, const char *path, int amode, int flags) {
int e, rc;
struct ZiposUri zipname;
if (!path || (IsAsan() && !__asan_is_valid(path, 1))) {
if (!path || (IsAsan() && !__asan_is_valid_str(path))) {
rc = efault();
} else if (__isfdkind(dirfd, kFdZip)) {
rc = enotsup();
+1 -1
View File
@@ -44,7 +44,7 @@
*/
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
(rc = __zipos_notat(dirfd, path)) == -1) {
+1 -1
View File
@@ -43,7 +43,7 @@
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
int flags) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
(rc = __zipos_notat(dirfd, path)) == -1) {
+223 -41
View File
@@ -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/internal.h"
#include "libc/calls/struct/fd.internal.h"
@@ -24,63 +25,131 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/wincrash.internal.h"
#include "libc/errno.h"
#include "libc/intrin/kmalloc.h"
#include "libc/intrin/weaken.h"
#include "libc/limits.h"
#include "libc/log/backtrace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filelockflags.h"
#include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/byhandlefileinformation.h"
#include "libc/nt/struct/overlapped.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/thread.h"
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
if (start < 0) return einval();
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
struct FileLock {
struct FileLock *next;
int64_t off;
int64_t len;
int fd;
bool exc;
};
struct FileLocks {
pthread_mutex_t mu;
struct FileLock *list;
struct FileLock *free;
};
static struct FileLocks g_locks;
static textwindows struct FileLock *NewFileLock(void) {
struct FileLock *fl;
if (g_locks.free) {
fl = g_locks.free;
g_locks.free = fl->next;
} else {
fl = kmalloc(sizeof(*fl));
}
bzero(fl, sizeof(*fl));
fl->next = g_locks.list;
g_locks.list = fl;
return fl;
}
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
static textwindows void FreeFileLock(struct FileLock *fl) {
fl->next = g_locks.free;
g_locks.free = fl;
}
static textwindows bool OverlapsFileLock(struct FileLock *fl, int64_t off,
int64_t len) {
uint64_t BegA, EndA, BegB, EndB;
BegA = off;
EndA = off + (len - 1);
BegB = fl->off;
EndB = fl->off + (fl->len - 1);
return MAX(BegA, BegB) < MIN(EndA, EndB);
}
static textwindows bool EncompassesFileLock(struct FileLock *fl, int64_t off,
int64_t len) {
return off <= fl->off && fl->off + fl->len <= off + len;
}
static textwindows bool EqualsFileLock(struct FileLock *fl, int64_t off,
int64_t len) {
return fl->off == off && off + len == fl->off + fl->len;
}
hidden textwindows void sys_fcntl_nt_lock_cleanup(int fd) {
struct FileLock *fl, *ft, **flp;
pthread_mutex_lock(&g_locks.mu);
for (flp = &g_locks.list, fl = *flp; fl;) {
if (fl->fd == fd) {
*flp = fl->next;
ft = fl->next;
FreeFileLock(fl);
fl = ft;
} else {
flp = &fl->next;
fl = *flp;
}
}
pthread_mutex_unlock(&g_locks.mu);
}
static textwindows int sys_fcntl_nt_lock(struct Fd *f, int fd, int cmd,
uintptr_t arg) {
int e;
struct flock *l;
uint32_t flags, err;
int64_t pos, off, len, size;
struct NtByHandleFileInformation info;
if (!GetFileInformationByHandle(f->handle, &info)) {
return __winerr();
}
pos = 0;
if (!SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) {
return __winerr();
}
struct FileLock *fl, *ft, **flp;
int64_t pos, off, len, end, size;
l = (struct flock *)arg;
len = l->l_len;
off = l->l_start;
size = (uint64_t)info.nFileSizeHigh << 32 | info.nFileSizeLow;
switch (l->l_whence) {
case SEEK_SET:
break;
case SEEK_CUR:
off = pos + off;
pos = 0;
if (SetFilePointerEx(f->handle, 0, &pos, SEEK_CUR)) {
off = pos + off;
} else {
return __winerr();
}
break;
case SEEK_END:
off = size - off;
off = INT64_MAX - off;
break;
default:
return einval();
}
if (!len) {
len = size - off;
len = INT64_MAX - off;
}
if (off < 0 || len < 0) {
if (off < 0 || len < 0 || __builtin_add_overflow(off, len, &end)) {
return einval();
}
@@ -89,8 +158,57 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
.Pointer = (void *)(uintptr_t)off};
if (l->l_type == F_RDLCK || l->l_type == F_WRLCK) {
if (cmd == F_SETLK || cmd == F_SETLKW) {
// make it possible to transition read locks to write locks
for (flp = &g_locks.list, fl = *flp; fl;) {
if (fl->fd == fd) {
if (EqualsFileLock(fl, off, len)) {
if (fl->exc == l->l_type == F_WRLCK) {
// we already have this lock
return 0;
} else {
// unlock our read lock and acquire write lock below
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
*flp = fl->next;
ft = fl->next;
FreeFileLock(fl);
fl = ft;
continue;
} else {
return -1;
}
}
break;
} else if (OverlapsFileLock(fl, off, len)) {
return enotsup();
}
}
flp = &fl->next;
fl = *flp;
}
}
// return better information on conflicting locks if possible
if (cmd == F_GETLK) {
for (fl = g_locks.list; fl; fl = fl->next) {
if (fl->fd == fd && //
OverlapsFileLock(fl, off, len) &&
(l->l_type == F_WRLCK || !fl->exc)) {
l->l_whence = SEEK_SET;
l->l_start = fl->off;
l->l_len = fl->len;
l->l_type == fl->exc ? F_WRLCK : F_RDLCK;
l->l_pid = getpid();
return 0;
}
}
}
flags = 0;
if (cmd != F_SETLKW) {
// TODO(jart): we should use expo backoff in wrapper function
// should not matter since sqlite doesn't need it
flags |= kNtLockfileFailImmediately;
}
if (l->l_type == F_WRLCK) {
@@ -101,68 +219,132 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int cmd, uintptr_t arg) {
if (ok) {
l->l_type = F_UNLCK;
if (!UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
notpossible;
return -1;
}
} else {
l->l_pid = -1;
ok = true;
}
} else if (ok) {
fl = NewFileLock();
fl->off = off;
fl->len = len;
fl->exc = l->l_type == F_WRLCK;
fl->fd = fd;
}
return ok ? 0 : -1;
}
if (l->l_type == F_UNLCK) {
if (cmd == F_GETLK) return einval();
e = errno;
if (UnlockFileEx(f->handle, 0, len, len >> 32, &ov)) {
return 0;
} else if (errno == ENOLCK) {
errno = e;
return 0;
} else {
return 0;
// allow a big range to unlock many small ranges
for (flp = &g_locks.list, fl = *flp; fl;) {
if (fl->fd == fd && EncompassesFileLock(fl, off, len)) {
struct NtOverlapped ov = {.hEvent = f->handle,
.Pointer = (void *)(uintptr_t)fl->off};
if (UnlockFileEx(f->handle, 0, fl->len, fl->len >> 32, &ov)) {
*flp = fl->next;
ft = fl->next;
FreeFileLock(fl);
fl = ft;
} else {
return -1;
}
} else {
flp = &fl->next;
fl = *flp;
}
}
// win32 won't let us carve up existing locks
int overlap_count = 0;
for (fl = g_locks.list; fl; fl = fl->next) {
if (fl->fd == fd && //
OverlapsFileLock(fl, off, len)) {
++overlap_count;
}
}
// try to handle the carving cases needed by sqlite
if (overlap_count == 1) {
for (fl = g_locks.list; fl; fl = fl->next) {
if (fl->fd == fd && //
off <= fl->off && //
off + len >= fl->off && //
off + len < fl->off + fl->len) {
// cleave left side of lock
struct NtOverlapped ov = {.hEvent = f->handle,
.Pointer = (void *)(uintptr_t)fl->off};
if (!UnlockFileEx(f->handle, 0, fl->len, fl->len >> 32, &ov)) {
return -1;
}
fl->len = (fl->off + fl->len) - (off + len);
fl->off = off + len;
ov.Pointer = (void *)(uintptr_t)fl->off;
if (!LockFileEx(f->handle, kNtLockfileExclusiveLock, 0, fl->len,
fl->len >> 32, &ov)) {
return -1;
}
return 0;
}
}
}
if (overlap_count) {
return enotsup();
}
return 0;
}
return einval();
}
static textwindows int sys_fcntl_nt_dupfd(int fd, int cmd, int start) {
if (start < 0) return einval();
return sys_dup_nt(fd, -1, (cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0), start);
}
textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
int rc;
uint32_t flags;
if (__isfdkind(fd, kFdFile) || __isfdkind(fd, kFdSocket)) {
if (cmd == F_GETFL) {
return g_fds.p[fd].flags &
(O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME |
O_NONBLOCK | O_RANDOM | O_SEQUENTIAL);
rc = g_fds.p[fd].flags &
(O_ACCMODE | O_APPEND | O_ASYNC | O_DIRECT | O_NOATIME | O_NONBLOCK |
O_RANDOM | O_SEQUENTIAL);
} else if (cmd == F_SETFL) {
// O_APPEND doesn't appear to be tunable at cursory glance
// O_NONBLOCK might require we start doing all i/o in threads
// O_DSYNC / O_RSYNC / O_SYNC maybe if we fsync() everything
// O_DIRECT | O_RANDOM | O_SEQUENTIAL | O_NDELAY possible but
// not worth it.
return einval();
rc = enosys();
} else if (cmd == F_GETFD) {
if (g_fds.p[fd].flags & O_CLOEXEC) {
return FD_CLOEXEC;
rc = FD_CLOEXEC;
} else {
return 0;
rc = 0;
}
} else if (cmd == F_SETFD) {
if (arg & FD_CLOEXEC) {
g_fds.p[fd].flags |= O_CLOEXEC;
return FD_CLOEXEC;
} else {
g_fds.p[fd].flags &= ~O_CLOEXEC;
return 0;
}
rc = 0;
} else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK) {
return sys_fcntl_nt_lock(g_fds.p + fd, cmd, arg);
pthread_mutex_lock(&g_locks.mu);
rc = sys_fcntl_nt_lock(g_fds.p + fd, fd, cmd, arg);
pthread_mutex_unlock(&g_locks.mu);
} else if (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC) {
return sys_fcntl_nt_dupfd(fd, cmd, arg);
rc = sys_fcntl_nt_dupfd(fd, cmd, arg);
} else {
return einval();
rc = einval();
}
} else {
return ebadf();
rc = ebadf();
}
return rc;
}
+15 -12
View File
@@ -31,7 +31,7 @@
#include "libc/zipos/zipos.internal.h"
/**
* Does things with file descriptor, via re-imagined hourglass api, e.g.
* Does things with file descriptor, e.g.
*
* CHECK_NE(-1, fcntl(fd, F_SETFD, FD_CLOEXEC));
*
@@ -41,12 +41,14 @@
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD, 3)), 3);
* CHECK_GE((newfd = fcntl(oldfd, F_DUPFD_CLOEXEC, 3)), 3);
*
* This function implements POSIX Advisory Locks, which let independent
* processes (and on Windows, threads too!) read/write lock byte ranges
* of files. See `test/libc/calls/lock_test.c` for an example.
* This function implements file record locking, which lets independent
* processes (and on Linux 3.15+, threads too!) lock arbitrary ranges
* associated with a file. See `test/libc/calls/lock_test.c` and other
* locking related tests in that folder.
*
* Please be warned that locks currently do nothing on Windows since
* figuring out how to polyfill them correctly is a work in progress.
* On Windows, the Cosmopolitan Libc polyfill for POSIX advisory locks
* only implements enough of its nuances to support SQLite's needs. Some
* possibilities, e.g. punching holes in lock, will raise `ENOTSUP`.
*
* @param fd is the file descriptor
* @param cmd can be one of:
@@ -56,12 +58,12 @@
* - `F_SETFL` sets file descriptor status flags
* - `F_DUPFD` is like dup() but `arg` is a minimum result, e.g. 3
* - `F_DUPFD_CLOEXEC` ditto but sets `O_CLOEXEC` on returned fd
* - `F_SETLK` for record locking where `arg` is `struct flock`
* - `F_SETLKW` ditto but waits (i.e. blocks) for lock
* - `F_SETLK` for record locking where `arg` is `struct flock *`
* - `F_SETLKW` ditto but waits for lock (SQLite avoids this)
* - `F_GETLK` to retrieve information about a record lock
* - `F_OFD_SETLK` for better locks on Linux and XNU
* - `F_OFD_SETLKW` for better locks on Linux and XNU
* - `F_OFD_GETLK` for better locks on Linux and XNU
* - `F_OFD_SETLK` for better non-blocking lock (Linux 3.15+ only)
* - `F_OFD_SETLKW` for better blocking lock (Linux 3.15+ only)
* - `F_OFD_GETLK` for better lock querying (Linux 3.15+ only)
* - `F_FULLFSYNC` on MacOS for fsync() with release barrier
* - `F_BARRIERFSYNC` on MacOS for fsync() with even more barriers
* - `F_SETNOSIGPIPE` on MacOS and NetBSD to control `SIGPIPE`
@@ -71,7 +73,7 @@
* - `F_NOCACHE` on MacOS to toggle data caching
* - `F_GETPIPE_SZ` on Linux to get pipe size
* - `F_SETPIPE_SZ` on Linux to set pipe size
* - `F_NOTIFY` raise `SIGIO` upon `fd` events in `arg` on Linux
* - `F_NOTIFY` raise `SIGIO` upon `fd` events in `arg` (Linux only)
* - `DN_ACCESS` for file access
* - `DN_MODIFY` for file modifications
* - `DN_CREATE` for file creations
@@ -88,6 +90,7 @@
* @raise ENOLCK if `F_SETLKW` would have exceeded `RLIMIT_LOCKS`
* @raise EPERM if `cmd` is `F_SETOWN` and we weren't authorized
* @raise ESRCH if `cmd` is `F_SETOWN` and process group not found
* @raise ENOTSUP on Windows if locking operation isn't supported yet
* @raise EDEADLK if `cmd` was `F_SETLKW` and waiting would deadlock
* @raise EMFILE if `cmd` is `F_DUPFD` or `F_DUPFD_CLOEXEC` and
* `RLIMIT_NOFILE` would be exceeded
+3 -17
View File
@@ -21,8 +21,7 @@
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
@@ -48,21 +47,8 @@ int fexecve(int fd, char *const argv[], char *const envp[]) {
(!__asan_is_valid_strlist(argv) || !__asan_is_valid_strlist(envp)))) {
rc = efault();
} else {
#ifdef SYSDEBUG
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "fexecve(%d, {", fd);
for (i = 0; argv[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", argv[i]);
}
kprintf("}, {");
for (i = 0; envp[i]; ++i) {
if (i) kprintf(", ");
kprintf("%#s", envp[i]);
}
kprintf("})\n");
}
#endif
STRACE("fexecve(%d, %s, %s) → ...", fd, DescribeStringList(argv),
DescribeStringList(envp));
if (IsLinux()) {
char path[14 + 12];
FormatInt32(stpcpy(path, "/proc/self/fd/"), fd);
+1 -1
View File
@@ -51,7 +51,7 @@ bool fileexists(const char *path) {
struct ZiposUri zipname;
uint16_t path16[PATH_MAX];
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
efault();
res = false;
} else if (_weaken(__zipos_open) &&
+1 -1
View File
@@ -31,7 +31,7 @@ int32_t sys_fstatat(int32_t dirfd, const char *path, struct stat *st,
int rc;
void *p;
union metastat ms;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (IsAsan() && !__asan_is_valid_str(path)) return efault();
if (IsLinux()) {
_Static_assert(sizeof(*st) == sizeof(ms.linux), "assumption broken");
if (IsAsan() && (st && !__asan_is_valid(st, sizeof(*st)))) return efault();
+1 -1
View File
@@ -63,7 +63,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
rc = __gettimeofday(tv, tz, 0).ax;
}
#if SYSDEBUG
if (!(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
if (__tls_enabled && !(__get_tls()->tib_flags & TIB_FLAG_TIME_CRITICAL)) {
STRACE("gettimeofday([%s], %p) → %d% m", DescribeTimeval(rc, tv), tz, rc);
}
#endif
+1 -2
View File
@@ -18,7 +18,6 @@ hidden extern const struct Fd kEmptyFd;
int __reservefd(int) hidden;
int __reservefd_unlocked(int) hidden;
void __releasefd(int) hidden;
void __releasefd_unlocked(int) hidden;
int __ensurefds(int) hidden;
int __ensurefds_unlocked(int) hidden;
void __printfds(void) hidden;
@@ -43,7 +42,7 @@ forceinline size_t _clampio(size_t size) {
}
}
int sys_close_nt(struct Fd *) hidden;
int sys_close_nt(struct Fd *, int) hidden;
bool _check_interrupts(bool, struct Fd *) hidden;
int sys_openat_metal(int, const char *, int, unsigned);
+1 -1
View File
@@ -51,7 +51,7 @@ bool isdirectory(const char *path) {
union metastat st;
struct ZiposUri zipname;
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
efault();
res = false;
} else if (_weaken(__zipos_open) &&
+1 -1
View File
@@ -48,7 +48,7 @@ bool isregularfile(const char *path) {
union metastat st;
struct ZiposUri zipname;
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
efault();
res = false;
} else if (_weaken(__zipos_open) &&
+1 -1
View File
@@ -51,7 +51,7 @@ bool issymlink(const char *path) {
union metastat st;
struct ZiposUri zipname;
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
efault();
res = false;
} else if (_weaken(__zipos_open) &&
+5 -1
View File
@@ -17,10 +17,10 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.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/str/str.h"
/**
@@ -38,6 +38,10 @@
* >0 can be SIGINT, SIGTERM, SIGKILL, SIGUSR1, etc.
* =0 checks both if pid exists and we can signal it
* @return 0 if something was accomplished, or -1 w/ errno
* @raise ESRCH if `pid` couldn't be found
* @raise EPERM if lacked permission to signal process
* @raise EPERM if pledge() is in play without `proc` promised
* @raise EINVAL if the provided `sig` is invalid or unsupported
* @asyncsignalsafe
*/
int kill(int pid, int sig) {
+1 -1
View File
@@ -41,7 +41,7 @@ int linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath,
int flags) {
int rc;
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
(!__asan_is_valid_str(oldpath) || !__asan_is_valid_str(newpath))) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
+2
View File
@@ -34,6 +34,8 @@ textwindows int64_t sys_lseek_nt(int fd, int64_t offset, int whence) {
} else {
return espipe();
}
} else if (__isfdkind(fd, kFdSocket)) {
return espipe();
} else {
return ebadf();
}
+1 -1
View File
@@ -53,7 +53,7 @@
*/
int mkdirat(int dirfd, const char *path, unsigned mode) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) {
if (IsAsan() && !__asan_is_valid_str(path)) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
(rc = __zipos_notat(dirfd, path)) == -1) {
+2 -2
View File
@@ -17,10 +17,10 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/ipc.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
@@ -36,7 +36,7 @@
int mkfifo(const char *pathname, unsigned mode) {
// TODO(jart): Windows?
int rc;
if (IsAsan() && !__asan_is_valid(pathname, 1)) {
if (IsAsan() && !__asan_is_valid_str(pathname)) {
rc = efault();
} else if (IsLinux()) {
rc = sys_mknod(pathname, mode | S_IFIFO, 0);
+2 -2
View File
@@ -17,10 +17,10 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/s.h"
#include "libc/sysv/errfuns.h"
@@ -40,7 +40,7 @@
*/
int mknod(const char *path, uint32_t mode, uint64_t dev) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (IsAsan() && !__asan_is_valid_str(path)) return efault();
if (mode & S_IFREG) return creat(path, mode & ~S_IFREG);
if (mode & S_IFDIR) return mkdir(path, mode & ~S_IFDIR);
if (mode & S_IFIFO) return mkfifo(path, mode & ~S_IFIFO);
+7 -5
View File
@@ -21,9 +21,7 @@
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
#include "libc/str/tpdecode.internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
@@ -61,9 +59,13 @@ textwindows int __mkntpath(const char *path,
/**
* Copies path for Windows NT.
*
* This entails (1) UTF-8 to UTF-16 conversion; (2) replacing
* forward-slashes with backslashes; and (3) remapping several
* well-known paths (e.g. /dev/null → NUL) for convenience.
* This function does the following chores:
*
* 1. Converting UTF-8 to UTF-16
* 2. Replacing forward-slashes with backslashes
* 3. Fixing drive letter paths, e.g. `/c/` → `c:\`
* 4. Add `\\?\` prefix for paths exceeding 260 chars
* 5. Remapping well-known paths, e.g. `/dev/null` → `NUL`
*
* @param flags is used by open()
* @param path16 is shortened so caller can prefix, e.g. \\.\pipe\, and
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/runtime/directmap.internal.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/runtime/pc.internal.h"
noasan int sys_munmap_metal(void *addr, size_t size) {
+3 -3
View File
@@ -16,11 +16,11 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/intrin/strace.internal.h"
/**
* Unmaps memory directly with system.
+2 -2
View File
@@ -56,7 +56,7 @@ static long double GetTimeSample(void) {
static long double MeasureNanosPerCycle(void) {
int i, n;
long double avg, samp;
__get_tls()->tib_flags |= TIB_FLAG_TIME_CRITICAL;
if (__tls_enabled) __get_tls()->tib_flags |= TIB_FLAG_TIME_CRITICAL;
if (IsWindows()) {
n = 10;
} else {
@@ -66,7 +66,7 @@ static long double MeasureNanosPerCycle(void) {
samp = GetTimeSample();
avg += (samp - avg) / i;
}
__get_tls()->tib_flags &= ~TIB_FLAG_TIME_CRITICAL;
if (__tls_enabled) __get_tls()->tib_flags &= ~TIB_FLAG_TIME_CRITICAL;
STRACE("MeasureNanosPerCycle cpn*1000=%d", (long)(avg * 1000));
return avg;
}
-2
View File
@@ -23,7 +23,6 @@
privileged void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
if (!cr) return;
ctx->uc_flags = cr->EFlags;
ctx->uc_mcontext.eflags = cr->EFlags;
ctx->uc_mcontext.rax = cr->Rax;
ctx->uc_mcontext.rbx = cr->Rbx;
@@ -51,7 +50,6 @@ privileged void _ntcontext2linux(ucontext_t *ctx, const struct NtContext *cr) {
privileged void _ntlinux2context(struct NtContext *cr, const ucontext_t *ctx) {
if (!cr) return;
cr->EFlags = ctx->uc_flags;
cr->EFlags = ctx->uc_mcontext.eflags;
cr->Rax = ctx->uc_mcontext.rax;
cr->Rbx = ctx->uc_mcontext.rbx;
+2 -2
View File
@@ -18,9 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/ntspawn.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/pushpop.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
@@ -80,6 +78,8 @@ textwindows int ntspawn(
rc = -1;
block = NULL;
if (__mkntpath(prog, prog16) == -1) return -1;
// we can't call malloc() because we're higher in the topological order
// we can't call kmalloc() because fork() calls this when kmalloc is locked
if ((handle = CreateFileMapping(-1, 0, pushpop(kNtPageReadwrite), 0,
sizeof(*block), 0)) &&
(block = MapViewOfFileEx(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
+2 -2
View File
@@ -53,7 +53,7 @@ static long double GetTimeSample(void) {
static long double MeasureNanosPerCycle(void) {
int i, n;
long double avg, samp;
__get_tls()->tib_flags |= TIB_FLAG_TIME_CRITICAL;
if (__tls_enabled) __get_tls()->tib_flags |= TIB_FLAG_TIME_CRITICAL;
if (IsWindows()) {
n = 30;
} else {
@@ -63,7 +63,7 @@ static long double MeasureNanosPerCycle(void) {
samp = GetTimeSample();
avg += (samp - avg) / i;
}
__get_tls()->tib_flags &= ~TIB_FLAG_TIME_CRITICAL;
if (__tls_enabled) __get_tls()->tib_flags &= ~TIB_FLAG_TIME_CRITICAL;
STRACE("MeasureNanosPerCycle cpn*1000=%d", (long)(avg * 1000));
return avg;
}
+1 -1
View File
@@ -88,7 +88,7 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
}
if (rc == -1) {
__releasefd_unlocked(fd);
__releasefd(fd);
}
__fds_unlock();
}
+1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/intrin/weaken.h"
+1 -1
View File
@@ -154,7 +154,7 @@ int openat(int dirfd, const char *file, int flags, ...) {
va_start(va, flags);
mode = va_arg(va, unsigned);
va_end(va);
if (file && (!IsAsan() || __asan_is_valid(file, 1))) {
if (file && (!IsAsan() || __asan_is_valid_str(file))) {
if (!__isfdkind(dirfd, kFdZip)) {
if (_weaken(__zipos_open) &&
_weaken(__zipos_parseuri)(file, &zipname) != -1) {
+3 -3
View File
@@ -41,7 +41,7 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
return -1;
}
if ((writer = __reservefd_unlocked(-1)) == -1) {
__releasefd_unlocked(reader);
__releasefd(reader);
__fds_unlock();
return -1;
}
@@ -73,8 +73,8 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
CloseHandle(hin);
}
}
__releasefd_unlocked(writer);
__releasefd_unlocked(reader);
__releasefd(writer);
__releasefd(reader);
__fds_unlock();
return -1;
}
+18 -10
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/pledge.internal.h"
#include "libc/calls/struct/bpf.h"
@@ -1605,19 +1606,26 @@ static privileged void AllowFcntlStdio(struct Filter *f) {
// The second argument of fcntl() must be one of:
//
// - F_GETLK (5)
// - F_SETLK (6)
// - F_SETLKW (7)
// - F_GETLK (0x05)
// - F_SETLK (0x06)
// - F_SETLKW (0x07)
// - F_OFD_GETLK (0x24)
// - F_OFD_SETLK (0x25)
// - F_OFD_SETLKW (0x26)
//
static privileged void AllowFcntlLock(struct Filter *f) {
static const struct sock_filter fragment[] = {
/*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fcntl, 0, 6 - 1),
/*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])),
/*L2*/ BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 5, 0, 5 - 3),
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 8, 5 - 4, 0),
/*L4*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
/*L5*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
/*L6*/ /* next filter */
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_fcntl, 0, 9),
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[1])),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x05, 5, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 4, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x07, 3, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x24, 2, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x25, 1, 0),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x26, 0, 1),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
/* next filter */
};
AppendFilter(f, PLEDGE(fragment));
}
+3 -28
View File
@@ -16,17 +16,9 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/sysv/errfuns.h"
@@ -68,8 +60,8 @@
* @norestart
*/
int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
int rc;
size_t n;
int i, rc;
uint64_t millis;
if (IsAsan() && (__builtin_mul_overflow(nfds, sizeof(struct pollfd), &n) ||
@@ -86,24 +78,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
rc = sys_poll_nt(fds, nfds, &millis, 0);
}
#if defined(SYSDEBUG) && _POLLTRACE
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "poll(");
if ((!IsAsan() && kisdangerous(fds)) ||
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
kprintf("%p", fds);
} else {
kprintf("[{");
for (i = 0; i < MIN(5, nfds); ++i) {
kprintf("%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
DescribePollFlags(fds[i].events),
DescribePollFlags(fds[i].revents));
}
kprintf("%s}]", i == 5 ? "..." : "");
}
kprintf(", %'zu, %'d) → %d% lm\n", nfds, timeout_ms, rc);
}
#endif
STRACE("poll(%s, %'zu, %'d) → %d% lm", DescribePollFds(rc, fds, nfds), nfds,
timeout_ms, rc);
return rc;
}
+5 -24
View File
@@ -16,15 +16,14 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timespec.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/sock/struct/pollfd.h"
#include "libc/sock/struct/pollfd.internal.h"
#include "libc/sysv/consts/sig.h"
@@ -58,7 +57,7 @@
int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
const sigset_t *sigmask) {
size_t n;
int e, i, rc;
int e, rc;
uint64_t millis;
sigset_t oldmask;
struct timespec ts, *tsp;
@@ -96,25 +95,7 @@ int ppoll(struct pollfd *fds, size_t nfds, const struct timespec *timeout,
rc = sys_poll_nt(fds, nfds, &millis, sigmask);
}
#if defined(SYSDEBUG) && _POLLTRACE
if (UNLIKELY(__strace > 0)) {
kprintf(STRACE_PROLOGUE "ppoll(");
if ((!IsAsan() && kisdangerous(fds)) ||
(IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd)))) {
kprintf("%p", fds);
} else {
kprintf("[{");
for (i = 0; i < MIN(5, nfds); ++i) {
kprintf("%s{%d, %s, %s}", i ? ", " : "", fds[i].fd,
DescribePollFlags(fds[i].events),
DescribePollFlags(fds[i].revents));
}
kprintf("%s}]", i == 5 ? "..." : "");
}
kprintf(", %'zu, %s, %s) → %d% lm\n", nfds, DescribeTimeval(0, timeout),
DescribeSigset(0, sigmask), rc);
}
#endif
STRACE("ppoll(%s, %'zu, %s, %s) → %d% lm", DescribePollFds(rc, fds, nfds),
nfds, DescribeTimespec(0, timeout), DescribeSigset(0, sigmask), rc);
return rc;
}
+2 -17
View File
@@ -16,12 +16,9 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
@@ -31,16 +28,13 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
int e, i;
size_t got;
bool masked;
ssize_t rc, toto;
sigset_t mask, oldmask;
if (fd < 0) {
return ebadf();
@@ -94,26 +88,17 @@ static ssize_t Preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
if (rc == -1) {
if (!toto) {
toto = -1;
} else if (errno != EINTR) {
notpossible;
}
break;
}
got = rc;
toto += got;
off += got;
if (got != iov[i].iov_len) {
break;
}
if (!masked) {
sigfillset(&mask);
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
masked = true;
}
}
if (masked) {
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
}
return toto;
+2 -17
View File
@@ -16,12 +16,9 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
@@ -31,17 +28,14 @@
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
int64_t off) {
int i, e;
bool masked;
size_t sent;
ssize_t rc, toto;
sigset_t mask, oldmask;
if (fd < 0) {
return ebadf();
@@ -95,26 +89,17 @@ static ssize_t Pwritev(int fd, const struct iovec *iov, int iovlen,
if (rc == -1) {
if (!toto) {
toto = -1;
} else if (errno != EINTR) {
notpossible;
}
break;
}
sent = rc;
toto += sent;
off += sent;
if (sent != iov[i].iov_len) {
break;
}
if (!masked) {
sigfillset(&mask);
_npassert(!sys_sigprocmask(SIG_SETMASK, &mask, &oldmask));
masked = true;
}
}
if (masked) {
_npassert(!sys_sigprocmask(SIG_SETMASK, &oldmask, 0));
}
return toto;
@@ -17,11 +17,18 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
// really want to avoid locking here so close() needn't block signals
void __releasefd(int fd) {
__fds_lock();
__releasefd_unlocked(fd);
__fds_unlock();
int f1, f2;
if (!(0 <= fd && fd < g_fds.n)) return;
bzero(g_fds.p + fd, sizeof(*g_fds.p));
f1 = atomic_load_explicit(&g_fds.f, memory_order_relaxed);
do {
f2 = MIN(fd, f1);
} while (!atomic_compare_exchange_weak_explicit(
&g_fds.f, &f1, f2, memory_order_release, memory_order_relaxed));
}
+1 -1
View File
@@ -47,7 +47,7 @@ int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
int rc;
if (IsAsan() &&
(!__asan_is_valid(oldpath, 1) || !__asan_is_valid(newpath, 1))) {
(!__asan_is_valid_str(oldpath) || !__asan_is_valid_str(newpath))) {
rc = efault();
} else if (_weaken(__zipos_notat) &&
((rc = __zipos_notat(olddirfd, oldpath)) == -1 ||
+12 -14
View File
@@ -16,25 +16,18 @@
│ 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/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/cmpxchg.h"
#include "libc/intrin/extend.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
// TODO(jart): make more of this code lockless
static volatile size_t mapsize;
@@ -71,9 +64,10 @@ int __ensurefds(int fd) {
* @asyncsignalsafe
*/
int __reservefd_unlocked(int start) {
int fd;
int fd, f1, f2;
for (;;) {
for (fd = MAX(start, g_fds.f); fd < g_fds.n; ++fd) {
f1 = atomic_load_explicit(&g_fds.f, memory_order_acquire);
for (fd = MAX(start, f1); fd < g_fds.n; ++fd) {
if (!g_fds.p[fd].kind) {
break;
}
@@ -81,7 +75,11 @@ int __reservefd_unlocked(int start) {
fd = __ensurefds_unlocked(fd);
bzero(g_fds.p + fd, sizeof(*g_fds.p));
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
_cmpxchg(&g_fds.f, fd, fd + 1);
// g_fds.f isn't guarded by our mutex
do {
f2 = MAX(fd + 1, f1);
} while (!atomic_compare_exchange_weak_explicit(
&g_fds.f, &f1, f2, memory_order_release, memory_order_relaxed));
return fd;
}
}
+2 -6
View File
@@ -19,9 +19,9 @@
#include "libc/assert.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/stdio/rand.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "libc/stdio/lcg.internal.h"
/**
* Returns handles of windows pids being tracked.
@@ -35,12 +35,8 @@
textwindows int __sample_pids(int pids[hasatleast 64],
int64_t handles[hasatleast 64],
bool exploratory) {
static uint64_t rando = 1;
static pthread_spinlock_t lock;
uint32_t i, j, base, count;
if (__threaded) pthread_spin_lock(&lock);
base = KnuthLinearCongruentialGenerator(&rando) >> 32;
pthread_spin_unlock(&lock);
base = _rand64() >> 32;
for (count = i = 0; i < g_fds.n; ++i) {
j = (base + i) % g_fds.n;
if (g_fds.p[j].kind == kFdProcess && (!exploratory || !g_fds.p[j].zombie)) {
+2 -2
View File
@@ -17,10 +17,10 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/console.h"
#include "libc/sysv/errfuns.h"
@@ -34,7 +34,7 @@ int setpgid(int pid, int pgid) {
rc = sys_setpgid(pid, pgid);
} else {
me = getpid();
if (pid == me && pgid == me) {
if ((!pid || pid == me) && (!pgid || pgid == me)) {
/*
* "When a process is created with CREATE_NEW_PROCESS_GROUP
* specified, an implicit call to SetConsoleCtrlHandler(NULL,TRUE)
+2676 -2
View File
File diff suppressed because it is too large. Load diff
+18 -26
View File
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/blocksigs.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
@@ -29,6 +30,7 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigaction.internal.h"
#include "libc/calls/struct/siginfo.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/calls/ucontext.h"
@@ -83,9 +85,11 @@ union metasigaction {
struct sigaction_xnu_out xnu_out;
};
void __sigenter_netbsd(int, void *, void *) hidden;
void __sigenter_freebsd(int, void *, void *) hidden;
void __sigenter_openbsd(int, void *, void *) hidden;
void __sigenter_xnu(int, struct siginfo *, void *) hidden;
void __sigenter_linux(int, struct siginfo *, void *) hidden;
void __sigenter_netbsd(int, struct siginfo *, void *) hidden;
void __sigenter_freebsd(int, struct siginfo *, void *) hidden;
void __sigenter_openbsd(int, struct siginfo *, void *) hidden;
static void sigaction_cosmo2native(union metasigaction *sa) {
if (!sa) return;
@@ -154,6 +158,7 @@ static int __sigaction(int sig, const struct sigaction *act,
"sigaction cosmo abi needs tuning");
int64_t arg4, arg5;
int rc, rva, oldrva;
sigaction_f sigenter;
struct sigaction *ap, copy;
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
if (!(0 < sig && sig < NSIG)) return einval();
@@ -181,11 +186,7 @@ static int __sigaction(int sig, const struct sigaction *act,
ap = &copy;
if (IsXnu()) {
ap->sa_restorer = (void *)&__sigenter_xnu;
if (rva < kSigactionMinRva) {
ap->sa_sigaction = (void *)(intptr_t)rva;
} else {
ap->sa_sigaction = (void *)&__sigenter_xnu;
}
sigenter = __sigenter_xnu;
// mitigate Rosetta signal handling strangeness
// https://github.com/jart/cosmopolitan/issues/455
ap->sa_flags |= SA_SIGINFO;
@@ -194,27 +195,21 @@ static int __sigaction(int sig, const struct sigaction *act,
ap->sa_flags |= SA_RESTORER;
ap->sa_restorer = &__restore_rt;
}
sigenter = __sigenter_linux;
} else if (IsNetbsd()) {
if (rva < kSigactionMinRva) {
ap->sa_sigaction = (void *)(intptr_t)rva;
} else {
ap->sa_sigaction = (sigaction_f)__sigenter_netbsd;
}
sigenter = __sigenter_netbsd;
} else if (IsFreebsd()) {
if (rva < kSigactionMinRva) {
ap->sa_sigaction = (void *)(intptr_t)rva;
} else {
ap->sa_sigaction = (sigaction_f)__sigenter_freebsd;
}
sigenter = __sigenter_freebsd;
} else if (IsOpenbsd()) {
if (rva < kSigactionMinRva) {
ap->sa_sigaction = (void *)(intptr_t)rva;
} else {
ap->sa_sigaction = (sigaction_f)__sigenter_openbsd;
}
sigenter = __sigenter_openbsd;
} else {
return enosys();
}
if (rva < kSigactionMinRva) {
ap->sa_sigaction = (void *)(intptr_t)rva;
} else {
ap->sa_sigaction = sigenter;
}
sigaction_cosmo2native((union metasigaction *)ap);
} else {
ap = NULL;
@@ -466,7 +461,6 @@ static int __sigaction(int sig, const struct sigaction *act,
* @return 0 on success or -1 w/ errno
* @see xsigaction() for a much better api
* @asyncsignalsafe
* @threadsafe
* @vforksafe
*/
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
@@ -474,9 +468,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
if (sig == SIGKILL || sig == SIGSTOP) {
rc = einval();
} else {
__sig_lock();
rc = __sigaction(sig, act, oldact);
__sig_unlock();
}
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act),
DescribeSigaction(rc, oldact), rc);
@@ -16,17 +16,16 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/runtime/runtime.h"
#include "libc/thread/semaphore.h"
#include "libc/calls/struct/sigset.h"
/**
* Closes named semaphore.
* Blocks all signals without strace logging.
*
* @param sem was created with sem_open()
* @return 0 on success, or -1 w/ errno
* @param neu is new signal mask for process
* @return old signal mask
*/
int sem_close(sem_t *sem) {
_npassert(!munmap(sem, FRAMESIZE));
return 0;
sigset_t _sigblockall(void) {
sigset_t ss;
sigfillset(&ss);
return _sigsetmask(ss);
}
+3 -3
View File
@@ -49,16 +49,16 @@ void _check_sigchld(void) {
i = WaitForMultipleObjects(n, handles, false, 0);
if (i == kNtWaitTimeout) return;
if (i == kNtWaitFailed) {
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
NTTRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());
return;
}
if (__sighandrvas[SIGCHLD] == (intptr_t)SIG_IGN ||
__sighandrvas[SIGCHLD] == (intptr_t)SIG_DFL) {
STRACE("new zombie fd=%d handle=%ld", pids[i], handles[i]);
NTTRACE("new zombie fd=%d handle=%ld", pids[i], handles[i]);
return;
}
if (__sighandflags[SIGCHLD] & SA_NOCLDWAIT) {
STRACE("SIGCHILD SA_NOCLDWAIT fd=%d handle=%ld", pids[i], handles[i]);
NTTRACE("SIGCHILD SA_NOCLDWAIT fd=%d handle=%ld", pids[i], handles[i]);
CloseHandle(handles[i]);
__releasefd(pids[i]);
}
+1 -1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
@@ -50,7 +51,6 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
g.uc.uc_flags = ctx->uc_flags;
__repmovsb(&g.uc.uc_sigmask, &ctx->uc_sigmask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
+48
View File
@@ -0,0 +1,48 @@
/*-*- 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 "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h"
#include "libc/intrin/likely.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"
privileged void __sigenter_linux(int sig, struct siginfo *info,
ucontext_t *ctx) {
int i, rva, flags;
rva = __sighandrvas[sig & (NSIG - 1)];
if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig & (NSIG - 1)];
// WSL1 doesn't set the fpregs field.
// https://github.com/microsoft/WSL/issues/2555
if ((flags & SA_SIGINFO) && UNLIKELY(!ctx->uc_mcontext.fpregs)) {
ctx->uc_mcontext.fpregs = &ctx->__fpustate;
for (i = 0; i < 8; ++i) {
long double nan = NAN;
memcpy(ctx->__fpustate.st + i, &nan, 16);
}
}
((sigaction_f)(_base + rva))(sig, info, ctx);
}
}
+1 -1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
@@ -46,7 +47,6 @@ privileged void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
__repstosb(&uc, 0, sizeof(uc));
__siginfo2cosmo(&si2, (void *)si);
uc.uc_mcontext.fpregs = &uc.__fpustate;
uc.uc_flags = ctx->uc_flags;
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
+3 -2
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
@@ -48,8 +49,8 @@ privileged void __sigenter_openbsd(int sig, struct siginfo_openbsd *openbsdinfo,
__repstosb(&g.uc, 0, sizeof(g.uc));
__siginfo2cosmo(&g.si, (void *)openbsdinfo);
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
__repmovsb(&g.uc.uc_sigmask, &ctx->sc_mask,
MIN(sizeof(g.uc.uc_sigmask), sizeof(ctx->sc_mask)));
g.uc.uc_sigmask.__bits[0] = ctx->sc_mask;
g.uc.uc_sigmask.__bits[1] = 0;
g.uc.uc_mcontext.rdi = ctx->sc_rdi;
g.uc.uc_mcontext.rsi = ctx->sc_rsi;
g.uc.uc_mcontext.rdx = ctx->sc_rdx;
+2 -1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/sections.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
@@ -470,8 +471,8 @@ privileged void __sigenter_xnu(void *fn, int infostyle, int sig,
} else {
__repstosb(&g, 0, sizeof(g));
if (xnuctx) {
g.uc.uc_flags = xnuctx->uc_onstack ? SA_ONSTACK : 0;
g.uc.uc_sigmask.__bits[0] = xnuctx->uc_sigmask;
g.uc.uc_sigmask.__bits[1] = 0;
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
+7 -1
View File
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/state.internal.h"
#include "libc/str/str.h"
#include "libc/thread/thread.h"
void(__sig_lock)(void) {
@@ -27,6 +28,11 @@ void(__sig_unlock)(void) {
pthread_mutex_unlock(&__sig_lock_obj);
}
__attribute__((__constructor__)) static void init(void) {
void __sig_funlock(void) {
bzero(&__sig_lock_obj, sizeof(__sig_lock_obj));
__sig_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
}
__attribute__((__constructor__)) static void __sig_init(void) {
pthread_atfork(__sig_lock, __sig_unlock, __sig_funlock);
}
File renamed without changes.
-1
View File
@@ -26,7 +26,6 @@
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/log/log.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
@@ -16,20 +16,25 @@
│ 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/thread/semaphore.h"
#include "libc/thread/semaphore.internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/dce.h"
#include "libc/sysv/consts/sig.h"
/**
* Removes named semaphore.
* Sets signal mask without strace logging.
*
* @param name can be absolute path or should be component w/o slashes
* @return 0 on success, or -1 w/ errno
* @raise EPERM if pledge() is in play w/o `cpath` promise
* @raise ENOENT if named semaphore doesn't exist
* @raise EACCES if permission is denied
* @param neu is new signal mask for process
* @return old signal mask
*/
int sem_unlink(const char *name) {
char path[PATH_MAX];
return unlink(__sem_name(name, path));
sigset_t _sigsetmask(sigset_t neu) {
sigset_t res;
if (IsMetal() || IsWindows()) {
__sig_mask(SIG_SETMASK, &neu, &res);
} else {
_npassert(!sys_sigprocmask(SIG_SETMASK, &neu, &res));
}
return res;
}
+4
View File
@@ -16,8 +16,10 @@ hidden extern const struct NtSecurityAttributes kNtIsInheritable;
void __fds_lock(void);
void __fds_unlock(void);
void __fds_funlock(void);
void __sig_lock(void);
void __sig_unlock(void);
void __sig_funlock(void);
#ifdef _NOPL0
#define __fds_lock() _NOPL0("__threadcalls", __fds_lock)
@@ -35,6 +37,8 @@ void __sig_unlock(void);
#define __sig_unlock() (__threaded ? __sig_unlock() : 0)
#endif
#define __vforked (__tls_enabled && (__get_tls()->tib_flags & TIB_FLAG_VFORKED))
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STATE_INTERNAL_H_ */
+1 -1
View File
@@ -25,7 +25,7 @@ struct Fd {
};
struct Fds {
int f; /* lowest free slot */
_Atomic(int) f; /* lowest free slot */
size_t n;
struct Fd *p, *e;
};
+1 -1
View File
@@ -9,7 +9,7 @@ struct flock { /* cosmopolitan abi */
int64_t l_start; /* starting offset */
int64_t l_len; /* no. bytes (0 means to end of file) */
int32_t l_pid; /* lock owner */
int32_t l_sysid; /* remote system id or zero for local */
int32_t l_sysid; /* remote system id or zero for local (freebsd) */
};
COSMOPOLITAN_C_END_
-2
View File
@@ -8,8 +8,6 @@
COSMOPOLITAN_C_START_
int sys_sigqueueinfo(int, const siginfo_t *) hidden;
void __sigenter_xnu(void *, int, int, struct siginfo_xnu *,
struct __darwin_ucontext *) hidden;
const char *DescribeSiginfo(char[300], int, const siginfo_t *);
#define DescribeSiginfo(x, y) DescribeSiginfo(alloca(300), x, y)
+3
View File
@@ -16,10 +16,13 @@ int sigorset(sigset_t *, const sigset_t *, const sigset_t *) paramsnonnull();
int sigisemptyset(const sigset_t *) paramsnonnull() nosideeffect;
int sigismember(const sigset_t *, int) paramsnonnull() nosideeffect;
int sigcountset(const sigset_t *) paramsnonnull() nosideeffect;
int sigisprecious(int) nosideeffect;
int sigprocmask(int, const sigset_t *, sigset_t *);
int sigsuspend(const sigset_t *);
int sigpending(sigset_t *);
int pthread_sigmask(int, const sigset_t *, sigset_t *);
sigset_t _sigsetmask(sigset_t);
sigset_t _sigblockall(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
+4 -5
View File
@@ -11,11 +11,10 @@
#define st_mtime_nsec st_mtim.tv_nsec
#define st_ctime_nsec st_ctim.tv_nsec
#define st_atimensec st_atim.tv_nsec
#define st_mtimensec st_mtim.tv_nsec
#define st_ctimensec st_ctim.tv_nsec
#define st_birthtime st_birthtim.tv_sec
#define st_birthtimensec st_birthtim.tv_nsec
#define st_atimensec st_atim.tv_nsec
#define st_mtimensec st_mtim.tv_nsec
#define st_ctimensec st_ctim.tv_nsec
#define st_birthtime st_birthtim.tv_sec
#define st_file_attributes st_flags
+2 -2
View File
@@ -17,12 +17,12 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
@@ -42,7 +42,7 @@
int symlinkat(const char *target, int newdirfd, const char *linkpath) {
int rc;
if (IsAsan() &&
(!__asan_is_valid(target, 1) || !__asan_is_valid(linkpath, 1))) {
(!__asan_is_valid_str(target) || !__asan_is_valid_str(linkpath))) {
rc = efault();
}
if (!IsWindows()) {
+2 -2
View File
@@ -17,11 +17,11 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/intrin/strace.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#define IsPeek(request) (IsLinux() && (request)-1u < 3)
@@ -46,7 +46,7 @@ int sys_ptrace(int op, ...) {
va_end(va);
rc = __sys_ptrace(op, pid, addr, data);
#ifdef SYSDEBUG
if (UNLIKELY(__strace > 0)) {
if (UNLIKELY(__strace > 0) && strace_enabled(0) > 0) {
if (rc != -1 && IsPeek(op) && data) {
STRACE("sys_ptrace(%s, %d, %p, [%p]) → %p% m", DescribePtrace(op), pid,
addr, *data, rc);
+2 -1
View File
@@ -10,8 +10,8 @@ COSMOPOLITAN_C_START_
│ cosmopolitan § syscalls » system five » structless synthetic jump slots ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
axdx_t __sys_fork(void) hidden;
axdx_t __sys_pipe(i32[hasatleast 2], i32) hidden;
axdx_t sys_fork(void) hidden;
axdx_t sys_getpid(void) hidden;
char *sys_getcwd(char *, u64) hidden;
char *sys_getcwd_xnu(char *, u64) hidden;
@@ -46,6 +46,7 @@ i32 sys_fchownat(i32, const char *, u32, u32, u32) hidden;
i32 sys_fcntl(i32, i32, u64) hidden;
i32 sys_fdatasync(i32) hidden;
i32 sys_flock(i32, i32) hidden;
i32 sys_fork(void) hidden;
i32 sys_fsync(i32) hidden;
i32 sys_ftruncate(i32, i64, i64) hidden;
i32 sys_getcontext(void *) hidden;
+34 -1
View File
@@ -16,8 +16,41 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/files.h"
#include "libc/sysv/errfuns.h"
static textwindows int sys_tcdrain_nt(int fd) {
if (!__isfdopen(fd)) return ebadf();
if (!FlushFileBuffers(g_fds.p[fd].handle)) return __winerr();
return 0;
}
/**
* Waits until all written output is transmitted.
*
* @param fd is file descriptor of tty
* @raise EBADF if `fd` isn't an open file descriptor
* @raise ENOTTY if `fd` is open but not a teletypewriter
* @raise EIO if process group of writer is orphoned, calling thread is
* not blocking `SIGTTOU`, and process isn't ignoring `SIGTTOU`
* @raise ENOSYS on bare metal
* @asyncsignalsafe
*/
int tcdrain(int fd) {
return ioctl(fd, TCSBRK, (void *)(intptr_t)1);
int rc;
if (IsMetal()) {
rc = enosys();
} else if (!IsWindows()) {
rc = sys_ioctl(fd, TCSBRK, (void *)(intptr_t)1);
} else {
rc = sys_tcdrain_nt(fd);
}
STRACE("tcdrain(%d) → %d% m", fd, rc);
return rc;
}
+74 -14
View File
@@ -16,31 +16,91 @@
│ 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/termios.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/strace.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/comms.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
#define kNtPurgeTxabort 1
#define kNtPurgeRxabort 2
static const char *DescribeFlow(char buf[12], int action) {
if (action == TCOOFF) return "TCOOFF";
if (action == TCOON) return "TCOON";
if (action == TCIOFF) return "TCIOFF";
if (action == TCION) return "TCION";
FormatInt32(buf, action);
return buf;
}
static int sys_tcflow_bsd(int fd, int action) {
int rc;
uint8_t c;
struct termios t;
if (action == TCOOFF) return sys_ioctl(fd, TIOCSTOP, 0);
if (action == TCOON) return sys_ioctl(fd, TIOCSTART, 0);
if (action != TCIOFF && action != TCION) return einval();
if (sys_ioctl(fd, TCGETS, &t) == -1) return -1;
c = t.c_cc[action == TCIOFF ? VSTOP : VSTART];
if (c == 255) return 0; // code is disabled
if (sys_write(fd, &c, 1) == -1) return -1;
return 0;
}
static dontinline textwindows int sys_tcflow_nt(int fd, int action) {
bool32 ok;
int64_t h;
if (!__isfdopen(fd)) return ebadf();
h = g_fds.p[fd].handle;
if (action == TCOOFF) {
ok = PurgeComm(h, kNtPurgeTxabort);
} else if (action == TCIOFF) {
ok = PurgeComm(h, kNtPurgeRxabort);
} else if (action == TCOON || action == TCION) {
ok = ClearCommBreak(h);
} else {
return einval();
}
return ok ? 0 : __winerr();
}
/**
* Changes flow of teletypewriter data.
*
* - `TCOOFF` suspends output
* - `TCOON` resumes output
* - `TCIOFF` transmits a STOP character
* - `TCION` transmits a START character
* @param fd is file descriptor of tty
* @param action may be one of:
* - `TCOOFF` to suspend output
* - `TCOON` to resume output
* - `TCIOFF` to transmit a `STOP` character
* - `TCION` to transmit a `START` character
* @return 0 on success, or -1 w/ errno
* @raise EINVAL if `action` is invalid
* @raise ENOSYS on Windows and Bare Metal
* @raise EBADF if `fd` isn't an open file descriptor
* @raise ENOTTY if `fd` is open but not a teletypewriter
* @raise EIO if process group of writer is orphoned, calling thread is
* not blocking `SIGTTOU`, and process isn't ignoring `SIGTTOU`
* @asyncsignalsafe
*/
int tcflow(int fd, int action) {
uint8_t c;
struct termios t;
if (!IsBsd()) return sys_ioctl(fd, TCXONC, action);
if (action == TCOOFF) return sys_ioctl(fd, TIOCSTOP, 0);
if (action == TCOON) return sys_ioctl(fd, TIOCSTART, 0);
if (action != TCIOFF && action != TCION) return einval();
if (tcgetattr(fd, &t) == -1) return -1;
if ((c = t.c_cc[action == TCIOFF ? VSTOP : VSTART]) != 255) {
if (sys_write(fd, &c, 1) == -1) return -1;
int rc;
if (IsMetal()) {
rc = enosys();
} else if (IsBsd()) {
rc = sys_ioctl(fd, TCXONC, action);
} else if (!IsWindows()) {
rc = sys_ioctl(fd, TCXONC, action);
} else {
rc = sys_tcflow_nt(fd, action);
}
return 0;
STRACE("tcflow(%d, %s) → %d% m", fd, DescribeFlow(alloca(12), action), rc);
return rc;
}
+59 -6
View File
@@ -16,17 +16,70 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/strace.internal.h"
#include "libc/mem/alloca.h"
#include "libc/nt/comms.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
#define kNtPurgeTxclear 4
#define kNtPurgeRxclear 8
static const char *DescribeFlush(char buf[12], int action) {
if (action == TCIFLUSH) return "TCIFLUSH";
if (action == TCOFLUSH) return "TCOFLUSH";
if (action == TCIOFLUSH) return "TCIOFLUSH";
FormatInt32(buf, action);
return buf;
}
static dontinline textwindows int sys_tcflush_nt(int fd, int queue) {
bool32 ok;
int64_t h;
if (!__isfdopen(fd)) return ebadf();
ok = true;
h = g_fds.p[fd].handle;
if (queue == TCIFLUSH || queue == TCIOFLUSH) {
ok &= !!PurgeComm(h, kNtPurgeRxclear);
}
if (queue == TCOFLUSH || queue == TCIOFLUSH) {
ok &= !!PurgeComm(h, kNtPurgeTxclear);
}
return ok ? 0 : __winerr();
}
/**
* Flushes teletypewriter data.
* Discards queued data on teletypewriter.
*
* - `TCIFLUSH` flushes data received but not read
* - `TCOFLUSH` flushes data written but not transmitted
* - `TCIOFLUSH` does both `TCOFLUSH` and `TCIFLUSH`
* @param queue may be one of:
* - `TCIFLUSH` flushes data received but not read
* - `TCOFLUSH` flushes data written but not transmitted
* - `TCIOFLUSH` does both `TCOFLUSH` and `TCIFLUSH`
* @return 0 on success, or -1 w/ errno
* @raise EINVAL if `action` is invalid
* @raise EBADF if `fd` isn't an open file descriptor
* @raise ENOTTY if `fd` is open but not a teletypewriter
* @raise EIO if process group of writer is orphoned, calling thread is
* not blocking `SIGTTOU`, and process isn't ignoring `SIGTTOU`
* @raise ENOSYS on bare metal
* @asyncsignalsafe
*/
int tcflush(int fd, int queue) {
/* TODO(jart): Windows? */
return sys_ioctl(fd, TCFLSH, queue);
int rc;
if (IsMetal()) {
rc = enosys();
} else if (!IsWindows()) {
rc = sys_ioctl(fd, TCFLSH, queue);
} else {
rc = sys_tcflush_nt(fd, queue);
}
STRACE("tcflush(%d, %s) → %d% m", fd, DescribeFlush(alloca(12), queue), rc);
return rc;
}
+18 -5
View File
@@ -16,16 +16,29 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/termios.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
/**
* Returns which process group controls terminal.
*
* @return process group id on success, or -1 w/ errno
* @raise ENOTTY if `fd` is isn't controlling teletypewriter
* @raise EBADF if `fd` isn't an open file descriptor
* @raise ENOSYS on Windows and Bare Metal
* @asyncsignalsafe
*/
int32_t tcgetpgrp(int fd) {
int pgrp;
if (ioctl(fd, TIOCGPGRP, &pgrp) < 0) return -1;
return pgrp;
int tcgetpgrp(int fd) {
int rc, pgrp;
if (IsWindows() || IsMetal()) {
rc = enosys();
} else {
rc = sys_ioctl(fd, TIOCGPGRP, &pgrp);
}
STRACE("tcgetpgrp(%d) → %d% m", fd, rc == -1 ? rc : pgrp);
return rc == -1 ? rc : pgrp;
}
Loaded 100 of 578 files, more files were not shown because too many files have changed in this diff. Show more