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 <c...@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 <c...@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);
_______________________________________________
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