diff --git a/.gitattributes b/.gitattributes
index 77bb8d060..fa3e12742 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,4 @@
# -*- conf -*-
*.gz binary
/build/bootstrap/*.com binary
-/build/bootstrap/*.com binary
/usr/share/zoneinfo/* binary
diff --git a/Makefile b/Makefile
index 66c2dbb77..4bea2a572 100644
--- a/Makefile
+++ b/Makefile
@@ -73,9 +73,38 @@ MODE := $(m)
endif
endif
+UNAME_M = $(shell uname -m)
+UNAME_S = $(shell uname -s)
+
+# apple still distributes a 17 year old version of gnu make
+ifeq ($(MAKE_VERSION), 3.81)
+$(error please use build/bootstrap/make.com)
+endif
+
+# provide instructions to non-linux users on unbundling gcc
+ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined
+ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
+ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux
+$(error you need to download https://justine.lol/cosmocc-0.0.12.zip and unzip it inside the cosmo directory)
+endif
+endif
+endif
+
+# the default build modes is empty string
+# on x86_64 hosts, MODE= is the same as MODE=x86_64
+# on aarch64 hosts, MODE= is changed to MODE=aarch64
+ifeq ($(MODE),)
+ifeq ($(UNAME_M),arm64)
+MODE := aarch64
+endif
+ifeq ($(UNAME_M),aarch64)
+MODE := aarch64
+endif
+endif
+
+# primary build rules
all: o
o: o/$(MODE)
-
o/$(MODE): \
o/$(MODE)/ape \
o/$(MODE)/dsp \
@@ -86,18 +115,23 @@ o/$(MODE): \
o/$(MODE)/examples \
o/$(MODE)/third_party
+# check if we're using o//third_party/make/make.com
+# we added sandboxing to guarantee cosmo's makefile is hermetic
+# it also shaves away 200ms of startup latency with native $(uniq)
ifneq ($(LANDLOCKMAKE_VERSION),)
+ifeq ($(UNAME_S),Linux)
ifeq ($(wildcard /usr/bin/ape),)
$(warning please run ape/apeinstall.sh if you intend to use landlock make)
$(shell sleep .5)
endif
+endif
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
.STRICT = 1
endif
endif
-.PLEDGE = stdio rpath wpath cpath fattr proc
-.UNVEIL = \
+.PLEDGE += stdio rpath wpath cpath fattr proc
+.UNVEIL += \
libc/integral \
libc/stdbool.h \
libc/disclaimer.inc \
diff --git a/bin/aarch64-unknown-cosmo-addr2line b/bin/aarch64-unknown-cosmo-addr2line
index d85555b40..0db247007 100755
--- a/bin/aarch64-unknown-cosmo-addr2line
+++ b/bin/aarch64-unknown-cosmo-addr2line
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-addr2line"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-addr2line"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/aarch64-unknown-cosmo-ar b/bin/aarch64-unknown-cosmo-ar
index 79a86a39e..cf683311d 100755
--- a/bin/aarch64-unknown-cosmo-ar
+++ b/bin/aarch64-unknown-cosmo-ar
@@ -1,5 +1,4 @@
#!/bin/sh
-
PROG=${0##*/}
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
@@ -9,8 +8,14 @@ fatal_error() {
exit 1
}
-if [ ! -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-ar" ]; then
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+if [ ! -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" ]; then
fatal_error "you need to run: aarch64-unknown-cosmo-cc --update"
fi
-exec "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-ar" "$@"
+exec "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" "$@"
diff --git a/bin/aarch64-unknown-cosmo-as b/bin/aarch64-unknown-cosmo-as
index ecc114d9b..8ce97fd5f 100755
--- a/bin/aarch64-unknown-cosmo-as
+++ b/bin/aarch64-unknown-cosmo-as
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-as"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-as"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/aarch64-unknown-cosmo-nm b/bin/aarch64-unknown-cosmo-nm
index bd25f1b79..fb51833e1 100755
--- a/bin/aarch64-unknown-cosmo-nm
+++ b/bin/aarch64-unknown-cosmo-nm
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-nm"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-nm"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/aarch64-unknown-cosmo-objcopy b/bin/aarch64-unknown-cosmo-objcopy
index f561cd9af..f9de8f3f6 100755
--- a/bin/aarch64-unknown-cosmo-objcopy
+++ b/bin/aarch64-unknown-cosmo-objcopy
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-objcopy"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objcopy"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/aarch64-unknown-cosmo-objdump b/bin/aarch64-unknown-cosmo-objdump
index 274bc8c4d..1429f137f 100755
--- a/bin/aarch64-unknown-cosmo-objdump
+++ b/bin/aarch64-unknown-cosmo-objdump
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-objdump"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objdump"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/aarch64-unknown-cosmo-strip b/bin/aarch64-unknown-cosmo-strip
index 4c1c8e7e5..a2cfd3377 100755
--- a/bin/aarch64-unknown-cosmo-strip
+++ b/bin/aarch64-unknown-cosmo-strip
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-${m:-aarch64}}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
-TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-strip"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-strip"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
diff --git a/bin/apecopy b/bin/apecopy
index 98d6eb549..8f2d80f0f 100755
--- a/bin/apecopy
+++ b/bin/apecopy
@@ -1,5 +1,4 @@
#!/bin/sh
-
PROG=${0##*/}
COSMO=${COSMO:-/opt/cosmo}
@@ -67,8 +66,14 @@ if [ ! -d "$COSMO" ]; then
fatal_error "you need to clone cosmopolitan to your $COSMO directory"
fi
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
if [ ! -f "$COSMO/o//tool/build/zipcopy.com" ] ||
- [ ! -f "$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-objcopy" ]; then
+ [ ! -f "$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" ]; then
if [ $CROSS -eq 0 ]; then
fatal_error "you need to run: cosmocc --update"
else
@@ -88,7 +93,7 @@ elif [ x"$INPUT" = x"$OUTPUT" ]; then
fatal_error "$INPUT: input and output file can't be the same"
fi
-"$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-objcopy" \
+"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
$OBJCOPYFLAGS \
"$INPUT" \
"$OUTPUT" || exit
diff --git a/bin/cosmoaddr2line b/bin/cosmoaddr2line
index 07d8bc886..85b8d85bf 100755
--- a/bin/cosmoaddr2line
+++ b/bin/cosmoaddr2line
@@ -1,15 +1,31 @@
#!/bin/sh
+COSMO=${COSMO:-/opt/cosmo}
+
set -- -apifCe "$@"
if [ -n "$ADDR2LINE" ]; then
exec "$ADDR2LINE" "$@"
fi
-COSMO=${COSMO:-/opt/cosmo}
+find_addr2line() {
+ if [ -x o/third_party/gcc/bin/$1-linux-cosmo-addr2line ]; then
+ ADDR2LINE=o/third_party/gcc/bin/$1-linux-cosmo-addr2line
+ elif [ -x o/third_party/gcc/bin/$1-linux-musl-addr2line ]; then
+ ADDR2LINE=o/third_party/gcc/bin/$1-linux-musl-addr2line
+ elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line" ]; then
+ ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line"
+ elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line" ]; then
+ ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line"
+ else
+ echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
+ exit 1
+ fi
+}
+
for ARCH in x86_64 aarch64; do
- o/third_party/gcc/bin/$ARCH-linux-musl-addr2line "$@" 2>/dev/null && exit
- "$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-addr2line" "$@" 2>/dev/null && exit
+ find_addr2line $ARCH
+ "$ADDR2LINE" "$@" 2>/dev/null && exit
done
-echo please set the ADDR2LINE environment variable >&2
+echo "error: addr2line failed" >&2
exit 1
diff --git a/bin/cosmocc b/bin/cosmocc
index eecc99756..5604cdf69 100755
--- a/bin/cosmocc
+++ b/bin/cosmocc
@@ -138,13 +138,19 @@ else
COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
fi
-CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-gcc"
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-gcc"
CRT="$COSMO/o/$MODE/libc/crt/crt.o"
LDLIBS="$COSMO/o/$MODE/cosmopolitan.a"
CPPFLAGS="$CPPFLAGS -isystem $COSMOS/include -isystem $COSMO/libc/isystem"
LDFLAGS="$LDFLAGS -L$COSMOS/lib"
if [ x"$PROG" != x"${PROG%++}" ]; then
- CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-g++"
+ CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-g++"
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS"
fi
@@ -360,7 +366,7 @@ if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then
# -> foo.com (ape)
# -> foo.com.dbg (elf)
mv -f "$OUTPUT" "$OUTPUT.dbg" || exit
- "$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-objcopy" \
+ "$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
$OBJCOPYFLAGS \
"$OUTPUT.dbg" \
"$OUTPUT" || exit
@@ -368,7 +374,7 @@ if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then
"$OUTPUT.dbg" \
"$OUTPUT" || exit
elif [ $SFLAG -eq 1 ]; then
- "$COSMO/o/third_party/gcc/bin/$ARCH-linux-musl-strip" \
+ "$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-strip" \
"$OUTPUT" || exit
fi
fi
diff --git a/bin/fatcosmoar b/bin/fatcosmoar
index f08d9a399..6d4f9698a 100755
--- a/bin/fatcosmoar
+++ b/bin/fatcosmoar
@@ -1,5 +1,4 @@
#!/bin/sh
-
PROG=${0##*/}
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
@@ -9,12 +8,18 @@ fatal_error() {
exit 1
}
-if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ar" ]; then
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" ]; then
fatal_error "you need to run: fatcosmocc --update"
fi
-AR_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ar"
-AR_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-ar"
+AR_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar"
+AR_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar"
if [ "$1" = "--version" ]; then
# note: only the underlying gnu compiler binaries are gpl
# our shell script is released with the isc license
diff --git a/bin/fatcosmocc b/bin/fatcosmocc
index e229b2609..ca7e9a9bf 100755
--- a/bin/fatcosmocc
+++ b/bin/fatcosmocc
@@ -182,6 +182,12 @@ if [ ! -f "$COSMOS/lib/libc.a" ] ||
exit 1
fi
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
FIXUPOBJ="$COSMO/o//tool/build/fixupobj.com"
TEMP_FILES=
SAVE_TEMPS=0
@@ -371,11 +377,11 @@ if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ]; then
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
fi
-CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc"
-CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc"
+CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-gcc"
+CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-gcc"
if [ x"$PROG" != x"${PROG%++}" ]; then
- CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-g++"
- CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-g++"
+ CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-g++"
+ CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-g++"
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
fi
diff --git a/bin/x86_64-unknown-cosmo-addr2line b/bin/x86_64-unknown-cosmo-addr2line
index 59bbad431..0b2b06950 100755
--- a/bin/x86_64-unknown-cosmo-addr2line
+++ b/bin/x86_64-unknown-cosmo-addr2line
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-addr2line"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-addr2line"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/bin/x86_64-unknown-cosmo-ar b/bin/x86_64-unknown-cosmo-ar
index dee1394bb..118b519aa 100755
--- a/bin/x86_64-unknown-cosmo-ar
+++ b/bin/x86_64-unknown-cosmo-ar
@@ -9,8 +9,14 @@ fatal_error() {
exit 1
}
-if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ar" ]; then
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" ]; then
fatal_error "you need to run: x86_64-unknown-cosmo-cc --update"
fi
-exec "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-ar" "$@"
+exec "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" "$@"
diff --git a/bin/x86_64-unknown-cosmo-as b/bin/x86_64-unknown-cosmo-as
index cacf0d6e9..470a711b2 100755
--- a/bin/x86_64-unknown-cosmo-as
+++ b/bin/x86_64-unknown-cosmo-as
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-as"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-as"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/bin/x86_64-unknown-cosmo-nm b/bin/x86_64-unknown-cosmo-nm
index 679370e60..b425f4a36 100755
--- a/bin/x86_64-unknown-cosmo-nm
+++ b/bin/x86_64-unknown-cosmo-nm
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-nm"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-nm"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/bin/x86_64-unknown-cosmo-objcopy b/bin/x86_64-unknown-cosmo-objcopy
index 9ec84bee4..90b764510 100755
--- a/bin/x86_64-unknown-cosmo-objcopy
+++ b/bin/x86_64-unknown-cosmo-objcopy
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objcopy"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objcopy"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/bin/x86_64-unknown-cosmo-objdump b/bin/x86_64-unknown-cosmo-objdump
index da25e9926..4c27d4881 100755
--- a/bin/x86_64-unknown-cosmo-objdump
+++ b/bin/x86_64-unknown-cosmo-objdump
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-objdump"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objdump"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/bin/x86_64-unknown-cosmo-strip b/bin/x86_64-unknown-cosmo-strip
index e9dd34ec6..34647e5d9 100755
--- a/bin/x86_64-unknown-cosmo-strip
+++ b/bin/x86_64-unknown-cosmo-strip
@@ -1,9 +1,15 @@
#!/bin/sh
-
MODE=${MODE:-$m}
COSMO=${COSMO:-/opt/cosmo}
COSMOS=${COSMOS:-/opt/cosmos}
-TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-strip"
+
+if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
+ BRAND=musl
+else
+ BRAND=cosmo
+fi
+
+TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-strip"
if [ ! -x "$TOOL" ]; then
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
diff --git a/build/bootstrap/ar.com b/build/bootstrap/ar.com
index f5bfc395b..c7ba5aadf 100755
Binary files a/build/bootstrap/ar.com and b/build/bootstrap/ar.com differ
diff --git a/build/bootstrap/cocmd.com b/build/bootstrap/cocmd.com
index d61b3d12b..021a5543b 100755
Binary files a/build/bootstrap/cocmd.com and b/build/bootstrap/cocmd.com differ
diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com
index d1eaa1a3b..023ebe3f9 100755
Binary files a/build/bootstrap/compile.com and b/build/bootstrap/compile.com differ
diff --git a/build/bootstrap/cp.com b/build/bootstrap/cp.com
index dc2c6f8d9..78848be2e 100755
Binary files a/build/bootstrap/cp.com and b/build/bootstrap/cp.com differ
diff --git a/build/bootstrap/fixupobj.com b/build/bootstrap/fixupobj.com
index fdf9f2719..5162a2bad 100755
Binary files a/build/bootstrap/fixupobj.com and b/build/bootstrap/fixupobj.com differ
diff --git a/build/bootstrap/gzip.com b/build/bootstrap/gzip.com
index 667d7369b..56bd4e409 100755
Binary files a/build/bootstrap/gzip.com and b/build/bootstrap/gzip.com differ
diff --git a/build/bootstrap/make.com b/build/bootstrap/make.com
index c9c8beb6c..347ca03d5 100755
Binary files a/build/bootstrap/make.com and b/build/bootstrap/make.com differ
diff --git a/build/bootstrap/mkdeps.com b/build/bootstrap/mkdeps.com
index 7fc162ae7..c406e1271 100755
Binary files a/build/bootstrap/mkdeps.com and b/build/bootstrap/mkdeps.com differ
diff --git a/build/bootstrap/mkdir.com b/build/bootstrap/mkdir.com
index f972be18c..5268fa76d 100755
Binary files a/build/bootstrap/mkdir.com and b/build/bootstrap/mkdir.com differ
diff --git a/build/bootstrap/objbincopy.com b/build/bootstrap/objbincopy.com
index 7b995000f..584783679 100755
Binary files a/build/bootstrap/objbincopy.com and b/build/bootstrap/objbincopy.com differ
diff --git a/build/bootstrap/package.com b/build/bootstrap/package.com
index b2cb8f00a..6fe200ea7 100755
Binary files a/build/bootstrap/package.com and b/build/bootstrap/package.com differ
diff --git a/build/bootstrap/pwd.com b/build/bootstrap/pwd.com
index e0dd91a20..6e43ae548 100755
Binary files a/build/bootstrap/pwd.com and b/build/bootstrap/pwd.com differ
diff --git a/build/bootstrap/rm.com b/build/bootstrap/rm.com
index 7d4b51a4a..2bf9c048f 100755
Binary files a/build/bootstrap/rm.com and b/build/bootstrap/rm.com differ
diff --git a/build/bootstrap/touch.com b/build/bootstrap/touch.com
index 724bc2ae7..70ea97a1c 100755
Binary files a/build/bootstrap/touch.com and b/build/bootstrap/touch.com differ
diff --git a/build/bootstrap/unbundle.com b/build/bootstrap/unbundle.com
index 0cb05dc6e..4147431cc 100755
Binary files a/build/bootstrap/unbundle.com and b/build/bootstrap/unbundle.com differ
diff --git a/build/bootstrap/zipcopy.com b/build/bootstrap/zipcopy.com
index a448c6cf8..e4c199230 100755
Binary files a/build/bootstrap/zipcopy.com and b/build/bootstrap/zipcopy.com differ
diff --git a/build/bootstrap/zipobj.com b/build/bootstrap/zipobj.com
index 9b2bbd30f..7efcc73db 100755
Binary files a/build/bootstrap/zipobj.com and b/build/bootstrap/zipobj.com differ
diff --git a/build/config.mk b/build/config.mk
index f36b6bb87..7d73d10f9 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -16,6 +16,12 @@ CONFIG_CCFLAGS += -O2 $(BACKTRACES)
CONFIG_CPPFLAGS += -DSYSDEBUG
TARGET_ARCH ?= -msse3
endif
+ifeq ($(MODE), x86_64)
+ENABLE_FTRACE = 1
+CONFIG_OFLAGS ?= -g
+CONFIG_CCFLAGS += -O2 $(BACKTRACES)
+CONFIG_CPPFLAGS += -DSYSDEBUG
+endif
ifeq ($(MODE), aarch64)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
@@ -39,8 +45,8 @@ CONFIG_CPPFLAGS += -DSYSDEBUG
endif
ifeq ($(MODE), aarch64-zero)
CONFIG_OFLAGS ?= -g
-OVERRIDE_CFLAGS += -O0
-OVERRIDE_CXXFLAGS += -O0
+OVERRIDE_CFLAGS += -O0 -fdce
+OVERRIDE_CXXFLAGS += -O0 -fdce
CONFIG_CPPFLAGS += -DSYSDEBUG
endif
@@ -166,7 +172,7 @@ ifeq ($(MODE), aarch64-dbg)
ENABLE_FTRACE = 1
CONFIG_OFLAGS ?= -g
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
-CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
+CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline -fdce
CONFIG_COPTS += -fsanitize=undefined
QUOTA ?= -C64 -L300
endif
diff --git a/build/definitions.mk b/build/definitions.mk
index f4b5341d7..751cbb5e6 100644
--- a/build/definitions.mk
+++ b/build/definitions.mk
@@ -94,17 +94,24 @@ endif
ifeq ($(PREFIX),)
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
-ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","")
-PREFIX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-
+ifeq ($(ARCH),x86_64)
+ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","")
+PREFIX = o/third_party/gcc/bin/x86_64-linux-cosmo-
else
IGNORE := $(shell build/bootstrap/unbundle.com)
PREFIX = o/third_party/gcc/bin/x86_64-linux-musl-
endif
-ifeq ($(ARCH), aarch64)
+endif # ($(ARCH),x86_64))
+ifeq ($(ARCH),aarch64)
+ifneq ("$(wildcard o/third_party/gcc/bin/aarch64-linux-cosmo-*)","")
+PREFIX = o/third_party/gcc/bin/aarch64-linux-cosmo-
+else
+IGNORE := $(shell build/bootstrap/unbundle.com)
PREFIX = o/third_party/gcc/bin/aarch64-linux-musl-
endif
-endif
-endif
+endif # ($(ARCH),aarch64)
+endif # ($(USE_SYSTEM_TOOLCHAIN),)
+endif # ($(PREFIX),)
AS = $(PREFIX)as
CC = $(PREFIX)gcc
@@ -116,7 +123,7 @@ GCC = $(PREFIX)gcc
STRIP = $(PREFIX)strip
OBJCOPY = $(PREFIX)objcopy
OBJDUMP = $(PREFIX)objdump
-ifneq ($(wildcard $(PWD)/$(PREFIX)addr2line), )
+ifneq ($(wildcard $(PWD)/$(PREFIX)addr2line),)
ADDR2LINE = $(PWD)/$(PREFIX)addr2line
else
ADDR2LINE = $(PREFIX)addr2line
diff --git a/build/objdump b/build/objdump
index 2e032aa04..103269f7b 100755
--- a/build/objdump
+++ b/build/objdump
@@ -1,6 +1,29 @@
#!/bin/sh
-if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
- exec o/third_party/gcc/bin/aarch64-linux-musl-objdump "$@"
-else
- exec o/third_party/gcc/bin/x86_64-linux-musl-objdump "$@"
+COSMO=${COSMO:-/opt/cosmo}
+
+if [ -n "$OBJDUMP" ]; then
+ exec "$OBJDUMP" "$@"
+fi
+
+find_objdump() {
+ if [ -x o/third_party/gcc/bin/$1-linux-cosmo-objdump ]; then
+ OBJDUMP=o/third_party/gcc/bin/$1-linux-cosmo-objdump
+ elif [ -x o/third_party/gcc/bin/$1-linux-musl-objdump ]; then
+ OBJDUMP=o/third_party/gcc/bin/$1-linux-musl-objdump
+ elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump" ]; then
+ OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-objdump"
+ elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump" ]; then
+ OBJDUMP="$COSMO/o/third_party/gcc/bin/$1-linux-musl-objdump"
+ else
+ echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
+ exit 1
+ fi
+}
+
+if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
+ find_objdump aarch64
+ exec "$OBJDUMP" "$@"
+else
+ find_objdump x86_64
+ exec "$OBJDUMP" "$@"
fi
diff --git a/libc/calls/assertfail.c b/libc/calls/assertfail.c
index 539998086..24782417f 100644
--- a/libc/calls/assertfail.c
+++ b/libc/calls/assertfail.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
+#include "libc/calls/struct/sigset.internal.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describebacktrace.internal.h"
@@ -28,9 +29,11 @@
*/
void __assert_fail(const char *expr, const char *file, int line) {
char ibuf[12];
+ sigset_t m = __sig_block();
FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed (",
program_invocation_short_name, " ",
DescribeBacktrace(__builtin_frame_address(0)), ")\n", NULL);
+ __sig_unblock(m);
abort();
}
diff --git a/libc/calls/blockcancel.internal.h b/libc/calls/blockcancel.internal.h
index b4d9848b8..5ca6ed3a5 100644
--- a/libc/calls/blockcancel.internal.h
+++ b/libc/calls/blockcancel.internal.h
@@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
#define COSMOPOLITAN_LIBC_CALLS_BLOCKCANCEL_H_
-#include "libc/thread/thread.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
diff --git a/libc/calls/createfileflags.c b/libc/calls/createfileflags.c
index 7d9e43f78..641564c20 100644
--- a/libc/calls/createfileflags.c
+++ b/libc/calls/createfileflags.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@@ -26,23 +27,6 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/errfuns.h"
-// code size optimization
-//
-#define _O_APPEND 0x00000400 // kNtFileAppendData
-#define _O_CREAT 0x00000040 // kNtOpenAlways
-#define _O_EXCL 0x00000080 // kNtCreateNew
-#define _O_TRUNC 0x00000200 // kNtCreateAlways
-#define _O_DIRECTORY 0x00010000 // kNtFileFlagBackupSemantics
-#define _O_UNLINK 0x04000100 // kNtFileAttributeTemporary|DeleteOnClose
-#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
-#define _O_NONBLOCK 0x00000800 // kNtFileFlagWriteThrough (not sent to win32)
-#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
-#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
-#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
-#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
-#define _O_CLOEXEC 0x00080000
-//
-
textwindows int GetNtOpenFlags(int flags, int mode, uint32_t *out_perm,
uint32_t *out_share, uint32_t *out_disp,
uint32_t *out_attr) {
diff --git a/libc/calls/createfileflags.internal.h b/libc/calls/createfileflags.internal.h
new file mode 100644
index 000000000..249c43e58
--- /dev/null
+++ b/libc/calls/createfileflags.internal.h
@@ -0,0 +1,22 @@
+#ifndef COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_
+#define COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_
+
+// code size optimization
+//
+#define _O_APPEND 0x00000400 // kNtFileAppendData
+#define _O_CREAT 0x00000040 // kNtOpenAlways
+#define _O_EXCL 0x00000080 // kNtCreateNew
+#define _O_TRUNC 0x00000200 // kNtCreateAlways
+#define _O_DIRECTORY 0x00010000 // kNtFileFlagBackupSemantics
+#define _O_UNLINK 0x04000100 // kNtFileAttributeTemporary|DeleteOnClose
+#define _O_DIRECT 0x00004000 // kNtFileFlagNoBuffering
+#define _O_NONBLOCK 0x00000800 // kNtFileFlagWriteThrough (not sent to win32)
+#define _O_RANDOM 0x80000000 // kNtFileFlagRandomAccess
+#define _O_SEQUENTIAL 0x40000000 // kNtFileFlagSequentialScan
+#define _O_COMPRESSED 0x20000000 // kNtFileAttributeCompressed
+#define _O_INDEXED 0x10000000 // !kNtFileAttributeNotContentIndexed
+#define _O_NOFOLLOW 0x00020000 // kNtFileFlagOpenReparsePoint
+#define _O_CLOEXEC 0x00080000
+//
+
+#endif /* COSMOPOLITAN_LIBC_CALLS_CREATEFILEFLAGS_INTERNAL_H_ */
diff --git a/libc/calls/dup-nt.c b/libc/calls/dup-nt.c
index f106e6fb3..f093326f3 100644
--- a/libc/calls/dup-nt.c
+++ b/libc/calls/dup-nt.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h"
@@ -65,10 +66,10 @@ static textwindows int sys_dup_nt_impl(int oldfd, int newfd, int flags,
kNtDuplicateSameAccess)) {
g_fds.p[newfd] = g_fds.p[oldfd];
g_fds.p[newfd].handle = handle;
- if (flags & O_CLOEXEC) {
- g_fds.p[newfd].flags |= O_CLOEXEC;
+ if (flags & _O_CLOEXEC) {
+ g_fds.p[newfd].flags |= _O_CLOEXEC;
} else {
- g_fds.p[newfd].flags &= ~O_CLOEXEC;
+ g_fds.p[newfd].flags &= ~_O_CLOEXEC;
}
rc = newfd;
} else {
diff --git a/libc/calls/fadvise-nt.c b/libc/calls/fadvise-nt.c
index 86dec5dde..c0a31468e 100644
--- a/libc/calls/fadvise-nt.c
+++ b/libc/calls/fadvise-nt.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
@@ -41,17 +42,17 @@ static textwindows int sys_fadvise_nt_impl(int fd, uint64_t offset,
h1 = g_fds.p[fd].handle;
mode = g_fds.p[fd].mode;
flags = g_fds.p[fd].flags;
- flags &= ~(O_SEQUENTIAL | O_RANDOM);
+ flags &= ~(_O_SEQUENTIAL | _O_RANDOM);
switch (advice) {
case MADV_NORMAL:
break;
case MADV_RANDOM:
- flags |= O_RANDOM;
+ flags |= _O_RANDOM;
break;
case MADV_WILLNEED:
case MADV_SEQUENTIAL:
- flags |= O_SEQUENTIAL;
+ flags |= _O_SEQUENTIAL;
break;
default:
return einval();
diff --git a/libc/calls/fchmod-nt.c b/libc/calls/fchmod-nt.c
new file mode 100644
index 000000000..99b66d8de
--- /dev/null
+++ b/libc/calls/fchmod-nt.c
@@ -0,0 +1,57 @@
+/*-*- 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 2023 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/internal.h"
+#include "libc/calls/struct/fd.internal.h"
+#include "libc/calls/syscall-nt.internal.h"
+#include "libc/calls/syscall_support-nt.internal.h"
+#include "libc/nt/enum/fileflagandattributes.h"
+#include "libc/nt/enum/fileinfobyhandleclass.h"
+#include "libc/nt/files.h"
+#include "libc/nt/struct/filebasicinfo.h"
+#include "libc/sysv/errfuns.h"
+
+textwindows int sys_fchmod_nt(int fd, uint32_t mode) {
+
+ // validate file descriptor
+ if (fd + 0u >= g_fds.n) return ebadf();
+ if (g_fds.p[fd].kind == kFdEmpty) return ebadf();
+
+ // get current information
+ struct NtFileBasicInfo fbi;
+ if (!GetFileInformationByHandleEx(g_fds.p[fd].handle, kNtFileBasicInfo, &fbi,
+ sizeof(fbi))) {
+ return __winerr();
+ }
+
+ // change attributes
+ if (mode & 0222) {
+ fbi.FileAttributes &= ~kNtFileAttributeReadonly;
+ } else {
+ fbi.FileAttributes |= kNtFileAttributeReadonly;
+ }
+
+ // set new attributes
+ if (!SetFileInformationByHandle(g_fds.p[fd].handle, kNtFileBasicInfo, &fbi,
+ sizeof(fbi))) {
+ return __winerr();
+ }
+
+ // all good
+ return 0;
+}
diff --git a/libc/calls/fchmod.c b/libc/calls/fchmod.c
index 092a8e57c..8be3e8f3a 100644
--- a/libc/calls/fchmod.c
+++ b/libc/calls/fchmod.c
@@ -17,18 +17,32 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
+#include "libc/calls/internal.h"
+#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
+#include "libc/intrin/strace.internal.h"
#include "libc/sysv/errfuns.h"
/**
* Changes file permissions via open()'d file descriptor.
*
* @param mode contains octal flags (base 8)
+ * @raise EROFS if `fd` is a `/zip/...` file
* @asyncsignalsafe
* @see chmod()
*/
int fchmod(int fd, uint32_t mode) {
- // TODO(jart): Windows
- return sys_fchmod(fd, mode);
+ int rc;
+ if (__isfdkind(fd, kFdZip)) {
+ rc = erofs();
+ } else if (IsLinux() || IsXnu() || IsFreebsd() || IsOpenbsd() || IsNetbsd()) {
+ rc = sys_fchmod(fd, mode);
+ } else if (IsWindows()) {
+ rc = sys_fchmod_nt(fd, mode);
+ } else {
+ rc = enosys();
+ }
+ STRACE("fchmod(%d, %#o) → %d% m", fd, mode, rc);
+ return rc;
}
diff --git a/libc/calls/fcntl-nt.c b/libc/calls/fcntl-nt.c
index 51e44d640..e2a3fd508 100644
--- a/libc/calls/fcntl-nt.c
+++ b/libc/calls/fcntl-nt.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/flock.h"
@@ -318,7 +319,7 @@ static textwindows int sys_fcntl_nt_lock(struct Fd *f, int fd, int cmd,
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);
+ 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) {
@@ -329,21 +330,21 @@ textwindows int sys_fcntl_nt(int fd, int cmd, uintptr_t arg) {
__isfdkind(fd, kFdConsole) || //
__isfdkind(fd, kFdDevNull)) {
if (cmd == F_GETFL) {
- rc = g_fds.p[fd].flags & (O_ACCMODE | O_APPEND | O_DIRECT | O_NONBLOCK |
- O_RANDOM | O_SEQUENTIAL);
+ rc = g_fds.p[fd].flags & (O_ACCMODE | _O_APPEND | _O_DIRECT |
+ _O_NONBLOCK | _O_RANDOM | _O_SEQUENTIAL);
} else if (cmd == F_SETFL) {
rc = sys_fcntl_nt_setfl(fd, arg);
} else if (cmd == F_GETFD) {
- if (g_fds.p[fd].flags & O_CLOEXEC) {
+ if (g_fds.p[fd].flags & _O_CLOEXEC) {
rc = FD_CLOEXEC;
} else {
rc = 0;
}
} else if (cmd == F_SETFD) {
if (arg & FD_CLOEXEC) {
- g_fds.p[fd].flags |= O_CLOEXEC;
+ g_fds.p[fd].flags |= _O_CLOEXEC;
} else {
- g_fds.p[fd].flags &= ~O_CLOEXEC;
+ g_fds.p[fd].flags &= ~_O_CLOEXEC;
}
rc = 0;
} else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK) {
diff --git a/libc/calls/fdatasync-nt.c b/libc/calls/fdatasync-nt.c
index 6c83d398e..4646b7b63 100644
--- a/libc/calls/fdatasync-nt.c
+++ b/libc/calls/fdatasync-nt.c
@@ -36,9 +36,8 @@ textwindows int sys_fdatasync_nt(int fd, bool fake) {
// kNtGenericWrite access, and MSDN doesn't document it.
return 0;
}
- if (_check_cancel() == -1) return -1;
- if (_check_signal(false) == -1) return -1;
if (fake) return 0;
+ if (_check_signal(false) == -1) return -1;
return FlushFileBuffers(g_fds.p[fd].handle) ? 0 : __winerr();
}
diff --git a/libc/calls/fstat-nt.c b/libc/calls/fstat-nt.c
index b71f17ac1..69f0e5cb4 100644
--- a/libc/calls/fstat-nt.c
+++ b/libc/calls/fstat-nt.c
@@ -107,11 +107,12 @@ textwindows int sys_fstat_nt(int fd, struct stat *st) {
case kFdSocket:
return sys_fstat_nt_socket(g_fds.p[fd].kind, st);
default:
- return sys_fstat_nt_handle(g_fds.p[fd].handle, st);
+ return sys_fstat_nt_handle(g_fds.p[fd].handle, 0, st);
}
}
-textwindows int sys_fstat_nt_handle(int64_t handle, struct stat *out_st) {
+textwindows int sys_fstat_nt_handle(int64_t handle, const char16_t *path,
+ struct stat *out_st) {
struct stat st = {0};
// Always set st_blksize to avoid divide by zero issues.
@@ -143,7 +144,7 @@ textwindows int sys_fstat_nt_handle(int64_t handle, struct stat *out_st) {
}
st.st_mode = 0444 & ~umask;
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
- IsWindowsExecutable(handle)) {
+ IsWindowsExecutable(handle, path)) {
st.st_mode |= 0111 & ~umask;
}
st.st_flags = wst.dwFileAttributes;
diff --git a/libc/calls/fstatat-nt.c b/libc/calls/fstatat-nt.c
index 720110ae7..9ff276c49 100644
--- a/libc/calls/fstatat-nt.c
+++ b/libc/calls/fstatat-nt.c
@@ -74,10 +74,11 @@ TryAgain:
((flags & AT_SYMLINK_NOFOLLOW) ? kNtFileFlagOpenReparsePoint
: 0),
0)) != -1) {
- rc = st ? sys_fstat_nt_handle(fh, st) : 0;
+ rc = st ? sys_fstat_nt_handle(fh, path16, st) : 0;
CloseHandle(fh);
} else if (dwDesiredAccess == kNtFileGenericRead &&
- GetLastError() == kNtErrorSharingViolation) {
+ (GetLastError() == kNtErrorAccessDenied ||
+ GetLastError() == kNtErrorSharingViolation)) {
dwDesiredAccess = kNtFileReadAttributes;
errno = e;
goto TryAgain;
diff --git a/libc/calls/getrandom-metal.c b/libc/calls/getrandom-metal.c
new file mode 100644
index 000000000..74be74be5
--- /dev/null
+++ b/libc/calls/getrandom-metal.c
@@ -0,0 +1,94 @@
+/*-*- 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 2023 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/intrin/asmflag.h"
+#include "libc/nexgen32e/x86feature.h"
+#include "libc/sysv/consts/grnd.h"
+#include "libc/sysv/errfuns.h"
+#ifdef __x86_64__
+
+static bool GetRandomRdseed(uint64_t *out) {
+ int i;
+ char cf;
+ uint64_t x;
+ for (i = 0; i < 10; ++i) {
+ asm volatile(CFLAG_ASM("rdseed\t%1")
+ : CFLAG_CONSTRAINT(cf), "=r"(x)
+ : /* no inputs */
+ : "cc");
+ if (cf) {
+ *out = x;
+ return true;
+ }
+ asm volatile("pause");
+ }
+ return false;
+}
+
+static bool GetRandomRdrand(uint64_t *out) {
+ int i;
+ char cf;
+ uint64_t x;
+ for (i = 0; i < 10; ++i) {
+ asm volatile(CFLAG_ASM("rdrand\t%1")
+ : CFLAG_CONSTRAINT(cf), "=r"(x)
+ : /* no inputs */
+ : "cc");
+ if (cf) {
+ *out = x;
+ return true;
+ }
+ asm volatile("pause");
+ }
+ return false;
+}
+
+static ssize_t GetRandomCpu(char *p, size_t n, int f, bool impl(uint64_t *)) {
+ uint64_t x;
+ size_t i, j;
+ for (i = 0; i < n; i += j) {
+ TryAgain:
+ if (!impl(&x)) {
+ if (f || i >= 256) break;
+ goto TryAgain;
+ }
+ for (j = 0; j < 8 && i + j < n; ++j) {
+ p[i + j] = x;
+ x >>= 8;
+ }
+ }
+ return n;
+}
+
+ssize_t sys_getrandom_metal(char *p, size_t n, int f) {
+ if (f & GRND_RANDOM) {
+ if (X86_HAVE(RDSEED)) {
+ return GetRandomCpu(p, n, f, GetRandomRdseed);
+ } else {
+ return enosys();
+ }
+ } else {
+ if (X86_HAVE(RDRND)) {
+ return GetRandomCpu(p, n, f, GetRandomRdrand);
+ } else {
+ return enosys();
+ }
+ }
+}
+
+#endif /* __x86_64__ */
diff --git a/libc/calls/getrandom.c b/libc/calls/getrandom.c
index b862ca2fa..3ced34951 100644
--- a/libc/calls/getrandom.c
+++ b/libc/calls/getrandom.c
@@ -55,78 +55,10 @@
__static_yoink("rdrand_init");
int sys_getentropy(void *, size_t) asm("sys_getrandom");
+ssize_t sys_getrandom_metal(char *, size_t, int);
static bool have_getrandom;
-static bool GetRandomRdseed(uint64_t *out) {
- int i;
- char cf;
- uint64_t x;
- for (i = 0; i < 10; ++i) {
- asm volatile(CFLAG_ASM("rdseed\t%1")
- : CFLAG_CONSTRAINT(cf), "=r"(x)
- : /* no inputs */
- : "cc");
- if (cf) {
- *out = x;
- return true;
- }
- asm volatile("pause");
- }
- return false;
-}
-
-static bool GetRandomRdrand(uint64_t *out) {
- int i;
- char cf;
- uint64_t x;
- for (i = 0; i < 10; ++i) {
- asm volatile(CFLAG_ASM("rdrand\t%1")
- : CFLAG_CONSTRAINT(cf), "=r"(x)
- : /* no inputs */
- : "cc");
- if (cf) {
- *out = x;
- return true;
- }
- asm volatile("pause");
- }
- return false;
-}
-
-static ssize_t GetRandomCpu(char *p, size_t n, int f, bool impl(uint64_t *)) {
- uint64_t x;
- size_t i, j;
- for (i = 0; i < n; i += j) {
- TryAgain:
- if (!impl(&x)) {
- if (f || i >= 256) break;
- goto TryAgain;
- }
- for (j = 0; j < 8 && i + j < n; ++j) {
- p[i + j] = x;
- x >>= 8;
- }
- }
- return n;
-}
-
-static ssize_t GetRandomMetal(char *p, size_t n, int f) {
- if (f & GRND_RANDOM) {
- if (X86_HAVE(RDSEED)) {
- return GetRandomCpu(p, n, f, GetRandomRdseed);
- } else {
- return enosys();
- }
- } else {
- if (X86_HAVE(RDRND)) {
- return GetRandomCpu(p, n, f, GetRandomRdrand);
- } else {
- return enosys();
- }
- }
-}
-
static void GetRandomEntropy(char *p, size_t n) {
unassert(n <= 256);
if (sys_getentropy(p, n)) notpossible;
@@ -181,8 +113,10 @@ ssize_t __getrandom(void *p, size_t n, unsigned f) {
}
} else if (IsFreebsd() || IsNetbsd()) {
rc = GetRandomBsd(p, n, GetRandomArnd);
+#ifdef __x86_64__
} else if (IsMetal()) {
- rc = GetRandomMetal(p, n, f);
+ rc = sys_getrandom_metal(p, n, f);
+#endif
} else {
BEGIN_CANCELATION_POINT;
rc = GetDevUrandom(p, n);
diff --git a/libc/calls/internal.h b/libc/calls/internal.h
index 94258beb1..f2fa4d731 100644
--- a/libc/calls/internal.h
+++ b/libc/calls/internal.h
@@ -24,11 +24,11 @@ int __ensurefds(int);
uint32_t sys_getuid_nt(void);
int __ensurefds_unlocked(int);
void __printfds(struct Fd *, size_t);
-int IsWindowsExecutable(int64_t);
int CountConsoleInputBytes(void);
int FlushConsoleInputBytes(void);
int64_t GetConsoleInputHandle(void);
int64_t GetConsoleOutputHandle(void);
+int IsWindowsExecutable(int64_t, const char16_t *);
void InterceptTerminalCommands(const char *, size_t);
forceinline int64_t __getfdhandleactual(int fd) {
diff --git a/libc/calls/interrupts-nt.c b/libc/calls/interrupts-nt.c
index 3af045bff..eb4d27e96 100644
--- a/libc/calls/interrupts-nt.c
+++ b/libc/calls/interrupts-nt.c
@@ -36,8 +36,10 @@ textwindows int _check_cancel(void) {
textwindows int _check_signal(bool restartable) {
int status;
+ if (_check_cancel() == -1) return -1;
if (!_weaken(__sig_check)) return 0;
if (!(status = _weaken(__sig_check)())) return 0;
+ if (_check_cancel() == -1) return -1;
if (status == 2 && restartable) return 0;
return eintr();
}
diff --git a/libc/calls/ioctl.c b/libc/calls/ioctl.c
index aca879bdb..819416fec 100644
--- a/libc/calls/ioctl.c
+++ b/libc/calls/ioctl.c
@@ -115,6 +115,7 @@ static int ioctl_fionread(int fd, uint32_t *arg) {
*arg = avail;
return 0;
} else if (GetLastError() == kNtErrorBrokenPipe) {
+ *arg = 0; // win32 can give epipe on reader end
return 0;
} else {
return __winerr();
diff --git a/libc/calls/ntaccesscheck.c b/libc/calls/ntaccesscheck.c
index e407a9545..895d4a357 100644
--- a/libc/calls/ntaccesscheck.c
+++ b/libc/calls/ntaccesscheck.c
@@ -108,7 +108,7 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
0)) != -1) {
unassert(GetFileInformationByHandle(hFile, &wst));
if ((wst.dwFileAttributes & kNtFileAttributeDirectory) ||
- IsWindowsExecutable(hFile)) {
+ IsWindowsExecutable(hFile, pathname)) {
rc = 0;
} else {
rc = eacces();
diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c
index 570ff6d59..c9420f1a8 100644
--- a/libc/calls/open-nt.c
+++ b/libc/calls/open-nt.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/sigset.internal.h"
@@ -56,31 +57,31 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
// implement no follow flag
// you can't open symlinks; use readlink
// this flag only applies to the final path component
- // if O_NOFOLLOW_ANY is passed (-1 on NT) it'll be rejected later
+ // if _O_NOFOLLOW_ANY is passed (-1 on NT) it'll be rejected later
uint32_t fattr = GetFileAttributes(path16);
- if (flags & O_NOFOLLOW) {
+ if (flags & _O_NOFOLLOW) {
if (fattr != -1u && (fattr & kNtFileAttributeReparsePoint)) {
return eloop();
}
- flags &= ~O_NOFOLLOW; // don't actually pass this to win32
+ flags &= ~_O_NOFOLLOW; // don't actually pass this to win32
}
// handle some obvious cases while we have the attributes
// we should ideally resolve symlinks ourself before doing this
if (fattr != -1u) {
if (fattr & kNtFileAttributeDirectory) {
- if ((flags & O_ACCMODE) != O_RDONLY || (flags & O_CREAT)) {
+ if ((flags & O_ACCMODE) != O_RDONLY || (flags & _O_CREAT)) {
// tried to open directory for writing. note that our
- // undocumented O_TMPFILE support on windows requires that a
+ // undocumented _O_TMPFILE support on windows requires that a
// filename be passed, rather than a directory like linux.
return eisdir();
}
// on posix, the o_directory flag is an advisory safeguard that
// isn't required. on windows, it's mandatory for opening a dir
- flags |= O_DIRECTORY;
+ flags |= _O_DIRECTORY;
} else if (!(fattr & kNtFileAttributeReparsePoint)) {
// we know for certain file isn't a directory
- if (flags & O_DIRECTORY) {
+ if (flags & _O_DIRECTORY) {
return enotdir();
}
}
@@ -186,7 +187,7 @@ textwindows int sys_open_nt(int dirfd, const char *file, uint32_t flags,
ssize_t rc;
BLOCK_SIGNALS;
__fds_lock();
- if (!(flags & O_CREAT)) mode = 0;
+ if (!(flags & _O_CREAT)) mode = 0;
if ((rc = fd = __reservefd_unlocked(-1)) != -1) {
if (startswith(file, "/dev/")) {
if (!strcmp(file + 5, "tty")) {
diff --git a/libc/calls/park.c b/libc/calls/park.c
index 119e29854..ee6ac3cf0 100644
--- a/libc/calls/park.c
+++ b/libc/calls/park.c
@@ -20,6 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.internal.h"
+#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/nt/enum/wait.h"
@@ -45,11 +46,13 @@ static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
pthread_cleanup_push((void *)CloseHandle, (void *)sem);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
om = __sig_beginwait(waitmask);
- if ((rc = _check_cancel()) != -1 && (rc = _check_signal(restartable)) != -1) {
- unassert((wi = WaitForSingleObject(sem, msdelay)) != -1u);
- if (restartable && !(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
- rc |= _check_signal(restartable);
- if (rc == -1 && errno == EINTR) _check_cancel();
+ if ((rc = _check_signal(restartable)) != -1) {
+ if ((wi = WaitForSingleObject(sem, msdelay)) != -1u) {
+ if (restartable && !(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
+ rc |= _check_signal(restartable);
+ } else {
+ rc = __winerr();
+ }
}
__sig_finishwait(om);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
diff --git a/libc/calls/read-nt.c b/libc/calls/read-nt.c
index 7ce32aaf0..72334878f 100644
--- a/libc/calls/read-nt.c
+++ b/libc/calls/read-nt.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/assert.h"
#include "libc/atomic.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/state.internal.h"
@@ -729,7 +730,7 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
ms = __ttyconf.vtime * 100;
}
}
- if (f->flags & O_NONBLOCK) {
+ if (f->flags & _O_NONBLOCK) {
return eagain(); // standard unix non-blocking
}
pt = _pthread_self();
@@ -738,12 +739,14 @@ static textwindows int WaitForConsole(struct Fd *f, sigset_t waitmask) {
pthread_cleanup_push((void *)CloseHandle, (void *)sem);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
m = __sig_beginwait(waitmask);
- if ((rc = _check_cancel()) != -1 && (rc = _check_signal(true)) != -1) {
+ if ((rc = _check_signal(true)) != -1) {
int64_t hands[2] = {sem, __keystroke.cin};
- unassert(WaitForMultipleObjects(2, hands, 0, ms) != -1u);
- if (~pt->pt_flags & PT_RESTARTABLE) rc = eintr();
- rc |= _check_signal(true);
- if (rc == -1 && errno == EINTR) _check_cancel();
+ if (WaitForMultipleObjects(2, hands, 0, ms) != -1u) {
+ if (!(pt->pt_flags & PT_RESTARTABLE)) rc = eintr();
+ rc |= _check_signal(true);
+ } else {
+ rc = __winerr();
+ }
}
__sig_finishwait(m);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
diff --git a/libc/calls/readwrite-nt.c b/libc/calls/readwrite-nt.c
index 06ba2b37b..040765899 100644
--- a/libc/calls/readwrite-nt.c
+++ b/libc/calls/readwrite-nt.c
@@ -17,6 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/fd.internal.h"
@@ -140,15 +141,16 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
pt->pt_flags |= PT_RESTARTABLE;
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_IO, memory_order_release);
m = __sig_beginwait(waitmask);
- if (f->flags & O_NONBLOCK) {
+ if (f->flags & _O_NONBLOCK) {
CancelIoEx(handle, &overlap);
eagained = true;
- } else if (_check_cancel()) {
- CancelIoEx(handle, &overlap);
- canceled = true;
} else if (_check_signal(true)) {
CancelIoEx(handle, &overlap);
- eintered = true;
+ if (errno == ECANCELED) {
+ canceled = true;
+ } else {
+ eintered = true;
+ }
} else {
WaitForSingleObject(overlap.hEvent, -1u);
}
@@ -197,7 +199,7 @@ sys_readwrite_nt(int fd, void *data, size_t size, ssize_t offset,
// it's also fine to do nothing here; punt to next cancelation point
if (GetLastError() == kNtErrorOperationAborted) {
if (_check_cancel() == -1) return ecanceled();
- if (!eintered && _check_signal(false)) return eintr();
+ if (!eintered && _check_signal(false)) return -1;
}
// if we chose to process a pending signal earlier then we preserve
diff --git a/libc/calls/setfl.c b/libc/calls/setfl.c
index e1fb8841a..56bbf00ed 100644
--- a/libc/calls/setfl.c
+++ b/libc/calls/setfl.c
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/createfileflags.internal.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
@@ -36,8 +37,9 @@ textwindows int sys_fcntl_nt_setfl(int fd, unsigned flags) {
// - O_DIRECT works but haven't tested
//
// the other bits are ignored.
- unsigned allowed = O_APPEND | O_SEQUENTIAL | O_RANDOM | O_DIRECT | O_NONBLOCK;
- unsigned needreo = O_APPEND | O_SEQUENTIAL | O_RANDOM | O_DIRECT;
+ unsigned allowed =
+ _O_APPEND | _O_SEQUENTIAL | _O_RANDOM | _O_DIRECT | _O_NONBLOCK;
+ unsigned needreo = _O_APPEND | _O_SEQUENTIAL | _O_RANDOM | _O_DIRECT;
unsigned newflag = (g_fds.p[fd].flags & ~allowed) | (flags & allowed);
if (g_fds.p[fd].kind == kFdFile &&
diff --git a/libc/calls/sig.c b/libc/calls/sig.c
index 1a6b8d996..bbb5b8f65 100644
--- a/libc/calls/sig.c
+++ b/libc/calls/sig.c
@@ -33,9 +33,7 @@
#include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bsf.h"
-#include "libc/intrin/bsr.h"
#include "libc/intrin/describebacktrace.internal.h"
-#include "libc/intrin/kprintf.h"
#include "libc/intrin/popcnt.h"
#include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h"
@@ -105,7 +103,7 @@ static textwindows int __sig_getter(struct CosmoTib *tib, atomic_ulong *sigs) {
pending = atomic_load_explicit(sigs, memory_order_acquire);
masked = atomic_load_explicit(&tib->tib_sigmask, memory_order_acquire);
if ((deliverable = pending & ~masked)) {
- sig = _bsf(deliverable) + 1;
+ sig = _bsfl(deliverable) + 1;
bit = 1ull << (sig - 1);
if (atomic_fetch_and_explicit(sigs, ~bit, memory_order_acq_rel) & bit) {
return sig;
@@ -263,7 +261,7 @@ textwindows void __sig_cancel(struct PosixThread *pt, int sig, unsigned flags) {
WakeByAddressSingle(blocker);
}
-// the user's signal handler callback is composed with this trampoline
+// the user's signal handler callback is wrapped with this trampoline
static textwindows wontreturn void __sig_tramp(struct SignalFrame *sf) {
int sig = sf->si.si_signo;
struct CosmoTib *tib = __get_tls();
diff --git a/libc/calls/struct/stat.internal.h b/libc/calls/struct/stat.internal.h
index 4e4fdcbfa..2d5f51dfb 100644
--- a/libc/calls/struct/stat.internal.h
+++ b/libc/calls/struct/stat.internal.h
@@ -9,7 +9,7 @@ int sys_fstat(int, struct stat *);
int sys_fstatat(int, const char *, struct stat *, int);
int sys_fstat_nt(int, struct stat *);
int sys_fstat_nt_special(int, struct stat *);
-int sys_fstat_nt_handle(int64_t, struct stat *);
+int sys_fstat_nt_handle(int64_t, const char16_t *, struct stat *);
int sys_fstatat_nt(int, const char *, struct stat *, int);
int sys_lstat_nt(const char *, struct stat *);
int sys_fstat_metal(int, struct stat *);
diff --git a/libc/calls/struct/utsname.h b/libc/calls/struct/utsname.h
index f98f07b3d..07c055f09 100644
--- a/libc/calls/struct/utsname.h
+++ b/libc/calls/struct/utsname.h
@@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_UTSNAME_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_UTSNAME_H_
-#define SYS_NMLN 321
+#define SYS_NMLN 150
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
diff --git a/libc/calls/syscall-nt.internal.h b/libc/calls/syscall-nt.internal.h
index 887c42099..4e5a8994c 100644
--- a/libc/calls/syscall-nt.internal.h
+++ b/libc/calls/syscall-nt.internal.h
@@ -12,6 +12,7 @@ int sys_execve_nt(const char *, char *const[], char *const[]);
int sys_faccessat_nt(int, const char *, int, uint32_t);
int sys_fadvise_nt(int, uint64_t, uint64_t, int);
int sys_fchdir_nt(int);
+int sys_fchmod_nt(int, uint32_t);
int sys_fchmodat_nt(int, const char *, uint32_t, int);
int sys_fcntl_nt(int, int, uintptr_t);
int sys_fdatasync_nt(int, bool);
diff --git a/libc/calls/ttyname_r.c b/libc/calls/ttyname_r.c
index a5617a259..be049136c 100644
--- a/libc/calls/ttyname_r.c
+++ b/libc/calls/ttyname_r.c
@@ -91,7 +91,12 @@ errno_t ttyname_r(int fd, char *buf, size_t size) {
} else if (IsWindows()) {
res = sys_ttyname_nt(fd, buf, size);
} else {
- res = ENOSYS;
+ // TODO(jart): Use that fstat(dev/ino) + readdir(/dev/) trick.
+ if (strlcpy(buf, "/dev/tty", size) < size) {
+ res = 0;
+ } else {
+ res = ERANGE;
+ }
}
errno = e;
STRACE("ttyname_r(%d, %#.*hhs) → %s", fd, (int)size, buf,
diff --git a/libc/calls/winexec.c b/libc/calls/winexec.c
index af14e2b9f..c8c96cb7d 100644
--- a/libc/calls/winexec.c
+++ b/libc/calls/winexec.c
@@ -18,14 +18,57 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.internal.h"
+#include "libc/intrin/bits.h"
#include "libc/nt/errors.h"
#include "libc/nt/events.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/overlapped.h"
+#include "libc/str/str.h"
+#include "libc/str/tab.internal.h"
+#include "third_party/linenoise/linenoise.h"
+
+#define EXT(s) READ32LE(s "\0\0")
+
+static bool IsGraph(wint_t c) {
+ return 0x21 <= c && c <= 0x7E;
+}
+
+static uint32_t GetFileExtension(const char16_t *s) {
+ uint32_t w;
+ size_t i, n;
+ n = s ? strlen16(s) : 0;
+ for (i = w = 0; n--;) {
+ wint_t c = s[n];
+ if (!IsGraph(c)) return 0;
+ if (c == '.') break;
+ if (++i > 4) return 0;
+ w <<= 8;
+ w |= kToLower[c];
+ }
+ return w;
+}
// checks if file should be considered an executable on windows
-textwindows int IsWindowsExecutable(int64_t handle) {
+textwindows int IsWindowsExecutable(int64_t handle, const char16_t *path) {
+
+ // fast path known file extensions
+ // shaves away 100ms of gnu make latency in cosmo monorepo
+ uint32_t ext;
+ if (!IsTiny() && (ext = GetFileExtension(path))) {
+ if (ext == EXT("c") || // c code
+ ext == EXT("cc") || // c++ code
+ ext == EXT("h") || // c/c++ header
+ ext == EXT("s") || // assembly code
+ ext == EXT("o")) { // object file
+ return false;
+ }
+ if (ext == EXT("com") || // mz executable
+ ext == EXT("exe") || // mz executable
+ ext == EXT("sh")) { // bourne shells
+ return true;
+ }
+ }
// read first two bytes of file
// access() and stat() aren't cancelation points
diff --git a/libc/integral/c.inc b/libc/integral/c.inc
index c4da8a4c5..99bdc1d2d 100644
--- a/libc/integral/c.inc
+++ b/libc/integral/c.inc
@@ -146,7 +146,6 @@ typedef struct {
} axdx_t;
#endif
-
#ifndef __chibicc__
#define va_list __builtin_va_list
#define va_arg(ap, type) __builtin_va_arg(ap, type)
@@ -620,12 +619,6 @@ void abort(void) wontreturn;
do { \
} while (0)
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-#define _Vector_size(k) __attribute__((__vector_size__(k)))
-#else
-#define _Vector_size(k) [k]
-#endif
-
#ifndef __STRICT_ANSI__
#define textstartup _Section(".text.startup")
#define textexit _Section(".text.exit")
diff --git a/libc/intrin/createfile.c b/libc/intrin/createfile.c
index 7a0db6195..183477e45 100644
--- a/libc/intrin/createfile.c
+++ b/libc/intrin/createfile.c
@@ -48,10 +48,25 @@ CreateFile(const char16_t *lpFileName, //
int64_t opt_hTemplateFile) {
int64_t hHandle;
uint32_t micros = 1;
+ char buf_accessflags[512];
+ (void)buf_accessflags;
+ char buf_shareflags[64];
+ (void)buf_shareflags;
+ char buf_secattr[32];
+ (void)buf_secattr;
+ char buf_flagattr[256];
+ (void)buf_flagattr;
TryAgain:
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
opt_lpSecurity, dwCreationDisposition,
dwFlagsAndAttributes, opt_hTemplateFile);
+ NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → {%ld, %d}", lpFileName,
+ (DescribeNtFileAccessFlags)(buf_accessflags, dwDesiredAccess),
+ (DescribeNtFileShareFlags)(buf_shareflags, dwShareMode),
+ (DescribeNtSecurityAttributes)(buf_secattr, opt_lpSecurity),
+ DescribeNtCreationDisposition(dwCreationDisposition),
+ (DescribeNtFileFlagAttr)(buf_flagattr, dwFlagsAndAttributes),
+ opt_hTemplateFile, hHandle, __imp_GetLastError());
if (hHandle == -1) {
switch (__imp_GetLastError()) {
case kNtErrorPipeBusy:
@@ -77,12 +92,5 @@ TryAgain:
}
__winerr();
}
- NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
- DescribeNtFileAccessFlags(dwDesiredAccess),
- DescribeNtFileShareFlags(dwShareMode),
- DescribeNtSecurityAttributes(opt_lpSecurity),
- DescribeNtCreationDisposition(dwCreationDisposition),
- DescribeNtFileFlagAttr(dwFlagsAndAttributes), opt_hTemplateFile,
- hHandle);
return hHandle;
}
diff --git a/libc/intrin/createthread.c b/libc/intrin/createthread.c
index d79cfe989..aa660e9b9 100644
--- a/libc/intrin/createthread.c
+++ b/libc/intrin/createthread.c
@@ -19,10 +19,12 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
+#include "libc/nt/runtime.h"
#include "libc/nt/struct/securityattributes.h"
#include "libc/nt/thread.h"
__msabi extern typeof(CreateThread) *const __imp_CreateThread;
+__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Opens file on the New Technology.
@@ -41,9 +43,10 @@ CreateThread(const struct NtSecurityAttributes *lpThreadAttributes,
int64_t hHandle;
hHandle = __imp_CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
lpParameter, dwCreationFlags, opt_lpThreadId);
- NTTRACE("CreateThread(%s, %'zu, %t, %p, %s, %p) → %ld% m",
+ NTTRACE("CreateThread(%s, %'zu, %t, %p, %s, %p) → {%ld, %d}",
DescribeNtSecurityAttributes(lpThreadAttributes), dwStackSize,
lpStartAddress, lpParameter,
- DescribeThreadCreateFlags(dwCreationFlags), opt_lpThreadId, hHandle);
+ DescribeThreadCreateFlags(dwCreationFlags), opt_lpThreadId, hHandle,
+ __imp_GetLastError());
return hHandle;
}
diff --git a/libc/intrin/flushfilebuffers.c b/libc/intrin/flushfilebuffers.c
index e96ef39bd..21f437909 100644
--- a/libc/intrin/flushfilebuffers.c
+++ b/libc/intrin/flushfilebuffers.c
@@ -19,8 +19,10 @@
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/files.h"
+#include "libc/nt/runtime.h"
__msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
+__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Flushes buffers of specified file to disk.
@@ -36,6 +38,7 @@ __msabi extern typeof(FlushFileBuffers) *const __imp_FlushFileBuffers;
textwindows bool32 FlushFileBuffers(int64_t hFile) {
bool32 ok;
ok = __imp_FlushFileBuffers(hFile);
- NTTRACE("FlushFileBuffers(%ld) → %hhhd% m", hFile, ok);
+ NTTRACE("FlushFileBuffers(%ld) → {%hhhd, %d}", hFile, ok,
+ __imp_GetLastError());
return ok;
}
diff --git a/libc/intrin/isdebuggerpresent.c b/libc/intrin/isdebuggerpresent.c
index c514d7dfa..7ee193002 100644
--- a/libc/intrin/isdebuggerpresent.c
+++ b/libc/intrin/isdebuggerpresent.c
@@ -33,7 +33,11 @@
#define kPid "TracerPid:\t"
static textwindows bool IsBeingDebugged(void) {
+#ifdef __x86_64__
return !!NtGetPeb()->BeingDebugged;
+#else
+ return false;
+#endif
}
/**
diff --git a/libc/intrin/macros.h b/libc/intrin/macros.h
index 44e9e668e..050b203ba 100644
--- a/libc/intrin/macros.h
+++ b/libc/intrin/macros.h
@@ -9,7 +9,8 @@
#if defined(__x86_64__) && !defined(__STRICT_ANSI__)
-typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias;
+typedef char __intrin_xmm_t
+ __attribute__((__vector_size__(16), __aligned__(16), __may_alias__));
#define INTRIN_SSEVEX_X_X_X_(PURE, ISA, OP, FLAGS, A, B, C) \
do { \
diff --git a/libc/intrin/reopenfile.c b/libc/intrin/reopenfile.c
index 759e06274..c62fd2caa 100644
--- a/libc/intrin/reopenfile.c
+++ b/libc/intrin/reopenfile.c
@@ -20,9 +20,11 @@
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/files.h"
+#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(ReOpenFile) *const __imp_ReOpenFile;
+__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Reopens file on the New Technology.
@@ -34,9 +36,10 @@ int64_t ReOpenFile(int64_t hOriginalFile, uint32_t dwDesiredAccess,
int64_t hHandle;
hHandle = __imp_ReOpenFile(hOriginalFile, dwDesiredAccess, dwShareMode,
dwFlagsAndAttributes);
- NTTRACE("ReOpenFile(%ld, %s, %s, %s) → %ld% m", hOriginalFile,
+ NTTRACE("ReOpenFile(%ld, %s, %s, %s) → {%ld, %d}", hOriginalFile,
DescribeNtFileAccessFlags(dwDesiredAccess),
DescribeNtFileShareFlags(dwShareMode),
- DescribeNtFileFlagAttr(dwFlagsAndAttributes), hHandle);
+ DescribeNtFileFlagAttr(dwFlagsAndAttributes), hHandle,
+ __imp_GetLastError());
return hHandle;
}
diff --git a/libc/intrin/terminateprocess.c b/libc/intrin/terminateprocess.c
index 752523fd0..2f0e3b1e1 100644
--- a/libc/intrin/terminateprocess.c
+++ b/libc/intrin/terminateprocess.c
@@ -23,6 +23,7 @@
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
+__msabi extern typeof(GetLastError) *const __imp_GetLastError;
/**
* Terminates the specified process and all of its threads.
@@ -30,6 +31,7 @@ __msabi extern typeof(TerminateProcess) *const __imp_TerminateProcess;
textwindows bool32 TerminateProcess(int64_t hProcess, uint32_t uWaitStatus) {
bool32 ok;
ok = __imp_TerminateProcess(hProcess, uWaitStatus);
- NTTRACE("TerminateProcess(%ld, %u) → %hhhd% m", hProcess, uWaitStatus, ok);
+ NTTRACE("TerminateProcess(%ld, %u) → {%hhhd, %d}", hProcess, uWaitStatus, ok,
+ __imp_GetLastError());
return ok;
}
diff --git a/libc/intrin/waitformultipleobjects.c b/libc/intrin/waitformultipleobjects.c
index 8382d794d..ef97e8c2e 100644
--- a/libc/intrin/waitformultipleobjects.c
+++ b/libc/intrin/waitformultipleobjects.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
+#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
@@ -26,14 +27,15 @@ __msabi extern typeof(WaitForMultipleObjects)
/**
* Waits for handles to change status.
- * @note this wrapper takes care of ABI, STRACE(), and __winerr()
+ *
+ * @return -1u on error w/ GetLastError()
+ * @raise kNtErrorInvalidParameter if `bWaitAll` and `lpHandles` has dupes
*/
uint32_t WaitForMultipleObjects(uint32_t nCount, const int64_t *lpHandles,
bool32 bWaitAll, uint32_t dwMilliseconds) {
uint32_t x;
x = __imp_WaitForMultipleObjects(nCount, lpHandles, bWaitAll, dwMilliseconds);
- if (x == -1u) __winerr();
- POLLTRACE("WaitForMultipleObjects(%ld, %p, %hhhd, %'d) → %d% m", nCount,
- lpHandles, bWaitAll, dwMilliseconds, x);
+ POLLTRACE("WaitForMultipleObjects(%ld, %p, %hhhd, %'d) → %d %d", nCount,
+ lpHandles, bWaitAll, dwMilliseconds, x, GetLastError());
return x;
}
diff --git a/libc/intrin/waitforsingleobject.c b/libc/intrin/waitforsingleobject.c
index 96ccc9681..e0d4d9975 100644
--- a/libc/intrin/waitforsingleobject.c
+++ b/libc/intrin/waitforsingleobject.c
@@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/strace.internal.h"
+#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
@@ -30,7 +31,7 @@ __msabi extern typeof(WaitForSingleObject) *const __imp_WaitForSingleObject;
uint32_t WaitForSingleObject(int64_t hHandle, uint32_t dwMilliseconds) {
uint32_t rc;
rc = __imp_WaitForSingleObject(hHandle, dwMilliseconds);
- POLLTRACE("WaitForSingleObject(%ld, %'d) → %d% m", hHandle, dwMilliseconds,
- rc);
+ POLLTRACE("WaitForSingleObject(%ld, %'d) → %d %d", hHandle, dwMilliseconds,
+ rc, GetLastError());
return rc;
}
diff --git a/libc/log/oncrash_arm64.c b/libc/log/oncrash_arm64.c
index 7e448af5c..82b2101fe 100644
--- a/libc/log/oncrash_arm64.c
+++ b/libc/log/oncrash_arm64.c
@@ -366,7 +366,7 @@ static relegated void __oncrash_impl(int sig, struct siginfo *si,
free(mem);
}
b->p[b->n - 1] = '\n';
- sys_write(2, b->p, MIN(b->i, b->n));
+ klog(b->p, MIN(b->i, b->n));
}
relegated void __oncrash(int sig, struct siginfo *si, void *arg) {
diff --git a/libc/proc/posix_spawn.c b/libc/proc/posix_spawn.c
index 959f7585f..bd9466dae 100644
--- a/libc/proc/posix_spawn.c
+++ b/libc/proc/posix_spawn.c
@@ -37,6 +37,7 @@
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h"
+#include "libc/intrin/bsf.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/dll.h"
#include "libc/intrin/strace.internal.h"
@@ -151,10 +152,11 @@ static textwindows bool spawnfds_exists(struct SpawnFds *fds, int fildes) {
return fildes + 0u < fds->n && fds->p[fildes].kind;
}
-static textwindows void spawnfds_close(struct SpawnFds *fds, int fildes) {
+static textwindows errno_t spawnfds_close(struct SpawnFds *fds, int fildes) {
if (spawnfds_exists(fds, fildes)) {
fds->p[fildes] = (struct Fd){0};
}
+ return 0;
}
static textwindows errno_t spawnfds_dup2(struct SpawnFds *fds, int fildes,
@@ -181,8 +183,8 @@ static textwindows errno_t spawnfds_dup2(struct SpawnFds *fds, int fildes,
}
static textwindows errno_t spawnfds_open(struct SpawnFds *fds, int64_t dirhand,
- int fildes, const char *path,
- int oflag, int mode) {
+ const char *path, int oflag, int mode,
+ int fildes) {
int64_t h;
errno_t err;
char16_t path16[PATH_MAX];
@@ -283,42 +285,47 @@ static textwindows errno_t posix_spawn_nt_impl(
// apply user file actions
if (file_actions) {
for (struct _posix_faction *a = *file_actions; a && !err; a = a->next) {
+ char errno_buf[30];
+ char oflags_buf[128];
+ char openmode_buf[15];
+ (void)errno_buf;
+ (void)oflags_buf;
+ (void)openmode_buf;
switch (a->action) {
case _POSIX_SPAWN_CLOSE:
- spawnfds_close(&fds, a->fildes);
+ err = spawnfds_close(&fds, a->fildes);
+ STRACE("spawnfds_close(%d) → %s", a->fildes,
+ (DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_DUP2:
err = spawnfds_dup2(&fds, a->fildes, a->newfildes);
- if (err) {
- STRACE("spawnfds_dup2(%d, %d) failed", a->fildes, a->newfildes);
- goto ReturnErr;
- }
+ STRACE("spawnfds_dup2(%d, %d) → %s", a->fildes, a->newfildes,
+ (DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_OPEN:
- err = spawnfds_open(&fds, dirhand, a->fildes, a->path, a->oflag,
- a->mode);
- if (err) {
- STRACE("spawnfds_open(%d, %#s) failed", a->fildes, a->path);
- goto ReturnErr;
- }
+ err = spawnfds_open(&fds, dirhand, a->path, a->oflag, a->mode,
+ a->fildes);
+ STRACE("spawnfds_open(%#s, %s, %s, %d) → %s", a->path,
+ (DescribeOpenFlags)(oflags_buf, a->oflag),
+ (DescribeOpenMode)(openmode_buf, a->oflag, a->mode), a->fildes,
+ (DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_CHDIR:
err = spawnfds_chdir(&fds, dirhand, a->path, &dirhand);
- if (err) {
- STRACE("spawnfds_chdir(%#s) failed", a->path);
- goto ReturnErr;
- }
+ STRACE("spawnfds_chdir(%#s) → %s", a->path,
+ (DescribeErrno)(errno_buf, err));
break;
case _POSIX_SPAWN_FCHDIR:
err = spawnfds_fchdir(&fds, a->fildes, &dirhand);
- if (err) {
- STRACE("spawnfds_fchdir(%d) failed", a->fildes);
- goto ReturnErr;
- }
+ STRACE("spawnfds_fchdir(%d) → %s", a->fildes,
+ (DescribeErrno)(errno_buf, err));
break;
default:
__builtin_unreachable();
}
+ if (err) {
+ goto ReturnErr;
+ }
}
}
@@ -572,9 +579,13 @@ errno_t posix_spawn(int *pid, const char *path,
}
}
if (flags & POSIX_SPAWN_SETRLIMIT) {
- for (int rez = 0; rez <= ARRAYLEN((*attrp)->rlim); ++rez) {
- if ((*attrp)->rlimset & (1u << rez)) {
- if (setrlimit(rez, (*attrp)->rlim + rez)) {
+ int rlimset = (*attrp)->rlimset;
+ while (rlimset) {
+ int resource = _bsf(rlimset);
+ rlimset &= ~(1u << resource);
+ if (setrlimit(resource, (*attrp)->rlim + resource)) {
+ // MacOS ARM64 RLIMIT_STACK always returns EINVAL
+ if (!IsXnuSilicon()) {
goto ChildFailed;
}
}
diff --git a/libc/proc/posix_spawn.internal.h b/libc/proc/posix_spawn.internal.h
index 855774be1..6dce26533 100644
--- a/libc/proc/posix_spawn.internal.h
+++ b/libc/proc/posix_spawn.internal.h
@@ -19,8 +19,8 @@ struct _posix_spawna {
bool schedparam_isset;
bool schedpolicy_isset;
int pgroup;
- int rlimset;
int schedpolicy;
+ int rlimset;
struct sched_param schedparam;
sigset_t sigmask;
sigset_t sigdefault;
diff --git a/libc/proc/posix_spawn_file_actions_addclose.c b/libc/proc/posix_spawn_file_actions_addclose.c
index 3bf4a7ee1..635ae64e0 100644
--- a/libc/proc/posix_spawn_file_actions_addclose.c
+++ b/libc/proc/posix_spawn_file_actions_addclose.c
@@ -32,7 +32,6 @@
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *file_actions,
int fildes) {
if (fildes < 0) return EBADF;
- if (IsWindows() && fildes > 2) return 0;
return __posix_spawn_add_file_action(file_actions,
(struct _posix_faction){
.action = _POSIX_SPAWN_CLOSE,
diff --git a/libc/proc/posix_spawn_file_actions_adddup2.c b/libc/proc/posix_spawn_file_actions_adddup2.c
index 449a86b2c..7768d9bb3 100644
--- a/libc/proc/posix_spawn_file_actions_adddup2.c
+++ b/libc/proc/posix_spawn_file_actions_adddup2.c
@@ -26,14 +26,12 @@
*
* @param file_actions was initialized by posix_spawn_file_actions_init()
* @return 0 on success, or errno on error
- * @raise ENOMEM if we require more vespene gas
* @raise EBADF if 'fildes' or `newfildes` is negative
- * @raise ENOTSUP if `newfildes` isn't 0, 1, or 2 on Windows
+ * @raise ENOMEM if insufficient memory was available
*/
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *file_actions,
int fildes, int newfildes) {
if (fildes < 0 || newfildes < 0) return EBADF;
- if (IsWindows() && newfildes > 2) return ENOTSUP;
return __posix_spawn_add_file_action(file_actions,
(struct _posix_faction){
.action = _POSIX_SPAWN_DUP2,
diff --git a/libc/proc/posix_spawnattr_getrlimit.c b/libc/proc/posix_spawnattr_getrlimit.c
index 2109bf89c..bb3e59981 100644
--- a/libc/proc/posix_spawnattr_getrlimit.c
+++ b/libc/proc/posix_spawnattr_getrlimit.c
@@ -21,6 +21,8 @@
#include "libc/macros.internal.h"
#include "libc/proc/posix_spawn.h"
#include "libc/proc/posix_spawn.internal.h"
+#include "libc/stdio/sysparam.h"
+#include "libc/sysv/consts/rlim.h"
/**
* Gets resource limit for spawned process.
@@ -31,7 +33,7 @@
*/
int posix_spawnattr_getrlimit(const posix_spawnattr_t *attr, int resource,
struct rlimit *rlim) {
- if ((0 <= resource && resource < ARRAYLEN((*attr)->rlim))) {
+ if (0 <= resource && resource < MIN(RLIM_NLIMITS, ARRAYLEN((*attr)->rlim))) {
if (((*attr)->rlimset & (1u << resource))) {
*rlim = (*attr)->rlim[resource];
return 0;
diff --git a/libc/proc/posix_spawnattr_setflags.c b/libc/proc/posix_spawnattr_setflags.c
index 12c00e325..9521bb9b2 100644
--- a/libc/proc/posix_spawnattr_setflags.c
+++ b/libc/proc/posix_spawnattr_setflags.c
@@ -37,9 +37,10 @@
*/
int posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags) {
if (flags &
- ~(POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF |
- POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSCHEDPARAM |
- POSIX_SPAWN_SETSCHEDULER | POSIX_SPAWN_SETSID)) {
+ ~(POSIX_SPAWN_USEVFORK | POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETPGROUP |
+ POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK |
+ POSIX_SPAWN_SETSCHEDPARAM | POSIX_SPAWN_SETSCHEDULER |
+ POSIX_SPAWN_SETSID | POSIX_SPAWN_SETRLIMIT)) {
return EINVAL;
}
(*attr)->flags = flags;
diff --git a/libc/proc/posix_spawnattr_setrlimit.c b/libc/proc/posix_spawnattr_setrlimit.c
index 10dabee61..90be67c43 100644
--- a/libc/proc/posix_spawnattr_setrlimit.c
+++ b/libc/proc/posix_spawnattr_setrlimit.c
@@ -21,6 +21,7 @@
#include "libc/macros.internal.h"
#include "libc/proc/posix_spawn.h"
#include "libc/proc/posix_spawn.internal.h"
+#include "libc/sysv/consts/rlim.h"
/**
* Sets resource limit on spawned process.
@@ -32,7 +33,7 @@
*/
int posix_spawnattr_setrlimit(posix_spawnattr_t *attr, int resource,
const struct rlimit *rlim) {
- if (0 <= resource && resource < ARRAYLEN((*attr)->rlim)) {
+ if (0 <= resource && resource < MIN(RLIM_NLIMITS, ARRAYLEN((*attr)->rlim))) {
(*attr)->flags |= POSIX_SPAWN_SETRLIMIT;
(*attr)->rlimset |= 1u << resource;
(*attr)->rlim[resource] = *rlim;
diff --git a/libc/proc/proc.c b/libc/proc/proc.c
index 38f8870cf..4c3cbef1e 100644
--- a/libc/proc/proc.c
+++ b/libc/proc/proc.c
@@ -103,12 +103,8 @@ static textwindows dontinstrument uint32_t __proc_worker(void *arg) {
__proc_unlock();
// wait for win32 to report any status change
- millis = n == 64 ? __SIG_PROC_INTERVAL_MS : -1u;
- i = WaitForMultipleObjects(n, handles, false, millis);
- if (i == -1u) {
- STRACE("PROC WORKER DYING: WAIT FAILED: %s", strerror(errno));
- break;
- }
+ millis = n == 64 ? 20 : -1u;
+ unassert((i = WaitForMultipleObjects(n, handles, false, millis)) != -1u);
i &= ~kNtWaitAbandoned;
if (!i || i == kNtWaitTimeout) continue;
GetExitCodeProcess(handles[i], &status);
diff --git a/libc/runtime/ftrace-hook.S b/libc/runtime/ftrace-hook.S
index 84dbca1ac..2537944fc 100644
--- a/libc/runtime/ftrace-hook.S
+++ b/libc/runtime/ftrace-hook.S
@@ -68,14 +68,15 @@ ftrace_hook:
#elif defined(__aarch64__)
- adrp x16,__ftrace
- ldr w16,[x16,#:lo12:__ftrace]
- cmp w16,0
- ble 1f
stp x29,x30,[sp,-384]!
mov x29,sp
-
stp x0,x1,[sp,16]
+
+ adrp x0,__ftrace
+ ldr w0,[x0,#:lo12:__ftrace]
+ cmp w0,0
+ ble 1f
+
stp x2,x3,[sp,32]
stp x4,x5,[sp,48]
stp x6,x7,[sp,64]
@@ -83,12 +84,12 @@ ftrace_hook:
stp x10,x11,[sp,96]
stp x12,x13,[sp,112]
stp x14,x15,[sp,128]
- str x19,[sp,160]
+ stp x16,x19,[sp,160]
stp x20,x21,[sp,176]
stp x22,x23,[sp,192]
stp x24,x25,[sp,208]
stp x26,x27,[sp,224]
- str x28,[sp,240]
+ stp x17,x28,[sp,240]
stp q0,q1,[sp,256]
stp q2,q3,[sp,288]
stp q4,q5,[sp,320]
@@ -96,27 +97,27 @@ ftrace_hook:
bl ftracer
- ldp x0,x1,[sp,16]
- ldp x2,x3,[sp,32]
- ldp x4,x5,[sp,48]
- ldp x6,x7,[sp,64]
- ldp x8,x9,[sp,80]
- ldp x10,x11,[sp,96]
- ldp x12,x13,[sp,112]
- ldp x14,x15,[sp,128]
- ldr x19,[sp,160]
- ldp x20,x21,[sp,176]
- ldp x22,x23,[sp,192]
- ldp x24,x25,[sp,208]
- ldp x26,x27,[sp,224]
- ldr x28,[sp,240]
- ldp q0,q1,[sp,256]
- ldp q2,q3,[sp,288]
- ldp q4,q5,[sp,320]
ldp q6,q7,[sp,352]
+ ldp q4,q5,[sp,320]
+ ldp q2,q3,[sp,288]
+ ldp q0,q1,[sp,256]
+ ldp x17,x28,[sp,240]
+ ldp x26,x27,[sp,224]
+ ldp x24,x25,[sp,208]
+ ldp x22,x23,[sp,192]
+ ldp x20,x21,[sp,176]
+ ldp x16,x19,[sp,160]
+ ldp x14,x15,[sp,128]
+ ldp x12,x13,[sp,112]
+ ldp x10,x11,[sp,96]
+ ldp x8,x9,[sp,80]
+ ldp x6,x7,[sp,64]
+ ldp x4,x5,[sp,48]
+ ldp x2,x3,[sp,32]
+1: ldp x0,x1,[sp,16]
ldp x29,x30,[sp],384
-1: ret
+ ret
#endif /* __x86_64__ */
.endfn ftrace_hook,globl,hidden
diff --git a/libc/sock/winsockblock.c b/libc/sock/winsockblock.c
index 9a0f18661..77849065e 100644
--- a/libc/sock/winsockblock.c
+++ b/libc/sock/winsockblock.c
@@ -90,12 +90,13 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock,
if (nonblock) {
CancelWinsockBlock(handle, &overlap);
eagained = true;
- } else if (_check_cancel()) {
- CancelWinsockBlock(handle, &overlap);
- canceled = true;
} else if (_check_signal(true)) {
CancelWinsockBlock(handle, &overlap);
- eintered = true;
+ if (errno == ECANCELED) {
+ canceled = true;
+ } else {
+ eintered = true;
+ }
} else {
status = WSAWaitForMultipleEvents(1, &overlap.hEvent, 0,
srwtimeout ? srwtimeout : -1u, 0);
@@ -142,7 +143,7 @@ __winsock_block(int64_t handle, uint32_t flags, bool nonblock,
}
if (GetLastError() == kNtErrorOperationAborted) {
if (_check_cancel() == -1) return ecanceled();
- if (!eintered && _check_signal(false)) return eintr();
+ if (!eintered && _check_signal(false)) return -1;
}
if (eintered) {
return eintr();
diff --git a/libc/sysv/sysv.c b/libc/sysv/sysv.c
index dc30c8a31..2fdcade5c 100644
--- a/libc/sysv/sysv.c
+++ b/libc/sysv/sysv.c
@@ -57,7 +57,7 @@ dontinline long systemfive_cancellable(void) {
return systemfive_cancel();
}
#if IsModeDbg()
- if (!(pth->flags & PT_INCANCEL)) {
+ if (!(pth->pt_flags & PT_INCANCEL)) {
if (_weaken(report_cancelation_point)) {
_weaken(report_cancelation_point)();
}
diff --git a/test/libc/calls/fchmod_test.c b/test/libc/calls/fchmod_test.c
new file mode 100644
index 000000000..3f95204fc
--- /dev/null
+++ b/test/libc/calls/fchmod_test.c
@@ -0,0 +1,41 @@
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
+╞══════════════════════════════════════════════════════════════════════════════╡
+│ Copyright 2023 Justine Alexandra Roberts Tunney │
+│ │
+│ Permission to use, copy, modify, and/or distribute this software for │
+│ any purpose with or without fee is hereby granted, provided that the │
+│ above copyright notice and this permission notice appear in all copies. │
+│ │
+│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
+│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
+│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
+│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
+│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
+│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
+│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
+│ PERFORMANCE OF THIS SOFTWARE. │
+╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
+#include "libc/calls/struct/stat.h"
+#include "libc/testlib/testlib.h"
+
+void SetUpOnce(void) {
+ testlib_enable_tmp_setup_teardown();
+}
+
+uint32_t GetMode(int fd) {
+ struct stat st;
+ ASSERT_SYS(0, 0, fstat(fd, &st));
+ return st.st_mode & 0777;
+}
+
+TEST(fchmod, canChangeReadOnlyBit) {
+ ASSERT_SYS(0, 3, creat("foo", 0600));
+ ASSERT_EQ(0600, GetMode(3));
+ ASSERT_SYS(0, 0, fchmod(3, 0400));
+ ASSERT_EQ(0400, GetMode(3));
+ ASSERT_SYS(0, 0, fchmod(3, 0600));
+ ASSERT_EQ(0600, GetMode(3));
+ ASSERT_SYS(0, 0, close(3));
+}
diff --git a/test/libc/calls/open_test.c b/test/libc/calls/open_test.c
index fe77d895b..7eced981e 100644
--- a/test/libc/calls/open_test.c
+++ b/test/libc/calls/open_test.c
@@ -495,3 +495,16 @@ TEST(open, mereOpen_doesntTouch) {
EXPECT_EQ(0, timespec_cmp(st.st_mtim, birth));
EXPECT_EQ(0, timespec_cmp(st.st_atim, birth));
}
+
+TEST(open, canTruncateExistingFile) {
+ struct stat st;
+ ASSERT_SYS(0, 0, xbarf("foo", "hello", -1));
+ ASSERT_SYS(0, 0, stat("foo", &st));
+ ASSERT_EQ(5, st.st_size);
+ ASSERT_SYS(0, 3, open("foo", O_RDWR | O_TRUNC));
+ ASSERT_SYS(0, 0, fstat(3, &st));
+ ASSERT_EQ(0, st.st_size);
+ ASSERT_SYS(0, 0, close(3));
+ ASSERT_SYS(0, 0, stat("foo", &st));
+ ASSERT_EQ(0, st.st_size);
+}
diff --git a/test/libc/thread/makecontext_test.c b/test/libc/thread/makecontext_test.c
index 3137e794f..81f641baf 100644
--- a/test/libc/thread/makecontext_test.c
+++ b/test/libc/thread/makecontext_test.c
@@ -21,6 +21,11 @@
#include "libc/dce.h"
#include "libc/limits.h"
#include "libc/mem/gc.internal.h"
+#include "libc/nt/createfile.h"
+#include "libc/nt/enum/accessmask.h"
+#include "libc/nt/enum/creationdisposition.h"
+#include "libc/nt/enum/fileflagandattributes.h"
+#include "libc/nt/enum/filesharemode.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
@@ -89,9 +94,14 @@ TEST(makecontext, crash) {
TEST(makecontext, backtrace) {
if (IsTiny()) return; // doesn't print full crash report
SPAWN(fork);
- ASSERT_SYS(0, 0, close(2));
- ASSERT_SYS(0, 2, creat("log", 0644));
- __klog_handle = 2;
+ if (IsWindows()) {
+ __klog_handle =
+ CreateFile(u"log", kNtFileAppendData,
+ kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
+ kNtOpenAlways, kNtFileAttributeNormal, 0);
+ } else {
+ __klog_handle = creat("log", 0644);
+ }
getcontext(&uc);
uc.uc_link = 0;
uc.uc_stack.ss_sp = NewCosmoStack();
diff --git a/test/libc/thread/test.mk b/test/libc/thread/test.mk
index 9c0a662b7..4391bc2cd 100644
--- a/test/libc/thread/test.mk
+++ b/test/libc/thread/test.mk
@@ -29,6 +29,7 @@ TEST_LIBC_THREAD_DIRECTDEPS = \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
+ LIBC_NT_KERNEL32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
diff --git a/third_party/make/config.h b/third_party/make/config.h
index 5411073dc..a94336401 100644
--- a/third_party/make/config.h
+++ b/third_party/make/config.h
@@ -286,12 +286,6 @@
/* Define to 1 if you have the `pipe' function. */
#define HAVE_PIPE 1
-/* Define to 1 if you have the `posix_spawn' function. */
-#define HAVE_POSIX_SPAWN 1
-
-/* Define to 1 if you have the `posix_spawnattr_setsigmask' function. */
-#define HAVE_POSIX_SPAWNATTR_SETSIGMASK 1
-
/* Define to 1 if you have the `pselect' function. */
#define HAVE_PSELECT 1
diff --git a/third_party/make/dirname.h b/third_party/make/dirname.h
index dc238bdce..07d6bee16 100644
--- a/third_party/make/dirname.h
+++ b/third_party/make/dirname.h
@@ -20,7 +20,7 @@
#ifndef DIRNAME_H_
# define DIRNAME_H_ 1
-#include "third_party/make/dosname.h"
+#include "third_party/make/filename.h"
# ifndef DIRECTORY_SEPARATOR
# define DIRECTORY_SEPARATOR '/'
diff --git a/third_party/make/dosname.h b/third_party/make/dosname.h
deleted file mode 100644
index add963f70..000000000
--- a/third_party/make/dosname.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* clang-format off */
-/* File names on MS-DOS/Windows systems.
-
- Copyright (C) 2000-2001, 2004-2006, 2009-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
- From Paul Eggert and Jim Meyering. */
-
-#ifndef _DOSNAME_H
-#define _DOSNAME_H
-
-#if (defined _WIN32 || defined __CYGWIN__ \
- || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__)
- /* This internal macro assumes ASCII, but all hosts that support drive
- letters use ASCII. */
-# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
- <= 'z' - 'a')
-# define FILE_SYSTEM_PREFIX_LEN(Filename) \
- (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
-# ifndef __CYGWIN__
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
-# endif
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-#else
-# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
-# define ISSLASH(C) ((C) == '/')
-#endif
-
-#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
-#endif
-
-#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
-# else
-# define IS_ABSOLUTE_FILE_NAME(F) \
- (ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
-#endif
-#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
-
-#endif /* DOSNAME_H_ */
diff --git a/third_party/make/filename.h b/third_party/make/filename.h
index 09f69601a..beb24dd13 100644
--- a/third_party/make/filename.h
+++ b/third_party/make/filename.h
@@ -29,23 +29,13 @@ extern "C" {
it may be concatenated to a directory pathname.
IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
*/
-#if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
- /* Native Windows, Cygwin, OS/2, DOS */
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-# define HAS_DEVICE(P) \
- ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
- && (P)[1] == ':')
-# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
-# define IS_PATH_WITH_DIR(P) \
- (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
-# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
-#else
- /* Unix */
# define ISSLASH(C) ((C) == '/')
-# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
-# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
-# define FILE_SYSTEM_PREFIX_LEN(P) 0
-#endif
+# define HAS_DEVICE(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
+# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
+# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
+# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
+# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
#ifdef __cplusplus
diff --git a/third_party/make/findprog-in.c b/third_party/make/findprog-in.c
index 50758700c..826b766f3 100644
--- a/third_party/make/findprog-in.c
+++ b/third_party/make/findprog-in.c
@@ -20,6 +20,9 @@
#include "libc/errno.h"
#include "libc/str/str.h"
#include "libc/mem/mem.h"
+#include "third_party/make/filename.h"
+#include "libc/calls/struct/stat.h"
+#include "libc/sysv/consts/s.h"
#include "third_party/make/config.h"
/* Specification. */
@@ -58,8 +61,8 @@ static const char * const suffixes[] =
/* Note: The cmd.exe program does a different lookup: It searches according
to the PATHEXT environment variable.
See .
- Also, it executes files ending .bat and .cmd directly without letting the
- kernel interpret the program file. */
+ Also, it executes files ending in .bat and .cmd directly without letting
+ the kernel interpret the program file. */
#elif defined __CYGWIN__
"", ".exe", ".com"
#elif defined __EMX__
@@ -73,7 +76,7 @@ static const char * const suffixes[] =
const char *
find_in_given_path (const char *progname, const char *path,
- bool optimize_for_exec)
+ const char *directory, bool optimize_for_exec)
{
{
bool has_slash = false;
@@ -101,6 +104,12 @@ find_in_given_path (const char *progname, const char *path,
with such a suffix is actually executable. */
int failure_errno;
size_t i;
+
+ const char *directory_as_prefix =
+ (directory != NULL && IS_RELATIVE_FILE_NAME (progname)
+ ? directory
+ : "");
+
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
const char *progbasename;
@@ -112,6 +121,8 @@ find_in_given_path (const char *progname, const char *path,
if (ISSLASH (*p))
progbasename = p + 1;
}
+
+ bool progbasename_has_dot = (strchr (progbasename, '.') != NULL);
#endif
/* Try all platform-dependent suffixes. */
@@ -123,12 +134,16 @@ find_in_given_path (const char *progname, const char *path,
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
/* File names without a '.' are not considered executable, and
for file names with a '.' no additional suffix is tried. */
- if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL))
+ if ((*suffix != '\0') != progbasename_has_dot)
#endif
{
- /* Concatenate progname and suffix. */
+ /* Concatenate directory_as_prefix, progname, suffix. */
char *progpathname =
- xconcatenated_filename ("", progname, suffix);
+ concatenated_filename (directory_as_prefix, progname,
+ suffix);
+
+ if (progpathname == NULL)
+ return NULL; /* errno is set here */
/* On systems which have the eaccess() system call, let's
use it. On other systems, let's hope that this program
@@ -136,14 +151,26 @@ find_in_given_path (const char *progname, const char *path,
call access() despite its design flaw. */
if (eaccess (progpathname, X_OK) == 0)
{
- /* Found! */
- if (strcmp (progpathname, progname) == 0)
+ /* Check that the progpathname does not point to a
+ directory. */
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
{
- free (progpathname);
- return progname;
+ if (! S_ISDIR (statbuf.st_mode))
+ {
+ /* Found! */
+ if (strcmp (progpathname, progname) == 0)
+ {
+ free (progpathname);
+ return progname;
+ }
+ else
+ return progpathname;
+ }
+
+ errno = EACCES;
}
- else
- return progpathname;
}
if (errno != ENOENT)
@@ -152,6 +179,36 @@ find_in_given_path (const char *progname, const char *path,
free (progpathname);
}
}
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ if (failure_errno == ENOENT && !progbasename_has_dot)
+ {
+ /* In the loop above, we skipped suffix = "". Do this loop
+ round now, merely to provide a better errno than ENOENT. */
+
+ char *progpathname =
+ concatenated_filename (directory_as_prefix, progname, "");
+
+ if (progpathname == NULL)
+ return NULL; /* errno is set here */
+
+ if (eaccess (progpathname, X_OK) == 0)
+ {
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
+ {
+ if (! S_ISDIR (statbuf.st_mode))
+ errno = ENOEXEC;
+ else
+ errno = EACCES;
+ }
+ }
+
+ failure_errno = errno;
+
+ free (progpathname);
+ }
+ #endif
errno = failure_errno;
return NULL;
@@ -165,17 +222,26 @@ find_in_given_path (const char *progname, const char *path,
path = "";
{
- int failure_errno;
/* Make a copy, to prepare for destructive modifications. */
- char *path_copy = xstrdup (path);
+ char *path_copy = strdup (path);
+ if (path_copy == NULL)
+ return NULL; /* errno is set here */
+
+ int failure_errno;
char *path_rest;
char *cp;
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ bool progname_has_dot = (strchr (progname, '.') != NULL);
+ #endif
+
failure_errno = ENOENT;
for (path_rest = path_copy; ; path_rest = cp + 1)
{
const char *dir;
bool last;
+ char *dir_as_prefix_to_free;
+ const char *dir_as_prefix;
size_t i;
/* Extract next directory in PATH. */
@@ -189,6 +255,25 @@ find_in_given_path (const char *progname, const char *path,
if (dir == cp)
dir = ".";
+ /* Concatenate directory and dir. */
+ if (directory != NULL && IS_RELATIVE_FILE_NAME (dir))
+ {
+ dir_as_prefix_to_free =
+ concatenated_filename (directory, dir, NULL);
+ if (dir_as_prefix_to_free == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ goto failed;
+ }
+ dir_as_prefix = dir_as_prefix_to_free;
+ }
+ else
+ {
+ dir_as_prefix_to_free = NULL;
+ dir_as_prefix = dir;
+ }
+
/* Try all platform-dependent suffixes. */
for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
{
@@ -197,12 +282,20 @@ find_in_given_path (const char *progname, const char *path,
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
/* File names without a '.' are not considered executable, and
for file names with a '.' no additional suffix is tried. */
- if ((*suffix != '\0') != (strchr (progname, '.') != NULL))
+ if ((*suffix != '\0') != progname_has_dot)
#endif
{
- /* Concatenate dir, progname, and suffix. */
+ /* Concatenate dir_as_prefix, progname, and suffix. */
char *progpathname =
- xconcatenated_filename (dir, progname, suffix);
+ concatenated_filename (dir_as_prefix, progname, suffix);
+
+ if (progpathname == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ free (dir_as_prefix_to_free);
+ goto failed;
+ }
/* On systems which have the eaccess() system call, let's
use it. On other systems, let's hope that this program
@@ -210,25 +303,45 @@ find_in_given_path (const char *progname, const char *path,
call access() despite its design flaw. */
if (eaccess (progpathname, X_OK) == 0)
{
- /* Found! */
- if (strcmp (progpathname, progname) == 0)
+ /* Check that the progpathname does not point to a
+ directory. */
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
{
- free (progpathname);
+ if (! S_ISDIR (statbuf.st_mode))
+ {
+ /* Found! */
+ if (strcmp (progpathname, progname) == 0)
+ {
+ free (progpathname);
- /* Add the "./" prefix for real, that
- xconcatenated_filename() optimized away. This
- avoids a second PATH search when the caller uses
- execl/execv/execlp/execvp. */
- progpathname =
- XNMALLOC (2 + strlen (progname) + 1, char);
- progpathname[0] = '.';
- progpathname[1] = NATIVE_SLASH;
- memcpy (progpathname + 2, progname,
- strlen (progname) + 1);
+ /* Add the "./" prefix for real, that
+ concatenated_filename() optimized away.
+ This avoids a second PATH search when the
+ caller uses execl/execv/execlp/execvp. */
+ progpathname =
+ (char *) malloc (2 + strlen (progname) + 1);
+ if (progpathname == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ free (dir_as_prefix_to_free);
+ goto failed;
+ }
+ progpathname[0] = '.';
+ progpathname[1] = NATIVE_SLASH;
+ memcpy (progpathname + 2, progname,
+ strlen (progname) + 1);
+ }
+
+ free (dir_as_prefix_to_free);
+ free (path_copy);
+ return progpathname;
+ }
+
+ errno = EACCES;
}
-
- free (path_copy);
- return progpathname;
}
if (errno != ENOENT)
@@ -237,11 +350,49 @@ find_in_given_path (const char *progname, const char *path,
free (progpathname);
}
}
+ #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
+ if (failure_errno == ENOENT && !progname_has_dot)
+ {
+ /* In the loop above, we skipped suffix = "". Do this loop
+ round now, merely to provide a better errno than ENOENT. */
+
+ char *progpathname =
+ concatenated_filename (dir_as_prefix, progname, "");
+
+ if (progpathname == NULL)
+ {
+ /* errno is set here. */
+ failure_errno = errno;
+ free (dir_as_prefix_to_free);
+ goto failed;
+ }
+
+ if (eaccess (progpathname, X_OK) == 0)
+ {
+ struct stat statbuf;
+
+ if (stat (progpathname, &statbuf) >= 0)
+ {
+ if (! S_ISDIR (statbuf.st_mode))
+ errno = ENOEXEC;
+ else
+ errno = EACCES;
+ }
+ }
+
+ failure_errno = errno;
+
+ free (progpathname);
+ }
+ #endif
+
+ free (dir_as_prefix_to_free);
if (last)
break;
}
+ failed:
/* Not found in PATH. */
free (path_copy);
diff --git a/third_party/make/findprog.h b/third_party/make/findprog.h
index 6d2d5b373..c6f9c8742 100644
--- a/third_party/make/findprog.h
+++ b/third_party/make/findprog.h
@@ -41,6 +41,10 @@ extern const char *find_in_path (const char *progname);
directory. A null PATH is equivalent to an empty PATH, that is, to the
singleton list that contains only the current directory.
+ If DIRECTORY is not NULL, all relative filenames (i.e. PROGNAME when it
+ contains a slash, and the PATH elements) are considered relative to
+ DIRECTORY instead of relative to the current directory of this process.
+
Determines the pathname that would be called by execlp/execvp of PROGNAME.
- If successful, it returns a pathname containing a slash (either absolute
or relative to the current directory). The returned string can be used
@@ -52,6 +56,7 @@ extern const char *find_in_path (const char *progname);
- EACCES: means that the program's file cannot be accessed (due to some
issue with one of the ancestor directories) or lacks the execute
permissions.
+ - ENOMEM: means out of memory.
If OPTIMIZE_FOR_EXEC is true, the function saves some work, under the
assumption that the resulting pathname will not be accessed directly,
only through execl/execv or execlp/execvp.
@@ -60,6 +65,7 @@ extern const char *find_in_path (const char *progname);
- On POSIX systems excluding Cygwin: a '/',
- On Windows, OS/2, DOS platforms: a '/' or '\'. */
extern const char *find_in_given_path (const char *progname, const char *path,
+ const char *directory,
bool optimize_for_exec);
diff --git a/third_party/make/job.c b/third_party/make/job.c
index 5003fb91f..198648209 100644
--- a/third_party/make/job.c
+++ b/third_party/make/job.c
@@ -47,6 +47,7 @@ this program. If not, see . */
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/nexgen32e/kcpuids.h"
+#include "libc/proc/posix_spawn.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
@@ -63,10 +64,14 @@ this program. If not, see . */
#include "libc/x/x.h"
#include "third_party/make/commands.h"
#include "third_party/make/dep.h"
+#include "third_party/make/findprog.h"
#include "third_party/make/os.h"
#include "third_party/make/variable.h"
// clang-format off
+#define USE_POSIX_SPAWN (!IsLinux() && !IsOpenbsd())
+#define HAVE_POSIX_SPAWNATTR_SETSIGMASK
+
#ifdef WINDOWS32
const char *default_shell = "sh.exe";
int no_default_sh_exe = 1;
@@ -1891,6 +1896,153 @@ child_execute_job (struct childbase *child,
fderr = child->output.err;
}
+ if (USE_POSIX_SPAWN) {
+ char *cmd;
+ posix_spawnattr_t attr;
+ posix_spawn_file_actions_t fa;
+ short flags = 0;
+
+ if ((r = posix_spawnattr_init (&attr)) != 0)
+ goto done;
+
+ if ((r = posix_spawn_file_actions_init (&fa)) != 0)
+ {
+ posix_spawnattr_destroy (&attr);
+ goto done;
+ }
+
+ // [jart] use setrlimit on posix_spawn
+ // TODO(jart): support landlock make rlimit variables
+ if (stack_limit.rlim_cur && RLIMIT_STACK < RLIM_NLIMITS)
+ {
+ posix_spawnattr_setrlimit (&attr, RLIMIT_STACK, &stack_limit);
+ flags |= POSIX_SPAWN_SETRLIMIT;
+ }
+
+ /* Unblock all signals. */
+#ifdef HAVE_POSIX_SPAWNATTR_SETSIGMASK
+ {
+ sigset_t mask;
+ sigemptyset (&mask);
+ r = posix_spawnattr_setsigmask (&attr, &mask);
+ if (r != 0)
+ goto cleanup;
+ flags |= POSIX_SPAWN_SETSIGMASK;
+ }
+#endif /* have posix_spawnattr_setsigmask() */
+
+ /* USEVFORK can give significant speedup on systems where it's available. */
+#ifdef POSIX_SPAWN_USEVFORK
+ flags |= POSIX_SPAWN_USEVFORK;
+#endif
+
+ /* For any redirected FD, dup2() it to the standard FD.
+ They are all marked close-on-exec already. */
+ if (fdin >= 0 && fdin != FD_STDIN)
+ if ((r = posix_spawn_file_actions_adddup2 (&fa, fdin, FD_STDIN)) != 0)
+ goto cleanup;
+ if (fdout != FD_STDOUT)
+ if ((r = posix_spawn_file_actions_adddup2 (&fa, fdout, FD_STDOUT)) != 0)
+ goto cleanup;
+ if (fderr != FD_STDERR)
+ if ((r = posix_spawn_file_actions_adddup2 (&fa, fderr, FD_STDERR)) != 0)
+ goto cleanup;
+
+ /* We can't use the POSIX_SPAWN_RESETIDS flag: when make is invoked under
+ restrictive environments like unshare it will fail with EINVAL. */
+
+ /* Apply the spawn flags. */
+ if ((r = posix_spawnattr_setflags (&attr, flags)) != 0)
+ goto cleanup;
+
+ /* Look up the program on the child's PATH, if needed. */
+ {
+ const char *p = NULL;
+ char **pp;
+
+ for (pp = child->environment; *pp != NULL; ++pp)
+ if ((*pp)[0] == 'P' && (*pp)[1] == 'A' && (*pp)[2] == 'T'
+ && (*pp)[3] == 'H' &&(*pp)[4] == '=')
+ {
+ p = (*pp) + 5;
+ break;
+ }
+
+ /* execvp() will use a default PATH if none is set; emulate that. */
+ if (p == NULL)
+ {
+ size_t l = confstr (_CS_PATH, NULL, 0);
+ if (l)
+ {
+ char *dp = alloca (l);
+ confstr (_CS_PATH, dp, l);
+ p = dp;
+ }
+ }
+
+ cmd = (char *)find_in_given_path (argv[0], p, NULL, 0);
+ }
+
+ if (!cmd)
+ {
+ r = errno;
+ goto cleanup;
+ }
+
+ /* Start the program. */
+ while ((r = posix_spawn (&pid, cmd, &fa, &attr, argv,
+ child->environment)) == EINTR)
+ ;
+
+ /* posix_spawn() doesn't provide sh fallback like exec() does; implement
+ it here. POSIX doesn't specify the path to sh so use the default. */
+
+ if (r == ENOEXEC)
+ {
+ char **nargv;
+ char **pp;
+ size_t l = 0;
+
+ for (pp = argv; *pp != NULL; ++pp)
+ ++l;
+
+ nargv = xmalloc (sizeof (char *) * (l + 3));
+ nargv[0] = (char *)default_shell;
+ nargv[1] = cmd;
+ memcpy (&nargv[2], &argv[1], sizeof (char *) * l);
+
+ while ((r = posix_spawn (&pid, nargv[0], &fa, &attr, nargv,
+ child->environment)) == EINTR)
+ ;
+
+ free (nargv);
+ }
+
+ if (r == 0)
+ {
+ /* Spawn succeeded but may fail later: remember the command. */
+ free (child->cmd_name);
+ if (cmd != argv[0])
+ child->cmd_name = cmd;
+ else
+ child->cmd_name = xstrdup(cmd);
+ }
+
+ cleanup:
+ posix_spawn_file_actions_destroy (&fa);
+ posix_spawnattr_destroy (&attr);
+
+ done:
+ if (r != 0)
+ pid = -1;
+
+ if (pid < 0)
+ OSS (error, NILF, "%s: %s", argv[0], strerror (r));
+
+ return pid;
+
+ } // USE_POSIX_SPAWN
+
pid = fork();
if (pid != 0)
return pid;
@@ -2446,17 +2598,23 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
shell = default_shell;
/* [jart] remove code that forces slow path if not using /bin/sh */
+ /* else if (strcmp (shell, default_shell)) */
+ /* goto slow; */
if (ifs)
for (cap = ifs; *cap != '\0'; ++cap)
- if (*cap != ' ' && *cap != '\t' && *cap != '\n')
+ if (*cap != ' ' && *cap != '\t' && *cap != '\n') {
+ // kprintf("slow because whitespace\n");
goto slow;
+ }
if (shellflags)
if (shellflags[0] != '-'
|| ((shellflags[1] != 'c' || shellflags[2] != '\0')
- && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0')))
+ && (shellflags[1] != 'e' || shellflags[2] != 'c' || shellflags[3] != '\0'))) {
+ // kprintf("slow because shell flags\n");
goto slow;
+ }
i = strlen (line) + 1;
@@ -2515,18 +2673,21 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
If we see any of those, punt.
But on MSDOS, if we use COMMAND.COM, double and single
quotes have the same effect. */
- else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell)
+ else if (instring == '"' && strchr ("\\$`", *p) != 0 && unixy_shell) {
+ // kprintf("slow because backslash\n");
goto slow;
- else
+ } else
*ap++ = *p;
}
- else if (strchr (sh_chars, *p) != 0)
+ else if (strchr (sh_chars, *p) != 0) {
/* Not inside a string, but it's a special char. */
+ // kprintf("slow because %#c found in %#s\n", *p, line);
goto slow;
- else if (one_shell && *p == '\n')
+ } else if (one_shell && *p == '\n') {
/* In .ONESHELL mode \n is a separator like ; or && */
+ // kprintf("slow because oneshell thing\n");
goto slow;
- else
+ } else
/* Not a special char. */
switch (*p)
{
@@ -2535,8 +2696,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
first word with no equals sign in it. This is not the case
with sh -k, but we never get here when using nonstandard
shell flags. */
- if (! seen_nonequals && unixy_shell)
+ if (! seen_nonequals && unixy_shell) {
+ // kprintf("slow because nonequals\n");
goto slow;
+ }
word_has_equals = 1;
*ap++ = '=';
break;
@@ -2590,10 +2753,12 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
/* Update SEEN_NONEQUALS, which tells us if every word
heretofore has contained an '='. */
seen_nonequals |= ! word_has_equals;
- if (word_has_equals && ! seen_nonequals)
+ if (word_has_equals && ! seen_nonequals) {
/* An '=' in a word before the first
word without one is magical. */
+ // kprintf("slow because word equals\n");
goto slow;
+ }
word_has_equals = 0; /* Prepare for the next word. */
/* If this argument is the command name,
@@ -2604,8 +2769,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
int j;
for (j = 0; sh_cmds[j] != 0; ++j)
{
- if (streq (sh_cmds[j], new_argv[0]))
+ if (streq (sh_cmds[j], new_argv[0])) {
+ // kprintf("slow because builtin shell commands\n");
goto slow;
+ }
}
}
@@ -2621,9 +2788,11 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
}
end_of_line:
- if (instring)
+ if (instring) {
/* Let the shell deal with an unterminated quote. */
+ // kprintf("slow because unterminated quote\n");
goto slow;
+ }
/* Terminate the last argument and the argument list. */
@@ -2636,8 +2805,10 @@ construct_command_argv_internal (char *line, char **restp, const char *shell,
{
int j;
for (j = 0; sh_cmds[j] != 0; ++j)
- if (streq (sh_cmds[j], new_argv[0]))
+ if (streq (sh_cmds[j], new_argv[0])) {
+ // kprintf("slow because sh_cmds\n");
goto slow;
+ }
}
if (new_argv[0] == 0)
diff --git a/third_party/make/main.c b/third_party/make/main.c
index 2bcd304e8..64697f8c0 100644
--- a/third_party/make/main.c
+++ b/third_party/make/main.c
@@ -971,7 +971,7 @@ reset_jobserver (void)
int
main (int argc, char **argv, char **envp)
{
- ShowCrashReports();
+ // ShowCrashReports();
static char *stdin_nm = 0;
int makefile_status = MAKE_SUCCESS;
@@ -982,7 +982,7 @@ main (int argc, char **argv, char **envp)
int argv_slots;
// [jart] workaround to prevent make -j fork bomb
- default_load_average = __get_cpu_count();
+ default_load_average = __get_cpu_count() * 1.5;
max_load_average = default_load_average;
/* Useful for attaching debuggers, etc. */
@@ -1042,10 +1042,6 @@ main (int argc, char **argv, char **envp)
#undef FATAL_SIG
-#ifndef NDEBUG
- ShowCrashReports();
-#endif
-
/* Do not ignore the child-death signal. This must be done before
any children could possibly be created; otherwise, the wait
functions won't work on systems with the SVR4 ECHILD brain
diff --git a/third_party/make/make.mk b/third_party/make/make.mk
index 760a17dde..2bbb13933 100644
--- a/third_party/make/make.mk
+++ b/third_party/make/make.mk
@@ -29,7 +29,6 @@ THIRD_PARTY_MAKE_HDRS = \
third_party/make/job.h \
third_party/make/unistd.h \
third_party/make/getprogname.h \
- third_party/make/dosname.h \
third_party/make/config.h \
third_party/make/concat-filename.h \
third_party/make/findprog.h \
diff --git a/third_party/mbedtls/aesni.c b/third_party/mbedtls/aesni.c
index 9695477a1..cc1d6a36b 100644
--- a/third_party/mbedtls/aesni.c
+++ b/third_party/mbedtls/aesni.c
@@ -130,8 +130,8 @@ int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx,
*/
void mbedtls_aesni_gcm_mult( unsigned char a[16], const uint64_t b[2] )
{
- uint64_t aa _Vector_size(16) forcealign(16);
- uint64_t bb _Vector_size(16) forcealign(16);
+ uint64_t aa __attribute__((__vector_size__(16), __aligned__(16)));
+ uint64_t bb __attribute__((__vector_size__(16), __aligned__(16)));
/* The inputs are in big-endian order, so byte-reverse them */
aa[0] = READ64BE(a+8);
diff --git a/third_party/nsync/futex.c b/third_party/nsync/futex.c
index 7d6513418..f34de99c4 100644
--- a/third_party/nsync/futex.c
+++ b/third_party/nsync/futex.c
@@ -169,11 +169,9 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
return 0;
}
if (pt) atomic_store_explicit (&pt->pt_blocker, w, memory_order_release);
- if (_check_cancel () == -1) return -1;
if (_check_signal (false) == -1) return -1;
ok = WaitOnAddress (w, &expect, sizeof(int), timespec_tomillis (wait));
- if (_check_signal (false) == -1) { _check_cancel (); return -1; }
- if (_check_cancel () == -1) return -1;
+ if (_check_signal (false) == -1) return -1;
if (ok) {
return 0;
} else {
diff --git a/tool/build/build.mk b/tool/build/build.mk
index 7d1b0d74b..46a801555 100644
--- a/tool/build/build.mk
+++ b/tool/build/build.mk
@@ -108,6 +108,7 @@ o/$(MODE)/tool/build/dso/sandbox.so: \
-s \
-shared \
-nostdlib \
+ -fuse-ld=bfd \
-Wl,--gc-sections \
o/$(MODE)/tool/build/dso/sandbox.o \
o/$(MODE)/libc/calls/pledge-linux.o \
diff --git a/tool/emacs/cosmo-stuff.el b/tool/emacs/cosmo-stuff.el
index 42648c5c7..278d3b67b 100644
--- a/tool/emacs/cosmo-stuff.el
+++ b/tool/emacs/cosmo-stuff.el
@@ -25,8 +25,23 @@
(require 'ld-script)
(require 'make-mode)
-(setq cosmo-dbg-mode "dbg")
-(setq cosmo-default-mode "")
+(setq cosmo-arch
+ (let ((arch (string-trim-right
+ (shell-command-to-string
+ "uname -m"))))
+ (cond ((string= arch "amd64") "x86_64")
+ ((string= arch "arm64") "aarch64")
+ (t arch))))
+
+(setq cosmo-default-mode
+ (cond ((string= cosmo-arch "aarch64") "aarch64")
+ (t "")))
+
+;; TODO(jart): How do we get GCC to do only dead code elimination?
+(setq cosmo-dbg-mode
+ (cond ((string= cosmo-arch "aarch64") "aarch64")
+ (t "dbg")))
+
(setq c-doc-comment-style 'javadown)
(add-to-list 'auto-mode-alist '("\\.x$" . c-mode)) ;; -aux-info
@@ -161,14 +176,23 @@
(cosmo-startswith "test/" pkg))))
(defun cosmo--make-mode (arg &optional default)
- (cond ((eq arg 1) "tiny")
+ (cond ((eq arg 1)
+ (cond ((string= cosmo-arch "aarch64") "aarch64-tiny")
+ (t "tiny")))
((eq arg 2) "opt")
((eq arg 3) "rel")
- ((eq arg 4) cosmo-dbg-mode)
- ((eq arg 5) "")
+ ((eq arg 4)
+ cosmo-dbg-mode)
+ ((eq arg 5)
+ (cond ((string= cosmo-arch "aarch64") "aarch64")
+ (t cosmo-default-mode)))
((eq arg 6) "llvm")
- ((eq arg 7) "aarch64")
- ((eq arg 8) "aarch64-tiny")
+ ((eq arg 7)
+ (cond ((string= cosmo-arch "aarch64") "x86_64")
+ (t "aarch64")))
+ ((eq arg 8)
+ (cond ((string= cosmo-arch "aarch64") "tiny")
+ (t "aarch64-tiny")))
(default default)
((cosmo-intest) cosmo-dbg-mode)
(t cosmo-default-mode)))