Merge nixio 0.2

This commit is contained in:
Steven Barth 2009-04-21 16:26:45 +00:00
parent 085a0a9ec0
commit a2b916ab73
43 changed files with 5260 additions and 336 deletions

201
libs/nixio/LICENSE Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,21 +1,27 @@
ifneq (,$(wildcard ../../build/config.mk))
include ../../build/config.mk
include ../../build/module.mk
include ../../build/gccconfig.mk
else
include standalone.mk
endif
AXTLS_VERSION = 1.2.1
AXTLS_DIR = axTLS
AXTLS_FILE = $(AXTLS_DIR)-$(AXTLS_VERSION).tar.gz
NIXIO_TLS ?= openssl
NIXIO_LDFLAGS =
NIXIO_LDFLAGS = -lcrypt
NIXIO_SO = nixio.so
NIXIO_OBJ = src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o \
src/poll.o src/io.o src/file.o src/splice.o src/process.o src/syslog.o \
src/tls-context.o src/tls-socket.o
src/bit.o src/binary.o src/fs.o src/user.o \
src/tls-crypto.o src/tls-context.o src/tls-socket.o
ifeq ($(NIXIO_TLS),axtls)
TLS_CFLAGS = -IaxTLS/ssl -IaxTLS/crypto -IaxTLS/config -include src/openssl-compat.h
TLS_DEPENDS = src/openssl-compat.o
NIXIO_OBJ += src/openssl-compat.o src/libaxtls.a
TLS_CFLAGS = -IaxTLS/ssl -IaxTLS/crypto -IaxTLS/config -include src/axtls-compat.h
TLS_DEPENDS = src/axtls-compat.o
NIXIO_OBJ += src/axtls-compat.o src/libaxtls.a
endif
ifeq ($(NIXIO_TLS),openssl)
@ -27,26 +33,43 @@ ifeq ($(OS),SunOS)
NIXIO_LDFLAGS += -lsocket -lnsl -lsendfile
endif
ifneq (,$(findstring MINGW,$(OS))$(findstring mingw,$(OS))$(findstring Windows,$(OS)))
NIXIO_CROSS_CC:=$(shell which i586-mingw32msvc-cc)
ifneq (,$(NIXIO_CROSS_CC))
CC:=$(NIXIO_CROSS_CC)
endif
NIXIO_OBJ += src/mingw-compat.o
NIXIO_LDFLAGS_POST:=-llua -lssl -lcrypto -lws2_32 -lgdi32
FPIC:=
EXTRA_CFLAGS += -D_WIN32_WINNT=0x0501
LUA_CFLAGS:=
NIXIO_SO:=nixio.dll
NIXIO_LDFLAGS:=
endif
%.o: %.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) -c -o $@ $<
src/tls-crypto.o: $(TLS_DEPENDS) src/tls-crypto.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/tls-crypto.c
src/tls-context.o: $(TLS_DEPENDS) src/tls-context.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/tls-context.c
src/tls-socket.o: $(TLS_DEPENDS) src/tls-socket.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/tls-socket.c
src/openssl-compat.o: src/libaxtls.a src/openssl-compat.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/openssl-compat.c
src/axtls-compat.o: src/libaxtls.a src/axtls-compat.c
$(COMPILE) $(NIXIO_CFLAGS) $(LUA_CFLAGS) $(FPIC) $(TLS_CFLAGS) -c -o $@ src/axtls-compat.c
mkdir -p dist
cp -pR axtls-root/* dist/
compile: $(NIXIO_OBJ)
$(LINK) $(SHLIB_FLAGS) $(NIXIO_LDFLAGS) -o src/nixio.so $(NIXIO_OBJ)
$(LINK) $(SHLIB_FLAGS) $(NIXIO_LDFLAGS) -o src/$(NIXIO_SO) $(NIXIO_OBJ) $(NIXIO_LDFLAGS_POST)
mkdir -p dist$(LUA_LIBRARYDIR)
cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so
cp src/$(NIXIO_SO) dist$(LUA_LIBRARYDIR)/$(NIXIO_SO)
$(AXTLS_DIR)/.prepared:
#rm -rf $(AXTLS_DIR)
@ -55,9 +78,13 @@ $(AXTLS_DIR)/.prepared:
touch $@
src/libaxtls.a: $(AXTLS_DIR)/.prepared
$(MAKE) -C $(AXTLS_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(EXTRA_CFLAGS) $(FPIC) '-Dalloca(size)=__builtin_alloca(size)' -Wall -pedantic -I../config -I../ssl -I../crypto" LDFLAGS="$(LDFLAGS)" OS="$(OS)" clean all
$(MAKE) -C $(AXTLS_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(EXTRA_CFLAGS) $(FPIC) -Wall -pedantic -I../config -I../ssl -I../crypto" LDFLAGS="$(LDFLAGS)" OS="$(OS)" clean all
cp -p $(AXTLS_DIR)/_stage/libaxtls.a src
clean: luaclean
rm -f src/*.o src/*.so src/*.a
rm -f src/*.o src/*.so src/*.a src/*.dll
rm -f $(AXTLS_DIR)/.prepared
install: build
cp -pR dist$(LUA_MODULEDIR)/* $(LUA_MODULEDIR)
cp -pR dist$(LUA_LIBRARYDIR)/* $(LUA_LIBRARYDIR)

10
libs/nixio/NOTICE Normal file
View file

@ -0,0 +1,10 @@
nixio - Linux I/O library for lua
Copyright 2009 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0.
Contains code from:
axTLS - Copyright 2008 Cameron Rich
Thanks for testing, feedback and code snippets:
John Crispin <blogic@openwrt.org>
Jo-Philipp Wich <xm@leipzig.freifunk.net>

View file

@ -1,7 +1,13 @@
Building:
Use GNU Make.
make or gmake depending on your system.
Special make flags:
With axTLS (standard):
make
With OpenSSL:
make NIXIO_TLS=openssl
OS Override Target OS [Linux|FreeBSD|SunOS|Windows]
NIXIO_TLS TLS-Library [*openssl|axtls]
NIXIO_CROSS_CC MinGW CC (Windows) `which i586-mingw32msvc-cc`
LUA_CFLAGS Lua CFLAGS `pkg-config --cflags lua5.1`
LUA_TARGET Lua compile target [*source|strip|compile]
LUA_MODULEDIR Install LUA_PATH "/usr/share/lua/5.1"
LUA_LIBRARYDIR Install LUA_CPATH "/usr/lib/lua/5.1"

View file

@ -0,0 +1,98 @@
--- General Information.
module "README"
--- General error handling information.
-- <ul>
-- <li> Most of the functions available in this library may fail. If any error
-- occurs the function returns <strong>nil or false</strong>, an error code
-- (usually errno) and an additional error message text (if avaialable).</li>
-- <li>At the moment false is only returned when a non-blocking I/O function
-- fails with EAGAIN, EWOULDBLOCK or WSAEWOULDBLOCK for any others nil is
-- returned as first parameter. Therefore you can use false to write portable
-- non-blocking I/O applications.</li>
-- <li>Note that the function documentation does only mention the return values
-- in case of a successful operation.</li>
-- <li>You can find a table of common error numbers and other useful constants
-- like signal numbers in <strong>nixio.const</strong> e.g. nixio.const.EINVAL,
-- nixio.const.SIGTERM, etc. For portability there is a second error constant
-- table <strong>nixio.const_sock</strong> for socket error codes. This might
-- be important if you are dealing with Windows applications, on POSIX however
-- const_sock is just an alias for const.</li>
-- <li>With some exceptions - which are explicitely stated in the function
-- documentation - all blocking functions are signal-protected and will not fail
-- with EINTR.</li>
-- <li>On POSIX the SIGPIPE signal will be set to ignore upon initialization.
-- You should restore the default behaviour or set a custom signal handler
-- in your program after loading nixio if you need this behaviour.</li>
-- </ul>
-- @class table
-- @name Errorhandling
-- @return !
--- Function conventions.
-- <br />In general all functions are namend and behave like their POSIX API
-- counterparts - where applicable - applying the following rules:
-- <ul>
-- <li>Functions should be named like the underlying POSIX API function ommiting
-- prefixes or suffixes - especially when placed in an object-context (
-- lockf -> File:lock, fsync -> File:sync, dup2 -> dup, ...)</li>
-- <li>If you are unclear about the behaviour of a function you should consult
-- your OS API documentation (e.g. the manpages).</li>
-- <li>If the name is significantly different from the POSIX-function, the
-- underlying function(s) are stated in the documentation.</li>
-- <li>Parameters should reflect those of the C-API, buffer length arguments and
-- by-reference parameters should be ommitted for pratical purposes.</li>
-- <li>If a C function accepts a bitfield as parameter, it should be translated
-- into lower case string flags representing the flags if the bitfield is the
-- last parameter and also ommiting prefixes or suffixes. (e.g. waitpid
-- (pid, &s, WNOHANG | WUNTRACED) -> waitpid(pid, "nohang", "untraced"),
-- getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) ->
-- Socket:getopt("socket", "reuseaddr"), etc.) </li>
-- <li>If it is not applicable to provide a string representation of the
-- bitfield a bitfield generator helper is provided. It is named FUNCTION_flags.
-- (open("/tmp/test", O_RDONLY | O_NONBLOCK) -> open("/tmp/test", open_flags(
-- "rdonly", "nonblock")))</li>
-- </ul>
-- @class table
-- @name Functions
-- @return !
--- Platform information.
-- <ul>
-- <li>The minimum platform requirements are a decent POSIX 2001 support.
-- Builds are more or less tested on Linux, Solaris and FreeBSD. Builds for
-- Windows XP SP1 and later can be compiled with MinGW either from Windows
-- itself or using the MinGW cross-compiler. Earlier versions of Windows are not
-- supported.</li>
-- <li>In general all functions which don't have any remarks
-- in their documentation are available on all platforms.</li>
-- <li>Functions with a (POSIX), (Linux) or similar prefix are only available
-- on these specific platforms. Same appplies to parameters of functions
-- with a similar suffix.</li>
-- <li>Some functions might have limitations on some platforms. This should
-- be stated in the documentation. Please also consult your OS API
-- documentation.</li>
-- </ul>
-- @usage Tes
-- @class table
-- @name Platforms
-- @return !
--- Cryptography and TLS libraries.
-- <ul>
-- <li>Currently 2 underlying cryptography libraries are supported: openssl and
-- axTLS. The name of the library in use is written to
-- <strong>nixio.tls_provider</strong></li>
-- <li>You should whenever possible use openssl as axTLS has only limited
-- support. It does not provide support for non-blocking sockets and
-- is probably less audited than openssl.</li>
-- <li>However in embedded development if you don't need openssl anyway
-- you may safe an essential amount of flash space (about 1 MB for the openssl
-- library) by choosing axTLS over openssl.</li>
-- <li>As the supported Windows versions are not suitable for embedded devices
-- axTLS is at the moment not supported on Windows.</li>
-- </ul>
-- @usage Tes
-- @class table
-- @name TLS-Crypto
-- @return !

View file

@ -0,0 +1,17 @@
--- Cryptographical Hash and HMAC object.
-- @cstyle instance
module "nixio.CryptoHash"
--- Add another chunk of data to be hashed.
-- @class function
-- @name CryptoHash.update
-- @param chunk Chunk of data
-- @return CryptoHash object (self)
--- Finalize the hash and return the digest.
-- @class function
-- @name CryptoHash.final
-- @usage You cannot call update on a hash object that was already finalized
-- you can however call final multiple times to get the digest.
-- @return hexdigest
-- @return buffer containing binary digest

View file

@ -0,0 +1,109 @@
--- Large File Object.
-- Large file operations are supported up to 52 bits if the Lua number type is
-- double (default).
-- @cstyle instance
module "nixio.File"
--- Write to the file descriptor.
-- @class function
-- @name File.write
-- @usage <strong>Warning:</strong> It is not guaranteed that all data
-- in the buffer is written at once especially when dealing with pipes.
-- You have to check the return value - the number of bytes actually written -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage Unlike standard Lua indexing the lowest offset and default is 0.
-- @param buffer Buffer holding the data to be written.
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @return number of bytes written
--- Read from a file descriptor.
-- @class function
-- @name File.read
-- @usage <strong>Warning:</strong> It is not guaranteed that all requested data
-- is read at once especially when dealing with pipes.
-- You have to check the return value - the length of the buffer actually read -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage The length of the return buffer is limited by the (compile time)
-- nixio buffersize which is <em>nixio.const.buffersize</em> (8192 by default).
-- Any read request greater than that will be safely truncated to this value.
-- @param length Amount of data to read (in Bytes).
-- @return buffer containing data successfully read
--- Reposition read / write offset of the file descriptor.
-- The seek will be done either from the beginning of the file or relative
-- to the current position or relative to the end.
-- @class function
-- @name File.seek
-- @usage This function calls lseek().
-- @param offset File Offset
-- @param whence Starting point [<strong>"set"</strong>, "cur", "end"]
-- @return new (absolute) offset position
--- Return the current read / write offset of the file descriptor.
-- @class function
-- @name File.tell
-- @usage This function calls lseek() with offset 0 from the current position.
-- @return offset position
--- Synchronizes the file with the storage device.
-- Returns when the file is successfully written to the disk.
-- @class function
-- @name File.sync
-- @usage This function calls fsync() when data_only equals false
-- otherwise fdatasync(), on Windows _commit() is used instead.
-- @usage fdatasync() is only supported by Linux and Solaris. For other systems
-- the <em>data_only</em> parameter is ignored and fsync() is always called.
-- @param data_only Do not synchronize the metadata. (optional, boolean)
-- @return true
--- Apply or test a lock on the file.
-- @class function
-- @name File.lock
-- @usage This function calls lockf() on POSIX and _locking() on Windows.
-- @usage The "lock" command is blocking, "tlock" is non-blocking,
-- "ulock" unlocks and "test" only tests for the lock.
-- @usage The "test" command is not available on Windows.
-- @usage Locks are by default advisory on POSIX, but mandatory on Windows.
-- @param command Locking Command ["lock", "tlock", "ulock", "test"]
-- @param length Amount of Bytes to lock from current offset (optional)
-- @return true
--- Get file status and attributes.
-- @class function
-- @name File.stat
-- @param field Only return a specific field, not the whole table (optional)
-- @usage This function calls fstat().
-- @return Table containing: <ul>
-- <li>atime = Last access timestamp</li>
-- <li>blksize = Blocksize (POSIX only)</li>
-- <li>blocks = Blocks used (POSIX only)</li>
-- <li>ctime = Creation timestamp</li>
-- <li>dev = Device ID</li>
-- <li>gid = Group ID</li>
-- <li>ino = Inode</li>
-- <li>modedec = Mode converted into a decimal number</li>
-- <li>modestr = Mode as string as returned by `ls -l`</li>
-- <li>mtime = Last modification timestamp</li>
-- <li>nlink = Number of links</li>
-- <li>rdev = Device ID (if special file)</li>
-- <li>size = Size in bytes</li>
-- <li>type = ["reg", "dir", "chr", "blk", "fifo", "lnk", "sock"]</li>
-- <li>uid = User ID</li>
-- </ul>
--- Close the file descriptor.
-- @class function
-- @name File.close
-- @return true
--- Get the number of the filedescriptor.
-- @class function
-- @name File.fileno
-- @return file descriptor number
--- (POSIX) Set the blocking mode of the file descriptor.
-- @class function
-- @name File.setblocking
-- @param blocking (boolean)
-- @return true

View file

@ -0,0 +1,170 @@
--- Socket Object.
-- Supports IPv4, IPv6 and UNIX (POSIX only) families.
-- @cstyle instance
module "nixio.Socket"
--- Get the local address of a socket.
-- @class function
-- @name Socket.getsockname
-- @return IP-Address
-- @return Port
--- Get the peer address of a socket.
-- @class function
-- @name Socket.getpeername
-- @return IP-Address
-- @return Port
--- Bind the socket to a network address.
-- @class function
-- @name Socket.bind
-- @usage This function calls getaddrinfo() and bind() but NOT listen().
-- @usage If <em>host</em> is a domain name it will be looked up and bind()
-- tries the IP-Addresses in the order returned by the DNS resolver
-- until the bind succeeds.
-- @usage UNIX sockets ignore the <em>port</em>,
-- and interpret <em>host</em> as a socket path.
-- @param host Host (optional, default: all addresses)
-- @param port Port or service description
-- @return true
--- Connect the socket to a network address.
-- @class function
-- @name Socket.connect
-- @usage This function calls getaddrinfo() and connect().
-- @usage If <em>host</em> is a domain name it will be looked up and connect()
-- tries the IP-Addresses in the order returned by the DNS resolver
-- until the connect succeeds.
-- @usage UNIX sockets ignore the <em>port</em>,
-- and interpret <em>host</em> as a socket path.
-- @param host Hostname or IP-Address (optional, default: localhost)
-- @param port Port or service description
-- @return true
--- Listen for connections on the socket.
-- @class function
-- @name Socket.listen
-- @param backlog Length of queue for pending connections
-- @return true
--- Accept a connection on the socket.
-- @class function
-- @name Socket.accept
-- @return Socket Object
-- @return Peer IP-Address
-- @return Peer Port
--- Send a message on the socket specifying the destination.
-- @class function
-- @name Socket.sendto
-- @usage <strong>Warning:</strong> It is not guaranteed that all data
-- in the buffer is written at once.
-- You have to check the return value - the number of bytes actually written -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage Unlike standard Lua indexing the lowest offset and default is 0.
-- @param buffer Buffer holding the data to be written.
-- @param host Target IP-Address
-- @param port Target Port
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @return number of bytes written
--- Send a message on the socket.
-- This function is identical to sendto except for the missing destination
-- paramters. See the sendto description for a detailed description.
-- @class function
-- @name Socket.send
-- @param buffer Buffer holding the data to be written.
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @see Socket.sendto
-- @return number of bytes written
--- Send a message on the socket (This is an alias for send).
-- See the sendto description for a detailed description.
-- @class function
-- @name Socket.write
-- @param buffer Buffer holding the data to be written.
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @see Socket.sendto
-- @return number of bytes written
--- Receive a message on the socket including the senders source address.
-- @class function
-- @name Socket.recvfrom
-- @usage <strong>Warning:</strong> It is not guaranteed that all requested data
-- is read at once.
-- You have to check the return value - the length of the buffer actually read -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage The length of the return buffer is limited by the (compile time)
-- nixio buffersize which is <em>nixio.const.buffersize</em> (8192 by default).
-- Any read request greater than that will be safely truncated to this value.
-- @param length Amount of data to read (in Bytes).
-- @return buffer containing data successfully read
-- @return host IP-Address of the sender
-- @return port Port of the sender
--- Receive a message on the socket.
-- This function is identical to recvfrom except that it does not return
-- the sender's source address. See the recvfrom description for more details.
-- @class function
-- @name Socket.recv
-- @param length Amount of data to read (in Bytes).
-- @see Socket.recvfrom
-- @return buffer containing data successfully read
--- Receive a message on the socket (This is an alias for recv).
-- See the recvfrom description for more details.
-- @class function
-- @name Socket.read
-- @param length Amount of data to read (in Bytes).
-- @see Socket.recvfrom
-- @return buffer containing data successfully read
--- Close the socket.
-- @class function
-- @name Socket.close
-- @return true
--- Shut down part of a full-duplex connection.
-- @class function
-- @name Socket.shutdown
-- @param how (optional, default: rdwr) ["rdwr", "rd", "wr"]
-- @return true
--- Get the number of the filedescriptor.
-- @class function
-- @name Socket.fileno
-- @return file descriptor number
--- Set the blocking mode of the socket.
-- @class function
-- @name Socket.setblocking
-- @param blocking (boolean)
-- @return true
--- Set a socket option.
-- @class function
-- @name Socket.setopt
-- @param level Level ["socket", "tcp", "ip", "ipv6"]
-- @param option Option ["keepalive", "reuseaddr", "sndbuf", "rcvbuf",
-- "priority", "broadcast", "linger", "sndtimeo", "rcvtimeo", "dontroute",
-- "bindtodevice", "error", "oobinline", "cork" (TCP), "nodelay" (TCP),
-- "mtu" (IP, IPv6), "hdrincl" (IP), "multicast_ttl" (IP), "multicast_loop"
-- (IP, IPv6), "multicast_if" (IP, IPv6), "v6only" (IPv6), "multicast_hops"
-- (IPv6), "add_membership" (IP, IPv6), "drop_membership" (IP, IPv6)]
-- @param value Value
-- @return true
--- Get a socket option.
-- @class function
-- @name Socket.getopt
-- @param level Level ["socket", "tcp", "ip", "ipv6"]
-- @param option Option ["keepalive", "reuseaddr", "sndbuf", "rcvbuf",
-- "priority", "broadcast", "linger", "sndtimeo", "rcvtimeo", "dontroute",
-- "bindtodevice", "error", "oobinline", "cork" (TCP), "nodelay" (TCP),
-- "mtu" (IP, IPv6), "hdrincl" (IP), "multicast_ttl" (IP), "multicast_loop"
-- (IP, IPv6), "multicast_if" (IP, IPv6), "v6only" (IPv6), "multicast_hops"
-- (IPv6), "add_membership" (IP, IPv6), "drop_membership" (IP, IPv6)]
-- @return Value

View file

@ -0,0 +1,46 @@
--- Transport Layer Security Context Object.
-- @cstyle instance
module "nixio.TLSContext"
--- Create a TLS Socket from a socket descriptor.
-- @class function
-- @name TLSContext.create
-- @param socket Socket Object
-- @return TLSSocket Object
--- Assign a PEM certificate to this context.
-- @class function
-- @name TLSContext.set_cert
-- @usage This function calls SSL_CTX_use_certificate_chain_file().
-- @param path Certificate File path
-- @return true
--- Assign a PEM private key to this context.
-- @class function
-- @name TLSContext.set_key
-- @usage This function calls SSL_CTX_use_PrivateKey_file().
-- @param path Private Key File path
-- @return true
--- Set the available ciphers for this context.
-- @class function
-- @name TLSContext.set_ciphers
-- @usage This function calls SSL_CTX_set_cipher_list().
-- @param cipherlist String containing a list of ciphers
-- @return true
--- Set the verification depth of this context.
-- @class function
-- @name TLSContext.set_verify_depth
-- @usage This function calls SSL_CTX_set_verify_depth().
-- @param depth Depth
-- @return true
--- Set the verification flags of this context.
-- @class function
-- @name TLSContext.set_verify
-- @usage This function calls SSL_CTX_set_verify().
-- @param flag1 First Flag ["none", "peer", "verify_fail_if_no_peer_cert",
-- "client_once"]
-- @param ... More Flags [-"-]
-- @return true

View file

@ -0,0 +1,73 @@
--- TLS Socket Object.
-- TLS Sockets contain the underlying socket and context in the fields
-- "socket" and "context".
-- @cstyle instance
module "nixio.TLSSocket"
--- Initiate the TLS handshake as client with the server.
-- @class function
-- @name TLSSocket.connect
-- @usage This function calls SSL_connect().
-- @usage You have to call either connect or accept before transmitting data.
-- @see TLSSocket.accept
-- @return true
--- Wait for a TLS handshake from a client.
-- @class function
-- @name TLSSocket.accept
-- @usage This function calls SSL_accept().
-- @usage You have to call either connect or accept before transmitting data.
-- @see TLSSocket.connect
-- @return true
--- Send a message to the socket.
-- @class function
-- @name TLSSocket.send
-- @usage This function calls SSL_write().
-- @usage <strong>Warning:</strong> It is not guaranteed that all data
-- in the buffer is written at once.
-- You have to check the return value - the number of bytes actually written -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage Unlike standard Lua indexing the lowest offset and default is 0.
-- @param buffer Buffer holding the data to be written.
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @return number of bytes written
--- Send a message on the socket (This is an alias for send).
-- See the send description for a detailed description.
-- @class function
-- @name TLSSocket.write
-- @param buffer Buffer holding the data to be written.
-- @param offset Offset to start reading the buffer from. (optional)
-- @param length Length of chunk to read from the buffer. (optional)
-- @see TLSSocket.send
-- @return number of bytes written
--- Receive a message on the socket.
-- @class function
-- @name TLSSocket.recv
-- @usage This function calls SSL_read().
-- @usage <strong>Warning:</strong> It is not guaranteed that all requested data
-- is read at once.
-- You have to check the return value - the length of the buffer actually read -
-- or use the safe IO functions in the high-level IO utility module.
-- @usage The length of the return buffer is limited by the (compile time)
-- nixio buffersize which is <em>nixio.const.buffersize</em> (8192 by default).
-- Any read request greater than that will be safely truncated to this value.
-- @param length Amount of data to read (in Bytes).
-- @return buffer containing data successfully read
--- Receive a message on the socket (This is an alias for recv).
-- See the recv description for more details.
-- @class function
-- @name TLSSocket.read
-- @param length Amount of data to read (in Bytes).
-- @see TLSSocket.recv
-- @return buffer containing data successfully read
--- Shut down the TLS connection.
-- @class function
-- @name TLSSocket.shutdown
-- @usage This function calls SSL_shutdown().
-- @return true

View file

@ -0,0 +1,130 @@
--- Unified high-level I/O utility API for Files, Sockets and TLS-Sockets.
-- These functions are added to the object function tables by doing <strong>
-- require "nixio.util"</strong>, can be used on all nixio IO Descriptors and
-- are based on the shared low-level read() and write() functions.
-- @cstyle instance
module "nixio.UnifiedIO"
--- Test whether the I/O-Descriptor is a socket.
-- @class function
-- @name UnifiedIO.is_socket
-- @return boolean
--- Test whether the I/O-Descriptor is a TLS socket.
-- @class function
-- @name UnifiedIO.is_tls_socket
-- @return boolean
--- Test whether the I/O-Descriptor is a file.
-- @class function
-- @name UnifiedIO.is_file
-- @return boolean
--- Read a block of data and wait until all data is available.
-- @class function
-- @name UnifiedIO.readall
-- @usage This function uses the low-level read function of the descriptor.
-- @usage If the length parameter is ommited, this function returns all data
-- that can be read before an end-of-file, end-of-stream, connection shutdown
-- or similar happens.
-- @usage If the descriptor is non-blocking this function may fail with EAGAIN.
-- @param length Bytes to read (optional)
-- @return data that was successfully read if no error occured
-- @return - reserved for error code -
-- @return - reserved for error message -
-- @return data that was successfully read even if an error occured
--- Write a block of data and wait until all data is written.
-- @class function
-- @name UnifiedIO.writeall
-- @usage This function uses the low-level write function of the descriptor.
-- @usage If the descriptor is non-blocking this function may fail with EAGAIN.
-- @param block Bytes to write
-- @return bytes that were successfully written if no error occured
-- @return - reserved for error code -
-- @return - reserved for error message -
-- @return bytes that were successfully written even if an error occured
--- Create a line-based iterator.
-- Lines may end with either \n or \r\n, these control chars are not included
-- in the return value.
-- @class function
-- @name UnifiedIO.linesource
-- @usage This function uses the low-level read function of the descriptor.
-- @usage <strong>Note:</strong> This function uses an internal buffer to read
-- ahead. Do NOT mix calls to read(all) and the returned iterator. If you want
-- to stop reading line-based and want to use the read(all) functions instead
-- you can pass "true" to the iterator which will flush the buffer
-- and return the bufferd data.
-- @usage If the limit parameter is ommited, this function uses the nixio
-- buffersize (8192B by default).
-- @usage If the descriptor is non-blocking the iterator may fail with EAGAIN.
-- @usage The iterator can be used as an LTN12 source.
-- @param limit Line limit
-- @return Line-based Iterator
--- Create a block-based iterator.
-- @class function
-- @name UnifiedIO.blocksource
-- @usage This function uses the low-level read function of the descriptor.
-- @usage The blocksize given is only advisory and to be seen as an upper limit,
-- if an underlying read returns less bytes the chunk is nevertheless returned.
-- @usage If the limit parameter is ommited, the iterator returns data
-- until an end-of-file, end-of-stream, connection shutdown or similar happens.
-- @usage The iterator will not buffer so it is safe to mix with calls to read.
-- @usage If the descriptor is non-blocking the iterator may fail with EAGAIN.
-- @usage The iterator can be used as an LTN12 source.
-- @param blocksize Advisory blocksize (optional)
-- @param limit Amount of data to consume (optional)
-- @return Block-based Iterator
--- Create a sink.
-- This sink will simply write all data that it receives and optionally
-- close the descriptor afterwards.
-- @class function
-- @name UnifiedIO.sink
-- @usage This function uses the writeall function of the descriptor.
-- @usage If the descriptor is non-blocking the sink may fail with EAGAIN.
-- @usage The iterator can be used as an LTN12 sink.
-- @param close_when_done (optional, boolean)
-- @return Sink
--- Copy data from the current descriptor to another one.
-- @class function
-- @name UnifiedIO.copy
-- @usage This function uses the blocksource function of the source descriptor
-- and the sink function of the target descriptor.
-- @usage If the limit parameter is ommited, data is copied
-- until an end-of-file, end-of-stream, connection shutdown or similar happens.
-- @usage If the descriptor is non-blocking the function may fail with EAGAIN.
-- @param fdout Target Descriptor
-- @param size Bytes to copy (optional)
-- @return bytes that were successfully written if no error occured
-- @return - reserved for error code -
-- @return - reserved for error message -
-- @return bytes that were successfully written even if an error occured
--- Copy data from the current descriptor to another one using kernel-space
-- copying if possible.
-- @class function
-- @name UnifiedIO.copyz
-- @usage This function uses the sendfile() syscall to copy the data or the
-- blocksource function of the source descriptor and the sink function
-- of the target descriptor as a fallback mechanism.
-- @usage Support for splice() on Linux is not implemented yet.
-- @usage If the limit parameter is ommited, data is copied
-- until an end-of-file, end-of-stream, connection shutdown or similar happens.
-- @usage If the descriptor is non-blocking the function may fail with EAGAIN.
-- @param fdout Target Descriptor
-- @param size Bytes to copy (optional)
-- @return bytes that were successfully written if no error occured
-- @return - reserved for error code -
-- @return - reserved for error message -
-- @return bytes that were successfully written even if an error occured
--- Close the descriptor.
-- @class function
-- @name UnifiedIO.close
-- @usage If the descriptor is a TLS-socket the underlying descriptor is
-- closed without touching the TLS connection.
-- @return true

View file

@ -0,0 +1,33 @@
--- Binary operations and conversion.
module "nixio.bin"
--- Return a hexadecimal ASCII represantation of the content of a buffer.
-- @class function
-- @name hexlify
-- @param buffer Buffer
-- @return representation using characters [0-9a-f]
--- Return a binary buffer from a hexadecimal ASCII representation.
-- @class function
-- @name unhexlify
-- @param hexvalue representation using characters [0-9a-f]
-- @return binary data
--- Calculate the CRC32 value of a buffer.
-- @class function
-- @name crc32
-- @param buffer Buffer
-- @param initial Initial CRC32 value (optional)
-- @return crc32 value
--- Base64 encode a given buffer.
-- @class function
-- @name b64encode
-- @param buffer Buffer
-- @return base64 encoded buffer
--- Base64 decode a given buffer.
-- @class function
-- @name b64decode
-- @param buffer Base 64 Encoded data
-- @return binary data

View file

@ -0,0 +1,86 @@
--- Bitfield operators and mainpulation functions.
-- Can be used as a drop-in replacement for bitlib.
module "nixio.bit"
--- Bitwise OR several numbers.
-- @class function
-- @name bor
-- @param oper1 First Operand
-- @param oper2 Second Operand
-- @param ... More Operands
-- @return number
--- Bitwise AND several numbers.
-- @class function
-- @name band
-- @param oper1 First Operand
-- @param oper2 Second Operand
-- @param ... More Operands
-- @return number
--- Bitwise XOR several numbers.
-- @class function
-- @name bxor
-- @param oper1 First Operand
-- @param oper2 Second Operand
-- @param ... More Operands
-- @return number
--- Left shift a number.
-- @class function
-- @name shl
-- @param oper number
-- @param shift bits to shift
-- @return number
--- Right shift a number.
-- @class function
-- @name shr
-- @param oper number
-- @param shift bits to shift
-- @return number
--- Arithmetically right shift a number.
-- @class function
-- @name ashr
-- @param oper number
-- @param shift bits to shift
-- @return number
--- Integer division of 2 or more numbers.
-- @class function
-- @name div
-- @param oper1 Operand 1
-- @param oper2 Operand 2
-- @param ... More Operands
-- @return number
--- Cast a number to the bit-operating range.
-- @class function
-- @name cast
-- @param oper number
-- @return number
--- Sets one or more flags of a bitfield.
-- @class function
-- @name set
-- @param bitfield Bitfield
-- @param flag1 First Flag
-- @param ... More Flags
-- @return altered bitfield
--- Unsets one or more flags of a bitfield.
-- @class function
-- @name unset
-- @param bitfield Bitfield
-- @param flag1 First Flag
-- @param ... More Flags
-- @return altered bitfield
--- Checks whether given flags are set in a bitfield.
-- @class function
-- @name check
-- @param bitfield Bitfield
-- @param flag1 First Flag
-- @param ... More Flags
-- @return true when all flags are set, otherwise false

View file

@ -0,0 +1,15 @@
--- Cryptographical library.
module "nixio.crypto"
--- Create a hash object.
-- @class function
-- @name nixio.crypto.hash
-- @param algo Algorithm ["sha1", "md5"]
-- @return CryptoHash Object
--- Create a HMAC object.
-- @class function
-- @name nixio.crypto.hmac
-- @param algo Algorithm ["sha1", "md5"]
-- @param key HMAC-Key
-- @return CryptoHash Object

View file

@ -0,0 +1,265 @@
--- Low-level and high-level filesystem manipulation library.
module "nixio.fs"
--- Check user's permission on a file.
-- @class function
-- @name nixio.fs.access
-- @param path Path
-- @param mode1 First Mode to check ["f", "r", "w", "x"]
-- @param ... More Modes to check [-"-]
-- @return true
--- Strip the directory part from a path.
-- @class function
-- @name nixio.fs.basename
-- @usage This function cannot fail and will never return nil.
-- @param path Path
-- @return basename
--- Strip the base from a path.
-- @class function
-- @name nixio.fs.dirname
-- @usage This function cannot fail and will never return nil.
-- @param path Path
-- @return dirname
--- Return the cannonicalized absolute pathname.
-- @class function
-- @name nixio.fs.realpath
-- @param path Path
-- @return absolute path
--- Remove a file or directory.
-- @class function
-- @name nixio.fs.remove
-- @param path Path
-- @return true
--- Delete a name and - if no links are left - the associated file.
-- @class function
-- @name nixio.fs.unlink
-- @param path Path
-- @return true
--- Renames a file or directory.
-- @class function
-- @name nixio.fs.rename
-- @param src Source path
-- @param dest Destination path
-- @usage It is normally not possible to rename files accross fileystems.
-- @return true
--- Remove an empty directory.
-- @class function
-- @name nixio.fs.rmdir
-- @param path Path
-- @return true
--- Create a new directory.
-- @class function
-- @name nixio.fs.mkdir
-- @param path Path
-- @param mode File mode (optional, see chmod and umask)
-- @see nixio.fs.chmod
-- @see nixio.umask
-- @return true
--- Change the file mode.
-- @class function
-- @name nixio.fs.chmod
-- @usage Windows only supports setting the write-protection through the
-- "Writable to others" bit.
-- @usage <strong>Notice:</strong> The mode-flag for the functions
-- open, mkdir, mkfifo are affected by the umask.
-- @param path Path
-- @param mode File mode
-- [decimal mode number, "[-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]"]
-- @see nixio.umask
-- @return true
--- Iterate over the entries of a directory.
-- @class function
-- @name nixio.fs.dir
-- @usage The special entries "." and ".." are omitted.
-- @param path Path
-- @return directory iterator returning one entry per call
--- Create a hard link.
-- @class function
-- @name nixio.fs.link
-- @usage This function calls link() on POSIX and CreateHardLink() on Windows.
-- @param oldpath Path
-- @param newpath Path
-- @return true
--- Change file last access and last modification time.
-- @class function
-- @name nixio.fs.utimes
-- @param path Path
-- @param actime Last access timestamp (optional, default: current time)
-- @param mtime Last modification timestamp (optional, default: actime)
-- @return true
--- Get file status and attributes.
-- @class function
-- @name nixio.fs.stat
-- @param path Path
-- @param field Only return a specific field, not the whole table (optional)
-- @return Table containing: <ul>
-- <li>atime = Last access timestamp</li>
-- <li>blksize = Blocksize (POSIX only)</li>
-- <li>blocks = Blocks used (POSIX only)</li>
-- <li>ctime = Creation timestamp</li>
-- <li>dev = Device ID</li>
-- <li>gid = Group ID</li>
-- <li>ino = Inode</li>
-- <li>modedec = Mode converted into a decimal number</li>
-- <li>modestr = Mode as string as returned by `ls -l`</li>
-- <li>mtime = Last modification timestamp</li>
-- <li>nlink = Number of links</li>
-- <li>rdev = Device ID (if special file)</li>
-- <li>size = Size in bytes</li>
-- <li>type = ["reg", "dir", "chr", "blk", "fifo", "lnk", "sock"]</li>
-- <li>uid = User ID</li>
-- </ul>
--- Get file status and attributes and do not resolve if target is a symlink.
-- @class function
-- @name nixio.fs.lstat
-- @param path Path
-- @param field Only return a specific field, not the whole table (optional)
-- @see nixio.fs.stat
-- @return Table containing attributes (see stat for a detailed description)
--- (POSIX) Change owner and group of a file.
-- @class function
-- @name nixio.fs.chown
-- @param path Path
-- @param user User ID or Username (optional)
-- @param group Group ID or Groupname (optional)
-- @return true
--- (POSIX) Change owner and group of a file and do not resolve
-- if target is a symlink.
-- @class function
-- @name nixio.fs.lchown
-- @param path Path
-- @param user User ID or Username (optional)
-- @param group Group ID or Groupname (optional)
-- @return true
--- (POSIX) Create a FIFO (named pipe).
-- @class function
-- @name nixio.fs.mkfifo
-- @param path Path
-- @param mode File mode (optional, see chmod and umask)
-- @see nixio.fs.chmod
-- @see nixio.umask
-- @return true
--- (POSIX) Create a symbolic link.
-- @class function
-- @name nixio.fs.symlink
-- @param oldpath Path
-- @param newpath Path
-- @return true
--- (POSIX) Read the target of a symbolic link.
-- @class function
-- @name nixio.fs.readlink
-- @param path Path
-- @return target path
--- (POSIX) Find pathnames matching a pattern.
-- @class function
-- @name nixio.fs.glob
-- @param pattern Pattern
-- @return path iterator
-- @return number of matches
--- (POSIX) Get filesystem statistics.
-- @class function
-- @name nixio.fs.statvfs
-- @param path Path to any file within the filesystem.
-- @return Table containing: <ul>
-- <li>bavail = available blocks</li>
-- <li>bfree = free blocks</li>
-- <li>blocks = number of fragments</li>
-- <li>frsize = fragment size</li>
-- <li>favail = available inodes</li>
-- <li>ffree = free inodes</li>
-- <li>files = inodes</li>
-- <li>flag = flags</li>
-- <li>fsid = filesystem ID</li>
-- <li>namemax = maximum filename length</li>
-- </ul>
--- Read the contents of a file into a buffer.
-- @class function
-- @name nixio.fs.readfile
-- @param path Path
-- @param limit Maximum bytes to read (optional)
-- @return file contents
--- Write a buffer into a file truncating the file first.
-- @class function
-- @name nixio.fs.writefile
-- @param path Path
-- @param data Data to write
-- @return true
--- Copy data between files.
-- @class function
-- @name nixio.fs.datacopy
-- @param src Source file path
-- @param dest Destination file path
-- @param limit Maximum bytes to copy (optional)
-- @return true
--- Copy a file, directory or symlink non-recursively preserving file mode,
-- timestamps, owner and group.
-- @class function
-- @name nixio.fs.copy
-- @usage The destination must always be a full destination path e.g. do not
-- omit the basename even if source and destination basename are equal.
-- @param src Source path
-- @param dest Destination path
-- @return true
--- Rename a file, directory or symlink non-recursively across filesystems.
-- @class function
-- @name nixio.fs.move
-- @usage The destination must always be a full destination path e.g. do not
-- omit the basename even if source and destination basename are equal.
-- @param src Source path
-- @param dest Destination path
-- @return true
--- Create a directory and all needed parent directories recursively.
-- @class function
-- @name nixio.fs.mkdirr
-- @param dest Destination path
-- @param mode File mode (optional, see chmod and umask)
-- @see nixio.fs.chmod
-- @see nixio.umask
-- @return true
--- Rename a file, directory or symlink recursively across filesystems.
-- @class function
-- @name nixio.fs.mover
-- @usage The destination must always be a full destination path e.g. do not
-- omit the basename even if source and destination basename are equal.
-- @param src Source path
-- @param dest Destination path
-- @return true
--- Copy a file, directory or symlink recursively preserving file mode,
-- timestamps, owner and group.
-- @class function
-- @name nixio.fs.copyr
-- @usage The destination must always be a full destination path e.g. do not
-- omit the basename even if source and destination basename are equal.
-- @param src Source path
-- @param dest Destination path
-- @return true

416
libs/nixio/docsrc/nixio.lua Normal file
View file

@ -0,0 +1,416 @@
--- General POSIX IO library.
module "nixio"
--- Look up a hostname and service via DNS.
-- @class function
-- @name nixio.getaddrinfo
-- @param host hostname to lookup (optional)
-- @param family address family [<strong>"any"</strong>, "inet", "inet6"]
-- @param service service name or port (optional)
-- @return Table containing one or more tables containing: <ul>
-- <li>family = ["inet", "inet6"]</li>
-- <li>socktype = ["stream", "dgram", "raw"]</li>
-- <li>address = Resolved IP-Address</li>
-- <li>port = Resolved Port (if service was given)</li>
-- </ul>
--- Reverse look up an IP-Address via DNS.
-- @class function
-- @name nixio.getnameinfo
-- @param ipaddr IPv4 or IPv6-Address
-- @return FQDN
--- Create a new socket and bind it to a network address.
-- This function is a shortcut for calling nixio.socket and then bind()
-- on the socket object.
-- @usage This functions calls getaddrinfo(), socket(),
-- setsockopt() and bind() but NOT listen().
-- @usage The <em>reuseaddr</em>-option is automatically set before binding.
-- @class function
-- @name nixio.bind
-- @param host Hostname or IP-Address (optional, default: all addresses)
-- @param port Port or service description
-- @param family Address family [<strong>"any"</strong>, "inet", "inet6"]
-- @param socktype Socket Type [<strong>"stream"</strong>, "dgram"]
-- @return Socket Object
--- Create a new socket and connect to a network address.
-- This function is a shortcut for calling nixio.socket and then connect()
-- on the socket object.
-- @usage This functions calls getaddrinfo(), socket() and connect().
-- @class function
-- @name nixio.connect
-- @param host Hostname or IP-Address (optional, default: localhost)
-- @param port Port or service description
-- @param family Address family [<strong>"any"</strong>, "inet", "inet6"]
-- @param socktype Socket Type [<strong>"stream"</strong>, "dgram"]
-- @return Socket Object
--- Open a file.
-- @class function
-- @name nixio.open
-- @usage Although this function also supports the traditional fopen()
-- file flags it does not create a file stream but uses the open() syscall.
-- @param path Filesystem path to open
-- @param flags Flag string or number (see open_flags).
-- [<strong>"r"</strong>, "r+", "w", "w+", "a", "a+"]
-- @param mode File mode for newly created files (see chmod, umask).
-- @see nixio.umask
-- @see nixio.open_flags
-- @return File Object
--- Generate flags for a call to open().
-- @class function
-- @name nixio.open_flags
-- @usage This function cannot fail and will never return nil.
-- @usage The "nonblock" and "ndelay" flags are aliases.
-- @usage The "nonblock", "ndelay" and "sync" flags are no-ops on Windows.
-- @param flag1 First Flag ["append", "creat", "excl", "nonblock", "ndelay",
-- "sync", "trunc", "rdonly", "wronly", "rdwr"]
-- @param ... More Flags [-"-]
-- @return flag to be used as second paramter to open
--- Duplicate a file descriptor.
-- @class function
-- @name nixio.dup
-- @usage This funcation calls dup2() if <em>newfd</em> is set, otherwise dup().
-- @param oldfd Old descriptor [File Object, Socket Object (POSIX only)]
-- @param newfd New descriptor to serve as copy (optional)
-- @return File Object of new descriptor
--- Create a pipe.
-- @class function
-- @name nixio.pipe
-- @return File Object of the read end
-- @return File Object of the write end
--- Get the last system error code.
-- @class function
-- @name nixio.errno
-- @return Error code
--- Get the error message for the corresponding error code.
-- @class function
-- @name nixio.strerror
-- @param errno System error code
-- @return Error message
--- Sleep for a specified amount of time.
-- @class function
-- @usage Not all systems support nanosecond precision but you can expect
-- to have at least maillisecond precision.
-- @usage This function is not signal-protected and may fail with EINTR.
-- @param seconds Seconds to wait (optional)
-- @param nanoseconds Nanoseconds to wait (optional)
-- @name nixio.nanosleep
-- @return true
--- Generate events-bitfield or parse revents-bitfield for poll.
-- @class function
-- @name nixio.poll_flags
-- @param mode1 revents-Flag bitfield returned from poll to parse OR
-- ["in", "out", "err", "pri" (POSIX), "hup" (POSIX), "nval" (POSIX)]
-- @param ... More mode strings for generating the flag [-"-]
-- @see nixio.poll
-- @return table with boolean fields reflecting the mode parameter
-- <strong>OR</strong> bitfield to use for the events-Flag field
--- Wait for some event on a file descriptor.
-- poll() sets the revents-field of the tables provided by fds to a bitfield
-- indicating the events that occured.
-- @class function
-- @usage This function works in-place on the provided table and only
-- writes the revents field, you can use other fields on your demand.
-- @usage All metamethods on the tables provided as fds are ignored.
-- @usage The revents-fields are not reset when the call times out.
-- You have to check the first return value to be 0 to handle this case.
-- @usage If you want to wait on a TLS-Socket you have to use the underlying
-- socket instead.
-- @usage On Windows poll is emulated through select(), can only be used
-- on socket descriptors and cannot take more than 64 descriptors per call.
-- @usage This function is not signal-protected and may fail with EINTR.
-- @param fds Table containing one or more tables containing <ul>
-- <li> fd = I/O Descriptor [Socket Object, File Object (POSIX)]</li>
-- <li> events = events to wait for (bitfield generated with poll_flags)</li>
-- </ul>
-- @param timeout Timeout in milliseconds
-- @name nixio.poll
-- @see nixio.poll_flags
-- @return number of ready IO descriptors
-- @return the fds-table with revents-fields set
--- (POSIX) Clone the current process.
-- @class function
-- @name nixio.fork
-- @return the child process id for the parent process, 0 for the child process
--- (POSIX) Send a signal to one or more processes.
-- @class function
-- @name nixio.kill
-- @param target Target process of process group.
-- @param signal Signal to send
-- @return true
--- (POSIX) Get the parent process id of the current process.
-- @class function
-- @name nixio.getppid
-- @return parent process id
--- (POSIX) Get the user id of the current process.
-- @class function
-- @name nixio.getuid
-- @return process user id
--- (POSIX) Get the group id of the current process.
-- @class function
-- @name nixio.getgid
-- @return process group id
--- (POSIX) Set the group id of the current process.
-- @class function
-- @name nixio.setgid
-- @param gid New Group ID
-- @return true
--- (POSIX) Set the user id of the current process.
-- @class function
-- @name nixio.setuid
-- @param gid New User ID
-- @return true
--- (POSIX) Change priority of current process.
-- @class function
-- @name nixio.nice
-- @param nice Nice Value
-- @return true
--- (POSIX) Create a new session and set the process group ID.
-- @class function
-- @name nixio.setsid
-- @return session id
--- (POSIX) Wait for a process to change state.
-- @class function
-- @name nixio.waitpid
-- @usage If the "nohang" is given this function becomes non-blocking.
-- @param pid Process ID (optional, default: any childprocess)
-- @param flag1 Flag (optional) ["nohang", "untraced", "continued"]
-- @param ... More Flags [-"-]
-- @return process id of child or 0 if no child has changed state
-- @return ["exited", "signaled", "stopped"]
-- @return [exit code, terminate signal, stop signal]
--- (POSIX) Get process times.
-- @class function
-- @name nixio.times
-- @return Table containing: <ul>
-- <li>utime = user time</li>
-- <li>utime = system time</li>
-- <li>cutime = children user time</li>
-- <li>cstime = children system time</li>
-- </ul>
--- (POSIX) Get information about current system and kernel.
-- @class function
-- @name nixio.uname
-- @return Table containing: <ul>
-- <li>sysname = operating system</li>
-- <li>nodename = network name (usually hostname)</li>
-- <li>release = OS release</li>
-- <li>version = OS version</li>
-- <li>machine = hardware identifier</li>
-- </ul>
--- Change the working directory.
-- @class function
-- @name nixio.chdir
-- @param path New working directory
-- @return true
--- Ignore or use set the default handler for a signal.
-- @class function
-- @name nixio.signal
-- @param signal Signal
-- @param handler ["ign", "dfl"]
-- @return true
--- Get the ID of the current process.
-- @class function
-- @name nixio.getpid
-- @return process id
--- Get the current working directory.
-- @class function
-- @name nixio.getcwd
-- @return workign directory
--- Get the current environment table or a specific environment variable.
-- @class function
-- @name nixio.getenv
-- @param variable Variable (optional)
-- @return environment table or single environment variable
--- Set or unset a environment variable.
-- @class function
-- @name nixio.setenv
-- @usage The environment variable will be unset if value is ommited.
-- @param variable Variable
-- @param value Value (optional)
-- @return true
--- Execute a file to replace the current process.
-- @class function
-- @name nixio.exec
-- @usage The name of the executable is automatically passed as argv[0]
-- @usage This function does not return on success.
-- @param executable Executable
-- @param ... Parameters
--- Invoke the shell and execute a file to replace the current process.
-- @class function
-- @name nixio.execp
-- @usage The name of the executable is automatically passed as argv[0]
-- @usage This function does not return on success.
-- @param executable Executable
-- @param ... Parameters
--- Execute a file with a custom environment to replace the current process.
-- @class function
-- @name nixio.exece
-- @usage The name of the executable is automatically passed as argv[0]
-- @usage This function does not return on success.
-- @param executable Executable
-- @param arguments Argument Table
-- @param environment Environment Table (optional)
--- Sets the file mode creation mask.
-- @class function
-- @name nixio.umask
-- @param mask New creation mask (see chmod for format specifications)
-- @return the old umask as decimal mode number
-- @return the old umask as mode string
--- (Linux) Get overall system statistics.
-- @class function
-- @name nixio.sysinfo
-- @return Table containing: <ul>
-- <li>uptime = system uptime in seconds</li>
-- <li>loads = {loadavg1, loadavg5, loadavg15}</li>
-- <li>totalram = total RAM</li>
-- <li>freeram = free RAM</li>
-- <li>sharedram = shared RAM</li>
-- <li>bufferram = buffered RAM</li>
-- <li>totalswap = total SWAP</li>
-- <li>freeswap = free SWAP</li>
-- <li>procs = number of running processes</li>
-- </ul>
--- Create a new socket.
-- @class function
-- @name nixio.socket
-- @param domain Domain ["inet", "inet6", "unix"]
-- @param type Type ["stream", "dgram", "raw"]
-- @return Socket Object
--- (POSIX) Send data from a file to a socket in kernel-space.
-- @class function
-- @name nixio.sendfile
-- @param socket Socket Object
-- @param file File Object
-- @param length Amount of data to send (in Bytes).
-- @return bytes sent
--- (Linux) Send data from / to a pipe in kernel-space.
-- @class function
-- @name nixio.splice
-- @param fdin Input I/O descriptor
-- @param fdout Output I/O descriptor
-- @param length Amount of data to send (in Bytes).
-- @param flags (optional, bitfield generated by splice_flags)
-- @see nixio.splice_flags
-- @return bytes sent
--- (Linux) Generate a flag bitfield for a call to splice.
-- @class function
-- @name nixio.splice_flags
-- @param flag1 First Flag ["move", "nonblock", "more"]
-- @param ... More flags [-"-]
-- @see nixio.splice
-- @return Flag bitfield
--- (POSIX) Open a connection to the system logger.
-- @class function
-- @name nixio.openlog
-- @param ident Identifier
-- @param flag1 Flag 1 ["cons", "nowait", "pid", "perror", "ndelay", "odelay"]
-- @param ... More flags [-"-]
--- (POSIX) Close the connection to the system logger.
-- @class function
-- @name nixio.closelog
--- (POSIX) Write a message to the system logger.
-- @class function
-- @name nixio.syslog
-- @param priority Priority ["emerg", "alert", "crit", "err", "warning",
-- "notice", "info", "debug"]
-- @param message
--- (POSIX) Set the logmask of the system logger for current process.
-- @class function
-- @name nixio.setlogmask
-- @param priority Priority ["emerg", "alert", "crit", "err", "warning",
-- "notice", "info", "debug"]
--- (POSIX) Encrypt a user password.
-- @class function
-- @name nixio.crypt
-- @param key Key
-- @param salt Salt
-- @return password hash
--- (POSIX) Get all or a specific user group.
-- @class function
-- @name nixio.getgr
-- @param group Group ID or groupname (optional)
-- @return Table containing: <ul>
-- <li>name = Group Name</li>
-- <li>gid = Group ID</li>
-- <li>passwd = Password</li>
-- <li>mem = {Member #1, Member #2, ...}</li>
-- </ul>
--- (POSIX) Get all or a specific user account.
-- @class function
-- @name nixio.getpw
-- @param user User ID or username (optional)
-- @return Table containing: <ul>
-- <li>name = Name</li>
-- <li>uid = ID</li>
-- <li>gid = Group ID</li>
-- <li>passwd = Password</li>
-- <li>dir = Home directory</li>
-- <li>gecos = Information</li>
-- <li>shell = Shell</li>
-- </ul>
--- (Linux, Solaris) Get all or a specific shadow password entry.
-- @class function
-- @name nixio.getsp
-- @param user username (optional)
-- @return Table containing: <ul>
-- <li>namp = Name</li>
-- <li>expire = Expiration Date</li>
-- <li>flag = Flags</li>
-- <li>inact = Inactivity Date</li>
-- <li>lstchg = Last change</li>
-- <li>max = Maximum</li>
-- <li>min = Minimum</li>
-- <li>warn = Warning</li>
-- <li>pwdp = Password Hash</li>
-- </ul>
--- Create a new TLS context.
-- @class function
-- @name nixio.tls
-- @return TLSContext Object

15
libs/nixio/lua/bit.lua Normal file
View file

@ -0,0 +1,15 @@
--[[
nixio - Linux I/O library for lua
Copyright 2009 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
return require "nixio".bit

175
libs/nixio/lua/nixio/fs.lua Normal file
View file

@ -0,0 +1,175 @@
--[[
nixio - Linux I/O library for lua
Copyright 2009 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
local table = require "table"
local nixio = require "nixio"
local type, ipairs, setmetatable = type, ipairs, setmetatable
require "nixio.util"
module ("nixio.fs", function(m) setmetatable(m, {__index = nixio.fs}) end)
function readfile(path, limit)
local fd, code, msg = nixio.open(path, "r")
local data
if not fd then
return nil, code, msg
end
data, code, msg = fd:readall(limit)
fd:close()
return data, code, msg
end
function writefile(path, data)
local fd, code, msg, stat = nixio.open(path, "w")
if not fd then
return nil, code, msg
end
stat, code, msg = fd:writeall(data)
fd:close()
return stat, code, msg
end
function datacopy(src, dest, size)
local fdin, code, msg = nixio.open(src, "r")
if not fdin then
return nil, code, msg
end
local fdout, code, msg = nixio.open(dest, "w")
if not fdout then
return nil, code, msg
end
local stat, code, msg, sent = fdin:copy(fdout, size)
fdin:close()
fdout:close()
return stat, code, msg, sent
end
function copy(src, dest)
local stat, code, msg, res = nixio.lstat(src)
if not stat then
return nil, code, msg
end
if stat.type == "dir" then
if nixio.stat(dest, type) ~= "dir" then
res, code, msg = nixio.mkdir(dest)
else
stat = true
end
elseif stat.type == "lnk" then
res, code, msg = nixio.symlink(nixio.readlink(src), dest)
else
res, code, msg = datacopy(src, dest)
end
if not res then
return nil, code, msg
end
nixio.utimes(dest, stat.atime, stat.mtime)
if nixio.lchown then
nixio.lchown(dest, stat.uid, stat.gid)
end
if stat.type ~= "lnk" then
nixio.chmod(dest, stat.modedec)
end
return true
end
function move(src, dest)
local stat, code, msg = nixio.rename(src, dest)
if not stat and code == nixio.const.EXDEV then
stat, code, msg = nixio.copy(src, dest)
if stat then
stat, code, msg = nixio.unlink(src)
end
end
return stat, code, msg
end
function mkdirr(dest, mode)
if nixio.stat(dest, "type") == "dir" then
return true
else
local stat, code, msg = nixio.mkdir(dest, mode)
if not stat and code == nixio.const.ENOENT then
stat, code, msg = mkdirr(nixio.dirname(dest), mode)
if stat then
stat, code, msg = nixio.mkdir(dest, mode)
end
end
return stat, code, msg
end
end
local function _recurse(cb, src, dest)
local type = nixio.lstat(src, "type")
if type ~= "dir" then
return cb(src, dest)
else
local stat, se, code, msg, s, c, m = true, nixio.const.sep
if dest then
s, c, m = cb(src, dest)
stat, code, msg = stat and s, c or code, m or msg
end
for e in nixio.dir(src) do
if dest then
s, c, m = _recurse(cb, src .. se .. e, dest .. se .. e)
else
s, c, m = _recurse(cb, src .. se .. e)
end
stat, code, msg = stat and s, c or code, m or msg
end
if not dest then -- Postfix
s, c, m = cb(src)
stat, code, msg = stat and s, c or code, m or msg
end
return stat, code, msg
end
end
function copyr(src, dest)
return _recurse(copy, src, dest)
end
function mover(src, dest)
local stat, code, msg = nixio.rename(src, dest)
if not stat and code == nixio.const.EXDEV then
stat, code, msg = _recurse(copy, src, dest)
if stat then
stat, code, msg = _recurse(nixio.remove, src)
end
end
return stat, code, msg
end
function remover(src)
return _recurse(nixio.remove, src)
end

View file

@ -18,11 +18,20 @@ local getmetatable, assert, pairs = getmetatable, assert, pairs
module "nixio.util"
local BUFFERSIZE = 8096
local BUFFERSIZE = nixio.const.buffersize
local ZIOBLKSIZE = 65536
local socket = nixio.meta_socket
local tls_socket = nixio.meta_tls_socket
local file = nixio.meta_file
function consume(iter)
local tbl = {}
for obj in iter do
tbl[#tbl+1] = obj
end
return tbl
end
local meta = {}
function meta.is_socket(self)
@ -38,50 +47,53 @@ function meta.is_file(self)
end
function meta.readall(self, len)
local block, code, msg = self:read(len)
local block, code, msg = self:read(len or BUFFERSIZE)
if not block then
return "", code, msg, len
return nil, code, msg, ""
elseif #block == 0 then
return "", nil, nil, len
return "", nil, nil, ""
end
local data, total = {block}, #block
while len > total do
block, code, msg = self:read(len - total)
while not len or len > total do
block, code, msg = self:read(len and (len - total) or BUFFERSIZE)
if not block then
return data, code, msg, len - #data
return nil, code, msg, table.concat(data)
elseif #block == 0 then
return data, nil, nil, len - #data
break
end
data[#data+1], total = block, total + #block
end
return (#data > 1 and table.concat(data) or data[1]), nil, nil, 0
local data = #data > 1 and table.concat(data) or data[1]
return data, nil, nil, data
end
meta.recvall = meta.readall
function meta.writeall(self, data)
local total, block = 0
local sent, code, msg = self:write(data)
if not sent then
return total, code, msg, data
return nil, code, msg, 0
end
while sent < #data do
block, total = data:sub(sent + 1), total + sent
sent, code, msg = self:write(block)
local total = sent
while total < #data do
sent, code, msg = self:write(data, total)
if not sent then
return total, code, msg, block
return nil, code, msg, total
end
total = total + sent
end
return total + sent, nil, nil, ""
return total, nil, nil, total
end
meta.sendall = meta.writeall
@ -105,9 +117,9 @@ function meta.linesource(self, limit)
bpos = endp
return line
elseif #buffer < limit + bpos then
local newblock, code = self:read(limit + bpos - #buffer)
local newblock, code, msg = self:read(limit + bpos - #buffer)
if not newblock then
return nil, code
return nil, code, msg
elseif #newblock == 0 then
return nil
end
@ -135,7 +147,7 @@ function meta.blocksource(self, bs, limit)
local block, code, msg = self:read(toread)
if not block then
return nil, code
return nil, code, msg
elseif #block == 0 then
return nil
else
@ -162,6 +174,40 @@ function meta.sink(self, close)
end
end
function meta.copy(self, fdout, size)
local source = self:blocksource(nil, size)
local sink = fdout:sink()
local sent, chunk, code, msg = 0
repeat
chunk, code, msg = source()
sink(chunk, code, msg)
sent = chunk and (sent + #chunk) or sent
until not chunk
return not code and sent or nil, code, msg, sent
end
function meta.copyz(self, fd, size)
local sent, lsent, code, msg = 0
if self:is_file() then
if nixio.sendfile and fd:is_socket() and self:stat("type") == "reg" then
repeat
lsent, code, msg = nixio.sendfile(fd, self, size or ZIOBLKSIZE)
if lsent then
sent = sent + lsent
size = size and (size - lsent)
end
until (not lsent or lsent == 0 or (size and size == 0))
if lsent or (not lsent and sent == 0 and
code ~= nixio.const.ENOSYS and code ~= nixio.const.EINVAL) then
return lsent and sent, code, msg, sent
end
end
end
return self:copy(fd, size)
end
function tls_socket.close(self)
return self.socket:close()
end

View file

@ -18,16 +18,79 @@
#include "nixio.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
/**
* address pushing helper
*/
int nixio__addr_parse(nixio_addr *addr, struct sockaddr *saddr) {
void *baddr;
addr->family = saddr->sa_family;
if (saddr->sa_family == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in*)saddr;
addr->port = ntohs(inetaddr->sin_port);
baddr = &inetaddr->sin_addr;
} else if (saddr->sa_family == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6*)saddr;
addr->port = ntohs(inet6addr->sin6_port);
baddr = &inet6addr->sin6_addr;
} else {
errno = EAFNOSUPPORT;
return -1;
}
if (!inet_ntop(saddr->sa_family, baddr, addr->host, sizeof(addr->host))) {
return -1;
}
return 0;
}
/**
* address pulling helper
*/
int nixio__addr_write(nixio_addr *addr, struct sockaddr *saddr) {
if (addr->family == AF_UNSPEC) {
if (strchr(addr->host, ':')) {
addr->family = AF_INET6;
} else {
addr->family = AF_INET;
}
}
if (addr->family == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in *)saddr;
memset(inetaddr, 0, sizeof(struct sockaddr_in));
if (inet_pton(AF_INET, addr->host, &inetaddr->sin_addr) < 1) {
return -1;
}
inetaddr->sin_family = AF_INET;
inetaddr->sin_port = htons((uint16_t)addr->port);
return 0;
} else if (addr->family == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6 *)saddr;
memset(inet6addr, 0, sizeof(struct sockaddr_in6));
if (inet_pton(AF_INET6, addr->host, &inet6addr->sin6_addr) < 1) {
return -1;
}
inet6addr->sin6_family = AF_INET6;
inet6addr->sin6_port = htons((uint16_t)addr->port);
return 0;
} else {
errno = EAFNOSUPPORT;
return -1;
}
}
/**
* getaddrinfo(host, family, port)
@ -70,9 +133,11 @@ static int nixio_getaddrinfo(lua_State *L) {
for (rp = result; rp != NULL; rp = rp->ai_next) {
/* avoid duplicate results */
#ifndef __WINNT__
if (!port && rp->ai_socktype != SOCK_STREAM) {
continue;
}
#endif
if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) {
lua_createtable(L, 0, port ? 4 : 2);
@ -101,31 +166,18 @@ static int nixio_getaddrinfo(lua_State *L) {
lua_setfield(L, -2, "socktype");
}
char ip[INET6_ADDRSTRLEN];
void *binaddr = NULL;
uint16_t binport = 0;
if (rp->ai_family == AF_INET) {
struct sockaddr_in *v4addr = (struct sockaddr_in*)rp->ai_addr;
binport = v4addr->sin_port;
binaddr = (void *)&v4addr->sin_addr;
} else if (rp->ai_family == AF_INET6) {
struct sockaddr_in6 *v6addr = (struct sockaddr_in6*)rp->ai_addr;
binport = v6addr->sin6_port;
binaddr = (void *)&v6addr->sin6_addr;
}
if (!inet_ntop(rp->ai_family, binaddr, ip, sizeof(ip))) {
nixio_addr addr;
if (nixio__addr_parse(&addr, rp->ai_addr)) {
freeaddrinfo(result);
return nixio__perror(L);
return nixio__perror_s(L);
}
if (port) {
lua_pushinteger(L, ntohs(binport));
lua_pushinteger(L, addr.port);
lua_setfield(L, -2, "port");
}
lua_pushstring(L, ip);
lua_pushstring(L, addr.host);
lua_setfield(L, -2, "address");
lua_rawseti(L, -2, i++);
}
@ -140,37 +192,29 @@ static int nixio_getaddrinfo(lua_State *L) {
* getnameinfo(address, family)
*/
static int nixio_getnameinfo(lua_State *L) {
const char *ip = luaL_checklstring(L, 1, NULL);
const char *family = luaL_optlstring(L, 2, "inet", NULL);
const char *ip = luaL_checkstring(L, 1);
const char *family = luaL_optstring(L, 2, NULL);
char host[NI_MAXHOST];
struct sockaddr *addr = NULL;
socklen_t alen = 0;
int res;
struct sockaddr_storage saddr;
nixio_addr addr;
memset(&addr, 0, sizeof(addr));
strncpy(addr.host, ip, sizeof(addr.host) - 1);
if (!strcmp(family, "inet")) {
struct sockaddr_in inetaddr;
memset(&inetaddr, 0, sizeof(inetaddr));
inetaddr.sin_family = AF_INET;
if (inet_pton(AF_INET, ip, &inetaddr.sin_addr) < 1) {
return luaL_argerror(L, 1, "invalid address");
}
alen = sizeof(inetaddr);
addr = (struct sockaddr *)&inetaddr;
if (!family) {
addr.family = AF_UNSPEC;
} else if (!strcmp(family, "inet")) {
addr.family = AF_INET;
} else if (!strcmp(family, "inet6")) {
struct sockaddr_in6 inet6addr;
memset(&inet6addr, 0, sizeof(inet6addr));
inet6addr.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, ip, &inet6addr.sin6_addr) < 1) {
return luaL_argerror(L, 1, "invalid address");
}
alen = sizeof(inet6addr);
addr = (struct sockaddr *)&inet6addr;
addr.family = AF_INET6;
} else {
return luaL_argerror(L, 2, "supported values: inet, inet6");
}
res = getnameinfo(addr, alen, host, sizeof(host), NULL, 0, NI_NAMEREQD);
nixio__addr_write(&addr, (struct sockaddr *)&saddr);
int res = getnameinfo((struct sockaddr *)&saddr, sizeof(saddr),
host, sizeof(host), NULL, 0, NI_NAMEREQD);
if (res) {
lua_pushnil(L);
lua_pushinteger(L, res);
@ -182,60 +226,42 @@ static int nixio_getnameinfo(lua_State *L) {
}
}
/**
* getsockname() / getpeername() helper
*/
static int nixio_sock__getname(lua_State *L, int sock) {
int sockfd = nixio__checksockfd(L);
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
char ipaddr[INET6_ADDRSTRLEN];
void *binaddr;
uint16_t port;
if (sock) {
if (getsockname(sockfd, (struct sockaddr*)&addr, &addrlen)) {
return nixio__perror(L);
}
} else {
if (getpeername(sockfd, (struct sockaddr*)&addr, &addrlen)) {
return nixio__perror(L);
}
}
if (addr.ss_family == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in*)&addr;
port = inetaddr->sin_port;
binaddr = &inetaddr->sin_addr;
} else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6*)&addr;
port = inet6addr->sin6_port;
binaddr = &inet6addr->sin6_addr;
} else {
return luaL_error(L, "unknown address family");
}
if (!inet_ntop(addr.ss_family, binaddr, ipaddr, sizeof(ipaddr))) {
return nixio__perror(L);
}
lua_pushstring(L, ipaddr);
lua_pushinteger(L, ntohs(port));
return 2;
}
/**
* getsockname()
*/
static int nixio_sock_getsockname(lua_State *L) {
return nixio_sock__getname(L, 1);
int sockfd = nixio__checksockfd(L);
struct sockaddr_storage saddr;
socklen_t addrlen = sizeof(saddr);
nixio_addr addr;
if (getsockname(sockfd, (struct sockaddr*)&saddr, &addrlen) ||
nixio__addr_parse(&addr, (struct sockaddr*)&saddr)) {
return nixio__perror_s(L);
}
lua_pushstring(L, addr.host);
lua_pushnumber(L, addr.port);
return 2;
}
/**
* getpeername()
*/
static int nixio_sock_getpeername(lua_State *L) {
return nixio_sock__getname(L, 0);
int sockfd = nixio__checksockfd(L);
struct sockaddr_storage saddr;
socklen_t addrlen = sizeof(saddr);
nixio_addr addr;
if (getpeername(sockfd, (struct sockaddr*)&saddr, &addrlen) ||
nixio__addr_parse(&addr, (struct sockaddr*)&saddr)) {
return nixio__perror_s(L);
}
lua_pushstring(L, addr.host);
lua_pushnumber(L, addr.port);
return 2;
}

