diff options
Diffstat (limited to 'libs/nixio')
43 files changed, 5247 insertions, 323 deletions
diff --git a/libs/nixio/LICENSE b/libs/nixio/LICENSE new file mode 100644 index 000000000..f49a4e16e --- /dev/null +++ b/libs/nixio/LICENSE @@ -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.
\ No newline at end of file diff --git a/libs/nixio/Makefile b/libs/nixio/Makefile index ca22328ae..8e87eaa10 100644 --- a/libs/nixio/Makefile +++ b/libs/nixio/Makefile @@ -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) diff --git a/libs/nixio/NOTICE b/libs/nixio/NOTICE new file mode 100644 index 000000000..f557831e8 --- /dev/null +++ b/libs/nixio/NOTICE @@ -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>
\ No newline at end of file diff --git a/libs/nixio/README b/libs/nixio/README index 01b836130..ba9b36b30 100644 --- a/libs/nixio/README +++ b/libs/nixio/README @@ -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" diff --git a/libs/nixio/docsrc/README.lua b/libs/nixio/docsrc/README.lua new file mode 100644 index 000000000..20793cefe --- /dev/null +++ b/libs/nixio/docsrc/README.lua @@ -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 !
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.CryptoHash.lua b/libs/nixio/docsrc/nixio.CryptoHash.lua new file mode 100644 index 000000000..a08b48d68 --- /dev/null +++ b/libs/nixio/docsrc/nixio.CryptoHash.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.File.lua b/libs/nixio/docsrc/nixio.File.lua new file mode 100644 index 000000000..368562a2a --- /dev/null +++ b/libs/nixio/docsrc/nixio.File.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.Socket.lua b/libs/nixio/docsrc/nixio.Socket.lua new file mode 100644 index 000000000..7123393bf --- /dev/null +++ b/libs/nixio/docsrc/nixio.Socket.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.TLSContext.lua b/libs/nixio/docsrc/nixio.TLSContext.lua new file mode 100644 index 000000000..7cc071195 --- /dev/null +++ b/libs/nixio/docsrc/nixio.TLSContext.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.TLSSocket.lua b/libs/nixio/docsrc/nixio.TLSSocket.lua new file mode 100644 index 000000000..b932cde0d --- /dev/null +++ b/libs/nixio/docsrc/nixio.TLSSocket.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.UnifiedIO.lua b/libs/nixio/docsrc/nixio.UnifiedIO.lua new file mode 100644 index 000000000..d0b189cf4 --- /dev/null +++ b/libs/nixio/docsrc/nixio.UnifiedIO.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.bin.lua b/libs/nixio/docsrc/nixio.bin.lua new file mode 100644 index 000000000..13e125d3c --- /dev/null +++ b/libs/nixio/docsrc/nixio.bin.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.bit.lua b/libs/nixio/docsrc/nixio.bit.lua new file mode 100644 index 000000000..3bdad51f2 --- /dev/null +++ b/libs/nixio/docsrc/nixio.bit.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.crypto.lua b/libs/nixio/docsrc/nixio.crypto.lua new file mode 100644 index 000000000..158d0fc0b --- /dev/null +++ b/libs/nixio/docsrc/nixio.crypto.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.fs.lua b/libs/nixio/docsrc/nixio.fs.lua new file mode 100644 index 000000000..5d08719e9 --- /dev/null +++ b/libs/nixio/docsrc/nixio.fs.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/docsrc/nixio.lua b/libs/nixio/docsrc/nixio.lua new file mode 100644 index 000000000..7efeab8ef --- /dev/null +++ b/libs/nixio/docsrc/nixio.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/lua/bit.lua b/libs/nixio/lua/bit.lua new file mode 100644 index 000000000..cdfecb1a4 --- /dev/null +++ b/libs/nixio/lua/bit.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/lua/nixio/fs.lua b/libs/nixio/lua/nixio/fs.lua new file mode 100644 index 000000000..f745ffe78 --- /dev/null +++ b/libs/nixio/lua/nixio/fs.lua @@ -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
\ No newline at end of file diff --git a/libs/nixio/lua/nixio/util.lua b/libs/nixio/lua/nixio/util.lua index 59bdce8f4..2c9fc93a3 100644 --- a/libs/nixio/lua/nixio/util.lua +++ b/libs/nixio/lua/nixio/util.lua @@ -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 diff --git a/libs/nixio/src/address.c b/libs/nixio/src/address.c index 8b9ae2807..835a8a2f9 100644 --- a/libs/nixio/src/address.c +++ b/libs/nixio/src/address.c @@ -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); @@ -183,59 +227,41 @@ static int nixio_getnameinfo(lua_State *L) { } /** - * getsockname() / getpeername() helper + * getsockname() */ -static int nixio_sock__getname(lua_State *L, int sock) { +static int nixio_sock_getsockname(lua_State *L) { 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"); - } + struct sockaddr_storage saddr; + socklen_t addrlen = sizeof(saddr); + nixio_addr addr; - if (!inet_ntop(addr.ss_family, binaddr, ipaddr, sizeof(ipaddr))) { - return nixio__perror(L); + if (getsockname(sockfd, (struct sockaddr*)&saddr, &addrlen) || + nixio__addr_parse(&addr, (struct sockaddr*)&saddr)) { + return nixio__perror_s(L); } - lua_pushstring(L, ipaddr); - lua_pushinteger(L, ntohs(port)); + lua_pushstring(L, addr.host); + lua_pushnumber(L, addr.port); return 2; } /** - * getsockname() - */ -static int nixio_sock_getsockname(lua_State *L) { - return nixio_sock__getname(L, 1); -} - -/** * 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; } diff --git a/libs/nixio/src/axtls-compat.c b/libs/nixio/src/axtls-compat.c new file mode 100644 index 000000000..2c5b746c2 --- /dev/null +++ b/libs/nixio/src/axtls-compat.c @@ -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; } diff --git a/libs/nixio/src/axtls-compat.h b/libs/nixio/src/axtls-compat.h new file mode 100644 index 000000000..77533ef4f --- /dev/null +++ b/libs/nixio/src/axtls-compat.h @@ -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); diff --git a/libs/nixio/src/binary.c b/libs/nixio/src/binary.c new file mode 100644 index 000000000..72425b113 --- /dev/null +++ b/libs/nixio/src/binary.c @@ -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"); +} diff --git a/libs/nixio/src/bind.c b/libs/nixio/src/bind.c index 785a28d5a..7b2b719e3 100644 --- a/libs/nixio/src/bind.c +++ b/libs/nixio/src/bind.c @@ -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 */ diff --git a/libs/nixio/src/bit.c b/libs/nixio/src/bit.c new file mode 100644 index 000000000..14fdecab1 --- /dev/null +++ b/libs/nixio/src/bit.c @@ -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"); +} diff --git a/libs/nixio/src/file.c b/libs/nixio/src/file.c index 2fe00c2a8..482752522 100644 --- a/libs/nixio/src/file.c +++ b/libs/nixio/src/file.c @@ -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"); } diff --git a/libs/nixio/src/fs.c b/libs/nixio/src/fs.c new file mode 100644 index 000000000..10727d030 --- /dev/null +++ b/libs/nixio/src/fs.c @@ -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 +} diff --git a/libs/nixio/src/io.c b/libs/nixio/src/io.c index 0ce4fcc3a..8b8f25b42 100644 --- a/libs/nixio/src/io.c +++ b/libs/nixio/src/io.c @@ -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) { + int e = WSAGetLastError(); + if (e == WSAECONNRESET || e == WSAECONNABORTED || e == WSAESHUTDOWN) { + readc = 0; + } + } +#endif + if (readc < 0) { - return nixio__perror(L); + 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"); - } - - if (!inet_ntop(addrobj.ss_family, binaddr, ipaddr, sizeof(ipaddr))) { - return nixio__perror(L); + return 1; } - - lua_pushstring(L, ipaddr); - lua_pushinteger(L, ntohs(port)); - - return 3; } } } diff --git a/libs/nixio/src/mingw-compat.c b/libs/nixio/src/mingw-compat.c new file mode 100644 index 000000000..02be504a1 --- /dev/null +++ b/libs/nixio/src/mingw-compat.c @@ -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); +} diff --git a/libs/nixio/src/mingw-compat.h b/libs/nixio/src/mingw-compat.h new file mode 100644 index 000000000..a26a4beec --- /dev/null +++ b/libs/nixio/src/mingw-compat.h @@ -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_ */ diff --git a/libs/nixio/src/nixio-tls.h b/libs/nixio/src/nixio-tls.h index 4c58dd136..0fac5a980 100644 --- a/libs/nixio/src/nixio-tls.h +++ b/libs/nixio/src/nixio-tls.h @@ -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_ */ diff --git a/libs/nixio/src/nixio.c b/libs/nixio/src/nixio.c index 3a70aa8da..457bbd1f2 100644 --- a/libs/nixio/src/nixio.c +++ b/libs/nixio/src/nixio.c @@ -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 */ diff --git a/libs/nixio/src/nixio.h b/libs/nixio/src/nixio.h index 23da17d44..8caa5b969 100644 --- a/libs/nixio/src/nixio.h +++ b/libs/nixio/src/nixio.h @@ -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); diff --git a/libs/nixio/src/poll.c b/libs/nixio/src/poll.c index fdec2caaf..4af32890a 100644 --- a/libs/nixio/src/poll.c +++ b/libs/nixio/src/poll.c @@ -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); } diff --git a/libs/nixio/src/process.c b/libs/nixio/src/process.c index a82e5660d..0e8ac8a29 100644 --- a/libs/nixio/src/process.c +++ b/libs/nixio/src/process.c @@ -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,103 +219,229 @@ 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_getpid(lua_State *L) { - lua_pushinteger(L, getpid()); +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; } -static int nixio_getppid(lua_State *L) { - lua_pushinteger(L, getppid()); - return 1; +#endif /* !__WINNT__ */ + +static int nixio_chdir(lua_State *L) { + return nixio__pstatus(L, !chdir(luaL_checkstring(L, 1))); } -static int nixio_getuid(lua_State *L) { - lua_pushinteger(L, getuid()); - return 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_getgid(lua_State *L) { - lua_pushinteger(L, getgid()); +static int nixio_getpid(lua_State *L) { + lua_pushinteger(L, getpid()); 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 1; +} - return nixio__pstatus(L, !setgid(gid)); +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_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>"); - } +static int nixio_exec(lua_State *L) { + return nixio__exec(L, NIXIO_EXECV); +} - return nixio__pstatus(L, !setuid(uid)); +static int nixio_execp(lua_State *L) { + return nixio__exec(L, NIXIO_EXECVP); } -static int nixio_nice(lua_State *L) { - int nval = luaL_checkint(L, 1); +static int nixio_exece(lua_State *L) { + return nixio__exec(L, NIXIO_EXECVE); +} - errno = 0; - nval = nice(nval); +static int nixio_getcwd(lua_State *L) { + char path[PATH_MAX]; - if (nval == -1 && errno) { - return nixio__perror(L); - } else { - lua_pushinteger(L, nval); + if (getcwd(path, sizeof(path))) { + lua_pushstring(L, path); return 1; + } else { + return nixio__perror(L); } } -static int nixio_setsid(lua_State *L) { - pid_t pid = setsid(); +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; +} - if (pid == -1) { +#ifdef __linux__ + +#include <sys/sysinfo.h> + +static int nixio_sysinfo(lua_State *L) { + struct sysinfo info; + if (sysinfo(&info)) { return nixio__perror(L); - } else { - lua_pushinteger(L, pid); - return 1; } -} -static int nixio_chdir(lua_State *L) { - return nixio__pstatus(L, !chdir(luaL_checkstring(L, 1))); + 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} }; diff --git a/libs/nixio/src/socket.c b/libs/nixio/src/socket.c index 336f34812..17c6afc79 100644 --- a/libs/nixio/src/socket.c +++ b/libs/nixio/src/socket.c @@ -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 */ diff --git a/libs/nixio/src/sockopt.c b/libs/nixio/src/sockopt.c index 2d68d12ef..7e063e4a3 100644 --- a/libs/nixio/src/sockopt.c +++ b/libs/nixio/src/sockopt.c @@ -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); } diff --git a/libs/nixio/src/splice.c b/libs/nixio/src/splice.c index f64144627..db215efb1 100644 --- a/libs/nixio/src/splice.c +++ b/libs/nixio/src/splice.c @@ -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__ */ diff --git a/libs/nixio/src/syslog.c b/libs/nixio/src/syslog.c index 9b3581df1..89f1b1dda 100644 --- a/libs/nixio/src/syslog.c +++ b/libs/nixio/src/syslog.c @@ -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__ */ diff --git a/libs/nixio/src/tls-crypto.c b/libs/nixio/src/tls-crypto.c new file mode 100644 index 000000000..c93b1aa18 --- /dev/null +++ b/libs/nixio/src/tls-crypto.c @@ -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"); +} diff --git a/libs/nixio/src/tls-socket.c b/libs/nixio/src/tls-socket.c index 0f504ccbb..fe4cb6075 100644 --- a/libs/nixio/src/tls-socket.c +++ b/libs/nixio/src/tls-socket.c @@ -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); diff --git a/libs/nixio/src/user.c b/libs/nixio/src/user.c new file mode 100644 index 000000000..adfe1f4f6 --- /dev/null +++ b/libs/nixio/src/user.c @@ -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); +} diff --git a/libs/nixio/standalone.mk b/libs/nixio/standalone.mk new file mode 100644 index 000000000..fe71f581a --- /dev/null +++ b/libs/nixio/standalone.mk @@ -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
\ No newline at end of file |