2021-05-14 12:36:58 +00:00
|
|
|
|
SYNOPSIS
|
|
|
|
|
|
2022-04-18 07:01:26 +00:00
|
|
|
|
redbean.com [-?BVabdfghjkmsuvz] [-p PORT] [-D DIR] [-- SCRIPTARGS...]
|
2021-05-14 12:36:58 +00:00
|
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
|
|
|
|
|
|
redbean - single-file distributable web server
|
|
|
|
|
|
2021-06-24 19:31:26 +00:00
|
|
|
|
OVERVIEW
|
|
|
|
|
|
|
|
|
|
redbean makes it possible to share web applications that run offline
|
|
|
|
|
as a single-file Actually Portable Executable PKZIP archive which
|
|
|
|
|
contains your assets. All you need to do is download the redbean.com
|
|
|
|
|
program below, change the filename to .zip, add your content in a zip
|
|
|
|
|
editing tool, and then change the extension back to .com.
|
|
|
|
|
|
|
|
|
|
redbean can serve 1 million+ gzip encoded responses per second on a
|
|
|
|
|
cheap personal computer. That performance is thanks to zip and gzip
|
|
|
|
|
using the same compression format, which enables kernelspace copies.
|
|
|
|
|
Another reason redbean goes fast is that it's a tiny static binary,
|
|
|
|
|
which makes fork memory paging nearly free.
|
|
|
|
|
|
|
|
|
|
redbean is also easy to modify to suit your own needs. The program
|
|
|
|
|
itself is written as a single .c file. It embeds the Lua programming
|
|
|
|
|
language and SQLite which let you write dynamic pages.
|
|
|
|
|
|
2022-04-21 11:01:42 +00:00
|
|
|
|
FEATURES
|
|
|
|
|
|
|
|
|
|
- Lua v5.4
|
|
|
|
|
- SQLite 3.35.5
|
|
|
|
|
- TLS v1.2 / v1.1 / v1.0
|
|
|
|
|
- HTTP v1.1 / v1.0 / v0.9
|
|
|
|
|
- Chromium-Zlib Compression
|
|
|
|
|
- Statusz Monitoring Statistics
|
|
|
|
|
- Self-Modifying PKZIP Object Store
|
|
|
|
|
- Linux + Windows + Mac + FreeBSD + OpenBSD + NetBSD
|
|
|
|
|
|
2021-05-14 12:36:58 +00:00
|
|
|
|
FLAGS
|
|
|
|
|
|
2022-04-18 07:01:26 +00:00
|
|
|
|
-h or -? help
|
2021-05-14 12:36:58 +00:00
|
|
|
|
-d daemonize
|
|
|
|
|
-u uniprocess
|
|
|
|
|
-z print port
|
|
|
|
|
-m log messages
|
2022-04-25 15:30:14 +00:00
|
|
|
|
-i interpreter mode
|
2021-06-24 19:31:26 +00:00
|
|
|
|
-b log message bodies
|
2021-05-14 12:36:58 +00:00
|
|
|
|
-a log resource usage
|
|
|
|
|
-g log handler latency
|
2022-04-13 21:43:42 +00:00
|
|
|
|
-e eval Lua code in arg
|
|
|
|
|
-F eval Lua code in file
|
2022-04-13 15:49:17 +00:00
|
|
|
|
-E show crash reports to public ips
|
2021-07-08 04:44:27 +00:00
|
|
|
|
-j enable ssl client verify
|
|
|
|
|
-k disable ssl fetch verify
|
2022-04-18 07:01:26 +00:00
|
|
|
|
-Z log worker system calls
|
2021-07-08 04:44:27 +00:00
|
|
|
|
-f log worker function calls
|
2021-11-15 05:26:56 +00:00
|
|
|
|
-B only use stronger cryptography
|
2022-05-18 23:41:29 +00:00
|
|
|
|
-X disable ssl server and client support
|
2022-07-09 08:18:55 +00:00
|
|
|
|
-* permit self-modification of executable
|
2022-05-29 15:14:55 +00:00
|
|
|
|
-J disable non-ssl server and client support
|
|
|
|
|
-% hasten startup by not generating an rsa key
|
2021-06-24 19:31:26 +00:00
|
|
|
|
-s increase silence [repeatable]
|
|
|
|
|
-v increase verbosity [repeatable]
|
|
|
|
|
-V increase ssl verbosity [repeatable]
|
2022-07-09 12:49:19 +00:00
|
|
|
|
-S increase pledge sandboxing [repeatable]
|
2021-06-24 19:31:26 +00:00
|
|
|
|
-H K:V sets http header globally [repeatable]
|
|
|
|
|
-D DIR overlay assets in local directory [repeatable]
|
|
|
|
|
-r /X=/Y redirect X to Y [repeatable]
|
|
|
|
|
-R /X=/Y rewrites X to Y [repeatable]
|
|
|
|
|
-K PATH tls private key path [repeatable]
|
|
|
|
|
-C PATH tls certificate(s) path [repeatable]
|
2022-03-15 00:19:31 +00:00
|
|
|
|
-A PATH add assets with path (recursive) [repeatable]
|
2021-06-24 19:31:26 +00:00
|
|
|
|
-M INT tunes max message payload size [def. 65536]
|
2021-07-08 04:44:27 +00:00
|
|
|
|
-t INT timeout ms or keepalive sec if <0 [def. 60000]
|
2021-06-24 19:31:26 +00:00
|
|
|
|
-p PORT listen port [def. 8080; repeatable]
|
|
|
|
|
-l ADDR listen addr [def. 0.0.0.0; repeatable]
|
|
|
|
|
-c SEC configures static cache-control
|
2022-05-14 11:33:58 +00:00
|
|
|
|
-W TTY use tty path to monitor memory pages
|
2021-05-14 12:36:58 +00:00
|
|
|
|
-L PATH log file location
|
|
|
|
|
-P PATH pid file location
|
|
|
|
|
-U INT daemon set user id
|
|
|
|
|
-G INT daemon set group id
|
2022-07-17 13:11:13 +00:00
|
|
|
|
-w PATH launch browser on startup
|
2022-04-28 16:42:36 +00:00
|
|
|
|
--strace enables system call tracing (see also -Z)
|
|
|
|
|
--ftrace enables function call tracing (see also -f)
|
2021-05-14 12:36:58 +00:00
|
|
|
|
|
2022-04-21 11:01:42 +00:00
|
|
|
|
KEYBOARD
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
CTRL-D EXIT
|
|
|
|
|
CTRL-C CTRL-C EXIT
|
|
|
|
|
CTRL-E END
|
|
|
|
|
CTRL-A START
|
|
|
|
|
CTRL-B BACK
|
|
|
|
|
CTRL-F FORWARD
|
|
|
|
|
CTRL-L CLEAR
|
|
|
|
|
CTRL-H BACKSPACE
|
|
|
|
|
CTRL-D DELETE
|
|
|
|
|
CTRL-N NEXT HISTORY
|
|
|
|
|
CTRL-P PREVIOUS HISTORY
|
|
|
|
|
CTRL-R SEARCH HISTORY
|
|
|
|
|
CTRL-G CANCEL SEARCH
|
|
|
|
|
ALT-< BEGINNING OF HISTORY
|
|
|
|
|
ALT-> END OF HISTORY
|
|
|
|
|
ALT-F FORWARD WORD
|
|
|
|
|
ALT-B BACKWARD WORD
|
|
|
|
|
CTRL-K KILL LINE FORWARDS
|
|
|
|
|
CTRL-U KILL LINE BACKWARDS
|
|
|
|
|
ALT-H KILL WORD BACKWARDS
|
|
|
|
|
CTRL-W KILL WORD BACKWARDS
|
|
|
|
|
CTRL-ALT-H KILL WORD BACKWARDS
|
|
|
|
|
ALT-D KILL WORD FORWARDS
|
|
|
|
|
CTRL-Y YANK
|
|
|
|
|
ALT-Y ROTATE KILL RING AND YANK AGAIN
|
|
|
|
|
CTRL-T TRANSPOSE
|
|
|
|
|
ALT-T TRANSPOSE WORD
|
|
|
|
|
ALT-U UPPERCASE WORD
|
|
|
|
|
ALT-L LOWERCASE WORD
|
|
|
|
|
ALT-C CAPITALIZE WORD
|
|
|
|
|
CTRL-\ QUIT PROCESS
|
|
|
|
|
CTRL-S PAUSE OUTPUT
|
|
|
|
|
CTRL-Q UNPAUSE OUTPUT (IF PAUSED)
|
|
|
|
|
CTRL-Q ESCAPED INSERT
|
|
|
|
|
CTRL-ALT-F FORWARD EXPR
|
|
|
|
|
CTRL-ALT-B BACKWARD EXPR
|
|
|
|
|
ALT-RIGHT FORWARD EXPR
|
|
|
|
|
ALT-LEFT BACKWARD EXPR
|
|
|
|
|
ALT-SHIFT-B BARF EXPR
|
|
|
|
|
ALT-SHIFT-S SLURP EXPR
|
|
|
|
|
CTRL-SPACE SET MARK
|
|
|
|
|
CTRL-X CTRL-X GOTO MARK
|
|
|
|
|
CTRL-Z SUSPEND PROCESS
|
|
|
|
|
ALT-\ SQUEEZE ADJACENT WHITESPACE
|
|
|
|
|
PROTIP REMAP CAPS LOCK TO CTRL
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-05-14 12:36:58 +00:00
|
|
|
|
USAGE
|
|
|
|
|
|
|
|
|
|
This executable is also a ZIP file that contains static assets.
|
|
|
|
|
You can run redbean interactively in your terminal as follows:
|
|
|
|
|
|
|
|
|
|
./redbean.com -vvvmbag # starts server verbosely
|
|
|
|
|
open http://127.0.0.1:8080/ # shows zip listing page
|
|
|
|
|
CTRL-C # 1x: graceful shutdown
|
|
|
|
|
CTRL-C # 2x: forceful shutdown
|
|
|
|
|
|
|
|
|
|
You can override the default listing page by adding:
|
|
|
|
|
|
|
|
|
|
zip redbean.com index.lua # lua server pages take priority
|
|
|
|
|
zip redbean.com index.html # default page for directory
|
|
|
|
|
|
|
|
|
|
The listing page only applies to the root directory. However the
|
|
|
|
|
default index page applies to subdirectories too. In order for it
|
|
|
|
|
to work, there needs to be an empty directory entry in the zip.
|
|
|
|
|
That should already be the default practice of your zip editor.
|
|
|
|
|
|
|
|
|
|
wget \
|
|
|
|
|
--mirror \
|
|
|
|
|
--convert-links \
|
|
|
|
|
--adjust-extension \
|
|
|
|
|
--page-requisites \
|
|
|
|
|
--no-parent \
|
|
|
|
|
--no-if-modified-since \
|
|
|
|
|
http://a.example/index.html
|
|
|
|
|
zip -r redbean.com a.example/ # default page for directory
|
|
|
|
|
|
|
|
|
|
redbean normalizes the trailing slash for you automatically:
|
|
|
|
|
|
|
|
|
|
$ printf 'GET /a.example HTTP/1.0\n\n' | nc 127.0.0.1 8080
|
|
|
|
|
HTTP/1.0 307 Temporary Redirect
|
|
|
|
|
Location: /a.example/
|
|
|
|
|
|
|
|
|
|
Virtual hosting is accomplished this way too. The Host is simply
|
|
|
|
|
prepended to the path, and if it doesn't exist, it gets removed.
|
|
|
|
|
|
|
|
|
|
$ printf 'GET / HTTP/1.1\nHost:a.example\n\n' | nc 127.0.0.1 8080
|
|
|
|
|
HTTP/1.1 200 OK
|
|
|
|
|
Link: <http://127.0.0.1/a.example/index.html>; rel="canonical"
|
|
|
|
|
|
|
|
|
|
If you mirror a lot of websites within your redbean then you can
|
|
|
|
|
actually tell your browser that redbean is your proxy server, in
|
|
|
|
|
which redbean will act as your private version of the Internet.
|
|
|
|
|
|
|
|
|
|
$ printf 'GET http://a.example HTTP/1.0\n\n' | nc 127.0.0.1 8080
|
|
|
|
|
HTTP/1.0 200 OK
|
|
|
|
|
Link: <http://127.0.0.1/a.example/index.html>; rel="canonical"
|
|
|
|
|
|
|
|
|
|
If you use a reverse proxy, then redbean recognizes the following
|
|
|
|
|
provided that the proxy forwards requests over the local network:
|
|
|
|
|
|
|
|
|
|
X-Forwarded-For: 203.0.113.42:31337
|
|
|
|
|
X-Forwarded-Host: foo.example:80
|
|
|
|
|
|
|
|
|
|
There's a text/plain statistics page called /statusz that makes
|
|
|
|
|
it easy to track and monitor the health of your redbean:
|
|
|
|
|
|
|
|
|
|
printf 'GET /statusz\n\n' | nc 127.0.0.1 8080
|
|
|
|
|
|
|
|
|
|
redbean will display an error page using the /redbean.png logo
|
|
|
|
|
by default, embedded as a bas64 data uri. You can override the
|
|
|
|
|
custom page for various errors by adding files to the zip root.
|
|
|
|
|
|
|
|
|
|
zip redbean.com 404.html # custom not found page
|
|
|
|
|
|
|
|
|
|
Audio video content should not be compressed in your ZIP files.
|
|
|
|
|
Uncompressed assets enable browsers to send Range HTTP request.
|
|
|
|
|
On the other hand compressed assets are best for gzip encoding.
|
|
|
|
|
|
|
|
|
|
zip redbean.com index.html # adds file
|
|
|
|
|
zip -0 redbean.com video.mp4 # adds without compression
|
|
|
|
|
|
|
|
|
|
You can have redbean run as a daemon by doing the following:
|
|
|
|
|
|
2021-06-24 19:31:26 +00:00
|
|
|
|
sudo ./redbean.com -vvdp80 -p443 -L redbean.log -P redbean.pid
|
2021-05-14 12:36:58 +00:00
|
|
|
|
kill -TERM $(cat redbean.pid) # 1x: graceful shutdown
|
|
|
|
|
kill -TERM $(cat redbean.pid) # 2x: forceful shutdown
|
|
|
|
|
|
|
|
|
|
redbean currently has a 32kb limit on request messages and 64kb
|
|
|
|
|
including the payload. redbean will grow to whatever the system
|
|
|
|
|
limits allow. Should fork() or accept() fail redbean will react
|
|
|
|
|
by going into "meltdown mode" which closes lingering workers.
|
|
|
|
|
You can trigger this at any time using:
|
|
|
|
|
|
|
|
|
|
kill -USR2 $(cat redbean.pid)
|
|
|
|
|
|
|
|
|
|
Another failure condition is running out of disk space in which
|
|
|
|
|
case redbean reacts by truncating the log file. Lastly, redbean
|
|
|
|
|
does the best job possible reporting on resource usage when the
|
|
|
|
|
logger is in debug mode noting that NetBSD is the best at this.
|
|
|
|
|
|
|
|
|
|
Your redbean is an actually portable executable, that's able to
|
|
|
|
|
run on six different operating systems. To do that, it needs to
|
2022-06-17 15:00:43 +00:00
|
|
|
|
extract a 4kb loader program to ${TMPDIR:-${HOME:-.}}/.ape that'll
|
|
|
|
|
map your redbean into memory. It does however check to see if `ape`
|
2022-05-25 18:31:08 +00:00
|
|
|
|
is on the system path beforehand. You can also "assimilate" any
|
|
|
|
|
redbean into the platform-local executable format by running:
|
|
|
|
|
|
|
|
|
|
$ file redbean.com
|
|
|
|
|
redbean.com: DOS/MBR boot sector
|
|
|
|
|
$ ./redbean.com --assimilate
|
|
|
|
|
$ file redbean.com
|
|
|
|
|
redbean.com: ELF 64-bit LSB executable
|
2021-05-14 12:36:58 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-06-24 19:31:26 +00:00
|
|
|
|
SECURITY
|
|
|
|
|
|
|
|
|
|
redbean uses a protocol polyglot for serving HTTP and HTTPS on
|
|
|
|
|
the same port numbers. For example, both of these are valid:
|
|
|
|
|
|
|
|
|
|
http://127.0.0.1:8080/
|
|
|
|
|
https://127.0.0.1:8080/
|
|
|
|
|
|
|
|
|
|
SSL verbosity is controlled as follows for troubleshooting:
|
|
|
|
|
|
|
|
|
|
-V log ssl errors
|
|
|
|
|
-VV log ssl state changes too
|
|
|
|
|
-VVV log ssl informational messages too
|
|
|
|
|
-VVVV log ssl verbose details too
|
|
|
|
|
|
2022-09-17 08:37:33 +00:00
|
|
|
|
redbean provides hardened ASAN (Address Sanitizer) builds that
|
|
|
|
|
proactively guard against any potential memory weaknesses that may be
|
|
|
|
|
discovered, such as buffer overruns, use after free, etc. MDOE=asan is
|
|
|
|
|
recomended when serving on the public Internet.
|
|
|
|
|
|
|
|
|
|
redbean also supports robust sandboxing on Linux Kernel 5.13+ and
|
|
|
|
|
OpenBSD. The recommended way to harden your redbean is to call the
|
|
|
|
|
pledge() and unveil() functions. For example, if you have a SQLite app
|
|
|
|
|
then the key to using these features is to connect to the db first:
|
|
|
|
|
|
|
|
|
|
function OnWorkerStart()
|
|
|
|
|
db = sqlite3.open("db.sqlite3")
|
|
|
|
|
db:busy_timeout(1000)
|
|
|
|
|
db:exec[[PRAGMA journal_mode=WAL]]
|
|
|
|
|
db:exec[[PRAGMA synchronous=NORMAL]]
|
|
|
|
|
db:exec[[SELECT x FROM warmup WHERE x = 1]]
|
|
|
|
|
assert(unix.setrlimit(unix.RLIMIT_RSS, 100 * 1024 * 1024))
|
|
|
|
|
assert(unix.setrlimit(unix.RLIMIT_CPU, 4))
|
|
|
|
|
assert(unix.unveil("/var/tmp", "rwc"))
|
|
|
|
|
assert(unix.unveil("/tmp", "rwc"))
|
|
|
|
|
assert(unix.unveil(nil, nil))
|
|
|
|
|
assert(unix.pledge("stdio flock rpath wpath cpath", nil,
|
|
|
|
|
unix.PLEDGE_PENALTY_RETURN_EPERM))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
What makes this technique interesting is redbean doesn't have file
|
|
|
|
|
system access to the database file, and instead uses an inherited file
|
|
|
|
|
descriptor that was opened beforehand. With SQLite the tmp access is
|
|
|
|
|
only needed to support things like covering indexes. The -Z flag is
|
|
|
|
|
also helpful to see where things go wrong, so you know which promises
|
|
|
|
|
are needed to support your use case.
|
|
|
|
|
|
|
|
|
|
pledge() will work on all Linux kernels since RHEL6 since it uses
|
|
|
|
|
SECCOMP BPF filtering. On the other hand, unveil() requires Landlock
|
|
|
|
|
LSM which was only introduced in 2021. If you need unveil() then be
|
|
|
|
|
sure to test the restrictions work. Most environments don't support
|
|
|
|
|
unveil(), so it's designed to be a no-op in unsupported environments.
|
|
|
|
|
|
|
|
|
|
Alternatively, there's CLI flags which make it simple to get started:
|
2022-07-09 12:49:19 +00:00
|
|
|
|
|
|
|
|
|
-S (online policy)
|
|
|
|
|
|
2022-08-07 23:18:33 +00:00
|
|
|
|
This causes unix.pledge("stdio rpath inet dns id") to be called on
|
2022-07-09 12:49:19 +00:00
|
|
|
|
workers after fork() is called. This permits read-only operations
|
|
|
|
|
and APIs like Fetch() that let workers send and receive data with
|
|
|
|
|
private and public Internet hosts. Access to the unix module is
|
|
|
|
|
somewhat restricted, disallowing its more powerful APIs like exec.
|
|
|
|
|
|
|
|
|
|
-SS (offline policy)
|
|
|
|
|
|
2022-08-07 23:18:33 +00:00
|
|
|
|
This causes unix.pledge("stdio rpath id") to be called on workers
|
2022-07-09 12:49:19 +00:00
|
|
|
|
after after fork() is called. This prevents workers from talking
|
|
|
|
|
to the network (other than the client) and allows read-only file
|
2022-08-07 23:18:33 +00:00
|
|
|
|
system access (e.g. `-D DIR` flag). The `id` group helps you to
|
|
|
|
|
call other functions important to redbean security, such as the
|
|
|
|
|
unix.setrlimit() function.
|
2022-07-09 12:49:19 +00:00
|
|
|
|
|
|
|
|
|
-SSS (contained policy)
|
|
|
|
|
|
|
|
|
|
This causes unix.pledge("stdio") to be called on workers after
|
|
|
|
|
after fork() is called. This prevents workers from communicating
|
|
|
|
|
with the network (other than the client connection) and prevents
|
|
|
|
|
file system access (with some exceptions like logging). Redbean
|
|
|
|
|
should only be able to serve from its own zip file in this mode.
|
|
|
|
|
Lua script access to the unix module is highly restricted.
|
|
|
|
|
|
2022-08-07 23:18:33 +00:00
|
|
|
|
Unlike the unix.pledge() function, these sandboxing flags use a more
|
|
|
|
|
permissive policy on Linux. Rather than killing the process, they'll
|
|
|
|
|
cause system calls to fail with EPERM instead. Therefore these flags
|
|
|
|
|
should be gentler when you want security errors to be recoverable.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
See http://redbean.dev for further details.
|
2021-06-24 19:31:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
LUA SERVER PAGES
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Any files with the extension .lua will be dynamically served by redbean.
|
|
|
|
|
Here's the simplest possible example:
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Write('<b>Hello World</b>')
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
The Lua Server Page above should be able to perform at 700,000 responses
|
|
|
|
|
per second on a Core i9, without any sort of caching. If you want a Lua
|
|
|
|
|
handler that can do 1,000,000 responses per second, then try adding the
|
|
|
|
|
following global handler to your /.init.lua file:
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
function OnHttpRequest()
|
|
|
|
|
Write('<b>Hello World</b>')
|
|
|
|
|
end
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Here's an example of a more typical workflow for Lua Server Pages using
|
|
|
|
|
the redbean API:
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
SetStatus(200)
|
|
|
|
|
SetHeader('Content-Type', 'text/plain; charset=utf-8')
|
|
|
|
|
Write('<p>Hello ')
|
|
|
|
|
Write(EscapeHtml(GetParam('name')))
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
We didn't need the first two lines in the previous example, because
|
|
|
|
|
they're implied by redbean automatically if you don't set them. Responses
|
|
|
|
|
are also buffered until the script finishes executing. That enables
|
|
|
|
|
redbean to make HTTP as easy as possible. In the future, API capabilities
|
|
|
|
|
will be expanded to make possible things like websockets.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
redbean embeds the Lua standard library. You can use packages such as io
|
|
|
|
|
to persist and share state across requests and connections, as well as the
|
|
|
|
|
StoreAsset function, and the lsqlite3 module.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Your Lua interpreter begins its life in the main process at startup in the
|
|
|
|
|
.init.lua, which is likely where you'll want to perform all your expensive
|
|
|
|
|
one-time operations like importing modules. Then, as requests roll in,
|
|
|
|
|
isolated processes are cloned from the blueprint you created.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
REPL
|
|
|
|
|
|
|
|
|
|
Your redbean displays a Read-Eval-Print-Loop that lets you modify the
|
|
|
|
|
state of the main server process while your server is running. Any
|
|
|
|
|
changes will propagate into forked clients.
|
|
|
|
|
|
|
|
|
|
Your REPL is displayed only when redbean is run as a non-daemon in a
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Unix terminal or the Windows 10 command prompt or PowerShell. Since
|
2022-04-26 04:16:05 +00:00
|
|
|
|
the REPL is a Lua REPL it's not included in a redbean-static builds.
|
|
|
|
|
|
|
|
|
|
redbean uses the same keyboard shortcuts as GNU Readline and Emacs.
|
|
|
|
|
Some of its keyboard commands (listed in a previous section) were
|
|
|
|
|
inspired by Paredit.
|
|
|
|
|
|
|
|
|
|
A history of your commands is saved to `~/.redbean_history`.
|
|
|
|
|
|
|
|
|
|
If you love the redbean repl and want to use it as your language
|
|
|
|
|
interpreter then you can pass the `-i` flag to put redbean into
|
|
|
|
|
interpreter mode.
|
|
|
|
|
|
|
|
|
|
redbean.com -i binarytrees.lua 15
|
|
|
|
|
|
2022-04-29 15:19:09 +00:00
|
|
|
|
When the `-i` flag is passed (for interpreter mode), redbean won't
|
|
|
|
|
start a web server and instead functions like the `lua` command. The
|
|
|
|
|
first command line argument becomes the script you want to run. If you
|
|
|
|
|
don't supply a script, then the repl without a web server is
|
|
|
|
|
displayed. This is useful for testing since redbean extensions and
|
|
|
|
|
modules for the Lua language, are still made available. You can also
|
|
|
|
|
write redbean scripts with shebang lines:
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
#!/usr/bin/redbean -i
|
|
|
|
|
print('hello world')
|
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
However UNIX operating systems usually require that interpreters be
|
2022-05-25 18:31:08 +00:00
|
|
|
|
encoded in its preferred executable format. You can assimilate your
|
|
|
|
|
redbean into the local format using the following commands:
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-05-25 18:31:08 +00:00
|
|
|
|
$ file redbean.com
|
|
|
|
|
redbean.com: DOS/MBR boot sector
|
|
|
|
|
$ ./redbean.com --assimilate
|
|
|
|
|
$ file redbean.com
|
|
|
|
|
redbean.com: ELF 64-bit LSB executable
|
|
|
|
|
$ sudo cp redbean.com /usr/bin/redbean
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
By following the above steps, redbean can be installed systemwide for
|
|
|
|
|
multiple user accounts. It's also possible to chmod the binary to have
|
2022-05-25 18:31:08 +00:00
|
|
|
|
setuid privileges. Please note that, if you do this, the UNIX section
|
|
|
|
|
provides further details on APIs like `unix.setuid` that will help you
|
|
|
|
|
remove root privileges from the process in the appropriate manner.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
LUA ENHANCEMENTS
|
|
|
|
|
|
|
|
|
|
We've made some enhancements to the Lua language that should make it
|
|
|
|
|
more comfortable for C/C++ and Python developers. Some of these
|
|
|
|
|
|
|
|
|
|
- redbean supports a printf modulus operator, like Python. For
|
|
|
|
|
example, you can say `"hello %s" % {"world"}` instead of
|
|
|
|
|
`string.format("hello %s", "world")`.
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
- redbean supports a string multiply operator, like Python. For
|
|
|
|
|
example, you can say `"hi" * 2` instead of `string.rep("hi", 2)`.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
- redbean supports octal (base 8) integer literals. For example
|
|
|
|
|
`0644 == 420` is the case in redbean, whereas in upstream Lua
|
|
|
|
|
`0644 == 644` would be the case.
|
|
|
|
|
|
2022-04-29 13:06:23 +00:00
|
|
|
|
- redbean supports binary (base 2) integer literals. For example
|
|
|
|
|
`0b1010 == 10` is the case in redbean, whereas in upstream Lua
|
|
|
|
|
`0b1010` would result in an error.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
- redbean supports the GNU syntax for the ASCII ESC character in
|
|
|
|
|
string literals. For example, `"\e"` is the same as `"\x1b"`.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
GLOBALS
|
|
|
|
|
|
|
|
|
|
arg: array[str]
|
|
|
|
|
|
|
|
|
|
Array of command line arguments, excluding those parsed by
|
|
|
|
|
getopt() in the C code, which stops parsing at the first
|
|
|
|
|
non-hyphenated arg. In some cases you can use the magic --
|
|
|
|
|
argument to delimit C from Lua arguments.
|
|
|
|
|
|
|
|
|
|
For example, if you launch your redbean as follows:
|
|
|
|
|
|
|
|
|
|
redbean.com -v arg1 arg2
|
|
|
|
|
|
|
|
|
|
Then your `/.init.lua` file will have the `arg` array like:
|
|
|
|
|
|
|
|
|
|
arg[-1] = '/usr/bin/redbean.com'
|
|
|
|
|
arg[ 0] = '/zip/.init.lua'
|
|
|
|
|
arg[ 1] = 'arg1'
|
|
|
|
|
arg[ 2] = 'arg2'
|
|
|
|
|
|
|
|
|
|
If you launch redbean in interpreter mode (rather than web
|
|
|
|
|
server) mode, then an invocation like this:
|
|
|
|
|
|
|
|
|
|
./redbean.com -i script.lua arg1 arg2
|
|
|
|
|
|
|
|
|
|
Would have an `arg` array like this:
|
|
|
|
|
|
|
|
|
|
arg[-1] = './redbean.com'
|
|
|
|
|
arg[ 0] = 'script.lua'
|
|
|
|
|
arg[ 1] = 'arg1'
|
|
|
|
|
arg[ 2] = 'arg2'
|
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
SPECIAL PATHS
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
/
|
|
|
|
|
redbean will generate a zip central directory listing for this
|
|
|
|
|
page, and this page only, but only if there isn't an /index.lua or
|
|
|
|
|
/index.html file defined.
|
|
|
|
|
|
|
|
|
|
/.init.lua
|
|
|
|
|
This script is run once in the main process at startup. This lets
|
|
|
|
|
you modify the state of the Lua interpreter before connection
|
|
|
|
|
processes are forked off. For example, it's a good idea to do
|
|
|
|
|
expensive one-time computations here. You can also use this file
|
|
|
|
|
to call the ProgramFOO() functions below. The init module load
|
|
|
|
|
happens after redbean's arguments and zip assets have been parsed,
|
|
|
|
|
but before calling functions like socket() and fork(). Note that
|
|
|
|
|
this path is a hidden file so that it can't be unintentionally run
|
|
|
|
|
by the network client.
|
|
|
|
|
|
|
|
|
|
/.reload.lua
|
|
|
|
|
This script is run from the main process when SIGHUP is received.
|
|
|
|
|
This only applies to redbean when running in daemon mode. Any
|
|
|
|
|
changes that are made to the Lua interpreter state will be
|
|
|
|
|
inherited by future forked connection processes. Note that this
|
|
|
|
|
path is a hidden file so that it can't be unintentionally run by
|
|
|
|
|
the network client.
|
|
|
|
|
|
|
|
|
|
/.lua/...
|
|
|
|
|
Your Lua modules go in this directory. The way it works is redbean
|
|
|
|
|
sets Lua's package.path to /zip/.lua/?.lua;/zip/.lua/?/init.lua by
|
|
|
|
|
default. Cosmopolitan Libc lets system calls like open read from
|
|
|
|
|
the ZIP structure, if the filename is prefixed with /zip/. So this
|
|
|
|
|
works like magic.
|
|
|
|
|
|
|
|
|
|
/redbean.png
|
|
|
|
|
If it exists, it'll be used as the / listing page icon, embedded
|
|
|
|
|
as a base64 URI.
|
|
|
|
|
|
2022-04-29 07:36:14 +00:00
|
|
|
|
/usr/share/zoneinfo
|
|
|
|
|
This directory contains a subset of the timezone database.
|
|
|
|
|
Your `TZ` environment variable controls which one of these
|
|
|
|
|
files is used by functions such as unix.localtime().
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
/usr/share/ssl/root
|
|
|
|
|
This directory contains your root certificate authorities. It is
|
|
|
|
|
needed so the Fetch() HTTPS client API can verify that a remote
|
|
|
|
|
certificate was signed by a third party. You can add your own
|
|
|
|
|
certificate files to this directory within the ZIP executable.
|
|
|
|
|
If you enable HTTPS client verification then redbean will check
|
|
|
|
|
that HTTPS clients (a) have a certificate and (b) it was signed.
|
|
|
|
|
|
2022-05-12 18:01:58 +00:00
|
|
|
|
/.args
|
|
|
|
|
Specifies default command-line arguments.
|
|
|
|
|
|
|
|
|
|
There's one argument per line. Trailing newline is ignored. If
|
|
|
|
|
the special argument `...` is *not* encountered, then the
|
|
|
|
|
replacement will only happen if *no* CLI args are specified.
|
|
|
|
|
If the special argument `...` *is* encountered, then it'll be
|
|
|
|
|
replaced with whatever CLI args were specified by the user.
|
|
|
|
|
|
|
|
|
|
For example, you might want to use redbean.com in interpreter
|
|
|
|
|
mode, where your script file is inside the zip. Then, if your
|
|
|
|
|
redbean is run, what you want is to have the default behavior
|
|
|
|
|
be running your script. In that case, you might:
|
|
|
|
|
|
|
|
|
|
$ cat <<'EOF' >.args
|
|
|
|
|
-i
|
|
|
|
|
/zip/hello.lua
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
$ cat <<'EOF' >hello.lua
|
|
|
|
|
print("hello world")
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
$ zip redbean.com .args hello.lua
|
|
|
|
|
$ ./redbean.com
|
|
|
|
|
hello world
|
|
|
|
|
|
|
|
|
|
Please note that if you ran:
|
|
|
|
|
|
|
|
|
|
$ ./redbean.com -vv
|
|
|
|
|
|
|
|
|
|
Then the default mode of redbean will kick back in. To prevent
|
|
|
|
|
that from happening, simply add the magic arg `...` to the end
|
|
|
|
|
of your `.args` file.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
HOOKS
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
OnHttpRequest()
|
|
|
|
|
If this function is defined in the global scope by your /.init.lua
|
2022-07-16 18:00:28 +00:00
|
|
|
|
then redbean will call it at the earliest possible moment to
|
2022-04-24 16:59:22 +00:00
|
|
|
|
hand over control for all messages (with the exception of OPTIONS
|
|
|
|
|
*). See functions like Route which asks redbean to do its default
|
|
|
|
|
thing from the handler.
|
|
|
|
|
|
|
|
|
|
OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
each time redbean accepts a new client connection. If it returns
|
2022-07-08 14:17:25 +00:00
|
|
|
|
`true`, redbean will close the connection without calling fork.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-19 03:17:14 +00:00
|
|
|
|
OnLogLatency(reqtimeus:int,contimeus:int)
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
each time redbean completes handling of a request, but before the
|
|
|
|
|
response is sent. The handler received the time (in µs) since the
|
|
|
|
|
request handling and connection handling started.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
each time redbean forks a connection handler worker process. The
|
|
|
|
|
ip/port of the remote client is provided, along with the ip/port
|
|
|
|
|
of the listening interface that accepted the connection. This may
|
|
|
|
|
be used to create a server activity dashboard, in which case the
|
|
|
|
|
data provider handler should set SetHeader('Connection','Close').
|
|
|
|
|
This won't be called in uniprocess mode.
|
|
|
|
|
|
|
|
|
|
OnProcessDestroy(pid:int)
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
each time redbean reaps a child connection process using wait4().
|
|
|
|
|
This won't be called in uniprocess mode.
|
|
|
|
|
|
2022-08-03 03:41:44 +00:00
|
|
|
|
OnServerHeartbeat()
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
on each server heartbeat. The heartbeat interval is configurable
|
2022-08-20 08:31:58 +00:00
|
|
|
|
with ProgramHeartbeatInterval.
|
2022-08-03 03:41:44 +00:00
|
|
|
|
|
2022-07-08 14:17:25 +00:00
|
|
|
|
OnServerListen(socketdescriptor:int,serverip:int,serverport:int) → bool
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
before redbean starts listening on a port. This hook can be used
|
|
|
|
|
to modify socket configuration to set `SO_REUSEPORT`, for example.
|
|
|
|
|
If it returns `true`, redbean will not listen to that ip/port.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
OnServerStart()
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
right before the main event loop starts.
|
|
|
|
|
|
|
|
|
|
OnServerStop()
|
|
|
|
|
If this function is defined it'll be called from the main process
|
|
|
|
|
after all the connection processes have been reaped and exit() is
|
|
|
|
|
ready to be called.
|
|
|
|
|
|
|
|
|
|
OnWorkerStart()
|
|
|
|
|
If this function is defined it'll be called from the child worker
|
|
|
|
|
process after it's been forked and before messages are handled.
|
|
|
|
|
This won't be called in uniprocess mode.
|
|
|
|
|
|
|
|
|
|
OnWorkerStop()
|
|
|
|
|
If this function is defined it'll be called from the child worker
|
|
|
|
|
process once _exit() is ready to be called. This won't be called
|
|
|
|
|
in uniprocess mode.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
FUNCTIONS
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Write(data:str)
|
|
|
|
|
Appends data to HTTP response payload buffer. This is buffered
|
|
|
|
|
independently of headers.
|
|
|
|
|
|
|
|
|
|
SetStatus(code:int[,reason:str])
|
|
|
|
|
Starts an HTTP response, specifying the parameters on its first
|
|
|
|
|
line. reason is optional since redbean can fill in the appropriate
|
|
|
|
|
text for well-known magic numbers, e.g. 200, 404, etc. This method
|
|
|
|
|
will reset the response and is therefore mutually exclusive with
|
|
|
|
|
ServeAsset and other Serve* functions. If this function isn't
|
|
|
|
|
called, then the default behavior is to send 200 OK.
|
|
|
|
|
|
|
|
|
|
SetHeader(name:str,value:str)
|
|
|
|
|
Appends HTTP header to response header buffer. name is
|
|
|
|
|
case-insensitive and restricted to non-space ASCII. value is a
|
|
|
|
|
UTF-8 string that must be encodable as ISO-8859-1. Leading and
|
|
|
|
|
trailing whitespace is trimmed automatically. Overlong characters
|
|
|
|
|
are canonicalized. C0 and C1 control codes are forbidden, with the
|
|
|
|
|
exception of tab. This function automatically calls SetStatus(200,
|
|
|
|
|
"OK") if a status has not yet been set. As SetStatus and Serve*
|
|
|
|
|
functions reset the response, SetHeader needs to be called after
|
|
|
|
|
SetStatus and Serve* functions are called. The header buffer is
|
|
|
|
|
independent of the payload buffer. Neither is written to the wire
|
|
|
|
|
until the Lua Server Page has finished executing. This function
|
|
|
|
|
disallows the setting of certain headers such as Content-Range and
|
|
|
|
|
Date, which are abstracted by the transport layer. In such cases,
|
|
|
|
|
consider calling ServeAsset.
|
|
|
|
|
|
|
|
|
|
SetCookie(name:str,value:str[,options:table])
|
|
|
|
|
Appends Set-Cookie HTTP header to the response header buffer.
|
|
|
|
|
Several Set-Cookie headers can be added to the same response.
|
|
|
|
|
__Host- and __Secure- prefixes are supported and may set or
|
|
|
|
|
overwrite some of the options (for example, specifying __Host-
|
|
|
|
|
prefix sets the Secure option to true, sets the path to "/", and
|
|
|
|
|
removes the Domain option). The following options can be used (their
|
|
|
|
|
lowercase equivalents are supported as well):
|
|
|
|
|
- Expires: sets the maximum lifetime of the cookie as an HTTP-date
|
|
|
|
|
timestamp. Can be specified as a Date in the RFC1123 (string)
|
|
|
|
|
format or as a UNIX timestamp (number of seconds).
|
|
|
|
|
- MaxAge: sets number of seconds until the cookie expires. A zero
|
|
|
|
|
or negative number will expire the cookie immediately. If both
|
|
|
|
|
Expires and MaxAge are set, MaxAge has precedence.
|
|
|
|
|
- Domain: sets the host to which the cookie will be sent.
|
|
|
|
|
- Path: sets the path that must be present in the request URL, or
|
|
|
|
|
the client will not send the Cookie header.
|
|
|
|
|
- Secure: (bool) requests the cookie to be only send to the
|
|
|
|
|
server when a request is made with the https: scheme.
|
|
|
|
|
- HttpOnly: (bool) forbids JavaScript from accessing the cookie.
|
|
|
|
|
- SameSite: (Strict, Lax, or None) controls whether a cookie is
|
|
|
|
|
sent with cross-origin requests, providing some protection
|
|
|
|
|
against cross-site request forgery attacks.
|
|
|
|
|
|
|
|
|
|
GetParam(name:str) → value:str
|
|
|
|
|
Returns first value associated with name. name is handled in a
|
|
|
|
|
case-sensitive manner. This function checks Request-URL parameters
|
|
|
|
|
first. Then it checks application/x-www-form-urlencoded from the
|
|
|
|
|
message body, if it exists, which is common for HTML forms sending
|
|
|
|
|
POST requests. If a parameter is supplied matching name that has
|
|
|
|
|
no value, e.g. foo in ?foo&bar=value, then the returned value will
|
|
|
|
|
be nil, whereas for ?foo=&bar=value it would be "". To
|
|
|
|
|
differentiate between no-equal and absent, use the HasParam
|
|
|
|
|
function. The returned value is decoded from ISO-8859-1 (only in
|
|
|
|
|
the case of Request-URL) and we assume that percent-encoded
|
|
|
|
|
characters were supplied by the client as UTF-8 sequences, which
|
|
|
|
|
are returned exactly as the client supplied them, and may
|
|
|
|
|
therefore may contain overlong sequences, control codes, NUL
|
|
|
|
|
characters, and even numbers which have been banned by the IETF.
|
|
|
|
|
It is the responsibility of the caller to impose further
|
|
|
|
|
restrictions on validity, if they're desired.
|
|
|
|
|
|
|
|
|
|
EscapeHtml(str) → str
|
|
|
|
|
Escapes HTML entities: The set of entities is &><"' which become
|
|
|
|
|
&><"'. This function is charset agnostic and
|
|
|
|
|
will not canonicalize overlong encodings. It is assumed that a
|
|
|
|
|
UTF-8 string will be supplied. See escapehtml.c.
|
|
|
|
|
|
|
|
|
|
LaunchBrowser([path:str])
|
|
|
|
|
Launches web browser on local machine with URL to this redbean
|
2022-09-01 05:14:06 +00:00
|
|
|
|
server. It is the responsibility of the caller to escape the path
|
|
|
|
|
with EscapePath if needed, as it's not escaped automatically.
|
|
|
|
|
This function may be called from /.init.lua.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
CategorizeIp(ip:uint32) → str
|
|
|
|
|
Returns a string describing an IP address. This is currently Class
|
|
|
|
|
A granular. It can tell you if traffic originated from private
|
|
|
|
|
networks, ARIN, APNIC, DOD, etc.
|
|
|
|
|
|
|
|
|
|
DecodeBase64(ascii:str) → binary:str
|
|
|
|
|
Turns ASCII into binary, in a permissive way that ignores
|
|
|
|
|
characters outside the base64 alphabet, such as whitespace. See
|
|
|
|
|
decodebase64.c.
|
|
|
|
|
|
|
|
|
|
DecodeLatin1(iso-8859-1:str) → utf-8:str
|
|
|
|
|
Turns ISO-8859-1 string into UTF-8.
|
|
|
|
|
|
|
|
|
|
EncodeBase64(binary:str) → ascii:str
|
|
|
|
|
Turns binary into ASCII. This can be used to create HTML data:
|
|
|
|
|
URIs that do things like embed a PNG file in a web page. See
|
|
|
|
|
encodebase64.c.
|
|
|
|
|
|
2022-07-10 00:34:41 +00:00
|
|
|
|
DecodeJson(input:str)
|
2022-07-12 06:06:49 +00:00
|
|
|
|
├─→ int64
|
|
|
|
|
├─→ string
|
|
|
|
|
├─→ double
|
|
|
|
|
├─→ array
|
|
|
|
|
├─→ object
|
2022-07-12 19:30:42 +00:00
|
|
|
|
├─→ false
|
2022-07-12 06:06:49 +00:00
|
|
|
|
├─→ true
|
2022-07-12 19:30:42 +00:00
|
|
|
|
├─→ nil
|
2022-07-09 18:44:19 +00:00
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Turns JSON string into a Lua data structure.
|
|
|
|
|
|
2022-07-12 19:30:42 +00:00
|
|
|
|
This is a generally permissive parser, in the sense that like
|
|
|
|
|
v8, it permits scalars as top-level values. Therefore we must
|
|
|
|
|
note that this API can be thought of as special, in the sense
|
|
|
|
|
|
|
|
|
|
val = assert(DecodeJson(str))
|
|
|
|
|
|
|
|
|
|
will usually do the right thing, except in cases where false
|
|
|
|
|
or null are the top-level value. In those cases, it's needed
|
|
|
|
|
to check the second value too in order to discern from error
|
|
|
|
|
|
|
|
|
|
val, err = DecodeJson(str)
|
|
|
|
|
if not val then
|
|
|
|
|
if err then
|
|
|
|
|
print('bad json', err)
|
|
|
|
|
elseif val == nil then
|
|
|
|
|
print('val is null')
|
|
|
|
|
elseif val == false then
|
|
|
|
|
print('val is false')
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
This parser supports 64-bit signed integers. If an overflow
|
|
|
|
|
happens, then the integer is silently coerced to double, as
|
|
|
|
|
consistent with v8. If a double overflows into Infinity, we
|
|
|
|
|
coerce it to `null` since that's what v8 does, and the same
|
|
|
|
|
goes for underflows which, like v8, are coerced to 0.0.
|
|
|
|
|
|
|
|
|
|
When objects are parsed, your Lua object can't preserve the
|
|
|
|
|
the original ordering of fields. As such, they'll be sorted
|
|
|
|
|
by EncodeJson() and may not round-trip with original intent
|
2022-07-12 06:06:49 +00:00
|
|
|
|
|
2022-07-14 06:02:19 +00:00
|
|
|
|
This parser has perfect conformance with JSONTestSuite.
|
|
|
|
|
|
2022-07-15 13:18:32 +00:00
|
|
|
|
This parser validates utf-8 and utf-16.
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
EncodeJson(value[, options:table])
|
2022-07-09 11:09:51 +00:00
|
|
|
|
├─→ json:str
|
|
|
|
|
├─→ true [if useoutput]
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
Turns Lua data structure into JSON string.
|
|
|
|
|
|
2022-08-05 22:42:17 +00:00
|
|
|
|
Since Lua tables are both hashmaps and arrays, we use a simple
|
|
|
|
|
fast algorithm for telling the two apart. Tables with non-zero
|
|
|
|
|
length (as reported by `#`) are encoded as arrays, and any
|
|
|
|
|
non-array elements are ignored. For example:
|
2022-07-13 06:31:06 +00:00
|
|
|
|
|
|
|
|
|
>: EncodeJson({2})
|
|
|
|
|
"[2]"
|
|
|
|
|
>: EncodeJson({[1]=2, ["hi"]=1})
|
|
|
|
|
"[2]"
|
|
|
|
|
|
|
|
|
|
If there are holes in your array, then the serialized array
|
|
|
|
|
will exclude everything after the first hole. If the beginning
|
|
|
|
|
of your array is a hole, then an error is returned.
|
|
|
|
|
|
|
|
|
|
>: EncodeJson({[1]=1, [3]=3})
|
|
|
|
|
"[1]"
|
|
|
|
|
>: EncodeJson({[2]=1, [3]=3})
|
|
|
|
|
"[]"
|
|
|
|
|
>: EncodeJson({[2]=1, [3]=3})
|
|
|
|
|
nil "json objects must only use string keys"
|
|
|
|
|
|
|
|
|
|
If the raw length of a table is reported as zero, then we
|
|
|
|
|
check for the magic element `[0]=false`. If it's present, then
|
2022-07-13 10:08:16 +00:00
|
|
|
|
your table will be serialized as empty array `[]`. An entry is
|
2022-07-13 06:31:06 +00:00
|
|
|
|
inserted by DecodeJson() automatically, only when encountering
|
|
|
|
|
empty arrays, and it's necessary in order to make empty arrays
|
|
|
|
|
round-trip. If raw length is zero and `[0]=false` is absent,
|
|
|
|
|
then your table will be serialized as an iterated object.
|
|
|
|
|
|
|
|
|
|
>: EncodeJson({})
|
|
|
|
|
"{}"
|
|
|
|
|
>: EncodeJson({[0]=false})
|
|
|
|
|
"[]"
|
|
|
|
|
>: EncodeJson({["hi"]=1})
|
|
|
|
|
"{\"hi\":1}"
|
|
|
|
|
>: EncodeJson({["hi"]=1, [0]=false})
|
|
|
|
|
"[]"
|
|
|
|
|
>: EncodeJson({["hi"]=1, [7]=false})
|
|
|
|
|
nil "json objects must only use string keys"
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
|
|
|
|
The following options may be used:
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- useoutput: (bool=false) encodes the result directly to the
|
2022-09-12 02:51:18 +00:00
|
|
|
|
output buffer and returns `true` value. This option is
|
2022-04-24 16:59:22 +00:00
|
|
|
|
ignored if used outside of request handling code.
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
- sorted: (bool=true) Lua uses hash tables so the order of
|
|
|
|
|
object keys is lost in a Lua table. So, by default, we use
|
2022-07-22 11:19:01 +00:00
|
|
|
|
`strcmp` to impose a deterministic output order. If you
|
|
|
|
|
don't care about ordering then setting `sorted=false`
|
|
|
|
|
should yield a performance boost in serialization.
|
2022-07-13 06:31:06 +00:00
|
|
|
|
|
2022-09-12 02:51:18 +00:00
|
|
|
|
- pretty: (bool=false) Setting this option to `true` will
|
2022-07-22 17:10:33 +00:00
|
|
|
|
cause tables with more than one entry to be formatted
|
|
|
|
|
across multiple lines for readability.
|
|
|
|
|
|
|
|
|
|
- indent: (str=" ") This option controls the indentation of
|
|
|
|
|
pretty formatting. This field is ignored if `pretty` isn't
|
2022-09-12 02:51:18 +00:00
|
|
|
|
`true`.
|
2022-07-22 17:10:33 +00:00
|
|
|
|
|
|
|
|
|
- maxdepth: (int=64) This option controls the maximum amount
|
|
|
|
|
of recursion the serializer is allowed to perform. The max
|
|
|
|
|
is 32767. You might not be able to set it that high if
|
|
|
|
|
there isn't enough C stack memory. Your serializer checks
|
|
|
|
|
for this and will return an error rather than crashing.
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
This function will return an error if:
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
|
|
|
|
- `value` is cyclic
|
|
|
|
|
- `value` has depth greater than 64
|
|
|
|
|
- `value` contains functions, user data, or threads
|
2022-07-12 06:06:49 +00:00
|
|
|
|
- `value` is table that blends string / non-string keys
|
2022-07-13 06:31:06 +00:00
|
|
|
|
- Your serializer runs out of C heap memory (setrlimit)
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
We assume strings in `value` contain UTF-8. This serializer
|
|
|
|
|
currently does not produce UTF-8 output. The output format is
|
|
|
|
|
right now ASCII. Your UTF-8 data will be safely transcoded to
|
|
|
|
|
\uXXXX sequences which are UTF-16. Overlong encodings in your
|
|
|
|
|
input strings will be canonicalized rather than validated.
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
NaNs are serialized as `null` and Infinities are `null` which
|
|
|
|
|
is consistent with the v8 behavior.
|
2022-07-12 19:30:42 +00:00
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
EncodeLua(value[, options:table])
|
2022-07-09 11:09:51 +00:00
|
|
|
|
├─→ luacode:str
|
|
|
|
|
├─→ true [if useoutput]
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Turns Lua data structure into Lua code string.
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
Since Lua uses tables as both hashmaps and arrays, tables will
|
|
|
|
|
only be serialized as an array with determinate order, if it's
|
|
|
|
|
an array in the strictest possible sense.
|
|
|
|
|
|
|
|
|
|
1. for all 𝑘=𝑣 in table, 𝑘 is an integer ≥1
|
|
|
|
|
2. no holes exist between MIN(𝑘) and MAX(𝑘)
|
|
|
|
|
3. if non-empty, MIN(𝑘) is 1
|
|
|
|
|
|
|
|
|
|
In all other cases, your table will be serialized as an object
|
|
|
|
|
which is iterated and displayed as a list of (possibly) sorted
|
|
|
|
|
entries that have equal signs.
|
|
|
|
|
|
|
|
|
|
>: EncodeLua({3, 2})
|
|
|
|
|
"{3, 2}"
|
|
|
|
|
>: EncodeLua({[1]=3, [2]=3})
|
|
|
|
|
"{3, 2}"
|
|
|
|
|
>: EncodeLua({[1]=3, [3]=3})
|
|
|
|
|
"{[1]=3, [3]=3}"
|
|
|
|
|
>: EncodeLua({["hi"]=1, [1]=2})
|
|
|
|
|
"{[1]=2, hi=1}"
|
|
|
|
|
|
2022-07-09 11:09:51 +00:00
|
|
|
|
The following options may be used:
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- useoutput: (bool=false) encodes the result directly to the
|
2022-09-12 02:51:18 +00:00
|
|
|
|
output buffer and returns `true` value. This option is
|
2022-04-24 16:59:22 +00:00
|
|
|
|
ignored if used outside of request handling code.
|
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
- sorted: (bool=true) Lua uses hash tables so the order of
|
|
|
|
|
object keys is lost in a Lua table. So, by default, we use
|
2022-07-22 11:19:01 +00:00
|
|
|
|
`strcmp` to impose a deterministic output order. If you
|
|
|
|
|
don't care about ordering then setting `sorted=false`
|
|
|
|
|
should yield a performance boost in serialization.
|
2022-07-13 06:31:06 +00:00
|
|
|
|
|
2022-09-12 02:51:18 +00:00
|
|
|
|
- pretty: (bool=false) Setting this option to `true` will
|
2022-07-22 17:10:33 +00:00
|
|
|
|
cause tables with more than one entry to be formatted
|
|
|
|
|
across multiple lines for readability.
|
|
|
|
|
|
|
|
|
|
- indent: (str=" ") This option controls the indentation of
|
|
|
|
|
pretty formatting. This field is ignored if `pretty` isn't
|
2022-09-12 02:51:18 +00:00
|
|
|
|
`true`.
|
2022-07-22 17:10:33 +00:00
|
|
|
|
|
|
|
|
|
- maxdepth: (int=64) This option controls the maximum amount
|
|
|
|
|
of recursion the serializer is allowed to perform. The max
|
|
|
|
|
is 32767. You might not be able to set it that high if
|
|
|
|
|
there isn't enough C stack memory. Your serializer checks
|
|
|
|
|
for this and will return an error rather than crashing.
|
|
|
|
|
|
2022-07-09 11:09:51 +00:00
|
|
|
|
If a user data object has a `__repr` or `__tostring` meta
|
|
|
|
|
method, then that'll be used to encode the Lua code.
|
|
|
|
|
|
2022-07-12 06:06:49 +00:00
|
|
|
|
This serializer is designed primarily to describe data. For
|
|
|
|
|
example, it's used by the REPL where we need to be able to
|
|
|
|
|
ignore errors when displaying data structures, since showing
|
|
|
|
|
most things imperfectly is better than crashing. Therefore
|
|
|
|
|
this isn't the kind of serializer you'd want to use to persist
|
|
|
|
|
data in prod. Try using the JSON serializer for that purpose.
|
|
|
|
|
|
2022-07-09 11:09:51 +00:00
|
|
|
|
Non-encodable value types (e.g. threads, functions) will be
|
|
|
|
|
represented as a string literal with the type name and pointer
|
2022-07-12 06:06:49 +00:00
|
|
|
|
address. The string description is of an unspecified format
|
|
|
|
|
that could most likely change. This encoder detects cyclic
|
|
|
|
|
tables; however instead of failing, it embeds a string of
|
|
|
|
|
unspecified layout describing the cycle.
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
2022-07-13 06:31:06 +00:00
|
|
|
|
Integer literals are encoded as decimal. However if the int64
|
|
|
|
|
number is ≥256 and has a population count of 1 then we switch
|
2022-07-20 21:01:15 +00:00
|
|
|
|
to representing the number in hexadecimal, for readability.
|
2022-07-13 06:31:06 +00:00
|
|
|
|
Hex numbers have leading zeroes added in order to visualize
|
|
|
|
|
whether the number fits in a uint16, uint32, or int64. Also
|
|
|
|
|
some numbers can only be encoded expressionally. For example,
|
|
|
|
|
NaNs are serialized as `0/0`, and Infinity is `math.huge`.
|
|
|
|
|
|
|
|
|
|
>: 7000
|
|
|
|
|
7000
|
|
|
|
|
>: 0x100
|
|
|
|
|
0x0100
|
|
|
|
|
>: 0x10000
|
|
|
|
|
0x00010000
|
|
|
|
|
>: 0x100000000
|
|
|
|
|
0x0000000100000000
|
|
|
|
|
>: 0/0
|
|
|
|
|
0/0
|
|
|
|
|
>: 1.5e+9999
|
|
|
|
|
math.huge
|
|
|
|
|
>: -9223372036854775807 - 1
|
|
|
|
|
-9223372036854775807 - 1
|
|
|
|
|
|
2022-07-12 06:06:49 +00:00
|
|
|
|
The only failure return condition currently implemented is
|
|
|
|
|
when C runs out of heap memory.
|
2022-07-09 11:09:51 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
EncodeLatin1(utf-8:str[,flags:int]) → iso-8859-1:str
|
|
|
|
|
Turns UTF-8 into ISO-8859-1 string.
|
|
|
|
|
|
|
|
|
|
EscapeFragment(str) → str
|
|
|
|
|
Escapes URL #fragment. The allowed characters are
|
|
|
|
|
-/?.~_@:!$&'()*+,;=0-9A-Za-z and everything else gets %XX encoded.
|
|
|
|
|
Please note that '& can still break HTML and that '() can still
|
|
|
|
|
break CSS URLs. This function is charset agnostic and will not
|
|
|
|
|
canonicalize overlong encodings. It is assumed that a UTF-8 string
|
|
|
|
|
will be supplied. See kescapefragment.c.
|
|
|
|
|
|
|
|
|
|
EscapeHost(str) → str
|
|
|
|
|
Escapes URL host. See kescapeauthority.c
|
|
|
|
|
|
|
|
|
|
EscapeLiteral(str) → str
|
|
|
|
|
Escapes JavaScript or JSON string literal content. The caller is
|
|
|
|
|
responsible for adding the surrounding quotation marks. This
|
|
|
|
|
implementation \uxxxx sequences for all non-ASCII sequences. HTML
|
|
|
|
|
entities are also encoded, so the output doesn't need EscapeHtml.
|
|
|
|
|
This function assumes UTF-8 input. Overlong encodings are
|
|
|
|
|
canonicalized. Invalid input sequences are assumed to be
|
|
|
|
|
ISO-8859-1. The output is UTF-16 since that's what JavaScript
|
|
|
|
|
uses. For example, some individual codepoints such as emoji
|
|
|
|
|
characters will encode as multiple \uxxxx sequences. Ints that are
|
|
|
|
|
impossible to encode as UTF-16 are substituted with the \xFFFD
|
|
|
|
|
replacement character. See escapejsstringliteral.c.
|
|
|
|
|
|
|
|
|
|
EscapeParam(str) → str
|
|
|
|
|
Escapes URL parameter name or value. The allowed characters are
|
|
|
|
|
-.*_0-9A-Za-z and everything else gets %XX encoded. This function
|
|
|
|
|
is charset agnostic and will not canonicalize overlong encodings.
|
|
|
|
|
It is assumed that a UTF-8 string will be supplied. See
|
|
|
|
|
kescapeparam.c.
|
|
|
|
|
|
|
|
|
|
EscapePass(str) → str
|
|
|
|
|
Escapes URL password. See kescapeauthority.c.
|
|
|
|
|
|
|
|
|
|
EscapePath(str) → str
|
|
|
|
|
Escapes URL path. This is the same as EscapeSegment except slash
|
|
|
|
|
is allowed. The allowed characters are -.~_@:!$&'()*+,;=0-9A-Za-z/
|
|
|
|
|
and everything else gets %XX encoded. Please note that '& can
|
|
|
|
|
still break HTML, so the output may need EscapeHtml too. Also note
|
|
|
|
|
that '() can still break CSS URLs. This function is charset
|
|
|
|
|
agnostic and will not canonicalize overlong encodings. It is
|
|
|
|
|
assumed that a UTF-8 string will be supplied. See kescapepath.c.
|
|
|
|
|
|
|
|
|
|
EscapeSegment(str) → str
|
|
|
|
|
Escapes URL path segment. This is the same as EscapePath except
|
|
|
|
|
slash isn't allowed. The allowed characters are
|
|
|
|
|
-.~_@:!$&'()*+,;=0-9A-Za-z and everything else gets %XX encoded.
|
|
|
|
|
Please note that '& can still break HTML, so the output may need
|
|
|
|
|
EscapeHtml too. Also note that '() can still break CSS URLs. This
|
|
|
|
|
function is charset agnostic and will not canonicalize overlong
|
|
|
|
|
encodings. It is assumed that a UTF-8 string will be supplied. See
|
|
|
|
|
kescapesegment.c.
|
|
|
|
|
|
|
|
|
|
EscapeUser(str) → str
|
|
|
|
|
Escapes URL username. See kescapeauthority.c.
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
EvadeDragnetSurveillance(bool)
|
|
|
|
|
If this option is programmed then redbean will not transmit a
|
|
|
|
|
Server Name Indicator (SNI) when performing Fetch() requests.
|
|
|
|
|
This function is not available in unsecure mode.
|
|
|
|
|
|
2022-05-12 05:06:42 +00:00
|
|
|
|
Fetch(url:str[,body:str|{method=value:str,body=value:str,headers=table,...}])
|
2022-07-08 14:13:51 +00:00
|
|
|
|
├─→ status:int, {header:str=value:str,...}, body:str
|
|
|
|
|
└─→ nil, error:str
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Sends an HTTP/HTTPS request to the specified URL. If only the URL is
|
|
|
|
|
provided, then a GET request is sent. If both URL and body parameters
|
|
|
|
|
are specified, then a POST request is sent. If any other method needs
|
|
|
|
|
to be specified (for example, PUT or DELETE), then passing a table as
|
2022-05-12 05:06:42 +00:00
|
|
|
|
the second value allows setting request method, body, and headers, as
|
|
|
|
|
well as some other options:
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- method (default = "GET"): sets the method to be used for the
|
|
|
|
|
request. The specified method is converted to uppercase.
|
|
|
|
|
- body (default = ""): sets the body value to be sent.
|
2022-05-12 05:06:42 +00:00
|
|
|
|
- headers: sets headers for the request using the key/value pairs
|
|
|
|
|
from this table. Only string keys are used and all the values are
|
|
|
|
|
converted to strings.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- followredirect (default = true): forces temporary and permanent
|
|
|
|
|
redirects to be followed. This behavior can be disabled by
|
|
|
|
|
passing `false`.
|
|
|
|
|
- maxredirects (default = 5): sets the number of allowed redirects
|
|
|
|
|
to minimize looping due to misconfigured servers. When the number
|
2022-05-12 05:06:42 +00:00
|
|
|
|
is exceeded, the last response is returned.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
When the redirect is being followed, the same method and body values
|
|
|
|
|
are being sent in all cases except when 303 status is returned. In
|
|
|
|
|
that case the method is set to GET and the body is removed before the
|
|
|
|
|
redirect is followed. Note that if these (method/body) values are
|
|
|
|
|
provided as table fields, they will be modified in place.
|
|
|
|
|
|
|
|
|
|
FormatHttpDateTime(seconds:int) → rfc1123:str
|
|
|
|
|
Converts UNIX timestamp to an RFC1123 string that looks like this:
|
|
|
|
|
Mon, 29 Mar 2021 15:37:13 GMT. See formathttpdatetime.c.
|
|
|
|
|
|
|
|
|
|
FormatIp(uint32) → str
|
|
|
|
|
Turns integer like 0x01020304 into a string like 1.2.3.4. See also
|
|
|
|
|
ParseIp for the inverse operation.
|
|
|
|
|
|
|
|
|
|
GetAssetComment(path:str) → str
|
|
|
|
|
Returns comment text associated with asset in the ZIP central
|
2022-06-24 01:54:35 +00:00
|
|
|
|
directory.
|
|
|
|
|
Also available as GetComment (deprecated).
|
|
|
|
|
|
|
|
|
|
GetAssetLastModifiedTime(path:str) → seconds:number
|
|
|
|
|
Returns UNIX timestamp for modification time of a ZIP asset (or
|
|
|
|
|
local file if the -D flag is used).
|
|
|
|
|
If both a file and a ZIP asset are present, then the file is used.
|
|
|
|
|
Also available as GetLastModifiedTime (deprecated).
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
GetAssetMode(path:str) → int
|
|
|
|
|
Returns UNIX-style octal mode for ZIP asset (or local file if the
|
2022-06-24 01:54:35 +00:00
|
|
|
|
-D flag is used).
|
|
|
|
|
If both a file and a ZIP asset are present, then the file is used.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
GetAssetSize(path:str) → int
|
|
|
|
|
Returns byte size of uncompressed contents of ZIP asset (or local
|
2022-06-24 01:54:35 +00:00
|
|
|
|
file if the -D flag is used).
|
|
|
|
|
If both a file and a ZIP asset are present, then the file is used.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
GetBody() → str
|
|
|
|
|
Returns the request message body if present or an empty string.
|
|
|
|
|
Also available as GetPayload (deprecated).
|
|
|
|
|
|
|
|
|
|
GetCookie(name:str) → str
|
|
|
|
|
Returns cookie value.
|
|
|
|
|
|
|
|
|
|
GetCryptoHash(name:str,payload:str[,key:str]) → str
|
|
|
|
|
Returns value of the specified cryptographic hash function. If the
|
|
|
|
|
key is provided, then HMAC value of the same function is returned.
|
|
|
|
|
The name can be one of the following strings: MD5, SHA1, SHA224,
|
|
|
|
|
SHA256, SHA384, SHA512, and BLAKE2B256.
|
|
|
|
|
|
|
|
|
|
GetRemoteAddr() → ip:uint32,port:uint16
|
|
|
|
|
Returns client ip4 address and port, e.g. 0x01020304,31337 would
|
|
|
|
|
represent 1.2.3.4:31337. This is the same as GetClientAddr except
|
|
|
|
|
it will use the ip:port from the X-Forwarded-For header, only if
|
|
|
|
|
IsPrivateIp or IsLoopbackIp return true. When multiple addresses
|
|
|
|
|
are present in the header, the last/right-most address is used.
|
|
|
|
|
|
2022-08-22 05:26:41 +00:00
|
|
|
|
GetResponseBody()
|
|
|
|
|
├─→ body:str
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
Returns the (uncompressed) response message body if present or an
|
|
|
|
|
empty string. May also return a partial or empty string during
|
|
|
|
|
streaming, as the full content may not be known at the call time.
|
|
|
|
|
Returns an error when decompression fails.
|
2022-07-22 18:22:39 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
GetClientAddr() → ip:uint32,port:uint16
|
|
|
|
|
Returns client socket ip4 address and port, e.g. 0x01020304,31337
|
|
|
|
|
would represent 1.2.3.4:31337. Please consider using GetRemoteAddr
|
|
|
|
|
instead, since the latter takes into consideration reverse proxy
|
|
|
|
|
scenarios.
|
|
|
|
|
|
|
|
|
|
GetClientFd() → int
|
|
|
|
|
Returns file descriptor being used for client connection.
|
|
|
|
|
This is useful for scripts that want to use unix:fork().
|
|
|
|
|
|
|
|
|
|
IsClientUsingSsl() → bool
|
|
|
|
|
Returns true if client connection has begun being managed by
|
|
|
|
|
the MbedTLS security layer. This is an important thing to
|
|
|
|
|
consider if a script is taking control of GetClientFd()
|
|
|
|
|
|
|
|
|
|
GetServerAddr() → ip:uint32,port:uint16
|
|
|
|
|
Returns address to which listening server socket is bound, e.g.
|
|
|
|
|
0x01020304,8080 would represent 1.2.3.4:8080. If -p 0 was supplied
|
|
|
|
|
as the listening port, then the port in this string will be
|
|
|
|
|
whatever number the operating system assigned.
|
|
|
|
|
|
|
|
|
|
GetDate() → seconds:int
|
|
|
|
|
Returns date associated with request that's used to generate the
|
|
|
|
|
Date header, which is now, give or take a second. The returned
|
|
|
|
|
value is a UNIX timestamp.
|
|
|
|
|
|
|
|
|
|
GetHeader(name:str) → value:str
|
|
|
|
|
Returns HTTP header. name is case-insensitive. The header value is
|
|
|
|
|
returned as a canonical UTF-8 string, with leading and trailing
|
|
|
|
|
whitespace trimmed, which was decoded from ISO-8859-1, which is
|
|
|
|
|
guaranteed to not have C0/C1 control sequences, with the exception
|
|
|
|
|
of the tab character. Leading and trailing whitespace is
|
|
|
|
|
automatically removed. In the event that the client suplies raw
|
|
|
|
|
UTF-8 in the HTTP message headers, the original UTF-8 sequence can
|
|
|
|
|
be losslessly restored by counter-intuitively recoding the
|
|
|
|
|
returned string back to Latin1. If the requested header is defined
|
|
|
|
|
by the RFCs as storing comma-separated values (e.g. Allow,
|
|
|
|
|
Accept-Encoding) and the field name occurs multiple times in the
|
|
|
|
|
message, then this function will fold those multiple entries into
|
|
|
|
|
a single string.
|
|
|
|
|
|
|
|
|
|
GetHeaders() → {name:str=value:str,...}
|
|
|
|
|
Returns HTTP headers as dictionary mapping header key strings to
|
|
|
|
|
their UTF-8 decoded values. The ordering of headers from the
|
|
|
|
|
request message is not preserved. Whether or not the same key can
|
|
|
|
|
repeat depends on whether or not it's a standard header, and if
|
|
|
|
|
so, if it's one of the ones that the RFCs define as repeatable.
|
2022-06-23 23:09:20 +00:00
|
|
|
|
See khttprepeatable.c. Those headers will not be folded. Standard
|
2022-04-24 16:59:22 +00:00
|
|
|
|
headers which aren't on that list, will be overwritten with the
|
|
|
|
|
last-occurring one during parsing. Extended headers are always
|
|
|
|
|
passed through exactly as they're received. Please consider using
|
|
|
|
|
GetHeader API if possible since it does a better job abstracting
|
|
|
|
|
these issues.
|
|
|
|
|
|
|
|
|
|
GetLogLevel() → int
|
|
|
|
|
Returns logger verbosity level. Likely return values are kLogDebug
|
|
|
|
|
> kLogVerbose > kLogInfo > kLogWarn > kLogError > kLogFatal.
|
|
|
|
|
|
|
|
|
|
GetHost() → str
|
|
|
|
|
Returns host associated with request. This will be the Host
|
|
|
|
|
header, if it's supplied. Otherwise it's the bind address.
|
|
|
|
|
|
|
|
|
|
GetHostOs() → str
|
|
|
|
|
Returns string that describes the host OS.
|
|
|
|
|
|
|
|
|
|
This can return:
|
|
|
|
|
|
|
|
|
|
- `"LINUX"`
|
|
|
|
|
- `"METAL"`
|
|
|
|
|
- `"WINDOWS"`
|
|
|
|
|
- `"XNU"`
|
|
|
|
|
- `"NETBSD"`
|
|
|
|
|
- `"FREEBSD"`
|
|
|
|
|
- `"OPENBSD"`
|
|
|
|
|
|
|
|
|
|
GetMonospaceWidth(str|char) → int
|
|
|
|
|
Returns monospace display width of string. This is useful for
|
|
|
|
|
fixed-width formatting. For example, CJK characters typically take
|
|
|
|
|
up two cells. This function takes into consideration combining
|
|
|
|
|
characters, which are discounted, as well as control codes and
|
|
|
|
|
ANSI escape sequences.
|
|
|
|
|
|
|
|
|
|
GetMethod() → str
|
|
|
|
|
Returns HTTP method. Normally this will be GET, HEAD, or POST in
|
|
|
|
|
which case redbean normalizes this value to its uppercase form.
|
|
|
|
|
Anything else that the RFC classifies as a "token" string is
|
|
|
|
|
accepted too, which might contain characters like &".
|
|
|
|
|
|
|
|
|
|
GetParams() → {{name:str[,value:str]},...}
|
|
|
|
|
Returns name=value parameters from Request-URL and
|
|
|
|
|
application/x-www-form-urlencoded message body in the order they
|
|
|
|
|
were received. This may contain duplicates. The inner array will
|
|
|
|
|
have either one or two items, depending on whether or not the
|
|
|
|
|
equals sign was used.
|
|
|
|
|
|
|
|
|
|
GetPath() → str
|
|
|
|
|
Returns the Request-URL path. This is guaranteed to begin with
|
|
|
|
|
"/". It is further guaranteed that no "//" or "/." exists in the
|
|
|
|
|
path. The returned value is returned as a UTF-8 string which was
|
|
|
|
|
decoded from ISO-8859-1. We assume that percent-encoded characters
|
|
|
|
|
were supplied by the client as UTF-8 sequences, which are returned
|
|
|
|
|
exactly as the client supplied them, and may therefore may contain
|
|
|
|
|
overlong sequences, control codes, NUL characters, and even
|
|
|
|
|
numbers which have been banned by the IETF. redbean takes those
|
|
|
|
|
things into consideration when performing path safety checks. It
|
|
|
|
|
is the responsibility of the caller to impose further restrictions
|
|
|
|
|
on validity, if they're desired.
|
|
|
|
|
|
|
|
|
|
GetEffectivePath() → str
|
|
|
|
|
Returns path as it was resolved by the routing algorithms, which
|
|
|
|
|
might contain the virtual host prepended if used.
|
|
|
|
|
|
|
|
|
|
GetScheme() → str
|
|
|
|
|
Returns scheme from Request-URL, if any.
|
|
|
|
|
|
|
|
|
|
GetSslIdentity() → str
|
|
|
|
|
Returns certificate subject or PSK identity from the current SSL
|
|
|
|
|
session. `nil` is returned for regular (non-SSL) connections.
|
|
|
|
|
|
|
|
|
|
GetStatus() → int
|
|
|
|
|
Returns current status (as set by an earlier SetStatus call) or
|
|
|
|
|
`nil` if the status hasn't been set yet.
|
|
|
|
|
|
|
|
|
|
GetTime() → seconds:number
|
|
|
|
|
Returns current time as a UNIX timestamp with 0.0001s precision.
|
|
|
|
|
|
|
|
|
|
GetUrl() → str
|
|
|
|
|
Returns the effective Request-URL as an ASCII string, where
|
|
|
|
|
illegal characters or UTF-8 is guaranteed to be percent encoded,
|
|
|
|
|
and has been normalized to include either the Host or
|
|
|
|
|
X-Forwarded-Host headers, if they exist, and possibly a scheme too
|
|
|
|
|
if redbean is being used as an HTTP proxy server. In the future
|
|
|
|
|
this API might change to return an object instead.
|
|
|
|
|
|
|
|
|
|
GetHttpVersion() → int
|
|
|
|
|
Returns the request HTTP protocol version, which can be 9 for
|
2022-06-24 01:54:35 +00:00
|
|
|
|
HTTP/0.9, 10 for HTTP/1.0, or 11 for HTTP/1.1.
|
|
|
|
|
Also available as GetVersion (deprecated).
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
GetHttpReason(code:int) → str
|
|
|
|
|
Returns a string describing the HTTP reason phrase.
|
|
|
|
|
See gethttpreason.c
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
GetRandomBytes([length:int]) → str
|
|
|
|
|
Returns string with the specified number of random bytes (1..256).
|
|
|
|
|
If no length is specified, then a string of length 16 is returned.
|
|
|
|
|
|
|
|
|
|
GetRedbeanVersion() → int
|
|
|
|
|
Returns the Redbean version in the format 0xMMmmpp, with major (MM),
|
|
|
|
|
minor (mm), and patch (pp) versions encoded. The version value 1.4
|
|
|
|
|
would be represented as 0x010400.
|
|
|
|
|
|
|
|
|
|
GetZipPaths([prefix:str]) → {path:str,...}
|
|
|
|
|
Returns paths of all assets in the zip central directory, prefixed
|
|
|
|
|
by a slash. If prefix parameter is provided, then only paths that
|
|
|
|
|
start with the prefix (case sensitive) are returned.
|
|
|
|
|
|
|
|
|
|
HasParam(name:str) → bool
|
|
|
|
|
Returns true if parameter with name was supplied in either the
|
|
|
|
|
Request-URL or an application/x-www-form-urlencoded message body.
|
|
|
|
|
|
|
|
|
|
HidePath(prefix:str)
|
|
|
|
|
Programs redbean / listing page to not display any paths beginning
|
|
|
|
|
with prefix. This function should only be called from /.init.lua.
|
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
IsHiddenPath(path:str) → bool
|
|
|
|
|
Returns true if the prefix of the given path is set with HidePath.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
IsPublicIp(uint32) → bool
|
|
|
|
|
Returns true if IP address is not a private network (10.0.0.0/8,
|
|
|
|
|
172.16.0.0/12, 192.168.0.0/16) and is not localhost (127.0.0.0/8).
|
|
|
|
|
Note: we intentionally regard TEST-NET IPs as public.
|
|
|
|
|
|
|
|
|
|
IsPrivateIp(uint32) → bool
|
|
|
|
|
Returns true if IP address is part of a private network
|
|
|
|
|
(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).
|
|
|
|
|
|
|
|
|
|
IsLoopbackIp(uint32) → bool
|
|
|
|
|
Returns true if IP address is part of the localhost network
|
|
|
|
|
(127.0.0.0/8).
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
IsAssetCompressed(path:str) → bool
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Returns true if ZIP artifact at path is stored on disk using
|
|
|
|
|
DEFLATE compression.
|
2022-06-24 01:54:35 +00:00
|
|
|
|
Also available as IsCompressed (deprecated).
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
IndentLines(str[,int]) → str
|
|
|
|
|
Adds spaces to beginnings of multiline string. If the int
|
|
|
|
|
parameter is not supplied then 1 space will be added.
|
|
|
|
|
|
|
|
|
|
LoadAsset(path:str) → str
|
|
|
|
|
Returns contents of file as string. The asset may be sourced from
|
|
|
|
|
either the zip (decompressed) or the local filesystem if the -D
|
|
|
|
|
flag was used. If slurping large file into memory is a concern,
|
|
|
|
|
then consider using ServeAsset which can serve directly off disk.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
StoreAsset(path:str, data:str[, mode:int])
|
2022-07-09 08:18:55 +00:00
|
|
|
|
Stores asset to executable's ZIP central directory. This
|
|
|
|
|
currently happens in an append-only fashion and is still
|
|
|
|
|
largely in the proof-of-concept stages. Currently only
|
|
|
|
|
supported on Linux, XNU, and FreeBSD. In order to use this
|
|
|
|
|
feature, the -* flag must be passed.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
Log(level:int, message:str)
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Emits message string to log, if level is less than or equal to
|
|
|
|
|
GetLogLevel. If redbean is running in interactive mode, then this
|
|
|
|
|
will log to the console. If redbean is running as a daemon or the
|
|
|
|
|
-L LOGFILE flag is passed, then this will log to the file.
|
|
|
|
|
Reasonable values for level are kLogDebug > kLogVerbose > kLogInfo
|
|
|
|
|
> kLogWarn > kLogError > kLogFatal. The logger emits timestamps in
|
|
|
|
|
the local timezone with microsecond precision. If log entries are
|
|
|
|
|
emitted more frequently than once per second, then the log entry
|
|
|
|
|
will display a delta timestamp, showing how much time has elapsed
|
|
|
|
|
since the previous log entry. This behavior is useful for quickly
|
|
|
|
|
measuring how long various portions of your code take to execute.
|
|
|
|
|
|
|
|
|
|
ParseHttpDateTime(rfc1123:str) → seconds:int
|
|
|
|
|
Converts RFC1123 string that looks like this: Mon, 29 Mar 2021
|
|
|
|
|
15:37:13 GMT to a UNIX timestamp. See parsehttpdatetime.c.
|
|
|
|
|
|
2022-09-20 02:23:24 +00:00
|
|
|
|
ParseUrl(url:str[, flags:int]) → URL
|
|
|
|
|
|
|
|
|
|
Parses URL.
|
|
|
|
|
|
|
|
|
|
An object containing the following fields is returned:
|
|
|
|
|
|
|
|
|
|
- `scheme` is a string, e.g. `"http"`
|
|
|
|
|
- `user` is the username string, or nil if absent
|
|
|
|
|
- `pass` is the password string, or nil if absent
|
|
|
|
|
- `host` is the hostname string, or nil if `url` was a path
|
|
|
|
|
- `port` is the port string, or nil if absent
|
|
|
|
|
- `path` is the path string, or nil if absent
|
|
|
|
|
- `params` is the URL paramaters, e.g. `/?a=b&c` would be
|
|
|
|
|
represented as the data structure `{{"a", "b"}, {"c"}, ...}`
|
|
|
|
|
- `fragment` is the stuff after the `#` character
|
|
|
|
|
|
|
|
|
|
`flags` may have:
|
|
|
|
|
|
|
|
|
|
- `kUrlPlus` to turn `+` into space
|
|
|
|
|
- `kUrlLatin1` to transcode ISO-8859-1 input into UTF-8
|
|
|
|
|
|
|
|
|
|
This parser is charset agnostic. Percent encoded bytes are
|
|
|
|
|
decoded for all fields. Returned values might contain things
|
|
|
|
|
like NUL characters, spaces, control codes, and non-canonical
|
|
|
|
|
encodings. Absent can be discerned from empty by checking if
|
|
|
|
|
the pointer is set.
|
|
|
|
|
|
|
|
|
|
There's no failure condition for this routine. This is a
|
|
|
|
|
permissive parser. This doesn't normalize path segments like
|
|
|
|
|
`.` or `..` so use IsAcceptablePath() to check for those. No
|
|
|
|
|
restrictions are imposed beyond that which is strictly
|
|
|
|
|
necessary for parsing. All the data that is provided will be
|
|
|
|
|
consumed to the one of the fields. Strict conformance is
|
|
|
|
|
enforced on some fields more than others, like scheme, since
|
|
|
|
|
it's the most non-deterministically defined field of them all.
|
|
|
|
|
|
|
|
|
|
Please note this is a URL parser, not a URI parser. Which
|
|
|
|
|
means we support everything everything the URI spec says we
|
|
|
|
|
should do except for the things we won't do, like tokenizing
|
|
|
|
|
path segments into an array and then nesting another array
|
|
|
|
|
beneath each of those for storing semicolon parameters. So
|
|
|
|
|
this parser won't make SIP easy. What it can do is parse HTTP
|
|
|
|
|
URLs and most URIs like data:opaque, better in fact than most
|
|
|
|
|
things which claim to be URI parsers.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
IsAcceptablePath(str) → bool
|
|
|
|
|
Returns true if path doesn't contain ".", ".." or "//" segments
|
|
|
|
|
See isacceptablepath.c
|
|
|
|
|
|
|
|
|
|
IsReasonablePath(str) → bool
|
|
|
|
|
Returns true if path doesn't contain "." or ".." segments.
|
|
|
|
|
See isreasonablepath.c
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
EncodeUrl(URL) → str
|
|
|
|
|
This function is the inverse of ParseUrl. The output will always
|
|
|
|
|
be correctly formatted. The exception is if illegal characters are
|
|
|
|
|
supplied in the scheme field, since there's no way of escaping
|
|
|
|
|
those. Opaque parts are escaped as though they were paths, since
|
|
|
|
|
many URI parsers won't understand things like an unescaped
|
|
|
|
|
question mark in path.
|
|
|
|
|
|
|
|
|
|
ParseIp(str) → int
|
|
|
|
|
Converts IPv4 address string to integer, e.g. "1.2.3.4" →
|
|
|
|
|
0x01020304, or returns -1 for invalid inputs. See also FormatIp
|
|
|
|
|
for the inverse operation.
|
|
|
|
|
|
2022-06-24 00:59:35 +00:00
|
|
|
|
ProgramAddr(ip:int)
|
|
|
|
|
ProgramAddr(host:str)
|
|
|
|
|
Configures the address on which to listen. This can be called
|
|
|
|
|
multiple times to set more than one address. If an integer is
|
|
|
|
|
provided then it should be a word-encoded IPv4 address, such
|
|
|
|
|
as the ones returned by ResolveIp(). If a string is provided,
|
|
|
|
|
it will first be passed to ParseIp() to see if it's an IPv4
|
|
|
|
|
address. If it isn't, then a HOSTS.TXT lookup is performed,
|
|
|
|
|
with fallback to the system-configured DNS resolution service.
|
|
|
|
|
Please note that in MODE=tiny the HOSTS.TXT and DNS resolution
|
|
|
|
|
isn't included, and therefore an IP must be provided.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
ProgramBrand(str)
|
|
|
|
|
Changes HTTP Server header, as well as the <h1> title on the /
|
|
|
|
|
listing page. The brand string needs to be a UTF-8 value that's
|
|
|
|
|
encodable as ISO-8859-1. If the brand is changed to something
|
|
|
|
|
other than redbean, then the promotional links will be removed
|
|
|
|
|
from the listing page too. This function should only be called
|
|
|
|
|
from /.init.lua.
|
|
|
|
|
|
|
|
|
|
ProgramCache(seconds:int)
|
|
|
|
|
Configures Cache-Control and Expires header generation for static
|
|
|
|
|
asset serving. A negative value will disable the headers. Zero
|
|
|
|
|
means don't cache. Greater than zero asks public proxies and
|
|
|
|
|
browsers to cache for a given number of seconds. This should only
|
|
|
|
|
be called from /.init.lua.
|
|
|
|
|
|
|
|
|
|
ProgramCertificate(pem:str)
|
|
|
|
|
Same as the -C flag if called from .init.lua, e.g.
|
|
|
|
|
ProgramCertificate(LoadAsset("/.sign.crt")) for zip loading or
|
|
|
|
|
ProgramCertificate(Slurp("/etc/letsencrypt.lol/fullchain.pem")) for
|
|
|
|
|
local file system only.
|
|
|
|
|
|
2022-08-24 16:35:17 +00:00
|
|
|
|
ProgramContentType(ext:str[, contenttype:str]) → str
|
|
|
|
|
Sets or returns content type associated with a file extension.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
ProgramHeader(name:str,value:str)
|
|
|
|
|
Appends HTTP header to the header buffer for all responses (whereas
|
|
|
|
|
SetHeader only appends a header to the current response buffer).
|
|
|
|
|
name is case-insensitive and restricted to non-space ASCII. value
|
|
|
|
|
is a UTF-8 string that must be encodable as ISO-8859-1. Leading and
|
|
|
|
|
trailing whitespace is trimmed automatically. Overlong characters
|
|
|
|
|
are canonicalized. C0 and C1 control codes are forbidden, with the
|
|
|
|
|
exception of tab. The header buffer is independent of the payload
|
|
|
|
|
buffer. This function disallows the setting of certain headers such
|
|
|
|
|
as Content-Range and Date, which are abstracted by the transport
|
|
|
|
|
layer.
|
|
|
|
|
|
2022-08-06 02:24:05 +00:00
|
|
|
|
ProgramHeartbeatInterval([milliseconds:int])
|
|
|
|
|
Sets the heartbeat interval (in milliseconds). 5000ms is the
|
|
|
|
|
default and 100ms is the minimum. If `milliseconds` is not
|
|
|
|
|
specified, then the current interval is returned.
|
2022-08-03 03:41:44 +00:00
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
ProgramTimeout(milliseconds:int|seconds:int)
|
|
|
|
|
Default timeout is 60000ms. Minimal value of timeout is 10(ms).
|
|
|
|
|
Negative values (<0) sets the keepalive in seconds.
|
|
|
|
|
This should only be called from /.init.lua.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
ProgramPort(uint16)
|
|
|
|
|
Hard-codes the port number on which to listen, which can be any
|
|
|
|
|
number in the range 1..65535, or alternatively 0 to ask the
|
|
|
|
|
operating system to choose a port, which may be revealed later on
|
|
|
|
|
by GetServerAddr or the -z flag to stdout.
|
|
|
|
|
|
2022-07-08 13:29:24 +00:00
|
|
|
|
ProgramMaxPayloadSize(int)
|
2022-06-10 10:28:46 +00:00
|
|
|
|
Sets the maximum HTTP message payload size in bytes. The
|
|
|
|
|
default is very conservatively set to 65536 so this is
|
|
|
|
|
something many people will want to increase. This limit is
|
|
|
|
|
enforced at the transport layer, before any Lua code is
|
2022-07-16 18:00:28 +00:00
|
|
|
|
called, because right now redbean stores and forwards
|
2022-06-10 10:28:46 +00:00
|
|
|
|
messages. (Use the UNIX API for raw socket streaming.) Setting
|
|
|
|
|
this to a very high value can be useful if you're less
|
|
|
|
|
concerned about rogue clients and would rather have your Lua
|
|
|
|
|
code be granted more control to bounce unreasonable messages.
|
|
|
|
|
If a value less than 1450 is supplied, it'll automatically be
|
|
|
|
|
increased to 1450, since that's the size of ethernet frames.
|
|
|
|
|
This function can only be called from .init.lua.
|
|
|
|
|
|
2022-08-05 22:21:27 +00:00
|
|
|
|
ProgramMaxWorkers(int)
|
|
|
|
|
Limits the number of workers forked by redbean. If that number
|
|
|
|
|
is reached, the server continues polling until the number of
|
|
|
|
|
workers is reduced or the value is updated. Setting it to 0
|
|
|
|
|
removes the limit (this is the default).
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
ProgramPrivateKey(pem:str)
|
|
|
|
|
Same as the -K flag if called from .init.lua, e.g.
|
|
|
|
|
ProgramPrivateKey(LoadAsset("/.sign.key")) for zip loading or
|
2022-05-27 06:17:19 +00:00
|
|
|
|
ProgramPrivateKey(Slurp("/etc/letsencrypt/privkey.pem")) for
|
2022-04-24 16:59:22 +00:00
|
|
|
|
local file system only.
|
|
|
|
|
|
|
|
|
|
ProgramRedirect(code:int,src:str,location:str)
|
|
|
|
|
Configures fallback routing for paths which would otherwise return
|
|
|
|
|
404 Not Found. If code is 0 then the path is rewritten internally
|
|
|
|
|
as an accelerated redirect. If code is 301, 302, 307, or 308 then
|
|
|
|
|
a redirect response will be sent to the client. This should only
|
|
|
|
|
be called from /.init.lua.
|
|
|
|
|
|
|
|
|
|
ProgramSslTicketLifetime(seconds:int)
|
|
|
|
|
Defaults to 86400 (24 hours). This may be set to ≤0 to disable
|
|
|
|
|
SSL tickets. It's a good idea to use these since it increases
|
|
|
|
|
handshake performance 10x and eliminates a network round trip.
|
2022-05-29 15:14:55 +00:00
|
|
|
|
This function is not available in unsecure mode.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
ProgramSslPresharedKey(key:str,identity:str)
|
2022-05-29 15:14:55 +00:00
|
|
|
|
This function can be used to enable the PSK ciphersuites which
|
|
|
|
|
simplify SSL and enhance its performance in controlled
|
2022-04-24 16:59:22 +00:00
|
|
|
|
environments. `key` may contain 1..32 bytes of random binary
|
|
|
|
|
data and identity is usually a short plaintext string. The
|
2022-05-29 15:14:55 +00:00
|
|
|
|
first time this function is called, the preshared key will be
|
|
|
|
|
added to both the client and the server SSL configs. If it's
|
|
|
|
|
called multiple times, then the remaining keys will be added
|
|
|
|
|
to the server, which is useful if you want to assign separate
|
|
|
|
|
keys to each client, each of which needs a separate identity
|
|
|
|
|
too. If this function is called multiple times with the same
|
|
|
|
|
identity string, then the latter call will overwrite the
|
|
|
|
|
prior. If a preshared key is supplied and no certificates or
|
|
|
|
|
key-signing-keys are programmed, then redbean won't bother
|
2022-04-24 16:59:22 +00:00
|
|
|
|
auto-generating any serving certificates and will instead use
|
2022-05-29 15:14:55 +00:00
|
|
|
|
only PSK ciphersuites. This function is not available in
|
|
|
|
|
unsecure mode.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
ProgramSslFetchVerify(enabled:bool)
|
|
|
|
|
May be used to disable the verification of certificates for
|
|
|
|
|
remote hosts when using the Fetch() API. This function is not
|
|
|
|
|
available in unsecure mode.
|
2022-05-29 15:14:55 +00:00
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
ProgramSslClientVerify(enabled:bool)
|
2022-05-29 15:14:55 +00:00
|
|
|
|
Enables the verification of certificates supplied by the HTTP
|
|
|
|
|
clients that connect to your redbean. This has the same effect
|
|
|
|
|
as the `-j` flag. Tuning this option alone does not preclude
|
|
|
|
|
the possibility of unsecured HTTP clients, which can be
|
|
|
|
|
disabled using ProgramSslRequired(). This function can only be
|
|
|
|
|
called from `.init.lua`. This function is not available in
|
|
|
|
|
unsecure mode.
|
|
|
|
|
|
|
|
|
|
ProgramSslRequired(mandatory:str)
|
|
|
|
|
Enables the blocking of HTTP so that all inbound clients and
|
|
|
|
|
must use the TLS transport layer. This has the same effect as
|
|
|
|
|
the `-J` flag. Fetch() is still allowed to make outbound HTTP
|
|
|
|
|
requests. This function can only be called from `.init.lua`.
|
|
|
|
|
This function is not available in unsecure mode.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
ProgramSslCiphersuite(name:str)
|
|
|
|
|
See https://redbean.dev/ for further details.
|
|
|
|
|
|
|
|
|
|
IsDaemon() → bool
|
|
|
|
|
Returns true if -d flag was passed to redbean.
|
|
|
|
|
|
|
|
|
|
ProgramUid(int)
|
|
|
|
|
Same as the -U flag if called from .init.lua for setuid()
|
|
|
|
|
|
|
|
|
|
ProgramGid(int)
|
|
|
|
|
Same as the -G flag if called from .init.lua for setgid()
|
|
|
|
|
|
|
|
|
|
ProgramDirectory(str)
|
|
|
|
|
Same as the -D flag if called from .init.lua for overlaying local
|
|
|
|
|
file system directories. This may be called multiple times. The
|
|
|
|
|
first directory programmed is preferred. These currently do not
|
|
|
|
|
show up in the index page listing.
|
|
|
|
|
|
|
|
|
|
ProgramLogMessages(bool)
|
|
|
|
|
Same as the -m flag if called from .init.lua for logging message
|
|
|
|
|
headers only.
|
|
|
|
|
|
|
|
|
|
ProgramLogBodies(bool)
|
|
|
|
|
Same as the -b flag if called from .init.lua for logging message
|
|
|
|
|
bodies as part of POST / PUT / etc. requests.
|
|
|
|
|
|
|
|
|
|
ProgramLogPath(str)
|
|
|
|
|
Same as the -L flag if called from .init.lua for setting the log
|
|
|
|
|
file path on the local file system. It's created if it doesn't
|
2022-07-16 18:00:28 +00:00
|
|
|
|
exist. This is called before de-escalating the user / group id.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
The file is opened in append only mode. If the disk runs out of
|
|
|
|
|
space then redbean will truncate the log file if has access to
|
|
|
|
|
change the log file after daemonizing.
|
|
|
|
|
|
|
|
|
|
ProgramPidPath(str)
|
|
|
|
|
Same as the -P flag if called from .init.lua for setting the pid
|
|
|
|
|
file path on the local file system. It's useful for reloading
|
|
|
|
|
daemonized redbean using `kill -HUP $(cat /var/run/redbean.pid)`
|
|
|
|
|
or terminating redbean with `kill $(cat /var/run/redbean.pid)`
|
|
|
|
|
which will gracefully terminate all clients. Sending the TERM
|
|
|
|
|
signal twice will cause a forceful shutdown, which might make
|
|
|
|
|
someone with a slow internet connection who's downloading big
|
|
|
|
|
files unhappy.
|
|
|
|
|
|
|
|
|
|
ProgramUniprocess([bool]) → bool
|
|
|
|
|
Same as the -u flag if called from .init.lua. Can be used to
|
|
|
|
|
configure the uniprocess mode. The current value is returned.
|
|
|
|
|
|
2022-07-23 03:44:24 +00:00
|
|
|
|
Slurp(filename:str[, i:int[, j:int]])
|
|
|
|
|
├─→ data:str
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-07-23 14:37:39 +00:00
|
|
|
|
Reads all data from file the easy way.
|
2022-07-23 03:44:24 +00:00
|
|
|
|
|
|
|
|
|
This function reads file data from local file system. Zip file
|
|
|
|
|
assets can be accessed using the `/zip/...` prefix.
|
|
|
|
|
|
|
|
|
|
`i` and `j` may be used to slice a substring in `filename`.
|
|
|
|
|
These parameters are 1-indexed and behave consistently with
|
|
|
|
|
Lua's string.sub() API. For example:
|
|
|
|
|
|
|
|
|
|
assert(Barf('x.txt', 'abc123'))
|
|
|
|
|
assert(assert(Slurp('x.txt', 2, 3)) == 'bc')
|
|
|
|
|
|
|
|
|
|
This function is uninterruptible so `unix.EINTR` errors will
|
|
|
|
|
be ignored. This should only be a concern if you've installed
|
|
|
|
|
signal handlers. Use the UNIX API if you need to react to it.
|
|
|
|
|
|
|
|
|
|
Barf(filename:str, data:str[, mode:int[, flags:int[, offset:int]]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Writes all data to file the easy way.
|
|
|
|
|
|
|
|
|
|
This function writes to the local file system.
|
|
|
|
|
|
|
|
|
|
`mode` defaults to `0644`. This parameter is ignored when
|
|
|
|
|
`flags` doesn't have `unix.O_CREAT`.
|
|
|
|
|
|
|
|
|
|
`flags` defaults to `unix.O_TRUNC | unix.O_CREAT`.
|
|
|
|
|
|
|
|
|
|
`offset` is 1-indexed and may be used to overwrite arbitrary
|
|
|
|
|
slices within a file when used in conjunction with `flags=0`.
|
|
|
|
|
For example:
|
|
|
|
|
|
|
|
|
|
assert(Barf('x.txt', 'abc123'))
|
|
|
|
|
assert(Barf('x.txt', 'XX', 0, 0, 3))
|
|
|
|
|
assert(assert(Slurp('x.txt', 1, 6)) == 'abXX23')
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Sleep(seconds:number)
|
|
|
|
|
Sleeps the specified number of seconds (can be fractional). The
|
|
|
|
|
smallest interval is a microsecond.
|
|
|
|
|
|
|
|
|
|
Route([host:str,[path:str]])
|
|
|
|
|
Instructs redbean to follow the normal HTTP serving path. This
|
|
|
|
|
function is useful when writing an OnHttpRequest handler, since
|
|
|
|
|
that overrides the serving path entirely. So if the handler
|
|
|
|
|
decides it doesn't want to do anything, it can simply call this
|
|
|
|
|
function, to hand over control back to the redbean core. By
|
|
|
|
|
default, the host and path arguments are supplied from the
|
|
|
|
|
resolved GetUrl value. This handler always resolves, since it will
|
|
|
|
|
generate a 404 Not Found response if redbean couldn't find an
|
|
|
|
|
appropriate endpoint.
|
|
|
|
|
|
|
|
|
|
RouteHost([host:str,[path:str]]) → bool
|
|
|
|
|
This is the same as Route, except it only implements the subset of
|
|
|
|
|
request routing needed for serving virtual-hosted assets, where
|
|
|
|
|
redbean tries to prefix the path with the hostname when looking up
|
|
|
|
|
a file. This function returns true if the request was resolved. If
|
|
|
|
|
it was resolved, then your OnHttpRequest request handler can still
|
|
|
|
|
set additional headers.
|
|
|
|
|
|
|
|
|
|
RoutePath([path:str]) → bool
|
|
|
|
|
This is the same as Route, except it only implements the subset of
|
|
|
|
|
request routing needed for serving assets. This function returns
|
|
|
|
|
true if the request was resolved. If it was resolved, then your
|
|
|
|
|
OnHttpRequest request handler can still set additional headers.
|
|
|
|
|
Note that the asset needs to have "read other" permissions;
|
|
|
|
|
otherwise this function logs a warning and returns 403 Forbidden.
|
|
|
|
|
If this is undesirable, use GetAssetMode and ServeAsset to bypass
|
|
|
|
|
the check.
|
|
|
|
|
|
|
|
|
|
ServeAsset(path:str)
|
|
|
|
|
Instructs redbean to serve static asset at path. This function
|
|
|
|
|
causes what would normally happen outside a dynamic handler to
|
|
|
|
|
happen. The asset can be sourced from either the zip or local
|
|
|
|
|
filesystem if -D is used. This function is mutually exclusive with
|
|
|
|
|
SetStatus and other Serve* functions.
|
|
|
|
|
|
|
|
|
|
ServeError(code:int[,reason:str])
|
|
|
|
|
Instructs redbean to serve a boilerplate error page. This takes
|
|
|
|
|
care of logging the error, setting the reason phrase, and adding a
|
|
|
|
|
payload. This function is mutually exclusive with SetStatus and
|
|
|
|
|
other Serve* functions.
|
|
|
|
|
|
|
|
|
|
ServeRedirect(code:int,location:str)
|
|
|
|
|
Instructs redbean to return the specified redirect code along with
|
|
|
|
|
the Location header set. This function is mutually exclusive with
|
|
|
|
|
SetStatus and other Serve* functions.
|
|
|
|
|
|
|
|
|
|
SetLogLevel(level:int)
|
|
|
|
|
Sets logger verbosity. Reasonable values for level are kLogDebug >
|
|
|
|
|
kLogVerbose > kLogInfo > kLogWarn > kLogError > kLogFatal. This is
|
|
|
|
|
reset at the end of the http request, so it can be used to disable
|
|
|
|
|
access log and message logging.
|
|
|
|
|
|
|
|
|
|
VisualizeControlCodes(str) → str
|
2022-07-12 19:30:42 +00:00
|
|
|
|
Replaces C0 control codes and trojan source characters with
|
|
|
|
|
descriptive UNICODE pictorial representation. This function
|
|
|
|
|
also canonicalizes overlong encodings. C1 control codes are
|
|
|
|
|
replaced with a JavaScript-like escape sequence.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Underlong(str) → str
|
|
|
|
|
Canonicalizes overlong encodings.
|
|
|
|
|
|
|
|
|
|
Crc32(initial:int,data:str) → int
|
|
|
|
|
Computes 32-bit CRC-32 used by zip/zlib/gzip/etc.
|
|
|
|
|
|
|
|
|
|
Crc32c(initial:int,data:str) → int
|
|
|
|
|
Computes 32-bit Castagnoli Cyclic Redundancy Check.
|
|
|
|
|
|
|
|
|
|
Md5(str) → str
|
|
|
|
|
Computes MD5 checksum, returning 16 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Sha1(str) → str
|
|
|
|
|
Computes SHA1 checksum, returning 20 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Sha224(str) → str
|
|
|
|
|
Computes SHA224 checksum, returning 28 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Sha256(str) → str
|
|
|
|
|
Computes SHA256 checksum, returning 32 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Sha384(str) → str
|
|
|
|
|
Computes SHA384 checksum, returning 48 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Sha512(str) → str
|
|
|
|
|
Computes SHA512 checksum, returning 64 bytes of binary.
|
|
|
|
|
|
|
|
|
|
Bsf(x:int) → int
|
|
|
|
|
Returns position of first bit set. Passing 0 will raise an error.
|
|
|
|
|
Same as the Intel x86 instruction BSF.
|
|
|
|
|
|
|
|
|
|
Bsr(x:int) → int
|
|
|
|
|
Returns binary logarithm of 𝑥. Passing 0 will raise an error. Same
|
|
|
|
|
as the Intel x86 instruction BSR.
|
|
|
|
|
|
|
|
|
|
Popcnt(x:int) → int
|
|
|
|
|
Returns number of bits set in integer.
|
|
|
|
|
|
|
|
|
|
Rdtsc() → int
|
|
|
|
|
Returns CPU timestamp counter.
|
|
|
|
|
|
|
|
|
|
Lemur64() → int
|
|
|
|
|
Returns fastest pseudorandom non-cryptographic random number. This
|
|
|
|
|
linear congruential generator passes practrand and bigcrush.
|
|
|
|
|
|
|
|
|
|
Rand64() → int
|
|
|
|
|
Returns nondeterministic pseudorandom non-cryptographic number. This
|
|
|
|
|
linear congruential generator passes practrand and bigcrush. This
|
|
|
|
|
generator is safe across fork(), threads, and signal handlers.
|
|
|
|
|
|
|
|
|
|
Rdrand() → int
|
|
|
|
|
Returns 64-bit hardware random integer from RDRND instruction, with
|
|
|
|
|
automatic fallback to getrandom() if not available.
|
|
|
|
|
|
|
|
|
|
Rdseed() → int
|
|
|
|
|
Returns 64-bit hardware random integer from RDSEED instruction, with
|
|
|
|
|
automatic fallback to RDRND and getrandom() if not available.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
GetCpuCount() → int
|
|
|
|
|
Returns CPU core count or 0 if it couldn't be determined.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
GetCpuCore() → int
|
|
|
|
|
Returns 0-indexed CPU core on which process is currently scheduled.
|
|
|
|
|
|
|
|
|
|
GetCpuNode() → int
|
|
|
|
|
Returns 0-indexed NUMA node on which process is currently scheduled.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
Decimate(str) → str
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Shrinks byte buffer in half using John Costella's magic kernel.
|
|
|
|
|
This downscales data 2x using an eight-tap convolution, e.g.
|
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
>: Decimate('\xff\xff\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00')
|
|
|
|
|
"\xff\x00\xff\x00\xff\x00"
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
This is very fast if SSSE3 is available (Intel 2004+ / AMD 2011+).
|
|
|
|
|
|
|
|
|
|
MeasureEntropy(data) → float
|
|
|
|
|
Returns Shannon entropy of array. This gives you an idea of
|
|
|
|
|
the density of information. Cryptographic random should be in
|
|
|
|
|
the ballpark of 7.9 whereas plaintext will be more like 4.5.
|
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
Deflate(uncompressed:str[, level:int])
|
|
|
|
|
├─→ compressed:str
|
|
|
|
|
└─→ nil, error:str
|
2022-05-16 23:49:20 +00:00
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
Compresses data.
|
2022-05-16 23:49:20 +00:00
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
>: Deflate("hello")
|
|
|
|
|
"\xcbH\xcd\xc9\xc9\x07\x00"
|
|
|
|
|
>: Inflate("\xcbH\xcd\xc9\xc9\x07\x00", 5)
|
2022-05-16 23:49:20 +00:00
|
|
|
|
"hello"
|
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
The output format is raw DEFLATE that's suitable for embedding
|
|
|
|
|
into formats like a ZIP file. It's recommended that, like ZIP,
|
|
|
|
|
you also store separately a Crc32() checksum in addition to
|
|
|
|
|
the original uncompressed size.
|
2022-05-16 23:49:20 +00:00
|
|
|
|
|
2022-05-17 17:41:23 +00:00
|
|
|
|
`level` is the compression level, which defaults to 7. The max
|
2022-07-08 16:47:04 +00:00
|
|
|
|
is 9. Lower numbers go faster (4 for instance is a sweet spot)
|
|
|
|
|
and higher numbers go slower but have better compression.
|
2022-05-17 17:41:23 +00:00
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
Inflate(compressed:str, maxoutsize:int)
|
|
|
|
|
├─→ uncompressed:str
|
|
|
|
|
└─→ nil, error:str
|
2022-05-17 17:41:23 +00:00
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
Decompresses data.
|
|
|
|
|
|
|
|
|
|
This function performs the inverse of Deflate(). It's
|
|
|
|
|
recommended that you perform a Crc32() check on the output
|
|
|
|
|
string after this function succeeds.
|
2022-05-17 17:41:23 +00:00
|
|
|
|
|
2022-07-08 16:47:04 +00:00
|
|
|
|
`maxoutsize` is the uncompressed size, which should be known.
|
|
|
|
|
However, it is permissable (although not advised) to specify
|
|
|
|
|
some large number in which case (on success) the byte length
|
|
|
|
|
of the output string may be less than `maxoutsize`.
|
2022-05-17 17:41:23 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Benchmark(func[, count[, maxattempts]])
|
|
|
|
|
└─→ nanos:real, ticks:int, overhead-ticks:int, tries:int
|
|
|
|
|
|
|
|
|
|
Performs microbenchmark.
|
|
|
|
|
|
|
|
|
|
The first value returned is the average number of nanoseconds that
|
|
|
|
|
`func` needed to execute. Nanoseconds are computed from RDTSC tick
|
|
|
|
|
counts, using an approximation that's measured beforehand with the
|
|
|
|
|
unix.clock_gettime() function.
|
|
|
|
|
|
|
|
|
|
The `ticks` result is the canonical average number of clock ticks.
|
|
|
|
|
|
|
|
|
|
This subroutine will subtract whatever the overhead happens to be
|
|
|
|
|
for benchmarking a function that does nothing. This overhead value
|
|
|
|
|
will be reported in the result.
|
|
|
|
|
|
|
|
|
|
`tries` indicates if your microbenchmark needed to be repeated,
|
|
|
|
|
possibly because your system is under load and the benchmark was
|
|
|
|
|
preempted by the operating system, or moved to a different core.
|
|
|
|
|
|
2022-04-29 13:06:23 +00:00
|
|
|
|
oct(int)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Formats string as octal integer literal string. If the provided
|
|
|
|
|
value is zero, the result will be `"0"`. Otherwise the resulting
|
|
|
|
|
value will be the zero-prefixed octal string. The result is
|
|
|
|
|
currently modulo 2^64. Negative numbers are converted to unsigned.
|
|
|
|
|
|
|
|
|
|
hex(int)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Formats string as hexadecimal integer literal string. If the
|
|
|
|
|
provided value is zero, the result will be `"0"`. Otherwise the
|
|
|
|
|
resulting value will be the `"0x"`-prefixed hex string. The result
|
|
|
|
|
is currently modulo 2^64. Negative numbers are converted to
|
|
|
|
|
unsigned.
|
|
|
|
|
|
|
|
|
|
bin(int)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Formats string as binary integer literal string. If the provided
|
|
|
|
|
value is zero, the result will be `"0"`. Otherwise the resulting
|
|
|
|
|
value will be the `"0b"`-prefixed binary str. The result is
|
|
|
|
|
currently modulo 2^64. Negative numbers are converted to unsigned.
|
|
|
|
|
|
2022-06-23 10:39:44 +00:00
|
|
|
|
ResolveIp(hostname:str)
|
|
|
|
|
├─→ ip:uint32
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Gets IP address associated with hostname.
|
|
|
|
|
|
|
|
|
|
This function first checks if hostname is already an IP address, in
|
|
|
|
|
which case it returns the result of `ParseIp`. Otherwise, it checks
|
|
|
|
|
HOSTS.TXT on the local system and returns the first IPv4 address
|
|
|
|
|
associated with hostname. If no such entry is found, a DNS lookup is
|
|
|
|
|
performed using the system configured (e.g. /etc/resolv.conf) DNS
|
|
|
|
|
resolution service. If the service returns multiple IN A records
|
2022-07-16 18:00:28 +00:00
|
|
|
|
then only the first one is returned.
|
2022-06-23 10:39:44 +00:00
|
|
|
|
|
|
|
|
|
The returned address is word-encoded in host endian order. For
|
|
|
|
|
example, 1.2.3.4 is encoded as 0x01020304. The `FormatIp` function
|
|
|
|
|
may be used to turn this value back into a string.
|
|
|
|
|
|
|
|
|
|
If no IP address could be found, then nil is returned alongside a
|
|
|
|
|
string of unspecified format describing the error. Calls to this
|
|
|
|
|
function may be wrapped in assert() if an exception is desired.
|
|
|
|
|
|
2022-10-17 18:02:04 +00:00
|
|
|
|
IsTrustedIp(ip:int)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if IP address is trustworthy.
|
|
|
|
|
|
|
|
|
|
If the ProgramTrustedIp() function has NOT been called then redbean
|
|
|
|
|
will consider the networks 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12,
|
|
|
|
|
and 192.168.0.0/16 to be trustworthy too. If ProgramTrustedIp() HAS
|
|
|
|
|
been called at some point earlier in your redbean's lifecycle, then
|
|
|
|
|
it'll trust the IPs and network subnets you specify instead.
|
|
|
|
|
|
|
|
|
|
The network interface addresses used by the host machine are always
|
|
|
|
|
considered trustworthy, e.g. 127.0.0.1. This may change soon, if we
|
|
|
|
|
decide to export a GetHostIps() API which queries your NIC devices.
|
|
|
|
|
|
|
|
|
|
ProgramTrustedIp(ip:int[, cidr:int])
|
|
|
|
|
|
|
|
|
|
Trusts an IP address or network.
|
|
|
|
|
|
|
|
|
|
This function may be used to configure the IsTrustedIp() function
|
|
|
|
|
which is how redbean determines if a client is allowed to send us
|
|
|
|
|
headers like X-Forwarded-For (cf GetRemoteAddr vs. GetClientAddr)
|
|
|
|
|
without them being ignored. Trusted IPs is also how redbean turns
|
|
|
|
|
off token bucket rate limiting selectively, so be careful. Here's
|
|
|
|
|
an example of how you could trust all of Cloudflare's IPs:
|
|
|
|
|
|
|
|
|
|
ProgramTrustedIp(ParseIp("103.21.244.0"), 22);
|
|
|
|
|
ProgramTrustedIp(ParseIp("103.22.200.0"), 22);
|
|
|
|
|
ProgramTrustedIp(ParseIp("103.31.4.0"), 22);
|
|
|
|
|
ProgramTrustedIp(ParseIp("104.16.0.0"), 13);
|
|
|
|
|
ProgramTrustedIp(ParseIp("104.24.0.0"), 14);
|
|
|
|
|
ProgramTrustedIp(ParseIp("108.162.192.0"), 18);
|
|
|
|
|
ProgramTrustedIp(ParseIp("131.0.72.0"), 22);
|
|
|
|
|
ProgramTrustedIp(ParseIp("141.101.64.0"), 18);
|
|
|
|
|
ProgramTrustedIp(ParseIp("162.158.0.0"), 15);
|
|
|
|
|
ProgramTrustedIp(ParseIp("172.64.0.0"), 13);
|
|
|
|
|
ProgramTrustedIp(ParseIp("173.245.48.0"), 20);
|
|
|
|
|
ProgramTrustedIp(ParseIp("188.114.96.0"), 20);
|
|
|
|
|
ProgramTrustedIp(ParseIp("190.93.240.0"), 20);
|
|
|
|
|
ProgramTrustedIp(ParseIp("197.234.240.0"), 22);
|
|
|
|
|
ProgramTrustedIp(ParseIp("198.41.128.0"), 17);
|
|
|
|
|
|
|
|
|
|
Although you might want consider trusting redbean's open source
|
|
|
|
|
freedom embracing solution to DDOS protection instead!
|
|
|
|
|
|
|
|
|
|
ProgramTokenBucket([replenish:num, cidr:int, reject:int, ignore:int, ban:int])
|
|
|
|
|
|
|
|
|
|
Enables DDOS protection.
|
|
|
|
|
|
|
|
|
|
Imagine you have 2**32 buckets, one for each IP address. Each bucket
|
|
|
|
|
can hold about 127 tokens. Every second a background worker puts one
|
|
|
|
|
token in each bucket. When a TCP client socket is opened, it takes a
|
|
|
|
|
token from its bucket, and then proceeds. If the bucket holds only a
|
|
|
|
|
third of its original tokens, then redbean sends them a 429 warning.
|
|
|
|
|
If the client ignores this warning and keeps sending requests, until
|
|
|
|
|
there's no tokens left, then the banhammer finally comes down.
|
|
|
|
|
|
|
|
|
|
This model of network rate limiting generously lets people "burst" a
|
|
|
|
|
tiny bit. For example someone might get a strong craving for content
|
|
|
|
|
and smash the reload button in Chrome 64 times in a fow seconds. But
|
|
|
|
|
since the client only get 1 new token per second, they'd better cool
|
|
|
|
|
their heels for a few minutes after doing that. This amount of burst
|
|
|
|
|
can be altered by choosing the `reject` / `ignore` / `ban` threshold
|
|
|
|
|
arguments. For example, if the `reject` parameter is set to 126 then
|
|
|
|
|
no bursting is allowed, which probably isn't a good idea.
|
|
|
|
|
|
|
|
|
|
redbean is programmed to acquire a token immediately after accept()
|
|
|
|
|
is called from the main server process, which is well before fork()
|
|
|
|
|
or read() or any Lua code happens. redbean then takes action, based
|
|
|
|
|
on the token count, which can be accept / reject / ignore / ban. If
|
|
|
|
|
redbean determines a ban is warrented, then 4-byte datagram is sent
|
|
|
|
|
to the unix domain socket `/var/run/blackhole.sock` which should be
|
|
|
|
|
operated using the blackholed program we distribute separately.
|
|
|
|
|
|
|
|
|
|
The trick redbean uses on Linux for example is insert rules in your
|
|
|
|
|
raw prerouting table. redbean is very fast at the application layer
|
|
|
|
|
so the biggest issue we've encountered in production is are kernels
|
|
|
|
|
themselves, and programming the raw prerouting table dynamically is
|
|
|
|
|
how we solved that.
|
|
|
|
|
|
|
|
|
|
`replenish` is the number of times per second a token should be
|
|
|
|
|
added to each bucket. The default value is 1 which means one token
|
|
|
|
|
is granted per second to all buckets. The minimum value is 1/3600
|
|
|
|
|
which means once per hour. The maximum value for this setting is
|
|
|
|
|
1e6, which means once every microsecond.
|
|
|
|
|
|
|
|
|
|
`cidr` is the specificity of judgement. Since creating 2^32 buckets
|
|
|
|
|
would need 4GB of RAM, redbean defaults this value to 24 which means
|
|
|
|
|
filtering applies to class c network blocks (i.e. x.x.x.*), and your
|
|
|
|
|
token buckets only take up 2^24 bytes of RAM (16MB). This can be set
|
|
|
|
|
to any number on the inclusive interval [8,32], where having a lower
|
|
|
|
|
number means you use less ram/cpu, but splash damage applies more to
|
|
|
|
|
your clients; whereas higher numbers means more ram/cpu usage, while
|
|
|
|
|
ensuring rate limiting only applies to specific compromised actors.
|
|
|
|
|
|
|
|
|
|
`reject` is the token count or treshold at which redbean should send
|
|
|
|
|
429 Too Many Request warnings to the client. Permitted values can be
|
|
|
|
|
anywhere between -1 and 126 inclusively. The default value is 30 and
|
|
|
|
|
-1 means disable to disable (assuming AcquireToken() will be used).
|
|
|
|
|
|
|
|
|
|
`ignore` is the token count or treshold, at which redbean should try
|
|
|
|
|
simply ignoring clients and close the connection without logging any
|
|
|
|
|
kind of warning, and without sending any response. The default value
|
|
|
|
|
for this setting is `MIN(reject / 2, 15)`. This must be less than or
|
|
|
|
|
equal to the `reject` setting. Allowed values are [-1,126] where you
|
|
|
|
|
can use -1 as a means of disabling `ignore`.
|
|
|
|
|
|
|
|
|
|
`ban` is the token count at which redbean should report IP addresses
|
|
|
|
|
to the blackhole daemon via a unix-domain socket datagram so they'll
|
|
|
|
|
get banned in the kernel routing tables. redbean's default value for
|
|
|
|
|
this setting is `MIN(ignore / 10, 1)`. Permitted values are [-1,126]
|
|
|
|
|
where -1 may be used as a means of disabling the `ban` feature.
|
|
|
|
|
|
|
|
|
|
This function throws an exception if the constraints described above
|
|
|
|
|
are not the case. Warnings are logged should redbean fail to connect
|
|
|
|
|
to the blackhole daemon, assuming it hasn't been disabled. It's safe
|
|
|
|
|
to use load balancing tools when banning is enabled, since you can't
|
|
|
|
|
accidentally ban your own network interface addresses, loopback ips,
|
|
|
|
|
or ProgramTrustedIp() addresses where these rate limits don't apply.
|
|
|
|
|
|
|
|
|
|
It's assumed will be called from the .init.lua global scope although
|
|
|
|
|
it could be used in interpreter mode, or from a forked child process
|
|
|
|
|
in which case the only processes that'll have ability to use it will
|
|
|
|
|
be that same process, and any descendent processes. This function is
|
|
|
|
|
only able to be called once.
|
|
|
|
|
|
|
|
|
|
This feature is not available in unsecure mode.
|
|
|
|
|
|
|
|
|
|
AcquireToken([ip:uint32])
|
|
|
|
|
└─→ int8
|
|
|
|
|
|
|
|
|
|
Atomically acquires token.
|
|
|
|
|
|
|
|
|
|
This routine atomically acquires a single token for an `ip` address.
|
|
|
|
|
The return value is the token count before the subtraction happened.
|
|
|
|
|
No action is taken based on the count, since the caller will decide.
|
|
|
|
|
|
|
|
|
|
`ip` should be an IPv4 address and this defaults to GetClientAddr(),
|
|
|
|
|
although other interpretations of its meaning are possible.
|
|
|
|
|
|
|
|
|
|
Your token buckets are stored in shared memory so this can be called
|
|
|
|
|
from multiple forked processes. which operate on the same values.
|
|
|
|
|
|
|
|
|
|
CountTokens([ip:uint32])
|
|
|
|
|
└─→ int8
|
|
|
|
|
|
|
|
|
|
Counts number of tokens in bucket.
|
|
|
|
|
|
|
|
|
|
This function is the same as AcquireToken() except no subtraction is
|
|
|
|
|
performed, i.e. no token is taken.
|
|
|
|
|
|
|
|
|
|
`ip` should be an IPv4 address and this defaults to GetClientAddr(),
|
|
|
|
|
although other interpretations of its meaning are possible.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-24 16:59:22 +00:00
|
|
|
|
CONSTANTS
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogDebug
|
|
|
|
|
Integer for debug logging level. See Log.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogVerbose
|
|
|
|
|
Integer for verbose logging level, which is less than kLogDebug.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogInfo
|
|
|
|
|
Integer for info logging level, which is less than kLogVerbose.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogWarn
|
|
|
|
|
Integer for warn logging level, which is less than kLogVerbose.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogError
|
|
|
|
|
Integer for error logging level, which is less than kLogWarn.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
kLogFatal
|
|
|
|
|
Integer for fatal logging level, which is less than kLogError.
|
|
|
|
|
Logging anything at this level will result in a backtrace and
|
|
|
|
|
process exit.
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
LSQLITE3 MODULE
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Please refer to the LuaSQLite3 Documentation.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
For example, you could put the following in your /.init.lua file:
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
sqlite3 = require "lsqlite3"
|
|
|
|
|
db = sqlite3.open_memory()
|
|
|
|
|
db:exec[[
|
|
|
|
|
CREATE TABLE test (
|
|
|
|
|
id INTEGER PRIMARY KEY,
|
|
|
|
|
content TEXT
|
|
|
|
|
);
|
|
|
|
|
INSERT INTO test (content) VALUES ('Hello World');
|
|
|
|
|
INSERT INTO test (content) VALUES ('Hello Lua');
|
|
|
|
|
INSERT INTO test (content) VALUES ('Hello Sqlite3');
|
|
|
|
|
]]
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Then, your Lua server pages or OnHttpRequest handler may perform SQL
|
|
|
|
|
queries by accessing the db global. The performance is good too, at about
|
|
|
|
|
400k qps.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
for row in db:nrows("SELECT * FROM test") do
|
|
|
|
|
Write(row.id.." "..row.content.."<br>")
|
|
|
|
|
end
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
redbean supports a subset of what's defined in the upstream LuaSQLite3
|
|
|
|
|
project. Most of the unsupported APIs relate to pointers and database
|
|
|
|
|
notification hooks.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-07-09 00:55:35 +00:00
|
|
|
|
RE MODULE
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
This module exposes an API for POSIX regular expressions which enable you
|
|
|
|
|
to validate input, search for substrings, extract pieces of strings, etc.
|
|
|
|
|
Here's a usage example:
|
|
|
|
|
|
|
|
|
|
# Example IPv4 Address Regular Expression (see also ParseIP)
|
|
|
|
|
p = re.compile([[^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$]])
|
2022-07-09 06:06:46 +00:00
|
|
|
|
m,a,b,c,d = assert(p:search(𝑠))
|
2022-04-24 16:59:22 +00:00
|
|
|
|
if m then
|
|
|
|
|
print("ok", tonumber(a), tonumber(b), tonumber(c), tonumber(d))
|
|
|
|
|
else
|
|
|
|
|
print("not ok")
|
|
|
|
|
end
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
re.search(regex:str, text:str[, flags:int])
|
|
|
|
|
├─→ match:str[, group1:str, ...]
|
|
|
|
|
└─→ nil, re.Errno
|
|
|
|
|
|
|
|
|
|
Searches for regular expression match in text.
|
|
|
|
|
|
|
|
|
|
This is a shorthand notation roughly equivalent to:
|
|
|
|
|
|
|
|
|
|
preg = re.compile(regex)
|
|
|
|
|
patt = preg:search(re, text)
|
|
|
|
|
|
|
|
|
|
`flags` defaults to zero and may have any of:
|
|
|
|
|
|
|
|
|
|
- `re.BASIC`
|
|
|
|
|
- `re.ICASE`
|
|
|
|
|
- `re.NEWLINE`
|
|
|
|
|
- `re.NOSUB`
|
|
|
|
|
- `re.NOTBOL`
|
|
|
|
|
- `re.NOTEOL`
|
|
|
|
|
|
|
|
|
|
This has exponential complexity. Please use re.compile() to
|
|
|
|
|
compile your regular expressions once from `/.init.lua`. This
|
|
|
|
|
API exists for convenience. This isn't recommended for prod.
|
|
|
|
|
|
|
|
|
|
This uses POSIX extended syntax by default.
|
|
|
|
|
|
|
|
|
|
re.compile(regex:str[, flags:int]) → re.Regex
|
|
|
|
|
├─→ preg:re.Regex
|
|
|
|
|
└─→ nil, re.Errno
|
|
|
|
|
|
|
|
|
|
Compiles regular expression.
|
|
|
|
|
|
|
|
|
|
`flags` defaults to zero and may have any of:
|
|
|
|
|
|
|
|
|
|
- `re.BASIC`
|
|
|
|
|
- `re.ICASE`
|
|
|
|
|
- `re.NEWLINE`
|
|
|
|
|
- `re.NOSUB`
|
|
|
|
|
|
|
|
|
|
This has an O(2^𝑛) cost. Consider compiling regular
|
|
|
|
|
expressions once from your `/.init.lua` file.
|
|
|
|
|
|
|
|
|
|
If `regex` is an untrusted user value, then `unix.setrlimit`
|
|
|
|
|
should be used to impose cpu and memory quotas for security.
|
|
|
|
|
|
|
|
|
|
This uses POSIX extended syntax by default.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
RE REGEX OBJECT
|
|
|
|
|
|
|
|
|
|
re.Regex:search(text:str[, flags:int])
|
|
|
|
|
├─→ match:str[, group1:str, ...]
|
|
|
|
|
└─→ nil, re.Errno
|
|
|
|
|
|
|
|
|
|
Executes precompiled regular expression.
|
|
|
|
|
|
|
|
|
|
Returns nothing (nil) if the pattern doesn't match anything.
|
|
|
|
|
Otherwise it pushes the matched substring and any
|
|
|
|
|
parenthesis-captured values too. Flags may contain re.NOTBOL
|
|
|
|
|
or re.NOTEOL to indicate whether or not text should be
|
|
|
|
|
considered at the start and/or end of a line.
|
|
|
|
|
|
|
|
|
|
`flags` defaults to zero and may have any of:
|
|
|
|
|
|
|
|
|
|
- `re.NOTBOL`
|
|
|
|
|
- `re.NOTEOL`
|
|
|
|
|
|
|
|
|
|
This has an O(𝑛) cost.
|
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
RE ERRNO OBJECT
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
re.Errno:errno()
|
|
|
|
|
└─→ errno:int
|
|
|
|
|
|
|
|
|
|
Returns regex error number.
|
|
|
|
|
|
|
|
|
|
re.Errno:doc()
|
|
|
|
|
└─→ description:str
|
|
|
|
|
|
|
|
|
|
Returns English string describing error code.
|
|
|
|
|
|
|
|
|
|
re.Errno:__tostring()
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Delegates to re.Errno:doc()
|
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
RE ERRORS
|
|
|
|
|
|
|
|
|
|
re.NOMATCH
|
|
|
|
|
No match
|
|
|
|
|
|
|
|
|
|
re.BADPAT
|
|
|
|
|
Invalid regex
|
|
|
|
|
|
|
|
|
|
re.ECOLLATE
|
|
|
|
|
Unknown collating element
|
|
|
|
|
|
|
|
|
|
re.ECTYPE
|
|
|
|
|
Unknown character class name
|
|
|
|
|
|
|
|
|
|
re.EESCAPE
|
|
|
|
|
Trailing backslash
|
|
|
|
|
|
|
|
|
|
re.ESUBREG
|
|
|
|
|
Invalid back reference
|
|
|
|
|
|
|
|
|
|
re.EBRACK
|
|
|
|
|
Missing `]`
|
|
|
|
|
|
|
|
|
|
re.EPAREN
|
|
|
|
|
Missing `)`
|
|
|
|
|
|
|
|
|
|
re.EBRACE
|
|
|
|
|
Missing `}`
|
|
|
|
|
|
|
|
|
|
re.BADBR
|
|
|
|
|
Invalid contents of `{}`
|
|
|
|
|
|
|
|
|
|
re.ERANGE
|
|
|
|
|
Invalid character range.
|
|
|
|
|
|
|
|
|
|
re.ESPACE
|
|
|
|
|
Out of memory
|
|
|
|
|
|
|
|
|
|
re.BADRPT
|
|
|
|
|
Repetition not preceded by valid expression
|
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
RE FLAGS
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
re.BASIC
|
|
|
|
|
Use this flag if you prefer the default POSIX regex syntax. We use
|
|
|
|
|
extended regex notation by default. For example, an extended
|
|
|
|
|
regular expression for matching an IP address might look like
|
|
|
|
|
([0-9]*)\.([0-9]*)\.([0-9]*)\.([0-9]*) whereas with basic syntax
|
|
|
|
|
it would look like \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).
|
|
|
|
|
This flag may only be used with re.compile and re.search.
|
|
|
|
|
|
|
|
|
|
re.ICASE
|
|
|
|
|
Use this flag to make your pattern case ASCII case-insensitive.
|
|
|
|
|
This means [a-z] will mean the same thing as [A-Za-z]. This flag
|
|
|
|
|
may only be used with re.compile and re.search.
|
|
|
|
|
|
|
|
|
|
re.NEWLINE
|
2022-07-09 06:06:46 +00:00
|
|
|
|
Use this flag to change the handling of NEWLINE (\x0a)
|
|
|
|
|
characters. When this flag is set, (1) a NEWLINE shall not be
|
|
|
|
|
matched by a "." or any form of a non-matching list, (2) a "^"
|
|
|
|
|
shall match the zero-length string immediately after a NEWLINE
|
|
|
|
|
(regardless of re.NOTBOL), and (3) a "$" shall match the
|
|
|
|
|
zero-length string immediately before a NEWLINE (regardless of
|
|
|
|
|
re.NOTEOL).
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
re.NOSUB
|
|
|
|
|
Causes re.search to only report success and failure. This is
|
2022-07-09 06:06:46 +00:00
|
|
|
|
reported via the API by returning empty string for success.
|
|
|
|
|
This flag may only be used with re.compile and re.search.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
re.NOTBOL
|
2022-07-09 06:06:46 +00:00
|
|
|
|
The first character of the string pointed to by string is not
|
|
|
|
|
the beginning of the line. This flag may only be used with
|
|
|
|
|
re.search and re.Regex:search.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
re.NOTEOL
|
2022-07-09 06:06:46 +00:00
|
|
|
|
The last character of the string pointed to by string is not
|
|
|
|
|
the end of the line. This flag may only be used with re.search
|
|
|
|
|
and re.Regex:search.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
PATH MODULE
|
|
|
|
|
|
|
|
|
|
The path module may be used to manipulate unix paths.
|
|
|
|
|
|
|
|
|
|
Note that we use unix paths on Windows. For example, if you have a
|
|
|
|
|
path like C:\foo\bar then it should be /c/foo/bar with redbean. It
|
|
|
|
|
should also be noted the unix module is more permissive when using
|
|
|
|
|
Windows paths, where translation to win32 is very light.
|
|
|
|
|
|
|
|
|
|
path.dirname(str)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Strips final component of path, e.g.
|
|
|
|
|
|
|
|
|
|
path │ dirname
|
|
|
|
|
───────────────────
|
|
|
|
|
. │ .
|
|
|
|
|
.. │ .
|
|
|
|
|
/ │ /
|
|
|
|
|
usr │ .
|
|
|
|
|
/usr/ │ /
|
|
|
|
|
/usr/lib │ /usr
|
|
|
|
|
/usr/lib/ │ /usr
|
|
|
|
|
|
|
|
|
|
path.basename(path:str)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Returns final component of path, e.g.
|
|
|
|
|
|
|
|
|
|
path │ basename
|
|
|
|
|
─────────────────────
|
|
|
|
|
. │ .
|
|
|
|
|
.. │ ..
|
|
|
|
|
/ │ /
|
|
|
|
|
usr │ usr
|
|
|
|
|
/usr/ │ usr
|
|
|
|
|
/usr/lib │ lib
|
|
|
|
|
/usr/lib/ │ lib
|
|
|
|
|
|
|
|
|
|
path.join(str, ...)
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Concatenates path components, e.g.
|
|
|
|
|
|
|
|
|
|
x │ y │ joined
|
|
|
|
|
─────────────────────────────────
|
|
|
|
|
/ │ / │ /
|
|
|
|
|
/usr │ lib │ /usr/lib
|
|
|
|
|
/usr/ │ lib │ /usr/lib
|
|
|
|
|
/usr/lib │ /lib │ /lib
|
|
|
|
|
|
|
|
|
|
You may specify 1+ arguments.
|
|
|
|
|
|
|
|
|
|
Specifying no arguments will raise an error. If nil arguments are
|
|
|
|
|
specified, then they're skipped over. If exclusively nil arguments
|
|
|
|
|
are passed, then nil is returned. Empty strings behave similarly to
|
|
|
|
|
nil, but unlike nil may coerce a trailing slash.
|
|
|
|
|
|
|
|
|
|
path.exists(path:str)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if path exists.
|
|
|
|
|
|
|
|
|
|
This function is inclusive of regular files, directories, and
|
|
|
|
|
special files. Symbolic links are followed are resolved. On error,
|
|
|
|
|
false is returned.
|
|
|
|
|
|
|
|
|
|
path.isfile(path:str)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if path exists and is regular file.
|
|
|
|
|
|
|
|
|
|
Symbolic links are not followed. On error, false is returned.
|
|
|
|
|
|
|
|
|
|
path.isdir(path:str)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if path exists and is directory.
|
|
|
|
|
|
|
|
|
|
Symbolic links are not followed. On error, false is returned.
|
|
|
|
|
|
|
|
|
|
path.islink(path:str)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if path exists and is symbolic link.
|
|
|
|
|
|
|
|
|
|
Symbolic links are not followed. On error, false is returned.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-03-18 10:17:08 +00:00
|
|
|
|
MAXMIND MODULE
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
This module may be used to get city/country/asn/etc from IPs, e.g.
|
2022-03-18 10:17:08 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
-- .init.lua
|
2022-04-29 15:19:09 +00:00
|
|
|
|
maxmind = require 'maxmind'
|
2022-04-24 16:59:22 +00:00
|
|
|
|
asndb = maxmind.open('/usr/local/share/maxmind/GeoLite2-ASN.mmdb')
|
2022-03-18 10:17:08 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
-- request handler
|
|
|
|
|
as = asndb:lookup(GetRemoteAddr())
|
|
|
|
|
if as then
|
2022-04-29 15:19:09 +00:00
|
|
|
|
asnum = as:get('autonomous_system_number')
|
|
|
|
|
asorg = as:get('autonomous_system_organization')
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Write(EscapeHtml(asnum))
|
|
|
|
|
Write(' ')
|
|
|
|
|
Write(EscapeHtml(asorg))
|
|
|
|
|
end
|
2022-03-18 10:17:08 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
For further details, please see maxmind.lua in redbean-demo.com.
|
2022-03-18 10:17:08 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
|
2022-07-17 09:40:39 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
FINGER MODULE
|
|
|
|
|
|
|
|
|
|
This is an experimental module that, like the maxmind module, gives
|
|
|
|
|
you insight into what kind of device is connecting to your redbean.
|
|
|
|
|
This module can help you protect your redbean because it provides
|
|
|
|
|
tools for identifying clients that misrepresent themselves. For
|
|
|
|
|
example the User-Agent header might report itself as a Windows
|
|
|
|
|
computer when the SYN packet says it's a Linux computer.
|
|
|
|
|
|
|
|
|
|
function OnServerListen(fd, ip, port)
|
|
|
|
|
unix.setsockopt(fd, unix.SOL_TCP, unix.TCP_SAVE_SYN, true)
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OnClientConnection(ip, port, serverip, serverport)
|
|
|
|
|
fd = GetClientFd()
|
|
|
|
|
syn = unix.getsockopt(fd, unix.SOL_TCP, unix.TCP_SAVED_SYN)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function OnHttpRequest()
|
|
|
|
|
Log(kLogInfo, "client is running %s and reports %s" % {
|
|
|
|
|
finger.GetSynFingerOs(finger.FingerSyn(syn)),
|
|
|
|
|
GetHeader('User-Agent')})
|
|
|
|
|
Route()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
The following functions are provided.
|
|
|
|
|
|
|
|
|
|
finger.FingerSyn(syn_packet_bytes:str)
|
|
|
|
|
├─→ synfinger:uint32
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Fingerprints IP+TCP SYN packet.
|
|
|
|
|
|
|
|
|
|
This returns a hash-like magic number that reflects the SYN packet
|
|
|
|
|
structure, e.g. ordering of options, maximum segment size, etc. We
|
|
|
|
|
make no guarantees this hashing algorithm won't change as we learn
|
|
|
|
|
more about the optimal way to fingerprint, so be sure to save your
|
|
|
|
|
syn packets too if you're using this feature, in case they need to
|
|
|
|
|
be rehashed in the future.
|
|
|
|
|
|
|
|
|
|
This function is nil/error propagating.
|
|
|
|
|
|
|
|
|
|
finger.GetSynFingerOs(synfinger:uint32)
|
|
|
|
|
├─→ osname:str
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Fingerprints IP+TCP SYN packet.
|
|
|
|
|
|
|
|
|
|
If `synfinger` is a known hard-coded magic number, then one of the
|
|
|
|
|
following strings may be returned:
|
|
|
|
|
|
|
|
|
|
- `"LINUX"`
|
|
|
|
|
- `"WINDOWS"`
|
|
|
|
|
- `"XNU"`
|
|
|
|
|
- `"NETBSD"`
|
|
|
|
|
- `"FREEBSD"`
|
|
|
|
|
- `"OPENBSD"`
|
|
|
|
|
|
|
|
|
|
If this function returns nil, then one thing you can do to help is
|
|
|
|
|
file an issue and share with us your SYN packet specimens. The way
|
|
|
|
|
we prefer to receive them is in EncodeLua(syn_packet_bytes) format
|
|
|
|
|
along with details on the operating system which you must know.
|
|
|
|
|
|
|
|
|
|
finger.DescribeSyn(syn_packet_bytes:str)
|
|
|
|
|
├─→ description:str
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Describes IP+TCP SYN packet.
|
|
|
|
|
|
|
|
|
|
The layout looks as follows:
|
|
|
|
|
|
|
|
|
|
TTL:OPTIONS:WSIZE:MSS
|
|
|
|
|
|
|
|
|
|
The `TTL`, `WSIZE`, and `MSS` fields are unsigned decimal fields.
|
|
|
|
|
|
|
|
|
|
The `OPTIONS` field communicates the ordering of the commonly used
|
|
|
|
|
subset of tcp options. The following character mappings are defined.
|
|
|
|
|
TCP options not on this list will be ignored.
|
|
|
|
|
|
|
|
|
|
- E: End of Option list
|
|
|
|
|
- N: No-Operation
|
|
|
|
|
- M: Maxmimum Segment Size
|
|
|
|
|
- K: Window Scale
|
|
|
|
|
- O: SACK Permitted
|
|
|
|
|
- A: SACK
|
|
|
|
|
- e: Echo (obsolete)
|
|
|
|
|
- r: Echo reply (obsolete)
|
|
|
|
|
- T: Timestamps
|
|
|
|
|
|
|
|
|
|
This function is nil/error propagating.
|
|
|
|
|
|
|
|
|
|
|
2022-05-27 20:25:46 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
ARGON2 MODULE
|
|
|
|
|
|
2022-07-16 18:00:28 +00:00
|
|
|
|
This module implements a password hashing algorithm based on blake2b
|
2022-05-27 20:25:46 +00:00
|
|
|
|
that won the Password Hashing Competition.
|
|
|
|
|
|
|
|
|
|
It can be used to securely store user passwords in your SQLite
|
|
|
|
|
database, in a way that destroys the password, but can be verified by
|
|
|
|
|
regenerating the hash again the next time the user logs in. Destroying
|
|
|
|
|
the password is important, since if your database is compromised, the
|
|
|
|
|
bad guys won't be able to use rainbow tables to recover the plain text
|
|
|
|
|
of the passwords.
|
|
|
|
|
|
|
|
|
|
Argon2 achieves this security by being expensive to compute. Care
|
|
|
|
|
should be taken in choosing parameters, since an HTTP endpoint that
|
|
|
|
|
uses Argon2 can just as easily become a denial of service vector. For
|
|
|
|
|
example, you may want to consider throttling your login endpoint.
|
|
|
|
|
|
|
|
|
|
argon2.hash_encoded(pass:str, salt:int[, config:table])
|
|
|
|
|
├─→ ascii:str
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Hashes password.
|
|
|
|
|
|
|
|
|
|
This is consistent with the README of the reference implementation:
|
|
|
|
|
|
|
|
|
|
>: assert(argon2.hash_encoded("password", "somesalt", {
|
|
|
|
|
variant = argon2.variants.argon2_i,
|
|
|
|
|
m_cost = 65536,
|
|
|
|
|
hash_len = 24,
|
|
|
|
|
parallelism = 4,
|
|
|
|
|
t_cost = 2,
|
|
|
|
|
}))
|
|
|
|
|
"$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG"
|
|
|
|
|
|
|
|
|
|
`pass` is the secret value to be encoded.
|
|
|
|
|
|
|
|
|
|
`salt` is a nonce value used to hash the string.
|
|
|
|
|
|
|
|
|
|
`config.m_cost` is the memory hardness in kibibytes, which defaults
|
|
|
|
|
to 4096 (4 mibibytes). It's recommended that this be tuned upwards.
|
|
|
|
|
|
|
|
|
|
`config.t_cost` is the number of iterations, which defaults to 3.
|
|
|
|
|
|
|
|
|
|
`config.parallelism` is the parallelism factor, which defaults to 1.
|
|
|
|
|
|
|
|
|
|
`config.hash_len` is the number of desired bytes in hash output,
|
|
|
|
|
which defaults to 32.
|
|
|
|
|
|
|
|
|
|
`config.variant` may be:
|
|
|
|
|
|
|
|
|
|
- `argon2.variants.argon2_id` blend of other two methods [default]
|
|
|
|
|
- `argon2.variants.argon2_i` maximize resistance to side-channel attacks
|
|
|
|
|
- `argon2.variants.argon2_d` maximize resistance to gpu cracking attacks
|
|
|
|
|
|
|
|
|
|
argon2.verify(encoded:str, pass:str)
|
|
|
|
|
├─→ ok:bool
|
|
|
|
|
└─→ nil, error:str
|
|
|
|
|
|
|
|
|
|
Verifies password, e.g.
|
|
|
|
|
|
|
|
|
|
>: argon2.verify(
|
|
|
|
|
"$argon2i$v=19$m=65536,t=2," ..
|
|
|
|
|
"p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG",
|
|
|
|
|
"password")
|
|
|
|
|
true
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-13 15:49:17 +00:00
|
|
|
|
UNIX MODULE
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This module exposes the low-level System Five system call interface.
|
|
|
|
|
This module works on all supported platforms, including Windows NT.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.open(path:str, flags:int[, mode:int[, dirfd:int]])
|
|
|
|
|
├─→ fd:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
Opens file.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
Returns a file descriptor integer that needs to be closed, e.g.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-29 15:19:09 +00:00
|
|
|
|
fd = assert(unix.open("/etc/passwd", unix.O_RDONLY))
|
2022-04-25 15:30:14 +00:00
|
|
|
|
print(unix.read(fd))
|
|
|
|
|
unix.close(fd)
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
`flags` should have one of:
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-12 16:43:01 +00:00
|
|
|
|
- `O_RDONLY`: open for reading (default)
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `O_WRONLY`: open for writing
|
|
|
|
|
- `O_RDWR`: open for reading and writing
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
The following values may also be OR'd into `flags`:
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-27 12:39:39 +00:00
|
|
|
|
- `O_CREAT` create file if it doesn't exist
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_TRUNC` automatic ftruncate(fd,0) if exists
|
2022-04-27 12:39:39 +00:00
|
|
|
|
- `O_CLOEXEC` automatic close() upon execve()
|
|
|
|
|
- `O_EXCL` exclusive access (see below)
|
|
|
|
|
- `O_APPEND` open file for append only
|
|
|
|
|
- `O_NONBLOCK` asks read/write to fail with EAGAIN rather than block
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_DIRECT` it's complicated (not supported on Apple and OpenBSD)
|
|
|
|
|
- `O_DIRECTORY` useful for stat'ing (hint on UNIX but required on NT)
|
|
|
|
|
- `O_NOFOLLOW` fail if it's a symlink (zero on Windows)
|
|
|
|
|
- `O_DSYNC` it's complicated (zero on non-Linux/Apple)
|
|
|
|
|
- `O_RSYNC` it's complicated (zero on non-Linux/Apple)
|
|
|
|
|
- `O_PATH` it's complicated (zero on non-Linux)
|
|
|
|
|
- `O_VERIFY` it's complicated (zero on non-FreeBSD)
|
|
|
|
|
- `O_SHLOCK` it's complicated (zero on non-BSD)
|
|
|
|
|
- `O_EXLOCK` it's complicated (zero on non-BSD)
|
2022-04-26 04:16:05 +00:00
|
|
|
|
- `O_NOATIME` don't record access time (zero on non-Linux)
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_RANDOM` hint random access intent (zero on non-Windows)
|
|
|
|
|
- `O_SEQUENTIAL` hint sequential access intent (zero on non-Windows)
|
|
|
|
|
- `O_COMPRESSED` ask fs to abstract compression (zero on non-Windows)
|
|
|
|
|
- `O_INDEXED` turns on that slow performance (zero on non-Windows)
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
There are three regular combinations for the above flags:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_RDONLY`: Opens existing file for reading. If it doesn't
|
|
|
|
|
exist then nil is returned and errno will be `ENOENT` (or in
|
|
|
|
|
some other cases `ENOTDIR`).
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_WRONLY|O_CREAT|O_TRUNC`: Creates file. If it already
|
|
|
|
|
exists, then the existing copy is destroyed and the opened
|
|
|
|
|
file will start off with a length of zero. This is the
|
|
|
|
|
behavior of the traditional creat() system call.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
- `O_WRONLY|O_CREAT|O_EXCL`: Create file only if doesn't exist
|
|
|
|
|
already. If it does exist then `nil` is returned along with
|
|
|
|
|
`errno` set to `EEXIST`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
`dirfd` defaults to to `unix.AT_FDCWD` and may optionally be set to
|
|
|
|
|
a directory file descriptor to which `path` is relative.
|
|
|
|
|
|
|
|
|
|
Returns `ENOENT` if `path` doesn't exist.
|
|
|
|
|
|
|
|
|
|
Returns `ENOTDIR` if `path` contained a directory component that
|
|
|
|
|
wasn't a directory.
|
|
|
|
|
|
|
|
|
|
unix.close(fd:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
Closes file descriptor.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
This function should never be called twice for the same file
|
|
|
|
|
descriptor, regardless of whether or not an error happened. The file
|
|
|
|
|
descriptor is always gone after close is called. So it technically
|
|
|
|
|
always succeeds, but that doesn't mean an error should be ignored.
|
|
|
|
|
For example, on NFS a close failure could indicate data loss.
|
|
|
|
|
|
|
|
|
|
Closing does not mean that scheduled i/o operations have been
|
|
|
|
|
completed. You'd need to use fsync() or fdatasync() beforehand to
|
|
|
|
|
ensure that. You shouldn't need to do that normally, because our
|
|
|
|
|
close implementation guarantees a consistent view, since on systems
|
|
|
|
|
where it isn't guaranteed (like Windows) close will implicitly sync.
|
|
|
|
|
|
|
|
|
|
File descriptors are automatically closed on exit().
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` wasn't valid.
|
|
|
|
|
|
|
|
|
|
Returns `EINTR` possibly maybe.
|
|
|
|
|
|
|
|
|
|
Returns `EIO` if an i/o error occurred.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.read(fd:int[, bufsiz:str[, offset:int]])
|
|
|
|
|
├─→ data:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
|
|
|
|
Reads from file descriptor.
|
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
This function returns empty string on end of file. The exception is
|
|
|
|
|
if `bufsiz` is zero, in which case an empty returned string means
|
|
|
|
|
the file descriptor works.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.write(fd:int, data:str[, offset:int])
|
|
|
|
|
├─→ wrotebytes:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
|
|
|
|
Writes to file descriptor.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.exit([exitcode:int])
|
|
|
|
|
└─→ ⊥
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Invokes `_Exit(exitcode)` on the process. This will immediately
|
|
|
|
|
halt the current process. Memory will be freed. File descriptors
|
|
|
|
|
will be closed. Any open connections it owns will be reset. This
|
|
|
|
|
function never returns.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.environ()
|
|
|
|
|
└─→ {str,...}
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Returns raw environment variables.
|
|
|
|
|
|
|
|
|
|
This allocates and constructs the C/C++ `environ` variable as a Lua
|
|
|
|
|
table consisting of string keys and string values.
|
|
|
|
|
|
|
|
|
|
This data structure preserves casing. On Windows NT, by convention,
|
|
|
|
|
environment variable keys are treated in a case-insensitive way. It
|
|
|
|
|
is the responsibility of the caller to consider this.
|
|
|
|
|
|
|
|
|
|
This data structure preserves valueless variables. It's possible on
|
|
|
|
|
both UNIX and Windows to have an environment variable without an
|
|
|
|
|
equals, even though it's unusual.
|
|
|
|
|
|
|
|
|
|
This data structure preserves duplicates. For example, on Windows,
|
|
|
|
|
there's some irregular uses of environment variables such as how the
|
|
|
|
|
command prompt inserts multiple environment variables with empty
|
|
|
|
|
string as keys, for its internal bookkeeping.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.fork()
|
|
|
|
|
├─┬─→ 0
|
|
|
|
|
│ └─→ childpid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Creates a new process mitosis style.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
This system call returns twice. The parent process gets the nonzero
|
|
|
|
|
pid. The child gets zero.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-07-11 12:55:17 +00:00
|
|
|
|
Here's a simple usage example of creating subprocesses, where we
|
|
|
|
|
fork off a child worker from a main process hook callback to do some
|
|
|
|
|
independent chores, such as sending an HTTP request back to redbean.
|
|
|
|
|
|
|
|
|
|
-- as soon as server starts, make a fetch to the server
|
|
|
|
|
-- then signal redbean to shutdown when fetch is complete
|
|
|
|
|
local onServerStart = function()
|
|
|
|
|
if assert(unix.fork()) == 0 then
|
|
|
|
|
local ok, headers, body = Fetch('http://127.0.0.1:8080/test')
|
|
|
|
|
unix.kill(unix.getppid(), unix.SIGTERM)
|
|
|
|
|
unix.exit(0)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
OnServerStart = onServerStart
|
|
|
|
|
|
|
|
|
|
We didn't need to use wait() here, because (a) we want redbean to go
|
|
|
|
|
back to what it was doing before as the Fetch() completes, and (b)
|
|
|
|
|
redbean's main process already has a zombie collector. However it's
|
|
|
|
|
a moot point, since once the fetch is done, the child process then
|
|
|
|
|
asks redbean to gracefully shutdown by sending SIGTERM its parent.
|
|
|
|
|
|
|
|
|
|
This is actually a situation where we *must* use fork, because the
|
|
|
|
|
purpose of the main redbean process is to call accept() and create
|
|
|
|
|
workers. So if we programmed redbean to use the main process to send
|
|
|
|
|
a blocking request to itself instead, then redbean would deadlock
|
|
|
|
|
and never be able to accept() the client.
|
|
|
|
|
|
|
|
|
|
While deadlocking is an extreme example, the truth is that latency
|
|
|
|
|
issues can crop up for the same reason that just cause jitter
|
|
|
|
|
instead, and as such, can easily go unnoticed. For example, if you
|
|
|
|
|
do something that takes longer than a few milliseconds from inside
|
|
|
|
|
your redbean heartbeat, then that's a few milliseconds in which
|
|
|
|
|
redbean is no longer concurrent, and tail latency is being added to
|
|
|
|
|
its ability to accept new connections. fork() does a great job at
|
|
|
|
|
solving this.
|
|
|
|
|
|
|
|
|
|
If you're not sure how long something will take, then when in doubt,
|
|
|
|
|
fork off a process. You can then report its completion to something
|
|
|
|
|
like SQLite. Redbean makes having lots of processes cheap. On Linux
|
|
|
|
|
they're about as lightweight as what heavyweight environments call
|
|
|
|
|
greenlets. You can easily have 10,000 Redbean workers on one PC.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Here's some benchmarks for fork() performance across platforms:
|
|
|
|
|
|
|
|
|
|
Linux 5.4 fork l: 97,200𝑐 31,395𝑛𝑠 [metal]
|
|
|
|
|
FreeBSD 12 fork l: 236,089𝑐 78,841𝑛𝑠 [vmware]
|
|
|
|
|
Darwin 20.6 fork l: 295,325𝑐 81,738𝑛𝑠 [metal]
|
|
|
|
|
NetBSD 9 fork l: 5,832,027𝑐 1,947,899𝑛𝑠 [vmware]
|
|
|
|
|
OpenBSD 6.8 fork l: 13,241,940𝑐 4,422,103𝑛𝑠 [vmware]
|
|
|
|
|
Windows10 fork l: 18,802,239𝑐 6,360,271𝑛𝑠 [metal]
|
|
|
|
|
|
|
|
|
|
One of the benefits of using fork() is it creates an isolation
|
|
|
|
|
barrier between the different parts of your app. This can lead to
|
|
|
|
|
enhanced reliability and security. For example, redbean uses fork so
|
|
|
|
|
it can wipe your ssl keys from memory before handing over control to
|
|
|
|
|
request handlers that process untrusted input. It also ensures that
|
|
|
|
|
if your Lua app crashes, it won't take down the server as a whole.
|
|
|
|
|
Hence it should come as no surprise that fork() would go slower on
|
|
|
|
|
operating systems that have more security features. So depending on
|
|
|
|
|
your use case, you can choose the operating system that suits you.
|
|
|
|
|
|
|
|
|
|
unix.commandv(prog:str)
|
|
|
|
|
├─→ path:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
|
|
|
|
Performs `$PATH` lookup of executable.
|
|
|
|
|
|
2022-04-29 15:19:09 +00:00
|
|
|
|
unix = require 'unix'
|
|
|
|
|
prog = assert(unix.commandv('ls'))
|
|
|
|
|
unix.execve(prog, {prog, '-hal', '.'}, {'PATH=/bin'})
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.exit(127)
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
We automatically suffix `.com` and `.exe` for all platforms when
|
|
|
|
|
path searching. By default, the current directory is not on the
|
|
|
|
|
path. If `prog` is an absolute path, then it's returned as-is. If
|
|
|
|
|
`prog` contains slashes then it's not path searched either and will
|
|
|
|
|
be returned if it exists.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.execve(prog:str[, args:List<*>, env:List<*>])
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
Exits current process, replacing it with a new instance of the
|
|
|
|
|
specified program. `prog` needs to be an absolute path, see
|
|
|
|
|
commandv(). `env` defaults to to the current `environ`. Here's
|
|
|
|
|
a basic usage example:
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
unix.execve("/bin/ls", {"/bin/ls", "-hal"}, {"PATH=/bin"})
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.exit(127)
|
|
|
|
|
|
|
|
|
|
`prog` needs to be the resolved pathname of your executable. You
|
|
|
|
|
can use commandv() to search your `PATH`.
|
|
|
|
|
|
|
|
|
|
`args` is a string list table. The first element in `args`
|
|
|
|
|
should be `prog`. Values are coerced to strings. This parameter
|
|
|
|
|
defaults to `{prog}`.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`env` is a string list table. Values are coerced to strings. No
|
|
|
|
|
ordering requirement is imposed. By convention, each string has its
|
|
|
|
|
key and value divided by an equals sign without spaces. If this
|
2022-07-16 18:00:28 +00:00
|
|
|
|
parameter is not specified, it'll default to the C/C++ `environ`
|
2022-04-24 16:59:22 +00:00
|
|
|
|
variable which is inherited from the shell that launched redbean.
|
|
|
|
|
It's the responsibility of the user to supply a sanitized environ
|
|
|
|
|
when spawning untrusted processes.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
execve() is normally called after fork() returns 0. If that isn't
|
|
|
|
|
the case, then your redbean worker will be destroyed.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
This function never returns on success.
|
|
|
|
|
|
|
|
|
|
`EAGAIN` is returned if you've enforced a max number of
|
|
|
|
|
processes using `setrlimit(RLIMIT_NPROC)`.
|
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
unix.dup(oldfd:int[, newfd:int[, flags:int[, lowest:int]]])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ newfd:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
Duplicates file descriptor.
|
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
`newfd` may be specified to choose a specific number for the new
|
|
|
|
|
file descriptor. If it's already open, then the preexisting one will
|
|
|
|
|
be silently closed. `EINVAL` is returned if `newfd` equals `oldfd`.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
`flags` can have `O_CLOEXEC` which means the returned file
|
|
|
|
|
descriptors will be automatically closed upon execve().
|
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
`lowest` defaults to zero and defines the lowest numbered file
|
|
|
|
|
descriptor that's acceptable to use. If `newfd` is specified then
|
|
|
|
|
`lowest` is ignored. For example, if you wanted to duplicate
|
|
|
|
|
standard input, then:
|
|
|
|
|
|
|
|
|
|
stdin2 = assert(unix.dup(0, nil, unix.O_CLOEXEC, 3))
|
|
|
|
|
|
|
|
|
|
Will ensure that, in the rare event standard output or standard
|
|
|
|
|
error are closed, you won't accidentally duplicate standard input to
|
|
|
|
|
those numbers.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.pipe([flags:int])
|
|
|
|
|
├─→ reader:int, writer:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
Creates fifo which enables communication between processes.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
- `O_CLOEXEC`: Automatically close file descriptor upon execve()
|
|
|
|
|
|
2022-04-27 12:39:39 +00:00
|
|
|
|
- `O_NONBLOCK`: Request `EAGAIN` be raised rather than blocking
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
- `O_DIRECT`: Enable packet mode w/ atomic reads and writes, so long
|
|
|
|
|
as they're no larger than `PIPE_BUF` (guaranteed to be 512+ bytes)
|
|
|
|
|
with support limited to Linux, Windows NT, FreeBSD, and NetBSD.
|
|
|
|
|
|
|
|
|
|
Returns two file descriptors: one for reading and one for writing.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Here's an example of how pipe(), fork(), dup(), etc. may be used
|
|
|
|
|
to serve an HTTP response containing the output of a subprocess.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
local unix = require "unix"
|
2022-04-26 04:16:05 +00:00
|
|
|
|
ls = assert(unix.commandv("ls"))
|
|
|
|
|
reader, writer = assert(unix.pipe())
|
|
|
|
|
if assert(unix.fork()) == 0 then
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.close(1)
|
|
|
|
|
unix.dup(writer)
|
|
|
|
|
unix.close(writer)
|
|
|
|
|
unix.close(reader)
|
|
|
|
|
unix.execve(ls, {ls, "-Shal"})
|
|
|
|
|
unix.exit(127)
|
|
|
|
|
else
|
|
|
|
|
unix.close(writer)
|
|
|
|
|
SetHeader('Content-Type', 'text/plain')
|
|
|
|
|
while true do
|
2022-04-26 04:16:05 +00:00
|
|
|
|
data, err = unix.read(reader)
|
|
|
|
|
if data then
|
|
|
|
|
if data ~= "" then
|
|
|
|
|
Write(data)
|
|
|
|
|
else
|
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
elseif err:errno() ~= EINTR then
|
|
|
|
|
Log(kLogWarn, tostring(err))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-26 04:16:05 +00:00
|
|
|
|
assert(unix.close(reader))
|
|
|
|
|
assert(unix.wait())
|
2022-04-21 16:15:36 +00:00
|
|
|
|
end
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.wait([pid:int[, options:int]])
|
|
|
|
|
├─→ pid:int, wstatus:int, unix.Rusage
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Waits for subprocess to terminate.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
`pid` defaults to `-1` which means any child process. Setting
|
|
|
|
|
`pid` to `0` is equivalent to `-getpid()`. If `pid < -1` then
|
|
|
|
|
that means wait for any pid in the process group `-pid`. Then
|
|
|
|
|
lastly if `pid > 0` then this waits for a specific process id
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Options may have `WNOHANG` which means don't block, check for
|
|
|
|
|
the existence of processes that are already dead (technically
|
|
|
|
|
speaking zombies) and if so harvest them immediately.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns the process id of the child that terminated. In other
|
|
|
|
|
cases, the returned `pid` is nil and `errno` is non-nil.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
The returned `wstatus` contains information about the process
|
|
|
|
|
exit status. It's a complicated integer and there's functions
|
|
|
|
|
that can help interpret it. For example:
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
-- wait for zombies
|
|
|
|
|
-- traditional technique for SIGCHLD handlers
|
|
|
|
|
while true do
|
2022-04-26 04:16:05 +00:00
|
|
|
|
pid, status = unix.wait(-1, unix.WNOHANG)
|
2022-04-21 16:15:36 +00:00
|
|
|
|
if pid then
|
2022-04-26 04:16:05 +00:00
|
|
|
|
if unix.WIFEXITED(status) then
|
2022-04-21 16:15:36 +00:00
|
|
|
|
print('child', pid, 'exited with',
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.WEXITSTATUS(status))
|
|
|
|
|
elseif unix.WIFSIGNALED(status) then
|
2022-04-21 16:15:36 +00:00
|
|
|
|
print('child', pid, 'crashed with',
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.strsignal(unix.WTERMSIG(status)))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
end
|
2022-04-26 04:16:05 +00:00
|
|
|
|
elseif status:errno() == unix.ECHILD then
|
|
|
|
|
Log(kLogDebug, 'no more zombies')
|
2022-04-21 16:15:36 +00:00
|
|
|
|
break
|
2022-04-26 04:16:05 +00:00
|
|
|
|
else
|
|
|
|
|
Log(kLogWarn, tostring(err))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
break
|
|
|
|
|
end
|
|
|
|
|
end
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-29 13:06:23 +00:00
|
|
|
|
unix.WIFEXITED(wstatus:int)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if process exited cleanly.
|
|
|
|
|
|
|
|
|
|
unix.WEXITSTATUS(wstatus:int)
|
|
|
|
|
└─→ exitcode:uint8
|
|
|
|
|
|
|
|
|
|
Returns code passed to exit() assuming `WIFEXITED(wstatus)` is true.
|
|
|
|
|
|
|
|
|
|
unix.WIFSIGNALED(wstatus:int)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if process terminated due to a signal.
|
|
|
|
|
|
|
|
|
|
unix.WTERMSIG(wstatus:int)
|
|
|
|
|
└─→ sig:uint8
|
|
|
|
|
|
|
|
|
|
Returns signal that caused process to terminate assuming
|
|
|
|
|
`WIFSIGNALED(wstatus)` is true.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getpid()
|
|
|
|
|
└─→ pid:int
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns process id of current process.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getppid()
|
|
|
|
|
└─→ pid:int
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns process id of parent process.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.kill(pid:int, sig:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Sends signal to process(es).
|
|
|
|
|
|
|
|
|
|
The impact of this action can be terminating the process, or
|
|
|
|
|
interrupting it to request something happen.
|
|
|
|
|
|
|
|
|
|
`pid` can be:
|
|
|
|
|
|
|
|
|
|
- `pid > 0` signals one process by id
|
|
|
|
|
- `== 0` signals all processes in current process group
|
|
|
|
|
- `-1` signals all processes possible (except init)
|
|
|
|
|
- `< -1` signals all processes in -pid process group
|
|
|
|
|
|
|
|
|
|
`sig` can be:
|
|
|
|
|
|
|
|
|
|
- `0` checks both if pid exists and we can signal it
|
|
|
|
|
- `SIGINT` sends ctrl-c keyboard interrupt
|
|
|
|
|
- `SIGQUIT` sends backtrace and exit signal
|
|
|
|
|
- `SIGTERM` sends shutdown signal
|
|
|
|
|
- etc.
|
|
|
|
|
|
|
|
|
|
Windows NT only supports the kill() signals required by the ANSI C89
|
|
|
|
|
standard, which are `SIGINT` and `SIGQUIT`. All other signals on the
|
|
|
|
|
Windows platform that are sent to another process via kill() will be
|
|
|
|
|
treated like `SIGKILL`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.raise(sig:int)
|
|
|
|
|
├─→ rc:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Triggers signal in current process.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
This is pretty much the same as `kill(getpid(), sig)`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.access(path:str, how:int[, flags:int[, dirfd:int]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Checks if effective user of current process has permission to access
|
|
|
|
|
file. `how` can be `R_OK`, `W_OK`, `X_OK`, or `F_OK` to check for
|
|
|
|
|
read, write, execute, and existence respectively.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
`flags` may have any of:
|
|
|
|
|
|
|
|
|
|
- `AT_SYMLINK_NOFOLLOW`: do not follow symbolic links.
|
|
|
|
|
|
|
|
|
|
unix.mkdir(path:str[, mode:int[, dirfd:int]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Makes directory.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`path` is the path of the directory you wish to create.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`mode` is octal permission bits, e.g. `0755`.
|
|
|
|
|
|
|
|
|
|
Fails with `EEXIST` if `path` already exists, whether it be a
|
|
|
|
|
directory or a file.
|
|
|
|
|
|
|
|
|
|
Fails with `ENOENT` if the parent directory of the directory you
|
|
|
|
|
want to create doesn't exist. For making `a/really/long/path/`
|
|
|
|
|
consider using makedirs() instead.
|
|
|
|
|
|
|
|
|
|
Fails with `ENOTDIR` if a parent directory component existed that
|
|
|
|
|
wasn't a directory.
|
|
|
|
|
|
|
|
|
|
Fails with `EACCES` if the parent directory doesn't grant write
|
|
|
|
|
permission to the current user.
|
|
|
|
|
|
|
|
|
|
Fails with `ENAMETOOLONG` if the path is too long.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.makedirs(path:str[, mode:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Makes directories.
|
|
|
|
|
|
2022-05-18 23:41:29 +00:00
|
|
|
|
Unlike mkdir() this convenience wrapper will automatically create
|
|
|
|
|
parent parent directories as needed. If the directory already exists
|
|
|
|
|
then, unlike mkdir() which returns EEXIST, the makedirs() function
|
|
|
|
|
will return success.
|
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`path` is the path of the directory you wish to create.
|
|
|
|
|
|
|
|
|
|
`mode` is octal permission bits, e.g. `0755`.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.chdir(path:str)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Changes current directory to `path`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.unlink(path:str[, dirfd:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Removes file at `path`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
If `path` refers to a symbolic link, the link is removed.
|
|
|
|
|
|
|
|
|
|
Returns `EISDIR` if `path` refers to a directory. See rmdir().
|
|
|
|
|
|
|
|
|
|
unix.rmdir(path:str[, dirfd:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Removes empty directory at `path`.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Returns `ENOTDIR` if `path` isn't a directory, or a path component
|
|
|
|
|
in `path` exists yet wasn't a directory.
|
|
|
|
|
|
|
|
|
|
unix.rename(oldpath:str, newpath:str[, olddirfd:int, newdirfd:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Renames file or directory.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.link(existingpath:str, newpath:str[, flags:int[, olddirfd, newdirfd]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Creates hard link, so your underlying inode has two names.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.symlink(target:str, linkpath:str[, newdirfd:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Creates symbolic link.
|
|
|
|
|
|
|
|
|
|
On Windows NT a symbolic link is called a "reparse point" and can
|
|
|
|
|
only be created from an administrator account. Your redbean will
|
|
|
|
|
automatically request the appropriate permissions.
|
|
|
|
|
|
|
|
|
|
unix.readlink(path:str[, dirfd:int])
|
|
|
|
|
├─→ content:str
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Reads contents of symbolic link.
|
|
|
|
|
|
|
|
|
|
Note that broken links are supported on all platforms. A symbolic
|
|
|
|
|
link can contain just about anything. It's important to not assume
|
|
|
|
|
that `content` will be a valid filename.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
On Windows NT, this function transliterates `\` to `/` and
|
|
|
|
|
furthermore prefixes `//?/` to WIN32 DOS-style absolute paths,
|
|
|
|
|
thereby assisting with simple absolute filename checks in addition
|
|
|
|
|
to enabling one to exceed the traditional 260 character limit.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.realpath(path:str)
|
|
|
|
|
├─→ path:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns absolute path of filename, with `.` and `..` components
|
|
|
|
|
removed, and symlinks will be resolved.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-06-18 08:10:29 +00:00
|
|
|
|
unix.utimensat(path[, asecs, ananos, msecs, mnanos[, dirfd[, flags]]])
|
|
|
|
|
├─→ 0
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Changes access and/or modified timestamps on file.
|
|
|
|
|
|
|
|
|
|
`path` is a string with the name of the file.
|
|
|
|
|
|
|
|
|
|
The `asecs` and `ananos` parameters set the access time. If they're
|
|
|
|
|
none or nil, the current time will be used.
|
|
|
|
|
|
|
|
|
|
The `msecs` and `mnanos` parameters set the modified time. If
|
|
|
|
|
they're none or nil, the current time will be used.
|
|
|
|
|
|
|
|
|
|
The nanosecond parameters (`ananos` and `mnanos`) must be on the
|
|
|
|
|
interval [0,1000000000) or `unix.EINVAL` is raised. On XNU this is
|
|
|
|
|
truncated to microsecond precision. On Windows NT, it's truncated to
|
|
|
|
|
hectonanosecond precision. These nanosecond parameters may also be
|
|
|
|
|
set to one of the following special values:
|
|
|
|
|
|
|
|
|
|
- `unix.UTIME_NOW`: Fill this timestamp with current time. This
|
|
|
|
|
feature is not available on old versions of Linux, e.g. RHEL5.
|
|
|
|
|
|
|
|
|
|
- `unix.UTIME_OMIT`: Do not alter this timestamp. This feature is
|
|
|
|
|
not available on old versions of Linux, e.g. RHEL5.
|
|
|
|
|
|
|
|
|
|
`dirfd` is a file descriptor integer opened with `O_DIRECTORY`
|
|
|
|
|
that's used for relative path names. It defaults to `unix.AT_FDCWD`.
|
|
|
|
|
|
|
|
|
|
`flags` may have have any of the following flags bitwise or'd
|
|
|
|
|
|
|
|
|
|
- `AT_SYMLINK_NOFOLLOW`: Do not follow symbolic links. This makes it
|
|
|
|
|
possible to edit the timestamps on the symbolic link itself,
|
|
|
|
|
rather than the file it points to.
|
|
|
|
|
|
|
|
|
|
unix.futimens(fd:int[, asecs, ananos, msecs, mnanos])
|
|
|
|
|
├─→ 0
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Changes access and/or modified timestamps on file descriptor.
|
|
|
|
|
|
|
|
|
|
`fd` is the file descriptor of a file opened with `unix.open`.
|
|
|
|
|
|
|
|
|
|
The `asecs` and `ananos` parameters set the access time. If they're
|
|
|
|
|
none or nil, the current time will be used.
|
|
|
|
|
|
|
|
|
|
The `msecs` and `mnanos` parameters set the modified time. If
|
|
|
|
|
they're none or nil, the current time will be used.
|
|
|
|
|
|
|
|
|
|
The nanosecond parameters (`ananos` and `mnanos`) must be on the
|
|
|
|
|
interval [0,1000000000) or `unix.EINVAL` is raised. On XNU this is
|
|
|
|
|
truncated to microsecond precision. On Windows NT, it's truncated to
|
|
|
|
|
hectonanosecond precision. These nanosecond parameters may also be
|
|
|
|
|
set to one of the following special values:
|
|
|
|
|
|
|
|
|
|
- `unix.UTIME_NOW`: Fill this timestamp with current time.
|
|
|
|
|
|
|
|
|
|
- `unix.UTIME_OMIT`: Do not alter this timestamp.
|
|
|
|
|
|
|
|
|
|
This system call is currently not available on very old versions of
|
|
|
|
|
Linux, e.g. RHEL5.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.chown(path:str, uid:int, gid:int[, flags:int[, dirfd:int]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-29 07:36:14 +00:00
|
|
|
|
Changes user and group on file.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Returns `ENOSYS` on Windows NT.
|
|
|
|
|
|
|
|
|
|
unix.chmod(path:str, mode:int[, flags:int[, dirfd:int]])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Changes mode bits on file.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
On Windows NT the chmod system call only changes the read-only
|
|
|
|
|
status of a file.
|
|
|
|
|
|
|
|
|
|
unix.getcwd()
|
|
|
|
|
├─→ path:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns current working directory.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
On Windows NT, this function transliterates `\` to `/` and
|
|
|
|
|
furthermore prefixes `//?/` to WIN32 DOS-style absolute paths,
|
|
|
|
|
thereby assisting with simple absolute filename checks in addition
|
|
|
|
|
to enabling one to exceed the traditional 260 character limit.
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
unix.rmrf(path:str)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Recursively removes filesystem path.
|
|
|
|
|
|
|
|
|
|
Like unix.makedirs() this function isn't actually a system call but
|
|
|
|
|
rather is a Libc convenience wrapper. It's intended to be equivalent
|
|
|
|
|
to using the UNIX shell's `rm -rf path` command.
|
|
|
|
|
|
|
|
|
|
`path` is the file or directory path you wish to destroy.
|
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
unix.fcntl(fd:int, unix.F_GETFD)
|
|
|
|
|
├─→ flags:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns file descriptor flags.
|
|
|
|
|
|
|
|
|
|
The returned `flags` may include any of:
|
|
|
|
|
|
|
|
|
|
- `unix.FD_CLOEXEC` if `fd` was opened with `unix.O_CLOEXEC`.
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` isn't open.
|
|
|
|
|
|
|
|
|
|
unix.fcntl(fd:int, unix.F_SETFD, flags:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Sets file descriptor flags.
|
|
|
|
|
|
|
|
|
|
`flags` may include any of:
|
|
|
|
|
|
|
|
|
|
- `unix.FD_CLOEXEC` to re-open `fd` with `unix.O_CLOEXEC`.
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` isn't open.
|
|
|
|
|
|
|
|
|
|
unix.fcntl(fd:int, unix.F_GETFL)
|
|
|
|
|
├─→ flags:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns file descriptor status flags.
|
|
|
|
|
|
|
|
|
|
`flags & unix.O_ACCMODE` includes one of:
|
|
|
|
|
|
|
|
|
|
- `O_RDONLY`
|
|
|
|
|
- `O_WRONLY`
|
|
|
|
|
- `O_RDWR`
|
|
|
|
|
|
|
|
|
|
Examples of values `flags & ~unix.O_ACCMODE` may include:
|
|
|
|
|
|
|
|
|
|
- `O_NONBLOCK`
|
|
|
|
|
- `O_APPEND`
|
|
|
|
|
- `O_SYNC`
|
|
|
|
|
- `O_ASYNC`
|
|
|
|
|
- `O_NOATIME` on Linux
|
|
|
|
|
- `O_RANDOM` on Windows
|
|
|
|
|
- `O_SEQUENTIAL` on Windows
|
|
|
|
|
- `O_DIRECT` on Linux/FreeBSD/NetBSD/Windows
|
|
|
|
|
|
|
|
|
|
Examples of values `flags & ~unix.O_ACCMODE` won't include:
|
|
|
|
|
|
|
|
|
|
- `O_CREAT`
|
|
|
|
|
- `O_TRUNC`
|
|
|
|
|
- `O_EXCL`
|
|
|
|
|
- `O_NOCTTY`
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` isn't open.
|
|
|
|
|
|
|
|
|
|
unix.fcntl(fd:int, unix.F_SETFL, flags:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Changes file descriptor status flags.
|
|
|
|
|
|
|
|
|
|
Examples of values `flags` may include:
|
|
|
|
|
|
|
|
|
|
- `O_NONBLOCK`
|
|
|
|
|
- `O_APPEND`
|
|
|
|
|
- `O_SYNC`
|
|
|
|
|
- `O_ASYNC`
|
|
|
|
|
- `O_NOATIME` on Linux
|
|
|
|
|
- `O_RANDOM` on Windows
|
|
|
|
|
- `O_SEQUENTIAL` on Windows
|
|
|
|
|
- `O_DIRECT` on Linux/FreeBSD/NetBSD/Windows
|
|
|
|
|
|
|
|
|
|
These values should be ignored:
|
|
|
|
|
|
|
|
|
|
- `O_RDONLY`, `O_WRONLY`, `O_RDWR`
|
|
|
|
|
- `O_CREAT`, `O_TRUNC`, `O_EXCL`
|
|
|
|
|
- `O_NOCTTY`
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` isn't open.
|
|
|
|
|
|
|
|
|
|
unix.fcntl(fd:int, unix.F_SETLK[, type[, start[, len[, whence]]]])
|
|
|
|
|
unix.fcntl(fd:int, unix.F_SETLKW[, type[, start[, len[, whence]]]])
|
|
|
|
|
├─→ true
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
Acquires lock on file interval.
|
|
|
|
|
|
|
|
|
|
POSIX Advisory Locks allow multiple processes to leave voluntary
|
|
|
|
|
hints to each other about which portions of a file they're using.
|
|
|
|
|
|
|
|
|
|
The command may be:
|
|
|
|
|
|
|
|
|
|
- `F_SETLK` to acquire lock if possible
|
|
|
|
|
- `F_SETLKW` to wait for lock if necessary
|
|
|
|
|
|
|
|
|
|
`fd` is file descriptor of open() file.
|
|
|
|
|
|
|
|
|
|
`type` may be one of:
|
|
|
|
|
|
|
|
|
|
- `F_RDLCK` for read lock (default)
|
|
|
|
|
- `F_WRLCK` for read/write lock
|
|
|
|
|
- `F_UNLCK` to unlock
|
|
|
|
|
|
|
|
|
|
`start` is 0-indexed byte offset into file. The default is zero.
|
|
|
|
|
|
|
|
|
|
`len` is byte length of interval. Zero is the default and it means
|
|
|
|
|
until the end of the file.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
`whence` may be one of:
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
- `SEEK_SET` start from beginning (default)
|
|
|
|
|
- `SEEK_CUR` start from current position
|
|
|
|
|
- `SEEK_END` start from end
|
|
|
|
|
|
|
|
|
|
Returns `EAGAIN` if lock couldn't be acquired. POSIX says this
|
|
|
|
|
theoretically could also be `EACCES` but we haven't seen this
|
|
|
|
|
behavior on any of our supported platforms.
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` wasn't open.
|
|
|
|
|
|
|
|
|
|
unix.fcntl(fd:int, unix.F_GETLK[, type[, start[, len[, whence]]]])
|
|
|
|
|
├─→ unix.F_UNLCK
|
|
|
|
|
├─→ type, start, len, whence, pid
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Acquires information about POSIX advisory lock on file.
|
|
|
|
|
|
|
|
|
|
This function accepts the same parameters as fcntl(F_SETLK) and
|
|
|
|
|
tells you if the lock acquisition would be successful for a given
|
|
|
|
|
range of bytes. If locking would have succeeded, then F_UNLCK is
|
|
|
|
|
returned. If the lock would not have succeeded, then information
|
|
|
|
|
about a conflicting lock is returned.
|
|
|
|
|
|
|
|
|
|
Returned `type` may be `F_RDLCK` or `F_WRLCK`.
|
|
|
|
|
|
|
|
|
|
Returned `pid` is the process id of the current lock owner.
|
|
|
|
|
|
|
|
|
|
This function is currently not supported on Windows.
|
|
|
|
|
|
|
|
|
|
Returns `EBADF` if `fd` wasn't open.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getsid(pid:int)
|
|
|
|
|
├─→ sid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Gets session id.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getpgrp()
|
|
|
|
|
├─→ pgid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Gets process group id.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setpgrp()
|
|
|
|
|
├─→ pgid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets process group id. This is the same as `setpgid(0,0)`.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setpgid(pid:int, pgid:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets process group id the modern way.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getpgid(pid:int)
|
|
|
|
|
├─→ pgid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Gets process group id the modern way.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setsid()
|
|
|
|
|
├─→ sid:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets session id.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
This function can be used to create daemons.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Fails with `ENOSYS` on Windows NT.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getuid()
|
|
|
|
|
└─→ uid:int
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Gets real user id.
|
|
|
|
|
|
|
|
|
|
On Windows this system call is polyfilled by running GetUserNameW()
|
|
|
|
|
through Knuth's multiplicative hash.
|
|
|
|
|
|
|
|
|
|
This function does not fail.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getgid()
|
|
|
|
|
└─→ gid:int
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Sets real group id.
|
|
|
|
|
|
|
|
|
|
On Windows this system call is polyfilled as getuid().
|
|
|
|
|
|
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.geteuid()
|
|
|
|
|
└─→ uid:int
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Gets effective user id.
|
|
|
|
|
|
|
|
|
|
For example, if your redbean is a setuid binary, then getuid() will
|
|
|
|
|
return the uid of the user running the program, and geteuid() shall
|
|
|
|
|
return zero which means root, assuming that's the file owning user.
|
|
|
|
|
|
|
|
|
|
On Windows this system call is polyfilled as getuid().
|
|
|
|
|
|
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getegid()
|
|
|
|
|
└─→ gid:int
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Gets effective group id.
|
|
|
|
|
|
|
|
|
|
On Windows this system call is polyfilled as getuid().
|
|
|
|
|
|
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.chroot(path:str)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Changes root directory.
|
|
|
|
|
|
|
|
|
|
Returns `ENOSYS` on Windows NT.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setuid(uid:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets user id.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
One use case for this function is dropping root privileges. Should
|
|
|
|
|
you ever choose to run redbean as root and decide not to use the
|
|
|
|
|
`-G` and `-U` flags, you can replicate that behavior in the Lua
|
|
|
|
|
processes you spawn as follows:
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
ok, err = unix.setgid(1000) -- check your /etc/groups
|
|
|
|
|
if not ok then Log(kLogFatal, tostring(err)) end
|
|
|
|
|
ok, err = unix.setuid(1000) -- check your /etc/passwd
|
|
|
|
|
if not ok then Log(kLogFatal, tostring(err)) end
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
If your goal is to relinquish privileges because redbean is a setuid
|
|
|
|
|
binary, then things are more straightforward:
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
ok, err = unix.setgid(unix.getgid())
|
|
|
|
|
if not ok then Log(kLogFatal, tostring(err)) end
|
|
|
|
|
ok, err = unix.setuid(unix.getuid())
|
|
|
|
|
if not ok then Log(kLogFatal, tostring(err)) end
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
See also the setresuid() function and be sure to refer to your local
|
|
|
|
|
system manual about the subtleties of changing user id in a way that
|
|
|
|
|
isn't restorable.
|
|
|
|
|
|
|
|
|
|
Returns `ENOSYS` on Windows NT if `uid` isn't `getuid()`.
|
|
|
|
|
|
2022-07-14 03:55:27 +00:00
|
|
|
|
unix.setfsuid(uid:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Sets user id for file system ops.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setgid(gid:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets group id.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Returns `ENOSYS` on Windows NT if `gid` isn't `getgid()`.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setresuid(real:int, effective:int, saved:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Sets real, effective, and saved user ids.
|
|
|
|
|
|
|
|
|
|
If any of the above parameters are -1, then it's a no-op.
|
|
|
|
|
|
|
|
|
|
Returns `ENOSYS` on Windows NT.
|
|
|
|
|
Returns `ENOSYS` on Macintosh and NetBSD if `saved` isn't -1.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setresgid(real:int, effective:int, saved:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Sets real, effective, and saved group ids.
|
|
|
|
|
|
|
|
|
|
If any of the above parameters are -1, then it's a no-op.
|
|
|
|
|
|
|
|
|
|
Returns `ENOSYS` on Windows NT.
|
|
|
|
|
Returns `ENOSYS` on Macintosh and NetBSD if `saved` isn't -1.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.umask(newmask:int)
|
|
|
|
|
└─→ oldmask:int
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sets file permission mask and returns the old one.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
This is used to remove bits from the `mode` parameter of functions
|
|
|
|
|
like open() and mkdir(). The masks typically used are 027 and 022.
|
|
|
|
|
Those masks ensure that, even if a file is created with 0666 bits,
|
|
|
|
|
it'll be turned into 0640 or 0644 so that users other than the owner
|
|
|
|
|
can't modify it.
|
|
|
|
|
|
|
|
|
|
To read the mask without changing it, try doing this:
|
|
|
|
|
|
|
|
|
|
mask = unix.umask(027)
|
|
|
|
|
unix.umask(mask)
|
|
|
|
|
|
|
|
|
|
On Windows NT this is a no-op and `mask` is returned.
|
|
|
|
|
|
|
|
|
|
This function does not fail.
|
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.syslog(priority:int, msg:str)
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Generates a log message, which will be distributed by syslogd.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`priority` is a bitmask containing the facility value and the level
|
|
|
|
|
value. If no facility value is ORed into priority, then the default
|
|
|
|
|
value set by openlog() is used. If set to NULL, the program name is
|
|
|
|
|
used. Level is one of `LOG_EMERG`, `LOG_ALERT`, `LOG_CRIT`,
|
|
|
|
|
`LOG_ERR`, `LOG_WARNING`, `LOG_NOTICE`, `LOG_INFO`, `LOG_DEBUG`.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
This function currently works on Linux, Windows, and NetBSD. On
|
|
|
|
|
WIN32 it uses the ReportEvent() facility.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.clock_gettime([clock:int])
|
|
|
|
|
├─→ seconds:int, nanos:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Returns nanosecond precision timestamp from system, e.g.
|
|
|
|
|
|
|
|
|
|
>: unix.clock_gettime()
|
|
|
|
|
1651137352 774458779
|
|
|
|
|
>: Benchmark(unix.clock_gettime)
|
|
|
|
|
126 393 571 1
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
`clock` can be any one of of:
|
|
|
|
|
|
|
|
|
|
- `CLOCK_REALTIME`: universally supported
|
2022-06-11 07:05:06 +00:00
|
|
|
|
- `CLOCK_REALTIME_FAST`: ditto but faster on freebsd
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `CLOCK_MONOTONIC`: universally supported
|
2022-06-11 07:05:06 +00:00
|
|
|
|
- `CLOCK_MONOTONIC_FAST`: ditto but faster on freebsd
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `CLOCK_MONOTONIC_RAW`: nearly universally supported
|
|
|
|
|
- `CLOCK_PROCESS_CPUTIME_ID`: linux and bsd
|
|
|
|
|
- `CLOCK_THREAD_CPUTIME_ID`: linux and bsd
|
|
|
|
|
- `CLOCK_REALTIME_COARSE`: : linux and openbsd
|
|
|
|
|
- `CLOCK_MONOTONIC_COARSE`: linux
|
|
|
|
|
- `CLOCK_PROF`: linux and netbsd
|
|
|
|
|
- `CLOCK_BOOTTIME`: linux and openbsd
|
|
|
|
|
- `CLOCK_REALTIME_ALARM`: linux-only
|
|
|
|
|
- `CLOCK_BOOTTIME_ALARM`: linux-only
|
2022-04-28 16:42:36 +00:00
|
|
|
|
- `CLOCK_TAI`: linux-only
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
|
|
|
|
Returns `EINVAL` if clock isn't supported on platform.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
This function only fails if `clock` is invalid.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This function goes fastest on Linux and Windows.
|
|
|
|
|
|
2022-09-18 10:02:13 +00:00
|
|
|
|
unix.nanosleep(seconds:int[, nanos:int])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ remseconds:int, remnanos:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Sleeps with nanosecond precision.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Returns `EINTR` if a signal was received while waiting.
|
|
|
|
|
|
2022-04-22 05:07:21 +00:00
|
|
|
|
unix.sync()
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.fsync(fd:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.fdatasync(fd:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
These functions are used to make programs slower by asking the
|
|
|
|
|
operating system to flush data to the physical medium.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.lseek(fd:int, offset:int[, whence:int])
|
|
|
|
|
├─→ newposbytes:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Seeks to file position.
|
2022-04-18 15:54:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`whence` can be one of:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
- `SEEK_SET`: Sets the file position to `offset` [default]
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- `SEEK_CUR`: Sets the file position to `position + offset`
|
|
|
|
|
- `SEEK_END`: Sets the file position to `filesize + offset`
|
|
|
|
|
|
|
|
|
|
Returns the new position relative to the start of the file.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.truncate(path:str[, length:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Reduces or extends underlying physical medium of file.
|
|
|
|
|
If file was originally larger, content >length is lost.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`length` defaults to zero.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ftruncate(fd:int[, length:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Reduces or extends underlying physical medium of open file.
|
|
|
|
|
If file was originally larger, content >length is lost.
|
|
|
|
|
|
|
|
|
|
`length` defaults to zero.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.socket([family:int[, type:int[, protocol:int]]])
|
|
|
|
|
├─→ fd:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
`family` defaults to `AF_INET` and can be:
|
|
|
|
|
|
2022-06-22 10:04:25 +00:00
|
|
|
|
- `AF_INET`: Creates Internet Protocol Version 4 (IPv4) socket.
|
|
|
|
|
|
|
|
|
|
- `AF_UNIX`: Creates local UNIX domain socket. On the New Technology
|
|
|
|
|
this requires Windows 10 and only works with `SOCK_STREAM`.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
`type` defaults to `SOCK_STREAM` and can be:
|
|
|
|
|
|
|
|
|
|
- `SOCK_STREAM`
|
|
|
|
|
- `SOCK_DGRAM`
|
|
|
|
|
- `SOCK_RAW`
|
|
|
|
|
- `SOCK_RDM`
|
|
|
|
|
- `SOCK_SEQPACKET`
|
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
You may bitwise OR any of the following into `type`:
|
2022-05-11 09:50:03 +00:00
|
|
|
|
|
|
|
|
|
- `SOCK_CLOEXEC`
|
|
|
|
|
- `SOCK_NONBLOCK`
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
`protocol` may be any of:
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
- `0` to let kernel choose [default]
|
2022-04-24 16:59:22 +00:00
|
|
|
|
- `IPPROTO_TCP`
|
|
|
|
|
- `IPPROTO_UDP`
|
|
|
|
|
- `IPPROTO_RAW`
|
2022-07-09 06:06:46 +00:00
|
|
|
|
- `IPPROTO_IP`
|
|
|
|
|
- `IPPROTO_ICMP`
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
unix.socketpair([family:int[, type:int[, protocol:int]]])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ fd1:int, fd2:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-05-11 09:50:03 +00:00
|
|
|
|
Creates bidirectional pipe.
|
|
|
|
|
|
|
|
|
|
`family` defaults to `AF_UNIX`.
|
|
|
|
|
|
|
|
|
|
`type` defaults to `SOCK_STREAM` and can be:
|
|
|
|
|
|
|
|
|
|
- `SOCK_STREAM`
|
|
|
|
|
- `SOCK_DGRAM`
|
|
|
|
|
- `SOCK_SEQPACKET`
|
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
You may bitwise OR any of the following into `type`:
|
2022-05-11 09:50:03 +00:00
|
|
|
|
|
|
|
|
|
- `SOCK_CLOEXEC`
|
|
|
|
|
- `SOCK_NONBLOCK`
|
|
|
|
|
|
|
|
|
|
`protocol` defaults to `0`.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.bind(fd:int[, ip:uint32, port:uint16])
|
2022-06-22 10:04:25 +00:00
|
|
|
|
unix.bind(fd:int[, unixpath:str])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Binds socket.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
`ip` and `port` are in host endian order. For example, if you
|
|
|
|
|
wanted to listen on `1.2.3.4:31337` you could do any of these
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.bind(sock, 0x01020304, 31337)
|
2022-04-24 16:59:22 +00:00
|
|
|
|
unix.bind(sock, ParseIp('1.2.3.4'), 31337)
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.bind(sock, 1 << 24 | 0 << 16 | 0 << 8 | 1, 31337)
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
`ip` and `port` both default to zero. The meaning of bind(0, 0)
|
|
|
|
|
is to listen on all interfaces with a kernel-assigned ephemeral
|
|
|
|
|
port number, that can be retrieved and used as follows:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
sock = assert(unix.socket()) -- create ipv4 tcp socket
|
|
|
|
|
assert(unix.bind(sock)) -- all interfaces ephemeral port
|
|
|
|
|
ip, port = assert(unix.getsockname(sock))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
print("listening on ip", FormatIp(ip), "port", port)
|
2022-04-26 04:16:05 +00:00
|
|
|
|
assert(unix.listen(sock))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
while true do
|
2022-04-26 04:16:05 +00:00
|
|
|
|
client, clientip, clientport = assert(unix.accept(sock))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
print("got client ip", FormatIp(clientip), "port", clientport)
|
|
|
|
|
unix.close(client)
|
|
|
|
|
end
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Further note that calling `unix.bind(sock)` is equivalent to not
|
|
|
|
|
calling bind() at all, since the above behavior is the default.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.siocgifconf()
|
|
|
|
|
├─→ {{name:str,ip:uint32,netmask:uint32}, ...}
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
Returns list of network adapter addresses.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getsockopt(fd:int, level:int, optname:int) → ...
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.setsockopt(fd:int, level:int, optname:int, ...) → ok:bool, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Tunes networking parameters.
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
`level` and `optname` may be one of the following pairs. The ellipses
|
|
|
|
|
type signature above changes depending on which options are used.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-17 09:40:39 +00:00
|
|
|
|
`optname` is the option feature magic number. The constants for
|
|
|
|
|
these will be set to `0` if the option isn't supported on the host
|
|
|
|
|
platform.
|
|
|
|
|
|
|
|
|
|
Raises `ENOPROTOOPT` if your `level` / `optname` combination isn't
|
|
|
|
|
valid, recognized, or supported on the host platform.
|
|
|
|
|
|
|
|
|
|
Raises `ENOTSOCK` if `fd` is valid but isn't a socket.
|
|
|
|
|
|
|
|
|
|
Raises `EBADF` if `fd` isn't valid.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getsockopt(fd:int, level:int, optname:int)
|
|
|
|
|
├─→ value:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.setsockopt(fd:int, level:int, optname:int, value:bool)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
- `SOL_SOCKET`, `SO_TYPE`
|
|
|
|
|
- `SOL_SOCKET`, `SO_DEBUG`
|
|
|
|
|
- `SOL_SOCKET`, `SO_ACCEPTCONN`
|
|
|
|
|
- `SOL_SOCKET`, `SO_BROADCAST`
|
|
|
|
|
- `SOL_SOCKET`, `SO_REUSEADDR`
|
|
|
|
|
- `SOL_SOCKET`, `SO_REUSEPORT`
|
|
|
|
|
- `SOL_SOCKET`, `SO_KEEPALIVE`
|
|
|
|
|
- `SOL_SOCKET`, `SO_DONTROUTE`
|
|
|
|
|
- `SOL_TCP`, `TCP_NODELAY`
|
|
|
|
|
- `SOL_TCP`, `TCP_CORK`
|
|
|
|
|
- `SOL_TCP`, `TCP_QUICKACK`
|
|
|
|
|
- `SOL_TCP`, `TCP_FASTOPEN_CONNECT`
|
|
|
|
|
- `SOL_TCP`, `TCP_DEFER_ACCEPT`
|
|
|
|
|
- `SOL_IP`, `IP_HDRINCL`
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.getsockopt(fd:int, level:int, optname:int)
|
|
|
|
|
├─→ value:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.setsockopt(fd:int, level:int, optname:int, value:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
- `SOL_SOCKET`, `SO_SNDBUF`
|
|
|
|
|
- `SOL_SOCKET`, `SO_RCVBUF`
|
|
|
|
|
- `SOL_SOCKET`, `SO_RCVLOWAT`
|
|
|
|
|
- `SOL_SOCKET`, `SO_SNDLOWAT`
|
|
|
|
|
- `SOL_TCP`, `TCP_KEEPIDLE`
|
|
|
|
|
- `SOL_TCP`, `TCP_KEEPINTVL`
|
|
|
|
|
- `SOL_TCP`, `TCP_FASTOPEN`
|
|
|
|
|
- `SOL_TCP`, `TCP_KEEPCNT`
|
|
|
|
|
- `SOL_TCP`, `TCP_MAXSEG`
|
|
|
|
|
- `SOL_TCP`, `TCP_SYNCNT`
|
|
|
|
|
- `SOL_TCP`, `TCP_NOTSENT_LOWAT`
|
|
|
|
|
- `SOL_TCP`, `TCP_WINDOW_CLAMP`
|
|
|
|
|
- `SOL_IP`, `IP_TOS`
|
|
|
|
|
- `SOL_IP`, `IP_MTU`
|
|
|
|
|
- `SOL_IP`, `IP_TTL`
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.getsockopt(fd:int, level:int, optname:int)
|
|
|
|
|
├─→ secs:int, nsecs:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.setsockopt(fd:int, level:int, optname:int, secs:int[, nanos:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
- `SOL_SOCKET`, `SO_RCVTIMEO`: If this option is specified then
|
2022-04-26 04:16:05 +00:00
|
|
|
|
your stream socket will have a read() / recv() timeout. If the
|
|
|
|
|
specified interval elapses without receiving data, then EAGAIN
|
|
|
|
|
shall be returned by read. If this option is used on listening
|
|
|
|
|
sockets, it'll be inherited by accepted sockets. Your redbean
|
|
|
|
|
already does this for GetClientFd() based on the `-t` flag.
|
|
|
|
|
|
2022-06-24 01:54:35 +00:00
|
|
|
|
- `SOL_SOCKET`, `SO_SNDTIMEO`: This is the same as `SO_RCVTIMEO`
|
2022-04-26 04:16:05 +00:00
|
|
|
|
but it applies to the write() / send() functions.
|
|
|
|
|
|
|
|
|
|
unix.getsockopt(fd:int, unix.SOL_SOCKET, unix.SO_LINGER)
|
|
|
|
|
├─→ seconds:int, enabled:bool
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.setsockopt(fd:int, unix.SOL_SOCKET, unix.SO_LINGER, secs:int, enabled:bool)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
This `SO_LINGER` parameter can be used to make close() a blocking
|
|
|
|
|
call. Normally when the kernel returns immediately when it receives
|
|
|
|
|
close(). Sometimes it's desirable to have extra assurance on errors
|
|
|
|
|
happened, even if it comes at the cost of performance.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-17 09:40:39 +00:00
|
|
|
|
unix.setsockopt(serverfd:int, unix.SOL_TCP, unix.TCP_SAVE_SYN, enabled:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
unix.getsockopt(clientfd:int, unix.SOL_TCP, unix.TCP_SAVED_SYN)
|
|
|
|
|
├─→ syn_packet_bytes:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-07-17 09:40:39 +00:00
|
|
|
|
This `TCP_SAVED_SYN` option may be used to retrieve the bytes of the
|
|
|
|
|
TCP SYN packet that the client sent when the connection for `fd` was
|
|
|
|
|
opened. In order for this to work, `TCP_SAVE_SYN` must have been set
|
|
|
|
|
earlier on the listening socket. This is Linux-only. You can use the
|
|
|
|
|
`OnServerListen` hook to enable SYN saving in your Redbean. When the
|
|
|
|
|
`TCP_SAVE_SYN` option isn't used, this may return empty string.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
unix.poll({[fd:int]=events:int, ...}[, timeoutms:int[, mask:unix.Sigset]])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ {[fd:int]=revents:int, ...}
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
Checks for events on a set of file descriptors.
|
|
|
|
|
|
|
|
|
|
The table of file descriptors to poll uses sparse integer keys. Any
|
|
|
|
|
pairs with non-integer keys will be ignored. Pairs with negative
|
|
|
|
|
keys are ignored by poll(). The returned table will be a subset of
|
|
|
|
|
the supplied file descriptors.
|
|
|
|
|
|
2022-07-01 00:41:51 +00:00
|
|
|
|
`events` and `revents` may be any combination (using bitwise OR) of:
|
|
|
|
|
|
|
|
|
|
- `POLLIN` (events, revents): There is data to read.
|
|
|
|
|
- `POLLOUT` (events, revents): Writing is now possible, although may
|
|
|
|
|
still block if available space in a socket or pipe is exceeded
|
|
|
|
|
(unless `O_NONBLOCK` is set).
|
|
|
|
|
- `POLLPRI` (events, revents): There is some exceptional condition
|
|
|
|
|
(for example, out-of-band data on a TCP socket).
|
|
|
|
|
- `POLLRDHUP` (events, revents): Stream socket peer closed
|
|
|
|
|
connection, or shut down writing half of connection.
|
|
|
|
|
- `POLLERR` (revents): Some error condition.
|
|
|
|
|
- `POLLHUP` (revents): Hang up. When reading from a channel such as
|
|
|
|
|
a pipe or a stream socket, this event merely indicates that the
|
|
|
|
|
peer closed its end of the channel.
|
|
|
|
|
- `POLLNVAL` (revents): Invalid request.
|
|
|
|
|
|
2022-08-17 06:23:34 +00:00
|
|
|
|
`timeoutms` is the number of milliseconds to block. The default is
|
|
|
|
|
-1 which means block indefinitely until there's an event or an
|
|
|
|
|
interrupt. If the timeout elapses without any such events, an empty
|
|
|
|
|
table is returned. A timeout of zero means non-blocking.
|
|
|
|
|
|
|
|
|
|
`mask` serves the purpose of enabling poll to listen for both file
|
|
|
|
|
descriptor events and signals. It's equivalent to saying:
|
|
|
|
|
|
|
|
|
|
oldmask = unix.sigprocmask(unix.SIG_SETMASK, mask);
|
|
|
|
|
unix.poll(fds, timeout);
|
|
|
|
|
unix.sigprocmask(unix.SIG_SETMASK, oldmask);
|
|
|
|
|
|
|
|
|
|
Except it'll happen atomically on supported platforms. The only
|
|
|
|
|
exceptions are MacOS and NetBSD where this behavior is simulated by
|
|
|
|
|
the polyfill. Atomicity is helpful for unit testing signal behavior.
|
|
|
|
|
|
|
|
|
|
`EINTR` is returned if the kernel decided to deliver a signal to a
|
|
|
|
|
signal handler instead during your call. This is a @norestart system
|
|
|
|
|
call that always returns `EINTR` even if `SA_RESTART` is in play.
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.gethostname()
|
|
|
|
|
├─→ host:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
Returns hostname of system.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.listen(fd:int[, backlog:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Begins listening for incoming connections on a socket.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.accept(serverfd:int[, flags:int])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ clientfd:int, ip:uint32, port:uint16
|
2022-06-22 10:04:25 +00:00
|
|
|
|
├─→ clientfd:int, unixpath:str
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Accepts new client socket descriptor for a listening tcp socket.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
|
|
|
|
- `SOCK_CLOEXEC`
|
|
|
|
|
- `SOCK_NONBLOCK`
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.connect(fd:int, ip:uint32, port:uint16)
|
2022-06-22 10:04:25 +00:00
|
|
|
|
unix.connect(fd:int, unixpath:str)
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Connects a TCP socket to a remote host.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
With TCP this is a blocking operation. For a UDP socket it simply
|
|
|
|
|
remembers the intended address so that send() or write() may be used
|
|
|
|
|
rather than sendto().
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getsockname(fd:int)
|
|
|
|
|
├─→ ip:uint32, port:uint16
|
2022-06-22 10:04:25 +00:00
|
|
|
|
├─→ unixpath:str
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Retrieves the local address of a socket.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.getpeername(fd:int)
|
|
|
|
|
├─→ ip:uint32, port:uint16
|
2022-06-22 10:04:25 +00:00
|
|
|
|
├─→ unixpath:str
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Retrieves the remote address of a socket.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-06-22 10:04:25 +00:00
|
|
|
|
This operation will either fail on `AF_UNIX` sockets or return an
|
|
|
|
|
empty string.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.recv(fd:int[, bufsiz:int[, flags:int]])
|
|
|
|
|
├─→ data:str
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `MSG_WAITALL`
|
|
|
|
|
- `MSG_DONTROUTE`
|
|
|
|
|
- `MSG_PEEK`
|
|
|
|
|
- `MSG_OOB`
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
unix.recvfrom(fd:int[, bufsiz:int[, flags:int]])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ data:str, ip:uint32, port:uint16
|
2022-06-22 10:04:25 +00:00
|
|
|
|
├─→ data:str, unixpath:str
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-25 15:30:14 +00:00
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `MSG_WAITALL`
|
|
|
|
|
- `MSG_DONTROUTE`
|
|
|
|
|
- `MSG_PEEK`
|
|
|
|
|
- `MSG_OOB`
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.send(fd:int, data:str[, flags:int])
|
|
|
|
|
├─→ sent:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
This is the same as `write` except it has a `flags` argument
|
2022-04-24 16:59:22 +00:00
|
|
|
|
that's intended for sockets.
|
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
- `MSG_NOSIGNAL`: Don't SIGPIPE on EOF
|
|
|
|
|
- `MSG_OOB`: Send stream data through out of bound channel
|
|
|
|
|
- `MSG_DONTROUTE`: Don't go through gateway (for diagnostics)
|
|
|
|
|
- `MSG_MORE`: Manual corking to belay nodelay (0 on non-Linux)
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.sendto(fd:int, data:str, ip:uint32, port:uint16[, flags:int])
|
2022-06-22 10:04:25 +00:00
|
|
|
|
unix.sendto(fd:int, data:str, unixpath:str[, flags:int])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
├─→ sent:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
This is useful for sending messages over UDP sockets to specific
|
2022-04-24 16:59:22 +00:00
|
|
|
|
addresses.
|
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
`flags` may have any combination (using bitwise OR) of:
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
- `MSG_OOB`
|
|
|
|
|
- `MSG_DONTROUTE`
|
|
|
|
|
- `MSG_NOSIGNAL`
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.shutdown(fd:int, how:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Partially closes socket.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
`how` is set to one of:
|
|
|
|
|
|
|
|
|
|
- `SHUT_RD`: sends a tcp half close for reading
|
|
|
|
|
- `SHUT_WR`: sends a tcp half close for writing
|
|
|
|
|
- `SHUT_RDWR`
|
|
|
|
|
|
|
|
|
|
This system call currently has issues on Macintosh, so portable code
|
|
|
|
|
should log rather than assert failures reported by shutdown().
|
|
|
|
|
|
|
|
|
|
unix.sigprocmask(how:int, newmask:unix.Sigset)
|
|
|
|
|
├─→ oldmask:unix.Sigset
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
Manipulates bitset of signals blocked by process.
|
|
|
|
|
|
|
|
|
|
`how` can be one of:
|
|
|
|
|
|
2022-05-15 06:25:54 +00:00
|
|
|
|
- `SIG_BLOCK`: applies `mask` to set of blocked signals using bitwise OR
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `SIG_UNBLOCK`: removes bits in `mask` from set of blocked signals
|
|
|
|
|
- `SIG_SETMASK`: replaces process signal mask with `mask`
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
`mask` is a unix.Sigset() object (see section below).
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
For example, to temporarily block `SIGTERM` and `SIGINT` so critical
|
|
|
|
|
work won't be interrupted, sigprocmask() can be used as follows:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
newmask = unix.Sigset(unix.SIGTERM)
|
|
|
|
|
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, newmask))
|
|
|
|
|
-- do something...
|
|
|
|
|
assert(unix.sigprocmask(unix.SIG_SETMASK, oldmask))
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.sigaction(sig:int[, handler:func|int[, flags:int[, mask:unix.Sigset]]])
|
|
|
|
|
├─→ oldhandler:func|int, flags:int, mask:unix.Sigset
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
`sig` can be one of:
|
|
|
|
|
|
|
|
|
|
- `unix.SIGINT`
|
|
|
|
|
- `unix.SIGQUIT`
|
|
|
|
|
- `unix.SIGTERM`
|
|
|
|
|
- etc.
|
|
|
|
|
|
|
|
|
|
`handler` can be:
|
|
|
|
|
|
|
|
|
|
- Lua function
|
|
|
|
|
- `unix.SIG_IGN`
|
|
|
|
|
- `unix.SIG_DFL`
|
|
|
|
|
|
|
|
|
|
`flags` can have:
|
|
|
|
|
|
|
|
|
|
- `unix.SA_RESTART`: Enables BSD signal handling semantics. Normally
|
|
|
|
|
i/o entrypoints check for pending signals to deliver. If one gets
|
|
|
|
|
delivered during an i/o call, the normal behavior is to cancel the
|
|
|
|
|
i/o operation and return -1 with `EINTR` in errno. If you use the
|
|
|
|
|
`SA_RESTART` flag then that behavior changes, so that any function
|
|
|
|
|
that's been annotated with @restartable will not return `EINTR`
|
|
|
|
|
and will instead resume the i/o operation. This makes coding
|
|
|
|
|
easier but it can be an anti-pattern if not used carefully, since
|
|
|
|
|
poor usage can easily result in latency issues. It also requires
|
|
|
|
|
one to do more work in signal handlers, so special care needs to
|
|
|
|
|
be given to which C library functions are @asyncsignalsafe.
|
|
|
|
|
|
|
|
|
|
- `unix.SA_RESETHAND`: Causes signal handler to be single-shot. This
|
|
|
|
|
means that, upon entry of delivery to a signal handler, it's reset
|
|
|
|
|
to the `SIG_DFL` handler automatically. You may use the alias
|
|
|
|
|
`SA_ONESHOT` for this flag, which means the same thing.
|
|
|
|
|
|
|
|
|
|
- `unix.SA_NODEFER`: Disables the reentrancy safety check on your signal
|
|
|
|
|
handler. Normally that's a good thing, since for instance if your
|
|
|
|
|
`SIGSEGV` signal handler happens to segfault, you're going to want
|
|
|
|
|
your process to just crash rather than looping endlessly. But in
|
|
|
|
|
some cases it's desirable to use `SA_NODEFER` instead, such as at
|
|
|
|
|
times when you wish to `longjmp()` out of your signal handler and
|
|
|
|
|
back into your program. This is only safe to do across platforms
|
|
|
|
|
for non-crashing signals such as `SIGCHLD` and `SIGINT`. Crash
|
|
|
|
|
handlers should use Xed instead to recover execution, because on
|
|
|
|
|
Windows a `SIGSEGV` or `SIGTRAP` crash handler might happen on a
|
|
|
|
|
separate stack and/or a separate thread. You may use the alias
|
|
|
|
|
`SA_NOMASK` for this flag, which means the same thing.
|
|
|
|
|
|
|
|
|
|
- `unix.SA_NOCLDWAIT`: Changes `SIGCHLD` so the zombie is gone and
|
|
|
|
|
you can't call wait() anymore; similar but may still deliver the
|
|
|
|
|
SIGCHLD.
|
|
|
|
|
|
|
|
|
|
- `unix.SA_NOCLDSTOP`: Lets you set `SIGCHLD` handler that's only
|
|
|
|
|
notified on exit/termination and not notified on `SIGSTOP`,
|
|
|
|
|
`SIGTSTP`, `SIGTTIN`, `SIGTTOU`, or `SIGCONT`.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
2022-07-09 06:06:46 +00:00
|
|
|
|
function OnSigUsr1(sig)
|
|
|
|
|
gotsigusr1 = true
|
|
|
|
|
end
|
2022-04-26 04:16:05 +00:00
|
|
|
|
gotsigusr1 = false
|
2022-07-09 06:06:46 +00:00
|
|
|
|
oldmask = assert(unix.sigprocmask(unix.SIG_BLOCK, unix.Sigset(unix.SIGUSR1)))
|
|
|
|
|
assert(unix.sigaction(unix.SIGUSR1, OnSigUsr1))
|
2022-04-26 04:16:05 +00:00
|
|
|
|
assert(unix.raise(unix.SIGUSR1))
|
2022-07-09 06:06:46 +00:00
|
|
|
|
assert(not gotsigusr1)
|
|
|
|
|
ok, err = unix.sigsuspend(oldmask)
|
|
|
|
|
assert(not ok)
|
|
|
|
|
assert(err:errno() == unix.EINTR)
|
|
|
|
|
assert(gotsigusr1)
|
|
|
|
|
assert(unix.sigprocmask(unix.SIG_SETMASK, oldmask))
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
It's a good idea to not do too much work in a signal handler.
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-09-09 11:20:13 +00:00
|
|
|
|
unix.sigpending()
|
|
|
|
|
├─→ mask:unix.Sigset
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns the set of signals that are pending for delivery.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
unix.sigsuspend([mask:unix.Sigset])
|
2022-04-26 04:16:05 +00:00
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Waits for signal to be delivered.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
The signal mask is temporarily replaced with `mask` during this
|
|
|
|
|
system call. `mask` specifies which signals should be blocked.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setitimer(which[, intervalsec, intns, valuesec, valuens])
|
|
|
|
|
├─→ intervalsec:int, intervalns:int, valuesec:int, valuens:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Causes `SIGALRM` signals to be generated at some point(s) in the
|
|
|
|
|
future. The `which` parameter should be `ITIMER_REAL`.
|
2022-04-21 11:01:42 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Here's an example of how to create a 400 ms interval timer:
|
2022-04-20 16:56:53 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
ticks = 0
|
2022-04-26 04:16:05 +00:00
|
|
|
|
assert(unix.sigaction(unix.SIGALRM, function(sig)
|
2022-04-24 16:59:22 +00:00
|
|
|
|
print('tick no. %d' % {ticks})
|
2022-04-21 16:15:36 +00:00
|
|
|
|
ticks = ticks + 1
|
2022-04-26 04:16:05 +00:00
|
|
|
|
end))
|
|
|
|
|
assert(unix.setitimer(unix.ITIMER_REAL, 0, 400e6, 0, 400e6))
|
2022-04-21 16:15:36 +00:00
|
|
|
|
while true do
|
|
|
|
|
unix.sigsuspend()
|
|
|
|
|
end
|
2022-04-20 16:56:53 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Here's how you'd do a single-shot timeout in 1 second:
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
|
|
|
|
|
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
|
2022-04-16 17:40:23 +00:00
|
|
|
|
|
2022-05-23 17:15:53 +00:00
|
|
|
|
`intns` needs to be on the interval `[0,1000000000)`
|
|
|
|
|
`valuens` needs to be on the interval `[0,1000000000)`
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.strsignal(sig:int) → str
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Turns platform-specific `sig` code into its symbolic name.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
For example:
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
>: unix.strsignal(9)
|
|
|
|
|
"SIGKILL"
|
|
|
|
|
>: unix.strsignal(unix.SIGKILL)
|
|
|
|
|
"SIGKILL"
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Please note that signal numbers are normally different across
|
|
|
|
|
supported platforms, and the constants should be preferred.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.setrlimit(resource:int, soft:int[, hard:int])
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
Changes resource limit.
|
|
|
|
|
|
|
|
|
|
`resource` may be one of:
|
|
|
|
|
|
|
|
|
|
- `RLIMIT_AS` limits the size of the virtual address space. This
|
|
|
|
|
will work on all platforms. It's emulated on XNU and Windows which
|
|
|
|
|
means it won't propagate across execve() currently.
|
|
|
|
|
|
|
|
|
|
- `RLIMIT_CPU` causes `SIGXCPU` to be sent to the process when the
|
|
|
|
|
soft limit on CPU time is exceeded, and the process is destroyed
|
|
|
|
|
when the hard limit is exceeded. It works everywhere but Windows
|
2022-05-15 06:25:54 +00:00
|
|
|
|
where it should be possible to poll getrusage() with setitimer().
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
- `RLIMIT_FSIZE` causes `SIGXFSZ` to sent to the process when the
|
|
|
|
|
soft limit on file size is exceeded and the process is destroyed
|
2022-05-15 06:25:54 +00:00
|
|
|
|
when the hard limit is exceeded. It works everywhere but Windows.
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
- `RLIMIT_NPROC` limits the number of simultaneous processes and it
|
|
|
|
|
should work on all platforms except Windows. Please be advised it
|
|
|
|
|
limits the process, with respect to the activities of the user id
|
|
|
|
|
as a whole.
|
|
|
|
|
|
|
|
|
|
- `RLIMIT_NOFILE` limits the number of open file descriptors and it
|
2022-05-15 06:25:54 +00:00
|
|
|
|
should work on all platforms except Windows (TODO).
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
|
|
|
|
If a limit isn't supported by the host platform, it'll be set to
|
|
|
|
|
127. On most platforms these limits are enforced by the kernel and
|
|
|
|
|
as such are inherited by subprocesses.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
`hard` defaults to whatever was specified in `soft`.
|
|
|
|
|
|
|
|
|
|
unix.getrlimit(resource:int)
|
|
|
|
|
├─→ soft:int, hard:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Returns information about resource limits for current process.
|
|
|
|
|
|
|
|
|
|
unix.getrusage([who:int])
|
|
|
|
|
├─→ unix.Rusage
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns information about resource usage for current process, e.g.
|
|
|
|
|
|
|
|
|
|
>: unix.getrusage()
|
|
|
|
|
{utime={0, 53644000}, maxrss=44896, minflt=545, oublock=24, nvcsw=9}
|
|
|
|
|
|
|
|
|
|
`who` defaults to `RUSAGE_SELF` and can be any of:
|
|
|
|
|
|
|
|
|
|
- `RUSAGE_SELF`: current process
|
|
|
|
|
- `RUSAGE_THREAD`: current thread
|
|
|
|
|
- `RUSAGE_CHILDREN`: not supported on Windows NT
|
|
|
|
|
- `RUSAGE_BOTH`: not supported on non-Linux
|
|
|
|
|
|
|
|
|
|
See the unix.Rusage section below for details on returned fields.
|
2022-04-21 20:44:59 +00:00
|
|
|
|
|
2022-08-11 18:27:25 +00:00
|
|
|
|
unix.pledge([promises:str[, execpromises:str[, mode:int]]])
|
2022-04-29 03:36:33 +00:00
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Restrict system operations.
|
|
|
|
|
|
|
|
|
|
This can be used to sandbox your redbean workers. It allows finer
|
|
|
|
|
customization compared to the `-S` flag.
|
|
|
|
|
|
2022-08-07 23:18:33 +00:00
|
|
|
|
Pledging causes most system calls to become unavailable. If a
|
|
|
|
|
forbidden system call is used, then the process will be killed. In
|
|
|
|
|
that case, on OpenBSD, your system log will explain which promise
|
|
|
|
|
you need. On Linux, we report the promise to stderr, with one
|
|
|
|
|
exception: reporting is currently not possible if you pledge exec.
|
2022-06-27 20:01:58 +00:00
|
|
|
|
|
|
|
|
|
Using pledge is irreversible. On Linux it causes PR_SET_NO_NEW_PRIVS
|
|
|
|
|
to be set on your process.
|
|
|
|
|
|
2022-04-29 03:36:33 +00:00
|
|
|
|
By default exit and exit_group are always allowed. This is useful
|
|
|
|
|
for processes that perform pure computation and interface with the
|
|
|
|
|
parent via shared memory.
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Once pledge is in effect, the chmod functions (if allowed) will not
|
|
|
|
|
permit the sticky/setuid/setgid bits to change. Linux will EPERM here
|
|
|
|
|
and OpenBSD should ignore those three bits rather than crashing.
|
|
|
|
|
|
|
|
|
|
User and group IDs also can't be changed once pledge is in effect.
|
|
|
|
|
OpenBSD should ignore the chown functions without crashing. Linux
|
|
|
|
|
will just EPERM.
|
|
|
|
|
|
2022-04-29 03:36:33 +00:00
|
|
|
|
`promises` is a string that may include any of the following groups
|
2022-07-18 14:23:15 +00:00
|
|
|
|
delimited by spaces. This list has been curated to focus on the
|
|
|
|
|
system calls for which this module provides wrappers. See the
|
|
|
|
|
Cosmopolitan Libc pledge() documentation for a comprehensive and
|
|
|
|
|
authoritative list of raw system calls. Having the raw system call
|
|
|
|
|
list may be useful if you're executing foreign programs.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
stdio
|
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
Allows read, write, send, recv, recvfrom, close, clock_getres,
|
|
|
|
|
clock_gettime, dup, fchdir, fstat, fsync, fdatasync, ftruncate,
|
|
|
|
|
getdents, getegid, getrandom, geteuid, getgid, getgroups,
|
|
|
|
|
getitimer, getpgid, getpgrp, getpid, hgetppid, getresgid,
|
|
|
|
|
getresuid, getrlimit, getsid, gettimeofday, getuid, lseek,
|
|
|
|
|
madvise, brk, mmap/mprotect (PROT_EXEC isn't allowed), msync,
|
|
|
|
|
munmap, gethostname, nanosleep, pipe, pipe2, poll, setitimer,
|
|
|
|
|
shutdown, sigaction, sigsuspend, sigprocmask, socketpair, umask,
|
|
|
|
|
wait4, getrusage, ioctl(FIONREAD), ioctl(FIONBIO), ioctl(FIOCLEX),
|
|
|
|
|
ioctl(FIONCLEX), fcntl(F_GETFD), fcntl(F_SETFD), fcntl(F_GETFL),
|
2022-08-16 02:52:00 +00:00
|
|
|
|
fcntl(F_SETFL), raise, kill(getpid()).
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
rpath
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows chdir, getcwd, open, stat, fstat, access, readlink, chmod,
|
|
|
|
|
chmod, fchmod.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
wpath
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows getcwd, open, stat, fstat, access, readlink, chmod, fchmod.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
cpath
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows rename, link, symlink, unlink, mkdir, rmdir.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
fattr
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows chmod, fchmod, utimensat, futimens.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
flock
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows flock, fcntl(F_GETLK), fcntl(F_SETLK), fcntl(F_SETLKW).
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
tty
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows isatty, tiocgwinsz, tcgets, tcsets, tcsetsw, tcsetsf.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
inet
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows socket (AF_INET), listen, bind, connect, accept,
|
|
|
|
|
getpeername, getsockname, setsockopt, getsockopt.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
unix
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
Allows socket (AF_UNIX), listen, bind, connect, accept,
|
2022-04-29 03:36:33 +00:00
|
|
|
|
getpeername, getsockname, setsockopt, getsockopt.
|
|
|
|
|
|
|
|
|
|
dns
|
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
Allows sendto, recvfrom, socket(AF_INET), connect.
|
|
|
|
|
|
|
|
|
|
recvfd
|
|
|
|
|
|
|
|
|
|
Allows recvmsg, recvmmsg.
|
|
|
|
|
|
|
|
|
|
sendfd
|
|
|
|
|
|
|
|
|
|
Allows sendmsg, sendmmsg.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
proc
|
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
Allows fork, vfork, clone, kill, tgkill, getpriority, setpriority,
|
2022-06-27 20:01:58 +00:00
|
|
|
|
setrlimit, setpgid, setsid.
|
2022-04-29 03:36:33 +00:00
|
|
|
|
|
|
|
|
|
id
|
|
|
|
|
|
|
|
|
|
Allows setuid, setreuid, setresuid, setgid, setregid, setresgid,
|
|
|
|
|
setgroups, setrlimit, getpriority, setpriority.
|
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
settime
|
|
|
|
|
|
|
|
|
|
Allows settimeofday and clock_adjtime.
|
|
|
|
|
|
2022-08-16 02:52:00 +00:00
|
|
|
|
chown
|
|
|
|
|
|
|
|
|
|
Allows chown.
|
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
unveil
|
|
|
|
|
|
|
|
|
|
Allows unveil().
|
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
exec
|
|
|
|
|
|
2022-07-24 09:56:03 +00:00
|
|
|
|
Allows execve.
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-24 09:56:03 +00:00
|
|
|
|
If the executable in question needs a loader, then you will need
|
|
|
|
|
"rpath prot_exec" too. With APE, security is strongest when you
|
2022-07-20 04:18:33 +00:00
|
|
|
|
assimilate your binaries beforehand, using the --assimilate flag,
|
2022-07-24 09:56:03 +00:00
|
|
|
|
or the o//tool/build/assimilate.com program. On OpenBSD this is
|
|
|
|
|
mandatory.
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
prot_exec
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
Allows mmap(PROT_EXEC) and mprotect(PROT_EXEC).
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-20 04:18:33 +00:00
|
|
|
|
This may be needed to launch non-static non-native executables,
|
|
|
|
|
such as non-assimilated APE binaries, or programs that link
|
|
|
|
|
dynamic shared objects, i.e. most Linux distro binaries.
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-23 00:07:25 +00:00
|
|
|
|
`execpromises` only matters if "exec" is specified in `promises`. In
|
|
|
|
|
that case, this specifies the promises that'll apply once execve()
|
|
|
|
|
happens. If this is NULL then the default is used, which is
|
|
|
|
|
unrestricted. OpenBSD allows child processes to escape the sandbox
|
|
|
|
|
(so a pledged OpenSSH server process can do things like spawn a root
|
|
|
|
|
shell). Linux however requires monotonically decreasing privileges.
|
|
|
|
|
This function will will perform some validation on Linux to make
|
|
|
|
|
sure that `execpromises` is a subset of `promises`. Your libc
|
2022-07-18 14:23:15 +00:00
|
|
|
|
wrapper for execve() will then apply its SECCOMP BPF filter later.
|
|
|
|
|
Since Linux has to do this before calling sys_execve(), the executed
|
|
|
|
|
process will be weakened to have execute permissions too.
|
|
|
|
|
|
2022-08-11 18:27:25 +00:00
|
|
|
|
`mode` if specified should specify one penalty:
|
|
|
|
|
|
|
|
|
|
- `unix.PLEDGE_PENALTY_KILL_THREAD` causes the violating thread to
|
|
|
|
|
be killed. This is the default on Linux. It's effectively the
|
|
|
|
|
same as killing the process, since redbean has no threads. The
|
|
|
|
|
termination signal can't be caught and will be either `SIGSYS`
|
|
|
|
|
or `SIGABRT`. Consider enabling stderr logging below so you'll
|
|
|
|
|
know why your program failed. Otherwise check the system log.
|
|
|
|
|
|
|
|
|
|
- `unix.PLEDGE_PENALTY_KILL_PROCESS` causes the process and all
|
|
|
|
|
its threads to be killed. This is always the case on OpenBSD.
|
|
|
|
|
|
|
|
|
|
- `unix.PLEDGE_PENALTY_RETURN_EPERM` causes system calls to just
|
|
|
|
|
return an `EPERM` error instead of killing. This is a gentler
|
|
|
|
|
solution that allows code to display a friendly warning. Please
|
|
|
|
|
note this may lead to weird behaviors if the software being
|
|
|
|
|
sandboxed is lazy about checking error results.
|
|
|
|
|
|
|
|
|
|
`mode` may optionally bitwise or the following flags:
|
|
|
|
|
|
|
|
|
|
- `unix.PLEDGE_STDERR_LOGGING` enables friendly error message
|
|
|
|
|
logging letting you know which promises are needed whenever
|
|
|
|
|
violations occur. Without this, violations will be logged to
|
|
|
|
|
`dmesg` on Linux if the penalty is to kill the process. You
|
|
|
|
|
would then need to manually look up the system call number and
|
|
|
|
|
then cross reference it with the cosmopolitan libc pledge()
|
|
|
|
|
documentation. You can also use `strace -ff` which is easier.
|
|
|
|
|
This is ignored OpenBSD, which already has a good system log.
|
|
|
|
|
Turning on stderr logging (which uses SECCOMP trapping) also
|
|
|
|
|
means that the `unix.WTERMSIG()` on your killed processes will
|
|
|
|
|
always be `unix.SIGABRT` on both Linux and OpenBSD. Otherwise,
|
|
|
|
|
Linux prefers to raise `unix.SIGSYS`.
|
|
|
|
|
|
2022-07-18 14:23:15 +00:00
|
|
|
|
unix.unveil(path:str, permissions:str)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
Restricts filesystem operations, e.g.
|
|
|
|
|
|
|
|
|
|
unix.unveil(".", "r"); -- current dir + children visible
|
|
|
|
|
unix.unveil("/etc", "r"); -- make /etc readable too
|
2022-07-23 12:22:19 +00:00
|
|
|
|
unix.unveil(nil, nil); -- commit and lock policy
|
2022-07-20 22:13:39 +00:00
|
|
|
|
|
|
|
|
|
Unveiling restricts a thread's view of the filesystem to a set of
|
|
|
|
|
allowed paths with specific privileges.
|
|
|
|
|
|
|
|
|
|
Once you start using unveil(), the entire file system is considered
|
|
|
|
|
hidden. You then specify, by repeatedly calling unveil(), which paths
|
2022-07-23 12:22:19 +00:00
|
|
|
|
should become unhidden. When you're finished, you call `unveil(nil,nil)`
|
2022-07-20 22:13:39 +00:00
|
|
|
|
which commits your policy, after which further use is forbidden, in
|
|
|
|
|
the current thread, as well as any threads or processes it spawns.
|
|
|
|
|
|
|
|
|
|
There are some differences between unveil() on Linux versus OpenBSD.
|
|
|
|
|
|
|
|
|
|
1. Build your policy and lock it in one go. On OpenBSD, policies take
|
|
|
|
|
effect immediately and may evolve as you continue to call unveil()
|
|
|
|
|
but only in a more restrictive direction. On Linux, nothing will
|
2022-07-23 12:22:19 +00:00
|
|
|
|
happen until you call `unveil(nil,nil)` which commits and locks.
|
2022-07-20 22:13:39 +00:00
|
|
|
|
|
|
|
|
|
2. Try not to overlap directory trees. On OpenBSD, if directory trees
|
|
|
|
|
overlap, then the most restrictive policy will be used for a given
|
|
|
|
|
file. On Linux overlapping may result in a less restrictive policy
|
|
|
|
|
and possibly even undefined behavior.
|
|
|
|
|
|
|
|
|
|
3. OpenBSD and Linux disagree on error codes. On OpenBSD, accessing
|
|
|
|
|
paths outside of the allowed set raises ENOENT, and accessing ones
|
|
|
|
|
with incorrect permissions raises EACCES. On Linux, both these
|
|
|
|
|
cases raise EACCES.
|
|
|
|
|
|
|
|
|
|
4. Unlike OpenBSD, Linux does nothing to conceal the existence of
|
|
|
|
|
paths. Even with an unveil() policy in place, it's still possible
|
|
|
|
|
to access the metadata of all files using functions like stat()
|
|
|
|
|
and open(O_PATH), provided you know the path. A sandboxed process
|
|
|
|
|
can always, for example, determine how many bytes of data are in
|
|
|
|
|
/etc/passwd, even if the file isn't readable. But it's still not
|
|
|
|
|
possible to use opendir() and go fishing for paths which weren't
|
|
|
|
|
previously known.
|
|
|
|
|
|
|
|
|
|
This system call is supported natively on OpenBSD and polyfilled on
|
|
|
|
|
Linux using the Landlock LSM[1].
|
|
|
|
|
|
|
|
|
|
`path` is the file or directory to unveil
|
|
|
|
|
|
|
|
|
|
`permissions` is a string consisting of zero or more of the
|
|
|
|
|
following characters:
|
|
|
|
|
|
|
|
|
|
- 'r' makes `path` available for read-only path operations,
|
|
|
|
|
corresponding to the pledge promise "rpath".
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
- `w` makes `path` available for write operations, corresponding
|
|
|
|
|
to the pledge promise "wpath".
|
2022-07-18 14:23:15 +00:00
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
- `x` makes `path` available for execute operations,
|
|
|
|
|
corresponding to the pledge promises "exec" and "execnative".
|
2022-06-27 20:01:58 +00:00
|
|
|
|
|
2022-07-20 22:13:39 +00:00
|
|
|
|
- `c` allows `path` to be created and removed, corresponding to
|
|
|
|
|
the pledge promise "cpath".
|
2022-06-27 20:01:58 +00:00
|
|
|
|
|
2022-04-27 12:39:39 +00:00
|
|
|
|
unix.gmtime(unixts:int)
|
|
|
|
|
├─→ year,mon,mday,hour,min,sec,gmtoffsec,wday,yday,dst:int,zone:str
|
|
|
|
|
└─→ nil,unix.Errno
|
|
|
|
|
|
2022-05-12 13:11:22 +00:00
|
|
|
|
Breaks down UNIX timestamp into Zulu Time numbers.
|
2022-04-27 12:39:39 +00:00
|
|
|
|
|
2022-05-12 13:11:22 +00:00
|
|
|
|
- `mon` 1 ≤ mon ≤ 12
|
|
|
|
|
- `mday` 1 ≤ mday ≤ 31
|
|
|
|
|
- `hour` 0 ≤ hour ≤ 23
|
|
|
|
|
- `min` 0 ≤ min ≤ 59
|
|
|
|
|
- `sec` 0 ≤ sec ≤ 60
|
|
|
|
|
- `gmtoff` ±93600 seconds
|
|
|
|
|
- `wday` 0 ≤ wday ≤ 6
|
|
|
|
|
- `yday` 0 ≤ yday ≤ 365
|
|
|
|
|
- `dst` 1 if daylight savings, 0 if not, -1 if not unknown
|
2022-04-27 12:39:39 +00:00
|
|
|
|
|
|
|
|
|
unix.localtime(unixts:int)
|
|
|
|
|
├─→ year,mon,mday,hour,min,sec,gmtoffsec,wday,yday,dst:int,zone:str
|
|
|
|
|
└─→ nil,unix.Errno
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Breaks down UNIX timestamp into local time numbers, e.g.
|
|
|
|
|
|
|
|
|
|
>: unix.localtime(unix.clock_gettime())
|
|
|
|
|
2022 4 28 2 14 22 -25200 4 117 1 "PDT"
|
2022-04-27 12:39:39 +00:00
|
|
|
|
|
2022-05-12 13:11:22 +00:00
|
|
|
|
This follows the same API as gmtime() which has further details.
|
2022-04-27 12:39:39 +00:00
|
|
|
|
|
|
|
|
|
Your redbean ships with a subset of the time zone database.
|
|
|
|
|
|
2022-04-29 07:36:14 +00:00
|
|
|
|
- `/zip/usr/share/zoneinfo/Honolulu` Z-10
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Anchorage` Z -9
|
|
|
|
|
- `/zip/usr/share/zoneinfo/GST` Z -8
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Boulder` Z -6
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Chicago` Z -5
|
|
|
|
|
- `/zip/usr/share/zoneinfo/New_York` Z -4
|
|
|
|
|
- `/zip/usr/share/zoneinfo/UTC` Z +0
|
|
|
|
|
- `/zip/usr/share/zoneinfo/GMT` Z +0
|
|
|
|
|
- `/zip/usr/share/zoneinfo/London` Z +1
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Berlin` Z +2
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Israel` Z +3
|
|
|
|
|
- `/zip/usr/share/zoneinfo/India` Z +5
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Beijing` Z +8
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Japan` Z +9
|
|
|
|
|
- `/zip/usr/share/zoneinfo/Sydney` Z+10
|
2022-04-27 12:39:39 +00:00
|
|
|
|
|
|
|
|
|
You can control which timezone is used using the `TZ` environment
|
|
|
|
|
variable. If your time zone isn't included in the above list, you
|
|
|
|
|
can simply copy it inside your redbean. The same is also the case
|
|
|
|
|
for future updates to the database, which can be swapped out when
|
|
|
|
|
needed, without having to recompile.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.stat(path:str[, flags:int[, dirfd:int]])
|
|
|
|
|
├─→ unix.Stat
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Gets information about file or directory.
|
|
|
|
|
|
|
|
|
|
`flags` may have any of:
|
|
|
|
|
|
|
|
|
|
- `AT_SYMLINK_NOFOLLOW`: do not follow symbolic links.
|
|
|
|
|
|
|
|
|
|
`dirfd` defaults to to `unix.AT_FDCWD` and may optionally be set to
|
|
|
|
|
a directory file descriptor to which `path` is relative.
|
|
|
|
|
|
|
|
|
|
unix.fstat(fd:int)
|
|
|
|
|
├─→ unix.Stat
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Gets information about opened file descriptor.
|
|
|
|
|
|
|
|
|
|
A common use for fstat() is getting the size of a file. For example:
|
|
|
|
|
|
|
|
|
|
fd = assert(unix.open("hello.txt", unix.O_RDONLY))
|
|
|
|
|
st = assert(unix.fstat(fd))
|
|
|
|
|
Log(kLogInfo, 'hello.txt is %d bytes in size' % {st:size()})
|
|
|
|
|
unix.close(fd)
|
|
|
|
|
|
2022-08-18 06:27:17 +00:00
|
|
|
|
unix.statfs(path:str)
|
|
|
|
|
├─→ unix.Statfs
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Gets information about filesystem.
|
|
|
|
|
|
|
|
|
|
`path` is the path of a file or directory in the mounted filesystem.
|
|
|
|
|
|
|
|
|
|
unix.fstatfs(fd:int)
|
|
|
|
|
├─→ unix.Statfs
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Gets information about filesystem.
|
|
|
|
|
|
|
|
|
|
`fd` is an open() file descriptor of a file or directory in the
|
|
|
|
|
mounted filesystem.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.opendir(path:str)
|
|
|
|
|
├─→ state:unix.Dir
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
|
|
|
|
Opens directory for listing its contents.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
For example, to print a simple directory listing:
|
|
|
|
|
|
|
|
|
|
Write('<ul>\r\n')
|
|
|
|
|
for name, kind, ino, off in assert(unix.opendir(dir)) do
|
|
|
|
|
if name ~= '.' and name ~= '..' then
|
|
|
|
|
Write('<li>%s\r\n' % {EscapeHtml(name)})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
Write('</ul>\r\n')
|
|
|
|
|
|
|
|
|
|
unix.fdopendir(fd:int)
|
|
|
|
|
├─→ next:function, state:unix.Dir
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
|
|
|
|
Opens directory for listing its contents, via an fd.
|
2022-04-21 16:15:36 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
`fd` should be created by `open(path, O_RDONLY|O_DIRECTORY)`. The
|
2022-08-17 06:58:26 +00:00
|
|
|
|
returned unix.Dir takes ownership of the file descriptor and will
|
|
|
|
|
close it automatically when garbage collected.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-06-27 20:01:58 +00:00
|
|
|
|
unix.isatty(fd:int)
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
Returns true if file descriptor is a teletypewriter. Otherwise nil
|
|
|
|
|
with an Errno object holding one of the following values:
|
|
|
|
|
|
|
|
|
|
- `ENOTTY` if `fd` is valid but not a teletypewriter
|
|
|
|
|
- `EBADF` if `fd` isn't a valid file descriptor.
|
|
|
|
|
- `EPERM` if pledge() is used without `tty` in lenient mode
|
|
|
|
|
|
|
|
|
|
No other error numbers are possible.
|
2022-06-27 20:01:58 +00:00
|
|
|
|
|
|
|
|
|
unix.tiocgwinsz(fd:int)
|
|
|
|
|
├─→ rows:int, cols:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns cellular dimensions of pseudoteletypewriter display.
|
|
|
|
|
|
2022-08-14 20:28:07 +00:00
|
|
|
|
unix.tmpfd()
|
|
|
|
|
├─→ fd:int
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Returns file descriptor of open anonymous file.
|
|
|
|
|
|
|
|
|
|
This creates a secure temporary file inside `$TMPDIR`. If it isn't
|
|
|
|
|
defined, then `/tmp` is used on UNIX and GetTempPath() is used on
|
|
|
|
|
the New Technology. This resolution of `$TMPDIR` happens once in a
|
|
|
|
|
ctor, which is copied to the `kTmpDir` global.
|
|
|
|
|
|
|
|
|
|
Once close() is called, the returned file is guaranteed to be
|
|
|
|
|
deleted automatically. On UNIX the file is unlink()'d before this
|
|
|
|
|
function returns. On the New Technology it happens upon close().
|
|
|
|
|
|
|
|
|
|
On the New Technology, temporary files created by this function
|
|
|
|
|
should have better performance, because `kNtFileAttributeTemporary`
|
|
|
|
|
asks the kernel to more aggressively cache and reduce i/o ops.
|
|
|
|
|
|
2022-10-06 11:55:26 +00:00
|
|
|
|
unix.sched_yield()
|
|
|
|
|
|
|
|
|
|
Relinquishes scheduled quantum.
|
|
|
|
|
|
|
|
|
|
unix.mapshared(size:int)
|
|
|
|
|
└─→ unix.Memory()
|
|
|
|
|
|
|
|
|
|
Creates interprocess shared memory mapping.
|
|
|
|
|
|
|
|
|
|
This function allocates special memory that'll be inherited across
|
|
|
|
|
fork in a shared way. By default all memory in Redbean is "private"
|
|
|
|
|
memory that's only viewable and editable to the process that owns
|
|
|
|
|
it. When unix.fork() happens, memory is copied appropriately so
|
|
|
|
|
that changes to memory made in the child process, don't clobber
|
|
|
|
|
the memory at those same addresses in the parent process. If you
|
|
|
|
|
don't want that to happen, and you want the memory to be shared
|
|
|
|
|
similar to how it would be shared if you were using threads, then
|
|
|
|
|
you can use this function to achieve just that.
|
|
|
|
|
|
|
|
|
|
The memory object this function returns may be accessed using its
|
|
|
|
|
methods, which support atomics and futexes. It's very low-level.
|
|
|
|
|
For example, you can use it to implement scalable mutexes:
|
|
|
|
|
|
|
|
|
|
mem = unix.mapshared(8000 * 8)
|
|
|
|
|
|
|
|
|
|
LOCK = 0 -- pick an arbitrary word index for lock
|
|
|
|
|
|
|
|
|
|
-- From Futexes Are Tricky Version 1.1 § Mutex, Take 3;
|
|
|
|
|
-- Ulrich Drepper, Red Hat Incorporated, June 27, 2004.
|
|
|
|
|
function Lock()
|
|
|
|
|
local ok, old = mem:cmpxchg(LOCK, 0, 1)
|
|
|
|
|
if not ok then
|
|
|
|
|
if old == 1 then
|
|
|
|
|
old = mem:xchg(LOCK, 2)
|
|
|
|
|
end
|
|
|
|
|
while old > 0 do
|
|
|
|
|
mem:wait(LOCK, 2)
|
|
|
|
|
old = mem:xchg(LOCK, 2)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
function Unlock()
|
2022-10-08 15:39:13 +00:00
|
|
|
|
old = mem:fetch_add(LOCK, -1)
|
2022-10-06 11:55:26 +00:00
|
|
|
|
if old == 2 then
|
|
|
|
|
mem:store(LOCK, 0)
|
|
|
|
|
mem:wake(LOCK, 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
It's possible to accomplish the same thing as unix.mapshared()
|
|
|
|
|
using files and unix.fcntl() advisory locks. However this goes
|
|
|
|
|
significantly faster. For example, that's what SQLite does and
|
|
|
|
|
we recommend using SQLite for IPC in redbean. But, if your app
|
|
|
|
|
has thousands of forked processes fighting for a file lock you
|
|
|
|
|
might need something lower level than file locks, to implement
|
|
|
|
|
things like throttling. Shared memory is a good way to do that
|
|
|
|
|
since there's nothing that's faster.
|
|
|
|
|
|
|
|
|
|
The `size` parameter needs to be a multiple of 8. The returned
|
|
|
|
|
memory is zero initialized. When allocating shared memory, you
|
|
|
|
|
should try to get as much use out of it as possible, since the
|
|
|
|
|
overhead of allocating a single shared mapping is 500 words of
|
|
|
|
|
resident memory and 8000 words of virtual memory. It's because
|
|
|
|
|
the Cosmopolitan Libc mmap() granularity is 2**16.
|
|
|
|
|
|
|
|
|
|
This system call does not fail. An exception is instead thrown
|
|
|
|
|
if sufficient memory isn't available.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
UNIX MEMORY OBJECT
|
|
|
|
|
|
|
|
|
|
unix.Memory encapsulates memory that's shared across fork() and
|
|
|
|
|
this module provides the fundamental synchronization primitives
|
|
|
|
|
|
|
|
|
|
Redbean memory maps may be used in two ways:
|
|
|
|
|
|
|
|
|
|
1. as an array of bytes a.k.a. a string
|
|
|
|
|
2. as an array of words a.k.a. integers
|
|
|
|
|
|
|
|
|
|
They're aliased, union, or overlapped views of the same memory.
|
|
|
|
|
For example if you write a string to your memory region, you'll
|
|
|
|
|
be able to read it back as an integer.
|
|
|
|
|
|
|
|
|
|
Reads, writes, and word operations will throw an exception if a
|
|
|
|
|
memory boundary error or overflow occurs.
|
|
|
|
|
|
|
|
|
|
unix.Memory:read([offset:int[, bytes:int]])
|
|
|
|
|
└─→ str
|
|
|
|
|
|
2022-10-08 15:43:57 +00:00
|
|
|
|
Reads bytes from memory region
|
|
|
|
|
|
2022-10-06 11:55:26 +00:00
|
|
|
|
`offset` is the starting byte index from which memory is copied,
|
|
|
|
|
which defaults to zero.
|
|
|
|
|
|
|
|
|
|
If `bytes` is none or nil, then the nul-terminated string at
|
|
|
|
|
`offset` is returned. You may specify `bytes` to safely read
|
|
|
|
|
binary data.
|
|
|
|
|
|
|
|
|
|
This operation happens atomically. Each shared mapping has a
|
|
|
|
|
single lock which is used to synchronize reads and writes to
|
|
|
|
|
that specific map. To make it scale, create additional maps.
|
|
|
|
|
|
2022-10-08 15:39:13 +00:00
|
|
|
|
unix.Memory:write([offset:int,] data:str[, bytes:int]])
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
Writes bytes to memory region.
|
|
|
|
|
|
|
|
|
|
`offset` is the starting byte index to which memory is copied,
|
|
|
|
|
which defaults to zero.
|
|
|
|
|
|
|
|
|
|
If `bytes` is none or nil, then an implicit nil-terminator
|
|
|
|
|
will be included after your `data` so things like json can
|
|
|
|
|
be easily serialized to shared memory.
|
|
|
|
|
|
|
|
|
|
This operation happens atomically. Each shared mapping has a
|
|
|
|
|
single lock which is used to synchronize reads and writes to
|
|
|
|
|
that specific map. To make it scale, create additional maps.
|
|
|
|
|
|
|
|
|
|
unix.Memory:load(word_index:int)
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Loads word from memory region.
|
|
|
|
|
|
|
|
|
|
This operation is atomic and has relaxed barrier semantics.
|
|
|
|
|
|
|
|
|
|
unix.Memory:store(word_index:int, value:int)
|
|
|
|
|
|
|
|
|
|
Stores word from memory region.
|
|
|
|
|
|
|
|
|
|
This operation is atomic and has relaxed barrier semantics.
|
|
|
|
|
|
|
|
|
|
unix.Memory:xchg(word_index:int, value:int)
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Exchanges value.
|
|
|
|
|
|
|
|
|
|
This sets word at `word_index` to `value` and returns the value
|
2022-10-06 22:08:29 +00:00
|
|
|
|
previously held within that word.
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
This operation is atomic and provides the same memory barrier
|
|
|
|
|
semantics as the aligned x86 LOCK XCHG instruction.
|
|
|
|
|
|
|
|
|
|
unix.Memory:cmpxchg(word_index:int, old:int, new:int)
|
|
|
|
|
└─→ success:bool, old:int
|
|
|
|
|
|
|
|
|
|
Compares and exchanges value.
|
|
|
|
|
|
|
|
|
|
This inspects the word at `word_index` and if its value is the same
|
|
|
|
|
as `old` then it'll be replaced by the value `new`, in which case
|
2022-10-06 22:08:29 +00:00
|
|
|
|
true shall be returned alongside `old`. If a different value was
|
|
|
|
|
held at word, then `false` shall be returned along with its value.
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
This operation happens atomically and provides the same memory
|
|
|
|
|
barrier semantics as the aligned x86 LOCK CMPXCHG instruction.
|
|
|
|
|
|
2022-10-06 16:41:22 +00:00
|
|
|
|
unix.Memory:fetch_add(word_index:int, value:int)
|
2022-10-06 11:55:26 +00:00
|
|
|
|
└─→ old:int
|
|
|
|
|
|
|
|
|
|
Fetches then adds value.
|
|
|
|
|
|
|
|
|
|
This method modifies the word at `word_index` to contain the sum of
|
2022-10-07 10:11:07 +00:00
|
|
|
|
its value and the `value` parameter. This method then returns the
|
2022-10-06 22:08:29 +00:00
|
|
|
|
value as it existed before the addition was performed.
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
This operation is atomic and provides the same memory barrier
|
|
|
|
|
semantics as the aligned x86 LOCK XADD instruction.
|
|
|
|
|
|
2022-10-06 16:41:22 +00:00
|
|
|
|
unix.Memory:fetch_and(word_index:int, value:int)
|
2022-10-06 11:55:26 +00:00
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Fetches and bitwise ands value.
|
|
|
|
|
|
|
|
|
|
This operation happens atomically and provides the same memory
|
|
|
|
|
barrier ordering semantics as its x86 implementation.
|
|
|
|
|
|
2022-10-06 16:41:22 +00:00
|
|
|
|
unix.Memory:fetch_or(word_index:int, value:int)
|
2022-10-06 11:55:26 +00:00
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Fetches and bitwise ors value.
|
|
|
|
|
|
|
|
|
|
This operation happens atomically and provides the same memory
|
|
|
|
|
barrier ordering semantics as its x86 implementation.
|
|
|
|
|
|
2022-10-06 16:41:22 +00:00
|
|
|
|
unix.Memory:fetch_xor(word_index:int, value:int)
|
2022-10-06 11:55:26 +00:00
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Fetches and bitwise xors value.
|
|
|
|
|
|
|
|
|
|
This operation happens atomically and provides the same memory
|
|
|
|
|
barrier ordering semantics as its x86 implementation.
|
|
|
|
|
|
|
|
|
|
unix.Memory:wait(word_index:int, expect:int[, abs_deadline:int[, nanos:int]])
|
|
|
|
|
├─→ 0
|
|
|
|
|
├─→ nil, unix.Errno(unix.EINTR)
|
|
|
|
|
├─→ nil, unix.Errno(unix.EAGAIN)
|
|
|
|
|
└─→ nil, unix.Errno(unix.ETIMEDOUT)
|
|
|
|
|
|
|
|
|
|
Waits for word to have a different value.
|
|
|
|
|
|
|
|
|
|
This method asks the kernel to suspend the process until either the
|
|
|
|
|
absolute deadline expires or we're woken up by another process that
|
|
|
|
|
calls unix.Memory:wake().
|
|
|
|
|
|
2022-10-08 04:29:40 +00:00
|
|
|
|
The `expect` parameter is the value you expect the word to have and
|
|
|
|
|
this function will return if that's not the case. Please note this
|
|
|
|
|
parameter doesn't imply the kernel will poll the value for you, and
|
|
|
|
|
you still need to call wake() when you know the memory's changed.
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
The default behavior is to wait until the heat death of the universe
|
|
|
|
|
if necessary. You may alternatively specify an absolute deadline. If
|
|
|
|
|
it's less than or equal to the value returned by clock_gettime, then
|
|
|
|
|
this routine is non-blocking. Otherwise we'll block at most until
|
|
|
|
|
the current time reaches the absolute deadline.
|
|
|
|
|
|
2022-10-08 04:29:40 +00:00
|
|
|
|
Futexes are supported natively on Linux, FreeBSD, and OpenBSD. When
|
|
|
|
|
this interface is used on other platforms this method will manually
|
|
|
|
|
poll the memory location with exponential backoff. Doing this works
|
|
|
|
|
well enough that we're passing the *NSYNC unit tests, but is not as
|
|
|
|
|
low latency as having kernel supported futexes.
|
2022-10-06 11:55:26 +00:00
|
|
|
|
|
|
|
|
|
`EINTR` if a signal is delivered while waiting on deadline. Callers
|
|
|
|
|
should use futexes inside a loop that is able to cope with spurious
|
|
|
|
|
wakeups. We don't actually guarantee the value at word has in fact
|
|
|
|
|
changed when this returns.
|
|
|
|
|
|
|
|
|
|
`EAGAIN` is raised if, upon entry, the word at `word_index` had a
|
|
|
|
|
different value than what's specified at `expect`.
|
|
|
|
|
|
|
|
|
|
`ETIMEDOUT` is raised when the absolute deadline expires.
|
|
|
|
|
|
|
|
|
|
unix.Memory:wake(index:int[, count:int])
|
|
|
|
|
└─→ woken:int
|
|
|
|
|
|
|
|
|
|
Wakes other processes waiting on word.
|
|
|
|
|
|
|
|
|
|
This method may be used to signal or broadcast to waiters. The
|
|
|
|
|
`count` specifies the number of processes that should be woken,
|
|
|
|
|
which defaults to `INT_MAX`.
|
|
|
|
|
|
|
|
|
|
The return value is the number of processes that were actually woken
|
|
|
|
|
as a result of the system call. No failure conditions are defined.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-24 16:59:22 +00:00
|
|
|
|
UNIX DIR OBJECT
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.Dir objects are created by opendir() or fdopendir(). The
|
2022-04-24 16:59:22 +00:00
|
|
|
|
following methods are available:
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.Dir:close()
|
|
|
|
|
├─→ true
|
|
|
|
|
└─→ nil, unix.Errno
|
|
|
|
|
|
|
|
|
|
Closes directory stream object and associated its file descriptor.
|
|
|
|
|
|
|
|
|
|
This is called automatically by the garbage collector.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
This may be called multiple times.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.Dir:read()
|
|
|
|
|
├─→ name:str, kind:int, ino:int, off:int
|
|
|
|
|
└─→ nil
|
|
|
|
|
|
|
|
|
|
Reads entry from directory stream.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
Returns `nil` if there are no more entries. On error, `nil` will
|
2022-04-21 16:15:36 +00:00
|
|
|
|
be returned and `errno` will be non-nil.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
`kind` can be any of:
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
- `DT_REG`: file is a regular file
|
|
|
|
|
- `DT_DIR`: file is a directory
|
|
|
|
|
- `DT_BLK`: file is a block device
|
|
|
|
|
- `DT_LNK`: file is a symbolic link
|
|
|
|
|
- `DT_CHR`: file is a character device
|
|
|
|
|
- `DT_FIFO`: file is a named pipe
|
|
|
|
|
- `DT_SOCK`: file is a named socket
|
2022-04-25 15:30:14 +00:00
|
|
|
|
- `DT_UNKNOWN`
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
Note: This function also serves as the `__call` metamethod, so that
|
|
|
|
|
unix.Dir objects may be used as a for loop iterator.
|
|
|
|
|
|
|
|
|
|
unix.Dir:fd()
|
|
|
|
|
├─→ fd:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Returns file descriptor of open directory object.
|
|
|
|
|
|
|
|
|
|
Returns `EOPNOTSUPP` if using a `/zip/...` path.
|
|
|
|
|
Returns `EOPNOTSUPP` if using Windows NT.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.Dir:tell()
|
|
|
|
|
├─→ off:int
|
|
|
|
|
└─→ nil, unix.Errno
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Returns current arbitrary offset into stream.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.Dir:rewind()
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-21 16:15:36 +00:00
|
|
|
|
Resets stream back to beginning.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
UNIX RUSAGE OBJECT
|
|
|
|
|
|
|
|
|
|
unix.Rusage objects are created by wait() or getrusage(). The
|
|
|
|
|
following accessor methods are available.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:utime()
|
|
|
|
|
└─→ seconds:int, nanos:int
|
|
|
|
|
|
|
|
|
|
Returns amount of CPU consumed in userspace.
|
|
|
|
|
|
|
|
|
|
It's always the case that `0 ≤ nanos < 1e9`.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is collected from GetProcessTimes().
|
|
|
|
|
|
|
|
|
|
unix.Rusage:stime()
|
|
|
|
|
└─→ seconds:int, nanos:int
|
|
|
|
|
|
|
|
|
|
Returns amount of CPU consumed in kernelspace.
|
|
|
|
|
|
|
|
|
|
It's always the case that `0 ≤ 𝑥 < 1e9`.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is collected from GetProcessTimes().
|
|
|
|
|
|
|
|
|
|
unix.Rusage:maxrss()
|
|
|
|
|
└─→ kilobytes:int
|
|
|
|
|
|
|
|
|
|
Returns amount of physical memory used at peak consumption.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is collected from
|
|
|
|
|
NtProcessMemoryCountersEx::PeakWorkingSetSize / 1024.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
unix.Rusage:idrss()
|
2022-04-28 16:42:36 +00:00
|
|
|
|
└─→ integralkilobytes:int
|
|
|
|
|
|
|
|
|
|
Returns integral private memory consumption w.r.t. scheduled ticks.
|
|
|
|
|
|
|
|
|
|
If you chart memory usage over the lifetime of your process, then
|
|
|
|
|
this would be the space filled in beneath the chart. The frequency
|
|
|
|
|
of kernel scheduling is defined as unix.CLK_TCK. Each time a tick
|
|
|
|
|
happens, the kernel samples your process's memory usage, by adding
|
|
|
|
|
it to this value. You can derive the average consumption from this
|
|
|
|
|
value by computing how many ticks are in `utime + stime`.
|
|
|
|
|
|
|
|
|
|
Currently only available on FreeBSD and NetBSD.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:ixrss()
|
|
|
|
|
└─→ integralkilobytes:int
|
|
|
|
|
|
|
|
|
|
Returns integral shared memory consumption w.r.t. scheduled ticks.
|
|
|
|
|
|
|
|
|
|
If you chart memory usage over the lifetime of your process, then
|
|
|
|
|
this would be the space filled in beneath the chart. The frequency
|
|
|
|
|
of kernel scheduling is defined as unix.CLK_TCK. Each time a tick
|
|
|
|
|
happens, the kernel samples your process's memory usage, by adding
|
|
|
|
|
it to this value. You can derive the average consumption from this
|
|
|
|
|
value by computing how many ticks are in `utime + stime`.
|
|
|
|
|
|
|
|
|
|
Currently only available on FreeBSD and NetBSD.
|
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
unix.Rusage:isrss()
|
2022-04-28 16:42:36 +00:00
|
|
|
|
└─→ integralkilobytes:int
|
|
|
|
|
|
|
|
|
|
Returns integral stack memory consumption w.r.t. scheduled ticks.
|
|
|
|
|
|
|
|
|
|
If you chart memory usage over the lifetime of your process, then
|
|
|
|
|
this would be the space filled in beneath the chart. The frequency
|
|
|
|
|
of kernel scheduling is defined as unix.CLK_TCK. Each time a tick
|
|
|
|
|
happens, the kernel samples your process's memory usage, by adding
|
|
|
|
|
it to this value. You can derive the average consumption from this
|
|
|
|
|
value by computing how many ticks are in `utime + stime`.
|
|
|
|
|
|
|
|
|
|
This is only applicable to redbean if its built with MODE=tiny,
|
|
|
|
|
because redbean likes to allocate its own deterministic stack.
|
|
|
|
|
|
|
|
|
|
Currently only available on FreeBSD and NetBSD.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:minflt()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of minor page faults.
|
|
|
|
|
|
|
|
|
|
This number indicates how many times redbean was preempted by the
|
|
|
|
|
kernel to memcpy() a 4096-byte page. This is one of the tradeoffs
|
|
|
|
|
fork() entails. This number is usually tinier, when your binaries
|
|
|
|
|
are tinier.
|
|
|
|
|
|
|
|
|
|
Not available on Windows NT.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:majflt()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of major page faults.
|
|
|
|
|
|
|
|
|
|
This number indicates how many times redbean was preempted by the
|
|
|
|
|
kernel to perform i/o. For example, you might have used mmap() to
|
|
|
|
|
load a large file into memory lazily.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is NtProcessMemoryCountersEx::PageFaultCount.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:nswap()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of swap operations.
|
|
|
|
|
|
|
|
|
|
Operating systems like to reserve hard disk space to back their RAM
|
|
|
|
|
guarantees, like using a gold standard for fiat currency. When your
|
|
|
|
|
system is under heavy memory load, swap operations may happen while
|
|
|
|
|
redbean is working. This number keeps track of them.
|
|
|
|
|
|
|
|
|
|
Not available on Linux, Windows NT.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:inblock()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of times filesystem had to perform input.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is NtIoCounters::ReadOperationCount.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:oublock()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of times filesystem had to perform output.
|
|
|
|
|
|
|
|
|
|
On Windows NT this is NtIoCounters::WriteOperationCount.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:msgsnd()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns count of ipc messages sent.
|
|
|
|
|
|
|
|
|
|
Not available on Linux, Windows NT.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:msgrcv()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns count of ipc messages received.
|
|
|
|
|
|
|
|
|
|
Not available on Linux, Windows NT.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:nsignals()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of signals received.
|
|
|
|
|
|
|
|
|
|
Not available on Linux.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:nvcsw()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of voluntary context switches.
|
|
|
|
|
|
|
|
|
|
This number is a good thing. It means your redbean finished its work
|
|
|
|
|
quickly enough within a time slice that it was able to give back the
|
|
|
|
|
remaining time to the system.
|
|
|
|
|
|
|
|
|
|
unix.Rusage:nivcsw()
|
|
|
|
|
└─→ count:int
|
|
|
|
|
|
|
|
|
|
Returns number of non-consensual context switches.
|
|
|
|
|
|
|
|
|
|
This number is a bad thing. It means your redbean was preempted by a
|
|
|
|
|
higher priority process after failing to finish its work, within the
|
|
|
|
|
allotted time slice.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-24 16:59:22 +00:00
|
|
|
|
UNIX STAT OBJECT
|
|
|
|
|
|
2022-04-25 15:30:14 +00:00
|
|
|
|
unix.Stat objects are created by stat() or fstat(). The following
|
2022-04-28 16:42:36 +00:00
|
|
|
|
accessor methods are available.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:size()
|
|
|
|
|
└─→ bytes:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Size of file in bytes.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:mode()
|
|
|
|
|
└─→ mode:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Contains file type and permissions.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
For example, `0010644` is what you might see for a file and
|
|
|
|
|
`0040755` is what you might see for a directory.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
To determine the file type:
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-06-23 11:05:51 +00:00
|
|
|
|
- `unix.S_ISREG(st:mode())` means regular file
|
|
|
|
|
- `unix.S_ISDIR(st:mode())` means directory
|
|
|
|
|
- `unix.S_ISLNK(st:mode())` means symbolic link
|
|
|
|
|
- `unix.S_ISCHR(st:mode())` means character device
|
|
|
|
|
- `unix.S_ISBLK(st:mode())` means block device
|
|
|
|
|
- `unix.S_ISFIFO(st:mode())` means fifo or pipe
|
|
|
|
|
- `unix.S_ISSOCK(st:mode())` means socket
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:uid()
|
|
|
|
|
└─→ uid:int
|
|
|
|
|
|
|
|
|
|
User ID of file owner.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:gid()
|
|
|
|
|
└─→ gid:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Group ID of file owner.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:birthtim()
|
|
|
|
|
└─→ unixts:int, nanos:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
File birth time.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This field should be accurate on Apple, Windows, and BSDs. On Linux
|
2022-07-16 18:00:28 +00:00
|
|
|
|
this is the minimum of atim/mtim/ctim. On Windows NT nanos is only
|
2022-04-28 16:42:36 +00:00
|
|
|
|
accurate to hectonanoseconds.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Here's an example of how you might print a file timestamp:
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
st = assert(unix.stat('/etc/passwd'))
|
|
|
|
|
unixts, nanos = st:birthtim()
|
|
|
|
|
year,mon,mday,hour,min,sec,gmtoffsec = unix.localtime(unixts)
|
|
|
|
|
Write('%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.9d%+.2d%.2d % {
|
|
|
|
|
year, mon, mday, hour, min, sec, nanos,
|
|
|
|
|
gmtoffsec / (60 * 60), math.abs(gmtoffsec) % 60})
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:mtim()
|
|
|
|
|
└─→ unixts:int, nanos:int
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Last modified time.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:atim()
|
|
|
|
|
└─→ unixts:int, nanos:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Last access time.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Please note that file systems are sometimes mounted with `noatime`
|
|
|
|
|
out of concern for i/o performance. Linux also provides `O_NOATIME`
|
|
|
|
|
as an option for open().
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
On Windows NT this is the same as birth time.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:ctim()
|
|
|
|
|
└─→ unixts:int, nanos:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Complicated time.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Means time file status was last changed on UNIX.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
On Windows NT this is the same as birth time.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:blocks()
|
|
|
|
|
└─→ count512:int
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Number of 512-byte blocks used by storage medium.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This provides some indication of how much physical storage a file
|
|
|
|
|
actually consumes. For example, for small file systems, your system
|
|
|
|
|
might report this number as being 8, which means 4096 bytes.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
On Windows NT, if `O_COMPRESSED` is used for a file, then this
|
|
|
|
|
number will reflect the size *after* compression. you can use:
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
st = assert(unix.stat("moby.txt"))
|
|
|
|
|
print('file size is %d bytes' % {st:size()})
|
|
|
|
|
print('file takes up %d bytes of space' % {st:blocks() * 512})
|
|
|
|
|
if GetHostOs() == 'WINDOWS' and st:flags() & 0x800 then
|
|
|
|
|
print('thanks to file system compression')
|
|
|
|
|
end
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-08-17 06:58:26 +00:00
|
|
|
|
To tell if compression is used on a file.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:blksize()
|
|
|
|
|
└─→ bytes:int
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Block size that underlying device uses.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This field might be of assistance in computing optimal i/o sizes.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Please note this field has no relationship to blocks, as the latter
|
|
|
|
|
is fixed at a 512 byte size.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:ino()
|
|
|
|
|
└─→ inode:int
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Inode number.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This can be used to detect some other process used rename() to swap
|
|
|
|
|
out a file underneath you, so you can do a refresh. redbean does it
|
|
|
|
|
during each main process heartbeat for its own use cases.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
On Windows NT this is set to NtByHandleFileInformation::FileIndex.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:dev()
|
|
|
|
|
└─→ dev:int
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
ID of device containing file.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
On Windows NT this is set to
|
|
|
|
|
NtByHandleFileInformation::VolumeSerialNumber.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.Stat:rdev()
|
|
|
|
|
└─→ rdev:int
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Information about device type.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This value may be set to 0 or -1 for files that aren't devices,
|
|
|
|
|
depending on the operating system. unix.major() and unix.minor()
|
|
|
|
|
may be used to extract the device numbers.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
|
2022-08-18 06:27:17 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
UNIX STATFS OBJECT
|
|
|
|
|
|
|
|
|
|
unix.Statfs objects are created by statfs() or fstatfs(). The
|
|
|
|
|
following accessor methods are available.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:fstypename()
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Type of filesystem.
|
|
|
|
|
|
|
|
|
|
Here's some examples of likely values:
|
|
|
|
|
|
|
|
|
|
- `"ext"` on Linux
|
|
|
|
|
- `"xfs"` on RHEL7
|
|
|
|
|
- `"apfs"` on Apple
|
|
|
|
|
- `"zfs"` on FreeBSD
|
|
|
|
|
- `"ffs"` on NetBSD and OpenBSD
|
|
|
|
|
- `"NTFS"` on Windows
|
|
|
|
|
|
|
|
|
|
unix.Statfs:type()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Type of filesystem.
|
|
|
|
|
|
|
|
|
|
This is a platform-specific magic number. Consider using the
|
|
|
|
|
unix.Statfs:fstypename() method instead. On Windows, this will
|
|
|
|
|
actually be a Knuth multiplicative hash of the name.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:bsize()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Optimal transfer block size.
|
|
|
|
|
|
|
|
|
|
This field serves two purposes:
|
|
|
|
|
|
|
|
|
|
1. It tells you how to chunk i/o operations. For local disks,
|
|
|
|
|
it'll likely be any value between 512 and 4096 depending on the
|
|
|
|
|
operating system. For network filesystems it will likely be a
|
|
|
|
|
much larger value, e.g. 512kb.
|
|
|
|
|
|
|
|
|
|
2. It can be multiplied with the fields `blocks`, `bfree`, and
|
|
|
|
|
`bavail` to obtain a byte count.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:blocks()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Total data blocks in filesystem.
|
|
|
|
|
|
|
|
|
|
The size of a block is measured as unix.Statfs:bsize().
|
|
|
|
|
|
|
|
|
|
unix.Statfs:bfree()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Total free blocks in filesystem.
|
|
|
|
|
|
|
|
|
|
The size of a block is measured as unix.Statfs:bsize().
|
|
|
|
|
|
|
|
|
|
unix.Statfs:bavail()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Total free blocks available in filesystem to unprivileged users.
|
|
|
|
|
|
|
|
|
|
The size of a block is measured as unix.Statfs:bsize().
|
|
|
|
|
|
|
|
|
|
unix.Statfs:files()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Total file nodes in filesystem.
|
|
|
|
|
|
|
|
|
|
On Windows this is always the maximum integer value.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:ffree()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Total free file nodes in filesystem.
|
|
|
|
|
|
|
|
|
|
On Windows this is always the maximum integer value.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:fsid()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Filesystem id.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:namelen()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Maximum length of filename components in bytes.
|
|
|
|
|
|
|
|
|
|
unix.Statfs:flags()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
Filesystem flags.
|
|
|
|
|
|
|
|
|
|
The following flags are defined:
|
|
|
|
|
|
|
|
|
|
- `ST_RDONLY`: Read-only filesystem (Linux/Windows/XNU/BSDs)
|
|
|
|
|
- `ST_NOSUID`: Setuid binaries forbidden (Linux/XNU/BSDs)
|
|
|
|
|
- `ST_NODEV`: Device files forbidden (Linux/XNU/BSDs)
|
|
|
|
|
- `ST_NOEXEC`: Execution forbidden (Linux/XNU/BSDs)
|
|
|
|
|
- `ST_SYNCHRONOUS`: Synchronous (Linux/XNU/BSDs)
|
|
|
|
|
- `ST_NOATIME`: No access time (Linux/XNU/BSDs)
|
|
|
|
|
- `ST_RELATIME`: Relative access time (Linux/NetBSD)
|
|
|
|
|
- `ST_APPEND`: Linux-only
|
|
|
|
|
- `ST_IMMUTABLE`: Linux-only
|
|
|
|
|
- `ST_MANDLOCK`: Linux-only
|
|
|
|
|
- `ST_NODIRATIME`: Linux-only
|
|
|
|
|
- `ST_WRITE`: Linux-only
|
|
|
|
|
|
|
|
|
|
unix.Statfs:owner()
|
|
|
|
|
└─→ int
|
|
|
|
|
|
|
|
|
|
User id of owner of filesystem mount.
|
|
|
|
|
|
|
|
|
|
On Linux this is always 0 for root. On Windows this is always 0.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
UNIX SIGSET OBJECT
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
The unix.Sigset class defines a mutable bitset that may currently
|
|
|
|
|
contain 128 entries. See `unix.NSIG` to find out how many signals
|
|
|
|
|
your operating system actually supports.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.Sigset(sig:int, ...)
|
|
|
|
|
└─→ unix.Sigset
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Constructs new signal bitset object.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.Sigset:add(sig:int)
|
|
|
|
|
|
|
|
|
|
Adds signal to bitset.
|
|
|
|
|
|
|
|
|
|
unix.Sigset:remove(sig:int)
|
|
|
|
|
|
|
|
|
|
Removes signal from bitset.
|
|
|
|
|
|
|
|
|
|
unix.Sigset:fill()
|
|
|
|
|
|
|
|
|
|
Sets all bits in signal bitset to true.
|
|
|
|
|
|
|
|
|
|
unix.Sigset:clear()
|
|
|
|
|
|
|
|
|
|
Sets all bits in signal bitset to false.
|
|
|
|
|
|
|
|
|
|
unix.Sigset:contains(sig:int)
|
|
|
|
|
└─→ bool
|
|
|
|
|
|
|
|
|
|
Returns true if `sig` is member of signal bitset.
|
|
|
|
|
|
|
|
|
|
unix.Sigset:__repr()
|
|
|
|
|
unix.Sigset:__tostring()
|
|
|
|
|
|
|
|
|
|
Returns Lua code string that recreates object.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-28 16:42:36 +00:00
|
|
|
|
UNIX SIGNAL MAGNUMS
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.SIGINT
|
|
|
|
|
Terminal CTRL-C keystroke.
|
|
|
|
|
|
|
|
|
|
unix.SIGQUIT
|
|
|
|
|
Terminal CTRL-\ keystroke.
|
|
|
|
|
|
|
|
|
|
unix.SIGHUP
|
|
|
|
|
Terminal hangup or daemon reload; auto-broadcasted to process group.
|
|
|
|
|
|
|
|
|
|
unix.SIGILL
|
|
|
|
|
Illegal instruction.
|
|
|
|
|
|
|
|
|
|
unix.SIGTRAP
|
|
|
|
|
INT3 instruction.
|
|
|
|
|
|
|
|
|
|
unix.SIGABRT
|
|
|
|
|
Process aborted.
|
|
|
|
|
|
|
|
|
|
unix.SIGBUS
|
|
|
|
|
Valid memory access that went beyond underlying end of file.
|
|
|
|
|
|
|
|
|
|
unix.SIGFPE
|
|
|
|
|
Illegal math.
|
|
|
|
|
|
|
|
|
|
unix.SIGKILL
|
|
|
|
|
Terminate with extreme prejudice.
|
|
|
|
|
|
|
|
|
|
unix.SIGUSR1
|
|
|
|
|
Do whatever you want.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.SIGUSR2
|
|
|
|
|
Do whatever you want.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.SIGSEGV
|
|
|
|
|
Invalid memory access.
|
|
|
|
|
|
|
|
|
|
unix.SIGPIPE
|
|
|
|
|
Write to closed file descriptor.
|
|
|
|
|
|
|
|
|
|
unix.SIGALRM
|
|
|
|
|
Sent by setitimer().
|
|
|
|
|
|
|
|
|
|
unix.SIGTERM
|
|
|
|
|
Terminate.
|
|
|
|
|
|
|
|
|
|
unix.SIGCHLD
|
|
|
|
|
Child process exited or terminated and is now a zombie (unless this
|
|
|
|
|
is SIG_IGN or SA_NOCLDWAIT) or child process stopped due to terminal
|
|
|
|
|
i/o or profiling/debugging (unless you used SA_NOCLDSTOP)
|
|
|
|
|
|
|
|
|
|
unix.SIGCONT
|
|
|
|
|
Child process resumed from profiling/debugging.
|
|
|
|
|
|
|
|
|
|
unix.SIGSTOP
|
|
|
|
|
Child process stopped due to profiling/debugging.
|
|
|
|
|
|
|
|
|
|
unix.SIGTSTP
|
|
|
|
|
Terminal CTRL-Z keystroke.
|
|
|
|
|
|
|
|
|
|
unix.SIGTTIN
|
|
|
|
|
Terminal input for background process.
|
|
|
|
|
|
|
|
|
|
unix.SIGTTOU
|
|
|
|
|
Terminal output for background process.
|
|
|
|
|
|
|
|
|
|
unix.SIGXCPU
|
|
|
|
|
CPU time limit exceeded.
|
|
|
|
|
|
|
|
|
|
unix.SIGXFSZ
|
|
|
|
|
File size limit exceeded.
|
|
|
|
|
|
|
|
|
|
unix.SIGVTALRM
|
|
|
|
|
Virtual alarm clock.
|
|
|
|
|
|
|
|
|
|
unix.SIGPROF
|
|
|
|
|
Profiling timer expired.
|
|
|
|
|
|
|
|
|
|
unix.SIGWINCH
|
|
|
|
|
Terminal resized.
|
|
|
|
|
|
|
|
|
|
unix.SIGPWR
|
|
|
|
|
Not implemented in most community editions of system five.
|
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
UNIX ERRNO OBJECT
|
|
|
|
|
|
|
|
|
|
This object is returned by system calls that fail. We prefer returning
|
|
|
|
|
an object because for many system calls, an error is part their normal
|
|
|
|
|
operation. For example, it's often desirable to use the errno() method
|
|
|
|
|
when performing a read() to check for EINTR.
|
|
|
|
|
|
|
|
|
|
unix.Errno:errno()
|
|
|
|
|
└─→ errno:int
|
|
|
|
|
|
|
|
|
|
Returns error magic number.
|
|
|
|
|
|
|
|
|
|
The error number is always different for different platforms. On
|
|
|
|
|
UNIX systems, error numbers occupy the range [1,127] in practice.
|
|
|
|
|
The System V ABI reserves numbers as high as 4095. On Windows NT,
|
|
|
|
|
error numbers can go up to 65535.
|
|
|
|
|
|
|
|
|
|
unix.Errno:winerr()
|
|
|
|
|
└─→ errno:int
|
|
|
|
|
|
|
|
|
|
Returns Windows error number.
|
|
|
|
|
|
|
|
|
|
On UNIX systems this is always 0. On Windows NT this will normally
|
|
|
|
|
be the same as errno(). Because Windows defines so many error codes,
|
|
|
|
|
there's oftentimes a multimapping between its error codes and System
|
|
|
|
|
Five. In those cases, this value reflect the GetLastError() result
|
|
|
|
|
at the time the error occurred.
|
|
|
|
|
|
|
|
|
|
unix.Errno:name()
|
|
|
|
|
└─→ symbol:str
|
|
|
|
|
|
|
|
|
|
Returns string of symbolic name of System Five error code.
|
|
|
|
|
|
|
|
|
|
For example, this might return `"EINTR"`.
|
|
|
|
|
|
|
|
|
|
unix.Errno:call()
|
|
|
|
|
└─→ symbol:str
|
|
|
|
|
|
|
|
|
|
Returns name of system call that failed.
|
|
|
|
|
|
|
|
|
|
For example, this might return `"read"` if read() was what failed.
|
|
|
|
|
|
|
|
|
|
unix.Errno:doc()
|
|
|
|
|
└─→ symbol:str
|
|
|
|
|
|
|
|
|
|
Returns English string describing System Five error code.
|
|
|
|
|
|
|
|
|
|
For example, this might return `"Interrupted system call"`.
|
|
|
|
|
|
|
|
|
|
unix.Errno:__tostring()
|
|
|
|
|
└─→ str
|
|
|
|
|
|
|
|
|
|
Returns verbose string describing error.
|
|
|
|
|
|
|
|
|
|
Different information components are delimited by slash.
|
|
|
|
|
|
|
|
|
|
For example, this might return `"EINTR/4/Interrupted system call"`.
|
|
|
|
|
|
|
|
|
|
On Windows NT this will include additional information about the
|
|
|
|
|
Windows error (including FormatMessage() output) if the WIN32 error
|
|
|
|
|
differs from the System Five error code.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-28 16:42:36 +00:00
|
|
|
|
UNIX ERROR MAGNUMS
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EINVAL
|
|
|
|
|
Invalid argument.
|
|
|
|
|
|
|
|
|
|
Raised by [pretty much everything].
|
|
|
|
|
|
|
|
|
|
unix.ENOSYS
|
|
|
|
|
System call not available on this platform. On Windows this is
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by chroot, setuid, setgid, getsid, setsid.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOENT
|
|
|
|
|
No such file or directory.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, bind, chdir, chmod, chown, chroot, clock_getres,
|
|
|
|
|
execve, opendir, inotify_add_watch, link, mkdir, mknod, open,
|
|
|
|
|
readlink, rename, rmdir, stat, swapon, symlink, truncate, unlink,
|
|
|
|
|
utime, utimensat.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOTDIR
|
|
|
|
|
Not a directory. This means that a directory component in a supplied
|
|
|
|
|
path *existed* but wasn't a directory. For example, if you try to
|
|
|
|
|
`open("foo/bar")` and `foo` is a regular file, then `ENOTDIR` will
|
|
|
|
|
be returned.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by open, access, chdir, chroot, execve, link, mkdir, mknod,
|
|
|
|
|
opendir, readlink, rename, rmdir, stat, symlink, truncate, unlink,
|
|
|
|
|
utimensat, bind, chmod, chown, fcntl, futimesat, inotify_add_watch.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EINTR
|
|
|
|
|
The greatest of all errnos; crucial for building real time reliable
|
|
|
|
|
software.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, clock_nanosleep, close, connect, dup, fcntl,
|
|
|
|
|
flock, getrandom, nanosleep, open, pause, poll, ptrace, read, recv,
|
|
|
|
|
select, send, sigsuspend, sigwaitinfo, truncate, wait, write.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EIO
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, acct, chdir, chmod, chown, chroot, close,
|
|
|
|
|
copy_file_range, execve, fallocate, fsync, ioperm, link, madvise,
|
|
|
|
|
mbind, pciconfig_read, ptrace, read, readlink, sendfile, statfs,
|
|
|
|
|
symlink, sync_file_range, truncate, unlink, write.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENXIO
|
|
|
|
|
No such device or address.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by lseek, open, prctl
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.E2BIG
|
|
|
|
|
Argument list too long.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by execve, sched_setattr.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOEXEC
|
|
|
|
|
Exec format error.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by execve, uselib.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ECHILD
|
|
|
|
|
No child process.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by wait, waitpid, waitid, wait3, wait4.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ESRCH
|
|
|
|
|
No such process.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by getpriority, getrlimit, getsid, ioprio_set, kill, setpgid,
|
|
|
|
|
tkill, utimensat.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EBADF
|
|
|
|
|
Bad file descriptor; cf. EBADFD.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, access, bind, chdir, chmod, chown, close, connect,
|
|
|
|
|
copy_file_range, dup, fcntl, flock, fsync, futimesat, opendir,
|
2022-08-17 20:41:21 +00:00
|
|
|
|
getpeername, getsockname, getsockopt, ioctl, link, listen, lseek,
|
|
|
|
|
mkdir, mknod, mmap, open, prctl, read, readahead, readlink, recv,
|
|
|
|
|
rename, select, send, shutdown, splice, stat, symlink, sync,
|
|
|
|
|
sync_file_range, timerfd_create, truncate, unlink, utimensat, write.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EAGAIN
|
|
|
|
|
Resource temporarily unavailable (e.g. SO_RCVTIMEO expired, too many
|
|
|
|
|
processes, too much memory locked, read or write with O_NONBLOCK
|
|
|
|
|
needs polling, etc.).
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, connect, fcntl, fork, getrandom, mincore, mlock,
|
|
|
|
|
mmap, mremap, poll, read, select, send, setresuid, setreuid, setuid,
|
|
|
|
|
sigwaitinfo, splice, tee, timer_create, timerfd_create, tkill,
|
|
|
|
|
write,
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EPIPE
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Broken pipe. Returned by write, send. This happens when you try
|
|
|
|
|
to write data to a subprocess via a pipe but the reader end has
|
2022-04-26 04:16:05 +00:00
|
|
|
|
already closed, possibly because the process died. Normally i/o
|
|
|
|
|
routines only return this if `SIGPIPE` doesn't kill the process.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
Unlike default UNIX programs, redbean currently ignores `SIGPIPE` by
|
|
|
|
|
default, so this error code is a distinct possibility when pipes or
|
|
|
|
|
sockets are being used.
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENAMETOOLONG
|
|
|
|
|
Filename too long. Cosmopolitan Libc currently defines `PATH_MAX` as
|
2022-04-28 16:42:36 +00:00
|
|
|
|
1024 characters. On UNIX that limit should only apply to system call
|
2022-05-05 02:52:54 +00:00
|
|
|
|
wrappers like realpath. On Windows NT it's observed by all system
|
2022-04-26 04:16:05 +00:00
|
|
|
|
calls that accept a pathname.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, bind, chdir, chmod, chown, chroot, execve,
|
2022-08-17 20:41:21 +00:00
|
|
|
|
gethostname, link, mkdir, mknod, open, readlink, rename, rmdir,
|
|
|
|
|
stat, symlink, truncate, unlink, utimensat.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EACCES
|
|
|
|
|
Permission denied.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, bind, chdir, chmod, chown, chroot, clock_getres,
|
2022-08-17 20:41:21 +00:00
|
|
|
|
connect, execve, fcntl, getpriority, link, mkdir, mknod, mmap,
|
|
|
|
|
mprotect, msgctl, open, prctl, ptrace, readlink, rename, rmdir,
|
|
|
|
|
semget, send, setpgid, socket, stat, symlink, truncate, unlink,
|
|
|
|
|
uselib, utime, utimensat.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOMEM
|
|
|
|
|
We require more vespene gas.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, bind, chdir, chmod, chown, chroot, clone,
|
|
|
|
|
copy_file_range, execve, fanotify_init, fork, getgroups, getrlimit,
|
2022-08-17 20:41:21 +00:00
|
|
|
|
link, mbind, mincore, mkdir, mknod, mlock, mmap, mprotect, mremap,
|
|
|
|
|
msync, open, poll, readlink, recv, rename, rmdir, select, send,
|
|
|
|
|
sigaltstack, splice, stat, subpage_prot, swapon, symlink,
|
|
|
|
|
sync_file_range, tee, timer_create, timerfd_create, unlink.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EPERM
|
|
|
|
|
Operation not permitted.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, chmod, chown, chroot, copy_file_range, execve,
|
|
|
|
|
fallocate, fanotify_init, fcntl, futex, get_robust_list,
|
|
|
|
|
getdomainname, getgroups, gethostname, getpriority, getrlimit,
|
|
|
|
|
getsid, gettimeofday, idle, init_module, io_submit, ioctl_console,
|
|
|
|
|
ioctl_ficlonerange, ioctl_fideduperange, ioperm, iopl, ioprio_set,
|
|
|
|
|
keyctl, kill, link, lookup_dcookie, madvise, mbind, membarrier,
|
|
|
|
|
migrate_pages, mkdir, mknod, mlock, mmap, mount, move_pages, msgctl,
|
|
|
|
|
nice, open, open_by_handle_at, pciconfig_read, perf_event_open,
|
|
|
|
|
pidfd_getfd, pidfd_send_signal, pivot_root, prctl, process_vm_readv,
|
|
|
|
|
ptrace, quotactl, reboot, rename, request_key, rmdir,
|
|
|
|
|
rt_sigqueueinfo, sched_setaffinity, sched_setattr, sched_setparam,
|
|
|
|
|
sched_setscheduler, seteuid, setfsgid, setfsuid, setgid, setns,
|
|
|
|
|
setpgid, setresuid, setreuid, setsid, setuid, setup, setxattr,
|
|
|
|
|
sigaltstack, spu_create, stime, swapon, symlink, syslog, truncate,
|
|
|
|
|
unlink, utime, utimensat, write.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOTBLK
|
|
|
|
|
Block device required.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by umount.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EBUSY
|
|
|
|
|
Device or resource busy.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by dup, fcntl, msync, prctl, ptrace, rename,
|
|
|
|
|
rmdir.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EEXIST
|
|
|
|
|
File exists.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-08-17 20:41:21 +00:00
|
|
|
|
Raised by link, mkdir, mknod, mmap, open, rename, rmdir, symlink
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EXDEV
|
|
|
|
|
Improper link.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by copy_file_range, link, rename.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENODEV
|
|
|
|
|
No such device.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by arch_prctl, mmap, open, prctl, timerfd_create.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EISDIR
|
2022-08-17 06:58:26 +00:00
|
|
|
|
Is a directory.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by copy_file_range, execve, open, read, rename, truncate,
|
|
|
|
|
unlink.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENFILE
|
|
|
|
|
Too many open files in system.
|
|
|
|
|
|
2022-08-17 20:41:21 +00:00
|
|
|
|
Raised by accept, execve, mmap, open, pipe, socket, socketpair,
|
|
|
|
|
swapon, timerfd_create, uselib, userfaultfd.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EMFILE
|
|
|
|
|
Too many open files.
|
|
|
|
|
|
2022-08-17 20:41:21 +00:00
|
|
|
|
Raised by accept, dup, execve, fcntl, open, pipe, socket,
|
|
|
|
|
socketpair, timerfd_create.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOTTY
|
|
|
|
|
Inappropriate i/o control operation.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by ioctl.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ETXTBSY
|
|
|
|
|
Won't open executable that's executing in write mode.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, copy_file_range, execve, mmap, open, truncate.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EFBIG
|
|
|
|
|
File too large.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by copy_file_range, open, truncate, write.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOSPC
|
|
|
|
|
No space left on device.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-08-17 20:41:21 +00:00
|
|
|
|
Raised by copy_file_range, fsync, link, mkdir, mknod, open, rename,
|
|
|
|
|
symlink, sync_file_range, write.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EDQUOT
|
|
|
|
|
Disk quota exceeded.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by link, mkdir, mknod, open, rename, symlink,
|
|
|
|
|
write.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ESPIPE
|
|
|
|
|
Invalid seek.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by lseek, splice, sync_file_range.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EROFS
|
|
|
|
|
Read-only filesystem.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by access, bind, chmod, chown, link, mkdir, mknod, open,
|
|
|
|
|
rename, rmdir, symlink, truncate, unlink, utime, utimensat.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EMLINK
|
|
|
|
|
Too many links;
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
raised by link, mkdir, rename.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ERANGE
|
|
|
|
|
Result too large.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by prctl.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EDEADLK
|
|
|
|
|
Resource deadlock avoided.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by fcntl.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOLCK
|
|
|
|
|
No locks available.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by fcntl, flock.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOTEMPTY
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Directory not empty. Raised by rmdir.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ELOOP
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Too many levels of symbolic links.
|
|
|
|
|
|
|
|
|
|
Raised by access, bind, chdir, chmod, chown, chroot, execve, link,
|
|
|
|
|
mkdir, mknod, open, readlink, rename, rmdir, stat, symlink,
|
|
|
|
|
truncate, unlink, utimensat.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOMSG
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by msgop.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EIDRM
|
|
|
|
|
Identifier removed.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by msgctl.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ETIME
|
|
|
|
|
Timer expired; timer expired.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EPROTO
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, connect, socket, socketpair.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EOVERFLOW
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by copy_file_range, fanotify_init, lseek, mmap,
|
|
|
|
|
open, stat, statfs
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOTSOCK
|
|
|
|
|
Not a socket.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, bind, connect, getpeername, getsockname,
|
|
|
|
|
getsockopt, listen, recv, send, shutdown.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EDESTADDRREQ
|
|
|
|
|
Destination address required.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by send, write.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EMSGSIZE
|
|
|
|
|
Message too long.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by send.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EPROTOTYPE
|
|
|
|
|
Protocol wrong type for socket.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENOPROTOOPT
|
|
|
|
|
Protocol not available.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by getsockopt, accept.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EPROTONOSUPPORT
|
|
|
|
|
Protocol not supported.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by socket, socketpair.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ESOCKTNOSUPPORT
|
|
|
|
|
Socket type not supported.
|
|
|
|
|
|
|
|
|
|
unix.ENOTSUP
|
|
|
|
|
Operation not supported.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by chmod, clock_getres, clock_nanosleep,
|
|
|
|
|
timer_create.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EOPNOTSUPP
|
|
|
|
|
Socket operation not supported.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, listen, mmap, prctl, readv, send,
|
|
|
|
|
socketpair.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EPFNOSUPPORT
|
|
|
|
|
Protocol family not supported.
|
|
|
|
|
|
|
|
|
|
unix.EAFNOSUPPORT
|
|
|
|
|
Address family not supported.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect, socket, socketpair
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EADDRINUSE
|
|
|
|
|
Address already in use.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by bind, connect, listen
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.EADDRNOTAVAIL
|
|
|
|
|
Address not available.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by bind, connect.
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENETDOWN
|
|
|
|
|
Network is down.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENETUNREACH
|
|
|
|
|
Host is unreachable.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept, connect
|
2022-04-26 04:16:05 +00:00
|
|
|
|
|
|
|
|
|
unix.ENETRESET
|
|
|
|
|
Connection reset by network.
|
|
|
|
|
|
|
|
|
|
unix.ECONNABORTED
|
|
|
|
|
Connection reset before accept.
|
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ECONNRESET
|
|
|
|
|
Connection reset by client.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by send.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOBUFS
|
|
|
|
|
No buffer space available;
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
raised by getpeername, getsockname, send.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EISCONN
|
|
|
|
|
Socket is connected.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect, send.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENOTCONN
|
|
|
|
|
Socket is not connected.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by getpeername, recv, send, shutdown.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ESHUTDOWN
|
|
|
|
|
Cannot send after transport endpoint shutdown; note that shutdown
|
|
|
|
|
write is an `EPIPE`.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ETOOMANYREFS
|
|
|
|
|
Too many references: cannot splice.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by sendmsg.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ETIMEDOUT
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Connection timed out.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ECONNREFUSED
|
|
|
|
|
System-imposed limit on the number of threads was encountered.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect, listen, recv.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EHOSTDOWN
|
|
|
|
|
Host is down.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept.
|
2022-04-18 07:01:26 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EHOSTUNREACH
|
|
|
|
|
Host is unreachable.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by accept.
|
2022-04-13 15:49:17 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.EALREADY
|
|
|
|
|
Connection already in progress.
|
2022-04-24 16:59:22 +00:00
|
|
|
|
|
2022-05-05 02:52:54 +00:00
|
|
|
|
Raised by connect, send.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
unix.ENODATA
|
|
|
|
|
No message is available in xsi stream or named pipe is being closed;
|
|
|
|
|
no data available; barely in posix; returned by ioctl; very close in
|
|
|
|
|
spirit to EPIPE?
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2022-04-28 16:42:36 +00:00
|
|
|
|
UNIX MISCELLANEOUS MAGNUMS
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
unix.ARG_MAX
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
Returns maximum length of arguments for new processes.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
2022-04-28 16:42:36 +00:00
|
|
|
|
This is the character limit when calling execve(). It's the sum of
|
|
|
|
|
the lengths of `argv` and `envp` including any nul terminators and
|
|
|
|
|
pointer arrays. For example to see how much your shell `envp` uses
|
|
|
|
|
|
|
|
|
|
$ echo $(($(env | wc -c) + 1 + ($(env | wc -l) + 1) * 8))
|
|
|
|
|
758
|
|
|
|
|
|
|
|
|
|
POSIX mandates this be 4096 or higher. On Linux this it's 128*1024.
|
|
|
|
|
On Windows NT it's 32767*2 because CreateProcess lpCommandLine and
|
|
|
|
|
environment block are separately constrained to 32,767 characters.
|
|
|
|
|
Most other systems define this limit much higher.
|
|
|
|
|
|
|
|
|
|
unix.BUFSIZ
|
|
|
|
|
|
|
|
|
|
Returns default buffer size.
|
|
|
|
|
|
|
|
|
|
The UNIX module does not perform any buffering between calls.
|
|
|
|
|
|
|
|
|
|
Each time a read or write is performed via the UNIX API your redbean
|
|
|
|
|
will allocate a buffer of this size by default. This current default
|
|
|
|
|
would be 4096 across platforms.
|
|
|
|
|
|
|
|
|
|
unix.CLK_TCK
|
|
|
|
|
|
|
|
|
|
Returns the scheduler frequency.
|
|
|
|
|
|
|
|
|
|
This is granularity at which the kernel does work. For example, the
|
|
|
|
|
Linux kernel normally operates at 100hz so its CLK_TCK will be 100.
|
|
|
|
|
|
|
|
|
|
This value is useful for making sense out of unix.Rusage data.
|
|
|
|
|
|
|
|
|
|
unix.PIPE_BUF
|
|
|
|
|
|
|
|
|
|
Returns maximum size at which pipe i/o is guaranteed atomic.
|
|
|
|
|
|
|
|
|
|
POSIX requires this be at least 512. Linux is more generous and
|
|
|
|
|
allows 4096. On Windows NT this is currently 4096, and it's the
|
|
|
|
|
parameter redbean passes to CreateNamedPipe().
|
|
|
|
|
|
|
|
|
|
unix.PATH_MAX
|
|
|
|
|
|
|
|
|
|
Returns maximum length of file path.
|
|
|
|
|
|
|
|
|
|
This applies to a complete path being passed to system calls.
|
|
|
|
|
|
|
|
|
|
POSIX.1 XSI requires this be at least 1024 so that's what most
|
|
|
|
|
platforms support. On Windows NT, the limit is technically 260
|
|
|
|
|
characters. Your redbean works around that by prefixing `//?/`
|
|
|
|
|
to your paths as needed. On Linux this limit will be 4096, but
|
|
|
|
|
that won't be the case for functions such as realpath that are
|
|
|
|
|
implemented at the C library level; however such functions are
|
|
|
|
|
the exception rather than the norm, and report enametoolong(),
|
|
|
|
|
when exceeding the libc limit.
|
|
|
|
|
|
|
|
|
|
unix.NAME_MAX
|
|
|
|
|
|
|
|
|
|
Returns maximum length of file path component.
|
|
|
|
|
|
|
|
|
|
POSIX requires this be at least 14. Most operating systems define it
|
|
|
|
|
as 255. It's a good idea to not exceed 253 since that's the limit on
|
|
|
|
|
DNS labels.
|
|
|
|
|
|
|
|
|
|
unix.NSIG
|
|
|
|
|
|
|
|
|
|
Returns maximum number of signals supported by underlying system.
|
|
|
|
|
|
|
|
|
|
The limit for unix.Sigset is 128 to support FreeBSD, but most
|
|
|
|
|
operating systems define this much lower, like 32. This constant
|
|
|
|
|
reflects the value chosen by the underlying operating system.
|
2021-07-09 00:55:35 +00:00
|
|
|
|
|
|
|
|
|
|
2022-05-27 06:17:19 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
LEGAL
|
|
|
|
|
|
|
|
|
|
redbean contains software licensed ISC, MIT, BSD-2, BSD-3, zlib
|
|
|
|
|
which makes it a permissively licensed gift to anyone who might
|
|
|
|
|
find it useful. The transitive closure of legalese can be found
|
|
|
|
|
inside the binary structure, because notice licenses require we
|
|
|
|
|
distribute the license along with any software that uses it. By
|
|
|
|
|
putting them in the binary, compliance in automated and no need
|
|
|
|
|
for further action on the part of the user who is distributing.
|
|
|
|
|
|
|
|
|
|
|
2022-04-26 04:16:05 +00:00
|
|
|
|
────────────────────────────────────────────────────────────────────────────────
|
2021-05-14 12:36:58 +00:00
|
|
|
|
SEE ALSO
|
|
|
|
|
|
2022-04-29 07:36:14 +00:00
|
|
|
|
https://redbean.dev/
|
2021-05-14 12:36:58 +00:00
|
|
|
|
https://news.ycombinator.com/item?id=26271117
|