View file

@ -0,0 +1,297 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Enable a subset of openssl compatible functions. We don't aim to be 100%
* compatible - just to be able to do basic ports etc.
*
* Only really tested on mini_httpd, so I'm not too sure how extensive this
* port is.
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "ssl.h"
static char *key_password = NULL;
void *SSLv23_server_method(void) { return NULL; }
void *SSLv3_server_method(void) { return NULL; }
void *TLSv1_server_method(void) { return NULL; }
void *SSLv23_client_method(void) { return NULL; }
void *SSLv3_client_method(void) { return NULL; }
void *TLSv1_client_method(void) { return NULL; }
void *SSLv23_method(void) { return NULL; }
void *TLSv1_method(void) { return NULL; }
SSL_CTX * SSL_CTX_new(void *meth)
{
SSL_CTX *ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER, 5);
return ssl_ctx;
}
void SSL_CTX_free(SSL_CTX * ssl_ctx)
{
ssl_ctx_free(ssl_ctx);
}
SSL * SSL_new(SSL_CTX *ssl_ctx)
{
SSL *ssl;
ssl = ssl_new(ssl_ctx, -1); /* fd is set later */
return ssl;
}
int SSL_set_fd(SSL *s, int fd)
{
s->client_fd = fd;
return 1; /* always succeeds */
}
int SSL_accept(SSL *ssl)
{
ssl->next_state = HS_CLIENT_HELLO;
while (ssl_read(ssl, NULL) == SSL_OK)
{
if (ssl->next_state == HS_CLIENT_HELLO)
return 1; /* we're done */
}
return -1;
}
int SSL_connect(SSL *ssl)
{
SET_SSL_FLAG(SSL_IS_CLIENT);
int stat = do_client_connect(ssl);
ssl_display_error(stat);
return (stat == SSL_OK) ? 1 : -1;
}
void SSL_free(SSL *ssl)
{
ssl_free(ssl);
}
int SSL_read(SSL *ssl, void *buf, int num)
{
uint8_t *read_buf;
int ret;
while ((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
if (ret > SSL_OK)
{
memcpy(buf, read_buf, ret > num ? num : ret);
}
return ret;
}
int SSL_write(SSL *ssl, const void *buf, int num)
{
return ssl_write(ssl, buf, num);
}
int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type)
{
return (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, file, NULL) == SSL_OK);
}
int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type)
{
return (ssl_obj_load(ssl_ctx, SSL_OBJ_RSA_KEY, file, key_password) == SSL_OK);
}
int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d)
{
return (ssl_obj_memory_load(ssl_ctx,
SSL_OBJ_X509_CERT, d, len, NULL) == SSL_OK);
}
int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
return 1;
}
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
{
return 1;
}
int SSL_CTX_use_certificate_chain_file(SSL_CTX *ssl_ctx, const char *file)
{
return (ssl_obj_load(ssl_ctx,
SSL_OBJ_X509_CERT, file, NULL) == SSL_OK);
}
int SSL_shutdown(SSL *ssl)
{
return 1;
}
/*** get/set session ***/
SSL_SESSION *SSL_get1_session(SSL *ssl)
{
return (SSL_SESSION *)ssl_get_session_id(ssl); /* note: wrong cast */
}
int SSL_set_session(SSL *ssl, SSL_SESSION *session)
{
memcpy(ssl->session_id, (uint8_t *)session, SSL_SESSION_ID_SIZE);
return 1;
}
void SSL_SESSION_free(SSL_SESSION *session) { }
/*** end get/set session ***/
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
return 0;
}
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
int (*verify_callback)(int, void *)) {
if (mode & SSL_VERIFY_PEER) {
ctx->options &= ~SSL_SERVER_VERIFY_LATER;
ctx->options |= SSL_CLIENT_AUTHENTICATION;
} else {
ctx->options |= SSL_SERVER_VERIFY_LATER;
ctx->options &= ~SSL_CLIENT_AUTHENTICATION;
}
}
void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) { }
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath)
{
return 1;
}
void *SSL_load_client_CA_file(const char *file)
{
return (void *)file;
}
void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file)
{
ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL);
}
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { }
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u)
{
key_password = (char *)u;
}
int SSL_peek(SSL *ssl, void *buf, int num)
{
memcpy(buf, ssl->bm_data, num);
return num;
}
void SSL_set_bio(SSL *ssl, void *rbio, void *wbio) { }
long SSL_get_verify_result(const SSL *ssl)
{
return ssl_handshake_status(ssl);
}
int SSL_state(SSL *ssl)
{
return 0x03; // ok state
}
/** end of could do better list */
void *SSL_get_peer_certificate(const SSL *ssl)
{
return &ssl->ssl_ctx->certs[0];
}
int SSL_clear(SSL *ssl)
{
return 1;
}
int SSL_CTX_check_private_key(const SSL_CTX *ctx)
{
return 1;
}
int SSL_CTX_set_cipher_list(SSL_CTX *s, const char *str)
{
return 1;
}
int SSL_get_error(const SSL *ssl, int ret)
{
ssl_display_error(ret);
return ret; /* TODO: return proper return code */
}
void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option) {}
int SSL_library_init(void ) { return 1; }
void SSL_load_error_strings(void ) {}
void ERR_print_errors_fp(FILE *fp) {}
long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx) {
return CONFIG_SSL_EXPIRY_TIME*3600; }
long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t) {
return SSL_CTX_get_timeout(ssl_ctx); }
void BIO_printf(FILE *f, const char *format, ...)
{
va_list(ap);
va_start(ap, format);
vfprintf(f, format, ap);
va_end(ap);
}
void* BIO_s_null(void) { return NULL; }
FILE *BIO_new(bio_func_type_t func)
{
if (func == BIO_s_null)
return fopen("/dev/null", "r");
else
return NULL;
}
FILE *BIO_new_fp(FILE *stream, int close_flag) { return stream; }
int BIO_free(FILE *a) { if (a != stdout && a != stderr) fclose(a); return 1; }

