lunix
is a Lua bindings library module to common Unix system APIs. The
module is regularly tested on recent versions of AIX, FreeBSD, Linux/glibc,
Linux/musl, NetBSD, OpenBSD, OS X, and Solaris. The best way to describe it
is in contradistinction to luaposix, the most popular bindings module for
Unix APIs in Lua.
Unlike luaposix, it strives to be as thread-safe as possible on the host
platform. Interfaces like strerror_r
and O_CLOEXEC
are used throughout
where appropriate. The module even includes a novel solution for the
inherently non-thread-safe umask
system call, where calling umask
from
one thread might result in another thread creating a file with unsafe or
unexpected permissions.
Unlike luaposix
, the library does not restrict itself to POSIX, and where
possible emulates an interface when not available natively on a supported
platform. For example, the library provides arc4random
(absent on Linux
and older Solaris releases), clock_gettime
(absent on older macOS
releases), and a thread-safe timegm
(absent on Solaris).
Unlike luaposix, the library prefers dealing with FILE
handles rather than
raw integer descriptors. This helps to mitigate and prevent leaks or
double-close bugs---a common source of problems in, e.g., asynchronous
applications where a descriptor is closed that has already been reassigned
to another resource. Routines like chdir
, stat
, and opendir
transparently accept string paths, FILE
handles, DIR
handles, and raw
integer descriptors.
lunix
supports the Lua 5.1, 5.2, and 5.3 APIs. lunix
supports LuaJIT wth
the caveat that when creating custom FILE
handles using fdopen
(directly
or indirectly through, e.g., fdup
) the process must have read access to an
existing filesystem resource (presently .
or /dev/null
) in order to
create a LUA_FILEHANDLE
object in the VM. This might not work in some
sandboxed environments.
The usual GNU-style flags are supported, such as CC
, CPPFLAGS
, CFLAGS
,
LDFLAGS
, SOFLAGS
, and LIBS
. ...
TODO. See lunix
Userguide PDF
Unlike recent versions of luaposix
, interfaces are not grouped into
submodules. (But see unix.unsafe
submodule.)
Both Unix and POSIX evolved organically over time and neither
consistently group interfaces, either by header or any other singular
convention. And while theoretically it could done de novo I feel that
might add confusion and is otherwise wasted effort. In C the interfaces
exist in a single namespace. While from a C source language perspective a
small handful of interfaces technically have naming conflicts depending on
which standard is selected at compile-time, in 2016 this is largely a
theoretical problem. Where it does exist (e.g. GNU strerror_r
vs POSIX
strerror_r
) this can easily be smoothed over transparently by lunix
.
Following the example of fopen
, lunix
implements a sister interface for
some routines to atomically wrap a descriptor within a FILE
handle. This
cannot be easily accomplished from Lua script because of the possibility of
memory allocation failure. (Despite a widespread myth, this can easily
happen even on systems like Linux in the presence of process resource
limits, regardless of allocation size.) For example, the lunix
routine
fdup
behaves just like dup
but returns a FILE
handle instead of an
integer descriptor. Note that both dup
and fdup
will accept either an
integer descriptor or FILE
handle.
Generally, errors with argument type or format are thrown using lua_error
.
System errors are returned directly using the idiomatic 3-tuple Lua
convention---nil or boolean false, error string description, error integer
code.
Some internal allocation errors are returned as-if they were system errors,
particularly where they arise in the C portion of an emulated routine. In
such a case the call may return with ENOMEM
even through neither the local
system nor the POSIX specification specify such an error. Other allocation
errors are thrown, particularly where they occur within the Lua/C preamble
of a binding.
The module takes great care to detect arithmetic overflow, including
undefined arithmetic conversions between lua_Integer
, lua_Number
, and
the relevant system types. When detected arithemtic overflow is generally
treated as a type error and thrown (see Errors, above).
TODO. See lunix
Userguide PDF.
All of the following routines are implemented though they may not yet be documented. Descriptions for some interfaces may be in the original PDF userguide.
arc4random : () -> (integer)
Returns a cryptographically strong, uniformly random 32-bit integer as a Lua
number. On Linux the RANDOM_UUID
sysctl
feature is used to seed the
generator if available; or on more recent Linux and Solaris kernels the
getrandom
interface.1 This avoids fiddling with file
descriptors, and also works in a chroot jail. On other platforms without a
native arc4random
interface, such as Solaris 11.2 or earlier, the
implementation must resort to /dev/urandom for seeding.
Note that unlike the original implementation on OpenBSD, arc4random on some older platforms (e.g. FreeBSD prior to 10.10) seeds itself from /dev/urandom. This could cause problems in chroot jails.
arc4random_buf : (n:integer) -> (string)
Returns a string of length arc4random
.
arc4random_stir : () -> (true)
Stir the arc4random entropy pool using the best available resources. This normally should be unnecessary and is a noop on some systems.
arc4random_uniform : (n:integer?) -> (integer)
Returns a cryptographically strong uniform random integer in the interval
arc4random
.
chdir : (path:string|file|fd:integer) -> (true) | (false, string, integer)
If chdir(2)
. Otherwise, if fchdir(2)
.
Returns true
on success, otherwise returns false
, an error string, and
an integer system error.
chown : (path:string|file|fd:integer, uid?, gid?) -> (true) | (false, string, integer)
chown(2)
, or a FILE handle
or integer file descriptor for use with fchown(2)
.
Returns true
on success, otherwise returns false
, an error string, and
an integer system error.
chroot : (path:string) -> (true) | (false, string, integer)
Attempt to chroot to the specified string
Returns true
on success, otherwise returns false
, an error string, and
an integer system error.
clock_gettime : (id:string|id:number) -> (integer) | (nil, string, integer)
CLOCK_REALTIME
or CLOCK_MONOTONIC
.
Returns a time value as a Lua floating point number, otherwise returns nil
,
an error string, and an integer system error.
closedir : (DIR) -> (true) | (false, string, integer)
Closes the DIR handle, releasing the underlying file descriptor.
execve : (path:string, {string*}, {string*}) -> (false, string, integer)
Executes $PATH
environment variable is not used.
On success never returns. On failure returns false
, an error string, and
an integer system error.
execl : (path:string, string*) -> (false, string, integer)
Executes $PATH
environment variable is not used. Any subsequent arguments are passed to the
new process image. The new process image inherits the current environment
table.
On success never returns. On failure returns false
, an error string, and
an integer system error.
execlp : (file:string, string*) -> (false, string, integer)
Executes $PATH
environment variable is used to search for
On success never returns. On failure returns false
, an error string, and
an integer system error.
execvp : (file:string, string*) -> (false, string, integer)
Executes $PATH
environment variable is used to search for
On success never returns. On failure returns false
, an error string, and an
integer system error.
_exit : (status:boolean?|status:integer?) -> ()
Exits the process immediately without first flushing and closing open
streams, and without calling atexit(3)
handlers. If true
or false
, exits with EXIT_SUCCESS
or EXIT_FAILURE
,
respectively. Otherwise, EXIT_SUCCESS
).
exit : (status:boolean?|status:integer?) -> ()
Like _exit
, but first flushes and closes open streams and calls
atexit(3)
handlers.
fdopen : (fd:integer, mode:string|integer) -> (FILE) | (nil, string, integer)
Returns a FILE object wrapping the specified descriptor. fopen
-style string mode or open
-style integer flags bit set.
fdup : (fh:FILE|DIR|integer, mode:string|integer) -> (FILE) | (nil, string, integer)
Atomic dup + fdopen, without the possibility of a descriptor leak upon OOM
or similar error (exception) while calling these in succession. fopen
-style string mode or open
-style integer flags bit set.
fileno : (fh:FILE|DIR|integer) -> (integer)
Resolves the specified FILE handle or DIR handle to an integer file descriptor. An integer descriptor is returned as-is.
flockfile : (fh:FILE) -> (true)
Locks the FILE handle true
.
This function only works on FILE handles and not DIR handles or integer descriptors.
ftrylockfile : (fh:FILE) -> (true|false)
Attempts to lock the FILE handle true
on success or false
if
funlockfile : (fh:FILE) -> (true)
Unlocks the FILE handle true
.
fork : () -> (integer) | (nil, string, integer)
Forks a new process. On success returns the PID of the new process in the
parent and the integer 0 in the child. Otherwise returns false
, an error
string, and an integer system error.
The unix.unsafe
module binds routines that can take or return pointers.
Pointer arguments might be taken directly as lightuserdata or integers
(intptr_t
), or indirectly as a string, depending on the routine.
In the latter case, if it's not known whether a syscall might write through
a pointer (e.g. fcntl
, getsockopt
), a string argument will be copied
into an internal buffer, a pointer to this buffer passed to the routine, and
then the contents of this buffer (possibly modified) returned as a string to
the caller in the return list; otherwise (e.g. strlen
) a pointer to the
string obtained via lua_tostring
is passed.
Copyright (c) 2014-2017, 2019-2023 William Ahern <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>Footnotes
-
Some Linux distributions, such as Red Hat, disable
sysctl(2)
. ↩