nixio next

splice() still does not work correctly
This commit is contained in:
Steven Barth 2009-02-12 19:48:06 +00:00
parent 4327f9250e
commit 5ff898e624
12 changed files with 405 additions and 36 deletions

View file

@ -5,7 +5,7 @@ include ../../build/gccconfig.mk
%.o: %.c
$(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $<
compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o src/io.o
compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o src/io.o src/file.o src/splice.o
$(LINK) $(SHLIB_FLAGS) -o src/nixio.so src/*.o
mkdir -p dist$(LUA_LIBRARYDIR)
cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so

View file

@ -0,0 +1,70 @@
--[[
nixio - Linux I/O library for lua
Copyright 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
local nixio = require "nixio"
local setmetatable, assert = setmetatable, assert
module "nixio.util"
local BUFFERSIZE = 8096
local socket = nixio.socket_meta
function socket.sendall(self, data)
local sent, code, msg = self:send(data)
if not sent then
return sent, code, msg, data
end
while sent < #data do
data = data:sub(sent + 1)
sent, code, msg = self:send(data)
if not sent then
return sent, code, msg, data
end
end
return true
end
function socket.linesource(self, limit)
limit = limit or BUFFERSIZE
local buffer = ""
return function(flush)
local line, endp, _
if flush then
line = buffer
buffer = ""
return line
end
while not line do
_, endp, line = buffer:find("^(.-)\r?\n")
if line then
buffer = buffer:sub(endp+1)
return line
elseif #buffer < limit then
local newblock, code = self:recv(limit - #buffer)
if not newblock then
return nil, code
end
buffer = buffer .. newblock
else
return nil, 0
end
end
end
end

View file

@ -16,15 +16,13 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>
#include "nixio.h"
/**
* getaddrinfo(host, family, port)

View file

@ -16,9 +16,7 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

202
libs/nixio/src/file.c Normal file
View file

@ -0,0 +1,202 @@
/*
* 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 <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static int nixio_file(lua_State *L) {
const char *filename = luaL_checklstring(L, 1, NULL);
const char *mode = luaL_optlstring(L, 2, "r", NULL);
FILE *file = fopen(filename, mode);
if (!file) {
return nixio__perror(L);
}
FILE **udata = lua_newuserdata(L, sizeof(FILE**));
*udata = file;
luaL_getmetatable(L, NIXIO_FILE_META);
lua_setmetatable(L, -2);
return 1;
}
static int nixio_pipe(lua_State *L) {
int pipefd[2];
FILE **udata;
if (pipe(pipefd)) {
return nixio__perror(L);
}
luaL_getmetatable(L, NIXIO_FILE_META);
udata = lua_newuserdata(L, sizeof(FILE**));
if (!(*udata = fdopen(pipefd[0], "r"))) {
return nixio__perror(L);
}
lua_pushvalue(L, -2);
lua_setmetatable(L, -2);
udata = lua_newuserdata(L, sizeof(FILE**));
if (!(*udata = fdopen(pipefd[1], "w"))) {
return nixio__perror(L);
}
lua_pushvalue(L, -3);
lua_setmetatable(L, -2);
return 2;
}
static int nixio_file_write(lua_State *L) {
FILE *fp = nixio__checkfile(L);
size_t len, written;
const char *data = luaL_checklstring(L, 2, &len);
written = fwrite(data, sizeof(char), len, fp);
if (written < 0) {
return nixio__perror(L);
} else {
return written;
}
}
/* Some code borrowed from Lua 5.1.4 liolib.c */
static int nixio_file_read(lua_State *L) {
FILE *f = nixio__checkfile(L);
size_t n = (size_t)luaL_checkinteger(L, 2);
luaL_argcheck(L, 2, n >= 0, "invalid length");
if (n == 0) {
if (feof(f)) {
return 0;
} else {
lua_pushliteral(L, "");
return 1;
}
}
size_t rlen; /* how much to read */
size_t nr; /* number of chars actually read */
luaL_Buffer b;
luaL_buffinit(L, &b);
rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
do {
char *p = luaL_prepbuffer(&b);
if (rlen > n) rlen = n; /* cannot read more than asked */
nr = fread(p, sizeof(char), rlen, f);
luaL_addsize(&b, nr);
n -= nr; /* still have to read `n' chars */
} while (n > 0 && nr == rlen); /* until end of count or eof */
luaL_pushresult(&b); /* close buffer */
return (n == 0 || lua_objlen(L, -1) > 0);
}
static int nixio_file_seek(lua_State *L) {
FILE *f = nixio__checkfile(L);
off_t len = (off_t)luaL_checknumber(L, 2);
int whence;
const char *whstr = luaL_optlstring(L, 3, "set", NULL);
if (!strcmp(whstr, "set")) {
whence = SEEK_SET;
} else if (!strcmp(whstr, "cur")) {
whence = SEEK_CUR;
} else if (!strcmp(whstr, "end")) {
whence = SEEK_END;
} else {
return luaL_argerror(L, 3, "supported values: set, cur, end");
}
return nixio__pstatus(L, !fseeko(f, len, whence));
}
static int nixio_file_tell(lua_State *L) {
FILE *f = nixio__checkfile(L);
off_t pos = ftello(f);
if (pos < 0) {
return nixio__perror(L);
} else {
lua_pushnumber(L, (lua_Number)pos);
return 1;
}
}
static int nixio_file_flush(lua_State *L) {
FILE *f = nixio__checkfile(L);
return nixio__pstatus(L, !fflush(f));
}
static int nixio_file_close(lua_State *L) {
FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
luaL_argcheck(L, *fpp, 1, "invalid file object");
int res = fclose(*fpp);
*fpp = NULL;
return nixio__pstatus(L, !res);
}
static int nixio_file__gc(lua_State *L) {
FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
if (*fpp) {
fclose(*fpp);
*fpp = NULL;
}
return 0;
}
/**
* string representation
*/
static int nixio_file__tostring(lua_State *L) {
lua_pushfstring(L, "nixio file %d", nixio__tofd(L, 1));
return 1;
}
/* method table */
static const luaL_reg M[] = {
{"write", nixio_file_write},
{"read", nixio_file_read},
{"tell", nixio_file_tell},
{"seek", nixio_file_seek},
{"flush", nixio_file_flush},
{"close", nixio_file_close},
{"__gc", nixio_file__gc},
{"__tostring", nixio_file__tostring},
{NULL, NULL}
};
/* module table */
static const luaL_reg R[] = {
{"open", nixio_file},
{"pipe", nixio_pipe},
{NULL, NULL}
};
void nixio_open_file(lua_State *L) {
luaL_register(L, NULL, R);
luaL_newmetatable(L, NIXIO_FILE_META);
luaL_register(L, NULL, M);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pop(L, 1);
}

View file

@ -16,9 +16,7 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

View file

@ -16,13 +16,10 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "nixio.h"
#define VERSION 0.1
@ -52,6 +49,12 @@ nixio_sock* nixio__checksock(lua_State *L) {
return sock;
}
FILE* nixio__checkfile(lua_State *L) {
FILE **fpp = (FILE**)luaL_checkudata(L, 1, NIXIO_FILE_META);
luaL_argcheck(L, *fpp, 1, "invalid file object");
return *fpp;
}
/* read fd from nixio_sock object */
int nixio__checksockfd(lua_State *L) {
return nixio__checksock(L)->fd;
@ -67,15 +70,16 @@ int nixio__checkfd(lua_State *L, int ud) {
int nixio__tofd(lua_State *L, int ud) {
void *udata = lua_touserdata(L, ud);
int fd = -1;
if (udata && lua_getmetatable(L, ud)) {
if (lua_getmetatable(L, ud)) {
luaL_getmetatable(L, NIXIO_META);
luaL_getmetatable(L, NIXIO_FILE_META);
luaL_getmetatable(L, LUA_FILEHANDLE);
if (lua_rawequal(L, -2, -3)) {
if (lua_rawequal(L, -3, -4)) {
fd = ((nixio_sock*)udata)->fd;
} else if (lua_rawequal(L, -1, -3)) {
fd = fileno(*((FILE **)udata));
} else if (lua_rawequal(L, -2, -4) || lua_rawequal(L, -1, -4)) {
fd = (*((FILE **)udata)) ? fileno(*((FILE **)udata)) : -1;
}
lua_pop(L, 3);
lua_pop(L, 4);
}
return fd;
}
@ -90,24 +94,26 @@ LUALIB_API int luaopen_nixio(lua_State *L) {
/* create metatable */
luaL_newmetatable(L, NIXIO_META);
/* method table */
lua_newtable(L);
/* metatable.__index = metatable */
lua_pushvalue(L, -1);
/* metatable.__index = M */
lua_setfield(L, -3, "__index");
lua_remove(L, -2);
lua_setfield(L, -2, "__index");
/* register module */
luaL_register(L, "nixio", R);
/* register metatable as socket_meta */
lua_pushvalue(L, -2);
lua_setfield(L, -2, "socket_meta");
/* register methods */
nixio_open_file(L);
nixio_open_socket(L);
nixio_open_sockopt(L);
nixio_open_bind(L);
nixio_open_address(L);
nixio_open_poll(L);
nixio_open_io(L);
nixio_open_splice(L);
/* module version */
lua_pushnumber(L, VERSION);

View file

@ -2,7 +2,16 @@
#define NIXIO_H_
#define NIXIO_META "nixio.socket"
#define NIXIO_FILE_META "nixio.file"
#define NIXIO_BUFFERSIZE 8096
#define _FILE_OFFSET_BITS 64
/* uClibc: broken as always */
#define _LARGEFILE_SOURCE
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
struct nixio_socket {
int fd;
@ -19,14 +28,17 @@ 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);
FILE* nixio__checkfile(lua_State *L);
/* Module functions */
void nixio_open_file(lua_State *L);
void nixio_open_socket(lua_State *L);
void nixio_open_sockopt(lua_State *L);
void nixio_open_bind(lua_State *L);
void nixio_open_address(lua_State *L);
void nixio_open_poll(lua_State *L);
void nixio_open_io(lua_State *L);
void nixio_open_splice(lua_State *L);
/* Method functions */

View file

@ -16,9 +16,7 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <poll.h>
#include <time.h>
#include <errno.h>

View file

@ -16,9 +16,7 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

View file

@ -16,9 +16,7 @@
* limitations under the License.
*/
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "nixio.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@ -181,7 +179,7 @@ void nixio_open_sockopt(lua_State *L) {
luaL_register(L, NULL, M);
lua_pop(L, 1);
luaL_getmetatable(L, LUA_FILEHANDLE);
luaL_getmetatable(L, NIXIO_FILE_META);
lua_pushcfunction(L, nixio_sock_setblocking);
lua_setfield(L, -2, "setblocking");
lua_pop(L, 1);

91
libs/nixio/src/splice.c Normal file
View file

@ -0,0 +1,91 @@
/*
* 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.
*/
#define _GNU_SOURCE
#include "nixio.h"
#include <fcntl.h>
/* guess what sucks... */
#ifdef __UCLIBC__
#include <unistd.h>
#include <sys/syscall.h>
ssize_t splice(int __fdin, __off64_t *__offin, int __fdout,
__off64_t *__offout, size_t __len, unsigned int __flags) {
return syscall(__NR_splice, __fdin, __offin, __fdout, __offout, __len, __flags);
}
#endif
/**
* Checks whether a flag is set in the table and translates it into a bitmap
*/
static void nixio_splice_flags__w(lua_State *L, int *m, int f, const char *t) {
lua_pushstring(L, t);
lua_rawget(L, -2);
if (lua_toboolean(L, -1)) {
*m |= f;
}
lua_pop(L, 1);
}
/**
* Translate integer to poll flags and vice versa
*/
static int nixio_splice_flags(lua_State *L) {
int flags = 0;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1);
nixio_splice_flags__w(L, &flags, SPLICE_F_MOVE, "move");
nixio_splice_flags__w(L, &flags, SPLICE_F_NONBLOCK, "nonblock");
nixio_splice_flags__w(L, &flags, SPLICE_F_MORE, "more");
lua_pushinteger(L, flags);
return 1;
}
static int nixio_splice(lua_State *L) {
int fd_in = nixio__checkfd(L, 1);
int fd_out = nixio__checkfd(L, 2);
size_t len = luaL_checkinteger(L, 3);
int flags = luaL_optinteger(L, 4, 0);
long spliced = splice(fd_in, NULL, fd_out, NULL, len, flags);
if (spliced < 0) {
return nixio__perror(L);
}
lua_pushnumber(L, spliced);
return 1;
}
/* module table */
static const luaL_reg R[] = {
{"splice", nixio_splice},
{"splice_flags", nixio_splice_flags},
{NULL, NULL}
};
void nixio_open_splice(lua_State *L) {
luaL_register(L, NULL, R);
}