View file

@ -0,0 +1,149 @@
/*
* Copyright (c) 2007, Cameron Rich
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the axTLS project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Enable a subset of openssl compatible functions. We don't aim to be 100%
* compatible - just to be able to do basic ports etc.
*
* Only really tested on mini_httpd, so I'm not too sure how extensive this
* port is.
*/
#include "nixio.h"
#include "config.h"
#define WITH_AXTLS 1
#define WITHOUT_OPENSSL 1
#define SSL_OP_NO_SSLv3 0x02000000L
#define SSL_OP_NO_SSLv2 0x01000000L
#define SSL_FILETYPE_PEM 1
#define SSL_VERIFY_NONE 0x00
#define SSL_VERIFY_PEER 0x01
#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
#define SSL_VERIFY_CLIENT_ONCE 0x03
#define MD5_DIGEST_LENGTH 16
#define SHA_DIGEST_LENGTH 20
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "ssl.h"
typedef SHA1_CTX SHA_CTX;
void *SSLv23_server_method(void);
void *SSLv3_server_method(void);
void *TLSv1_server_method(void);
void *SSLv23_client_method(void);
void *SSLv3_client_method(void);
void *TLSv1_client_method(void);
void *SSLv23_method(void);
void *TLSv1_method(void);
typedef void * (*ssl_func_type_t)(void);
typedef void * (*bio_func_type_t)(void);
SSL_CTX * SSL_CTX_new(void *meth);
void SSL_CTX_free(SSL_CTX * ssl_ctx);
SSL * SSL_new(SSL_CTX *ssl_ctx);
int SSL_set_fd(SSL *s, int fd);
int SSL_accept(SSL *ssl);
int SSL_connect(SSL *ssl);
void SSL_free(SSL *ssl);
int SSL_read(SSL *ssl, void *buf, int num);
int SSL_write(SSL *ssl, const void *buf, int num);
int SSL_CTX_use_certificate_file(SSL_CTX *ssl_ctx, const char *file, int type);
int SSL_CTX_use_PrivateKey_file(SSL_CTX *ssl_ctx, const char *file, int type);
int SSL_CTX_use_certificate_ASN1(SSL_CTX *ssl_ctx, int len, const uint8_t *d);
int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
unsigned int sid_ctx_len);
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
int SSL_CTX_use_certificate_chain_file(SSL_CTX *ssl_ctx, const char *file);
int SSL_shutdown(SSL *ssl);
/*** get/set session ***/
SSL_SESSION *SSL_get1_session(SSL *ssl);
int SSL_set_session(SSL *ssl, SSL_SESSION *session);
void SSL_SESSION_free(SSL_SESSION *session);
/*** end get/set session ***/
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
int (*verify_callback)(int, void *));
void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth);
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath);
void *SSL_load_client_CA_file(const char *file);
void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file);
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
int SSL_peek(SSL *ssl, void *buf, int num);
void SSL_set_bio(SSL *ssl, void *rbio, void *wbio);
long SSL_get_verify_result(const SSL *ssl);
int SSL_state(SSL *ssl);
/** end of could do better list */
void *SSL_get_peer_certificate(const SSL *ssl);
int SSL_clear(SSL *ssl);
int SSL_CTX_check_private_key(const SSL_CTX *ctx);
int SSL_CTX_set_cipher_list(SSL_CTX *s, const char *str);
int SSL_get_error(const SSL *ssl, int ret);
void SSL_CTX_set_options(SSL_CTX *ssl_ctx, int option);
int SSL_library_init(void );
void SSL_load_error_strings(void );
void ERR_print_errors_fp(FILE *fp);
long SSL_CTX_get_timeout(const SSL_CTX *ssl_ctx);
long SSL_CTX_set_timeout(SSL_CTX *ssl_ctx, long t);
void BIO_printf(FILE *f, const char *format, ...);
void* BIO_s_null(void);
FILE *BIO_new(bio_func_type_t func);
FILE *BIO_new_fp(FILE *stream, int close_flag);
int BIO_free(FILE *a);

