Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Feb 2018 01:15:26 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r329500 - in head/stand: common liblua
Message-ID:  <201802180115.w1I1FQPv087458@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Sun Feb 18 01:15:25 2018
New Revision: 329500
URL: https://svnweb.freebsd.org/changeset/base/329500

Log:
  Lua loader: Add barebones "lfs" module
  
  Add a Lua FileSystem module, an emulation of a subset of the permissively
  licensed (MIT) Lua library of the same name[0], to our loader's Lua
  environment.
  
  [0]: https://github.com/keplerproject/luafilesystem/
  
  Reviewed by:	kevans
  Sponsored by:	Dell EMC Isilon
  Differential Revision:	https://reviews.freebsd.org/D14418

Added:
  head/stand/liblua/lfs.c   (contents, props changed)
  head/stand/liblua/lfs.h   (contents, props changed)
Modified:
  head/stand/common/interp_lua.c
  head/stand/liblua/Makefile

Modified: head/stand/common/interp_lua.c
==============================================================================
--- head/stand/common/interp_lua.c	Sun Feb 18 01:13:58 2018	(r329499)
+++ head/stand/common/interp_lua.c	Sun Feb 18 01:15:25 2018	(r329500)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <lauxlib.h>
 #include <lualib.h>
 #include <lutils.h>
