diff options
Diffstat (limited to 'libs/nixio/src/file.c')
-rw-r--r-- | libs/nixio/src/file.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/libs/nixio/src/file.c b/libs/nixio/src/file.c new file mode 100644 index 0000000000..13a40c4999 --- /dev/null +++ b/libs/nixio/src/file.c @@ -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); +} |