313
libs/nixio/src/binary.c Normal file
View file

@ -0,0 +1,313 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio.h"
#include <stdlib.h>
static char nixio__bin2hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
static unsigned char nixio__b64encode_tbl[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static unsigned char nixio__b64decode_tbl[] = {
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
};
static const uint32_t nixio__crc32_tbl[] = {
0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
0x2d02ef8dU
};
static int nixio_bin_crc32(lua_State *L) {
size_t len;
const char *buffer = luaL_checklstring(L, 1, &len);
uint32_t value = luaL_optnumber(L, 2, 0);
value = ~value;
for (size_t i=0; i<len; i++) {
value = nixio__crc32_tbl[(value ^ buffer[i]) & 0xffU ] ^ (value >> 8);
}
lua_pushinteger(L, (int)(value ^ 0xffffffffU));
return 1;
}
static int nixio_bin_hexlify(lua_State *L) {
size_t len, lenout;
luaL_checktype(L, 1, LUA_TSTRING);
const unsigned char *data = (unsigned char*)lua_tolstring(L, 1, &len);
if (len == 0) {
lua_pushvalue(L, 1);
return 1;
}
lenout = len * 2;
luaL_argcheck(L, lenout > len, 1, "size overflow");
char *out = malloc(lenout);
if (!out) {
return luaL_error(L, NIXIO_OOM);
}
for (size_t i=0; i < len; i++) {
out[2*i] = nixio__bin2hex[(data[i] & 0xf0) >> 4];
out[2*i+1] = nixio__bin2hex[(data[i] & 0x0f)];
}
lua_pushlstring(L, out, lenout);
free(out);
return 1;
}
static int nixio_bin_unhexlify(lua_State *L) {
size_t len, lenout;
const char *data = luaL_checklstring(L, 1, &len);
if (len == 0) {
lua_pushvalue(L, 1);
return 1;
} else if (len % 2) {
errno = EINVAL;
return nixio__perror(L);
}
lenout = len / 2;
char *out = malloc(lenout);
if (!out) {
return luaL_error(L, NIXIO_OOM);
}
for (size_t i=0; i < lenout; i++) {
char c = data[2*i];
if (c >= '0' && c <= '9') {
out[i] = (c - '0') << 4;
} else if (c >= 'a' && c <= 'f') {
out[i] = (c - 'a' + 10) << 4;
} else if (data[2*i] >= 'A' && c <= 'F') {
out[i] = (c - 'A' + 10) << 4;
} else {
free(out);
errno = EINVAL;
return nixio__perror(L);
}
c = data[2*i+1];
if (c >= '0' && c <= '9') {
out[i] += c - '0';
} else if (c >= 'a' && c <= 'f') {
out[i] += c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
out[i] += c - 'A' + 10;
} else {
free(out);
errno = EINVAL;
return nixio__perror(L);
}
}
lua_pushlstring(L, out, lenout);
free(out);
return 1;
}
static int nixio_bin_b64encode(lua_State *L) {
size_t len, lenout, pad, i;
const char *data = luaL_checklstring(L, 1, &len);
lenout = len / 3;
lenout *= 4;
pad = len % 3;
if (len == 0) {
lua_pushvalue(L, 1);
return 1;
} else if (pad) {
lenout += 4;
}
luaL_argcheck(L, lenout > len, 1, "size overflow");
char *out = malloc(lenout);
if (!out) {
return luaL_error(L, NIXIO_OOM);
}
char *o = out;
for (i = 0; i < len; i += 3) {
uint32_t cv = (data[i] << 16) | (data[i+1] << 8) | data[i+2];
*(o+3) = nixio__b64encode_tbl[ cv & 0x3f];
*(o+2) = nixio__b64encode_tbl[(cv >> 6) & 0x3f];
*(o+1) = nixio__b64encode_tbl[(cv >> 12) & 0x3f];
*o = nixio__b64encode_tbl[(cv >> 18) & 0x3f];
o += 4;
}
if (pad) {
uint32_t cv = data[len-pad] << 16;
*(o-1) = '=';
*(o-2) = '=';
if (pad == 2) {
cv |= data[len-pad+1] << 8;
*(o-2) = nixio__b64encode_tbl[(cv >> 6) & 0x3f];
}
*(o-3) = nixio__b64encode_tbl[(cv >> 12) & 0x3f];
*(o-4) = nixio__b64encode_tbl[(cv >> 18) & 0x3f];
}
lua_pushlstring(L, out, lenout);
free(out);
return 1;
}
static int nixio_bin_b64decode(lua_State *L) {
size_t len, lenout, i;
const char *dt = luaL_checklstring(L, 1, &len);
if (len == 0) {
lua_pushvalue(L, 1);
return 1;
} else if (len % 4) {
errno = EINVAL;
return nixio__perror(L);
}
lenout = len / 4 * 3;
unsigned char *out = malloc(lenout);
if (!out) {
return luaL_error(L, NIXIO_OOM);
}
unsigned char *o = out;
for (i = 0; i < len; i += 4) {
uint32_t cv = 0;
for (int j = 0; j < 4; j++) {
unsigned char c = dt[i + j] - 43;
if (c > 79 || (c = nixio__b64decode_tbl[c]) == 0xff) {
free(out);
errno = EINVAL;
return nixio__perror(L);
}
cv |= c;
if (j != 3) {
cv <<= 6;
}
}
*(o+2) = (unsigned char)(cv & 0xff);
*(o+1) = (unsigned char)((cv >> 8) & 0xff);
*o = (unsigned char)((cv >> 16) & 0xff);
o += 3;
}
if (dt[len-1] == '=') {
lenout--;
}
if (dt[len-2] == '=') {
lenout--;
}
lua_pushlstring(L, (char*)out, lenout);
free(out);
return 1;
}
/* module table */
static const luaL_reg R[] = {
{"hexlify", nixio_bin_hexlify},
{"unhexlify", nixio_bin_unhexlify},
{"crc32", nixio_bin_crc32},
{"b64encode", nixio_bin_b64encode},
{"b64decode", nixio_bin_b64decode},
{NULL, NULL}
};
void nixio_open_bin(lua_State *L) {
lua_newtable(L);
luaL_register(L, NULL, R);
lua_setfield(L, -2, "bin");
}

View file

@ -18,15 +18,11 @@
#include "nixio.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
/**
* connect()/bind() shortcut
*/
@ -87,6 +83,9 @@ static int nixio__bind_connect(lua_State *L, int do_bind) {
}
if (do_bind) {
int one = 1;
setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR,
(char*)&one, sizeof(one));
status = bind(sock->fd, rp->ai_addr, rp->ai_addrlen);
} else {
do {
@ -103,7 +102,11 @@ static int nixio__bind_connect(lua_State *L, int do_bind) {
}
do {
#ifndef __WINNT__
clstat = close(sock->fd);
#else
clstat = closesocket(sock->fd);
#endif
} while (clstat == -1 && errno == EINTR);
}
@ -111,7 +114,7 @@ static int nixio__bind_connect(lua_State *L, int do_bind) {
/* on failure */
if (status) {
return nixio__perror(L);
return nixio__perror_s(L);
}
luaL_getmetatable(L, NIXIO_META);
@ -183,6 +186,7 @@ static int nixio_sock__bind_connect(lua_State *L, int do_bind) {
}
freeaddrinfo(result);
#ifndef __WINNT__
} else if (sock->domain == AF_UNIX) {
size_t pathlen;
const char *path = luaL_checklstring(L, 2, &pathlen);
@ -200,10 +204,11 @@ static int nixio_sock__bind_connect(lua_State *L, int do_bind) {
sizeof(addr));
} while (status == -1 && errno == EINTR);
}
#endif
} else {
return luaL_error(L, "not supported");
}
return nixio__pstatus(L, !status);
return nixio__pstatus_s(L, !status);
}
/**
@ -225,8 +230,8 @@ static int nixio_sock_connect(lua_State *L) {
*/
static int nixio_sock_listen(lua_State *L) {
int sockfd = nixio__checksockfd(L);
lua_Integer backlog = luaL_checkinteger(L, 2);
return nixio__pstatus(L, !listen(sockfd, backlog));
int backlog = luaL_checkinteger(L, 2);
return nixio__pstatus_s(L, !listen(sockfd, backlog));
}
/**
@ -234,18 +239,16 @@ static int nixio_sock_listen(lua_State *L) {
*/
static int nixio_sock_accept(lua_State *L) {
nixio_sock *sock = nixio__checksock(L);
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
char ipaddr[INET6_ADDRSTRLEN];
void *binaddr;
uint16_t port;
struct sockaddr_storage saddr;
nixio_addr addr;
socklen_t saddrlen = sizeof(saddr);
int newfd;
do {
newfd = accept(sock->fd, (struct sockaddr *)&addr, &addrlen);
newfd = accept(sock->fd, (struct sockaddr *)&saddr, &saddrlen);
} while (newfd == -1 && errno == EINTR);
if (newfd < 0) {
return nixio__perror(L);
return nixio__perror_s(L);
}
/* create userdata */
@ -256,25 +259,13 @@ static int nixio_sock_accept(lua_State *L) {
memcpy(clsock, sock, sizeof(clsock));
clsock->fd = newfd;
if (addr.ss_family == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in*)&addr;
port = inetaddr->sin_port;
binaddr = &inetaddr->sin_addr;
} else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6*)&addr;
port = inet6addr->sin6_port;
binaddr = &inet6addr->sin6_addr;
if (!nixio__addr_parse(&addr, (struct sockaddr *)&saddr)) {
lua_pushstring(L, addr.host);
lua_pushnumber(L, addr.port);
return 3;
} else {
return luaL_error(L, "unknown address family");
return 1;
}
if (!inet_ntop(addr.ss_family, binaddr, ipaddr, sizeof(ipaddr))) {
return nixio__perror(L);
}
lua_pushstring(L, ipaddr);
lua_pushinteger(L, ntohs(port));
return 3;
}
/* module table */

125
libs/nixio/src/bit.c Normal file
View file

