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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to