Skip site navigation (1)Skip section navigation (2)
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>