summaryrefslogtreecommitdiffhomepage
path: root/libs/nixio/src
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2009-04-21 16:26:45 +0000
committerSteven Barth <steven@midlink.org>2009-04-21 16:26:45 +0000
commita2b916ab736802050b19562b7c163e3f3bb1566f (patch)
treed35b68f7bcac43f66f4cdb915ef327b76856594b /libs/nixio/src
parent085a0a9ec040fc3ea5ee537d2cee724aa775747b (diff)
Merge nixio 0.2
Diffstat (limited to 'libs/nixio/src')
-rw-r--r--libs/nixio/src/address.c198
-rw-r--r--libs/nixio/src/axtls-compat.c297
-rw-r--r--libs/nixio/src/axtls-compat.h149
-rw-r--r--libs/nixio/src/binary.c313
-rw-r--r--libs/nixio/src/bind.c57
-rw-r--r--libs/nixio/src/bit.c125
-rw-r--r--libs/nixio/src/file.c104
-rw-r--r--libs/nixio/src/fs.c566
-rw-r--r--libs/nixio/src/io.c95
-rw-r--r--libs/nixio/src/mingw-compat.c220
-rw-r--r--libs/nixio/src/mingw-compat.h112
-rw-r--r--libs/nixio/src/nixio-tls.h30
-rw-r--r--libs/nixio/src/nixio.c64
-rw-r--r--libs/nixio/src/nixio.h66
-rw-r--r--libs/nixio/src/poll.c32
-rw-r--r--libs/nixio/src/process.c374
-rw-r--r--libs/nixio/src/socket.c17
-rw-r--r--libs/nixio/src/sockopt.c192
-rw-r--r--libs/nixio/src/splice.c11
-rw-r--r--libs/nixio/src/syslog.c15
-rw-r--r--libs/nixio/src/tls-crypto.c188
-rw-r--r--libs/nixio/src/tls-socket.c22
-rw-r--r--libs/nixio/src/user.c257
23 files changed, 3217 insertions, 287 deletions
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);
+}