Date: Sat, 24 Feb 2018 02:57:24 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r329895 - in head/stand: liblua libsa Message-ID: <201802240257.w1O2vO7Y046881@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Sat Feb 24 02:57:24 2018 New Revision: 329895 URL: https://svnweb.freebsd.org/changeset/base/329895 Log: liblua: Implement write support Write support (even if it only works on UFS) will be needed for nextboot functionality. Reviewed by: cem, imp Differential Revision: https://reviews.freebsd.org/D14478 Modified: head/stand/liblua/lstd.c head/stand/liblua/lstd.h head/stand/liblua/lutils.c head/stand/libsa/stand.h Modified: head/stand/liblua/lstd.c ============================================================================== --- head/stand/liblua/lstd.c Sat Feb 24 02:52:39 2018 (r329894) +++ head/stand/liblua/lstd.c Sat Feb 24 02:57:24 2018 (r329895) @@ -35,13 +35,32 @@ FILE * 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 @@ fread(void *ptr, size_t size, size_t count, FILE *stre 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, ptr, size * count); + if (w == -1) + return (0); + + stream->offset += w; + return ((size_t)w); } int Modified: head/stand/liblua/lstd.h ============================================================================== --- head/stand/liblua/lstd.h Sat Feb 24 02:52:39 2018 (r329894) +++ head/stand/liblua/lstd.h Sat Feb 24 02:57:24 2018 (r329895) @@ -51,6 +51,7 @@ typedef struct DIR 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); Modified: head/stand/liblua/lutils.c ============================================================================== --- head/stand/liblua/lutils.c Sat Feb 24 02:52:39 2018 (r329894) +++ head/stand/liblua/lutils.c Sat Feb 24 02:57:24 2018 (r329895) @@ -165,15 +165,24 @@ lua_printc(lua_State *L) 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,61 @@ lua_readfile(lua_State *L) 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, or nil, an error string, and + * the errno. + */ +static int +lua_writefile(lua_State *L) +{ + FILE **f; + const char *buf; + int i, nargs; + size_t bufsz, w, wrsz; + + buf = NULL; + bufsz = 0; + w = 0; + wrsz = 0; + nargs = lua_gettop(L); + if (nargs < 2) { + errno = EINVAL; + return luaL_fileresult(L, 0, NULL); + } + + f = (FILE**)lua_touserdata(L, 1); + + if (f == NULL || *f == NULL) { + errno = EINVAL; + return luaL_fileresult(L, 0, NULL); + } + + /* Do a validation pass first */ + for (i = 0; i < nargs - 1; i++) { + /* + * With Lua's API, lua_isstring really checks if the argument + * is a string or a number. The latter will be implicitly + * converted to a string by our later call to lua_tolstring. + */ + if (!lua_isstring(L, i + 2)) { + errno = EINVAL; + return luaL_fileresult(L, 0, NULL); + } + } + for (i = 0; i < nargs - 1; i++) { + /* We've already validated; there's no chance of failure */ + buf = lua_tolstring(L, i + 2, &bufsz); + wrsz = fwrite(buf, 1, bufsz, *f); + if (wrsz < bufsz) + return luaL_fileresult(L, 0, NULL); + w += wrsz; + } + lua_pushinteger(L, w); + return 1; +} + #define REG_SIMPLE(n) { #n, lua_ ## n } static const struct luaL_Reg loaderlib[] = { REG_SIMPLE(delay), @@ -257,6 +321,7 @@ static const struct luaL_Reg iolib[] = { REG_SIMPLE(ischar), { "open", lua_openfile }, { "read", lua_readfile }, + { "write", lua_writefile }, { NULL, NULL }, }; #undef REG_SIMPLE Modified: head/stand/libsa/stand.h ============================================================================== --- head/stand/libsa/stand.h Sat Feb 24 02:52:39 2018 (r329894) +++ head/stand/libsa/stand.h Sat Feb 24 02:57:24 2018 (r329895) @@ -286,6 +286,9 @@ extern int open(const char *, int); #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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802240257.w1O2vO7Y046881>