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(const 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,32 @@ fopen(const char *filename, const char *mode) { struct stat st; - int fd; + int fd, m, o; FILE *f; - if (mode == NULL || mode[0] != 'r') + if (mode == NULL) return NULL; - fd = open(filename, O_RDONLY); + switch (*mode++) { + case 'r': /* open for reading */ + m = O_RDONLY; + o = 0; + break; + + case 'w': /* open for writing */ + m = O_WRONLY; + /* These are not actually implemented yet */ + o = O_CREAT | O_TRUNC; + break; + + default: /* illegal mode */ + return (NULL); + } + + if (*mode == '+') + m = O_RDWR; + + fd = open(filename, m | o); if (fd < 0) return NULL; @@ -83,6 +102,21 @@ stream->offset += r; return (r); +} + +size_t +fwrite(const void *ptr, size_t size, size_t count, FILE *stream) +{ + ssize_t w; + + if (stream == NULL || ptr == NULL) + return (0); + w = write(stream->fd, (void *)(uintptr_t)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,24 @@ 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"); + mode = "r"; + if (nargs > 1) { + mode = lua_tostring(L, 2); + if (mode == NULL) { + lua_pushnil(L); + return 1; + } + } + FILE * f = fopen(str, mode); if (f != NULL) { FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**)); *ptr = f; @@ -237,6 +246,68 @@ return 2; } +/* + * Implements io.write(file, ...) + * Any number of string and number arguments may be passed to it, + * and it will return the number of bytes written. + */ +static int +lua_writefile(lua_State *L) +{ + FILE **f; + int i, nargs; + size_t w; + const char **args; + size_t *argsz; + + argsz = NULL; + 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(const char *) * nargs); + if (args == NULL) { + lua_pushinteger(L, 0); + return 1; + } + argsz = malloc(sizeof(size_t) * nargs); + if (argsz == NULL) { + free(args); + lua_pushinteger(L, 0); + return 1; + } + /* + * 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] = lua_tolstring(L, i + 2, &argsz[i]); + if (args[i] == NULL) { + free(args); + free(argsz); + lua_pushinteger(L, 0); + return 1; + } + } + for (i = 0; i < nargs - 1; i++) { + w += fwrite(args[i], 1, argsz[i], *f); + } + free(args); + free(argsz); + lua_pushinteger(L, w); + return 1; +} + #define REG_SIMPLE(n) { #n, lua_ ## n } static const struct luaL_Reg loaderlib[] = { REG_SIMPLE(delay), @@ -257,6 +328,7 @@ REG_SIMPLE(ischar), { "open", lua_openfile }, { "read", lua_readfile }, + { "write", lua_writefile }, { NULL, NULL }, }; #undef REG_SIMPLE Index: stand/libsa/stand.h =================================================================== --- stand/libsa/stand.h +++ stand/libsa/stand.h @@ -286,6 +286,9 @@ #define O_RDONLY 0x0 #define O_WRONLY 0x1 #define O_RDWR 0x2 +/* NOT IMPLEMENTED */ +#define O_CREAT 0x0200 /* create if nonexistent */ +#define O_TRUNC 0x0400 /* truncate to zero length */ extern int close(int); extern void closeall(void); extern ssize_t read(int, void *, size_t);