@ -0,0 +1,125 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio.h"
#include <stdint.h>
#include <stdlib.h>
/* 52 bit maximum precision */
#define NIXIO_BIT_BMAX 52
#define NIXIO_BIT_NMAX 0xfffffffffffff
#define NIXIO_BIT_XOP(BIT_XOP) \
uint64_t oper = luaL_checknumber(L, 1); \
const int args = lua_gettop(L); \
\
for (int i = 2; i <= args; i++) { \
uint64_t oper2 = luaL_checknumber(L, i); \
oper BIT_XOP oper2; \
} \
\
lua_pushnumber(L, oper); \
return 1; \
static int nixio_bit_or(lua_State *L) {
NIXIO_BIT_XOP(|=);
}
static int nixio_bit_and(lua_State *L) {
NIXIO_BIT_XOP(&=);
}
static int nixio_bit_xor(lua_State *L) {
NIXIO_BIT_XOP(^=);
}
static int nixio_bit_unset(lua_State *L) {
NIXIO_BIT_XOP(&= ~);
}
static int nixio_bit_not(lua_State *L) {
lua_pushnumber(L, (~((uint64_t)luaL_checknumber(L, 1))) & NIXIO_BIT_NMAX);
return 1;
}
static int nixio_bit_shl(lua_State *L) {
uint64_t oper = luaL_checknumber(L, 1);
oper <<= luaL_checkinteger(L, 2);
if (oper > NIXIO_BIT_NMAX) {
return luaL_error(L, "arithmetic overflow");
} else {
lua_pushnumber(L, oper);
return 1;
}
}
static int nixio_bit_ashr(lua_State *L) {
int64_t oper = luaL_checknumber(L, 1);
lua_pushnumber(L, oper >> luaL_checkinteger(L, 2));
return 1;
}
static int nixio_bit_shr(lua_State *L) {
uint64_t oper = luaL_checknumber(L, 1);
lua_pushnumber(L, oper >> luaL_checkinteger(L, 2));
return 1;
}
static int nixio_bit_div(lua_State *L) {
NIXIO_BIT_XOP(/=);
}
static int nixio_bit_check(lua_State *L) {
uint64_t oper = luaL_checknumber(L, 1);
uint64_t oper2 = luaL_checknumber(L, 2);
lua_pushboolean(L, (oper & oper2) == oper2);
return 1;
}
static int nixio_bit_cast(lua_State *L) {
lua_pushnumber(L, ((uint64_t)luaL_checknumber(L, 1)) & NIXIO_BIT_NMAX);
return 1;
}
/* module table */
static const luaL_reg R[] = {
{"bor", nixio_bit_or},
{"set", nixio_bit_or},
{"band", nixio_bit_and},
{"bxor", nixio_bit_xor},
{"unset", nixio_bit_unset},
{"bnot", nixio_bit_not},
{"rshift", nixio_bit_shr},
{"arshift", nixio_bit_ashr},
{"lshift", nixio_bit_shl},
{"div", nixio_bit_div},
{"check", nixio_bit_check},
{"cast", nixio_bit_cast},
{NULL, NULL}
};
void nixio_open_bit(lua_State *L) {
lua_newtable(L);
luaL_register(L, NULL, R);
lua_pushnumber(L, NIXIO_BIT_BMAX);
lua_setfield(L, -2, "bits");
lua_pushnumber(L, NIXIO_BIT_NMAX);
lua_setfield(L, -2, "max");
lua_setfield(L, -2, "bit");
}

View file

