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 Solaris), clock_gettime
(absent on OS X), 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. 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.
fileno -> (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 : (fd:FILE) -> (true|false)
Attempts to lock the FILE handle true
on success or false
if
funlockfile : (fd: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.
Footnotes
-
Some Linux distributions, such as Red Hat, disable
sysctl(2)
. โฉ