diff options
Diffstat (limited to 'libexec/flua/modules/lfs.c')
-rw-r--r-- | libexec/flua/modules/lfs.c | 448 |
1 files changed, 0 insertions, 448 deletions
diff --git a/libexec/flua/modules/lfs.c b/libexec/flua/modules/lfs.c deleted file mode 100644 index 8cb8d6fc9fed..000000000000 --- a/libexec/flua/modules/lfs.c +++ /dev/null @@ -1,448 +0,0 @@ -/*- - * 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> -#ifndef _STANDALONE -#include <sys/stat.h> -#include <dirent.h> -#include <errno.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#endif - -#include <lua.h> -#include "lauxlib.h" -#include "lfs.h" - -#ifdef _STANDALONE -#include "lstd.h" -#include "lutils.h" -#include "bootstrap.h" -#endif - -#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. Example code: - * - * attrs, errormsg, errorcode = lfs.attributes("/boot") - * if attrs == nil then - * print(errormsg) - * return errorcode - * end - * - * for k, v in pairs(attrs) do - * print(k .. ":\t" .. v) - * end - * return 0 - * - * Prints (on success): - * 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_pushtype(lua_State *L __unused, const struct dirent *ent __unused) -{ - - /* - * This is a non-standard extension to luafilesystem for loader's - * benefit. The extra stat() calls to determine the entry type can - * be quite expensive on some systems, so this speeds up enumeration of - * /boot greatly by providing the type up front. - * - * This extension is compatible enough with luafilesystem, in that we're - * just using an extra return value for the iterator. - */ -#ifdef _STANDALONE - lua_pushinteger(L, ent->d_type); - return 1; -#else - return 0; -#endif -} - -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"); - -#ifdef _STANDALONE - entry = readdirfd(dp->fd); -#else - entry = readdir(dp); -#endif - if (entry == NULL) { - closedir(dp); - *dpp = NULL; - return 0; - } - - lua_pushstring(L, entry->d_name); - return 1 + lua_dir_iter_pushtype(L, entry); -} - -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); - lua_pushfstring(L, "cannot convert first argument to string"); - lua_pushinteger(L, EINVAL); - return 3; - } - - 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; -} - -#ifndef _STANDALONE -#define lfs_mkdir_impl(path) (mkdir((path), \ - S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | \ - S_IROTH | S_IXOTH)) - -static int -lua_mkdir(lua_State *L) -{ - const char *path; - int error, serrno; - - path = luaL_checkstring(L, 1); - if (path == NULL) { - lua_pushnil(L); - lua_pushfstring(L, "cannot convert first argument to string"); - lua_pushinteger(L, EINVAL); - return 3; - } - - error = lfs_mkdir_impl(path); - if (error == -1) { - /* Save it; unclear what other libc functions may be invoked */ - serrno = errno; - lua_pushnil(L); - lua_pushfstring(L, strerror(serrno)); - lua_pushinteger(L, serrno); - return 3; - } - - lua_pushboolean(L, 1); - return 1; -} - -static int -lua_rmdir(lua_State *L) -{ - const char *path; - int error, serrno; - - path = luaL_checkstring(L, 1); - if (path == NULL) { - lua_pushnil(L); - lua_pushfstring(L, "cannot convert first argument to string"); - lua_pushinteger(L, EINVAL); - return 3; - } - - error = rmdir(path); - if (error == -1) { - /* Save it; unclear what other libc functions may be invoked */ - serrno = errno; - lua_pushnil(L); - lua_pushfstring(L, strerror(serrno)); - lua_pushinteger(L, serrno); - return 3; - } - - lua_pushboolean(L, 1); - return 1; -} -#endif - -#define REG_SIMPLE(n) { #n, lua_ ## n } -static const struct luaL_Reg fslib[] = { - REG_SIMPLE(attributes), - REG_SIMPLE(dir), -#ifndef _STANDALONE - REG_SIMPLE(mkdir), - REG_SIMPLE(rmdir), -#endif - { NULL, NULL }, -}; -#undef REG_SIMPLE - -int -luaopen_lfs(lua_State *L) -{ - register_metatable(L); - luaL_newlib(L, fslib); -#ifdef _STANDALONE - /* Non-standard extension for loader, used with lfs.dir(). */ - lua_pushinteger(L, DT_DIR); - lua_setfield(L, -2, "DT_DIR"); -#endif - return 1; -} |