Compare commits

..
Author SHA1 Message Date
Justine Tunney d6a039821f Release redbean 1.5 2021-11-15 07:39:38 -08:00
Oguz Bektas f12c6c1b5e Fix comment for nc example (#323)
The "Host" header is missing from the command for making the
request, so we get empty response.
2021-11-15 06:48:46 -08:00
Paul Kulchenko fdb543cbb3 Fix incorrect reference in Lua encoding (#324) 2021-11-13 13:10:09 -08:00
Paul Kulchenko 1d6216a775 Add encode json and encode Lua functions to redbean (#322) 2021-11-13 12:49:29 -08:00
Jørgen Kvalsvik 206091617a Don't pass unused args to printf (#311)
The final print does not print any content, only the byte-offset of the
end-block, which makes the A, B params unused. From gcc:

    bd.c:77:17: warning: too many arguments for format [-Wformat-extra-args]
        if (o) printf("%08x\n", o, A, B);
2021-11-13 01:10:45 -08:00
Justine Tunney 777d08a839 Fix mistake with IsHeaderRepeatable 2021-11-12 20:54:30 -08:00
Justine Tunney 98192c1079 Add undocumented IsHeaderRepeatable to redbean
This API is intended to help unblock framework code. It should
ideally be abstracted by redbean which is why it's undocumented.

See #97
2021-11-12 19:03:35 -08:00
Justine Tunney 7064d736e3 Increase some quotas
- Double mem quota (fixes #296) because linking Python is
  expensive and not easily tuned on a case-by-case basis

- Increase latency greatly for mkdeps tool since it's the
  first thing that runs and effetively manages to load
  17,000 files into the hard disk cache (see #97)
2021-11-12 16:38:54 -08:00
Justine Tunney 245a9c206b Fix redbean build
Also ran clang-format on redbean.c

See #312 and #321
2021-11-12 16:34:18 -08:00
Paul Kulchenko 1bdc8faa65 Add redbean function for simple HMAC (#321) 2021-11-12 16:26:14 -08:00
Paul Kulchenko 8f05990d5a Extend GetZipPaths to accept an optional prefix (#320) 2021-11-12 15:28:05 -08:00
Gautham 7fe9e70117 Backporting METH_FASTCALL from Python 3.7 (#317)
* dict copy speedup

refer to bpo-31179 or python/cpython@boa7a037b8fde

* __build_class__() uses METH_FASTCALL

refer python/cpython@69de71b255
refer python/cpython@773dc6dd06

a single test related to __prepare__ fails.

* type_prepare uses METH_FASTCALL

refer python/cpython@d526cfe546
refer python/cpython@80ab22fa2c

the prepare-related test still fails.  It's just related to the error
message format though.

* separate into ParseStack and ParseStackAndKeywords

refer python/cpython@6518a93cb1
refer python/cpython@3e1fad6913
refer python/cpython@c0083fc47d

* Add _PyArg_NoStackKeywords

refer python/cpython@29d39cc8f5

* _PyStack_UnpackDict now returns int

refer python/cpython@998c20962c

* METH_FASTCALL changes to .inc files

done via python's Argument Clinic tool,
refer python/cpython@259f0e4437

* Added _PyArg_UnpackStack

refer python/cpython@fe54dda08

* Argument Clinic FASTCALL again

refer python/cpython@0c4a828ca

* Argument Clinic for ordered dictionary object

refer python/cpython@b05cbac052

* speed up getargs

refer python/cpython@1741441649

* FASTCALL for sorted, next, and getattr

refer python/cpython@5a60ecaa7a
refer python/cpython@fda6d0acf0
refer python/cpython@84b388bb80

* Optimize methoddescr_call

refer python/cpython@2a1b676d1f
refer python/cpython@c52572319c
refer python/cpython@35ecebe165
refer python/cpython@8128d5a491

* cleanup _PyMethodDef_RawFastCallDict

refer python/cpython@0a2e46835d
refer python/cpython@98ccba8344
refer python/cpython@c89ef828cf
refer python/cpython@250e4b0063

* print now uses METH_FASTCALL

refer python/cpython@c3858bd7c6
refer python/cpython@bd584f169f
refer python/cpython@06d34393c2

* _struct module now uses Argument Clinic

refer python/cpython@3f2d10132d

* make deque methods faster

refer python/cpython@dd407d5006

* recursive calls in PyObject_Call

refer python/cpython@7399a05965

only partially ported, because RawFastCallKeywords hasn't been ported

* add macros

refer python/cpython@68a001dd59

* all tests pass in MODE=dbg

* convert some internal functions to FASTCALL

__import__ might need to be changed later, if it is possible to backport
the METH_FASTCALL | METH_KEYWORDS flag distinction later.

* speed up unpickling

refer python/cpython@bee09aecc2

* added _PyMethodDef_RawFastCallKeywords

refer python/cpython@7399a05965

* PyCFunction_Call performance

refer python/cpython@12c5838dae

* avoid PyMethodObject in slots

main change in python/cpython@516b98161a
test_exceptions changed in python/cpython@331bbe6aaa
type_settattro changed in python/cpython@193f7e094f
_PyObject_CallFunctionVa changed in python/cpython@fe4ff83049

* fix refcount error found in MODE=dbg

all tests now pass in MODE=dbg
2021-11-12 15:26:57 -08:00
Gautham 6f658f058b Change noinline to dontinline (#312)
We defined `noinline` as an abbreviation for the longer version
`__attribute__((__noinline__))` which caused name clashes since
third party codebases often write it as `__attribute__((noinline))`.
2021-11-12 15:12:18 -08:00
Paul Kulchenko ca611efc43 Redbean getstatus and more (#308)
* Add GetBody() Lua API to redbean.
   This improves consistency with RFC 7230 terminology and
   should be favored over the old GetPayload function.
* Add GetStatus() API to redbean.
   This is useful to get status after it's changed/set by Redbean,
   for example if 505 or 508 is set when ServeRedirect is called.
* Introduce GetAssetComment() API to redbean.
   This function should be favored over the old name GetComment().
* Introduce IsLoopbackClient() API to redbean
* Limit redbean reason to 128 chars when set instead of reporting an error
2021-11-12 15:00:41 -08:00
Paul Kulchenko e5d1536256 Redbean doc updates (#307)
* Fix redbean re.NEWLINE documentation
* Add documentation for method and body parameters in redbean Fetch
* Add documentation for redbean ProgramAddr
* Update redbean SetHeader documentation to clarify behavior with Serve* calls
2021-11-01 18:52:02 -07:00
Gautham d7ff346b52 Add some Python 3.7 backports (#306)
* make.com now uses stack size of 2mb
* optimize _PyCFunction_FastCallKeywords
* backport python@cpython/7fc252adfbedece75f2330bcfdadbf84dee7836f
2021-10-29 22:54:14 -07:00
Justine Tunney 903cc38c37 Revert "Make MODE=tiny not depend on default build"
This reverts commit 30cd28b1f8.
2021-10-26 17:14:38 -07:00
ahgamut 3616f2a432 get make to build 2021-10-26 14:58:05 -07:00
ahgamut 7a50dba812 changes made to enable compilation 2021-10-26 14:58:05 -07:00
ahgamut 19f70a154e add make-4.3.tar.gz 2021-10-26 14:58:05 -07:00
jacereda 0a0997a872 Add WIN32 symbols for OpenGL support (#304) 2021-10-26 14:18:13 -07:00
Justine Tunney 30cd28b1f8 Make MODE=tiny not depend on default build
This issue was spotted by @ahgamut in #292.
2021-10-25 16:26:22 -07:00
Justine Tunney 91d783352a Apply fixup to cthread initialization (#301)
Cosmopolitan Threads are currently Linux-only (with some NetBSD
and Windows support too!). This change ensures we only initialize
the high-level threading runtime when Cosmopolitan Threads are used.
2021-10-25 16:22:10 -07:00
Florian Lemaitre 45a7435788 [WIP] Threading phase 2 (#301)
* Exponential back-off
* Removed "native" specifier
* Abstract away Futex for cthread
* Complete setup for TLS (including main thread)
2021-10-25 16:02:26 -07:00
Paul Kulchenko 660ff56d40 Redbean fix lua panic (#300)
* Fix Lua panic in redbean when calling request/connection functions from .init.lua

The error calls were triggered appropriately, but used the global Lua
state instead of the current Lua state (within protected call), which
triggered Lua panic. This executes the error in the proper context.

* Rename global Lua state object to make its (mis-)usage easier to detect
2021-10-25 14:54:56 -07:00
Paul Kulchenko c00755f921 Improve error messages for consistency (#297) 2021-10-25 14:44:04 -07:00
Paul Kulchenko 013f03e33f Redbean fix redirect (#294)
* Fix redbean crash during redirect in debug logging mode

* Add reset for redirect loop check in redbean Route

Without this reset a combination of RoutePath() and Route() calls
could return "508 loop detected", since RoutePath could be called
twice for the same redirected path.

The protection against looping is still there, as it can only
loop inside the Route() call (as it always serves something).

* Update redbean redirect message for clarity
2021-10-25 14:04:57 -07:00
Gautham 49db877fbe Minimize Python startup imports (#292)
* get_exports_list should return list
* remove unintentional `CC=clang` in makefile
* avoid importing sysconfig during startup

site.py requires only a couple of functions from sysconfig, but needs to
load the entirety of sysconfig to get those functions. This commit
makes it such that sysconfig is imported only when sys.platform is darwin.

* remove redundant constants from stat module

The constants are only there in case the C implementation (ie the _stat
module) is not available. With Cosmopolitan the _stat module is always
available. The entire Lib/stat.py file can be removed if the Windows-based
constants can be moved into the Modules/_stat.c.

* minimal changes to os.py

python checks os-based assumptions at startup, some of  which can be
bypassed since this is Cosmopolitan Python.
2021-10-25 14:04:04 -07:00
Et7f3 253ac31a64 Fix build from docker build with alpine from macOS (#286)
* fix(build): Remove unused variable and fix const warning.
* fix(build): Fix others -Werror=discarded-qualifiers
Co-authored-by: Élie BRAMI <[email protected]>
2021-10-25 13:39:05 -07:00
Justine Tunney 67b5200a0b Add MODE=optlinux build mode (#141) 2021-10-14 19:36:49 -07:00
Justine Tunney 226aaf3547 Improve memory safety
This commit makes numerous refinements to cosmopolitan memory handling.

The default stack size has been reduced from 2mb to 128kb. A new macro
is now provided so you can easily reconfigure the stack size to be any
value you want. Work around the breaking change by adding to your main:

    STATIC_STACK_SIZE(0x00200000);  // 2mb stack

If you're not sure how much stack you need, then you can use:

    STATIC_YOINK("stack_usage_logging");

After which you can `sort -nr o/$MODE/stack.log`. Based on the unit test
suite, nothing in the Cosmopolitan repository (except for Python) needs
a stack size greater than 30kb. There are also new macros for detecting
the size and address of the stack at runtime, e.g. GetStackAddr(). We
also now support sigaltstack() so if you want to see nice looking crash
reports whenever a stack overflow happens, you can put this in main():

    ShowCrashReports();

Under `make MODE=dbg` and `make MODE=asan` the unit testing framework
will now automatically print backtraces of memory allocations when
things like memory leaks happen. Bugs are now fixed in ASAN global
variable overrun detection. The memtrack and asan runtimes also handle
edge cases now. The new tools helped to identify a few memory leaks,
which are fixed by this change.

This change should fix an issue reported in #288 with ARG_MAX limits.
Fixing this doubled the performance of MKDEPS.COM and AR.COM yet again.
2021-10-13 17:27:13 -07:00
Florian Lemaitre a0b39f886c [WIP] Threading (#282)
* Thread creation
* Proper thread creation and exit
* Join/Detach protocol
* Added semaphore with futex (hopefully fast)
2021-10-13 11:26:05 -07:00
Gautham d852640a1e Add Python ftrace contextmanager (#285) 2021-10-13 11:00:25 -07:00
Justine Tunney 425a57080d Fix minor issues 2021-10-08 20:51:11 -07:00
Justine Tunney bba144246a Improve Das Blinkenlights
It's now possible to scroll panels is the TUI while the display
is blocked on input. INT 16h now translates UTF-8 to CP-437 and
displays unmappable characters using a lambda symbol. Bracketed
paste mode guards will also be filtered out.
2021-10-08 16:44:19 -07:00
Justine Tunney 7061c79c22 Make fixes, improvements, and chibicc python bindings
- python now mixes audio 10x faster
- python octal notation is restored
- chibicc now builds code 3x faster
- chibicc now has help documentation
- chibicc can now generate basic python bindings
- linenoise now supports some paredit-like features

See #141
2021-10-08 08:41:57 -07:00
Justine Tunney 28997f3acb Make mkdeps.com go faster
This program usually runs once at the begininng of each GNU Make
invocation. It generates an o//depend file with 170,000 lines of
Makefile code to define source -> headers relationships.

This change makes that take 650 milliseconds rather than 1,100ms
by improving the performance of strstr(), using longsort(), plus
migrating to the new append library.
2021-10-04 06:46:46 -07:00
Justine Tunney 725f4d79f6 Apply fixes and speedups 2021-10-04 03:23:31 -07:00
Justine Tunney 7521bf9e73 Add stack overflow checking to Python 2021-10-02 10:50:41 -07:00
Justine Tunney 47a53e143b Productionize new APE loader and more
The APE_NO_MODIFY_SELF loader payload has been moved out of the examples
folder and improved so that it works on BSD systems, and permits general
elf program headers. This brings its quality up enough that it should be
acceptable to use by default for many programs, e.g. Python, Lua, SQLite
and Python. It's the responsibility of the user to define an appropriate
TMPDIR if /tmp is considered an adversarial environment. Mac OS shall be
supported by APE_NO_MODIFY_SELF soon.

Fixes and improvements have been made to program_executable_name as it's
now the one true way to get the absolute path of the executing image.

This change fixes a memory leak in linenoise history loading, introduced
by performance optimizations in 51904e2687
This change fixes a longstanding regression with Mach system calls, that
23ae9dfceb back in February which impacted
our sched_yield() implementation, which is why no one noticed until now.

The Blinkenlights PC emulator has been improved. We now fix rendering on
XNU and BSD by not making the assumption that the kernel terminal driver
understands UTF8 since that seems to break its internal modeling of \r\n
which is now being addressed by using \e[𝑦H instead. The paneling is now
more compact in real mode so you won't need to make your font as tiny if
you're only emulating an 8086 program. The CLMUL ISA is now emulated too

This change also makes improvement to time. CLOCK_MONOTONIC now does the
right thing on Windows NT. The nanosecond time module functions added in
Python 3.7 have been backported.

This change doubles the performance of Argon2 password stretching simply
by not using its copy_block and xor_block helper functions, as they were
trivial to inline thus resulting in us needing to iterate over each 1024
byte block four fewer times.

This change makes code size improvements. _PyUnicode_ToNumeric() was 64k
in size and now it's 10k. The CJK codec lookup tables now use lazy delta
zigzag deflate (δzd) encoding which reduces their size from 600k to 200k
plus the code bloat caused by macro abuse in _decimal.c is now addressed
so our fully-loaded statically-linked hermetically-sealed Python virtual
interpreter container is now 9.4 megs in the default build mode and 5.5m
in MODE=tiny which leaves plenty of room for chibicc.

The pydoc web server now accommodates the use case of people who work by
SSH'ing into a different machine w/ python.com -m pydoc -p8080 -h0.0.0.0

Finally Python Capsulae delenda est and won't be supported in the future
2021-10-02 08:27:03 -07:00
Justine Tunney 9cb54218ab Add error checks to Python objectifier (#281)
PYOBJ.COM was failing when statically analyzing _pyio.py in MODE=dbg
because co_consts contained a big number, which dirtied the interpreter
exception state. We now do comprehensive error checking w/ Python API.

The -DSTACK_FRAME_UNLIMITED CPPFLAG has been removed from DES since its
self test function has been fixed to use heap memory rather than making
aggressive use of the stack.

This change also fixes a regression with function tracing (the --ftrace
flag a.k.a. ftrace_install() a.k.a. cosmo.ftrace) in ASAN build modes.
Lastly, the _tracemalloc module should now always be available for use
in MODE=dbg.
2021-10-02 06:17:17 -07:00
Gautham 57f0eed382 Fix Pyston speedups (#281)
We remove (i.e. hide behind a debug ifdef) the recursion checking methods,
and the memory hooks and memory allocator methods. ASAN mode has no
PYMALLOC, so we need a macro. Fix build break with des.c stack allocation.
2021-10-02 01:28:51 -07:00
Gautham 2fe8571010 Add zipimport hook at the end just in case (#280)
In Python, the zipimport path hook is usually the first entry in
sys.path_hooks, so that any zip files in sys.path can be handled
correctly. In the APE, the zipimport hook was removed because it was
relatively slow compared to Cosmopolitan when it came to handling
imports from the APE's internal zip store.

However, some python scripts (for example when pip installs some
packages) modify sys.path to consider a local zip file, and then attempt
to import from it. This change prevents potential "unable to import"
errors in such cases, so that Actually Portable Python can be more of a
drop-in improved replacement.
2021-09-29 01:50:34 -07:00
Paul Kulchenko 9cabdaabfd Add clock() polyfill on Windows (#279)
We normally use CLOCK_PROCESS_CPUTIME_ID but there's no clock_gettime()
on Windows NT.
2021-09-28 02:14:24 -07:00
Justine Tunney 39bf41f4eb Make numerous improvements
- Python static hello world now 1.8mb
- Python static fully loaded now 10mb
- Python HTTPS client now uses MbedTLS
- Python REPL now completes import stmts
- Increase stack size for Python for now
- Begin synthesizing posixpath and ntpath
- Restore Python \N{UNICODE NAME} support
- Restore Python NFKD symbol normalization
- Add optimized code path for Intel SHA-NI
- Get more Python unit tests passing faster
- Get Python help() pagination working on NT
- Python hashlib now supports MbedTLS PBKDF2
- Make memcpy/memmove/memcmp/bcmp/etc. faster
- Add Mersenne Twister and Vigna to LIBC_RAND
- Provide privileged __printf() for error code
- Fix zipos opendir() so that it reports ENOTDIR
- Add basic chmod() implementation for Windows NT
- Add Cosmo's best functions to Python cosmo module
- Pin function trace indent depth to that of caller
- Show memory diagram on invalid access in MODE=dbg
- Differentiate stack overflow on crash in MODE=dbg
- Add stb_truetype and tools for analyzing font files
- Upgrade to UNICODE 13 and reduce its binary footprint
- COMPILE.COM now logs resource usage of build commands
- Start implementing basic poll() support on bare metal
- Set getauxval(AT_EXECFN) to GetModuleFileName() on NT
- Add descriptions to strerror() in non-TINY build modes
- Add COUNTBRANCH() macro to help with micro-optimizations
- Make error / backtrace / asan / memory code more unbreakable
- Add fast perfect C implementation of μ-Law and a-Law audio codecs
- Make strtol() functions consistent with other libc implementations
- Improve Linenoise implementation (see also github.com/jart/bestline)
- COMPILE.COM now suppresses stdout/stderr of successful build commands
2021-09-28 01:52:34 -07:00
Paul Kulchenko fa7b4f5bd1 Updated lua-Argon2 to use Argon2_id variant
As recommended in RFC9106:
https://www.rfc-editor.org/rfc/rfc9106.html#name-recommendations
2021-09-27 21:42:40 -07:00
Paul Kulchenko b883473a6c Remove optimized blamka rounds from Argon2
Optimized blamka rounds occasionally SIGSERV for me,
so the reference implementation is used instead.
2021-09-27 21:42:40 -07:00
Paul Kulchenko af1153e057 Reorganize handling of added SSE intrinsics to simplify. 2021-09-27 21:42:40 -07:00
Paul Kulchenko 2e4b40042a Add missing Intel SSE2 intrinsics needed for Argon2 2021-09-27 21:42:40 -07:00
Paul Kulchenko 42aafc847e Update lua-argon2 for cosmopolitan/redbean 2021-09-27 21:42:40 -07:00
Paul Kulchenko b51db9f923 Add lua-argon2 module for redbean/lua 2021-09-27 21:42:40 -07:00
Paul Kulchenko 6fba9601ff Update Argon2 for cosmopolitan libc 2021-09-27 21:42:40 -07:00
Paul Kulchenko 9e7773a076 Add Argon2 implementation 2021-09-27 21:42:40 -07:00
jacereda 48a2668239 Fix bad dependency (#276) 2021-09-27 20:39:38 -07:00
Paul Kulchenko 5ffeaa8e33 Fix SSE scalar ops (#271) 2021-09-17 16:49:53 -07:00
Florian Lemaitre 18ccfeb919 Embed APE loader inside APE (#267)
The `ape-no-modify-self.o` bootloader now has an mmap-based
payload that helps read-only APE binaries be load faster since it
doesn't need to copy any files.
2021-09-17 16:49:10 -07:00
Justine Tunney b5f743cdc3 Begin incorporating Python unit tests into build
We now build a separate APE binary for each test so they can run in
parallel. We've got 148 tests running fast and stable so far.
2021-09-12 21:04:44 -07:00
Justine Tunney 51904e2687 Improve Python and Linenoise
This change reinvents all the GNU Readline features I discovered that I
couldn't live without, e.g. UTF-8, CTRL-R search and CTRL-Y yanking. It
now feels just as good in terms of user interface from the subconscious
workflow perspective. It's real nice to finally have an embeddable line
reader that's actually good with a 30 kb footprint and a bsd-2 license.

This change adds a directory to the examples folder, explaining how the
new Python compiler may be used.  Some of the bugs with Python binaries
have been addressed but overall it's still a work in progress.
2021-09-11 22:30:37 -07:00
Justine Tunney ad52387b74 Fix race condition in quickjs build config (#251)
qjsc.com now has a -n do nothing flag so the makefile can create a
localized binary. See also #267 where we have an exciting new change
aiming to address this particular APE gotcha.
2021-09-11 22:16:17 -07:00
agreppin 6ad0602392 quickjs: add repl + qjscalc (#251)
- Compile repl.js & qjscalc.js and include them in qjs.com zip
- Change quickjs-libc.c / js_os_poll to handle Windows console

This last change is needed because poll and select on Windows forbid
non-socket handles and Cosmopolitan Libc hasn't polyfilled that yet.
2021-09-11 16:52:49 -07:00
Paul Kulchenko 1b93066883 Add GetCookie to redbean Lua (#269) 2021-09-11 16:46:21 -07:00
Justine Tunney 559b024e1d Decentralize Python native module linkage
We can now link even smaller Python binaries. For example, the hello.com
program in the Python build directory is a compiled linked executable of
hello.py which just prints hello world. Using decentralized sections, we
can make that binary 1.9mb in size (noting that python.com is 6.3 megs!)

This works for nontrivial programs too. For example, say we want an APE
binary that's equivalent to python.com -m http.server. Our makefile now
builds such a binary using the new launcher and it's only 3.2mb in size
since Python sources get turned into ELF objects, which tell our linker
that we need things like native hashing algorithm code.
2021-09-07 11:40:11 -07:00
Justine Tunney dfa0359b50 Exclude .py files in MODE=rel / tiny 2021-09-06 19:34:57 -07:00
Justine Tunney 4f41f2184d Improve Python tree-shaking 2021-09-06 19:24:10 -07:00
Justine Tunney 5bb2275788 Get bzip2 to build 2021-09-06 17:36:47 -07:00
Justine Tunney a8fb68af4b Add bzip2 1.0.8 2021-09-06 15:51:57 -07:00
Paul Kulchenko 1eed7d47bd Add error reporting to redbean Slurp (#268)
This should allow `content = assert(Slurp(filename))` to work as
expected and report an error if file doesn't exist or can't be read.
2021-09-06 08:21:37 -07:00
Justine Tunney 44c87b83ff Implement tree-shaking for Python sources 2021-09-05 01:20:03 -07:00
Justine Tunney 81287b7ec0 Introduce Python objectifier (#259) 2021-09-04 15:44:00 -07:00
Justine Tunney 34b68f1945 Make mappings unlimited on NT
This change might also fix fork() in certain cases on NT.
2021-09-04 13:20:47 -07:00
Justine Tunney ab64c746cc Fix issues with InfoZip build
Artifacts weren't being invalidated because THIRD_PARTY_ZIP_SRCS_C
needed to be renamed THIRD_PARTY_ZIP_SRCS. This caused a build break.
2021-09-04 06:50:57 -07:00
Justine Tunney a81192e0b9 Fix some build breaks 2021-09-04 02:29:57 -07:00
Gautham 27f7ffd4fd Add speedups from pyston (#264)
This should make Python go 30% faster. It does that by trading
away some debuggability, like _tracemalloc. It can be re-enabled
using `make MODE=dbg`.
2021-09-04 02:21:37 -07:00
Paul Kulchenko 31dd714081 Add SetCookie method to redbean Lua (#265) 2021-09-04 02:12:12 -07:00
Justine Tunney 969174e155 Add APE interpreter example (#263) 2021-09-04 00:58:21 -07:00
Justine Tunney 5b60e5a37d Fix termios struct on Linux
The termios::c_cc field turned out to be incorrectly defined on Linux
due to some confusion between the glibc and kernel definitions. We'll
be using the kernel definition, since it has the strongest consensus.

Fields have been have been added to struct stat for BSD compatibility
such as st_birthtim, plus the GLIBC compatibility of isystem/sys/stat
has been improved.
2021-09-03 22:19:41 -07:00
Paul Kulchenko 0584684a82 Improve logger API (#262)
This breaking change improves naming consistency.

- Rename LOGF to INFOF
- Rename recently introduced ANYF to LOGF
- Remove V* log calls, as they are not being used
2021-09-03 21:14:26 -07:00
Justine Tunney 50937be752 Fix select() on Windows for timeout (#141) 2021-08-26 15:59:55 -07:00
Justine Tunney 3085ac7837 Improve system call support 2021-08-25 21:36:17 -07:00
Gautham 63b867bd2f Added _multiprocessing to Python (#259)
Also changed some PYTHON_YOINKs so that http.server would work in
MODE=tiny.
2021-08-25 19:45:59 -07:00
Paul Kulchenko 0b7737b20a Fix redbean StoreAsset w/ Deflate (#258) 2021-08-25 05:43:26 -07:00
Paul Kulchenko 818926dbae Fix redbean latency and resource usage logging (#257) 2021-08-22 20:16:10 -07:00
Justine Tunney 7d25fb0090 Import some Lua documentation
I personally find it easier to read the documentation in Emacs
using JavaDoc style comments.
2021-08-22 15:03:04 -07:00
Paul Kulchenko 41b9eb6873 Redbean log improvements (#256)
* Update log level for redbean messages for better log content
* Add categories to redbean log messages
* Reorganize Lua error logging for consistency
* Replace perror logging with FATALF
* Update server failure reporting to better identify response code
* Replace `flogf` with DIEF logging for consistency
2021-08-22 15:01:52 -07:00
Justine Tunney 00611e9b06 Improve ZIP filesystem and change its prefix
The ZIP filesystem has a breaking change. You now need to use /zip/ to
open() / opendir() / etc. assets within the ZIP structure of your APE
binary, instead of the previous convention of using zip: or zip! URIs.
This is needed because Python likes to use absolute paths, and having
ZIP paths encoded like URIs simply broke too many things.

Many more system calls have been updated to be able to operate on ZIP
files and file descriptors. In particular fcntl() and ioctl() since
Python would do things like ask if a ZIP file is a terminal and get
confused when the old implementation mistakenly said yes, because the
fastest way to guarantee native file descriptors is to dup(2). This
change also improves the async signal safety of zipos and ensures it
doesn't maintain any open file descriptors beyond that which the user
has opened.

This change makes a lot of progress towards adding magic numbers that
are specific to platforms other than Linux. The philosophy here is that,
if you use an operating system like FreeBSD, then you should be able to
take advantage of FreeBSD exclusive features, even if we don't polyfill
them on other platforms. For example, you can now open() a file with the
O_VERIFY flag. If your program runs on other platforms, then Cosmo will
automatically set O_VERIFY to zero. This lets you safely use it without
the need for #ifdef or ifstatements which detract from readability.

One of the blindspots of the ASAN memory hardening we use to offer Rust
like assurances has always been that memory passed to the kernel via
system calls (e.g. writev) can't be checked automatically since the
kernel wasn't built with MODE=asan. This change makes more progress
ensuring that each system call will verify the soundness of memory
before it's passed to the kernel. The code for doing these checks is
fast, particularly for buffers, where it can verify 64 bytes a cycle.

- Correct O_LOOP definition on NT
- Introduce program_executable_name
- Add ASAN guards to more system calls
- Improve termios compatibility with BSDs
- Fix bug in Windows auxiliary value encoding
- Add BSD and XNU specific errnos and open flags
- Add check to ensure build doesn't talk to internet
2021-08-22 01:11:53 -07:00
Paul Kulchenko 2730c66f4a Add GetTime to redbean Lua (#255) 2021-08-22 00:59:47 -07:00
Paul Kulchenko c506584174 Don't hyphenate delta log lines (#253) 2021-08-19 09:43:01 -07:00
Justine Tunney ed485391da Reduce memory needed by ASAN morgue 2021-08-19 09:34:24 -07:00
Justine Tunney d5a37de435 Fix upstream Lua test breakage due to Linenoise 2021-08-19 09:34:24 -07:00
Justine Tunney 65f32fad52 Fix regression in _gclongjmp() 2021-08-19 09:34:24 -07:00
Justine Tunney da45c7c80b Clean up gdtoa code 2021-08-19 09:34:24 -07:00
Paul Kulchenko 7341336b1a Improve redbean docs (#249)
- Add Location to ProgramHeader exclusions
- Add ProgramHeader documentation
- Update ProgramRedirect to check location validity
2021-08-19 09:34:50 -07:00
Paul Kulchenko a63b147a93 Add file/line reporting to redbean LuaLog (#250) 2021-08-19 09:32:33 -07:00
Paul Kulchenko 0ba3617e7f Add ERRORF macro for kLogError log level (#252) 2021-08-19 04:14:08 -07:00
Justine Tunney 8af197560e Improve Libc by making Python work even better
Actually Portable Python is now outperforming the Python binaries
that come bundled with Linux distros, at things like HTTP serving.
You can now have a fully featured Python install in just one .com
file that runs on six operating systems and is about 10mb in size.
With tuning, the tiniest is ~1mb. We've got most of the libraries
working, including pysqlite, and the repl now feels very pleasant.
The things you can't do quite yet are: threads and shared objects
but that can happen in the future, if the community falls in love
with this project and wants to see it developed further. Changes:

- Add siginterrupt()
- Add sqlite3 to Python
- Add issymlink() helper
- Make GetZipCdir() faster
- Add tgamma() and finite()
- Add legacy function lutimes()
- Add readlink() and realpath()
- Use heap allocations when appropriate
- Reorganize Python into two-stage build
- Save Lua / Python shell history to dotfile
- Integrate Python Lib embedding into linkage
- Make isregularfile() and isdirectory() go faster
- Make Python shell auto-completion work perfectly
- Make crash reports work better if changed directory
- Fix Python+NT open() / access() flag overflow error
- Disable Python tests relating to \N{LONG NAME} syntax
- Have Python REPL copyright() show all notice embeddings

The biggest technical challenge at the moment is working around
when Python tries to be too clever about filenames.
2021-08-18 22:16:23 -07:00
Gautham 98ccbf44b1 Tell _frozen_importlib to consider bytecode first (#248) 2021-08-18 21:58:05 -07:00
Justine Tunney ebb8c85496 Experiment with making Python go faster
The goal is to put the compiled pyc files in the APE ZIP.
2021-08-18 21:57:11 -07:00
Paul Kulchenko 4486ad5c9e Add ServeRedirect function to redbean Lua (#246) 2021-08-17 14:26:33 -07:00
2566 changed files with 629854 additions and 139833 deletions

No files matched your search

+28 -25
View File
@@ -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 \
+1 -1
View File
@@ -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 |
+36 -24
View File
@@ -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
View File
@@ -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
View File
@@ -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) \
+10
View File
@@ -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
View File
@@ -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);
}
+32
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -14,4 +14,4 @@
# so it grants many small performance improvements.
mkdir -p o/tmp
echo o/tmp
echo $PWD/o/tmp
+19 -10
View File
@@ -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 $@ $<
+46
View File
@@ -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;
}
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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; \
-1
View File
@@ -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] =
-63
View File
@@ -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__
+40
View 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;
}
+38
View File
@@ -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;
}
+37
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+2
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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"
+24
View File
@@ -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
View File
@@ -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
+21
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+5
View File
@@ -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;
}
+116
View File
@@ -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
+4
View File
@@ -0,0 +1,4 @@
def main():
print('cosmopolitan is cool!')
if __name__ == '__main__':
main()
+1
View File
@@ -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"
+77
View File
@@ -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
View File
@@ -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;
}
+63
View File
@@ -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;
}
+98
View File
@@ -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;
}
}
+2
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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;
}
}
}
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+2 -1
View File
@@ -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;
+43
View File
@@ -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;
}
}
+1
View File
@@ -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 ─╬─│┼
+84
View File
@@ -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;
}
+14
View File
@@ -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 ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
+1
View File
@@ -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__)
+1 -1
View File
@@ -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;
}
+16
View File
@@ -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_ */
+4 -4
View File
@@ -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; \
})
+5 -2
View File
@@ -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;
+32
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+21
View File
@@ -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
View File
@@ -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 &&
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+55
View File
@@ -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();
}
}
+4 -4
View File
@@ -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);
}
}
+1 -1
View File
@@ -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();
+3
View File
@@ -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
View File
@@ -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;
}
}
+8 -1
View File
@@ -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()) {
+1
View File
@@ -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
View File
@@ -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;
}
+2
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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.
+6 -9
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/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);
+30
View File
@@ -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 {
+4
View File
@@ -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);
}
+1
View File
@@ -16,6 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h"
#include "libc/sysv/errfuns.h"
+7
View File
@@ -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 {
+2 -1
View File
@@ -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;
+2
View File
@@ -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
View File
@@ -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()
*/
+39
View File
@@ -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();
}
+55
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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