mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 08:08:04 -10:00
Compare commits
98
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6a039821f | ||
|
|
f12c6c1b5e | ||
|
|
fdb543cbb3 | ||
|
|
1d6216a775 | ||
|
|
206091617a | ||
|
|
777d08a839 | ||
|
|
98192c1079 | ||
|
|
7064d736e3 | ||
|
|
245a9c206b | ||
|
|
1bdc8faa65 | ||
|
|
8f05990d5a | ||
|
|
7fe9e70117 | ||
|
|
6f658f058b | ||
|
|
ca611efc43 | ||
|
|
e5d1536256 | ||
|
|
d7ff346b52 | ||
|
|
903cc38c37 | ||
|
|
3616f2a432 | ||
|
|
7a50dba812 | ||
|
|
19f70a154e | ||
|
|
0a0997a872 | ||
|
|
30cd28b1f8 | ||
|
|
91d783352a | ||
|
|
45a7435788 | ||
|
|
660ff56d40 | ||
|
|
c00755f921 | ||
|
|
013f03e33f | ||
|
|
49db877fbe | ||
|
|
253ac31a64 | ||
|
|
67b5200a0b | ||
|
|
226aaf3547 | ||
|
|
a0b39f886c | ||
|
|
d852640a1e | ||
|
|
425a57080d | ||
|
|
bba144246a | ||
|
|
7061c79c22 | ||
|
|
28997f3acb | ||
|
|
725f4d79f6 | ||
|
|
7521bf9e73 | ||
|
|
47a53e143b | ||
|
|
9cb54218ab | ||
|
|
57f0eed382 | ||
|
|
2fe8571010 | ||
|
|
9cabdaabfd | ||
|
|
39bf41f4eb | ||
|
|
fa7b4f5bd1 | ||
|
|
b883473a6c | ||
|
|
af1153e057 | ||
|
|
2e4b40042a | ||
|
|
42aafc847e | ||
|
|
b51db9f923 | ||
|
|
6fba9601ff | ||
|
|
9e7773a076 | ||
|
|
48a2668239 | ||
|
|
5ffeaa8e33 | ||
|
|
18ccfeb919 | ||
|
|
b5f743cdc3 | ||
|
|
51904e2687 | ||
|
|
ad52387b74 | ||
|
|
6ad0602392 | ||
|
|
1b93066883 | ||
|
|
559b024e1d | ||
|
|
dfa0359b50 | ||
|
|
4f41f2184d | ||
|
|
5bb2275788 | ||
|
|
a8fb68af4b | ||
|
|
1eed7d47bd | ||
|
|
44c87b83ff | ||
|
|
81287b7ec0 | ||
|
|
34b68f1945 | ||
|
|
ab64c746cc | ||
|
|
a81192e0b9 | ||
|
|
27f7ffd4fd | ||
|
|
31dd714081 | ||
|
|
969174e155 | ||
|
|
5b60e5a37d | ||
|
|
0584684a82 | ||
|
|
50937be752 | ||
|
|
3085ac7837 | ||
|
|
63b867bd2f | ||
|
|
0b7737b20a | ||
|
|
818926dbae | ||
|
|
7d25fb0090 | ||
|
|
41b9eb6873 | ||
|
|
00611e9b06 | ||
|
|
2730c66f4a | ||
|
|
c506584174 | ||
|
|
ed485391da | ||
|
|
d5a37de435 | ||
|
|
65f32fad52 | ||
|
|
da45c7c80b | ||
|
|
7341336b1a | ||
|
|
a63b147a93 | ||
|
|
0ba3617e7f | ||
|
|
8af197560e | ||
|
|
98ccbf44b1 | ||
|
|
ebb8c85496 | ||
|
|
4486ad5c9e |
No files matched your search
@@ -59,10 +59,9 @@
|
||||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = /bin/sh
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
|
||||
SANITY := $(shell build/sanitycheck $$PPID)
|
||||
GNUMAKEFLAGS += --output-sync
|
||||
SHELL = /bin/sh
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
|
||||
SANITY := $(shell build/sanitycheck $$PPID)
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
@@ -115,8 +114,10 @@ include third_party/gdtoa/gdtoa.mk # │ You can finally call malloc()
|
||||
include libc/time/time.mk # │
|
||||
include libc/alg/alg.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include libc/thread/thread.mk # │
|
||||
include net/net.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include third_party/bzip2/bzip2.mk # │
|
||||
include dsp/core/core.mk # │
|
||||
include libc/x/x.mk # │
|
||||
include third_party/stb/stb.mk # │
|
||||
@@ -138,19 +139,22 @@ include libc/testlib/testlib.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/make/make.mk
|
||||
include third_party/argon2/argon2.mk
|
||||
include third_party/sqlite3/sqlite3.mk
|
||||
include third_party/mbedtls/test/test.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/infozip/infozip.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
include third_party/chibicc/test/test.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include examples/examples.mk
|
||||
include examples/pyapp/pyapp.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/hash/hash.mk
|
||||
@@ -166,6 +170,7 @@ include test/libc/runtime/test.mk
|
||||
include test/libc/sock/test.mk
|
||||
include test/libc/bits/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/log/test.mk
|
||||
include test/libc/unicode/test.mk
|
||||
include test/libc/calls/test.mk
|
||||
include test/libc/x/test.mk
|
||||
@@ -212,30 +217,25 @@ tags: TAGS HTAGS
|
||||
o/$(MODE)/.x:
|
||||
@mkdir -p $(@D) && touch $@
|
||||
|
||||
ifneq ($(findstring 4.,,$(MAKE_VERSION)),$(MAKE_VERSION))
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
$(file >$@,$(SRCS))
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
$(file >$@,$(HDRS) $(INCS))
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(INCS) $(INCS),$(file >>$@,$(x)))
|
||||
else
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^SRCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^HDRS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^INCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
endif
|
||||
|
||||
$(file >$@,$(INCS))
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt
|
||||
@$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS)
|
||||
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
|
||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
|
||||
@rm -f $@
|
||||
@$(COMPILE) -ATAGS -T$@ $(TAGS) $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
|
||||
@rm -f $@
|
||||
@$(COMPILE) -ATAGS -T$@ build/htags -L $< -o $@
|
||||
|
||||
@@ -281,6 +281,7 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_THREAD \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
@@ -308,6 +309,7 @@ COSMOPOLITAN_HEADERS = \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_UNICODE \
|
||||
@@ -320,14 +322,15 @@ COSMOPOLITAN_HEADERS = \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_REGEX
|
||||
|
||||
o/$(MODE)/cosmopolitan.a.txt:
|
||||
printf "%s\n" $(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)))))
|
||||
o/$(MODE)/cosmopolitan.a: $(filter-out o/libc/stubs/exit11.o,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS)))
|
||||
o/$(MODE)/cosmopolitan.a: \
|
||||
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||
|
||||
o/cosmopolitan.h: \
|
||||
o/$(MODE)/tool/build/rollup.com \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
|
||||
@$(COMPILE) -AROLLUP -T$@ $^ >$@
|
||||
$(file >$@.args,libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$@.args >$@
|
||||
|
||||
o/cosmopolitan.html: \
|
||||
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
|
||||
|
||||
@@ -92,4 +92,4 @@ find o -name \*.com | xargs ls -rShal | less
|
||||
| FreeBSD | 12 | 2018 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| NetBSD | 9.1 | 2020 |
|
||||
| GNU Make | 3.80 | 2010 |
|
||||
| GNU Make | 4.0 | 2015 |
|
||||
@@ -5,16 +5,16 @@
|
||||
│ │
|
||||
│ 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. │
|
||||
│ above copyright notice & 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. │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL │
|
||||
│ THE AUTHOR BE LIABLE FOR ANY SPECIAL DIRECT INDIRECT, OR EVEN │
|
||||
│ CONSEQUENTIAL DAMAGE OR ANY DAMAGES WHATSOEVER RESULTING FROM │
|
||||
│ LOSS OF USE, DATA OR PROFITS WHETHER IN AN ACTION OF CONTRACT │
|
||||
│ NEGLIGENCE OR OTHER TORTIOUS ACTION, THAT ARISE OUT OF, OR IN │
|
||||
│ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
@@ -540,27 +540,33 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
// modify the binary to follow the local system's convention.
|
||||
// There isn't a one-size-fits-all approach for this, thus we
|
||||
// present two choices.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
// Try to use a system-wide APE loader.
|
||||
.ascii "type ape-loader >/dev/null 2>&1 && "
|
||||
.ascii "exec ape-loader \"$o\" \"$@\"\n"
|
||||
#ifdef APE_LOADER
|
||||
// There is no system-wide APE loader, but there is one
|
||||
// embedded inside the APE. So if the system is not MacOs,
|
||||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "if [ ! -d /Applications ]; then\n"
|
||||
.ascii "t=\"${TMPDIR:-/tmp}/ape-loader\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=\""
|
||||
.shstub ape_loader_dd_skip,2
|
||||
.ascii "\" count=\""
|
||||
.shstub ape_loader_dd_count,2
|
||||
.ascii "\" bs=64 2>/dev/null &&\n"
|
||||
.ascii "chmod 755 \"$t.$$\" &&\n"
|
||||
.ascii "mv \"$t.$$\" \"$t\"\n"
|
||||
.ascii "}\n"
|
||||
.ascii "exec \"$t\" \"$o\" \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
#endif
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
// The default behavior is: to overwrite the header in place.
|
||||
// We prefer this because it's a tiny constant one time cost.
|
||||
// We simply printf a 64-byte header and call execve() again.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
#ifdef APE_BUILDSAFE
|
||||
// This code is intended for binaries in build/bootstrap/. It
|
||||
// causes them to not self-modify since they're checked-in to
|
||||
// version control. It assumes cosmopolitan's build prefix is
|
||||
// being used by convention and that the program has the noop
|
||||
// flag -n which is used to prime the binary.
|
||||
.ascii "if [ ${o##o/} = $o ]; then\n"
|
||||
.ascii " if ! [ o/$o -nt $o ]; then\n"
|
||||
.ascii " mkdir -p o/${o%/*} || exit\n"
|
||||
.ascii " cp -f $o o/$o.$$ || exit\n"
|
||||
.ascii " o/$o.$$ -n || exit\n"
|
||||
.ascii " mv -f o/$o.$$ o/$o || exit\n"
|
||||
.ascii " fi\n"
|
||||
.ascii " exec o/$o \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
#endif
|
||||
#else
|
||||
// The alternative behavior is to copy to $TMPDIR and edit.
|
||||
// This imposes a variety of caveats of its own that should
|
||||
@@ -645,6 +651,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.ascii "fi\n"
|
||||
.ascii "exit $R\n"
|
||||
.endobj apesh
|
||||
#ifdef APE_LOADER
|
||||
.section .ape.loader,"a",@progbits
|
||||
.incbin APE_LOADER
|
||||
.previous
|
||||
#endif /* APE_LOADER */
|
||||
#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */
|
||||
|
||||
#if SupportsSystemv() || SupportsMetal()
|
||||
@@ -1549,6 +1560,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.type __test_end,@object
|
||||
|
||||
.section .commentprologue,"a",@progbits
|
||||
.globl kLegalNotices
|
||||
.type kLegalNotices,@object
|
||||
.hidden kLegalNotices
|
||||
kLegalNotices:/*
|
||||
|
||||
+31
-2
@@ -237,6 +237,7 @@ SECTIONS {
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
|
||||
.text . : {
|
||||
BYTE(0x90) /* TODO: fix blinkenlights symbol __map_phdrs */
|
||||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
@@ -289,6 +290,9 @@ SECTIONS {
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
|
||||
*(.rodata .rodata.*)
|
||||
*(.ubsan.types)
|
||||
@@ -338,6 +342,19 @@ SECTIONS {
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
/*END: Read Only Data */
|
||||
} :Rom
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
_tdata_end = .;
|
||||
}
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
_tbss_end = .;
|
||||
}
|
||||
|
||||
.data . : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
@@ -367,6 +384,15 @@ SECTIONS {
|
||||
} :Ram
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*BEGIN: payload (for now, only the APE loader) */
|
||||
.payload ALIGN(64) : {
|
||||
/* Loader */
|
||||
HIDDEN(ape_loader = .);
|
||||
KEEP(*(.ape.loader))
|
||||
. = ALIGN(64);
|
||||
HIDDEN(ape_loader_end = .);
|
||||
}
|
||||
/*END: payload */
|
||||
/*BEGIN: bss memory void */
|
||||
|
||||
.zip . : {
|
||||
@@ -472,10 +498,10 @@ HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
|
||||
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE);
|
||||
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000 - STACKSIZE);
|
||||
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_filesz = 0);
|
||||
HIDDEN(ape_stack_memsz = STACKSIZE);
|
||||
HIDDEN(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
|
||||
HIDDEN(ape_stack_align = 16);
|
||||
|
||||
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
|
||||
@@ -508,6 +534,9 @@ HIDDEN(ape_bss_filesz = 0);
|
||||
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
|
||||
HIDDEN(ape_bss_align = PAGESIZE);
|
||||
|
||||
SHSTUB2(ape_loader_dd_skip, RVA(ape_loader) / 64);
|
||||
SHSTUB2(ape_loader_dd_count, (ape_loader_end - ape_loader) / 64);
|
||||
|
||||
#if SupportsXnu()
|
||||
SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
|
||||
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
|
||||
|
||||
+20
-14
@@ -15,14 +15,12 @@
|
||||
|
||||
PKGS += APE
|
||||
|
||||
APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
APE = o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APE_BUILDSAFE = \
|
||||
$(APE_DEPS) \
|
||||
o/$(MODE)/ape/ape-buildsafe.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
APE_NO_MODIFY_SELF = \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
@@ -34,8 +32,10 @@ APELINK = \
|
||||
APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||
APE_SRCS = $(filter %.S,$(APE_FILES))
|
||||
APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
|
||||
APE_SRCS_C = ape/loader.c
|
||||
APE_SRCS_S = $(filter %.S,$(APE_FILES))
|
||||
APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
||||
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
@@ -48,14 +48,20 @@ o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
ape/relocations.h
|
||||
|
||||
$(APE_OBJS): $(BUILD_FILES) \
|
||||
ape/ape.mk
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S o/$(MODE)/ape/loader.elf
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_LOADER="\"o/$(MODE)/ape/loader.elf\"" -DAPE_NO_MODIFY_SELF $<
|
||||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_NO_MODIFY_SELF $<
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) $(cpp.flags) -fpie -Os -ffreestanding -mno-red-zone -fno-ident -fno-gnu-unique -c $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/ape/ape-buildsafe.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_BUILDSAFE $<
|
||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) $(cpp.flags) -Os -ffreestanding -mno-red-zone -fno-ident -fno-gnu-unique -c -S $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/ape/loader.elf: \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/loader1.o \
|
||||
ape/loader.lds
|
||||
@$(ELFLINK) -s -z max-page-size=0x10
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE) \
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef COSMOPOLITAN_APE_CONFIG_H_
|
||||
#define COSMOPOLITAN_APE_CONFIG_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define STATIC_SYMBOL(NAME, VALUE) \
|
||||
asm(".equ\t" NAME "," VALUE "\n\t" \
|
||||
".globl\t" NAME)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_APE_CONFIG_H_ */
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
/*-*- 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 2021 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/bits/bits.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/elf/struct/phdr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* @fileoverview APE embeddable loader for Linux and BSD, e.g.
|
||||
*
|
||||
* m=tiny
|
||||
* make -j8 MODE=$m o/$m/ape o/$m/examples/printargs.com
|
||||
* o/$m/ape/loader.elf o/$m/examples/printargs.com
|
||||
*
|
||||
* @note this can probably be used as a binfmt_misc interpreter
|
||||
*/
|
||||
|
||||
#define LINUX 0
|
||||
#define FREEBSD 1
|
||||
#define NETBSD 2
|
||||
#define OPENBSD 3
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS (os == LINUX ? 32 : 4096)
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
|
||||
#define __NR_read (os == LINUX ? 0 : 3)
|
||||
#define __NR_write (os == LINUX ? 1 : 4)
|
||||
#define __NR_open (os == LINUX ? 2 : 5)
|
||||
#define __NR_close (os == LINUX ? 3 : 6)
|
||||
#define __NR_exit (os == LINUX ? 60 : 1)
|
||||
#define __NR_mmap (os == LINUX ? 9 : os == FREEBSD ? 477 : 197)
|
||||
#define __NR_fstat \
|
||||
(os == LINUX ? 5 : os == FREEBSD ? 551 : os == OPENBSD ? 53 : 440)
|
||||
|
||||
static wontreturn void Exit(int os, long rc) {
|
||||
asm volatile("syscall"
|
||||
: /* no outputs */
|
||||
: "a"(__NR_exit), "D"(rc)
|
||||
: "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
static void Close(int os, long fd) {
|
||||
long ax, di;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=D"(di)
|
||||
: "0"(__NR_close), "1"(fd)
|
||||
: "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
|
||||
static long Read(int os, long fd, void *data, unsigned long size) {
|
||||
bool cf;
|
||||
long ax, di, si, dx;
|
||||
asm volatile("clc\n\t"
|
||||
"syscall"
|
||||
: "=@ccc"(cf), "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "1"(__NR_read), "2"(fd), "3"(data), "4"(size)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||
if (cf) ax = -ax;
|
||||
return ax;
|
||||
}
|
||||
|
||||
static void Write(int os, long fd, const void *data, unsigned long size) {
|
||||
long ax, di, si, dx;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"(__NR_write), "1"(fd), "2"(data), "3"(size)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
|
||||
static long Fstat(int os, long fd, union metastat *st) {
|
||||
long ax, di, si;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=D"(di), "=S"(si)
|
||||
: "0"(__NR_fstat), "1"(fd), "2"(st)
|
||||
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
static void Msyscall(int os, long p, long n) {
|
||||
long ax, di, si;
|
||||
if (os == OPENBSD) {
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax), "=D"(di), "=S"(si)
|
||||
: "0"(37), "1"(p), "2"(n)
|
||||
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
}
|
||||
|
||||
static long Open(int os, const char *path, long flags, long mode) {
|
||||
bool cf;
|
||||
long ax, di, si, dx;
|
||||
asm volatile("clc\n\t"
|
||||
"syscall"
|
||||
: "=@ccc"(cf), "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "1"(__NR_open), "2"(path), "3"(flags), "4"(mode)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||
if (cf) ax = -ax;
|
||||
return ax;
|
||||
}
|
||||
|
||||
static long Mmap(int os, long addr, long size, long prot, long flags, long fd,
|
||||
long off) {
|
||||
bool cf;
|
||||
long ax;
|
||||
register long flags_ asm("r10") = flags;
|
||||
register long fd_ asm("r8") = fd;
|
||||
register long off_ asm("r9") = off;
|
||||
asm volatile("push\t%%r9\n\t"
|
||||
"push\t%%r9\n\t"
|
||||
"clc\n\t"
|
||||
"syscall\n\t"
|
||||
"pop\t%%r9\n\t"
|
||||
"pop\t%%r9"
|
||||
: "=@ccc"(cf), "=a"(ax)
|
||||
: "1"(__NR_mmap), "D"(addr), "S"(size), "d"(prot), "r"(flags_),
|
||||
"r"(fd_), "r"(off_)
|
||||
: "rcx", "r11", "memory");
|
||||
if (cf) ax = -ax;
|
||||
return ax;
|
||||
}
|
||||
|
||||
static size_t GetFdSize(int os, int fd) {
|
||||
union metastat st;
|
||||
if (!Fstat(os, fd, &st)) {
|
||||
if (os == LINUX) {
|
||||
return st.linux.st_size;
|
||||
} else if (os == FREEBSD) {
|
||||
return st.freebsd.st_size;
|
||||
} else if (os == OPENBSD) {
|
||||
return st.openbsd.st_size;
|
||||
} else {
|
||||
return st.netbsd.st_size;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t Length(const char *s) {
|
||||
size_t n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void Emit(int os, const char *s) {
|
||||
Write(os, 2, s, Length(s));
|
||||
}
|
||||
|
||||
static void Log(int os, const char *s) {
|
||||
#ifndef NDEBUG
|
||||
Emit(os, "ape loader error: ");
|
||||
Emit(os, s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Spawn(int os, int fd, long *sp, char *b, struct Elf64_Ehdr *e) {
|
||||
size_t i;
|
||||
int prot, flags;
|
||||
long code, codesize;
|
||||
struct Elf64_Phdr *p;
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
Log(os, "EI_CLASS != ELFCLASS64\n");
|
||||
return;
|
||||
}
|
||||
if (e->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||
Log(os, "EI_CLASS != ELFCLASS64\n");
|
||||
return;
|
||||
}
|
||||
if (e->e_machine != EM_NEXGEN32E) {
|
||||
Log(os, "e_machine != EM_NEXGEN32E\n");
|
||||
return;
|
||||
}
|
||||
if (e->e_type != ET_EXEC) {
|
||||
Log(os, "e_type != ET_EXEC\n");
|
||||
return;
|
||||
}
|
||||
if (e->e_phoff + e->e_phnum * sizeof(*p) > 0x1000) {
|
||||
Log(os, "phnum out of bounds\n");
|
||||
return;
|
||||
}
|
||||
code = 0;
|
||||
codesize = 0;
|
||||
for (p = (struct Elf64_Phdr *)(b + e->e_phoff), i = e->e_phnum; i--;) {
|
||||
if (p[i].p_type != PT_LOAD) continue;
|
||||
if ((p[i].p_vaddr | p[i].p_filesz | p[i].p_memsz | p[i].p_offset) & 0xfff) {
|
||||
Log(os, "ape requires strict page size padding and alignment\n");
|
||||
return;
|
||||
}
|
||||
prot = 0;
|
||||
flags = MAP_FIXED | MAP_PRIVATE;
|
||||
if (p[i].p_flags & PF_R) {
|
||||
prot |= PROT_READ;
|
||||
}
|
||||
if (p[i].p_flags & PF_W) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
if (p[i].p_flags & PF_X) {
|
||||
prot |= PROT_EXEC;
|
||||
code = p[i].p_vaddr;
|
||||
codesize = p[i].p_filesz;
|
||||
}
|
||||
if (p[i].p_memsz > p[i].p_filesz) {
|
||||
if (Mmap(os, p[i].p_vaddr + p[i].p_filesz, p[i].p_memsz - p[i].p_filesz,
|
||||
prot, flags | MAP_ANONYMOUS, -1, 0) < 0) {
|
||||
Log(os, "bss mmap failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (p[i].p_filesz) {
|
||||
if (Mmap(os, p[i].p_vaddr, p[i].p_filesz, prot, flags, fd,
|
||||
p[i].p_offset) < 0) {
|
||||
Log(os, "image mmap failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Close(os, fd);
|
||||
Msyscall(os, code, codesize);
|
||||
sp[1] = sp[0] - 1;
|
||||
++sp;
|
||||
asm volatile("mov\t%2,%%rsp\n\t"
|
||||
"jmpq\t*%1"
|
||||
: /* no outputs */
|
||||
: "D"(os == FREEBSD ? sp : 0), "S"(e->e_entry), "d"(sp)
|
||||
: "memory");
|
||||
unreachable;
|
||||
}
|
||||
|
||||
void loader(long di, long *sp) {
|
||||
size_t size;
|
||||
long rc, *auxv;
|
||||
char *p, **argv;
|
||||
int c, i, fd, os, argc;
|
||||
union {
|
||||
struct Elf64_Ehdr ehdr;
|
||||
char p[0x1000];
|
||||
} u;
|
||||
os = 0;
|
||||
if (di) {
|
||||
os = FREEBSD;
|
||||
sp = (long *)di;
|
||||
}
|
||||
argc = *sp;
|
||||
argv = (char **)(sp + 1);
|
||||
auxv = (long *)(argv + argc + 1);
|
||||
for (;;) {
|
||||
if (!*auxv++) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!auxv[0]) {
|
||||
os = OPENBSD;
|
||||
}
|
||||
for (; auxv[0]; auxv += 2) {
|
||||
if (!os) {
|
||||
if (auxv[0] == AT_EXECFN_NETBSD) {
|
||||
os = NETBSD;
|
||||
if (argc > 1) {
|
||||
auxv[1] = (long)argv[1];
|
||||
}
|
||||
} else if (auxv[0] == AT_EXECFN_LINUX) {
|
||||
if (argc > 1) {
|
||||
auxv[1] = (long)argv[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argc < 2) {
|
||||
Emit(os, "usage: loader PROG [ARGS...]\n");
|
||||
} else if ((fd = Open(os, argv[1], O_RDONLY, 0)) < 0) {
|
||||
Log(os, "open failed\n");
|
||||
} else if ((rc = Read(os, fd, u.p, sizeof(u.p))) < 0) {
|
||||
Log(os, "read failed\n");
|
||||
} else if (rc != sizeof(u.p)) {
|
||||
Log(os, "file too small\n");
|
||||
} else if (READ32LE(u.p) == READ32LE("\177ELF")) {
|
||||
Spawn(os, fd, sp, u.p, &u.ehdr);
|
||||
} else {
|
||||
for (p = u.p; p < u.p + sizeof(u.p); ++p) {
|
||||
if (READ64LE(p) == READ64LE("printf '")) {
|
||||
for (i = 0, p += 8; p + 3 < u.p + sizeof(u.p) && (c = *p++) != '\'';) {
|
||||
if (c == '\\') {
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c = *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
u.p[i++] = c;
|
||||
}
|
||||
if (i >= 64 && READ32LE(u.p) == READ32LE("\177ELF")) {
|
||||
Spawn(os, fd, sp, u.p, &u.ehdr);
|
||||
Exit(os, 127);
|
||||
}
|
||||
}
|
||||
}
|
||||
Log(os, "could not find printf elf in first page\n");
|
||||
}
|
||||
Exit(os, 127);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 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. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
ENTRY(_start)
|
||||
OUTPUT_FORMAT(binary)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
filesz = . - ehdr;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
@@ -16,18 +16,80 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 202,_init_posix_memalign
|
||||
hook_posix_memalign:
|
||||
// APE Loader Executable Structure
|
||||
// Linux, FreeBSD, NetBSD, OpenBSD
|
||||
|
||||
.align 8
|
||||
ehdr: .ascii "\177ELF"
|
||||
.byte ELFCLASS64
|
||||
.byte ELFDATA2LSB
|
||||
.byte 1
|
||||
.byte ELFOSABI_FREEBSD
|
||||
.quad 0
|
||||
.endobj hook_posix_memalign,globl,hidden
|
||||
.previous
|
||||
.word ET_EXEC # e_type
|
||||
.word EM_NEXGEN32E # e_machine
|
||||
.long 1 # e_version
|
||||
.quad _start # e_entry
|
||||
.quad phdrs - ehdr # e_phoff
|
||||
.quad 0 # e_shoff
|
||||
.long 0 # e_flags
|
||||
.word 64 # e_ehsize
|
||||
.word 56 # e_phentsize
|
||||
.word 3 # e_phnum
|
||||
.word 0 # e_shentsize
|
||||
.word 0 # e_shnum
|
||||
.word 0 # e_shstrndx
|
||||
.endobj ehdr,globl
|
||||
|
||||
.init.start 202,_init_posix_memalign
|
||||
.hidden dlposix_memalign
|
||||
ezlea dlposix_memalign,ax
|
||||
stosq
|
||||
yoink free
|
||||
.init.end 202,_init_posix_memalign
|
||||
// memcpy(0x200000, loader); xor %eax,%eax; jmp 0x200000
|
||||
jg47h: .org 0x47
|
||||
.endobj jg47h
|
||||
|
||||
_start: mov %rsp,%rsi
|
||||
jmp loader
|
||||
.endfn _start,globl
|
||||
|
||||
.align 8
|
||||
phdrs: .long PT_LOAD # p_type
|
||||
.long PF_R|PF_X # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad ehdr # p_vaddr
|
||||
.quad ehdr # p_paddr
|
||||
.quad filesz # p_filesz
|
||||
.quad filesz # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
.long PT_GNU_STACK # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad 0 # p_vaddr
|
||||
.quad 0 # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad 0 # p_memsz
|
||||
.quad 16 # p_align
|
||||
.long PT_NOTE # p_type
|
||||
.long PF_R # p_flags
|
||||
.quad note - ehdr # p_offset
|
||||
.quad note # p_vaddr
|
||||
.quad note # p_paddr
|
||||
.quad notesize # p_filesz
|
||||
.quad notesize # p_memsz
|
||||
.quad 8 # p_align
|
||||
.endobj phdrs
|
||||
|
||||
note: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "OpenBSD"
|
||||
2: .align 4
|
||||
3: .long 0
|
||||
4: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "NetBSD"
|
||||
2: .align 4
|
||||
3: .long 901000000
|
||||
4: .endobj note
|
||||
notesize = . - note
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+59
-51
@@ -9,17 +9,13 @@
|
||||
# - Reasonably small
|
||||
# - Reasonably optimized
|
||||
# - Reasonably debuggable
|
||||
|
||||
ifeq ($(MODE),)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-Og
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Optimized Mode
|
||||
@@ -31,21 +27,39 @@ endif
|
||||
# - No memory corruption detection
|
||||
# - assert() / CHECK_xx() may leak code into binary for debuggability
|
||||
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
|
||||
|
||||
ifeq ($(MODE), opt)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-O3
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Optimized Linux Mode
|
||||
#
|
||||
# - `make MODE=optlinux`
|
||||
# - Turns on red zone
|
||||
# - Turns off backtraces
|
||||
# - Turns off function tracing
|
||||
# - Turns off support for older cpu models
|
||||
# - Turns off support for other operating systems
|
||||
ifeq ($(MODE), optlinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx \
|
||||
-DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += \
|
||||
-O3
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Release Mode
|
||||
@@ -61,19 +75,16 @@ endif
|
||||
# - DCHECK_xx() statements removed
|
||||
# - No memory corruption detection
|
||||
# - CHECK_xx() won't leak strings into binary
|
||||
|
||||
ifeq ($(MODE), rel)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
PYFLAGS += \
|
||||
-O1
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
@@ -86,19 +97,14 @@ endif
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
|
||||
ifeq ($(MODE), asan)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
@@ -110,26 +116,20 @@ endif
|
||||
# - Stack canaries
|
||||
# - No optimization (TODO)
|
||||
# - Enormous binaries
|
||||
|
||||
ifeq ($(MODE), dbg)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DMODE_DBG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-O2
|
||||
|
||||
-O2 \
|
||||
-fno-inline
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-pie
|
||||
|
||||
endif
|
||||
|
||||
# Tiny Mode
|
||||
@@ -143,20 +143,26 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tiny)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
|
||||
# Linux-Only Tiny Mode
|
||||
@@ -171,20 +177,21 @@ endif
|
||||
# - No portability
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
@@ -201,13 +208,14 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinuxbsd)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=113
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -230,13 +238,14 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinysysv)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=121
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -259,7 +268,6 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinynowin)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
|
||||
+15
-11
@@ -42,7 +42,6 @@
|
||||
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
|
||||
V ?= 1
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
|
||||
@@ -70,7 +69,7 @@ GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
ADDR2LINE = $(shell pwd)/o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell pwd)
|
||||
@@ -78,25 +77,29 @@ IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
HELLO := $(shell build/hello)
|
||||
TMPDIR := $(shell build/findtmp)
|
||||
SPAWNER := $(shell build/getcompile) -V$(shell build/getccversion $(CC))
|
||||
COMPILE = $(SPAWNER) $(QUOTA)
|
||||
COMPILE = $(SPAWNER) $(HARNESSFLAGS) $(QUOTA)
|
||||
|
||||
export ADDR2LINE
|
||||
export LC_ALL
|
||||
export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
export V
|
||||
|
||||
FTRACE = \
|
||||
-pg
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-schedule-insns2 \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-sanitize=all \
|
||||
-fwrapv
|
||||
|
||||
OLD_CODE = \
|
||||
@@ -128,9 +131,7 @@ DEFAULT_COPTS = \
|
||||
-fno-gnu-unique \
|
||||
-fstrict-aliasing \
|
||||
-fstrict-overflow \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-semantic-interposition \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
-fno-semantic-interposition
|
||||
|
||||
MATHEMATICAL = \
|
||||
-O3 \
|
||||
@@ -164,15 +165,18 @@ DEFAULT_ASFLAGS = \
|
||||
DEFAULT_LDFLAGS = \
|
||||
-static \
|
||||
-nostdlib \
|
||||
-m elf_x86_64 \
|
||||
-melf_x86_64 \
|
||||
--gc-sections \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker \
|
||||
-z max-page-size=0x1000
|
||||
-zmax-page-size=0x1000
|
||||
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
PYFLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ASONLYFLAGS = \
|
||||
-c \
|
||||
-g \
|
||||
@@ -205,7 +209,7 @@ cpp.flags = \
|
||||
$(CONFIG_CPPFLAGS) \
|
||||
$(CPPFLAGS) \
|
||||
$(OVERRIDE_CPPFLAGS) \
|
||||
-include libc/integral/normalize.inc
|
||||
-includelibc/integral/normalize.inc
|
||||
|
||||
copt.flags = \
|
||||
$(TARGET_ARCH) \
|
||||
|
||||
+1
-1
@@ -14,4 +14,4 @@
|
||||
# so it grants many small performance improvements.
|
||||
|
||||
mkdir -p o/tmp
|
||||
echo o/tmp
|
||||
echo $PWD/o/tmp
|
||||
+19
-10
@@ -16,7 +16,6 @@
|
||||
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
o/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
|
||||
o/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
@@ -31,12 +30,11 @@ o/%.o: o/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx
|
||||
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||
o/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
|
||||
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/%.zip.o: o/% ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
@@ -61,8 +59,9 @@ o/$(MODE)/%.s: o/$(MODE)/%.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTP
|
||||
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
|
||||
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
o/$(MODE)/%.cxx.o: %.c ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) -xc++ $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ansi.o: %.ansi.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
|
||||
@@ -73,13 +72,23 @@ o/$(MODE)/%.c2x.o: %.c2x.c ; @$(COMPILE) -AOBJECTIFY.c2x $(OBJECTIFY.c2x
|
||||
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -tT$@ $< $(TESTARGS)
|
||||
o/$(MODE)/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
|
||||
o/%.a:
|
||||
$(file >$@.args,$^)
|
||||
@$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ @$@.args
|
||||
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
|
||||
@$(COMPILE) -APYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
|
||||
@$(COMPILE) -APYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
@$(COMPILE) -ALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
@@ -0,0 +1,46 @@
|
||||
/*-*- 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 2021 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 "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Compresses 16-bit signed linear audio sample with a-Law.
|
||||
*
|
||||
* @param x is clamped to 16-bits of which the top 14 are considered
|
||||
* @return coded number in range [0..255]
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int alaw(int x) {
|
||||
int a, b, e, i;
|
||||
if ((a = x) < 0) a = ~a;
|
||||
a >>= 4;
|
||||
if (a > 15) {
|
||||
if ((i = a >> 5)) {
|
||||
b = (__builtin_clz(i) ^ 31) + 1;
|
||||
a >>= b;
|
||||
a -= 16;
|
||||
a += (b + 1) << 4;
|
||||
} else {
|
||||
e = 1;
|
||||
a -= 16;
|
||||
a += 16;
|
||||
}
|
||||
}
|
||||
if (x >= 0) a |= 128;
|
||||
return a ^ 85;
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
void *byte2double(long n, const void *p, double weight, double bias) {
|
||||
long i;
|
||||
double f, *dst;
|
||||
unsigned char *src;
|
||||
const unsigned char *src;
|
||||
if ((dst = valloc(n * sizeof(double)))) {
|
||||
for (src = p, i = 0; i < n; ++i) {
|
||||
f = src[i];
|
||||
|
||||
+3
-7
@@ -3,23 +3,19 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Digital Signal Processing.
|
||||
*/
|
||||
|
||||
int alaw(int);
|
||||
int unalaw(int);
|
||||
int mulaw(int);
|
||||
int unmulaw(int);
|
||||
void *double2byte(long, const void *, double, double) vallocesque;
|
||||
void *byte2double(long, const void *, double, double) vallocesque;
|
||||
|
||||
void *dct(float[8][8], float, float, float, float, float);
|
||||
void *dctjpeg(float[8][8]);
|
||||
|
||||
double det3(const double[3][3]) nosideeffect;
|
||||
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
|
||||
void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]);
|
||||
void *vmatmul3(double[restrict 3], const double[3], const double[3][3]);
|
||||
void *matvmul3(double[restrict 3], const double[3][3], const double[3]);
|
||||
|
||||
double rgb2stdtv(double) pureconst;
|
||||
double rgb2lintv(double) pureconst;
|
||||
double rgb2stdpc(double, double) pureconst;
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \
|
||||
do { \
|
||||
T z1, z2, z3, z4, z5, z11, z13; \
|
||||
T t0, t1, t2, t3, t4, t5, t6, t7, t8, t10, t11, t12, t13; \
|
||||
T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \
|
||||
t0 = A + H; \
|
||||
t7 = A - H; \
|
||||
t1 = B + G; \
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
*/
|
||||
void float2short(size_t n, short pcm16[n][8], const float binary32[n][8]) {
|
||||
size_t i, j;
|
||||
float f[8], w[8];
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
pcm16[i][j] =
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#define BIAS 0x84
|
||||
|
||||
// Encodes audio sample with µ-Law.
|
||||
//
|
||||
// This is both the highest quality and most widely supported
|
||||
// telephony codec, whose use was phased out in the 2000's in
|
||||
// favor of cost-saving GSM audio compression that was so bad
|
||||
// consumers were willing to pay more cash, for the privilege
|
||||
// of saving telcos even more money w/ text messaging. Mu Law
|
||||
// reduces PCM data to half its original size, by diminishing
|
||||
// audio bands not vocalized by human voice.
|
||||
//
|
||||
// @param %edi is pcm sample
|
||||
// @return %eax is uint8_t encoded sample
|
||||
mulaw: .leafprologue
|
||||
.profilable
|
||||
mov $BIAS,%eax
|
||||
xor %edx,%edx
|
||||
test %edi,%edi
|
||||
js 1f
|
||||
lea (%edi,%eax),%eax
|
||||
mov $0xFF,%dl
|
||||
jmp 2f
|
||||
1: sub %edi,%eax
|
||||
mov $0x7F,%dl
|
||||
2: mov %eax,%esi
|
||||
or $0xFF,%sil
|
||||
bsr %esi,%esi
|
||||
sub $7,%esi
|
||||
cmp $8,%esi
|
||||
jge 4f
|
||||
lea 3(%rdx),%ecx
|
||||
sar %cl,%eax
|
||||
and $0xF,%eax
|
||||
shl $4,%esi
|
||||
or %esi,%eax
|
||||
xor %edx,%eax
|
||||
3: .leafepilogue
|
||||
4: xor $0x7F,%dl
|
||||
mov %edx,%eax
|
||||
jmp 3b
|
||||
.endfn mulaw,globl
|
||||
.source __FILE__
|
||||
@@ -0,0 +1,40 @@
|
||||
/*-*- 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 2021 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 "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Compresses 16-bit signed linear audio sample with μ-Law.
|
||||
*
|
||||
* @param x is clamped to 16-bits of which the top 14 are considered
|
||||
* @return coded number in range [0..255]
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int mulaw(int x) {
|
||||
int b, i, a, s, l, h;
|
||||
a = x < 0 ? (~x >> 2) + 33 : (x >> 2) + 33;
|
||||
if (a > 8191) a = 8191;
|
||||
i = a >> 6;
|
||||
s = i ? (__builtin_clz(i) ^ 31) + 2 : 1;
|
||||
h = 8 - s;
|
||||
l = (a >> s) & 15;
|
||||
l = 15 - l;
|
||||
b = (h << 4) | l;
|
||||
if (x >= 0) b |= 128;
|
||||
return b;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*-*- 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 2021 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 "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Expands a-Law coded to audio sample.
|
||||
*
|
||||
* @param x is coded number masked to range [0..255]
|
||||
* @return 16-bit signed linear audio sample
|
||||
* @note generate lut to save 2 cycles
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int unalaw(int x) {
|
||||
int e, i, m;
|
||||
i = (x ^ 85) & 127;
|
||||
e = i >> 4;
|
||||
m = i & 15;
|
||||
if (e > 0) m += 16;
|
||||
m = (m << 4) + 8;
|
||||
if (e > 1) m = m << (e - 1);
|
||||
return x & 128 ? m : -m;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*-*- 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 2021 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 "dsp/core/core.h"
|
||||
#include "libc/bits/likely.h"
|
||||
|
||||
/**
|
||||
* Expands μ-Law coded to audio sample.
|
||||
*
|
||||
* @param x is coded number masked to range [0..255]
|
||||
* @return 16-bit signed linear audio sample
|
||||
* @note generate lut to save 2 cycles
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int unmulaw(int x) {
|
||||
int e, m, k, s;
|
||||
e = (~x >> 4) & 7;
|
||||
m = ~x & 15;
|
||||
k = 4 << (e + 1);
|
||||
s = (128 << e) + k * m + k / 2 - 4 * 33;
|
||||
return x & 128 ? s : -s;
|
||||
}
|
||||
+19
-19
@@ -591,24 +591,24 @@ void plm_video_decode_sequence_header(plm_video_t *self) {
|
||||
|
||||
self->has_sequence_header = true;
|
||||
|
||||
LOGF("%s:\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;",
|
||||
"New MPEG Sequence", "width", self->width, "height", self->height,
|
||||
"framerate", self->framerate, "pixel_aspect_ratio",
|
||||
self->pixel_aspect_ratio, "mb_size", self->mb_size, "mb_width",
|
||||
self->mb_width, "mb_height", self->mb_height, "luma_width",
|
||||
self->luma_width, "luma_height", self->luma_height, "chroma_width",
|
||||
self->chroma_width, "chroma_height", self->chroma_height);
|
||||
INFOF("%s:\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;",
|
||||
"New MPEG Sequence", "width", self->width, "height", self->height,
|
||||
"framerate", self->framerate, "pixel_aspect_ratio",
|
||||
self->pixel_aspect_ratio, "mb_size", self->mb_size, "mb_width",
|
||||
self->mb_width, "mb_height", self->mb_height, "luma_width",
|
||||
self->luma_width, "luma_height", self->luma_height, "chroma_width",
|
||||
self->chroma_width, "chroma_height", self->chroma_height);
|
||||
}
|
||||
|
||||
static void plm_video_copy_macroblock(plm_video_t *self, int motion_h,
|
||||
@@ -1082,7 +1082,7 @@ static plm_frame_t *plm_video_decode_impl(plm_video_t *self) {
|
||||
plm_frame_t *plm_video_decode(plm_video_t *self) {
|
||||
long double tsc;
|
||||
plm_frame_t *res;
|
||||
LOGF("plm_video_decode");
|
||||
INFOF("plm_video_decode");
|
||||
tsc = nowl();
|
||||
res = plm_video_decode_impl(self);
|
||||
plmpegdecode_latency_ = lroundl((nowl() - tsc) * 1e6l);
|
||||
|
||||
+2
-1
@@ -47,7 +47,8 @@ __m128 tty2rgbf_(struct TtyRgb rgbxt) {
|
||||
|
||||
static int rgb2xterm256_(int r, int g, int b) {
|
||||
int cerr, gerr, ir, ig, ib, gray, grai, cr, cg, cb, gv;
|
||||
gray = round(r * .299 + g * .587 + b * .114);
|
||||
gray = round(871024 / 4096299. * r + 8788810 / 12288897. * g +
|
||||
887015 / 12288897. * b);
|
||||
grai = gray > 238 ? 23 : (gray - 3) / 10;
|
||||
ir = r < 48 ? 0 : r < 115 ? 1 : (r - 35) / 40;
|
||||
ig = g < 48 ? 0 : g < 115 ? 1 : (g - 35) / 40;
|
||||
|
||||
+1
-1
@@ -739,7 +739,7 @@ static struct TtyRgb *CopyChunk(struct TtyRgb chunk[hasatleast 4],
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static noinline char *CopyRun(char *v, size_t n,
|
||||
static dontinline char *CopyRun(char *v, size_t n,
|
||||
struct TtyRgb lastchunk[hasatleast 4],
|
||||
const struct TtyRgb **c, size_t *x,
|
||||
struct TtyRgb *bg, struct TtyRgb *fg,
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ STATIC_YOINK("ssl_root_support");
|
||||
#define DFL_FILENAME "cert.crt"
|
||||
#define DFL_CA_FILE ""
|
||||
#define DFL_CRL_FILE ""
|
||||
#define DFL_CA_PATH "zip:usr/share/ssl/root"
|
||||
#define DFL_CA_PATH "/zip/usr/share/ssl/root"
|
||||
#define DFL_SERVER_NAME "localhost"
|
||||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Cosmopolitan C is just as awesome as Go!
|
||||
* Example contributed by @Keithcat1 (#266)
|
||||
*/
|
||||
main() {
|
||||
_defer(printf, "Done!\n");
|
||||
for (long i = 0; i < 100000; i++) {
|
||||
printf("%i ", i);
|
||||
_defer(free, malloc(100)); // longhand for _gc(malloc(100))
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -50,6 +50,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_OHMYPLUS \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
@@ -60,6 +61,7 @@ EXAMPLES_DIRECTDEPS = \
|
||||
LIBC_SYSV \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_UNICODE \
|
||||
@@ -69,12 +71,13 @@ EXAMPLES_DIRECTDEPS = \
|
||||
NET_HTTPS \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_QUICKJS \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_LINENOISE \
|
||||
THIRD_PARTY_LUA \
|
||||
THIRD_PARTY_MBEDTLS \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_QUICKJS \
|
||||
THIRD_PARTY_STB \
|
||||
THIRD_PARTY_XED \
|
||||
THIRD_PARTY_ZLIB \
|
||||
@@ -129,6 +132,16 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
|
||||
$(APE)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/hello.com.dbg: \
|
||||
$(EXAMPLES_DEPS) \
|
||||
o/$(MODE)/examples/hello.o \
|
||||
o/$(MODE)/examples/examples.pkg \
|
||||
$(CRT) \
|
||||
$(APE_NO_MODIFY_SELF)
|
||||
@$(APELINK)
|
||||
|
||||
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
|
||||
|
||||
$(EXAMPLES_OBJS): examples/examples.mk
|
||||
|
||||
usr/share/dict/words: usr/share/dict/words.gz
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
fputs("USAGE: EXEC.COM PROG ARGV₀ [ARGV₁...]\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
execv(argv[1], argv + 2);
|
||||
return 127;
|
||||
}
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
noinline void dostuff(const char *s) {
|
||||
dontinline void dostuff(const char *s) {
|
||||
int i, us;
|
||||
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
|
||||
for (i = 0; i < 5; ++i) {
|
||||
|
||||
+78
-52
@@ -9,12 +9,15 @@
|
||||
#endif
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/rand/xorshift.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
@@ -94,14 +97,6 @@ uint64_t knuth(void) {
|
||||
return a | b << 32;
|
||||
}
|
||||
|
||||
uint64_t vigna(void) {
|
||||
static uint64_t x;
|
||||
uint64_t z = (x += 0x9e3779b97f4a7c15);
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
uint64_t rngset64(void) {
|
||||
static unsigned i;
|
||||
static uint64_t s;
|
||||
@@ -130,66 +125,97 @@ uint64_t libc(void) {
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t kernel(void) {
|
||||
uint64_t GetRandom(void) {
|
||||
uint64_t x;
|
||||
CHECK_EQ(8, getrandom(&x, 8, GRND_NORDRND));
|
||||
CHECK_EQ(8, getrandom(&x, 8, 0));
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t hardware(void) {
|
||||
uint64_t x;
|
||||
CHECK_EQ(8, getrandom(&x, 8, GRND_NOSYSTEM));
|
||||
uint32_t python(void) {
|
||||
#define K 0 // 624 /* wut */
|
||||
#define N 624
|
||||
#define M 397
|
||||
static int index;
|
||||
static char once;
|
||||
static uint32_t mt[N];
|
||||
static const uint32_t mag01[2] = {0, 0x9908b0dfu};
|
||||
uint32_t y;
|
||||
int kk;
|
||||
if (!once) {
|
||||
char *sp;
|
||||
ssize_t rc;
|
||||
uint32_t i, j, k, s[K];
|
||||
mt[0] = 19650218;
|
||||
for (i = 1; i < N; i++) {
|
||||
mt[i] = (1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
|
||||
}
|
||||
if (K) {
|
||||
for (sp = (char *)s, i = 0; i < sizeof(s); i += rc) {
|
||||
if ((rc = getrandom(sp + i, sizeof(s) - i, 0)) == -1) {
|
||||
if (errno != EINTR) abort();
|
||||
}
|
||||
}
|
||||
for (i = 1, j = 0, k = MAX(N, K); k; k--) {
|
||||
mt[i] =
|
||||
(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525u)) + s[j] + j;
|
||||
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
||||
if (++j >= K) j = 0;
|
||||
}
|
||||
for (k = N - 1; k; k--) {
|
||||
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941u)) - i;
|
||||
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
||||
}
|
||||
mt[0] = 0x80000000;
|
||||
explicit_bzero(s, sizeof(s));
|
||||
}
|
||||
once = 1;
|
||||
}
|
||||
if (index >= N) {
|
||||
for (kk = 0; kk < N - M; kk++) {
|
||||
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
||||
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 1];
|
||||
}
|
||||
for (; kk < N - 1; kk++) {
|
||||
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
||||
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 1];
|
||||
}
|
||||
y = (mt[N - 1] & 0x80000000u) | (mt[0] & 0x7fffffffu);
|
||||
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 1];
|
||||
index = 0;
|
||||
}
|
||||
y = mt[index++];
|
||||
y ^= y >> 11;
|
||||
y ^= (y << 7) & 0x9d2c5680u;
|
||||
y ^= (y << 15) & 0xefc60000u;
|
||||
y ^= y >> 18;
|
||||
return y;
|
||||
#undef M
|
||||
#undef N
|
||||
#undef K
|
||||
}
|
||||
|
||||
uint64_t pythonx2(void) {
|
||||
uint64_t x = python();
|
||||
x <<= 32;
|
||||
x |= python();
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64_t rdrnd(void) {
|
||||
char cf;
|
||||
int i = 0;
|
||||
uint64_t x;
|
||||
CHECK(X86_HAVE(RDRND));
|
||||
for (;;) {
|
||||
asm volatile(CFLAG_ASM("rdrand\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return x;
|
||||
if (++i < 10) continue;
|
||||
asm volatile("pause");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t rdseed(void) {
|
||||
char cf;
|
||||
int i = 0;
|
||||
uint64_t x;
|
||||
CHECK(X86_HAVE(RDSEED));
|
||||
for (;;) {
|
||||
asm volatile(CFLAG_ASM("rdseed\t%1")
|
||||
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
||||
: /* no inputs */
|
||||
: "cc");
|
||||
if (cf) return x;
|
||||
if (++i < 10) continue;
|
||||
asm volatile("pause");
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct Function {
|
||||
const char *s;
|
||||
uint64_t (*f)(void);
|
||||
} kFunctions[] = {
|
||||
{"ape", ape}, //
|
||||
{"hardware", hardware}, //
|
||||
{"getrandom", GetRandom}, //
|
||||
{"inc", inc}, //
|
||||
{"kernel", kernel}, //
|
||||
{"knuth", knuth}, //
|
||||
{"libc", libc}, //
|
||||
{"moby", moby}, //
|
||||
{"mt19937", _mt19937}, //
|
||||
{"python", pythonx2}, //
|
||||
{"rand64", rand64}, //
|
||||
{"rdrand", rdrnd}, //
|
||||
{"rdrnd", rdrnd}, //
|
||||
{"rdrand", rdrand}, //
|
||||
{"rdrnd", rdrand}, //
|
||||
{"rdseed", rdseed}, //
|
||||
{"rngset64", rngset64}, //
|
||||
{"unixv6", unixv6}, //
|
||||
@@ -224,7 +250,7 @@ int main(int argc, char *argv[]) {
|
||||
break;
|
||||
case 'c':
|
||||
case 'n':
|
||||
count = strtoul(optarg, 0, 0);
|
||||
count = sizetol(optarg, 1024);
|
||||
break;
|
||||
case 'h':
|
||||
PrintUsage(stdout, EXIT_SUCCESS);
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ int main(int argc, char *argv[]) {
|
||||
luaL_openlibs(L);
|
||||
lua_pushcfunction(L, NativeAdd);
|
||||
lua_setglobal(L, "NativeAdd");
|
||||
luaL_dofile(L, "zip:examples/hellolua.lua");
|
||||
luaL_dofile(L, "/zip/examples/hellolua.lua");
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -145,7 +145,7 @@ void SpellChecker(void) {
|
||||
}
|
||||
|
||||
void LoadWords(void) {
|
||||
CHECK_NOTNULL((f = fopen("zip:usr/share/dict/words", "r")));
|
||||
CHECK_NOTNULL((f = fopen("/zip/usr/share/dict/words", "r")));
|
||||
while (getline(&line, &linesize, f) > 0) {
|
||||
critbit0_insert(&words, strtolower(chomp(line)));
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
* Here's an example usage:
|
||||
*
|
||||
* make -j8 o//examples/nc.com
|
||||
* printf 'GET /\r\n\r\n' | o//examples/nc.com justine.lol 80
|
||||
* printf 'GET /\r\nHost: justine.lol\r\n\r\n' | o//examples/nc.com justine.lol 80
|
||||
*
|
||||
* Once upon time we called this command "telnet"
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1818,7 +1818,7 @@ size_t FindZipGames(void) {
|
||||
!memcmp((ZIP_CFILE_NAME(zipos->map + cf) +
|
||||
ZIP_CFILE_NAMESIZE(zipos->map + cf) - 4),
|
||||
".nes", 4) &&
|
||||
(name = xasprintf("zip:%.*s", ZIP_CFILE_NAMESIZE(zipos->map + cf),
|
||||
(name = xasprintf("/zip/%.*s", ZIP_CFILE_NAMESIZE(zipos->map + cf),
|
||||
ZIP_CFILE_NAME(zipos->map + cf)))) {
|
||||
APPEND(&zipgames_.p, &zipgames_.i, &zipgames_.n, &name);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
@@ -70,6 +72,8 @@ int main(int argc, char *argv[], char **envp) {
|
||||
unsigned long *auxp;
|
||||
char fmt[64], **env;
|
||||
struct AuxiliaryValue *auxinfo;
|
||||
uint32_t varlen;
|
||||
char16_t var[PATH_MAX];
|
||||
printf("\nArguments:\n");
|
||||
for (i = 0; i < __argc; ++i) {
|
||||
printf(" ☼ %s\n", argv[i]);
|
||||
@@ -91,5 +95,6 @@ int main(int argc, char *argv[], char **envp) {
|
||||
printf(" ☼ kTmpPath = %`'s\n", kTmpPath);
|
||||
printf(" ☼ kNtSystemDirectory = %`'s\n", kNtSystemDirectory);
|
||||
printf(" ☼ kNtWindowsDirectory = %`'s\n", kNtWindowsDirectory);
|
||||
printf(" ☼ program_executable_name = %`'s\n", program_executable_name);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Actually Portable Python Tutorial
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This tutorial demonstrates how to compile Python apps as tiny
|
||||
# static multiplatform APE executables as small as 1.9m in size
|
||||
# using Cosmopolitan, which is a BSD-style multitenant codebase
|
||||
#
|
||||
# GETTING STARTED
|
||||
#
|
||||
# # run these commands after cloning the cosmo repo on linux
|
||||
# $ make -j8 o//examples/pyapp/pyapp.com
|
||||
# $ o//examples/pyapp/pyapp.com
|
||||
# cosmopolitan is cool!
|
||||
#
|
||||
# HOW IT WORKS
|
||||
#
|
||||
# $ pyobj.com -m -o pyapp.o pyapp.py
|
||||
# $ ld -static -nostdlib -T o//ape/ape.lds ape.o crt.o \
|
||||
# pyapp.o \
|
||||
# cosmopolitan-python-stage2.a \
|
||||
# cosmopolitan-sqlite3.a \
|
||||
# cosmopolitan-linenoise.a \
|
||||
# cosmopolitan-bzip2.a \
|
||||
# cosmopolitan-python-stage1.a \
|
||||
# cosmopolitan.a
|
||||
# $ ./pyapp.com
|
||||
# cosmopolitan is cool!
|
||||
#
|
||||
# NOTES
|
||||
#
|
||||
# If you enjoy this tutorial, let us know [email protected]. If
|
||||
# you're building something cool, then we can we can add you to
|
||||
# our .gitowners file which grants you commit access so you can
|
||||
# indepnedently maintain your package, as part of the mono-repo
|
||||
|
||||
PKGS += PYAPP
|
||||
PYAPP = $(PYAPP_DEPS) o/$(MODE)/examples/pyapp/pyapp.a
|
||||
PYAPP_COMS = o/$(MODE)/examples/pyapp/pyapp.com
|
||||
PYAPP_BINS = $(PYAPP_COMS) $(PYAPP_COMS:%=%.dbg)
|
||||
|
||||
# Specify our Cosmopolitan library dependencies
|
||||
#
|
||||
# - THIRD_PARTY_PYTHON_STAGE1 plus THIRD_PARTY_PYTHON_STAGE2 will
|
||||
# define the Python CAPI and supported standard library modules
|
||||
#
|
||||
PYAPP_DIRECTDEPS = \
|
||||
THIRD_PARTY_PYTHON_STAGE2
|
||||
|
||||
# Compute the transitive closure of dependencies. There's dozens of
|
||||
# other static libraries we need, in order to build a static binary
|
||||
# such as fmt.a, runtime.a, str.a etc. This magic statement figures
|
||||
# them all out and arranges them in the correct order.
|
||||
PYAPP_DEPS := $(call uniq,$(foreach x,$(PYAPP_DIRECTDEPS),$($(x))))
|
||||
|
||||
# # Asks PYOBJ.COM to turn our Python source into an ELF object which
|
||||
# # contains (a) embedded zip file artifacts of our .py file and .pyc
|
||||
# # which it it compiled; and (b) statically analyzed listings of our
|
||||
# # python namespaces and imports that GNU ld will use for tree shake
|
||||
# # NOTE: This code can be commented out since it's in build/rules.mk
|
||||
# o/$(MODE)/examples/pyapp/pyapp.o: examples/pyapp/pyapp.py o/$(MODE)/third_party/python/pyobj
|
||||
# o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
|
||||
|
||||
# We need to define how the repository source code path gets mapped
|
||||
# into an APE ZIP file path. By convention, we place Python modules
|
||||
# in `.python/` (which is accessible via open() system calls, using
|
||||
# the synthetic path `"/zip/.python/"`) which means that if we want
|
||||
# to turn `pyapp/pyapp.py` into `.python/pyapp.py` so it's imported
|
||||
# using `import pyapp` then we can simply append to PYOBJ.COM flags
|
||||
# flags above asking it to strip one directory component and prefix
|
||||
# Lastly be sure that whenever you use this variable override trick
|
||||
# you only do it to .o files, since otherwise it'll ruin everything
|
||||
# Passing -m to PYOBJ.COM causes a C main() function to get yoinked
|
||||
# and it means our Python module can no longer be used as a library
|
||||
o/$(MODE)/examples/pyapp/pyapp.o: PYFLAGS += -m -C2 -P.python
|
||||
|
||||
# Asks PACKAGE.COM to sanity check our DIRECTDEPS and symbol graph.
|
||||
# This program functions as an incremental linker. It also provides
|
||||
# enhancements to the object code that GCC generated similar to LTO
|
||||
# so be certain that your .com.dbg rule depends on the .pkg output!
|
||||
o/$(MODE)/examples/pyapp/pyapp.pkg: \
|
||||
o/$(MODE)/examples/pyapp/pyapp.o \
|
||||
$(foreach x,$(PYAPP_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
# Ask GNU LD to link our APE executable within an ELF binary shell.
|
||||
# The CRT and APE dependencies are special dependencies that define
|
||||
# your _start() / WinMain() entrpoints as well as APE linker script
|
||||
o/$(MODE)/examples/pyapp/pyapp.com.dbg: \
|
||||
$(PYAPP_DEPS) \
|
||||
o/$(MODE)/examples/pyapp/pyapp.pkg \
|
||||
o/$(MODE)/examples/pyapp/pyapp.o \
|
||||
$(CRT) \
|
||||
$(APE)
|
||||
$(LINK) $(LINKARGS) -o $@
|
||||
|
||||
# # Unwrap the APE .COM binary, that's embedded within the linked file
|
||||
# # NOTE: This line can be commented out, since it's in build/rules.mk
|
||||
# o/$(MODE)/examples/pyapp/pyapp.com: \
|
||||
# o/$(MODE)/examples/pyapp/pyapp.com.dbg
|
||||
# $(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
# Ensure that build config changes will invalidate build artifacts.
|
||||
o/$(MODE)/examples/pyapp/pyapp.o: \
|
||||
examples/pyapp/pyapp.mk
|
||||
|
||||
# By convention we want to be able to say `make -j8 o//examples/pyapp`
|
||||
# and have it build all targets the package defines.
|
||||
.PHONY: o/$(MODE)/examples/pyapp
|
||||
o/$(MODE)/examples/pyapp: \
|
||||
o/$(MODE)/examples/pyapp/pyapp.com \
|
||||
o/$(MODE)/examples/pyapp/pyapp.com.dbg
|
||||
@@ -0,0 +1,4 @@
|
||||
def main():
|
||||
print('cosmopolitan is cool!')
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Stack Overflow Demo
|
||||
*/
|
||||
|
||||
#define N INT_MAX
|
||||
|
||||
STATIC_STACK_SIZE(FRAMESIZE);
|
||||
|
||||
int A(int f(), int n) {
|
||||
if (n < N) {
|
||||
return f(f, n + 1) - 1;
|
||||
} else {
|
||||
return N;
|
||||
}
|
||||
}
|
||||
|
||||
int (*Ap)(int (*)(), int) = A;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
return !!Ap(Ap, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
error: Uncaught SIGSEGV (Stack Overflow) on rhel5 pid 368
|
||||
./o//examples/stackoverflow.com
|
||||
EUNKNOWN[No error information][0]
|
||||
Linux rhel5 2.6.18-8.el5 #1 SMP Thu Mar 15 19:46:53 EDT 2007
|
||||
|
||||
0x0000000000406896: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
0x0000000000406898: A at examples/stackoverflow.c:24
|
||||
etc. etc.
|
||||
|
||||
RAX 0000000000000000 RBX 0000000000000001 RDI 000000000040687e ST(0) 0.0
|
||||
RCX 0000000000417125 RDX 000000000041cd70 RSI 0000000000000efe ST(1) 0.0
|
||||
RBP 00006ffffffe1000 RSP 00006ffffffe1000 RIP 0000000000406897 ST(2) 0.0
|
||||
R8 0000000000000000 R9 0000000000000022 R10 0000000000000008 ST(3) 0.0
|
||||
R11 0000000000000293 R12 0000000000000001 R13 00007ffc70b4fc48 ST(4) 0.0
|
||||
R14 00007ffc70b4fc58 R15 00007ffc70b4fd18 VF IF
|
||||
|
||||
XMM0 00000000000000000000000000000000 XMM8 00000000000000000000000000000000
|
||||
XMM1 ffffffffffffeb030000000000000000 XMM9 00000000000000000000000000000000
|
||||
XMM2 0000000000000000ffffffffffffffff XMM10 00000000000000000000000000000000
|
||||
XMM3 00000000000000000000000000000000 XMM11 00000000000000000000000000000000
|
||||
XMM4 00000000000000000000000000000000 XMM12 00000000000000000000000000000000
|
||||
XMM5 00000000000000000000000000000000 XMM13 00000000000000000000000000000000
|
||||
XMM6 00000000000000000000000000000000 XMM14 00000000000000000000000000000000
|
||||
XMM7 00000000000000000000000000000000 XMM15 00000000000000000000000000000000
|
||||
|
||||
100080000000-100080030000 rw-pa-- 3x automap
|
||||
6ffffffe0000-6fffffff0000 rw-paSF 1x stack
|
||||
# 4 frames mapped w/ 0 frames gapped
|
||||
*/
|
||||
+46
-5
@@ -10,10 +10,13 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
@@ -22,38 +25,76 @@
|
||||
* This demonstrates the more powerful aspects of the printf() DSL.
|
||||
*/
|
||||
|
||||
bool numeric;
|
||||
|
||||
const char *DescribeFileType(unsigned mode) {
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFIFO:
|
||||
return "S_IFIFO"; /* pipe */
|
||||
case S_IFCHR:
|
||||
return "S_IFCHR"; /* character device */
|
||||
case S_IFDIR:
|
||||
return "S_IFDIR"; /* directory */
|
||||
case S_IFBLK:
|
||||
return "S_IFBLK"; /* block device */
|
||||
case S_IFREG:
|
||||
return "S_IFREG"; /* regular file */
|
||||
case S_IFLNK:
|
||||
return "S_IFLNK"; /* symbolic link */
|
||||
case S_IFSOCK:
|
||||
return "S_IFSOCK"; /* socket */
|
||||
default:
|
||||
return "wut";
|
||||
}
|
||||
}
|
||||
|
||||
void PrintFileMetadata(const char *pathname, struct stat *st) {
|
||||
int fd;
|
||||
printf("\n%s:", pathname);
|
||||
CHECK_NE(-1, stat(pathname, st));
|
||||
if (numeric) {
|
||||
fd = atoi(pathname);
|
||||
CHECK_NE(-1, fstat(fd, st), "fd=%d", fd);
|
||||
} else {
|
||||
CHECK_NE(-1, stat(pathname, st), "pathname=%s", pathname);
|
||||
}
|
||||
printf("\n"
|
||||
"%-32s%,ld\n"
|
||||
"%-32s%,ld\n"
|
||||
"%-32s%#lx\n"
|
||||
"%-32s%#lx\n"
|
||||
"%-32s%ld\n"
|
||||
"%-32s%#o\n"
|
||||
"%-32s%#o (%s)\n"
|
||||
"%-32s%d\n"
|
||||
"%-32s%d\n"
|
||||
"%-32s%d\n"
|
||||
"%-32s%d\n"
|
||||
"%-32s%ld\n"
|
||||
"%-32s%ld\n"
|
||||
"%-32s%s\n"
|
||||
"%-32s%s\n"
|
||||
"%-32s%s\n"
|
||||
"%-32s%s\n",
|
||||
"bytes in file", st->st_size, "physical bytes", st->st_blocks * 512,
|
||||
"device id w/ file", st->st_dev, "inode", st->st_ino,
|
||||
"hard link count", st->st_nlink, "mode / permissions", st->st_mode,
|
||||
"owner id", st->st_uid, "group id", st->st_gid,
|
||||
DescribeFileType(st->st_mode), "owner id", st->st_uid, "group id",
|
||||
st->st_gid, "flags", st->st_flags, "gen", st->st_gen,
|
||||
"device id (if special)", st->st_rdev, "block size", st->st_blksize,
|
||||
"access time", _gc(xiso8601(&st->st_atim)), "modified time",
|
||||
_gc(xiso8601(&st->st_mtim)), "c[omplicated]time",
|
||||
_gc(xiso8601(&st->st_ctim)));
|
||||
_gc(xiso8601(&st->st_ctim)), "birthtime",
|
||||
_gc(xiso8601(&st->st_birthtim)));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
size_t i;
|
||||
struct stat st;
|
||||
for (i = 1; i < argc; ++i) {
|
||||
PrintFileMetadata(argv[i], &st);
|
||||
if (!strcmp(argv[i], "-n")) {
|
||||
numeric = true;
|
||||
} else {
|
||||
PrintFileMetadata(argv[i], &st);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/thread/create.h"
|
||||
#include "libc/thread/self.h"
|
||||
#include "libc/thread/detach.h"
|
||||
#include "libc/thread/join.h"
|
||||
#include "libc/thread/sem.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
cthread_sem_t semaphore;
|
||||
|
||||
__thread int test_tls = 0x12345678;
|
||||
|
||||
int worker(void* arg) {
|
||||
void* p;
|
||||
arch_prctl(ARCH_GET_FS, &p);
|
||||
cthread_sem_signal(&semaphore);
|
||||
|
||||
cthread_t self = cthread_self();
|
||||
int tid = self->tid;
|
||||
sleep(1);
|
||||
//sleep(10000);
|
||||
printf("[%p] %d -> 0x%x\n", self, tid, test_tls);
|
||||
(void)arg;
|
||||
return 4;
|
||||
}
|
||||
|
||||
int main() {
|
||||
cthread_t self = cthread_self();
|
||||
int tid = self->tid;
|
||||
printf("[%p] %d -> 0x%x\n", self, tid, test_tls);
|
||||
cthread_sem_init(&semaphore, 0);
|
||||
|
||||
cthread_t thread;
|
||||
int rc = cthread_create(&thread, NULL, &worker, NULL);
|
||||
if (rc == 0) {
|
||||
cthread_sem_wait(&semaphore, 0, NULL);
|
||||
//printf("thread created: %p\n", thread);
|
||||
sleep(1);
|
||||
#if 1
|
||||
cthread_join(thread, &rc);
|
||||
#else
|
||||
rc = cthread_detach(thread);
|
||||
sleep(2);
|
||||
#endif
|
||||
cthread_sem_signal(&semaphore);
|
||||
cthread_sem_wait(&semaphore, 0, NULL);
|
||||
//printf("thread joined: %p -> %d\n", thread, rc);
|
||||
} else {
|
||||
printf("ERROR: thread could not be started: %d\n", rc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
/**
|
||||
* @fileoverview command for showing how long a command takes
|
||||
*
|
||||
* This offers the following improvements over the existing `time`
|
||||
* command that's incorporated into most shells:
|
||||
*
|
||||
* - This will show microseconds if seconds < 1
|
||||
* - This will launch APE binaries on systems with broken libc execv()
|
||||
*/
|
||||
|
||||
#define WRITE(FD, STR) write(FD, STR, strlen(STR))
|
||||
|
||||
void OnChild(void *arg) {
|
||||
char **argv = arg;
|
||||
execv(argv[0], argv);
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
long double GetTimeval(struct timeval t) {
|
||||
return t.tv_sec + t.tv_usec * 1e-6l;
|
||||
}
|
||||
|
||||
void PrintMetric(const char *name, long double d) {
|
||||
char buf[256], *p = buf;
|
||||
long mins, secs, mils, mics;
|
||||
mins = d / 60;
|
||||
secs = fmodl(d, 60);
|
||||
mils = fmodl(d * 1000, 1000);
|
||||
mics = fmodl(d * 1000000, 1000);
|
||||
p = stpcpy(p, name), *p++ = '\t';
|
||||
p += int64toarray_radix10(mins, p), *p++ = 'm';
|
||||
p += int64toarray_radix10(secs, p), *p++ = '.';
|
||||
*p++ = '0' + mils / 100;
|
||||
*p++ = '0' + mils / 10 % 10;
|
||||
*p++ = '0' + mils % 10;
|
||||
if (!secs) {
|
||||
*p++ = '0' + mics / 100;
|
||||
*p++ = '0' + mics / 10 % 10;
|
||||
*p++ = '0' + mics % 10;
|
||||
}
|
||||
*p++ = 's';
|
||||
*p++ = '\n';
|
||||
write(2, buf, p - buf);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ws;
|
||||
char *exepath;
|
||||
struct rusage r;
|
||||
long double real;
|
||||
char exebuf[PATH_MAX];
|
||||
if (argc >= 2) {
|
||||
if ((exepath = commandv(argv[1], exebuf))) {
|
||||
real = nowl();
|
||||
argv[1] = exepath;
|
||||
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {
|
||||
PrintMetric("real", nowl() - real);
|
||||
PrintMetric("user", GetTimeval(r.ru_utime));
|
||||
PrintMetric("sys", GetTimeval(r.ru_stime));
|
||||
if (WIFEXITED(ws)) {
|
||||
return WEXITSTATUS(ws);
|
||||
} else {
|
||||
return 128 + WTERMSIG(ws);
|
||||
}
|
||||
} else {
|
||||
perror("xvspawn");
|
||||
return 127;
|
||||
}
|
||||
} else {
|
||||
perror(argv[1]);
|
||||
return 127;
|
||||
}
|
||||
} else {
|
||||
WRITE(2, "Usage: ");
|
||||
WRITE(2, argv[0]);
|
||||
WRITE(2, " PROG [ARGS...]\n");
|
||||
return EX_USAGE;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define CTRL(C) ((C) ^ 0b01000000)
|
||||
#define ENABLE_SAFE_PASTE "\e[?2004h"
|
||||
#define ENABLE_MOUSE_TRACKING "\e[?1000;1002;1015;1006h"
|
||||
#define DISABLE_MOUSE_TRACKING "\e[?1000;1002;1015;1006l"
|
||||
#define PROBE_DISPLAY_SIZE "\e7\e[9979;9979H\e[6n\e8"
|
||||
@@ -71,6 +72,7 @@ int rawmode(void) {
|
||||
t.c_cflag |= CS8;
|
||||
t.c_iflag |= IUTF8;
|
||||
ioctl(1, TCSETS, &t);
|
||||
write(1, ENABLE_SAFE_PASTE, strlen(ENABLE_SAFE_PASTE));
|
||||
write(1, ENABLE_MOUSE_TRACKING, strlen(ENABLE_MOUSE_TRACKING));
|
||||
write(1, PROBE_DISPLAY_SIZE, strlen(PROBE_DISPLAY_SIZE));
|
||||
return 0;
|
||||
|
||||
+141
-35
@@ -111,6 +111,8 @@
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
@@ -125,6 +127,7 @@
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/paths.h"
|
||||
@@ -132,6 +135,7 @@
|
||||
#include "libc/runtime/sysconf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
@@ -141,6 +145,7 @@
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
#include "third_party/linenoise/linenoise.h"
|
||||
#include "third_party/musl/passwd.h"
|
||||
|
||||
#define likely(expr) __builtin_expect(!!(expr), 1)
|
||||
@@ -597,30 +602,16 @@
|
||||
* shell. If SHELL is defined, we try to map the standard UNIX library
|
||||
* routines to ash routines using defines.
|
||||
*/
|
||||
/* #undef stdout /\* TODO(jart): XXX *\/ */
|
||||
/* #undef stderr */
|
||||
/* #undef putc */
|
||||
/* #undef putchar */
|
||||
#undef fileno
|
||||
/* #define stdout out1 */
|
||||
/* #define stderr out2 */
|
||||
#undef printf
|
||||
#define printf out1fmt
|
||||
/* #define putc(c, file) outc(c, file) */
|
||||
/* #define putchar(c) out1c(c) */
|
||||
#define FILE struct output
|
||||
#define fileno(f) ((f)->fd)
|
||||
/* #define ferror outerr */
|
||||
#define Printf out1fmt
|
||||
#define INITARGS(argv)
|
||||
#define setprogname(s)
|
||||
#define getprogname() commandname
|
||||
|
||||
#define setlocate(l, s) 0
|
||||
#define equal(s1, s2) (strcmp(s1, s2) == 0)
|
||||
/* #define getenv(p) bltinlookup((p), 0) */
|
||||
#define isodigit(c) ((c) >= '0' && (c) <= '7')
|
||||
#define octtobin(c) ((c) - '0')
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
#define equal(s1, s2) (!strcmp(s1, s2))
|
||||
#define isodigit(c) ((c) >= '0' && (c) <= '7')
|
||||
#define octtobin(c) ((c) - '0')
|
||||
#define scopy(s1, s2) ((void)strcpy(s2, s1))
|
||||
|
||||
#define TRACE(param)
|
||||
/* #define TRACE(param) \ */
|
||||
@@ -1030,6 +1021,7 @@ struct t_op {
|
||||
│ cosmopolitan § the unbourne shell » bss ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
static int inter;
|
||||
static char **argptr; /* argument list for builtin commands */
|
||||
static char **gargv;
|
||||
static char **t_wp;
|
||||
@@ -1827,7 +1819,7 @@ printfesque(3) static int fmtstr(char *outbuf, unsigned length, const char *fmt,
|
||||
return ret > (int)length ? length : ret;
|
||||
}
|
||||
|
||||
printfesque(2) static int xasprintf(char **sp, const char *fmt, ...) {
|
||||
printfesque(2) static int Xasprintf(char **sp, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int ret;
|
||||
va_start(ap, fmt);
|
||||
@@ -5629,12 +5621,128 @@ static int pgetc2() {
|
||||
return c;
|
||||
}
|
||||
|
||||
static void AddUniqueCompletion(linenoiseCompletions *c, char *s) {
|
||||
size_t i;
|
||||
if (!s) return;
|
||||
for (i = 0; i < c->len; ++i) {
|
||||
if (!strcmp(s, c->cvec[i])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
c->cvec = realloc(c->cvec, ++c->len * sizeof(*c->cvec));
|
||||
c->cvec[c->len - 1] = s;
|
||||
}
|
||||
|
||||
static void CompleteCommand(const char *p, const char *q, const char *b, linenoiseCompletions *c) {
|
||||
DIR *d;
|
||||
size_t i;
|
||||
struct dirent *e;
|
||||
const char *x, *y, *path;
|
||||
struct tblentry **pp, *cmdp;
|
||||
for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
|
||||
for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
|
||||
if (cmdp->cmdtype >= 0 && !strncmp(cmdp->cmdname, p, q - p)) {
|
||||
AddUniqueCompletion(c, strdup(cmdp->cmdname));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(kBuiltinCmds); ++i) {
|
||||
if (!strncmp(kBuiltinCmds[i].name, p, q - p)) {
|
||||
AddUniqueCompletion(c, strdup(kBuiltinCmds[i].name));
|
||||
}
|
||||
}
|
||||
for (y = x = lookupvar("PATH"); *y; x = y + 1) {
|
||||
if ((path = strndup(x, (y = strchrnul(x, ':')) - x))) {
|
||||
if ((d = opendir(path))) {
|
||||
while ((e = readdir(d))) {
|
||||
if (e->d_type == DT_REG && !strncmp(e->d_name, p, q - p)) {
|
||||
AddUniqueCompletion(c, strdup(e->d_name));
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CompleteFilename(const char *p, const char *q, const char *b, linenoiseCompletions *c) {
|
||||
DIR *d;
|
||||
char *buf;
|
||||
const char *g;
|
||||
struct dirent *e;
|
||||
if ((buf = malloc(512))) {
|
||||
if ((g = memrchr(p, '/', q - p))) {
|
||||
*(char *)mempcpy(buf, p, MIN(g - p, 511)) = 0;
|
||||
p = ++g;
|
||||
} else {
|
||||
strcpy(buf, ".");
|
||||
}
|
||||
if ((d = opendir(buf))) {
|
||||
while ((e = readdir(d))) {
|
||||
if (!strcmp(e->d_name, ".")) continue;
|
||||
if (!strcmp(e->d_name, "..")) continue;
|
||||
if (!strncmp(e->d_name, p, q - p)) {
|
||||
snprintf(buf, 512, "%.*s%s%s", p - b, b, e->d_name, e->d_type == DT_DIR ? "/" : "");
|
||||
AddUniqueCompletion(c, strdup(buf));
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void ShellCompletion(const char *p, linenoiseCompletions *c) {
|
||||
bool slashed;
|
||||
const char *q, *b;
|
||||
struct tblentry **pp, *cmdp;
|
||||
for (slashed = false, b = p, q = (p += strlen(p)); p > b; --p) {
|
||||
if (p[-1] == '/' && p[-1] == '\\') slashed = true;
|
||||
if (!isalnum(p[-1]) && (p[-1] != '.' && p[-1] != '_' && p[-1] != '-' && p[-1] != '+' &&
|
||||
p[-1] != '[' && p[-1] != '/' && p[-1] != '\\')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (b == p && !slashed) {
|
||||
CompleteCommand(p, q, b, c);
|
||||
} else {
|
||||
CompleteFilename(p, q, b, c);
|
||||
}
|
||||
}
|
||||
|
||||
static char *ShellHint(const char *p, const char **ansi1, const char **ansi2) {
|
||||
char *h = 0;
|
||||
linenoiseCompletions c = {0};
|
||||
ShellCompletion(p, &c);
|
||||
if (c.len == 1) {
|
||||
h = strdup(c.cvec[0] + strlen(p));
|
||||
}
|
||||
linenoiseFreeCompletions(&c);
|
||||
return h;
|
||||
}
|
||||
|
||||
static ssize_t preadfd(void) {
|
||||
ssize_t nr;
|
||||
char *buf = parsefile->buf;
|
||||
char *p, *buf = parsefile->buf;
|
||||
parsefile->nextc = buf;
|
||||
retry:
|
||||
nr = read(parsefile->fd, buf, IBUFSIZ - 1);
|
||||
if (!parsefile->fd && isatty(0)) {
|
||||
linenoiseSetFreeHintsCallback(free);
|
||||
linenoiseSetHintsCallback(ShellHint);
|
||||
linenoiseSetCompletionCallback(ShellCompletion);
|
||||
if ((p = linenoiseWithHistory("$ ", "unbourne"))) {
|
||||
nr = min(strlen(p), IBUFSIZ - 2);
|
||||
memcpy(buf, p, nr);
|
||||
buf[nr++] = '\n';
|
||||
free(p);
|
||||
} else {
|
||||
write(1, "\n", 1);
|
||||
nr = 0;
|
||||
}
|
||||
} else {
|
||||
nr = read(parsefile->fd, buf, IBUFSIZ - 1);
|
||||
}
|
||||
if (nr < 0) {
|
||||
if (errno == EINTR) goto retry;
|
||||
if (parsefile->fd == 0 && errno == EAGAIN) {
|
||||
@@ -7036,12 +7144,12 @@ static int readcmd(int argc, char **argv) {
|
||||
if (prompt && isatty(0)) {
|
||||
outstr(prompt, out2);
|
||||
}
|
||||
if (*(ap = argptr) == NULL) sh_error("arg count");
|
||||
if (!*(ap = argptr)) sh_error("arg count");
|
||||
status = 0;
|
||||
STARTSTACKSTR(p);
|
||||
goto start;
|
||||
for (;;) {
|
||||
switch (read(STDIN_FILENO, &c, 1)) {
|
||||
switch (read(0, &c, 1)) {
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
@@ -7051,7 +7159,7 @@ static int readcmd(int argc, char **argv) {
|
||||
status = 1;
|
||||
goto out;
|
||||
}
|
||||
if (c == '\0') continue;
|
||||
if (!c) continue;
|
||||
if (newloc >= startloc) {
|
||||
if (c == '\n') goto resetbs;
|
||||
goto put;
|
||||
@@ -8820,7 +8928,7 @@ static void setprompt(int which) {
|
||||
int show;
|
||||
needprompt = 0;
|
||||
whichprompt = which;
|
||||
show = 1;
|
||||
show = 0;
|
||||
if (show) {
|
||||
pushstackmark(&smark, stackblocksize());
|
||||
outstr(getprompt(NULL), out2);
|
||||
@@ -9361,13 +9469,13 @@ static void sigblockall(sigset_t *oldmask) {
|
||||
{ \
|
||||
switch ((char *)param - (char *)array) { \
|
||||
default: \
|
||||
(void)printf(f, array[0], array[1], func); \
|
||||
(void)Printf(f, array[0], array[1], func); \
|
||||
break; \
|
||||
case sizeof(*param): \
|
||||
(void)printf(f, array[0], func); \
|
||||
(void)Printf(f, array[0], func); \
|
||||
break; \
|
||||
case 0: \
|
||||
(void)printf(f, func); \
|
||||
(void)Printf(f, func); \
|
||||
break; \
|
||||
} \
|
||||
}
|
||||
@@ -9377,13 +9485,13 @@ static void sigblockall(sigset_t *oldmask) {
|
||||
int ret; \
|
||||
switch ((char *)param - (char *)array) { \
|
||||
default: \
|
||||
ret = xasprintf(sp, f, array[0], array[1], func); \
|
||||
ret = Xasprintf(sp, f, array[0], array[1], func); \
|
||||
break; \
|
||||
case sizeof(*param): \
|
||||
ret = xasprintf(sp, f, array[0], func); \
|
||||
ret = Xasprintf(sp, f, array[0], func); \
|
||||
break; \
|
||||
case 0: \
|
||||
ret = xasprintf(sp, f, func); \
|
||||
ret = Xasprintf(sp, f, func); \
|
||||
break; \
|
||||
} \
|
||||
ret; \
|
||||
@@ -9996,7 +10104,7 @@ static int timescmd() {
|
||||
struct tms buf;
|
||||
long int clk_tck = sysconf(_SC_CLK_TCK);
|
||||
times(&buf);
|
||||
printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", (int)(buf.tms_utime / clk_tck / 60),
|
||||
Printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", (int)(buf.tms_utime / clk_tck / 60),
|
||||
((double)buf.tms_utime) / clk_tck, (int)(buf.tms_stime / clk_tck / 60),
|
||||
((double)buf.tms_stime) / clk_tck, (int)(buf.tms_cutime / clk_tck / 60),
|
||||
((double)buf.tms_cutime) / clk_tck, (int)(buf.tms_cstime / clk_tck / 60),
|
||||
@@ -10788,8 +10896,6 @@ static int exitcmd(int argc, char **argv) {
|
||||
* is used to figure out how far we had gotten.
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
showcrashreports();
|
||||
unsetenv("PS1");
|
||||
char *shinit;
|
||||
volatile int state;
|
||||
struct jmploc jmploc;
|
||||
|
||||
@@ -21,7 +21,7 @@ forceinline void *bisect(const void *k, const void *data, size_t n, size_t size,
|
||||
} else if (c < 0) {
|
||||
r = m - 1;
|
||||
} else {
|
||||
return p + m * size;
|
||||
return (char *)p + m * size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ different_byte_found:
|
||||
struct CritbitNode *newnode = malloc(sizeof(struct CritbitNode));
|
||||
newnode->byte = newbyte;
|
||||
newnode->otherbits = newotherbits;
|
||||
newnode->child[1 - newdirection] = ubytes;
|
||||
newnode->child[1 - newdirection] = (void*)ubytes;
|
||||
void **wherep = &t->root;
|
||||
for (;;) {
|
||||
unsigned char *wp = *wherep;
|
||||
|
||||
@@ -39,5 +39,5 @@ char *critbit0_get(struct critbit0 *t, const char *u) {
|
||||
const int direction = (1 + (q->otherbits | c)) >> 8;
|
||||
p = q->child[direction];
|
||||
}
|
||||
return strncmp(u, (const char *)p, ulen) == 0 ? (const char *)p : NULL;
|
||||
return strncmp(u, (char *)p, ulen) == 0 ? (char *)p : NULL;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/alg/arraylist2.internal.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -38,7 +39,7 @@ char *replacestr(const char *s, const char *needle, const char *replacement) {
|
||||
nlen = strlen(needle);
|
||||
rlen = strlen(replacement);
|
||||
res_i = 0;
|
||||
res_n = max(left, 32);
|
||||
res_n = MAX(left, 32);
|
||||
if ((res_p = malloc(res_n * sizeof(char)))) {
|
||||
do {
|
||||
if (!(p2 = memmem(p1, left, needle, nlen))) break;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*-*- 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 2021 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/bits/bits.h"
|
||||
|
||||
/**
|
||||
* Extracts bit field from array.
|
||||
*/
|
||||
unsigned bextra(const unsigned *p, size_t i, char b) {
|
||||
unsigned k, r, w;
|
||||
w = sizeof(unsigned) * CHAR_BIT;
|
||||
if (b) {
|
||||
b &= w - 1;
|
||||
i *= b;
|
||||
k = i & (w - 1);
|
||||
i /= w;
|
||||
if (k <= w - b) {
|
||||
return (p[i] >> k) & ((1u << (b - 1)) | ((1u << (b - 1)) - 1));
|
||||
} else {
|
||||
r = p[i] >> k;
|
||||
r |= p[i + 1] << (w - k);
|
||||
r &= (1ul << b) - 1;
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ bool cmpxchg(void *, intptr_t, intptr_t, size_t);
|
||||
bool lockcmpxchg(void *, intptr_t, intptr_t, size_t);
|
||||
intptr_t atomic_load(void *, size_t);
|
||||
intptr_t atomic_store(void *, intptr_t, size_t);
|
||||
unsigned bextra(const unsigned *, size_t, char);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § bits » no assembly required ─╬─│┼
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*-*- 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 2021 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/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
|
||||
/**
|
||||
* Returns population count of array.
|
||||
*
|
||||
* @param a is byte sequence
|
||||
* @return number of bits set to one
|
||||
* @note 30gbps on Nehalem (Intel 2008+) otherwise 3gbps
|
||||
*/
|
||||
size_t _countbits(const void *a, size_t n) {
|
||||
int i;
|
||||
size_t t;
|
||||
unsigned b;
|
||||
uint64_t x;
|
||||
long Ai, Bi, Ci, Di;
|
||||
long Ao, Bo, Co, Do;
|
||||
const char *p, *e;
|
||||
t = 0;
|
||||
p = a;
|
||||
e = p + n;
|
||||
if (!IsTiny()) {
|
||||
if (X86_HAVE(POPCNT)) {
|
||||
while (p + sizeof(long) * 4 <= e) {
|
||||
__builtin_memcpy(&Ai, p + 000, sizeof(long));
|
||||
__builtin_memcpy(&Bi, p + 010, sizeof(long));
|
||||
__builtin_memcpy(&Ci, p + 020, sizeof(long));
|
||||
__builtin_memcpy(&Di, p + 030, sizeof(long));
|
||||
asm("popcnt\t%1,%0" : "=r"(Ao) : "r"(Ai) : "cc");
|
||||
asm("popcnt\t%1,%0" : "=r"(Bo) : "r"(Bi) : "cc");
|
||||
asm("popcnt\t%1,%0" : "=r"(Co) : "r"(Ci) : "cc");
|
||||
asm("popcnt\t%1,%0" : "=r"(Do) : "r"(Di) : "cc");
|
||||
t += Ao + Bo + Co + Do;
|
||||
p += sizeof(long) * 4;
|
||||
}
|
||||
while (p + sizeof(long) <= e) {
|
||||
__builtin_memcpy(&Ai, p, 8);
|
||||
asm("popcnt\t%1,%0" : "=r"(Ao) : "rm"(Ai) : "cc");
|
||||
p += sizeof(long);
|
||||
t += Ao;
|
||||
}
|
||||
} else {
|
||||
while (p + 8 <= e) {
|
||||
__builtin_memcpy(&x, p, 8);
|
||||
x = x - ((x >> 1) & 0x5555555555555555);
|
||||
x = ((x >> 2) & 0x3333333333333333) + (x & 0x3333333333333333);
|
||||
x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0f;
|
||||
x = (x + (x >> 32)) & 0xffffffff;
|
||||
x = x + (x >> 16);
|
||||
x = (x + (x >> 8)) & 0x7f;
|
||||
t += x;
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (p < e) {
|
||||
b = *p++ & 255;
|
||||
b = b - ((b >> 1) & 0x55);
|
||||
b = ((b >> 2) & 0x33) + (b & 0x33);
|
||||
b = (b + (b >> 4)) & 15;
|
||||
t += b;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -218,6 +218,20 @@ struct thatispacked mayalias __usi128ma {
|
||||
#define _mm_cmpunord_sd(M128D_0, M128D_1) \
|
||||
__builtin_ia32_cmpunordsd((__v2df)(M128D_0), (__v2df)(M128D_1))
|
||||
|
||||
#define _mm_SSE2(op, A, B) \
|
||||
({ \
|
||||
__m128i R = A; \
|
||||
asm(#op " %1, %0" \
|
||||
: "+x"(R) : "xm"(B)); \
|
||||
R; \
|
||||
})
|
||||
#define _mm_mul_epu32(A, B) _mm_SSE2(pmuludq, A, B)
|
||||
#define _mm_add_epi64(A, B) _mm_SSE2(paddq, A, B)
|
||||
#define _mm_srli_epi64(A, B) _mm_SSE2(psrlq, A, B)
|
||||
#define _mm_slli_epi64(A, B) _mm_SSE2(psllq, A, B)
|
||||
#define _mm_unpacklo_epi64(A, B) _mm_SSE2(punpcklqdq, A, B)
|
||||
#define _mm_unpackhi_epi64(A, B) _mm_SSE2(punpckhqdq, A, B)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § it's a trap! » sse2 » miscellaneous ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
size_t _countbits(const void *, size_t);
|
||||
unsigned long popcnt(unsigned long) pureconst;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
@@ -26,5 +26,5 @@
|
||||
* @see rounddown2pow()
|
||||
*/
|
||||
unsigned long roundup2pow(unsigned long x) {
|
||||
return x > 1 ? 1ul << (bsrl(x - 1) + 1) : x ? 1 : 0;
|
||||
return x > 1 ? 2ul << bsrl(x - 1) : x ? 1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_BITS_XADD_H_
|
||||
#define COSMOPOLITAN_LIBC_BITS_XADD_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define _xadd(p, v) \
|
||||
({ \
|
||||
typeof(*(p)) Res; \
|
||||
autotype(Res) Val = (v); \
|
||||
asm volatile("xadd\t%0,%1" : "=r"(Res), "+m"(*(p)) : "0"(Val)); \
|
||||
Res + Val; \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_BITS_XADD_H_ */
|
||||
@@ -100,7 +100,7 @@ typedef float __m128_u _Vector_size(16) forcealign(1) mayalias;
|
||||
#define _mm_add_ss(m128_0, m128_1) \
|
||||
({ \
|
||||
__m128 a = m128_0; \
|
||||
__m128 b = m128_0; \
|
||||
__m128 b = m128_1; \
|
||||
a[0] += b[0]; \
|
||||
a; \
|
||||
})
|
||||
@@ -108,7 +108,7 @@ typedef float __m128_u _Vector_size(16) forcealign(1) mayalias;
|
||||
#define _mm_sub_ss(m128_0, m128_1) \
|
||||
({ \
|
||||
__m128 a = m128_0; \
|
||||
__m128 b = m128_0; \
|
||||
__m128 b = m128_1; \
|
||||
a[0] -= b[0]; \
|
||||
a; \
|
||||
})
|
||||
@@ -116,7 +116,7 @@ typedef float __m128_u _Vector_size(16) forcealign(1) mayalias;
|
||||
#define _mm_mul_ss(m128_0, m128_1) \
|
||||
({ \
|
||||
__m128 a = m128_0; \
|
||||
__m128 b = m128_0; \
|
||||
__m128 b = m128_1; \
|
||||
a[0] *= b[0]; \
|
||||
a; \
|
||||
})
|
||||
@@ -124,7 +124,7 @@ typedef float __m128_u _Vector_size(16) forcealign(1) mayalias;
|
||||
#define _mm_div_ss(m128_0, m128_1) \
|
||||
({ \
|
||||
__m128 a = m128_0; \
|
||||
__m128 b = m128_0; \
|
||||
__m128 b = m128_1; \
|
||||
a[0] /= b[0]; \
|
||||
a; \
|
||||
})
|
||||
|
||||
@@ -19,9 +19,12 @@
|
||||
#include "libc/calls/math.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
/**
|
||||
* Adds resource usages.
|
||||
*/
|
||||
void AddRusage(struct rusage *x, const struct rusage *y) {
|
||||
AddTimeval(&x->ru_utime, &y->ru_utime);
|
||||
AddTimeval(&x->ru_stime, &y->ru_stime);
|
||||
x->ru_utime = AddTimeval(x->ru_utime, y->ru_utime);
|
||||
x->ru_stime = AddTimeval(x->ru_stime, y->ru_stime);
|
||||
x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss);
|
||||
x->ru_ixrss += y->ru_ixrss;
|
||||
x->ru_idrss += y->ru_idrss;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*-*- 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 2021 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/math.h"
|
||||
|
||||
/**
|
||||
* Adds two microsecond timestamps.
|
||||
*/
|
||||
struct timespec AddTimespec(struct timespec x, struct timespec y) {
|
||||
x.tv_sec += y.tv_sec;
|
||||
x.tv_nsec += y.tv_nsec;
|
||||
if (x.tv_nsec >= 10000000000) {
|
||||
x.tv_nsec -= 10000000000;
|
||||
x.tv_sec += 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
+10
-6
@@ -18,11 +18,15 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/math.h"
|
||||
|
||||
void AddTimeval(struct timeval *x, const struct timeval *y) {
|
||||
x->tv_sec += y->tv_sec;
|
||||
x->tv_usec += y->tv_usec;
|
||||
if (x->tv_usec >= 1000000) {
|
||||
x->tv_usec -= 1000000;
|
||||
x->tv_sec += 1;
|
||||
/**
|
||||
* Adds two microsecond timestamps.
|
||||
*/
|
||||
struct timeval AddTimeval(struct timeval x, struct timeval y) {
|
||||
x.tv_sec += y.tv_sec;
|
||||
x.tv_usec += y.tv_usec;
|
||||
if (x.tv_usec >= 1000000) {
|
||||
x.tv_usec -= 1000000;
|
||||
x.tv_sec += 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
+18
-63
@@ -5,13 +5,13 @@
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/sigval.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/sysinfo.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/tms.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/typedef/sighandler_t.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/pflink.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
@@ -56,6 +56,7 @@
|
||||
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) ((s)&0x7f)
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
@@ -71,6 +72,7 @@ bool fileexists(const char *);
|
||||
bool isdirectory(const char *);
|
||||
bool isexecutable(const char *);
|
||||
bool isregularfile(const char *);
|
||||
bool issymlink(const char *);
|
||||
bool32 isatty(int) nosideeffect;
|
||||
bool32 ischardev(int) nosideeffect;
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
@@ -85,36 +87,38 @@ int chdir(const char *);
|
||||
int chmod(const char *, uint32_t);
|
||||
int chown(const char *, uint32_t, uint32_t);
|
||||
int chroot(const char *);
|
||||
int clone(int (*)(void *), void *, int, void *, ...);
|
||||
int close(int);
|
||||
int closedir(DIR *);
|
||||
int creat(const char *, uint32_t) nodiscard;
|
||||
int creat(const char *, uint32_t);
|
||||
int dirfd(DIR *);
|
||||
int dup(int) nodiscard;
|
||||
int dup(int);
|
||||
int dup2(int, int);
|
||||
int dup3(int, int, int);
|
||||
int execl(const char *, const char *, ...) nullterminated();
|
||||
int execle(const char *, const char *, ...) nullterminated((1));
|
||||
int execlp(const char *, const char *, ...) nullterminated();
|
||||
int execv(const char *, char *const[]) paramsnonnull();
|
||||
int execve(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int execvp(const char *, char *const[]) paramsnonnull();
|
||||
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
||||
int execv(const char *, char *const[]);
|
||||
int execve(const char *, char *const[], char *const[]);
|
||||
int execvp(const char *, char *const[]);
|
||||
int execvpe(const char *, char *const[], char *const[]);
|
||||
int faccessat(int, const char *, int, uint32_t);
|
||||
int fadvise(int, uint64_t, uint64_t, int);
|
||||
int fchdir(int);
|
||||
int fchmod(int, uint32_t) nothrow;
|
||||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||
int fchmodat(int, const char *, uint32_t, int);
|
||||
int fchown(int, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, uint32_t);
|
||||
int fchownat(int, const char *, uint32_t, uint32_t, int);
|
||||
int fcntl(int, int, ...);
|
||||
int fdatasync(int);
|
||||
int filecmp(const char *, const char *);
|
||||
int flock(int, int);
|
||||
int fork(void);
|
||||
int fstat(int, struct stat *);
|
||||
int fstatat(int, const char *, struct stat *, uint32_t);
|
||||
int fstatat(int, const char *, struct stat *, int);
|
||||
int fsync(int);
|
||||
int ftruncate(int, int64_t);
|
||||
int getdents(unsigned, void *, unsigned, long *);
|
||||
int getdomainname(char *, size_t);
|
||||
int gethostname(char *, size_t);
|
||||
int getpgid(int);
|
||||
@@ -126,8 +130,9 @@ int getrusage(int, struct rusage *);
|
||||
int kill(int, int);
|
||||
int killpg(int, int);
|
||||
int link(const char *, const char *) nothrow;
|
||||
int linkat(int, const char *, int, const char *, uint32_t);
|
||||
int linkat(int, const char *, int, const char *, int);
|
||||
int lstat(const char *, struct stat *);
|
||||
int lutimes(const char *, const struct timeval[2]);
|
||||
int madvise(void *, uint64_t, int);
|
||||
int mkdir(const char *, uint32_t);
|
||||
int mkdirat(int, const char *, uint32_t);
|
||||
@@ -152,7 +157,6 @@ int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||
int posix_madvise(void *, uint64_t, int);
|
||||
int prctl();
|
||||
int raise(int);
|
||||
int readlink(const char *, char *, size_t);
|
||||
int reboot(int);
|
||||
int remove(const char *);
|
||||
int rename(const char *, const char *);
|
||||
@@ -174,8 +178,8 @@ int setreuid(uint32_t, uint32_t);
|
||||
int setrlimit(int, const struct rlimit *);
|
||||
int setsid(void);
|
||||
int setuid(uint32_t);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
int sigignore(int);
|
||||
int siginterrupt(int, int);
|
||||
int sigprocmask(int, const struct sigset *, struct sigset *);
|
||||
int sigqueue(int, int, const union sigval);
|
||||
int sigsuspend(const struct sigset *);
|
||||
@@ -201,7 +205,6 @@ intptr_t syscall(int, ...);
|
||||
long ptrace(int, int, void *, void *);
|
||||
long telldir(DIR *);
|
||||
long times(struct tms *);
|
||||
sighandler_t signal(int, sighandler_t);
|
||||
size_t GetFileSize(const char *);
|
||||
size_t getfiledescriptorsize(int);
|
||||
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
|
||||
@@ -213,6 +216,7 @@ ssize_t pwrite(int, const void *, size_t, int64_t);
|
||||
ssize_t pwritev(int, const struct iovec *, int, int64_t);
|
||||
ssize_t read(int, void *, size_t);
|
||||
ssize_t readansi(int, char *, size_t);
|
||||
ssize_t readlink(const char *, char *, size_t);
|
||||
ssize_t readlinkat(int, const char *, char *, size_t);
|
||||
ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
||||
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
|
||||
@@ -241,55 +245,6 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
|
||||
#define getcwd(BUF, SIZE) \
|
||||
(__builtin_constant_p(BUF) && !(BUF) ? get_current_dir_name() \
|
||||
: getcwd(BUF, SIZE))
|
||||
|
||||
void _init_onntconsoleevent(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
#ifndef __SIGACTION_YOINK
|
||||
#define __SIGACTION_YOINK(SIG) \
|
||||
do { \
|
||||
if (SupportsWindows()) { \
|
||||
if (__builtin_constant_p(SIG)) { \
|
||||
switch (SIG) { \
|
||||
case SIGINT: \
|
||||
case SIGQUIT: \
|
||||
case SIGHUP: \
|
||||
case SIGTERM: \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
break; \
|
||||
case SIGTRAP: \
|
||||
case SIGILL: \
|
||||
case SIGSEGV: \
|
||||
case SIGABRT: \
|
||||
case SIGFPE: \
|
||||
YOINK(_init_wincrash); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} else { \
|
||||
YOINK(_init_onntconsoleevent); \
|
||||
YOINK(_init_wincrash); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define sigaction(SIG, ACT, OLD) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
sigaction(SIG, (ACT), OLD); \
|
||||
})
|
||||
|
||||
#define signal(SIG, HAND) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
signal(SIG, HAND); \
|
||||
})
|
||||
|
||||
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
|
||||
|
||||
|
||||
@@ -67,6 +67,8 @@ o/$(MODE)/libc/calls/raise.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
$(NO_MAGIC)
|
||||
|
||||
o/$(MODE)/libc/calls/termios2linux.o \
|
||||
o/$(MODE)/libc/calls/termios2host.o \
|
||||
o/$(MODE)/libc/calls/sigenter-freebsd.o \
|
||||
o/$(MODE)/libc/calls/sigenter-netbsd.o \
|
||||
o/$(MODE)/libc/calls/sigenter-openbsd.o \
|
||||
@@ -75,6 +77,25 @@ o/$(MODE)/libc/calls/ntcontext2linux.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
-O3
|
||||
|
||||
# TODO(jart): make va_arg optimize well in default mode
|
||||
o//libc/calls/ioctl.o \
|
||||
o//libc/calls/ioctl_default.o \
|
||||
o//libc/calls/ioctl_fioclex-nt.o \
|
||||
o//libc/calls/ioctl_fioclex.o \
|
||||
o//libc/calls/ioctl_siocgifconf-nt.o \
|
||||
o//libc/calls/ioctl_siocgifconf.o \
|
||||
o//libc/calls/ioctl_tcgets-nt.o \
|
||||
o//libc/calls/ioctl_tcgets.o \
|
||||
o//libc/calls/ioctl_tcsets-nt.o \
|
||||
o//libc/calls/ioctl_tcsets.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocgwinsz.o \
|
||||
o//libc/calls/ioctl_tiocswinsz-nt.o \
|
||||
o//libc/calls/ioctl_tiocswinsz.o \
|
||||
o//libc/calls/fcntl.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/libc/calls/execl.o \
|
||||
o/$(MODE)/libc/calls/execle.o \
|
||||
o/$(MODE)/libc/calls/execlp.o \
|
||||
|
||||
+28
-4
@@ -17,18 +17,21 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_chdir_nt(const char *path) {
|
||||
uint32_t n;
|
||||
int e, ms, len;
|
||||
char16_t path16[PATH_MAX];
|
||||
char16_t path16[PATH_MAX], var[4];
|
||||
if ((len = __mkntpath(path, path16)) == -1) return -1;
|
||||
if (path16[len - 1] != u'\\') {
|
||||
if (len + 1 + 1 > PATH_MAX) return enametoolong();
|
||||
if (len && path16[len - 1] != u'\\') {
|
||||
if (len + 2 > PATH_MAX) return enametoolong();
|
||||
path16[len + 0] = u'\\';
|
||||
path16[len + 1] = u'\0';
|
||||
}
|
||||
@@ -38,7 +41,28 @@ textwindows int sys_chdir_nt(const char *path) {
|
||||
*/
|
||||
for (ms = 1;; ms *= 2) {
|
||||
if (SetCurrentDirectory(path16)) {
|
||||
return 0;
|
||||
/*
|
||||
* Now we need to set a magic environment variable.
|
||||
*/
|
||||
if ((n = GetCurrentDirectory(ARRAYLEN(path16), path16))) {
|
||||
if (n < ARRAYLEN(path16)) {
|
||||
if (!((path16[0] == '/' && path16[1] == '/') ||
|
||||
(path16[0] == '\\' && path16[1] == '\\'))) {
|
||||
var[0] = '=';
|
||||
var[1] = path16[0];
|
||||
var[2] = ':';
|
||||
var[3] = 0;
|
||||
if (!SetEnvironmentVariable(var, path16)) {
|
||||
return __winerr();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return enametoolong();
|
||||
}
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
} else {
|
||||
e = GetLastError();
|
||||
if (ms <= 512 &&
|
||||
|
||||
@@ -18,14 +18,19 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets current directory.
|
||||
*
|
||||
* This does *not* update the `PWD` environment variable.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @see fchdir()
|
||||
*/
|
||||
int chdir(const char *path) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_chdir(path);
|
||||
} else {
|
||||
|
||||
+1
-4
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
@@ -33,8 +32,6 @@
|
||||
* CHECK_NE(-1, chmod("/usr/bin/sudo", 04755)); // setuid bit
|
||||
* CHECK_NE(-1, chmod("/usr/bin/wall", 02755)); // setgid bit
|
||||
*
|
||||
* This works on Windows NT if you ignore the error ;-)
|
||||
*
|
||||
* @param pathname must exist
|
||||
* @param mode contains octal flags (base 8)
|
||||
* @errors ENOENT, ENOTDIR, ENOSYS
|
||||
@@ -42,5 +39,5 @@
|
||||
* @see fchmod()
|
||||
*/
|
||||
int chmod(const char *pathname, uint32_t mode) {
|
||||
return sys_fchmodat(AT_FDCWD, pathname, mode, 0);
|
||||
return fchmodat(AT_FDCWD, pathname, mode, 0);
|
||||
}
|
||||
+1
-2
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
@@ -33,5 +32,5 @@
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int chown(const char *pathname, uint32_t uid, uint32_t gid) {
|
||||
return sys_fchownat(AT_FDCWD, pathname, uid, gid, 0);
|
||||
return fchownat(AT_FDCWD, pathname, uid, gid, 0);
|
||||
}
|
||||
+16
-1
@@ -19,6 +19,11 @@
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/accounting.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
||||
/**
|
||||
* Returns how much CPU program has consumed on time-sharing system.
|
||||
@@ -28,7 +33,17 @@
|
||||
*/
|
||||
int64_t clock(void) {
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) return -1;
|
||||
struct NtFileTime creation_time, exit_time, kernel_time, user_time;
|
||||
int64_t proc, total;
|
||||
// polyfill on Windows where CLOCK_PROCESS_CPUTIME_ID may be not available
|
||||
if (IsWindows() && CLOCK_PROCESS_CPUTIME_ID == -1) {
|
||||
proc = GetCurrentProcess();
|
||||
if (!GetProcessTimes(proc, &creation_time,
|
||||
&exit_time, &kernel_time, &user_time)) return -1;
|
||||
total = ReadFileTime(kernel_time) + ReadFileTime(user_time);
|
||||
ts = WindowsDurationToTimeSpec(total);
|
||||
}
|
||||
else if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) return -1;
|
||||
return ts.tv_sec * CLOCKS_PER_SEC +
|
||||
ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*-*- 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 2021 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/fmt/conv.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_clock_gettime_nt(int clockid, struct timespec *ts) {
|
||||
int64_t ms;
|
||||
struct timespec res;
|
||||
struct NtFileTime ft;
|
||||
static struct timespec mono;
|
||||
if (clockid == CLOCK_REALTIME) {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
*ts = FileTimeToTimeSpec(ft);
|
||||
return 0;
|
||||
} else if (clockid == CLOCK_MONOTONIC || clockid == CLOCK_MONOTONIC_RAW) {
|
||||
ms = GetTickCount64();
|
||||
res.tv_sec = ms / 1000;
|
||||
res.tv_nsec = ms % 1000 * 1000000;
|
||||
res.tv_nsec += rdtsc() / 3 % 1000000000;
|
||||
if (res.tv_nsec > 1000000000) {
|
||||
res.tv_nsec -= 1000000000;
|
||||
res.tv_sec += 1;
|
||||
}
|
||||
if (res.tv_sec > mono.tv_sec ||
|
||||
(res.tv_sec == mono.tv_sec && res.tv_nsec > mono.tv_nsec)) {
|
||||
mono = res;
|
||||
} else {
|
||||
res = mono;
|
||||
}
|
||||
*ts = res;
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,9 @@
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -40,8 +42,8 @@
|
||||
int clock_gettime(int clockid, struct timespec *ts) {
|
||||
int rc;
|
||||
axdx_t ad;
|
||||
struct NtFileTime ft;
|
||||
if (!ts) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(ts, sizeof(*ts))) return efault();
|
||||
if (clockid == -1) return einval();
|
||||
if (!IsWindows()) {
|
||||
if ((rc = sys_clock_gettime(clockid, ts)) == -1 && errno == ENOSYS) {
|
||||
@@ -56,8 +58,6 @@ int clock_gettime(int clockid, struct timespec *ts) {
|
||||
}
|
||||
return rc;
|
||||
} else {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
*ts = FileTimeToTimeSpec(ft);
|
||||
return 0;
|
||||
return sys_clock_gettime_nt(clockid, ts);
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ textwindows int sys_close_nt(struct Fd *fd) {
|
||||
FlushFileBuffers(fd->handle);
|
||||
}
|
||||
ok = CloseHandle(fd->handle);
|
||||
if (fd->kind == kFdConsole) {
|
||||
if (fd->kind == kFdConsole && fd->extra && fd->extra != -1) {
|
||||
ok &= CloseHandle(fd->extra);
|
||||
}
|
||||
return ok ? 0 : __winerr();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
*/
|
||||
int close(int fd) {
|
||||
int rc;
|
||||
if (fd == -1) return 0;
|
||||
if (fd < 0) return einval();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_close)(fd);
|
||||
@@ -59,5 +61,6 @@ int close(int fd) {
|
||||
}
|
||||
}
|
||||
__releasefd(fd);
|
||||
SYSDEBUG("close(%d) -> %d", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
+69
-43
@@ -18,38 +18,55 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static bool AccessCommand(char path[hasatleast PATH_MAX], const char *name,
|
||||
size_t namelen, size_t pathlen) {
|
||||
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
static noasan bool EndsWithIgnoreCase(const char *p, size_t n, const char *s) {
|
||||
size_t i, m;
|
||||
m = __strlen(s);
|
||||
if (n >= m) {
|
||||
for (i = n - m; i < n; ++i) {
|
||||
if (kToLower[p[i] & 255] != (*s++ & 255)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
memcpy(path + pathlen, name, namelen + 1);
|
||||
if (isexecutable(path)) return true;
|
||||
memcpy(path + pathlen + namelen, ".com", 5);
|
||||
if (isexecutable(path)) return true;
|
||||
memcpy(path + pathlen + namelen, ".exe", 5);
|
||||
if (isexecutable(path)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
||||
size_t namelen) {
|
||||
static noasan bool AccessCommand(const char *name,
|
||||
char path[hasatleast PATH_MAX], size_t namelen,
|
||||
const char *suffix, size_t pathlen) {
|
||||
size_t suffixlen;
|
||||
suffixlen = __strlen(suffix);
|
||||
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return -1;
|
||||
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
|
||||
path[pathlen] = !IsWindows() ? '/'
|
||||
: __memchr(path, '\\', pathlen) ? '\\'
|
||||
: '/';
|
||||
pathlen++;
|
||||
}
|
||||
__repmovsb(path + pathlen, name, namelen);
|
||||
__repmovsb(path + pathlen + namelen, suffix, suffixlen + 1);
|
||||
return isexecutable(path);
|
||||
}
|
||||
|
||||
static noasan bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
|
||||
size_t namelen, const char *suffix) {
|
||||
size_t i;
|
||||
const char *p;
|
||||
p = firstnonnull(emptytonull(getenv("PATH")), "/bin:/usr/local/bin:/usr/bin");
|
||||
for (;;) {
|
||||
for (i = 0; p[i] && p[i] != ':' && p[i] != ';'; ++i) {
|
||||
if (i < PATH_MAX) path[i] = p[i];
|
||||
if (i < PATH_MAX) {
|
||||
path[i] = p[i];
|
||||
}
|
||||
}
|
||||
if (AccessCommand(path, name, namelen, i)) {
|
||||
if (AccessCommand(name, path, namelen, suffix, i)) {
|
||||
return true;
|
||||
}
|
||||
if (p[i] == ':' || p[i] == ';') {
|
||||
@@ -61,6 +78,23 @@ static bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
||||
return false;
|
||||
}
|
||||
|
||||
static noasan bool FindCommand(const char *name,
|
||||
char pathbuf[hasatleast PATH_MAX],
|
||||
size_t namelen, const char *suffix) {
|
||||
if (memchr(name, '/', namelen) || memchr(name, '\\', namelen)) {
|
||||
pathbuf[0] = 0;
|
||||
return AccessCommand(name, pathbuf, namelen, suffix, 0);
|
||||
}
|
||||
return ((IsWindows() &&
|
||||
(AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
|
||||
AccessCommand(name, pathbuf, namelen, suffix,
|
||||
stpcpy(pathbuf, ".") - pathbuf))) ||
|
||||
SearchPath(name, pathbuf, namelen, suffix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves full pathname of executable.
|
||||
*
|
||||
@@ -70,37 +104,29 @@ static bool SearchPath(char path[hasatleast PATH_MAX], const char *name,
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
char *p;
|
||||
noasan char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
int olderr;
|
||||
size_t namelen;
|
||||
int rc, olderr;
|
||||
if (!(namelen = strlen(name))) {
|
||||
if (!name) {
|
||||
efault();
|
||||
return 0;
|
||||
}
|
||||
if (!(namelen = __strlen(name))) {
|
||||
enoent();
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (namelen + 1 > PATH_MAX) {
|
||||
enametoolong();
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
if (strchr(name, '/') || strchr(name, '\\')) {
|
||||
if (AccessCommand(strcpy(pathbuf, ""), name, namelen, 0)) {
|
||||
return pathbuf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
olderr = errno;
|
||||
if ((IsWindows() &&
|
||||
(AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf) ||
|
||||
AccessCommand(pathbuf, name, namelen,
|
||||
stpcpy(pathbuf, ".") - pathbuf))) ||
|
||||
SearchPath(pathbuf, name, namelen)) {
|
||||
errno = olderr;
|
||||
if (FindCommand(name, pathbuf, namelen, "") ||
|
||||
(!EndsWithIgnoreCase(name, namelen, ".exe") &&
|
||||
!EndsWithIgnoreCase(name, namelen, ".com") &&
|
||||
!EndsWithIgnoreCase(name, namelen, ".com.dbg") &&
|
||||
(FindCommand(name, pathbuf, namelen, ".com") ||
|
||||
FindCommand(name, pathbuf, namelen, ".exe")))) {
|
||||
return pathbuf;
|
||||
} else {
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static textwindows int sys_copyfile_nt(const char *src, const char *dst,
|
||||
int flags) {
|
||||
int flags) {
|
||||
int64_t fhsrc, fhdst;
|
||||
struct NtFileTime accessed, modified;
|
||||
char16_t src16[PATH_MAX], dst16[PATH_MAX];
|
||||
@@ -99,6 +99,13 @@ static int sys_copyfile(const char *src, const char *dst, int flags) {
|
||||
|
||||
/**
|
||||
* Copies file.
|
||||
*
|
||||
* This implementation goes 2x faster than the `cp` command that comes
|
||||
* included with most systems since we use the newer copy_file_range()
|
||||
* system call rather than sendfile().
|
||||
*
|
||||
* @param flags may have COPYFILE_PRESERVE_TIMESTAMPS, COPYFILE_NOCLOBBER
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int copyfile(const char *src, const char *dst, int flags) {
|
||||
if (!IsWindows()) {
|
||||
|
||||
@@ -47,6 +47,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags) {
|
||||
if (DuplicateHandle(proc, g_fds.p[oldfd].handle, proc, &g_fds.p[newfd].handle,
|
||||
0, true, kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].extra = g_fds.p[oldfd].extra;
|
||||
g_fds.p[newfd].flags = flags;
|
||||
return newfd;
|
||||
} else {
|
||||
|
||||
+7
-3
@@ -18,6 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
@@ -28,10 +29,13 @@
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
nodiscard int dup(int fd) {
|
||||
int dup(int fd) {
|
||||
int fd2;
|
||||
if (!IsWindows()) {
|
||||
return sys_dup(fd);
|
||||
fd2 = sys_dup(fd);
|
||||
} else {
|
||||
return sys_dup_nt(fd, -1, 0);
|
||||
fd2 = sys_dup_nt(fd, -1, 0);
|
||||
}
|
||||
SYSDEBUG("dup(%d) -> %d", fd, fd2);
|
||||
return fd2;
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
@@ -31,6 +32,7 @@
|
||||
* @vforksafe
|
||||
*/
|
||||
int dup2(int oldfd, int newfd) {
|
||||
SYSDEBUG("dup2(%d, %d)", oldfd, newfd);
|
||||
if (oldfd == newfd) return newfd;
|
||||
if (!IsWindows()) {
|
||||
return sys_dup3(oldfd, newfd, 0);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -35,6 +36,7 @@
|
||||
* @see dup(), dup2()
|
||||
*/
|
||||
int dup3(int oldfd, int newfd, int flags) {
|
||||
SYSDEBUG("dup3(%d, %d, %d)", oldfd, newfd, flags);
|
||||
if (!IsWindows()) {
|
||||
return sys_dup3(oldfd, newfd, flags);
|
||||
} else {
|
||||
|
||||
+12
-2
@@ -24,6 +24,10 @@
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static void __ensurefds_destroy(void) {
|
||||
weaken(free)(g_fds.p);
|
||||
}
|
||||
|
||||
int __ensurefds(int fd) {
|
||||
size_t n1, n2;
|
||||
struct Fd *p1, *p2;
|
||||
@@ -35,10 +39,16 @@ int __ensurefds(int fd) {
|
||||
n2 = MAX(fd + 1, n1 + (n1 << 1));
|
||||
if ((p2 = weaken(malloc)(n2 * sizeof(*p1)))) {
|
||||
memcpy(p2, p1, n1 * sizeof(*p1));
|
||||
memset(p2 + n1, 0, (n2 - n1) * sizeof(*p1));
|
||||
if (p1 != g_fds.__init_p && weaken(free)) weaken(free)(p1);
|
||||
bzero(p2 + n1, (n2 - n1) * sizeof(*p1));
|
||||
if (cmpxchg(&g_fds.p, p1, p2)) {
|
||||
g_fds.n = n2;
|
||||
if (weaken(free)) {
|
||||
if (p1 == g_fds.__init_p) {
|
||||
atexit(__ensurefds_destroy);
|
||||
} else {
|
||||
weaken(free)(p1);
|
||||
}
|
||||
}
|
||||
return fd;
|
||||
} else if (weaken(free)) {
|
||||
weaken(free)(p2);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Executes program, with PATH search and current environment.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
@@ -30,26 +31,22 @@
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
textwindows int sys_execve_nt(const char *program, char *const argv[],
|
||||
char *const envp[]) {
|
||||
char *const envp[]) {
|
||||
int rc;
|
||||
size_t i;
|
||||
uint32_t dwExitCode;
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtProcessInformation procinfo;
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
bzero(&startinfo, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = g_fds.p[0].handle;
|
||||
startinfo.hStdOutput = g_fds.p[1].handle;
|
||||
startinfo.hStdError = g_fds.p[2].handle;
|
||||
for (i = 2; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
rc = ntspawn(program, argv, envp, NULL, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
&procinfo);
|
||||
rc = ntspawn(program, argv, envp, 0, 0, 0, 1, 0, 0, &startinfo, &procinfo);
|
||||
if (rc == -1) return -1;
|
||||
CloseHandle(g_fds.p[0].handle);
|
||||
CloseHandle(g_fds.p[1].handle);
|
||||
CloseHandle(procinfo.hThread);
|
||||
do {
|
||||
WaitForSingleObject(procinfo.hProcess, -1);
|
||||
|
||||
@@ -18,7 +18,12 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Replaces current process with program.
|
||||
@@ -34,6 +39,31 @@
|
||||
* @vforksafe
|
||||
*/
|
||||
int execve(const char *program, char *const argv[], char *const envp[]) {
|
||||
size_t i;
|
||||
if (!program || !argv || !envp) return efault();
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(program, 1) || !__asan_is_valid_strlist(argv) ||
|
||||
!__asan_is_valid_strlist(envp))) {
|
||||
return efault();
|
||||
}
|
||||
if (DEBUGSYS) {
|
||||
__printf("SYS: execve(%s, {", program);
|
||||
for (i = 0; argv[i]; ++i) {
|
||||
if (i) __printf(", ");
|
||||
__printf("%s", argv[i]);
|
||||
}
|
||||
__printf("}, {");
|
||||
for (i = 0; envp[i]; ++i) {
|
||||
if (i) __printf(", ");
|
||||
__printf("%s", envp[i]);
|
||||
}
|
||||
__printf("})\n");
|
||||
}
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_execve(program, argv, envp);
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Executes program, with path environment search.
|
||||
@@ -34,6 +37,7 @@
|
||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||
char *exe;
|
||||
char pathbuf[PATH_MAX];
|
||||
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
|
||||
if (!(exe = commandv(prog, pathbuf))) return -1;
|
||||
return execve(exe, argv, envp);
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Checks if effective user can access path in particular ways.
|
||||
@@ -34,6 +37,10 @@
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_faccessat(dirfd, path, mode, flags);
|
||||
} else {
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||
textwindows int sys_fadvise_nt(int fd, uint64_t offset, uint64_t len,
|
||||
int advice) {
|
||||
int64_t h2;
|
||||
NtStatus status;
|
||||
uint32_t sharemode;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
/**
|
||||
* Sets current directory based on file descriptor.
|
||||
*
|
||||
* This does *not* update the `PWD` environment variable.
|
||||
*
|
||||
* @see open(path, O_DIRECTORY)
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
|
||||
+1
-14
@@ -22,22 +22,9 @@
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Changes file permissions via open()'d file descriptor, e.g.:
|
||||
*
|
||||
* CHECK_NE(-1, chmod("foo/bar.txt", 0644));
|
||||
* CHECK_NE(-1, chmod("o/default/program.com", 0755));
|
||||
* CHECK_NE(-1, chmod("privatefolder/", 0700));
|
||||
*
|
||||
* The esoteric bits generally available on System V are:
|
||||
*
|
||||
* CHECK_NE(-1, chmod("/opt/", 01000)); // sticky bit
|
||||
* CHECK_NE(-1, chmod("/usr/bin/sudo", 04755)); // setuid bit
|
||||
* CHECK_NE(-1, chmod("/usr/bin/wall", 02755)); // setgid bit
|
||||
*
|
||||
* This works on Windows NT if you ignore the error ;-)
|
||||
* Changes file permissions via open()'d file descriptor.
|
||||
*
|
||||
* @param mode contains octal flags (base 8)
|
||||
* @errors ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see chmod()
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*-*- 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 2021 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/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/files.h"
|
||||
|
||||
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
|
||||
int flags) {
|
||||
uint32_t attr;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
if ((attr = GetFileAttributes(path16)) != -1) {
|
||||
if (mode & 0200) {
|
||||
attr &= ~kNtFileAttributeReadonly;
|
||||
} else {
|
||||
attr |= kNtFileAttributeReadonly;
|
||||
}
|
||||
if (SetFileAttributes(path16, attr)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return __winerr();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*-*- 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 2021 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/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Changes permissions on file, e.g.:
|
||||
*
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "foo/bar.txt", 0644));
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "o/default/program.com", 0755));
|
||||
* CHECK_NE(-1, fchmodat(AT_FDCWD, "privatefolder/", 0700));
|
||||
*
|
||||
* @param path must exist
|
||||
* @param mode contains octal flags (base 8)
|
||||
* @param flags can have `AT_SYMLINK_NOFOLLOW`
|
||||
* @errors ENOENT, ENOTDIR, ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see fchmod()
|
||||
*/
|
||||
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
|
||||
int rc;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
rc = -1; /* TODO(jart): implement me */
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_fchmodat(dirfd, path, mode, flags);
|
||||
} else {
|
||||
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
|
||||
}
|
||||
SYSDEBUG("fchmodat(%d, %s, %o, %d) -> %d %s", (long)dirfd, path, mode, flags,
|
||||
rc != -1 ? "" : strerror(errno));
|
||||
return rc;
|
||||
}
|
||||
+13
-4
@@ -16,11 +16,16 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Changes owner and/or group of pathname.
|
||||
* Changes owner and/or group of path.
|
||||
*
|
||||
* @param dirfd is open()'d relative-to directory, or AT_FDCWD, etc.
|
||||
* @param uid is user id, or -1 to not change
|
||||
@@ -32,7 +37,11 @@
|
||||
* @see /etc/group for group ids
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int fchownat(int dirfd, const char *pathname, uint32_t uid, uint32_t gid,
|
||||
uint32_t flags) {
|
||||
return sys_fchownat(dirfd, pathname, uid, gid, flags);
|
||||
int fchownat(int dirfd, const char *path, uint32_t uid, uint32_t gid,
|
||||
int flags) {
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
|
||||
return -1; /* TODO(jart): implement me */
|
||||
}
|
||||
return sys_fchownat(dirfd, path, uid, gid, flags);
|
||||
}
|
||||
+12
-3
@@ -16,9 +16,12 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Does things with file descriptor, via re-imagined hourglass api, e.g.
|
||||
@@ -45,9 +48,15 @@ int fcntl(int fd, int cmd, ...) {
|
||||
va_start(va, cmd);
|
||||
arg = va_arg(va, uintptr_t);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_fcntl(fd, cmd, arg);
|
||||
if (fd >= 0) {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_fcntl)(fd, cmd, arg);
|
||||
} else if (!IsWindows()) {
|
||||
return sys_fcntl(fd, cmd, arg);
|
||||
} else {
|
||||
return sys_fcntl_nt(fd, cmd, arg);
|
||||
}
|
||||
} else {
|
||||
return sys_fcntl_nt(fd, cmd, arg);
|
||||
return einval();
|
||||
}
|
||||
}
|
||||
+38
-10
@@ -16,35 +16,63 @@
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/metastat.internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/zipos/zipos.internal.h"
|
||||
|
||||
/**
|
||||
* Returns true if file exists at path.
|
||||
*
|
||||
* This function is equivalent to:
|
||||
*
|
||||
* struct stat st;
|
||||
* return stat(path, &st) != -1;
|
||||
*
|
||||
* Please note that things which aren't strictly files, e.g. directories
|
||||
* or sockets, could be considered files for the purposes of this
|
||||
* function. The stat() function may be used to differentiate them.
|
||||
*/
|
||||
bool fileexists(const char *path) {
|
||||
int rc, olderr;
|
||||
struct stat st;
|
||||
int e;
|
||||
bool res;
|
||||
union metastat st;
|
||||
struct ZiposUri zipname;
|
||||
uint16_t path16[PATH_MAX];
|
||||
if (!IsWindows()) {
|
||||
olderr = errno;
|
||||
rc = stat(path, &st);
|
||||
if (rc == -1 && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = olderr;
|
||||
e = errno;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
|
||||
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
|
||||
res = true;
|
||||
} else {
|
||||
res = false;
|
||||
}
|
||||
return rc != -1;
|
||||
} else if (IsMetal()) {
|
||||
res = false;
|
||||
} else if (!IsWindows()) {
|
||||
if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) {
|
||||
res = true;
|
||||
} else {
|
||||
res = false;
|
||||
}
|
||||
} else if (__mkntpath(path, path16) != -1) {
|
||||
res = GetFileAttributes(path16) != -1u;
|
||||
} else {
|
||||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
return GetFileAttributes(path16) != -1u;
|
||||
res = false;
|
||||
}
|
||||
SYSDEBUG("fileexists(%s) -> %s %s", path, res ? "true" : "false",
|
||||
res ? "" : strerror(errno));
|
||||
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
|
||||
errno = e;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ textwindows int sys_flock_nt(int fd, int op) {
|
||||
struct NtOverlapped ov;
|
||||
struct NtByHandleFileInformation info;
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
bzero(&ov, sizeof(ov));
|
||||
if (GetFileInformationByHandle(g_fds.p[fd].handle, &info) &&
|
||||
((!(op & LOCK_UN) &&
|
||||
LockFileEx(g_fds.p[fd].handle, op, 0, info.nFileSizeLow,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
int sys_fstat_metal(int fd, struct stat *st) {
|
||||
if (fd < 0) return einval();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||
memset(st, 0, sizeof(*st));
|
||||
bzero(st, sizeof(*st));
|
||||
st->st_dev = g_fds.p[fd].handle;
|
||||
st->st_rdev = g_fds.p[fd].handle;
|
||||
st->st_nlink = 1;
|
||||
|
||||
Loaded 100 of 2566 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user