+#include <lfs.h>
 
 struct interp_lua_softc {
 	lua_State	*luap;
@@ -86,6 +87,7 @@ static const luaL_Reg loadedlibs[] = {
 //  {LUA_UTF8LIBNAME, luaopen_utf8},
 //  {LUA_DBLIBNAME, luaopen_debug},
   {"io", luaopen_io},
+  {"lfs", luaopen_lfs},
   {"loader", luaopen_loader},
   {NULL, NULL}
 };

Modified: head/stand/liblua/Makefile
==============================================================================
--- head/stand/liblua/Makefile	Sun Feb 18 01:13:58 2018	(r329499)
+++ head/stand/liblua/Makefile	Sun Feb 18 01:15:25 2018	(r329500)
@@ -21,7 +21,7 @@ SRCS+=	lauxlib.c lbaselib.c lstrlib.c loadlib.c
 #SRCS+=	lbitlib.c liolib.c lmathlib.c loslib.c ltablib.c
 
 # Our utilities.
-SRCS+=	lstd.c lutils.c
+SRCS+=	lfs.c lstd.c lutils.c
 
 WARNS=	3
 

Added: head/stand/liblua/lfs.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/stand/liblua/lfs.c	Sun Feb 18 01:15:25 2018	(r329500)
@@ -0,0 +1,333 @@
+/*-
+ * Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Portions derived from https://github.com/keplerproject/luafilesystem under
+ * the terms of the MIT license:
+ *
+ * Copyright (c) 2003-2014 Kepler Project.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <lua.h>
+#include "lauxlib.h"
+#include "lfs.h"
+#include "lstd.h"
+#include "lutils.h"
+#include "bootstrap.h"
+
+#ifndef nitems
+#define	nitems(x)	(sizeof((x)) / sizeof((x)[0]))
+#endif
+
+/*
+ * The goal is to emulate a subset of the upstream Lua FileSystem library, as
+ * faithfully as possible in the boot environment.  Only APIs that seem useful
+ * need to emulated.
+ *
+ * Example usage:
+ *
+ *     for file in lfs.dir("/boot") do
+ *         print("\t"..file)
+ *     end
+ *
+ * Prints:
+ *     .
+ *     ..
+ * (etc.)
+ *
+ * The other available API is lfs.attributes(), which functions somewhat like
+ * stat(2) and returns a table of values:
+ *
+ *     for k, v in pairs(lfs.attributes("/boot")) do
+ *         print(k .. ":\t" .. v)
+ *     end
+ *
+ * Prints:
+ *     gid:    0
+ *     change: 140737488342640
+ *     mode:   directory
+ *     rdev:   0
+ *     ino:    4199275
+ *     dev:    140737488342544
+ *     modification:   140737488342576
+ *     size:   512
+ *     access: 140737488342560
+ *     permissions:    755
+ *     nlink:  58283552
+ *     uid:    1001
+ */
+
+#define DIR_METATABLE "directory iterator metatable"
+
+static int
+lua_dir_iter_next(lua_State *L)
+{
+	struct dirent *entry;
+	DIR *dp, **dpp;
+
+	dpp = (DIR **)luaL_checkudata(L, 1, DIR_METATABLE);
+	dp = *dpp;
+	luaL_argcheck(L, dp != NULL, 1, "closed directory");
+
+	entry = readdirfd(dp->fd);
+	if (entry == NULL) {
+		closedir(dp);
+		*dpp = NULL;
+		return 0;
+	}
+
+	lua_pushstring(L, entry->d_name);
+	return 1;
+}
+
+static int
+lua_dir_iter_close(lua_State *L)
+{
+	DIR *dp, **dpp;
+
+	dpp = (DIR **)lua_touserdata(L, 1);
+	dp = *dpp;
+	if (dp == NULL)
+		return 0;
+
+	closedir(dp);
+	*dpp = NULL;
+	return 0;
+}
+
+static int
+lua_dir(lua_State *L)
+{
+	const char *path;
+	DIR *dp;
+
+	if (lua_gettop(L) != 1) {
+		lua_pushnil(L);
+		return 1;
+	}
+
+	path = luaL_checkstring(L, 1);
+	dp = opendir(path);
+	if (dp == NULL) {
+		lua_pushnil(L);
+		return 1;
+	}
+
+	lua_pushcfunction(L, lua_dir_iter_next);
+	*(DIR **)lua_newuserdata(L, sizeof(DIR **)) = dp;
+	luaL_getmetatable(L, DIR_METATABLE);
+	lua_setmetatable(L, -2);
+	return 2;
+}
+
+static void
+register_metatable(lua_State *L)
+{
+	/*
+	 * Create so-called metatable for iterator object returned by
+	 * lfs.dir().
+	 */
+	luaL_newmetatable(L, DIR_METATABLE);
+
+	lua_newtable(L);
+	lua_pushcfunction(L, lua_dir_iter_next);
+	lua_setfield(L, -2, "next");
+	lua_pushcfunction(L, lua_dir_iter_close);
+	lua_setfield(L, -2, "close");
+
+	/* Magically associate anonymous method table with metatable. */
+	lua_setfield(L, -2, "__index");
+	/* Implement magic destructor method */
+	lua_pushcfunction(L, lua_dir_iter_close);
+	lua_setfield(L, -2, "__gc");
+
+	lua_pop(L, 1);
+}
+
+#define PUSH_INTEGER(lname, stname)				\
+static void							\
+push_st_ ## lname (lua_State *L, struct stat *sb)		\
+{								\
+	lua_pushinteger(L, (lua_Integer)sb->st_ ## stname);	\
+}
+PUSH_INTEGER(dev, dev)
+PUSH_INTEGER(ino, ino)
+PUSH_INTEGER(nlink, nlink)
+PUSH_INTEGER(uid, uid)
+PUSH_INTEGER(gid, gid)
+PUSH_INTEGER(rdev, rdev)
+PUSH_INTEGER(access, atime)
+PUSH_INTEGER(modification, mtime)
+PUSH_INTEGER(change, ctime)
+PUSH_INTEGER(size, size)
+#undef PUSH_INTEGER
+
+static void
+push_st_mode(lua_State *L, struct stat *sb)
+{
+	const char *mode_s;
+	mode_t mode;
+
+	mode = (sb->st_mode & S_IFMT);
+	if (S_ISREG(mode))
+		mode_s = "file";
+	else if (S_ISDIR(mode))
+		mode_s = "directory";
+	else if (S_ISLNK(mode))
+		mode_s = "link";
+	else if (S_ISSOCK(mode))
+		mode_s = "socket";
+	else if (S_ISFIFO(mode))
+		mode_s = "fifo";
+	else if (S_ISCHR(mode))
+		mode_s = "char device";
+	else if (S_ISBLK(mode))
+		mode_s = "block device";
+	else
+		mode_s = "other";
+
+	lua_pushstring(L, mode_s);
+}
+
+static void
+push_st_permissions(lua_State *L, struct stat *sb)
+{
+	char buf[20];
+
+	/*
+	 * XXX
+	 * Could actually format as "-rwxrwxrwx" -- do we care?
+	 */
+	snprintf(buf, sizeof(buf), "%o", sb->st_mode & ~S_IFMT);
+	lua_pushstring(L, buf);
+}
+
+#define PUSH_ENTRY(n)	{ #n, push_st_ ## n }
+struct stat_members {
+	const char *name;
+	void (*push)(lua_State *, struct stat *);
+} members[] = {
+	PUSH_ENTRY(mode),
+	PUSH_ENTRY(dev),
+	PUSH_ENTRY(ino),
+	PUSH_ENTRY(nlink),
+	PUSH_ENTRY(uid),
+	PUSH_ENTRY(gid),
+	PUSH_ENTRY(rdev),
+	PUSH_ENTRY(access),
+	PUSH_ENTRY(modification),
+	PUSH_ENTRY(change),
+	PUSH_ENTRY(size),
+	PUSH_ENTRY(permissions),
+};
+#undef PUSH_ENTRY
+
+static int
+lua_attributes(lua_State *L)
+{
+	struct stat sb;
+	const char *path, *member;
+	size_t i;
+	int rc;
+
+	path = luaL_checkstring(L, 1);
+	if (path == NULL) {
+		lua_pushnil(L);
+		return 1;
+	}
+
+	rc = stat(path, &sb);
+	if (rc != 0) {
+		lua_pushnil(L);
+		lua_pushfstring(L,
+		    "cannot obtain information from file '%s': %s", path,
+		    strerror(errno));
+		lua_pushinteger(L, errno);
+		return 3;
+	}
+
+	if (lua_isstring(L, 2)) {
+		member = lua_tostring(L, 2);
+		for (i = 0; i < nitems(members); i++) {
+			if (strcmp(members[i].name, member) != 0)
+				continue;
+
+			members[i].push(L, &sb);
+			return 1;
+		}
+		return luaL_error(L, "invalid attribute name '%s'", member);
+	}
+
+	/* Create or reuse existing table */
+	lua_settop(L, 2);
+	if (!lua_istable(L, 2))
+		lua_newtable(L);
+
+	/* Export all stat data to caller */
+	for (i = 0; i < nitems(members); i++) {
+		lua_pushstring(L, members[i].name);
+		members[i].push(L, &sb);
+		lua_rawset(L, -3);
+	}
+	return 1;
+}
+
+#define REG_SIMPLE(n)	{ #n, lua_ ## n }
+static const struct luaL_Reg fslib[] = {
+	REG_SIMPLE(attributes),
+	REG_SIMPLE(dir),
+	{ NULL, NULL },
+};
+#undef REG_SIMPLE
+
+int
+luaopen_lfs(lua_State *L)
+{
+	register_metatable(L);
+	luaL_newlib(L, fslib);
+	return 1;
+}

Added: head/stand/liblua/lfs.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/stand/liblua/lfs.h	Sun Feb 18 01:15:25 2018	(r329500)
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2018 Conrad Meyer <cem@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#pragma once
+
+#include <lua.h>
+
+int luaopen_lfs(lua_State *L);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802180115.w1I1FQPv087458>