Index: stand/liblua/lstd.h =================================================================== --- stand/liblua/lstd.h +++ stand/liblua/lstd.h @@ -51,6 +51,7 @@ FILE *fopen(const char *filename, const char *mode); FILE *freopen( const char *filename, const char *mode, FILE *stream); size_t fread(void *ptr, size_t size, size_t count, FILE *stream); +size_t fwrite(void *ptr, size_t size, size_t count, FILE *stream); int fclose(FILE *stream); int ferror(FILE *stream); int feof(FILE *stream); Index: stand/liblua/lstd.c =================================================================== --- stand/liblua/lstd.c +++ stand/liblua/lstd.c @@ -35,13 +35,20 @@ fopen(const char *filename, const char *mode) { struct stat st; - int fd; + int fd, flags, modelen; FILE *f; - if (mode == NULL || mode[0] != 'r') + if (mode == NULL || (mode[0] != 'r' && mode[0] != 'w')) return NULL; - fd = open(filename, O_RDONLY); + modelen = strlen(mode); + flags = O_WRONLY; + /* This is a rough approximation of what fopen(2) does */ + if (mode[0] == 'r') + flags = O_RDONLY; + if (modelen > 1 && mode[1] == '+') + flags = O_RDWR; + fd = open(filename, flags); if (fd < 0) return NULL; @@ -83,6 +90,21 @@ stream->offset += r; return (r); +} + +size_t +fwrite(void *ptr, size_t size, size_t count, FILE *stream) +{ + ssize_t w; + + if (stream == NULL || ptr == NULL) + return (0); + w = write(stream->fd, ptr, size * count); + if (w == -1) + return (0); + + stream->offset += w; + return ((size_t)w); } int Index: stand/liblua/lutils.c =================================================================== --- stand/liblua/lutils.c +++ stand/liblua/lutils.c @@ -165,15 +165,18 @@ static int lua_openfile(lua_State *L) { - const char *str; + const char *mode, *str; + int nargs; - if (lua_gettop(L) != 1) { + nargs = lua_gettop(L); + if (nargs < 1 || nargs > 2) { lua_pushnil(L); return 1; } str = lua_tostring(L, 1); - - FILE * f = fopen(str, "r"); + if (nargs > 1) + mode = lua_tostring(L, 2); + FILE * f = fopen(str, mode); if (f != NULL) { FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**)); *ptr = f; @@ -237,6 +240,52 @@ return 2; } +static int +lua_writefile(lua_State *L) +{ + FILE **f; + int i, nargs; + size_t w; + const char * buf; + char **args; + + nargs = lua_gettop(L); + if (nargs < 2) { + lua_pushinteger(L, 0); + return 1; + } + + f = (FILE**)lua_touserdata(L, 1); + + if (f == NULL || *f == NULL) { + lua_pushinteger(L, 0); + return 1; + } + + w = 0; + args = malloc(sizeof(char *) * nargs); + if (args == NULL) + return 0; + /* + * Do a single pass and get all of the strings, so we at least don't + * fail mid-write because of an invalid argument. + */ + for (i = 0; i < nargs - 1; i++) { + args[i] = (char *)(intptr_t)luaL_checkstring(L, i + 2); + if (args[i] == NULL) { + lua_pushinteger(L, 0); + return 1; + } + } + for (i = 0; i < nargs - 1; i++) { + buf = args[i]; + w += fwrite(__DECONST(char *, buf), 1, strlen(buf), *f); + } + free(args); + lua_pushinteger(L, w); + return 1; +} + #define REG_SIMPLE(n) { #n, lua_ ## n } static const struct luaL_Reg loaderlib[] = { REG_SIMPLE(delay), @@ -257,6 +306,7 @@ REG_SIMPLE(ischar), { "open", lua_openfile }, { "read", lua_readfile }, + { "write", lua_writefile }, { NULL, NULL }, }; #undef REG_SIMPLE