@ -30,12 +30,37 @@
static int nixio_open(lua_State *L) {
const char *filename = luaL_checklstring(L, 1, NULL);
int flags = luaL_optint(L, 2, O_RDONLY);
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
int flags;
if (lua_isnoneornil(L, 2)) {
flags = O_RDONLY;
} else if (lua_isnumber(L, 2)) {
flags = lua_tointeger(L, 2);
} else if (lua_isstring(L, 2)) {
const char *str = lua_tostring(L, 2);
if (!strcmp(str, "r")) {
flags = O_RDONLY;
} else if (!strcmp(str, "r+")) {
flags = O_RDWR;
} else if (!strcmp(str, "w")) {
flags = O_WRONLY | O_CREAT | O_TRUNC;
} else if (!strcmp(str, "w+")) {
flags = O_RDWR | O_CREAT | O_TRUNC;
} else if (!strcmp(str, "a")) {
flags = O_WRONLY | O_CREAT | O_APPEND;
} else if (!strcmp(str, "a+")) {
flags = O_RDWR | O_CREAT | O_APPEND;
} else {
return luaL_argerror(L, 2, "supported values: r, r+, w, w+, a, a+");
}
} else {
return luaL_argerror(L, 2, "open flags or string expected");
}
int fd;
do {
fd = open(filename, flags, mode);
fd = open(filename, flags, nixio__check_mode(L, 3, 0666));
} while (fd == -1 && errno == EINTR);
if (fd == -1) {
return nixio__perror(L);
@ -66,9 +91,13 @@ static int nixio_open_flags(lua_State *L) {
} else if (!strcmp(flag, "excl")) {
mode |= O_EXCL;
} else if (!strcmp(flag, "nonblock") || !strcmp(flag, "ndelay")) {
#ifndef __WINNT__
mode |= O_NONBLOCK;
#endif
} else if (!strcmp(flag, "sync")) {
#ifndef __WINNT__
mode |= O_SYNC;
#endif
} else if (!strcmp(flag, "trunc")) {
mode |= O_TRUNC;
} else if (!strcmp(flag, "rdonly")) {
@ -141,6 +170,23 @@ static int nixio_file_write(lua_State *L) {
ssize_t sent;
const char *data = luaL_checklstring(L, 2, &len);
if (lua_gettop(L) > 2) {
int offset = luaL_optint(L, 3, 0);
if (offset) {
if (offset < len) {
data += offset;
len -= offset;
} else {
len = 0;
}
}
unsigned int wlen = luaL_optint(L, 4, len);
if (wlen < len) {
len = wlen;
}
}
do {
sent = write(fd, data, len);
} while(sent == -1 && errno == EINTR);
@ -155,7 +201,7 @@ static int nixio_file_write(lua_State *L) {
static int nixio_file_read(lua_State *L) {
int fd = nixio__checkfd(L, 1);
char buffer[NIXIO_BUFFERSIZE];
int req = luaL_checkinteger(L, 2);
uint req = luaL_checkinteger(L, 2);
int readc;
/* We limit the readsize to NIXIO_BUFFERSIZE */
@ -208,13 +254,33 @@ static int nixio_file_tell(lua_State *L) {
}
}
static int nixio_file_stat(lua_State *L) {
nixio_stat_t buf;
if (fstat(nixio__checkfd(L, 1), &buf)) {
return nixio__perror(L);
} else {
nixio__push_stat(L, &buf);
if (lua_isstring(L, 2)) {
lua_getfield(L, -1, lua_tostring(L, 2));
}
return 1;
}
}
static int nixio_file_sync(lua_State *L) {
int fd = nixio__checkfd(L, 1);
#ifndef BSD
int meta = lua_toboolean(L, 2);
return nixio__pstatus(L, (meta) ? !fsync(fd) : !fdatasync(fd));
int stat;
#if (!defined BSD && !defined __WINNT__)
int dataonly = lua_toboolean(L, 2);
do {
stat = (dataonly) ? fdatasync(fd) : fsync(fd);
} while (stat == -1 && errno == EINTR);
return nixio__pstatus(L, !stat);
#else
return nixio__pstatus(L, !fsync(fd));
do {
stat = fsync(fd);
} while (stat == -1 && errno == EINTR);
return nixio__pstatus(L, !stat);
#endif
}
@ -282,6 +348,7 @@ static const luaL_reg M[] = {
{"read", nixio_file_read},
{"tell", nixio_file_tell},
{"seek", nixio_file_seek},
{"stat", nixio_file_stat},
{"sync", nixio_file_sync},
{"lock", nixio_file_lock},
{"close", nixio_file_close},
@ -306,5 +373,26 @@ void nixio_open_file(lua_State *L) {
luaL_register(L, NULL, M);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
int *uin = lua_newuserdata(L, sizeof(int));
int *uout = lua_newuserdata(L, sizeof(int));
int *uerr = lua_newuserdata(L, sizeof(int));
if (!uin || !uout || !uerr) {
luaL_error(L, "out of memory");
}
*uin = STDIN_FILENO;
*uout = STDOUT_FILENO;
*uerr = STDERR_FILENO;
for (int i = -4; i < -1; i++) {
lua_pushvalue(L, -4);
lua_setmetatable(L, i);
}
lua_setfield(L, -5, "stderr");
lua_setfield(L, -4, "stdout");
lua_setfield(L, -3, "stdin");
lua_setfield(L, -2, "meta_file");
}

566
libs/nixio/src/fs.c Normal file
View file

@ -0,0 +1,566 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio.h"
#include <libgen.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <dirent.h>
/* Reads argument from given index and transforms it into a mode bitfield */
int nixio__check_mode(lua_State *L, int idx, int def) {
if (lua_isnoneornil(L, idx) && def > 0) {
return def;
} else if (lua_isstring(L, idx) && lua_objlen(L, idx) == 9) {
int mode = 0;
const char *modestr = lua_tostring(L, idx);
int i;
for (i=0; i<9; i++) {
if (i % 3 == 0) { /* read flags */
if (modestr[i] == 'r') {
mode |= 1 << (8 - i);
} else if (modestr[i] != '-') {
break;
}
} else if (i % 3 == 1) { /* write flags */
if (modestr[i] == 'w') {
mode |= 1 << (8 - i);
} else if (modestr[i] != '-') {
break;
}
} else if (i == 2) {
if (modestr[i] == 'x') {
mode |= 00100;
} else if (modestr[i] == 's') {
mode |= 04100;
} else if (modestr[i] == 'S') {
mode |= 04000;
} else if (modestr[i] != '-') {
break;
}
} else if (i == 5) {
if (modestr[i] == 'x') {
mode |= 00010;
} else if (modestr[i] == 's') {
mode |= 02010;
} else if (modestr[i] == 'S') {
mode |= 02000;
} else if (modestr[i] != '-') {
break;
}
} else if (i == 8) {
if (modestr[i] == 'x') {
mode |= 00001;
} else if (modestr[i] == 't') {
mode |= 01001;
} else if (modestr[i] == 'T') {
mode |= 01000;
} else if (modestr[i] != '-') {
break;
}
}
}
if (i == 9) { /* successfully parsed */
return mode;
}
} else if (lua_isnumber(L, idx)) {
int decmode = lua_tointeger(L, idx);
int s = (decmode % 10000) / 1000;
int u = (decmode % 1000) / 100;
int g = (decmode % 100) / 10;
int o = (decmode % 10);
if (s>=0 && s<=7 && u>=0 && u<=7 && g>=0 && g<=7 && o>=0 && o<=7) {
return (s << 9) + (u << 6) + (g << 3) + o;
}
}
return luaL_argerror(L, idx, "supported values: [0-7]?[0-7][0-7][0-7], "
"[-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]");
}
/* Transforms a mode into the modestring */
int nixio__mode_write(int mode, char *modestr) {
if (modestr) {
modestr[0] = (mode & 00400) ? 'r' : '-';
modestr[1] = (mode & 00200) ? 'w' : '-';
modestr[2] = ((mode & 04100) == 04100) ? 's' :
(mode & 04000) ? 'S' : (mode & 00100) ? 'x' : '-';
modestr[3] = (mode & 00040) ? 'r' : '-';
modestr[4] = (mode & 00020) ? 'w' : '-';
modestr[5] = ((mode & 02010) == 02010) ? 's' :
(mode & 02000) ? 'S' : (mode & 00010) ? 'x' : '-';
modestr[6] = (mode & 00004) ? 'r' : '-';
modestr[7] = (mode & 00002) ? 'w' : '-';
modestr[8] = ((mode & 01001) == 01001) ? 't' :
(mode & 01000) ? 'T' : (mode & 00001) ? 'x' : '-';
}
return (mode & 00007) + ((mode & 00070) >> 3) * 10 +
((mode & 00700) >> 6) * 100 + ((mode & 07000) >> 9) * 1000;
}
static int nixio_access(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
int mode = F_OK;
for (const char *s = luaL_optstring(L, 2, "f"); *s; s++) {
if (*s == 'r') {
mode |= R_OK;
} else if (*s == 'w') {
mode |= W_OK;
} else if (*s == 'x') {
mode |= X_OK;
} else if (*s != 'f') {
return luaL_argerror(L, 2, "supported values: [frwx]");
}
}
return nixio__pstatus(L, !access(path, mode));
}
static int nixio_basename(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
char base[PATH_MAX];
base[PATH_MAX-1] = 0;
strncpy(base, path, PATH_MAX-1);
lua_pushstring(L, basename(base));
return 1;
}
static int nixio_dirname(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
char base[PATH_MAX];
base[PATH_MAX-1] = 0;
strncpy(base, path, PATH_MAX-1);
lua_pushstring(L, dirname(base));
return 1;
}
static int nixio_realpath(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
char real[PATH_MAX];
if (!realpath(path, real)) {
return nixio__perror(L);
} else {
lua_pushstring(L, real);
return 1;
}
}
static int nixio_remove(lua_State *L) {
return nixio__pstatus(L, !remove(luaL_checkstring(L, 1)));
}
static int nixio_unlink(lua_State *L) {
return nixio__pstatus(L, !unlink(luaL_checkstring(L, 1)));
}
static int nixio_rename(lua_State *L) {
return nixio__pstatus(L,
!rename(luaL_checkstring(L, 1), luaL_checkstring(L, 2)));
}
static int nixio_rmdir(lua_State *L) {
return nixio__pstatus(L, !rmdir(luaL_checkstring(L, 1)));
}
static int nixio_mkdir(lua_State *L) {
return nixio__pstatus(L,
!mkdir(luaL_checkstring(L, 1), nixio__check_mode(L, 2, 0777)));
}
static int nixio_chmod(lua_State *L) {
return nixio__pstatus(L,
!chmod(luaL_checkstring(L, 1), nixio__check_mode(L, 2, -1)));
}
static int nixio_dir__gc(lua_State *L) {
DIR **dirp = lua_touserdata(L, 1);
if (dirp && *dirp) {
closedir(*dirp);
*dirp = NULL;
}
return 0;
}
static int nixio_dir__iter(lua_State *L) {
DIR **dirp = lua_touserdata(L, lua_upvalueindex(1));
struct dirent *entry;
const char *n = NULL;
if (*dirp) {
do {
entry = readdir(*dirp);
n = (entry) ? entry->d_name : NULL;
} while(n && n[0] == '.' && (n[1] == 0 || (n[1] == '.' && n[2] == 0)));
}
if (n) {
lua_pushstring(L, n);
} else {
if (*dirp) {
closedir(*dirp);
*dirp = NULL;
}
lua_pushnil(L);
}
return 1;
}
static int nixio_dir(lua_State *L) {
const char *path = luaL_optstring(L, 1, ".");
DIR **dirp = lua_newuserdata(L, sizeof(DIR *));
*dirp = opendir(path);
if (!*dirp) {
return nixio__perror(L);
} else {
luaL_getmetatable(L, NIXIO_DIR_META);
lua_setmetatable(L, -2);
lua_pushcclosure(L, nixio_dir__iter, 1);
return 1;
}
}
static int nixio_link(lua_State *L) {
return nixio__pstatus(L,
!link(luaL_checkstring(L, 1), luaL_checkstring(L, 2)));
}
static int nixio_utimes(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
if (lua_gettop(L) < 2) {
return nixio__pstatus(L, !utimes(path, NULL));
} else {
double atime = luaL_checknumber(L, 2);
double mtime = luaL_optnumber(L, 3, atime);
struct timeval times[2];
times[0].tv_sec = atime;
times[0].tv_usec = (long)((atime - (int64_t)atime) * 1000000);
times[1].tv_sec = mtime;
times[1].tv_usec = (long)((mtime - (int64_t)mtime) * 1000000);
return nixio__pstatus(L, !utimes(path, times));
}
}
int nixio__push_stat(lua_State *L, nixio_stat_t *buf) {
lua_createtable(L, 0, 15);
lua_pushinteger(L, buf->st_dev);
lua_setfield(L, -2, "dev");
lua_pushinteger(L, buf->st_ino);
lua_setfield(L, -2, "ino");
if (S_ISREG(buf->st_mode)) {
lua_pushliteral(L, "reg");
} else if (S_ISDIR(buf->st_mode)) {
lua_pushliteral(L, "dir");
} else if (S_ISCHR(buf->st_mode)) {
lua_pushliteral(L, "chr");
} else if (S_ISBLK(buf->st_mode)) {
lua_pushliteral(L, "blk");
} else if (S_ISFIFO(buf->st_mode)) {
lua_pushliteral(L, "fifo");
} else if (S_ISLNK(buf->st_mode)) {
lua_pushliteral(L, "lnk");
} else if (S_ISSOCK(buf->st_mode)) {
lua_pushliteral(L, "sock");
} else {
lua_pushliteral(L, "unknown");
}
lua_setfield(L, -2, "type");
char modestr[9];
lua_pushinteger(L, nixio__mode_write(buf->st_mode, modestr));
lua_setfield(L, -2, "modedec");
lua_pushlstring(L, modestr, 9);
lua_setfield(L, -2, "modestr");
lua_pushinteger(L, buf->st_nlink);
lua_setfield(L, -2, "nlink");
lua_pushinteger(L, buf->st_uid);
lua_setfield(L, -2, "uid");
lua_pushinteger(L, buf->st_gid);
lua_setfield(L, -2, "gid");
lua_pushinteger(L, buf->st_rdev);
lua_setfield(L, -2, "rdev");
lua_pushnumber(L, buf->st_size);
lua_setfield(L, -2, "size");
lua_pushinteger(L, buf->st_atime);
lua_setfield(L, -2, "atime");
lua_pushinteger(L, buf->st_mtime);
lua_setfield(L, -2, "mtime");
lua_pushinteger(L, buf->st_ctime);
lua_setfield(L, -2, "ctime");
#ifndef __WINNT__
lua_pushinteger(L, buf->st_blksize);
lua_setfield(L, -2, "blksize");
lua_pushinteger(L, buf->st_blocks);
lua_setfield(L, -2, "blocks");
#endif
return 1;
}
static int nixio_stat(lua_State *L) {
nixio_stat_t buf;
if (stat(luaL_checkstring(L, 1), &buf)) {
return nixio__perror(L);
} else {
nixio__push_stat(L, &buf);
if (lua_isstring(L, 2)) {
lua_getfield(L, -1, lua_tostring(L, 2));
}
return 1;
}
}
static int nixio_lstat(lua_State *L) {
nixio_stat_t buf;
if (stat(luaL_checkstring(L, 1), &buf)) {
return nixio__perror(L);
} else {
nixio__push_stat(L, &buf);
if (lua_isstring(L, 2)) {
lua_getfield(L, -1, lua_tostring(L, 2));
}
return 1;
}
}
#ifndef __WINNT__
static int nixio_chown(lua_State *L) {
return nixio__pstatus(L,
!chown(
luaL_checkstring(L, 1),
lua_isnoneornil(L, 2) ? -1 : nixio__check_user(L, 2),
lua_isnoneornil(L, 3) ? -1 : nixio__check_group(L, 3)
)
);
}
static int nixio_lchown(lua_State *L) {
return nixio__pstatus(L,
!lchown(
luaL_checkstring(L, 1),
lua_isnoneornil(L, 2) ? -1 : nixio__check_user(L, 2),
lua_isnoneornil(L, 3) ? -1 : nixio__check_group(L, 3)
)
);
}
static int nixio_mkfifo(lua_State *L) {
return nixio__pstatus(L,
!mkfifo(luaL_checkstring(L, 1), nixio__check_mode(L, 2, -1)));
}
static int nixio_symlink(lua_State *L) {
return nixio__pstatus(L,
!symlink(luaL_checkstring(L, 1), luaL_checkstring(L, 2)));
}
static int nixio_readlink(lua_State *L) {
char dest[PATH_MAX];
ssize_t res = readlink(luaL_checkstring(L, 1), dest, sizeof(dest));
if (res < 0) {
return nixio__perror(L);
} else {
lua_pushlstring(L, dest, res);
return 1;
}
}
#include <glob.h>
typedef struct {
glob_t gl;
size_t pos;
int freed;
} nixio_glob_t;
static int nixio_glob__iter(lua_State *L) {
nixio_glob_t *globres = lua_touserdata(L, lua_upvalueindex(1));
if (!globres->freed && globres->pos < globres->gl.gl_pathc) {
lua_pushstring(L, globres->gl.gl_pathv[(globres->pos)++]);
} else {
if (!globres->freed) {
globfree(&globres->gl);
globres->freed = 1;
}
lua_pushnil(L);
}
return 1;
}
static int nixio_glob__gc(lua_State *L) {
nixio_glob_t *globres = lua_touserdata(L, 1);
if (globres && !globres->freed) {
globres->freed = 1;
globfree(&globres->gl);
}
return 0;
}
static int nixio_glob(lua_State *L) {
const char *pattern = luaL_optstring(L, 1, "*");
nixio_glob_t *globres = lua_newuserdata(L, sizeof(nixio_glob_t));
if (!globres) {
return luaL_error(L, NIXIO_OOM);
}
globres->pos = 0;
globres->freed = 0;
int globstat = glob(pattern, 0, NULL, &globres->gl);
if (globstat == GLOB_NOMATCH) {
lua_pushcfunction(L, nixio__nulliter);
lua_pushinteger(L, 0);
} else if (globstat) {
return nixio__perror(L);
} else {
luaL_getmetatable(L, NIXIO_GLOB_META);
lua_setmetatable(L, -2);
lua_pushcclosure(L, nixio_glob__iter, 1);
lua_pushinteger(L, globres->gl.gl_pathc);
}
return 2;
}
#include <sys/statvfs.h>
static int nixio__push_statvfs(lua_State *L, struct statvfs *buf) {
lua_createtable(L, 0, 12);
lua_pushnumber(L, buf->f_bavail);
lua_setfield(L, -2, "bavail");
lua_pushnumber(L, buf->f_bfree);
lua_setfield(L, -2, "bfree");
lua_pushnumber(L, buf->f_blocks);
lua_setfield(L, -2, "blocks");
lua_pushnumber(L, buf->f_bsize);
lua_setfield(L, -2, "bsize");
lua_pushnumber(L, buf->f_frsize);
lua_setfield(L, -2, "frsize");
lua_pushnumber(L, buf->f_favail);
lua_setfield(L, -2, "favail");
lua_pushnumber(L, buf->f_ffree);
lua_setfield(L, -2, "ffree");
lua_pushnumber(L, buf->f_files);
lua_setfield(L, -2, "files");
lua_pushnumber(L, buf->f_flag);
lua_setfield(L, -2, "flag");
lua_pushnumber(L, buf->f_fsid);
lua_setfield(L, -2, "fsid");
lua_pushnumber(L, buf->f_namemax);
lua_setfield(L, -2, "namemax");
return 1;
}
static int nixio_statvfs(lua_State *L) {
struct statvfs buf;
if (statvfs(luaL_optstring(L, 1, "."), &buf)) {
return nixio__perror(L);
} else {
return nixio__push_statvfs(L, &buf);
}
}
#endif /* !__WINNT__ */
/* module table */
static const luaL_reg R[] = {
#ifndef __WINNT__
{"glob", nixio_glob},
{"mkfifo", nixio_mkfifo},
{"symlink", nixio_symlink},
{"readlink", nixio_readlink},
{"chown", nixio_chown},
{"lchown", nixio_lchown},
{"statvfs", nixio_statvfs},
#endif
{"chmod", nixio_chmod},
{"access", nixio_access},
{"basename", nixio_basename},
{"dir", nixio_dir},
{"dirname", nixio_dirname},
{"realpath", nixio_realpath},
{"mkdir", nixio_mkdir},
{"rmdir", nixio_rmdir},
{"link", nixio_link},
{"unlink", nixio_unlink},
{"utimes", nixio_utimes},
{"rename", nixio_rename},
{"remove", nixio_remove},
{"stat", nixio_stat},
{"lstat", nixio_lstat},
{NULL, NULL}
};
void nixio_open_fs(lua_State *L) {
lua_newtable(L);
luaL_register(L, NULL, R);
lua_setfield(L, -2, "fs");
luaL_newmetatable(L, NIXIO_DIR_META);
lua_pushcfunction(L, nixio_dir__gc);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
#ifndef __WINNT__
luaL_newmetatable(L, NIXIO_GLOB_META);
lua_pushcfunction(L, nixio_glob__gc);
lua_setfield(L, -2, "__gc");
lua_pop(L, 1);
#endif
}

View file

@ -18,12 +18,10 @@
#include "nixio.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
/**
@ -33,34 +31,46 @@ static int nixio_sock__sendto(lua_State *L, int to) {
nixio_sock *sock = nixio__checksock(L);
struct sockaddr *addr = NULL;
socklen_t alen = 0;
int argoff = 2;
if (to) {
const char *address = luaL_checklstring(L, 3, NULL);
uint16_t port = (uint16_t)luaL_checkinteger(L, 4);
argoff += 2;
const char *address = luaL_checkstring(L, 3);
struct sockaddr_storage addrstor;
addr = (struct sockaddr*)&addrstor;
if (sock->domain == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in *)addr;
if (inet_pton(sock->domain, address, &inetaddr->sin_addr) < 0) {
return luaL_argerror(L, 3, "invalid address");
}
inetaddr->sin_port = htons(port);
alen = sizeof(*inetaddr);
} else if (sock->domain == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6 *)addr;
if (inet_pton(sock->domain, address, &inet6addr->sin6_addr) < 0) {
return luaL_argerror(L, 3, "invalid address");
}
inet6addr->sin6_port = htons(port);
alen = sizeof(*inet6addr);
} else {
return luaL_argerror(L, 1, "supported families: inet, inet6");
nixio_addr naddr;
memset(&naddr, 0, sizeof(naddr));
strncpy(naddr.host, address, sizeof(naddr.host) - 1);
naddr.port = (uint16_t)luaL_checkinteger(L, 4);
naddr.family = sock->domain;
if (nixio__addr_write(&naddr, addr)) {
return nixio__perror_s(L);
}
}
size_t len;
ssize_t sent;
const char *data = luaL_checklstring(L, 2, &len);
if (lua_gettop(L) > argoff) {
int offset = luaL_optint(L, argoff + 1, 0);
if (offset) {
if (offset < len) {
data += offset;
len -= offset;
} else {
len = 0;
}
}
unsigned int wlen = luaL_optint(L, argoff + 2, len);
if (wlen < len) {
len = wlen;
}
}
do {
sent = sendto(sock->fd, data, len, 0, addr, alen);
} while(sent == -1 && errno == EINTR);
@ -68,7 +78,7 @@ static int nixio_sock__sendto(lua_State *L, int to) {
lua_pushinteger(L, sent);
return 1;
} else {
return nixio__perror(L);
return nixio__perror_s(L);
}
}
@ -94,7 +104,7 @@ static int nixio_sock__recvfrom(lua_State *L, int from) {
nixio_sock *sock = nixio__checksock(L);
char buffer[NIXIO_BUFFERSIZE];
struct sockaddr_storage addrobj;
int req = luaL_checkinteger(L, 2);
uint req = luaL_checkinteger(L, 2);
int readc;
if (from && sock->domain != AF_INET && sock->domain != AF_INET6) {
@ -111,38 +121,31 @@ static int nixio_sock__recvfrom(lua_State *L, int from) {
readc = recvfrom(sock->fd, buffer, req, 0, addr, &alen);
} while (readc == -1 && errno == EINTR);
#ifdef __WINNT__
if (readc < 0) {
return nixio__perror(L);
int e = WSAGetLastError();
if (e == WSAECONNRESET || e == WSAECONNABORTED || e == WSAESHUTDOWN) {
readc = 0;
}
}
#endif
if (readc < 0) {
return nixio__perror_s(L);
} else {
lua_pushlstring(L, buffer, readc);
if (!from) {
return 1;
} else {
char ipaddr[INET6_ADDRSTRLEN];
void *binaddr;
uint16_t port;
if (addrobj.ss_family == AF_INET) {
struct sockaddr_in *inetaddr = (struct sockaddr_in*)addr;
port = inetaddr->sin_port;
binaddr = &inetaddr->sin_addr;
} else if (addrobj.ss_family == AF_INET6) {
struct sockaddr_in6 *inet6addr = (struct sockaddr_in6*)addr;
port = inet6addr->sin6_port;
binaddr = &inet6addr->sin6_addr;
nixio_addr naddr;
if (!nixio__addr_parse(&naddr, (struct sockaddr *)&addrobj)) {
lua_pushstring(L, naddr.host);
lua_pushnumber(L, naddr.port);
return 3;
} else {
return luaL_error(L, "unknown address family");
return 1;
}
if (!inet_ntop(addrobj.ss_family, binaddr, ipaddr, sizeof(ipaddr))) {
return nixio__perror(L);
}
lua_pushstring(L, ipaddr);
lua_pushinteger(L, ntohs(port));
return 3;
}
}
}

View file

@ -0,0 +1,220 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio.h"
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/locking.h>
#include <sys/time.h>
#include <sys/utime.h>
void nixio_open__mingw(lua_State *L) {
_fmode = _O_BINARY;
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa)) {
luaL_error(L, "Unable to initialize Winsock");
}
lua_newtable(L);
NIXIO_WSA_CONSTANT(WSAEACCES);
NIXIO_WSA_CONSTANT(WSAEINTR);
NIXIO_WSA_CONSTANT(WSAEINVAL);
NIXIO_WSA_CONSTANT(WSAEBADF);
NIXIO_WSA_CONSTANT(WSAEFAULT);
NIXIO_WSA_CONSTANT(WSAEMFILE);
NIXIO_WSA_CONSTANT(WSAENAMETOOLONG);
NIXIO_WSA_CONSTANT(WSAELOOP);
NIXIO_WSA_CONSTANT(WSAEAFNOSUPPORT);
NIXIO_WSA_CONSTANT(WSAENOBUFS);
NIXIO_WSA_CONSTANT(WSAEPROTONOSUPPORT);
NIXIO_WSA_CONSTANT(WSAENOPROTOOPT);
NIXIO_WSA_CONSTANT(WSAEADDRINUSE);
NIXIO_WSA_CONSTANT(WSAENETDOWN);
NIXIO_WSA_CONSTANT(WSAENETUNREACH);
NIXIO_WSA_CONSTANT(WSAECONNABORTED);
NIXIO_WSA_CONSTANT(WSAECONNRESET);
lua_setfield(L, -2, "const_sock");
}
const char* nixio__mgw_inet_ntop
(int af, const void *src, char *dst, socklen_t size) {
struct sockaddr_storage saddr;
memset(&saddr, 0, sizeof(saddr));
DWORD hostlen = size, sl;
if (af == AF_INET) {
struct sockaddr_in *saddr4 = (struct sockaddr_in *)&saddr;
memcpy(&saddr4->sin_addr, src, sizeof(saddr4->sin_addr));
saddr4->sin_family = AF_INET;
saddr4->sin_port = 0;
sl = sizeof(struct sockaddr_in);
} else if (af == AF_INET6) {
struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&saddr;
memcpy(&saddr6->sin6_addr, src, sizeof(saddr6->sin6_addr));
saddr6->sin6_family = AF_INET6;
saddr6->sin6_port = 0;
sl = sizeof(struct sockaddr_in6);
} else {
return NULL;
}
if (WSAAddressToString((struct sockaddr*)&saddr, sl, NULL, dst, &hostlen)) {
return NULL;
}
return dst;
}
int nixio__mgw_inet_pton (int af, const char *src, void *dst) {
struct sockaddr_storage sa;
int sl = sizeof(sa);
if (!WSAStringToAddress((char*)src, af, NULL, (struct sockaddr*)&sa, &sl)) {
if (af == AF_INET) {
struct in_addr ina = ((struct sockaddr_in *)&sa)->sin_addr;
memcpy(dst, &ina, sizeof(ina));
return 1;
} else if (af == AF_INET6) {
struct in_addr6 ina6 = ((struct sockaddr_in6 *)&sa)->sin6_addr;
memcpy(dst, &ina6, sizeof(ina6));
return 1;
} else {
WSASetLastError(WSAEAFNOSUPPORT);
return -1;
}
} else {
return -1;
}
}
int nixio__mgw_nanosleep(const struct timespec *req, struct timespec *rem) {
if (rem) {
rem->tv_sec = 0;
rem->tv_nsec = 0;
}
Sleep(req->tv_sec * 1000 + req->tv_nsec * 1000000);
return 0;
}
int nixio__mgw_poll(struct pollfd *fds, int nfds, int timeout) {
if (!fds || !nfds) {
Sleep(timeout);
return 0;
}
struct timeval tv;
int high = 0, rf = 0, wf = 0, ef = 0;
fd_set rfds, wfds, efds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
for (int i = 0; i < nfds; i++) {
if (fds->events & POLLIN) {
FD_SET(fds->fd, &rfds);
rf++;
}
if (fds->events & POLLOUT) {
FD_SET(fds->fd, &wfds);
wf++;
}
if (fds->events & POLLERR) {
FD_SET(fds->fd, &efds);
ef++;
}
if (fds->fd > high) {
high = fds->fd;
}
}
int stat = select(high + 1, (rf) ? &rfds : NULL,
(wf) ? &wfds : NULL, (ef) ? &efds : NULL, &tv);
if (stat < 1) {
errno = WSAGetLastError();
return stat;
}
high = 0;
for (int i = 0; i < nfds; i++) {
fds->revents = 0;
if ((fds->events & POLLIN) && FD_ISSET(fds->fd, &rfds)) {
fds->revents |= POLLIN;
}
if ((fds->events & POLLOUT) && FD_ISSET(fds->fd, &wfds)) {
fds->revents |= POLLOUT;
}
if ((fds->events & POLLERR) && FD_ISSET(fds->fd, &efds)) {
fds->revents |= POLLERR;
}
if (fds->revents) {
high++;
}
}
return high;
}
int nixio__mgw_lockf(int fd, int cmd, off_t len) {
int stat;
if (cmd == F_LOCK) {
do {
stat = _locking(fd, _LK_LOCK, len);
} while (stat == -1 && errno == EDEADLOCK);
} else if (cmd == F_TLOCK) {
stat = _locking(fd, _LK_NBLCK, len);
} else if (cmd == F_ULOCK) {
stat = _locking(fd, _LK_UNLCK, len);
} else {
stat = -1;
errno = EINVAL;
}
return stat;
}
char* nixio__mgw_realpath(const char *path, char *resolved) {
if (GetFullPathName(path, PATH_MAX, resolved, NULL)) {
return resolved;
} else {
errno = GetLastError();
return NULL;
}
}
int nixio__mgw_link(const char *oldpath, const char *newpath) {
if (!CreateHardLink(newpath, oldpath, NULL)) {
errno = GetLastError();
return -1;
} else {
return 0;
}
}
int nixio__mgw_utimes(const char *filename, const struct timeval times[2]) {
struct _utimbuf timebuffer;
timebuffer.actime = times[0].tv_sec;
timebuffer.modtime = times[1].tv_sec;
return _utime(filename, &timebuffer);
}

View file

@ -0,0 +1,112 @@
#ifndef NIXIO_MINGW_COMPAT_H_
#define NIXIO_MINGW_COMPAT_H_
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <process.h>
#include <stdint.h>
#include <sys/stat.h>
#include <errno.h>
typedef unsigned int uint;
typedef unsigned long ulong;
#define S_ISLNK(m) 0
#define S_ISSOCK(m) 0
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#define ENOPROTOOPT WSAENOPROTOOPT
#define SHUT_RD SD_RECEIVE
#define SHUT_WR SD_SEND
#define SHUT_RDWR SD_BOTH
#define pipe(fds) _pipe(fds, 65536, 0)
#define fsync _commit
#define lseek lseek64
#define stat _stati64
#define lstat _stati64
#define fstat _fstati64
#define F_LOCK 1
#define F_ULOCK 0
#define F_TLOCK 2
#define F_TEST 3
int nixio__mgw_lockf(int fd, int cmd, off_t len);
#define lockf nixio__mgw_lockf
const char* nixio__mgw_inet_ntop
(int af, const void *src, char *dst, socklen_t size);
#define inet_ntop nixio__mgw_inet_ntop
int nixio__mgw_inet_pton (int af, const char *src, void *dst);
#define inet_pton nixio__mgw_inet_pton
#ifndef POLLIN
#define POLLIN 0x001
#define POLLOUT 0x004
#define POLLERR 0x008
struct pollfd {
int fd;
short events;
short revents;
};
#endif
typedef int nfds_t;
int nixio__mgw_poll(struct pollfd *fds, nfds_t nfds, int timeout);
#define poll nixio__mgw_poll
struct timespec {
time_t tv_sec;
long tv_nsec;
};
int nixio__mgw_nanosleep(const struct timespec *req, struct timespec *rem);
#define nanosleep nixio__mgw_nanosleep
char* nixio__mgw_realpath(const char *path, char *resolved);
#define realpath nixio__mgw_realpath
int nixio__mgw_link(const char *oldpath, const char *newpath);
#define link nixio__mgw_link
int nixio__mgw_utimes(const char *filename, const struct timeval times[2]);
#define utimes nixio__mgw_utimes
#define setenv(k, v, o) !SetEnvironmentVariable(k, v)
#define unsetenv(k) !SetEnvironmentVariable(k, NULL)
#define execv(p, a) execv(p, (const char* const*)a)
#define execvp(p, a) execvp(p, (const char* const*)a)
#define execve(p, a, e) execve(p, (const char* const*)a, (const char* const*)e)
#define mkdir(p, m) mkdir(p)
#define nixio__perror_s(L) \
errno = WSAGetLastError(); \
return nixio__perror(L);
#define nixio__pstatus_s(L, c) \
errno = WSAGetLastError(); \
return nixio__pstatus(L, c);
#define NIXIO_WSA_CONSTANT(x) \
lua_pushinteger(L, x); \
lua_setfield(L, -2, #x+3);
void nixio_open__mingw(lua_State *L);
#endif /* NIXIO_MINGW_COMPAT_H_ */

View file

@ -2,9 +2,12 @@
#define NIXIO_TLS_H_
#include "nixio.h"
#include <sys/types.h>
#ifndef WITHOUT_OPENSSL
#include <openssl/ssl.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#endif
#define NIXIO_TLS_CTX_META "nixio.tls.ctx"
@ -20,4 +23,31 @@ typedef struct nixio_tls_socket {
#endif
} nixio_tls_sock;
#define NIXIO_CRYPTO_HASH_META "nixio.crypto.hash"
#define NIXIO_DIGEST_SIZE 64
#define NIXIO_CRYPTO_BLOCK_SIZE 64
#define NIXIO_HASH_NONE 0
#define NIXIO_HASH_MD5 0x01
#define NIXIO_HASH_SHA1 0x02
#define NIXIO_HMAC_BIT 0x40
typedef int(*nixio_hash_initcb)(void *);
typedef int(*nixio_hash_updatecb)(void *, const void *, unsigned long);
typedef int(*nixio_hash_finalcb)(unsigned char *, void *);
typedef struct nixio_hash_obj {
uint type;
unsigned char digest[NIXIO_DIGEST_SIZE];
size_t digest_size;
unsigned char key[NIXIO_CRYPTO_BLOCK_SIZE];
size_t key_size;
size_t block_size;
void *ctx;
nixio_hash_initcb init;
nixio_hash_updatecb update;
nixio_hash_finalcb final;
} nixio_hash;
#endif /* NIXIO_TLS_H_ */

View file

@ -27,7 +27,7 @@
/* pushes nil, error number and errstring on the stack */
int nixio__perror(lua_State *L) {
if (errno == EAGAIN) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
lua_pushboolean(L, 0);
} else {
lua_pushnil(L);
@ -85,6 +85,17 @@ int nixio__tofd(lua_State *L, int ud) {
return fd;
}
/* An empty iterator */
int nixio__nulliter(lua_State *L) {
lua_pushnil(L);
return 1;
}
static int nixio_errno(lua_State *L) {
lua_pushinteger(L, errno);
return 1;
}
static int nixio_strerror(lua_State *L) {
lua_pushstring(L, strerror(luaL_checkinteger(L, 1)));
return 1;
@ -92,12 +103,13 @@ static int nixio_strerror(lua_State *L) {
/* object table */
static const luaL_reg R[] = {
{"errno", nixio_errno},
{"strerror", nixio_strerror},
{NULL, NULL}
};
/* entry point */
LUALIB_API int luaopen_nixio(lua_State *L) {
NIXIO_API int luaopen_nixio(lua_State *L) {
/* create metatable */
luaL_newmetatable(L, NIXIO_META);
@ -113,6 +125,9 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
lua_setfield(L, -2, "meta_socket");
/* register methods */
#ifdef __WINNT__
nixio_open__mingw(L);
#endif
nixio_open_file(L);
nixio_open_socket(L);
nixio_open_sockopt(L);
@ -123,6 +138,11 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
nixio_open_splice(L);
nixio_open_process(L);
nixio_open_syslog(L);
nixio_open_bit(L);
nixio_open_bin(L);
nixio_open_fs(L);
nixio_open_user(L);
nixio_open_tls_crypto(L);
nixio_open_tls_context(L);
nixio_open_tls_socket(L);
@ -131,13 +151,21 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
lua_setfield(L, -2, "version");
/* some constants */
lua_createtable(L, 0, 49);
lua_newtable(L);
lua_pushliteral(L, NIXIO_SEP);
lua_setfield(L, -2, "sep");
lua_pushliteral(L, NIXIO_PATHSEP);
lua_setfield(L, -2, "pathsep");
lua_pushinteger(L, NIXIO_BUFFERSIZE);
lua_setfield(L, -2, "buffersize");
NIXIO_PUSH_CONSTANT(EACCES);
NIXIO_PUSH_CONSTANT(EINTR);
NIXIO_PUSH_CONSTANT(ENOSYS);
NIXIO_PUSH_CONSTANT(EINVAL);
NIXIO_PUSH_CONSTANT(EWOULDBLOCK);
NIXIO_PUSH_CONSTANT(EAGAIN);
NIXIO_PUSH_CONSTANT(ENOMEM);
NIXIO_PUSH_CONSTANT(ENOENT);
@ -152,37 +180,51 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
NIXIO_PUSH_CONSTANT(EISDIR);
NIXIO_PUSH_CONSTANT(EPERM);
NIXIO_PUSH_CONSTANT(EEXIST);
NIXIO_PUSH_CONSTANT(ELOOP);
NIXIO_PUSH_CONSTANT(EMFILE);
NIXIO_PUSH_CONSTANT(ENAMETOOLONG);
NIXIO_PUSH_CONSTANT(ENFILE);
NIXIO_PUSH_CONSTANT(ENODEV);
NIXIO_PUSH_CONSTANT(EXDEV);
NIXIO_PUSH_CONSTANT(ENOTDIR);
NIXIO_PUSH_CONSTANT(ENXIO);
NIXIO_PUSH_CONSTANT(EOVERFLOW);
NIXIO_PUSH_CONSTANT(EROFS);
NIXIO_PUSH_CONSTANT(EBUSY);
NIXIO_PUSH_CONSTANT(ESRCH);
NIXIO_PUSH_CONSTANT(SIGINT);
NIXIO_PUSH_CONSTANT(SIGTERM);
NIXIO_PUSH_CONSTANT(SIGSEGV);
#ifndef __WINNT__
NIXIO_PUSH_CONSTANT(EWOULDBLOCK);
NIXIO_PUSH_CONSTANT(ELOOP);
NIXIO_PUSH_CONSTANT(EOVERFLOW);
NIXIO_PUSH_CONSTANT(ETXTBSY);
NIXIO_PUSH_CONSTANT(EAFNOSUPPORT);
NIXIO_PUSH_CONSTANT(ENOBUFS);
NIXIO_PUSH_CONSTANT(EPROTONOSUPPORT);
NIXIO_PUSH_CONSTANT(ENOPROTOOPT);
NIXIO_PUSH_CONSTANT(EBUSY);
NIXIO_PUSH_CONSTANT(ESRCH);
NIXIO_PUSH_CONSTANT(EADDRINUSE);
NIXIO_PUSH_CONSTANT(ENETDOWN);
NIXIO_PUSH_CONSTANT(ENETUNREACH);
NIXIO_PUSH_CONSTANT(SIGALRM);
NIXIO_PUSH_CONSTANT(SIGINT);
NIXIO_PUSH_CONSTANT(SIGTERM);
NIXIO_PUSH_CONSTANT(SIGKILL);
NIXIO_PUSH_CONSTANT(SIGHUP);
NIXIO_PUSH_CONSTANT(SIGSTOP);
NIXIO_PUSH_CONSTANT(SIGCONT);
NIXIO_PUSH_CONSTANT(SIGSEGV);
NIXIO_PUSH_CONSTANT(SIGCHLD);
NIXIO_PUSH_CONSTANT(SIGQUIT);
NIXIO_PUSH_CONSTANT(SIGUSR1);
NIXIO_PUSH_CONSTANT(SIGUSR2);
NIXIO_PUSH_CONSTANT(SIGIO);
NIXIO_PUSH_CONSTANT(SIGURG);
NIXIO_PUSH_CONSTANT(SIGPIPE);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "const_sock");
signal(SIGPIPE, SIG_IGN);
#endif /* !__WINNT__ */
lua_setfield(L, -2, "const");
/* remove meta table */

View file

@ -1,9 +1,12 @@
#ifndef NIXIO_H_
#define NIXIO_H_
#define NIXIO_OOM "out of memory"
#define NIXIO_META "nixio.socket"
#define NIXIO_FILE_META "nixio.file"
#define NIXIO_BUFFERSIZE 8096
#define NIXIO_GLOB_META "nixio.glob"
#define NIXIO_DIR_META "nixio.dir"
#define _FILE_OFFSET_BITS 64
#define NIXIO_PUSH_CONSTANT(x) \
@ -17,6 +20,8 @@
#include <lualib.h>
#include <lauxlib.h>
#define NIXIO_BUFFERSIZE 8192
typedef struct nixio_socket {
int fd;
int domain;
@ -24,12 +29,66 @@ typedef struct nixio_socket {
int protocol;
} nixio_sock;
typedef struct nixio_address {
int family;
char host[128];
int port;
} nixio_addr;
int nixio__perror(lua_State *L);
int nixio__pstatus(lua_State *L, int condition);
#ifndef __WINNT__
#define NIXIO_API extern
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <sys/un.h>
#include <netdb.h>
#include <poll.h>
#include <sys/stat.h>
#include <errno.h>
#define NIXIO_SEP "/"
#define NIXIO_PATHSEP ":"
#define nixio__perror_s nixio__perror
#define nixio__pstatus_s nixio__pstatus
int nixio__check_group(lua_State *L, int idx);
int nixio__check_user(lua_State *L, int idx);
typedef struct stat nixio_stat_t;
#else /* __WINNT__ */
#define NIXIO_API extern __declspec(dllexport)
#define NIXIO_SEP "\\"
#define NIXIO_PATHSEP ";"
#include "mingw-compat.h"
typedef struct _stati64 nixio_stat_t;
#endif
nixio_sock* nixio__checksock(lua_State *L);
int nixio__checksockfd(lua_State *L);
int nixio__checkfd(lua_State *L, int ud);
int nixio__tofd(lua_State *L, int ud);
int nixio__nulliter(lua_State *L);
int nixio__addr_parse(nixio_addr *addr, struct sockaddr *saddr);
int nixio__addr_write(nixio_addr *addr, struct sockaddr *saddr);
int nixio__check_mode(lua_State *L, int idx, int def);
int nixio__mode_write(int mode, char *modestr);
int nixio__push_stat(lua_State *L, nixio_stat_t *buf);
/* Module functions */
void nixio_open_file(lua_State *L);
@ -42,6 +101,11 @@ void nixio_open_io(lua_State *L);
void nixio_open_splice(lua_State *L);
void nixio_open_process(lua_State *L);
void nixio_open_syslog(lua_State *L);
void nixio_open_bit(lua_State *L);
void nixio_open_bin(lua_State *L);
void nixio_open_fs(lua_State *L);
void nixio_open_user(lua_State *L);
void nixio_open_tls_crypto(lua_State *L);
void nixio_open_tls_context(lua_State *L);
void nixio_open_tls_socket(lua_State *L);

View file

@ -17,12 +17,10 @@
*/
#include "nixio.h"
#include <poll.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "nixio.h"
/**
@ -71,11 +69,13 @@ static int nixio_poll_flags(lua_State *L) {
flags = luaL_checkinteger(L, 1);
lua_newtable(L);
nixio_poll_flags__r(L, &flags, POLLIN, "in");
nixio_poll_flags__r(L, &flags, POLLPRI, "pri");
nixio_poll_flags__r(L, &flags, POLLOUT, "out");
nixio_poll_flags__r(L, &flags, POLLERR, "err");
#ifndef __WINNT__
nixio_poll_flags__r(L, &flags, POLLPRI, "pri");
nixio_poll_flags__r(L, &flags, POLLHUP, "hup");
nixio_poll_flags__r(L, &flags, POLLNVAL, "nval");
#endif
} else {
flags = 0;
const int j = lua_gettop(L);
@ -83,16 +83,22 @@ static int nixio_poll_flags(lua_State *L) {
const char *flag = luaL_checkstring(L, i);
if (!strcmp(flag, "in")) {
flags |= POLLIN;
} else if (!strcmp(flag, "pri")) {
flags |= POLLPRI;
} else if (!strcmp(flag, "out")) {
flags |= POLLOUT;
} else if (!strcmp(flag, "err")) {
flags |= POLLERR;
} else if (!strcmp(flag, "pri")) {
#ifndef __WINNT__
flags |= POLLPRI;
#endif
} else if (!strcmp(flag, "hup")) {
#ifndef __WINNT__
flags |= POLLHUP;
#endif
} else if (!strcmp(flag, "nval")) {
#ifndef __WINNT__
flags |= POLLNVAL;
#endif
} else {
return luaL_argerror(L, i,
"supported values: in, pri, out, err, hup, nval");
@ -114,11 +120,19 @@ static int nixio_poll(lua_State *L) {
/* we are being abused as sleep() replacement... */
if (lua_isnoneornil(L, 1) || len < 1) {
return nixio__pstatus(L, !poll(NULL, 0, timeout));
if (!poll(NULL, 0, timeout)) {
lua_pushinteger(L, 0);
return 1;
} else {
return nixio__perror(L);
}
}
luaL_checktype(L, 1, LUA_TTABLE);
struct pollfd *fds = calloc(len, sizeof(struct pollfd));
if (!fds) {
return luaL_error(L, NIXIO_OOM);
}
for (i = 0; i < len; i++) {
lua_rawgeti(L, 1, i+1);
@ -145,7 +159,11 @@ static int nixio_poll(lua_State *L) {
status = poll(fds, (nfds_t)len, timeout);
if (status < 1) {
if (status == 0) {
free(fds);
lua_pushboolean(L, 0);
return 1;
} else if (status < 0) {
free(fds);
return nixio__perror(L);
}

View file

@ -17,15 +17,98 @@
*/
#include "nixio.h"
#include <pwd.h>
#include <grp.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#define NIXIO_EXECVE 0x01
#define NIXIO_EXECV 0x02
#define NIXIO_EXECVP 0x03
int nixio__exec(lua_State *L, int m) {
const char *path = luaL_checkstring(L, 1);
const char *arg;
int argn, i;
if (m == NIXIO_EXECVE) {
luaL_checktype(L, 2, LUA_TTABLE);
argn = lua_objlen(L, 2) + 1;
} else {
argn = lua_gettop(L);
}
char **args = lua_newuserdata(L, sizeof(char*) * (argn + 1));
args[argn] = NULL;
args[0] = (char *)path;
if (m == NIXIO_EXECVE) {
for (i = 1; i < argn; i++) {
lua_rawgeti(L, 2, i);
arg = lua_tostring(L, -1);
luaL_argcheck(L, arg, 2, "invalid argument");
args[i] = (char *)arg;
}
if (lua_isnoneornil(L, 3)) {
execv(path, args);
} else {
luaL_checktype(L, 3, LUA_TTABLE);
argn = 0;
lua_pushnil(L);
while (lua_next(L, 3)) {
if (!lua_checkstack(L, 1)) {
lua_settop(L, 0);
return luaL_error(L, "stack overflow");
}
if (!lua_type(L, -2) != LUA_TSTRING || !lua_isstring(L, -1)) {
return luaL_argerror(L, 3, "invalid environment");
}
lua_pushfstring(L, "%s=%s",
lua_tostring(L, -2), lua_tostring(L, -1));
lua_insert(L, 4);
lua_pop(L, 1);
argn++;
}
char **env = lua_newuserdata(L, sizeof(char*) * (argn + 1));
env[argn] = NULL;
for (i = 1; i < argn; i++) {
env[i-1] = (char *)lua_tostring(L, -i);
}
execve(path, args, env);
}
} else {
for (i = 2; i <= argn; i++) {
arg = luaL_checkstring(L, i);
args[i-1] = (char *)arg;
}
if (m == NIXIO_EXECV) {
execv(path, args);
} else {
execvp(path, args);
}
}
return nixio__perror(L);
}
#ifndef __WINNT__
#include <sys/utsname.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
static int nixio_fork(lua_State *L) {
pid_t pid = fork();
if (pid == -1) {
@ -36,16 +119,55 @@ static int nixio_fork(lua_State *L) {
}
}
static int nixio_signal(lua_State *L) {
int sig = luaL_checkinteger(L, 1);
const char *val = luaL_checkstring(L, 2);
static int nixio_kill(lua_State *L) {
return nixio__pstatus(L, !kill(luaL_checkint(L, 1), luaL_checkint(L, 2)));
}
if (!strcmp(val, "ign") || !strcmp(val, "ignore")) {
return nixio__pstatus(L, signal(sig, SIG_IGN) != SIG_ERR);
} else if (!strcmp(val, "dfl") || !strcmp(val, "default")) {
return nixio__pstatus(L, signal(sig, SIG_DFL) != SIG_ERR);
static int nixio_getppid(lua_State *L) {
lua_pushinteger(L, getppid());
return 1;
}
static int nixio_getuid(lua_State *L) {
lua_pushinteger(L, getuid());
return 1;
}
static int nixio_getgid(lua_State *L) {
lua_pushinteger(L, getgid());
return 1;
}
static int nixio_setgid(lua_State *L) {
return nixio__pstatus(L, !setgid(nixio__check_group(L, 1)));
}
static int nixio_setuid(lua_State *L) {
return nixio__pstatus(L, !setuid(nixio__check_user(L, 1)));
}
static int nixio_nice(lua_State *L) {
int nval = luaL_checkint(L, 1);
errno = 0;
nval = nice(nval);
if (nval == -1 && errno) {
return nixio__perror(L);
} else {
return luaL_argerror(L, 2, "supported values: ign, dfl");
lua_pushinteger(L, nval);
return 1;
}
}
static int nixio_setsid(lua_State *L) {
pid_t pid = setsid();
if (pid == -1) {
return nixio__perror(L);
} else {
lua_pushinteger(L, pid);
return 1;
}
}
@ -97,8 +219,71 @@ static int nixio_wait(lua_State *L) {
return 3;
}
static int nixio_kill(lua_State *L) {
return nixio__pstatus(L, !kill(luaL_checkint(L, 1), luaL_checkint(L, 2)));
static int nixio_times(lua_State *L) {
struct tms buf;
if (times(&buf) == -1) {
return nixio__perror(L);
} else {
lua_createtable(L, 0, 4);
lua_pushnumber(L, buf.tms_cstime);
lua_setfield(L, -2, "cstime");
lua_pushnumber(L, buf.tms_cutime);
lua_setfield(L, -2, "cutime");
lua_pushnumber(L, buf.tms_stime);
lua_setfield(L, -2, "stime");
lua_pushnumber(L, buf.tms_utime);
lua_setfield(L, -2, "utime");
return 1;
}
}
static int nixio_uname(lua_State *L) {
struct utsname buf;
if (uname(&buf)) {
return nixio__perror(L);
}
lua_createtable(L, 0, 5);
lua_pushstring(L, buf.machine);
lua_setfield(L, -2, "machine");
lua_pushstring(L, buf.version);
lua_setfield(L, -2, "version");
lua_pushstring(L, buf.release);
lua_setfield(L, -2, "release");
lua_pushstring(L, buf.nodename);
lua_setfield(L, -2, "nodename");
lua_pushstring(L, buf.sysname);
lua_setfield(L, -2, "sysname");
return 1;
}
#endif /* !__WINNT__ */
static int nixio_chdir(lua_State *L) {
return nixio__pstatus(L, !chdir(luaL_checkstring(L, 1)));
}
static int nixio_signal(lua_State *L) {
int sig = luaL_checkinteger(L, 1);
const char *val = luaL_checkstring(L, 2);
if (!strcmp(val, "ign") || !strcmp(val, "ignore")) {
return nixio__pstatus(L, signal(sig, SIG_IGN) != SIG_ERR);
} else if (!strcmp(val, "dfl") || !strcmp(val, "default")) {
return nixio__pstatus(L, signal(sig, SIG_DFL) != SIG_ERR);
} else {
return luaL_argerror(L, 2, "supported values: ign, dfl");
}
}
static int nixio_getpid(lua_State *L) {
@ -106,94 +291,157 @@ static int nixio_getpid(lua_State *L) {
return 1;
}
static int nixio_getppid(lua_State *L) {
lua_pushinteger(L, getppid());
return 1;
}
static int nixio_getuid(lua_State *L) {
lua_pushinteger(L, getuid());
return 1;
}
static int nixio_getgid(lua_State *L) {
lua_pushinteger(L, getgid());
return 1;
}
static int nixio_setgid(lua_State *L) {
gid_t gid;
if (lua_isstring(L, 1)) {
struct group *g = getgrnam(lua_tostring(L, 1));
gid = (!g) ? -1 : g->gr_gid;
} else if (lua_isnumber(L, 1)) {
gid = lua_tointeger(L, 1);
static int nixio_getenv(lua_State *L) {
const char *key = luaL_optstring(L, 1, NULL);
if (key) {
const char *val = getenv(key);
if (val) {
lua_pushstring(L, val);
} else {
lua_pushnil(L);
}
} else {
return luaL_argerror(L, 1, "supported values: <groupname>, <gid>");
lua_newtable(L);
extern char **environ;
for (char **c = environ; *c; c++) {
const char *delim = strchr(*c, '=');
if (!delim) {
return luaL_error(L, "invalid environment");
}
lua_pushlstring(L, *c, delim-*c);
lua_pushstring(L, delim + 1);
lua_rawset(L, -3);
}
}
return nixio__pstatus(L, !setgid(gid));
return 1;
}
static int nixio_setuid(lua_State *L) {
uid_t uid;
if (lua_isstring(L, 1)) {
struct passwd *p = getpwnam(lua_tostring(L, 1));
uid = (!p) ? -1 : p->pw_uid;
} else if (lua_isnumber(L, 1)) {
uid = lua_tointeger(L, 1);
} else {
return luaL_argerror(L, 1, "supported values: <username>, <uid>");
}
return nixio__pstatus(L, !setuid(uid));
static int nixio_setenv(lua_State *L) {
const char *key = luaL_checkstring(L, 1);
const char *val = luaL_optstring(L, 2, NULL);
return nixio__pstatus(L, (val) ? !setenv(key, val, 1) : !unsetenv(key));
}
static int nixio_nice(lua_State *L) {
int nval = luaL_checkint(L, 1);
static int nixio_exec(lua_State *L) {
return nixio__exec(L, NIXIO_EXECV);
}
errno = 0;
nval = nice(nval);
static int nixio_execp(lua_State *L) {
return nixio__exec(L, NIXIO_EXECVP);
}
if (nval == -1 && errno) {
return nixio__perror(L);
} else {
lua_pushinteger(L, nval);
static int nixio_exece(lua_State *L) {
return nixio__exec(L, NIXIO_EXECVE);
}
static int nixio_getcwd(lua_State *L) {
char path[PATH_MAX];
if (getcwd(path, sizeof(path))) {
lua_pushstring(L, path);
return 1;
}
}
static int nixio_setsid(lua_State *L) {
pid_t pid = setsid();
if (pid == -1) {
return nixio__perror(L);
} else {
lua_pushinteger(L, pid);
return 1;
return nixio__perror(L);
}
}
static int nixio_chdir(lua_State *L) {
return nixio__pstatus(L, !chdir(luaL_checkstring(L, 1)));
static int nixio_umask(lua_State *L) {
char mask[9];
lua_pushinteger(L,
nixio__mode_write(umask(nixio__check_mode(L, 1, -1)), mask));
lua_pushlstring(L, mask, 9);
return 2;
}
#ifdef __linux__
#include <sys/sysinfo.h>
static int nixio_sysinfo(lua_State *L) {
struct sysinfo info;
if (sysinfo(&info)) {
return nixio__perror(L);
}
lua_createtable(L, 0, 12);
lua_pushnumber(L, info.bufferram);
lua_setfield(L, -2, "bufferram");
lua_pushnumber(L, info.freehigh);
lua_setfield(L, -2, "freehigh");
lua_pushnumber(L, info.freeram);
lua_setfield(L, -2, "freeram");
lua_pushnumber(L, info.freeswap);
lua_setfield(L, -2, "freeswap");
lua_createtable(L, 0, 3);
for (int i=0; i<3; i++) {
lua_pushnumber(L, info.loads[i] / 65536.);
lua_rawseti(L, -2, i+1);
}
lua_setfield(L, -2, "loads");
lua_pushnumber(L, info.mem_unit);
lua_setfield(L, -2, "mem_unit");
lua_pushnumber(L, info.procs);
lua_setfield(L, -2, "procs");
lua_pushnumber(L, info.sharedram);
lua_setfield(L, -2, "sharedram");
lua_pushnumber(L, info.totalhigh);
lua_setfield(L, -2, "totalhigh");
lua_pushnumber(L, info.totalram);
lua_setfield(L, -2, "totalram");
lua_pushnumber(L, info.totalswap);
lua_setfield(L, -2, "totalswap");
lua_pushnumber(L, info.uptime);
lua_setfield(L, -2, "uptime");
return 1;
}
#endif
/* module table */
static const luaL_reg R[] = {
#ifdef __linux__
{"sysinfo", nixio_sysinfo},
#endif
#ifndef __WINNT__
{"fork", nixio_fork},
{"wait", nixio_wait},
{"kill", nixio_kill},
{"nice", nixio_nice},
{"chdir", nixio_chdir},
{"getpid", nixio_getpid},
{"getppid", nixio_getppid},
{"getuid", nixio_getuid},
{"getgid", nixio_getgid},
{"setuid", nixio_setuid},
{"setgid", nixio_setgid},
{"setsid", nixio_setsid},
{"wait", nixio_wait},
{"waitpid", nixio_wait},
{"times", nixio_times},
{"uname", nixio_uname},
#endif
{"chdir", nixio_chdir},
{"signal", nixio_signal},
{"getpid", nixio_getpid},
{"getenv", nixio_getenv},
{"setenv", nixio_setenv},
{"putenv", nixio_setenv},
{"exec", nixio_exec},
{"execp", nixio_execp},
{"exece", nixio_exece},
{"getcwd", nixio_getcwd},
{"umask", nixio_umask},
{NULL, NULL}
};

View file

@ -17,12 +17,9 @@
*/
#include "nixio.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "nixio.h"
/**
@ -79,7 +76,7 @@ static int nixio_socket(lua_State *L) {
sock->fd = socket(sock->domain, sock->type, sock->protocol);
if (sock->fd < 0) {
return nixio__perror(L);
return nixio__perror_s(L);
}
return 1;
@ -95,10 +92,14 @@ static int nixio_sock_close(lua_State *L) {
sock->fd = -1;
do {
#ifndef __WINNT__
res = close(sockfd);
#else
res = closesocket(sockfd);
#endif
} while (res == -1 && errno == EINTR);
return nixio__pstatus(L, !res);
return nixio__pstatus_s(L, !res);
}
/**
@ -109,7 +110,11 @@ static int nixio_sock__gc(lua_State *L) {
int res;
if (sock && sock->fd != -1) {
do {
#ifndef __WINNT__
res = close(sock->fd);
#else
res = closesocket(sock->fd);
#endif
} while (res == -1 && errno == EINTR);
}
return 0;
@ -141,7 +146,7 @@ static int nixio_sock_shutdown(lua_State *L) {
return luaL_argerror(L, 2, "supported values: both, read, write");
}
return nixio__pstatus(L, !shutdown(sockfd, how));
return nixio__pstatus_s(L, !shutdown(sockfd, how));
}
/* module table */

View file

@ -17,17 +17,25 @@
*/
#include "nixio.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <net/if.h>
#include <sys/time.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "nixio.h"
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#endif
#ifndef IPV6_DROP_MEMBERSHIP
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
#endif
static int nixio_sock_fileno(lua_State *L) {
lua_pushinteger(L, nixio__checkfd(L, 1));
return 1;
}
/**
* setblocking()
@ -36,6 +44,9 @@ static int nixio_sock_setblocking(lua_State *L) {
int fd = nixio__checkfd(L, 1);
luaL_checkany(L, 2);
int set = lua_toboolean(L, 2);
#ifndef __WINNT__
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
@ -49,50 +60,64 @@ static int nixio_sock_setblocking(lua_State *L) {
}
return nixio__pstatus(L, !fcntl(fd, F_SETFL, flags));
#else /* __WINNT__ */
lua_getmetatable(L, 1);
luaL_getmetatable(L, NIXIO_META);
if (lua_equal(L, -1, -2)) { /* Socket */
unsigned long val = !set;
return nixio__pstatus_s(L, !ioctlsocket(fd, FIONBIO, &val));
} else { /* File */
WSASetLastError(WSAENOTSOCK);
return nixio__perror_s(L);
}
#endif /* __WINNT__ */
}
static int nixio__gso_int(lua_State *L, int fd, int level, int opt, int set) {
int value;
socklen_t optlen = sizeof(value);
if (!set) {
if (!getsockopt(fd, level, opt, &value, &optlen)) {
if (!getsockopt(fd, level, opt, (char *)&value, &optlen)) {
lua_pushinteger(L, value);
return 1;
}
} else {
value = luaL_checkinteger(L, set);
if (!setsockopt(fd, level, opt, &value, optlen)) {
if (!setsockopt(fd, level, opt, (char *)&value, optlen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror(L);
return nixio__perror_s(L);
}
static int nixio__gso_ling(lua_State *L, int fd, int level, int opt, int set) {
struct linger value;
socklen_t optlen = sizeof(value);
if (!set) {
if (!getsockopt(fd, level, opt, &value, &optlen)) {
if (!getsockopt(fd, level, opt, (char *)&value, &optlen)) {
lua_pushinteger(L, value.l_onoff ? value.l_linger : 0);
return 1;
}
} else {
value.l_linger = luaL_checkinteger(L, set);
value.l_onoff = value.l_linger ? 1 : 0;
if (!setsockopt(fd, level, opt, &value, optlen)) {
if (!setsockopt(fd, level, opt, (char *)&value, optlen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror(L);
return nixio__perror_s(L);
}
static int nixio__gso_timev(lua_State *L, int fd, int level, int opt, int set) {
struct timeval value;
socklen_t optlen = sizeof(value);
if (!set) {
if (!getsockopt(fd, level, opt, &value, &optlen)) {
if (!getsockopt(fd, level, opt, (char *)&value, &optlen)) {
lua_pushinteger(L, value.tv_sec);
lua_pushinteger(L, value.tv_usec);
return 2;
@ -100,12 +125,12 @@ static int nixio__gso_timev(lua_State *L, int fd, int level, int opt, int set) {
} else {
value.tv_sec = luaL_checkinteger(L, set);
value.tv_usec = luaL_optinteger(L, set + 1, 0);
if (!setsockopt(fd, level, opt, &value, optlen)) {
if (!setsockopt(fd, level, opt, (char *)&value, optlen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror(L);
return nixio__perror_s(L);
}
#ifdef SO_BINDTODEVICE
@ -114,7 +139,7 @@ static int nixio__gso_b(lua_State *L, int fd, int level, int opt, int set) {
if (!set) {
socklen_t optlen = IFNAMSIZ;
char ifname[IFNAMSIZ];
if (!getsockopt(fd, level, opt, ifname, &optlen)) {
if (!getsockopt(fd, level, opt, (char *)ifname, &optlen)) {
lua_pushlstring(L, ifname, optlen);
return 1;
}
@ -122,16 +147,76 @@ static int nixio__gso_b(lua_State *L, int fd, int level, int opt, int set) {
size_t valuelen;
const char *value = luaL_checklstring(L, set, &valuelen);
luaL_argcheck(L, valuelen <= IFNAMSIZ, set, "invalid interface name");
if (!setsockopt(fd, level, opt, value, valuelen)) {
if (!setsockopt(fd, level, opt, (char *)value, valuelen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror(L);
return nixio__perror_s(L);
}
#endif /* SO_BINDTODEVICE */
static int nixio__gso_mreq4(lua_State *L, int fd, int level, int opt, int set) {
struct ip_mreq value;
socklen_t optlen = sizeof(value);
if (!set) {
char buf[INET_ADDRSTRLEN];
if (!getsockopt(fd, level, opt, (char *)&value, &optlen)) {
if (!inet_ntop(AF_INET, &value.imr_multiaddr, buf, sizeof(buf))) {
return nixio__perror_s(L);
}
lua_pushstring(L, buf);
if (!inet_ntop(AF_INET, &value.imr_interface, buf, sizeof(buf))) {
return nixio__perror_s(L);
}
lua_pushstring(L, buf);
return 2;
}
} else {
const char *maddr = luaL_checkstring(L, set);
const char *iface = luaL_optstring(L, set + 1, "0.0.0.0");
if (inet_pton(AF_INET, maddr, &value.imr_multiaddr) < 1) {
return nixio__perror_s(L);
}
if (inet_pton(AF_INET, iface, &value.imr_interface) < 1) {
return nixio__perror_s(L);
}
if (!setsockopt(fd, level, opt, (char *)&value, optlen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror_s(L);
}
static int nixio__gso_mreq6(lua_State *L, int fd, int level, int opt, int set) {
struct ipv6_mreq val;
socklen_t optlen = sizeof(val);
if (!set) {
char buf[INET_ADDRSTRLEN];
if (!getsockopt(fd, level, opt, (char *)&val, &optlen)) {
if (!inet_ntop(AF_INET6, &val.ipv6mr_multiaddr, buf, sizeof(buf))) {
return nixio__perror_s(L);
}
lua_pushstring(L, buf);
lua_pushnumber(L, val.ipv6mr_interface);
return 2;
}
} else {
const char *maddr = luaL_checkstring(L, set);
if (inet_pton(AF_INET6, maddr, &val.ipv6mr_multiaddr) < 1) {
return nixio__perror_s(L);
}
val.ipv6mr_interface = luaL_optlong(L, set + 1, 0);
if (!setsockopt(fd, level, opt, (char *)&val, optlen)) {
lua_pushboolean(L, 1);
return 1;
}
}
return nixio__perror_s(L);
}
/**
* get/setsockopt() helper
*/
@ -183,9 +268,6 @@ static int nixio__getsetsockopt(lua_State *L, int set) {
);
}
} else if (!strcmp(level, "tcp")) {
if (sock->type != SOCK_STREAM) {
return luaL_error(L, "not a TCP socket");
}
if (!strcmp(option, "cork")) {
#ifdef TCP_CORK
return nixio__gso_int(L, sock->fd, IPPROTO_TCP, TCP_CORK, set);
@ -197,8 +279,71 @@ static int nixio__getsetsockopt(lua_State *L, int set) {
} else {
return luaL_argerror(L, 3, "supported values: cork, nodelay");
}
} else if (!strcmp(level, "ip")) {
if (!strcmp(option, "mtu")) {
#ifdef IP_MTU
return nixio__gso_int(L, sock->fd, IPPROTO_IP, IP_MTU, set);
#else
return nixio__pstatus(L, !(errno = ENOPROTOOPT));
#endif
} else if (!strcmp(option, "hdrincl")) {
return nixio__gso_int(L, sock->fd, IPPROTO_IP, IP_HDRINCL,
set);
} else if (!strcmp(option, "multicast_loop")) {
return nixio__gso_int(L, sock->fd, IPPROTO_IP, IP_MULTICAST_LOOP,
set);
} else if (!strcmp(option, "multicast_ttl")) {
return nixio__gso_int(L, sock->fd, IPPROTO_IP, IP_MULTICAST_TTL,
set);
} else if (!strcmp(option, "multicast_if")) {
return nixio__gso_mreq4(L, sock->fd, IPPROTO_IP, IP_MULTICAST_IF,
set);
} else if (!strcmp(option, "add_membership")) {
return nixio__gso_mreq4(L, sock->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
set);
} else if (!strcmp(option, "drop_membership")) {
return nixio__gso_mreq4(L, sock->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
set);
} else {
return luaL_argerror(L, 3,
"supported values: hdrincl, mtu, multicast_loop, "
"multicast_ttl, multicast_if, add_membership, drop_membership");
}
} else if (!strcmp(level, "ipv6")) {
if (!strcmp(option, "mtu")) {
#ifdef IPV6_MTU
return nixio__gso_int(L, sock->fd, IPPROTO_IPV6, IPV6_MTU, set);
#else
return nixio__pstatus(L, !(errno = ENOPROTOOPT));
#endif
} else if (!strcmp(option, "v6only")) {
#ifdef IPV6_V6ONLY
return nixio__gso_int(L, sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, set);
#else
return nixio__pstatus(L, !(errno = ENOPROTOOPT));
#endif
} else if (!strcmp(option, "multicast_loop")) {
return nixio__gso_int(L, sock->fd, IPPROTO_IPV6,
IPV6_MULTICAST_LOOP, set);
} else if (!strcmp(option, "multicast_hops")) {
return nixio__gso_int(L, sock->fd, IPPROTO_IPV6,
IPV6_MULTICAST_HOPS, set);
} else if (!strcmp(option, "multicast_if")) {
return nixio__gso_mreq6(L, sock->fd, IPPROTO_IPV6,
IPV6_MULTICAST_IF, set);
} else if (!strcmp(option, "add_membership")) {
return nixio__gso_mreq6(L, sock->fd, IPPROTO_IPV6,
IPV6_ADD_MEMBERSHIP, set);
} else if (!strcmp(option, "drop_membership")) {
return nixio__gso_mreq6(L, sock->fd, IPPROTO_IPV6,
IPV6_DROP_MEMBERSHIP, set);
} else {
return luaL_argerror(L, 3,
"supported values: v6only, mtu, multicast_loop, multicast_hops,"
" multicast_if, add_membership, drop_membership");
}
} else {
return luaL_argerror(L, 2, "supported values: socket, tcp");
return luaL_argerror(L, 2, "supported values: socket, tcp, ip, ipv6");
}
}
@ -221,6 +366,9 @@ static const luaL_reg M[] = {
{"setblocking", nixio_sock_setblocking},
{"getsockopt", nixio_sock_getsockopt},
{"setsockopt", nixio_sock_setsockopt},
{"getopt", nixio_sock_getsockopt},
{"setopt", nixio_sock_setsockopt},
{"fileno", nixio_sock_fileno},
{NULL, NULL}
};
@ -232,5 +380,7 @@ void nixio_open_sockopt(lua_State *L) {
luaL_getmetatable(L, NIXIO_FILE_META);
lua_pushcfunction(L, nixio_sock_setblocking);
lua_setfield(L, -2, "setblocking");
lua_pushcfunction(L, nixio_sock_fileno);
lua_setfield(L, -2, "fileno");
lua_pop(L, 1);
}

View file

@ -27,6 +27,9 @@
#include <unistd.h>
#include <sys/param.h>
#ifndef __WINNT__
#ifndef BSD
#include <sys/sendfile.h>
#else
@ -150,6 +153,14 @@ static const luaL_reg R[] = {
{NULL, NULL}
};
void nixio_open_splice(lua_State *L) {
luaL_register(L, NULL, R);
}
#else /* __WINNT__ */
void nixio_open_splice(lua_State *L) {
}
#endif /* !__WINNT__ */

View file

@ -18,6 +18,8 @@
#include "nixio.h"
#include <string.h>
#ifndef __WINNT__
#include <syslog.h>
@ -57,7 +59,7 @@ static int nixio_closelog(lua_State *L) {
return 0;
}
static int nixio__syslogmasg(lua_State *L, int dolog) {
static int nixio__syslogmask(lua_State *L, int dolog) {
int priority;
const char *flag = luaL_checkstring(L, 1);
@ -92,11 +94,11 @@ static int nixio__syslogmasg(lua_State *L, int dolog) {
}
static int nixio_setlogmask(lua_State *L) {
return nixio__syslogmasg(L, 0);
return nixio__syslogmask(L, 0);
}
static int nixio_syslog(lua_State *L) {
return nixio__syslogmasg(L, 1);
return nixio__syslogmask(L, 1);
}
/* module table */
@ -111,3 +113,10 @@ static const luaL_reg R[] = {
void nixio_open_syslog(lua_State *L) {
luaL_register(L, NULL, R);
}
#else /* __WINNT__ */
void nixio_open_syslog(lua_State *L) {
}
#endif /* __WINNT__ */

188
libs/nixio/src/tls-crypto.c Normal file
View file

@ -0,0 +1,188 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio-tls.h"
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
static char nixio__bin2hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
static int nixio_crypto_hash__init(lua_State *L, int hmac) {
const char *type = luaL_checkstring(L, 1);
nixio_hash *hash = lua_newuserdata(L, sizeof(nixio_hash));
if (!strcmp(type, "md5")) {
hash->type = NIXIO_HASH_MD5;
hash->digest_size = MD5_DIGEST_LENGTH;
hash->block_size = 64;
hash->ctx = malloc(sizeof(MD5_CTX));
if (!hash->ctx) {
return luaL_error(L, NIXIO_OOM);
}
MD5_Init((MD5_CTX*)hash->ctx);
hash->init = (nixio_hash_initcb)MD5_Init;
hash->update = (nixio_hash_updatecb)MD5_Update;
hash->final = (nixio_hash_finalcb)MD5_Final;
} else if (!strcmp(type, "sha1")) {
hash->type = NIXIO_HASH_SHA1;
hash->digest_size = SHA_DIGEST_LENGTH;
hash->block_size = 64;
hash->ctx = malloc(sizeof(SHA_CTX));
if (!hash->ctx) {
return luaL_error(L, NIXIO_OOM);
}
SHA1_Init((SHA_CTX*)hash->ctx);
hash->init = (nixio_hash_initcb)SHA1_Init;
hash->update = (nixio_hash_updatecb)SHA1_Update;
hash->final = (nixio_hash_finalcb)SHA1_Final;
} else {
luaL_argerror(L, 1, "supported values: md5, sha1");
}
luaL_getmetatable(L, NIXIO_CRYPTO_HASH_META);
lua_setmetatable(L, -2);
if (hmac) {
const char *key = luaL_checklstring(L, 2, &hash->key_size);
if (hash->key_size > hash->block_size) {
hash->update(hash->ctx, key, hash->key_size);
hash->final(hash->digest, hash->ctx);
hash->init(hash->ctx);
hash->key_size = hash->digest_size;
memcpy(hash->key, hash->digest, hash->key_size);
} else {
memcpy(hash->key, key, hash->key_size);
}
unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
for (uint i = 0; i < hash->block_size; i++) {
pad[i] = (i < hash->key_size) ? (0x36 ^ hash->key[i]) : 0x36;
}
hash->update(hash->ctx, pad, hash->block_size);
hash->type |= NIXIO_HMAC_BIT;
}
return 1;
}
static int nixio_crypto_hash(lua_State *L) {
return nixio_crypto_hash__init(L, 0);
}
static int nixio_crypto_hmac(lua_State *L) {
return nixio_crypto_hash__init(L, 1);
}
static int nixio_crypto_hash_update(lua_State *L) {
nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
if (hash->type) {
size_t len;
const char *chunk = luaL_checklstring(L, 2, &len);
hash->update(hash->ctx, chunk, len);
lua_pushvalue(L, 1);
return 1;
} else {
return luaL_error(L, "Tried to update finalized hash object.");
}
}
static int nixio_crypto_hash_final(lua_State *L) {
nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
if (hash->type & NIXIO_HMAC_BIT) {
hash->final(hash->digest, hash->ctx);
hash->init(hash->ctx);
unsigned char pad[NIXIO_CRYPTO_BLOCK_SIZE];
for (uint i = 0; i < hash->block_size; i++) {
pad[i] = (i < hash->key_size) ? (0x5c ^ hash->key[i]) : 0x5c;
}
hash->update(hash->ctx, pad, hash->block_size);
hash->update(hash->ctx, hash->digest, hash->digest_size);
}
if (hash->type) {
hash->type = NIXIO_HASH_NONE;
hash->final(hash->digest, hash->ctx);
free(hash->ctx);
}
char hashdigest[NIXIO_DIGEST_SIZE*2];
for (uint i=0; i < hash->digest_size; i++) {
hashdigest[2*i] = nixio__bin2hex[(hash->digest[i] & 0xf0) >> 4];
hashdigest[2*i+1] = nixio__bin2hex[(hash->digest[i] & 0x0f)];
}
lua_pushlstring(L, hashdigest, hash->digest_size * 2);
memcpy(hashdigest, hash->digest, hash->digest_size);
lua_pushlstring(L, hashdigest, hash->digest_size);
return 2;
}
static int nixio_crypto_hash__gc(lua_State *L) {
nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
if (hash->type) {
hash->final(hash->digest, hash->ctx);
free(hash->ctx);
hash->type = NIXIO_HASH_NONE;
}
return 0;
}
static int nixio_crypto_hash__tostring(lua_State *L) {
nixio_hash *hash = luaL_checkudata(L, 1, NIXIO_CRYPTO_HASH_META);
lua_pushfstring(L, "nixio hash object: %p", hash);
return 1;
}
/* module table */
static const luaL_reg R[] = {
{"hash", nixio_crypto_hash},
{"hmac", nixio_crypto_hmac},
{NULL, NULL}
};
/* hash table */
static const luaL_reg M[] = {
{"update", nixio_crypto_hash_update},
{"final", nixio_crypto_hash_final},
{"__gc", nixio_crypto_hash__gc},
{"__tostring", nixio_crypto_hash__tostring},
{NULL, NULL}
};
void nixio_open_tls_crypto(lua_State *L) {
luaL_newmetatable(L, NIXIO_CRYPTO_HASH_META);
luaL_register(L, NULL, M);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
lua_newtable(L);
luaL_register(L, NULL, R);
lua_setfield(L, -2, "crypto");
}

View file

@ -1,4 +1,4 @@
/*
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
@ -65,7 +65,7 @@ static SSL* nixio__checktlssock(lua_State *L) {
static int nixio_tls_sock_recv(lua_State *L) {
SSL *sock = nixio__checktlssock(L);
nixio_tls__check_connected(L);
int req = luaL_checkinteger(L, 2);
uint req = luaL_checkinteger(L, 2);
luaL_argcheck(L, req >= 0, 2, "out of range");
@ -172,6 +172,24 @@ static int nixio_tls_sock_send(lua_State *L) {
size_t len;
ssize_t sent;
const char *data = luaL_checklstring(L, 2, &len);
if (lua_gettop(L) > 2) {
int offset = luaL_optint(L, 3, 0);
if (offset) {
if (offset < len) {
data += offset;
len -= offset;
} else {
len = 0;
}
}
unsigned int wlen = luaL_optint(L, 4, len);
if (wlen < len) {
len = wlen;
}
}
sent = SSL_write(sock, data, len);
if (sent > 0) {
lua_pushinteger(L, sent);

257
libs/nixio/src/user.c Normal file
View file

@ -0,0 +1,257 @@
/*
* nixio - Linux I/O library for lua
*
* Copyright (C) 2009 Steven Barth <steven@midlink.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "nixio.h"
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <sys/param.h>
#ifndef __WINNT__
#include <grp.h>
#include <pwd.h>
#ifndef BSD
#include <shadow.h>
#include <crypt.h>
#endif
int nixio__check_group(lua_State *L, int idx) {
if (lua_isnumber(L, idx)) {
return lua_tointeger(L, idx);
} else if (lua_isstring(L, idx)) {
struct group *g = getgrnam(lua_tostring(L, idx));
return (!g) ? -1 : g->gr_gid;
} else {
return luaL_argerror(L, idx, "supported values: <groupname>, <gid>");
}
}
int nixio__check_user(lua_State *L, int idx) {
if (lua_isnumber(L, idx)) {
return lua_tointeger(L, idx);
} else if (lua_isstring(L, idx)) {
struct passwd *p = getpwnam(lua_tostring(L, idx));
return (!p) ? -1 : p->pw_uid;
} else {
return luaL_argerror(L, idx, "supported values: <username>, <uid>");
}
}
static int nixio__push_group(lua_State *L, struct group *gr) {
lua_createtable(L, 0, 4);
lua_pushstring(L, gr->gr_name);
lua_setfield(L, -2, "name");
lua_pushstring(L, gr->gr_passwd);
lua_setfield(L, -2, "passwd");
lua_pushinteger(L, gr->gr_gid);
lua_setfield(L, -2, "gid");
lua_newtable(L);
for (int i=0; gr->gr_mem[i]; i++) {
lua_pushstring(L, gr->gr_mem[i]);
lua_rawseti(L, -2, i+1);
}
lua_setfield(L, -2, "mem");
return 1;
}
static int nixio_getgr(lua_State *L) {
struct group *gr;
errno = 0;
if (lua_isnumber(L, 1)) {
gr = getgrgid(lua_tonumber(L, 1));
} else if (lua_isstring(L, 1)) {
gr = getgrnam(lua_tostring(L, 1));
} else if (lua_isnoneornil(L, 1)) {
lua_newtable(L);
int i = 0;
setgrent();
while ((gr = getgrent())) {
nixio__push_group(L, gr);
lua_rawseti(L, -2, ++i);
}
if (errno) {
return nixio__perror(L);
}
endgrent();
return 1;
} else {
return luaL_argerror(L, 1, "supported values: <groupname>, <gid>");
}
if (!gr) {
return nixio__perror(L);
} else {
return nixio__push_group(L, gr);
}
}
static int nixio__push_passwd(lua_State *L, struct passwd *pw) {
lua_createtable(L, 0, 7);
lua_pushstring(L, pw->pw_name);
lua_setfield(L, -2, "name");
lua_pushstring(L, pw->pw_passwd);
lua_setfield(L, -2, "passwd");
lua_pushinteger(L, pw->pw_gid);
lua_setfield(L, -2, "gid");
lua_pushinteger(L, pw->pw_uid);
lua_setfield(L, -2, "uid");
lua_pushstring(L, pw->pw_dir);
lua_setfield(L, -2, "dir");
lua_pushstring(L, pw->pw_gecos);
lua_setfield(L, -2, "gecos");
lua_pushstring(L, pw->pw_shell);
lua_setfield(L, -2, "shell");
return 1;
}
static int nixio_getpw(lua_State *L) {
struct passwd *pw;
errno = 0;
if (lua_isnumber(L, 1)) {
pw = getpwuid(lua_tonumber(L, 1));
} else if (lua_isstring(L, 1)) {
pw = getpwnam(lua_tostring(L, 1));
} else if (lua_isnoneornil(L, 1)) {
lua_newtable(L);
int i = 0;
setpwent();
while ((pw = getpwent())) {
nixio__push_passwd(L, pw);
lua_rawseti(L, -2, ++i);
}
if (errno) {
return nixio__perror(L);
}
endpwent();
return 1;
} else {
return luaL_argerror(L, 1, "supported values: <username>, <uid>");
}
if (!pw) {
return nixio__perror(L);
} else {
return nixio__push_passwd(L, pw);
}
}
#ifndef BSD
static int nixio__push_spwd(lua_State *L, struct spwd *sp) {
lua_createtable(L, 0, 9);
lua_pushstring(L, sp->sp_namp);
lua_setfield(L, -2, "namp");
lua_pushinteger(L, sp->sp_expire);
lua_setfield(L, -2, "expire");
lua_pushinteger(L, sp->sp_flag);
lua_setfield(L, -2, "flag");
lua_pushinteger(L, sp->sp_inact);
lua_setfield(L, -2, "inact");
lua_pushinteger(L, sp->sp_lstchg);
lua_setfield(L, -2, "lstchg");
lua_pushinteger(L, sp->sp_max);
lua_setfield(L, -2, "max");
lua_pushinteger(L, sp->sp_min);
lua_setfield(L, -2, "min");
lua_pushinteger(L, sp->sp_warn);
lua_setfield(L, -2, "warn");
lua_pushstring(L, sp->sp_pwdp);
lua_setfield(L, -2, "pwdp");
return 1;
}
static int nixio_getsp(lua_State *L) {
struct spwd *sp;
errno = 0;
if (lua_isstring(L, 1)) {
sp = getspnam(lua_tostring(L, 1));
} else if (lua_isnoneornil(L, 1)) {
lua_newtable(L);
int i = 0;
setspent();
while ((sp = getspent())) {
nixio__push_spwd(L, sp);
lua_rawseti(L, -2, ++i);
}
if (errno) {
return nixio__perror(L);
}
endspent();
return 1;
} else {
return luaL_argerror(L, 1, "supported values: <username>");
}
if (!sp) {
return nixio__perror(L);
} else {
return nixio__push_spwd(L, sp);
}
}
#endif /* !BSD */
static int nixio_crypt(lua_State *L) {
const char *key = luaL_checkstring(L, 1);
const char *salt = luaL_checkstring(L, 2);
const char *hash = crypt(key, salt);
if (hash) {
lua_pushstring(L, hash);
} else {
lua_pushnil(L);
}
return 1;
}
/* module table */
static const luaL_reg R[] = {
{"crypt", nixio_crypt},
{"getgr", nixio_getgr},
{"getpw", nixio_getpw},
#ifndef BSD
{"getsp", nixio_getsp},
#endif
{NULL, NULL}
};
#else /* __WINNT__ */
static const luaL_reg R[] = {
{NULL, NULL}
};
#endif
void nixio_open_user(lua_State *L) {
luaL_register(L, NULL, R);
}

56
libs/nixio/standalone.mk Normal file
View file

@ -0,0 +1,56 @@
LUAC = luac
LUAC_OPTIONS = -s
LUA_TARGET ?= source
LUA_MODULEDIR = /usr/local/share/lua/5.1
LUA_LIBRARYDIR = /usr/local/lib/lua/5.1
OS ?= $(shell uname)
LUA_SHLIBS = $(shell pkg-config --silence-errors --libs lua5.1 || pkg-config --silence-errors --libs lua-5.1 || pkg-config --silence-errors --libs lua)
LUA_LIBS = $(if $(LUA_SHLIBS),$(LUA_SHLIBS),$(firstword $(wildcard /usr/lib/liblua.a /usr/local/lib/liblua.a /opt/local/lib/liblua.a)))
LUA_CFLAGS = $(shell pkg-config --silence-errors --cflags lua5.1 || pkg-config --silence-errors --cflags lua-5.1 || pkg-config --silence-errors --cflags lua)
CC = gcc
AR = ar
RANLIB = ranlib
CFLAGS = -O2
FPIC = -fPIC
EXTRA_CFLAGS = --std=gnu99
WFLAGS = -Wall -Werror -pedantic
CPPFLAGS =
COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) $(WFLAGS)
ifeq ($(OS),Darwin)
SHLIB_FLAGS = -bundle -undefined dynamic_lookup
else
SHLIB_FLAGS = -shared
endif
LINK = $(CC) $(LDFLAGS)
.PHONY: all build compile luacompile luasource clean luaclean
all: build
build: luabuild gccbuild
luabuild: lua$(LUA_TARGET)
gccbuild: compile
compile:
clean: luaclean
luasource:
mkdir -p dist$(LUA_MODULEDIR)
cp -pR root/* dist 2>/dev/null || true
cp -pR lua/* dist$(LUA_MODULEDIR) 2>/dev/null || true
for i in $$(find dist -name .svn); do rm -rf $$i || true; done
luastrip: luasource
for i in $$(find dist -type f -name '*.lua'); do perl -e 'undef $$/; open( F, "< $$ARGV[0]" ) || die $$!; $$src = <F>; close F; $$src =~ s/--\[\[.*?\]\](--)?//gs; $$src =~ s/^\s*--.*?\n//gm; open( F, "> $$ARGV[0]" ) || die $$!; print F $$src; close F' $$i; done
luacompile: luasource
for i in $$(find dist -name *.lua -not -name debug.lua); do $(LUAC) $(LUAC_OPTIONS) -o $$i $$i; done
luaclean:
rm -rf dist