pax_global_header00006660000000000000000000000064147544437410014527gustar00rootroot0000000000000052 comment=e6b94b37c19c4bd19a7dc475a4f4cb56f61f5da9 luaposix-36.3/000077500000000000000000000000001475444374100133265ustar00rootroot00000000000000luaposix-36.3/.github/000077500000000000000000000000001475444374100146665ustar00rootroot00000000000000luaposix-36.3/.github/workflows/000077500000000000000000000000001475444374100167235ustar00rootroot00000000000000luaposix-36.3/.github/workflows/spec.yml000066400000000000000000000020701475444374100203770ustar00rootroot00000000000000name: spec on: push: branches: [ '*' ] pull_request: branches: [ 'master' ] jobs: test: strategy: fail-fast: false matrix: lua-version: ["5.4", "5.3", "5.2", "5.1", "luajit"] strict: ["std.strict", ""] runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: luarocks/gh-actions-lua@v10 with: luaVersion: ${{ matrix.lua-version }} - uses: luarocks/gh-actions-luarocks@v5 - name: install run: | sudo apt-get install -y libyaml-dev luarocks install ansicolors luarocks install ldoc luarocks install luacov luarocks install specl luarocks install std._debug luarocks install typecheck test -n "${{ matrix.strict }}" && luarocks install std.strict || true - name: build run: | luarocks make --force - name: test run: | specl -vfreport --coverage spec/*_spec.yaml bash <(curl -s https://codecov.io/bash) -f luacov.report.out luaposix-36.3/.gitignore000066400000000000000000000001721475444374100153160ustar00rootroot00000000000000*~ *.o *.so *.src.rock /ChangeLog /COPYING /Makefile /build-aux/config.ld /lib/posix/version.lua /luaposix-*.tar.gz /TAGS luaposix-36.3/.luacov000066400000000000000000000001521475444374100146160ustar00rootroot00000000000000modules = { ['posix'] = 'lib/posix/init.lua', ['posix.*'] = 'lib', } runreport = true tick = true luaposix-36.3/.slackid000066400000000000000000000000421475444374100147350ustar00rootroot00000000000000aspirinc:JyWeNrIdS0J5nf2Pn2BS1cih luaposix-36.3/AUTHORS000066400000000000000000000011221475444374100143720ustar00rootroot00000000000000luaposix is the work of several authors (see git history for contributors). It is based on two earlier libraries: An earlier version of luaposix (up to 5.1.11) Copyright Reuben Thomas 2010-2011 Copyright Natanael Copa 2008-2010 Clean up and bug fixes by Leo Razoumov 2006-10-11 Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 Based on original by Claudio Terra for Lua 3.x, with contributions by Roberto Ierusalimschy. John Belmonte wrote the example program tree.lua. luaposix-36.3/ChangeLog.old000066400000000000000000000040111475444374100156510ustar00rootroot00000000000000History is now tracked in git. https://github.com/luaposix/luaposix 2008-07-18 Natanael Copa * fix rpoll to ignore the POLLHUP and POLLNVAL reported at: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=491257 * added crypt(). Patch from dev.openwrt.org 2008-06-03 Natanael Copa * replace luaL_openlib with the newer luaL_register. * Support for building on Darwin/OSX. Patch from Felix Fietkau 2008-01-29 Natanael Copa * added openlog(), syslog() and closelog() * fixed dup() to handle lua files * renamed exec() to execp() and added a new exec func that uses execv(3) * added fileno() 2008-01-25 Natanael Copa * created fork luaposix o added poll() patch from: http://lua-users.org/lists/lua-l/2007-11/msg00346.html o cleaned up Makefile 2006-10-16 Leo Razoumov * Added glob wrapper (Pglob) implementated by George Created corresponding test. 2006-10-12 Leo Razoumov * Starting with Luiz Henrique de Figueiredo (LHF) 2006-04-07 version of lposix.c fixed the following problems when compiling for Lua-5.1 (Lua-5.1.x) o Added missing functions to lposix.c: Prmdir, Punlink o Restored older lposix-5.0 implementation of the following functions: Pumask, Pchmod * restored modemuncher.c from lposix-5.0 since April 2006 lposix.c version has broken implementation of modemunch(...) function. * Function Ptimes: wrong conversion of clock ticks to seconds. Replaced scaling by CLOCKS_PER_SEC macro (that should never be used, btw) with POSIX compliant sysconf(_SC_CLK_TCK) value. * Update test.lua and tree.lua to reflect lposix.c API changes * Deleted posix.lua loader file not needed anymore in Lua-5.1 module system * Remaining problems: Pumask does not take mask in octal form, it only understand alphabetic notation like "u=rwx" luaposix-36.3/LICENSE000066400000000000000000000020521475444374100143320ustar00rootroot00000000000000Copyright (C) 2006-2025 luaposix authors 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. luaposix-36.3/NEWS.md000066400000000000000000001167651475444374100144440ustar00rootroot00000000000000# luaposix NEWS - User visible changes ## Noteworthy changes in release 36.3 (2025-02-16) [stable] ### Bugs Fixed - `posix.sys.socket.recvfrom` no longer casts a ssize_t result into an int. - `posix.poll.rpoll` LDocs usage example updated to match current API. - Using conditional compilation for functions that have been implemented when compiling with luajit. ### New Features - Adds `tcgetwinsize` and `tcsetwinsize` functions to `posix.termio` enabling to get and set winsize, when supported by the underlying host system. ## Noteworthy changes in release 36.2.1 (2023-06-16) [stable] ### Incompatible Changes - Using latest typecheck and specl rocks requires that our argument errors list all typenames in full ("integer" not "int") and unions in order ("nil or string" not "string or nil". All luaposix APIs now report argument type errors accordingly. ### Bugs Fixed - `posix.unistd.read` and `posix.sys.socket.recv` no longer hide the underlying real error by casting a ssize_t result into an unsigned size_t local. - Fix a typo in the `lflag` argument name in the termios table LDocs. - `posix.sys.*` submodules are correctly preloaded into the module table returned by `require 'posix'` so that this undocumented, deprecated and slow way to access the functions therein continues to work for now: local posix = require 'posix' local stat = posix.sys.stat.stat For new code, consider this fast and documented alternative, that does not load every available luaposix API from disk (especially if your project does not use APIs from every luaposix module): local stat = require 'posix.sys.stat'.stat - Removed `IUTF8` from the documented list of supported `iflag` values in `posix.termios` because it was previously unimplemented. Implemented non-portable support as an XSI extension, as it isn't a part of the POSIX standard. ## Noteworthy changes in release 36.1 (2023-01-31) [stable] ### Bugs Fixed - `luke` now uses the same cpp defines for conftests as will be used for module compilation, otherwise we are potentially testing and compiling with different sets of features. - `tm.tm_gmtoff` and `tm.tm_zone` are populated on Linux distros that require compiling with `-D_BSD_SOURCE`. ## Noteworthy changes in release 36.0 (2023-01-29) [stable] ### Incompatible Changes - `posix.spawn` always returns `integer`, `string` whether `fork` fails immediately, or whatever `wait`ing for the spawned process reports. When the second result value is "exited", the first is the exit status; for "killed" or "stopped" second value, the first is the signal number that caused it; otherwise first the `errno` error number, followed by the associated error string. The documentation for `posix.spawn` has always been wrong up until now, but this small change to simplify the returned results will require checking whether the second result value is "exited", "killed", "stopped" or any other string before interpreting the first result... which was also necessary in prior versions too, but now the interpretion of non-zero status by clients is less messy and somewhat compatible with the happy path of using previous releases. - Argument type errors for `posix.sys.msg.msgctl`, `posix.sys.resource.setrlimit`, `posix.sys.socket.bind`, `posix.sys.socket.connect`, `posix.sys.socket.getaddrinfo`, `posix.sys.socket.sendto` and `posix.time.nanosleep` all use "integer" in full rather than "int". ### Bugs Fixed - `luke` no longer crashes in `std.normalize` require loops occasionally in Lua 5.4. - Don't leak `err` into global scope from `compat.open` - Correct LDoc comments for `sys.resource.setrlimit`. - Where an integer argument is expected, for consistency with Lua 5.2 and older, always allow 0.0 to be accepted as if 0 had been passed. For example: `pwd.getpwuid(0.0)`. - `require 'posix'.glob '.*'` continues to invoke the backwards compatibility `glob` function, but that no longer prevents access to the preloaded `require 'posix'.glob.glob` binding. - The `fcntl` binding is still available from the top-level `posix` module as `require 'posix'.fcntl`, but that no longer prevents access to the preloaded `require 'posix'.fcntl.fcntl` binding. - `poll.poll` and `poll.rpoll` LDocs correctly describe the returned integer as being `0` for timeout or the number of ready file descriptors. - `stdio.fdopen` returned streams can be closed from Lua 5.1 without a NULL pointer dereference crash. - Both `sys.resource.getrlimit` and `sys.resource.setrlimit` properly roundtrip `rlim_t` values. - `sys.socket.getpeername` and `sys.socket.getsockname` now return a correctly filled `sockaddr` table. In case of an AF_UNIX socket, the returned `path` is now cropped to the correct length. - `time` constants are `nil` valued, even on hosts which fail to define them when _POSIX_TIMERS is set as if they should be. - `time.gmtime` and `time.localtime` no longer wrap around with arguments of 2^31 and larger. - `time.gmtime` and `time.localtime` propagate any `tm_gmoffset` and `tm_zone` fields supported by the host's `struct tm`. - `time.strftime` reliably fills %z and %Z specifiers. Note that if your host POSIX library provides a `strftime` that assumes the local timezone, %z will always print the local UTC offset, regardless of the `tm_gmoffset` field value passed in. Consider (subject to host strftime implementation!): local t = require 'posix.time' local now = t.time() local zulu_t = t.strftime("%c UTC+0000", t.gmtime(now))) local localt = t.strftime("%c %Z UTC%z", t.localtime(now))) - `unistd.getcwd` no longer leaks memory if __GNU__ was defined at compile time. - `unistd.readlink` works reliably inside a /proc filesystem. - `unistd.write` takes an optional third argument `nbytes` to conform better to the SUSv3 specification. For backwards compatibility, the entirety of `buf` is written when a third argument is not passed (or is `nil`). - Many bindings use now a lua_Integer (with at least 53 bits for magnitude, depending on the host Lua version) instead of a C int type to pass numeric arguments, so much larger values can be successfully passed to and from the following bindings: `fcntl.open`, `posix.fcntl.posix_fadvise`, `fnmatch.fnmatch`, `posix.grp.getgrgid`, `pwd.getpwuid`, `sched.sched_getscheduler`, `sched.sched_setscheduler`, `signal.kill`, `signal.killpg`, `signal.raise`, `sys.msg.msgget`, `sys.msg.msgrcv`, `sys.socket.recv`, `sys.socket.recvfrom`, `sys.socket.setsockopt`, `sys.stat.S_ISBLK`, `sys.stat.S_ISCHR`, `sys.stat.S_ISDIR`, `sys.stat.S_ISFIFO`, `sys.stat.S_ISLNK`, `sys.stat.S_ISREG`, `sys.stat.S_ISSOCK`, `sys.stat.chmod`, `sys.stat.mkdir`, `sys.stat.mkfifo`, `sys.stat.umask`, `sys.wait.wait`, `syslog.LOG_MASK`, `time.mktime`, `unistd._exit`, `unistd.alarm`, `unistd.ftruncate`, `unistd.getegid`, `unistd.geteguid`, `unistd.getgid`, `unistd.getopt`, `unistd.getpgrp`, `unistd.getpid`, `unistd.getppid`, `unistd.getuid`, `unistd.gethostid`, `unistd.lseek`, `unistd.pathconf`, `unistd.read`, `unistd.setpid`, `unistd.sleep`, `unistd.sysconf`, `unistd.truncate`, `utime.utime`. - Most of the spec examples run correctly on FreeBSD now! ### New Features - `unistd.write` takes an optional fourth argument `offset` to allow efficent writing of a substring of `buf`. For backwards compatibility, the entirety of `buf` is written when the third and fourth arguments are not passed (or are `nil`). - When running in luajit, use luajit's internal `bit` functions instead of depending on the `bit32` module being available. ## Noteworthy changes in release 35.1 (2021-09-09) [stable] ### Bugs Fixed - Documentation cleanups: full and correct return docs including an errnum where necessary; make sure we have a link to SUSv3 wherever available; add an ', if successful' suffix to a normap return result followed by error return results; fixed several typos. - Update fork2.lua example to match current APIs ### New Features - Support AF_PACKET socket family, where available. - Support SIGINFO, SIGWINCH and SA_RESTART, where available. ## Noteworthy changes in release 35.0 (2020-07-06) [stable] ### Incompatible Changes - Internally, we use our own bitwise operation wrapper functions rather than bit32 where possible. This means bitwise operations when running under Lua 5.3+ work on 64bit integers. ### Bugs Fixed - `posix.deprecated.getrlimit` and `posix.deprecated.setrlimit` pass tests again. ### New Features - Initial support for Lua 5.4. ## Noteworthy changes in release 34.1.1 (2019-07-27) [stable] ### Bugs Fixed - `posix.compat` really does work without `std.normalize` in the `package.path` now. ## Noteworthy changes in release 34.1 (2019-07-20) [stable] ### Bugs Fixed - `luke` works with upgraded bootstrap luarocks version of `require`. - `posix.glob.glob` does not return a random errno on failure now, but new module constants `GLOB_ABORTED`, `GLOB_NOMATCH` or `GLOB_NOSPACE`. - `posix.deprecated.clock_getres` and `posix.deprecated.clock_gettime` work again. ### New Features - `posix.glob.glob` supports now module constants as a second argument: `GLOB_NOCHECK` and `GLOB_ERR`. - `posix.sys.socket` now supports IPV6 link-local addresses. - use `std.strict`, `std._debug` and `typecheck` modules when available, otherwise behave normally without those additional runtime checks. ## Noteworthy changes in release 34.0.4 (2018-02-20) [stable] ### Bugs Fixed - `posix.time.clock_getres`, `posix.time.clock_gettime` `posix.time.CLOCK_MONOTONIC`, `posix.time.CLOCK_REALTIME`, `posix.time.CLOCK_PROCESS_CPUTIME_ID` and `posix.time.CLOCK_THREAD_CPUTIME_ID` are all properly elided on macOS again. - `spec/spec_helper.lua` now looks in the correct objdir for object modules built by luke, instead of hard-coding `./linux/?.so`, so specl examples work on macOS and others again. ## Noteworthy changes in release 34.0.3 (2018-02-19) [stable] ### Bugs Fixed - `posix.deprecated.fadvise` is properly elided on macOS and other hosts that have no `posix.fcntl.posix_fadvise` implementation. ## Noteworthy changes in release 34.0.2 (2018-02-17) [stable] ### Incompatible Changes - `require 'posix'` (or any of its submodules) always returns a populated module table, but no longer sets `_G.posix` or any other global symbol on Lua 5.1 (including LuaJIT). If you were relying on this behaviour, please change your require statments to an assignment: ```lua local posix = require 'posix' ``` ### Bugs Fixed - `posix.sys.wait.wait` returns `, "running"` when the child has not exited yet, and `wait` was called with `WNOHANG` set. - specs don't fail on valid -1 return values from `posix.sysconf`. - loading posix (or any of its submodules) no longer leaks symbols into the global namespace on Lua 5.1 (including LuaJIT). ## Noteworthy changes in release 34.0.1 (2017-07-09) [stable] ### Bugs Fixed - `posix.sys.socket` works correctly on macOS again. - `posix.sys.socket` abstract namespaces work correctly on Linux. - `posix.syslog.openlog` keeps a copy of it's ident parameter string in the Lua registry to ensure we don't hang on to a dangling pointer. - latest `build-aux/luke` and upgraded lukefile work correctly on macOS now. ## Noteworthy changes in release 34.0 (2017-05-06) [stable] ### Incompatible Changes - `posix.syslog` constants `LOG_AUTHPRIV`, `LOG_FTP` and `LOG_SYSLOG` are no longer documented, and only defined when supported by the host C library. They are not part of the POSIX API, and prevented compilation of luaposix on AIX and Solaris. - `getopt.getopt` was a binding to the GNU `getopt_long` extension, which is not a POSIX API, and prevents luaposix from compiling on hosts that do not provide the extended API. Instead we now correctly bind POSIX getopt(3) in `posix.unistd`. If you still have code that uses the old non-POSIX binding, then LuaRocks has the Lua only `alt-getopt` module which is very similar, and works even when the host C library has no `getopt_long` API; alternatively, you should consider migrating to the far more powerful Lua-only `optparse` library, also available from LuaRocks. ### New Features - Replaced all Autotools and supporting Slingshot code with new Lua- based `build-aux/luke` and `lukefile` describing how to compile and install everything. Building with LuaRocks now leverages this too. - New `posix.sys.socket.getsockopt` and `posix.sys.socket.getpeername` bindings. - New `posix.sys.msg.msgctl` binding, and `posix.sys.msg.IPC_RMID`, `posix.sys.msg.IPC_SET` and `posix.sys.msg.IPC_STAT` constants to use with it. - New `posix.unistd.ftruncate` and `posix.unistd.truncate` bindings. - `posix.fcntl.fcntl` now accepts undocumented `posix.fcntl.O_TMPFILE` value where supported by the host C library. ### Bugs Fixed - `posix.unistd.ttyname` now returns an error message in addition to `nil` when it fails. ## Noteworthy changes in release 33.4.0 (2016-02-27) [stable] ### Incompatible Changes - posix.curses has been split back out into its own separate project again. If you want to upgrade your posix.curses using project, something like the following minimal change will work equivalently (assuming you have the new lcurses on your package path): ```lua local posix = require 'posix' posix.curses = posix.curses or require 'lcurses' ``` ### New Features - New `posix.stdio.rename` binding. - New `posix.fcntl.FD_CLOEXEC` flag for `posix.fcntl.fcntl`. - New `posix.fcntl.O_CLOEXEC` flag for `posix.fcntl.open`, where supported by the underlying system. Falling back to FD_CLOEXEC is an exercise to the caller, so that non-atomicity is surfaced: ```lua -- without error checking, for clarity fd = fcntl.open ("/foo/bar", fcntl.O_CLOEXEC, stat.S_IRWXU) if fcntl.O_CLOEXEC == 0 then local flags = fcntl.fcntl (fd, fcntl.F_GETFD) fcntl.fcntl (fd, fcntl.F_SETFD, bit.bor (flags, fcntl.FD_CLOEXEC) end ``` - New `posix.unistd.tcgetpgrp` and `posix.unistd.tcsetpgrp` bindings where supported by host C library. - `posix.sys.socket` AF_UNIX path handling improvements enable use of Linux only abstract namespace sockets. - Documentation links now point at the newer OpenGroup issue 7 specs. ### Bugs Fixed - Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=15088. Predicate use of POSIX sched.h APIs on presence of sched.h, since glibc defines _POSIX_PRIORITY_SCHEDULING erroneously, and musl libc provides the sched.h APIs but doesn't define _POSIX_PRIORITY_SCHEDULING. - `posix.sys.socket` AF_UNIX APIs pass path arguments by length instead of terminating at the first \0 byte. - `posix.unistd.readlink` no longer fails when reading a link to an unsized buffer or character special device node. - `execx` is no longer leaked into the global namespace after loading the posix module. - `examples/fork2.lua` works correctly again. - `posix.timeradd`, `posix.timercmp` and `posix.timersub` correctly handle tables from the modern thin wrapper API (posix.sys.time), while retaining compatibility with the legacy compatibility wrappers (posix.gettimeofday). ## Noteworthy changes in release 33.3.1 (2015-03-01) [stable] ### Incompatible Changes - The briefly lived `posix.system` API has been removed. It was renamed to `posix.spawn` shortly after introduction, and can still be accessed by the new symbol name. ### Bugs Fixed - `local posix = require "posix"` works again, fixing the regression introduced in the last release. The automated Travis checks have been improved to catch this sort of bug in future. ## Noteworthy changes in release 33.3.0 (2015-02-28) [stable] ### New Features - Improved documentation of `sockaddr` tables for `posix.sys.socket` calls. - New `posix.sys.socket.getsockname` binding. - Remove the `posix.bit32` library, and use Lua’s built-in `bit32` library. - Can now be linked against NetBSD curses, albeit with several functions not implemented by that library returning a "not implemented" error as a consequence. - New functions `popen`, `popen_pipeline` and `pclose` mimic the POSIX functions of the same name while allowing tasks to be Lua functions. - `fdopen` has been re-added, working on all supported Lua versions. - `execx` allows a Lua function or command to be exec’d; `spawn` is now implemented in terms of it. ### Incompatible Changes - The ncurses-only `KEY_MOUSE` definition has been removed from `posix.curses`. ### Bugs Fixed - `posix.sys.resource` only provides RLIM_SAVED_CUR and RLIM_SAVED_MAX if they are defined by the C library (which FreeBSD 10 does not). - `posix.dirent.dir` and `posix.dirent.files` now raise a Lua `error()` when unable to open the path argument, for orthogonality with `io.lines`. - Workaround for manifest key clash between `posix.so` and `posix.lua` in LuaRocks. ## Noteworthy changes in release 33.2.1 (2015-01-04) [stable] ### Bugs Fixed - Install posix.curses.html documentation file correctly. ## Noteworthy changes in release 33.2.0 (2015-01-03) [stable] ### New Features - QNX support. ### Bugs Fixed - `posix.time.gmtime` and `posix.time.localtime` specifications now work correctly in January too! ## Noteworthy changes in release 33.1.0 (2014-12-19) [stable] ### New Features - New `posix.bit32` module with band, bnot and bor functions that can be used from any supported Lua release, without worrying about loading an external bit operations library. - Preliminary Lua 5.3.0 compatibility. ### Bugs Fixed - No more 'Bad Hints' errors from `posix.sys.socket.getaddrinfo` on many hosts. - `stdlib.setenv` accepts a 3rd argument again. ## Noteworthy changes in release 33.0.0 (2014-11-04) [stable] ### New Features - The curses library is fully integrated into luaposix, including reasonably comprehensive LDoc documentation (certainly much better than the single wooly web-page in previous releases). For backwards compatibility, all APIs are re-exported from the `curses` module. - Most constants available through luaposix are now listed in the LDocs of the submodule that defines them. - For backwards compatibility, everything is still lumped together in the `posix.???` namespace, but, now raw APIs have been reorganised according to the POSIX header files they belong to: ```lua local posix = require "posix" local fcntl = require "posix.fcntl" local unistd = require "posix.unistd" local fd = fcntl.open ("x", bit32.bor (posix.O_WRONLY, posix.O_CREAT), "u=rw") unistd.write (fd, "Hello, World!\n") unistd.close (fd) ``` This makes the documentation easier to navigate, and for a better mapping between luaposix APIs and the C functions they wrap, so translating from C is now easier than ever. - Each of the newly separated submodules is self-contained, and can be copied to another project for compiling and/or loading in a custom Lua runtime. If you want to make use of this, in addition to the source for the modules you copy, you'll also need at least the files `ext/posix/_helpers.c` and `ext/include/lua52compat.c`, and also `ext/include/strlcat.c` for one or two of them. - Where submodule calls return a table representation of a similar C struct from a POSIX API, the Lua return tables have an appropriate `_type` field metatable entry compatible with lua-stdlib `std.object.type`. - `posix.signal.signal` now accepts the constants `posix.signal.SIG_DFL` or `posix.signal.SIG_IGN` in place of the strings "SIG_DFL" and "SIG_IGN". - The submodule bindings `posix.time.gmtime`, `posix.time.localtime`, `posix.time.mktime`, `posix.time.strftime` and `posix.time.strptime` now accept or create PosixTm tables with 1-to-1 field name mappings with the POSIX `struct tm`. The old APIs with custom field names is still available as `posix.gmtime`, `posix.localtime`, `posix.mktime`, `posix.strftime` and `posix.strptime`. - Similarly, `posix.time.nanosleep` now takes and returns a PosixTimespec table. The old API is still available as `posix.nanosleep`. - Where supported by the underlying system, `posix.time.clock_getres` and `posix.time.clock_gettime` now require a constant inte argument (newly defined in the `posix.time` submodule), and returns a PosixTimespec table. The old APIs are still available as `posix.clock_getres` and `posix.clock_gettime`. - Add `posix.unistd.gethostid`. The old `posix.hostid` API is still available as an alias. - Add group APIs from grp.h: `posix.grp.endgrent`, `posix.grp.getgrent`, `posix.grp.getgrgid`, `posix.grp.getgrnam` and `posix.grp.setgrent`. Consequently, `posix.getgroup` is now reimplemented in Lua over the POSIX APIs. - `posix.getgroup` defaults to current effective group when called with no arguments, for consistency with `posix.getpasswd` API. - Add pwd APIs from pwd.h: `posix.pwd.endpwent`, `posix.grp.getpwent`, `posix.pwd.getpwnam`, `posix.pwd.getpwuid` and `posix.pwd.setpwent`. Consequently, `posix.getpasswd` is now reimplemented in Lua over the POSIX APIs. - Add missing constants from sys/resource.h: `posix.sys.resource.RLIM_INFINITY`, `posix.sys.resource.RLIM_SAVED_CUR`, `posix.sys.resource.RLIM_SAVED_MAX`, `posix.sys.resource.RLIMIT_CORE`, `posix.sys.resource.RLIMIT_CPU`, `posix.sys.resource.RLIMIT_DATA`, `posix.sys.resource.RLIMIT_FSIZE`, `posix.sys.resource.RLIMIT_NOFILE`, `posix.sys.resource.RLIMIT_STACK`, `posix.sys.resource.RLIMIT_AS`. - Add missing APIs from unistd.h: `posix.unistd.getegid`, `posix.unistd.geteuid`, `posix.unistd.getgid`, `posix.unistd.getuid`, `posix.unistd.getpgrp`, `posix.unistd.getpid`, `posix.unistd.getppid`. Consequently, `posix.getpid` is now reimplemented in Lua over the POSIX APIs. - Add missing constants from signal.h; `posix.signal.SIG_DFL` and `posix.signal.SIG_IGN'. - Add missing APIs from sys/stat.h: `posix.sys.stat.S_ISBLK`, `posix.sys.stat.S_ISCHR`, `posix.sys.stat.S_ISDIR`, `posix.sys.stat.S_ISFIFO`, `posix.sys.stat.S_ISLNK`, `posix.sys.stat.S_ISREG`, `posix.sys.stat.S_ISSOCK`. - Add missing constants from sys/stat.h: `posix.sys.stat.S_IFMT`, `posix.sys.stat.S_IFBLK`, `posix.sys.stat.S_IFCHR`, `posix.sys.stat.S_IFDIR`, `posix.sys.stat.S_IFIFO`, `posix.sys.stat.S_IFLNK`, `posix.sys.stat.S_IFREG`, `posix.sys.stat.S_IRWXU`, `posix.sys.stat.S_IRUSR`, `posix.sys.stat.S_IWUSR`, `posix.sys.stat.S_IXUSR`, `posix.sys.stat.S_IRWXG`, `posix.sys.stat.S_IRGRP`, `posix.sys.stat.S_IWGRP`, `posix.sys.stat.S_IXGRP`, `posix.sys.stat.S_IRWXO`, `posix.sys.stat.S_IROTH`, `posix.sys.stat.S_IWOTH`, `posix.sys.stat.S_IXOTH`, `posix.sys.stat.S_ISGID`, `posix.sys.stat.S_ISUID`. - Add missing constants from syslog.h: `posix.syslog.LOG_CONS`, `posix.syslog.LOG_NDELAY` and `posix.syslog.LOG_PID`. - Add missing API from syslog.h: `posix.syslog.LOG_MASK`. Use this to convert syslog priority constants into mask bits suitable for bitwise ORing as the argument to `posix.syslog.setlogmask`. - Add missing constants from time.h: `posix.time.CLOCK_MONOTONIC`, `posix.time.CLOCK_PROCESS_CPUTIME_ID`, `posix.time.CLOCK_REALTIME` and `posix.time.CLOCK_THREAD_CPUTIME_ID`. - New `posix.unistd.exec` and `posix.unistd.execp` require a table of arguments, with [0] defaulting to the command name. The old string tuple passing API is still available as `posix.exec` and `posix.execp`. - `posix.util.openpty` has moved to `posix.openpty`. The old API is still available as an alias. - All posix APIs now fully and correctly diagnose extraneous and wrong type arguments with an error. - Add `posix.IPC_NOWAIT`, `posix.MSG_EXCEPT` and `posix.MSG_NOERROR` constants for message queues. - Add `posix.IPPROTO_UDP` for socket programming. - Add `posix.AI_NUMERICSERV` for posix.getaddrinfo hints flags. - Add `posix.WUNTRACED` for posix.wait flags. - Add `curses.A_COLOR` (where supported by the underlying curses library) for extracting color pair assignments from the results of `curses.window.winch`. - Add missing `curses.KEY_F31` constant. ### Bugs Fixed - `posix.fadvise` is now spelled `posix.fcntl.posix_fadvise` and takes a file descriptor first argument rather than a Lua file handle. The old misspelled bad argument type version is undocumented but still works. - `posix.getpasswd`, `posix.getpid`, `posix.pathconf`, `posix.stat`, `posix.statvfs`, `posix.sysconf` and `posix.times` process a single table argument with a list of types correctly. - `posix.syslog.openlog` now takes the bitwise OR of those constants. The old string option specified API is still available as `posix.openlog`. - `posix.syslog.setlogmask` now takes the bitwise OR of bits returned by passing priority constants to `posix.syslog.LOG_MASK`. The old API will continue to be available as `posix.setlogmask`. - `posix.readlink` is much more robust, and reports errors accurately. - configured installation installs `posix.so` into the lua cpath directory correctly. - fixed a long-standing bug where the stdio buffers were not restored after some posix.fcntl() examples, resulting in the `make check` output being truncated -- often before terminal colors were returned to normal. ## Noteworthy changes in release 32 (2014-05-30) [stable] ### New Features - Support for posix.socketpair call and posix.AF_UNIX constant. - Previously undocumented spawn, pipeline, pipeline_iterator, pipeline_slurp, euidaccess, timeradd, timercmp and timersub have been moved from the posix table, which is reserved for strictly POSIX APIs to the posix.sys subtable. The sys submodule automatically loads on first reference, so no need to require it manually if you already have the main posix module loaded. - posix api documentation is separated into groups for better discovery. ### Bugs Fixed - Builds correctly on hosts with no IPV6 capability. - Small improvements in organisation of generated html docs. - posix.openpty doesn't crash. - configure now detects Lua correctly with busybox grep. - Many fine portability fixes from latest gnulib. - Missing docs for accept, bind, connect, getaddrinfo, listen, recv, recvfrom, send, sendto, setsockopt, shutdown, socket and socketpair apis is now provided. - Missng docs for tcdrain, tcflow, tcflush, tcgetattr, tcsendbreak and tcsetattr terminal apis are now provided. - Docs for apis implemented in Lua are now shown correctly. ## Noteworthy changes in release 31 (2013-09-09) [stable] ### New Features - Missing termios cc flags are now available. ### Bugs Fixed - posix.tcgetattr and posix.tcsetattr no save and restore all flags, regardless of whether they are local extensions to POSIX. ## Noteworthy changes in release 30 (2013-08-29) [stable] ### New Features - Support for file locks with fcntl() using F_SETLK, F_SETLKW, F_GETLK, F_RDLCK, F_WRLCK and F_UNLCK. - Preliminary support for GNU Hurd, and OpenBSD. ### Bugs Fixed - posix.shutdown can actually be called now. - Report the correct argument number in posix function error messages. - Much reduced compiler warning noise. - Many small typos and inconsistencies, see ChangeLog for details. ## Noteworthy changes in release 29 (2013-06-28) [stable] - This release adds wresize to curses, and sync, fsync, fdatasync, nice, lseek as well as socket programming functions. Several small improvements to the documentation were also added. - luaposix is compatible with Lua 5.1, Lua 5.2 and luajit 2.0, so the 5.1 prefix to the release version has become an anachronism and has been dropped from this release onwards. ### New Features - Move to the Slingshot release system, which (among many other improvements) fixes release tarballs from github to work with the standard GNU-style: `./configure, make, make install`. `bootstrap` is still distributed for those who need to re-bootstrap with a different version of gnulib and/or slingshot. - Much improved former lunit and ad-hoc test scripts to Specl. ## Noteworthy changes in release 5.1.28 (2013-03-23) [stable] - This release fixes the previously unannounced posix.pipeline_iterator and posix.pipeline_slurp functions, and adds a test for them. A workaround for having LUA_INIT_5_2 set has been added to the build system. ## Noteworthy changes in release 5.1.27 (2013-03-17) [stable] - This release fixes broken Lua 5.1 compatibility in release 5.1.26 (sorry! And thanks to Nick McVeity for the bug report and patch); renames posix.system to posix.spawn (the old name is available for backwards compatibility), generalizing it to take a shell command, file and arguments, or Lua function; and adds posix.pipeline, which makes it easy to run a pipeline of processes, each a shell command, program, or Lua function. ## Noteworthy changes in release 5.1.26 (2013-03-04) [stable] - This release adds killpg, realpath and openpty, adds a flags parameter to signal, and improves some documentation. ## Noteworthy changes in release 5.1.25 (2013-02-20) [stable] - This release adds support for message queues and UNIX 98 pseudoterminals (thanks very much to the respective contributors), and allows argv[0] to be set in exec calls. ## Noteworthy changes in release 5.1.24 (2013-02-15) [stable] - This release adds isatty and constants STDIN_FILENO, STDOUT_FILENO and STDERR_FILENO, fixes a bug in readlink, adds a day field to time tables for compatibility with os.date, and overhauls the build and release system. ## Noteworthy changes in release 5.1.23 (2012-10-04) [stable] - This release fixes the curses module for Lua 5.2; previously it would not load with an unknown symbol error. The build process for luarocks has been made more robust. ## Noteworthy changes in release 5.1.22 (2012-09-13) [stable] - This release fixes building on Mac OS X and some other OSes which don't like building empty libraries. Thanks to Robert McLay for the bug report. ## Noteworthy changes in release 5.1.21 (2012-09-10) [stable] - This release adds comprehensive documentation for the posix module, from Steve Donovan and Natanael Copa. - It makes one small change: rpoll now uses file descriptors, not Lua file objects (hence, via fileno, it can use both). - Perhaps most importantly, it marks a change of maintainer, from Reuben Thomas to Alexander Nikolaev. Thanks very much to Alexander for agreeing to take over. Luaposix has garnered considerable interest in recent months, and more contributors have stepped forwards with patches. Alexander will help to oversee a maturing API, coordinate ongoing improvements and additions, and help ensure that luaposix doesn't fall back into disrepair as it has several times in the past. ## Noteworthy changes in release 5.1.20 (2012-06-22) [stable] ### New Features - Improves signal handling. - Improves the posix.system and creat functions (all thanks to Steve Donovan). - Adds mkdtemp (thanks, 7hemroc). - Adds statvfs (thanks to Like Ma). - improves the tests. - Adds some code guidelines. ### Bugs Fixed - Fixes a bug in getgroup. - Fixes some space leaks (thanks, Alexander Nikolaev), - Copes with sysconf for _PC_PATH_MAX returning -1. ### Incompatible Changes - The API of posix.open has changed to be more like the C version: the file creation and status flags are now constants in the POSIX namespace. This enables them to be used outside calls to open, and makes posix.open less magic. posix.open will now raise an error if no creation flags are given when O_CREAT is used. ## Noteworthy changes in release 5.1.19 (2012-04-10) [stable] - This release avoids the use of PATH_MAX, and copes with arbitrarily-long paths. The implementation of strlcpy is changed to a BSD-licensed implementation; the previously-used implementation was LGPL-licensed, which is not MIT-compatible; thanks to Alexander Gladysh for bringing this problem to my attention. (This was just mis-released as 5.1.18; sorry!) ## Noteworthy changes in release 5.1.18 (2012-03-26) [stable] - This release implements full Lua 5.2 compatibility; thanks to Enrico Tassi for poking me to get this done. ## Noteworthy changes in release 5.1.17 (2012-02-29) [stable] - This release improves support for Lua 5.2; the curses module should now work fine (the posix module still needs updating). Signal handling has been improved to make it possible to chain to a C signal handler, and a bug in resetting the process's signal mask after running a Lua handler has been fixed. ## Noteworthy changes in release 5.1.16 (2012-02-18) [stable] - This release includes rewritten fcntl and signals support, and bug fixes for read, chmod, getgroups and waitpid. curses boolean return values are now Lua booleans rather than 0 for OK or ERR for not OK. fnmatch, strptime and mktime are now supported, chmod now supports octal modes, thereâs much expanded poll support, and some non-POSIX and obsolete features have been removed. There are more tests and the build system has been improved. Thanks go to the many contributors to this release. ## Noteworthy changes in release 5.1.15 (2011-09-29) [stable] - This release adds dup, pipe, pipe2 and more fcntl support (thanks to Alexander V. Nikolaev and Alexander Gladysh for the patches). Two bugs in the test code which used incorrect paths and caused only one set of tests to run have been fixed. ## Noteworthy changes in release 5.1.14 (2011-09-19) [stable] - This release allows some constants to be case-insensitive in Lua, and fixes a small build-system bug. ## Noteworthy changes in release 5.1.13 (2011-09-17) [stable] This release adds a rockspec. ## Noteworthy changes in release 5.1.12 (2011-09-09) [stable] - This release adds some basic functions such as open, close, read and write, and integrates the pure Lua module which was previously in Lua stdlib. It also adds a whole new module, curses, which was previously in the separate lcurses project (curses is part of the POSIX standard). ### Incompatible Changes - Note that the C part of the POSIX module is now called posix_c.so (or similar), so if you have an old posix.so (or similar) you should delete it to avoid clashing with the new posix.lua. ## Noteworthy changes in release 5.1.11 (2011-04-27) [stable] - Apologies, 5.1.10, released earlier today, had a buffer overflow bug in the new mkstemp function. 5.1.11, just out, fixes it. ## Noteworthy changes in release 5.1.10 (2011-04-27) [stable] ### This release adds mkstemp, adds some fixes for building on Mac OS X (thanks to Gary Vaughan), removes some non-POSIX rlimit constants, guards some functions that were not correctly guarded, so that they will not be compiled on systems that don't support them, and makes other minor fixes. ## Noteworthy changes in release 5.1.9 (2011-03-24) [stable] ### New Features - support for signals and for getopt. See below for details. - Equally, there is still only the barest documentation: to use the various APIs you have to grep to see if the one you want is there and then read the C comment which gives the Lua API. If anyone is interested in adding better documentation, I'd be delighted to hear from them. (My work on luaposix is purely aimed at getting the support I need for GNU Zile, but as usual I welcome patches from others. luaposix is still far from complete, so please send patches for your favourite POSIX APIs!) - luaposix 5.1.9 improves compatibility with Darwin/Mac OS X, and adds various new API bindings, for signals, getgroups, setting errno and _exit, as well as some slight code cleanup. ## Noteworthy changes in release 5.1.8 (2013-03-23) [stable] ### Bugs Fixed - fix bugs for setrlimit and gettimeofday. - an improvement to test.lua. - better use of POSIX feature macros to determine what APIs to support. - removal of the obsolete timezone argument to gettimeofday, - remove the non-POSIX gecos field of struct passwd - improvements to the build system - some code tidy-up, - removal of Lua 5.0 compatibility ### New APIs - abort, raise, isprint, isgraph, errno and stdio.h constants, and getopt_long. ## Noteworthy changes in release 5.1.7 (2013-03-23) [stable] A new minor bugfix release of luaposix is out. ### Bugs Fixed - make clock_* functions' argument optional - fixes posix.version string ## Noteworthy changes in release 5.1.6 (2010-08-11) [stable] - This release adds time functions: gettimeofday, clock_getres, clock_gettime, localtime, gmtime, time, strftime. ## Noteworthy changes in release 5.1.5 (20??-??-??) [stable] The release notes for this release were lost in the mists of thyme. ## Noteworthy changes in release 5.1.4 (2008-07-18) [stable] - Includes a fix for rpoll() from debian[1] and a patch from openwrt[2] that adds crypt(). ## Noteworthy changes in release 5.1.3 (2013-03-23) [stable] No changes. ## Noteworthy changes in release 5.1.2 (2008-01-29) [stable] ### Incompatible changes - Please note that this release breakes the API for dup() and exec() ### New Features - dup() now takes and returns lua files rather than file descriptors (int). - exec() uses now execv(3) rather than execvp(3). This means that the PATH environment variable is no longer used which means that all scripts currently using exec() without an absolute path will break. If you need the PATH variable, use the new execp() function. - Added openlog(), syslog() and closelog() functions. - The openlog(ident, [option], [facility]) function differs from the recently released luasyslog by giving the user possibility to set "option". The "option" parameter is a string containing one or more of the chars: ``` 'c' - LOG_CONS 'n' - LOG_NDELAY 'e' - LOG_PERROR 'p' - LOG_PID ``` It is possible to disable those funcs compile time by setting the ENABLE_SYSLOG define to 0. - fileno() function was added. ## Noteworthy changes in release 5.1.1 (2008-01-25) [stable] - I have forked lposix. First release includes some patches submitted on this list. This first release is basicly lposix with a cleaned up Makefile + the patches found here: http://lua-users.org/lists/lua-l/2006-10/msg00448.html http://lua-users.org/lists/lua-l/2007-11/msg00346.html - When the promised extened OS library[1] arrives I will most likely remove the overlapping functions in luaposix. posix specific functions that does not overlap will still be maintained and added. (e.g dup()) - Releases numbered 5.1.x[.y] will work with lua-5.1 series. The 'x' will add/change features and .y releases will be strict bugfixes (no new features). - I had planned to add syslog functions and fix dup() to handle lua files (FILE*) rather than file descriptors (int). Now that luasyslog just released I will have to re-evaluate that. luaposix-36.3/README.md000066400000000000000000000124501475444374100146070ustar00rootroot00000000000000luaposix ======== By the [luaposix project][github] [![License](https://img.shields.io/:license-mit-blue.svg)](https://mit-license.org) [![workflow status](https://github.com/luaposix/luaposix/actions/workflows/spec.yml/badge.svg?branch=release-v36.3)](https://github.com/luaposix/luaposix/actions) [![codecov.io](https://codecov.io/github/luaposix/luaposix/coverage.svg?branch=release-v36.3)](https://codecov.io/github/luaposix/luaposix?branch=release-v36.3) This is a POSIX binding for [LuaJIT][], [Lua][] 5.1, 5.2, 5.3 and 5.4; like most libraries it simply binds to C APIs on the underlying system, so it won't work on non-POSIX systems. However, it does try to detect the level of POSIX conformance of the underlying system and bind only available APIs. For a while, luaposix contained support for curses functionality too, but now that has its own [lcurses][] repository again, where it is being maintained separately. luaposix is released under the [MIT license][mit] (the same license as Lua itsef). There is no warranty. [github]: https://github.com/luaposix/luaposix "luaposix repository" [lcurses]: https://github.com/lcurses/lcurses "lcurses repository" [lua]: https://www.lua.org/ "The Lua Project" [luajit]: https://luajit.org/ "The LuaJIT Project" [mit]: https://mit-license.org "MIT license" Installation ------------ The simplest and best way to install luaposix is with [LuaRocks][]. To install the latest release (recommended): ```bash luarocks install luaposix ``` To install current git master (for testing, before submitting a bug report for example): ```bash luarocks install http://raw.github.com/luaposix/luaposix/master/luaposix-git-1.rockspec ``` The best way to install without [LuaRocks][], is to call the bundled `build-aux/luke` command, as shown in the `build` section of the included rockspec file, from a freshly cloned working copy. Note that you'll be responsible for providing dependencies if you choose not to let [LuaRocks][] handle them for you, though you can find a list of minimal dependencies in the rockspec file. If you are repackaging or redistributing [luaposix][github], it is better to start from a [release tarball][releases], because the [master][github] development branch is branch is unstable, and sometimes breaks subtly, or does not build at all, or provides experimental new APIs that end up being removed prior to the next official release. Note that there are full logs of complete builds for every commit in [Github Actions][actions], which you can compare with your progress if you get stuck. [luarocks]: http://www.luarocks.org "Lua package manager" [releases]: http://github.com/luaposix/luaposix/releases [actions]: https://github.com/luaposix/luaposix/actions Use --- The library is split into submodules according to the POSIX header file API declarations, which you can require individually: ```lua local unistd = require 'posix.unistd' ``` The authoritative online POSIX reference is published at [SUSv3][]. [susv3]: http://www.opengroup.org/onlinepubs/007904875/toc.htm Documentation ------------- The latest release of this library is [documented in LDoc][github.io]. Pre-built HTML files are included in the release, and contain links to the appropriate [SUSv3][] manual pages. [github.io]: http://luaposix.github.io/luaposix Example code ------------ See the example program `tree.lua`, along with the many small examples in the generated documentation and BDD `specs/*_spec.yaml`. For a complete application, see the [GNU Zile][]. [GNU Zile]: http://git.savannah.gnu.org/cgit/zile.git/log/?h=lua "A cut-down Emacs clone" Bugs reports and code contributions ----------------------------------- These libraries are maintained by their users. Please make bug reports and suggestions as [GitHub issues][issues]. Pull requests are especially appreciated. But first, please check that your issue has not already been reported by someone else, and that it is not already fixed on [master][github] in preparation for the next release (See Installation section above for how to temporarily install master with [LuaRocks][]). There is no strict coding style, but please bear in mind the following points when proposing changes: 0. Follow existing code. There are a lot of useful patterns and avoided traps there. 1. 8-character indentation using TABs in C sources; 3-character indentation using SPACEs in Lua sources. 2. Simple strings are easiest to type using single-quote delimiters saving double-quotes for where a string contains apostrophes. 3. Save horizontal space by only using SPACEs where the parser requires them. 4. Use vertical space to separate out compound statements to help the coverage reports discover untested lines. 5. Prefer explicit string function calls over object methods, to mitigate issues with monkey-patching in caller environment. 6. No non-POSIX APIs; no platform-specific code. When wrapping APIs introduced in POSIX 2001 or later, add an appropriate #if. If your platform isn't quite POSIX, you may find a gnulib module to bridge the gap. If absolutely necessary, use luke feature tests. 7. Thin wrappers: although some existing code contradicts this, wrap POSIX APIs in the simplest way possible. If necessary, more convenient wrappers can be added in Lua (posix.lua). [issues]: http://github.com/luaposix/luaposix/issues luaposix-36.3/build-aux/000077500000000000000000000000001475444374100152205ustar00rootroot00000000000000luaposix-36.3/build-aux/config.ld.in000066400000000000000000000027431475444374100174210ustar00rootroot00000000000000-- -*- lua -*- title = "@package@ @version@ Reference" project = "@package@ @version@" description = "POSIX bindings for Lua" tparam_alias "string" tparam_alias "int" tparam_alias "bool" -- Manual page links point to the OpenGroup POSIX spec, issue 7 (POSIX.2008). local upat = "http://pubs.opengroup.org/onlinepubs/9699919799/functions/%s.html" custom_see_handler("^([%w_]+)%((%d)%)$",function(name,section) local url = upat:format(name) return name .. "(" .. section .. ")", url end) dir = "../doc" file = { "../lib/posix/init.lua", "../lib/posix/compat.lua", -- Documents added to posix module "../ext/posix/ctype.c", "../ext/posix/dirent.c", "../ext/posix/errno.c", "../ext/posix/fcntl.c", "../ext/posix/fnmatch.c", "../ext/posix/glob.c", "../ext/posix/grp.c", "../ext/posix/libgen.c", "../ext/posix/poll.c", "../ext/posix/pwd.c", "../ext/posix/sched.c", "../ext/posix/signal.c", "../ext/posix/stdio.c", "../ext/posix/stdlib.c", "../ext/posix/sys/msg.c", "../ext/posix/sys/resource.c", "../ext/posix/sys/socket.c", "../ext/posix/sys/stat.c", "../ext/posix/sys/statvfs.c", "../ext/posix/sys/time.c", "../ext/posix/sys/times.c", "../ext/posix/sys/utsname.c", "../ext/posix/sys/wait.c", "../ext/posix/syslog.c", "../ext/posix/termio.c", "../ext/posix/time.c", "../ext/posix/unistd.c", "../ext/posix/utime.c", } examples = "../doc/examples" boilerplate = true backtick_references = false format = "markdown" merge = true sort = true luaposix-36.3/build-aux/luke000077500000000000000000001051211475444374100161060ustar00rootroot00000000000000#!/usr/bin/env lua --[[ minified code follows, see --help text for source location! ]] local require=function(modname)if package.loaded[modname]==nil then if type(package.preload[modname])~="function"then io.stderr:write("module '" .. modname .. "' not found:\n no valid field package.preload['" .. modname .. "']\n") return nil end package.loaded[modname]=package.preload[modname](modname,"package.preload")end return package.loaded[modname]end package.preload['luke._base']=function() local _ENV=require'std.normalize'{}local function fatal(...)local msg=(...)if select('#',...)>1 then msg=format(...)end stderr:write('luke: fatal: '..msg..'\n')exit(1)end return{diagnose=function(predicate,...)if not predicate then fatal(...)end end,fatal=fatal,} end package.preload['luke.cli']=function() local _ENV=require'std.normalize'{'luke._base','luke.lukefile','luke.platforms','std.functional',}local function version()print[[ luke (Luke) 0.3 Written by Gary V. Vaughan , 2014 Copyright (C) 2023, Gary V. Vaughan Luke comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of Luke under the terms of the MIT license; it may be used for any purpose at absolutely no cost, without permission. See for details. ]]exit(0)end local function help()print[[ Usage: luke [OPTION]... [VAR=VALUE]... [TARGET] Use the source, Luke! --help print this help, then exit --version print version number, then exit --file=FILE use FILE instead of lukefile --value=NAME print the value of variable NAME --quiet without any output --verbose provide more progress output Each TARGET can be one of the module table keys from lukefile, or: all build all targets in lukefile install copy all built targets to $PREFIX If no TARGET is given, 'all' is implied. Report bugs to https://github.com/gvvaughan/luke/issues.]]exit(0)end local function opterr(...)local msg=(...)if select('#',...)>1 then msg=format(...)end msg=gsub(msg,'%.$','')stderr:write('luke: error: '..msg..'.\n')stderr:write("luke: try '"..arg[0].." --help' for help.\n")exit(2)end local function display(...)return stdout:write(concat{...})end local function dump(...)local s=concat(map(list(...),str))if len(s)>0 then gsub(concat(map(list(...),str)),'\n*$','\n'):gsub('(.-)\n',function(line)stderr:write(' DEBUG: '..line..'\n')end)end end local function interpolate_to_substitute(s)return(gsub(s,'%$([%w_]+)','@%1@'))end return{parse_arguments=function(args)local r={clidefs={},valreqs={},fname='lukefile',install={},log=nop,targets={},verbose=nop,write=display,}map(args,function(opt)case(opt,{['--debug']=function()r.log=dump end,['%-%-file=(.+)']=function(optarg)r.fname=optarg end,['%-%-value=(.+)']=function(optarg)r.valreqs[#r.valreqs+1]=optarg end,['--quiet']=function()r.write=nop end,['--verbose']=function()r.verbose=display end,['--help']=help,['--version']=version,['([^-][^=]-)=(.+)']=function(name,value)r.clidefs[name]=value end,function(opt)if match(opt,'^-')~=nil then opterr("unrecognized option '%s'",opt)end append(r.targets,opt)end,})end)return r end,validate_arguments=function(parsed)local luke,err=loadluke(parsed.fname)diagnose(luke~=nil,'bad %s: %s',parsed.fname,err)if isempty(luke.modules or{})then fatal("no modules table in '%s', nothing to build",parsed.fname)end local targets=call(function()if isempty(parsed.targets)or contains(parsed.targets,'all')then return except(flatten(parsed.targets,keys(luke.modules)),'all')end local r=filter(parsed.targets,function(target)if target~='install'and luke.modules[target]==nil then fatal("no rule to make target '%s'",target)end return true end)assert(len(r)>0,"no build targets specified")return r end)local install local build=pluck(targets,luke.modules)if contains(targets,'install')then install=build or luke.modules end luke.modules=build if isempty(luke.modules)then luke.external_dependencies=nil end luke.substitute=merge(luke.substitute or{},{package=interpolate_to_substitute(luke.package),version=interpolate_to_substitute(luke.version),})luke.variables=merge(luke.variables or{},collect_variables(luke),{LUA_DIR='/usr',LUA_BINDIR='$LUA_DIR/bin',LUA_INCDIR='$LUA_DIR/include/lua$LUAVERSION',LUA_LIBDIR='$LUA_DIR/lib',objdir=platforms[1],package=luke.package,version=luke.version,})return{clidefs=parsed.clidefs,install=install,log=parsed.log,luke=luke,valreqs=parsed.valreqs,verbose=parsed.verbose,write=parsed.write,}end,} end package.preload['luke.compile']=function() local _ENV=require'std.normalize'{'luke._base','luke.environment','std.functional','type.context-manager','type.path',SHELLMETACHARS='[%s%$"]',}local function spawn(env,...)local command=interpolate(env,concat({...},' '))return with(TmpFile(),TmpFile(),function(out,err)local pipe=concat{command,' >',out.filename,' 2>',err.filename,'; printf $?'}return tonumber(slurp(Pipe(pipe))),slurp(File(err.filename)),slurp(File(out.filename))end)end local function run(L,env,command)L.write(interpolate(env,concat(command,' ')),'\n')local status,err,out=spawn(env,unpack(command))if status~=0 then if L.write==nop then stdout:write(concat(command,' ')..'\n')end stderr:write(err..'\n')end return status,out,err end local function defines(...)return zip_with(merge({},unpack(except(list(...),nil))),function(name,value)local fmt=cond({[int(value)==1]='-D%s'},{[match(value,SHELLMETACHARS)~=nil]="-D%s='%s'"},{[true]='-D%s=%s'})return format(fmt,name,value)end)end local function incdirs(...)return map(flatten(...),function(v)return'-I'..v end)end local function libdirs(...)return map(flatten(...),function(v)return'-L'..v end)end local function c_module_path(objdir,name)return format('%s/%s.$LIB_EXTENSION',objdir,gsub(name,'%.','/'))end local function c_source(module,objdir)local path=gsub(module,'%.','/')local src=c_module_path(objdir,path)return src,(gsub('$INST_LIBDIR/'..path,'/[^/]+$',''))end local function lua_source(module,src)local abspath='$INST_LUADIR/'..gsub(module,'%.','/')if match(src,'/init%.lua$')then abspath=abspath..'/init'end abspath=abspath..'.lua'return src,(gsub(abspath,'/[^/]+%.lua$',''))end local function module_to_path(module,sources,objdir)return dropuntil(sources,function(source)return case(source,{['.*%.[ch]']=bind(c_source,{module,objdir}),['(.*%.[ch])%.in']=bind(c_source,{module,objdir}),['.*%.lua']=bind(lua_source,{module}),['(.*%.lua)%.in']=bind(lua_source,{module}),function(src)fatal("unsupported source type '%s'",src)end,})end)end return{build_c_module=function(L,env,luke,name)local rules=luke.modules[name]local c_module=c_module_path(luke.variables.objdir,name)local command={'$MAKEDIRS',dirname(c_module)}local status,err,out=spawn(env,unpack(command))if status~=0 then stdout:write(concat(command,' ')..'\n')stderr:write(err..'\n')exit(status)end return run(L,env,flatten('$CC $CFLAGS $LIBFLAG $PKGFLAGS $CPPFLAGS',defines(rules.defines,luke.defines),incdirs(rules.incdirs,luke.incdirs),rules.sources,'-o',c_module,'$LDFLAGS',libdirs(rules.libdirs,luke.libdirs),'$LIBS',rules.libraries,luke.libraries))end,c_modules=function(modules)return filter(keys(modules),function(name)return dropuntil(modules[name].sources,bind(match,{[2]='%.[ch]$'}))end)end,defines=defines,incdirs=incdirs,install_modules=function(L,env,luke,modules)return reduce(keys(modules),0,function(status,name)if status==0 then local src,dir=module_to_path(name,modules[name].sources,luke.variables.objdir)if not exists(interpolate(env,dir))then status=run(L,env,{'$MAKEDIRS',dir})end if status==0 then status=run(L,env,{'$INSTALL',src,dir..'/'})end end return status end)end,libdirs=libdirs,run_command=run,spawn=spawn,} end package.preload['luke.configure']=function() local _ENV=require'std.normalize'{'luke._base','luke.compile','luke.environment','std.functional','type.context-manager','type.dict',CCPROGS={'cc','gcc','clang'},}local function logspawn(L,env,filename,...)local status,err=spawn(env,...)if status~=0 and err~=''then with(File(filename,'r'),function(h)L.log(h.filename..':')L.log(slurp(h))end)L.log(err)end return status end local function checking(L,...)L.verbose('checking ',concat({...},' '),'... ')end local function found_library(L,x)if x==nil or x==''then L.verbose'none required'elseif isempty(x)then L.verbose'not supported'else L.verbose(x)end L.verbose'\n'return x end local function found_prog(L,x)L.verbose(x and'yes\n'or'no\n')return x end local function found_result(L,x)L.verbose(x==0 and'yes\n'or'no\n')return x~=0 and 0 or 1 end local function bindirs(...)return map(flatten(...),function(v)return v..':'end)end local function compile_command(L,env,config,filename)local command=flatten('$CC','-c','$CFLAGS',defines(L.luke.defines),incdirs(config.incdir),'$CPPFLAGS',filename)L.log(interpolate(env,concat(command,' ')))return unpack(command)end local function link_command(L,env,config,a_out,source,lib)local command=flatten('$CC','$CFLAGS',defines(L.luke.defines),incdirs(config.incdir),'$CPPFLAGS','-o',a_out,source,libdirs(config.libdir),'$LDFLAGS',lib,'$libs',CONFIGENV.libs)L.log(interpolate(env,concat(command,' ')))return unpack(command)end local function check_executable_in_path(L,env,config,prog)local PATH=concat(bindirs(config.bindir))..getenv('PATH')local found=dropuntil(gmatch(PATH,'[^:]+'),function(path)local progpath=path..'/'..prog return with(File(progpath,'r'),function(h)return h and isfile(h.context)and progpath or nil end)end)L.log(found and'found '..found or prog..' not found')return found~=nil end local function check_header_compile(L,env,config,header,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format('%s\n#include "%s"\n',extra_hdrs,header))conftest:flush()return logspawn(L,env,conftest.filename,compile_command(L,env,config,conftest.filename))end)end local function check_struct_member_compile(L,env,config,structname,member,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format([[ %s int main () { static %s aggr; if (sizeof aggr.%s) return 0; return 0; } ]],extra_hdrs,structname,member))conftest:flush()return logspawn(L,env,conftest.filename,compile_command(L,env,config,conftest.filename))end)end local function try_link(L,env,config,lib,symbol)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char %s (); int main () { return %s (); } ]],symbol,symbol))conftest:flush()return logspawn(L,env,conftest.filename,link_command(L,env,config,a_out.filename,conftest.filename,lib))end)end local function try_compile(L,env,config,headers)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[ %s #if !defined %s || %s == -1 choke me #endif int main() { return 0; } ]],headers,config.ifdef,config.ifdef))conftest:flush()return logspawn(L,env,conftest.filename,link_command(L,env,config,a_out.filename,conftest.filename))end)end local function check_func_decl(L,env,config,fname,extra_hdrs)return with(CTest(),function(conftest)conftest:write(format([[ %s int main() { #ifndef %s (void) %s; #endif return 0; } ]],extra_hdrs,fname,fname))conftest:flush()return logspawn(L,env,conftest.filename,compile_command(L,env,config,conftest.filename))end)end local function check_func_link(L,env,config,fname)return with(CTest(),TmpFile(),function(conftest,a_out)conftest:write(format([[ /* Define to an innocous variant, in case declares it. For example, HP-UX 11i declares gettimeofday. */ #define %s innocuous_%s /* System header to define __stub macros and hopefully few prototypes, which can conflict with declaration below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef %s /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char %s (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_%s || defined __stub__%s choke me #endif int main () { return %s (); } ]],fname,fname,fname,fname,fname,fname,fname))conftest:flush()return logspawn(L,env,conftest.filename,link_command(L,env,config,a_out.filename,conftest.filename))end)end local function add_external_deps(env,config,prefix)if prefix~=nil then for k,v in next,{bindir='$%s_BINDIR',incdir='$%s_INCDIR',libdir='$%s_LIBDIR'}do local envvar=interpolate(env,format(v,prefix))if envvar~=''then config[k]=envvar end end end end local function format_includes(includes)return map(includes or{},function(include)return format('#include "%s"',include)end)end local configure=setmetatable(OrderedDict({checkprog=function(L,env,config)return dropuntil(config.progs,function(prog)checking(L,'for',prog)if found_prog(L,check_executable_in_path(L,env,config,prog))then return prog end end)or fatal('cannot find '..config.checkprog)end},{checkheader=function(L,env,config)checking(L,'for',config.checkheader)local extra_hdrs=concat(format_includes(config.includes),'\n')return found_result(L,check_header_compile(L,env,config,config.checkheader,extra_hdrs))end},{checkdecl=function(L,env,config)checking(L,'whether',config.checkdecl,'is declared')local extra_hdrs=concat(format_includes(config.includes),'\n')return found_result(L,check_func_decl(L,env,config,config.checkdecl,extra_hdrs))end},{checksymbol=function(L,env,config)checking(L,'for library containing',config.checksymbol)if config.ifdef~=nil then local headers=concat(format_includes(config.includes),'\n')if try_compile(L,env,config,headers)~=0 then return found_library(L,{})end end local libraries,symbol=config.libraries,config.checksymbol local trylibs=reduce(libraries,{''},function(r,lib)append(r,'-l'..lib)end)return dropuntil(trylibs,function(lib)if try_link(L,env,config,lib,symbol)==0 then if lib~=''then if CONFIGENV.libs~=''then CONFIGENV.libs=' '..CONFIGENV.libs end CONFIGENV.libs=lib..CONFIGENV.libs end return found_library(L,lib)end end)or call(function()L.verbose'\n'fatal("required symbol '%s' not found in any of libc, lib%s",symbol,concat(libraries,', lib'))end)end},{checkfunc=function(L,env,config)checking(L,'for',config.checkfunc)return found_result(L,check_func_link(L,env,config,config.checkfunc))end},{checkmember=function(L,env,config)checking(L,'for',config.checkmember)local extra_hdrs=concat(format_includes(config.includes),'\n')local i=find(config.checkmember,'%.')local structname=sub(config.checkmember,1,i-1)local member=sub(config.checkmember,i+1)return found_result(L,check_struct_member_compile(L,env,config,structname,member,extra_hdrs))end}),{__call=function(self,L,env,config,prefix)return case(type(config),{['number']=function()return str(config)end,['string']=function()return config end,['table']=function()return dropuntil(self,function(fname)if config[fname]~=nil then add_external_deps(env,config,prefix)return apply(self[fname],list(L,env,config))end end)or fatal("unable to configure with keys '%s'",concat(keys(config),"', '"))end,function(type)fatal("unsupported configure type '%s'",type)end,})end,})return{config_compiler=function(L,env)local CC=env.CC if CC==nil then CC=configure(L,env,{checkprog='C compiler',progs=CCPROGS})env=makeenv(env,{CC=CC})end checking(L,interpolate(env,'whether $CC works'))local cm=CTest()local works,err=with(cm,function(conftest)conftest:write('typedef int x;\n')conftest:flush()return spawn(env,'$compile',conftest.filename)end)if works~=0 then L.verbose'no\n'L.log(interpolate(env,'$compile '..cm.filename))if err and err~=''then L.log(err)end fatal('could not find a working C compiler')end found_prog(L,CC)return env end,config_ldoc=function(L,env)local LDOC=env.LDOC if LDOC==nil then LDOC=configure(L,env,{checkprog='LDocs generator',progs={'ldoc','true'}})env=makeenv(env,{LDOC=LDOC})end return env end,configure=configure,} end package.preload['luke.environment']=function() local _ENV=require'std.normalize'{'luke.platforms','std.functional',LUAVERSION=string.gsub(_VERSION,'[^0-9%.]+',''),}local env_mt={__index=function(self,varname)return dropuntil(self,function(env)local value=env[varname]if value~=nil then self[varname]=value return value end end)end,}local function interpolate_with(pattern,env,s)local r=''while r~=s do r=s s=gsub(r,pattern,function(varname)return env[varname]or''end)end return r end local function isenv(t)return getmetatable(t)==env_mt end return{CONFIGENV={compile='$CC -c $CFLAGS $CPPFLAGS',libs='',link='$CC $CFLAGS $CPPFLAGS $LDFLAGS',},DEFAULTENV=filter_platforms{LUAVERSION=LUAVERSION,PREFIX='/usr/local',INST_LIBDIR='$PREFIX/lib/lua/$LUAVERSION',INST_LUADIR='$PREFIX/share/lua/$LUAVERSION',LIB_EXTENSION='so',OBJ_EXTENSION='o',INSTALL='cp',MAKEDIRS='mkdir -p',CFLAGS='-O2',platforms={macosx={LIBFLAG='-fPIC -bundle -undefined dynamic_lookup -all_load',},LIBFLAG='-shared -fPIC',},},SHELLENV=setmetatable({},{__index=function(_,v)return getenv(v)end,}),expand=bind(interpolate_with,{'@([^@]+)@'}),interpolate=bind(interpolate_with,{'%$([%w_]+)'}),makeenv=function(...)local env=reduce(except(list(...),nil),function(r,t)if isenv(t)then map(t,bind(append,{r}))else append(r,t)end end)return setmetatable(env,env_mt)end,} end package.preload['luke']=function() local _ENV=require'std.normalize'{'luke.cli','luke.compile','luke.configure','luke.environment','luke.lukefile','std.functional',}local function run_ldocs(L,env,ldocs)return run_command(L,env,flatten{'$LDOC -c',ldocs.sources,'.'})end local function build_modules(L,env)local conf=makeenv(CONFIGENV,env)if not isempty(L.luke.ldocs or{})then conf=config_ldoc(L,conf)env=makeenv(env,{LDOC=conf.LDOC})end local c=c_modules(L.luke.modules)if not isempty(c)then conf=config_compiler(L,conf)env=makeenv(env,{CC=conf.CC})end L.luke=run_configs(L,conf,L.luke)local substitute=makeenv(L.clidefs,L.luke.substitute,SHELLENV)L.luke=run_templates(L,substitute,L.luke)local status=dropuntil(c,isnonzero,function(name)return build_c_module(L,env,L.luke,name)end)or 0 if status==0 and not isempty(L.luke.ldocs or{})then status=run_ldocs(L,env,L.luke.ldocs)end return status end return{main=function(args)local L=validate_arguments(parse_arguments(args))local env=makeenv(L.clidefs,L.luke.variables,DEFAULTENV,SHELLENV)local status=0 if not isempty(L.valreqs)then map(L.valreqs,function(name)print(interpolate(env,concat{name,"='$",name,"'"}))end)exit(0)end if status==0 and not isempty(L.luke.modules or{})then status=build_modules(L,env)end if status==0 then status=install_modules(L,env,L.luke,L.install)end return status end,} end package.preload['luke.lukefile']=function() local _ENV=require'std.normalize'{'luke._base','luke.configure','luke.environment','luke.platforms','std.functional','type.context-manager',}local function has_anykey(t,keylist)return any(map(keylist,function(k)return t[k]~=nil end))end local function isconfig(x)return istable(x)and has_anykey(x,configure)end local function collect_configs(luke,modulename,configs,sectionname)configs=configs or{}for k,v in next,luke do if isconfig(v)then append(configs,{t=luke,k=k,module=modulename,section=sectionname})elseif istable(v)then if k=='modules'or k=='external_dependencies'then for name,rules in next,v do collect_configs(rules,name,configs,k)end else collect_configs(v,modulename,configs,sectionname)end end end return configs end local function deepcopy(t)return mapvalues(t,function(v)return case(type(v),{['table']=function()return deepcopy(v)end,v,})end)end local weighting=setmetatable(copy(configure),{__call=function(self,config)local t=config.t[config.k]for i=1,len(self)do if t[self[i]]~=nil then return i end end end})local function config_cmp(a,b)return weighting(a)0 then return{sources=rules}elseif isstring(rules.sources)then return merge({sources={rules.sources}},normalize_configs(rules))end return normalize_configs(rules)end,function(v)fatal("unsupported rule type '%s'",v)end,})end local function unwrap_external_dependencies(luke)if istable(luke.external_dependencies)then for prefix,config in next,luke.external_dependencies do if istable(config)and next(config)and config.library~=''then luke.incdirs=append(luke.incdirs or{},format('$%s_INCDIR',prefix))luke.libdirs=append(luke.libdirs or{},format('$%s_LIBDIR',prefix))luke.libraries=append(luke.libraries or{},config.library)end end luke.external_dependencies=nil end return luke end return{loadluke=function(filename)local content,err=slurp(File(filename))if content==nil then return nil,err end local r={}local chunk,err=loadstring(content,filename,r)if chunk==nil then return nil,"Error loading file: "..err end local ok,err=pcall(chunk)if not ok then return nil,"Error running file: "..err end r=filter_platforms(r)r.external_dependencies=normalize_configs(r.external_dependencies)r.ldocs=normalize_rules(r.ldocs)r.modules=mapvalues(r.modules,normalize_rules)return r end,collect_variables=function(luke)return collect_variables(luke,{})end,run_configs=function(L,env,luke)local r=deepcopy(luke)local all_configs=collect_configs(r)sort(all_configs,config_cmp)map(all_configs,function(config)local prefix=case(config.section,{external_dependencies=function()return config.module end,})config.t[config.k]=configure(L,env,config.t[config.k],prefix)end)return unwrap_external_dependencies(r)end,run_templates=function(L,env,luke)local r=copy(luke)local rewrite=bind(rewrite_template_files,{L,env})r.modules=mapvalues(r.modules,function(rules)rules.sources=map(rules.sources,rewrite)end)if r.ldocs then r.ldocs.sources=map(r.ldocs.sources,rewrite)end return r end,} end package.preload['luke.platforms']=function() local _ENV=require'std.normalize'{'std.functional',}local CANON={['AIX']=list('aix','unix'),['FreeBSD']=list('freebsd','bsd','unix'),['OpenBSD']=list('openbsd','bsd','unix'),['NetBSD']=list('netbsd','bsd','unix'),['Darwin']=list('macosx','bsd','unix'),['Linux']=list('linux','unix'),['SunOS']=list('solaris','unix'),['^CYGWIN']=list('cygwin','unix'),['^MSYS']=list('msys','cygwin','unix'),['^Windows']=list('win32','windows'),['^MINGW']=list('mingw32','win32','windows'),['^procnto']=list('qnx'),['QNX']=list('qnx'),['Haiku']=list('haiku','unix'),}local ALLPLATFORMS=reduce(values(CANON),function(acc,platforms)map(platforms,function(v)acc[v]=true end)end)local function match_uname(canon,uname,x)return match(uname,x)and canon[x]end local function toplatforms(canon,uname)local literalkeys,patternkeys=partition(keys(canon),function(k)return sub(k,1,1)~='^'end)return(pluck(literalkeys,canon)or{})[uname]or dropuntil(map(patternkeys,bind(match_uname,{canon,uname})))or list('unix')end local supported=toplatforms(CANON,popen('uname -s'):read'*l')local function isplatform(x)return ALLPLATFORMS[x]~=nil end local function filter_platforms(t,using,predicate)local r,supported,isplatform={},using or supported,predicate or isplatform for k,v in next,t do if k=='platforms'then local matches=filter(supported,bind(get,{v}))local default=except(keys(v),isplatform)merge(r,hoist(matches,v)or pluck(default,v))elseif istable(v)then r[k]=filter_platforms(v,supported)else r[k]=r[k]or v end end return r end return{filter_platforms=filter_platforms,platforms=supported,toplatforms=toplatforms,} end package.preload['std.functional']=function() local _ENV=require'std.normalize'{destructure=next,isfile=function(x)return io.type(x)=='file'end,wrap=coroutine.wrap,yield=coroutine.yield,}local function apply(fn,argu)assert(fn~=nil,'cannot apply nil-valued function')if iscallable(fn)then return fn(unpack(argu))end return fn end local function call(fn,...)assert(fn~=nil,'cannot call nil-valued function')if iscallable(fn)then return fn(...)end return fn end local function wrapnonnil(iterator)return function(...)local r=list(iterator(...))if r[1]~=nil then return r end end end local function each(seq)if type(seq)=='function'then return wrapnonnil(seq)end local i,n=0,int(seq.n)or len(seq)return function()if i=i and n or i-1 return apply(fn,argu)end end,call=call,case=function(s,branches)if branches[s]~=nil then return call(branches[s],s)end local DEFAULT=1 for pattern,fn in next,branches do if pattern~=DEFAULT then local argu=list(match(s,'^'..pattern..'$'))if argu[1]~=nil then return apply(fn,argu)end end end local default=branches[DEFAULT]if iscallable(default)then return call(default,s)end return default end,cond=function(...)for clauseu in each(list(...))do local expr,consequence=destructure(unpack(clauseu))if expr then return call(consequence,expr)end end end,contains=function(seq,predicate)if type(predicate)~='function'then predicate=eq(predicate)end for valu in each(seq)do if predicate(unpack(valu))then return true end end end,destructure=destructure,dropuntil=function(seq,predicate,block)if block==nil then predicate,block=isnonnil,predicate end if block~=nil then for valu in each(seq)do local r=list(block(unpack(valu)))if predicate(unpack(r))then return unpack(r)end end else for r in each(seq)do if predicate(unpack(r))then return unpack(r)end end end end,except=except,filter=function(seq,predicate)predicate=mkpredicate(predicate)local r={}for valu in each(seq)do if predicate(unpack(valu))then r[#r+1]=unpack(valu)end end return r end,flatten=flatten,foldkeys=function(keymap,dict,combinator)local r={}for k,v in next,dict or{}do local key=keymap[k]if key then r[key]=combinator(v,dict[key])else r[k]=r[k]or v end end return r end,get=function(dict,key)return(dict or{})[key]end,hoist=function(keylist,dict)local r={}for keyu in each(keylist)do merge(r,dict[unpack(keyu)])end return next(r)and r or nil end,id=function(...)return...end,isempty=function(x)return type(x)=='table'and not next(x)end,isfile=isfile,isfunction=function(x)return type(x)=='function'end,isnil=function(x)return x==nil end,isstring=function(x)return type(x)=='string'end,istable=function(x)return type(x)=='table'end,isnonzero=function(x)return x~=0 end,keys=function(iterable)local r=list()for k in next,iterable or{}do append(r,k)end return r end,map=function(seq,block)local r=list()for valu in each(seq)do append(r,block(unpack(valu)))end return r end,mapvalues=function(iterable,block)local r={}for k,v in next,iterable or{}do r[k]=block(v)or v end return r end,nop=function()end,partition=function(seq,block)local r,s=list(),list()for valu in each(seq)do append(block(unpack(valu))and r or s,unpack(valu))end return r,s end,pluck=function(keylist,dict)local r={}for keyu in each(keylist)do local key=unpack(keyu)r[key]=dict[key]end return next(r)and r or nil end,reduce=function(seq,acc,block)if block==nil then acc,block={},acc end for valu in each(seq)do acc=block(acc,unpack(valu))or acc end return acc end,values=function(iterable)local r=list()for _,v in next,iterable or{}do append(r,v)end return r end,zip_with=function(iterable,block)local r=list()for k,v in next,iterable or{}do append(r,block(k,v))end return r end,} end package.preload['std.normalize']=function() local ceil=math.ceil local concat=table.concat local config=package.config local getmetatable=getmetatable local loadstring=loadstring local match=string.match local next=next local pack=table.pack or function(...)return{n=select('#',...),...}end local setfenv=setfenv local sort=table.sort local tointeger=math.tointeger local tonumber=tonumber local tostring=tostring local type=type local unpack=table.unpack or unpack local dirsep,pathsep,pathmark,execdir,igmark=match(config,'^([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)\n([^\n]+)')local function copy(iterable)local r={}for k,v in next,iterable or{}do r[k]=v end return r end local int=(function(f)if f==nil then return function(x)if type(x)=='number'and ceil(x)-x==0.0 then return x end end elseif f'1'~=nil then return function(x)if type(x)=='number'then return tointeger(x)end end end return f end)(tointeger)local function iscallable(x)return type(x)=='function'and x or(getmetatable(x)or{}).__call end local function getmetamethod(x,n)return iscallable((getmetatable(x)or{})[tostring(n)])end local function rawlen(x)if type(x)~='table'then return#x end local n=#x for i=1,n do if x[i]==nil then return i-1 end end return n end local function len(x)local m=getmetamethod(x,'__len')return m and m(x)or rawlen(x)end if setfenv then local _loadstring=loadstring loadstring=function(s,filename,env)chunk,err=_loadstring(s,filename)if chunk~=nil and env~=nil then setfenv(chunk,env)end return chunk,err end else loadstring=function(s,filename,env)return load(s,filename,"t",env)end setfenv=function()end end local function keysort(a,b)if int(a)then return int(b)==nil or an then n=i end end return n end,merge=function(r,...)local argu=pack(...)for i=1,argu.n do for k,v in next,argu[i]or{}do r[k]=r[k]or v end end return r end,next=next,open=io.open,pack=pack,pcall=pcall,pop=function(seq)local n,r=seq.n or len(seq)r,seq[n]=seq[n]if int(seq.n)and seq.n>0 then seq.n=seq.n-1 end return r end,popen=io.popen,print=print,rawget=rawget,rawset=rawset,rep=string.rep,rm=function()end,select=select,setmetatable=setmetatable,sort=sort,stderr=io.stderr,stdout=io.stdout,str=str,sub=string.sub,tmpname=os.tmpname,tonumber=tonumber,type=type,unpack=function(seq,i,j)return unpack(seq,int(i)or 1,int(j)or int(seq.n)or len(seq))end,write=io.write,},{__call=function(self,env,level)local userenv,level=copy(self),level or 1 for name,value in next,env do if int(name)and type(value)=='string'then for k,v in next,(require(value))do userenv[k]=userenv[k]or v end else userenv[name]=value end end setfenv(level+1,userenv)return userenv end,}) end package.preload['type.context-manager']=function() local _ENV=require'std.normalize'{'std.functional',}local contextmanager_mt={__index=function(self,key)if iscallable(self.context[key])then return function(_,...)return self.context[key](self.context,...)end end if key=='filename'then return self[1]end end,}local function ContextManager(release,acquire,...)local fh,err=acquire(...)if not fh then return nil,err end local cm={context=fh,release=release,n=select("#",...),...}if cm.context~=nil then setmetatable(cm,contextmanager_mt)end return cm end local function context_close(cm)return isfile(cm.context)and close(cm.context)end local function with(...)local argu=list(...)local block=pop(argu)local r=list(apply(block,argu))map(argu,function(cm)if cm~=nil then cm:release()end end)return unpack(r)end return{ContextManager=ContextManager,CTest=function()local conftest=tmpname()return ContextManager(function(cm)rm(conftest)rm(gsub(conftest,'^.*/','')..'.o')if context_close(cm)then return rm(cm.filename)end return false end,open,conftest..'.c','w')end,File=function(fname,mode)return ContextManager(context_close,open,fname,mode)end,Pipe=function(cmd,mode)return ContextManager(context_close,popen,cmd,mode)end,TmpFile=function(fname,mode)return ContextManager(function(cm)if context_close(cm)then return rm(cm.filename)end return false end,open,fname or tmpname(),mode or'w')end,slurp=function(cm,...)if not cm then return cm,...end return with(cm,function(h)return h:read'*a'end)end,with=with,} end package.preload['type.dict']=function() local _ENV=require'std.normalize'{destructure=next,}return{OrderedDict=function(...)local r,argu={},list(...)for i=1,argu.n do local k,v=destructure(argu[i])append(r,k)r[k]=v end return r end,} end package.preload['type.path']=function() local _ENV=require'std.normalize'{}local BASENAMEPAT='.*'..dirsep local DIRNAMEPAT=dirsep..'[^'..dirsep..']*$'return{basename=function(path)return(gsub(path,BASENAMEPAT,''))end,dirname=function(path)return(gsub(path,DIRNAMEPAT,'',1))end,exists=function(path)local fh=open(path)if fh==nil then return false end close(fh)return true end,} end os.exit(require'luke'.main(arg)) luaposix-36.3/doc/000077500000000000000000000000001475444374100140735ustar00rootroot00000000000000luaposix-36.3/doc/examples/000077500000000000000000000000001475444374100157115ustar00rootroot00000000000000luaposix-36.3/doc/examples/abstract-ns-client.lua000066400000000000000000000005531475444374100221140ustar00rootroot00000000000000#!/usr/bin/env lua local M = require 'posix.sys.socket' local dgram = arg[1] or 'test data' -- Create an AF_UNIX datagram socket local s, errmsg = M.socket(M.AF_UNIX, M.SOCK_DGRAM, 0) assert(s ~= nil, errmsg) -- Sendto the abtract AF_UNIX name 'mysocket' local rc, errmsg = M.sendto(s, dgram, {family=M.AF_UNIX, path='\0mysocket'}) assert(rc ~= nil, errmsg) luaposix-36.3/doc/examples/abstract-ns-client.lua.html000066400000000000000000000121301475444374100230510ustar00rootroot00000000000000 luaposix 36.3 Reference

abstract-ns-client.lua

#!/usr/bin/env lua

local M = require 'posix.sys.socket'


local dgram = arg[1] or 'test data'

-- Create an AF_UNIX datagram socket
local s, errmsg = M.socket(M.AF_UNIX, M.SOCK_DGRAM, 0)
assert(s ~= nil, errmsg)

-- Sendto the abtract AF_UNIX name 'mysocket'
local rc, errmsg = M.sendto(s, dgram, {family=M.AF_UNIX, path='\0mysocket'})
assert(rc ~= nil, errmsg)
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/abstract-ns-server.lua000066400000000000000000000010241475444374100221360ustar00rootroot00000000000000#!/usr/bin/env lua local M = require 'posix.sys.socket' -- Create an AF_UNIX datagram socket local s, errmsg = M.socket(M.AF_UNIX, M.SOCK_DGRAM, 0) assert(s ~ = nil, errmsg) -- Bind to the abtract AF_UNIX name 'mysocket' local rc, errmsg = M.bind(s, {family=M.AF_UNIX, path='\0mysocket'}) assert(rc = = 0, errmsg) -- Receive datagrams on the socket and print out the contents local dgram while true do dgram, errmsg = M.recv(s, 1024) assert(dgram ~ = nil, errmsg) print('Got packet: [' .. tostring(dgram) .. ']') end luaposix-36.3/doc/examples/abstract-ns-server.lua.html000066400000000000000000000130441475444374100231060ustar00rootroot00000000000000 luaposix 36.3 Reference

abstract-ns-server.lua

#!/usr/bin/env lua

local M = require 'posix.sys.socket'


-- Create an AF_UNIX datagram socket
local s, errmsg = M.socket(M.AF_UNIX, M.SOCK_DGRAM, 0)
assert(s ~ = nil, errmsg)

-- Bind to the abtract AF_UNIX name 'mysocket'
local rc, errmsg = M.bind(s, {family=M.AF_UNIX, path='\0mysocket'})
assert(rc =  = 0, errmsg)

-- Receive datagrams on the socket and print out the contents
local dgram
while true do
   dgram, errmsg = M.recv(s, 1024)
   assert(dgram ~ = nil, errmsg)
   print('Got packet: [' .. tostring(dgram) .. ']')
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/dir.lua000066400000000000000000000003041475444374100171670ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.dirent' local ok, files = pcall(M.dir, '/var/log') if not ok then print('/var/log: ' .. files) end for _, f in ipairs(files) do print(f) end luaposix-36.3/doc/examples/dir.lua.html000066400000000000000000000116101475444374100201340ustar00rootroot00000000000000 luaposix 36.3 Reference luaposix-36.3/doc/examples/dup2.lua000066400000000000000000000017301475444374100172670ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.unistd' local function pipe() local r, w = M.pipe() assert(r ~= nil, w) return r, w end local stdout_r, stdout_w = pipe() local stderr_r, stderr_w = pipe() local pid, errmsg = M.fork() assert(pid ~= nil, errmsg) if pid == 0 then -- Child Process: M.close(stdout_r) M.close(stderr_r) M.dup2(stdout_w, M.STDOUT_FILENO) M.dup2(stderr_w, M.STDERR_FILENO) -- Exec() a subprocess here instead if you like -- io.stdout:write 'output string' io.stderr:write 'oh noes!' os.exit(42) else -- Parent Process: M.close(stdout_w) M.close(stderr_w) local function read(msg, fd) local outs, errmsg = M.read(fd, 1024) assert(outs ~= nil, errmsg) print(msg, outs) end read('STDOUT:', stdout_r) read('STDERR:', stderr_r) local childpid, reason, status = require 'posix.sys.wait'.wait(pid) assert(childpid ~= nil, reason) print('child ' .. reason, status) end luaposix-36.3/doc/examples/dup2.lua.html000066400000000000000000000161241475444374100202350ustar00rootroot00000000000000 luaposix 36.3 Reference

dup2.lua

#! /usr/bin/env lua

local M = require 'posix.unistd'


local function pipe()
   local r, w = M.pipe()
   assert(r ~= nil, w)
   return r, w
end

local stdout_r, stdout_w = pipe()
local stderr_r, stderr_w = pipe()

local pid, errmsg = M.fork()
assert(pid ~= nil, errmsg)

if pid == 0 then
   -- Child Process:

   M.close(stdout_r)
   M.close(stderr_r)

   M.dup2(stdout_w, M.STDOUT_FILENO)
   M.dup2(stderr_w, M.STDERR_FILENO)

   -- Exec() a subprocess here instead if you like --

   io.stdout:write 'output string'
   io.stderr:write 'oh noes!'
   os.exit(42)

else
   -- Parent Process:

   M.close(stdout_w)
   M.close(stderr_w)

   local function read(msg, fd)
      local outs, errmsg = M.read(fd, 1024)
      assert(outs ~= nil, errmsg)
      print(msg, outs)
   end

   read('STDOUT:', stdout_r)
   read('STDERR:', stderr_r)


   local childpid, reason, status = require 'posix.sys.wait'.wait(pid)
   assert(childpid ~= nil, reason)
   print('child ' .. reason, status)
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/fork.lua000066400000000000000000000011571475444374100173610ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.unistd' local r,w = M.pipe() local childpid = M.fork() if childpid == 0 then -- child reads from pipe M.close(w) -- close unused write end local b = M.read(r, 1) while #b == 1 do -- got a byte from the pipe, write it to stdout io.write(b) b = M.read(r, 1) end M.close(r) M._exit(0) else -- parent writes to pipe M.close(r) -- close unused read end -- write the bytes for the child process to the pipe M.write(w,'hello dolly\n') M.close(w) -- wait for child to finish require 'posix.sys.wait'.wait(childpid) end luaposix-36.3/doc/examples/fork.lua.html000066400000000000000000000140231475444374100203200ustar00rootroot00000000000000 luaposix 36.3 Reference

fork.lua

#! /usr/bin/env lua

local M = require 'posix.unistd'


local r,w = M.pipe()
local childpid = M.fork()
if childpid == 0 then
   -- child reads from pipe
   M.close(w)  -- close unused write end

   local b = M.read(r, 1)
   while #b == 1 do
      -- got a byte from the pipe, write it to stdout
      io.write(b)
      b = M.read(r, 1)
   end
   M.close(r)
   M._exit(0)

else
   -- parent writes to pipe
   M.close(r) -- close unused read end

   -- write the bytes for the child process to the pipe
   M.write(w,'hello dolly\n')
   M.close(w)
   -- wait for child to finish
   require 'posix.sys.wait'.wait(childpid)
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/fork2.lua000066400000000000000000000012151475444374100174360ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.unistd' print ('parent: my pid is: ' .. M.getpid()) local childpid, errmsg = M.fork () if childpid == nil then print('parent: The fork failed: ' .. errmsg) elseif childpid == 0 then print('child: Hello World! I am pid: ' .. M.getpid()) print("child: I'll sleep for 1 second ... ") M.sleep(1) print('child: Good bye'); else print("parent: While the child sleeps, I'm still running.") print('parent: waiting for child (pid:' .. childpid .. ') to die...') require 'posix.sys.wait'.wait(childpid) print("parent: child died, but I'm still alive.") print('parent: Good bye') end luaposix-36.3/doc/examples/fork2.lua.html000066400000000000000000000136771475444374100204200ustar00rootroot00000000000000 luaposix 36.3 Reference

fork2.lua

#! /usr/bin/env lua

local M = require 'posix.unistd'


print ('parent: my pid is: ' .. M.getpid())

local childpid, errmsg = M.fork ()

if childpid == nil then
   print('parent: The fork failed: ' .. errmsg)
elseif childpid == 0 then
   print('child: Hello World! I am pid: ' .. M.getpid())
   print("child: I'll sleep for 1 second ... ")
   M.sleep(1)
   print('child: Good bye');
else
   print("parent: While the child sleeps, I'm still running.")
   print('parent: waiting for child (pid:' .. childpid .. ') to die...')
   require 'posix.sys.wait'.wait(childpid)
   print("parent: child died, but I'm still alive.")
   print('parent: Good bye')
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/getopt.lua000066400000000000000000000010661475444374100177210ustar00rootroot00000000000000#! /usr/bin/env lua local getopt = require 'posix.unistd'.getopt local last_index = 1 for r, optarg, optind in getopt(arg, 'ha:s:') do if r == '?' then return print('unrecognized option', arg[optind -1]) end last_index = optind if r == 'h' then print '-h print this help text' print '-a ARG a flag with required argument' print '-s ARG a different flag with a required argument' elseif r == 'a' or r == 's' then print('we were passed', r, optarg) end end for i = last_index, #arg do print(i, arg[i]) end luaposix-36.3/doc/examples/getopt.lua.html000066400000000000000000000135621475444374100206700ustar00rootroot00000000000000 luaposix 36.3 Reference

getopt.lua

#! /usr/bin/env lua

local getopt = require 'posix.unistd'.getopt


local last_index = 1
for r, optarg, optind in getopt(arg, 'ha:s:') do
   if r == '?' then
      return print('unrecognized option', arg[optind -1])
   end
   last_index = optind
   if r == 'h' then
      print '-h      print this help text'
      print '-a ARG  a flag with required argument'
      print '-s ARG  a different flag with a required argument'
   elseif r == 'a' or r == 's' then
      print('we were passed', r, optarg)
   end
end

for i = last_index, #arg do
   print(i, arg[i])
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/glob.lua000066400000000000000000000002001475444374100173270ustar00rootroot00000000000000#! /usr/bin/env lua local glob = require 'posix.glob'.glob for _, j in pairs(glob('/proc/[0-9]*/exe', 0)) do print(j) end luaposix-36.3/doc/examples/glob.lua.html000066400000000000000000000112361475444374100203050ustar00rootroot00000000000000 luaposix 36.3 Reference luaposix-36.3/doc/examples/limit.lua000066400000000000000000000010211475444374100175240ustar00rootroot00000000000000#! /usr/bin/env lua -- limit.lua -- Limiting the CPU time used by a child process; -- it will be killed and we don't get the final message local M = require 'posix.sys.resource' local times = require 'posix.sys.times'.times M.setrlimit (M.RLIMIT_CPU, {rlim_cur=1, rlim_max=1}) local t = times().elapsed local pid = require 'posix.unistd'.fork () if pid == 0 then -- child print 'start' for i = 1, 1e9 do end print 'finish' else print (require 'posix.sys.wait'.wait (pid)) print (times().elapsed - t) end luaposix-36.3/doc/examples/limit.lua.html000066400000000000000000000135111475444374100204760ustar00rootroot00000000000000 luaposix 36.3 Reference

limit.lua

#! /usr/bin/env lua

-- limit.lua
-- Limiting the CPU time used by a child process;
-- it will be killed and we don't get the final message

local M = require 'posix.sys.resource'


local times = require 'posix.sys.times'.times

M.setrlimit (M.RLIMIT_CPU, {rlim_cur=1, rlim_max=1})

local t = times().elapsed

local pid = require 'posix.unistd'.fork ()
if pid == 0 then -- child
   print 'start'
   for i = 1, 1e9 do
   end
   print 'finish'
else
   print (require 'posix.sys.wait'.wait (pid))
   print (times().elapsed - t)
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/lock.lua000066400000000000000000000013131475444374100173420ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.fcntl' local S = require 'posix.sys.stat' local fd = M.open( 'file.txt', M.O_CREAT + M.O_WRONLY + M.O_TRUNC, S.S_IRUSR + S.S_IWUSR + S.S_IRGRP + S.S_IROTH ) -- Set lock on file local lock = { l_type = M.F_WRLCK; -- Exclusive lock l_whence = M.SEEK_SET; -- Relative to beginning of file l_start = 0; -- Start from 1st byte l_len = 0; -- Lock whole file } if M.fcntl(fd, M.F_SETLK, lock) == -1 then error('file locked by another process') end -- Do something with file while it's locked require 'posix.unistd'.write(fd, 'Lorem ipsum\n') -- Release the lock lock.l_type = M.F_UNLCK M.fcntl(fd, M.F_SETLK, lock) luaposix-36.3/doc/examples/lock.lua.html000066400000000000000000000134331475444374100203130ustar00rootroot00000000000000 luaposix 36.3 Reference

lock.lua

#! /usr/bin/env lua

local M = require 'posix.fcntl'


local S = require 'posix.sys.stat'


local fd = M.open(
   'file.txt',
   M.O_CREAT + M.O_WRONLY + M.O_TRUNC,
   S.S_IRUSR + S.S_IWUSR + S.S_IRGRP + S.S_IROTH
)

-- Set lock on file
local lock = {
   l_type = M.F_WRLCK;     -- Exclusive lock
   l_whence = M.SEEK_SET;  -- Relative to beginning of file
   l_start = 0;            -- Start from 1st byte
   l_len = 0;              -- Lock whole file
}

if M.fcntl(fd, M.F_SETLK, lock) == -1 then
   error('file locked by another process')
end

-- Do something with file while it's locked
require 'posix.unistd'.write(fd, 'Lorem ipsum\n')

-- Release the lock
lock.l_type = M.F_UNLCK
M.fcntl(fd, M.F_SETLK, lock)
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/netlink-uevent.lua000066400000000000000000000010341475444374100213620ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.sys.socket' if M.AF_NETLINK ~= nil then local getpid = require 'posix.unistd'.getpid local fd, err = M.socket(M.AF_NETLINK, M.SOCK_DGRAM, M.NETLINK_KOBJECT_UEVENT) assert(fd, err) local ok, err = M.bind(fd, {family=M.AF_NETLINK, pid=getpid(), groups=-1}) assert(ok, err) while true do local data, err = M.recv(fd, 16384) assert(data, err) for k, v in string.gmatch(data, '%z(%u+)=([^%z]+)') do print(k, v) end print '\n' end end luaposix-36.3/doc/examples/netlink-uevent.lua.html000066400000000000000000000134021475444374100223270ustar00rootroot00000000000000 luaposix 36.3 Reference

netlink-uevent.lua

#! /usr/bin/env lua

local M = require 'posix.sys.socket'


if M.AF_NETLINK ~= nil then
   local getpid = require 'posix.unistd'.getpid

   local fd, err = M.socket(M.AF_NETLINK, M.SOCK_DGRAM, M.NETLINK_KOBJECT_UEVENT)
   assert(fd, err)

   local ok, err = M.bind(fd, {family=M.AF_NETLINK, pid=getpid(), groups=-1})
   assert(ok, err)

   while true do
      local data, err = M.recv(fd, 16384)
      assert(data, err)
      for k, v in string.gmatch(data, '%z(%u+)=([^%z]+)') do
         print(k, v)
      end
      print '\n'
   end
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/packet-socket.lua000066400000000000000000000006261475444374100211550ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.sys.socket' -- Packet socket loopback test -- Need CAP_NET_RAW, otherwise get "Operation not permitted" if M.AF_PACKET ~= nil then local fd = assert(M.socket(M.AF_PACKET, M.SOCK_RAW, 0)) assert(M.bind(fd, {family=M.AF_PACKET, ifindex=M.if_nametoindex("lo")})) assert(M.send(fd, string.rep("1", 64)) == 64) require 'posix.unistd'.close(fd) end luaposix-36.3/doc/examples/packet-socket.lua.html000066400000000000000000000125761475444374100221270ustar00rootroot00000000000000 luaposix 36.3 Reference

packet-socket.lua

#! /usr/bin/env lua

local M = require 'posix.sys.socket'

-- Packet socket loopback test
-- Need CAP_NET_RAW, otherwise get "Operation not permitted"
if M.AF_PACKET ~= nil then
    local fd = assert(M.socket(M.AF_PACKET, M.SOCK_RAW, 0))
    assert(M.bind(fd, {family=M.AF_PACKET, ifindex=M.if_nametoindex("lo")}))
    assert(M.send(fd, string.rep("1", 64)) == 64)
    require 'posix.unistd'.close(fd)
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/ping.lua000066400000000000000000000013711475444374100173530ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.sys.socket' if M.SOCK_RAW and M.SO_BINDTODEVICE then -- Open raw socket local fd, err = M.socket(M.AF_INET, M.SOCK_RAW, M.IPPROTO_ICMP) assert(fd, err) -- Optionally, bind to specific device local ok, err = M.setsockopt(fd, M.SOL_SOCKET, M.SO_BINDTODEVICE, 'wlan0') assert(ok, err) -- Create raw ICMP echo (ping) message local data = string.char(0x08, 0x00, 0x89, 0x98, 0x6e, 0x63, 0x00, 0x04, 0x00) -- Send message local ok, err = M.sendto(fd, data, {family=M.AF_INET, addr='8.8.8.8', port=0}) assert(ok, err) -- Read reply local data, sa = M.recvfrom(fd, 1024) assert(data, sa) if data then print('Received ICMP message from ' .. sa.addr) end end luaposix-36.3/doc/examples/ping.lua.html000066400000000000000000000143341475444374100203210ustar00rootroot00000000000000 luaposix 36.3 Reference

ping.lua

#! /usr/bin/env lua

local M = require 'posix.sys.socket'


if M.SOCK_RAW and M.SO_BINDTODEVICE then
   -- Open raw socket

   local fd, err = M.socket(M.AF_INET, M.SOCK_RAW, M.IPPROTO_ICMP)
   assert(fd, err)

   -- Optionally, bind to specific device

   local ok, err = M.setsockopt(fd, M.SOL_SOCKET, M.SO_BINDTODEVICE, 'wlan0')
   assert(ok, err)

   -- Create raw ICMP echo (ping) message

   local data = string.char(0x08, 0x00, 0x89, 0x98, 0x6e, 0x63, 0x00, 0x04, 0x00)

   -- Send message

   local ok, err = M.sendto(fd, data, {family=M.AF_INET, addr='8.8.8.8', port=0})
   assert(ok, err)

   -- Read reply

   local data, sa = M.recvfrom(fd, 1024)
   assert(data, sa)

   if data then
      print('Received ICMP message from ' .. sa.addr)
   end
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/poll.lua000066400000000000000000000011211475444374100173550ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.unistd' local F = require 'posix.fcntl' local fd1 = F.open(arg[1], F.O_RDONLY) local fd2 = F.open(arg[2], F.O_RDONLY) local fds = { [fd1] = {events={IN=true}}, [fd2] = {events={IN=true}} } while true do require 'posix.poll'.poll(fds, -1) for fd in pairs(fds) do if fds[fd].revents.IN then local res = M.read(fd,1024) M.write(1,res); end if fds[fd].revents.HUP then M.close(fd) fds[fd] = nil if not next(fds) then return end end end end luaposix-36.3/doc/examples/poll.lua.html000066400000000000000000000141751475444374100203350ustar00rootroot00000000000000 luaposix 36.3 Reference

poll.lua

#! /usr/bin/env lua

local M = require 'posix.unistd'


local F = require 'posix.fcntl'


local fd1 = F.open(arg[1], F.O_RDONLY)
local fd2 = F.open(arg[2], F.O_RDONLY)

local fds = {
   [fd1] = {events={IN=true}},
   [fd2] = {events={IN=true}}
}

while true do
   require 'posix.poll'.poll(fds, -1)
   for fd in pairs(fds) do
      if fds[fd].revents.IN then
         local res = M.read(fd,1024)
         M.write(1,res);
      end
      if fds[fd].revents.HUP then
         M.close(fd)
         fds[fd] = nil
         if not next(fds) then
            return
         end
      end
   end
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/rt_sched.lua000066400000000000000000000071501475444374100202120ustar00rootroot00000000000000#! /usr/bin/env lua --[[ This example tests sched_setscheduler() / sched_getscheduler() The script must be run as privileged process (CAP_SYS_NICE on linux) ]] local M = require 'posix.sched' local mypid = require 'posix.unistd'.getpid() -- get sched params from ps(1) local function get_ps_sched(pid) local fp = io.popen(string.format('ps --no-headers -o "policy,rtprio" %s', pid)) local res, err = fp:read'*a' assert(res, err) fp:close() local policy, rtprio = string.match(res, '([^%s]+)%s+([^%s]+)') assert(policy) assert(rtprio) return policy, rtprio end do -- Tests on own process -- get scheduler policy for own process local res, err = M.sched_getscheduler(0) -- 0 pid: own process assert(res == M.SCHED_OTHER) local res, err = M.sched_getscheduler() -- default pid: own process assert(res == M.SCHED_OTHER) local policy, rtprio = get_ps_sched(mypid) assert(policy== 'TS') assert(rtprio== '-') -- set realtime priority on own process : SCHED_FIFO local res, err = M.sched_setscheduler(0, p.SCHED_FIFO, 10 ) assert(res, err) local policy, rtprio = get_ps_sched(mypid) assert(policy == 'FF') assert(rtprio == '10') local res, err = M.sched_getscheduler(0) assert(res == M.SCHED_FIFO) -- set realtime priority on own process SCHED_RR local res, err = M.sched_setscheduler(0, M.SCHED_RR, 11 ) assert(res, err) local policy, rtprio = get_ps_sched(mypid) assert(policy == 'RR') assert(rtprio == '11') local res, err = M.sched_getscheduler(0) assert(res == M.SCHED_RR) -- no parameters: reset own process to normal priority : local res, err = M.sched_setscheduler() assert(res, err) local policy, rtprio = get_ps_sched(mypid) assert(policy == 'TS') assert(rtprio == '-') local res, err = M.sched_getscheduler(0) assert(res == M.SCHED_OTHER) end -- fork a child to check sched_setscheduler on other process do local U = require 'posix.unistd' local r, w = U.pipe() local childpid = U.fork() if childpid == 0 then -- child: block on pipe until parent is finshed U.close(w) -- close unused write end local b = U.read(r,1) U._exit(0) end -- parent: U.close(r) do -- do tests -- get scheduler policy for child process local res, err = M.sched_getscheduler(childpid) assert(res == M.SCHED_OTHER) local policy, rtprio = get_ps_sched(childpid) assert(policy == 'TS') assert(rtprio == '-') -- set realtime priority on child process : SCHED_FIFO local res, err = M.sched_setscheduler(childpid, M.SCHED_FIFO, 10 ) assert(res, err) local policy, rtprio = get_ps_sched(childpid) assert(policy == 'FF') assert(rtprio == '10') local res, err = M.sched_getscheduler(childpid) assert(res == M.SCHED_FIFO) -- set realtime priority on child process SCHED_RR local res, err = M.sched_setscheduler(childpid, M.SCHED_RR, 11 ) assert(res, err) local policy, rtprio = get_ps_sched(childpid) assert(policy == 'RR') assert(rtprio == '11') local res, err = M.sched_getscheduler(childpid) assert(res == M.SCHED_RR) -- no parameters after pid: reset child process to normal priority : local res, err = M.sched_setscheduler(childpid) assert(res, err) local policy, rtprio = get_ps_sched(childpid) assert(policy == 'TS') assert(rtprio == '-') local res, err = M.sched_getscheduler(childpid) assert(res == M.SCHED_OTHER) end -- stop child U.write(w, 'stop') U.close(w) require 'posix.sys.wait'.wait(childpid) end luaposix-36.3/doc/examples/rt_sched.lua.html000066400000000000000000000321071475444374100211550ustar00rootroot00000000000000 luaposix 36.3 Reference

rt_sched.lua

#! /usr/bin/env lua

--[[
 This example tests sched_setscheduler() / sched_getscheduler()
 The script must be run as privileged process (CAP_SYS_NICE on linux)
]]

local M = require 'posix.sched'


local mypid = require 'posix.unistd'.getpid()

-- get sched params from ps(1)
local function get_ps_sched(pid)
   local fp = io.popen(string.format('ps --no-headers -o "policy,rtprio" %s', pid))
   local res, err = fp:read'*a'
   assert(res, err)
   fp:close()
   local policy, rtprio = string.match(res, '([^%s]+)%s+([^%s]+)')
   assert(policy)
   assert(rtprio)
   return policy, rtprio
end


do -- Tests on own process

   -- get scheduler policy for own process
   local res, err = M.sched_getscheduler(0) -- 0 pid: own process
   assert(res == M.SCHED_OTHER)
   local res, err = M.sched_getscheduler() -- default pid: own process
   assert(res == M.SCHED_OTHER)

   local policy, rtprio = get_ps_sched(mypid)
   assert(policy== 'TS')
   assert(rtprio== '-')


   -- set realtime priority on own process : SCHED_FIFO
   local res, err = M.sched_setscheduler(0, p.SCHED_FIFO, 10 )
   assert(res, err)

   local policy, rtprio = get_ps_sched(mypid)
   assert(policy == 'FF')
   assert(rtprio == '10')

   local res, err = M.sched_getscheduler(0)
   assert(res == M.SCHED_FIFO)


   -- set realtime priority on own process SCHED_RR
   local res, err = M.sched_setscheduler(0, M.SCHED_RR, 11 )
   assert(res, err)

   local policy, rtprio = get_ps_sched(mypid)
   assert(policy == 'RR')
   assert(rtprio == '11')

   local res, err = M.sched_getscheduler(0)
   assert(res == M.SCHED_RR)


   -- no parameters: reset own process to normal priority :
   local res, err = M.sched_setscheduler()
   assert(res, err)

   local policy, rtprio = get_ps_sched(mypid)
   assert(policy == 'TS')
   assert(rtprio == '-')

   local res, err = M.sched_getscheduler(0)
   assert(res == M.SCHED_OTHER)
end


-- fork a child to check sched_setscheduler on other process
do
   local U = require 'posix.unistd'

   local r, w = U.pipe()
   local childpid = U.fork()
   if childpid == 0 then
      -- child: block on pipe until parent is finshed
      U.close(w)  -- close unused write end
      local b = U.read(r,1)
      U._exit(0)
   end

   -- parent:
   U.close(r)

   do -- do tests
      -- get scheduler policy for child process
      local res, err = M.sched_getscheduler(childpid)
      assert(res == M.SCHED_OTHER)

      local policy, rtprio = get_ps_sched(childpid)
      assert(policy == 'TS')
      assert(rtprio == '-')


      -- set realtime priority on child process : SCHED_FIFO
      local res, err = M.sched_setscheduler(childpid, M.SCHED_FIFO, 10 )
      assert(res, err)

      local policy, rtprio = get_ps_sched(childpid)
      assert(policy == 'FF')
      assert(rtprio == '10')

      local res, err = M.sched_getscheduler(childpid)
      assert(res == M.SCHED_FIFO)


      -- set realtime priority on child process SCHED_RR
      local res, err = M.sched_setscheduler(childpid, M.SCHED_RR, 11 )
      assert(res, err)

      local policy, rtprio = get_ps_sched(childpid)
      assert(policy == 'RR')
      assert(rtprio == '11')

      local res, err = M.sched_getscheduler(childpid)
      assert(res == M.SCHED_RR)


      -- no parameters after pid: reset child process to normal priority :
      local res, err = M.sched_setscheduler(childpid)
      assert(res, err)

      local policy, rtprio = get_ps_sched(childpid)
      assert(policy == 'TS')
      assert(rtprio == '-')

      local res, err = M.sched_getscheduler(childpid)
      assert(res == M.SCHED_OTHER)
   end

   -- stop child
   U.write(w, 'stop')
   U.close(w)
   require 'posix.sys.wait'.wait(childpid)
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/signal.lua000066400000000000000000000027571475444374100177040ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.signal' local unistd = require 'posix.unistd' local syswait = require 'posix.sys.wait' local function go(fn, ...) local childpid = unistd.fork() if childpid == 0 then -- run function as child unistd._exit(fn(...) or 0) else return childpid end end local verbose = #arg > 0 local function sleepx(secs) while true do secs = unistd.sleep(secs) if verbose then print('sleep', secs) end if secs == 0 then return end end end local nchild, nsig = 0, 0 M.signal(M.SIGCHLD, function() local pid, status, code = syswait.wait(-1, syswait.WNOHANG) while pid do if pid ~= 0 then if verbose then print('wait', pid, status, code) end nchild = nchild + 1 end pid, status, code = syswait.wait(-1, syswait.WNOHANG) end end) local function handler(signo) if verbose then print('handled', signo) end nsig = nsig + 1 end M.signal(M.SIGUSR1, handler) M.signal(M.SIGUSR2, handler) M.signal(60, handler) local function killp(nsig) return M.kill(unistd.getppid(), nsig) end c1 = go(function() unistd.sleep(1); killp(M.SIGUSR1); killp(M.SIGUSR2) end) c2 = go(function() unistd.sleep(2); killp(M.SIGUSR2); end) c3 = go(function() unistd.sleep(2); killp(M.SIGUSR1) end) sleepx(3) if verbose then print('children', nchild, 'signals', nsig) else assert(nchild == 3) assert(nsig == 4) print '+++ tests OK +++' end luaposix-36.3/doc/examples/signal.lua.html000066400000000000000000000225671475444374100206500ustar00rootroot00000000000000 luaposix 36.3 Reference

signal.lua

#! /usr/bin/env lua

local M = require 'posix.signal'


local unistd = require 'posix.unistd'
local syswait = require 'posix.sys.wait'


local function go(fn, ...)
   local childpid = unistd.fork()
   if childpid == 0 then -- run function as child
      unistd._exit(fn(...) or 0)
   else
      return childpid
   end
end

local verbose = #arg > 0

local function sleepx(secs)
   while true do
      secs = unistd.sleep(secs)
      if verbose then
         print('sleep', secs)
      end
      if secs == 0 then
         return
      end
   end
end

local nchild, nsig = 0, 0

M.signal(M.SIGCHLD, function()
   local pid, status, code = syswait.wait(-1, syswait.WNOHANG)
   while pid do
      if pid ~= 0 then
         if verbose then
            print('wait', pid, status, code)
         end
         nchild = nchild + 1
      end
      pid, status, code = syswait.wait(-1, syswait.WNOHANG)
   end
end)

local function handler(signo)
   if verbose then
      print('handled', signo)
   end
   nsig = nsig + 1
end

M.signal(M.SIGUSR1, handler)
M.signal(M.SIGUSR2, handler)
M.signal(60, handler)

local function killp(nsig)
   return M.kill(unistd.getppid(), nsig)
end

c1 = go(function() unistd.sleep(1); killp(M.SIGUSR1); killp(M.SIGUSR2) end)
c2 = go(function() unistd.sleep(2); killp(M.SIGUSR2); end)
c3 = go(function() unistd.sleep(2); killp(M.SIGUSR1) end)

sleepx(3)

if verbose then
   print('children', nchild, 'signals', nsig)
else
   assert(nchild == 3)
   assert(nsig ==   4)
   print '+++ tests OK +++'
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/socket.lua000066400000000000000000000024151475444374100177060ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.sys.socket' local sig = require 'posix.signal' sig.signal(sig.SIGPIPE, function() print 'pipe' end) -- Get Lua web site title local r, err = M.getaddrinfo('www.lua.org', 'http', {family=M.AF_INET, socktype=M.SOCK_STREAM}) if not r then error(err) end local fd = M.socket(M.AF_INET, M.SOCK_STREAM, 0) local ok, err, e = M.connect(fd, r[1]) local sa = M.getsockname(fd) print('Local socket bound to ' .. sa.addr .. ':' .. tostring(sa.port)) if err then error(err) end M.send(fd, 'GET / HTTP/1.0\r\nHost: www.lua.org\r\n\r\n') local data = {} while true do local b = M.recv(fd, 1024) if not b or #b == 0 then break end table.insert(data, b) end require 'posix.unistd'.close(fd) data = table.concat(data) print(string.match(data, '(.+)')) -- Loopback UDP test, IPV4 and IPV6 local fd = M.socket(M.AF_INET6, M.SOCK_DGRAM, 0) M.bind(fd, {family=M.AF_INET6, addr='::', port=9999}) M.sendto(fd, 'Test ipv4', {family=M.AF_INET, addr='127.0.0.1', port=9999}) M.sendto(fd, 'Test ipv6', {family=M.AF_INET6, addr='::', port=9999}) for i = 1, 2 do local ok, r = M.recvfrom(fd, 1024) if ok then print(ok, r.addr, r.port) else print(ok, r) end end require 'posix.unistd'.close(fd) os.exit(0) luaposix-36.3/doc/examples/socket.lua.html000066400000000000000000000205571475444374100206600ustar00rootroot00000000000000 luaposix 36.3 Reference

socket.lua

#! /usr/bin/env lua

local M = require 'posix.sys.socket'


local sig = require 'posix.signal'
sig.signal(sig.SIGPIPE, function() print 'pipe' end)

-- Get Lua web site title
local r, err = M.getaddrinfo('www.lua.org', 'http', {family=M.AF_INET, socktype=M.SOCK_STREAM})
if not r then
   error(err)
end

local fd = M.socket(M.AF_INET, M.SOCK_STREAM, 0)
local ok, err, e = M.connect(fd, r[1])
local sa = M.getsockname(fd)
print('Local socket bound to ' .. sa.addr .. ':' .. tostring(sa.port))
if err then
   error(err)
end

M.send(fd, 'GET / HTTP/1.0\r\nHost: www.lua.org\r\n\r\n')
local data = {}
while true do
   local b = M.recv(fd, 1024)
   if not b or #b == 0 then
      break
   end
   table.insert(data, b)
end
require 'posix.unistd'.close(fd)

data = table.concat(data)
print(string.match(data, '<TITLE>(.+)</TITLE>'))

-- Loopback UDP test, IPV4 and IPV6
local fd = M.socket(M.AF_INET6, M.SOCK_DGRAM, 0)
M.bind(fd, {family=M.AF_INET6, addr='::', port=9999})
M.sendto(fd, 'Test ipv4', {family=M.AF_INET, addr='127.0.0.1', port=9999})
M.sendto(fd, 'Test ipv6', {family=M.AF_INET6, addr='::', port=9999})
for i = 1, 2 do
   local ok, r = M.recvfrom(fd, 1024)
   if ok then
      print(ok, r.addr, r.port)
   else
      print(ok, r)
   end
end
require 'posix.unistd'.close(fd)

os.exit(0)
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/termios.lua000066400000000000000000000032761475444374100201060ustar00rootroot00000000000000#! /usr/bin/env lua local M = require 'posix.termio' local F = require 'posix.fcntl' local U = require 'posix.unistd' local dev = arg[1] or '/dev/ttyUSB0' -- Open serial port and do settings local fds, err = F.open(dev, F.O_RDWR + F.O_NONBLOCK) if not fds then print('Could not open serial port ' .. dev .. ':', err) os.exit(1) end M.tcsetattr(fds, 0, { cflag = M.B115200 + M.CS8 + M.CLOCAL + M.CREAD, iflag = M.IGNPAR, oflag = M.OPOST, cc = { [M.VTIME] = 0, [M.VMIN] = 1, } }) -- Set stdin to non canonical mode. Save current settings local save = M.tcgetattr(0) M.tcsetattr(0, 0, { cc = { [M.VTIME] = 0, [M.VMIN] = 1 } }) -- Loop, reading and writing between ports. ^C stops local set = { [0] = {events={IN=true}}, [fds] = {events={IN =true}}, } U.write(1, 'Starting terminal, hit ^C to exit\r\n') local function exit(msg) M.tcsetattr(0, 0, save) print '\n' print(msg) os.exit(0) end while true do local r = require 'posix.poll'.poll(set, -1) for fd, d in pairs(set) do if d.revents and d.revents.IN then if fd == 0 then local d, err = U.read(0, 1024) if not d then exit(err) end if d == string.char(3) then exit('Bye') end local ok, err = U.write(fds, d) if not ok then exit(err) end end if fd == fds then local d, err = U.read(fds, 1024) if not d then exit(err) end local ok, err = U.write(1, d) if not ok then exit(err) end end end end end luaposix-36.3/doc/examples/termios.lua.html000066400000000000000000000227661475444374100210560ustar00rootroot00000000000000 luaposix 36.3 Reference

termios.lua

#! /usr/bin/env lua

local M = require 'posix.termio'


local F = require 'posix.fcntl'
local U = require 'posix.unistd'


local dev = arg[1] or '/dev/ttyUSB0'

-- Open serial port and do settings
local fds, err = F.open(dev, F.O_RDWR + F.O_NONBLOCK)
if not fds then
   print('Could not open serial port ' .. dev .. ':', err)
   os.exit(1)
end

M.tcsetattr(fds, 0, {
   cflag = M.B115200 + M.CS8 + M.CLOCAL + M.CREAD,
   iflag = M.IGNPAR,
   oflag = M.OPOST,
   cc = {
      [M.VTIME] = 0,
      [M.VMIN] = 1,
   }
})

-- Set stdin to non canonical mode. Save current settings
local save = M.tcgetattr(0)
M.tcsetattr(0, 0, {
   cc = {
      [M.VTIME] = 0,
      [M.VMIN] = 1
   }
})

-- Loop, reading and writing between ports. ^C stops
local set = {
   [0] = {events={IN=true}},
   [fds] = {events={IN =true}},
}

U.write(1, 'Starting terminal, hit ^C to exit\r\n')

local function exit(msg)
   M.tcsetattr(0, 0, save)
   print '\n'
   print(msg)
   os.exit(0)
end

while true do
   local r = require 'posix.poll'.poll(set, -1)
   for fd, d in pairs(set) do
      if d.revents and d.revents.IN then
         if fd == 0 then
            local d, err = U.read(0, 1024)
            if not d then
               exit(err)
            end
            if d == string.char(3) then
               exit('Bye')
            end
            local ok, err = U.write(fds, d)
            if not ok then
               exit(err)
            end
         end
         if fd == fds then
            local d, err = U.read(fds, 1024)
            if not d then
               exit(err)
            end
            local ok, err = U.write(1, d)
            if not ok then
               exit(err)
            end
         end
      end
   end
end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/examples/tree.lua000066400000000000000000000037441475444374100173630ustar00rootroot00000000000000#! /usr/bin/env lua -- tree view of the file system like the 'tree' unix utility -- John Belmonte local dir = require 'posix.dirent'.dir local islink = require 'posix.sys.stat'.S_ISLNK local isdir = require 'posix.sys.stat'.S_ISDIR local readlink = require 'posix.unistd'.readlink local stat = require 'posix.sys.stat'.stat local leaf_indent = '| ' local tail_leaf_indent = ' ' local leaf_prefix = '|-- ' local tail_leaf_prefix = '`-- ' local link_prefix = ' -> ' local function printf(...) io.write(string.format(...)) end local function do_directory(directory, level, prefix) local num_dirs = 0 local num_files = 0 local files = dir(directory) local last_file_index = #files table.sort(files) for i, name in ipairs(files) do if name ~= '.' and name ~= '..' then local full_name = string.format('%s/%s', directory, name) local info = assert(stat(full_name)) local is_tail = (i==last_file_index) local prefix2 = is_tail and tail_leaf_prefix or leaf_prefix local link = '' if islink(info.st_mode) ~= 0 then linked_name = assert(readlink(full_name)) link = string.format('%s%s', link_prefix, linked_name) end printf('%s%s%s%s\n', prefix, prefix2, name, link) if isdir(info.st_mode) ~= 0 then local indent = is_tail and tail_leaf_indent or leaf_indent -- TODO: cache string concatenation sub_dirs, sub_files = do_directory(full_name, level+1, prefix .. indent) num_dirs = num_dirs + sub_dirs + 1 num_files = num_files + sub_files else num_files = num_files + 1 end end end return num_dirs, num_files end local function fore(directory) print(directory) num_dirs, num_files = do_directory(directory, 0, '') printf('\n%d directories, %d files\n', num_dirs, num_files) end directory = (arg and #arg > 0) and arg[1] or '.' fore(directory) luaposix-36.3/doc/examples/tree.lua.html000066400000000000000000000230271475444374100203220ustar00rootroot00000000000000 luaposix 36.3 Reference

tree.lua

#! /usr/bin/env lua

-- tree view of the file system like the 'tree' unix utility
-- John Belmonte <jvb@prairienet.org>

local dir = require 'posix.dirent'.dir
local islink = require 'posix.sys.stat'.S_ISLNK
local isdir = require 'posix.sys.stat'.S_ISDIR
local readlink = require 'posix.unistd'.readlink
local stat = require 'posix.sys.stat'.stat

local leaf_indent = '|   '
local tail_leaf_indent = '   '
local leaf_prefix = '|-- '
local tail_leaf_prefix = '`-- '
local link_prefix = ' -> '

local function printf(...)
  io.write(string.format(...))
end

local function do_directory(directory, level, prefix)
   local num_dirs = 0
   local num_files = 0
   local files = dir(directory)
   local last_file_index = #files
   table.sort(files)
   for i, name in ipairs(files) do
      if name ~= '.' and name ~= '..' then
         local full_name = string.format('%s/%s', directory, name)
         local info = assert(stat(full_name))
         local is_tail = (i==last_file_index)
         local prefix2 = is_tail and tail_leaf_prefix or leaf_prefix
         local link = ''
         if islink(info.st_mode) ~= 0 then
            linked_name = assert(readlink(full_name))
            link = string.format('%s%s', link_prefix, linked_name)
         end
         printf('%s%s%s%s\n', prefix, prefix2, name, link)
         if isdir(info.st_mode) ~= 0 then
            local indent = is_tail and tail_leaf_indent or leaf_indent
            -- TODO: cache string concatenation
            sub_dirs, sub_files = do_directory(full_name, level+1,
               prefix .. indent)
            num_dirs = num_dirs + sub_dirs + 1
            num_files = num_files + sub_files
         else
            num_files = num_files + 1
         end
      end
   end
   return num_dirs, num_files
end

local function fore(directory)
   print(directory)
   num_dirs, num_files = do_directory(directory, 0, '')
   printf('\n%d directories, %d files\n', num_dirs, num_files)
end

directory = (arg and #arg > 0) and arg[1] or '.'
fore(directory)
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/index.html000066400000000000000000000254361475444374100161020ustar00rootroot00000000000000 luaposix 36.3 Reference

POSIX bindings for Lua

Modules

posix Lua POSIX bindings.
posix.ctype Character tests.
posix.dirent Directory Iterators.
posix.errno System error codes and messages.
posix.fcntl File Control.
posix.fnmatch Filename matching.
posix.glob Generate pathnames matching a shell-style pattern.
posix.grp Group Database Operations.
posix.libgen General Library.
posix.poll Synchronous I/O Multiplexing.
posix.pwd Password Database Operations.
posix.sched Kernel Thread Scheduling Priority.
posix.signal Software Signal Facilities.
posix.stdio A few Standard I/O functions not already in Lua core.
posix.stdlib Standard Posix Library functions.
posix.sys.msg Sys V Message Queue Operations.
posix.sys.resource Control Maximum System Resource Consumption.
posix.sys.socket BSD Sockets.
posix.sys.stat File Status Querying and Setting.
posix.sys.statvfs Retrieve File System Information.
posix.sys.time Get and Set System Date and Time.
posix.sys.times Process Times.
posix.sys.utsname Get System Identification.
posix.sys.wait Wait for Process Termination.
posix.syslog Control System Log.
posix.termio Control Terminal I/O.
posix.time Time and Clock Functions.
posix.unistd Unix Standard APIs.
posix.utime Set File Times.

Examples

abstract-ns-client.lua
abstract-ns-server.lua
dir.lua
dup2.lua
fork.lua
fork2.lua
getopt.lua
glob.lua
limit.lua
lock.lua
netlink-uevent.lua
packet-socket.lua
ping.lua
poll.lua
rt_sched.lua
signal.lua
socket.lua
termios.lua
tree.lua
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/ldoc.css000066400000000000000000000143471475444374100155370ustar00rootroot00000000000000/* BEGIN RESET Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 2.8.2r1 */ html { color: #000; background: #FFF; } body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td { margin: 0; padding: 0; } table { border-collapse: collapse; border-spacing: 0; } fieldset,img { border: 0; } address,caption,cite,code,dfn,em,strong,th,var,optgroup { font-style: inherit; font-weight: inherit; } del,ins { text-decoration: none; } li { margin-left: 20px; } caption,th { text-align: left; } h1,h2,h3,h4,h5,h6 { font-size: 100%; font-weight: bold; } q:before,q:after { content: ''; } abbr,acronym { border: 0; font-variant: normal; } sup { vertical-align: baseline; } sub { vertical-align: baseline; } legend { color: #000; } input,button,textarea,select,optgroup,option { font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; } input,button,textarea,select {*font-size:100%; } /* END RESET */ body { margin-left: 1em; margin-right: 1em; font-family: arial, helvetica, geneva, sans-serif; background-color: #ffffff; margin: 0px; } code, tt { font-family: monospace; font-size: 1.1em; } span.parameter { font-family:monospace; } span.parameter:after { content:":"; } span.types:before { content:"("; } span.types:after { content:")"; } .type { font-weight: bold; font-style:italic } body, p, td, th { font-size: .95em; line-height: 1.2em;} p, ul { margin: 10px 0 0 0px;} strong { font-weight: bold;} em { font-style: italic;} h1 { font-size: 1.5em; margin: 20px 0 20px 0; } h2, h3, h4 { margin: 15px 0 10px 0; } h2 { font-size: 1.25em; } h3 { font-size: 1.15em; } h4 { font-size: 1.06em; } a:link { font-weight: bold; color: #004080; text-decoration: none; } a:visited { font-weight: bold; color: #006699; text-decoration: none; } a:link:hover { text-decoration: underline; } hr { color:#cccccc; background: #00007f; height: 1px; } blockquote { margin-left: 3em; } ul { list-style-type: disc; } p.name { font-family: "Andale Mono", monospace; padding-top: 1em; } pre { background-color: rgb(245, 245, 245); border: 1px solid #C0C0C0; /* silver */ padding: 10px; margin: 10px 0 10px 0; overflow: auto; font-family: "Andale Mono", monospace; } pre.example { font-size: .85em; } table.index { border: 1px #00007f; } table.index td { text-align: left; vertical-align: top; } #container { margin-left: 1em; margin-right: 1em; background-color: #f0f0f0; } #product { text-align: center; border-bottom: 1px solid #cccccc; background-color: #ffffff; } #product big { font-size: 2em; } #main { background-color: #f0f0f0; border-left: 2px solid #cccccc; } #navigation { float: left; width: 14em; vertical-align: top; background-color: #f0f0f0; overflow: visible; } #navigation h2 { background-color:#e7e7e7; font-size:1.1em; color:#000000; text-align: left; padding:0.2em; border-top:1px solid #dddddd; border-bottom:1px solid #dddddd; } #navigation ul { font-size:1em; list-style-type: none; margin: 1px 1px 10px 1px; } #navigation li { text-indent: -1em; display: block; margin: 3px 0px 0px 22px; } #navigation li li a { margin: 0px 3px 0px -1em; } #content { margin-left: 14em; padding: 1em; width: 700px; border-left: 2px solid #cccccc; border-right: 2px solid #cccccc; background-color: #ffffff; } #about { clear: both; padding: 5px; border-top: 2px solid #cccccc; background-color: #ffffff; } @media print { body { font: 12pt "Times New Roman", "TimeNR", Times, serif; } a { font-weight: bold; color: #004080; text-decoration: underline; } #main { background-color: #ffffff; border-left: 0px; } #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } #content { padding: 1em; background-color: #ffffff; } #navigation { display: none; } pre.example { font-family: "Andale Mono", monospace; font-size: 10pt; page-break-inside: avoid; } } table.module_list { border-width: 1px; border-style: solid; border-color: #cccccc; border-collapse: collapse; } table.module_list td { border-width: 1px; padding: 3px; border-style: solid; border-color: #cccccc; } table.module_list td.name { background-color: #f0f0f0; min-width: 200px; } table.module_list td.summary { width: 100%; } table.function_list { border-width: 1px; border-style: solid; border-color: #cccccc; border-collapse: collapse; } table.function_list td { border-width: 1px; padding: 3px; border-style: solid; border-color: #cccccc; } table.function_list td.name { background-color: #f0f0f0; min-width: 200px; } table.function_list td.summary { width: 100%; } ul.nowrap { overflow:auto; white-space:nowrap; } dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;} dl.table h3, dl.function h3 {font-size: .95em;} /* stop sublists from having initial vertical space */ ul ul { margin-top: 0px; } ol ul { margin-top: 0px; } ol ol { margin-top: 0px; } ul ol { margin-top: 0px; } /* make the target distinct; helps when we're navigating to a function */ a:target + * { background-color: #FF9; } /* styles for prettification of source */ pre .comment { color: #558817; } pre .constant { color: #a8660d; } pre .escape { color: #844631; } pre .keyword { color: #aa5050; font-weight: bold; } pre .library { color: #0e7c6b; } pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } pre .string { color: #8080ff; } pre .number { color: #f8660d; } pre .function-name { color: #60447f; } pre .operator { color: #2239a8; font-weight: bold; } pre .preprocessor, pre .prepro { color: #a33243; } pre .global { color: #800080; } pre .user-keyword { color: #800080; } pre .prompt { color: #558817; } pre .url { color: #272fc2; text-decoration: underline; } luaposix-36.3/doc/modules/000077500000000000000000000000001475444374100155435ustar00rootroot00000000000000luaposix-36.3/doc/modules/posix.ctype.html000066400000000000000000000143441475444374100207240ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.ctype

Character tests.

Functions

isgraph (character) Check for any printable character except space.
isprint (character) Check for any printable character including space.


Functions

isgraph (character)
Check for any printable character except space.

Parameters:

Returns:

    int non-zero if character is not in the class

See also:

isprint (character)
Check for any printable character including space.

Parameters:

Returns:

    int non-zero if character is not in the class

See also:

generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.dirent.html000066400000000000000000000137331475444374100210660ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.dirent

Directory Iterators.

Functions

dir ([path="."]) Contents of directory.
files ([path="."]) Iterator over all files in named directory.


Functions

dir ([path="."])
Contents of directory.

Parameters:

  • path string directory to act on (default ".")

Returns:

    table contents of path

See also:

files ([path="."])
Iterator over all files in named directory.

Parameters:

  • path string directory to act on (default ".")

Returns:

    an iterator
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.errno.html000066400000000000000000000470661475444374100207340ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.errno

System error codes and messages.

Usually, you'll be able to work with the error messages returned as the second value from failed calls directly, without having to manually save and stringify the system messages as you would in C. For completeness, the functions are still available here.

Functions

errno ([n=current errno]) Describe an error code/and or read errno
set_errno (n) Set errno.

Constants

posix.errno Error constants.


Functions

errno ([n=current errno])
Describe an error code/and or read errno

Parameters:

  • n int optional error code (default current errno)

Returns:

  1. description
  2. error code

See also:

Usage:

    local strerr, nerr = posix.errno ()
set_errno (n)
Set errno.

Parameters:

  • n int error code

See also:

Usage:

    posix.errno (posix.EBADF)

Constants

posix.errno
Error constants. Any constants not available in the underlying system will be nil valued.

If you find one of the luaposix APIs returns an error code not listed here, please raise an issue here, stating the symbolic name of the constant (from /usr/include/errno.h or equivalent).

Fields:

  • E2BIG int argument list too long
  • EACCES int permission denied
  • EADDRINUSE int address already in use
  • EADDRNOTAVAIL int can't assign requested address
  • EAFNOSUPPORT int address family not supported by protocol family
  • EAGAIN int resource temporarily unavailable
  • EALREADY int operation already in progress
  • EBADF int bad file descriptor
  • EBADMSG int bad message
  • EBUSY int resource busy
  • ECANCELED int operation canceled
  • ECHILD int no child processes
  • ECONNABORTED int software caused connection abort
  • ECONNREFUSED int connection refused
  • ECONNRESET int connection reset by peer
  • EDEADLK int resource deadlock avoided
  • EDESTADDRREQ int destination address required
  • EDOM int numerical argument out of domain
  • EEXIST int file exists
  • EFAULT int bad address
  • EFBIG int file too large
  • EHOSTUNREACH int no route to host
  • EIDRM int identifier removed
  • EILSEQ int illegal byte sequence
  • EINPROGRESS int operation now in progress
  • EINTR int interrupted system call
  • EINVAL int invalid argument
  • EIO int input/output error
  • EISCONN int socket is already connected
  • EISDIR int is a directory
  • ELOOP int too many levels of symbolic links
  • EMFILE int too many open files
  • EMLINK int too many links
  • EMSGSIZE int message too long
  • ENAMETOOLONG int file name too long
  • ENETDOWN int network is down
  • ENETRESET int network dropped connection on reset
  • ENETUNREACH int network is unreachable
  • ENFILE int too many open files in system
  • ENOBUFS int no buffer space available
  • ENODEV int operation not supported by device
  • ENOENT int no such file or directory
  • ENOEXEC int exec format error
  • ENOLCK int no locks available
  • ENOMEM int cannot allocate memory
  • ENOMSG int no message of desired type
  • ENOPROTOOPT int protocol not available
  • ENOSPC int no space left on device
  • ENOSYS int function not implemented
  • ENOTCONN int socket is not connected
  • ENOTDIR int not a directory
  • ENOTEMPTY int directory not empty
  • ENOTSOCK int socket operation on non-socket
  • ENOTSUP int operation not supported
  • ENOTTY int inappropriate ioctl for device
  • ENXIO int device not configured
  • EOPNOTSUPP int operation not supported on socket
  • EOVERFLOW int value too large to be stored in data type
  • EPERM int operation not permitted
  • EPIPE int broken pipe
  • EPROTO int protocol error
  • EPROTONOSUPPORT int protocol not supported
  • EPROTOTYPE int protocol wrong type for socket
  • ERANGE int result too large
  • EROFS int read-only file system
  • ESPIPE int illegal seek
  • ESRCH int no such process
  • ETIMEDOUT int operation timed out
  • ETXTBSY int text file busy
  • EWOULDBLOCK int operation would block
  • EXDEV int cross-device link

Usage:

    -- Print errno constants supported on this host.
    for name, value in pairs (require "posix.errno") do
      if type (value) == "number" then
        print (name, value)
      end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.fcntl.html000066400000000000000000000476351475444374100207170ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.fcntl

File Control.

Low-level control over file descriptors, including creating new file descriptors with open.

Functions

fcntl (fd, cmd[, arg=0]) Manipulate file descriptor.
open (path, oflags[, mode=511]) Open a file.
posix_fadvise (fd, offset, len, advice) Instruct kernel on appropriate cache behaviour for a file or file segment.

Tables

flock Advisory file locks.

Constants

posix.fcntl Fcntl constants.


Functions

fcntl (fd, cmd[, arg=0])
Manipulate file descriptor.

Parameters:

  • fd int file descriptor to act on
  • cmd int operation to perform
  • arg int or flock when cmd is F_GETLK, F_SETLK or F_SETLKW, then arg is a flock table, otherwise an integer with meaning dependent upon the value of cmd. (default 0)

Returns:

    integer return value depending on cmd, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local flag = posix.fcntl (fd, posix.F_GETFL)
open (path, oflags[, mode=511])
Open a file.

Parameters:

  • path string
  • oflags int bitwise OR of zero or more of O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_CREAT, O_DSYNC, O_EXCL, O_NOCTTY, O_NONBLOCK, O_RSYNC, O_SYNC and O_TRUNC (and O_CLOEXEC, where supported)
  • mode int access modes used by O_CREAT (default 511)

Returns:

    int file descriptor for path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local P = require "posix.fcntl"
    fd = P.open ("data", bit.bor (P.O_CREAT, P.O_RDWR), bit.bor (P.S_IRWXU, P.S_IRGRP))
posix_fadvise (fd, offset, len, advice)
Instruct kernel on appropriate cache behaviour for a file or file segment.

Parameters:

  • fd int open file descriptor
  • offset int start of region
  • len int number of bytes in region
  • advice int one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or POSIX_FADV_DONTNEED

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

flock
Advisory file locks. Passed as arg to fcntl when cmd is F_GETLK, F_SETLK or F_SETLKW.

Fields:

  • l_start int starting offset
  • l_len int len = 0 means until end of file
  • l_pid int lock owner
  • l_type int lock type
  • l_whence int one of SEEK_SET, SEEK_CUR or SEEK_END

Constants

posix.fcntl
Fcntl constants. Any constants not available in the underlying system will be 0 valued, if they are usually bitwise ORed with other values, otherwise nil.

Fields:

  • AT_EACCESS int test access permitted for effective IDs, not real IDs
  • AT_FDCWD int indicate *at functions to use current directory
  • AT_REMOVEDIR int remove directory instead of unlinking file
  • AT_SYMLINK_FOLLOW int follow symbolic links
  • AT_SYMLINK_NOFOLLOW int do not follow symbolic links
  • FD_CLOEXEC int close file descriptor on exec flag
  • F_DUPFD int duplicate file descriptor
  • F_GETFD int get file descriptor flags
  • F_SETFD int set file descriptor flags
  • F_GETFL int get file status flags
  • F_SETFL int set file status flags
  • F_GETLK int get record locking information
  • F_SETLK int set record locking information
  • F_SETLKW int set lock, and wait if blocked
  • F_GETOWN int get SIGIO/SIGURG process owner
  • F_SETOWN int set SIGIO/SIGURG process owner
  • F_RDLCK int shared or read lock
  • F_WRLCK int exclusive or write lock
  • F_UNLCK int unlock
  • O_RDONLY int open for reading only
  • O_WRONLY int open for writing only
  • O_RDWR int open for reading and writing
  • O_APPEND int set append mode
  • O_CLOEXEC int set FD_CLOEXEC atomically
  • O_CREAT int create if nonexistent
  • O_DSYNC int synchronise io data integrity
  • O_EXCL int error if file already exists
  • O_NOCTTY int don't assign controlling terminal
  • O_NONBLOCK int no delay
  • O_RSYNC int synchronise file read integrity
  • O_SYNC int synchronise file write integrity
  • O_TRUNC int truncate to zero length
  • POSIX_FADV_NORMAL int no advice
  • POSIX_FADV_SEQUENTIAL int expecting to access data sequentially
  • POSIX_FADV_RANDOM int expecting to access data randomly
  • POSIX_FADV_NOREUSE int expecting to access data once only
  • POSIX_FADV_WILLNEED int expecting to access data in the near future
  • POSIX_FADV_DONTNEED int not expecting to access the data in the near future

Usage:

    -- Print fcntl constants supported on this host.
    for name, value in pairs (require "posix.fcntl") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.fnmatch.html000066400000000000000000000202711475444374100212140ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.fnmatch

Filename matching.

Functions and constants for matching known filenames against shell-style pattern strings.

See also:

Functions

fnmatch (pat, name[, flags=0]) Match a filename against a shell pattern.

Constants

posix.fnmatch Fnmatch constants.


Functions

fnmatch (pat, name[, flags=0])
Match a filename against a shell pattern.

Parameters:

  • pat string shell pattern
  • name string filename
  • flags int optional (default 0)

Returns:

    int 0, if successful

Or

    int FNM_NOMATCH

Or

    int some other non-zero integer if fnmatch itself failed

See also:

Constants

posix.fnmatch
Fnmatch constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • FNM_PATHNAME int slashes in pathname must be matched by slash in pattern
  • FNM_NOESCAPE int disable backslash escaping
  • FNM_NOMATCH int match failed
  • FNM_PERIOD int periods in pathname must be matched by period in pattern

Usage:

    -- Print fnmatch constants supported on this host.
    for name, value in pairs (require "posix.fnmatch") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.glob.html000066400000000000000000000206151475444374100205210ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.glob

Generate pathnames matching a shell-style pattern.

Functions generating a table of filenames that match a shell-style pattern string.

Functions

glob ([pat="*"], flags) Find all files in this directory matching a shell pattern.

Constants

posix.glob Glob constants.


Functions

glob ([pat="*"], flags)
Find all files in this directory matching a shell pattern.

Parameters:

  • pat string shell glob pattern (default "*")
  • flags bitwise inclusive OR of zero or more of GLOB_ERR, GLOB_MARK and GLOB_NOCHECK

Returns:

    table matching filenames, if successful

Or

  1. nil
  2. one of GLOB_ABORTED, GLOB_NOMATCH or GLOB_NOSPACE

See also:

Constants

posix.glob
Glob constants.

Fields:

  • GLOB_MARK int append slashes to matches that are directories.
  • GLOB_ERR int instead of ignoring non-readable directories, return GLOB_ABORTED
  • GLOB_ABORTED int encountered a non-readable directory
  • GLOB_NOCHECK int return the original pattern if there are no matches
  • GLOB_NOMATCH int pattern does not match any existing pathname
  • GLOB_NOSPACE int not enough memory to continue

Usage:

    -- Print glob constants supported on this host.
    for name, value in pairs (require "posix.glob") do
      if type (value) == "number" then
        print (name, value)
      end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.grp.html000066400000000000000000000254421475444374100203710ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.grp

Group Database Operations.

Query the system group database.

See also:

Functions

endgrent () Release group database resources.
getgrent () Fetch next group.
getgrgid (gid) Fetch group with given group id.
getgrnam (name) Fetch named group.
setgrent () Rewind next getgrent back to start of database.

Tables

PosixGroup Group record.


Functions

endgrent ()
Release group database resources.

See also:

getgrent ()
Fetch next group.

Returns:

    PosixGroup next group record

See also:

Usage:

    local grp = require "posix.grp"
    t = grp.getgrent ()
    while t ~= nil do
      process (t)
      t = grp.getgrent ()
    end
    grp.endgrent ()
getgrgid (gid)
Fetch group with given group id.

Parameters:

  • gid int group id

Returns:

    PosixGroup group record for gid, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local grp = require "posix.grp"
    t = grp.getgrgid (0)
getgrnam (name)
Fetch named group.

Parameters:

Returns:

    PosixGroup group record for name, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local grp = require "posix.grp"
    t = grp.getgrnam "wheel"
setgrent ()
Rewind next getgrent back to start of database.

See also:

Tables

PosixGroup
Group record.

Fields:

  • gr_mem list a list of group members
  • gr_name string name of group
  • gr_gid int unique group id
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.html000066400000000000000000000731641475444374100176060ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix

Lua POSIX bindings.

In addition to the convenience functions documented in this module, many APIs from submodules are copied into the return table for backwards compatibility and, if necessary, wrapped to match the deprecated API.

This means that your old code will continue to work, but that you can use the improved documented APIs in new code.

Functions

chmod (path, mode) Change the mode of the path.
creat (path, mode) Create a file.
euidaccess (file, mode) Check permissions like posix.unistd.access, but for euid.
execx (task, ...) Exec a command or Lua function.
glob (args) Find all files in this directory matching a shell pattern.
mkdir (path) Make a directory.
mkfifo (path) Make a FIFO pipe.
msgget (key[, flags=0[, mode='rw-rw-rw-']]) Get a message queue identifier
open (path, oflags, modestr) Open a file.
openpty () Open a pseudo-terminal.
pclose (pfd) Close a pipeline opened with popen or popen_pipeline.
popen (task, mode[, pipe_fn]) Run a command or Lua function in a sub-process.
popen_pipeline (t, mode[, pipe_fn]) Perform a series of commands and Lua functions as a pipeline.
setlogmask (...) Set log priority mask
spawn (task, ...) Run a command or function in a sub-process using posix.execx.
timeradd (x, y) Add one gettimeofday() returned timeval to another.
timercmp (x, y) Compare one gettimeofday() returned timeval with another
timersub (x, y) Subtract one gettimeofday() returned timeval from another.
umask ([mode]) Set file mode creation mask.

Metamethods

__index (name) Preloading of luaposix modules.


Functions

chmod (path, mode)
Change the mode of the path.

Parameters:

  • path string existing file path
  • mode string

    one of the following formats:

    * 'rwxrwxrwx' (e.g. 'rw-rw-r--')
    * 'ugo+-=rwx' (e.g. 'u+w')
    * '+-=rwx'    (e.g. '+w')
    

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    chmod('bin/dof', '+x')
creat (path, mode)
Create a file. This function is obsoleted by posix.fcntl.open with posix.O_CREAT.

Parameters:

  • path string name of file to create
  • mode string permissions with which to create file

Returns:

    int file descriptor of file at path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    fd = creat('data', 'rw-r-----')
euidaccess (file, mode)
Check permissions like posix.unistd.access, but for euid. Based on the glibc function of the same name. Does not always check for read-only file system, text busy, etc., and does not work with ACLs &c.

Parameters:

  • file string file to check
  • mode string checks to perform (as for access)

Returns:

    int 0, if access allowed

Or

    nil (and errno is set)
execx (task, ...)
Exec a command or Lua function.

Parameters:

  • task table or function argument list for posix.unistd.execp or a Lua function, which should read from standard input, write to standard output, and return an exit code
  • ... positional arguments to the function

Returns:

  1. nil on error (normally does not return)
  2. string error message
glob (args)
Find all files in this directory matching a shell pattern. The flag MARK appends a trailing slash to matches that are directories.

Parameters:

  • args table, string or nil the three possible parameters can be used to override the default values for pattern and MARK, which are "*" and false respectively. A table will be checked for optional keys pattern and MARK. A string will be used as the glob pattern.

Returns:

    table matching files and directories, if successful

Or

  1. nil
  2. one of GLOB_BORTED, GLOB_NOMATCH or GLOB_NOSPACE

See also:

mkdir (path)
Make a directory.

Parameters:

  • path string location in file system to create directory

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum
mkfifo (path)
Make a FIFO pipe.

Parameters:

  • path string location in file system to create fifo

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum
msgget (key[, flags=0[, mode='rw-rw-rw-']])
Get a message queue identifier

Parameters:

  • key int message queue id, or IPC_PRIVATE for a new queue
  • flags int bitwise OR of zero or more from IPC_CREAT and IPC_EXCL (default 0)
  • mode string execute bits are ignored (default 'rw-rw-rw-')

Returns:

    int message queue identifier, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

open (path, oflags, modestr)
Open a file.

Parameters:

  • path string file to act on
  • oflags int bitwise OR of zero or more of O_RDONLY, O_WRONLY, O_RDWR, O_APPEND, O_CREAT, O_DSYNC, O_EXCL, O_NOCTTY, O_NONBLOCK, O_RSYNC, O_SYNC, O_TRUNC
  • modestr string (used with O_CREAT; see chmod for format)

Returns:

    int file descriptor for path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    fd = posix.open('data', bit.bor(posix.O_CREAT, posix.O_RDWR), 'rw-r-----')
openpty ()
Open a pseudo-terminal. Based on the glibc function of the same name.

Returns:

  1. int master file descriptor
  2. int slave file descriptor
  3. string slave file name, if successful

Or

  1. nil
  2. string error message
  3. int errnum
pclose (pfd)
Close a pipeline opened with popen or popen_pipeline.

Parameters:

  • pfd table pipeline object

Returns:

    values as for posix.sys.wait.wait, for the last (or only) stage of the pipeline
popen (task, mode[, pipe_fn])
Run a command or Lua function in a sub-process.

Parameters:

  • task table argument list for posix.unistd.execp or a Lua function, which should read from standard input, write to standard output, and return an exit code
  • mode string "r" for read or "w" for write
  • pipe_fn function function returning a paired read and write file descriptor (default posix.unistd.pipe) (optional)

Returns:

    pfd pipeline object

See also:

popen_pipeline (t, mode[, pipe_fn])
Perform a series of commands and Lua functions as a pipeline.

Parameters:

Returns:

    pfd pipeline object
setlogmask (...)
Set log priority mask

Parameters:

  • ... int zero or more of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING, LOG_NOTICE, LOG_INFO and LOG_DEBUG

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum
spawn (task, ...)
Run a command or function in a sub-process using posix.execx.

Parameters:

  • task table argument list for posix.unistd.execp or a Lua function, which should read from standard input, write to standard output, and return an exit code
  • ... as for posix.execx

Returns:

  1. int exit status, or signal number responsible for "killed" or "stopped"
  2. string "exited", "killed" or "stopped"

Or

  1. int errnum
  2. string error message
timeradd (x, y)
Add one gettimeofday() returned timeval to another.

Parameters:

  • x a timeval
  • y another timeval

Returns:

    x + y, adjusted for usec overflow
timercmp (x, y)
Compare one gettimeofday() returned timeval with another

Parameters:

  • x a timeval
  • y another timeval

Returns:

    0 if x and y are equal, >0 if x is newer, <0 if y is newer
timersub (x, y)
Subtract one gettimeofday() returned timeval from another.

Parameters:

  • x a timeval
  • y another tiimeval

Returns:

    x - y, adjusted for usec underflow
umask ([mode])
Set file mode creation mask.

Parameters:

  • mode string file creation mask string (optional)

Returns:

    string previous umask

See also:

Metamethods

__index (name)
Preloading of luaposix modules. Submodule tables are also preloaded into this top-level module, where they can be accessed without requiring them separately.

Parameters:

Returns:

    table or nil the submodule that was preloaded to satisfy name, otherwise nil if no such submodule is available.

Usage:

    local version = require 'posix'.version
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.libgen.html000066400000000000000000000156471475444374100210470ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.libgen

General Library.

Functions for separating a pathname into file and directory components.

Functions

basename (path) File part of path.
dirname (path) Directory name of path.


Functions

basename (path)
File part of path.

Parameters:

Returns:

    string filename part of path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

dirname (path)
Directory name of path.

Parameters:

Returns:

    string directory part of path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.poll.html000066400000000000000000000212301475444374100205360ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.poll

Synchronous I/O Multiplexing.

Examine file descriptors for events, such as readyness for I/O.

Functions

poll (fds[, timeout=-1]) Wait for events on multiple file descriptors.
rpoll (fd[, timeout=-1]) Wait for some event on a file descriptor.


Functions

poll (fds[, timeout=-1])
Wait for events on multiple file descriptors.

Parameters:

  • fds table list of file descriptors
  • timeout int maximum timeout in milliseconds, or -1 to block indefinitely (default -1)

Returns:

    int 0 if timed out, number of fd's ready if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

rpoll (fd[, timeout=-1])
Wait for some event on a file descriptor. Based on a lua-l list post.

Parameters:

  • fd int file descriptor
  • timeout int maximum timeout in milliseconds, or -1 to block indefinitely (default -1)

Returns:

    int 0 if timed out, number of fd's ready if successful

Or

  1. nil
  2. error message
  3. int errnum

See also:

Usage:

    local stdio = require "posix.stdio"
    
    local fh = io.open "one"
    while true do
      local r = rpoll (stdio.fileno(fh), 500)
      if r == 0 then
        print 'timeout'
      elseif r == 1 then
        print (fh:read ())
      else
        print "finish!"
        break
      end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.pwd.html000066400000000000000000000262621475444374100203740ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.pwd

Password Database Operations.

Query the system password database.

Functions

endpwent () Release password database resources.
getpwent () Fetch next password entry.
getpwnam (name) Fetch named user.
getpwuid (uid) Fetch password entry with given user id.
setpwent () Rewind next getpwent back to start of database.

Tables

PosixPasswd Password record.


Functions

endpwent ()
Release password database resources.

See also:

getpwent ()
Fetch next password entry.

Returns:

    PosixPasswd next password record

See also:

Usage:

    local pwd = require "posix.pwd"
    t = pwd.getpwent ()
    while t ~= nil do
      process (t)
      t = pwd.getpwent ()
    end
    pwd.endpwent ()
getpwnam (name)
Fetch named user.

Parameters:

Returns:

    PosixPasswd passwd record for name, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local pwd = require "posix.pwd"
    t = pwd.getpwnam "root"
getpwuid (uid)
Fetch password entry with given user id.

Parameters:

  • uid int user id

Returns:

    PosixPasswd passwd record for uid, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local pwd = require "posix.pwd"
    t = pwd.getpwuid (0)
setpwent ()
Rewind next getpwent back to start of database.

See also:

Tables

PosixPasswd
Password record.

Fields:

  • pw_name string user's login name
  • pw_uid int unique user id
  • pw_gid int user's default group id
  • pw_dir string initial working directory
  • pw_shell string user's login shell path
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sched.html000066400000000000000000000232341475444374100206640ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sched

Kernel Thread Scheduling Priority.

Where supported by the underlying system, functions to discover and change the kernel thread scheduling priority. If the module loads successfully, but there is no kernel support, then posix.sched.version will be set, but the unsupported APIs will be nil.

Functions

sched_getscheduler ([pid=0]) get scheduling policy
sched_setscheduler ([pid=0[, policy=`SCHED_OTHER`[, priority=0]]]) set scheduling policy/priority

Constants

posix.sched Scheduler constants.


Functions

sched_getscheduler ([pid=0])
get scheduling policy

Parameters:

  • pid int process to act on, or 0 for caller process (default 0)

Returns:

    int scheduling policy SCHED_FIFO, SCHED_RR, SCHED_OTHER, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

sched_setscheduler ([pid=0[, policy=`SCHED_OTHER`[, priority=0]]])
set scheduling policy/priority

Parameters:

  • pid int process to act on, or 0 for caller process (default 0)
  • policy int one of SCHED_FIFO, SCHED_RR or SCHED_OTHER (default `SCHED_OTHER`)
  • priority int must be 0 for SCHED_OTHER, or else a positive number below 100 for real-time policies (default 0)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Constants

posix.sched
Scheduler constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • SCHED_FIFO int first-in, first-out scheduling policy
  • SCHED_RR int round-robin scheduling policy
  • SCHED_OTHER int another scheduling policy

Usage:

    -- Print scheduler constants supported on this host.
    for name, value in pairs (require "posix.sched") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.signal.html000066400000000000000000000413711475444374100210550ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.signal

Software Signal Facilities.

Constants and functions for propagating signals among processes.

Note that posix.signal.signal is implemented with sigaction(2) for consistent semantics across platforms. Also note that installed signal handlers are not called immediatly upon occurrence of a signal. Instead, in order to keep the interperter state clean, they are executed in the context of a debug hook which is called as soon as the interpreter enters a new function, returns from the currently executing function, or after the execution of the current instruction has ended.

Functions

kill (pid, opt) Send a signal to the given process.
killpg (pgrp[, sig=`SIGTERM`]) Send a signal to the given process group.
raise (sig) Raise a signal on this process.
signal (signum[, handler=SIG_DFL[, flags]]) Install a signal handler for this signal number.

Constants

posix.signal Signal constants.


Functions

kill (pid, opt)
Send a signal to the given process.

Parameters:

  • pid int process to act on
  • opt int =SIGTERM sig signal to send

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

killpg (pgrp[, sig=`SIGTERM`])
Send a signal to the given process group.

Parameters:

  • pgrp int group id to act on, or 0 for the sending process`s group
  • sig int signal to send (default `SIGTERM`)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

raise (sig)
Raise a signal on this process.

Parameters:

  • sig int signal to send

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

signal (signum[, handler=SIG_DFL[, flags]])
Install a signal handler for this signal number. Although this is the same API as signal(2), it uses sigaction for guaranteed semantics.

Parameters:

  • signum int
  • handler function function, or SIG_IGN or SIG_DFL constants (default SIG_DFL)
  • flags the sa_flags element of struct sigaction (optional)

Returns:

    function previous handler function

See also:

Constants

posix.signal
Signal constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • SIGABRT int abort ()
  • SIGALRM int alarm clock
  • SIGBUS int bus error
  • SIGCHLD int to parent on child stop or exit
  • SIGCONT int continue a stopped process
  • SIGFPE int floating point error
  • SIGHUP int hangup
  • SIGILL int illegal instruction
  • SIGINFO int information request
  • SIGINT int interrupt
  • SIGKILL int kill
  • SIGPIPE int write on pipe with no reader
  • SIGQUIT int quit
  • SIGSEGV int segmentation violation
  • SIGSTOP int stop
  • SIGSYS int bad argument to system call
  • SIGTERM int terminate
  • SIGTRAP int trace trap
  • SIGTSTP int stop signal from tty
  • SIGTTIN int to readers process group on background tty read
  • SIGTTOU int to readers process group on background tty output
  • SIGURG int urgent condition on i/o channel
  • SIGUSR1 int user defined
  • SIGUSR2 int user defined
  • SIGVTALRM int virtual time alarm
  • SIGWINCH int window size change
  • SIGXCPU int exceeded cpu time limit
  • SIGXFSZ int exceeded file size limit
  • SA_NOCLDSTOP int do not generate a SIGCHLD on child stop
  • SA_NOCLDWAIT int don't keep zombies child processes
  • SA_NODEFER int don't mask the signal we're delivering
  • SA_RESETHAND int reset to SIG_DFL when taking a signal
  • SA_RESTART int allow syscalls to restart instead of returning EINTR

Usage:

    -- Print signal constants supported on this host.
    for name, value in pairs (require "posix.signal") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.stdio.html000066400000000000000000000310261475444374100207160ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.stdio

A few Standard I/O functions not already in Lua core.

Functions

ctermid () Name of controlling terminal.
fdopen (fd, mode) Create a Lua file object from a file descriptor.
fileno (file) File descriptor corresponding to a Lua file object.
rename (oldpath, newpath) Change the name or location of a file

Constants

posix.stdio Stdio constants.


Functions

ctermid ()
Name of controlling terminal.

Returns:

    string controlling terminal for current process

See also:

fdopen (fd, mode)
Create a Lua file object from a file descriptor.

Parameters:

  • fd int file descriptor
  • mode string the mode in which to open the file descriptor

Returns:

    file Lua file object fd, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local fdopen = require "posix.stdio".fdopen
    local STDOUT_FILENO = require "posix.unistd".STDOUT_FILENO
    stdout = fdopen (STDOUT_FILENO, "w")
fileno (file)
File descriptor corresponding to a Lua file object.

Parameters:

  • file file Lua file object

Returns:

    int file descriptor for file, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local stdio = require "posix.stdio"
    local unistd = require "posix.unistd"
    assert (stdio.fileno (io.stdout) == unistd.STDOUT_FILENO)
rename (oldpath, newpath)
Change the name or location of a file

Parameters:

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local ok, errmsg = P.rename (oldpath, newpath)
    if not ok then error (errmsg) end

Constants

posix.stdio
Stdio constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • _IOFBF int fully buffered
  • _IOLBF int line buffered
  • _IONBF int unbuffered
  • BUFSIZ int size of buffer
  • EOF int end of file
  • FOPEN_MAX int maximum number of open files
  • FILENAME_MAX int maximum length of filename

Usage:

    -- Print stdio constants supported on this host.
    for name, value in pairs (require "posix.stdio") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.stdlib.html000066400000000000000000000417421475444374100210630ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.stdlib

Standard Posix Library functions.

Functions

abort () Abort the program immediately.
getenv ([name]) Get value of environment variable, or all variables.
grantpt (fd) Grant access to a slave pseudoterminal
mkdtemp (templ) Create a unique temporary directory.
mkstemp (templ) Create a unique temporary file.
openpt (oflags) Open a pseudoterminal.
ptsname (fd) Get the name of a slave pseudo-terminal
realpath (path) Find canonicalized absolute pathname.
setenv (name[, value[, overwrite]]) Set an environment variable for this process.
unlockpt (fd) Unlock a pseudoterminal master/slave pair


Functions

abort ()
Abort the program immediately.

See also:

getenv ([name])
Get value of environment variable, or all variables.

Parameters:

  • name string if nil, get all (optional)

Returns:

    value if name given, otherwise a name-indexed table of values.

See also:

Usage:

    for a,b in pairs(posix.getenv()) do print(a, b) end
grantpt (fd)
Grant access to a slave pseudoterminal

Parameters:

  • fd int descriptor returned by openpt

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

mkdtemp (templ)
Create a unique temporary directory.

Parameters:

  • templ string pattern that ends in six 'X' characters

Returns:

    string path to directory, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

mkstemp (templ)
Create a unique temporary file.

Parameters:

  • templ string pattern that ends in six 'X' characters

Returns:

  1. int open file descriptor
  2. string path to file, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local stdlib = require "posix.stdlib"
    stdlib.mkstemp 'wooXXXXXX'
openpt (oflags)
Open a pseudoterminal.

Parameters:

  • oflags int bitwise OR of zero or more of O_RDWR and O_NOCTTY

Returns:

    file descriptor of pseudoterminal, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

ptsname (fd)
Get the name of a slave pseudo-terminal

Parameters:

  • fd int descriptor returned by openpt

Returns:

    path name of the slave terminal device, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

realpath (path)
Find canonicalized absolute pathname.

Parameters:

Returns:

    string canonicalized absolute path, if successful

Or

  1. nil
  2. string error messag
  3. int errnum

See also:

setenv (name[, value[, overwrite]])
Set an environment variable for this process. (Child processes will inherit this)

Parameters:

  • name string
  • value string (maybe nil, meaning 'unset') (optional)
  • overwrite non-nil prevents overwriting a variable (optional)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

unlockpt (fd)
Unlock a pseudoterminal master/slave pair

Parameters:

  • fd int descriptor returned by openpt

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.msg.html000066400000000000000000000415251475444374100212040ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.msg

Sys V Message Queue Operations.

Where supported by the underlying system, functions to send and receive interprocess messages. If the module loads successfully, but there is no system support, then posix.sys.msg.version will be set, but the unsupported APIs wil be nil.

Functions

msgctl (id, cmd)
msgget (key[, flags=0]) Get a message queue identifier
msgrcv (id, size, type[, flags=0]) Receive message from a message queue
msgsnd (id, type, message[, flags=0]) Send message to a message queue

Tables

PosixMsqid Message queue record.

Constants

posix.sys.msg Message constants.


Functions

msgctl (id, cmd)

Parameters:

  • id int message queue identifier returned by msgget
  • cmd int one of IPC_STAT, IPC_SET or IPC_RMID

Returns:

    PosixMsqid table for id, with IPC_STAT, if successful

Or

    non-nil, with IPC_SET or IPC_RMID, if successful

Or

  1. nil otherwise
  2. string error message
  3. int errnum

See also:

Usage:

    local sysvmsg = require 'posix.sys.msg'
    local msq = sysvmsg.msgget(sysvmsg.IPC_PRIVATE)
    local msqid, errmsg = sysvmsg.msgctl(msq, sysvmsg.IPC_STAT)
    assert(msqid, errmsg)
    assert(sysvmsg.msgctl(msq, sysvmsg.IPC_RMID))
msgget (key[, flags=0])
Get a message queue identifier

Parameters:

  • key int message queue id, or IPC_PRIVATE for a new queue
  • flags int bitwise OR of zero or more from IPC_CREAT and IPC_EXCL, and access permissions S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH and S_IWOTH (from posix.sys.stat) (default 0)

Returns:

    int message queue identifier, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

msgrcv (id, size, type[, flags=0])
Receive message from a message queue

Parameters:

  • id int message queue identifier returned by msgget
  • size int maximum message size
  • type int message type (optional, default - 0)
  • flags int bitwise OR of zero or more of IPC_NOWAIT, MSG_EXCEPT and MSG_NOERROR (default 0)

Returns:

  1. int message type from msgsnd
  2. string message text, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

msgsnd (id, type, message[, flags=0])
Send message to a message queue

Parameters:

  • id int message queue identifier returned by msgget
  • type int arbitrary message type
  • message string content
  • flags int optionally IPC_NOWAIT (default 0)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

PosixMsqid
Message queue record.

Fields:

  • msg_qnum int number of messages on the queue
  • msg_qbytes int number of bytes allowed on the queue
  • msg_lspid int process id of last msgsnd
  • msg_lrpid int process id of last msgrcv
  • msg_stime int time of last msgsnd
  • msg_rtime int time of last msgrcv
  • msg_ctime int time of last change

Constants

posix.sys.msg
Message constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • IPC_STAT int return a Msqid table from msgctl
  • IPC_SET int set the Msqid fields from msgctl
  • IPC_RMID int remove a message queue with msgctl
  • IPC_CREAT int create entry if key does not exist
  • IPC_EXCL int fail if key exists
  • IPC_PRIVATE int private key
  • IPC_NOWAIT int error if request must wait
  • MSG_EXCEPT int read messages with differing type
  • MSG_NOERROR int truncate received message rather than erroring

Usage:

    -- Print msg constants supported on this host.
    for name, value in pairs (require "posix.sys.msg") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.resource.html000066400000000000000000000305331475444374100222420ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.resource

Control Maximum System Resource Consumption.

Functions

getrlimit (resource) Get resource limits for this process.
setrlimit (resource[, softlimit[, hardlimit]]) Set a resource limit for subsequent child processes.

Tables

PosixRlimit Resource limit record.

Constants

posix.sys.resource Rlimit constants.


Functions

getrlimit (resource)
Get resource limits for this process.

Parameters:

  • resource int one of RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_NOFILE, RLIMIT_STACK or RLIMIT_AS

Returns:

  1. int softlimit
  2. int hardlimit, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sysres = require "posix.sys.resource"
    sysres.getrlimit(sysres.RLIMIT_NOFILE)
setrlimit (resource[, softlimit[, hardlimit]])
Set a resource limit for subsequent child processes.

Parameters:

  • resource int one of RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_NOFILE, RLIMIT_STACK or RLIMIT_AS
  • softlimit process may receive a signal when reached (optional)
  • hardlimit process may be terminated when reached (optional)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sysres = require "posix.sys.resource"
    local lim = sysres.getlimit(sysres.RLIMIT_NOFILE)
    lim.rlim_cur = lim.rlim_cur / 2
    sysres.setrlimit(sysres.RLIMIT_NOFILE, lim)

Tables

PosixRlimit
Resource limit record.

Fields:

  • rlim_cur int current soft limit
  • rlim_max int hard limit

Constants

posix.sys.resource
Rlimit constants.

Fields:

  • RLIM_INFINITY int unlimited resource usage
  • RLIM_SAVED_CUR int saved current resource soft limit
  • RLIM_SAVED_MAX int saved resource hard limit
  • RLIMIT_CORE int maximum bytes allowed for a core file
  • RLIMIT_CPU int maximum cputime secconds allowed per process
  • RLIMIT_DATA int maximum data segment bytes per process
  • RLIMIT_FSIZE int maximum bytes in any file
  • RLIMIT_NOFILE int maximum number of open files per process
  • RLIMIT_STACK int maximum stack segment bytes per process
  • RLIMIT_AS int maximum bytes total address space per process

Usage:

    -- Print resource constants supported on this host.
    for name, value in pairs (require "posix.sys.resource") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.socket.html000066400000000000000000001421001475444374100216750ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.socket

BSD Sockets.

Where supported by the underlying system, functions and constants to create, connect and communicate over BSD sockets. If the module loads successfully, but there is no kernel support, then posix.sys.socket.version will be set, but the unsupported APIs will be nil.

Functions

accept (fd) Accept a connection on a socket.
bind (fd, addr) Bind an address to a socket.
connect (fd, addr) Initiate a connection on a socket.
getaddrinfo (host, service[, hints]) Network address and service translation.
getpeername (sockfd) Get socket peer name.
getsockname (sockfd) Get socket name.
getsockopt (fd, level, name) Get options on sockets.
if_nametoindex (ifname) Get network interface index by name.
listen (fd, backlog) Listen for connections on a socket.
recv (fd, count) Receive a message from a socket.
recvfrom (fd, count) Receive a message from a socket.
send (fd, buffer) Send a message from a socket.
sendto (fd, buffer, destination) Send a message from a socket.
setsockopt (fd, level, name, value1[, value2]) Get and set options on sockets.
shutdown (fd, how) Shut down part of a full-duplex connection.
socket (domain, type, options) Create an endpoint for communication.
socketpair (domain, socktype, options) Create a pair of connected sockets.

Tables

PosixAddrInfo Address information hints.
sockaddr Socket address.

Constants

posix.sys.socket Socket constants.


Functions

accept (fd)
Accept a connection on a socket.

Parameters:

  • fd int socket descriptor to act on

Returns:

  1. int connection descriptor
  2. table connection address, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

bind (fd, addr)
Bind an address to a socket.

Parameters:

  • fd int socket descriptor to act on
  • addr sockaddr socket address

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

connect (fd, addr)
Initiate a connection on a socket.

Parameters:

  • fd int socket descriptor to act on
  • addr sockaddr socket address

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

getaddrinfo (host, service[, hints])
Network address and service translation.

Parameters:

  • host string name of a host. For IPv6, link-local addresses like 'ff02::1%eth0' are supported.
  • service string name of service
  • hints PosixAddrInfo table (optional)

Returns:

    list of sockaddr tables, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

      local sys_sock = require "posix.sys.socket"
      local res, errmsg, errcode = sys_sock.getaddrinfo ("www.lua.org", "http",
        { family = sys_sock.IF_INET, socktype = sys_sock.SOCK_STREAM }
    )
getpeername (sockfd)
Get socket peer name.

Parameters:

  • sockfd int socket descriptor

Returns:

    sockaddr the address to which the socket sockfd is connected to, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    sa, err = posix.getpeername (sockfd)
getsockname (sockfd)
Get socket name.

Parameters:

  • sockfd int socket descriptor

Returns:

    sockaddr the current address to which the socket sockfd is bound, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    sa, err = posix.getsockname (sockfd)
getsockopt (fd, level, name)
Get options on sockets.

Parameters:

  • fd int socket descriptor
  • level int one of SOL_SOCKET, IPPROTO_IPV6, IPPROTO_TCP
  • name int option name, varies according to level value

Returns:

    the value of the requested socket option, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    val, errmsg, errnum = sys_sock.getsockopt(
      sock, sys_sock.SOL_SOCKET, sys_sock.SO_SNDTIMEO
    )
    print('Send timeout ', val.tv_sec + val.tv_usec / 1000000)
if_nametoindex (ifname)
Get network interface index by name. Needed for packet sockets, since SO_BINDTODEVICE won't work on packet family.

Parameters:

  • ifname string interface name

Returns:

    int interface index, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    ifindex, errmsg, errnum = sys_sock.if_nametoindex("eth0")
listen (fd, backlog)
Listen for connections on a socket.

Parameters:

  • fd int socket descriptor to act on
  • backlog int maximum length for queue of pending connections

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

recv (fd, count)
Receive a message from a socket.

Parameters:

  • fd int socket descriptor to act on
  • count int maximum number of bytes to receive

Returns:

    string received bytes, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

recvfrom (fd, count)
Receive a message from a socket.

Parameters:

  • fd int socket descriptor to act on
  • count int maximum number of bytes to receive

Returns:

  1. int received bytes
  2. sockaddr address of message source, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

send (fd, buffer)
Send a message from a socket.

Parameters:

  • fd int socket descriptor to act on
  • buffer string message bytes to send

Returns:

    int number of bytes sent, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

sendto (fd, buffer, destination)
Send a message from a socket.

Parameters:

  • fd int socket descriptor to act on
  • buffer string message bytes to send
  • destination sockaddr socket address

Returns:

    int number of bytes sent, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

setsockopt (fd, level, name, value1[, value2])
Get and set options on sockets.

Parameters:

  • fd int socket descriptor
  • level int one of SOL_SOCKET, IPPROTO_IPV6, IPPROTO_TCP
  • name int option name, varies according to level value
  • value1 option value to set
  • value2 some option names need an additional value (optional)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    ok, errmsg = sys_sock.setsockopt (
      sock, sys_sock.SOL_SOCKET, sys_sock.SO_SNDTIMEO, 1, 0
    )
shutdown (fd, how)
Shut down part of a full-duplex connection.

Parameters:

  • fd int socket descriptor to act on
  • how int one of SHUT_RD, SHUT_WR or SHUT_RDWR

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    ok, errmsg = sys_sock.shutdown (sock, sys_sock.SHUT_RDWR)
socket (domain, type, options)
Create an endpoint for communication.

Parameters:

  • domain int one of AF_INET, AF_INET6, AF_UNIX, AF_NETLINK or AF_PACKET
  • type int one of SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
  • options int usually 0, but some socket types might implement other protocols.

Returns:

    int socket descriptor, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    sockd = sys_sock.socket (sys_sock.AF_INET, sys_sock.SOCK_STREAM, 0)
socketpair (domain, socktype, options)
Create a pair of connected sockets.

Parameters:

  • domain int one of AF_INET, AF_INET6, AF_UNIX or AF_NETLINK
  • socktype int one of SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
  • options int usually 0, but some socket types might implement other protocols.

Returns:

  1. int descriptor of one end of the socket pair
  2. int descriptor of the other end of the pair, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_sock = require "posix.sys.socket"
    sockr, sockw = sys_sock.socketpair (sys_sock.AF_INET, sys_sock.SOCK_STREAM, 0)

Tables

PosixAddrInfo
Address information hints.

Fields:

  • family int one of AF_INET, AF_INET6, AF_UNIX, AF_NETLINK or AF_PACKET
  • flags int bitwise OR of zero or more of AI_ADDRCONFIG, AI_ALL, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV, AI_PASSIVE and AI_V4MAPPED
  • socktype int one of SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
  • protocol int one of IPPROTO_TCP or IPPROTO_UDP
sockaddr
Socket address. All sockaddr tables have the family field, and depending on its value, also a subset of the following fields too.

Fields:

  • family int one of AF_INET, AF_INET6, AF_UNIX, AF_NETLINK or AF_PACKET
  • port int socket port number for AF_INET (and equivalently AF_INET6) family (optional)
  • addr string socket host address in correct format, for AF_INET family (optional)
  • socktype int one of SOCK_STREAM, SOCK_DGRAM or SOCK_RAW for AF_INET family (optional)
  • canonname string canonical name for service location, for AF_INET family (optional)
  • protocol int one of IPPROTO_TCP or IPPROTO_UDP, for AF_INET family (optional)
  • path string location in file system, for AF_UNIX family (optional)
  • pid int process identifier, for AF_NETLINK family (optional)
  • groups int process group owner identifier, for AF_NETLINK family (optional)
  • ifindex int interface index, for AF_PACKET family (optional)

Constants

posix.sys.socket
Socket constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • AF_INET int IP protocol family
  • AF_INET6 int IP version 6
  • AF_NETLINK int Netlink protocol family
  • AF_PACKET int Packet protocol family
  • AF_UNIX int local to host
  • AF_UNSPEC int unspecified
  • AI_ADDRCONFIG int use host configuration for returned address type
  • AI_ALL int return IPv4 mapped and IPv6 addresses
  • AI_CANONNAME int request canonical name
  • AI_NUMERICHOST int don't use domain name resolution
  • AI_NUMERICSERV int don't use service name resolution
  • AI_PASSIVE int address is intended for bind
  • AI_V4MAPPED int IPv4 mapped addresses are acceptable
  • IPPROTO_ICMP int internet control message protocol
  • IPPROTO_IP int internet protocol
  • IPPROTO_IPV6 int IPv6 header
  • IPPROTO_TCP int transmission control protocol
  • IPPROTO_UDP int user datagram protocol
  • IPV6_JOIN_GROUP int
  • IPV6_LEAVE_GROUP int
  • IPV6_MULTICAST_HOPS int
  • IPV6_MULTICAST_IF int
  • IPV6_MULTICAST_LOOP int
  • IPV6_UNICAST_HOPS int
  • IPV6_V6ONLY int
  • NETLINK_AUDIT int auditing
  • NETLINK_CONNECTOR int
  • NETLINK_DNRTMSG int decnet routing messages
  • NETLINK_ECRYPTFS int
  • NETLINK_FIB_LOOKUP int
  • NETLINK_FIREWALL int firewalling hook
  • NETLINK_GENERIC int
  • NETLINK_IP6_FW int
  • NETLINK_ISCSI int open iSCSI
  • NETLINK_KOBJECT_UEVENT int kernel messages to userspace
  • NETLINK_NETFILTER int netfilter subsystem
  • NETLINK_NFLOG int netfilter/iptables ULOG
  • NETLINK_ROUTE int routing/device hook
  • NETLINK_SCSITRANSPORT int SCSI transports
  • NETLINK_SELINUX int SELinux event notifications
  • NETLINK_UNUSED int unused number
  • NETLINK_USERSOCK int reserved for user mode socket protocols
  • NETLINK_XFRM int ipsec
  • SHUT_RD int no more receptions
  • SHUT_RDWR int no more receptions or transmissions
  • SHUT_WR int no more transmissions
  • SOCK_DGRAM int connectionless unreliable datagrams
  • SOCK_RAW int raw protocol interface
  • SOCK_STREAM int connection based byte stream
  • SOL_SOCKET int socket level
  • SOMAXCONN int maximum concurrent connections
  • SO_ACCEPTCONN int does this socket accept connections
  • SO_BINDTODEVICE int bind to a particular device
  • SO_BROADCAST int permit broadcasts
  • SO_DEBUG int turn-on socket debugging
  • SO_DONTROUTE int bypass standard routing
  • SO_ERROR int set socket error flag
  • SO_KEEPALIVE int periodically transmit keep-alive message
  • SO_LINGER int linger on a posix.unistd.close if data is still present
  • SO_OOBINLINE int leave out-of-band data inline
  • SO_RCVBUF int set receive buffer size
  • SO_RCVLOWAT int set receive buffer low water mark
  • SO_RCVTIMEO int set receive timeout
  • SO_REUSEADDR int reuse local addresses
  • SO_SNDBUF int set send buffer size
  • SO_SNDLOWAT int set send buffer low water mark
  • SO_SNDTIMEO int set send timeout
  • SO_TYPE int get the socket type
  • TCP_NODELAY int don't delay send for packet coalescing

Usage:

    -- Print socket constants supported on this host.
    for name, value in pairs (require "posix.sys.socket") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.stat.html000066400000000000000000000667501475444374100214000ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.stat

File Status Querying and Setting.

Functions

S_ISBLK (mode) Test for a block special file.
S_ISCHR (mode) Test for a character special file.
S_ISDIR (mode) Test for a directory.
S_ISFIFO (mode) Test for a fifo special file.
S_ISLNK (mode) Test for a symbolic link.
S_ISREG (mode) Test for a regular file.
S_ISSOCK (mode) Test for a socket.
chmod (path, mode) Change the mode of the path.
fstat (fd) Information about a file descriptor.
lstat (path) Information about an existing file path.
mkdir (path[, mode=511]) Make a directory.
mkfifo (path[, mode=511]) Make a FIFO pipe.
stat (path) Information about an existing file path.
umask (mode) Set file mode creation mask.

Tables

PosixStat File state record.

Constants

posix.sys.stat Stat constants.


Functions

S_ISBLK (mode)
Test for a block special file.

Parameters:

Returns:

    int non-zero if mode represents a block special file
S_ISCHR (mode)
Test for a character special file.

Parameters:

Returns:

    int non-zero if mode represents a character special file
S_ISDIR (mode)
Test for a directory.

Parameters:

Returns:

    int non-zero if mode represents a directory
S_ISFIFO (mode)
Test for a fifo special file.

Parameters:

Returns:

    int non-zero if mode represents a fifo special file
S_ISLNK (mode)
Test for a symbolic link.

Parameters:

Returns:

    int non-zero if mode represents a symbolic link
S_ISREG (mode)
Test for a regular file.

Parameters:

Returns:

    int non-zero if mode represents a regular file
S_ISSOCK (mode)
Test for a socket.

Parameters:

Returns:

    int non-zero if mode represents a socket
chmod (path, mode)
Change the mode of the path.

Parameters:

  • path string existing file path to act on
  • mode int access modes to set for path

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_stat = require "posix.sys.stat"
    sys_stat.chmod ('bin/dof', bit.bor (sys_stat.S_IRWXU, sys_stat.S_IRGRP))
fstat (fd)
Information about a file descriptor.

Parameters:

  • fd int file descriptor to act on

Returns:

    PosixStat information about fd, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local fcntl = require "posix.fcntl"
    local sys_stat = require "posix.sys.stat"
    local fd = assert(fcntl.open("/etc/hostname", fcntl.O_RDONLY))
    for a, b in pairs (sys_stat.fstat(fd)) do print (a, b) end
lstat (path)
Information about an existing file path. If file is a symbolic link, return information about the link itself.

Parameters:

Returns:

    PosixStat information about path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_stat = require "posix.sys.stat"
    for a, b in pairs (sys_stat.lstat "/etc/") do print (a, b) end
mkdir (path[, mode=511])
Make a directory.

Parameters:

  • path string location in file system to create directory
  • mode int access modes to set for path (default 511)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

mkfifo (path[, mode=511])
Make a FIFO pipe.

Parameters:

  • path string location in file system to create fifo
  • mode int access modes to set for path (default 511)

Returns:

    int file descriptor for path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

stat (path)
Information about an existing file path. If file is a symbolic link, return information about the file the link points to.

Parameters:

Returns:

    PosixStat information about path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local sys_stat = require "posix.sys.stat"
    for a, b in pairs (sys_stat.stat "/etc/") do print (a, b) end
umask (mode)
Set file mode creation mask.

Parameters:

  • mode int new file creation mask

Returns:

    int previous umask

See also:

Tables

PosixStat
File state record.

Fields:

  • st_dev int device id
  • st_ino int inode number
  • st_mode int mode of file
  • st_nlink int number of hardlinks to file
  • st_uid int user id of file owner
  • st_gid int group id of file owner
  • st_rdev int additional device specific id for special files
  • st_size int file size in bytes
  • st_atime int time of last access
  • st_mtime int time of last data modification
  • st_ctime int time of last state change
  • st_blksize int preferred block size
  • st_blocks int number of blocks allocated

Constants

posix.sys.stat
Stat constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • S_IFMT int file type mode bitmask
  • S_IFBLK int block special
  • S_IFCHR int character special
  • S_IFDIR int directory
  • S_IFIFO int fifo
  • S_IFLNK int symbolic link
  • S_IFREG int regular file
  • S_IFSOCK int socket
  • S_IRWXU int user read, write and execute
  • S_IRUSR int user read
  • S_IWUSR int user write
  • S_IXUSR int user execute
  • S_IRWXG int group read, write and execute
  • S_IRGRP int group read
  • S_IWGRP int group write
  • S_IXGRP int group execute
  • S_IRWXO int other read, write and execute
  • S_IROTH int other read
  • S_IWOTH int other write
  • S_IXOTH int other execute
  • S_ISGID int set group id on execution
  • S_ISUID int set user id on execution

Usage:

    -- Print stat constants supported on this host.
    for name, value in pairs (require "posix.sys.stat") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.statvfs.html000066400000000000000000000250131475444374100221020ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.statvfs

Retrieve File System Information.

Where supported by the underlying system, query the file system. If the module loads, but there is no kernel support, then posix.sys.statvfs.version will be set, but the unsupported APIs will be nil.

Functions

statvfs (path) Get file system statistics.

Tables

PosixStatvfs Files system information record.

Constants

posix.sys.statvfs Statvfs constants.


Functions

statvfs (path)
Get file system statistics.

Parameters:

  • path string any path within the mounted file system

Returns:

    PosixStatvfs information about file system containing path, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local statvfs = require "posix.sys.statvfs".statvfs
    for a, b in pairs (statvfs "/") do print (a, b) end

Tables

PosixStatvfs
Files system information record.

Fields:

  • f_bsize int file system block size
  • f_frsize int fundamental file system block size
  • f_blocks int number of *f_frsize* sized blocks in file system
  • f_bfree int number of free blocks
  • f_bavail int number of free blocks available to non-privileged process
  • f_files int number of file serial numbers
  • f_ffree int number of free file serial numbers
  • f_favail int number of free file serial numbers available
  • f_fsid int file system id
  • f_flag int flag bits
  • f_namemax int maximum filename length

Constants

posix.sys.statvfs
Statvfs constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • ST_RDONLY int read-only file system
  • ST_NOSUID int does not support S_ISUID nor S_ISGID file mode bits

Usage:

    -- Print statvfs constants supported on this host.
    for name, value in pairs (require "posix.sys.statvfs") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.time.html000066400000000000000000000146241475444374100213540ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.time

Get and Set System Date and Time.

Functions

gettimeofday () Get time of day.

Tables

PosixTimeval Time value.


Functions

gettimeofday ()
Get time of day.

Returns:

    PosixTimeval time elapsed since epoch, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

PosixTimeval
Time value.

Fields:

  • tv_sec int seconds elapsed
  • tv_usec int remainder in microseconds

See also:

generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.times.html000066400000000000000000000153101475444374100215300ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.times

Process Times.

Functions

times () Get the current process times.

Tables

PosixTms Process times record.


Functions

times ()
Get the current process times.

Returns:

    PosixTms time accounting for this process, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

PosixTms
Process times record. All times are measured in cpu seconds.

Fields:

  • tms_utime int time spent executing user instructions
  • tms_stime int time spent in system execution
  • tms_cutime int sum of *tms_utime* for calling process and its children
  • tms_cstime int sum of *tms_stime* for calling process and its children
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.utsname.html000066400000000000000000000160011475444374100220610ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.utsname

Get System Identification.

Functions

uname () Return information about this machine.

Tables

utsname System identification record.


Functions

uname ()
Return information about this machine.

Returns:

    utsname system information, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

utsname
System identification record.

Fields:

  • machine string hardware platform name
  • nodename string network node name
  • release string operating system release level
  • sysname string operating system name
  • version string operating system version
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.sys.wait.html000066400000000000000000000204471475444374100213620ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.sys.wait

Wait for Process Termination.

Functions

wait ([pid=-1[, options]]) Wait for child process to terminate.

Constants

posix.sys.wait Wait constants.


Functions

wait ([pid=-1[, options]])
Wait for child process to terminate.

Parameters:

  • pid int child process id to wait for, or -1 for any child process (default -1)
  • options int bitwise OR of WNOHANG and WUNTRACED (optional)

Returns:

  1. int pid of running child, if not exited yet and called with WNOHANG
  2. string "running"

Or

  1. int pid of terminated child, if successful
  2. string "exited", "killed" or "stopped"
  3. int exit status, or signal number responsible for "killed" or "stopped"

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Constants

posix.sys.wait
Wait constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • WNOHANG int don't block waiting
  • WUNTRACED int report status of stopped children

Usage:

    -- Print wait constants supported on this host.
    for name, value in pairs (require "posix.sys.wait") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.syslog.html000066400000000000000000000364701475444374100211240ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.syslog

Control System Log.

Functions

LOG_MASK (priority) Mask bit for given log priority.
closelog () Close system log.
openlog (ident[, option[, facility=`LOG_USER`]]) Open the system logger.
setlogmask (mask) Set log priority mask.
syslog (priority, message) Write to the system logger.

Constants

posix.syslog System logging constants.


Functions

LOG_MASK (priority)
Mask bit for given log priority.

Parameters:

  • priority int one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING, LOG_NOTICE, LOG_INFO or LOG_DEBUG

Returns:

    int mask bit corresponding to priority

See also:

closelog ()
Close system log.

See also:

openlog (ident[, option[, facility=`LOG_USER`]])
Open the system logger.

Parameters:

  • ident string all messages will start with this
  • option int bitwise OR of zero or more of LOG_CONS, LOG_NDELAY, or LOG_PID (optional)
  • facility int one of LOG_AUTH, LOG_CRON, LOG_DAEMON, LOG_KERN, LOG_LPR, LOG_MAIL, LOG_NEWS, LOG_SECURITY, LOG_USER, LOG_UUCP or LOG_LOCAL0 through LOG_LOCAL7 (default `LOG_USER`)

See also:

setlogmask (mask)
Set log priority mask.

Parameters:

Returns:

    int previous mask, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

syslog (priority, message)
Write to the system logger.

Parameters:

  • priority int one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_WARNING, LOG_NOTICE, LOG_INFO or LOG_DEBUG
  • message string log message

See also:

Constants

posix.syslog
System logging constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • LOG_AUTH int security/authorisation messages
  • LOG_CONS int write directly to system console
  • LOG_CRON int clock daemon
  • LOG_DAEMON int system daemons
  • LOG_KERN int kernel messages
  • LOG_LOCAL0 int reserved for local use
  • LOG_LOCAL1 int reserved for local use
  • LOG_LOCAL2 int reserved for local use
  • LOG_LOCAL3 int reserved for local use
  • LOG_LOCAL4 int reserved for local use
  • LOG_LOCAL5 int reserved for local use
  • LOG_LOCAL6 int reserved for local use
  • LOG_LOCAL7 int reserved for local use
  • LOG_LPR int line printer subsystem
  • LOG_MAIL int mail system
  • LOG_NDELAY int open the connection immediately
  • LOG_NEWS int network news subsystem
  • LOG_PID int include process id with each log message
  • LOG_USER int random user-level messages
  • LOG_UUCP int unix-to-unix copy subsystem
  • LOG_EMERG int system is unusable
  • LOG_ALERT int action must be taken immediately
  • LOG_CRIT int critical conditions
  • LOG_ERR int error conditions
  • LOG_WARNING int warning conditions
  • LOG_NOTICE int normal but significant conditions
  • LOG_INFO int informational
  • LOG_DEBUG int debug-level messages

Usage:

    -- Print syslog constants supported on this host.
    for name, value in pairs (require "posix.syslog") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.termio.html000066400000000000000000000567561475444374100211140ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.termio

Control Terminal I/O.

Functions and constants for controlling terminal behaviour.

Functions

tcdrain (fd) Wait for all written output to reach the terminal.
tcflow (fd, action) Suspend transmission or receipt of data.
tcflush (fd, action) Discard any data already written but not yet sent to the terminal.
tcgetattr (fd) Get termios state.
tcgetwinsize (fd) Get terminal window size.
tcsendbreak (fd, duration) Send a stream of zero valued bits.
tcsetattr (fd, actions, a) Set termios state.
tcsetwinsize (fd, winsize) Set terminal window size.

Tables

PosixWinsize Winsize record.
ccs Control characters.
termios Terminal attributes.


Functions

tcdrain (fd)
Wait for all written output to reach the terminal.

Parameters:

  • fd int terminal descriptor to act on

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

tcflow (fd, action)
Suspend transmission or receipt of data.

Parameters:

  • fd int terminal descriptor to act on
  • action int one of TCOOFF, TCOON, TCIOFF or TCION

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

tcflush (fd, action)
Discard any data already written but not yet sent to the terminal.

Parameters:

  • fd int terminal descriptor to act on
  • action int one of TCIFLUSH, TCOFLUSH, TCIOFLUSH

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

tcgetattr (fd)
Get termios state.

Parameters:

  • fd int terminal descriptor

Returns:

    error message if failed

Or

    termios terminal attributes, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local termios, errmsg = tcgetattr (fd)
tcgetwinsize (fd)
Get terminal window size.

Parameters:

  • fd int terminal descriptor to act on

Returns:

    PosixWinsize winsize current winsize for fd, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local termio = require "posix.termio"
    local ws, errmsg, errnum = termio.tcgetwinsize(fd)
    if ws then
      print("rows=", ws.row, "cols=", ws.col, "xpixel=", ws.xpixel, "ypixel=", ws.ypixel)
    else
      print("Error: ", errmsg, errnum)
    end
tcsendbreak (fd, duration)
Send a stream of zero valued bits.

Parameters:

  • fd int terminal descriptor
  • duration int if non-zero, stream for some implementation defined time

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

tcsetattr (fd, actions, a)
Set termios state.

Parameters:

  • fd int terminal descriptor to act on
  • actions int bitwise OR of one or more of TCSANOW, TCSADRAIN, TCSAFLUSH and TSASOFT
  • a termios table with fields from iflag, oflag, cflag, lflag and cc, each formed by bor operations with various posix constants

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local termio = require "posix.termio"
    ok, errmsg = tcsetattr (fd, 0, { cc = { [termio.VTIME] = 0, [termio.VMIN] = 1 })
tcsetwinsize (fd, winsize)
Set terminal window size.

Parameters:

  • fd int terminal descriptor to act on
  • winsize PosixWinsize to apply to fd

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local termio = require "posix.termio"
    local ok, errmsg, errnum = termio.tcsetwinsize(fd, {row=24, col=80})
    if not ok then
      print("Error: ", errmsg, errnum)
    end

Tables

PosixWinsize
Winsize record. Any fields not available in the underlying system will be nil valued.

Fields:

  • ws_row int rows, in characters
  • ws_col int columns, in characters
  • ws_xpixel int width, in pixels
  • ws_ypixel int height, in pixels
ccs
Control characters. The field names below are not strings, but index constants each referring to a terminal control character.

Fields:

  • VINTR int interrupt control character
  • VQUIT int quit control character
  • WERASE int erase control character
  • VKILL int kill control character
  • VEOF int end-of-file control character
  • VEOL int end-of-line control charactor
  • VEOL2 int another end-of-line control charactor
  • VMIN int 1
  • VTIME int 0
  • VSTART int xon/xoff start control character
  • VSTOP int xon/xoff stop control character
  • VSUSP int suspend control character
termios
Terminal attributes. The constants named below are all available in this submodule's namespace, as long as they are supported by the underlying system.

Fields:

  • cc ccs array of terminal control characters
  • cflag int bitwise OR of zero or more of CSIZE, CS5, CS6, CS7, CS8, CSTOPB, CREAD, PARENB, PARODD, HUPCL, CLOCAL and CRTSCTS
  • iflag int input flags; bitwise OR of zero or more of IGNBRK, BRKINT, IGNPAR, PARMRK, INPCK, ISTRIP, INLCR, IGNCR, ICRNL, IXON, IXOFF, IXANY, and IMAXBEL
  • lflag int local flags; bitwise OR of zero or more of ISIG, ICANON, ECHO, ECHOE, ECHOK', 'ECHONL, NOFLSH, IEXTEN and TOSTOP
  • oflag int output flags; bitwise OR of zero or more of OPOST, ONLCR, OXTABS, ONOEOT, OCRNL, ONOCR, ONLRET, OFILL, NLDLY, TABDLY, CRDLY, FFDLY, BSDLY, VTDLY and OFDEL
  • ispeed int the input baud rate, one of B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200,
  • ospeed int the output baud rate (see ispeed for possible values)
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.time.html000066400000000000000000000504101475444374100205300ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.time

Time and Clock Functions.

Functions

clock_getres (clk) Find the precision of a clock.
clock_gettime (clk) Read a clock.
gmtime (t) Convert epoch time value to a broken-down UTC time.
localtime (t) Convert epoch time value to a broken-down local time.
mktime (broken) Convert a broken-down localtime table into an epoch time.
nanosleep (requested) Sleep with nanosecond precision.
strftime (format, tm) Return a time string according to format.
strptime (s, format) Parse a date string.
time () Get current time.

Tables

PosixTimespec Timespec record.
PosixTm Datetime record.

Constants

posix.time Standard constants.


Functions

clock_getres (clk)
Find the precision of a clock.

Parameters:

  • clk int name of clock, one of CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_MONOTONIC or CLOCK_THREAD_CPUTIME_ID

Returns:

    PosixTimespec resolution of clk, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

clock_gettime (clk)
Read a clock.

Parameters:

  • clk int name of clock, one of CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_MONOTONIC or CLOCK_THREAD_CPUTIME_ID

Returns:

    PosixTimespec current value of clk, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

gmtime (t)
Convert epoch time value to a broken-down UTC time.

Parameters:

  • t int seconds since epoch

Returns:

    PosixTm broken-down time, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

localtime (t)
Convert epoch time value to a broken-down local time.

Parameters:

  • t int seconds since epoch

Returns:

    PosixTm broken-down time, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

mktime (broken)
Convert a broken-down localtime table into an epoch time.

Parameters:

Returns:

    int seconds since epoch

See also:

nanosleep (requested)
Sleep with nanosecond precision.

Parameters:

Returns:

    int 0 if requested time has elapsed, if successful

Or

  1. nil
  2. string error message
  3. int errnum
  4. PosixTimespec unslept time remaining, if interrupted

See also:

strftime (format, tm)
Return a time string according to format. Note that if your host POSIX library provides a strftime that assumes the local timezone, %z will always print the local UTC offset, regardless of the tm_gmoffset field value passed in.

Parameters:

  • format string specifier with % place-holders
  • tm PosixTm broken-down local time

Returns:

    string format with place-holders plugged with tm values

See also:

strptime (s, format)
Parse a date string.

Parameters:

Returns:

  1. PosixTm broken-down local time
  2. int next index of first character not parsed as part of the date, if successful

Or

    nil

See also:

Usage:

    posix.strptime('20','%d').monthday == 20
time ()
Get current time.

Returns:

    int time in seconds since epoch, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Tables

PosixTimespec
Timespec record.

Fields:

  • tv_sec int seconds
  • tv_nsec int nanoseconds

See also:

PosixTm
Datetime record.

Fields:

  • tm_sec int second [0,60]
  • tm_min int minute [0,59]
  • tm_hour int hour [0,23]
  • tm_mday int day of month [1, 31]
  • tm_mon int month of year [0,11]
  • tm_year int years since 1900
  • tm_wday int day of week [0=Sunday,6]
  • tm_yday int day of year [0,365[
  • tm_isdst int 0 if daylight savings time is not in effect

Constants

posix.time
Standard constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • CLOCK_MONOTONIC int the identifier for the system-wide monotonic clock
  • CLOCK_PROCESS_CPUTIME_ID int the identifier for the current process CPU-time clock
  • CLOCK_REALTIME int the identifier for the system-wide realtime clock
  • CLOCK_THREAD_CPUTIME_ID int the identifier for the current thread CPU-time clock

Usage:

    -- Print posix.time constants supported on this host.
    for name, value in pairs (require "posix.time") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.unistd.html000066400000000000000000002115351475444374100211070ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.unistd

Unix Standard APIs.

Where the underlying system does not support one of these functions, it will have a nil value in the module table.

Functions

_exit (status) Terminate the calling process.
access (path[, mode="f"]) Check real user's permissions for a file.
alarm (seconds) Schedule an alarm signal.
chdir (path) Set the working directory.
chown (path, uid, gid) Change ownership of a file.
close (fd) Close an open file descriptor.
crypt (trypass, salt) Encrypt a password.
dup (fd) Duplicate an open file descriptor.
dup2 (fd, newfd) Duplicate one open file descriptor to another.
exec (path, argt) Execute a program at exactly path.
execp (path, argt) Execute a program found using command PATH search, like the shell.
fdatasync (fd) Synchronize a file's in-core state with storage device without metadata.
fork () Fork this program.
fsync (fd) Synchronize a file's in-core state with storage device.
ftruncate (fd, length) Truncate a file to a specified length.
getcwd () Current working directory for this process.
getegid () Return effective group id of calling process.
geteuid () Return effective user id of calling process.
getgid () Return group id of calling process.
getgroups () Get list of supplementary group ids.
gethostid () Get host id.
getopt (arg, opts[, opterr=0[, optind=1]]) Parse command-line options.
getpgrp () Return process group id of calling process.
getpid () Return process id of calling process.
getppid () Return parent process id of calling process.
getuid () Return user id of calling process.
isatty (fd) Test whether a file descriptor refers to a terminal.
lchown (path, uid, gid) This is like chown, but does not dereference symbolic links.
link (target, link[, soft=false]) Create a link.
linkat (targetdir, target, linkdir, link, flags) Create a link at specified directory.
lseek (fd, offset, whence) reposition read/write file offset
nice (inc) change process priority
pathconf (path, key) Get a value for a configuration option for a filename.
pipe () Creates a pipe.
read (fd, count) Read bytes from a file.
readlink (path) Read value of a symbolic link.
rmdir (path) Remove a directory.
setpid (what, id[, gid]) Set the uid, euid, gid, egid, sid or pid & gid.
sleep (seconds) Sleep for a number of seconds.
sync () Commit buffer cache to disk.
sysconf (key) Get configuration information at runtime.
tcgetpgrp (fd) Get id of foreground process group of terminal fd.
tcsetpgrp (fd, pgid) Make process group pgid the foreground process group of terminal fd.
truncate (path, length) Truncate a file to a specified length.
ttyname ([fd=0]) Name of a terminal device.
unlink (path) Unlink a file.
write (fd, buf[, nbytes=#buf[, offset=0]]) Write bytes to a file.

Constants

posix.unistd Standard constants.


Functions

_exit (status)
Terminate the calling process.

Parameters:

  • status int process exit status

See also:

access (path[, mode="f"])
Check real user's permissions for a file.

Parameters:

  • path string file to act on
  • mode string can contain 'r','w','x' and 'f' (default "f")

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    status, errstr, errno = unistd.access("/etc/passwd", "rw")
alarm (seconds)
Schedule an alarm signal.

Parameters:

  • seconds int number of seconds to send SIGALRM in

Returns:

    int number of seconds remaining in previous alarm or 0

See also:

Usage:

    local unistd = require "posix.unistd"
    seconds = unistd.alarm(10)
chdir (path)
Set the working directory.

Parameters:

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    status, errstr, errno = unistd.chdir ("/var/tmp")
chown (path, uid, gid)
Change ownership of a file.

Parameters:

  • path string existing file path
  • uid string or int new owner user id
  • gid string or int new owner group id

Returns:

    int 0, if successful

Or

  1. nil
  2. string error messoge
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    -- will fail for a normal user, and print an error
    print(unistd.chown ("/etc/passwd", 100, 200))
close (fd)
Close an open file descriptor.

Parameters:

  • fd int file descriptor to act on

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    local ok, errmsg = unistd.close (log)
    if not ok then error (errmsg) end
crypt (trypass, salt)
Encrypt a password. Not recommended for general encryption purposes.

Parameters:

  • trypass string string to hash
  • salt string two-character string from [a-zA-Z0-9./]

Returns:

    encrypted string

See also:

Usage:

    local pwd = require "posix.pwd"
    local unistd = require "posix.unistd"
    
    local salt, hash = pwd.pwent:match ":$6$(.-)$([^:]+)"
    if unistd.crypt (trypass, salt) ~= hash then
      error "wrong password"
    end
dup (fd)
Duplicate an open file descriptor.

Parameters:

  • fd int file descriptor to act on

Returns:

    int new file descriptor duplicating fd, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local stdio = require "posix.stdio"
    local unistd = require "posix.unistd"
    
    outfd = unistd.dup (stdio.fileno (io.stdout))
dup2 (fd, newfd)
Duplicate one open file descriptor to another. If newfd references an open file already, it is closed before being reallocated to fd.

Parameters:

  • fd int an open file descriptor to act on
  • newfd int new descriptor to duplicate fd

Returns:

    int new file descriptor, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

exec (path, argt)
Execute a program at exactly path.

Parameters:

  • path string
  • argt table arguments (table can include index 0)

Returns:

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    exec ("/bin/bash", {[0] = "-sh", "--norc"})
execp (path, argt)
Execute a program found using command PATH search, like the shell.

Parameters:

  • path string
  • argt table arguments (table can include index 0)

Returns:

  1. nil
  2. string error message
  3. int errnum

See also:

fdatasync (fd)
Synchronize a file's in-core state with storage device without metadata.

Parameters:

  • fd int

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

fork ()
Fork this program.

Returns:

    int 0 in the resulting child process

Or

    int process id of child, in the calling process

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    
    local pid, errmsg = unistd.fork ()
    if pid == nil then
      error (errmsg)
    elseif pid == 0 then
      print ("in child:", unistd.getpid "pid")
    else
      print (require "posix.sys.wait".wait (pid))
    end
    os.exit ()
fsync (fd)
Synchronize a file's in-core state with storage device.

Parameters:

  • fd int

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

ftruncate (fd, length)
Truncate a file to a specified length.

Parameters:

  • fd int the file descriptor to act on
  • length int the length to truncate to

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

getcwd ()
Current working directory for this process.

Returns:

    string path of current working directory, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

getegid ()
Return effective group id of calling process.

Returns:

    int effective group id of calling process

See also:

geteuid ()
Return effective user id of calling process.

Returns:

    int effective user id of calling process

See also:

getgid ()
Return group id of calling process.

Returns:

    int group id of calling process

See also:

getgroups ()
Get list of supplementary group ids.

Returns:

    table group id, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

gethostid ()
Get host id.

Returns:

    int host id, if successful

Or

  1. nil
  2. string error message

See also:

getopt (arg, opts[, opterr=0[, optind=1]])
Parse command-line options.

Parameters:

  • arg command line arguments
  • opts string short option specifier
  • opterr int index of the option with an error (default 0)
  • optind int index of the next unprocessed option (default 1)

Returns:

    option iterator, returning 3 values

See also:

Usage:

    local getopt = require "posix.getopt".getopt
    for opt, opterr, i in getopt (arg, "ho:v", opterr, i) do
      process (arg, opterr, i)
    end
getpgrp ()
Return process group id of calling process.

Returns:

    int process group id of calling process

See also:

getpid ()
Return process id of calling process.

Returns:

    int process id of calling process
getppid ()
Return parent process id of calling process.

Returns:

    int parent process id of calling process

See also:

getuid ()
Return user id of calling process.

Returns:

    int user id of calling process

See also:

isatty (fd)
Test whether a file descriptor refers to a terminal.

Parameters:

  • fd int file descriptor to act on

Returns:

    int 1 if fd is open and refers to a terminal, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

lchown (path, uid, gid)
This is like chown, but does not dereference symbolic links. In other words, if a file is a symlink, then it changes ownership of the symlink itself.

Parameters:

  • path string existing file path
  • uid string or int new owner user id
  • gid string or int new owner group id

Returns:

    int 0, if successful

Or

  1. nil
  2. string error messoge
  3. int errnum

See also:

Usage:

    local unistd = require "posix.unistd"
    -- will fail for a normal user, and print an error
    print(unistd.lchown ("/etc/passwd", 100, 200))
link (target, link[, soft=false])
Create a link.

Parameters:

  • target string name
  • link string name
  • soft bool link (default false)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

linkat (targetdir, target, linkdir, link, flags)
Create a link at specified directory.

Parameters:

  • targetdir int fd
  • target string name
  • linkdir int fd
  • link string name
  • flags int

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

lseek (fd, offset, whence)
reposition read/write file offset

Parameters:

  • fd int open file descriptor to act on
  • offset int bytes to seek
  • whence int one of SEEK_SET, SEEK_CUR or SEEK_END

Returns:

    int new offset, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

nice (inc)
change process priority

Parameters:

  • inc int adds inc to the nice value for the calling process

Returns:

    int new nice value, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

pathconf (path, key)
Get a value for a configuration option for a filename.

Parameters:

  • path string optional
  • key int one of _PC_LINK_MAX, _PC_MAX_CANON, _PC_NAME_MAX, _PC_PIPE_BUF, _PC_CHOWN_RESTRICTED, _PC_NO_TRUNC or _PC_VDISABLE

Returns:

    int associated path configuration value

See also:

Usage:

    local unistd = require "posix.unistd"
    for a, b in pairs (unistd.pathconf "/dev/tty") do print(a, b) end
pipe ()
Creates a pipe.

Returns:

  1. int read end file descriptor
  2. int write end file descriptor, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

read (fd, count)
Read bytes from a file.

Parameters:

  • fd int the file descriptor to act on
  • count int maximum number of bytes to read

Returns:

    string string from fd with at most count bytes, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

readlink (path)
Read value of a symbolic link.

Parameters:

Returns:

    string link target, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

rmdir (path)
Remove a directory.

Parameters:

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

setpid (what, id[, gid])
Set the uid, euid, gid, egid, sid or pid & gid.

Parameters:

  • what string one of 'u', 'U', 'g', 'G', 's', 'p' (upper-case means "effective")
  • id int (uid, gid or pid for every value of what except 's')
  • gid int (only for what value 'p') (optional)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

sleep (seconds)
Sleep for a number of seconds.

Parameters:

  • seconds int minimum numebr of seconds to sleep

Returns:

    int 0 if the requested time has elapsed

Or

    int unslept seconds remaining, if interrupted

See also:

sync ()
Commit buffer cache to disk.

See also:

sysconf (key)
Get configuration information at runtime.

Parameters:

  • key int one of _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_JOB_CONTROL, _SC_OPEN_MAX, _SC_NGROUPS_MAX, _SC_SAVED_IDS, _SC_STREAM_MAX, _SC_PAGESIZE, _SC_TZNAME_MAX or _SC_VERSION,

Returns:

    int associated system configuration value

See also:

tcgetpgrp (fd)
Get id of foreground process group of terminal fd.

Parameters:

  • fd int the file descriptor of the controlling terminal of the current process

Returns:

    int id of foreground process group, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

tcsetpgrp (fd, pgid)
Make process group pgid the foreground process group of terminal fd.

Parameters:

  • fd int the file descriptor of the controlling terminal of the current process
  • pgid int id of the process group to make foreground process group

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

truncate (path, length)
Truncate a file to a specified length.

Parameters:

  • path string file to act on
  • length int the length to truncate to

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

ttyname ([fd=0])
Name of a terminal device.

Parameters:

  • fd int file descriptor to process (default 0)

Returns:

    string name, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

unlink (path)
Unlink a file.

Parameters:

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

write (fd, buf[, nbytes=#buf[, offset=0]])
Write bytes to a file. If nbytes is nil or omitted, write all bytes from offset through to the end of buf. If offset is nil or omitted, start writing bytes from the beginning of buf. Bounds checks are enforced, returning posix.errno.EINVAL before attempting to write any bytes, if the requested parameters would access bytes outside buf.

Parameters:

  • fd int the file descriptor to act on
  • buf string containing bytes to write
  • nbytes int number of bytes to write (default #buf)
  • offset int skip the first offset bytes of buf (default 0)

Returns:

    int number of bytes written, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

Constants

posix.unistd
Standard constants. Any constants not available in the underlying system will be nil valued.

Fields:

  • _PC_CHOWN_RESTRICTED int return 1 if chown requires appropriate privileges, 0 otherwise
  • _PC_LINK_MAX int maximum file link count
  • _PC_MAX_CANON int maximum bytes in terminal canonical input line
  • _PC_MAX_INPUT int maximum number of bytes in a terminal input queue
  • _PC_NAME_MAX int maximum number of bytes in a file name
  • _PC_NO_TRUNC int return 1 if over-long file names are truncated
  • _PC_PATH_MAXmaximum int number of bytes in a pathname
  • _PC_PIPE_BUF int maximum number of bytes in an atomic pipe write
  • _PC_VDISABLE int terminal character disabling value
  • _SC_ARG_MAX int maximum bytes of argument to posix.unistd.execp
  • _SC_CHILD_MAX int maximum number of processes per user
  • _SC_CLK_TCK int statistics clock frequency
  • _SC_JOB_CONTROL int return 1 if system has job control, -1 otherwise
  • _SC_NGROUPS_MAX int maximum number of supplemental groups
  • _SC_OPEN_MAX int maximum number of open files per user
  • _SC_SAVED_IDS int return 1 if system supports saved user and group ids, -1 otherwise
  • _SC_STREAM_MAX int maximum number of streams per process
  • _SC_TZNAME_MAX int maximum number of timezone types
  • _SC_VERSION int POSIX.1 compliance version
  • SEEK_CUR int relative file pointer position
  • SEEK_END int set file pointer to the end of file
  • SEEK_SET int absolute file pointer position
  • STDERR_FILENO int standard error file descriptor
  • STDIN_FILENO int standard input file descriptor
  • STDOUT_FILENO int standard output file descriptor

Usage:

    -- Print unistd constants supported on this host.
    for name, value in pairs (require "posix.unistd") do
      if type (value) == "number" then
        print (name, value)
       end
    end
generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/doc/modules/posix.utime.html000066400000000000000000000141011475444374100207120ustar00rootroot00000000000000 luaposix 36.3 Reference

Module posix.utime

Set File Times.

Functions

utime (path[, mtime=now[, atime=now]]) Change file last access and modification times.


Functions

utime (path[, mtime=now[, atime=now]])
Change file last access and modification times.

Parameters:

  • path string existing file path
  • mtime int modification time (default now)
  • atime int access time (default now)

Returns:

    int 0, if successful

Or

  1. nil
  2. string error message
  3. int errnum

See also:

generated by LDoc 1.5.0 Last updated 2025-02-16 13:16:41
luaposix-36.3/ext/000077500000000000000000000000001475444374100141265ustar00rootroot00000000000000luaposix-36.3/ext/include/000077500000000000000000000000001475444374100155515ustar00rootroot00000000000000luaposix-36.3/ext/include/_helpers.c000066400000000000000000000257011475444374100175230ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ #ifndef LUAPOSIX__HELPERS_C #define LUAPOSIX__HELPERS_C 1 /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # define _GNU_SOURCE 1 #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS 1 #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # define _TANDEM_SOURCE 1 #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # define __EXTENSIONS__ 1 #endif #include #include #include #include #include /* for _POSIX_VERSION */ #if !defined PATH_MAX # define PATH_MAX 1024 #endif /* Some systems set _POSIX_C_SOURCE over _POSIX_VERSION! */ #if _POSIX_C_SOURCE >= 200112L || _POSIX_VERSION >= 200112L || _XOPEN_SOURCE >= 600 # define LPOSIX_2001_COMPLIANT 1 #endif #if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700 # define LPOSIX_2008_COMPLIANT 1 # ifndef LPOSIX_2001_COMPLIANT # define LPOSIX_2001_COMPLIANT # endif #endif #include "lua.h" #include "lualib.h" #include "lauxlib.h" #if LUA_VERSION_NUM < 503 # define lua_isinteger lua_isnumber # if LUA_VERSION_NUM == 501 # include "compat-5.2.c" # endif #endif #if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 || LUA_VERSION_NUM == 504 # define lua_objlen lua_rawlen # define lua_strlen lua_rawlen #endif #define _LPOSIX_VERSION_STRING(m) \ ("posix." m " for " LUA_VERSION " / " PACKAGE " " VERSION) #define LPOSIX_VERSION_STRING(m) _LPOSIX_VERSION_STRING(m) #ifndef STREQ # define STREQ(a, b) (strcmp (a, b) == 0) #endif /* Mark unused parameters required only to match a function type specification. */ #ifdef __GNUC__ # define LPOSIX_UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) #else # define LPOSIX_UNUSED(x) UNUSED_ ## x #endif /* LPOSIX_STMT_BEG/END are used to create macros that expand to a single compound statement in a portable way. */ #if defined __GNUC__ && !defined __STRICT_ANSI__ && !defined __cplusplus # define LPOSIX_STMT_BEG (void)( # define LPOSIX_STMT_END ) #else # if (defined sun || defined __sun__) # define LPOSIX_STMT_BEG if (1) # define LPOSIX_STMT_END else (void)0 # else # define LPOSIX_STMT_BEG do # define LPOSIX_STMT_END while (0) # endif #endif /* The extra indirection to these macros is required so that if the arguments are themselves macros, they will get expanded too. */ #define LPOSIX__SPLICE(_s, _t) _s##_t #define LPOSIX_SPLICE(_s, _t) LPOSIX__SPLICE(_s, _t) #define LPOSIX__STR(_s) #_s #define LPOSIX_STR(_s) LPOSIX__STR(_s) /* The +1 is to step over the leading '_' that is required to prevent premature expansion of MENTRY arguments if we didn't add it. */ #define LPOSIX__STR_1(_s) (#_s + 1) #define LPOSIX_STR_1(_s) LPOSIX__STR_1(_s) #define LPOSIX_CONST(_f) LPOSIX_STMT_BEG { \ lua_pushinteger(L, _f); \ lua_setfield(L, -2, #_f); \ } LPOSIX_STMT_END #define LPOSIX_FUNC(_s) {LPOSIX_STR_1(_s), (_s)} #define pushokresult(b) pushboolresult((int) (b) == OK) #ifndef errno extern int errno; #endif /* ========================= * * Bad argument diagnostics. * * ========================= */ static int argtypeerror(lua_State *L, int narg, const char *expected) { const char *got = luaL_typename(L, narg); return luaL_argerror(L, narg, lua_pushfstring(L, "%s expected, got %s", expected, got)); } static void checktype(lua_State *L, int narg, int t, const char *expected) { if (lua_type(L, narg) != t) argtypeerror (L, narg, expected); } static lua_Integer expectinteger(lua_State *L, int narg, const char *expected) { int isconverted = 0; lua_Integer d = lua_tointegerx(L, narg, &isconverted); if (!isconverted) argtypeerror(L, narg, expected); return d; } /* As soon as specl's badargs.diagnose can handle it... change these to "integer"! */ #define checkinteger(L,n) (expectinteger(L,n,"integer")) #define checkint(L,n) ((int)expectinteger(L,n,"integer")) #define checklong(L,n) ((long)expectinteger(L,n,"integer")) static int optboolean(lua_State *L, int narg, int def) { if (lua_isnoneornil(L, narg)) return def; checktype (L, narg, LUA_TBOOLEAN, "boolean or nil"); return (int)lua_toboolean(L, narg); } static lua_Integer expectoptinteger(lua_State *L, int narg, lua_Integer def, const char *expected) { if (lua_isnoneornil(L, narg)) return def; return expectinteger(L, narg, expected); } /* As soon as specl's badargs.diagnose can handle it... change these to "integer or nil"! */ #define optinteger(L,n,d) (expectoptinteger(L,n,d,"integer or nil")) #define optint(L,n,d) ((int)expectoptinteger(L,n,d,"integer or nil")) #define optlong(L,n,d) ((long)expectoptinteger(L,n,d,"integer or nil")) static const char * optstring(lua_State *L, int narg, const char *def) { const char *s; if (lua_isnoneornil(L, narg)) return def; s = lua_tolstring(L, narg, NULL); if (!s) argtypeerror(L, narg, "nil or string"); return s; } static void checknargs(lua_State *L, int maxargs) { int nargs = lua_gettop(L); lua_pushfstring(L, "no more than %d argument%s expected, got %d", maxargs, maxargs == 1 ? "" : "s", nargs); luaL_argcheck(L, nargs <= maxargs, maxargs + 1, lua_tostring (L, -1)); lua_pop(L, 1); } /* Try a lua_getfield from the table on the given index. On success the field * is pushed and 0 is returned, on failure nil and an error message is pushed and 2 * is returned */ static void checkfieldtype(lua_State *L, int index, const char *k, int expect_type, const char *expected) { int got_type; lua_getfield(L, index, k); got_type = lua_type(L, -1); if (expected == NULL) expected = lua_typename(L, expect_type); lua_pushfstring(L, "%s expected for field '%s', got %s", expected, k, got_type == LUA_TNIL ? "no value" : lua_typename(L, got_type)); luaL_argcheck(L, got_type == expect_type, index, lua_tostring(L, -1)); lua_pop(L, 1); } #define NEXT_IKEY -2 #define NEXT_IVALUE -1 static void checkismember(lua_State *L, int index, int n, const char *const S[]) { /* Diagnose non-string type field names. */ int got_type = lua_type(L, NEXT_IKEY); luaL_argcheck(L, lua_isstring(L, NEXT_IKEY), index, lua_pushfstring(L, "invalid %s field name", lua_typename(L, got_type))); /* Check field name is listed in S. */ { const char *k = lua_tostring(L, NEXT_IKEY); int i; for (i = 0; i < n; ++i) if (STREQ(S[i], k)) return; } /* Diagnose invalid field name. */ luaL_argcheck(L, 0, index, lua_pushfstring(L, "invalid field name '%s'", lua_tostring(L, NEXT_IKEY))); } #undef NEXT_IKEY #undef NEXT_IVALUE static void checkfieldnames(lua_State *L, int index, int n, const char * const S[]) { for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) checkismember(L, index, n, S); } #define checkfieldnames(L,i,S) (checkfieldnames)(L,i,sizeof(S)/sizeof(*S),S) static lua_Integer checkintegerfield(lua_State *L, int index, const char *k) { lua_Integer r; checkfieldtype(L, index, k, LUA_TNUMBER, "integer"); r = lua_tointeger(L, -1); lua_pop(L, 1); return r; } #define checkintfield(L,i,k) ((int)checkintegerfield(L,i,k)) #define checklongfield(L,i,k) ((long)checkintegerfield(L,i,k)) static int checknumberfield(lua_State *L, int index, const char *k) { int r; checkfieldtype(L, index, k, LUA_TNUMBER, "number"); r = lua_tonumber(L, -1); lua_pop(L, 1); return r; } static const char * checklstringfield(lua_State *L, int index, const char *k, size_t *plen) { const char *r; checkfieldtype(L, index, k, LUA_TSTRING, NULL); r = lua_tolstring(L, -1, plen); lua_pop(L, 1); return r; /* XXX UNSAFE! */ } #define checkstringfield(L,i,s) (checklstringfield(L,i,s,NULL)) static lua_Integer optintegerfield(lua_State *L, int index, const char *k, int def) { int got_type; lua_getfield(L, index, k); got_type = lua_type(L, -1); lua_pop(L, 1); if (got_type == LUA_TNONE || got_type == LUA_TNIL) return def; return checkintegerfield(L, index, k); } #define optintfield(L,i,k,d) ((int)optintegerfield(L,i,k,d)) #define optlongfield(L,i,k,d) ((long)optintegerfield(L,i,k,d)) static const char * optstringfield(lua_State *L, int index, const char *k, const char *def) { int got_type; lua_getfield(L, index, k); got_type = lua_type(L, -1); lua_pop(L, 1); if (got_type == LUA_TNONE || got_type == LUA_TNIL) return def; return checkstringfield(L, index, k); } static int pusherror(lua_State *L, const char *info) { lua_pushnil(L); if (info==NULL) lua_pushstring(L, strerror(errno)); else lua_pushfstring(L, "%s: %s", info, strerror(errno)); lua_pushinteger(L, errno); return 3; } #define pushboolresult(b) (lua_pushboolean(L, (b)), 1) #define pushintegerresult(n) (lua_pushinteger(L, (n)), 1) #define pushstringresult(s) (lua_pushstring(L, (s)), 1) static int pushresult(lua_State *L, int i, const char *info) { if (i==-1) return pusherror(L, info); return pushintegerresult(i); } static void badoption(lua_State *L, int i, const char *what, int option) { luaL_argerror(L, i, lua_pushfstring(L, "invalid %s option '%c'", what, option)); } /* ================== * * Utility functions. * * ================== */ static int binding_notimplemented(lua_State *L, const char *fname, const char *libname) { lua_pushnil(L); lua_pushfstring(L, "'%s' is not implemented by host %s library", fname, libname); return 2; } #define pushintegerfield(k,v) LPOSIX_STMT_BEG { \ lua_pushinteger(L, (lua_Integer) v); lua_setfield(L, -2, k); \ } LPOSIX_STMT_END #define pushnumberfield(k,v) LPOSIX_STMT_BEG { \ lua_pushnumber(L, (lua_Number) v); lua_setfield(L, -2, k); \ } LPOSIX_STMT_END #define pushstringfield(k,v) LPOSIX_STMT_BEG { \ if (v) { \ lua_pushstring(L, (const char *) v); \ lua_setfield(L, -2, k); \ } \ } LPOSIX_STMT_END #define pushlstringfield(k,v,l) LPOSIX_STMT_BEG { \ if (l > 0 && v) { \ lua_pushlstring(L, (const char *) v, (size_t) l); \ lua_setfield(L, -2, k); \ } \ } LPOSIX_STMT_END #define pushliteralfield(k,v) LPOSIX_STMT_BEG { \ if (v) { \ lua_pushliteral(L, v); \ lua_setfield(L, -2, k); \ } \ } LPOSIX_STMT_END #define settypemetatable(t) LPOSIX_STMT_BEG { \ if (luaL_newmetatable(L, t) == 1) \ pushliteralfield("_type", t); \ lua_setmetatable(L, -2); \ } LPOSIX_STMT_END #define setintegerfield(_p, _n) pushintegerfield(LPOSIX_STR(_n), _p->_n) #define setnumberfield(_p, _n) pushnumberfield(LPOSIX_STR(_n), _p->_n) #define setstringfield(_p, _n) pushstringfield(LPOSIX_STR(_n), _p->_n) #endif /*LUAPOSIX__HELPERS_C*/ luaposix-36.3/ext/include/compat-5.2.c000066400000000000000000000466131475444374100175140ustar00rootroot00000000000000#include #include #include "lua.h" #include "lauxlib.h" #include "compat-5.2.h" #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 int lua_absindex (lua_State *L, int i) { if (i < 0 && i > LUA_REGISTRYINDEX) i += lua_gettop(L) + 1; return i; } void lua_rawgetp (lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); lua_pushlightuserdata(L, (void*)p); lua_rawget(L, abs_i); } void lua_rawsetp (lua_State *L, int i, const void *p) { int abs_i = lua_absindex(L, i); luaL_checkstack(L, 1, "not enough stack slots"); lua_pushlightuserdata(L, (void*)p); lua_insert(L, -2); lua_rawset(L, abs_i); } #if !defined(COMPAT52_IS_LUAJIT) void lua_copy (lua_State *L, int from, int to) { int abs_to = lua_absindex(L, to); luaL_checkstack(L, 1, "not enough stack slots"); lua_pushvalue(L, from); lua_replace(L, abs_to); } void *luaL_testudata (lua_State *L, int i, const char *tname) { void *p = lua_touserdata(L, i); luaL_checkstack(L, 2, "not enough stack slots"); if (p == NULL || !lua_getmetatable(L, i)) return NULL; else { int res = 0; luaL_getmetatable(L, tname); res = lua_rawequal(L, -1, -2); lua_pop(L, 2); if (!res) p = NULL; } return p; } lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { lua_Number n = lua_tonumber(L, i); if (isnum != NULL) { *isnum = (n != 0 || lua_isnumber(L, i)); } return n; } #endif #define PACKAGE_KEY "_COMPAT52_PACKAGE" static void push_package_table (lua_State *L) { lua_pushliteral(L, PACKAGE_KEY); lua_rawget(L, LUA_REGISTRYINDEX); if (!lua_istable(L, -1)) { lua_pop(L, 1); /* try to get package table from globals */ lua_pushliteral(L, "package"); lua_rawget(L, LUA_GLOBALSINDEX); if (lua_istable(L, -1)) { lua_pushliteral(L, PACKAGE_KEY); lua_pushvalue(L, -2); lua_rawset(L, LUA_REGISTRYINDEX); } } } void lua_getuservalue (lua_State *L, int i) { luaL_checktype(L, i, LUA_TUSERDATA); luaL_checkstack(L, 2, "not enough stack slots"); lua_getfenv(L, i); lua_pushvalue(L, LUA_GLOBALSINDEX); if (lua_rawequal(L, -1, -2)) { lua_pop(L, 1); lua_pushnil(L); lua_replace(L, -2); } else { lua_pop(L, 1); push_package_table(L); if (lua_rawequal(L, -1, -2)) { lua_pop(L, 1); lua_pushnil(L); lua_replace(L, -2); } else lua_pop(L, 1); } } void lua_setuservalue (lua_State *L, int i) { luaL_checktype(L, i, LUA_TUSERDATA); if (lua_isnil(L, -1)) { luaL_checkstack(L, 1, "not enough stack slots"); lua_pushvalue(L, LUA_GLOBALSINDEX); lua_replace(L, -2); } lua_setfenv(L, i); } /* ** Adapted from Lua 5.2.0 */ #if !defined(COMPAT52_IS_LUAJIT) void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { luaL_checkstack(L, nup+1, "too many upvalues"); for (; l->name != NULL; l++) { /* fill the table with given functions */ int i; lua_pushstring(L, l->name); for (i = 0; i < nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -(nup + 1)); lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ } lua_pop(L, nup); /* remove upvalues */ } void luaL_setmetatable (lua_State *L, const char *tname) { luaL_checkstack(L, 1, "not enough stack slots"); luaL_getmetatable(L, tname); lua_setmetatable(L, -2); } #endif int luaL_getsubtable (lua_State *L, int i, const char *name) { int abs_i = lua_absindex(L, i); luaL_checkstack(L, 3, "not enough stack slots"); lua_pushstring(L, name); lua_gettable(L, abs_i); if (lua_istable(L, -1)) return 1; lua_pop(L, 1); lua_newtable(L); lua_pushstring(L, name); lua_pushvalue(L, -2); lua_settable(L, abs_i); return 0; } #if !defined(COMPAT52_IS_LUAJIT) static int countlevels (lua_State *L) { lua_Debug ar; int li = 1, le = 1; /* find an upper bound */ while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } /* do a binary search */ while (li < le) { int m = (li + le)/2; if (lua_getstack(L, m, &ar)) li = m + 1; else le = m; } return le - 1; } static int findfield (lua_State *L, int objidx, int level) { if (level == 0 || !lua_istable(L, -1)) return 0; /* not found */ lua_pushnil(L); /* start 'next' loop */ while (lua_next(L, -2)) { /* for each pair in table */ if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ if (lua_rawequal(L, objidx, -1)) { /* found object? */ lua_pop(L, 1); /* remove value (but keep name) */ return 1; } else if (findfield(L, objidx, level - 1)) { /* try recursively */ lua_remove(L, -2); /* remove table (but keep name) */ lua_pushliteral(L, "."); lua_insert(L, -2); /* place '.' between the two names */ lua_concat(L, 3); return 1; } } lua_pop(L, 1); /* remove value */ } return 0; /* not found */ } static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { int top = lua_gettop(L); lua_getinfo(L, "f", ar); /* push function */ lua_pushvalue(L, LUA_GLOBALSINDEX); if (findfield(L, top + 1, 2)) { lua_copy(L, -1, top + 1); /* move name to proper place */ lua_pop(L, 2); /* remove pushed values */ return 1; } else { lua_settop(L, top); /* remove function and global table */ return 0; } } static void pushfuncname (lua_State *L, lua_Debug *ar) { if (*ar->namewhat != '\0') /* is there a name? */ lua_pushfstring(L, "function " LUA_QS, ar->name); else if (*ar->what == 'm') /* main? */ lua_pushliteral(L, "main chunk"); else if (*ar->what == 'C') { if (pushglobalfuncname(L, ar)) { lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); lua_remove(L, -2); /* remove name */ } else lua_pushliteral(L, "?"); } else lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); } #define LEVELS1 12 /* size of the first part of the stack */ #define LEVELS2 10 /* size of the second part of the stack */ void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level) { lua_Debug ar; int top = lua_gettop(L); int numlevels = countlevels(L1); int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; if (msg) lua_pushfstring(L, "%s\n", msg); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L1, level++, &ar)) { if (level == mark) { /* too many levels? */ lua_pushliteral(L, "\n\t..."); /* add a '...' */ level = numlevels - LEVELS2; /* and skip to last ones */ } else { lua_getinfo(L1, "Slnt", &ar); lua_pushfstring(L, "\n\t%s:", ar.short_src); if (ar.currentline > 0) lua_pushfstring(L, "%d:", ar.currentline); lua_pushliteral(L, " in "); pushfuncname(L, &ar); lua_concat(L, lua_gettop(L) - top); } } lua_concat(L, lua_gettop(L) - top); } #endif void luaL_checkversion (lua_State *L) { (void)L; } #if !defined(COMPAT52_IS_LUAJIT) int luaL_fileresult (lua_State *L, int stat, const char *fname) { int en = errno; /* calls to Lua API may change this value */ if (stat) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); if (fname) lua_pushfstring(L, "%s: %s", fname, strerror(en)); else lua_pushstring(L, strerror(en)); lua_pushnumber(L, (lua_Number)en); return 3; } } #endif #endif /* Lua 5.0 or Lua 5.1 */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 #include typedef LUAI_INT32 LUA_INT32; /********************************************************************/ /* extract of 5.2's luaconf.h */ /* detects proper defines for faster unsigned<->number conversion */ /* see copyright notice at the end of this file */ /********************************************************************/ #if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) #define LUA_WIN /* enable goodies for regular Windows platforms */ #endif #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ /* Microsoft compiler on a Pentium (32 bit) ? */ #if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ #define LUA_MSASMTRICK #define LUA_IEEEENDIAN 0 #define LUA_NANTRICK /* pentium 32 bits? */ #elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ #define LUA_IEEE754TRICK #define LUA_IEEELL #define LUA_IEEEENDIAN 0 #define LUA_NANTRICK /* pentium 64 bits? */ #elif defined(__x86_64) /* }{ */ #define LUA_IEEE754TRICK #define LUA_IEEEENDIAN 0 #elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ #define LUA_IEEE754TRICK #define LUA_IEEEENDIAN 1 #else /* }{ */ /* assume IEEE754 and a 32-bit integer type */ #define LUA_IEEE754TRICK #endif /* } */ #endif /* } */ /********************************************************************/ /* extract of 5.2's llimits.h */ /* gives us lua_number2unsigned and lua_unsigned2number */ /* see copyright notice at the end of this file */ /********************************************************************/ #if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ /* trick with Microsoft assembler for X86 */ #define lua_number2unsigned(i,n) \ {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} #elif defined(LUA_IEEE754TRICK) /* }{ */ /* the next trick should work on any machine using IEEE754 with a 32-bit int type */ union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; #if !defined(LUA_IEEEENDIAN) /* { */ #define LUAI_EXTRAIEEE \ static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; #define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) #else #define LUA_IEEEENDIANLOC LUA_IEEEENDIAN #define LUAI_EXTRAIEEE /* empty */ #endif /* } */ #define lua_number2int32(i,n,t) \ { LUAI_EXTRAIEEE \ volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } #define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) #endif /* } */ /* the following definitions always work, but may be slow */ #if !defined(lua_number2unsigned) /* { */ /* the following definition assures proper modulo behavior */ #if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) #include #define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) #define lua_number2unsigned(i,n) \ ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) #else #define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) #endif #endif /* } */ #if !defined(lua_unsigned2number) /* on several machines, coercion from unsigned to double is slow, so it may be worth to avoid */ #define lua_unsigned2number(u) \ (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) #endif /********************************************************************/ static void compat52_call_lua (lua_State *L, char const code[], size_t len, int nargs, int nret) { lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); if (lua_type(L, -1) != LUA_TFUNCTION) { lua_pop(L, 1); if (luaL_loadbuffer(L, code, len, "=none")) lua_error(L); lua_pushvalue(L, -1); lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); } lua_insert(L, -nargs-1); lua_call(L, nargs, nret); } static const char compat52_arith_code[] = { 'l', 'o', 'c', 'a', 'l', ' ', 'o', 'p', ',', 'a', ',', 'b', '=', '.', '.', '.', '\n', 'i', 'f', ' ', 'o', 'p', '=', '=', '0', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '+', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '1', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '-', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '2', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '*', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '3', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '/', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '4', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '%', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '5', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '^', 'b', '\n', 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '6', ' ', 't', 'h', 'e', 'n', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', '-', 'a', '\n', 'e', 'n', 'd', '\n', '\0' }; void lua_arith (lua_State *L, int op) { if (op < LUA_OPADD && op > LUA_OPUNM) luaL_error(L, "invalid 'op' argument for lua_arith"); luaL_checkstack(L, 5, "not enough stack slots"); if (op == LUA_OPUNM) lua_pushvalue(L, -1); lua_pushnumber(L, op); lua_insert(L, -3); compat52_call_lua(L, compat52_arith_code, sizeof(compat52_arith_code)-1, 3, 1); } static const char compat52_compare_code[] = { 'l', 'o', 'c', 'a', 'l', ' ', 'a', ',', 'b', '=', '.', '.', '.', '\n', 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '<', '=', 'b', '\n', '\0' }; int lua_compare (lua_State *L, int idx1, int idx2, int op) { int result = 0; switch (op) { case LUA_OPEQ: return lua_equal(L, idx1, idx2); case LUA_OPLT: return lua_lessthan(L, idx1, idx2); case LUA_OPLE: luaL_checkstack(L, 5, "not enough stack slots"); idx1 = lua_absindex(L, idx1); idx2 = lua_absindex(L, idx2); lua_pushvalue(L, idx1); lua_pushvalue(L, idx2); compat52_call_lua(L, (void*)compat52_compare_code, sizeof(compat52_compare_code)-1, 2, 1); result = lua_toboolean(L, -1); lua_pop(L, 1); return result; default: luaL_error(L, "invalid 'op' argument for lua_compare"); } return 0; } void lua_pushunsigned (lua_State *L, lua_Unsigned n) { lua_pushnumber(L, lua_unsigned2number(n)); } lua_Unsigned luaL_checkunsigned (lua_State *L, int i) { lua_Unsigned result; lua_Number n = lua_tonumber(L, i); if (n == 0 && !lua_isnumber(L, i)) luaL_checktype(L, i, LUA_TNUMBER); lua_number2unsigned(result, n); return result; } lua_Unsigned lua_tounsignedx (lua_State *L, int i, int *isnum) { lua_Unsigned result; lua_Number n = lua_tonumberx(L, i, isnum); lua_number2unsigned(result, n); return result; } lua_Unsigned luaL_optunsigned (lua_State *L, int i, lua_Unsigned def) { return luaL_opt(L, luaL_checkunsigned, i, def); } #if !defined(COMPAT52_IS_LUAJIT) lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { lua_Integer n = lua_tointeger(L, i); if (isnum != NULL) { *isnum = (n != 0 || lua_isnumber(L, i)); } return n; } #endif void lua_len (lua_State *L, int i) { switch (lua_type(L, i)) { case LUA_TSTRING: /* fall through */ case LUA_TTABLE: if (!luaL_callmeta(L, i, "__len")) lua_pushnumber(L, (int)lua_objlen(L, i)); break; case LUA_TUSERDATA: if (luaL_callmeta(L, i, "__len")) break; /* maybe fall through */ default: luaL_error(L, "attempt to get length of a %s value", lua_typename(L, lua_type(L, i))); } } int luaL_len (lua_State *L, int i) { int res = 0, isnum = 0; luaL_checkstack(L, 1, "not enough stack slots"); lua_len(L, i); res = (int)lua_tointegerx(L, -1, &isnum); lua_pop(L, 1); if (!isnum) luaL_error(L, "object length is not a number"); return res; } const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { if (!luaL_callmeta(L, idx, "__tostring")) { int t = lua_type(L, idx); switch (t) { case LUA_TNIL: lua_pushliteral(L, "nil"); break; case LUA_TSTRING: case LUA_TNUMBER: lua_pushvalue(L, idx); break; case LUA_TBOOLEAN: if (lua_toboolean(L, idx)) lua_pushliteral(L, "true"); else lua_pushliteral(L, "false"); break; default: lua_pushfstring(L, "%s: %p", lua_typename(L, t), lua_topointer(L, idx)); break; } } return lua_tolstring(L, -1, len); } #if !defined(COMPAT52_IS_LUAJIT) void luaL_requiref (lua_State *L, char const* modname, lua_CFunction openf, int glb) { luaL_checkstack(L, 3, "not enough stack slots"); lua_pushcfunction(L, openf); lua_pushstring(L, modname); lua_call(L, 1, 1); lua_getglobal(L, "package"); lua_getfield(L, -1, "loaded"); lua_replace(L, -2); lua_pushvalue(L, -2); lua_setfield(L, -2, modname); lua_pop(L, 1); if (glb) { lua_pushvalue(L, -1); lua_setglobal(L, modname); } } #endif void luaL_buffinit (lua_State *L, luaL_Buffer_52 *B) { /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ B->b.p = NULL; B->b.L = NULL; B->b.lvl = 0; /* reuse the buffer from the 5.1-style luaL_Buffer though! */ B->ptr = B->b.buffer; B->capacity = LUAL_BUFFERSIZE; B->nelems = 0; B->L2 = L; } char *luaL_prepbuffsize (luaL_Buffer_52 *B, size_t s) { if (B->capacity - B->nelems < s) { /* needs to grow */ char* newptr = NULL; size_t newcap = B->capacity * 2; if (newcap - B->nelems < s) newcap = B->nelems + s; if (newcap < B->capacity) /* overflow */ luaL_error(B->L2, "buffer too large"); newptr = lua_newuserdata(B->L2, newcap); memcpy(newptr, B->ptr, B->nelems); if (B->ptr != B->b.buffer) lua_replace(B->L2, -2); /* remove old buffer */ B->ptr = newptr; B->capacity = newcap; } return B->ptr+B->nelems; } void luaL_addlstring (luaL_Buffer_52 *B, const char *s, size_t l) { memcpy(luaL_prepbuffsize(B, l), s, l); luaL_addsize(B, l); } void luaL_addvalue (luaL_Buffer_52 *B) { size_t len = 0; const char *s = lua_tolstring(B->L2, -1, &len); if (!s) luaL_error(B->L2, "cannot convert value to string"); if (B->ptr != B->b.buffer) lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ luaL_addlstring(B, s, len); lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); } void luaL_pushresult (luaL_Buffer_52 *B) { lua_pushlstring(B->L2, B->ptr, B->nelems); if (B->ptr != B->b.buffer) lua_replace(B->L2, -2); /* remove userdata buffer */ } #endif /* LUA_VERSION_NUM == 501 */ /********************************************************************* * This file contains parts of Lua 5.2's source code: * * Copyright (C) 1994-2013 Lua.org, PUC-Rio. * * 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. *********************************************************************/ luaposix-36.3/ext/include/compat-5.2.h000066400000000000000000000112601475444374100175070ustar00rootroot00000000000000#include #include #include #include "lua.h" #include "lauxlib.h" #include "lualib.h" #if !defined(LUA_VERSION_NUM) /* Lua 5.0 */ #define LUA_QL(x) "'" x "'" #define LUA_QS LUA_QL("%s") #define luaL_Reg luaL_reg #define luaL_opt(L, f, n, d) \ (lua_isnoneornil(L, n) ? (d) : f(L, n)) #define luaL_addchar(B,c) \ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ (*(B)->p++ = (char)(c))) #endif /* Lua 5.0 */ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 /* Lua 5.1 */ /* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h, * LuaJIT uses luaconf_h. If you use PUC-Rio's include files * but LuaJIT's library, you will need to define the macro * COMPAT52_IS_LUAJIT yourself! */ #if !defined(COMPAT52_IS_LUAJIT) && defined(luaconf_h) #define COMPAT52_IS_LUAJIT #endif /* LuaJIT doesn't define these unofficial macros ... */ #if !defined(LUAI_INT32) #include #if INT_MAX-20 < 32760 #define LUAI_INT32 long #define LUAI_UINT32 unsigned long #elif INT_MAX > 2147483640L #define LUAI_INT32 int #define LUAI_UINT32 unsigned int #else #error "could not detect suitable lua_Unsigned datatype" #endif #endif #define LUA_OPADD 0 #define LUA_OPSUB 1 #define LUA_OPMUL 2 #define LUA_OPDIV 3 #define LUA_OPMOD 4 #define LUA_OPPOW 5 #define LUA_OPUNM 6 #define LUA_OPEQ 0 #define LUA_OPLT 1 #define LUA_OPLE 2 typedef LUAI_UINT32 lua_Unsigned; typedef struct luaL_Buffer_52 { luaL_Buffer b; /* make incorrect code crash! */ char *ptr; size_t nelems; size_t capacity; lua_State *L2; } luaL_Buffer_52; #define luaL_Buffer luaL_Buffer_52 typedef struct luaL_Stream { FILE *f; /* The following field is for LuaJIT which adds a uint32_t field * to file handles. */ lua_Unsigned type; lua_CFunction closef; } luaL_Stream; #define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) #define lua_rawlen(L, i) lua_objlen(L, i) void lua_arith (lua_State *L, int op); int lua_compare (lua_State *L, int idx1, int idx2, int op); void lua_pushunsigned (lua_State *L, lua_Unsigned n); lua_Unsigned luaL_checkunsigned (lua_State *L, int i); lua_Unsigned lua_tounsignedx (lua_State *L, int i, int *isnum); lua_Unsigned luaL_optunsigned (lua_State *L, int i, lua_Unsigned def); void lua_len (lua_State *L, int i); int luaL_len (lua_State *L, int i); const char *luaL_tolstring (lua_State *L, int idx, size_t *len); #define luaL_buffinit luaL_buffinit_52 void luaL_buffinit (lua_State *L, luaL_Buffer_52 *B); #define luaL_prepbuffsize luaL_prepbuffsize_52 char *luaL_prepbuffsize (luaL_Buffer_52 *B, size_t s); #define luaL_addlstring luaL_addlstring_52 void luaL_addlstring (luaL_Buffer_52 *B, const char *s, size_t l); #define luaL_addvalue luaL_addvalue_52 void luaL_addvalue (luaL_Buffer_52 *B); #define luaL_pushresult luaL_pushresult_52 void luaL_pushresult (luaL_Buffer_52 *B); #undef luaL_buffinitsize #define luaL_buffinitsize(L, B, s) \ (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) #undef luaL_prepbuffer #define luaL_prepbuffer(B) \ luaL_prepbuffsize(B, LUAL_BUFFERSIZE) #undef luaL_addchar #define luaL_addchar(B, c) \ ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ ((B)->ptr[(B)->nelems++] = (c))) #undef luaL_addsize #define luaL_addsize(B, s) \ ((B)->nelems += (s)) #undef luaL_addstring #define luaL_addstring(B, s) \ luaL_addlstring(B, s, strlen(s)) #undef luaL_pushresultsize #define luaL_pushresultsize(B, s) \ (luaL_addsize(B, s), luaL_pushresult(B)) #endif /* Lua 5.1 */ #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 /* Lua 5.0 *or* 5.1 */ #define LUA_OK 0 #define lua_pushglobaltable(L) \ lua_pushvalue(L, LUA_GLOBALSINDEX) void luaL_checkversion (lua_State *L); #if !defined(COMPAT52_IS_LUAJIT) #define luaL_newlib(L, l) \ (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); void luaL_requiref (lua_State *L, char const* modname, lua_CFunction openf, int glb); void lua_copy (lua_State *L, int from, int to); void *luaL_testudata (lua_State *L, int i, const char *tname); lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); void luaL_setmetatable (lua_State *L, const char *tname); void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); int luaL_fileresult (lua_State *L, int stat, const char *fname); #endif #endif /* Lua 5.0 *or* 5.1 */ int lua_absindex (lua_State *L, int i); void lua_rawgetp (lua_State *L, int i, const void *p); void lua_rawsetp (lua_State *L, int i, const void *p); void lua_getuservalue (lua_State *L, int i); void lua_setuservalue (lua_State *L, int i); int luaL_getsubtable (lua_State *L, int i, const char *name); luaposix-36.3/ext/posix/000077500000000000000000000000001475444374100152705ustar00rootroot00000000000000luaposix-36.3/ext/posix/ctype.c000066400000000000000000000030671475444374100165660ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Character tests. @module posix.ctype */ #include #include "_helpers.c" static int bind_ctype(lua_State *L, int (*cb)(int)) { const char *s = luaL_checkstring(L, 1); char c = *s; checknargs(L, 1); lua_pop(L, 1); return pushintegerresult(cb((int)c)); } /*** Check for any printable character except space. @function isgraph @string character to act on @treturn int non-zero if character is not in the class @see isgraph(3) */ static int Pisgraph(lua_State *L) { return bind_ctype(L, &isgraph); } /*** Check for any printable character including space. @function isprint @string character to act on @treturn int non-zero if character is not in the class @see isprint(3) */ static int Pisprint(lua_State *L) { return bind_ctype(L, &isprint); } static const luaL_Reg posix_ctype_fns[] = { LPOSIX_FUNC( Pisgraph ), LPOSIX_FUNC( Pisprint ), {NULL, NULL} }; LUALIB_API int luaopen_posix_ctype(lua_State *L) { luaL_newlib(L, posix_ctype_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("ctype")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/dirent.c000066400000000000000000000052301475444374100167210ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Directory Iterators. @module posix.dirent */ #include #include "_helpers.c" /*** Contents of directory. @function dir @string[opt="."] path directory to act on @treturn table contents of *path* @see dir.lua */ static int Pdir(lua_State *L) { const char *path = optstring(L, 1, "."); DIR *d; checknargs(L, 1); d = opendir(path); /* Throw an argument error for consistency with eg. io.lines */ if (d == NULL) { const char *msg = strerror (errno); msg = lua_pushfstring(L, "%s: %s", path, msg); return luaL_argerror(L, 1, msg); } else { int i; struct dirent *entry; lua_newtable(L); for (i=1; (entry = readdir(d)) != NULL; i++) { lua_pushstring(L, entry->d_name); lua_rawseti(L, -2, i); } closedir(d); return 1; } } static int aux_files(lua_State *L) { DIR **p = (DIR **)lua_touserdata(L, lua_upvalueindex(1)); DIR *d = *p; struct dirent *entry; if (d == NULL) return 0; entry = readdir(d); if (entry == NULL) { closedir(d); *p=NULL; return 0; } return pushstringresult(entry->d_name); } static int dir_gc (lua_State *L) { DIR *d = *(DIR **)lua_touserdata(L, 1); if (d!=NULL) closedir(d); return 0; } /*** Iterator over all files in named directory. @function files @string[opt="."] path directory to act on @return an iterator */ static int Pfiles(lua_State *L) { const char *path = optstring(L, 1, "."); DIR **d; checknargs(L, 1); d = (DIR **)lua_newuserdata(L, sizeof(DIR *)); *d = opendir(path); /* Throw an argument error for consistency with eg. io.lines */ if (*d == NULL) { const char *msg = strerror (errno); msg = lua_pushfstring(L, "%s: %s", path, msg); return luaL_argerror(L, 1, msg); } if (luaL_newmetatable(L, PACKAGE " dir handle")) { lua_pushcfunction(L, dir_gc); lua_setfield(L, -2, "__gc"); } lua_setmetatable(L, -2); lua_pushcclosure(L, aux_files, 1); return 1; } static const luaL_Reg posix_dirent_fns[] = { LPOSIX_FUNC( Pdir ), LPOSIX_FUNC( Pfiles ), {NULL, NULL} }; LUALIB_API int luaopen_posix_dirent(lua_State *L) { luaL_newlib(L, posix_dirent_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("dirent")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/errno.c000066400000000000000000000205351475444374100165660ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** System error codes and messages. Usually, you'll be able to work with the error messages returned as the second value from failed calls directly, without having to manually save and stringify the system messages as you would in C. For completeness, the functions are still available here. @module posix.errno */ #include #include #include #include "_helpers.c" #ifndef errno extern int errno; #endif /*** Describe an error code/and or read `errno` @function errno @int[opt=current errno] n optional error code @return description @return error code @see strerror(3) @see errno @usage local strerr, nerr = posix.errno () */ static int Perrno(lua_State *L) { int n = optint(L, 1, errno); checknargs(L, 1); lua_pushstring(L, strerror(n)); lua_pushinteger(L, n); return 2; } /*** Set errno. @function set_errno @int n error code @see errno(3) @usage posix.errno (posix.EBADF) */ static int Pset_errno(lua_State *L) { errno = checkint(L, 1); checknargs(L, 1); return 0; } static const luaL_Reg posix_errno_fns[] = { LPOSIX_FUNC( Perrno ), LPOSIX_FUNC( Pset_errno ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Error constants. Any constants not available in the underlying system will be `nil` valued. If you find one of the luaposix APIs returns an error code not listed here, please raise an issue [here](http://github.com/luaposix/luaposixissues), stating the symbolic name of the constant (from `/usr/include/errno.h` or equivalent). @table posix.errno @int E2BIG argument list too long @int EACCES permission denied @int EADDRINUSE address already in use @int EADDRNOTAVAIL can't assign requested address @int EAFNOSUPPORT address family not supported by protocol family @int EAGAIN resource temporarily unavailable @int EALREADY operation already in progress @int EBADF bad file descriptor @int EBADMSG bad message @int EBUSY resource busy @int ECANCELED operation canceled @int ECHILD no child processes @int ECONNABORTED software caused connection abort @int ECONNREFUSED connection refused @int ECONNRESET connection reset by peer @int EDEADLK resource deadlock avoided @int EDESTADDRREQ destination address required @int EDOM numerical argument out of domain @int EEXIST file exists @int EFAULT bad address @int EFBIG file too large @int EHOSTUNREACH no route to host @int EIDRM identifier removed @int EILSEQ illegal byte sequence @int EINPROGRESS operation now in progress @int EINTR interrupted system call @int EINVAL invalid argument @int EIO input/output error @int EISCONN socket is already connected @int EISDIR is a directory @int ELOOP too many levels of symbolic links @int EMFILE too many open files @int EMLINK too many links @int EMSGSIZE message too long @int ENAMETOOLONG file name too long @int ENETDOWN network is down @int ENETRESET network dropped connection on reset @int ENETUNREACH network is unreachable @int ENFILE too many open files in system @int ENOBUFS no buffer space available @int ENODEV operation not supported by device @int ENOENT no such file or directory @int ENOEXEC exec format error @int ENOLCK no locks available @int ENOMEM cannot allocate memory @int ENOMSG no message of desired type @int ENOPROTOOPT protocol not available @int ENOSPC no space left on device @int ENOSYS function not implemented @int ENOTCONN socket is not connected @int ENOTDIR not a directory @int ENOTEMPTY directory not empty @int ENOTSOCK socket operation on non-socket @int ENOTSUP operation not supported @int ENOTTY inappropriate ioctl for device @int ENXIO device not configured @int EOPNOTSUPP operation not supported on socket @int EOVERFLOW value too large to be stored in data type @int EPERM operation not permitted @int EPIPE broken pipe @int EPROTO protocol error @int EPROTONOSUPPORT protocol not supported @int EPROTOTYPE protocol wrong type for socket @int ERANGE result too large @int EROFS read-only file system @int ESPIPE illegal seek @int ESRCH no such process @int ETIMEDOUT operation timed out @int ETXTBSY text file busy @int EWOULDBLOCK operation would block @int EXDEV cross-device link @usage -- Print errno constants supported on this host. for name, value in pairs (require "posix.errno") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_errno(lua_State *L) { luaL_newlib(L, posix_errno_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("errno")); lua_setfield(L, -2, "version"); #ifdef E2BIG LPOSIX_CONST( E2BIG ); #endif #ifdef EACCES LPOSIX_CONST( EACCES ); #endif #ifdef EADDRINUSE LPOSIX_CONST( EADDRINUSE ); #endif #ifdef EADDRNOTAVAIL LPOSIX_CONST( EADDRNOTAVAIL ); #endif #ifdef EAFNOSUPPORT LPOSIX_CONST( EAFNOSUPPORT ); #endif #ifdef EAGAIN LPOSIX_CONST( EAGAIN ); #endif #ifdef EALREADY LPOSIX_CONST( EALREADY ); #endif #ifdef EBADF LPOSIX_CONST( EBADF ); #endif #ifdef EBADMSG LPOSIX_CONST( EBADMSG ); #endif #ifdef EBUSY LPOSIX_CONST( EBUSY ); #endif #ifdef ECANCELED LPOSIX_CONST( ECANCELED ); #endif #ifdef ECHILD LPOSIX_CONST( ECHILD ); #endif #ifdef ECONNABORTED LPOSIX_CONST( ECONNABORTED ); #endif #ifdef ECONNREFUSED LPOSIX_CONST( ECONNREFUSED ); #endif #ifdef ECONNRESET LPOSIX_CONST( ECONNRESET ); #endif #ifdef EDEADLK LPOSIX_CONST( EDEADLK ); #endif #ifdef EDESTADDRREQ LPOSIX_CONST( EDESTADDRREQ ); #endif #ifdef EDOM LPOSIX_CONST( EDOM ); #endif #ifdef EEXIST LPOSIX_CONST( EEXIST ); #endif #ifdef EFAULT LPOSIX_CONST( EFAULT ); #endif #ifdef EFBIG LPOSIX_CONST( EFBIG ); #endif #ifdef EHOSTUNREACH LPOSIX_CONST( EHOSTUNREACH ); #endif #ifdef EIDRM LPOSIX_CONST( EIDRM ); #endif #ifdef EILSEQ LPOSIX_CONST( EILSEQ ); #endif #ifdef EINPROGRESS LPOSIX_CONST( EINPROGRESS ); #endif #ifdef EINTR LPOSIX_CONST( EINTR ); #endif #ifdef EINVAL LPOSIX_CONST( EINVAL ); #endif #ifdef EIO LPOSIX_CONST( EIO ); #endif #ifdef EISCONN LPOSIX_CONST( EISCONN ); #endif #ifdef EISDIR LPOSIX_CONST( EISDIR ); #endif #ifdef ELOOP LPOSIX_CONST( ELOOP ); #endif #ifdef EMFILE LPOSIX_CONST( EMFILE ); #endif #ifdef EMLINK LPOSIX_CONST( EMLINK ); #endif #ifdef EMSGSIZE LPOSIX_CONST( EMSGSIZE ); #endif #ifdef ENAMETOOLONG LPOSIX_CONST( ENAMETOOLONG ); #endif #ifdef ENETDOWN LPOSIX_CONST( ENETDOWN ); #endif #ifdef ENETRESET LPOSIX_CONST( ENETRESET ); #endif #ifdef ENETUNREACH LPOSIX_CONST( ENETUNREACH ); #endif #ifdef ENFILE LPOSIX_CONST( ENFILE ); #endif #ifdef ENOBUFS LPOSIX_CONST( ENOBUFS ); #endif #ifdef ENODEV LPOSIX_CONST( ENODEV ); #endif #ifdef ENOENT LPOSIX_CONST( ENOENT ); #endif #ifdef ENOEXEC LPOSIX_CONST( ENOEXEC ); #endif #ifdef ENOLCK LPOSIX_CONST( ENOLCK ); #endif #ifdef ENOMEM LPOSIX_CONST( ENOMEM ); #endif #ifdef ENOMSG LPOSIX_CONST( ENOMSG ); #endif #ifdef ENOPROTOOPT LPOSIX_CONST( ENOPROTOOPT ); #endif #ifdef ENOSPC LPOSIX_CONST( ENOSPC ); #endif #ifdef ENOSYS LPOSIX_CONST( ENOSYS ); #endif #ifdef ENOTCONN LPOSIX_CONST( ENOTCONN ); #endif #ifdef ENOTDIR LPOSIX_CONST( ENOTDIR ); #endif #ifdef ENOTEMPTY LPOSIX_CONST( ENOTEMPTY ); #endif #ifdef ENOTSOCK LPOSIX_CONST( ENOTSOCK ); #endif #ifdef ENOTSUP LPOSIX_CONST( ENOTSUP ); #endif #ifdef ENOTTY LPOSIX_CONST( ENOTTY ); #endif #ifdef ENXIO LPOSIX_CONST( ENXIO ); #endif #ifdef EOPNOTSUPP LPOSIX_CONST( EOPNOTSUPP ); #endif #ifdef EOVERFLOW LPOSIX_CONST( EOVERFLOW ); #endif #ifdef EPERM LPOSIX_CONST( EPERM ); #endif #ifdef EPIPE LPOSIX_CONST( EPIPE ); #endif #ifdef EPROTO LPOSIX_CONST( EPROTO ); #endif #ifdef EPROTONOSUPPORT LPOSIX_CONST( EPROTONOSUPPORT ); #endif #ifdef EPROTOTYPE LPOSIX_CONST( EPROTOTYPE ); #endif #ifdef ERANGE LPOSIX_CONST( ERANGE ); #endif #ifdef EROFS LPOSIX_CONST( EROFS ); #endif #ifdef ESPIPE LPOSIX_CONST( ESPIPE ); #endif #ifdef ESRCH LPOSIX_CONST( ESRCH ); #endif #ifdef ETIMEDOUT LPOSIX_CONST( ETIMEDOUT ); #endif #ifdef ETXTBSY LPOSIX_CONST( ETXTBSY ); #endif #ifdef EWOULDBLOCK LPOSIX_CONST( EWOULDBLOCK ); #endif #ifdef EXDEV LPOSIX_CONST( EXDEV ); #endif return 1; } luaposix-36.3/ext/posix/fcntl.c000066400000000000000000000213161475444374100165450ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** File Control. Low-level control over file descriptors, including creating new file descriptors with `open`. @module posix.fcntl */ #include "_helpers.c" #include /* Darwin fails to define O_RSYNC. */ #ifndef O_RSYNC #define O_RSYNC 0 #endif /* FreeBSD 10 fails to define O_DSYNC. */ #ifndef O_DSYNC #define O_DSYNC 0 #endif /* POSIX.2001 uses FD_CLOEXEC instead. */ #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif /*** Advisory file locks. Passed as *arg* to @{fcntl} when *cmd* is `F_GETLK`, `F_SETLK` or `F_SETLKW`. @table flock @int l_start starting offset @int l_len len = 0 means until end of file @int l_pid lock owner @int l_type lock type @int l_whence one of `SEEK_SET`, `SEEK_CUR` or `SEEK_END` */ /*** Manipulate file descriptor. @function fcntl @int fd file descriptor to act on @int cmd operation to perform @tparam[opt=0] int|flock arg when *cmd* is `F_GETLK`, `F_SETLK` or `F_SETLKW`, then *arg* is a @{flock} table, otherwise an integer with meaning dependent upon the value of *cmd*. @return[1] integer return value depending on *cmd*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fcntl(2) @see lock.lua @usage local flag = posix.fcntl (fd, posix.F_GETFL) */ static int Pfcntl(lua_State *L) { int fd = checkint(L, 1); int cmd = checkint(L, 2); int arg; struct flock lockinfo; int r; checknargs(L, 3); switch (cmd) { case F_SETLK: case F_SETLKW: case F_GETLK: luaL_checktype(L, 3, LUA_TTABLE); /* Copy fields to flock struct */ lua_getfield(L, 3, "l_type"); lockinfo.l_type = (short)lua_tointeger(L, -1); lua_getfield(L, 3, "l_whence"); lockinfo.l_whence = (short)lua_tointeger(L, -1); lua_getfield(L, 3, "l_start"); lockinfo.l_start = (off_t)lua_tointeger(L, -1); lua_getfield(L, 3, "l_len"); lockinfo.l_len = (off_t)lua_tointeger(L, -1); /* Lock */ r = fcntl(fd, cmd, &lockinfo); /* Copy fields from flock struct */ lua_pushinteger(L, lockinfo.l_type); lua_setfield(L, 3, "l_type"); lua_pushinteger(L, lockinfo.l_whence); lua_setfield(L, 3, "l_whence"); lua_pushinteger(L, lockinfo.l_start); lua_setfield(L, 3, "l_start"); lua_pushinteger(L, lockinfo.l_len); lua_setfield(L, 3, "l_len"); lua_pushinteger(L, lockinfo.l_pid); lua_setfield(L, 3, "l_pid"); break; default: arg = optint(L, 3, 0); r = fcntl(fd, cmd, arg); break; } return pushresult(L, r, "fcntl"); } /*** Open a file. @function open @string path @int oflags bitwise OR of zero or more of `O_RDONLY`, `O_WRONLY`, `O_RDWR`, `O_APPEND`, `O_CREAT`, `O_DSYNC`, `O_EXCL`, `O_NOCTTY`, `O_NONBLOCK`, `O_RSYNC`, `O_SYNC` and `O_TRUNC` (and `O_CLOEXEC`, where supported) @int[opt=511] mode access modes used by `O_CREAT` @treturn[1] int file descriptor for *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see open(2) @usage local P = require "posix.fcntl" fd = P.open ("data", bit.bor (P.O_CREAT, P.O_RDWR), bit.bor (P.S_IRWXU, P.S_IRGRP)) */ static int Popen(lua_State *L) { const char *path = luaL_checkstring(L, 1); int oflags = checkint(L, 2); checknargs(L, 3); return pushresult(L, open(path, oflags, (mode_t)optinteger(L, 3, 511)), path); } #if HAVE_POSIX_FADVISE /*** Instruct kernel on appropriate cache behaviour for a file or file segment. @function posix_fadvise @int fd open file descriptor @int offset start of region @int len number of bytes in region @int advice one of `POSIX_FADV_NORMAL`, `POSIX_FADV_SEQUENTIAL`, `POSIX_FADV_RANDOM`, `POSIX_FADV_NOREUSE`, `POSIX_FADV_WILLNEED` or `POSIX_FADV_DONTNEED` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see posix_fadvise(2) */ static int Pposix_fadvise(lua_State *L) { int fd = checkint(L, 1); off_t offset = (off_t)checkinteger(L, 2); off_t len = (off_t)checkinteger(L, 3); int advice = checkint(L, 4); int r; checknargs(L, 4); r = posix_fadvise(fd, offset, len, advice); return pushresult(L, r == 0 ? 0 : -1, "posix_fadvise"); } #endif static const luaL_Reg posix_fcntl_fns[] = { LPOSIX_FUNC( Pfcntl ), LPOSIX_FUNC( Popen ), #if HAVE_POSIX_FADVISE LPOSIX_FUNC( Pposix_fadvise ), #endif {NULL, NULL} }; /*** Constants. @section constants */ /*** Fcntl constants. Any constants not available in the underlying system will be `0` valued, if they are usually bitwise ORed with other values, otherwise `nil`. @table posix.fcntl @int AT_EACCESS test access permitted for effective IDs, not real IDs @int AT_FDCWD indicate *at functions to use current directory @int AT_REMOVEDIR remove directory instead of unlinking file @int AT_SYMLINK_FOLLOW follow symbolic links @int AT_SYMLINK_NOFOLLOW do not follow symbolic links @int FD_CLOEXEC close file descriptor on exec flag @int F_DUPFD duplicate file descriptor @int F_GETFD get file descriptor flags @int F_SETFD set file descriptor flags @int F_GETFL get file status flags @int F_SETFL set file status flags @int F_GETLK get record locking information @int F_SETLK set record locking information @int F_SETLKW set lock, and wait if blocked @int F_GETOWN get SIGIO/SIGURG process owner @int F_SETOWN set SIGIO/SIGURG process owner @int F_RDLCK shared or read lock @int F_WRLCK exclusive or write lock @int F_UNLCK unlock @int O_RDONLY open for reading only @int O_WRONLY open for writing only @int O_RDWR open for reading and writing @int O_APPEND set append mode @int O_CLOEXEC set FD_CLOEXEC atomically @int O_CREAT create if nonexistent @int O_DSYNC synchronise io data integrity @int O_EXCL error if file already exists @int O_NOCTTY don't assign controlling terminal @int O_NONBLOCK no delay @int O_RSYNC synchronise file read integrity @int O_SYNC synchronise file write integrity @int O_TRUNC truncate to zero length @int POSIX_FADV_NORMAL no advice @int POSIX_FADV_SEQUENTIAL expecting to access data sequentially @int POSIX_FADV_RANDOM expecting to access data randomly @int POSIX_FADV_NOREUSE expecting to access data once only @int POSIX_FADV_WILLNEED expecting to access data in the near future @int POSIX_FADV_DONTNEED not expecting to access the data in the near future @usage -- Print fcntl constants supported on this host. for name, value in pairs (require "posix.fcntl") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_fcntl(lua_State *L) { luaL_newlib(L, posix_fcntl_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("fcntl")); lua_setfield(L, -2, "version"); /* posix *at flags */ #ifdef AT_EACCESS LPOSIX_CONST( AT_EACCESS ); #endif #ifdef AT_FDCWD LPOSIX_CONST( AT_FDCWD ); #endif #ifdef AT_REMOVEDIR LPOSIX_CONST( AT_REMOVEDIR ); #endif #ifdef AT_SYMLINK_FOLLOW LPOSIX_CONST( AT_SYMLINK_FOLLOW ); #endif #ifdef AT_SYMLINK_NOFOLLOW LPOSIX_CONST( AT_SYMLINK_NOFOLLOW ); #endif /* Linux-specific *at flags */ #ifdef AT_EMPTY_PATH LPOSIX_CONST( AT_EMPTY_PATH ); #endif #ifdef AT_NO_AUTOMOUNT LPOSIX_CONST( AT_NO_AUTOMOUNT ); #endif /* fcntl flags */ LPOSIX_CONST( FD_CLOEXEC ); LPOSIX_CONST( F_DUPFD ); LPOSIX_CONST( F_GETFD ); LPOSIX_CONST( F_SETFD ); LPOSIX_CONST( F_GETFL ); LPOSIX_CONST( F_SETFL ); LPOSIX_CONST( F_GETLK ); LPOSIX_CONST( F_SETLK ); LPOSIX_CONST( F_SETLKW ); LPOSIX_CONST( F_GETOWN ); LPOSIX_CONST( F_SETOWN ); LPOSIX_CONST( F_RDLCK ); LPOSIX_CONST( F_WRLCK ); LPOSIX_CONST( F_UNLCK ); /* file creation & status flags */ LPOSIX_CONST( O_RDONLY ); LPOSIX_CONST( O_WRONLY ); LPOSIX_CONST( O_RDWR ); LPOSIX_CONST( O_APPEND ); LPOSIX_CONST( O_CREAT ); LPOSIX_CONST( O_DSYNC ); LPOSIX_CONST( O_EXCL ); LPOSIX_CONST( O_NOCTTY ); LPOSIX_CONST( O_NONBLOCK ); LPOSIX_CONST( O_RSYNC ); LPOSIX_CONST( O_SYNC ); LPOSIX_CONST( O_TRUNC ); LPOSIX_CONST( O_CLOEXEC ); /* Linux 3.11 and above */ #ifdef O_TMPFILE LPOSIX_CONST( O_TMPFILE ); #endif /* posix_fadvise flags */ #ifdef POSIX_FADV_NORMAL LPOSIX_CONST( POSIX_FADV_NORMAL ); #endif #ifdef POSIX_FADV_SEQUENTIAL LPOSIX_CONST( POSIX_FADV_SEQUENTIAL ); #endif #ifdef POSIX_FADV_RANDOM LPOSIX_CONST( POSIX_FADV_RANDOM ); #endif #ifdef POSIX_FADV_NOREUSE LPOSIX_CONST( POSIX_FADV_NOREUSE ); #endif #ifdef POSIX_FADV_WILLNEED LPOSIX_CONST( POSIX_FADV_WILLNEED ); #endif #ifdef POSIX_FADV_DONTNEED LPOSIX_CONST( POSIX_FADV_DONTNEED ); #endif return 1; } luaposix-36.3/ext/posix/fnmatch.c000066400000000000000000000043411475444374100170560ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Filename matching. Functions and constants for matching known filenames against shell-style pattern strings. @see posix.glob @module posix.fnmatch */ #include #include "_helpers.c" /*** Match a filename against a shell pattern. @function fnmatch @string pat shell pattern @string name filename @int[opt=0] flags optional @treturn[1] int `0`, if successful @treturn[2] int `FNM_NOMATCH` @treturn[3] int some other non-zero integer if fnmatch itself failed @see fnmatch(3) */ static int Pfnmatch(lua_State *L) { const char *pattern = luaL_checkstring(L, 1); const char *string = luaL_checkstring(L, 2); int flags = optint(L, 3, 0); int res; checknargs(L, 3); return pushintegerresult(fnmatch(pattern, string, flags)); } static const luaL_Reg posix_fnmatch_fns[] = { LPOSIX_FUNC( Pfnmatch ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Fnmatch constants. Any constants not available in the underlying system will be `nil` valued. @table posix.fnmatch @int FNM_PATHNAME slashes in pathname must be matched by slash in pattern @int FNM_NOESCAPE disable backslash escaping @int FNM_NOMATCH match failed @int FNM_PERIOD periods in pathname must be matched by period in pattern @usage -- Print fnmatch constants supported on this host. for name, value in pairs (require "posix.fnmatch") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_fnmatch(lua_State *L) { luaL_newlib(L, posix_fnmatch_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("fnmatch")); lua_setfield(L, -2, "version"); /* from fnmatch.h */ LPOSIX_CONST( FNM_PATHNAME ); LPOSIX_CONST( FNM_NOESCAPE ); LPOSIX_CONST( FNM_NOMATCH ); LPOSIX_CONST( FNM_PERIOD ); return 1; } luaposix-36.3/ext/posix/glob.c000066400000000000000000000052101475444374100163550ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Generate pathnames matching a shell-style pattern. Functions generating a table of filenames that match a shell-style pattern string. @module posix.glob */ #include #include "_helpers.c" /*** Find all files in this directory matching a shell pattern. @function glob @string[opt="*"] pat shell glob pattern @param flags bitwise inclusive OR of zero or more of `GLOB_ERR`, `GLOB_MARK` and `GLOB_NOCHECK` @treturn[1] table matching filenames, if successful @treturn[2] nil @treturn[2] one of `GLOB_ABORTED`, `GLOB_NOMATCH` or `GLOB_NOSPACE` @see glob(3) @see glob.lua */ static int Pglob(lua_State *L) { const char *pattern = optstring(L, 1, "*"); int flags = checkint(L, 2); int globret = 0; glob_t globres; checknargs(L, 2); if ((globret = glob(pattern, flags, NULL, &globres)) != 0) { lua_pushnil(L); lua_pushinteger(L, globret); return 2; } else { unsigned int i; lua_newtable(L); for (i=1; i<=globres.gl_pathc; i++) { lua_pushstring(L, globres.gl_pathv[i-1]); lua_rawseti(L, -2, i); } globfree(&globres); return 1; } } static const luaL_Reg posix_glob_fns[] = { LPOSIX_FUNC( Pglob ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Glob constants. @table posix.glob @int GLOB_MARK append slashes to matches that are directories. @int GLOB_ERR instead of ignoring non-readable directories, return GLOB_ABORTED @int GLOB_ABORTED encountered a non-readable directory @int GLOB_NOCHECK return the original pattern if there are no matches @int GLOB_NOMATCH pattern does not match any existing pathname @int GLOB_NOSPACE not enough memory to continue @usage -- Print glob constants supported on this host. for name, value in pairs (require "posix.glob") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_glob(lua_State *L) { luaL_newlib(L, posix_glob_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("glob")); lua_setfield(L, -2, "version"); LPOSIX_CONST( GLOB_ERR ); LPOSIX_CONST( GLOB_MARK ); LPOSIX_CONST( GLOB_NOCHECK ); LPOSIX_CONST( GLOB_ABORTED ); LPOSIX_CONST( GLOB_NOMATCH ); LPOSIX_CONST( GLOB_NOSPACE ); return 1; } luaposix-36.3/ext/posix/grp.c000066400000000000000000000067421475444374100162350ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Group Database Operations. Query the system group database. @see posix.pwd @module posix.grp */ #include #include "_helpers.c" /*** Group record. @table PosixGroup @string gr_name name of group @int gr_gid unique group id @tfield list gr_mem a list of group members */ static int pushgroup(lua_State *L, struct group *g) { if (!g) return lua_pushnil(L), 1; lua_createtable(L, 0, 3); setintegerfield(g, gr_gid); setstringfield(g, gr_name); if (g->gr_mem) { int i; lua_newtable(L); for (i = 0; g->gr_mem[i] != NULL; i++) { lua_pushstring(L, g->gr_mem[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "gr_mem"); } settypemetatable("PosixGroup"); return 1; } /*** Release group database resources. @function endgrent @see endgrent(3) @see getgrent */ static int Pendgrent(lua_State *L) { checknargs(L, 0); endgrent(); return 0; } /*** Fetch next group. @function getgrent @treturn PosixGroup next group record @see getgrent(3) @see endgrent @usage local grp = require "posix.grp" t = grp.getgrent () while t ~= nil do process (t) t = grp.getgrent () end grp.endgrent () */ static int Pgetgrent(lua_State *L) { struct group *g; checknargs(L, 0); g = getgrent(); if (!g && errno == 0) endgrent(); return pushgroup(L, g); } /*** Fetch group with given group id. @function getgrgid @int gid group id @treturn[1] PosixGroup group record for *gid*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getgrgid(3) @usage local grp = require "posix.grp" t = grp.getgrgid (0) */ static int Pgetgrgid(lua_State *L) { gid_t gid = (gid_t)checkinteger(L, 1); struct group *g; checknargs(L, 1); errno = 0; /* so we can recognise a successful empty result */ g = getgrgid(gid); if (!g && errno != 0) return pusherror(L, "getgrgid"); return pushgroup(L, g); } /*** Fetch named group. @function getgrnam @string name group name @treturn[1] PosixGroup group record for *name*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getgrnam(3) @usage local grp = require "posix.grp" t = grp.getgrnam "wheel" */ static int Pgetgrnam(lua_State *L) { const char *name = luaL_checkstring(L, 1); struct group *g; checknargs(L, 1); errno = 0; /* so we can recognise a successful empty result */ g = getgrnam (name); if (!g && errno != 0) return pusherror(L, "getgrnam"); return pushgroup(L, g); } /*** Rewind next @{getgrent} back to start of database. @function setgrent @see setgrent(3) @see getgrent */ static int Psetgrent(lua_State *L) { checknargs(L, 0); setgrent(); return 0; } static const luaL_Reg posix_grp_fns[] = { LPOSIX_FUNC( Pendgrent ), LPOSIX_FUNC( Pgetgrent ), LPOSIX_FUNC( Pgetgrgid ), LPOSIX_FUNC( Pgetgrnam ), LPOSIX_FUNC( Psetgrent ), {NULL, NULL} }; LUALIB_API int luaopen_posix_grp(lua_State *L) { luaL_newlib(L, posix_grp_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("grp")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/libgen.c000066400000000000000000000043241475444374100166770ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** General Library. Functions for separating a pathname into file and directory components. @module posix.libgen */ #include #include "_helpers.c" /*** File part of path. @function basename @string path file to act on @treturn[1] string filename part of *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see basename(3) */ static int Pbasename(lua_State *L) { char *b; size_t len; void *ud; lua_Alloc lalloc; const char *path = luaL_checklstring(L, 1, &len); size_t path_len; checknargs(L, 1); path_len = strlen(path) + 1; lalloc = lua_getallocf(L, &ud); if ((b = lalloc(ud, NULL, 0, path_len)) == NULL) return pusherror(L, "lalloc"); lua_pushstring(L, basename(strcpy(b,path))); lalloc(ud, b, path_len, 0); return 1; } /*** Directory name of path. @function dirname @string path file to act on @treturn[1] string directory part of *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see dirname(3) */ static int Pdirname(lua_State *L) { char *b; size_t len; void *ud; lua_Alloc lalloc; const char *path = luaL_checklstring(L, 1, &len); size_t path_len; checknargs(L, 1); path_len = strlen(path) + 1; lalloc = lua_getallocf(L, &ud); if ((b = lalloc(ud, NULL, 0, path_len)) == NULL) return pusherror(L, "lalloc"); lua_pushstring(L, dirname(strcpy(b,path))); lalloc(ud, b, path_len, 0); return 1; } static const luaL_Reg posix_libgen_fns[] = { LPOSIX_FUNC( Pbasename ), LPOSIX_FUNC( Pdirname ), {NULL, NULL} }; LUALIB_API int luaopen_posix_libgen(lua_State *L) { luaL_newlib(L, posix_libgen_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("libgen")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/poll.c000066400000000000000000000145071475444374100164110ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Synchronous I/O Multiplexing. Examine file descriptors for events, such as readyness for I/O. @module posix.poll */ #include #include "_helpers.c" static struct { short bit; const char *name; } poll_event_map[] = { #define MAP(_NAME) \ {POLL##_NAME, #_NAME} MAP(IN), MAP(PRI), MAP(OUT), MAP(ERR), MAP(HUP), MAP(NVAL), #undef MAP }; #define PPOLL_EVENT_NUM (sizeof(poll_event_map) / sizeof(*poll_event_map)) static void poll_events_createtable(lua_State *L) { lua_createtable(L, 0, PPOLL_EVENT_NUM); } static short poll_events_from_table(lua_State *L, int table) { short events = 0; size_t i; /* Convert to absolute index */ if (table < 0) table = lua_gettop(L) + table + 1; for (i = 0; i < PPOLL_EVENT_NUM; i++) { lua_getfield(L, table, poll_event_map[i].name); if (lua_toboolean(L, -1)) events |= poll_event_map[i].bit; lua_pop(L, 1); } return events; } static void poll_events_to_table(lua_State *L, int table, short events) { size_t i; /* Convert to absolute index */ if (table < 0) table = lua_gettop(L) + table + 1; for (i = 0; i < PPOLL_EVENT_NUM; i++) { lua_pushboolean(L, events & poll_event_map[i].bit); lua_setfield(L, table, poll_event_map[i].name); } } static nfds_t poll_fd_list_check_table(lua_State *L, int table) { nfds_t fd_num = 0; /* * Assume table is an argument number. * Should be an assert(table > 0). */ luaL_checktype(L, table, LUA_TTABLE); /* Nil key - the one before first */ lua_pushnil(L); /* Push each key/value pair, popping previous key */ while (lua_next(L, 1) != 0) { /* Verify the fd key */ luaL_argcheck(L, lua_isinteger(L, -2), table, "contains non-integer key(s)"); /* Verify the table value */ luaL_argcheck(L, lua_istable(L, -1), table, "contains non-table value(s)"); lua_getfield(L, -1, "events"); luaL_argcheck(L, lua_istable(L, -1), table, "contains invalid value table(s)"); lua_pop(L, 1); lua_getfield(L, -1, "revents"); luaL_argcheck(L, lua_isnil(L, -1) || lua_istable(L, -1), table, "contains invalid value table(s)"); lua_pop(L, 1); /* Remove value (but leave the key) */ lua_pop(L, 1); /* Count the fds */ fd_num++; } return fd_num; } static void poll_fd_list_from_table(lua_State *L, int table, struct pollfd *fd_list) { struct pollfd *pollfd = fd_list; /* * Assume the table didn't change since * the call to poll_fd_list_check_table */ /* Convert to absolute index */ if (table < 0) table = lua_gettop(L) + table + 1; /* Nil key - the one before first */ lua_pushnil(L); /* Push each key/value pair, popping previous key */ while (lua_next(L, table) != 0) { /* Transfer the fd key */ pollfd->fd = lua_tointeger(L, -2); /* Transfer "events" field from the value */ lua_getfield(L, -1, "events"); pollfd->events = poll_events_from_table(L, -1); lua_pop(L, 1); /* Remove value (but leave the key) */ lua_pop(L, 1); /* Proceed to next fd */ pollfd++; } } static void poll_fd_list_to_table(lua_State *L, int table, const struct pollfd *fd_list) { const struct pollfd *pollfd = fd_list; /* * Assume the table didn't change since * the call to poll_fd_list_check_table. */ /* Convert to absolute index */ if (table < 0) table = lua_gettop(L) + table + 1; /* Nil key - the one before first */ lua_pushnil(L); /* Push each key/value pair, popping previous key */ while (lua_next(L, 1) != 0) { /* Transfer "revents" field to the value */ lua_getfield(L, -1, "revents"); if (lua_isnil(L, -1)) { lua_pop(L, 1); poll_events_createtable(L); lua_pushvalue(L, -1); lua_setfield(L, -3, "revents"); } poll_events_to_table(L, -1, pollfd->revents); lua_pop(L, 1); /* Remove value (but leave the key) */ lua_pop(L, 1); /* Proceed to next fd */ pollfd++; } } /*** Wait for events on multiple file descriptors. @function poll @tparam table fds list of file descriptors @int[opt=-1] timeout maximum timeout in milliseconds, or -1 to block indefinitely @treturn[1] int `0` if timed out, number of *fd*'s ready if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see poll(2) @see rpoll @see poll.lua */ static int Ppoll(lua_State *L) { struct pollfd *fd_list, static_fd_list[16]; nfds_t fd_num = poll_fd_list_check_table(L, 1); int r, timeout = optint(L, 2, -1); checknargs(L, 2); fd_list = (fd_num <= sizeof(static_fd_list) / sizeof(*static_fd_list)) ? static_fd_list : lua_newuserdata(L, sizeof(*fd_list) * fd_num); poll_fd_list_from_table(L, 1, fd_list); r = poll(fd_list, fd_num, timeout); /* If any of the descriptors changed state */ if (r > 0) poll_fd_list_to_table(L, 1, fd_list); return pushresult(L, r, NULL); } /*** Wait for some event on a file descriptor. Based on [a lua-l list post](http://lua-users.org/lists/lua-l/2007-11/msg00346.html). @function rpoll @int fd file descriptor @int[opt=-1] timeout maximum timeout in milliseconds, or `-1` to block indefinitely @treturn[1] int `0` if timed out, number of *fd*'s ready if successful @return[2] nil @return[2] error message @treturn[2] int errnum @see poll @usage local stdio = require "posix.stdio" local fh = io.open "one" while true do local r = rpoll (stdio.fileno(fh), 500) if r == 0 then print 'timeout' elseif r == 1 then print (fh:read ()) else print "finish!" break end end */ static int Prpoll(lua_State *L) { struct pollfd fds; int file = checkint(L, 1); int timeout = checkint(L, 2); checknargs(L, 2); fds.fd = file; fds.events = POLLIN; return pushresult(L, poll(&fds, 1, timeout), NULL); } static const luaL_Reg posix_poll_fns[] = { LPOSIX_FUNC( Ppoll ), LPOSIX_FUNC( Prpoll ), {NULL, NULL} }; LUALIB_API int luaopen_posix_poll(lua_State *L) { luaL_newlib(L, posix_poll_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("poll")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/posix.c000066400000000000000000000021021475444374100165710ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ #include "ctype.c" #include "dirent.c" #include "errno.c" #include "fcntl.c" #include "fnmatch.c" #include "glob.c" #include "grp.c" #include "libgen.c" #include "poll.c" #include "pwd.c" #include "sched.c" #include "signal.c" #include "stdio.c" #include "stdlib.c" #include "sys/msg.c" #include "sys/resource.c" #include "sys/socket.c" #include "sys/stat.c" #include "sys/statvfs.c" #include "sys/time.c" #include "sys/times.c" #include "sys/utsname.c" #include "sys/wait.c" #include "syslog.c" #include "termio.c" #include "time.c" #include "unistd.c" #include "utime.c" luaposix-36.3/ext/posix/pwd.c000066400000000000000000000070731475444374100162350ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Password Database Operations. Query the system password database. @module posix.pwd */ #include #include #include /* for geteuid(2) */ #include "_helpers.c" /*** Password record. @table PosixPasswd @string pw_name user's login name @int pw_uid unique user id @int pw_gid user's default group id @string pw_dir initial working directory @string pw_shell user's login shell path */ static int pushpasswd(lua_State *L, struct passwd *p) { if (!p) return lua_pushnil(L), 1; lua_createtable(L, 0, 6); setintegerfield(p, pw_uid); setintegerfield(p, pw_gid); setstringfield(p, pw_name); setstringfield(p, pw_dir); setstringfield(p, pw_shell); setstringfield(p, pw_passwd); settypemetatable("PosixPasswd"); return 1; } /*** Release password database resources. @function endpwent @see endpwent(3) @see getpwent */ static int Pendpwent(lua_State *L) { checknargs(L, 0); endpwent(); return 0; } /*** Fetch next password entry. @function getpwent @treturn PosixPasswd next password record @see getpwent(3) @see endpwent @usage local pwd = require "posix.pwd" t = pwd.getpwent () while t ~= nil do process (t) t = pwd.getpwent () end pwd.endpwent () */ static int Pgetpwent(lua_State *L) { struct passwd *p; checknargs(L, 0); p = getpwent(); if (!p && errno == 0) endpwent(); return pushpasswd(L, p); } /*** Fetch named user. @function getpwnam @string name user name @treturn[1] PosixPasswd passwd record for *name*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getpwnam(3) @usage local pwd = require "posix.pwd" t = pwd.getpwnam "root" */ static int Pgetpwnam(lua_State *L) { const char *name = luaL_checkstring(L, 1); struct passwd *p; checknargs(L, 1); errno = 0; /* so we can recognise a successful empty result */ p = getpwnam (name); if (!p && errno != 0) return pusherror(L, "getpwnam"); return pushpasswd(L, p); } /*** Fetch password entry with given user id. @function getpwuid @int uid user id @treturn[1] PosixPasswd passwd record for *uid*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getpwuid(3) @usage local pwd = require "posix.pwd" t = pwd.getpwuid (0) */ static int Pgetpwuid(lua_State *L) { uid_t uid = (uid_t)checkinteger(L, 1); struct passwd *p; checknargs(L, 1); errno = 0; /* so we can recognise a successful empty result */ p = getpwuid(uid); if (!p && errno != 0) return pusherror(L, "getpwuid"); return pushpasswd(L, p); } /*** Rewind next @{getpwent} back to start of database. @function setpwent @see setpwent(3) @see getpwent */ static int Psetpwent(lua_State *L) { checknargs(L, 0); setpwent(); return 0; } static const luaL_Reg posix_pwd_fns[] = { LPOSIX_FUNC( Pendpwent ), LPOSIX_FUNC( Pgetpwent ), LPOSIX_FUNC( Pgetpwnam ), LPOSIX_FUNC( Pgetpwuid ), LPOSIX_FUNC( Psetpwent ), {NULL, NULL} }; LUALIB_API int luaopen_posix_pwd(lua_State *L) { luaL_newlib(L, posix_pwd_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("pwd")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/sched.c000066400000000000000000000066641475444374100165360ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Kernel Thread Scheduling Priority. Where supported by the underlying system, functions to discover and change the kernel thread scheduling priority. If the module loads successfully, but there is no kernel support, then `posix.sched.version` will be set, but the unsupported APIs will be `nil`. @module posix.sched */ /* cannot use unistd.h for _POSIX_PRIORITY_SCHEDULING, because on Linux glibc it is defined even though the APIs are not implemented :-( */ #ifdef HAVE_SCHED_H #include #endif #include "_helpers.c" /*** get scheduling policy @function sched_getscheduler @int[opt=0] pid process to act on, or `0` for caller process @treturn[1] int scheduling policy `SCHED_FIFO`, `SCHED_RR`, `SCHED_OTHER`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see sched_getscheduler(2) */ #if HAVE_SCHED_GETSCHEDULER static int Psched_getscheduler(lua_State *L) { struct sched_param sched_param = {0}; pid_t pid = (pid_t)optinteger(L, 1, 0); checknargs(L, 1); return pushresult(L, sched_getscheduler(pid), NULL); } #endif /*** set scheduling policy/priority @function sched_setscheduler @int[opt=0] pid process to act on, or `0` for caller process @int[opt=`SCHED_OTHER`] policy one of `SCHED_FIFO`, `SCHED_RR` or `SCHED_OTHER` @int[opt=0] priority must be `0` for `SCHED_OTHER`, or else a positive number below 100 for real-time policies @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see sched_setscheduler(2) */ #if HAVE_SCHED_SETSCHEDULER static int Psched_setscheduler(lua_State *L) { struct sched_param sched_param = {0}; pid_t pid = (pid_t)optinteger(L, 1, 0); int policy = optint(L, 2, SCHED_OTHER); sched_param.sched_priority = optint (L, 3, 0); checknargs(L, 3); return pushresult(L, sched_setscheduler(pid, policy, &sched_param), NULL); } #endif static const luaL_Reg posix_sched_fns[] = { #if HAVE_SCHED_GETSCHEDULER LPOSIX_FUNC( Psched_getscheduler ), #endif #if HAVE_SCHED_SETSCHEDULER LPOSIX_FUNC( Psched_setscheduler ), #endif {NULL, NULL} }; /*** Constants. @section constants */ /*** Scheduler constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sched @int SCHED_FIFO first-in, first-out scheduling policy @int SCHED_RR round-robin scheduling policy @int SCHED_OTHER another scheduling policy @usage -- Print scheduler constants supported on this host. for name, value in pairs (require "posix.sched") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sched(lua_State *L) { luaL_newlib(L, posix_sched_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sched")); lua_setfield(L, -2, "version"); /* Psched_setscheduler flags */ #ifdef SCHED_FIFO LPOSIX_CONST( SCHED_FIFO ); #endif #ifdef SCHED_RR LPOSIX_CONST( SCHED_RR ); #endif #ifdef SCHED_OTHER LPOSIX_CONST( SCHED_OTHER ); #endif return 1; } luaposix-36.3/ext/posix/signal.c000066400000000000000000000242461475444374100167210ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Software Signal Facilities. Constants and functions for propagating signals among processes. Note that `posix.signal.signal` is implemented with sigaction(2) for consistent semantics across platforms. Also note that installed signal handlers are not called immediatly upon occurrence of a signal. Instead, in order to keep the interperter state clean, they are executed in the context of a debug hook which is called as soon as the interpreter enters a new function, returns from the currently executing function, or after the execution of the current instruction has ended. @module posix.signal */ #include #include "_helpers.c" /*** Send a signal to the given process. @function kill @int pid process to act on @int[opt=`SIGTERM` sig signal to send @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see kill(2) */ static int Pkill(lua_State *L) { pid_t pid = (pid_t)checkinteger(L, 1); int sig = optint(L, 2, SIGTERM); checknargs(L, 2); return pushresult(L, kill(pid, sig), NULL); } /*** Send a signal to the given process group. @function killpg @int pgrp group id to act on, or `0` for the sending process`s group @int[opt=`SIGTERM`] sig signal to send @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see killpg(2) */ static int Pkillpg(lua_State *L) { pid_t pgrp = (pid_t)checkinteger(L, 1); int sig = optint(L, 2, SIGTERM); checknargs(L, 2); return pushresult(L, killpg(pgrp, sig), NULL); } /*** Raise a signal on this process. @function raise @int sig signal to send @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see raise(3) */ static int Praise(lua_State *L) { int sig = checkint(L, 1); checknargs(L, 1); lua_pop(L, 1); return pushintegerresult(raise(sig)); } static lua_State *signalL; #define SIGNAL_QUEUE_MAX 25 static volatile sig_atomic_t signal_pending, defer_signal; static volatile sig_atomic_t signal_count = 0; static volatile sig_atomic_t signals[SIGNAL_QUEUE_MAX]; #define sigmacros_map \ MENTRY( _DFL ) \ MENTRY( _IGN ) static const char *const Ssigmacros[] = { #define MENTRY(_s) LPOSIX_STR_1(LPOSIX_SPLICE(_SIG, _s)), sigmacros_map #undef MENTRY NULL }; static void (*Fsigmacros[])(int) = { #define MENTRY(_s) LPOSIX_SPLICE(SIG, _s), sigmacros_map #undef MENTRY NULL }; static void sig_handle (lua_State *L, lua_Debug *LPOSIX_UNUSED (ar)) { /* Block all signals until we have run the Lua signal handler */ sigset_t mask, oldmask; sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &oldmask); lua_sethook(L, NULL, 0, 0); /* Get signal handlers table */ lua_pushlightuserdata(L, &signalL); lua_rawget(L, LUA_REGISTRYINDEX); /* Empty the signal queue */ while (signal_count--) { sig_atomic_t signalno = signals[signal_count]; /* Get handler */ lua_pushinteger(L, signalno); lua_gettable(L, -2); /* Call handler with signal number */ lua_pushinteger(L, signalno); if (lua_pcall(L, 1, 0, 0) != 0) fprintf(stderr,"error in signal handler %ld: %s\n", (long)signalno, lua_tostring(L,-1)); } signal_count = 0; /* reset global to initial state */ /* Having run the Lua signal handler, restore original signal mask */ sigprocmask(SIG_SETMASK, &oldmask, NULL); } static void sig_postpone (int i) { if (defer_signal) { signal_pending = i; return; } if (signal_count == SIGNAL_QUEUE_MAX) return; defer_signal++; /* Queue signals */ signals[signal_count] = i; signal_count ++; lua_sethook(signalL, sig_handle, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); defer_signal--; /* re-raise any pending signals */ if (defer_signal == 0 && signal_pending != 0) raise (signal_pending); } static int sig_handler_wrap (lua_State *L) { int sig = luaL_checkinteger(L, lua_upvalueindex(1)); void (*handler)(int) = lua_touserdata(L, lua_upvalueindex(2)); handler(sig); return 0; } /*** Install a signal handler for this signal number. Although this is the same API as signal(2), it uses sigaction for guaranteed semantics. @function signal @int signum @tparam[opt=SIG_DFL] function handler function, or `SIG_IGN` or `SIG_DFL` constants @param[opt] flags the `sa_flags` element of `struct sigaction` @treturn function previous handler function @see sigaction(2) @see signal.lua */ static int Psignal (lua_State *L) { struct sigaction sa, oldsa; int sig = checkint(L, 1), ret; void (*handler)(int) = sig_postpone; checknargs(L, 3); /* Check handler is OK */ switch (lua_type(L, 2)) { case LUA_TNIL: case LUA_TSTRING: handler = Fsigmacros[luaL_checkoption(L, 2, "SIG_DFL", Ssigmacros)]; break; case LUA_TFUNCTION: if (lua_tocfunction(L, 2) == sig_handler_wrap) { lua_getupvalue(L, 2, 1); handler = lua_touserdata(L, -1); lua_pop(L, 1); } break; default: argtypeerror(L, 2, "function, nil or string"); break; } /* Set up C signal handler, getting old handler */ sa.sa_handler = handler; sa.sa_flags = optint(L, 3, 0); sigfillset(&sa.sa_mask); ret = sigaction(sig, &sa, &oldsa); if (ret == -1) return 0; /* Set Lua handler if necessary */ if (handler == sig_postpone) { lua_pushlightuserdata(L, &signalL); /* We could use an upvalue, but we need this for sig_handle anyway. */ lua_rawget(L, LUA_REGISTRYINDEX); lua_pushvalue(L, 1); lua_pushvalue(L, 2); lua_rawset(L, -3); lua_pop(L, 1); } /* Push old handler as result */ if (oldsa.sa_handler == sig_postpone) { lua_pushlightuserdata(L, &signalL); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushvalue(L, 1); lua_rawget(L, -2); } else if (oldsa.sa_handler == SIG_DFL) lua_pushstring(L, "SIG_DFL"); else if (oldsa.sa_handler == SIG_IGN) lua_pushstring(L, "SIG_IGN"); else { lua_pushinteger(L, sig); lua_pushlightuserdata(L, oldsa.sa_handler); lua_pushcclosure(L, sig_handler_wrap, 2); } return 1; } static const luaL_Reg posix_signal_fns[] = { LPOSIX_FUNC( Pkill ), LPOSIX_FUNC( Pkillpg ), LPOSIX_FUNC( Praise ), LPOSIX_FUNC( Psignal ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Signal constants. Any constants not available in the underlying system will be `nil` valued. @table posix.signal @int SIGABRT abort () @int SIGALRM alarm clock @int SIGBUS bus error @int SIGCHLD to parent on child stop or exit @int SIGCONT continue a stopped process @int SIGFPE floating point error @int SIGHUP hangup @int SIGILL illegal instruction @int SIGINFO information request @int SIGINT interrupt @int SIGKILL kill @int SIGPIPE write on pipe with no reader @int SIGQUIT quit @int SIGSEGV segmentation violation @int SIGSTOP stop @int SIGSYS bad argument to system call @int SIGTERM terminate @int SIGTRAP trace trap @int SIGTSTP stop signal from tty @int SIGTTIN to readers process group on background tty read @int SIGTTOU to readers process group on background tty output @int SIGURG urgent condition on i/o channel @int SIGUSR1 user defined @int SIGUSR2 user defined @int SIGVTALRM virtual time alarm @int SIGWINCH window size change @int SIGXCPU exceeded cpu time limit @int SIGXFSZ exceeded file size limit @int SA_NOCLDSTOP do not generate a SIGCHLD on child stop @int SA_NOCLDWAIT don't keep zombies child processes @int SA_NODEFER don't mask the signal we're delivering @int SA_RESETHAND reset to SIG_DFL when taking a signal @int SA_RESTART allow syscalls to restart instead of returning EINTR @usage -- Print signal constants supported on this host. for name, value in pairs (require "posix.signal") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_signal(lua_State *L) { luaL_newlib(L, posix_signal_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("signal")); lua_setfield(L, -2, "version"); /* Signals table stored in registry for Psignal and sig_handle */ lua_pushlightuserdata(L, &signalL); lua_newtable(L); lua_rawset(L, LUA_REGISTRYINDEX); signalL = L; /* For sig_postpone */ /* Signals */ #ifdef SIGABRT LPOSIX_CONST( SIGABRT ); #endif #ifdef SIGALRM LPOSIX_CONST( SIGALRM ); #endif #ifdef SIGBUS LPOSIX_CONST( SIGBUS ); #endif #ifdef SIGCHLD LPOSIX_CONST( SIGCHLD ); #endif #ifdef SIGCONT LPOSIX_CONST( SIGCONT ); #endif #ifdef SIGFPE LPOSIX_CONST( SIGFPE ); #endif #ifdef SIGHUP LPOSIX_CONST( SIGHUP ); #endif #ifdef SIGILL LPOSIX_CONST( SIGILL ); #endif #ifdef SIGINFO LPOSIX_CONST( SIGINFO ); #endif #ifdef SIGINT LPOSIX_CONST( SIGINT ); #endif #ifdef SIGKILL LPOSIX_CONST( SIGKILL ); #endif #ifdef SIGPIPE LPOSIX_CONST( SIGPIPE ); #endif #ifdef SIGQUIT LPOSIX_CONST( SIGQUIT ); #endif #ifdef SIGSEGV LPOSIX_CONST( SIGSEGV ); #endif #ifdef SIGSTOP LPOSIX_CONST( SIGSTOP ); #endif #ifdef SIGTERM LPOSIX_CONST( SIGTERM ); #endif #ifdef SIGTSTP LPOSIX_CONST( SIGTSTP ); #endif #ifdef SIGTTIN LPOSIX_CONST( SIGTTIN ); #endif #ifdef SIGTTOU LPOSIX_CONST( SIGTTOU ); #endif #ifdef SIGUSR1 LPOSIX_CONST( SIGUSR1 ); #endif #ifdef SIGUSR2 LPOSIX_CONST( SIGUSR2 ); #endif #ifdef SIGSYS LPOSIX_CONST( SIGSYS ); #endif #ifdef SIGTRAP LPOSIX_CONST( SIGTRAP ); #endif #ifdef SIGURG LPOSIX_CONST( SIGURG ); #endif #ifdef SIGVTALRM LPOSIX_CONST( SIGVTALRM ); #endif #ifdef SIGWINCH LPOSIX_CONST( SIGWINCH ); #endif #ifdef SIGXCPU LPOSIX_CONST( SIGXCPU ); #endif #ifdef SIGXFSZ LPOSIX_CONST( SIGXFSZ ); #endif /* String constants */ lua_pushliteral(L, "SIG_DFL"); lua_setfield(L, -2, "SIG_DFL"); lua_pushliteral(L, "SIG_IGN"); lua_setfield(L, -2, "SIG_IGN"); /* Signal flags */ #ifdef SA_NOCLDSTOP LPOSIX_CONST( SA_NOCLDSTOP ); #endif #ifdef SA_NOCLDWAIT LPOSIX_CONST( SA_NOCLDWAIT ); #endif #ifdef SA_NODEFER LPOSIX_CONST( SA_NODEFER ); #endif #ifdef SA_RESETHAND LPOSIX_CONST( SA_RESETHAND ); #endif #ifdef SA_RESTART LPOSIX_CONST( SA_RESTART ); #endif return 1; } luaposix-36.3/ext/posix/stdio.c000066400000000000000000000115311475444374100165570ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** A few Standard I/O functions not already in Lua core. @module posix.stdio */ #include #include "_helpers.c" /*** Name of controlling terminal. @function ctermid @treturn string controlling terminal for current process @see ctermid(3) */ static int Pctermid(lua_State *L) { char b[L_ctermid]; checknargs(L, 0); return pushstringresult(ctermid(b)); } /*** File descriptor corresponding to a Lua file object. @function fileno @tparam file file Lua file object @treturn[1] int file descriptor for *file*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fileno(3) @usage local stdio = require "posix.stdio" local unistd = require "posix.unistd" assert (stdio.fileno (io.stdout) == unistd.STDOUT_FILENO) */ static int Pfileno(lua_State *L) { FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE); checknargs(L, 1); return pushresult(L, fileno(f), NULL); } /* This helper function is adapted from Lua 5.3's liolib.c */ static int stdio_fclose (lua_State *L) { int res = -1; luaL_Stream *p = ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)); if (p->f == NULL) return 0; res = fclose(p->f); p->f = NULL; return luaL_fileresult(L, (res == 0), NULL); } /* This function could be used more generally; see */ static int pushfile (lua_State *L, int fd, const char *mode) { luaL_Stream *p = (luaL_Stream *)lua_newuserdata(L, sizeof(luaL_Stream)); luaL_getmetatable(L, LUA_FILEHANDLE); lua_setmetatable(L, -2); #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501 /* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h, LuaJIT uses luaconf_h. If you use PUC-Rio's include files but LuaJIT's library, you're on your own here! */ # if !defined(luaconf_h) lua_createtable(L, 0, 1); lua_pushcfunction(L, stdio_fclose); lua_setfield(L, -2, "__close"); lua_setfenv(L, -2); /* set fenv for 'fdopen' */ # endif #endif p->closef = stdio_fclose; p->f = fdopen(fd, mode); return p->f != NULL; } /*** Create a Lua file object from a file descriptor. @function fdopen @tparam int fd file descriptor @tparam string mode the mode in which to open the file descriptor @treturn[1] file Lua file object *fd*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fdopen(3) @usage local fdopen = require "posix.stdio".fdopen local STDOUT_FILENO = require "posix.unistd".STDOUT_FILENO stdout = fdopen (STDOUT_FILENO, "w") */ static int Pfdopen(lua_State *L) /** fdopen(fd, mode) */ { int fd = checkint(L, 1); const char *mode = luaL_checkstring(L, 2); checknargs(L, 2); if (!pushfile(L, fd, mode)) return pusherror(L, "fdopen"); return 1; } /*** Change the name or location of a file @function rename @tparam string oldpath @tparam string newpath @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see rename(2) @usage local ok, errmsg = P.rename (oldpath, newpath) if not ok then error (errmsg) end */ static int Prename(lua_State *L) /** rename(oldpath, newpath) */ { const char *oldpath = luaL_checkstring(L, 1); const char *newpath = luaL_checkstring(L, 2); checknargs(L, 2); return pushresult(L, rename(oldpath, newpath), NULL); } static const luaL_Reg posix_stdio_fns[] = { LPOSIX_FUNC( Pctermid ), LPOSIX_FUNC( Pfileno ), LPOSIX_FUNC( Pfdopen ), LPOSIX_FUNC( Prename ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Stdio constants. Any constants not available in the underlying system will be `nil` valued. @table posix.stdio @int _IOFBF fully buffered @int _IOLBF line buffered @int _IONBF unbuffered @int BUFSIZ size of buffer @int EOF end of file @int FOPEN_MAX maximum number of open files @int FILENAME_MAX maximum length of filename @usage -- Print stdio constants supported on this host. for name, value in pairs (require "posix.stdio") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_stdio(lua_State *L) { luaL_newlib(L, posix_stdio_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("stdio")); lua_setfield(L, -2, "version"); /* stdio.h constants */ /* Those that are omitted already have a Lua interface, or alternative. */ LPOSIX_CONST( _IOFBF ); LPOSIX_CONST( _IOLBF ); LPOSIX_CONST( _IONBF ); LPOSIX_CONST( BUFSIZ ); LPOSIX_CONST( EOF ); LPOSIX_CONST( FOPEN_MAX ); LPOSIX_CONST( FILENAME_MAX ); return 1; } luaposix-36.3/ext/posix/stdlib.c000066400000000000000000000153741475444374100167270ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Standard Posix Library functions. @module posix.stdlib */ #include /* for open(2) */ #include #include "_helpers.c" /*** Abort the program immediately. @function abort @see abort(3) */ static int Pabort(lua_State *L) { checknargs(L, 0); abort(); return 0; /* Avoid a compiler warning (or possibly cause one if the compiler's too clever, sigh). */ } /*** Get value of environment variable, or _all_ variables. @function getenv @string[opt] name if nil, get all @return value if name given, otherwise a name-indexed table of values. @see getenv(3) @usage for a,b in pairs(posix.getenv()) do print(a, b) end */ static int Pgetenv(lua_State *L) { checknargs(L, 1); if (lua_isnoneornil(L, 1)) { extern char **environ; char **e; lua_newtable(L); for (e=environ; *e!=NULL; e++) { char *s=*e; char *eq=strchr(s, '='); if (eq==NULL) /* will this ever happen? */ { lua_pushstring(L, s); lua_pushboolean(L, 1); } else { lua_pushlstring(L, s, eq-s); lua_pushstring(L, eq+1); } lua_settable(L, -3); } } else lua_pushstring(L, getenv(optstring(L, 1, "lua_isnoneornil prevents this happening"))); return 1; } /*** Grant access to a slave pseudoterminal @function grantpt @int fd descriptor returned by openpt @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see grantpt(3) @see openpt @see ptsname @see unlockpt */ static int Pgrantpt(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, grantpt(fd), "grantpt"); } /*** Create a unique temporary directory. @function mkdtemp @string templ pattern that ends in six 'X' characters @treturn[1] string path to directory, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see mkdtemp(3) */ static int Pmkdtemp(lua_State *L) { #if defined LPOSIX_2008_COMPLIANT const char *path = luaL_checkstring(L, 1); size_t path_len = strlen(path) + 1; void *ud; lua_Alloc lalloc; char *tmppath; char *r; checknargs(L, 1); lalloc = lua_getallocf(L, &ud); if ((tmppath = lalloc(ud, NULL, 0, path_len)) == NULL) return pusherror(L, "lalloc"); strcpy(tmppath, path); if ((r = mkdtemp(tmppath))) lua_pushstring(L, tmppath); lalloc(ud, tmppath, path_len, 0); return (r == NULL) ? pusherror(L, path) : 1; #else return binding_notimplemented(L, "mkdtemp", "C"); #endif } /*** Create a unique temporary file. @function mkstemp @string templ pattern that ends in six 'X' characters @treturn[1] int open file descriptor @treturn[1] string path to file, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see mkstemp(3) @usage local stdlib = require "posix.stdlib" stdlib.mkstemp 'wooXXXXXX' */ static int Pmkstemp(lua_State *L) { const char *path = luaL_checkstring(L, 1); size_t path_len = strlen(path) + 1; void *ud; lua_Alloc lalloc; char *tmppath; int r; checknargs(L, 1); lalloc = lua_getallocf(L, &ud); if ((tmppath = lalloc(ud, NULL, 0, path_len)) == NULL) return pusherror(L, "lalloc"); strcpy(tmppath, path); r = mkstemp(tmppath); if (r != -1) { lua_pushinteger(L, r); lua_pushstring(L, tmppath); } lalloc(ud, tmppath, path_len, 0); return (r == -1) ? pusherror(L, path) : 2; } /*** Open a pseudoterminal. @function openpt @int oflags bitwise OR of zero or more of `O_RDWR` and `O_NOCTTY` @return[1] file descriptor of pseudoterminal, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see posix_openpt(3) @see grantpt @see ptsname @see unlockpt */ static int Popenpt(lua_State *L) { int flags = checkint(L, 1); checknargs(L, 1); /* The name of the pseudo-device is specified by POSIX */ return pushresult(L, open("/dev/ptmx", flags), NULL); } /*** Get the name of a slave pseudo-terminal @function ptsname @int fd descriptor returned by @{openpt} @return[1] path name of the slave terminal device, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see ptsname(3) @see grantpt @see unlockpt */ static int Pptsname(lua_State *L) { int fd = checkint(L, 1); const char* slave; checknargs(L, 1); slave = ptsname(fd); if (!slave) return pusherror(L, "getptsname"); return pushstringresult(slave); } /*** Find canonicalized absolute pathname. @function realpath @string path file to act on @treturn[1] string canonicalized absolute path, if successful @return[2] nil @treturn[2] string error messag @treturn[2] int errnum @see realpath(3) */ static int Prealpath(lua_State *L) { char *s; checknargs(L, 1); if ((s = realpath(luaL_checkstring(L, 1), NULL)) == NULL) return pusherror(L, "realpath"); lua_pushstring(L, s); free(s); return 1; } /*** Set an environment variable for this process. (Child processes will inherit this) @function setenv @string name @string[opt] value (maybe nil, meaning 'unset') @param[opt] overwrite non-nil prevents overwriting a variable @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see setenv(3) */ static int Psetenv(lua_State *L) { const char *name=luaL_checkstring(L, 1); const char *value=optstring(L, 2, NULL); checknargs(L, 3); if (value==NULL) { unsetenv(name); return pushresult(L, 0, NULL); } else { int overwrite=lua_isnoneornil(L, 3) || lua_toboolean(L, 3); return pushresult(L, setenv(name,value,overwrite), NULL); } } /*** Unlock a pseudoterminal master/slave pair @function unlockpt @int fd descriptor returned by openpt @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see unlockpt(3) @see openpt @see ptsname @see grantpt */ static int Punlockpt(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, unlockpt(fd), "unlockpt"); } static const luaL_Reg posix_stdlib_fns[] = { LPOSIX_FUNC( Pabort ), LPOSIX_FUNC( Pgetenv ), LPOSIX_FUNC( Pgrantpt ), LPOSIX_FUNC( Pmkdtemp ), LPOSIX_FUNC( Pmkstemp ), LPOSIX_FUNC( Popenpt ), LPOSIX_FUNC( Pptsname ), LPOSIX_FUNC( Prealpath ), LPOSIX_FUNC( Psetenv ), LPOSIX_FUNC( Punlockpt ), {NULL, NULL} }; LUALIB_API int luaopen_posix_stdlib(lua_State *L) { luaL_newlib(L, posix_stdlib_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("stdlib")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/sys/000077500000000000000000000000001475444374100161065ustar00rootroot00000000000000luaposix-36.3/ext/posix/sys/msg.c000066400000000000000000000202401475444374100170360ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Sys V Message Queue Operations. Where supported by the underlying system, functions to send and receive interprocess messages. If the module loads successfully, but there is no system support, then `posix.sys.msg.version` will be set, but the unsupported APIs wil be `nil`. @module posix.sys.msg */ #if HAVE_SYS_MSG_H && HAVE_MSGRCV && HAVE_MSGSND # define HAVE_SYSV_MESSAGING 1 #else # define HAVE_SYSV_MESSAGING 0 #endif #include "_helpers.c" #if HAVE_SYSV_MESSAGING #include #include #include /*** Message queue record. @table PosixMsqid @int msg_qnum number of messages on the queue @int msg_qbytes number of bytes allowed on the queue @int msg_lspid process id of last msgsnd @int msg_lrpid process id of last msgrcv @int msg_stime time of last msgsnd @int msg_rtime time of last msgrcv @int msg_ctime time of last change */ static int pushmsqid(lua_State *L, struct msqid_ds *msqid) { if (!msqid) return lua_pushnil(L), 1; lua_createtable(L, 0, 8); setintegerfield(msqid, msg_qnum); setintegerfield(msqid, msg_qbytes); setintegerfield(msqid, msg_lspid); setintegerfield(msqid, msg_lrpid); setintegerfield(msqid, msg_stime); setintegerfield(msqid, msg_rtime); setintegerfield(msqid, msg_ctime); lua_createtable(L, 0, 5); pushintegerfield("uid", msqid->msg_perm.uid); pushintegerfield("gid", msqid->msg_perm.gid); pushintegerfield("cuid", msqid->msg_perm.cuid); pushintegerfield("cgid", msqid->msg_perm.cgid); pushintegerfield("mode", msqid->msg_perm.mode); lua_setfield(L, -2, "msg_perm"); settypemetatable("PosixMsqid"); return 1; } static const char *Smsqid_fields[] = { "msg_qbytes", "msg_perm" }; static const char *Sipcperm_fields[] = { "uid", "gid", "mode" }; static void tomsqid(lua_State *L, int index, struct msqid_ds *msqid) { int subindex; luaL_checktype(L, index, LUA_TTABLE); /* Copy fields to msqid struct */ msqid->msg_qbytes = (msglen_t)checkintegerfield(L, index, "msg_qbytes"); checkfieldtype(L, index, "msg_perm", LUA_TTABLE, "table"); subindex = lua_gettop(L); msqid->msg_perm.uid = (uid_t)checkintegerfield(L, subindex, "uid"); msqid->msg_perm.gid = (gid_t)checkintegerfield(L, subindex, "gid"); msqid->msg_perm.mode = checkintfield(L, subindex, "mode"); checkfieldnames(L, index, Smsqid_fields); checkfieldnames(L, subindex, Sipcperm_fields); } /*** @function msgctl @int id message queue identifier returned by @{msgget} @int cmd one of `IPC_STAT`, `IPC_SET` or `IPC_RMID` @PosixMsqid[opt=nil] values to set with `IPC_SET` @treturn[1] PosixMsqid table for *id*, with `IPC_STAT`, if successful @treturn[2] non-nil, with `IPC_SET` or `IPC_RMID`, if successful @treturn[3] nil otherwise @treturn[3] string error message @treturn[3] int errnum @see msgctl(2) @usage local sysvmsg = require 'posix.sys.msg' local msq = sysvmsg.msgget(sysvmsg.IPC_PRIVATE) local msqid, errmsg = sysvmsg.msgctl(msq, sysvmsg.IPC_STAT) assert(msqid, errmsg) assert(sysvmsg.msgctl(msq, sysvmsg.IPC_RMID)) */ static int Pmsgctl(lua_State *L) { int id = checkint(L, 1); int cmd = checkint(L, 2); struct msqid_ds msqid; switch (cmd) { case IPC_RMID: checknargs(L, 2); return pushresult(L, msgctl(id, cmd, NULL), "msgctl"); case IPC_SET: checknargs(L, 3); tomsqid(L, 3, &msqid); return pushresult(L, msgctl(id, cmd, &msqid), "msgctl"); case IPC_STAT: checknargs(L, 2); if (msgctl(id, cmd, &msqid) < 0) return pusherror(L, "msgctl"); return pushmsqid(L, &msqid); default: checknargs(L, 3); return pusherror(L, "unsupported cmd value"); } } /*** Get a message queue identifier @function msgget @int key message queue id, or `IPC_PRIVATE` for a new queue @int[opt=0] flags bitwise OR of zero or more from `IPC_CREAT` and `IPC_EXCL`, and access permissions `S_IRUSR`, `S_IWUSR`, `S_IRGRP`, `S_IWGRP`, `S_IROTH` and `S_IWOTH` (from @{posix.sys.stat}) @treturn[1] int message queue identifier, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see msgget(2) */ static int Pmsgget(lua_State *L) { checknargs (L, 2); return pushresult(L, msgget((key_t)checkinteger(L, 1), optint(L, 2, 0)), "msgget"); } /*** Send message to a message queue @function msgsnd @int id message queue identifier returned by @{msgget} @int type arbitrary message type @string message content @int[opt=0] flags optionally `IPC_NOWAIT` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see msgsnd(2) */ static int Pmsgsnd(lua_State *L) { void *ud; lua_Alloc lalloc = lua_getallocf(L, &ud); struct { long mtype; char mtext[0]; } *msg; size_t len; size_t msgsz; ssize_t r; int msgid = checkint(L, 1); long msgtype = checklong(L, 2); const char *msgp = luaL_checklstring(L, 3, &len); int msgflg = optint(L, 4, 0); checknargs(L, 4); msgsz = sizeof(long) + len; if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL) return pusherror(L, "lalloc"); msg->mtype = msgtype; memcpy(msg->mtext, msgp, len); r = msgsnd(msgid, msg, msgsz, msgflg); lua_pushinteger(L, r); lalloc(ud, msg, msgsz, 0); return (r == -1 ? pusherror(L, NULL) : 1); } /*** Receive message from a message queue @function msgrcv @int id message queue identifier returned by @{msgget} @int size maximum message size @int type message type (optional, default - 0) @int[opt=0] flags bitwise OR of zero or more of `IPC_NOWAIT`, `MSG_EXCEPT` and `MSG_NOERROR` @treturn[1] int message type from @{msgsnd} @treturn[1] string message text, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see msgrcv(2) */ static int Pmsgrcv(lua_State *L) { int msgid = checkint(L, 1); size_t msgsz = (size_t)checkinteger(L, 2); long msgtyp = optlong(L, 3, 0); int msgflg = optint(L, 4, 0); void *ud; lua_Alloc lalloc; struct { long mtype; char mtext[0]; } *msg; checknargs(L, 4); lalloc = lua_getallocf(L, &ud); if ((msg = lalloc(ud, NULL, 0, msgsz)) == NULL) return pusherror(L, "lalloc"); int res = msgrcv(msgid, msg, msgsz, msgtyp, msgflg); if (res != -1) { lua_pushinteger(L, msg->mtype); lua_pushlstring(L, msg->mtext, res - sizeof(long)); } lalloc(ud, msg, msgsz, 0); return (res == -1) ? pusherror(L, NULL) : 2; } #endif /*!HAVE_SYSV_MESSAGING*/ static const luaL_Reg posix_sys_msg_fns[] = { #if HAVE_SYSV_MESSAGING LPOSIX_FUNC( Pmsgctl ), LPOSIX_FUNC( Pmsgget ), LPOSIX_FUNC( Pmsgsnd ), LPOSIX_FUNC( Pmsgrcv ), #endif {NULL, NULL} }; /*** Constants. @section constants */ /*** Message constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sys.msg @int IPC_STAT return a Msqid table from msgctl @int IPC_SET set the Msqid fields from msgctl @int IPC_RMID remove a message queue with msgctl @int IPC_CREAT create entry if key does not exist @int IPC_EXCL fail if key exists @int IPC_PRIVATE private key @int IPC_NOWAIT error if request must wait @int MSG_EXCEPT read messages with differing type @int MSG_NOERROR truncate received message rather than erroring @usage -- Print msg constants supported on this host. for name, value in pairs (require "posix.sys.msg") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_msg(lua_State *L) { luaL_newlib(L, posix_sys_msg_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.msg")); lua_setfield(L, -2, "version"); #if HAVE_SYSV_MESSAGING LPOSIX_CONST( IPC_CREAT ); # ifdef MSG_EXCEPT LPOSIX_CONST( MSG_EXCEPT ); # endif LPOSIX_CONST( IPC_EXCL ); # ifdef MSG_NOERROR LPOSIX_CONST( MSG_NOERROR ); # endif LPOSIX_CONST( IPC_NOWAIT ); LPOSIX_CONST( IPC_PRIVATE ); LPOSIX_CONST( IPC_RMID ); LPOSIX_CONST( IPC_SET ); LPOSIX_CONST( IPC_STAT ); #endif return 1; } luaposix-36.3/ext/posix/sys/resource.c000066400000000000000000000105441475444374100201050ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Control Maximum System Resource Consumption. @module posix.sys.resource */ #include #include "_helpers.c" /* OpenBSD 5.6 recommends using RLIMIT_DATA in place of missing RLIMIT_AS */ #ifndef RLIMIT_AS # define RLIMIT_AS RLIMIT_DATA #endif /*** Resource limit record. @table PosixRlimit @int rlim_cur current soft limit @int rlim_max hard limit */ static int pushrlimit(lua_State *L, struct rlimit *lim) { if (!lim) return lua_pushnil(L), 1; lua_createtable(L, 0, 2); setintegerfield(lim, rlim_cur); setintegerfield(lim, rlim_max); settypemetatable("PosixRlimit"); return 1; } /*** Get resource limits for this process. @function getrlimit @int resource one of `RLIMIT_CORE`, `RLIMIT_CPU`, `RLIMIT_DATA`, `RLIMIT_FSIZE`, `RLIMIT_NOFILE`, `RLIMIT_STACK` or `RLIMIT_AS` @treturn[1] int softlimit @treturn[1] int hardlimit, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getrlimit(2) @see setrlimit @usage local sysres = require "posix.sys.resource" sysres.getrlimit(sysres.RLIMIT_NOFILE) */ static int Pgetrlimit(lua_State *L) { struct rlimit lim; int r; checknargs(L, 1); r = getrlimit(checkint(L, 1), &lim); if (r < 0) return pusherror(L, "getrlimit"); return pushrlimit(L, &lim); } /*** Set a resource limit for subsequent child processes. @function setrlimit @int resource one of `RLIMIT_CORE`, `RLIMIT_CPU`, `RLIMIT_DATA`, `RLIMIT_FSIZE`, `RLIMIT_NOFILE`, `RLIMIT_STACK` or `RLIMIT_AS` @param[opt] softlimit process may receive a signal when reached @param[opt] hardlimit process may be terminated when reached @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see setrlimit(2) @see getrlimit @see limit.lua @usage local sysres = require "posix.sys.resource" local lim = sysres.getlimit(sysres.RLIMIT_NOFILE) lim.rlim_cur = lim.rlim_cur / 2 sysres.setrlimit(sysres.RLIMIT_NOFILE, lim) */ static const char *Srlimit_fields[] = { "rlim_cur", "rlim_max" }; static int Psetrlimit(lua_State *L) { struct rlimit lim; int rid = checkint(L, 1); luaL_checktype(L, 2, LUA_TTABLE); checknargs(L, 2); lim.rlim_cur = (rlim_t)checkintegerfield(L, 2, "rlim_cur"); lim.rlim_max = (rlim_t)checkintegerfield(L, 2, "rlim_max"); checkfieldnames(L, 2, Srlimit_fields); return pushresult(L, setrlimit(rid, &lim), "setrlimit"); } static const luaL_Reg posix_sys_resource_fns[] = { LPOSIX_FUNC( Pgetrlimit ), LPOSIX_FUNC( Psetrlimit ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Rlimit constants. @table posix.sys.resource @int RLIM_INFINITY unlimited resource usage @int RLIM_SAVED_CUR saved current resource soft limit @int RLIM_SAVED_MAX saved resource hard limit @int RLIMIT_CORE maximum bytes allowed for a core file @int RLIMIT_CPU maximum cputime secconds allowed per process @int RLIMIT_DATA maximum data segment bytes per process @int RLIMIT_FSIZE maximum bytes in any file @int RLIMIT_NOFILE maximum number of open files per process @int RLIMIT_STACK maximum stack segment bytes per process @int RLIMIT_AS maximum bytes total address space per process @usage -- Print resource constants supported on this host. for name, value in pairs (require "posix.sys.resource") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_resource(lua_State *L) { luaL_newlib(L, posix_sys_resource_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.resource")); lua_setfield(L, -2, "version"); LPOSIX_CONST( RLIM_INFINITY ); #if defined RLIM_SAVED_CUR LPOSIX_CONST( RLIM_SAVED_CUR ); #endif #if defined RLIM_SAVED_MAX LPOSIX_CONST( RLIM_SAVED_MAX ); #endif LPOSIX_CONST( RLIMIT_CORE ); LPOSIX_CONST( RLIMIT_CPU ); LPOSIX_CONST( RLIMIT_DATA ); LPOSIX_CONST( RLIMIT_FSIZE ); LPOSIX_CONST( RLIMIT_NOFILE ); LPOSIX_CONST( RLIMIT_STACK ); LPOSIX_CONST( RLIMIT_AS ); return 1; } luaposix-36.3/ext/posix/sys/socket.c000066400000000000000000000731531475444374100175530ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** BSD Sockets. Where supported by the underlying system, functions and constants to create, connect and communicate over BSD sockets. If the module loads successfully, but there is no kernel support, then `posix.sys.socket.version` will be set, but the unsupported APIs will be `nil`. @module posix.sys.socket */ #include "_helpers.c" /* For LPOSIX_2001_COMPLIANT */ #include #if LPOSIX_2001_COMPLIANT #include #if HAVE_LINUX_NETLINK_H #include #endif #if HAVE_LINUX_IF_PACKET_H #include #endif #include /* Needs to be before net/if.h on OpenBSD 5.6 */ #ifdef HAVE_NET_IF_H #include #endif #include #include #include #include #include #include /*** Socket address. All sockaddr tables have the *family* field, and depending on its value, also a subset of the following fields too. @table sockaddr @int family one of `AF_INET`, `AF_INET6`, `AF_UNIX`, `AF_NETLINK` or `AF_PACKET` @int[opt] port socket port number for `AF_INET` (and equivalently `AF_INET6`) *family* @string[opt] addr socket host address in correct format, for `AF_INET` *family* @int[opt] socktype one of `SOCK_STREAM`, `SOCK_DGRAM` or `SOCK_RAW` for `AF_INET` *family* @string[opt] canonname canonical name for service location, for `AF_INET` *family* @int[opt] protocol one of `IPPROTO_TCP` or `IPPROTO_UDP`, for `AF_INET` *family* @string[opt] path location in file system, for `AF_UNIX` *family* @int[opt] pid process identifier, for `AF_NETLINK` *family* @int[opt] groups process group owner identifier, for `AF_NETLINK` *family* @int[opt] ifindex interface index, for `AF_PACKET` *family* */ /*** Address information hints. @table PosixAddrInfo @int family one of `AF_INET`, `AF_INET6`, `AF_UNIX`, `AF_NETLINK` or `AF_PACKET` @int flags bitwise OR of zero or more of `AI_ADDRCONFIG`, `AI_ALL`, `AI_CANONNAME`, `AI_NUMERICHOST`, `AI_NUMERICSERV`, `AI_PASSIVE` and `AI_V4MAPPED` @int socktype one of `SOCK_STREAM`, `SOCK_DGRAM` or `SOCK_RAW` @int protocol one of `IPPROTO_TCP` or `IPPROTO_UDP` */ static int pushsockaddrinfo(lua_State *L, int family, struct sockaddr *sa) { char addr[INET6_ADDRSTRLEN]; lua_newtable(L); pushintegerfield("family", family); switch (family) { case AF_INET: { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; inet_ntop(family, &sa4->sin_addr, addr, sizeof addr); pushintegerfield("port", ntohs(sa4->sin_port)); pushstringfield("addr", addr); break; } case AF_INET6: { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; inet_ntop(family, &sa6->sin6_addr, addr, sizeof addr); pushintegerfield("port", ntohs(sa6->sin6_port)); pushstringfield("addr", addr); pushintegerfield("flowinfo", ntohl(sa6->sin6_flowinfo)); pushintegerfield("scope_id", sa6->sin6_scope_id); break; } case AF_UNIX: { struct sockaddr_un *sau = (struct sockaddr_un *)sa; size_t path_len = sizeof sau->sun_path; char *end = memchr(sau->sun_path, 0, path_len); if (end) path_len = end - sau->sun_path; pushlstringfield("path", sau->sun_path, path_len); break; } #if HAVE_LINUX_NETLINK_H case AF_NETLINK: { struct sockaddr_nl *san = (struct sockaddr_nl *)sa; pushintegerfield("pid", san->nl_pid); pushintegerfield("groups", san->nl_groups); break; } #endif #if HAVE_LINUX_IF_PACKET_H case AF_PACKET: { struct sockaddr_ll *sal = (struct sockaddr_ll *)sa; pushintegerfield("ifindex", sal->sll_ifindex); break; } #endif } settypemetatable("PosixAddrInfo"); return 1; } /*** Create an endpoint for communication. @function socket @int domain one of `AF_INET`, `AF_INET6`, `AF_UNIX`, `AF_NETLINK` or `AF_PACKET` @int type one of `SOCK_STREAM`, `SOCK_DGRAM` or `SOCK_RAW` @int options usually 0, but some socket types might implement other protocols. @treturn[1] int socket descriptor, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see socket(2) @usage local sys_sock = require "posix.sys.socket" sockd = sys_sock.socket (sys_sock.AF_INET, sys_sock.SOCK_STREAM, 0) */ static int Psocket(lua_State *L) { int domain = checkint(L, 1); int type = checkint(L, 2); int options = checkint(L, 3); checknargs(L, 3); return pushresult(L, socket(domain, type, options), NULL); } /*** Create a pair of connected sockets. @function socketpair @int domain one of `AF_INET`, `AF_INET6`, `AF_UNIX` or `AF_NETLINK` @int socktype one of `SOCK_STREAM`, `SOCK_DGRAM` or `SOCK_RAW` @int options usually 0, but some socket types might implement other protocols. @treturn[1] int descriptor of one end of the socket pair @treturn[1] int descriptor of the other end of the pair, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see socketpair(2) @usage local sys_sock = require "posix.sys.socket" sockr, sockw = sys_sock.socketpair (sys_sock.AF_INET, sys_sock.SOCK_STREAM, 0) */ static int Psocketpair(lua_State *L) { int domain = checkint(L, 1); int socktype = checkint(L, 2); int options = checkint(L, 3); int fd[2]; int rc; checknargs(L, 3); if ((rc = socketpair(domain, socktype, options, fd)) < 0) return pusherror(L, "socketpair"); lua_pushinteger(L, fd[0]); lua_pushinteger(L, fd[1]); return 2; } static const char *Safinet_fields[] = { /* AF_INET6 only */ "flowinfo", "scope_id", /* AF_INET4 and AF_INET6 shared */ "family", "port", "addr", /* Also allow getaddrinfo result tables */ "socktype", "canonname", "protocol" }; static const char *Safunix_fields[] = { "family", "path" }; static const char *Safnetlink_fields[] = { "family", "pid", "groups" }; static const char *Safpacket_fields[] = { "family", "ifindex" }; #define Safinet4_fields (Safinet_fields + 2) #define Safinet6_fields Safinet_fields /* Populate a sockaddr_storage with the info from the given lua table */ static int sockaddr_from_lua(lua_State *L, int index, struct sockaddr_storage *sa, socklen_t *addrlen) { int family, r = -1; luaL_checktype(L, index, LUA_TTABLE); family = checkintfield(L, index, "family"); memset(sa, 0, sizeof *sa); switch (family) { case AF_INET: { struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; int port = checkintfield(L, index, "port"); const char *addr = checkstringfield(L, index, "addr"); int nfields = (sizeof(Safinet_fields)/sizeof(*Safinet_fields))-2; (checkfieldnames)(L, index, nfields, Safinet4_fields); if (inet_pton(AF_INET, addr, &sa4->sin_addr) == 1) { sa4->sin_family = family; sa4->sin_port = htons(port); *addrlen = sizeof(*sa4); r = 0; } break; } case AF_INET6: { struct sockaddr_in6 *sa6= (struct sockaddr_in6 *)sa; int port = checkintfield(L, index, "port"); const char *addr = checkstringfield(L, index, "addr"); /* For compatibility, the next two fields are optional */ uint32_t flowinfo = (uint32_t)optintegerfield(L, index, "flowinfo", 0); uint32_t scope_id = (uint32_t)optintegerfield(L, index, "scope_id", 0); checkfieldnames (L, index, Safinet6_fields); if (inet_pton(AF_INET6, addr, &sa6->sin6_addr) == 1) { sa6->sin6_family= family; sa6->sin6_port = htons(port); sa6->sin6_flowinfo = htonl(flowinfo); sa6->sin6_scope_id = scope_id; *addrlen = sizeof(*sa6); r = 0; } break; } case AF_UNIX: { struct sockaddr_un *sau = (struct sockaddr_un *)sa; size_t bufsize = sizeof(sau->sun_path); size_t pathlen; const char *path = checklstringfield(L, index, "path", &pathlen); checkfieldnames (L, index, Safunix_fields); if (pathlen > bufsize) pathlen = bufsize; memcpy(sau->sun_path, path, pathlen); sau->sun_family = family; *addrlen = sizeof(*sau) - bufsize + pathlen; r = 0; break; } #if HAVE_LINUX_NETLINK_H case AF_NETLINK: { struct sockaddr_nl *san = (struct sockaddr_nl *)sa; san->nl_family = family; san->nl_pid = checkintfield(L, index, "pid"); san->nl_groups = checkintfield(L, index, "groups"); *addrlen = sizeof(*san); checkfieldnames (L, index, Safnetlink_fields); r = 0; break; } #endif #if HAVE_LINUX_IF_PACKET_H case AF_PACKET: { struct sockaddr_ll *sal = (struct sockaddr_ll *)sa; sal->sll_family = family; sal->sll_ifindex = checkintfield(L, index, "ifindex"); *addrlen = sizeof(*sal); checkfieldnames (L, index, Safpacket_fields); r = 0; break; } #endif default: lua_pushfstring(L, "unsupported family type %d", family); luaL_argcheck(L, 0, index, lua_tostring (L, -1)); lua_pop (L, 1); break; } return r; } static const char *Sai_fields[] = { "family", "socktype", "protocol", "flags" }; /*** Network address and service translation. @function getaddrinfo @string host name of a host. For IPv6, link-local addresses like 'ff02::1%eth0' are supported. @string service name of service @tparam[opt] PosixAddrInfo hints table @treturn[1] list of @{sockaddr} tables, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getaddrinfo(2) @usage local sys_sock = require "posix.sys.socket" local res, errmsg, errcode = sys_sock.getaddrinfo ("www.lua.org", "http", { family = sys_sock.IF_INET, socktype = sys_sock.SOCK_STREAM } ) */ static int Pgetaddrinfo(lua_State *L) { int n = 1; const char *host = optstring(L, 1, NULL); const char *service = NULL; struct addrinfo *res, hints; memset(&hints, 0, sizeof hints); hints.ai_family = PF_UNSPEC; checknargs(L, 3); switch (lua_type(L, 2)) { case LUA_TNONE: case LUA_TNIL: if (host == NULL) argtypeerror(L, 2, "integer or string"); break; case LUA_TNUMBER: case LUA_TSTRING: service = lua_tostring(L, 2); break; default: argtypeerror(L, 2, "integer, nil or string"); break; } switch (lua_type(L, 3)) { case LUA_TNONE: case LUA_TNIL: break; case LUA_TTABLE: checkfieldnames (L, 3, Sai_fields); hints.ai_family = optintfield(L, 3, "family", PF_UNSPEC); hints.ai_socktype = optintfield(L, 3, "socktype", 0); hints.ai_protocol = optintfield(L, 3, "protocol", 0); hints.ai_flags = optintfield(L, 3, "flags", 0); break; default: argtypeerror(L, 3, "nil or table"); break; } { int r; if ((r = getaddrinfo(host, service, &hints, &res)) != 0) { lua_pushnil(L); lua_pushstring(L, gai_strerror(r)); lua_pushinteger(L, r); return 3; } } /* Copy getaddrinfo() result into Lua table */ { struct addrinfo *p; lua_newtable(L); for (p = res; p != NULL; p = p->ai_next) { lua_pushinteger(L, n++); pushsockaddrinfo(L, p->ai_family, p->ai_addr); pushintegerfield("socktype", p->ai_socktype); pushstringfield("canonname", p->ai_canonname); pushintegerfield("protocol", p->ai_protocol); lua_settable(L, -3); } } freeaddrinfo(res); return 1; } /*** Initiate a connection on a socket. @function connect @int fd socket descriptor to act on @tparam sockaddr addr socket address @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see connect(2) */ static int Pconnect(lua_State *L) { struct sockaddr_storage sa; socklen_t salen; int fd = checkint(L, 1); checknargs (L, 2); if (sockaddr_from_lua(L, 2, &sa, &salen) != 0) return pusherror(L, "not a valid IPv4 or IPv6 address argument"); return pushresult(L, connect(fd, (struct sockaddr *)&sa, salen), "connect"); } /*** Bind an address to a socket. @function bind @int fd socket descriptor to act on @tparam sockaddr addr socket address @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see bind(2) */ static int Pbind(lua_State *L) { struct sockaddr_storage sa; socklen_t salen; int fd; checknargs (L, 2); fd = checkint(L, 1); if (sockaddr_from_lua(L, 2, &sa, &salen) != 0) return pusherror(L, "not a valid IPv4 or IPv6 argument"); return pushresult(L, bind(fd, (struct sockaddr *)&sa, salen), "bind"); } /*** Listen for connections on a socket. @function listen @int fd socket descriptor to act on @int backlog maximum length for queue of pending connections @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see listen(2) */ static int Plisten(lua_State *L) { int fd = checkint(L, 1); int backlog = checkint(L, 2); checknargs(L, 2); return pushresult(L, listen(fd, backlog), "listen"); } /*** Accept a connection on a socket. @function accept @int fd socket descriptor to act on @treturn[1] int connection descriptor @treturn[1] table connection address, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see accept(2) */ static int Paccept(lua_State *L) { int fd_client; struct sockaddr_storage sa; unsigned int salen; int fd = checkint(L, 1); checknargs(L, 1); salen = sizeof(sa); fd_client = accept(fd, (struct sockaddr *)&sa, &salen); if (fd_client == -1) return pusherror(L, "accept"); lua_pushinteger(L, fd_client); return 1 + pushsockaddrinfo(L, sa.ss_family, (struct sockaddr *)&sa); } /*** Receive a message from a socket. @function recv @int fd socket descriptor to act on @int count maximum number of bytes to receive @treturn[1] string received bytes, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see recv(2) */ static int Precv(lua_State *L) { int fd = checkint(L, 1); size_t count = (size_t)checkinteger(L, 2); ssize_t ret; void *ud, *buf; lua_Alloc lalloc; checknargs(L, 2); lalloc = lua_getallocf(L, &ud); /* Reset errno in case lalloc doesn't set it */ errno = 0; if ((buf = lalloc(ud, NULL, 0, count)) == NULL && count > 0) return pusherror(L, "lalloc"); ret = recv(fd, buf, count, 0); if (ret < 0) { lalloc(ud, buf, count, 0); return pusherror(L, NULL); } lua_pushlstring(L, buf, ret); lalloc(ud, buf, count, 0); return 1; } /*** Receive a message from a socket. @function recvfrom @int fd socket descriptor to act on @int count maximum number of bytes to receive @treturn[1] int received bytes @treturn[1] sockaddr address of message source, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see recvfrom(2) */ static int Precvfrom(lua_State *L) { int fd = checkint(L, 1); size_t count = (size_t)checkinteger(L, 2); ssize_t ret; void *ud, *buf; lua_Alloc lalloc; socklen_t salen; struct sockaddr_storage sa; checknargs(L, 2); lalloc = lua_getallocf(L, &ud); /* Reset errno in case lalloc doesn't set it */ errno = 0; if ((buf = lalloc(ud, NULL, 0, count)) == NULL && count > 0) return pusherror(L, "lalloc"); salen = sizeof(sa); ret = recvfrom(fd, buf, count, 0, (struct sockaddr *)&sa, &salen); if (ret < 0) { lalloc(ud, buf, count, 0); return pusherror(L, NULL); } lua_pushlstring(L, buf, ret); lalloc(ud, buf, count, 0); return 1 + pushsockaddrinfo(L, sa.ss_family, (struct sockaddr *)&sa); } /*** Send a message from a socket. @function send @int fd socket descriptor to act on @string buffer message bytes to send @treturn[1] int number of bytes sent, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see send(2) */ static int Psend(lua_State *L) { int fd = checkint (L, 1); size_t len; const char *buf = luaL_checklstring(L, 2, &len); checknargs(L, 2); return pushresult(L, send(fd, buf, len, 0), "send"); } /*** Send a message from a socket. @function sendto @int fd socket descriptor to act on @string buffer message bytes to send @tparam sockaddr destination socket address @treturn[1] int number of bytes sent, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see sendto(2) */ static int Psendto(lua_State *L) { size_t len; int fd = checkint(L, 1); const char *buf = luaL_checklstring(L, 2, &len); struct sockaddr_storage sa; socklen_t salen; checknargs (L, 3); if (sockaddr_from_lua(L, 3, &sa, &salen) != 0) return pusherror (L, "not a valid IPv4 or IPv6 argument"); return pushresult(L, sendto(fd, buf, len, 0, (struct sockaddr *)&sa, salen), "sendto"); } /*** Shut down part of a full-duplex connection. @function shutdown @int fd socket descriptor to act on @int how one of `SHUT_RD`, `SHUT_WR` or `SHUT_RDWR` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see shutdown(2) @usage local sys_sock = require "posix.sys.socket" ok, errmsg = sys_sock.shutdown (sock, sys_sock.SHUT_RDWR) */ static int Pshutdown(lua_State *L) { int fd = checkint(L, 1); int how = checkint(L, 2); checknargs(L, 2); return pushresult(L, shutdown(fd, how), "shutdown"); } /*** Get and set options on sockets. @function setsockopt @int fd socket descriptor @int level one of `SOL_SOCKET`, `IPPROTO_IPV6`, `IPPROTO_TCP` @int name option name, varies according to `level` value @param value1 option value to set @param[opt] value2 some option *name*s need an additional value @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see setsockopt(2) @usage local sys_sock = require "posix.sys.socket" ok, errmsg = sys_sock.setsockopt ( sock, sys_sock.SOL_SOCKET, sys_sock.SO_SNDTIMEO, 1, 0 ) */ static int Psetsockopt(lua_State *L) { int fd = checkint(L, 1); int level = checkint(L, 2); int optname = checkint(L, 3); struct linger linger; struct timeval tv; struct ipv6_mreq mreq6; #ifdef SO_BINDTODEVICE char ifname[IFNAMSIZ]; #endif int vint = 0; void *val = NULL; socklen_t len = sizeof(vint); switch (level) { case SOL_SOCKET: switch (optname) { case SO_LINGER: checknargs(L, 5); linger.l_onoff = checkinteger(L, 4); linger.l_linger = checkinteger(L, 5); val = &linger; len = sizeof(linger); break; case SO_RCVTIMEO: case SO_SNDTIMEO: checknargs(L, 5); tv.tv_sec = checkinteger(L, 4); tv.tv_usec = checkinteger(L, 5); val = &tv; len = sizeof(tv); break; #ifdef SO_BINDTODEVICE case SO_BINDTODEVICE: checknargs(L, 4); strncpy(ifname, luaL_checkstring(L, 4), IFNAMSIZ - 1); ifname[IFNAMSIZ - 1] = '\0'; val = ifname; len = strlen(ifname); break; #endif default: checknargs(L, 4); break; } break; #if defined IPV6_JOIN_GROUP && defined IPV6_LEAVE_GROUP case IPPROTO_IPV6: switch (optname) { case IPV6_JOIN_GROUP: case IPV6_LEAVE_GROUP: checknargs(L, 4); memset(&mreq6, 0, sizeof mreq6); inet_pton(AF_INET6, luaL_checkstring(L, 4), &mreq6.ipv6mr_multiaddr); val = &mreq6; len = sizeof(mreq6); break; default: checknargs(L, 4); break; } break; #endif case IPPROTO_TCP: switch (optname) { default: checknargs(L, 4); break; } break; default: break; } /* Default fallback to int if no specific handling of type above */ if (val == NULL) { vint = checkinteger(L, 4); val = &vint; len = sizeof(vint); } return pushresult(L, setsockopt(fd, level, optname, val, len), "setsockopt"); } /*** Get options on sockets. @function getsockopt @int fd socket descriptor @int level one of `SOL_SOCKET`, `IPPROTO_IPV6`, `IPPROTO_TCP` @int name option name, varies according to `level` value @return[1] the value of the requested socket option, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getsockopt(2) @usage local sys_sock = require "posix.sys.socket" val, errmsg, errnum = sys_sock.getsockopt( sock, sys_sock.SOL_SOCKET, sys_sock.SO_SNDTIMEO ) print('Send timeout ', val.tv_sec + val.tv_usec / 1000000) */ static int Pgetsockopt(lua_State *L) { int fd = checkint(L, 1); int level = checkint(L, 2); int optname = checkint(L, 3); checknargs(L, 3); struct linger linger; struct timeval tv; int err = 0; #ifdef SO_BINDTODEVICE char ifname[IFNAMSIZ]; #endif int vint = 0; void *val = NULL; socklen_t len = sizeof(vint); switch (level) { case SOL_SOCKET: switch (optname) { case SO_LINGER: val = &linger; len = sizeof(linger); break; case SO_RCVTIMEO: case SO_SNDTIMEO: val = &tv; len = sizeof(tv); break; #ifdef SO_BINDTODEVICE case SO_BINDTODEVICE: val = ifname; len = IFNAMSIZ; break; #endif default: break; } break; default: break; } /* Default fallback to int if no specific handling of type above */ if (val == NULL) { val = &vint; len = sizeof(vint); } err = getsockopt(fd, level, optname, val, &len); if (err == -1) { return pusherror(L, "getsockopt"); } if (val == &tv) { lua_createtable(L, 0, 2); pushintegerfield("tv_sec", tv.tv_sec); pushintegerfield("tv_usec", tv.tv_usec); settypemetatable("PosixTimeval"); } else if (val == &linger) { lua_createtable(L, 0, 2); pushintegerfield("l_linger", linger.l_linger); pushintegerfield("l_onoff", linger.l_onoff); settypemetatable("PosixLinger"); } #ifdef SO_BINDTODEVICE else if (val == &ifname) { lua_pushlstring(L, ifname, len); } #endif else { lua_pushinteger(L, vint); } return 1; } /*** Get socket name. @function getsockname @see getsockname(2) @int sockfd socket descriptor @treturn[1] sockaddr the current address to which the socket *sockfd* is bound, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @usage sa, err = posix.getsockname (sockfd) */ static int Pgetsockname(lua_State *L) { int fd = checkint(L, 1); struct sockaddr_storage sa; socklen_t salen = sizeof sa; checknargs (L, 1); if (getsockname(fd, (struct sockaddr *)&sa, &salen) != 0) return pusherror(L, "getsockname"); return pushsockaddrinfo(L, sa.ss_family, (struct sockaddr *)&sa); } /*** Get socket peer name. @function getpeername @int sockfd socket descriptor @treturn[1] sockaddr the address to which the socket *sockfd* is connected to, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getpeername(2) @usage sa, err = posix.getpeername (sockfd) */ static int Pgetpeername(lua_State *L) { int fd = checkint(L, 1); struct sockaddr_storage sa; socklen_t salen = sizeof sa; checknargs (L, 1); if (getpeername(fd, (struct sockaddr *)&sa, &salen) != 0) return pusherror(L, "getpeername"); return pushsockaddrinfo(L, sa.ss_family, (struct sockaddr *)&sa); } /*** Get network interface index by name. Needed for packet sockets, since SO_BINDTODEVICE won't work on packet family. @function if_nametoindex @string ifname interface name @treturn[1] int interface index, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see if_nametoindex(3) @usage local sys_sock = require "posix.sys.socket" ifindex, errmsg, errnum = sys_sock.if_nametoindex("eth0") */ static int Pif_nametoindex(lua_State *L) { const char *ifname = luaL_checkstring(L, 1); checknargs (L, 1); int ifindex = (int)if_nametoindex(ifname); if (ifindex == 0) return pusherror(L, "if_nametoindex"); lua_pushinteger(L, ifindex); return 1; } #endif static const luaL_Reg posix_sys_socket_fns[] = { #if LPOSIX_2001_COMPLIANT LPOSIX_FUNC( Psocket ), LPOSIX_FUNC( Psocketpair ), LPOSIX_FUNC( Pgetaddrinfo ), LPOSIX_FUNC( Pconnect ), LPOSIX_FUNC( Pbind ), LPOSIX_FUNC( Plisten ), LPOSIX_FUNC( Paccept ), LPOSIX_FUNC( Precv ), LPOSIX_FUNC( Precvfrom ), LPOSIX_FUNC( Psend ), LPOSIX_FUNC( Psendto ), LPOSIX_FUNC( Pshutdown ), LPOSIX_FUNC( Psetsockopt ), LPOSIX_FUNC( Pgetsockopt ), LPOSIX_FUNC( Pgetsockname ), LPOSIX_FUNC( Pgetpeername ), LPOSIX_FUNC( Pif_nametoindex ), #endif {NULL, NULL} }; /*** Constants. @section constants */ /*** Socket constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sys.socket @int AF_INET IP protocol family @int AF_INET6 IP version 6 @int AF_NETLINK Netlink protocol family @int AF_PACKET Packet protocol family @int AF_UNIX local to host @int AF_UNSPEC unspecified @int AI_ADDRCONFIG use host configuration for returned address type @int AI_ALL return IPv4 mapped and IPv6 addresses @int AI_CANONNAME request canonical name @int AI_NUMERICHOST don't use domain name resolution @int AI_NUMERICSERV don't use service name resolution @int AI_PASSIVE address is intended for @{bind} @int AI_V4MAPPED IPv4 mapped addresses are acceptable @int IPPROTO_ICMP internet control message protocol @int IPPROTO_IP internet protocol @int IPPROTO_IPV6 IPv6 header @int IPPROTO_TCP transmission control protocol @int IPPROTO_UDP user datagram protocol @int IPV6_JOIN_GROUP @int IPV6_LEAVE_GROUP @int IPV6_MULTICAST_HOPS @int IPV6_MULTICAST_IF @int IPV6_MULTICAST_LOOP @int IPV6_UNICAST_HOPS @int IPV6_V6ONLY @int NETLINK_AUDIT auditing @int NETLINK_CONNECTOR @int NETLINK_DNRTMSG decnet routing messages @int NETLINK_ECRYPTFS @int NETLINK_FIB_LOOKUP @int NETLINK_FIREWALL firewalling hook @int NETLINK_GENERIC @int NETLINK_IP6_FW @int NETLINK_ISCSI open iSCSI @int NETLINK_KOBJECT_UEVENT kernel messages to userspace @int NETLINK_NETFILTER netfilter subsystem @int NETLINK_NFLOG netfilter/iptables ULOG @int NETLINK_ROUTE routing/device hook @int NETLINK_SCSITRANSPORT SCSI transports @int NETLINK_SELINUX SELinux event notifications @int NETLINK_UNUSED unused number @int NETLINK_USERSOCK reserved for user mode socket protocols @int NETLINK_XFRM ipsec @int SHUT_RD no more receptions @int SHUT_RDWR no more receptions or transmissions @int SHUT_WR no more transmissions @int SOCK_DGRAM connectionless unreliable datagrams @int SOCK_RAW raw protocol interface @int SOCK_STREAM connection based byte stream @int SOL_SOCKET socket level @int SOMAXCONN maximum concurrent connections @int SO_ACCEPTCONN does this socket accept connections @int SO_BINDTODEVICE bind to a particular device @int SO_BROADCAST permit broadcasts @int SO_DEBUG turn-on socket debugging @int SO_DONTROUTE bypass standard routing @int SO_ERROR set socket error flag @int SO_KEEPALIVE periodically transmit keep-alive message @int SO_LINGER linger on a @{posix.unistd.close} if data is still present @int SO_OOBINLINE leave out-of-band data inline @int SO_RCVBUF set receive buffer size @int SO_RCVLOWAT set receive buffer low water mark @int SO_RCVTIMEO set receive timeout @int SO_REUSEADDR reuse local addresses @int SO_SNDBUF set send buffer size @int SO_SNDLOWAT set send buffer low water mark @int SO_SNDTIMEO set send timeout @int SO_TYPE get the socket type @int TCP_NODELAY don't delay send for packet coalescing @usage -- Print socket constants supported on this host. for name, value in pairs (require "posix.sys.socket") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_socket(lua_State *L) { luaL_newlib(L, posix_sys_socket_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.socket")); lua_setfield(L, -2, "version"); #if LPOSIX_2001_COMPLIANT LPOSIX_CONST( SOMAXCONN ); LPOSIX_CONST( AF_UNSPEC ); LPOSIX_CONST( AF_INET ); LPOSIX_CONST( AF_INET6 ); LPOSIX_CONST( AF_UNIX ); # if HAVE_LINUX_NETLINK_H LPOSIX_CONST( AF_NETLINK ); # endif # if HAVE_LINUX_IF_PACKET_H LPOSIX_CONST( AF_PACKET ); # endif LPOSIX_CONST( SOL_SOCKET ); LPOSIX_CONST( IPPROTO_TCP ); LPOSIX_CONST( IPPROTO_UDP ); LPOSIX_CONST( IPPROTO_IP ); LPOSIX_CONST( IPPROTO_IPV6 ); # ifdef IPPROTO_ICMP LPOSIX_CONST( IPPROTO_ICMP ); # endif LPOSIX_CONST( SOCK_STREAM ); LPOSIX_CONST( SOCK_DGRAM ); # ifdef SOCK_RAW LPOSIX_CONST( SOCK_RAW ); # endif LPOSIX_CONST( SHUT_RD ); LPOSIX_CONST( SHUT_WR ); LPOSIX_CONST( SHUT_RDWR ); LPOSIX_CONST( SO_ACCEPTCONN ); LPOSIX_CONST( SO_BROADCAST ); LPOSIX_CONST( SO_LINGER ); LPOSIX_CONST( SO_RCVTIMEO ); LPOSIX_CONST( SO_SNDTIMEO ); # ifdef SO_BINDTODEVICE LPOSIX_CONST( SO_BINDTODEVICE ); # endif LPOSIX_CONST( SO_DEBUG ); LPOSIX_CONST( SO_DONTROUTE ); LPOSIX_CONST( SO_ERROR ); LPOSIX_CONST( SO_KEEPALIVE ); LPOSIX_CONST( SO_OOBINLINE ); LPOSIX_CONST( SO_RCVBUF ); LPOSIX_CONST( SO_RCVLOWAT ); LPOSIX_CONST( SO_REUSEADDR ); LPOSIX_CONST( SO_SNDBUF ); LPOSIX_CONST( SO_SNDLOWAT ); LPOSIX_CONST( SO_TYPE ); LPOSIX_CONST( TCP_NODELAY ); # ifdef AI_ADDRCONFIG LPOSIX_CONST( AI_ADDRCONFIG ); # endif # ifdef AI_ALL LPOSIX_CONST( AI_ALL ); # endif LPOSIX_CONST( AI_CANONNAME ); LPOSIX_CONST( AI_NUMERICHOST ); LPOSIX_CONST( AI_NUMERICSERV ); LPOSIX_CONST( AI_PASSIVE ); # ifdef AI_V4MAPPED LPOSIX_CONST( AI_V4MAPPED ); # endif # ifdef IPV6_JOIN_GROUP LPOSIX_CONST( IPV6_JOIN_GROUP ); # endif # ifdef IPV6_LEAVE_GROUP LPOSIX_CONST( IPV6_LEAVE_GROUP ); # endif # ifdef IPV6_MULTICAST_HOPS LPOSIX_CONST( IPV6_MULTICAST_HOPS ); # endif # ifdef IPV6_MULTICAST_IF LPOSIX_CONST( IPV6_MULTICAST_IF ); # endif # ifdef IPV6_MULTICAST_LOOP LPOSIX_CONST( IPV6_MULTICAST_LOOP ); # endif # ifdef IPV6_UNICAST_HOPS LPOSIX_CONST( IPV6_UNICAST_HOPS ); # endif # ifdef IPV6_V6ONLY LPOSIX_CONST( IPV6_V6ONLY ); # endif # if HAVE_LINUX_NETLINK_H LPOSIX_CONST( NETLINK_ROUTE ); LPOSIX_CONST( NETLINK_UNUSED ); LPOSIX_CONST( NETLINK_USERSOCK ); LPOSIX_CONST( NETLINK_FIREWALL ); LPOSIX_CONST( NETLINK_NFLOG ); LPOSIX_CONST( NETLINK_XFRM ); LPOSIX_CONST( NETLINK_SELINUX ); LPOSIX_CONST( NETLINK_ISCSI ); LPOSIX_CONST( NETLINK_AUDIT ); LPOSIX_CONST( NETLINK_FIB_LOOKUP ); LPOSIX_CONST( NETLINK_CONNECTOR ); LPOSIX_CONST( NETLINK_NETFILTER ); LPOSIX_CONST( NETLINK_IP6_FW ); LPOSIX_CONST( NETLINK_DNRTMSG ); LPOSIX_CONST( NETLINK_KOBJECT_UEVENT ); LPOSIX_CONST( NETLINK_GENERIC ); LPOSIX_CONST( NETLINK_SCSITRANSPORT ); LPOSIX_CONST( NETLINK_ECRYPTFS ); # endif #endif return 1; } luaposix-36.3/ext/posix/sys/stat.c000066400000000000000000000230071475444374100172270ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** File Status Querying and Setting. @module posix.sys.stat */ #include #include "_helpers.c" /*** File state record. @table PosixStat @int st_dev device id @int st_ino inode number @int st_mode mode of file @int st_nlink number of hardlinks to file @int st_uid user id of file owner @int st_gid group id of file owner @int st_rdev additional device specific id for special files @int st_size file size in bytes @int st_atime time of last access @int st_mtime time of last data modification @int st_ctime time of last state change @int st_blksize preferred block size @int st_blocks number of blocks allocated */ static int pushstat(lua_State *L, struct stat *st) { if (!st) return lua_pushnil(L), 1; lua_createtable(L, 0, 13); setintegerfield(st, st_dev); setintegerfield(st, st_ino); setintegerfield(st, st_mode); setintegerfield(st, st_nlink); setintegerfield(st, st_uid); setintegerfield(st, st_gid); setintegerfield(st, st_rdev); setintegerfield(st, st_size); setintegerfield(st, st_blksize); setintegerfield(st, st_blocks); /* st_[amc]time is a macro on at least Mac OS, so we have to assign field name strings manually. */ pushintegerfield("st_atime", st->st_atime); pushintegerfield("st_mtime", st->st_mtime); pushintegerfield("st_ctime", st->st_ctime); settypemetatable("PosixStat"); return 1; } /*** Test for a block special file. @function S_ISBLK @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a block special file */ static int PS_ISBLK(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISBLK((mode_t)checkinteger(L, 1))); } /*** Test for a character special file. @function S_ISCHR @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a character special file */ static int PS_ISCHR(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISCHR((mode_t)checkinteger(L, 1))); } /*** Test for a directory. @function S_ISDIR @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a directory */ static int PS_ISDIR(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISDIR((mode_t)checkinteger(L, 1))); } /*** Test for a fifo special file. @function S_ISFIFO @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a fifo special file */ static int PS_ISFIFO(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISFIFO((mode_t)checkinteger(L, 1))); } /*** Test for a symbolic link. @function S_ISLNK @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a symbolic link */ static int PS_ISLNK(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISLNK((mode_t)checkinteger(L, 1))); } /*** Test for a regular file. @function S_ISREG @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a regular file */ static int PS_ISREG(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISREG((mode_t)checkinteger(L, 1))); } /*** Test for a socket. @function S_ISSOCK @int mode the st_mode field of a @{PosixStat} @treturn int non-zero if *mode* represents a socket */ static int PS_ISSOCK(lua_State *L) { checknargs(L, 1); return pushintegerresult(S_ISSOCK((mode_t)checkinteger(L, 1))); } /*** Change the mode of the path. @function chmod @string path existing file path to act on @int mode access modes to set for *path* @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see chmod(2) @usage local sys_stat = require "posix.sys.stat" sys_stat.chmod ('bin/dof', bit.bor (sys_stat.S_IRWXU, sys_stat.S_IRGRP)) */ static int Pchmod(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 2); return pushresult(L, chmod(path, (mode_t)checkinteger(L, 2)), path); } /*** Information about an existing file path. If file is a symbolic link, return information about the link itself. @function lstat @string path file to act on @treturn[1] PosixStat information about *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see lstat(2) @see stat @usage local sys_stat = require "posix.sys.stat" for a, b in pairs (sys_stat.lstat "/etc/") do print (a, b) end */ static int Plstat(lua_State *L) { struct stat s; const char *path = luaL_checkstring(L, 1); checknargs(L, 1); if (lstat(path, &s) == -1) return pusherror(L, path); return pushstat(L, &s); } /*** Information about a file descriptor. @function fstat @int fd file descriptor to act on @treturn[1] PosixStat information about *fd*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fstat(2) @see stat @usage local fcntl = require "posix.fcntl" local sys_stat = require "posix.sys.stat" local fd = assert(fcntl.open("/etc/hostname", fcntl.O_RDONLY)) for a, b in pairs (sys_stat.fstat(fd)) do print (a, b) end */ static int Pfstat(lua_State *L) { struct stat s; int fd = checkint(L, 1); checknargs(L, 1); if (fstat(fd, &s) == -1) return pusherror(L, "fstat"); return pushstat(L, &s); } /*** Make a directory. @function mkdir @string path location in file system to create directory @int[opt=511] mode access modes to set for *path* @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see mkdir(2) */ static int Pmkdir(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 2); return pushresult(L, mkdir(path, (mode_t)optinteger(L, 2, 0777)), path); } /*** Make a FIFO pipe. @function mkfifo @string path location in file system to create fifo @int[opt=511] mode access modes to set for *path* @treturn[1] int file descriptor for *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see mkfifo(2) */ static int Pmkfifo(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 2); return pushresult(L, mkfifo(path, (mode_t)optinteger(L, 2, 0777)), path); } /*** Information about an existing file path. If file is a symbolic link, return information about the file the link points to. @function stat @string path file to act on @treturn[1] PosixStat information about *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see stat(2) @see lstat @usage local sys_stat = require "posix.sys.stat" for a, b in pairs (sys_stat.stat "/etc/") do print (a, b) end */ static int Pstat(lua_State *L) { struct stat s; const char *path = luaL_checkstring(L, 1); checknargs(L, 1); if (stat(path, &s) == -1) return pusherror(L, path); return pushstat(L, &s); } /*** Set file mode creation mask. @function umask @int mode new file creation mask @treturn int previous umask @see umask(2) @see posix.umask */ static int Pumask(lua_State *L) { checknargs(L, 1); return pushintegerresult(umask((mode_t)checkinteger(L, 1))); } static const luaL_Reg posix_sys_stat_fns[] = { LPOSIX_FUNC( PS_ISBLK ), LPOSIX_FUNC( PS_ISCHR ), LPOSIX_FUNC( PS_ISDIR ), LPOSIX_FUNC( PS_ISFIFO ), LPOSIX_FUNC( PS_ISLNK ), LPOSIX_FUNC( PS_ISREG ), LPOSIX_FUNC( PS_ISSOCK ), LPOSIX_FUNC( Pchmod ), LPOSIX_FUNC( Plstat ), LPOSIX_FUNC( Pfstat ), LPOSIX_FUNC( Pmkdir ), LPOSIX_FUNC( Pmkfifo ), LPOSIX_FUNC( Pstat ), LPOSIX_FUNC( Pumask ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Stat constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sys.stat @int S_IFMT file type mode bitmask @int S_IFBLK block special @int S_IFCHR character special @int S_IFDIR directory @int S_IFIFO fifo @int S_IFLNK symbolic link @int S_IFREG regular file @int S_IFSOCK socket @int S_IRWXU user read, write and execute @int S_IRUSR user read @int S_IWUSR user write @int S_IXUSR user execute @int S_IRWXG group read, write and execute @int S_IRGRP group read @int S_IWGRP group write @int S_IXGRP group execute @int S_IRWXO other read, write and execute @int S_IROTH other read @int S_IWOTH other write @int S_IXOTH other execute @int S_ISGID set group id on execution @int S_ISUID set user id on execution @usage -- Print stat constants supported on this host. for name, value in pairs (require "posix.sys.stat") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_stat(lua_State *L) { luaL_newlib(L, posix_sys_stat_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.stat")); lua_setfield(L, -2, "version"); LPOSIX_CONST( S_IFMT ); LPOSIX_CONST( S_IFBLK ); LPOSIX_CONST( S_IFCHR ); LPOSIX_CONST( S_IFDIR ); LPOSIX_CONST( S_IFIFO ); LPOSIX_CONST( S_IFLNK ); LPOSIX_CONST( S_IFREG ); LPOSIX_CONST( S_IFSOCK ); LPOSIX_CONST( S_IRWXU ); LPOSIX_CONST( S_IRUSR ); LPOSIX_CONST( S_IWUSR ); LPOSIX_CONST( S_IXUSR ); LPOSIX_CONST( S_IRWXG ); LPOSIX_CONST( S_IRGRP ); LPOSIX_CONST( S_IWGRP ); LPOSIX_CONST( S_IXGRP ); LPOSIX_CONST( S_IRWXO ); LPOSIX_CONST( S_IROTH ); LPOSIX_CONST( S_IWOTH ); LPOSIX_CONST( S_IXOTH ); LPOSIX_CONST( S_ISGID ); LPOSIX_CONST( S_ISUID ); return 1; } luaposix-36.3/ext/posix/sys/statvfs.c000066400000000000000000000065011475444374100177460ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Retrieve File System Information. Where supported by the underlying system, query the file system. If the module loads, but there is no kernel support, then `posix.sys.statvfs.version` will be set, but the unsupported APIs will be `nil`. @module posix.sys.statvfs */ #if defined HAVE_STATVFS #include #include "_helpers.c" /*** Files system information record. @table PosixStatvfs @int f_bsize file system block size @int f_frsize fundamental file system block size @int f_blocks number of *f_frsize* sized blocks in file system @int f_bfree number of free blocks @int f_bavail number of free blocks available to non-privileged process @int f_files number of file serial numbers @int f_ffree number of free file serial numbers @int f_favail number of free file serial numbers available @int f_fsid file system id @int f_flag flag bits @int f_namemax maximum filename length */ static int pushstatvfs(lua_State *L, struct statvfs *sv) { if (!sv) return lua_pushnil(L), 1; lua_createtable(L, 0, 11); setintegerfield(sv, f_bsize); setintegerfield(sv, f_frsize); setintegerfield(sv, f_blocks); setintegerfield(sv, f_bfree); setintegerfield(sv, f_bavail); setintegerfield(sv, f_files); setintegerfield(sv, f_ffree); setintegerfield(sv, f_favail); setintegerfield(sv, f_fsid); setintegerfield(sv, f_flag); setintegerfield(sv, f_namemax); settypemetatable("PosixStatvfs"); return 1; } /*** Get file system statistics. @function statvfs @string path any path within the mounted file system @treturn[1] PosixStatvfs information about file system containing *path*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see statvfs(3) @usage local statvfs = require "posix.sys.statvfs".statvfs for a, b in pairs (statvfs "/") do print (a, b) end */ static int Pstatvfs(lua_State *L) { struct statvfs s; const char *path = luaL_checkstring(L, 1); checknargs(L, 1); if (statvfs(path, &s) == -1) return pusherror(L, path); return pushstatvfs(L, &s); } static const luaL_Reg posix_sys_statvfs_fns[] = { LPOSIX_FUNC( Pstatvfs ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Statvfs constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sys.statvfs @int ST_RDONLY read-only file system @int ST_NOSUID does not support `S_ISUID` nor `S_ISGID` file mode bits @usage -- Print statvfs constants supported on this host. for name, value in pairs (require "posix.sys.statvfs") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_statvfs(lua_State *L) { luaL_newlib(L, posix_sys_statvfs_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.statvfs")); lua_setfield(L, -2, "version"); LPOSIX_CONST( ST_RDONLY ); LPOSIX_CONST( ST_NOSUID ); return 1; } #endif luaposix-36.3/ext/posix/sys/time.c000066400000000000000000000032341475444374100172120ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Get and Set System Date and Time. @module posix.sys.time */ #include #include "_helpers.c" /*** Time value. @table PosixTimeval @int tv_sec seconds elapsed @int tv_usec remainder in microseconds @see posix.time.PosixTimespec */ static int pushtimeval(lua_State *L, struct timeval *tv) { if (!tv) return lua_pushnil(L), 1; lua_createtable(L, 0, 2); setintegerfield(tv, tv_sec); setintegerfield(tv, tv_usec); settypemetatable("PosixTimeval"); return 1; } /*** Get time of day. @function gettimeofday @treturn[1] PosixTimeval time elapsed since *epoch*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see gettimeofday(2) */ static int Pgettimeofday(lua_State *L) { struct timeval tv; checknargs(L, 0); if (gettimeofday(&tv, NULL) == -1) return pusherror(L, "gettimeofday"); return pushtimeval(L, &tv); } static const luaL_Reg posix_sys_time_fns[] = { LPOSIX_FUNC( Pgettimeofday ), {NULL, NULL} }; LUALIB_API int luaopen_posix_sys_time(lua_State *L) { luaL_newlib(L, posix_sys_time_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.time")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/sys/times.c000066400000000000000000000042131475444374100173730ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Process Times. @module posix.sys.times */ #include #include "_helpers.c" #define pushtimefield(k,x) pushintegerfield((k), ((lua_Integer)x)/clk_tck) /*** Process times record. All times are measured in cpu seconds. @table PosixTms @int tms_utime time spent executing user instructions @int tms_stime time spent in system execution @int tms_cutime sum of *tms_utime* for calling process and its children @int tms_cstime sum of *tms_stime* for calling process and its children */ static int pushtms(lua_State *L) { static long clk_tck = 0; struct tms t; clock_t elapsed = times(&t); if (elapsed == (clock_t) -1) return pusherror(L, "times"); if (clk_tck == 0) clk_tck = sysconf(_SC_CLK_TCK); lua_createtable(L, 0, 5); /* record elapsed time, and save accounting to struct */ pushtimefield("elapsed", elapsed); /* record struct entries */ pushtimefield("tms_utime", t.tms_utime); pushtimefield("tms_stime", t.tms_stime); pushtimefield("tms_cutime", t.tms_cutime); pushtimefield("tms_cstime", t.tms_cstime); settypemetatable("PosixTms"); return 1; } /*** Get the current process times. @function times @treturn[1] PosixTms time accounting for this process, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see times(2) */ static int Ptimes(lua_State *L) { checknargs(L, 0); return pushtms(L); } static const luaL_Reg posix_sys_times_fns[] = { LPOSIX_FUNC( Ptimes ), {NULL, NULL} }; LUALIB_API int luaopen_posix_sys_times(lua_State *L) { luaL_newlib(L, posix_sys_times_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.times")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/sys/utsname.c000066400000000000000000000035021475444374100177260ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Get System Identification. @module posix.sys.utsname */ #include #include "_helpers.c" /*** System identification record. @table utsname @string machine hardware platform name @string nodename network node name @string release operating system release level @string sysname operating system name @string version operating system version */ static int pushutsname(lua_State *L, struct utsname *u) { if (!u) return lua_pushnil(L), 1; lua_createtable(L, 0, 5); setstringfield(u, machine); setstringfield(u, nodename); setstringfield(u, release); setstringfield(u, sysname); setstringfield(u, version); settypemetatable("PosixUtsname"); return 1; } /*** Return information about this machine. @function uname @treturn[1] utsname system information, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see uname(2) */ static int Puname(lua_State *L) { struct utsname u; checknargs(L, 0); if (uname(&u)==-1) return pusherror(L, "uname"); return pushutsname(L, &u); } static const luaL_Reg posix_sys_utsname_fns[] = { LPOSIX_FUNC( Puname ), {NULL, NULL} }; LUALIB_API int luaopen_posix_sys_utsname(lua_State *L) { luaL_newlib(L, posix_sys_utsname_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.utsname")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/ext/posix/sys/wait.c000066400000000000000000000052161475444374100172220ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Wait for Process Termination. @module posix.sys.wait */ #include #include "_helpers.c" /*** Wait for child process to terminate. @function wait @int[opt=-1] pid child process id to wait for, or -1 for any child process @int[opt] options bitwise OR of `WNOHANG` and `WUNTRACED` @treturn[1] int pid of running child, if not exited yet and called with `WNOHANG` @treturn[1] string "running" @treturn[2] int pid of terminated child, if successful @treturn[2] string "exited", "killed" or "stopped" @treturn[2] int exit status, or signal number responsible for "killed" or "stopped" @return[3] nil @treturn[3] string error message @treturn[3] int errnum @see waitpid(2) @see posix.unistd.fork */ static int Pwait(lua_State *L) { int status = 0; pid_t pid = (pid_t)optinteger(L, 1, -1); int options = optint(L, 2, 0); checknargs(L, 2); pid = waitpid(pid, &status, options); if (pid == -1) return pusherror(L, NULL); lua_pushinteger(L, pid); if (pid == 0) { lua_pushliteral(L,"running"); return 2; } else if (WIFEXITED(status)) { lua_pushliteral(L,"exited"); lua_pushinteger(L, WEXITSTATUS(status)); return 3; } else if (WIFSIGNALED(status)) { lua_pushliteral(L,"killed"); lua_pushinteger(L, WTERMSIG(status)); return 3; } else if (WIFSTOPPED(status)) { lua_pushliteral(L,"stopped"); lua_pushinteger(L, WSTOPSIG(status)); return 3; } return 1; } static const luaL_Reg posix_sys_wait_fns[] = { LPOSIX_FUNC( Pwait ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Wait constants. Any constants not available in the underlying system will be `nil` valued. @table posix.sys.wait @int WNOHANG don't block waiting @int WUNTRACED report status of stopped children @usage -- Print wait constants supported on this host. for name, value in pairs (require "posix.sys.wait") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_sys_wait(lua_State *L) { luaL_newlib(L, posix_sys_wait_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("sys.wait")); lua_setfield(L, -2, "version"); LPOSIX_CONST( WNOHANG ); LPOSIX_CONST( WUNTRACED ); return 1; } luaposix-36.3/ext/posix/syslog.c000066400000000000000000000131611475444374100167560ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Control System Log. @module posix.syslog */ #include "_helpers.c" /* For LPOSIX_2001_COMPLIANT */ #if LPOSIX_2001_COMPLIANT #include /*** Open the system logger. @function openlog @string ident all messages will start with this @int[opt] option bitwise OR of zero or more of `LOG_CONS`, `LOG_NDELAY`, or `LOG_PID` @int[opt=`LOG_USER`] facility one of `LOG_AUTH`, `LOG_CRON`, `LOG_DAEMON`, `LOG_KERN`, `LOG_LPR`, `LOG_MAIL`, `LOG_NEWS`, `LOG_SECURITY`, `LOG_USER`, `LOG_UUCP` or `LOG_LOCAL0` through `LOG_LOCAL7` @see openlog(3) */ static int Popenlog(lua_State *L) { const char *ident = luaL_checkstring(L, 1); int option = optint(L, 2, 0); int facility = optint(L, 3, LOG_USER); checknargs(L, 3); /* Save the ident string in our registry slot. */ lua_pushlightuserdata(L, &Popenlog); lua_pushstring(L, ident); lua_rawset(L, LUA_REGISTRYINDEX); /* Use another copy of the same interned string for openlog(). */ lua_pushstring(L, ident); openlog(lua_tostring(L, -1), option, facility); return 0; } /*** Write to the system logger. @function syslog @int priority one of `LOG_EMERG`, `LOG_ALERT`, `LOG_CRIT`, `LOG_WARNING`, `LOG_NOTICE`, `LOG_INFO` or `LOG_DEBUG` @string message log message @see syslog(3) */ static int Psyslog(lua_State *L) { int priority = checkint(L, 1); const char *msg = luaL_checkstring(L, 2); checknargs(L, 2); syslog(priority, "%s", msg); return 0; } /*** Close system log. @function closelog @see closelog(3) */ static int Pcloselog(lua_State *L) { checknargs(L, 0); closelog(); return 0; } /*** Set log priority mask. @function setlogmask @int mask bitwise OR of @{LOG_MASK} bits. @treturn[1] int previous mask, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see setlogmask(3) */ static int Psetlogmask(lua_State *L) { checknargs(L, 1); return pushresult(L, setlogmask(optint(L, 1, 0)), "setlogmask"); } /*** Mask bit for given log priority. @function LOG_MASK @int priority one of `LOG_EMERG`, `LOG_ALERT`, `LOG_CRIT`, `LOG_WARNING`, `LOG_NOTICE`, `LOG_INFO` or `LOG_DEBUG` @treturn int mask bit corresponding to *priority* @see setlogmask(3) */ static int PLOG_MASK(lua_State *L) { checknargs(L, 1); return pushintegerresult(LOG_MASK(checkint(L, 1))); } #endif static const luaL_Reg posix_syslog_fns[] = { #if LPOSIX_2001_COMPLIANT LPOSIX_FUNC( PLOG_MASK ), LPOSIX_FUNC( Popenlog ), LPOSIX_FUNC( Psyslog ), LPOSIX_FUNC( Pcloselog ), LPOSIX_FUNC( Psetlogmask ), #endif {NULL, NULL} }; /*** Constants. @section constants */ /*** System logging constants. Any constants not available in the underlying system will be `nil` valued. @table posix.syslog @int LOG_AUTH security/authorisation messages @int LOG_CONS write directly to system console @int LOG_CRON clock daemon @int LOG_DAEMON system daemons @int LOG_KERN kernel messages @int LOG_LOCAL0 reserved for local use @int LOG_LOCAL1 reserved for local use @int LOG_LOCAL2 reserved for local use @int LOG_LOCAL3 reserved for local use @int LOG_LOCAL4 reserved for local use @int LOG_LOCAL5 reserved for local use @int LOG_LOCAL6 reserved for local use @int LOG_LOCAL7 reserved for local use @int LOG_LPR line printer subsystem @int LOG_MAIL mail system @int LOG_NDELAY open the connection immediately @int LOG_NEWS network news subsystem @int LOG_PID include process id with each log message @int LOG_USER random user-level messages @int LOG_UUCP unix-to-unix copy subsystem @int LOG_EMERG system is unusable @int LOG_ALERT action must be taken immediately @int LOG_CRIT critical conditions @int LOG_ERR error conditions @int LOG_WARNING warning conditions @int LOG_NOTICE normal but significant conditions @int LOG_INFO informational @int LOG_DEBUG debug-level messages @usage -- Print syslog constants supported on this host. for name, value in pairs (require "posix.syslog") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_syslog(lua_State *L) { luaL_newlib(L, posix_syslog_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("syslog")); lua_setfield(L, -2, "version"); #if LPOSIX_2001_COMPLIANT LPOSIX_CONST( LOG_CONS ); LPOSIX_CONST( LOG_NDELAY ); LPOSIX_CONST( LOG_PID ); LPOSIX_CONST( LOG_AUTH ); LPOSIX_CONST( LOG_CRON ); LPOSIX_CONST( LOG_DAEMON ); LPOSIX_CONST( LOG_KERN ); LPOSIX_CONST( LOG_LOCAL0 ); LPOSIX_CONST( LOG_LOCAL1 ); LPOSIX_CONST( LOG_LOCAL2 ); LPOSIX_CONST( LOG_LOCAL3 ); LPOSIX_CONST( LOG_LOCAL4 ); LPOSIX_CONST( LOG_LOCAL5 ); LPOSIX_CONST( LOG_LOCAL6 ); LPOSIX_CONST( LOG_LOCAL7 ); LPOSIX_CONST( LOG_LPR ); LPOSIX_CONST( LOG_MAIL ); LPOSIX_CONST( LOG_NEWS ); LPOSIX_CONST( LOG_USER ); LPOSIX_CONST( LOG_UUCP ); LPOSIX_CONST( LOG_EMERG ); LPOSIX_CONST( LOG_ALERT ); LPOSIX_CONST( LOG_CRIT ); LPOSIX_CONST( LOG_ERR ); LPOSIX_CONST( LOG_WARNING ); LPOSIX_CONST( LOG_NOTICE ); LPOSIX_CONST( LOG_INFO ); LPOSIX_CONST( LOG_DEBUG ); /* Remainder for backwards compatibility - not defined by POSIX */ # ifdef LOG_AUTHPRIV LPOSIX_CONST( LOG_AUTHPRIV ); # endif # ifdef LOG_FTP LPOSIX_CONST( LOG_FTP ); # endif # ifdef LOG_SYSLOG LPOSIX_CONST( LOG_SYSLOG ); # endif #endif return 1; } luaposix-36.3/ext/posix/termio.c000066400000000000000000000366521475444374100167470ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Control Terminal I/O. Functions and constants for controlling terminal behaviour. @module posix.termio */ #include #include #include #include "lua.h" #include "lauxlib.h" #include "_helpers.c" #if HAVE_TERMIOS_H /*** Control characters. The field names below are not strings, but index constants each referring to a terminal control character. @table ccs @int VINTR interrupt control character @int VQUIT quit control character @int WERASE erase control character @int VKILL kill control character @int VEOF end-of-file control character @int VEOL end-of-line control charactor @int VEOL2 another end-of-line control charactor @int VMIN 1 @int VTIME 0 @int VSTART xon/xoff start control character @int VSTOP xon/xoff stop control character @int VSUSP suspend control character */ /*** Terminal attributes. The constants named below are all available in this submodule's namespace, as long as they are supported by the underlying system. @table termios @int cflag bitwise OR of zero or more of `CSIZE`, `CS5`, `CS6`, `CS7`, `CS8`, `CSTOPB`, `CREAD`, `PARENB`, `PARODD`, `HUPCL`, `CLOCAL` and `CRTSCTS` @int iflag input flags; bitwise OR of zero or more of `IGNBRK`, `BRKINT`, `IGNPAR`, `PARMRK`, `INPCK`, `ISTRIP`, `INLCR`, `IGNCR`, `ICRNL`, `IXON`, `IXOFF`, `IXANY`, and `IMAXBEL` @int lflag local flags; bitwise OR of zero or more of `ISIG`, `ICANON`, `ECHO`, `ECHOE`, `ECHOK', 'ECHONL`, `NOFLSH`, `IEXTEN` and `TOSTOP` @int oflag output flags; bitwise OR of zero or more of `OPOST`, `ONLCR`, `OXTABS`, `ONOEOT`, `OCRNL`, `ONOCR`, `ONLRET`, `OFILL`, `NLDLY`, `TABDLY`, `CRDLY`, `FFDLY`, `BSDLY`, `VTDLY` and `OFDEL` @tfield ccs cc array of terminal control characters @int ispeed the input baud rate, one of `B0`, `B50`, `B75`, `B110`, `B134`, `B150`, `B200`, `B300`, `B600`, `B1200`, `B1800`, `B2400`, `B4800`, `B9600`, `B19200`, `B38400`, `B57600`, `B115200`, @int ospeed the output baud rate (see ispeed for possible values) */ /*** Winsize record. Any fields not available in the underlying system will be `nil` valued. @table PosixWinsize @int ws_row rows, in characters @int ws_col columns, in characters @int ws_xpixel width, in pixels @int ws_ypixel height, in pixels */ static int pushwinsize(lua_State *L, struct winsize *ws) { if(!ws) return lua_pushnil(L), 1; lua_createtable(L, 0, 2); setintegerfield(ws, ws_row); setintegerfield(ws, ws_col); #if HAVE_WS_XPIXEL && HAVE_WS_YPIXEL setintegerfield(ws, ws_xpixel); setintegerfield(ws, ws_ypixel); #endif settypemetatable("PosixWinsize"); return 1; } static const char *Swinsize_fields[] = { "ws_row", "ws_col", "ws_xpixel", "ws_ypixel" }; static void towinsize(lua_State *L, int index, struct winsize *ws) { static const struct winsize nullws; *ws = nullws; luaL_checktype(L, index, LUA_TTABLE); ws->ws_row = optintfield(L, index, "ws_row", 0); ws->ws_col = optintfield(L, index, "ws_col", 0); #if HAVE_WS_XPIXEL && HAVE_WS_YPIXEL ws->ws_xpixel = optintfield(L, index, "ws_xpixel", 0); ws->ws_ypixel = optintfield(L, index, "ws_ypixel", 0); #endif checkfieldnames(L, index, Swinsize_fields); } /*** Wait for all written output to reach the terminal. @function tcdrain @int fd terminal descriptor to act on @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcdrain(3) */ static int Ptcdrain(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, tcdrain(fd), NULL); } /*** Suspend transmission or receipt of data. @function tcflow @int fd terminal descriptor to act on @int action one of `TCOOFF`, `TCOON`, `TCIOFF` or `TCION` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcflow(3) */ static int Ptcflow(lua_State *L) { int fd = checkint(L, 1); int action = checkint(L, 2); checknargs(L, 2); return pushresult(L, tcflow(fd, action), NULL); } /*** Discard any data already written but not yet sent to the terminal. @function tcflush @int fd terminal descriptor to act on @int action one of `TCIFLUSH`, `TCOFLUSH`, `TCIOFLUSH` @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcflush(3) */ static int Ptcflush(lua_State *L) { int fd = checkint(L, 1); int qs = checkint(L, 2); checknargs(L, 2); return pushresult(L, tcflush(fd, qs), NULL); } /*** Get termios state. @function tcgetattr @int fd terminal descriptor @treturn[1] termios terminal attributes, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @return error message if failed @see tcgetattr(3) @usage local termios, errmsg = tcgetattr (fd) */ static int Ptcgetattr(lua_State *L) { int r, i; struct termios t; int fd = checkint(L, 1); checknargs(L, 1); r = tcgetattr(fd, &t); if (r == -1) return pusherror(L, NULL); lua_newtable(L); pushintegerfield("iflag", t.c_iflag); pushintegerfield("oflag", t.c_oflag); pushintegerfield("lflag", t.c_lflag); pushintegerfield("cflag", t.c_cflag); pushintegerfield("ispeed",cfgetispeed(&t)); pushintegerfield("ospeed",cfgetospeed(&t)); lua_newtable(L); for (i=0; i * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Time and Clock Functions. @module posix.time */ #include #include #include "_helpers.c" static const char *Stimespec_fields[] = { "tv_sec", "tv_nsec" }; static void totimespec(lua_State *L, int index, struct timespec *ts) { luaL_checktype(L, index, LUA_TTABLE); ts->tv_sec = (time_t)optintegerfield(L, index, "tv_sec", 0); ts->tv_nsec = optlongfield(L, index, "tv_nsec", 0); checkfieldnames(L, index, Stimespec_fields); } /*** Timespec record. @table PosixTimespec @int tv_sec seconds @int tv_nsec nanoseconds @see posix.sys.time.PosixTimeval */ static int pushtimespec(lua_State *L, struct timespec *ts) { if (!ts) return lua_pushnil(L), 1; lua_createtable(L, 0, 2); setintegerfield(ts, tv_sec); setintegerfield(ts, tv_nsec); settypemetatable("PosixTimespec"); return 1; } /* for compatibility, we accept tm_gmtoff and tm_zone as fields even * if the underlying OS doesn't. */ static const char *Stm_fields[] = { "tm_sec", "tm_min", "tm_hour", "tm_mday", "tm_mon", "tm_year", "tm_wday", "tm_yday", "tm_isdst", "tm_gmtoff", "tm_zone" }; static void totm(lua_State *L, int index, struct tm *t) { static const struct tm nulltm; *t = nulltm; luaL_checktype(L, index, LUA_TTABLE); t->tm_sec = optintfield(L, index, "tm_sec", 0); t->tm_min = optintfield(L, index, "tm_min", 0); t->tm_hour = optintfield(L, index, "tm_hour", 0); t->tm_mday = optintfield(L, index, "tm_mday", 0); t->tm_mon = optintfield(L, index, "tm_mon", 0); t->tm_year = optintfield(L, index, "tm_year", 0); t->tm_wday = optintfield(L, index, "tm_wday", 0); t->tm_yday = optintfield(L, index, "tm_yday", 0); t->tm_isdst = optintfield(L, index, "tm_isdst", 0); #if HAVE_TM_GMTOFF t->tm_gmtoff = optintfield(L, index, "tm_gmtoff", 0); #endif #if HAVE_TM_ZONE t->tm_zone = optstringfield(L, index, "tm_zone", NULL); #endif checkfieldnames(L, index, Stm_fields); } /*** Datetime record. @table PosixTm @int tm_sec second [0,60] @int tm_min minute [0,59] @int tm_hour hour [0,23] @int tm_mday day of month [1, 31] @int tm_mon month of year [0,11] @int tm_year years since 1900 @int tm_wday day of week [0=Sunday,6] @int tm_yday day of year [0,365[ @int tm_isdst 0 if daylight savings time is not in effect */ static int pushtm(lua_State *L, struct tm *t) { if (!t) return lua_pushnil(L), 1; lua_createtable(L, 0, 9); setintegerfield(t, tm_sec); setintegerfield(t, tm_min); setintegerfield(t, tm_hour); setintegerfield(t, tm_mday); setintegerfield(t, tm_mon); setintegerfield(t, tm_year); setintegerfield(t, tm_wday); setintegerfield(t, tm_yday); setintegerfield(t, tm_isdst); #if HAVE_TM_GMTOFF setintegerfield(t, tm_gmtoff); #endif #if HAVE_TM_ZONE setstringfield(t, tm_zone); #endif settypemetatable("PosixTm"); return 1; } #if defined _POSIX_TIMERS && _POSIX_TIMERS != -1 /*** Find the precision of a clock. @function clock_getres @int clk name of clock, one of `CLOCK_REALTIME`, `CLOCK_PROCESS_CPUTIME_ID`, `CLOCK_MONOTONIC` or `CLOCK_THREAD_CPUTIME_ID` @treturn[1] PosixTimespec resolution of *clk*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see clock_getres(3) */ static int Pclock_getres(lua_State *L) { struct timespec resolution; int clk = checkint(L, 1); checknargs(L, 1); if (clock_getres(clk, &resolution) == -1) return pusherror(L, "clock_getres"); return pushtimespec(L, &resolution); } /*** Read a clock. @function clock_gettime @int clk name of clock, one of `CLOCK_REALTIME`, `CLOCK_PROCESS_CPUTIME_ID`, `CLOCK_MONOTONIC` or `CLOCK_THREAD_CPUTIME_ID` @treturn[1] PosixTimespec current value of *clk*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see clock_gettime(3) */ static int Pclock_gettime(lua_State *L) { struct timespec ts; int clk = checkint(L, 1); checknargs(L, 1); if (clock_gettime(clk, &ts) == -1) return pusherror(L, "clock_gettime"); return pushtimespec(L, &ts); } #endif /*** Convert epoch time value to a broken-down UTC time. @function gmtime @int t seconds since epoch @treturn[1] PosixTm broken-down time, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see gmtime(3) */ static int Pgmtime(lua_State *L) { struct tm t; time_t epoch = checklong(L, 1); checknargs(L, 1); if (gmtime_r(&epoch, &t) == NULL) return pusherror(L, "gmtime"); return pushtm(L, &t); } /*** Convert epoch time value to a broken-down local time. @function localtime @int t seconds since epoch @treturn[1] PosixTm broken-down time, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see localtime(3) @see mktime */ static int Plocaltime(lua_State *L) { struct tm t; time_t epoch = checklong(L, 1); checknargs(L, 1); if (localtime_r(&epoch, &t) == NULL) return pusherror(L, "localtime"); return pushtm(L, &t); } /*** Convert a broken-down localtime table into an epoch time. @function mktime @tparam PosixTm broken-down localtime @treturn int seconds since epoch @see mktime(3) @see localtime */ static int Pmktime(lua_State *L) { struct tm t; time_t epoch; checknargs(L, 1); totm(L, 1, &t); if ((epoch = mktime(&t)) < 0) return 0; return pushintegerresult(epoch); } /*** Sleep with nanosecond precision. @function nanosleep @tparam PosixTimespec requested sleep time @treturn[1] int `0` if requested time has elapsed, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @treturn[2] PosixTimespec unslept time remaining, if interrupted @see nanosleep(2) @see posix.unistd.sleep */ static int Pnanosleep(lua_State *L) { struct timespec req; struct timespec rem; int r; totimespec(L, 1, &req); checknargs(L, 1); r = pushresult (L, nanosleep(&req, &rem), "nanosleep"); if (r == 3 && errno == EINTR) r = r + pushtimespec (L, &rem); return r; } /*** Return a time string according to *format*. Note that if your host POSIX library provides a `strftime` that assumes the local timezone, %z will always print the local UTC offset, regardless of the `tm_gmoffset` field value passed in. @function strftime @string format specifier with `%` place-holders @tparam PosixTm tm broken-down local time @treturn string *format* with place-holders plugged with *tm* values @see strftime(3) */ static int Pstrftime(lua_State *L) { char tmp[256]; const char *fmt = luaL_checkstring(L, 1); struct tm t; totm(L, 2, &t); checknargs(L, 2); strftime(tmp, sizeof(tmp), fmt, &t); return pushstringresult(tmp); } /*** Parse a date string. @function strptime @string s @string format same as for `strftime` @usage posix.strptime('20','%d').monthday == 20 @treturn[1] PosixTm broken-down local time @treturn[1] int next index of first character not parsed as part of the date, if successful @return[2] nil @see strptime(3) */ static int Pstrptime(lua_State *L) { struct tm t; const char *s = luaL_checkstring(L, 1); const char *fmt = luaL_checkstring(L, 2); char *r; checknargs(L, 2); memset(&t, 0, sizeof(struct tm)); r = strptime(s, fmt, &t); if (r) { pushtm(L, &t); lua_pushinteger(L, r - s + 1); return 2; } else return 0; } /*** Get current time. @function time @treturn[1] int time in seconds since epoch, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see time(2) */ static int Ptime(lua_State *L) { time_t t = time(NULL); checknargs(L, 0); if ((time_t) -1 == t) return pusherror(L, "time"); lua_pushinteger(L, t); return 1; } static const luaL_Reg posix_time_fns[] = { #if defined _POSIX_TIMERS && _POSIX_TIMERS != -1 LPOSIX_FUNC( Pclock_getres ), LPOSIX_FUNC( Pclock_gettime ), #endif LPOSIX_FUNC( Pgmtime ), LPOSIX_FUNC( Plocaltime ), LPOSIX_FUNC( Pmktime ), LPOSIX_FUNC( Pnanosleep ), LPOSIX_FUNC( Pstrftime ), LPOSIX_FUNC( Pstrptime ), LPOSIX_FUNC( Ptime ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Standard constants. Any constants not available in the underlying system will be `nil` valued. @table posix.time @int CLOCK_MONOTONIC the identifier for the system-wide monotonic clock @int CLOCK_PROCESS_CPUTIME_ID the identifier for the current process CPU-time clock @int CLOCK_REALTIME the identifier for the system-wide realtime clock @int CLOCK_THREAD_CPUTIME_ID the identifier for the current thread CPU-time clock @usage -- Print posix.time constants supported on this host. for name, value in pairs (require "posix.time") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_time(lua_State *L) { luaL_newlib(L, posix_time_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("time")); lua_setfield(L, -2, "version"); #if defined CLOCK_MONOTONIC LPOSIX_CONST( CLOCK_MONOTONIC ); #endif #if defined CLOCK_PROCESS_CPUTIME_ID LPOSIX_CONST( CLOCK_PROCESS_CPUTIME_ID ); #endif #if defined CLOCK_REALTIME LPOSIX_CONST( CLOCK_REALTIME ); #endif #if defined CLOCK_THREAD_CPUTIME_ID LPOSIX_CONST( CLOCK_THREAD_CPUTIME_ID ); #endif return 1; } luaposix-36.3/ext/posix/unistd.c000066400000000000000000000760061475444374100167530ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Unix Standard APIs. Where the underlying system does not support one of these functions, it will have a `nil` value in the module table. @module posix.unistd */ #if HAVE_CRYPT_H # include #endif #include #include #include #include #include #include "_helpers.c" static uid_t mygetuid(lua_State *L, int i) { if (lua_isnoneornil(L, i)) return (uid_t)-1; else if (lua_isinteger(L, i)) return (uid_t) lua_tointeger(L, i); else if (lua_isstring(L, i)) { struct passwd *p = getpwnam(lua_tostring(L, i)); return (p == NULL) ? (uid_t) -1 : p->pw_uid; } else return argtypeerror(L, i, "integer, nil or string"); } static gid_t mygetgid(lua_State *L, int i) { if (lua_isnoneornil(L, i)) return (gid_t)-1; else if (lua_isinteger(L, i)) return (gid_t) lua_tointeger(L, i); else if (lua_isstring(L, i)) { struct group *g = getgrnam(lua_tostring(L, i)); return (g == NULL) ? (uid_t) -1 : g->gr_gid; } else return argtypeerror(L, i, "integer, nil or string"); } /*** Terminate the calling process. @function _exit @int status process exit status @see _exit(2) */ static int P_exit(lua_State *L) { pid_t ret = (pid_t)checkinteger(L, 1); checknargs(L, 1); _exit(ret); return 0; /* Avoid a compiler warning (or possibly cause one if the compiler's too clever, sigh). */ } /*** Check real user's permissions for a file. @function access @string path file to act on @string[opt="f"] mode can contain 'r','w','x' and 'f' @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see access(2) @usage local unistd = require "posix.unistd" status, errstr, errno = unistd.access("/etc/passwd", "rw") */ static int Paccess(lua_State *L) { int mode=F_OK; const char *path=luaL_checkstring(L, 1); const char *s; checknargs(L, 2); for (s=optstring(L, 2, "f"); *s!=0 ; s++) switch (*s) { case ' ': break; case 'r': mode |= R_OK; break; case 'w': mode |= W_OK; break; case 'x': mode |= X_OK; break; case 'f': mode |= F_OK; break; default: badoption(L, 2, "mode", *s); break; } return pushresult(L, access(path, mode), path); } /*** Schedule an alarm signal. @function alarm @int seconds number of seconds to send SIGALRM in @return int number of seconds remaining in previous alarm or `0` @see alarm(2) @usage local unistd = require "posix.unistd" seconds = unistd.alarm(10) */ static int Palarm(lua_State *L) { int seconds = checkint(L, 1); checknargs(L, 1); return pushintegerresult(alarm(seconds)); } /*** Set the working directory. @function chdir @string path file to act on @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see chdir(2) @usage local unistd = require "posix.unistd" status, errstr, errno = unistd.chdir ("/var/tmp") */ static int Pchdir(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 1); return pushresult(L, chdir(path), path); } /*** Change ownership of a file. @function chown @string path existing file path @tparam string|int uid new owner user id @tparam string|int gid new owner group id @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error messoge @treturn[2] int errnum @see chown(2) @usage local unistd = require "posix.unistd" -- will fail for a normal user, and print an error print(unistd.chown ("/etc/passwd", 100, 200)) */ static int Pchown(lua_State *L) { const char *path = luaL_checkstring(L, 1); uid_t uid = mygetuid(L, 2); gid_t gid = mygetgid(L, 3); checknargs(L, 3); return pushresult(L, chown(path, uid, gid), path); } /*** Close an open file descriptor. @function close @int fd file descriptor to act on @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see close(2) @usage local unistd = require "posix.unistd" local ok, errmsg = unistd.close (log) if not ok then error (errmsg) end */ static int Pclose(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, close(fd), NULL); } #if defined HAVE_CRYPT /*** Encrypt a password. Not recommended for general encryption purposes. @function crypt @string trypass string to hash @string salt two-character string from [a-zA-Z0-9./] @return encrypted string @see crypt(3) @usage local pwd = require "posix.pwd" local unistd = require "posix.unistd" local salt, hash = pwd.pwent:match ":$6$(.-)$([^:]+)" if unistd.crypt (trypass, salt) ~= hash then error "wrong password" end */ static int Pcrypt(lua_State *L) { const char *str, *salt; char *r; str = luaL_checkstring(L, 1); salt = luaL_checkstring(L, 2); if (strlen(salt) < 2) luaL_error(L, "not enough salt"); checknargs(L, 2); r = crypt(str, salt); return pushstringresult(r); } #endif /*** Duplicate an open file descriptor. @function dup @int fd file descriptor to act on @treturn[1] int new file descriptor duplicating *fd*, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see dup(2) @usage local stdio = require "posix.stdio" local unistd = require "posix.unistd" outfd = unistd.dup (stdio.fileno (io.stdout)) */ static int Pdup(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, dup(fd), NULL); } /*** Duplicate one open file descriptor to another. If *newfd* references an open file already, it is closed before being reallocated to *fd*. @function dup2 @int fd an open file descriptor to act on @int newfd new descriptor to duplicate *fd* @treturn[1] int new file descriptor, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see dup2(2) */ static int Pdup2(lua_State *L) { int fd = checkint(L, 1); int newfd = checkint(L, 2); checknargs(L, 2); return pushresult(L, dup2(fd, newfd), NULL); } static int runexec(lua_State *L, int use_shell) { char **argv; const char *path = luaL_checkstring(L, 1); int i, n; checknargs(L, 2); if (lua_type(L, 2) != LUA_TTABLE) argtypeerror(L, 2, "table"); n = lua_objlen(L, 2); argv = lua_newuserdata(L, (n + 2) * sizeof(char*)); /* Set argv[0], defaulting to command */ argv[0] = (char*) path; lua_pushinteger(L, 0); lua_gettable(L, 2); if (lua_type(L, -1) == LUA_TSTRING) argv[0] = (char*)lua_tostring(L, -1); else lua_pop(L, 1); /* Read argv[1..n] from table. */ for (i=1; i<=n; i++) { lua_pushinteger(L, i); lua_gettable(L, 2); argv[i] = (char*)lua_tostring(L, -1); } argv[n+1] = NULL; (use_shell ? execvp : execv) (path, argv); return pusherror(L, path); } /*** Execute a program at exactly *path*. @function exec @string path @tparam table argt arguments (table can include index 0) @return nil @treturn string error message @treturn int errnum @see execve(2) @usage exec ("/bin/bash", {[0] = "-sh", "--norc"}) */ static int Pexec(lua_State *L) { return runexec(L, 0); } /*** Execute a program found using command PATH search, like the shell. @function execp @string path @tparam table argt arguments (table can include index 0) @return nil @treturn string error message @treturn int errnum @see execve(2) */ static int Pexecp(lua_State *L) { return runexec(L, 1); } #if HAVE_FDATASYNC #if !HAVE_DECL_FDATASYNC extern int fdatasync (); #endif /*** Synchronize a file's in-core state with storage device without metadata. @function fdatasync @int fd @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fdatasync(2) */ static int Pfdatasync(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, fdatasync(fd), NULL); } #endif /*** Fork this program. @function fork @treturn[1] int `0` in the resulting child process @treturn[2] int process id of child, in the calling process @return[3] nil @treturn[3] string error message @treturn[3] int errnum @see fork(2) @see fork.lua @see fork2.lua @usage local unistd = require "posix.unistd" local pid, errmsg = unistd.fork () if pid == nil then error (errmsg) elseif pid == 0 then print ("in child:", unistd.getpid "pid") else print (require "posix.sys.wait".wait (pid)) end os.exit () */ static int Pfork(lua_State *L) { checknargs(L, 0); return pushresult(L, fork(), NULL); } /*** Synchronize a file's in-core state with storage device. @function fsync @int fd @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see fsync(2) @see sync */ static int Pfsync(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, fsync(fd), NULL); } /*** Current working directory for this process. @function getcwd @treturn[1] string path of current working directory, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getcwd(3) */ static int Pgetcwd(lua_State *L) { #ifdef __GNU__ char *r = get_current_dir_name(); checknargs(L, 0); if (r != NULL) lua_pushstring(L, r); free(r); #else long size = pathconf(".", _PC_PATH_MAX); void *ud; lua_Alloc lalloc; char *b, *r; checknargs(L, 0); lalloc = lua_getallocf(L, &ud); if (size == -1) size = _POSIX_PATH_MAX; /* FIXME: Retry if this is not long enough */ if ((b = lalloc(ud, NULL, 0, (size_t)size + 1)) == NULL) return pusherror(L, "lalloc"); r = getcwd(b, (size_t)size); if (r != NULL) lua_pushstring(L, b); lalloc(ud, b, (size_t)size + 1, 0); #endif return (r == NULL) ? pusherror(L, ".") : 1; } /*** Return effective group id of calling process. @function getegid @treturn int effective group id of calling process @see getgid */ static int Pgetegid(lua_State *L) { checknargs(L, 0); return pushintegerresult(getegid()); } /*** Return effective user id of calling process. @function geteuid @treturn int effective user id of calling process @see getuid */ static int Pgeteuid(lua_State *L) { checknargs(L, 0); return pushintegerresult(geteuid()); } /*** Return group id of calling process. @function getgid @treturn int group id of calling process @see getegid */ static int Pgetgid(lua_State *L) { checknargs(L, 0); return pushintegerresult(getgid()); } #if LPOSIX_2001_COMPLIANT /*** Get list of supplementary group ids. @function getgroups @treturn[1] table group id, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see getgroups(2) */ static int Pgetgroups(lua_State *L) { int n_group_slots = getgroups(0, NULL); checknargs(L, 0); if (n_group_slots < 0) return pusherror(L, NULL); else if (n_group_slots == 0) lua_newtable(L); else { gid_t *group; int n_groups; int i; group = lua_newuserdata(L, sizeof(*group) * n_group_slots); n_groups = getgroups(n_group_slots, group); if (n_groups < 0) return pusherror(L, NULL); lua_createtable(L, n_groups, 0); for (i = 0; i < n_groups; i++) { lua_pushinteger(L, group[i]); lua_rawseti(L, -2, i + 1); } } return 1; } #endif /*** Current logged-in user. @treturn[1] string username, if successful @return[2] nil @see getlogin(3) */ static int Pgetlogin(lua_State *L) { checknargs(L, 0); return pushstringresult(getlogin()); } static int iter_getopt(lua_State *L) { int r, argc = lua_tointeger(L, lua_upvalueindex(1)); char **argv = (char **)lua_touserdata(L, lua_upvalueindex(3)); char c; if (argv == NULL) /* If we have already completed, return now. */ return 0; /* Fetch upvalues to pass to getopt. */ r = getopt(argc, argv, lua_tostring(L, lua_upvalueindex(2))); if (r == -1) return 0; c = (char) r; lua_pushlstring(L, &c, 1); lua_pushstring(L, optarg); lua_pushinteger(L, optind); return 3; } /*** Parse command-line options. @function getopt @param arg command line arguments @string opts short option specifier @int[opt=0] opterr index of the option with an error @int[opt=1] optind index of the next unprocessed option @treturn option iterator, returning 3 values @see getopt(3) @see getopt.lua @usage local getopt = require "posix.getopt".getopt for opt, opterr, i in getopt (arg, "ho:v", opterr, i) do process (arg, opterr, i) end */ static int Pgetopt(lua_State *L) { int argc, i; const char *optstring; char **argv; checknargs(L, 4); checktype(L, 1, LUA_TTABLE, "list"); optstring = luaL_checkstring(L, 2); opterr = optinteger(L, 3, 0); optind = optinteger(L, 4, 1); argc = (int)lua_objlen(L, 1) + 1; lua_pushinteger(L, argc); lua_pushstring(L, optstring); argv = lua_newuserdata(L, (argc + 1) * sizeof(char *)); argv[argc] = NULL; for (i = 0; i < argc; i++) { lua_pushinteger(L, i); lua_gettable(L, 1); argv[i] = (char *)luaL_checkstring(L, -1); } /* Push remaining upvalues, and make and push closure. */ lua_pushcclosure(L, iter_getopt, 3 + argc); return 1; } /*** Return process group id of calling process. @function getpgrp @treturn int process group id of calling process @see getpid */ static int Pgetpgrp(lua_State *L) { checknargs(L, 0); return pushintegerresult(getpgrp()); } /*** Return process id of calling process. @function getpid @treturn int process id of calling process */ static int Pgetpid(lua_State *L) { checknargs(L, 0); return pushintegerresult(getpid()); } /*** Return parent process id of calling process. @function getppid @treturn int parent process id of calling process @see getpid */ static int Pgetppid(lua_State *L) { checknargs(L, 0); return pushintegerresult(getppid()); } /*** Return user id of calling process. @function getuid @treturn int user id of calling process @see geteuid */ static int Pgetuid(lua_State *L) { checknargs(L, 0); return pushintegerresult(getuid()); } /*** Get host id. @function gethostid @treturn[1] int host id, if successful @return[2] nil @treturn[2] string error message @see gethostid(3) */ static int Pgethostid(lua_State *L) { checknargs(L, 0); #if HAVE_GETHOSTID return pushintegerresult(gethostid()); #else lua_pushnil(L); lua_pushliteral(L, "unsupported by this host"); return 2; #endif } /*** Test whether a file descriptor refers to a terminal. @function isatty @int fd file descriptor to act on @treturn[1] int `1` if *fd* is open and refers to a terminal, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see isatty(3) */ static int Pisatty(lua_State *L) { int fd = checkint(L, 1); checknargs(L, 1); return pushresult(L, isatty(fd) == 0 ? -1 : 1, "isatty"); } #if LPOSIX_2001_COMPLIANT /*** This is like `chown`, but does not dereference symbolic links. In other words, if a file is a symlink, then it changes ownership of the symlink itself. @function lchown @string path existing file path @tparam string|int uid new owner user id @tparam string|int gid new owner group id @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error messoge @treturn[2] int errnum @see lchown(2) @usage local unistd = require "posix.unistd" -- will fail for a normal user, and print an error print(unistd.lchown ("/etc/passwd", 100, 200)) */ static int Plchown(lua_State *L) { const char *path = luaL_checkstring(L, 1); uid_t uid = mygetuid(L, 2); gid_t gid = mygetgid(L, 3); checknargs(L, 3); return pushresult(L, lchown(path, uid, gid), path); } #endif /*** Create a link. @function link @string target name @string link name @bool[opt=false] soft link @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see link(2) @see symlink(2) */ static int Plink(lua_State *L) { const char *oldpath = luaL_checkstring(L, 1); const char *newpath = luaL_checkstring(L, 2); int symbolicp = optboolean(L, 3, 0); checknargs(L, 3); return pushresult(L, (symbolicp ? symlink : link)(oldpath, newpath), NULL); } /*** Create a link at specified directory. @function linkat @int targetdir fd @string target name @int linkdir fd @string link name @int flags @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see linkat(2) */ static int Plinkat(lua_State *L) { int olddirfd = checkint(L, 1); const char *oldpath = luaL_checkstring(L, 2); int newdirfd = checkint(L, 3); const char *newpath = luaL_checkstring(L, 4); int flags = checkint(L, 5); checknargs(L, 5); return pushresult(L, linkat(olddirfd, oldpath, newdirfd, newpath, flags), NULL); } /*** reposition read/write file offset @function lseek @int fd open file descriptor to act on @int offset bytes to seek @int whence one of `SEEK_SET`, `SEEK_CUR` or `SEEK_END` @treturn[1] int new offset, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see lseek(2) */ static int Plseek(lua_State *L) { int fd = checkint(L, 1); off_t offset = (off_t)checkinteger(L, 2); int whence = checkint(L, 3); checknargs(L, 3); return pushresult(L, lseek(fd, offset, whence), NULL); } /*** change process priority @function nice @int inc adds inc to the nice value for the calling process @treturn[1] int new nice value, if successful @return[2] nil @return[2] string error message @treturn[2] int errnum @see nice(2) */ static int Pnice(lua_State *L) { int inc = checkint(L, 1); checknargs(L, 1); return pushresult(L, nice(inc), "nice"); } /*** Get a value for a configuration option for a filename. @function pathconf @string path optional @int key one of `_PC_LINK_MAX`, `_PC_MAX_CANON`, `_PC_NAME_MAX`, `_PC_PIPE_BUF`, `_PC_CHOWN_RESTRICTED`, `_PC_NO_TRUNC` or `_PC_VDISABLE` @treturn int associated path configuration value @see pathconf(3) @usage local unistd = require "posix.unistd" for a, b in pairs (unistd.pathconf "/dev/tty") do print(a, b) end */ static int Ppathconf(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 2); return pushintegerresult(pathconf(path, checkint(L, 2))); } /*** Creates a pipe. @function pipe @treturn[1] int read end file descriptor @treturn[1] int write end file descriptor, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see pipe(2) @see fork.lua */ static int Ppipe(lua_State *L) { int pipefd[2]; int rc; checknargs(L, 0); rc = pipe(pipefd); if (rc < 0) return pusherror(L, "pipe"); lua_pushinteger(L, pipefd[0]); lua_pushinteger(L, pipefd[1]); return 2; } /*** Read bytes from a file. @function read @int fd the file descriptor to act on @int count maximum number of bytes to read @treturn[1] string string from *fd* with at most *count* bytes, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see read(2) */ static int Pread(lua_State *L) { int fd = checkint(L, 1); size_t count = (size_t)checkinteger(L, 2); ssize_t ret; void *ud, *buf; lua_Alloc lalloc; checknargs(L, 2); lalloc = lua_getallocf(L, &ud); /* Reset errno in case lalloc doesn't set it */ errno = 0; if ((buf = lalloc(ud, NULL, 0, count)) == NULL && count > 0) return pusherror(L, "lalloc"); ret = read(fd, buf, count); if (ret >= 0) lua_pushlstring(L, buf, ret); lalloc(ud, buf, count, 0); return (ret < 0) ? pusherror(L, NULL) : 1; } /*** Read value of a symbolic link. @function readlink @string path file to act on @treturn[1] string link target, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see readlink(2) */ static int Preadlink(lua_State *L) { char b[PATH_MAX]; struct stat s; const char *path = luaL_checkstring(L, 1); void *ud; lua_Alloc lalloc; ssize_t n; checknargs(L, 1); errno = 0; /* ignore outstanding unreported errors */ /* s.st_size is length of linkname, with no trailing \0 */ if (lstat(path, &s) < 0) return pusherror(L, path); if (!S_ISLNK(s.st_mode)) { lua_pushnil(L); lua_pushfstring(L, "%s: not a symbolic link", path); lua_pushinteger(L, EINVAL); return 3; } n = readlink(path, b, PATH_MAX); if (n < 0) /* report new errors from this function */ return pusherror(L, "readlink"); lua_pushlstring(L, b, n); return 1; } /*** Remove a directory. @function rmdir @string path file to act on @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see rmdir(2) */ static int Prmdir(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 1); return pushresult(L, rmdir(path), path); } /*** Set the uid, euid, gid, egid, sid or pid & gid. @function setpid @string what one of 'u', 'U', 'g', 'G', 's', 'p' (upper-case means "effective") @int id (uid, gid or pid for every value of `what` except 's') @int[opt] gid (only for `what` value 'p') @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see setuid(2) @see seteuid(2) @see setgid(2) @see setegid(2) @see setsid(2) @see setpgid(2) */ static int Psetpid(lua_State *L) { const char *what=luaL_checkstring(L, 1); checknargs(L, *what == 'p' ? 3 : 2); switch (*what) { case 'U': return pushresult(L, seteuid(mygetuid(L, 2)), NULL); case 'u': return pushresult(L, setuid(mygetuid(L, 2)), NULL); case 'G': return pushresult(L, setegid(mygetgid(L, 2)), NULL); case 'g': return pushresult(L, setgid(mygetgid(L, 2)), NULL); case 's': return pushresult(L, setsid(), NULL); case 'p': { pid_t pid = (pid_t)checkinteger(L, 2); pid_t pgid = (pid_t)checkinteger(L, 3); return pushresult(L, setpgid(pid,pgid), NULL); } default: badoption(L, 1, "id", *what); return 0; } } /*** Sleep for a number of seconds. @function sleep @int seconds minimum numebr of seconds to sleep @treturn[1] int `0` if the requested time has elapsed @treturn[2] int unslept seconds remaining, if interrupted @see sleep(3) @see posix.time.nanosleep */ static int Psleep(lua_State *L) { unsigned int seconds = checkint(L, 1); checknargs(L, 1); return pushintegerresult(sleep(seconds)); } /*** Commit buffer cache to disk. @function sync @see fsync @see sync(2) */ static int Psync(lua_State *L) { checknargs(L, 0); sync(); return 0; } /*** Get configuration information at runtime. @function sysconf @int key one of `_SC_ARG_MAX`, `_SC_CHILD_MAX`, `_SC_CLK_TCK`, `_SC_JOB_CONTROL`, `_SC_OPEN_MAX`, `_SC_NGROUPS_MAX`, `_SC_SAVED_IDS`, `_SC_STREAM_MAX`, `_SC_PAGESIZE`, `_SC_TZNAME_MAX` or `_SC_VERSION`, @treturn int associated system configuration value @see sysconf(3) */ static int Psysconf(lua_State *L) { checknargs(L, 1); return pushintegerresult(sysconf(checkint(L, 1))); } /*** Name of a terminal device. @function ttyname @int[opt=0] fd file descriptor to process @treturn[1] string name, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see ttyname(3) */ static int Pttyname(lua_State *L) { int fd = optint(L, 1, 0); char *name; checknargs(L, 1); name = ttyname(fd); if (name != NULL) return pushstringresult(name); if (errno != 0) return pusherror(L, "ttyname"); lua_pushnil(L); lua_pushliteral(L, "not a tty"); return 2; } #if LPOSIX_2001_COMPLIANT /*** Get id of foreground process group of terminal *fd*. @function tcgetpgrp @int fd the file descriptor of the controlling terminal of the current process @treturn[1] int id of foreground process group, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcgetpgrp(2) */ static int Ptcgetpgrp(lua_State *L) { int fd = checkint(L, 1); return pushresult(L, tcgetpgrp(fd), NULL); } /*** Make process group *pgid* the foreground process group of terminal *fd*. @function tcsetpgrp @int fd the file descriptor of the controlling terminal of the current process @int pgid id of the process group to make foreground process group @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see tcsetpgrp(2) */ static int Ptcsetpgrp(lua_State *L) { int fd = checkint(L, 1); pid_t pgid = (pid_t)checkinteger(L, 2); return pushresult(L, tcsetpgrp(fd, pgid), NULL); } #endif /*** Unlink a file. @function unlink @string path @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see unlink(2) */ static int Punlink(lua_State *L) { const char *path = luaL_checkstring(L, 1); checknargs(L, 1); return pushresult(L, unlink(path), path); } /*** Write bytes to a file. If *nbytes* is `nil` or omitted, write all bytes from *offset* through to the end of *buf*. If *offset* is `nil` or omitted, start writing bytes from the beginning of *buf*. Bounds checks are enforced, returning `posix.errno.EINVAL` before attempting to write any bytes, if the requested parameters would access bytes outside *buf*. @function write @int fd the file descriptor to act on @string buf containing bytes to write @int[opt=#buf] nbytes number of bytes to write @int[opt=0] offset skip the first offset bytes of buf @treturn[1] int number of bytes written, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see write(2) */ static int Pwrite(lua_State *L) { const int fd = checkint(L, 1); const char *buf = luaL_checkstring(L, 2); const int buflen = lua_objlen(L, 2); ssize_t nbytes = (ssize_t)optinteger(L, 3, buflen); const off_t offset = (off_t)optinteger(L, 4, 0); off_t invalid_offset = offset; checknargs(L, 4); /* `write(fd, buf, nil, #buf - 3)` -> write the last 3 bytes in buf */ if (offset && lua_type(L, 3) == LUA_TNIL) nbytes = buflen - offset; /* calling write with nbytes `0` may cause unspecified behaviour */ if (nbytes == 0) return pushintegerresult(0); if (offset >= 0 && nbytes > 0 && offset + nbytes <= buflen) return pushresult(L, write(fd, buf + offset, nbytes), NULL); if (offset + nbytes < 0 || offset + nbytes > buflen) invalid_offset += nbytes; errno = EINVAL; lua_pushnil(L); lua_pushfstring(L, "write: invalid attempt to access offset %d in a buffer of length %d", invalid_offset, buflen); lua_pushinteger(L, errno); return 3; } /*** Truncate a file to a specified length. @function ftruncate @int fd the file descriptor to act on @int length the length to truncate to @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see ftruncate(2) */ static int Pftruncate(lua_State *L) { int fd = checkint(L, 1); off_t length = (off_t)checkinteger(L, 2); checknargs(L, 2); return pushresult(L, ftruncate(fd, length), NULL); } /*** Truncate a file to a specified length. @function truncate @string path file to act on @int length the length to truncate to @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see ftruncate(2) */ static int Ptruncate(lua_State *L) { const char *path = luaL_checkstring(L, 1); off_t length = (off_t)checkinteger(L, 2); checknargs(L, 2); return pushresult(L, truncate(path, length), NULL); } static const luaL_Reg posix_unistd_fns[] = { LPOSIX_FUNC( P_exit ), LPOSIX_FUNC( Paccess ), LPOSIX_FUNC( Palarm ), LPOSIX_FUNC( Pchdir ), LPOSIX_FUNC( Pchown ), LPOSIX_FUNC( Pclose ), #if defined HAVE_CRYPT LPOSIX_FUNC( Pcrypt ), #endif LPOSIX_FUNC( Pdup ), LPOSIX_FUNC( Pdup2 ), LPOSIX_FUNC( Pexec ), LPOSIX_FUNC( Pexecp ), #if HAVE_FDATASYNC LPOSIX_FUNC( Pfdatasync ), #endif LPOSIX_FUNC( Pfork ), LPOSIX_FUNC( Pfsync ), LPOSIX_FUNC( Pgetcwd ), #if LPOSIX_2001_COMPLIANT LPOSIX_FUNC( Pgetgroups ), #endif LPOSIX_FUNC( Pgetegid ), LPOSIX_FUNC( Pgeteuid ), LPOSIX_FUNC( Pgetgid ), LPOSIX_FUNC( Pgetlogin ), LPOSIX_FUNC( Pgetopt ), LPOSIX_FUNC( Pgetpgrp ), LPOSIX_FUNC( Pgetpid ), LPOSIX_FUNC( Pgetppid ), LPOSIX_FUNC( Pgetuid ), LPOSIX_FUNC( Pgethostid ), LPOSIX_FUNC( Pisatty ), #if LPOSIX_2001_COMPLIANT LPOSIX_FUNC( Plchown ), #endif LPOSIX_FUNC( Plink ), LPOSIX_FUNC( Plinkat ), LPOSIX_FUNC( Plseek ), LPOSIX_FUNC( Pnice ), LPOSIX_FUNC( Ppathconf ), LPOSIX_FUNC( Ppipe ), LPOSIX_FUNC( Pread ), LPOSIX_FUNC( Preadlink ), LPOSIX_FUNC( Prmdir ), LPOSIX_FUNC( Psetpid ), LPOSIX_FUNC( Psleep ), LPOSIX_FUNC( Psync ), LPOSIX_FUNC( Psysconf ), LPOSIX_FUNC( Pttyname ), #if LPOSIX_2001_COMPLIANT LPOSIX_FUNC( Ptcgetpgrp ), LPOSIX_FUNC( Ptcsetpgrp ), #endif LPOSIX_FUNC( Punlink ), LPOSIX_FUNC( Pwrite ), LPOSIX_FUNC( Pftruncate ), LPOSIX_FUNC( Ptruncate ), {NULL, NULL} }; /*** Constants. @section constants */ /*** Standard constants. Any constants not available in the underlying system will be `nil` valued. @table posix.unistd @int _PC_CHOWN_RESTRICTED return 1 if chown requires appropriate privileges, 0 otherwise @int _PC_LINK_MAX maximum file link count @int _PC_MAX_CANON maximum bytes in terminal canonical input line @int _PC_MAX_INPUT maximum number of bytes in a terminal input queue @int _PC_NAME_MAX maximum number of bytes in a file name @int _PC_NO_TRUNC return 1 if over-long file names are truncated @int _PC_PATH_MAXmaximum number of bytes in a pathname @int _PC_PIPE_BUF maximum number of bytes in an atomic pipe write @int _PC_VDISABLE terminal character disabling value @int _SC_ARG_MAX maximum bytes of argument to @{posix.unistd.execp} @int _SC_CHILD_MAX maximum number of processes per user @int _SC_CLK_TCK statistics clock frequency @int _SC_JOB_CONTROL return 1 if system has job control, -1 otherwise @int _SC_NGROUPS_MAX maximum number of supplemental groups @int _SC_OPEN_MAX maximum number of open files per user @int _SC_SAVED_IDS return 1 if system supports saved user and group ids, -1 otherwise @int _SC_STREAM_MAX maximum number of streams per process @int _SC_TZNAME_MAX maximum number of timezone types @int _SC_VERSION POSIX.1 compliance version @int SEEK_CUR relative file pointer position @int SEEK_END set file pointer to the end of file @int SEEK_SET absolute file pointer position @int STDERR_FILENO standard error file descriptor @int STDIN_FILENO standard input file descriptor @int STDOUT_FILENO standard output file descriptor @usage -- Print unistd constants supported on this host. for name, value in pairs (require "posix.unistd") do if type (value) == "number" then print (name, value) end end */ LUALIB_API int luaopen_posix_unistd(lua_State *L) { luaL_newlib(L, posix_unistd_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("unistd")); lua_setfield(L, -2, "version"); /* pathconf arguments */ LPOSIX_CONST( _PC_CHOWN_RESTRICTED ); LPOSIX_CONST( _PC_LINK_MAX ); LPOSIX_CONST( _PC_MAX_CANON ); LPOSIX_CONST( _PC_MAX_INPUT ); LPOSIX_CONST( _PC_NAME_MAX ); LPOSIX_CONST( _PC_NO_TRUNC ); LPOSIX_CONST( _PC_PATH_MAX ); LPOSIX_CONST( _PC_PIPE_BUF ); LPOSIX_CONST( _PC_VDISABLE ); /* sysconf arguments */ LPOSIX_CONST( _SC_ARG_MAX ); LPOSIX_CONST( _SC_CHILD_MAX ); LPOSIX_CONST( _SC_CLK_TCK ); LPOSIX_CONST( _SC_JOB_CONTROL ); LPOSIX_CONST( _SC_NGROUPS_MAX ); LPOSIX_CONST( _SC_OPEN_MAX ); LPOSIX_CONST( _SC_PAGESIZE ); LPOSIX_CONST( _SC_SAVED_IDS ); LPOSIX_CONST( _SC_STREAM_MAX ); LPOSIX_CONST( _SC_TZNAME_MAX ); LPOSIX_CONST( _SC_VERSION ); /* lseek arguments */ LPOSIX_CONST( SEEK_CUR ); LPOSIX_CONST( SEEK_END ); LPOSIX_CONST( SEEK_SET ); /* Miscellaneous */ LPOSIX_CONST( STDERR_FILENO ); LPOSIX_CONST( STDIN_FILENO ); LPOSIX_CONST( STDOUT_FILENO ); return 1; } luaposix-36.3/ext/posix/utime.c000066400000000000000000000027361475444374100165670ustar00rootroot00000000000000/* * POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. * Copyright (C) 2013-2025 Gary V. Vaughan * Copyright (C) 2010-2013 Reuben Thomas * Copyright (C) 2008-2010 Natanael Copa * Clean up and bug fixes by Leo Razoumov 2006-10-11 * Luiz Henrique de Figueiredo 07 Apr 2006 23:17:49 * Based on original by Claudio Terra for Lua 3.x. * With contributions by Roberto Ierusalimschy. * With documentation from Steve Donovan 2012 */ /*** Set File Times. @module posix.utime */ #include #include #include "_helpers.c" /*** Change file last access and modification times. @function utime @string path existing file path @int[opt=now] mtime modification time @int[opt=now] atime access time @treturn[1] int `0`, if successful @return[2] nil @treturn[2] string error message @treturn[2] int errnum @see utime(2) */ static int Putime(lua_State *L) { struct utimbuf times; time_t currtime = time(NULL); const char *path = luaL_checkstring(L, 1); times.modtime = (time_t)optinteger(L, 2, currtime); times.actime = (time_t)optinteger(L, 3, currtime); checknargs(L, 3); return pushresult(L, utime(path, ×), path); } static const luaL_Reg posix_utime_fns[] = { LPOSIX_FUNC( Putime ), {NULL, NULL} }; LUALIB_API int luaopen_posix_utime(lua_State *L) { luaL_newlib(L, posix_utime_fns); lua_pushstring(L, LPOSIX_VERSION_STRING("utime")); lua_setfield(L, -2, "version"); return 1; } luaposix-36.3/lib/000077500000000000000000000000001475444374100140745ustar00rootroot00000000000000luaposix-36.3/lib/posix/000077500000000000000000000000001475444374100152365ustar00rootroot00000000000000luaposix-36.3/lib/posix/_base.lua000066400000000000000000000045011475444374100170120ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2014-2025 Gary V. Vaughan ]] --[[-- Private argument checking helpers. Undocumented internal helpers for argcheck wrapping. @module posix._base ]] local HAVE_TYPECHECK, typecheck = pcall(require, 'typecheck') local HAVE_BITWISE_OPS, bitwise = pcall(require, 'posix._bitwise') if not HAVE_BITWISE_OPS then if jit and bit then bitwise = bit else bitwise = require 'bit32' end end local _ENV = require 'posix._strict' { S_IRUSR = require 'posix.sys.stat'.S_IRUSR, S_IWUSR = require 'posix.sys.stat'.S_IWUSR, S_IXUSR = require 'posix.sys.stat'.S_IXUSR, S_IRGRP = require 'posix.sys.stat'.S_IRGRP, S_IWGRP = require 'posix.sys.stat'.S_IWGRP, S_IXGRP = require 'posix.sys.stat'.S_IXGRP, S_IROTH = require 'posix.sys.stat'.S_IROTH, S_IWOTH = require 'posix.sys.stat'.S_IWOTH, S_IXOTH = require 'posix.sys.stat'.S_IXOTH, S_ISUID = require 'posix.sys.stat'.S_ISUID, S_ISGID = require 'posix.sys.stat'.S_ISGID, band = bitwise.band, concat = table.concat, error = error, format = string.format, } local MODE_MAP = { {c='r', b=S_IRUSR}, {c='w', b=S_IWUSR}, {c='x', b=S_IXUSR}, {c='r', b=S_IRGRP}, {c='w', b=S_IWGRP}, {c='x', b=S_IXGRP}, {c='r', b=S_IROTH}, {c='w', b=S_IWOTH}, {c='x', b=S_IXOTH}, } return { MODE_MAP = MODE_MAP, argerror = function(name, i, extramsg, level) level = level or 1 local s = format("bad argument #%d to '%s'", i, name) if extramsg ~= nil then s = s .. ' (' .. extramsg .. ')' end error(s, level + 1) end, argscheck = HAVE_TYPECHECK and typecheck.argscheck or function(_, fn) return fn end, band = bitwise.band, bor = bitwise.bor, bnot = bitwise.bnot, pushmode = function(mode) local m = {} for i = 1, 9 do if band(mode, MODE_MAP[i].b) ~= 0 then m[i] = MODE_MAP[i].c else m[i] = '-' end end if band(mode, S_ISUID) ~= 0 then if band(mode, S_IXUSR) ~= 0 then m[3] = 's' else m[3] = 'S' end end if band(mode, S_ISGID) ~= 0 then if band(mode, S_IXGRP) ~= 0 then m[6] = 's' else m[6] = 'S' end end return concat(m) end, } luaposix-36.3/lib/posix/_bitwise.lua000066400000000000000000000007641475444374100175550ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2 & 5.3. Copyright (C) 2022-2025 Gary V. Vaughan ]] --[[-- Private argument checking helpers. Undocumented internal helpers for bitwise operations on Lua 5.3+. @module posix._bitwise ]] return { band = function(a, ...) for _, v in next, {...} do a = a & v end return a end, bor = function(a, ...) for _, v in next, {...} do a = a | v end return a end, bnot = function(a) return ~a end, } luaposix-36.3/lib/posix/_strict.lua000066400000000000000000000012011475444374100174020ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2014-2025 Gary V. Vaughan ]] --[[-- Private argument checking helpers. Undocumented internal helpers for strict environment wrapping. @module posix._strict ]] local setfenv = rawget(_G, 'setfenv') or function() end local strict do local ok, _debug = pcall(require, 'std._debug.init') if ok and _debug.strict then ok, strict = pcall(require, 'std.strict.init') end if not ok then strict = function(env) return env end end end return function(env, level) env = strict(env) setfenv(1+(level or 1), env) return env end luaposix-36.3/lib/posix/compat.lua000066400000000000000000000220461475444374100172300ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2014-2025 Gary V. Vaughan ]] --[[-- Legacy Lua POSIX bindings. APIs for maintaining compatibility with previous releases. @module posix ]] local LOG_MASK = require 'posix.syslog'.LOG_MASK local MODE_MAP = require 'posix._base'.MODE_MAP local O_CREAT = require 'posix.fcntl'.O_CREAT local O_TRUNC = require 'posix.fcntl'.O_TRUNC local O_WRONLY = require 'posix.fcntl'.O_WRONLY local S_IRGRP = require 'posix.sys.stat'.S_IRGRP local S_IROTH = require 'posix.sys.stat'.S_IROTH local S_IRUSR = require 'posix.sys.stat'.S_IRUSR local S_IRWXG = require 'posix.sys.stat'.S_IRWXG local S_IRWXO= require 'posix.sys.stat'.S_IRWXO local S_IRWXU = require 'posix.sys.stat'.S_IRWXU local S_ISGID = require 'posix.sys.stat'.S_ISGID local S_ISUID = require 'posix.sys.stat'.S_ISUID local S_IWGRP = require 'posix.sys.stat'.S_IWGRP local S_IWOTH = require 'posix.sys.stat'.S_IWOTH local S_IWUSR = require 'posix.sys.stat'.S_IWUSR local S_IXGRP = require 'posix.sys.stat'.S_IXGRP local S_IXOTH = require 'posix.sys.stat'.S_IXOTH local S_IXUSR = require 'posix.sys.stat'.S_IXUSR local argerror = require 'posix._base'.argerror local argscheck = require 'posix._base'.argscheck local chmod = require 'posix.sys.stat'.chmod local band = require 'posix._base'.band local bnot = require 'posix._base'.bnot local bor = require 'posix._base'.bor local concat = table.concat local gsub = string.gsub local match = string.match local mkdir = require 'posix.sys.stat'.mkdir local mkfifo = require 'posix.sys.stat'.mkfifo local msgget = require 'posix.sys.msg'.msgget local open = require 'posix.fcntl'.open local pushmode = require 'posix._base'.pushmode local setlogmask = require 'posix.syslog'.setlogmask local stat = require 'posix.sys.stat'.stat local sub = string.sub local tonumber = tonumber local umask = require 'posix.sys.stat'.umask local RWXALL = bor(S_IRWXU, S_IRWXG, S_IRWXO) local FCREAT = bor(O_CREAT, O_WRONLY, O_TRUNC) local function rwxrwxrwx(modestr) local mode = 0 for i = 1, 9 do if sub(modestr, i, i) == MODE_MAP[i].c then mode = bor(mode, MODE_MAP[i].b) elseif sub(modestr, i, i) == 's' then if i == 3 then mode = bor(mode, S_ISUID, S_IXUSR) elseif i == 6 then mode = bor(mode, S_ISGID, S_IXGRP) else return nil -- bad mode end end end return mode end local function octal_mode(modestr) local mode = 0 for i = 1, #modestr do mode = mode * 8 + tonumber(sub(modestr, i, i)) end return mode end local function mode_munch(mode, modestr) if modestr == nil then return nil, 'string expected, got no value' elseif #modestr == 9 and match(modestr, '^[-rswx]+$') then return rwxrwxrwx(modestr) elseif match(modestr, '^[0-7]+$') then return octal_mode(modestr) elseif match(modestr, '^[ugoa]+%s*[-+=]%s*[rswx]+,*') then gsub(modestr, '%s*(%a+)%s*(.)%s*(%a+),*', function(who, op, what) local bits, bobs = 0, 0 if match(who, '[ua]') then bits = bor(bits, S_ISUID, S_IRWXU) end if match(who, '[ga]') then bits = bor(bits, S_ISGID, S_IRWXG) end if match(who, '[oa]') then bits = bor(bits, S_IRWXO) end if match(what, 'r') then bobs = bor(bobs, S_IRUSR, S_IRGRP, S_IROTH) end if match(what, 'w') then bobs = bor(bobs, S_IWUSR, S_IWGRP, S_IWOTH) end if match(what, 'x') then bobs = bor(bobs, S_IXUSR, S_IXGRP, S_IXOTH) end if match(what, 's') then bobs = bor(bobs, S_ISUID, S_ISGID) end if op == '+' then -- mode |= bits & bobs mode = bor(mode, band(bits, bobs)) elseif op == '-' then -- mode &= ~(bits & bobs) mode = band(mode, bnot(band(bits, bobs))) elseif op == '=' then -- mode =(mode & ~bits) |(bits & bobs) mode = bor(band(mode, bnot(bits)), band(bits, bobs)) end end) return mode else return nil, 'bad mode' end end return { --- Change the mode of the path. -- @function chmod -- @string path existing file path -- @string mode one of the following formats: -- -- * 'rwxrwxrwx' (e.g. 'rw-rw-r--') -- * 'ugo+-=rwx' (e.g. 'u+w') -- * '+-=rwx' (e.g. '+w') -- -- @return[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see chmod(2) -- @usage chmod('bin/dof', '+x') chmod = argscheck('chmod(string, string)', function(path, modestr) local mode = (stat(path) or {}).st_mode local bits, err = mode_munch(mode or 0, modestr) if bits == nil then argerror('chmod', 2, err, 2) end return chmod(path, band(bits, RWXALL)) end), --- Create a file. -- This function is obsoleted by @{posix.fcntl.open} with `posix.O_CREAT`. -- @function creat -- @string path name of file to create -- @string mode permissions with which to create file -- @treturn[1] int file descriptor of file at *path*, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see creat(2) -- @see posix.chmod -- @usage -- fd = creat('data', 'rw-r-----') creat = argscheck('creat(string, string)', function(path, modestr) local bits, err = mode_munch(0, modestr) if bits == nil then argerror('creat', 2, err, 2) end return open(path, FCREAT, band(bits, RWXALL)) end), --- Make a directory. -- @function mkdir -- @string path location in file system to create directory -- @treturn[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum mkdir = argscheck('mkdir(string)', function(path) return mkdir(path, RWXALL) end), --- Make a FIFO pipe. -- @function mkfifo -- @string path location in file system to create fifo -- @treturn[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum mkfifo = argscheck('mkfifo(string)', function(path) return mkfifo(path, RWXALL) end), --- Get a message queue identifier -- @function msgget -- @int key message queue id, or `IPC_PRIVATE` for a new queue -- @int[opt=0] flags bitwise OR of zero or more from `IPC_CREAT` and `IPC_EXCL` -- @string[opt='rw-rw-rw-'] mode execute bits are ignored -- @treturn[1] int message queue identifier, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see msgget(2) msgget = argscheck('msgget(int, ?int, ?string)', function(key, msgflg, modestr) local bits, err = mode_munch(0, modestr) if bits == nil then argerror('msgget', 3, err, 2) end return msgget(key, bor(msgflg, band(bits, RWXALL))) end), --- Open a file. -- @function open -- @string path file to act on -- @int oflags bitwise OR of zero or more of `O_RDONLY`, `O_WRONLY`, `O_RDWR`, -- `O_APPEND`, `O_CREAT`, `O_DSYNC`, `O_EXCL`, `O_NOCTTY`, `O_NONBLOCK`, -- `O_RSYNC`, `O_SYNC`, `O_TRUNC` -- @string modestr(used with `O_CREAT`; see @{chmod} for format) -- @treturn[1] int file descriptor for *path*, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see open(2) -- @usage -- fd = posix.open('data', bit.bor(posix.O_CREAT, posix.O_RDWR), 'rw-r-----') open = argscheck('open(string, int, [string])', function(path, oflags, modestr) local bits, err if band(oflags, O_CREAT) ~= 0 then bits, err = mode_munch(0, modestr) if bits == nil then argerror('open', 3, err, 2) end bits = band(bits, RWXALL) end return open(path, oflags, bits) end), --- Set log priority mask -- @function setlogmask -- @int ... zero or more of `LOG_EMERG`, `LOG_ALERT`, `LOG_CRIT`, -- `LOG_WARNING`, `LOG_NOTICE`, `LOG_INFO` and `LOG_DEBUG` -- @treturn[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum setlogmask = argscheck('setlogmask(?int...)', function(...) local mask, i, t = 0, 1, {...} while t[i] do mask = bor(mask, LOG_MASK(t[i])) i = i + 1 end return setlogmask(mask) end), --- Set file mode creation mask. -- @function umask -- @string[opt] mode file creation mask string -- @treturn string previous umask -- @see umask(2) -- @see posix.sys.stat.umask umask = argscheck('umask([?string])', function(modestr) modestr = modestr or '' local mode = umask(0) umask(mode) mode = band(bnot(mode), RWXALL) if modestr ~= '' then local bits, err = mode_munch(mode, modestr) if bits == nil then argerror('umask', 1, err, 2) end mode = band(bits, RWXALL) umask(bnot(mode)) end return pushmode(mode) end), } luaposix-36.3/lib/posix/deprecated.lua000066400000000000000000000761301475444374100200500ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2014-2025 Gary V. Vaughan ]] --[[-- Legacy Lua POSIX bindings. Undocumented Legacy APIs for compatibility with previous releases. @module posix.deprecated ]] local HAVE_DEBUG, _debug = pcall(require, 'std._debug') local argerror = require 'posix._base'.argerror local _ENV = require 'posix._strict' { CLOCK_MONOTONIC = require 'posix.time'.CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID = require 'posix.time'.CLOCK_PROCESS_CPUTIME_ID, CLOCK_REALTIME = require 'posix.time'.CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID = require 'posix.time'.CLOCK_THREAD_CPUTIME_ID, FNM_NOMATCH = require 'posix.fnmatch'.FNM_NOMATCH, LOG_CONS = require 'posix.syslog'.LOG_CONS, LOG_NDELAY = require 'posix.syslog'.LOG_NDELAY, LOG_PID = require 'posix.syslog'.LOG_PID, RLIMIT_AS = require 'posix.sys.resource'.RLIMIT_AS, RLIMIT_CORE = require 'posix.sys.resource'.RLIMIT_CORE, RLIMIT_CPU = require 'posix.sys.resource'.RLIMIT_CPU, RLIMIT_DATA = require 'posix.sys.resource'.RLIMIT_DATA, RLIMIT_FSIZE = require 'posix.sys.resource'.RLIMIT_FSIZE, RLIMIT_NOFILE = require 'posix.sys.resource'.RLIMIT_NOFILE, RLIMIT_STACK = require 'posix.sys.resource'.RLIMIT_STACK, S_ISBLK = require 'posix.sys.stat'.S_ISBLK, S_ISCHR = require 'posix.sys.stat'.S_ISCHR, S_ISDIR = require 'posix.sys.stat'.S_ISDIR, S_ISFIFO = require 'posix.sys.stat'.S_ISFIFO, S_ISLNK = require 'posix.sys.stat'.S_ISLNK, S_ISREG = require 'posix.sys.stat'.S_ISREG, S_ISSOCK = require 'posix.sys.stat'.S_ISSOCK, _PC_CHOWN_RESTRICTED = require 'posix.unistd'._PC_CHOWN_RESTRICTED, _PC_LINK_MAX = require 'posix.unistd'._PC_LINK_MAX, _PC_MAX_CANON = require 'posix.unistd'._PC_MAX_CANON, _PC_MAX_INPUT = require 'posix.unistd'._PC_MAX_INPUT, _PC_NAME_MAX = require 'posix.unistd'._PC_NAME_MAX, _PC_NO_TRUNC = require 'posix.unistd'._PC_NO_TRUNC, _PC_PATH_MAX = require 'posix.unistd'._PC_PATH_MAX, _PC_PIPE_BUF = require 'posix.unistd'._PC_PIPE_BUF, _PC_VDISABLE = require 'posix.unistd'._PC_VDISABLE, _SC_ARG_MAX = require 'posix.unistd'._SC_ARG_MAX, _SC_CHILD_MAX = require 'posix.unistd'._SC_CHILD_MAX, _SC_CLK_TCK = require 'posix.unistd'._SC_CLK_TCK, _SC_JOB_CONTROL = require 'posix.unistd'._SC_JOB_CONTROL, _SC_NGROUPS_MAX = require 'posix.unistd'._SC_NGROUPS_MAX, _SC_OPEN_MAX = require 'posix.unistd'._SC_OPEN_MAX, _SC_PAGESIZE = require 'posix.unistd'._SC_PAGESIZE, _SC_SAVED_IDS = require 'posix.unistd'._SC_SAVED_IDS, _SC_STREAM_MAX = require 'posix.unistd'._SC_STREAM_MAX, _SC_TZNAME_MAX = require 'posix.unistd'._SC_TZNAME_MAX, _SC_VERSION = require 'posix.unistd'._SC_VERSION, _debug = HAVE_DEBUG and _debug or {}, argscheck = require 'posix._base'.argscheck, bind = require 'posix.sys.socket'.bind, bor = require 'posix._base'.bor, clock_getres = require 'posix.time'.clock_getres or false, clock_gettime = require 'posix.time'.clock_gettime or false, connect = require 'posix.sys.socket'.connect, error = error, exec = require 'posix.unistd'.exec, execp = require 'posix.unistd'.execp, fileno = require 'posix.stdio'.fileno, fnmatch = require 'posix.fnmatch'.fnmatch, format = string.format, getegid = require 'posix.unistd'.getegid, geteuid = require 'posix.unistd'.geteuid, getgid = require 'posix.unistd'.getgid, getgrgid = require 'posix.grp'.getgrgid, getgrnam = require 'posix.grp'.getgrnam, gethostid = require 'posix.unistd'.gethostid, getpgrp = require 'posix.unistd'.getpgrp, getppid = require 'posix.unistd'.getppid, getpwnam = require 'posix.pwd'.getpwnam, getpwuid = require 'posix.pwd'.getpwuid, getrlimit = require 'posix.sys.resource'.getrlimit, gettimeofday = require 'posix.sys.time'.gettimeofday, getuid = require 'posix.unistd'.getuid, getpid = require 'posix.unistd'.getpid, gmtime = require 'posix.time'.gmtime, gsub = string.gsub, isgraph = require 'posix.ctype'.isgraph, isprint = require 'posix.ctype'.isprint, localtime = require 'posix.time'.localtime, lower = string.lower, lstat = require 'posix.sys.stat'.lstat, mktime = require 'posix.time'.mktime, nanosleep = require 'posix.time'.nanosleep, next = next, nonempty = next, openlog = require 'posix.syslog'.openlog, pathconf = require 'posix.unistd'.pathconf, posix_fadvise = require 'posix.fcntl'.posix_fadvise or false, pushmode = require 'posix._base'.pushmode, require = require, select = select, setrlimit = require 'posix.sys.resource'.setrlimit, statvfs = require 'posix.sys.statvfs'.statvfs, strftime = require 'posix.time'.strftime, strptime = require 'posix.time'.strptime, sub = string.sub, sysconf = require 'posix.unistd'.sysconf, time = require 'posix.time'.time, times = require 'posix.sys.times'.times, type = type, uname = require 'posix.sys.utsname'.uname, unpack = table.unpack or unpack, } -- FIXME: specl-14.x breaks function environments here :( local bor, exec, getegid, getgrgid, getgrnam, getrlimit, gmtime, gsub, localtime, lower, mktime, nanosleep, strftime, strptime, sub, time, uname = bor, exec, getegid, getgrgid, getgrnam, getrlimit, gmtime, gsub, localtime, lower, mktime, nanosleep, strftime, strptime, sub, time, uname local OPENLOG_MAP = { [' '] = 0, c = LOG_CONS, n = LOG_NDELAY, p = LOG_PID, } local RLIMIT_MAP = { core = RLIMIT_CORE, cpu = RLIMIT_CPU, data = RLIMIT_DATA, fsize = RLIMIT_FSIZE, nofile = RLIMIT_NOFILE, stack = RLIMIT_STACK, as = RLIMIT_AS, } -- Convert a legacy API tm table to a posix.time.PosixTm compatible table. local function PosixTm(legacytm) return { tm_sec = legacytm.sec, tm_min = legacytm.min, tm_hour = legacytm.hour, -- For compatibility with Lua os.date() use 'day' if 'monthday' is -- not set. tm_mday = legacytm.monthday or legacytm.day, tm_mon = legacytm.month - 1, tm_year = legacytm.year - 1900, tm_wday = legacytm.weekday, tm_yday = legacytm.yearday, tm_isdst = legacytm.is_dst and 1 or (legacytm.is_dst ~= nil and 0 or -1), tm_gmtoff = legacytm.gmtoff, tm_zone = legacytm.zone } end -- Convert a posix.time.PosixTm into a legacy API tm table. local function LegacyTm(posixtm) return { sec = posixtm.tm_sec, min = posixtm.tm_min, hour = posixtm.tm_hour, monthday = posixtm.tm_mday, day = posixtm.tm_mday, month = posixtm.tm_mon + 1, year = posixtm.tm_year + 1900, weekday = posixtm.tm_wday, yearday = posixtm.tm_yday, is_dst = posixtm.tm_isdst > 0 or (posixtm.tm_isdst < 0 and nil), gmtoff = posixtm.tm_gmtoff, zone = posixtm.tm_zone } end local function argtypeerror(name, i, expect, actual, level) level = level or 1 local fmt = '%s expected, got %s' argerror( name, i, format(fmt, expect, gsub(type(actual), 'nil', 'no value')), level + 1 ) end local function badoption(name, i, what, option, level) level = level or 1 local fmt = "invalid %s option '%s'" argerror(name, i, format(fmt, what, option), level + 1) end local function checkstring(name, i, actual, level) level = level or 1 if type(actual) ~= 'string' then argtypeerror(name, i, 'string', actual, level + 1) end return actual end local function optstring(name, i, actual, def, level) level = level or 1 if actual ~= nil and type(actual) ~= 'string' then argtypeerror(name, i, 'nil or string', actual, level + 1) end return actual or def end local function toomanyargerror(name, expected, got, level) level = level or 1 local fmt = 'no more than %d argument%s expected, got %d' argerror( name, expected + 1, format(fmt, expected, expected == 1 and '' or 's', got), level + 1 ) end local function checkselection(fname, argi, fields, level) level = level or 1 local field1, type1 = fields[1], type(fields[1]) if type1 == 'table' and #fields > 1 then toomanyargerror(fname, argi, #fields + argi - 1, level + 1) elseif field1 ~= nil and type1 ~= 'table' and type1 ~= 'string' then argtypeerror(fname, argi, 'nil, string or table', field1, level + 1) end for i = 2, #fields do checkstring(fname, i + argi -1, fields[i], level + 1) end end local function doselection(name, argoffset, fields, map) if #fields == 1 and type(fields[1]) == 'table' then fields = fields[1] end if nonempty(fields) then local r = {} for i = 1, #fields do local v = fields[i] if map[v] then r[#r + 1] = map[v] else argerror(name, i + argoffset, "invalid option '" .. v .. "'", 2) end end return unpack(r) else return map end end local get_clk_id_const local Pclock_getres if clock_getres then -- When supported by underlying system get_clk_id_const = function(name) local map = { monotonic = CLOCK_MONOTONIC, process_cputime_id = CLOCK_PROCESS_CPUTIME_ID, thread_cputime_id = CLOCK_THREAD_CPUTIME_ID, } return map[name] or CLOCK_REALTIME end Pclock_getres = argscheck('clock_getres([?string])', function(name) local ts = require 'posix.time'.clock_getres(get_clk_id_const(name)) return ts.tv_sec, ts.tv_nsec end) end local Pclock_gettime if clock_gettime then -- When supported by underlying system Pclock_gettime = argscheck('clock_gettime([?string])', function(name) local ts = require 'posix.time'.clock_gettime(get_clk_id_const(name)) return ts.tv_sec, ts.tv_nsec end) end local function Pexec(path, ...) local argt = (...) if type(argt) ~= 'table' then argt = {...} end return exec(path, argt) end if _debug.argcheck then Pexec = function(path, ...) checkstring('exec', 1, path) local argt = (...) if type(argt) == 'string' then argt = {...} for i = 1, #argt do checkstring('exec', i + 1, argt[i]) end elseif type(argt) == 'table' then local n = select('#', ...) if n > 1 then toomanyargerror('exec', 2, n + 1) end else argtypeerror('exec', 2, 'nil, string or table', argt) end return exec(path, argt) end end local function Pexecp(path, ...) local argt = (...) if type(argt) ~= 'table' then argt = {...} end return execp(path, argt) end if _debug.argcheck then Pexecp = function(path, ...) checkstring('execp', 1, path) local argt = (...) if type(argt) == 'string' then argt = {...} for i = 1, #argt do checkstring('execp', i + 1, argt[i]) end elseif type(argt) == 'table' then local n = select('#', ...) if n > 1 then toomanyargerror('execp', 2, n + 1) end else argtypeerror('execp', 2, 'nil, string or table', argt) end return execp(path, argt) end end local Pfadvise if posix_fadvise then -- When supported by underlying system Pfadvise = argscheck('fadvise(FILE*, int, int, int)', function(fh, ...) return posix_fadvise(fileno(fh), ...) end) end local function Pgetpasswd(user, ...) user = user or geteuid() local p if type(user) == 'number' then p = getpwuid(user) elseif type(user) == 'string' then p = getpwnam(user) end if p ~= nil then return doselection('getpasswd', 1, {...}, { dir = p.pw_dir, gid = p.pw_gid, name = p.pw_name, passwd = p.pw_passwd, shell = p.pw_shell, uid = p.pw_uid, }) end end if _debug.argcheck then local _getpasswd = Pgetpasswd Pgetpasswd = function(user, ...) checkselection('getpasswd', 2, {...}, 2) return _getpasswd(user, ...) end end local function Pgetpid(...) return doselection('getpid', 0, {...}, { egid = getegid(), euid = geteuid(), gid = getgid(), uid = getuid(), pgrp = getpgrp(), pid = getpid(), ppid = getppid(), }) end if _debug.argcheck then local _getpid = Pgetpid Pgetpid = function(...) checkselection('getpid', 1, {...}, 2) return _getpid(...) end end local Spathconf = { CHOWN_RESTRICTED = _PC_CHOWN_RESTRICTED, LINK_MAX = _PC_LINK_MAX, MAX_CANON = _PC_MAX_CANON, MAX_INPUT = _PC_MAX_INPUT, NAME_MAX = _PC_NAME_MAX, NO_TRUNC = _PC_NO_TRUNC, PATH_MAX = _PC_PATH_MAX, PIPE_BUF = _PC_PIPE_BUF, VDISABLE = _PC_VDISABLE, } local function Ppathconf(path, ...) local argt, map = {...}, {} if path ~= nil and Spathconf[path] ~= nil then path, argt = '.', {path, ...} end for k, v in next, Spathconf do map[k] = pathconf(path or '.', v) end return doselection('pathconf', 1, {...}, map) end if _debug.argcheck then local _pathconf = Ppathconf Ppathconf = function(path, ...) if path ~= nil and Spathconf[path] ~= nil then checkselection('pathconf', 1, {path, ...}, 2) else optstring('pathconf', 1, path, '.', 2) checkselection('pathconf', 2, {...}, 2) end return _pathconf(path, ...) end end local function filetype(mode) if S_ISREG(mode) ~= 0 then return 'regular' elseif S_ISLNK(mode) ~= 0 then return 'link' elseif S_ISDIR(mode) ~= 0 then return 'directory' elseif S_ISCHR(mode) ~= 0 then return 'character device' elseif S_ISBLK(mode) ~= 0 then return 'block device' elseif S_ISFIFO(mode) ~= 0 then return 'fifo' elseif S_ISSOCK(mode) ~= 0 then return 'socket' else return '?' end end local function Pstat(path, ...) -- for bugwards compatibility with v<=32 local info = lstat(path) if info ~= nil then return doselection('stat', 1, {...}, { dev = info.st_dev, ino = info.st_ino, mode = pushmode(info.st_mode), nlink = info.st_nlink, uid = info.st_uid, gid = info.st_gid, size = info.st_size, atime = info.st_atime, mtime = info.st_mtime, ctime = info.st_ctime, type = filetype(info.st_mode), }) end end if _debug.argcheck then local _stat = Pstat Pstat = function(path, ...) checkstring('stat', 1, path, 2) checkselection('stat', 2, {...}, 2) return _stat(path, ...) end end local function Pstatvfs(path, ...) local info = statvfs(path) if info ~= nil then return doselection('statvfs', 1, {...}, { bsize = info.f_bsize, frsize = info.f_frsize, blocks = info.f_blocks, bfree = info.f_bfree, bavail = info.f_bavail, files = info.f_files, ffree = info.f_ffree, favail = info.f_favail, fsid = info.f_fsid, flag = info.f_flag, namemax = info.f_namemax, }) end end if _debug.argcheck then local _statvfs = Pstatvfs Pstatvfs = function(path, ...) checkstring('statvfs', 1, path, 2) checkselection('statvfs', 2, {...}, 2) return _statvfs(path, ...) end end local function Psysconf(...) return doselection('sysconf', 0, {...}, { ARG_MAX = sysconf(_SC_ARG_MAX), CHILD_MAX = sysconf(_SC_CHILD_MAX), CLK_TCK = sysconf(_SC_CLK_TCK), JOB_CONTROL = sysconf(_SC_JOB_CONTROL), NGROUPS_MAX = sysconf(_SC_NGROUPS_MAX), OPEN_MAX = sysconf(_SC_OPEN_MAX), PAGESIZE = sysconf(_SC_PAGESIZE), SAVED_IDS = sysconf(_SC_SAVED_IDS), STREAM_MAX = sysconf(_SC_STREAM_MAX), TZNAME_MAX = sysconf(_SC_TZNAME_MAX), VERSION = sysconf(_SC_VERSION), }) end if _debug.argcheck then local _sysconf = Psysconf Psysconf = function(...) checkselection('sysconf', 1, {...}, 2) return _sysconf(...) end end local function Ptimes(...) local info = times() return doselection('times', 0, {...}, { utime = info.tms_utime, stime = info.tms_stime, cutime = info.tms_cutime, cstime = info.tms_cstime, elapsed = info.elapsed, }) end if _debug.argcheck then local _times = Ptimes Ptimes = function(...) checkselection('times', 1, {...}, 2) return _times(...) end end return { --- Bind an address to a socket. -- @function bind -- @int fd socket descriptor to act on -- @tparam PosixSockaddr addr socket address -- @treturn[1] bool `true`, if successful -- @return[2] nil -- @treturn[2] string error messag -- @treturn[2] int errnum -- @see bind(2) bind = function(...) local rt = {bind(...)} if rt[1] == 0 then return true end return unpack(rt) end, --- Find the precision of a clock. -- @function clock_getres -- @string[opt='realtime'] name name of clock, one of 'monotonic', -- 'process\_cputime\_id', 'realtime', or 'thread\_cputime\_id' -- @treturn[1] int seconds -- @treturn[1] int nanoseconds, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see clock_getres(3) clock_getres = Pclock_getres, --- Read a clock -- @function clock_gettime -- @string[opt='realtime'] name name of clock, one of 'monotonic', -- 'process\_cputime\_id', 'realtime', or 'thread\_cputime\_id' -- @treturn[1] int seconds -- @treturn[1] int nanoseconds, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see clock_gettime(3) clock_gettime = Pclock_gettime, --- Initiate a connection on a socket. -- @function connect -- @int fd socket descriptor to act on -- @tparam PosixSockaddr addr socket address -- @treturn[1] bool `true`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see connect(2) connect = function(...) local rt = {connect(...)} if rt[1] == 0 then return true end return unpack(rt) end, --- Execute a program without using the shell. -- @function exec -- @string path -- @tparam[opt] table|strings ... table or tuple of arguments(table can include index 0) -- @return nil -- @treturn string error message -- @treturn int errnum -- @see execve(2) exec = Pexec, --- Execute a program with the shell. -- @function execp -- @string path -- @tparam[opt] table|strings ... table or tuple of arguments(table can include index 0) -- @return nil -- @treturn string error message -- @treturn int errnum -- @see execve(2) execp = Pexecp, --- Instruct kernel on appropriate cache behaviour for a file or file segment. -- @function fadvise -- @tparam file fh Lua file object -- @int offset start of region -- @int len number of bytes in region -- @int advice one of `POSIX_FADV_NORMAL, `POSIX_FADV_SEQUENTIAL, -- `POSIX_FADV_RANDOM`, `POSIX_FADV_\NOREUSE`, `POSIX_FADV_WILLNEED` or -- `POSIX_FADV_DONTNEED` -- @treturn[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @see posix_fadvise(2) fadvise = Pfadvise, --- Match a filename against a shell pattern. -- @function fnmatch -- @string pat shell pattern -- @string name filename -- @treturn bool `true` if *pat* matched *name*, otherwise `false` -- @raise error if fnmatch failed -- @see posix.fnmatch.fnmatch fnmatch = function(...) local r = fnmatch(...) if r == 0 then return true elseif r == FNM_NOMATCH then return false end error 'fnmatch failed' end, --- Information about a group. -- @function getgroup -- @tparam[opt=current group] int|string group id or group name -- @treturn group group information -- @usage -- print(posix.getgroup(posix.getgid()).name) getgroup = argscheck('getgroup([?int|string])', function(grp) grp = grp or getegid() local g if type(grp) == 'number' then g = getgrgid(grp) elseif type(grp) == 'string' then g = getgrnam(grp) end if g ~= nil then return {name=g.gr_name, gid=g.gr_gid, mem=g.gr_mem} end end), --- Get the password entry for a user. -- @function getpasswd -- @tparam[opt=current user] int|string user name or id -- @string ... field names, each one of 'uid', 'name', 'gid', 'passwd', -- 'dir' or 'shell' -- @return ... values, or a table of all fields if *user* is `nil` -- @usage for a,b in pairs(posix.getpasswd 'root') do print(a, b) end -- @usage print(posix.getpasswd('root', 'shell')) getpasswd = argscheck('getpasswd(?int|string, [?string...])', Pgetpasswd), --- Get process identifiers. -- @function getpid -- @tparam[opt] table|string type one of 'egid', 'euid', 'gid', 'uid', -- 'pgrp', 'pid' or 'ppid'; or a single list of the same -- @string[opt] ... unless *type* was a table, zero or more additional -- type strings -- @return ... values, or a table of all fields if no option given -- @usage for a,b in pairs(posix.getpid()) do print(a, b) end -- @usage print(posix.getpid('uid', 'euid')) getpid = Pgetpid, --- Get resource limits for this process. -- @function getrlimit -- @string resource one of 'core', 'cpu', 'data', 'fsize', 'nofile', -- 'stack' or 'as' -- @treturn[1] int soft limit -- @treturn[1] int hard limit, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum getrlimit = argscheck('getrlimit(string)', function (rcstr) local rc = RLIMIT_MAP[lower(rcstr)] if rc == nil then argerror('getrlimit', 1, "invalid option '" .. rcstr .. "'") end local rlim = getrlimit(rc) return rlim.rlim_cur, rlim.rlim_max end), --- Get time of day. -- @function gettimeofday -- @treturn timeval time elapsed since *epoch* -- @see gettimeofday(2) gettimeofday = function(...) local tv = gettimeofday(...) return {sec=tv.tv_sec, usec=tv.tv_usec} end, --- Convert epoch time value to a broken-down UTC time. -- Here, broken-down time tables the month field is 1-based not -- 0-based, and the year field is the full year, not years since -- 1900. -- @function gmtime -- @int[opt=now] t seconds since epoch -- @treturn table broken-down time gmtime = argscheck('gmtime([?int])', function(epoch) return LegacyTm(gmtime(epoch or time())) end), --- Get host id. -- @function hostid -- @treturn int unique host identifier hostid = gethostid, --- Check for any printable character except space. -- @function isgraph -- @string character to act on -- @treturn bool non-`false` if character is in the class -- @see isgraph(3) isgraph = function(...) return isgraph(...) ~= 0 end, --- Check for any printable character including space. -- @function isprint -- @string character to act on -- @treturn bool non-`false` if character is in the class -- @see isprint(3) isprint = function(...) return isprint(...) ~= 0 end, --- Convert epoch time value to a broken-down local time. -- Here, broken-down time tables the month field is 1-based not -- 0-based, and the year field is the full year, not years since -- 1900. -- @function localtime -- @int[opt=now] t seconds since epoch -- @treturn table broken-down time localtime = argscheck('localtime([?int])', function(epoch) return LegacyTm(localtime(epoch or time())) end), --- Convert a broken-down localtime table into an epoch time. -- @function mktime -- @tparam tm broken-down localtime table -- @treturn in seconds since epoch -- @see mktime(3) -- @see localtime mktime = argscheck('mktime([?table])', function(legacytm) local posixtm = legacytm and PosixTm(legacytm) or localtime(time()) return mktime(posixtm) end), --- Sleep with nanosecond precision. -- @function nanosleep -- @int seconds requested sleep time -- @int nanoseconds requested sleep time -- @treturn[1] int `0` if requested time has elapsed, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum -- @treturn[2] int unslept seconds remaining, if interrupted -- @treturn[2] int unslept nanoseconds remaining, if interrupted -- @see nanosleep(2) -- @see posix.unistd.sleep nanosleep = argscheck('nanosleep(int, int)', function(sec, nsec) local r, errmsg, errno, timespec = nanosleep {tv_sec=sec, tv_nsec=nsec} if r == 0 then return 0 end return r, errmsg, errno, timespec.tv_sec, timespec.tv_nsec end), --- Open the system logger. -- @function openlog -- @string ident all messages will start with this -- @string[opt] option any combination of 'c'(directly to system console -- if an error sending), 'n'(no delay) and 'p'(show PID) -- @int [opt=`LOG_USER`] facility one of `LOG_AUTH`, `LOG_AUTHORITY`, -- `LOG_CRON`, `LOG_DAEMON`, `LOG_KERN`, `LOG_LPR`, `LOG_MAIL`, -- `LOG_NEWS`, `LOG_SECURITY`, `LOG_USER`, `LOG_UUCP` or `LOG_LOCAL0` -- through `LOG_LOCAL7` -- @see syslog(3) openlog = argscheck('openlog(string, ?string, [?int])', function(ident, optstr, facility) local option = 0 if optstr then for i = 1, #optstr do local c = sub(optstr, i, i) if OPENLOG_MAP[c] == nil then badoption('openlog', 2, 'openlog', c) end option = bor(option, OPENLOG_MAP[c]) end end return openlog(ident, option, facility) end ), --- Get configuration information at runtime. -- @function pathconf -- @string[opt='.'] path file to act on -- @tparam[opt] table|string key one of 'CHOWN_RESTRICTED', 'LINK_MAX', -- 'MAX_CANON', 'MAX_INPUT', 'NAME_MAX', 'NO_TRUNC', 'PATH_MAX', 'PIPE_BUF' -- or 'VDISABLE' -- @string[opt] ... unless *type* was a table, zero or more additional -- type strings -- @return ... values, or a table of all fields if no option given -- @see sysconf(2) -- @usage for a,b in pairs(posix.pathconf '/dev/tty') do print(a, b) end pathconf = Ppathconf, --- Set resource limits for this process. -- @function setrlimit -- @string resource one of 'core', 'cpu', 'data', 'fsize', 'nofile', -- 'stack' or 'as' -- @int[opt] softlimit process may receive a signal when reached -- @int[opt] hardlimit process may be terminated when reached -- @treturn[1] int `0`, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum setrlimit = argscheck('setrlimit(string, [?int], [?int])', function(rcstr, cur, max) local rc = RLIMIT_MAP[lower(rcstr)] if rc == nil then argerror('setrlimit', 1, "invalid option '" .. rcstr .. "'") end local lim if cur == nil or max == nil then lim = getrlimit(rc) end return setrlimit(rc, { rlim_cur = cur or lim.rlim_cur, rlim_max = max or lim.rlim_max, }) end), --- Information about an existing file path. -- If the file is a symbolic link, return information about the link -- itself. -- @function stat -- @string path file to act on -- @tparam[opt] table|string field one of 'dev', 'ino', 'mode', 'nlink', -- 'uid', 'gid', 'rdev', 'size', 'atime', 'mtime', 'ctime' or 'type' -- @string[opt] ... unless *field* was a table, zero or more additional -- field names -- @return values, or table of all fields if no option given -- @see stat(2) -- @usage for a,b in pairs(P,stat '/etc/') do print(a, b) end stat = Pstat, --- Fetch file system statistics. -- @function statvfs -- @string path any path within the mounted file system -- @tparam[opt] table|string field one of 'bsize', 'frsize', 'blocks', -- 'bfree', 'bavail', 'files', 'ffree', 'favail', 'fsid', 'flag', -- 'namemax' -- @string[opt] ... unless *field* was a table, zero or more additional -- field names -- @return values, or table of all fields if no option given -- @see statvfs(2) -- @usage for a,b in pairs(P,statvfs '/') do print(a, b) end statvfs = Pstatvfs, --- Write a time out according to a format. -- @function strftime -- @string format specifier with `%` place-holders -- @tparam[opt] PosixTm tm broken-down local time -- @treturn string *format* with place-holders plugged with *tm* values -- @see strftime(3) strftime = argscheck('strftime(string, [?table])', function(fmt, legacytm) local posixtm = legacytm and PosixTm(legacytm) or localtime(time()) return strftime(fmt, posixtm) end), --- Parse a date string. -- @function strptime -- @string s -- @string format same as for `strftime` -- @usage posix.strptime('20','%d').monthday == 20 -- @treturn[1] PosixTm broken-down local time -- @treturn[1] int next index of first character not parsed as part of the date, if successful -- @return[2] nil -- @see strptime(3) strptime = argscheck('strptime(string, string)', function(s, fmt) local tm, i = strptime(s, fmt) return LegacyTm(tm), i end), --- Get configuration information at runtime. -- @function sysconf -- @tparam[opt] table|string key one of 'ARG_MAX', 'CHILD_MAX', -- 'CLK_TCK', 'JOB_CONTROL', 'NGROUPS_MAX', 'OPEN_MAX', 'SAVED_IDS', -- 'STREAM_MAX', 'TZNAME_MAX' or 'VERSION' -- @string[opt] ... unless *type* was a table, zero or more additional -- type strings -- @return ... values, or a table of all fields if no option given -- @see sysconf(2) -- @usage for a,b in pairs(posix.sysconf()) do print(a, b) end -- @usage print(posix.sysconf('STREAM_MAX', 'ARG_MAX')) sysconf = Psysconf, --- Get the current process times. -- @function times -- @tparam[opt] table|string key one of 'utime', 'stime', 'cutime', -- 'cstime' or 'elapsed' -- @string[opt] ... unless *key* was a table, zero or more additional -- key strings. -- @return values, or a table of all fields if no keys given -- @see times(2) -- @usage for a,b in pairs(posix.times()) do print(a, b) end -- @usage print(posix.times('utime', 'elapsed') times = Ptimes, --- Return information about this machine. -- @function uname -- @see uname(2) -- @string[opt='%s %n %r %v %m'] format contains zero or more of: -- -- * %m machine name -- * %n node name -- * %r release -- * %s sys name -- * %v version -- -- @treturn[1] string filled *format* string, if successful -- @return[2] nil -- @treturn[2] string error message uname = argscheck('uname([?string])', function(spec) local u = uname() return gsub(optstring('uname', 1, spec, '%s %n %r %v %m'), '%%(.)', function(s) if s == '%' then return '%' elseif s == 'm' then return u.machine elseif s == 'n' then return u.nodename elseif s == 'r' then return u.release elseif s == 's' then return u.sysname elseif s == 'v' then return u.version else badoption('uname', 1, 'format', s) end end) end), } --- Group information. -- @table group -- @string name name of group -- @int gid unique group id -- @string ... list of group members luaposix-36.3/lib/posix/init.lua000066400000000000000000000362141475444374100167120ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2013-2025 Gary V. Vaughan Copyright (C) 2010-2013 Reuben Thomas Copyright (C) 2008-2010 Natanael Copa ]] --[[-- Lua POSIX bindings. In addition to the convenience functions documented in this module, many APIs from submodules are copied into the return table for backwards compatibility and, if necessary, wrapped to match the deprecated API. This means that your old code will continue to work, but that you can use the improved documented APIs in new code. @module posix ]] local _ENV = require 'posix._strict' { GLOB_MARK = require 'posix.glob'.GLOB_MARK, O_NOCTTY = require 'posix.fcntl'.O_NOCTTY, O_RDWR = require 'posix.fcntl'.O_RDWR, STDIN_FILENO = require 'posix.unistd'.STDIN_FILENO, STDOUT_FILENO = require 'posix.unistd'.STDOUT_FILENO, _exit = require 'posix.unistd'._exit, access = require 'posix.unistd'.access, argscheck = require 'posix._base'.argscheck, assert = assert, bor = require 'posix._base'.bor, close = require 'posix.unistd'.close, dup2 = require 'posix.unistd'.dup2, errno = require 'posix.errno'.errno, error = error, execp = require 'posix.unistd'.execp, exit = os.exit, fork = require 'posix.unistd'.fork, getegid = require 'posix.unistd'.getegid, geteuid = require 'posix.unistd'.geteuid, getgid = require 'posix.unistd'.getgid, getuid= require 'posix.unistd'.getuid, glob = require 'posix.glob'.glob, grantpt = require 'posix.stdlib'.grantpt, gsub = string.gsub, insert = table.insert, match = string.match, next = next, open = require 'posix.fcntl'.open, openpt = require 'posix.stdlib'.openpt, pcall = pcall, pipe = require 'posix.unistd'.pipe, ptsname = require 'posix.stdlib'.ptsname, rawget = rawget, rawset = rawset, remove = table.remove, require = require, set_errno = require 'posix.errno'.set_errno, setmetatable = setmetatable, stat = require 'posix.sys.stat'.stat, sub = string.sub, tonumber = tonumber, type = type, unlockpt = require 'posix.stdlib'.unlockpt, wait = require 'posix.sys.wait'.wait, } -- FIXME: specl-14.x breaks function environments here :( local GLOB_MARK, STDIN_FILENO, STDOUT_FILENO, _exit, close, errno, execp, exit, fork, glob, insert, pipe, remove, wait = GLOB_MARK, STDIN_FILENO, STDOUT_FILENO, _exit, close, errno, execp, exit, fork, glob, insert, pipe, remove, wait local function Peuidaccess(file, mode) local euid, egid = geteuid(), getegid() if getuid() == euid and getgid() == egid then -- If we are not set-uid or set-gid, access does the same. return access(file, mode) end local stats = stat(file) if not stats then return end -- The super-user can read and write any file, and execute any file -- that anyone can execute. if euid == 0 and ((not match(mode, 'x')) or match(stats.st_mode, 'x')) then return 0 end -- Convert to simple list of modes. mode = gsub(mode, '[^rwx]', '') if mode == '' then return 0 -- The file exists. end -- Get the modes we need. local granted = sub(stats.st_mode, 1, 3) if euid == stats.st_uid then granted = sub(stats.st_mode, 7, 9) elseif egid == stats.st_gid or set.new(posix.getgroups()):member(stats.st_gid) then granted = sub(stats.st_mode, 4, 6) end granted = gsub(granted, '[^rwx]', '') if gsub('[^' .. granted .. ']', mode) == '' then return 0 end set_errno(EACCESS) end local function Pexecx(task, ...) if type(task) == 'table' then local path = remove(task, 1) execp(path, task) -- Only get here if there's an error; kill the fork local _, n = errno() _exit(n) else -- Function call must flush open file descriptors et.al. with `os.exit()` exit(task(...) or 0) end end local function Pglob(args) -- Support previous `glob '.*'` style calls. if type(args) == 'string' then args = {pattern=args} elseif type(args) ~= 'table' then args = {} end local flags = 0 if args.MARK then flags = GLOB_MARK end return glob(args.pattern, flags) end local function Popenpty(term, win) local ok, slave, slave_name local master, errmsg, errnum = openpt(bor(O_RDWR, O_NOCTTY)) if master then ok, errmsg, errnum = grantpt(master) if ok then ok, errmsg, errnum = unlockpt(master) if ok then slave_name, errmsg, errnum = ptsname(master) if slave_name then slave, errmsg, errnum = open(slave_name, bor(O_RDWR, O_NOCTTY)) if slave then return master, slave, slave_name end end end end close(master) end return nil, errmsg, errnum end local function Ppclose(pfd) close(pfd.fd) for i = 1, #pfd.pids - 1 do wait(pfd.pids[i]) end local _, reason, status = wait(pfd.pids[#pfd.pids]) return reason, status end local function move_fd(from_fd, to_fd) if from_fd ~= to_fd then if not dup2(from_fd, to_fd) then error 'error dup2-ing' end close(from_fd) end end local function Ppopen(task, mode, pipe_fn) local read_fd, write_fd = (pipe_fn or pipe)() if not read_fd then error 'error opening pipe' end local parent_fd, child_fd, in_fd, out_fd if mode == 'r' then parent_fd, child_fd, in_fd, out_fd = read_fd, write_fd, STDIN_FILENO, STDOUT_FILENO elseif mode == 'w' then parent_fd, child_fd, in_fd, out_fd = write_fd, read_fd, STDOUT_FILENO, STDIN_FILENO else error 'invalid mode' end local pid = fork() if pid == nil then error 'error forking' elseif pid == 0 then -- child process move_fd(child_fd, out_fd) close(parent_fd) Pexecx(task, child_fd, in_fd, out_fd) end -- parent process close(child_fd) return {pids={pid}, fd=parent_fd} end local function Ppopen_pipeline(tasks, mode, pipe_fn) local first, from, to, inc = 1, 2, #tasks, 1 if mode == 'w' then first, from, to, inc = #tasks, #tasks - 1, 1, -1 end local pfd = Ppopen(tasks[first], mode, pipe_fn) for i = from, to, inc do local pfd_next = Ppopen(function(fd, in_fd, out_fd) move_fd(pfd.fd, in_fd) Pexecx(tasks[i]) end, mode, pipe_fn) close(pfd.fd) pfd.fd = pfd_next.fd insert(pfd.pids, pfd_next.pids[1]) end return pfd end local function Pspawn(task, ...) local pid, errmsg, errnum = fork() if pid == nil then -- fork failed return errnum, errmsg elseif pid == 0 then -- child process Pexecx(task, ...) end -- parent process: local _, reason, status = wait(pid) return status, reason -- If wait failed, status is errnum & reason is errmsg end local function Ptimeradd(x, y) local sec, usec = 0, 0 if x.tv_sec or x.tv_usec then sec = sec + (tonumber(x.tv_sec) or 0) usec = usec + (tonumber(x.tv_usec) or 0) else sec = sec + (tonumber(x.sec) or 0) usec = usec + (tonumber(x.usec) or 0) end if y.tv_sec or y.tv_usec then sec = sec + (tonumber(y.tv_sec) or 0) usec = usec + (tonumber(y.tv_usec) or 0) else sec = sec + (tonumber(y.sec) or 0) usec = usec + (tonumber(y.usec) or 0) end while usec > 1000000 do sec = sec + 1 usec = usec - 1000000 end return {sec=sec, usec=usec} end local function Ptimercmp(x, y) local x = {sec=x.tv_sec or x.sec or 0, usec=x.tv_usec or x.usec or 0} local y = {sec=y.tv_sec or y.sec or 0, usec=y.tv_usec or y.usec or 0} if x.sec ~= y.sec then return x.sec - y.sec else return x.usec - y.usec end end local function Ptimersub(x,y) local sec, usec = 0, 0 if x.tv_sec or x.tv_usec then sec = (tonumber(x.tv_sec) or 0) usec = (tonumber(x.tv_usec) or 0) else sec = (tonumber(x.sec) or 0) usec = (tonumber(x.usec) or 0) end if y.tv_sec or y.tv_usec then sec = sec - (tonumber(y.tv_sec) or 0) usec = usec - (tonumber(y.tv_usec) or 0) else sec = sec - (tonumber(y.sec) or 0) usec = usec - (tonumber(y.usec) or 0) end while usec < 0 do sec = sec - 1 usec = usec + 1000000 end return { sec = sec, usec = usec } end -- For backwards compatibility, copy all table entries into M namespace. local M = { --- Close a pipeline opened with popen or popen_pipeline. -- @function pclose -- @tparam table pfd pipeline object -- @return values as for @{posix.sys.wait.wait}, for the last (or only) -- stage of the pipeline pclose = argscheck('pclose(table)', Ppclose), --- Check permissions like @{posix.unistd.access}, but for euid. -- Based on the glibc function of the same name. Does not always check -- for read-only file system, text busy, etc., and does not work with -- ACLs &c. -- @function euidaccess -- @string file file to check -- @string mode checks to perform (as for access) -- @treturn[1] int `0`, if access allowed -- @return[2] nil (and errno is set) euidaccess = argscheck('euidaccess(string, string)', Peuidaccess), --- Exec a command or Lua function. -- @function execx -- @tparam table|function task argument list for @{posix.unistd.execp} -- or a Lua function, which should read from standard input, write to -- standard output, and return an exit code -- @param ... positional arguments to the function -- @treturn nil on error (normally does not return) -- @treturn string error message execx = argscheck('execx(function|table, [any...])', Pexecx), --- Find all files in this directory matching a shell pattern. -- The flag MARK appends a trailing slash to matches that are directories. -- @function glob -- @tparam table|string|nil args the three possible parameters can be used to -- override the default values for `pattern` and `MARK`, which are `"*"` and -- `false` respectively. A table will be checked for optional keys `pattern` -- and `MARK`. A string will be used as the glob pattern. -- @treturn[1] table matching files and directories, if successful -- @return[2] nil -- @treturn[2] one of `GLOB_BORTED`, `GLOB_NOMATCH` or `GLOB_NOSPACE` -- @see posix.glob.glob glob = argscheck('glob([?string|table])', Pglob), --- Open a pseudo-terminal. -- Based on the glibc function of the same name. -- @function openpty -- @fixme add support for term and win arguments -- @treturn[1] int master file descriptor -- @treturn[1] int slave file descriptor -- @treturn[1] string slave file name, if successful -- @return[2] nil -- @treturn[2] string error message -- @treturn[2] int errnum openpty = argscheck('openpty()', Popenpty), --- Run a command or Lua function in a sub-process. -- @function popen -- @tparam table task argument list for @{posix.unistd.execp} or a Lua -- function, which should read from standard input, write to standard -- output, and return an exit code -- @tparam string mode `"r"` for read or `"w"` for write -- @func[opt] pipe_fn function returning a paired read and -- write file descriptor (*default* @{posix.unistd.pipe}) -- @treturn pfd pipeline object -- @see posix.execx -- @see posix.spawn popen = argscheck('popen(function|table, string, [?function])', Ppopen), --- Perform a series of commands and Lua functions as a pipeline. -- @function popen_pipeline -- @tparam table t tasks for @{posix.execx} -- @tparam string mode `"r"` for read or `"w"` for write -- @func[opt] pipe_fn function returning a paired read and -- write file descriptor (*default* @{posix.unistd.pipe}) -- @treturn pfd pipeline object popen_pipeline = argscheck('popen_pipeline(function|table, string, [?function])', Ppopen_pipeline), --- Run a command or function in a sub-process using @{posix.execx}. -- @function spawn -- @tparam table task argument list for @{posix.unistd.execp} or a Lua -- function, which should read from standard input, write to standard -- output, and return an exit code -- @param ... as for @{posix.execx} -- @treturn[1] int exit status, or signal number responsible for "killed" or "stopped" -- @treturn[1] string "exited", "killed" or "stopped" -- @treturn[2] int errnum -- @treturn[2] string error message spawn = argscheck('spawn(function|table, [?any...])', Pspawn), --- Add one gettimeofday() returned timeval to another. -- @function timeradd -- @param x a timeval -- @param y another timeval -- @return x + y, adjusted for usec overflow timeradd = argscheck('timeradd(table, table)', Ptimeradd), --- Compare one gettimeofday() returned timeval with another -- @function timercmp -- @param x a timeval -- @param y another timeval -- @return 0 if x and y are equal, >0 if x is newer, <0 if y is newer timercmp = argscheck('timercmp(table, table)', Ptimercmp), --- Subtract one gettimeofday() returned timeval from another. -- @function timersub -- @param x a timeval -- @param y another tiimeval -- @return x - y, adjusted for usec underflow timersub = argscheck('timersub(table, table)', Ptimersub), } do local names = { 'ctype', 'dirent', 'errno', 'fcntl', 'fnmatch', 'glob', 'grp', 'libgen', 'poll', 'pwd', 'sched', 'signal', 'stdio', 'stdlib', 'sys.msg', 'sys.resource', 'sys.socket', 'sys.stat', 'sys.statvfs', 'sys.time', 'sys.times', 'sys.utsname', 'sys.wait', 'syslog', 'termio', 'time', 'unistd', 'utime' } for i = 1, #names do local name = names[i] local t = require('posix.' .. name) for k, v in next, t do if k ~= 'version' and k ~= 'glob' then assert(M[k] == nil, 'posix namespace clash: ' .. name .. '.' .. k) rawset(M, k, v) end end end -- Inject deprecated APIs (overwriting submodules) for backwards compatibility. for k, v in next, (require 'posix.deprecated') do rawset(M, k, v) end for k, v in next, (require 'posix.compat') do rawset(M, k, v) end --- Metamethods -- @section metamethods --- Preloading of luaposix modules. -- Submodule tables are also preloaded into this top-level module, where -- they can be accessed without requiring them separately. -- @function __index -- @string name submodule name -- @treturn table|nil the submodule that was preloaded to satisfy `name`, -- otherwise `nil` if no such submodule is available. -- @usage -- local version = require 'posix'.version local systable = {} for i = 1, #names do local name = names[i] local t = require('posix.' .. name) -- careful assignment to not change the function name in error messages local fn = {[name] = rawget(M, name)} if fn[name] then -- replace with a functable with a __call metamethod for existing function! setmetatable(t, { __call = function(_, ...) return fn[name](...) end, }) end local sysname = match(name, '^sys%.(.*)$') if sysname then rawset(systable, sysname, t) else rawset(M, name, t) end end rawset(M, 'sys', systable) rawset(M, 'version', require('posix.version')) end return M luaposix-36.3/lib/posix/sys.lua000066400000000000000000000005411475444374100165570ustar00rootroot00000000000000local posix = require 'posix' local M = {} -- For backwards compatibility with release 32, copy previous -- entries into `posix.sys` namespace. local fns = { 'euidaccess', 'pipeline', 'pipeline_iterator', 'pipeline_slurp', 'spawn', 'timeradd', 'timercmp', 'timersub' } for i = 1, #fns do local fn = fns[i] M[fn] = posix[fn] end return M luaposix-36.3/lib/posix/util.lua000066400000000000000000000002621475444374100167160ustar00rootroot00000000000000--[[ POSIX library for Lua 5.1, 5.2, 5.3 & 5.4. Copyright (C) 2014-2025 Gary V. Vaughan ]] -- Backwards compatibility alias. return { openpty = require 'posix'.openpty, } luaposix-36.3/lib/posix/version.lua.in000066400000000000000000000000741475444374100200340ustar00rootroot00000000000000return 'posix for ' .. _VERSION .. ' / @package@ @version@' luaposix-36.3/luaposix-36.3-1.rockspec000066400000000000000000000030561475444374100174560ustar00rootroot00000000000000local _MODREV, _SPECREV = '36.3', '-1' package = 'luaposix' version = _MODREV .. _SPECREV description = { summary = 'Lua bindings for POSIX', detailed = [[ A library binding various POSIX APIs. POSIX is the IEEE Portable Operating System Interface standard. luaposix is based on lposix. ]], homepage = 'http://github.com/luaposix/luaposix/', license = 'MIT/X11', } dependencies = { 'lua >= 5.1, < 5.5', } do -- We only want to install a bit32 module for Lua 5.1. local _ENV={package=nil, dependencies=dependencies} if package then dependencies[#dependencies + 1] = 'bit32' end end source = { url = 'http://github.com/luaposix/luaposix/archive/v' .. _MODREV .. '.zip', dir = 'luaposix-' .. _MODREV, } build = { type = 'command', build_command = '$(LUA) build-aux/luke' .. ' package="' .. package .. '"' .. ' version="' .. _MODREV .. '"' .. ' PREFIX="$(PREFIX)"' .. ' LUA="$(LUA)"' .. ' LUA_INCDIR="$(LUA_INCDIR)"' .. ' CC="$(CC)"' .. ' LD="$(LD)"' .. ' CFLAGS="$(CFLAGS)"' .. ' LIBFLAG="$(LIBFLAG)"' .. ' LIB_EXTENSION="$(LIB_EXTENSION)"' .. ' OBJ_EXTENSION="$(OBJ_EXTENSION)"' .. ' INST_LIBDIR="$(LIBDIR)"' .. ' INST_LUADIR="$(LUADIR)"' , install_command = '$(LUA) build-aux/luke install --quiet' .. ' INST_LIBDIR="$(LIBDIR)"' .. ' INST_LUADIR="$(LUADIR)"' , } if _MODREV == 'git' then dependencies[#dependencies + 1] = 'ldoc' source = { url = 'git://github.com/luaposix/luaposix.git', } end luaposix-36.3/lukefile000066400000000000000000000122451475444374100150550ustar00rootroot00000000000000package = 'luaposix' version = '$USER' defines = { PACKAGE = '"$package"', VERSION = '"$version"', NDEBUG = 1, _FORTIFY_SOURCE = 2, platforms = { aix = {_ALL_SOURCE = 1}, bsd = {_BSD_SOURCE = 1}, freebsd = {__BSD_VISIBLE = 1}, -- Some Linux distros only reveal tm.tm_gmtoff and tm.tm_zone with -- _BSD_SOURCE defined. linux = { _BSD_SOURCE = 1, _DEFAULT_SOURCE = 1, }, macosx = {_DARWIN_C_SOURCE = 1}, -- QNX is only POSIX 2001, but _XOPEN_SOURCE turns off other functions -- luaposix can bind. qnx = {_POSIX_C_SOURCE = '200112L'}, unix = { _POSIX_C_SOURCE = '200809L', _XOPEN_SOURCE = 700, }, -- Otherwise, enable POSIX 2008. Please send the output of `uname -s` if -- your host is not compliant. _POSIX_C_SOURCE = '200809L', }, } incdirs = { 'ext/include', '$LUA_INCDIR', } ldocs = 'build-aux/config.ld.in' modules = { ['posix'] = 'lib/posix/init.lua', ['posix._base'] = 'lib/posix/_base.lua', ['posix._bitwise'] = 'lib/posix/_bitwise.lua', ['posix._strict'] = 'lib/posix/_strict.lua', ['posix.compat'] = 'lib/posix/compat.lua', ['posix.deprecated'] = 'lib/posix/deprecated.lua', ['posix.sys'] = 'lib/posix/sys.lua', ['posix.util'] = 'lib/posix/util.lua', ['posix.ctype'] = 'ext/posix/ctype.c', ['posix.dirent'] = 'ext/posix/dirent.c', ['posix.errno'] = 'ext/posix/errno.c', ['posix.fcntl'] = { defines = { HAVE_POSIX_FADVISE = {checkfunc='posix_fadvise'}, }, sources = 'ext/posix/fcntl.c', }, ['posix.fnmatch'] = 'ext/posix/fnmatch.c', ['posix.glob'] = 'ext/posix/glob.c', ['posix.grp'] = 'ext/posix/grp.c', ['posix.libgen'] = 'ext/posix/libgen.c', ['posix.poll'] = 'ext/posix/poll.c', ['posix.pwd'] = 'ext/posix/pwd.c', ['posix.sched'] = { defines = { HAVE_SCHED_H = {checkheader='sched.h'}, HAVE_SCHED_GETSCHEDULER = {checkfunc='sched_getscheduler'}, HAVE_SCHED_SETSCHEDULER = {checkfunc='sched_setscheduler'}, }, sources = 'ext/posix/sched.c', }, ['posix.signal'] = 'ext/posix/signal.c', ['posix.stdio'] = 'ext/posix/stdio.c', ['posix.stdlib'] = 'ext/posix/stdlib.c', ['posix.sys.msg'] = { defines = { HAVE_SYS_MSG_H = {checkheader='sys/msg.h'}, HAVE_MSGRCV = {checkfunc='msgrcv'}, HAVE_MSGSND = {checkfunc='msgsnd'}, }, sources = 'ext/posix/sys/msg.c', }, ['posix.sys.resource'] = 'ext/posix/sys/resource.c', ['posix.sys.socket'] = { defines = { HAVE_NET_IF_H = {checkheader='net/if.h', include='sys/socket.h'}, HAVE_LINUX_NETLINK_H = {checkheader='linux/netlink.h', include='sys/socket.h'}, HAVE_LINUX_IF_PACKET_H = {checkheader='linux/if_packet.h', include='sys/socket.h'}, }, libraries = { {checksymbol='socket', library='socket'}, }, sources = 'ext/posix/sys/socket.c', }, ['posix.sys.stat'] = 'ext/posix/sys/stat.c', ['posix.sys.statvfs'] = { defines = { HAVE_STATVFS = {checkfunc='statvfs'}, }, sources = 'ext/posix/sys/statvfs.c', }, ['posix.sys.time'] = 'ext/posix/sys/time.c', ['posix.sys.times'] = 'ext/posix/sys/times.c', ['posix.sys.utsname'] = 'ext/posix/sys/utsname.c', ['posix.sys.wait'] = 'ext/posix/sys/wait.c', ['posix.syslog'] = 'ext/posix/syslog.c', ['posix.termio'] = { defines = { HAVE_TERMIOS_H = {checkheader='termios.h'}, HAVE_WS_XPIXEL = {checkmember='struct winsize.ws_xpixel', include='termios.h'}, HAVE_WS_YPIXEL = {checkmember='struct winsize.ws_ypixel', include='termios.h'}, }, sources = 'ext/posix/termio.c', }, ['posix.time'] = { defines = { HAVE_TM_GMTOFF = {checkmember='struct tm.tm_gmtoff', include='time.h'}, HAVE_TM_ZONE = {checkmember='struct tm.tm_zone', include='time.h'}, }, libraries = { { ifdef = '_POSIX_TIMERS', include = 'unistd.h', checksymbol = 'clock_gettime', library = 'rt', }, }, sources = 'ext/posix/time.c', }, ['posix.unistd'] = { defines = { HAVE_CRYPT = {checkfunc='crypt'}, HAVE_CRYPT_H = {checkheader='crypt.h'}, HAVE_DECL_FDATASYNC = {checkdecl='fdatasync', include='unistd.h'}, HAVE_FDATASYNC = {checkfunc='fdatasync'}, HAVE_GETHOSTID = {checkfunc='gethostid'}, }, libraries = { {checksymbol='crypt', library='crypt'}, }, sources = 'ext/posix/unistd.c', }, ['posix.utime'] = 'ext/posix/utime.c', ['posix.version'] = 'lib/posix/version.lua.in', } luaposix-36.3/spec/000077500000000000000000000000001475444374100142605ustar00rootroot00000000000000luaposix-36.3/spec/lposix_spec.yaml000066400000000000000000000026231475444374100174770ustar00rootroot00000000000000before: this_module = 'posix' global_table = '_G' M = require(this_module) specify lposix: - before: fcntl, fileno = M.fcntl, M.fileno O_NONBLOCK = M.O_NONBLOCK - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - context with fcntl F_GETFL: - before: F_GETFL, F_SETFL = M.F_GETFL, M.F_SETFL fdin = fileno (io.stdin) flags = fcntl (fdin, F_GETFL) restore = flags - after: fcntl (fdin, F_SETFL, restore) - it returns flags as a non-negative number: expect (type (flags)).should_be "number" expect (flags >= 0).should_be (true) - it resets O_NONBLOCK bit, if any: fcntl (fdin, F_SETFL, band (flags, bnot (O_NONBLOCK))) flags = fcntl (fdin, F_GETFL) expect (band (flags, O_NONBLOCK)).should_be (0) - it sets O_NONBLOCK bit: fcntl (fdin, F_SETFL, bor (flags, O_NONBLOCK)) flags = fcntl (fdin, F_GETFL) expect (band (flags, O_NONBLOCK)).should_not_be (0) - it returns nil for negative fd argument: ret, msg, errno = fcntl (-7, F_GETFL) expect (ret).should_be (nil) - it returns nil for unopened fd argument: ret, msg, errno = fcntl (666, F_GETFL) expect (ret).should_be (nil) - it diagnoses incorrect userdata argument: expect (fcntl ("foobar", F_GETFL)).should_error "integer expected" luaposix-36.3/spec/posix_compat_spec.yaml000066400000000000000000000142661475444374100206740ustar00rootroot00000000000000before: this_module = 'posix' global_table = '_G' M = require(this_module) specify posix.compat: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe chmod: - before: chmod, stat = M.chmod, M.stat touch "xxx" chmod("xxx", "rwxr-x---") - after: os.remove "xxx" - context with bad arguments: | examples { ["it diagnoses argument #2 invalid mode"] = function() expect(chmod(".", "g+vv")).to_raise.any_of { "bad argument #2 to '?' (bad mode)", "bad argument #2 to 'chmod' (bad mode)", } end } badargs.diagnose(chmod, "chmod(string, string)") - it sets file mode with longhand mode string: mode = "rw---xr--" expect(Emsg(chmod("xxx", mode))).to_be "" expect(stat("xxx", "mode")).to_be(mode) - "it sets attributes with '='": expect(Emsg(chmod("xxx", "o=w"))).to_be "" expect(stat("xxx", "mode")).to_be "rwxr-x-w-" - "it adds attributes with '+'": expect(Emsg(chmod("xxx", "g+w"))).to_be "" expect(stat("xxx", "mode")).to_be "rwxrwx---" - "it removes attributes with '-'": expect(Emsg(chmod("xxx", "u-r"))).to_be "" expect(stat("xxx", "mode")).to_be "-wxr-x---" - it accepts comma separated attribute specifications: expect(Emsg(chmod("xxx", "a+x,g+w,u-w"))).to_be "" expect(stat("xxx", "mode")).to_be "r-xrwx--x" - it diagnoses missing files: os.remove "xxx" expect(Emsg(chmod("xxx", "a=rwx"))).to_contain "No such file or directory" - describe creat: - before: creat = M.creat - context with bad arguments: | badargs.diagnose(creat, "creat(string, string)") examples { ["it diagnoses argument #2 invalid mode"] = function() expect(creat("not/existing", "g+vv")).to_raise.any_of { "bad argument #2 to '?' (bad mode)", "bad argument #2 to 'creat' (bad mode)", } end } - describe mkdir: - before: dir = M.mkdtemp(template) chdir, mkdir = M.chdir, M.mkdir cwd = M.getcwd() - after: chdir(cwd) rmtmp(dir) - context with bad arguments: badargs.diagnose(mkdir, "mkdir(string)") - it creates the named directory: expect(Emsg(mkdir(dir .. "/subdir"))).not_to_contain "exists" expect(Emsg(chdir(dir .. "/subdir"))).not_to_contain "No such flle or directory" - it diagnoses already existing directory: expect(Emsg(mkdir(dir))).to_contain "exists" - describe mkfifo: - before: dir = M.mkdtemp(template) mkfifo = M.mkfifo - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(mkfifo, "mkfifo(string)") - it creates the named fifo: expect(Emsg(mkfifo(dir .. "/fifo"))).not_to_contain "exists" expect(M.stat(dir .. "/fifo").type).to_be "fifo" - it diagnoses already existing fifo: expect(Emsg(mkfifo(dir))).to_contain "exists" - describe msgget: - before: msgget = M.msgget EEXIST, IPC_CREAT, IPC_EXCL = M.EEXIST, M.IPC_CREAT, M.IPC_EXCL - context with bad arguments: badargs.diagnose(msgget, "msgget(int, ?int, ?string)") - it creates a queue: if msgget then modestr = "rw-rw-rw-" mq, err, errnum = msgget(100, bor(IPC_CREAT, IPC_EXCL), modestr) if errnum == EEXIST then mq, err = msgget(100, 0, modestr) end expect(mq).not_to_be(nil) expect(err).to_be(nil) end - describe open: # M.open ignores the mode argument if flags does not include # O_CREAT, which `badargs.diagnose` can't express; ergo manual # checks here... - before: O_CREAT = M.O_CREAT open, typeerrors = init(posix, "open") - 'it diagnoses missing argument #1': expect(open()).to_raise.any_of(typeerrors(1, "string")) - 'it diagnoses argument #1 type not string': expect(open(false)).to_raise.any_of(typeerrors(1, "string", "boolean")) - 'it diagnoses missing argument #2': expect(open("not/existing")).to_raise.any_of(typeerrors(2, "int")) - 'it diagnoses argument #2 type not int': expect(open("not/existing", false)). to_raise.any_of(typeerrors(2, "int", "boolean")) - 'it diagnoses missing argument #3': expect(open("not/existing", O_CREAT)). to_raise.any_of(typeerrors(3, "string")) - 'it diagnoses argument #3 type not string': expect(open("not/existing", O_CREAT, false)). to_raise.any_of(typeerrors(3, "string", "boolean")) - 'it diagnoses argument #3 invalid mode': | expect(open("not/existing", O_CREAT, "g+vv")).to_raise.any_of { "bad argument #3 to '?' (bad mode)", "bad argument #3 to 'open' (bad mode)", } - 'it diagnoses too many arguments': expect(open("not/existing", -1, "o-s", false)).to_raise.any_of(typeerrors(4)) - describe setlogmask: - context with bad arguments: if M.setlogmask then badargs.diagnose(M.setlogmask, "setlogmask(?int*)") end - describe umask: - before: stat, umask = M.stat, M.umask saved = umask() umask "rwxr-x---" dir = M.mkdtemp(template) - after: rmtmp(dir) umask(saved) - context with bad arguments: | examples { ["it diagnoses argument #1 invalid mode"] = function() expect(umask("g+vv")).to_raise.any_of { "bad argument #1 to '?' (bad mode)", "bad argument #1 to 'umask' (bad mode)", } end } badargs.diagnose(umask, "umask(?string)") - it returns current umask: expect(umask()).to_be "rwxr-x---" - "it sets attributes with '='": expect(umask "a=r").to_be "r--r--r--" - "it adds attributes with '+'": expect(umask "g+w").to_be "rwxrwx---" - "it removes attributes with '-'": expect(umask "u-r").to_be "-wxr-x---" - it accepts comma separated attribute specifications: expect(umask "a+r,g+w,u-x").to_be "rw-rwxr--" - it controls the mode of newly created files: xxx, mode = dir .. "/xxx", "rw--w-r--" umask(mode) touch(xxx) expect(stat(xxx, "mode")).to_be(mode) os.remove(xxx) luaposix-36.3/spec/posix_ctype_spec.yaml000066400000000000000000000016751475444374100205350ustar00rootroot00000000000000before: this_module = 'posix.ctype' global_table = '_G' M = require(this_module) specify posix.ctype: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe isgraph: - before: isgraph = M.isgraph - context with bad arguments: badargs.diagnose(isgraph, "(string)") - it returns non-zero for successful tests: expect(type(isgraph 'a')).to_be "number" expect(isgraph 'a').not_to_be(0) - it returns zero for failed tests: expect(isgraph ' ').to_be(0) - describe isprint: - before: isprint = M.isprint - context with bad arguments: badargs.diagnose(isprint, "(string)") - it returns non-zero for successful tests: expect(type(isprint 'a')).to_be "number" expect(isprint 'a').not_to_be(0) - it returns zero for failed tests: expect(isprint(string.char(0))).to_be(0) luaposix-36.3/spec/posix_deprecated_spec.yaml000066400000000000000000001206611475444374100215060ustar00rootroot00000000000000before: this_module = 'posix' global_table = '_G' M = require(this_module) specify posix.deprecated: - before: socket, getaddrinfo, close = M.socket, M.getaddrinfo, M.close AF_INET, AF_INET6, AF_UNIX, AF_NETLINK = M.AF_INET, M.AF_INET6, M.AF_UNIX, M.AF_NETLINK SOCK_STREAM = M.SOCK_STREAM EPOCH = M.time() - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe connect: - before: connect, typeerrors = init(M, "connect") - context with bad arguments: | badargs.diagnose(connect, "connect(int, table)") examples { ["it diagnoses wrong family types"] = function() expect(connect(42, {family=false})). to_raise.any_of(typeerrors(2, "integer", "family", "boolean")) expect(connect(42, {family=-1})).to_raise.any_of { "bad argument #2 to '?' (unsupported family type -1)", "bad argument #2 to 'connect' (unsupported family type -1)", } end } examples { ["it diagnoses wrong AF_INET field types"] = function() expect(connect(42, {family=AF_INET, port=false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(connect(42, {family=AF_INET, port=9999, addr=false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET fields"] = function() expect(connect(42, { family=AF_INET, port=9999, addr="127.0.0.1", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_INET6 field types"] = function() expect(connect(42, {family = AF_INET6, port = false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(connect(42, {family = AF_INET6, port = 9999, addr = false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET6 fields"] = function() expect(connect(42, { family=AF_INET6, port=9999, addr="::", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_UNIX field types"] = function() expect(connect(42, {family = AF_UNIX, path = false})). to_raise.any_of(typeerrors(2, "string", "path", "boolean")) end } examples { ["it diagnoses invalid AF_UNIX fields"] = function() expect(connect(42, {family=AF_UNIX, path="/tmp/afunix", port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } if AF_NETLINK then examples { ["it diagnoses wrong AF_NETLINK field types"] = function() expect(connect(42, {family = AF_NETLINK, pid = false})). to_raise.any_of(typeerrors(2, "integer", "pid", "boolean")) expect(connect(42, {family = AF_NETLINK, pid = 9999, groups = false})). to_raise.any_of(typeerrors(2, "integer", "groups", "boolean")) end } examples { ["it diagnoses invalid AF_NETLINK fields"] = function() expect(connect(42, {family=AF_NETLINK, pid=9999, groups=9999, port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } end - it returns true on success: fd = socket(AF_INET, SOCK_STREAM, 0) ait = getaddrinfo("www.lua.org", "http", {family = AF_INET, socktype = SOCK_STREAM}) expect(connect(fd, ait[1])).to_be(true) close(fd) - describe bind: - before: bind, typeerrors = init(M, "bind") - context with bad arguments: | badargs.diagnose(bind, "bind(int, table)") examples { ["it diagnoses wrong family types"] = function() expect(bind(42, {family=false})). to_raise.any_of(typeerrors(2, "integer", "family", "boolean")) expect(bind(42, {family=-1})).to_raise.any_of { "bad argument #2 to '?' (unsupported family type -1)", "bad argument #2 to 'bind' (unsupported family type -1)", } end } examples { ["it diagnoses wrong AF_INET field types"] = function() expect(bind(42, {family=AF_INET, port=false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(bind(42, {family=AF_INET, port=9999, addr=false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET fields"] = function() expect(bind(42, { family=AF_INET, port=9999, addr="127.0.0.1", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_INET6 field types"] = function() expect(bind(42, {family = AF_INET6, port = false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(bind(42, {family = AF_INET6, port = 9999, addr = false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET6 fields"] = function() expect(bind(42, { family=AF_INET6, port=9999, addr="::", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_UNIX field types"] = function() expect(bind(42, {family = AF_UNIX, path = false})). to_raise.any_of(typeerrors(2, "string", "path", "boolean")) end } examples { ["it diagnoses invalid AF_UNIX fields"] = function() expect(bind(42, {family=AF_UNIX, path="/tmp/afunix", port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } if AF_NETLINK then examples { ["it diagnoses wrong AF_NETLINK field types"] = function() expect(bind(42, {family = AF_NETLINK, pid = false})). to_raise.any_of(typeerrors(2, "integer", "pid", "boolean")) expect(bind(42, {family = AF_NETLINK, pid = 9999, groups = false})). to_raise.any_of(typeerrors(2, "integer", "groups", "boolean")) end } examples { ["it diagnoses invalid AF_NETLINK fields"] = function() expect(bind(42, {family=AF_NETLINK, pid=9999, groups=9999, port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } end - it returns true on success: fd = socket(AF_INET, SOCK_STREAM, 0) expect(bind(fd, {family = AF_INET, addr = "127.0.0.1", port = 13457 })).to_be(true) close(fd) - describe clock_getres: - before: clock_getres = M.clock_getres - context with bad arguments: if clock_getres then badargs.diagnose(clock_getres, "clock_getres(?string)") end - it takes deprecated string arguments: if clock_getres then local time = require 'posix.time' expect(clock_getres()). to_be(time.clock_getres(time.CLOCK_REALTIME).tv_sec) expect(clock_getres 'monotonic'). to_be(time.clock_getres(time.CLOCK_MONOTONIC).tv_sec) expect(clock_getres 'process_cputime_id'). to_be(time.clock_getres(time.CLOCK_PROCESS_CPUTIME_ID).tv_sec) expect(clock_getres 'thread_cputime_id'). to_be(time.clock_getres(time.CLOCK_THREAD_CPUTIME_ID).tv_sec) end - describe clock_gettime: - before: clock_gettime = M.clock_gettime - context with bad arguments: if clock_gettime then badargs.diagnose(clock_gettime, "clock_gettime(?string)") end - it takes deprecated string arguments: if clock_gettime then local time = require 'posix.time' expect(clock_gettime()). to_be(time.clock_gettime(time.CLOCK_REALTIME).tv_sec) expect(clock_gettime 'monotonic'). to_be(time.clock_gettime(time.CLOCK_MONOTONIC).tv_sec) expect(clock_gettime 'process_cputime_id'). to_be(time.clock_gettime(time.CLOCK_PROCESS_CPUTIME_ID).tv_sec) expect(clock_gettime 'thread_cputime_id'). to_be(time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID).tv_sec) end - describe exec: - before: exec, typeerrors = init(M, "exec") # M.exec takes a string or non-empty table as its second # argument, followed by zero or more strings only if the second # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not string': expect(exec(false)).to_raise.any_of(typeerrors(1, "string", "boolean")) - 'it diagnoses argument #2 type not table or string': expect(exec("cmd", false)). to_raise.any_of(typeerrors(2, "?string|table", "boolean")) - 'it diagnoses argument #3 type not string': expect(exec("cmd", "cmd", false)). to_raise.any_of(typeerrors(3, "string", "boolean")) - it diagnoses too many arguments: expect(exec("cmd", {}, false)).to_raise.any_of(typeerrors(3)) - describe execp: - before: # redirect output to /dev/null dup2, fork, open, wait, O_WRONLY, O_APPEND = M.dup2, M.fork, M.open, M.wait, M.O_WRONLY, M.O_APPEND P_CHILD = 0 function child(...) quietly = open("/dev/null", bor(O_WRONLY, O_APPEND)) dup2(quietly, 1) execp(...) expect("not reached").to_be(true) end execp, typeerrors = init(M, "execp") # M.execp takes a string or non-empty table as its second # argument, followed by zero or more strings only if the second # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not string': expect(execp(false)).to_raise.any_of(typeerrors(1, "string", "boolean")) - 'it diagnoses argument #2 type not table or string': expect(execp("cmd", false)). to_raise.any_of(typeerrors(2, "?string|table", "boolean")) - 'it diagnoses argument #3 type not string': expect(execp("cmd", "cmd", false)). to_raise.any_of(typeerrors(3, "string", "boolean")) - it diagnoses too many arguments: expect(execp("cmd", {}, false)).to_raise.any_of(typeerrors(3)) - it overwrites the running process with a shell invocation: process = fork() if process == P_CHILD then child("date", "+[%c]") else p, msg, ret = wait(process) expect(table.concat {msg, " ", tostring(ret)}).to_be "exited 0" end - it accepts a table of arguments: process = fork() if process == P_CHILD then child("date", {"+[%c]"}) else p, msg, ret = wait(process) expect(table.concat {msg, " ", tostring(ret)}).to_be "exited 0" end - "it sets argv[0]": - describe fadvise: - context with bad arguments: if M.fadvise then badargs.diagnose(M.fadvise, "fadvise(FILE*, int, int, int)") end - describe fnmatch: - before: fnmatch, FNM_PATHNAME, FNM_PERIOD = M.fnmatch, M.FNM_PATHNAME, M.FNM_PERIOD - context with bad arguments: badargs.diagnose(fnmatch, "fnmatch(string, string, ?int)") - it matches a file path against itself: expect(fnmatch("test", "test")).to_be(true) - "it matches * against any filename characters": expect(fnmatch("tes*", "test")).to_be(true) expect(fnmatch("tes*", "test2")).to_be(true) expect(fnmatch("*t*", "test")).to_be(true) - "it matches ? against a single filename character": expect(fnmatch("tes?", "test")).to_be(true) expect(fnmatch("t???", "test")).to_be(true) expect(fnmatch("tes?", "tes")).to_be(false) expect(fnmatch("tes?", "test2")).to_be(false) - "it doesn't match path separators with FNM_PATHNAME": expect(fnmatch("*test", "/test")).to_be(true) expect(fnmatch("*test", "/test", FNM_PATHNAME)).to_be(false) - "it doesn't match periods with FNM_PERIOD": expect(fnmatch("*test", ".test")).to_be(true) expect(fnmatch("*test", ".test", FNM_PERIOD)).to_be(false) - describe getgroup: - before: getgrgid, getgroup, getegid = M.getgrgid, M.getgroup, M.getegid groot = getgrgid(0).gr_name - context with bad arguments: badargs.diagnose(M.getgroup, "getgroup([?int|string])") - it returns a table for an existing group: expect(type(getgroup(groot))).to_be "table" - it fetches current group by default: expect(getgroup()).to_equal(getgroup(getegid())) - it fetches a group by gid: expect(getgroup(0).name).to_be(groot) expect(getgroup(0).gid).to_be(0) expect(type(getgroup(0).mem)).to_be "table" - it fetches a group by name: expect(getgroup(groot).name).to_be(groot) expect(getgroup(groot).gid).to_be(0) expect(type(getgroup(groot).mem)).to_be "table" - describe getpasswd: - before: getenv, getgid, getpasswd, getuid = M.getenv, M.getgid, M.getpasswd, M.getuid user = getpasswd((getenv "USER"), "name") root = getpasswd(0, "name") - context with bad arguments: - before: getpasswd, typeerrors = init(posix, "getpasswd") - 'it diagnoses argument #1 type not integer, nil or string': expect(getpasswd(false)). to_raise.any_of(typeerrors(1, "?int|string", "boolean")) - it fetches the user uid: expect(getpasswd(user).uid).to_be(getuid()) expect(getpasswd(root, "uid")).to_be(0) - it fetches the user name: expect(getpasswd(user).name).to_be(user) expect(getpasswd(0, "name")).to_be(root) expect(getpasswd(root, "name")).to_be(root) - it fetches the user gid: expect(getpasswd(user).gid).to_be(getgid()) expect(getpasswd(0, "gid")).to_be(0) expect(getpasswd(root, "gid")).to_be(0) - it fetches the user password: expect(getpasswd(user).passwd).to_match.any_of {"x", "%*+"} expect(getpasswd(0, "passwd")).to_match.any_of {"x", "%*+"} expect(getpasswd(root, "passwd")).to_match.any_of {"x", "%*+"} - it fetches the user home directory: expect(getpasswd(user, "dir")).to_be(getenv "HOME") - it fetches a subtable of named fields: expect({getpasswd(user, "name", "dir")}). to_equal {user, getenv "HOME"} - it fetches everything without an argument: t = getpasswd(user) for k, v in pairs(t) do expect(t[k]).to_be(getpasswd(user, k)) end - describe getpid: - before: unistd = M.unistd getpid, typeerrors = init(M, "getpid") # M.getpid takes an optional string or table as its first # argument, followed by zero or more strings only if the first # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not nil, string or table': expect(getpid(false)).to_raise. any_of(typeerrors(1, "?string|table", "boolean")) - 'it diagnoses argument #1 string invalid': | expect(getpid("fubar")).to_raise.any_of { "bad argument #1 to '?' (invalid option 'fubar')", "bad argument #1 to 'getpid' (invalid option 'fubar')", } - 'it diagnoses argument #2 type not string': expect(getpid("ppid", false)). to_raise.any_of(typeerrors(2, "string", "boolean")) - it diagnoses too many arguments: expect(getpid({}, false)).to_raise.any_of(typeerrors(2)) - it fetches the effective group id: expect(getpid().egid).to_be(unistd.getegid()) expect(getpid "egid").to_be(unistd.getegid()) - it fetches the effective user id: expect(getpid().euid).to_be(unistd.geteuid()) expect(getpid "euid").to_be(unistd.geteuid()) - it fetches the group id: expect(getpid().gid).to_be(unistd.getgid()) expect(getpid "gid").to_be(unistd.getgid()) - it fetches the user id: expect(getpid().uid).to_be(unistd.getuid()) expect(getpid "uid").to_be(unistd.getuid()) - it fetches the process group: expect(getpid().pgrp).to_be(unistd.getpgrp()) expect(getpid "pgrp").to_be(unistd.getpgrp()) - it fetches the process id: expect(getpid().pid).to_be(unistd.getpid()) expect(getpid "pid").to_be(unistd.getpid()) - it fetches the parent process id: expect(getpid().ppid).to_be(unistd.getppid()) expect(getpid "ppid").to_be(unistd.getppid()) - it returns them all when called with no argument: expect(getpid()).to_equal { egid = unistd.getegid(), euid = unistd.geteuid(), gid = unistd.getgid(), uid = unistd.getuid(), pgrp = unistd.getpgrp(), pid = unistd.getpid(), ppid = unistd.getppid(), } - describe getrlimit: - before: getrlimit = M.getrlimit - context with bad arguments: | examples { ["it diagnoses argument #1 invalid option"] = function() expect(getrlimit("fubar")).to_raise.any_of { "bad argument #1 to '?' (invalid option 'fubar')", "bad argument #1 to 'getrlimit' (invalid option 'fubar')", } end } badargs.diagnose(getrlimit, "getrlimit(string)") - it fetches resource limits for a process: for _, rc in pairs {"core", "cpu", "data", "fsize", "nofile", "stack", "as"} do cur, max = getrlimit(rc) expect(type(cur)).to_be "number" expect(type(max)).to_be "number" end - describe gettimeofday: - before: gettimeofday = M.gettimeofday - context with bad arguments: badargs.diagnose(gettimeofday, "gettimeofday()") - it fetches the current epoch time: t = gettimeofday() expect(t.sec).to_be_within_n_of {value=EPOCH, delta=1} expect(type(t.usec)).to_be "number" expect(t.usec >= 0).to_be(true) - describe gmtime: - before: gmtime = M.gmtime - context with bad arguments: badargs.diagnose(gmtime, "gmtime(?int)") - it returns a table: expect(prototype(gmtime(EPOCH))).to_be "table" - it fetches broken-down time values: t = gmtime(EPOCH) fields = {"sec", "min", "hour", "day", "monthday", "month", "year", "weekday", "yearday", "is_dst"} if t.gmtoff ~= nil then fields[1+#fields] = "gmtoff" end if t.zone ~= nil then fields[1+#fields] = "zone" end expect(t).to_contain.a_permutation_of(fields) for _, field in pairs(fields) do if field == "zone" then expect(type(t[field])).to_be "string" elseif field == "is_dst" then expect(type(t[field])).to_be "boolean" else expect(type(t[field])).to_be "number" if field ~= "gmtoff" then expect(t[field] >= 0).to_be(true) else expect(t[field] == 0).to_be(true) end end end - it returns a month in the range 1-12: # A recent December afternoon in epoch seconds... expect(gmtime(1418734089).month).to_be(12) t = gmtime(EPOCH) expect(t.month >= 1 and t.month <= 12).to_be(true) - it returns full year: expect(gmtime(EPOCH).year > 2000).to_be(true) - describe hostid: - context with bad arguments: badargs.diagnose(M.hostid, "()") - describe isgraph: - before: isgraph = M.isgraph - context with bad arguments: badargs.diagnose(isgraph, "isgraph(string)") - it returns true for successful tests: expect(isgraph 'a').to_be(true) - it returns false for failed tests: expect(isgraph ' ').to_be(false) - describe isprint: - before: isprint = M.isprint - context with bad arguments: badargs.diagnose(isprint, "isprint(string)") - it returns true for successful tests: expect(isprint 'a').to_be(true) - it returns false for failed tests: expect(isprint(string.char(0))).to_be(false) - describe localtime: - before: localtime = M.localtime - context with bad arguments: badargs.diagnose(localtime, "localtime(?int)") - it returns a table: expect(prototype(localtime(EPOCH))).to_be "table" - it fetches broken-down time values: t = localtime(EPOCH) fields = {"sec", "min", "hour", "day", "monthday", "month", "year", "weekday", "yearday", "is_dst"} if t.gmtoff ~= nil then fields[1+#fields] = "gmtoff" end if t.zone ~= nil then fields[1+#fields] = "zone" end expect(t).to_contain.a_permutation_of(fields) for _, field in pairs(fields) do if field == "zone" then expect(type(t[field])).to_be "string" elseif field == "is_dst" then expect(type(t[field])).to_be "boolean" else expect(type(t[field])).to_be "number" if field ~= "gmtoff" then expect(t[field] >= 0).to_be(true) end end end - it returns a month in the range 1-12: # A recent December afternoon in epoch seconds... expect(localtime(1418734089).month).to_be(12) t = localtime(EPOCH) expect(t.month >= 1 and t.month <= 12).to_be(true) - it returns years since 1900: expect(localtime(EPOCH).year > 2000).to_be(true) - describe mktime: - before: localtime, mktime, time = M.localtime, M.mktime, M.time t = localtime(EPOCH) - context with bad arguments: badargs.diagnose(mktime, "mktime(?table)") - it returns an epoch time: expect(prototype(mktime(t))).to_be "number" - it is the inverse of localtime: expect(mktime(t)).to_be_within_n_of {value=EPOCH, delta=1} - it defaults to current time: expect(mktime()).to_be_within_n_of {value=EPOCH, delta=1} - describe nanosleep: - context with bad arguments: badargs.diagnose(M.nanosleep, "nanosleep(int, int)") - it returns an integer: expect(M.nanosleep(0, 10)).to_be(0) - describe openlog: - before: openlog = M.openlog - context with bad arguments: | if openlog then badargs.diagnose(openlog, "openlog(string, ?string, [?int])") examples { ["it diagnoses invalid options"] = function() expect(openlog("log", "cp*")).to_raise.any_of { "bad argument #2 to '?' (invalid openlog option '*')", "bad argument #2 to 'openlog' (invalid openlog option '*')", } end } end - describe pathconf: - before: pathconf, typeerrors = init(posix, "pathconf") # M.pathconf takes an optional string or table as its second # argument, followed by zero or more strings only if the second # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not string': expect(pathconf(false)). to_raise.any_of(typeerrors(1, "?string", "boolean")) - 'it diagnoses argument #2 type not string, table or nil': expect(pathconf(".", false)). to_raise.any_of(typeerrors(2, "?string|table", "boolean")) - 'it diagnoses argument #2 string invalid': | expect(pathconf(".", "fubar")).to_raise.any_of { "bad argument #2 to '?' (invalid option 'fubar')", "bad argument #2 to 'pathconf' (invalid option 'fubar')", } - 'it diagnoses argument #3 type not string': expect(pathconf(".", "NAME_MAX", false)). to_raise.any_of(typeerrors(3, "string", "boolean")) - it diagnoses too many arguments: expect(pathconf(".", {}, false)).to_raise.any_of(typeerrors(3)) - it returns whether chown can be used on the given file: expect(type(pathconf().CHOWN_RESTRICTED)).to_be "number" expect(pathconf(".", "CHOWN_RESTRICTED") >= 0).to_be(true) - it fetches the maximum number of links to the given file: expect(type(pathconf().LINK_MAX)).to_be "number" expect(pathconf(".", "LINK_MAX") >= 0).to_be(true) - it fetches the maximum formatted line input length for a tty: | -- not passing a tty, so should return -1 expect(type(pathconf().MAX_CANON)).to_be "number" pending "issue #102" expect(pathconf(".", "MAX_CANON")).to_be(-1) - it fetches the maximum raw line input length for a tty: | -- not passing a tty, so should return -1 expect(type(pathconf().MAX_INPUT)).to_be "number" pending "issue #102" expect(pathconf(".", "MAX_INPUT")).to_be(-1) - it fetches the maximum filename length in this directory: expect(type(pathconf().NAME_MAX)).to_be "number" expect(pathconf(".", "NAME_MAX") >= 0).to_be(true) - it fetches whether accessing overlong filenames is an error: expect(type(pathconf().NO_TRUNC)).to_be "number" expect(pathconf(".", "NO_TRUNC") >= 0).to_be(true) - it fetches the maximum relative path length from this directory: expect(type(pathconf().PATH_MAX)).to_be "number" expect(pathconf(".", "PATH_MAX") >= 0).to_be(true) - it fetches the size of the pipe buffer: expect(type(pathconf().PIPE_BUF)).to_be "number" expect(pathconf(".", "PIPE_BUF") >= 0).to_be(true) - it fetches whether special character processing can be disabled: | -- not passing a tty, so should return -1 expect(type(pathconf().VDISABLE)).to_be "number" pending "issue #102" expect(pathconf(".", "VDISABLE")).to_be(-1) - it fetches a subtable of named fields: expect({pathconf(".", "VDISABLE", "NAME_MAX")}). to_equal {pathconf(".", "VDISABLE"), pathconf(".", "NAME_MAX")} - it fetches everything without an argument: t = pathconf() for k, v in pairs(t) do expect(t[k]).to_be(pathconf(".", k)) end - describe setrlimit: - before: setrlimit = M.setrlimit - context with bad arguments: | examples { ["it diagnoses argument #1 invalid option"] = function() expect(setrlimit("fubar")).to_raise.any_of { "bad argument #1 to '?' (invalid option 'fubar')", "bad argument #1 to 'setrlimit' (invalid option 'fubar')", } end } badargs.diagnose(setrlimit, "setrlimit(string, ?int, ?int)") - describe stat: - before: fmt = "%b %d %H:%M" getegid, geteuid = M.getegid, M.geteuid stat, typeerrors = init(posix, "stat") dir = M.mkdtemp(template) M.chown(dir, geteuid(), getegid()) M.mkdir(dir .. "/subdir") M.link("subdir", dir .. "/soft", true) touch(dir .. "/file") M.link(dir .. "/file", dir .. "/hard") M.link("no such destination", dir .. "/dangling", true) M.mkfifo(dir .. "/fifo") - after: rmtmp(dir) # M.stat takes an optional string or table as its second # argument, followed by zero or more strings only if the second # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses missing argument #1': expect(stat()).to_raise.any_of(typeerrors(1, "string")) - 'it diagnoses argument #1 type not string': expect(stat(false)). to_raise.any_of(typeerrors(1, "string", "boolean")) - 'it diagnoses argument #2 type not string, table or nil': expect(stat(".", false)). to_raise.any_of(typeerrors(2, "?string|table", "boolean")) - 'it diagnoses argument #2 string invalid': | expect(stat(".", "fubar")).to_raise.any_of { "bad argument #2 to '?' (invalid option 'fubar')", "bad argument #2 to 'stat' (invalid option 'fubar')", } - 'it diagnoses argument #3 type not string': expect(stat(".", "type", false)). to_raise.any_of(typeerrors(3, "string", "boolean")) - it diagnoses too many arguments: expect(stat(".", {}, false)). to_raise.any_of(typeerrors(3)) - it fetches the file inode: expect(stat(dir .. "/hard").ino).to_be(stat(dir .. "/file").ino) - it fetches the file type: expect(stat(dir).type).to_be "directory" expect(stat(dir .. "/file", "type")).to_be "regular" expect(stat(dir .. "/soft", "type")).to_be "link" expect(stat(dir .. "/hard", "type")).to_be "regular" - it fetches the file size: # skip directory size, which is system dependent expect(stat(dir .. "/file").size).to_be(0) expect(stat(dir .. "/soft", "size")).to_be(string.len("subdir")) expect(stat(dir .. "/hard", "size")). to_be(stat(dir .. "/file", "size")) - it fetches the file access time: expect(stat(dir .. "/file", "atime")). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file modification time: expect(stat(dir .. "/file", "mtime")). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file creation time: expect(stat(dir .. "/file", "ctime")). to_be_within_n_of {value=EPOCH, delta=2} - it fetches the file access mode: expect(stat(dir .. "/file").mode).to_match("^[-rwx]+$") expect(stat(dir .. "/subdir", "mode")).to_match("^[-rwx]+$") - it fetches the number of links: expect(stat(dir .. "/file").nlink).to_be(2) expect(stat(dir .. "/soft", "nlink")).to_be(1) expect(stat(dir .. "/hard", "nlink")). to_be(stat(dir .. "/file", "nlink")) expect(stat(dir .. "/subdir", "nlink")).to_be(2) - it fetches the owner id: expect(stat(dir .. "/file").uid).to_be(geteuid()) expect(stat(dir .. "/subdir", "uid")).to_be(geteuid()) - it fetches the owner group id: expect(stat(dir .. "/file").gid).to_be(getegid()) expect(stat(dir .. "/subdir", "gid")).to_be(getegid()) - it fetches a subtable of named fields: expect({stat(dir .. "/file", "type", "size", "nlink")}). to_equal {"regular", 0, 2} - it fetches everything without an argument: t = stat(dir .. "/file") for k, v in pairs(t) do expect(t[k]).to_be(stat(dir .. "/file", k)) end - describe statvfs: - before: statvfs, typeerrors = init(posix, "statvfs") # M.statvfs takes an optional string or table as its second # argument, followed by zero or more strings only if the second # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: | if statvfs then examples { ["it diagnoses missing argument #1"] = function() expect(statvfs()).to_raise.any_of(typeerrors(1, "string")) end } examples { ["it diagnoses argument #1 type not string"] = function() expect(statvfs(false)). to_raise.any_of(typeerrors(1, "string", "boolean")) end } examples { ["it diagnoses argument #2 type not string, table or nil"] = function() expect(statvfs(".", false)). to_raise.any_of(typeerrors(2, "?string|table", "boolean")) end } examples { ["it diagnoses argument #2 string invalid"] = function() expect(statvfs(".", "fubar")).to_raise.any_of { "bad argument #2 to '?' (invalid option 'fubar')", "bad argument #2 to 'statvfs' (invalid option 'fubar')", } end } examples { ["it diagnoses argument #3 type not string"] = function() expect(statvfs(".", "files", false)). to_raise.any_of(typeerrors(3, "string", "boolean")) end } examples { ["it diagnoses too many arguments"] = function() expect(statvfs(".", {}, false)).to_raise.any_of(typeerrors(3)) end } end - it fetches statistics for a mounted file system: if statvfs then sv = statvfs "/" expect(type(sv)).to_be "table" expect(sv.bsize).to_be(statvfs("/", "bsize")) for _, field in pairs {"bsize", "frsize", "blocks", "bfree", "bavail", "files", "ffree", "favail", "flag", "namemax"} do expect(type(sv[field])).to_be "number" expect(sv[field] >= 0).to_be(true) end end - it returns a non-negative value from fsid: | -- Merge this back into the previous example when #102 is fixed if statvfs then sv = statvfs "/" pending "issue #102" expect(sv[field] >= 0).to_be(true) end - describe strftime: - before: strftime = M.strftime t = { is_dst = true, weekday = 0, sec = 2, min = 3, hour = 4, monthday = 5, month = 6, year = 7, yearday = 8, gmtoff = -32400, zone = "AKST", } - context with bad arguments: badargs.diagnose(strftime, "strftime(string, ?table)") - context with place-holders: - it plugs weekday: expect(strftime("%w", t)).to_be "0" - it plugs sec: expect(strftime("%S", t)).to_be "02" - it plugs min: expect(strftime("%M", t)).to_be "03" - it plugs hour: expect(strftime("%H", t)).to_be "04" - it plugs monthday: expect(strftime("%d", t)).to_be "05" - it plugs month: expect(strftime("%m", t)).to_be "06" - it plugs year: expect(strftime("%y", t)).to_be "07" - it plugs yearday: expect(strftime("%j", t)).to_be "009" - it plugs timezone: expect(strftime("%Z", t)).to_be "AKST" - it defaults to current time: f = io.popen("date +'%Y-%m-%d'", "r") expect(strftime "%Y-%m-%d\n"). to_be(f:read("*a")) f:close() - describe strptime: - before: strptime = M.strptime - context with bad arguments: badargs.diagnose(strptime, "strptime(string, string)") - context with place-holders: - before: t, i = strptime("Mon Jun 4 03:02:01 BST 1906 garbage", "%a %b %d %H:%M:%S BST %Y") - it returns the first unconsumed character: expect(i).to_be(29) # tm_yday and tm_isdst are not set by strptime - it scans into weekday: expect(t.weekday).to_be(1) - it scans into sec: expect(t.sec).to_be(1) - it scans into min: expect(t.min).to_be(2) - it scans into hour: expect(t.hour).to_be(3) - it scans into monthday: expect(t.monthday).to_be(4) - it scans into month: expect(t.month).to_be(6) - it scans into year: expect(t.year).to_be(1906) - describe sysconf: - before: sysconf, typeerrors = init(posix, "sysconf") positive_or_minusone = function(value) expect(type(value)).to_be "number" expect(value).not_to_be(0) expect(value >= -1).to_be(true) end # M.sysconf takes an optional string or table as its first # argument, followed by zero or more strings only if the first # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not string, table or nil': expect(sysconf(false)). to_raise.any_of(typeerrors(1, "?string|table", "boolean")) - 'it diagnoses argument #1 string invalid': | expect(sysconf("fubar")).to_raise.any_of { "bad argument #1 to '?' (invalid option 'fubar')", "bad argument #1 to 'sysconf' (invalid option 'fubar')", } - 'it diagnoses argument #2 type not string': expect(sysconf("ARG_MAX", false)). to_raise.any_of(typeerrors(2, "string", "boolean")) - it diagnoses too many arguments: expect(sysconf({}, false)).to_raise.any_of(typeerrors(2)) - it fetches the maximum number of exec arguments: positive_or_minusone(sysconf().ARG_MAX) positive_or_minusone(sysconf "ARG_MAX") - it fetches the number processes per user: positive_or_minusone(sysconf().CHILD_MAX) positive_or_minusone(sysconf "CHILD_MAX") - it fetches the number of clock ticks per second: positive_or_minusone(sysconf().CLK_TCK) positive_or_minusone(sysconf "CLK_TCK") - it fetches the job control version: positive_or_minusone(sysconf().JOB_CONTROL) positive_or_minusone(sysconf "JOB_CONTROL") - it fetches the maximum number of groups: positive_or_minusone(sysconf().NGROUPS_MAX) positive_or_minusone(sysconf "NGROUPS_MAX") - it fetches the maximum number of open descriptors: positive_or_minusone(sysconf().OPEN_MAX) positive_or_minusone(sysconf "OPEN_MAX") - it fetches the size of memory pages: positive_or_minusone(sysconf().PAGESIZE) positive_or_minusone(sysconf "PAGESIZE") - it fetches the number of saved ids: positive_or_minusone(sysconf().SAVED_IDS) positive_or_minusone(sysconf "SAVED_IDS") - it fetches the maximum number of open streams: positive_or_minusone(sysconf().STREAM_MAX) positive_or_minusone(sysconf "STREAM_MAX") - it fetches the maximum length of a timezone name: positive_or_minusone(sysconf().TZNAME_MAX) positive_or_minusone(sysconf "TZNAME_MAX") - "it fetches the POSIX.1 version": positive_or_minusone(sysconf().VERSION) positive_or_minusone(sysconf "VERSION") - it fetches a subtable of named fields: expect({sysconf("VERSION", "ARG_MAX", "OPEN_MAX")}). to_equal {sysconf "VERSION", sysconf "ARG_MAX", sysconf "OPEN_MAX"} - it fetches everything without an argument: t = sysconf() for k, v in pairs(t) do expect(t[k]).to_be(sysconf(k)) end - describe times: - before: table.unpack = table.unpack or unpack times, typeerrors = init(posix, "times") # M.times takes an optional string or table as its first # argument, followed by zero or more strings only if the first # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: - 'it diagnoses argument #1 type not string, table or nil': expect(times(false)). to_raise.any_of(typeerrors(1, "?string|table", "boolean")) - 'it diagnoses argument #1 string invalid': | expect(times("fubar")).to_raise.any_of { "bad argument #1 to '?' (invalid option 'fubar')", "bad argument #1 to 'times' (invalid option 'fubar')", } - 'it diagnoses argument #2 type not string': expect(times("utime", false)). to_raise.any_of(typeerrors(2, "string", "boolean")) - it diagnoses too many arguments: expect(times({}, false)).to_raise.any_of(typeerrors(2)) - it fetches the user time: expect(type(times().utime)).to_be "number" expect(times("utime") >= 0).to_be(true) - it fetches the system time: expect(type(times().stime)).to_be "number" expect(times("stime") >= 0).to_be(true) - it fetches the children user time: expect(type(times().cutime)).to_be "number" expect(times("cutime") >= 0).to_be(true) - it fetches the children system time: expect(type(times().cstime)).to_be "number" expect(times("cstime") >= 0).to_be(true) - it fetches the elapsed time: expect(type(times().elapsed)).to_be "number" expect(times("elapsed") >= 0).to_be(true) - it fetches a subtable of named fields: | keys = {"utime", "cutime"} t = {times(table.unpack(keys))} for _, v in ipairs(t) do expect(type(v)).to_be "number" end - it fetches everything without an argument: keys = {"utime", "stime", "cutime", "cstime", "elapsed"} t = times() expect(t).to_contain.all_of(keys) for _, v in ipairs(keys) do expect(type(t[v])).to_be "number" end - describe uname: - before: uname = M.uname - context with bad arguments: | badargs.diagnose(uname, "uname(?string)") examples { ['it diagnoses bad specifier format options'] = function() expect(uname("foo %_")). to_error "bad argument #1 to 'uname' (invalid format option '_')" end } - it substitutes %n: expect(uname "%n").to_be(cmd_output "uname -n") - it substitutes %m: expect(uname "%m").to_be(cmd_output "uname -m") - it substitutes %r: expect(uname "%r").to_be(cmd_output "uname -r") - it outputs everything with no arguments: expect(uname():gsub("%s+"," "):gsub("%s$","")).to_be(cmd_output("uname -s -n -r -v -m"):gsub("%s+"," "):gsub("%s$","")) luaposix-36.3/spec/posix_dirent_spec.yaml000066400000000000000000000040241475444374100206650ustar00rootroot00000000000000before: this_module = 'posix.dirent' global_table = '_G' M = require(this_module) posix = require 'posix' specify posix.dirent: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe dir: - before: dir = M.dir - context with bad arguments: | badargs.diagnose(dir, "(?string)") examples { ["it diagnoses argument #1 not a valid file"] = function() expect(dir "/not/exists").to_raise.any_of { -- Can't be any more accurate, because error message is system specific "bad argument #1 to 'dir' (/not/exists: ", "bad argument #1 to '?' (/not/exists: ", } end } - describe files: - before: # Make and change into a temporary subdirectory where we can # control all the contents for self-contained examples. link, mkdir, mkdtemp = posix.link, posix.mkdir, posix.mkdtemp origwd = posix.getcwd() dir, errmsg = mkdtemp(template) mkdir(dir .. "/subdir") link("subdir", dir .. "/soft", true) touch(dir .. "/file") link(dir .. "/file", dir .. "/hard") link("no such destination", dir .. "/dangling", true) files = M.files - after: posix.chdir(origwd) rmtmp(dir) - context with bad arguments: | badargs.diagnose(files, "(?string)") examples { ["it diagnoses argument #1 not a valid file"] = function() expect(files "/not/exists").to_raise.any_of { -- Can't be any more accurate, because error message is system specific "bad argument #1 to 'files' (/not/exists: ", "bad argument #1 to '?' (/not/exists: ", } end } - it returns a table of files in the given directory: t = {} for f in files(dir) do table.insert(t, f) end table.sort(t) expect(t).to_equal {".", "..", "dangling", "file", "hard", "soft", "subdir"} luaposix-36.3/spec/posix_fcntl_spec.yaml000066400000000000000000000026151475444374100205120ustar00rootroot00000000000000before: this_module = 'posix.fcntl' global_table = '_G' M = require(this_module) posix = require 'posix' specify posix.fcntl: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe open: - before: | unistd = require "posix.unistd" O_CREAT, O_RDONLY, O_WRONLY = M.O_CREAT, M.O_RDONLY, M.O_WRONLY open = M.open close, read, write = unistd.close, unistd.read, unistd.write dir = posix.mkdtemp(template) fh = io.open(dir .. "/file", "w") fh:write "garbage\n" fh:close() - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(open, "(string, int, ?int)") - it opens an existing file: fd, err = open(dir .. "/file", O_RDONLY) expect(type(fd)).to_be "number" expect(fd >= 0).to_be(true) expect(read(fd, 10)).to_be "garbage\n" close(fd) - it opens a new file: buf = "more garbage\n" fd, err = open(dir .. "/creat", bor(O_CREAT, O_WRONLY)) expect(type(fd)).to_be "number" expect(fd >= 0).to_be(true) expect(write(fd, buf)).to_be(#buf) close(fd) - describe posix_fadvise: - before: posix_fadvise = M.posix_fadvise - context with bad arguments: if posix_fadvise then badargs.diagnose(posix_fadvise, "(int, int, int, int)") end luaposix-36.3/spec/posix_fnmatch_spec.yaml000066400000000000000000000025741475444374100210300ustar00rootroot00000000000000before: this_module = 'posix.fnmatch' global_table = '_G' M = require(this_module) specify posix.fnmatch: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe fnmatch: - before: fnmatch, FNM_PATHNAME, FNM_PERIOD, FNM_NOMATCH = M.fnmatch, M.FNM_PATHNAME, M.FNM_PERIOD, M.FNM_NOMATCH - context with bad arguments: badargs.diagnose(fnmatch, "(string, string, ?int)") - it matches a file path against itself: expect(fnmatch("test", "test")).to_be(0) - "it matches * against any filename characters": expect(fnmatch("tes*", "test")).to_be(0) expect(fnmatch("tes*", "test2")).to_be(0) expect(fnmatch("*t*", "test")).to_be(0) - "it matches ? against a single filename character": expect(fnmatch("tes?", "test")).to_be(0) expect(fnmatch("t???", "test")).to_be(0) expect(fnmatch("tes?", "tes")).to_be(FNM_NOMATCH) expect(fnmatch("tes?", "test2")).to_be(FNM_NOMATCH) - "it doesn't match path separators with FNM_PATHNAME": expect(fnmatch("*test", "/test")).to_be(0) expect(fnmatch("*test", "/test", FNM_PATHNAME)).to_be(FNM_NOMATCH) - "it doesn't match periods with FNM_PERIOD": expect(fnmatch("*test", ".test")).to_be(0) expect(fnmatch("*test", ".test", FNM_PERIOD)).to_be(FNM_NOMATCH) luaposix-36.3/spec/posix_glob_spec.yaml000066400000000000000000000057541475444374100203360ustar00rootroot00000000000000before: this_module = 'posix.glob' global_table = '_G' M = require(this_module) specify posix.glob: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe glob.GLOB_MARK: - before: MARK = M.GLOB_MARK - it is a number: expect(type(MARK)).to_be "number" - describe glob: - before: glob, MARK = M.glob, M.GLOB_MARK chdir = require 'posix'.chdir chmod = require 'posix'.chmod mkdir = require 'posix'.mkdir mkdtemp = require 'posix'.mkdtemp origwd = require 'posix'.getcwd() - after: chdir(origwd) - context with bad arguments: badargs.diagnose(glob, "(?string, int)") - it returns nil and GLOB_NOMATCH if there are no matches: dir = mkdtemp(template) chdir(dir) globlist, err = glob("foo", 0) expect(err).to_be(M.GLOB_NOMATCH) expect(type(globlist)).to_be "nil" rmtmp(dir) - it returns a table of matches: dir = mkdtemp(template) chdir(dir) touch("match") globlist = glob("*", 0) expect(type(globlist)).to_be "table" rmtmp(dir) - it ignores non-readable directories: dir = mkdtemp(template) chdir(dir) mkdir("readable") mkdir("unreadable") touch("readable/match") touch("unreadable/match") chmod("unreadable", "a-rwx") globlist, err = glob("*/match", 0) expect(globlist).to_equal {"readable/match"} chmod("unreadable", "u+rwx") rmtmp(dir) - it matches files in the current directory: dir = mkdtemp(template) chdir(dir) touch("test.1") touch("test.2") touch("extra_file") globlist = glob("test.*", 0) expect(type(globlist)).to_be "table" expect(globlist).to_equal {"test.1", "test.2"} rmtmp(dir) - it matches files and directories in the current directory: dir = mkdtemp(template) chdir(dir) touch("test.1") touch("test.2") mkdir("foo") mkdir("bar") globlist = glob("*", 0) expect(type(globlist)).to_be "table" expect(globlist).to_equal {"bar", "foo", "test.1", "test.2"} rmtmp(dir) - it returns unmatched pattern for GLOB_NOCHECK: dir = mkdtemp(template) chdir(dir) globlist = glob("nomatch", M.GLOB_NOCHECK) expect(globlist).to_equal {"nomatch"} - it uses '*' as the pattern if pattern is nil: dir = mkdtemp(template) chdir(dir) touch("test.1") touch("test.2") mkdir("foo") mkdir("bar") globlist = glob(nil, 0) expect(type(globlist)).to_be "table" expect(globlist).to_equal {"bar", "foo", "test.1", "test.2"} rmtmp(dir) - it adds '/' to directory names if GLOB_MARK is passed: dir = mkdtemp(template) chdir(dir) mkdir("foo") mkdir("bar") globlist = glob(nil, MARK) expect(type(globlist)).to_be "table" expect(globlist).to_equal {"bar/", "foo/"} rmtmp(dir) luaposix-36.3/spec/posix_grp_spec.yaml000066400000000000000000000047771475444374100202070ustar00rootroot00000000000000before: this_module = 'posix.grp' global_table = '_G' M = require(this_module) specify posix.grp: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - before: getgrgid = require 'posix'.getgrgid getgrnam = require 'posix'.getgrnam - describe endgrent: - before: endgrent = M.endgrent - context with bad arguments: badargs.diagnose(endgrent, "()") - it returns 'nil': expect(endgrent()).to_be(nil) - it rewinds the group database: g = M.getgrent() M.getgrent() endgrent() expect(M.getgrent()).to_equal(g) - describe getgrent: - before: getgrent = M.getgrent - context with bad arguments: badargs.diagnose(getgrent, "()") - it returns a PosixGroup for an existing group: expect(prototype(getgrent())).to_be "PosixGroup" - it fetches a different group on subsequent calls: g = getgrent() expect(getgrent()).not_to_equal(g) - it returns nil after the last entry was fetched: g = getgrent() while(g) do h = getgrent() expect(g).not_to_equal(h) g = h end expect(g).to_be(nil) M.endgrent() - describe getgrgid: - before: groot = getgrgid(0).gr_name - context with bad arguments: badargs.diagnose(getgrgid, "(int)") - it returns a PosixGroup for an existing group: expect(prototype(getgrgid(0))).to_be "PosixGroup" - it fetches a group by gid: expect(getgrgid(0).gr_name).to_be(groot) expect(getgrgid(0).gr_gid).to_be(0) expect(type(getgrgid(0).gr_mem)).to_be "table" - describe getgrnam: - before: groot = getgrgid(0).gr_name - context with bad arguments: badargs.diagnose(getgrnam, "(string)") - it returns 'nil' for a non-existent group: expect(getgrnam "veryunlikelygroupname").to_be(nil) - it returns a PosixGroup for an existing group: expect(prototype(getgrnam(groot))).to_be "PosixGroup" - it fetches a group by name: expect(getgrnam(groot).gr_name).to_be(groot) expect(getgrnam(groot).gr_gid).to_be(0) expect(type(getgrnam(groot).gr_mem)).to_be "table" - describe setgrent: - before: setgrent = M.setgrent - context with bad arguments: badargs.diagnose(setgrent, "()") - it returns 'nil': expect(setgrent()).to_be(nil) - it rewinds the group database: g = M.getgrent() M.getgrent() setgrent() expect(M.getgrent()).to_equal(g) luaposix-36.3/spec/posix_pwd_spec.yaml000066400000000000000000000054161475444374100202000ustar00rootroot00000000000000before: this_module = 'posix.pwd' global_table = '_G' M = require(this_module) specify posix.pwd: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe endpwent: - before: endpwent = M.endpwent - context with bad arguments: badargs.diagnose(endpwent, "()") - it returns 'nil': expect(endpwent()).to_be(nil) - it rewinds the passwd database: p = M.getpwent() M.getpwent() endpwent() expect(M.getpwent()).to_equal(p) - describe getpwent: - before: getpwent = M.getpwent - context with bad arguments: badargs.diagnose(getpwent, "()") - it returns a PosixPasswd for an existing user: expect(prototype(getpwent())).to_be "PosixPasswd" - it fetches a different user on subsequent calls: p = getpwent() expect(getpwent()).not_to_equal(p) - it returns nil after the last entry was fetched: p = getpwent() while(p) do q = getpwent() expect(p).not_to_equal(q) p = q end expect(p).to_be(nil) M.endpwent() - describe getpwnam: - before: getpwnam = M.getpwnam - context with bad arguments: badargs.diagnose(getpwnam, "(string)") - it returns 'nil' for a non-existent user: expect(getpwnam "veryunlikelyusername").to_be(nil) - it returns a PosixPasswd for an existing user: expect(prototype(getpwnam "root")).to_be "PosixPasswd" - it fetches a passwd entry by name: expect(getpwnam("root").pw_name).to_be "root" expect(getpwnam("root").pw_uid).to_be(0) expect(getpwnam("root").pw_gid).to_be(0) expect(type(getpwnam("root").pw_dir)).to_be "string" expect(type(getpwnam("root").pw_shell)).to_be "string" - describe getpwuid: - before: getpwuid = M.getpwuid - context with bad arguments: badargs.diagnose(getpwuid, "(int)") - context with weird arguments: - it accepts integer valued float arguments: expect(prototype(getpwuid(0.0))).to_be "PosixPasswd" - it returns a PosixPasswd for an existing user: expect(prototype(getpwuid(0))).to_be "PosixPasswd" - it fetches a passwd entry by gid: expect(getpwuid(0).pw_name).to_be "root" expect(getpwuid(0).pw_uid).to_be(0) expect(getpwuid(0).pw_gid).to_be(0) expect(type(getpwuid(0).pw_dir)).to_be "string" expect(type(getpwuid(0).pw_shell)).to_be "string" - describe setpwent: - before: setpwent = M.setpwent - context with bad arguments: badargs.diagnose(setpwent, "()") - it returns 'nil': expect(setpwent()).to_be(nil) - it rewinds the passwd database: p = M.getpwent() M.getpwent() setpwent() expect(M.getpwent()).to_equal(p) luaposix-36.3/spec/posix_signal_spec.yaml000066400000000000000000000012411475444374100206530ustar00rootroot00000000000000before: this_module = 'posix.signal' global_table = '_G' M = require(this_module) specify posix.signal: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe kill: - context with bad arguments: badargs.diagnose(M.kill, "(int, ?int)") - describe killpg: - context with bad arguments: badargs.diagnose(M.killpg, "(int, ?int)") - describe raise: - context with bad arguments: badargs.diagnose(M.raise, "(int)") - describe signal: - context with bad arguments: badargs.diagnose(M.signal, "(int, ?function|string, ?int)") luaposix-36.3/spec/posix_spec.yaml000066400000000000000000000751551475444374100173350ustar00rootroot00000000000000# Specl specifications for APIs in posix.c # # Specifications are topographically sorted, with fundamental calls specified # at the top of the file, and calls with dependencies on correct functioning # of earlier specifications further down. # # If you get a series of failed expectations, fixing the earliest failures # first will often clear up later failures automatically! before: this_module = 'posix' global_table = '_G' M = require(this_module) specify posix: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe euidaccess: - before: f = M.euidaccess - context with bad arguments: badargs.diagnose(f, "euidaccess(string, string)") - describe errno: - context with bad arguments: badargs.diagnose(M.errno, "(?int)") - describe set_errno: - context with bad arguments: badargs.diagnose(M.set_errno, "(int)") - describe getopt: - context with bad arguments: badargs.diagnose(M.getopt, "(list, string, ?int, ?int)") - describe openpty: - context with bad arguments: badargs.diagnose(M.openpty, "openpty()") - describe execx: - before: fork = require 'posix.unistd'.fork wait = require 'posix.sys.wait'.wait f = function(...) if fork() == 0 then M.execx(...) end return ({wait()})[3] end - context with bad arguments: badargs.diagnose(M.execx, "execx(function|table, ?any*)") - it executes a command returning normal exit status: expect(f{"true"}).to_be(0) - it executes a command returning abnormal exit status: expect(f{"false"}).to_be(1) - it executes a command with additional arguments: expect(luaproc([[ os.exit(require "posix".execx {"echo", "foo"}) ]])).to_succeed_with "foo\n" - it propagates failed command errno: expect(f{"no-such-command-exists"}).to_be(require 'posix.errno'.ENOENT) - it executes a function returning normal exit status: expect(f(function() end)).to_be(0) - it executes a function and propagates result: expect(f(function() return 2 end)).to_be(2) - it executes a function with arguments and propagates result: expect(f(function(i) return i end, 3)).to_be(3) - it executes a function with output to stdout: expect(luaproc([[ os.exit(require "posix".execx(function() io.stdout:write "foo\n" end)) ]])).to_succeed_with "foo\n" - describe spawn: - before: f = M.spawn - context with bad arguments: badargs.diagnose(f, "spawn(function|table, ?any*)") - it spawns a command and can detect success: expect(f({"true"})).to_be(0) - it can detect failure: expect(f({"false"})).to_be(1) - it can pass a table of arguments: expect(luaproc([[ os.exit(require "posix".spawn {"echo", "foo"}) ]])).to_succeed_with "foo\n" - it can pass a function: expect(luaproc([[ os.exit(require "posix".spawn(function() io.stdout:write "foo\n" end)) ]])).to_succeed_with "foo\n" - describe popen: - before: popen, pclose = M.popen, M.pclose read, write, BUFSIZE = M.read, M.write, M.BUFSIZ - context with bad arguments: badargs.diagnose(popen, "popen(function|table, string, ?function)") - it spawns a command and reads its output: p = popen({"echo", "foo"}, "r") s = M.read(p.fd, M.BUFSIZ) pclose(p) expect(s).to_equal "foo\n" - it spawns a command and writes its input: | script = [[ local M = require "posix" local p = M.popen({"wc"}, "w") local s = "foo bar baz\n" local r = M.write(p.fd, s) M.pclose(p) os.exit(r == #s and 0 or 1) ]] expect(luaproc(script)).to_succeed_while_matching "^%s*1%s+3%s+12\n$" - describe popen_pipeline: - before: popen_pipeline, pclose = M.popen_pipeline, M.pclose read, write, BUFSIZE = M.read, M.write, M.BUFSIZ - context with bad arguments: badargs.diagnose(popen_pipeline, "popen_pipeline(function|table, string, ?function)") - it spawns a pipeline and reads its output: p = popen_pipeline({{"echo", "foo", "bar", "baz"}, {"wc"}, {"wc", "-l"}}, "r") expect(read(p.fd, M.BUFSIZ)).to_match("^%s*1\n") pclose(p) - it spawns a pipeline and writes its input: | script = [[ local M = require "posix" local s = "foo bar baz\n" local p = M.popen_pipeline({{"cat"}, {"wc"}}, "w") local r = M.write(p.fd, s) M.pclose(p) os.exit(r == #s and 0 or 1) ]] expect(luaproc(script)).to_succeed_while_matching "^%s*1%s+3%s+12\n$" - describe timeradd: - before: tv1 = {tv_sec=2, tv_usec=123456} tv2 = {tv_sec=1, tv_usec=876543} f = M.timeradd - context with bad arguments: badargs.diagnose(f, "timeradd(table, table)") - context with systime.gettimeofday timervals: - it adds both fields of a timerval: expect(f(tv1, tv2)).to_equal {sec=3, usec=999999} - it adds both fields of a systime timerval: expect(f(tv1, tv2)).to_equal {sec=3, usec=999999} - it carries overflow second: expect(f(tv2, tv2)).to_equal {sec=3, usec=753086} - it does not require 'tv_sec' field: expect(f(tv1, {tv_usec=876543})). to_equal {sec= 2, usec=999999} expect(f({tv_usec= 123456}, {tv_usec=876543})). to_equal {sec=0, usec=999999} - it does not require 'tv_usec' field: expect(f(tv1, {tv_sec=1})). to_equal {sec=3, usec=123456} expect(f({tv_sec=2}, {tv_sec=1})). to_equal {sec=3, usec=0} - context with legacy timervals: - before: stv1 = {sec=tv1.tv_sec, usec=tv1.tv_usec} stv2 = {sec=tv2.tv_sec, usec=tv2.tv_usec} - it adds both fields of a timerval: expect(f(stv1, stv2)).to_equal {sec=3, usec=999999} - it carries overflow second: expect(f(stv2, stv2)).to_equal {sec=3, usec=753086} - it does not require 'sec' field: expect(f(stv1, {usec=876543})).to_equal {sec=2, usec=999999} expect(f({usec=123456}, {usec=876543})).to_equal {sec=0, usec=999999} - it does not require 'usec' field: expect(f(stv1, {sec=1})).to_equal {sec=3, usec=123456} expect(f({sec=2}, {sec=1})).to_equal {sec=3, usec=0} - describe timercmp: - before: tv1 = {tv_sec=2, tv_usec=123456} tv2 = {tv_sec=1, tv_usec=876543} f = M.timercmp - context with bad arguments: badargs.diagnose(f, "timercmp(table, table)") - context with systime.gettimeofday timervals: - it returns 0 if timers are equal: expect(f(tv1, tv1)).to_equal(0) - it returns positive integer if second timer is greater than first: expect(f(tv1, tv2) > 0).to_be(true) - it returns negative integer if first timer is greater than the second: expect(f(tv2, tv1) < 0).to_be(true) - context with legacy timervals: - before: stv1 = {sec=tv1.tv_sec, usec=tv1.tv_usec} stv2 = {sec=tv2.tv_sec, usec=tv2.tv_usec} - it returns 0 if timers are equal: expect(f(stv1, stv1)).to_equal(0) - it returns positive integer if second timer is greater than first: expect(f(stv1, stv2) > 0).to_be(true) - it returns negative integer if first timer is greater than the second: expect(f(stv2, stv1) < 0).to_be(true) - describe timersub: - before: tv1 = {tv_sec=2, tv_usec=876543} tv2 = {tv_sec=1, tv_usec=123456} f = M.timersub - context with bad arguments: badargs.diagnose(f, "timersub(table, table)") - context with systime.gettimeofday timervals: - it subtracts both fields of a timerval: expect(f(tv1, tv2)).to_equal {sec=1, usec=753087} - it carries overflow second: expect(f(tv2, tv1)).to_equal {sec=-2, usec=246913} - it does not require 'tv_sec' field: expect(f(tv1, {tv_usec=123456})).to_equal {sec=2, usec=753087} expect(f({tv_usec=876543}, {tv_usec=123456})). to_equal {sec=0, usec=753087} - it does not require 'tv_usec' field: expect(f(tv1, {tv_sec=1})).to_equal {sec=1, usec=876543} expect(f({tv_sec=2}, {tv_sec=1})).to_equal {sec=1, usec=0} - context with legacy timervals: - before: stv1 = {sec=tv1.tv_sec, usec=tv1.tv_usec} stv2 = {sec=tv2.tv_sec, usec=tv2.tv_usec} - it subtracts both fields of a timerval: expect(f(stv1, stv2)).to_equal {sec=1, usec=753087} - it carries overflow second: expect(f(stv2, stv1)).to_equal {sec=-2, usec=246913} - it does not require 'sec' field: expect(f(stv1, {usec=123456})).to_equal {sec=2, usec=753087} expect(f({usec = 876543}, {usec = 123456})). to_equal {sec=0, usec=753087} - it does not require 'usec' field: expect(f(stv1, {sec=1})).to_equal {sec=1, usec=876543} expect(f({sec=2}, {sec=1})).to_equal {sec=1, usec=0} - specify file descriptors: - describe fileno: - context with bad arguments: badargs.diagnose(M.fileno, "(file)") - describe rpoll: - context with bad arguments: badargs.diagnose(M.rpoll, "(int, int)") - describe poll: - context with bad arguments: badargs.diagnose(M.poll, "(table, ?int)") - describe close: - context with bad arguments: badargs.diagnose(M.close, "(int)") - describe dup: - context with bad arguments: badargs.diagnose(M.dup, "(int)") - describe dup2: - context with bad arguments: badargs.diagnose(M.dup2, "(int, int)") - describe pipe: - before: pipe, read, write = M.pipe, M.read, M.write data = "0123456789" pout, pin = pipe() - after: M.close(pin) M.close(pout) - context with bad arguments: badargs.diagnose(pipe, "()") - it creates a pipe: expect(pout > 0).to_be(true) expect(pin > 0).to_be(true) - it can buffer characters: write(pin, data) expect(read(pout, data:len())).to_be(data) - describe read: - context with bad arguments: badargs.diagnose(M.read, "(int, int)") - describe write: - before: EINVAL, read, write = M.EINVAL, M.read, M.write data = "0123456789" pout, pin = M.pipe() - after: M.close(pin) M.close(pout) - context with bad arguments: badargs.diagnose(M.write, "(int, string, ?int, ?int)") - context out of bounds: - 'it diagnoses argument #3 too small': | expect({write(pin, data, -1)}).to_equal { nil, "write: invalid attempt to access offset -1 in a buffer of length 10", EINVAL, } - 'it diagnoses argument #3 too large': | expect({write(pin, data, 99)}).to_equal { nil, "write: invalid attempt to access offset 99 in a buffer of length 10", EINVAL, } - 'it diagnoses argument #4 too small': | expect({write(pin, data, nil, -1)}).to_equal { nil, "write: invalid attempt to access offset -1 in a buffer of length 10", EINVAL, } - 'it diagnoses argument #4 too large': | expect({write(pin, data, nil, 99)}).to_equal { nil, "write: invalid attempt to access offset 99 in a buffer of length 10", EINVAL, } expect({write(pin, data, 6, 6)}).to_equal { nil, "write: invalid attempt to access offset 12 in a buffer of length 10", EINVAL, } - it returns number of bytes written: expect(write(pin, data)).to_be(data:len()) expect(write(pin, data, 4)).to_be(4) expect(write(pin, data, nil, 4)).to_be(data:len() - 4) - it accepts a zero-length buffer: expect(write(pin, '')).to_be(0) expect(write(pin, data, 0)).to_be(0) - it writes buffer contents: write(pin, data) expect(read(pout, data:len())).to_be(data) - it writes first nbytes of buffer: write(pin, data, 4) expect(read(pout, data:len())).to_be '0123' - it writes a substring of buffer: write(pin, data, 4, 4) expect(read(pout, data:len())).to_be '4567' - it writes to end of buffer when nbytes is nil: write(pin, data, nil, 4) expect(read(pout, data:len())).to_be '456789' - describe fcntl: - before: F_GETLK, F_SETLK, F_SETLKW = M.F_GETLK, M.F_SETLK, M.F_SETLKW F_RDLCK, F_WRLCK, F_UNLCK = M.F_RDLCK, M.F_WRLCK, M.F_UNLCK SEEK_SET, SEEK_CUR, SEEK_END = M.SEEK_SET, M.SEEK_CUR, M.SEEK_END fcntl, typeerrors = init(posix, "fcntl") # M.fcntl diagnoses the third arg differently depending on # the value of `cmd`, which `diagnose.badargs` can't express; ergo # manual checks here... - context with bad arguments: - 'it diagnoses missing argument #1': expect(fcntl()).to_raise.any_of(typeerrors(1, "int")) - 'it diagnoses argument #1 type not int': expect(fcntl(false)).to_raise.any_of(typeerrors(1, "int", "boolean")) - 'it diagnoses missing argument #2': expect(fcntl(-1)).to_raise.any_of(typeerrors(2, "int")) - 'it diagnoses argument #2 type not int': expect(fcntl(-1, false)).to_raise.any_of(typeerrors(2, "int", "boolean")) - 'it diagnoses missing argument #3 to F_GETLK': expect(fcntl(-1, F_GETLK)).to_raise.any_of(typeerrors(3, "table")) - 'it diagnoses argument #3 type to F_GETLK not table': expect(fcntl(-1, F_GETLK, false)). to_raise.any_of(typeerrors(3, "table", "boolean")) - 'it diagnoses argument #3 type to non-F_GETLK not int': expect(fcntl(-1, 0, false)). to_raise.any_of(typeerrors(3, "?int", "boolean")) - 'it diagnoses too many arguments': expect(fcntl(-1, F_GETLK, {}, false)).to_raise.any_of(typeerrors(4)) expect(fcntl(-1, 0, -1, false)).to_raise.any_of(typeerrors(4)) - it has all needed constants: expect(type(F_GETLK)).to_be "number" expect(type(F_SETLK)).to_be "number" expect(type(F_SETLKW)).to_be "number" expect(type(F_RDLCK)).to_be "number" expect(type(F_WRLCK)).to_be "number" expect(type(F_UNLCK)).to_be "number" expect(type(SEEK_SET)).to_be "number" expect(type(SEEK_CUR)).to_be "number" expect(type(SEEK_END)).to_be "number" - context when file locking: - before: mkstemp, open, close = M.mkstemp, M.open, M.close fork, wait, errno = M.fork, M.wait, M.errno O_RDWR, EAGAIN, EACCES = M.O_RDWR, M.EAGAIN, M.EACCES P_CHILD = 0 SUCCESS = 0 fd, path = mkstemp "tmpXXXXXX" close(fd) parent_pid = M.getpid "pid" query_lock = { l_type = F_RDLCK, l_whence = SEEK_SET, l_start = 0, l_len = 0, } write_lock = { l_type = F_WRLCK, l_whence = SEEK_SET, l_start = 0, l_len = 0, } - after: os.remove(path) - it checks whether lock is possible with F_GETLK: fd = open(path, O_RDWR) result = fcntl(fd, F_GETLK, query_lock) expect(result).to_be(SUCCESS) expect(query_lock.l_type).to_be(F_UNLCK) close(fd) - it can lock file with F_SETLK: | parent_fd = open(path, O_RDWR) result = fcntl(parent_fd, F_SETLK, write_lock) expect(result).to_be(SUCCESS) process = fork() if process == P_CHILD then child_fd = open(path, O_RDWR) result = fcntl(child_fd, F_GETLK, query_lock) close(child_fd) --(not sure how to expect() in subprocess) if result ~= SUCCESS then os.exit(10) elseif query_lock.l_pid ~= parent_pid then os.exit(11) else os.exit(12) end else _, _, exit_code = wait(process) expect(exit_code).to_be(12) end close(parent_fd) - it returns error if cannot lock file with F_SETLK: | parent_fd = open(path, O_RDWR) result = fcntl(parent_fd, F_SETLK, write_lock) expect(result).to_be(SUCCESS) process = fork() if process == P_CHILD then child_fd = open(path, O_RDWR) result, errmsg, errcode = fcntl(child_fd, F_SETLK, write_lock) close(child_fd) --(not sure how to expect() in subprocess) if result == SUCCESS then os.exit(100) elseif result == nil and errcode ~= EACCES and errcode ~= EAGAIN then os.exit(errcode) else os.exit(101) end else _, _, exit_code = wait(process) expect({exit_code, errno(exit_code)}).to_equal {101, errno(101)} end close(parent_fd) - describe lseek: - before: close, lseek, open, read, write = M.close, M.lseek, M.open, M.read, M.write SEEK_SET, SEEK_CUR, SEEK_END = M.SEEK_SET, M.SEEK_CUR, M.SEEK_END - context with bad arguments: badargs.diagnose(lseek, "(int, int, int)") - it changes the current position of a file descriptor: _, path = M.mkstemp(template) fd = open(path, M.O_RDWR) expect(fd).not_to_be(nil) write(fd, "0123456789") lseek(fd, 3, SEEK_SET) expect(read(fd, 3)).to_be "345" lseek(fd, -2, SEEK_CUR) expect(read(fd, 3)).to_be "456" lseek(fd, -5, SEEK_END) expect(read(fd, 3)).to_be "567" close(fd) os.remove(path) - specify file system: - before: # Make and change into a temporary subdirectory where we can # control all the contents for self-contained examples. link, mkdir, mkdtemp = M.link, M.mkdir, M.mkdtemp origwd = M.getcwd() dir, errmsg = mkdtemp(template) mkdir(dir .. "/subdir") link("subdir", dir .. "/soft", true) touch(dir .. "/file") link(dir .. "/file", dir .. "/hard") link("no such destination", dir .. "/dangling", true) - after: M.chdir(origwd) rmtmp(dir) - describe sync: - context with bad arguments: badargs.diagnose(M.sync, "()") - describe fsync: - context with bad arguments: badargs.diagnose(M.fsync, "(int)") - describe fdatasync: - context with bad arguments: if M.fdatasync then badargs.diagnose(M.fdatasync, "(int)") end - describe basename: - before: basename = M.basename - context with bad arguments: badargs.diagnose(basename, "(string)") - it returns a path without leading directories: expect(basename "/foo/bar").to_be "bar" - describe dirname: - before: dirname = M.dirname - context with bad arguments: badargs.diagnose(dirname, "(string)") - it return a path without final element: expect(dirname "/foo/bar").to_be "/foo" - describe dir: - context with bad arguments: badargs.diagnose(M.dir, "(?string)") - describe glob: - before: chdir, glob, mkdtemp = M.chdir, M.glob, M.mkdtemp mkdir = M.mkdir - context with bad arguments: badargs.diagnose(glob, "glob([?string|table])") - it matches files in the given directory: dir = mkdtemp(template) touch(dir .. "/test.1") touch(dir .. "/test.2") touch(dir .. "/extra_file") chdir(dir) globlist, errmsg = glob "test.*" expect(errmsg).to_be(nil) expect(type(globlist)).to_be "table" expect(globlist).to_equal {"test.1", "test.2"} rmtmp(dir) - it matches files and directories in the given directory: dir = mkdtemp(template) touch(dir .. "/test.1") chdir(dir) mkdir("foo") mkdir("bar") globlist = glob() expect(globlist).to_equal {"bar", "foo", "test.1"} rmtmp(dir) - it adds / to filenames if GLOB_MARK is true: dir = mkdtemp(template) chdir(dir) mkdir("foo") mkdir("bar") globlist = glob({pattern="*", MARK=true}) expect(globlist).to_equal {"bar/", "foo/"} rmtmp(dir) - it does not add / to filenames if GLOB_MARK is false: dir = mkdtemp(template) chdir(dir) mkdir("foo") mkdir("bar") globlist = glob({MARK=false}) expect(globlist).to_equal {"bar", "foo"} rmtmp(dir) - describe files: - before: files = M.files - context with bad arguments: badargs.diagnose(files, "(?string)") - it returns a table of files in the given directory: t = {} for f in files(dir) do table.insert(t, f) end table.sort(t) expect(t).to_equal {".", "..", "dangling", "file", "hard", "soft", "subdir"} - describe getcwd: - context with bad arguments: badargs.diagnose(M.getcwd, "()") - describe chdir: - before: chdir, chmod, getcwd, mkdir, rmdir = M.chdir, M.chmod, M.getcwd, M.mkdir, M.rmdir cwd = getcwd() - after: chdir(cwd) pcall(rmdir, "x") - context with bad arguments: badargs.diagnose(chdir, "(string)") - it changes to a relative directory: thisdir = M.basename(getcwd()) expect(Emsg(chdir("../" .. thisdir))). not_to_contain "No such file or directory" expect(Emsg(chdir "..")).not_to_contain "No such file or directory" - it changes to an absolute directory: expect(Emsg(chdir "/var/tmp/")). not_to_contain "No such file or directory" - it diagnoses missing directory: expect(Emsg(chdir "very_unlikely_to_exist")). to_contain "No such file or directory" - it diagnoses insufficient permissions: mkdir "x" chmod("x", "a-rwx") expect(Emsg(chdir "x")). to_contain "Permission denied" rmdir "x" - describe rmdir: - before: mkdir, rmdir = M.mkdir, M.rmdir - context with bad arguments: badargs.diagnose(rmdir, "(string)") - it removes the named directory: mkdir "x" expect(Emsg(rmdir "x")).not_to_contain "No such file or directory" - it diagnoses missing directory: expect(Emsg(rmdir ".")).to_contain "Invalid argument" - describe unlink: - context with bad arguments: badargs.diagnose(M.unlink, "(string)") - describe link: - before: link, stat = M.link, M.stat touch "xxx" - after: os.remove "xxx" - context with bad arguments: badargs.diagnose(link, "(string, string, ?boolean)") - it creates hard links: expect(Emsg(link("xxx", "xxx-hard"))).to_be "" expect(stat("xxx-hard", "ino")).to_be(stat("xxx", "ino")) os.remove "xxx-hard" - it creates soft links: expect(Emsg(link("xxx", "xxx-soft", true))).to_be "" expect(stat("xxx-soft", "type")).to_be "link" os.remove "xxx-soft" - describe readlink: - before: readlink = M.readlink - context with bad arguments: badargs.diagnose(readlink, "(string)") - it diagnoses missing file: | _, err, code = readlink "does not exist!" expect(err).to_match "^does not exist!: " expect(code).to_be(M.ENOENT) - it diagnoses non-symbolic link: | _, err, code = readlink(dir .. "/file") expect(err).to_be(dir .. "/file: not a symbolic link") expect(code).to_be(M.EINVAL) - it reads the contents of a symbolic link: expect(readlink(dir .. "/soft")).to_be "subdir" - it reads the contents of a dangling symbolic link: expect(readlink(dir .. "/dangling")).to_be "no such destination" - describe access: - before: access = M.access touch "xxx" - after: os.remove "xxx" - context with bad arguments: badargs.diagnose(M.access, "(string, ?string)") - it checks whether a file is visible to the real user: expect(Emsg(access("xxx", "f"))).to_be "" - it checks whether a file is readable by the real user: expect(Emsg(access("xxx", "r"))).to_be "" - it checks whether a file is writable by the real user: expect(Emsg(access("xxx", "w"))).to_be "" - "it defaults to 'f' with no mode argument": expect(access("xxx")).to_be(access("xxx", "f")) - it diagnoses missing files: os.remove "xxx" expect(Emsg(access "xxx")).to_contain "No such file or directory" - describe utime: - before: stat, utime = M.stat, M.utime touch "xxx" - after: os.remove "xxx" - context with bad arguments: badargs.diagnose(M.utime, "(string, ?int, ?int)") - it sets the last file modification time: mtime = stat("/etc", "mtime") expect(stat("xxx", "mtime")).not_to_equal(mtime) expect(Emsg(utime("xxx", mtime))).to_be "" expect(stat("xxx", "mtime")).to_equal(mtime) - it sets the last file access time: atime = stat("/etc", "atime") expect(stat("xxx", "atime")).not_to_equal(atime) expect(Emsg(utime("xxx", nil, atime))).to_be "" expect(stat("xxx", "atime")).to_equal(atime) - specify process management: - describe nice: - before: nice = M.nice - context with bad arguments: badargs.diagnose(nice, "(int)") - it adjusts the process priority: old = nice(1) expect(old).not_to_be(nil) new = nice(2) expect(new).to_be(old + 2) - describe fork: # NOTE: Calling expect in a child process does not report results # back to parent, so we send test data over a pipe. - before: nice, execp, fork, getpid, getppid, wait = M.nice, M.execp, M.fork, M.getpid, M.getppid, M.wait _exit, close, pipe, read, write = M._exit, M.close, M.pipe, M.read, M.write P_CHILD = 0 - context with bad arguments: badargs.diagnose(fork, "()") - it copies itself to a new child process: | r, w = pipe() process, status = fork(), 67 if process == P_CHILD then close(r) -- close unused read end -- write parent pid and child pid to shared pipe. write(w, tostring(getppid()).."\n") write(w, tostring(getpid "pid").."\n") close(w) _exit(status) else M.close(w) -- close unused write end p, msg, ret = wait(process) expect(p).to_be(process) expect(msg).to_be "exited" expect(ret).to_be(status) -- check pids from child process. buf = M.read(r, 1024) cppid, cpid = string.match(buf, "(%d+)\n(%d+)\n") close(r) expect(cppid).to_be(tostring(getpid "pid")) expect(cpid).to_be(tostring(process)) end - describe _exit: - context with bad arguments: badargs.diagnose(M. _exit, "(int)") - describe wait: - context with bad arguments: badargs.diagnose(M.wait, "(?int, ?int)") - describe setpid: - before: setpid, typeerrors = init(posix, "setpid") - context with bad arguments: - 'it diagnoses missing argument #1': expect(setpid()).to_raise.any_of(typeerrors(1, "string")) - 'it diagnoses argument #1 type not string': expect(setpid(false)).to_raise.any_of(typeerrors(1, "string", "boolean")) - 'it diagnoses argument #1 invalid option': | expect(setpid "fubar").to_raise.any_of { "bad argument #1 to '?' (invalid id option 'f')", "bad argument #1 to 'setpid' (invalid id option 'f')", } - 'it diagnoses missing argument #2': expect(setpid "p").to_raise.any_of(typeerrors(2, "int")) - 'it diagnoses argument #2 type not int': expect(setpid("p", false)). to_raise.any_of(typeerrors(2, "int", "boolean")) - 'it diagnoses missing argument #3': expect(setpid("p", 0)).to_raise.any_of(typeerrors(3, "int")) - 'it diagnoses argument #3 type not int': expect(setpid("p", 0, false)). to_raise.any_of(typeerrors(3, "int", "boolean")) - it diagnoses too many arguments: expect(setpid("p", 0, 0, false)).to_raise.any_of(typeerrors(4)) expect(setpid("u", 0, false)).to_raise.any_of(typeerrors(3)) - describe sleep: - context with bad arguments: badargs.diagnose(M.sleep, "(int)") - describe sched_setscheduler: - context with bad arguments: if M.sched_setscheduler then badargs.diagnose(M.sched_setscheduler, "(?int, ?int, ?int)") end - describe sched_getscheduler: - context with bad arguments: if M.sched_getscheduler then badargs.diagnose(M.sched_getscheduler, "(?int)") end - describe ctermid: - before: ctermid = M.ctermid - context with bad arguments: badargs.diagnose(M.ctermid, "()") - it returns the pathname of the controlling terminal: expect(ctermid()).to_match.any_of {"/.*pts.*", "/.*tty.*"} - describe isatty: - context with bad arguments: badargs.diagnose(M.isatty, "(int)") - describe tcsetattr: - context with bad arguments: badargs.diagnose(M.tcsetattr, "(int, int, table)") - describe tcgetattr: - context with bad arguments: badargs.diagnose(M.tcgetattr, "(int)") - describe tcsendbreak: - context with bad arguments: badargs.diagnose(M.tcsendbreak, "(int, int)") - describe tcdrain: - context with bad arguments: badargs.diagnose(M.tcdrain, "(int)") - describe tcflush: - context with bad arguments: badargs.diagnose(M.tcflush, "(int, int)") - describe tcflow: - context with bad arguments: badargs.diagnose(M.tcflow, "(int, int)") - describe tcgetwinsize: - context with bad arguments: if M.tcgetwinsize then badargs.diagnose(M.tcgetwinsize, "(int)") end - describe tcsetwinsize: - context with bad arguments: if M.tcsetwinsize then badargs.diagnose(M.tcsetwinsize, "(int, table)") end - specify user management: - describe getlogin: - context with bad arguments: badargs.diagnose(M.getlogin, "()") - describe getgroups: - context with bad arguments: if M.getgroups then badargs.diagnose(M.getgroups, "()") end - describe crypt: - before: crypt = M.crypt key, salt = "hello", "pl" - context with bad arguments: if M.crypt then badargs.diagnose(M.crypt, "(string, string)") end - it can perform repeatable one-way hashing: hash = crypt(key, salt) expect(crypt(key, salt)).to_be(hash) - it encrypts differently for a different salt: expect(crypt(key, salt)).not_to_equal(crypt(key, "/.")) luaposix-36.3/spec/posix_stdio_spec.yaml000066400000000000000000000051631475444374100205270ustar00rootroot00000000000000before: this_module = 'posix.stdio' global_table = '_G' M = require(this_module) specify posix.stdio: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe fdopen: - before: fdopen = M.fdopen fd = fdopen(require 'posix.unistd'.STDOUT_FILENO, "w") - context with bad arguments: badargs.diagnose(fdopen, "(int,string)") - it duplicates a stream: expect(type(fd)).to_be "userdata" - it closes an open stream: | script = [[ local fcntl = require "posix.fcntl" local stdio = require "posix.stdio" local sys_stat = require "posix.sys.stat" local unlink = require "posix.unistd".unlink function create_file(path) local flags = fcntl.O_WRONLY + fcntl.O_CREAT + fcntl.O_EXCL local mode = sys_stat.S_IRUSR + sys_stat.S_IWUSR local fd, message, open_err = fcntl.open(path, flags, mode) if not fd then return nil, message end return stdio.fdopen(fd, "w") end local path = '.delete.me' unlink(path) local f, msg = create_file(path) if not f then print(msg) else f:close() end unlink(path) os.exit(0) ]] pending "issue #217" expect(luaproc(script)).to_succeed_with '' - it writes to the duplicated stream: | script = [[ local stdio = require "posix.stdio" local fd = stdio.fdopen(require 'posix.unistd'.STDOUT_FILENO, "w") -- Lua 5.1 file.write returns true; > 5.1 returns file handle local r = fd:write("writing to fdopen(stdout)") os.exit(r ~= nil and 0 or 1) ]] pending "issue #217" expect(luaproc(script)).to_succeed_with "writing to fdopen(stdout)" - describe rename: - before: rename = M.rename fd, path = require "posix.stdlib".mkstemp(template) - after: require 'posix.unistd'.close(fd) os.remove(path) - context with bad arguments: badargs.diagnose(rename, "(string,string)") - it renames an existing file: newpath = path .. ".renamed" expect(fd).not_to_be(nil) require 'posix.unistd'.write(fd, "rename me") rename(path, newpath) expect(io.open(path, "r")).to_be(nil) fh = io.open(newpath, "r") expect(fh).not_to_be(nil) expect(fh:read()).to_be "rename me" fh:close() rename(newpath, path) luaposix-36.3/spec/posix_stdlib_spec.yaml000066400000000000000000000112421475444374100206610ustar00rootroot00000000000000before: this_module = 'posix.stdlib' global_table = '_G' M = require(this_module) specify posix.stdlib: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe abort: - context with bad arguments: badargs.diagnose(M.abort, "()") - describe getenv: - before: getenv = M.getenv - context with bad arguments: badargs.diagnose(getenv, "(?string)") - it fetches a table of process environment variables: | volatile = { _=true, CWD=true, LUA_PATH=true, PWD=true, SHLVL=true, } ESC = string.char(27) for k,v in pairs(getenv()) do if not volatile[k] then expect(hell.spawn('echo "' .. k .. '=$' .. k .. '" | tr "' .. ESC .. '" "^"')). to_contain_output(k .. "=" .. string.gsub(v, '\\033', '^')) end end - it fetches a named process environment variable: expect(getenv "USER").to_be(cmd_output('echo "$USER"')) expect(getenv "HOME").to_be(cmd_output('echo "$HOME"')) - it returns nil for an absent environment setting: expect(getenv "very_unlikely_to_be_set").to_be(nil) - describe grantpt: - context with bad arguments: badargs.diagnose(M.grantpt, "(int)") - describe mkdtemp: - before: st = require "posix.sys.stat" mkdtemp = M.mkdtemp stat, IFMT, IFDIR, IRWXU = st.stat, st.S_IFMT, st.S_IFDIR, st.S_IRWXU IRWXA = bor(st.S_IRWXU, st.S_IRWXG, st.S_IRWXO) - context with bad arguments: badargs.diagnose(mkdtemp, "(string)") - it creates a temporary directory from a template: dir, errmsg = mkdtemp(template) expect(dir).not_to_be(nil) dirstat = stat(dir) expect(band(dirstat.st_mode, IFMT)).to_be(IFDIR) expect(band(dirstat.st_mode, IRWXA)).to_be(IRWXU) rmtmp(dir) - describe mkstemp: - before: fc = require "posix.fcntl" st = require "posix.sys.stat" unistd = require "posix.unistd" O_RDONLY, open = fc.O_RDONLY, fc.open mkstemp = M.mkstemp close, isatty, read, write = unistd.close, unistd.isatty, unistd.read, unistd.write stat, IFMT, IFREG = st.stat, st.S_IFMT, st.S_IFREG IRW_U = bor(st.S_IRUSR, st.S_IWUSR) IRWXA = bor(st.S_IRWXU, st.S_IRWXG, st.S_IRWXO) fd, path = mkstemp(template) - after: close(fd) os.remove(path) - context with bad arguments: badargs.diagnose(mkstemp, "(string)") - it creates a temporary file from a template: expect(fd).not_to_be(nil) write(fd, "12345") expect(isatty(fd)).not_to_be(true) fstat = stat(path) expect(band(fstat.st_mode, IFMT)).to_be(IFREG) expect(band(fstat.st_mode, IRWXA)).to_be(IRW_U) expect(fstat.st_size).to_be(5) fd2 = open(path, O_RDONLY) expect(read(fd2, 5)).to_be "12345" close(fd2) - it creates a new temporary file on each call: fd2, another = mkstemp(template) expect(fd2).not_to_be(fd) expect(another).not_to_be(path) close(fd2) os.remove(another) - describe openpt: - before: fc = require "posix.fcntl" st = require "posix.sys.stat" close = require "posix.unistd".close grantpt, openpt, ptsname, unlockpt = M.grantpt, M.openpt, M.ptsname, M.unlockpt O_RDWR, O_NOCTTY, open = fc.O_RDWR, fc.O_NOCTTY, fc.open stat, IFMT, IFCHR = st.stat, st.S_IFMT, st.S_IFCHR - context with bad arguments: badargs.diagnose(openpt, "(int)") - it can create a pseudoterminal: masterfd = openpt(bor(O_RDWR, O_NOCTTY)) expect(type(masterfd)).to_be "number" expect(masterfd > 0).to_be(true) expect(Emsg(grantpt(masterfd))).to_be "" expect(Emsg(unlockpt(masterfd))).to_be "" slavename = ptsname(masterfd) slavestat = stat(slavename) expect(band(slavestat.st_mode, IFMT)).to_be(IFCHR) slavefd = open(slavename, bor(O_RDWR, O_NOCTTY)) expect(type(slavefd)).to_be "number" expect(slavefd > 0).to_be(true) close(slavefd) close(masterfd) - describe ptsname: - context with bad arguments: badargs.diagnose(M.ptsname, "(int)") - describe realpath: - context with bad arguments: badargs.diagnose(M.realpath, "(string)") - describe setenv: - before: getenv, setenv = M.getenv, M.setenv - context with bad arguments: badargs.diagnose(M.setenv, "(string, ?string, ?any)") - it sets a new value in the process environment: setenv("MYVAR", "123") expect(getenv "MYVAR").to_be "123" setenv("MYVAR", nil) expect(getenv "MYVAR").to_be(nil) - describe unlockpt: - context with bad arguments: badargs.diagnose(M.unlockpt, "(int)") luaposix-36.3/spec/posix_sys_msg_spec.yaml000066400000000000000000000141371475444374100210720ustar00rootroot00000000000000before: this_module = 'posix.sys.msg' global_table = '_G' M = require(this_module) specify posix.sys.msg: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - before: errno = require 'posix.errno' msg = require 'posix.sys.msg' st = require 'posix.sys.stat' unistd = require 'posix.unistd' EPOCH = require 'posix.time'.time() EEXIST = errno.EEXIST msgget, msgsnd, msgrcv = M.msgget, M.msgsnd, M.msgrcv IPC_CREAT, IPC_EXCL = M.IPC_CREAT, M.IPC_EXCL S_IRUSR, S_IRGRP, S_IROTH = st.S_IRUSR, st.S_IRGRP, st.S_IROTH S_IWUSR, S_IWGRP, S_IWOTH = st.S_IWUSR, st.S_IWGRP, st.S_IWOTH mode = bor(S_IRUSR, S_IRGRP, S_IROTH, S_IWUSR, S_IWGRP, S_IWOTH) mq, err, errnum = msgget(100, bor(IPC_CREAT, IPC_EXCL, mode)) if errnum == EEXIST then mq, err = msgget(100, mode) end mtype = 42 mdata = 'Answer to the Ultimate Question of Life' - describe msgget: - context with bad arguments: badargs.diagnose(msgget, ' (int, ?int)') - it creates a queue: expect(mq).not_to_be(nil) expect(err).to_be(nil) - describe msgsnd: - context with bad arguments: badargs.diagnose(msgsnd, ' (int, int, string, ?int)') - it sends a message: ok, err = msgsnd(mq, mtype, mdata) expect(ok).not_to_be(err) - describe msgrcv: - context with bad arguments: badargs.diagnose(msgrcv, ' (int, int, ?int, ?int)') - it receives a message: expect({msgrcv(mq, 128)}).to_equal {mtype, mdata, nil} - describe msgctl: - before: msgctl = M.msgctl IPC_RMID, IPC_SET, IPC_STAT = M.IPC_RMID, M.IPC_SET, M.IPC_STAT objtype = function(x) return(getmetatable(x) or {})._type end - context with bad arguments: # Not really 'any*' for arg3, but that's all we can do without knowing arg2! badargs.diagnose(msgctl, ' (int, int, any*)') - context with IPC_STAT: - it diagnoses too many arguments: expect(msgctl(mq, IPC_STAT, false)). to_raise 'no more than 2 arguments expected, got 3' - it returns a new table on each invocation: expect(msgctl(mq, IPC_STAT)).not_to_be(msgctl(mq, IPC_STAT)) - it returns correctly populated PosixMsqid table: msqid = msgctl(mq, IPC_STAT) expect(objtype(msqid)).to_be 'PosixMsqid' expect(type(msqid.msg_qnum)).to_be 'number' expect(type(msqid.msg_qbytes)).to_be 'number' expect(msqid.msg_lspid).to_be(unistd.getpid()) expect(msqid.msg_lrpid).to_be(unistd.getpid()) expect(msqid.msg_stime).to_be_within_n_of {value=EPOCH, delta=1} expect(msqid.msg_rtime).to_be_within_n_of {value=EPOCH, delta=1} expect(msqid.msg_perm.uid).to_be(unistd.getuid()) expect(msqid.msg_perm.gid).to_be(unistd.getgid()) expect(msqid.msg_perm.cuid).to_be(msqid.msg_perm.uid) expect(msqid.msg_perm.cgid).to_be(msqid.msg_perm.gid) expect(msqid.msg_perm.mode).to_be(mode) - context with IPC_SET: - before: sleep = require 'posix.unistd'.sleep msqid = { msg_perm = { uid = unistd.getuid(), gid = unistd.getgid(), mode = mode, }, msg_qbytes = 1024, } - 'it diagnoses missing argument #3': expect(msgctl(mq, IPC_SET)).to_raise 'table expected, got no value' - 'it diagnoses argument #3 type not table': expect(msgctl(mq, IPC_SET, false)).to_raise 'table expected, got boolean' - 'it diagnoses argument #3 with missing fields': msqid.msg_qbytes = nil expect(msgctl(mq, IPC_SET, msqid)). to_raise "integer expected for field 'msg_qbytes', got no value" expect(msgctl(mq, IPC_SET, {msg_qbytes=1024})). to_raise "table expected for field 'msg_perm', got no value" - 'it diagnoses argument #3 with bad field types': msqid.msg_qbytes = false expect(msgctl(mq, IPC_SET, msqid)). to_raise "integer expected for field 'msg_qbytes', got boolean" expect(msgctl(mq, IPC_SET, {msg_qbytes=1024, msg_perm=false})). to_raise "table expected for field 'msg_perm', got boolean" - 'it diagnoses argument #3 with bad field names': msqid.bogus = 1 expect(msgctl(mq, IPC_SET, msqid)). to_raise "invalid field name 'bogus'" - 'it diagnoses argument #3 with missing subfields': msqid.msg_perm.mode = nil expect(msgctl(mq, IPC_SET, msqid)). to_raise "integer expected for field 'mode', got no value" - 'it diagnoses argument #3 with bad subfield types': msqid.msg_perm.mode = false expect(msgctl(mq, IPC_SET, msqid)). to_raise "integer expected for field 'mode', got boolean" - 'it diagnoses argument #3 with bad subfield names': msqid.msg_perm.bogus = 1 expect(msgctl(mq, IPC_SET, msqid)). to_raise "invalid field name 'bogus'" - it diagnoses too many arguments: expect(msgctl(mq, IPC_SET, {}, nil)). to_raise 'no more than 3 arguments expected, got 4' - it sets specified fields in the message queue: expect(msgctl(mq, IPC_SET, msqid)).not_to_be(nil) r = msgctl(mq, IPC_STAT) expect(r.msg_perm.uid).to_be(unistd.getuid()) expect(r.msg_perm.gid).to_be(unistd.getgid()) expect(r.msg_perm.mode).to_be(mode) expect(r.msg_qbytes).to_be(1024) - it updates ctime field: msqid.msg_qbytes = 666 ctime = msgctl(mq, IPC_STAT).msg_ctime expect(ctime).not_to_be(nil) sleep(2) expect(msgctl(mq, IPC_SET, msqid)).not_to_be(nil) expect(msgctl(mq, IPC_STAT).msg_ctime).not_to_be(ctime) - context with IPC_RMID: - it diagnoses too many arguments to IPC_RMID cmd: expect(msgctl(mq, IPC_RMID, false)).to_raise 'no more than 2 arguments expected, got 3' - it removes a queue: ok, err = msgctl(mq, IPC_RMID) expect(ok).not_to_be(err) - it diagnoses a bad queue: | ok, err = msgctl(mq, IPC_RMID) expect(ok).to_be(nil) expect(err).to_contain 'msgctl: ' luaposix-36.3/spec/posix_sys_resource_spec.yaml000066400000000000000000000055461475444374100221370ustar00rootroot00000000000000before: this_module = 'posix.sys.resource' global_table = '_G' M = require(this_module) specify posix.sys.resource: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe getrlimit: - before: getrlimit = M.getrlimit - context with bad arguments: badargs.diagnose(getrlimit, "(int)") - it returns a PosixRlimit: expect(prototype(getrlimit(M.RLIMIT_AS))).to_be "PosixRlimit" - it fetches resource limits for a process: for _, rc in pairs {"RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA", "RLIMIT_FSIZE", "RLIMIT_NOFILE", "RLIMIT_STACK", "RLIMIT_AS"} do rlim = getrlimit(M[rc]) expect(type(rlim.rlim_cur)).to_be "number" expect(type(rlim.rlim_max)).to_be "number" end - describe setrlimit: - before: setrlimit, typeerrors = init(M, "setrlimit") getrlimit = M.getrlimit - context with bad arguments: | badargs.diagnose(setrlimit, "(int, table)") examples { ["context diagnosing rlimit table fields"] = { { ["it diagnoses argument #2 missing rlim_cur field"] = function() expect(setrlimit(-1, {})).to_raise. any_of(typeerrors(2, "integer", "rlim_cur", "no value")) end }, { ["it diagnoses argument #2 rlim_cur field type not int"] = function() expect(setrlimit(-1, {rlim_cur = false})).to_raise. any_of(typeerrors(2, "integer", "rlim_cur", "boolean")) end }, { ["it diagnoses argument #2 missing rlim_max field"] = function() expect(setrlimit(-1, {rlim_cur = -1})).to_raise. any_of(typeerrors(2, "integer", "rlim_max", "no value")) end }, { ["it diagnoses argument #2 rlim_max field type not int"] = function() expect(setrlimit(-1, {rlim_cur = -1, rlim_max = false})).to_raise. any_of(typeerrors(2, "integer", "rlim_max", "boolean")) end }, { ["it diagnoses argument #2 spurious fields"] = function() expect(setrlimit(-1, {rlim_cur = -1, rlim_max = -1, bogus = false})). to_raise.any_of(typeerrors(2, nil, "bogus")) end }, } } - it accepts PosixRlimit argument: | for _, rc in pairs {"RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA", "RLIMIT_FSIZE", "RLIMIT_NOFILE", "RLIMIT_STACK", "RLIMIT_AS"} do rlim = getrlimit(M[rc]) expect({setrlimit(M[rc], rlim)}).to_equal.any_of { {0}, {nil, "setrlimit: Operation not permitted", 1}, } end luaposix-36.3/spec/posix_sys_socket_spec.yaml000066400000000000000000000404721475444374100215750ustar00rootroot00000000000000before: this_module = 'posix.sys.socket' global_table = '_G' M = require(this_module) specify posix.sys.socket: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe socket: - context with bad arguments: badargs.diagnose(M.socket, "(int, int, int)") - describe socketpair: - context with bad arguments: badargs.diagnose(M.socketpair, "(int, int, int)") - describe getaddrinfo: - before: getaddrinfo, typeerrors = init(M, "getaddrinfo") - context with bad arguments: | badargs.diagnose(getaddrinfo, "(?string, ?string|int, ?table)") examples { ["it diagnoses unspecified host and service"] = function() expect(getaddrinfo()).to_raise. any_of(typeerrors(2, "integer or string")) end } examples { ["it diagnoses invalid hints fields"] = function() expect(getaddrinfo("localhost", nil, { protacol=M.IPPROTO_TCP })).to_raise.any_of(typeerrors(3, nil, "protacol")) expect(getaddrinfo("localhost", nil, { family=M.AF_INET, sacktype=M.SOCK_DGRAM, protocol=M.IPPROTO_TCP, })).to_raise.any_of(typeerrors(3, nil, "sacktype")) end } examples { ["it diagnoses wrong hints field types"] = function() expect(getaddrinfo("localhost", nil, { family=false, })).to_raise.any_of(typeerrors(3, "integer", "family", "boolean")) expect(getaddrinfo("localhost", nil, { family=M.AF_INET, socktype=false, })).to_raise.any_of(typeerrors(3, "integer", "socktype", "boolean")) expect(getaddrinfo("localhost", nil, { family=M.AF_INET, socktype=M.SOCK_DGRAM, protocol=false, })).to_raise.any_of(typeerrors(3, "integer", "protocol", "boolean")) expect(getaddrinfo("localhost", nil, { family=M.AF_INET, socktype=M.SOCK_DGRAM, protocol=M.IPPROTO_TCP, flags=false, })).to_raise.any_of(typeerrors(3, "integer", "flags", "boolean")) end } - describe connect: - before: connect, typeerrors = init(M, "connect") - context with bad arguments: | badargs.diagnose(connect, "(int, table)") examples { ["it diagnoses wrong family types"] = function() expect(connect(42, {family=false})). to_raise.any_of(typeerrors(2, "integer", "family", "boolean")) expect(connect(42, {family=-1})).to_raise.any_of { "bad argument #2 to 'connect' (unsupported family type -1)", "bad argument #2 to '?' (unsupported family type -1)", } end } examples { ["it diagnoses wrong AF_INET field types"] = function() expect(connect(42, {family=M.AF_INET, port=false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(connect(42, {family=M.AF_INET, port=9999, addr=false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET fields"] = function() expect(connect(42, { family=M.AF_INET, port=9999, addr="127.0.0.1", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_INET6 field types"] = function() expect(connect(42, {family = M.AF_INET6, port = false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(connect(42, {family = M.AF_INET6, port = 9999, addr = false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET6 fields"] = function() expect(connect(42, { family=M.AF_INET6, port=9999, addr="::", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_UNIX field types"] = function() expect(connect(42, {family = M.AF_UNIX, path = false})). to_raise.any_of(typeerrors(2, "string", "path", "boolean")) end } examples { ["it diagnoses invalid AF_UNIX fields"] = function() expect(connect(42, {family=M.AF_UNIX, path="/tmp/afunix", port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } if M.AF_NETLINK then examples { ["it diagnoses wrong AF_NETLINK field types"] = function() expect(connect(42, {family = M.AF_NETLINK, pid = false})). to_raise.any_of(typeerrors(2, "integer", "pid", "boolean")) expect(connect(42, {family = M.AF_NETLINK, pid = 9999, groups = false})). to_raise.any_of(typeerrors(2, "integer", "groups", "boolean")) end } examples { ["it diagnoses invalid AF_NETLINK fields"] = function() expect(connect(42, {family=M.AF_NETLINK, pid=9999, groups=9999, port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } end - describe bind: - before: bind, typeerrors = init(M, "bind") - context with bad arguments: | badargs.diagnose(bind, "(int, table)") examples { ["it diagnoses wrong family types"] = function() expect(bind(42, {family=false})). to_raise.any_of(typeerrors(2, "integer", "family", "boolean")) expect(bind(42, {family=-1})).to_raise.any_of { "bad argument #2 to '?' (unsupported family type -1)", "bad argument #2 to 'bind' (unsupported family type -1)", } end } examples { ["it diagnoses wrong AF_INET field types"] = function() expect(bind(42, {family=M.AF_INET, port=false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(bind(42, {family=M.AF_INET, port=9999, addr=false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET fields"] = function() expect(bind(42, { family=M.AF_INET, port=9999, addr="127.0.0.1", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_INET6 field types"] = function() expect(bind(42, {family = M.AF_INET6, port = false})). to_raise.any_of(typeerrors(2, "integer", "port", "boolean")) expect(bind(42, {family = M.AF_INET6, port = 9999, addr = false})). to_raise.any_of(typeerrors(2, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET6 fields"] = function() expect(bind(42, { family=M.AF_INET6, port=9999, addr="::", flags=false })).to_raise.any_of(typeerrors(2, nil, "flags")) end } examples { ["it diagnoses wrong AF_UNIX field types"] = function() expect(bind(42, {family = M.AF_UNIX, path = false})). to_raise.any_of(typeerrors(2, "string", "path", "boolean")) end } examples { ["it diagnoses invalid AF_UNIX fields"] = function() expect(bind(42, {family=M.AF_UNIX, path="/tmp/afunix", port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } if M.AF_NETLINK then examples { ["it diagnoses wrong AF_NETLINK field types"] = function() expect(bind(42, {family = M.AF_NETLINK, pid = false})). to_raise.any_of(typeerrors(2, "integer", "pid", "boolean")) expect(bind(42, {family = M.AF_NETLINK, pid = 9999, groups = false})). to_raise.any_of(typeerrors(2, "integer", "groups", "boolean")) end } examples { ["it diagnoses invalid AF_NETLINK fields"] = function() expect(bind(42, {family=M.AF_NETLINK, pid=9999, groups=9999, port=9999})). to_raise.any_of(typeerrors(2, nil, "port")) end } end - describe listen: - context with bad arguments: badargs.diagnose(M.listen, "(int, int)") - describe accept: - context with bad arguments: badargs.diagnose(M.accept, "(int)") - describe recv: - context with bad arguments: badargs.diagnose(M.recv, "(int, int)") - describe recvfrom: - context with bad arguments: badargs.diagnose(M.recvfrom, "(int, int)") - describe send: - context with bad arguments: badargs.diagnose(M.send, "(int, string)") - describe sendto: - before: sendto, typeerrors = init(M, "sendto") - context with bad arguments: | badargs.diagnose(sendto, "(int, string, table)") examples { ["it diagnoses wrong family types"] = function() expect(sendto(42, "msg", {family=false})). to_raise.any_of(typeerrors(3, "integer", "family", "boolean")) expect(sendto(42, "msg", {family=-1})).to_raise.any_of { "bad argument #3 to '?' (unsupported family type -1)", "bad argument #3 to 'sendto' (unsupported family type -1)", } end } examples { ["it diagnoses wrong AF_INET field types"] = function() expect(sendto(42, "msg", {family=M.AF_INET, port=false})). to_raise.any_of(typeerrors(3, "integer", "port", "boolean")) expect(sendto(42, "msg", {family=M.AF_INET, port=9999, addr=false})). to_raise.any_of(typeerrors(3, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET fields"] = function() expect(sendto(42, "msg", { family=M.AF_INET, port=9999, addr="127.0.0.1", flags=false })).to_raise.any_of(typeerrors(3, nil, "flags")) end } examples { ["it diagnoses wrong AF_INET6 field types"] = function() expect(sendto(42, "msg", {family = M.AF_INET6, port = false})). to_raise.any_of(typeerrors(3, "integer", "port", "boolean")) expect(sendto(42, "msg", {family = M.AF_INET6, port = 9999, addr = false})). to_raise.any_of(typeerrors(3, "string", "addr", "boolean")) end } examples { ["it diagnoses invalid AF_INET6 fields"] = function() expect(sendto(42, "msg", { family=M.AF_INET6, port=9999, addr="::", flags=false })).to_raise.any_of(typeerrors(3, nil, "flags")) end } examples { ["it diagnoses wrong AF_UNIX field types"] = function() expect(sendto(42, "msg", {family = M.AF_UNIX, path = false})). to_raise.any_of(typeerrors(3, "string", "path", "boolean")) end } examples { ["it diagnoses invalid AF_UNIX fields"] = function() expect(sendto(42, "msg", {family=M.AF_UNIX, path="/tmp/afunix", port=9999})). to_raise.any_of(typeerrors(3, nil, "port")) end } if M.AF_NETLINK then examples { ["it diagnoses wrong AF_NETLINK field types"] = function() expect(sendto(42, "msg", {family = M.AF_NETLINK, pid = false})). to_raise.any_of(typeerrors(3, "integer", "pid", "boolean")) expect(sendto(42, "msg", {family = M.AF_NETLINK, pid = 9999, groups = false})). to_raise.any_of(typeerrors(3, "integer", "groups", "boolean")) end } examples { ["it diagnoses invalid AF_NETLINK fields"] = function() expect(sendto(42, "msg", {family=M.AF_NETLINK, pid=9999, groups=9999, port=9999})). to_raise.any_of(typeerrors(3, nil, "port")) end } end - describe shutdown: - context with bad arguments: badargs.diagnose(M.shutdown, "(int, int)") - describe getsockname: - context with bad arguments: badargs.diagnose(M.getsockname, "(int)") - describe getpeername: - context with bad arguments: badargs.diagnose(M.getpeername, "(int)") - describe setsockopt: - before: setsockopt, typeerrors = init(M, "setsockopt") - context with bad arguments: - 'it diagnoses missing argument #1': expect(setsockopt()).to_raise.any_of(typeerrors(1, "int")) - 'it diagnoses argument #1 type not int': expect(setsockopt(false)).to_raise.any_of(typeerrors(1, "int", "boolean")) - 'it diagnoses missing argument #2': expect(setsockopt(1)).to_raise.any_of(typeerrors(2, "int")) - 'it diagnoses argument #2 type not int': expect(setsockopt(1, false)).to_raise.any_of(typeerrors(2, "int", "boolean")) - 'it diagnoses missing argument #3': expect(setsockopt(1, 2)).to_raise.any_of(typeerrors(3, "int")) - 'it diagnoses argument #3 type not int': expect(setsockopt(1, 2, false)).to_raise.any_of(typeerrors(3, "int", "boolean")) - 'it diagnoses missing argument #4': expect(setsockopt(1, M.SOL_SOCKET, M.SO_LINGER)). to_raise.any_of(typeerrors(4, "int")) - 'it diagnoses argument #4 type not int': expect(setsockopt(1, M.SOL_SOCKET, M.SO_LINGER, false)). to_raise.any_of(typeerrors(4, "int", "boolean")) - 'it diagnoses missing argument #5': expect(setsockopt(1, M.SOL_SOCKET, M.SO_LINGER, 4)). to_raise.any_of(typeerrors(5, "int")) - 'it diagnoses argument #5 type not int': expect(setsockopt(1, M.SOL_SOCKET, M.SO_LINGER, 4, false)). to_raise.any_of(typeerrors(5, "int", "boolean")) - it diagnoses too many arguments: expect(setsockopt(1, M.SOL_SOCKET, M.IPPROTO_TCP, 4, false)). to_raise.any_of(typeerrors(5)) expect(setsockopt(1, M.SOL_SOCKET, M.SO_LINGER, 4, 5, false)). to_raise.any_of(typeerrors(6)) - it communicates with IPV4 and IPV6 over loopback: | fd = M.socket(M.AF_INET6, M.SOCK_DGRAM, 0) expect(type(fd)).to_be "number" expect(fd >= 0).to_be(true) expect(setsockopt(fd, M.SOL_SOCKET, M.SO_RCVTIMEO, 1, 0)).to_be(0) expect(M.bind(fd, {family=M.AF_INET6, addr="::", port=9999})). to_be(0) pending "not portable" sockt = {family=M.AF_INET, addr="127.0.0.1", port=59999} expect({M.sendto(fd, "Test ipv4", sockt)}).to_equal.any_of { {9}, {nil, "sendto: Invalid argument", 22}, } pending "issue #92" data, so = M.recvfrom(fd, 1024) expect(data).to_be "Test ipv4" - describe getsockopt: - before: testsock = M.socket(M.AF_INET, M.SOCK_STREAM, 0) getsockopt, typeerrors = init(M, "getsockopt") - context with bad arguments: - 'it diagnoses missing argument #1': expect(getsockopt()).to_raise.any_of(typeerrors(1, "int")) - 'it diagnoses argument #1 type not int': expect(getsockopt(false)).to_raise.any_of(typeerrors(1, "int", "boolean")) - 'it diagnoses missing argument #2': expect(getsockopt(1)).to_raise.any_of(typeerrors(2, "int")) - 'it diagnoses argument #2 type not int': expect(getsockopt(1, false)).to_raise.any_of(typeerrors(2, "int", "boolean")) - 'it diagnoses missing argument #3': expect(getsockopt(1, 2)).to_raise.any_of(typeerrors(3, "int")) - 'it diagnoses argument #3 type not int': expect(getsockopt(1, 2, false)).to_raise.any_of(typeerrors(3, "int", "boolean")) - it diagnoses too many arguments: expect(getsockopt(1, M.SOL_SOCKET, M.IPPROTO_TCP, 4)). to_raise.any_of(typeerrors(4)) - it returns a timeval for SO_RCVTIMEO: expect(getmetatable(getsockopt(testsock, M.SOL_SOCKET, M.SO_RCVTIMEO))._type). to_be("PosixTimeval") - it returns a timeval for SO_SNDTIMEO: expect(getmetatable(getsockopt(testsock, M.SOL_SOCKET, M.SO_SNDTIMEO))._type). to_be("PosixTimeval") - it returns a linger struct for SO_LINGER: expect(getmetatable(getsockopt(testsock, M.SOL_SOCKET, M.SO_LINGER))._type). to_be("PosixLinger") - it returns a number for SO_ERROR: expect(type(getsockopt(testsock, M.SOL_SOCKET, M.SO_ERROR))). to_be("number") luaposix-36.3/spec/posix_sys_stat_spec.yaml000066400000000000000000000410061475444374100212520ustar00rootroot00000000000000before: this_module = 'posix.sys.stat' global_table = '_G' M = require(this_module) specify posix.sys.stat: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - before: posix = require 'posix' EPOCH = require 'posix.time'.time() RWXALL = bor(M.S_IRWXU, M.S_IRWXG, M.S_IRWXO) dir = posix.mkdtemp(template) posix.chown(dir, posix.geteuid(), posix.getegid()) posix.mkdir(dir .. "/subdir") posix.mkdir(dir .. "/subdir/deeper") posix.link("subdir", dir .. "/soft", true) touch(dir .. "/file") posix.link(dir .. "/file", dir .. "/hard") posix.link("no such destination", dir .. "/dangling", true) posix.mkfifo(dir .. "/fifo") - after: rmtmp(dir) - describe chmod: - before: chmod, lstat = M.chmod, M.lstat chmod(dir .. "/file", bor(M.S_IRWXU, M.S_IRGRP, M.S_IXGRP)) - context with bad arguments: | badargs.diagnose(chmod, "(string, int)") examples { ["it diagnoses non-existent files"] = function() expect(Emsg(chmod(dir .. "/not existing file", M.S_IRWXU))). to_contain "No such file or directory" end } - it sets file mode: mode = bor(M.S_IRUSR, M.S_IWUSR, M.S_IXGRP, M.S_IROTH) chmod(dir .. "/file", mode) expect(band(lstat(dir .. "/file").st_mode, RWXALL)).to_be(mode) - describe lstat: - before: getegid, geteuid = posix.getegid, posix.geteuid lstat = M.lstat - context with bad arguments: badargs.diagnose(lstat, "(string)") - it returns a PosixStat: expect(prototype(lstat(dir .. "/file"))).to_be "PosixStat" - it fetches the device id: dev = lstat(dir .. "/file").st_dev expect(type(dev)).to_be "number" expect(dev >= 0).to_be(true) expect(dev).to_be(lstat(dir).st_dev) - it fetches the file inode: ino = lstat(dir .. "/file").st_ino expect(type(ino)).to_be "number" expect(ino >= 0).to_be(true) expect(ino).to_be(lstat(dir .. "/hard").st_ino) expect(ino).not_to_be(lstat(dir .. "/soft").st_ino) - context with file mode: - it fetches the file access mode: mode = lstat(dir).st_mode expect(type(mode)).to_be "number" expect(band(mode, M.S_IRWXU)).to_be(M.S_IRWXU) - it recognises directories: expect(M.S_ISBLK(lstat(dir).st_mode)).to_be(0) expect(M.S_ISCHR(lstat(dir).st_mode)).to_be(0) expect(M.S_ISDIR(lstat(dir).st_mode)).not_to_be(0) expect(M.S_ISFIFO(lstat(dir).st_mode)).to_be(0) expect(M.S_ISREG(lstat(dir).st_mode)).to_be(0) expect(M.S_ISLNK(lstat(dir).st_mode)).to_be(0) expect(M.S_ISSOCK(lstat(dir).st_mode)).to_be(0) - it recognises fifos: expect(M.S_ISBLK(lstat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISCHR(lstat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISDIR(lstat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISFIFO(lstat(dir .. "/fifo").st_mode)).not_to_be(0) expect(M.S_ISREG(lstat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISLNK(lstat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISSOCK(lstat(dir .. "/fifo").st_mode)).to_be(0) - it recognises regular files: expect(M.S_ISBLK(lstat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISCHR(lstat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISDIR(lstat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISFIFO(lstat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISREG(lstat(dir .. "/file").st_mode)).not_to_be(0) expect(M.S_ISLNK(lstat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISSOCK(lstat(dir .. "/file").st_mode)).to_be(0) - it recognises soft links: expect(M.S_ISBLK(lstat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISCHR(lstat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISDIR(lstat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISFIFO(lstat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISREG(lstat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISLNK(lstat(dir .. "/soft").st_mode)).not_to_be(0) expect(M.S_ISSOCK(lstat(dir .. "/soft").st_mode)).to_be(0) - it fetches the number of links: expect(lstat(dir .. "/file").st_nlink).to_be(2) expect(lstat(dir .. "/soft").st_nlink).to_be(1) expect(lstat(dir .. "/hard").st_nlink). to_be(lstat(dir .. "/file").st_nlink) expect(lstat(dir .. "/subdir").st_nlink).to_be(3) - it fetches the owner id: expect(lstat(dir .. "/file").st_uid).to_be(geteuid()) expect(lstat(dir .. "/subdir").st_uid).to_be(geteuid()) - it fetches the owner group id: expect(lstat(dir .. "/file").st_gid).to_be(getegid()) expect(lstat(dir .. "/subdir").st_gid).to_be(getegid()) - it fetches the device special file id: pending "mknod not yet bound" - it fetches the file size: # skip directory size, which is system dependent expect(lstat(dir .. "/file").st_size).to_be(0) expect(lstat(dir .. "/soft").st_size).to_be(string.len("subdir")) expect(lstat(dir .. "/hard").st_size). to_be(lstat(dir .. "/file").st_size) - it fetches the file access time: expect(lstat(dir .. "/file").st_atime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file modification time: expect(lstat(dir .. "/file").st_mtime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file change time: expect(lstat(dir .. "/file").st_ctime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the device block size: blksize = lstat(dir .. "/file").st_blksize expect(type(blksize)).to_be "number" expect(blksize > 0).to_be(true) expect(blksize).to_be(lstat(dir .. "/hard").st_blksize) - it fetches the number of blocks: blocks = lstat(dir .. "/file").st_blocks expect(type(blocks)).to_be "number" expect(blocks >= 0).to_be(true) expect(blocks).to_be(lstat(dir .. "/hard").st_blocks) - describe fstat: - before: fc = require "posix.fcntl" fd_dir = fc.open(dir, fc.O_RDONLY) fd_file = fc.open(dir .. "/file", fc.O_RDONLY) fd_hard = fc.open(dir .. "/hard", fc.O_RDONLY) fd_fifo = fc.open(dir .. "/fifo", bor(fc.O_RDONLY, fc.O_NONBLOCK)) fd_subdir = fc.open(dir .. "/subdir", fc.O_RDONLY) getegid, geteuid = posix.getegid, posix.geteuid fstat = M.fstat - context with bad arguments: badargs.diagnose(fstat, "(int)") - it returns a PosixStat: expect(prototype(fstat(fd_file))).to_be "PosixStat" - it fetches the device id: dev = fstat(fd_file).st_dev expect(type(dev)).to_be "number" expect(dev >= 0).to_be(true) expect(dev).to_be(fstat(fd_dir).st_dev) - it fetches the file inode: ino = fstat(fd_file).st_ino expect(type(ino)).to_be "number" expect(ino >= 0).to_be(true) expect(ino).to_be(fstat(fd_hard).st_ino) - context with file mode: - it fetches the file access mode: mode = fstat(fd_dir).st_mode expect(type(mode)).to_be "number" expect(band(mode, M.S_IRWXU)).to_be(M.S_IRWXU) - it recognises directories: expect(M.S_ISBLK(fstat(fd_dir).st_mode)).to_be(0) expect(M.S_ISCHR(fstat(fd_dir).st_mode)).to_be(0) expect(M.S_ISDIR(fstat(fd_dir).st_mode)).not_to_be(0) expect(M.S_ISFIFO(fstat(fd_dir).st_mode)).to_be(0) expect(M.S_ISREG(fstat(fd_dir).st_mode)).to_be(0) expect(M.S_ISLNK(fstat(fd_dir).st_mode)).to_be(0) expect(M.S_ISSOCK(fstat(fd_dir).st_mode)).to_be(0) - it recognises fifos: expect(M.S_ISBLK(fstat(fd_fifo).st_mode)).to_be(0) expect(M.S_ISCHR(fstat(fd_fifo).st_mode)).to_be(0) expect(M.S_ISDIR(fstat(fd_fifo).st_mode)).to_be(0) expect(M.S_ISFIFO(fstat(fd_fifo).st_mode)).not_to_be(0) expect(M.S_ISREG(fstat(fd_fifo).st_mode)).to_be(0) expect(M.S_ISLNK(fstat(fd_fifo).st_mode)).to_be(0) expect(M.S_ISSOCK(fstat(fd_fifo).st_mode)).to_be(0) - it recognises regular files: expect(M.S_ISBLK(fstat(fd_file).st_mode)).to_be(0) expect(M.S_ISCHR(fstat(fd_file).st_mode)).to_be(0) expect(M.S_ISDIR(fstat(fd_file).st_mode)).to_be(0) expect(M.S_ISFIFO(fstat(fd_file).st_mode)).to_be(0) expect(M.S_ISREG(fstat(fd_file).st_mode)).not_to_be(0) expect(M.S_ISLNK(fstat(fd_file).st_mode)).to_be(0) expect(M.S_ISSOCK(fstat(fd_file).st_mode)).to_be(0) - it fetches the number of links: expect(fstat(fd_file).st_nlink).to_be(2) expect(fstat(fd_hard).st_nlink). to_be(fstat(fd_file).st_nlink) expect(fstat(fd_subdir).st_nlink).to_be(3) - it fetches the owner id: expect(fstat(fd_file).st_uid).to_be(geteuid()) expect(fstat(fd_subdir).st_uid).to_be(geteuid()) - it fetches the owner group id: expect(fstat(fd_file).st_gid).to_be(getegid()) expect(fstat(fd_subdir).st_gid).to_be(getegid()) - it fetches the device special file id: pending "mknod not yet bound" - it fetches the file size: # skip directory size, which is system dependent expect(fstat(fd_file).st_size).to_be(0) expect(fstat(fd_hard).st_size).to_be(fstat(fd_file).st_size) - it fetches the file access time: expect(fstat(fd_file).st_atime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file modification time: expect(fstat(fd_file).st_mtime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file change time: expect(fstat(fd_file).st_ctime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the device block size: blksize = fstat(fd_file).st_blksize expect(type(blksize)).to_be "number" expect(blksize > 0).to_be(true) expect(blksize).to_be(fstat(fd_hard).st_blksize) - it fetches the number of blocks: blocks = fstat(fd_file).st_blocks expect(type(blocks)).to_be "number" expect(blocks >= 0).to_be(true) expect(blocks).to_be(fstat(fd_hard).st_blocks) - describe mkdir: - before: dir = posix.mkdtemp(template) lstat, mkdir = M.lstat, M.mkdir - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(mkdir, "(string, ?int)") - it creates the named directory: expect(Emsg(mkdir(dir .. "/subdir"))).not_to_contain "exists" mode = lstat(dir .. "/subdir").st_mode expect(M.S_ISDIR(mode)).not_to_be(0) - it sets the new directory permissions: mkdir(dir .. "/subdir", M.S_IRWXU) mode = lstat(dir .. "/subdir").st_mode expect(band(mode, RWXALL)).to_be(M.S_IRWXU) - it diagnoses already existing directory: expect(Emsg(mkdir(dir, RWXALL))).to_contain "exists" - describe mkfifo: - before: dir = posix.mkdtemp(template) lstat, mkfifo = M.lstat, M.mkfifo - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(mkfifo, "(string, ?int)") - it creates the named fifo: expect(Emsg(mkfifo(dir .. "/fifo"))).not_to_contain "exists" mode = lstat(dir .. "/fifo").st_mode expect(M.S_ISFIFO(mode)).not_to_be(0) - it sets the new fifo permissions: mkfifo(dir .. "/fifo", M.S_IRWXU) mode = lstat(dir .. "/fifo").st_mode expect(band(mode, RWXALL)).to_be(M.S_IRWXU) - it diagnoses already existing fifo: expect(Emsg(mkfifo(dir, RWXALL))).to_contain "exists" - describe stat: - before: getegid, geteuid = posix.getegid, posix.geteuid stat = M.stat - context with bad arguments: badargs.diagnose(stat, "(string)") - it returns a PosixStat: expect(prototype(stat(dir .. "/file"))).to_be "PosixStat" - it fetches the device id: dev = stat(dir .. "/file").st_dev expect(type(dev)).to_be "number" expect(dev >= 0).to_be(true) expect(dev).to_be(stat(dir).st_dev) - it fetches the file inode: ino = stat(dir .. "/file").st_ino expect(type(ino)).to_be "number" expect(ino >= 0).to_be(true) expect(ino).to_be(stat(dir .. "/hard").st_ino) expect(ino).not_to_be(stat(dir .. "/soft").st_ino) - context with file mode: - it fetches the file access mode: mode = stat(dir).st_mode expect(type(mode)).to_be "number" expect(band(mode, M.S_IRWXU)).to_be(M.S_IRWXU) - it recognises directories: expect(M.S_ISBLK(stat(dir).st_mode)).to_be(0) expect(M.S_ISCHR(stat(dir).st_mode)).to_be(0) expect(M.S_ISDIR(stat(dir).st_mode)).not_to_be(0) expect(M.S_ISFIFO(stat(dir).st_mode)).to_be(0) expect(M.S_ISREG(stat(dir).st_mode)).to_be(0) expect(M.S_ISLNK(stat(dir).st_mode)).to_be(0) expect(M.S_ISSOCK(stat(dir).st_mode)).to_be(0) - it recognises fifos: expect(M.S_ISBLK(stat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISCHR(stat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISDIR(stat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISFIFO(stat(dir .. "/fifo").st_mode)).not_to_be(0) expect(M.S_ISREG(stat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISLNK(stat(dir .. "/fifo").st_mode)).to_be(0) expect(M.S_ISSOCK(stat(dir .. "/fifo").st_mode)).to_be(0) - it recognises regular files: expect(M.S_ISBLK(stat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISCHR(stat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISDIR(stat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISFIFO(stat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISREG(stat(dir .. "/file").st_mode)).not_to_be(0) expect(M.S_ISLNK(stat(dir .. "/file").st_mode)).to_be(0) expect(M.S_ISSOCK(stat(dir .. "/file").st_mode)).to_be(0) - it recognises soft links: expect(M.S_ISBLK(stat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISCHR(stat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISDIR(stat(dir .. "/soft").st_mode)).not_to_be(0) expect(M.S_ISFIFO(stat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISREG(stat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISLNK(stat(dir .. "/soft").st_mode)).to_be(0) expect(M.S_ISSOCK(stat(dir .. "/soft").st_mode)).to_be(0) - it fetches the number of links: expect(stat(dir .. "/file").st_nlink).to_be(2) expect(stat(dir .. "/soft").st_nlink). to_be(stat(dir .. "/subdir").st_nlink) expect(stat(dir .. "/hard").st_nlink). to_be(stat(dir .. "/file").st_nlink) expect(stat(dir .. "/subdir").st_nlink).to_be(3) - it fetches the owner id: expect(stat(dir .. "/file").st_uid).to_be(geteuid()) expect(stat(dir .. "/subdir").st_uid).to_be(geteuid()) - it fetches the owner group id: expect(stat(dir .. "/file").st_gid).to_be(getegid()) expect(stat(dir .. "/subdir").st_gid).to_be(getegid()) - it fetches the device special file id: pending "mknod not yet bound" - it fetches the file size: # skip directory size, which is system dependent expect(stat(dir .. "/file").st_size).to_be(0) expect(stat(dir .. "/soft").st_size).not_to_be(string.len("subdir")) expect(stat(dir .. "/hard").st_size). to_be(stat(dir .. "/file").st_size) - it fetches the file access time: expect(stat(dir .. "/file").st_atime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file modification time: expect(stat(dir .. "/file").st_mtime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the file change time: expect(stat(dir .. "/file").st_ctime). to_be_within_n_of {value=EPOCH, delta=1} - it fetches the device block size: blksize = stat(dir .. "/file").st_blksize expect(type(blksize)).to_be "number" expect(blksize > 0).to_be(true) expect(blksize).to_be(stat(dir .. "/hard").st_blksize) - it fetches the number of blocks: blocks = stat(dir .. "/file").st_blocks expect(type(blocks)).to_be "number" expect(blocks >= 0).to_be(true) expect(blocks).to_be(stat(dir .. "/hard").st_blocks) - describe umask: - before: lstat, umask = M.lstat, M.umask newmask = band(M.S_IWGRP, M.S_IRWXO) origmask = umask(newmask) - after: umask(origmask) - context with bad arguments: badargs.diagnose(umask, "(int)") - it returns current umask: expect(umask(0)).to_be(newmask) expect(umask(newmask)).to_be(0) - it controls the mode of newly created files: all = bor(M.S_IRWXU, M.S_IRWXG, M.S_IRWXO) xxx, mask = dir .. "/xxx", bor(M.S_IRWXO, M.S_IWGRP, M.S_IXGRP) umask(mask) touch(xxx) expect(band(lstat(xxx).st_mode, all)).to_be(bor(M.S_IRUSR, M.S_IWUSR, M.S_IRGRP)) os.remove(xxx) luaposix-36.3/spec/posix_sys_statvfs_spec.yaml000066400000000000000000000023521475444374100217720ustar00rootroot00000000000000before: this_module = 'posix.sys.statvfs' global_table = '_G' M = require(this_module) specify posix.sys.statvfs: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe statvfs: - before: statvfs = M.statvfs - context with bad arguments: if statvfs then badargs.diagnose(statvfs, "(string)") end - it returns a PosixStatvfs: if statvfs then expect(prototype(statvfs("/"))).to_be "PosixStatvfs" end - it fetches statistics for a mounted file system: if statvfs then sv = statvfs "/" expect(type(sv)).to_be "table" for _, field in pairs {"f_bsize", "f_frsize", "f_blocks", "f_bfree", "f_bavail", "f_files", "f_ffree", "f_favail", "f_flag", "f_namemax"} do expect(type(sv[field])).to_be "number" expect(sv[field] >= 0).to_be(true) end end - it returns a non-negative value from fsid: | -- Merge this back into the previous example when #102 is fixed if statvfs then sv = statvfs "/" pending "issue #102" expect(sv[field] >= 0).to_be(true) end luaposix-36.3/spec/posix_sys_time_spec.yaml000066400000000000000000000014161475444374100212360ustar00rootroot00000000000000before: this_module = 'posix.sys.time' global_table = '_G' M = require(this_module) specify posix.sys.time: - before: EPOCH = require 'posix.time'.time() - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe gettimeofday: - before: gettimeofday = M.gettimeofday - context with bad arguments: badargs.diagnose(gettimeofday, "()") - it returns a PosixTimeval: expect(prototype(gettimeofday())).to_be "PosixTimeval" - it fetches the current epoch time: tv = gettimeofday() expect(tv.tv_sec).to_be_within_n_of {value=EPOCH, delta=1} expect(type(tv.tv_usec)).to_be "number" expect(tv.tv_usec >= 0).to_be(true) luaposix-36.3/spec/posix_sys_times_spec.yaml000066400000000000000000000020401475444374100214130ustar00rootroot00000000000000before: this_module = 'posix.sys.times' global_table = '_G' M = require(this_module) specify posix.sys.times: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe times: - before: table.unpack = table.unpack or unpack times = M.times # posix.times takes an optional string or table as its first # argument, followed by zero or more strings only if the first # argument was a string; since we can't express that with # `badargs.diagnose` do it all manually again... - context with bad arguments: badargs.diagnose(times, "()") - it returns a PosixTms: expect(prototype(times())).to_be "PosixTms" - it fetches everything without an argument: keys = { "tms_utime", "tms_stime", "tms_cutime", "tms_cstime", "elapsed" } t = times() expect(t).to_contain.a_permutation_of(keys) for _, key in ipairs(keys) do expect(type(t[key])).to_be "number" end luaposix-36.3/spec/posix_sys_utsname_spec.yaml000066400000000000000000000016361475444374100217600ustar00rootroot00000000000000before: this_module = 'posix.sys.utsname' global_table = '_G' M = require(this_module) specify posix.sys.utsname: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe uname: - before: uname = M.uname u = uname() - context with bad arguments: badargs.diagnose(uname, "()") - it returns a PosixUtsname: expect(prototype(u)).to_be "PosixUtsname" - it returns machine name: expect(u.machine).to_be(cmd_output "uname -m") - it returns nodename: expect(u.nodename).to_be(cmd_output "uname -n") - it returns operating system release: expect(u.release).to_be(cmd_output "uname -r") - it returns system name: expect(u.sysname).to_be(cmd_output "uname -s") - it returns operating system version: expect(u.version).to_be(cmd_output "uname -v") luaposix-36.3/spec/posix_syslog_spec.yaml000066400000000000000000000017111475444374100207200ustar00rootroot00000000000000before: this_module = 'posix.syslog' global_table = '_G' M = require(this_module) specify posix.syslog: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - describe LOG_MASK: - context with bad arguments: if M.LOG_MASK then badargs.diagnose(M.LOG_MASK, "(int)") end - describe closelog: - context with bad arguments: if M.closelog then badargs.diagnose(M.closelog, "()") end - describe openlog: - context with bad arguments: | if M.openlog then badargs.diagnose(M.openlog, "(string, ?int, ?int)") end - describe setlogmask: - context with bad arguments: if M.setlogmask then badargs.diagnose(M.setlogmask, "(?int)") end - describe syslog: - context with bad arguments: if M.syslog then badargs.diagnose(M.syslog, "(int, string)") end luaposix-36.3/spec/posix_time_spec.yaml000066400000000000000000000163261475444374100203460ustar00rootroot00000000000000before: this_module = 'posix.time' global_table = '_G' M = require(this_module) specify posix.time: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - before: EPOCH = M.time() - describe clock_getres: - before: clock_getres = M.clock_getres - context with bad arguments: if clock_getres then badargs.diagnose(clock_getres, "(int)") end - it returns a PosixTimespec: if clock_getres then expect(prototype(clock_getres(M.CLOCK_REALTIME))). to_be "PosixTimespec" end - describe clock_gettime: - before: clock_gettime = M.clock_gettime - context with bad arguments: if clock_gettime then badargs.diagnose(clock_gettime, "(int)") end - it returns a PosixTimespec: if clock_getres then expect(prototype(clock_gettime(M.CLOCK_REALTIME))). to_be "PosixTimespec" end - describe gmtime: - before: gmtime = M.gmtime - context with bad arguments: badargs.diagnose(gmtime, "(int)") - it returns a PosixTm: expect(prototype(gmtime(EPOCH))).to_be "PosixTm" - it fetches broken-down time values: t = gmtime(EPOCH) fields = {"tm_sec", "tm_min", "tm_hour", "tm_mday", "tm_mon", "tm_year", "tm_wday", "tm_yday", "tm_isdst"} if t.tm_gmtoff ~= nil then fields[1+#fields] = "tm_gmtoff" end if t.tm_zone ~= nil then fields[1+#fields] = "tm_zone" end expect(t).to_contain.a_permutation_of(fields) for _, field in pairs(fields) do if field == "tm_zone" then expect(type(t[field])).to_be "string" else expect(type(t[field])).to_be "number" if field ~= "tm_gmtoff" then expect(t[field] >= 0).to_be(true) else expect(t[field] == 0).to_be(true) end end end - it returns a month in the range 0-11: # A recent December afternoon in epoch seconds... expect(gmtime(1418734089).tm_mon).to_be(11) t = gmtime(EPOCH) expect(t.tm_mon >= 0 and t.tm_mon < 12).to_be(true) - it returns years since 1900: expect(gmtime(EPOCH).tm_year < 1900).to_be(true) - it does not wrap around after 2^31 seconds: expect(gmtime(2147483647).tm_year).to_be(gmtime(2147483648).tm_year) - describe localtime: - before: localtime = M.localtime - context with bad arguments: badargs.diagnose(localtime, "(int)") - it returns a PosixTm: expect(prototype(localtime(EPOCH))).to_be "PosixTm" - it fetches broken-down time values: t = localtime(EPOCH) fields = {"tm_sec", "tm_min", "tm_hour", "tm_mday", "tm_mon", "tm_year", "tm_wday", "tm_yday", "tm_isdst"} if t.tm_gmtoff ~= nil then fields[1+#fields] = "tm_gmtoff" end if t.tm_zone ~= nil then fields[1+#fields] = "tm_zone" end expect(t).to_contain.a_permutation_of(fields) for _, field in pairs(fields) do if field == "tm_zone" then expect(type(t[field])).to_be "string" else expect(type(t[field])).to_be "number" if field ~= "tm_gmtoff" then expect(t[field] >= 0).to_be(true) end end end - it returns a month in the range 0-11: # A recent December afternoon in epoch seconds... expect(localtime(1418734089).tm_mon).to_be(11) t = localtime(EPOCH) expect(t.tm_mon >= 0 and t.tm_mon < 12).to_be(true) - it returns years since 1900: expect(localtime(EPOCH).tm_year < 1900).to_be(true) - it does not wrap around after 2^31 seconds: expect(localtime(2147483647).tm_year).to_be(localtime(2147483648).tm_year) - describe mktime: - before: mktime = M.mktime t = M.localtime(EPOCH) - context with bad arguments: badargs.diagnose(mktime, "(table)") - it returns an epoch time: expect(prototype(mktime(t))).to_be "number" - it is the inverse of localtime: expect(mktime(t)).to_be(EPOCH) - describe nanosleep: - before: nanosleep, typeerrors = init(M, "nanosleep") - context with bad arguments: | badargs.diagnose(nanosleep, "(table)") examples { ["context diagnosing timespec table fields"] = { { ["it diagnoses argument #1 tv_sec field type not integer"] = function() expect(nanosleep {tv_sec = false}). to_raise.any_of(typeerrors(1, "integer", "tv_sec", "boolean")) end }, { ["it diagnoses argument #1 tv_nsec field type not integer"] = function() expect(nanosleep {tv_sec = -1, tv_nsec = false}). to_raise.any_of(typeerrors(1, "integer", "tv_nsec", "boolean")) end }, { ["it diagnoses argument #1 spurious fields"] = function() expect(nanosleep {tv_sec = -1, tv_nsec = -1, bogus = false}). to_raise.any_of(typeerrors(1, nil, "bogus")) end }, } } - it returns an integer: expect(nanosleep {tv_sec = 0, tv_nsec = 10}).to_be(0) - describe strftime: - before: strftime = M.strftime t = { tm_isdst=0, tm_wday=1, tm_sec=2, tm_min=3, tm_hour=4, tm_mday=5, tm_mon=6, tm_year=7, tm_yday=8, tm_gmtoff=-32400, tm_zone="AKST" } - context with bad arguments: badargs.diagnose(strftime, "(string, table)") - context with place-holders: - it plugs tm_wday: expect(strftime("%w", t)).to_be "1" - it plugs tm_sec: expect(strftime("%S", t)).to_be "02" - it plugs tm_min: expect(strftime("%M", t)).to_be "03" - it plugs tm_hour: expect(strftime("%H", t)).to_be "04" - it plugs tm_mday: expect(strftime("%d", t)).to_be "05" - it plugs tm_mon: expect(strftime("%m", t)).to_be "07" - it plugs tm_year: expect(strftime("%y", t)).to_be "07" - it plugs tm_yday: expect(strftime("%j", t)).to_be "009" - it plugs timezone: expect(strftime("%Z", t)).to_be "AKST" - describe strptime: - before: strptime = M.strptime - context with bad arguments: badargs.diagnose(strptime, "(string, string)") - context with place-holders: - before: t, i = strptime("Mon Jun 4 03:02:01 BST 1906 garbage", "%a %b %d %H:%M:%S BST %Y") - it returns the first unconsumed character: expect(i).to_be(29) # tm_yday and tm_isdst are not set by strptime - it scans into tm_wday: expect(t.tm_wday).to_be(1) - it scans into tm_sec: expect(t.tm_sec).to_be(1) - it scans into tm_min: expect(t.tm_min).to_be(2) - it scans into tm_hour: expect(t.tm_hour).to_be(3) - it scans into tm_mday: expect(t.tm_mday).to_be(4) - it scans into tm_mon: expect(t.tm_mon).to_be(5) - it scans into tm_year: expect(t.tm_year).to_be(6) - describe time: - before: time = M.time - context with bad arguments: badargs.diagnose(time, "()") - it returns epoch seconds: expect(type(time())).to_be "number" expect(time() > 0).to_be(true) luaposix-36.3/spec/posix_unistd_spec.yaml000066400000000000000000000325401475444374100207120ustar00rootroot00000000000000before: this_module = 'posix.unistd' global_table = '_G' M = require(this_module) specify posix.unistd: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - before: | fcntl = require "posix.fcntl" pwd = require "posix.pwd" -- Assume $USER is the process owner, egid is gid and euid is uid ids = pwd.getpwnam(os.getenv "USER") - describe alarm: - before: alarm = M.alarm - it returns zero when passed zero: | zero = alarm(0) expect(zero).to_be(0) - it can set and reset an alarm: | zero = alarm(10) ten = alarm(0) expect(ten>0).to_be(true) - describe chown: - context with bad arguments: badargs.diagnose(M.chown, "(string, ?int|string, ?int|string)") - describe exec: - context with bad arguments: badargs.diagnose(M.exec, "(string, table)") - describe execp: - before: | execp = M.execp P_CHILD = 0 -- redirect output to /dev/null function child(...) quietly = fcntl.open("/dev/null", bor(fcntl.O_WRONLY, fcntl.O_APPEND)) M.dup2(quietly, 1) execp(...) expect("not reached").to_be(true) end - context with bad arguments: badargs.diagnose(execp, "(string, table)") - it overwrites the running process with a shell invocation: process = M.fork() if process == P_CHILD then child("date", {"+[%c]"}) else p, msg, ret = require 'posix.sys.wait'.wait(process) expect(table.concat {msg, " ", tostring(ret)}).to_be "exited 0" end - "it sets argv[0]": - describe ftruncate: - before: | ftruncate = M.ftruncate function echo(fname, s) local fh = io.open(fname, 'w') fh:write(s .. '\n') fh:close() return #s + 1 end function flen(fname) local fh = io.open(fname, 'r') local r = fh:read '*a' fh:close() return #r end - context with bad arguments: badargs.diagnose(ftruncate, "(int, int)") - it truncates an open file descriptor: fname = os.tmpname() len = echo(fname, 'line 1') echo(fname, 'line 2') fd = fcntl.open(fname, bor(fcntl.O_CREAT, fcntl.O_WRONLY)) expect(ftruncate(fd, len)).not_to_be(nil) M.close(fd) expect(flen(fname)).to_be(len) os.remove(fname) - describe getegid: - before: getegid = M.getegid - context with bad arguments: badargs.diagnose(getegid, "()") - it returns the effective group id: expect(getegid()).to_be(ids.pw_gid) - describe geteuid: - before: geteuid = M.geteuid - context with bad arguments: badargs.diagnose(geteuid, "()") - it returns the effective user id: expect(geteuid()).to_be(ids.pw_uid) - describe getgid: - before: getgid = M.getgid - context with bad arguments: badargs.diagnose(getgid, "()") - it returns the group id: expect(getgid()).to_be(ids.pw_gid) - describe gethostid: - before: gethostid = M.gethostid - context with bad arguments: badargs.diagnose(gethostid, "()") - it returns an integer: expect(math.floor(gethostid())).to_be(gethostid()) - describe getuid: - before: getuid = M.getuid - context with bad arguments: badargs.diagnose(getuid, "()") - it returns the user id: expect(getuid()).to_be(ids.pw_uid) - describe getpgrp: - before: getpgrp = M.getpgrp - context with bad arguments: badargs.diagnose(getpgrp, "()") - it returns a positive integer: expect(math.floor(getpgrp())).to_be(getpgrp()) expect(getpgrp() > 0).to_be(true) - describe getpid: - before: getpid = M.getpid - context with bad arguments: badargs.diagnose(getpid, "()") - it returns the a positive integer: expect(math.floor(getpid())).to_be(getpid()) expect(getpid() > 0).to_be(true) - describe getppid: - before: getppid = M.getppid - context with bad arguments: badargs.diagnose(getppid, "()") - it returns a positive integer: expect(math.floor(getppid())).to_be(getppid()) expect(getppid() > 0).to_be(true) - it does not return the process id: expect(getppid()).not_to_be(M.getpid()) - describe lchown: - context with bad arguments: badargs.diagnose(M.lchown, "(string, ?int|string, ?int|string)") - describe link: - before: link = M.link st = require "posix.sys.stat" lstat = st.lstat S_ISREG, S_ISLNK = st.S_ISREG, st.S_ISLNK dir = posix.mkdtemp(template) touch(dir .. "/file") - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(link, "(string, string, ?boolean)") - it creates hard link without optional param: st_before = lstat(dir .. "/file") link(dir .. "/file", dir .. "/hard") st_after = lstat(dir .. "/file") st_link = lstat(dir .. "/hard") expect(st_before.st_nlink + 1).to_be(st_after.st_nlink) expect(st_after.st_nlink).to_be(st_link.st_nlink) expect(S_ISREG(st_link.st_mode)).not_to_be(0) expect(S_ISLNK(st_link.st_mode)).to_be(0) - it creates hard link with optional param: st_before = lstat(dir .. "/file") link(dir .. "/file", dir .. "/hard", false) st_after = lstat(dir .. "/file") st_link = lstat(dir .. "/hard") expect(st_before.st_nlink + 1).to_be(st_after.st_nlink) expect(st_after.st_nlink).to_be(st_link.st_nlink) expect(S_ISREG(st_link.st_mode)).not_to_be(0) expect(S_ISLNK(st_link.st_mode)).to_be(0) - it creates soft link: st_before = lstat(dir .. "/file") link(dir .. "/file", dir .. "/soft", true) st_after = lstat(dir .. "/file") st_link = lstat(dir .. "/soft") expect(st_before.st_nlink).to_be(st_after.st_nlink) expect(S_ISREG(st_link.st_mode)).to_be(0) expect(S_ISLNK(st_link.st_mode)).not_to_be(0) - describe linkat: - before: linkat = M.linkat link = M.link st = require "posix.sys.stat" lstat = st.lstat S_ISREG, S_ISLNK = st.S_ISREG, st.S_ISLNK AT_FDCWD, AT_SYMLINK_FOLLOW = fcntl.AT_FDCWD, fcntl.AT_SYMLINK_FOLLOW dir = posix.mkdtemp(template) touch(dir .. "/file") dirfd = fcntl.open(dir, fcntl.O_RDONLY) - after: M.close(dirfd) rmtmp(dir) - context with bad arguments: badargs.diagnose(linkat, "(int, string, int, string, int)") - it creates hard link using AT_FDCWD: st_before = lstat(dir .. "/file") linkat(AT_FDCWD, dir .. "/file", AT_FDCWD, dir .. "/hard", 0) st_after = lstat(dir .. "/file") st_link = lstat(dir .. "/hard") expect(st_before.st_nlink + 1).to_be(st_after.st_nlink) expect(st_after.st_nlink).to_be(st_link.st_nlink) expect(S_ISREG(st_link.st_mode)).not_to_be(0) - it creates hard link in directory specified by fd: st_before = lstat(dir .. "/file") linkat(dirfd, "file", dirfd, "hard", 0) st_after = lstat(dir .. "/file") st_link = lstat(dir .. "/hard") expect(st_before.st_nlink + 1).to_be(st_after.st_nlink) expect(st_after.st_nlink).to_be(st_link.st_nlink) expect(S_ISREG(st_link.st_mode)).not_to_be(0) - it creates hard link to file symbolic link: # linkat without AT_SYMLINK_FOLLOW returns ENOTSUPP on some filesystems link(dir .. "/file", dir .. "/soft", true) st_before = lstat(dir .. "/file") if linkat(dirfd, "soft", dirfd, "hard", 0) == 0 then st_after = lstat(dir .. "/file") st_hard = lstat(dir .. "/hard") st_soft = lstat(dir .. "/soft") expect(st_before.st_nlink).to_be(st_after.st_nlink) expect(st_soft.st_nlink).to_be(st_hard.st_nlink) expect(S_ISREG(st_hard.st_mode)).to_be(0) expect(S_ISLNK(st_hard.st_mode)).not_to_be(0) end - it creates hard link to file referenced by symbolic link: link(dir .. "/file", dir .. "/soft", true) st_before = lstat(dir .. "/file") linkat(dirfd, "soft", dirfd, "hard", AT_SYMLINK_FOLLOW) st_after = lstat(dir .. "/file") st_hard = lstat(dir .. "/hard") st_soft = lstat(dir .. "/soft") expect(st_before.st_nlink + 1).to_be(st_after.st_nlink) expect(st_after.st_nlink).to_be(st_hard.st_nlink) expect(S_ISREG(st_hard.st_mode)).not_to_be(0) expect(S_ISLNK(st_hard.st_mode)).to_be(0) - describe pathconf: - before: pathconf = M.pathconf - context with bad arguments: badargs.diagnose(pathconf, "(string, int)") - it returns whether chown can be used on the given file: expect(type(pathconf(".", M._PC_CHOWN_RESTRICTED))).to_be "number" - it fetches the maximum number of links to the given file: expect(type(pathconf(".", M._PC_LINK_MAX))).to_be "number" - it fetches the maximum formatted line input length for a tty: expect(type(pathconf(".", M._PC_MAX_CANON))).to_be "number" - it fetches the maximum raw line input length for a tty: expect(type(pathconf(".", M._PC_MAX_INPUT))).to_be "number" - it fetches the maximum filename length in this directory: expect(type(pathconf(".", M._PC_NAME_MAX))).to_be "number" - it fetches whether accessing overlong filenames is an error: expect(type(pathconf(".", M._PC_NO_TRUNC))).to_be "number" - it fetches the maximum relative path length from this directory: expect(type(pathconf(".", M._PC_PATH_MAX))).to_be "number" - it fetches the size of the pipe buffer: expect(type(pathconf(".", M._PC_PIPE_BUF))).to_be "number" - it fetches whether special character processing can be disabled: expect(type(pathconf(".", M._PC_VDISABLE))).to_be "number" - describe readlink: - before: link, readlink = M.link, M.readlink dir = posix.mkdtemp(template) touch(dir .. "/file") link(dir .. "/file", dir .. "/soft", true) - after: rmtmp(dir) - context with bad arguments: badargs.diagnose(readlink, "(string)") - it diagnoses non-symlink path: | EINVAL = require "posix.errno".EINVAL expect({readlink(".")}).to_equal {nil, ".: not a symbolic link", EINVAL} - it returns the destination path of a symlink: expect(readlink(dir .. "/soft")).to_be(dir .. "/file") - it works on Linux /proc links: proclink = "/proc/self/fd/0" lstat = require "posix.sys.stat".lstat S_ISLNK = require "posix.sys.stat".S_ISLNK st_mode = (lstat(proclink) or {}).st_mode if st_mode and S_ISLNK(st_mode) then expect(readlink(proclink)).not_to_be(nil) end - describe sysconf: - before: sysconf = M.sysconf - context with bad arguments: badargs.diagnose(sysconf, "(int)") - it fetches the maximum number of exec arguments: expect(type(sysconf(M._SC_ARG_MAX))).to_be "number" - it fetches the number processes per user: expect(type(sysconf(M._SC_CHILD_MAX))).to_be "number" - it fetches the number of clock ticks per second: expect(type(sysconf(M._SC_CLK_TCK))).to_be "number" - it fetches the job control version: expect(type(sysconf(M._SC_JOB_CONTROL))).to_be "number" - it fetches the maximum number of groups: expect(type(sysconf(M._SC_NGROUPS_MAX))).to_be "number" - it fetches the maximum number of open descriptors: expect(type(sysconf(M._SC_OPEN_MAX))).to_be "number" - it fetches the size of memory pages: expect(type(sysconf(M._SC_PAGESIZE))).to_be "number" - it fetches the number of saved ids: expect(type(sysconf(M._SC_SAVED_IDS))).to_be "number" - it fetches the maximum number of open streams: expect(type(sysconf(M._SC_STREAM_MAX))).to_be "number" - it fetches the maximum length of a timezone name: expect(type(sysconf(M._SC_TZNAME_MAX))).to_be "number" - it fetches the POSIX.1 version: expect(type(sysconf(M._SC_VERSION))).to_be "number" - describe truncate: - before: | truncate = M.truncate function echo(fname, s) local fh = io.open(fname, 'w') fh:write(s .. '\n') fh:close() return #s + 1 end function flen(fname) local fh = io.open(fname, 'r') local r = fh:read '*a' fh:close() return #r end - context with bad arguments: badargs.diagnose(truncate, "(string, int)") - it truncates a named file: fname = os.tmpname() len = echo(fname, 'line 1') echo(fname, 'line 2') expect(ftruncate(fname, len)).not_to_be(nil) expect(flen(fname)).to_be(len) os.remove(fname) - describe ttyname: - before: ttyname, typeerrors = init(posix, "ttyname") r = pack(ttyname(2)) - context with bad arguments: - 'it diagnoses argument #1 type not int or nil': expect(ttyname(false)).to_raise.any_of(typeerrors(1, "integer or nil", "boolean")) - 'it diagnoses argument #1 not a tty descriptor': expect(ttyname(-1)).to_be(nil) - it diagnoses too many arguments: expect(ttyname(1, false)).to_raise.any_of(typeerrors(2)) - it returns nil and an error string: if r.n ~= 1 then expect(r[1]).to_be(nil) expect(type(r[2])).to_be "string" end - it returns a string: if r.n == 1 then expect(type(r[1])).to_be "string" end - it takes a file descriptor argument: if r.n == 1 then expect(r[1]).to_contain.any_of {"console", "pts", "tty"} end - it defaults the first argument to 0: expect(ttyname()).to_be(ttyname(0)) luaposix-36.3/spec/posix_version_spec.yaml000066400000000000000000000007151475444374100210700ustar00rootroot00000000000000before: this_module = 'posix.version' global_table = '_G' M = require(this_module) specify posix.version: - context when required: - it does not touch the global table: expect(show_apis {added_to=global_table, by=this_module}). to_equal {} - it is set: expect(M).not_to_be(nil) - it describes this module: expect(M).to_match '^posix ' - it ends with the release number: expect(M).to_match.any_of {' %d[%.%d]*$', ' git$'} luaposix-36.3/spec/spec_helper.lua000077500000000000000000000161021475444374100172570ustar00rootroot00000000000000local unpack = table.unpack or unpack do local std = require 'specl.std' local spawn = require 'specl.shell'.spawn local objdir = spawn('./build-aux/luke --value=objdir').output package.path = std.package.normalize ( './lib/?.lua', './lib/?/init.lua', package.path ) package.cpath = std.package.normalize( './' .. objdir:match("^objdir='(.*)'") .. '/?.so', package.cpath ) end local bit = require 'posix._base' band, bnot, bor = bit.band, bit.bnot, bit.bor badargs = require 'specl.badargs' hell = require 'specl.shell' posix = require 'posix' local gsub = string.gsub -- Allow user override of LUA binary used by hell.spawn, falling -- back to environment PATH search for 'lua' if nothing else works. local LUA = os.getenv 'LUA' or 'lua' -- Easily check for std.object.type compatibility. function prototype(o) return(getmetatable(o) or {})._type or io.type(o) or type(o) end local function mkscript(code) local f = os.tmpname() local h = io.open(f, 'w') h:write(code) h:close() return f end --- Run some Lua code with the given arguments and input. -- @string code valid Lua code -- @tparam[opt={}] string|table arg single argument, or table of -- arguments for the script invocation -- @string[opt] stdin standard input contents for the script process -- @treturn specl.shell.Process|nil status of resulting process if -- execution was successful, otherwise nil function luaproc(code, arg, stdin) local f = mkscript(code) if type(arg) ~= 'table' then arg = {arg} end local cmd = {LUA, f, unpack(arg)} -- inject env and stdin keys separately to avoid truncating `...` in -- cmd constructor cmd.stdin = stdin cmd.env = { LUA = LUA, LUA_CPATH = package.cpath, LUA_PATH = package.path, LUA_INIT = '', LUA_INIT_5_2 = '', LUA_INIT_5_3 = '', PATH = os.getenv 'PATH' } local proc = hell.spawn(cmd) os.remove(f) return proc end -- Use a consistent template for all temporary files. TMPDIR = posix.getenv('TMPDIR') or '/tmp' template = TMPDIR .. '/luaposix-test-XXXXXX' -- Allow comparison against the error message of a function call result. function Emsg(_, msg) return msg or '' end -- Collect stdout from a shell command, and strip surrounding whitespace. function cmd_output(cmd) return hell.spawn(cmd).output:gsub('^%s+', ''):gsub('%s+$', '') end local st = require 'posix.sys.stat' local stat, S_ISDIR = st.lstat, st.S_ISDIR -- Recursively remove a temporary directory. function rmtmp(dir) for f in posix.files(dir) do if f ~= '.' and f ~= '..' then local path = dir .. '/' .. f if S_ISDIR(stat(path).st_mode) ~= 0 then rmtmp(path) else os.remove(path) end end end os.remove(dir) end -- Create an empty file at PATH. function touch(path) io.open(path, 'w+'):close() end -- Format a bad argument type error. local function typeerrors(fname, i, want, field, got) return { badargs.format('?', i, want, field, got), -- LuaJIT badargs.format(fname, i, want, field, got), -- PUC-Rio } end function init(M, fname) return M[fname], function(...) return typeerrors(fname, ...) end end pack = table.pack or function(...) return {n=select('#', ...), ...} end local function tabulate_output(code) local proc = luaproc(code) if proc.status ~= 0 then return error(proc.errout) end local r = {} gsub(proc.output, '(%S*)[%s]*', function(x) if x ~= '' then r[x] = true end end) return r end --- Show changes to tables wrought by a require statement. -- There are a few modes to this function, controlled by what named -- arguments are given. Lists new keys in T1 after 'require 'import'`: -- -- show_apis {added_to=T1, by=import} -- -- List keys returned from `require 'import'`, which have the same -- value in T1: -- -- show_apis {from=T1, used_by=import} -- -- List keys from `require 'import'`, which are also in T1 but with -- a different value: -- -- show_apis {from=T1, enhanced_by=import} -- -- List keys from T2, which are also in T1 but with a different value: -- -- show_apis {from=T1, enhanced_in=T2} -- -- @tparam tabble argt one of the combinations above -- @treturn table a list of keys according to criteria above function show_apis(argt) local added_to, from, not_in, enhanced_in, enhanced_after, by = argt.added_to, argt.from, argt.not_in, argt.enhanced_in, argt.enhanced_after, argt.by if added_to and by then return tabulate_output([[ local before, after = {}, {} for k in pairs(]] .. added_to .. [[) do before[k] = true end local M = require ']] .. by .. [[' for k in pairs(]] .. added_to .. [[) do after[k] = true end for k in pairs(after) do if not before[k] then print(k) end end ]]) elseif from and not_in then return tabulate_output([[ local _ENV = require 'std.normalize' { from = ']] .. from .. [[', M = require ']] .. not_in .. [[', } for k in pairs(M) do -- M[1] is typically the module namespace name, don't match -- that! if k ~= 1 and from[k] ~= M[k] then print(k) end end ]]) elseif from and enhanced_in then return tabulate_output([[ local _ENV = require 'std.normalize' { from = ']] .. from .. [[', M = require ']] .. enhanced_in .. [[', } for k, v in pairs(M) do if from[k] ~= M[k] and from[k] ~= nil then print(k) end end ]]) elseif from and enhanced_after then return tabulate_output([[ local _ENV = require 'std.normalize' { from = ']] .. from .. [[', } local before , after = {}, {} for k, v in pairs(from) do before[k] = v end ]] .. enhanced_after .. [[ for k, v in pairs(from) do after[k] = v end for k, v in pairs(before) do if after[k] ~= nil and after[k] ~= v then print(k) end end ]]) end assert(false, 'missing argument to show_apis') end do --[[ ================ ]]-- --[[ Custom matchers. ]]-- --[[ ================ ]]-- local Matcher = require 'specl.matchers'.Matcher local matchers = require 'specl.matchers'.matchers -- Avoid timestamp race-conditions. matchers.be_within_n_of = Matcher { function(self, actual, expected) local delta = expected.delta or 1 local value = expected.value or expected[1] return(value <= actual + delta) and(value >= actual - delta) end, actual = 'within_of', format_expect = function(self, expect) local delta = tostring(expect.delta or 1) local value = tostring(expect.value or expect[1]) return ' number within ' .. delta .. ' of ' .. value .. ', ' end, } end