diff --git a/libexec/flua/Makefile b/libexec/flua/Makefile index 29d57211b2ae..cc750e30525f 100644 --- a/libexec/flua/Makefile +++ b/libexec/flua/Makefile @@ -1,69 +1,71 @@ .include # New flua modules should be added here rather than to SUBDIR so that we can do # the right thing for both bootstrap flua and target flua. The former does not # do any shared libs, so we just build them all straight into flua itself rather # than mucking about with the infrastructure to make them linkable -- thus, why # these are all structured to have a Makefile that describes what we want # *installed*, and a Makefile.inc that describes what we need to *build*. +FLUA_MODULES+= lfbsd +FLUA_MODULES+= lfs FLUA_MODULES+= libhash .ifndef BOOTSTRAPPING # Bootstrap flua can't usefully do anything with libjail anyways, because it # can't assume it's being run on a system that even supports jails. FLUA_MODULES+= libjail .endif FLUA_MODULES+= libucl FLUA_MODULES+= liblyaml +FLUA_MODULES+= lposix .ifdef BOOTSTRAPPING # libfreebsd is generally omitted from the bootstrap flua because its # functionality largely assumes a FreeBSD kernel/system headers, so it doesn't # really offer functionality that we can use in bootstrap. CFLAGS+= -I${.CURDIR} -DBOOTSTRAPPING SHAREDIR= ${WORLDTMP}/legacy/usr/share/flua FLUA_PATH= ${SHAREDIR}/?.lua;${SHAREDIR}/?/init.lua CFLAGS+= -DBOOTSTRAP_FLUA_PATH=\"${FLUA_PATH:Q}\" .for mod in ${FLUA_MODULES} .include "${mod}/Makefile.inc" .endfor .else FLUA_MODULES+= libfreebsd SUBDIR+= ${FLUA_MODULES} .endif LUASRC?= ${SRCTOP}/contrib/lua/src .PATH: ${LUASRC} PROG= flua WARNS?= 3 CWARNFLAGS.gcc+= -Wno-format-nonliteral LIBADD+= lua # Entry point SRCS+= lua.c # FreeBSD Extensions .PATH: ${.CURDIR}/modules SRCS+= linit_flua.c -SRCS+= lfs.c lposix.c lfbsd.c CFLAGS+= -I${SRCTOP}/lib/liblua -I${.CURDIR}/modules -I${LUASRC} CFLAGS+= -DLUA_PROGNAME="\"${PROG}\"" # readline bits; these aren't needed if we're building a bootstrap flua, as we # don't expect that one to see any REPL usage. .if !defined(BOOTSTRAPPING) CFLAGS+= -DLUA_USE_READLINE CFLAGS+= -I${SRCTOP}/lib/libedit -I${SRCTOP}/contrib/libedit LIBADD+= edit LDFLAGS+= -Wl,-E .endif .include diff --git a/libexec/flua/lfbsd/Makefile b/libexec/flua/lfbsd/Makefile new file mode 100644 index 000000000000..e2a4aae14bcd --- /dev/null +++ b/libexec/flua/lfbsd/Makefile @@ -0,0 +1,5 @@ +SHLIB_NAME= fbsd.so +WARNS?= 3 + +.include "Makefile.inc" +.include diff --git a/libexec/flua/lfbsd/Makefile.inc b/libexec/flua/lfbsd/Makefile.inc new file mode 100644 index 000000000000..7a78ef82e0fc --- /dev/null +++ b/libexec/flua/lfbsd/Makefile.inc @@ -0,0 +1,2 @@ +.PATH: ${.PARSEDIR} +SRCS+= lfbsd.c diff --git a/libexec/flua/modules/lfbsd.c b/libexec/flua/lfbsd/lfbsd.c similarity index 99% rename from libexec/flua/modules/lfbsd.c rename to libexec/flua/lfbsd/lfbsd.c index ef660ba9fd77..541b6c9611df 100644 --- a/libexec/flua/modules/lfbsd.c +++ b/libexec/flua/lfbsd/lfbsd.c @@ -1,285 +1,289 @@ /* * SPDX-License-Identifier: BSD-2-Clause * * Copyright 2023 Baptiste Daroussin * Copyright (C) 2025 Kyle Evans * * Redistribution and use in source and binary forms, with or without * modification, are permitted providing 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 ``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 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. */ #include #include #include #include #include #include #include #include #include #include "lauxlib.h" #include "lfbsd.h" +#include "bootstrap.h" + #define FBSD_PROCESSHANDLE "fbsd_process_t*" struct fbsd_process { int pid; int stdin_fileno; int stdout_fileno; }; extern char **environ; static const char** luaL_checkarraystrings(lua_State *L, int arg) { const char **ret; lua_Integer n, i; int t; int abs_arg = lua_absindex(L, arg); luaL_checktype(L, abs_arg, LUA_TTABLE); n = lua_rawlen(L, abs_arg); ret = lua_newuserdata(L, (n+1)*sizeof(char*)); for (i=0; i 0 && n <= 2, n >= 2 ? 2 : n, "fbsd.exec takes exactly one or two arguments"); capture_stdout = lua_toboolean(L, 2); if (pipe(stdin_pipe) < 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } if (capture_stdout && pipe(stdout_pipe) < 0) { close_pipes(stdin_pipe); lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } proc = lua_newuserdata(L, sizeof(*proc)); proc->stdin_fileno = stdin_pipe[1]; proc->stdout_fileno = stdout_pipe[1]; posix_spawn_file_actions_init(&action); posix_spawn_file_actions_adddup2(&action, stdin_pipe[0], STDIN_FILENO); posix_spawn_file_actions_addclose(&action, stdin_pipe[1]); if (stdin_pipe[0] != STDIN_FILENO) posix_spawn_file_actions_addclose(&action, stdin_pipe[0]); /* * Setup stdout to be captured if requested. Otherwise, we just let it * go to our own stdout. */ if (stdout_pipe[0] != -1) { posix_spawn_file_actions_adddup2(&action, stdout_pipe[0], STDOUT_FILENO); posix_spawn_file_actions_addclose(&action, stdout_pipe[1]); if (stdout_pipe[0] != STDOUT_FILENO) { posix_spawn_file_actions_addclose(&action, stdout_pipe[0]); } } argv = luaL_checkarraystrings(L, 1); if (0 != (r = posix_spawnp(&pid, argv[0], &action, NULL, (char*const*)argv, environ))) { close_pipes(stdin_pipe); close_pipes(stdout_pipe); posix_spawn_file_actions_destroy(&action); lua_pop(L, 2); /* Pop off the process handle and args. */ lua_pushnil(L); lua_pushstring(L, strerror(r)); lua_pushinteger(L, r); return (3); } lua_pop(L, 1); close(stdin_pipe[0]); if (stdout_pipe[0] != -1) close(stdout_pipe[0]); posix_spawn_file_actions_destroy(&action); proc->pid = pid; luaL_setmetatable(L, FBSD_PROCESSHANDLE); return (1); } static int lua_process_close(lua_State *L) { struct fbsd_process *proc; int pstat, r; proc = luaL_checkudata(L, 1, FBSD_PROCESSHANDLE); while (waitpid(proc->pid, &pstat, 0) == -1) { if ((r = errno) != EINTR) { lua_pushnil(L); lua_pushstring(L, strerror(r)); lua_pushinteger(L, r); return (3); } } if (!WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) { lua_pushnil(L); lua_pushstring(L, "Abnormal termination"); return (2); } if (proc->stdin_fileno >= 0) { close(proc->stdin_fileno); proc->stdin_fileno = -1; } if (proc->stdout_fileno >= 0) { close(proc->stdout_fileno); proc->stdout_fileno = -1; } lua_pushboolean(L, 1); return (1); } static int lua_process_makestdio(lua_State *L, int fd, const char *mode) { luaL_Stream *p; FILE *fp; int r; if (fd == -1) { lua_pushnil(L); lua_pushstring(L, "Stream not captured"); return (2); } fp = fdopen(fd, mode); if (fp == NULL) { r = errno; lua_pushnil(L); lua_pushstring(L, strerror(r)); lua_pushinteger(L, r); return (3); } p = lua_newuserdata(L, sizeof(*p)); p->closef = &lua_process_close; p->f = fp; luaL_setmetatable(L, LUA_FILEHANDLE); return (1); } static int lua_process_stdin(lua_State *L) { struct fbsd_process *proc; proc = luaL_checkudata(L, 1, FBSD_PROCESSHANDLE); return (lua_process_makestdio(L, proc->stdin_fileno, "w")); } static int lua_process_stdout(lua_State *L) { struct fbsd_process *proc; proc = luaL_checkudata(L, 1, FBSD_PROCESSHANDLE); return (lua_process_makestdio(L, proc->stdout_fileno, "r")); } #define PROCESS_SIMPLE(n) { #n, lua_process_ ## n } static const struct luaL_Reg fbsd_process[] = { PROCESS_SIMPLE(close), PROCESS_SIMPLE(stdin), PROCESS_SIMPLE(stdout), { NULL, NULL }, }; static const struct luaL_Reg fbsd_process_meta[] = { { "__index", NULL }, { "__gc", lua_process_close }, { "__close", lua_process_close }, { NULL, NULL }, }; #define REG_SIMPLE(n) { #n, lua_ ## n } static const struct luaL_Reg fbsd_lib[] = { REG_SIMPLE(exec), { NULL, NULL }, }; #undef REG_SIMPLE int luaopen_fbsd(lua_State *L) { luaL_newlib(L, fbsd_lib); luaL_newmetatable(L, FBSD_PROCESSHANDLE); luaL_setfuncs(L, fbsd_process_meta, 0); luaL_newlibtable(L, fbsd_process); luaL_setfuncs(L, fbsd_process, 0); lua_setfield(L, -2, "__index"); lua_pop(L, 1); return (1); } + +FLUA_MODULE(fbsd); diff --git a/libexec/flua/modules/lfbsd.h b/libexec/flua/lfbsd/lfbsd.h similarity index 100% rename from libexec/flua/modules/lfbsd.h rename to libexec/flua/lfbsd/lfbsd.h diff --git a/libexec/flua/lfs/Makefile b/libexec/flua/lfs/Makefile new file mode 100644 index 000000000000..3df83d6d2fc1 --- /dev/null +++ b/libexec/flua/lfs/Makefile @@ -0,0 +1,5 @@ +SHLIB_NAME= lfs.so +WARNS?= 3 + +.include "Makefile.inc" +.include diff --git a/libexec/flua/lfs/Makefile.inc b/libexec/flua/lfs/Makefile.inc new file mode 100644 index 000000000000..9d40c42dc0e6 --- /dev/null +++ b/libexec/flua/lfs/Makefile.inc @@ -0,0 +1,2 @@ +.PATH: ${.PARSEDIR} +SRCS+= lfs.c diff --git a/libexec/flua/modules/lfs.c b/libexec/flua/lfs/lfs.c similarity index 99% rename from libexec/flua/modules/lfs.c rename to libexec/flua/lfs/lfs.c index 8cb8d6fc9fed..517e16ae65c8 100644 --- a/libexec/flua/modules/lfs.c +++ b/libexec/flua/lfs/lfs.c @@ -1,448 +1,453 @@ /*- * Copyright (c) 2018 Conrad Meyer * 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 #ifndef _STANDALONE #include #include #include #include #include #include #endif #include #include "lauxlib.h" #include "lfs.h" #ifdef _STANDALONE #include "lstd.h" #include "lutils.h" -#include "bootstrap.h" #endif +#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. 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; } + +#ifndef _STANDALONE +FLUA_MODULE(lfs); +#endif diff --git a/libexec/flua/modules/lfs.h b/libexec/flua/lfs/lfs.h similarity index 100% rename from libexec/flua/modules/lfs.h rename to libexec/flua/lfs/lfs.h diff --git a/libexec/flua/libhash/lhash.c b/libexec/flua/libhash/lhash.c index 7127ddc1d530..f455f006bf27 100644 --- a/libexec/flua/libhash/lhash.c +++ b/libexec/flua/libhash/lhash.c @@ -1,181 +1,183 @@ /*- * Copyright (c) 2024 Netflix, Inc * * SPDX-License-Identifier: BSD-2-Clause */ #include #include "lauxlib.h" #include "lhash.h" #include #include #include "bootstrap.h" #define SHA256_META "SHA256 meta table" #define SHA256_DIGEST_LEN 32 /* * Note C++ comments indicate the before -- after state of the stack, in with a * similar convention to forth's ( ) comments. Lua indexes are from 1 and can be * read left to right (leftmost is 1). Negative are relative to the end (-1 is * rightmost). A '.' indicates a return value left on the stack (all values to * its right). Trivial functions don't do this. */ /* * Updates the digest with the new data passed in. Takes 1 argument, which * is converted to a string. */ static int lua_sha256_update(lua_State *L) { size_t len; const unsigned char *data; SHA256_CTX *ctx; ctx = luaL_checkudata(L, 1, SHA256_META); data = luaL_checklstring(L, 2, &len); SHA256_Update(ctx, data, len); lua_settop(L, 1); return (1); } /* * Finalizes the digest value and returns it as a 32-byte binary string. The ctx * is zeroed. */ static int lua_sha256_digest(lua_State *L) { SHA256_CTX *ctx; unsigned char digest[SHA256_DIGEST_LEN]; ctx = luaL_checkudata(L, 1, SHA256_META); SHA256_Final(digest, ctx); lua_pushlstring(L, digest, sizeof(digest)); return (1); } /* * Finalizes the digest value and returns it as a 64-byte ascii string of hex * numbers. The ctx is zeroed. */ static int lua_sha256_hexdigest(lua_State *L) { SHA256_CTX *ctx; char buf[SHA256_DIGEST_LEN * 2 + 1]; unsigned char digest[SHA256_DIGEST_LEN]; static const char hex[]="0123456789abcdef"; int i; ctx = luaL_checkudata(L, 1, SHA256_META); SHA256_Final(digest, ctx); for (i = 0; i < SHA256_DIGEST_LEN; i++) { buf[i+i] = hex[digest[i] >> 4]; buf[i+i+1] = hex[digest[i] & 0x0f]; } buf[i+i] = '\0'; lua_pushstring(L, buf); return (1); } /* * Zeros out the ctx before garbage collection. Normally this is done in * obj:digest or obj:hexdigest, but if not, it will be wiped here. Lua * manages freeing the ctx memory. */ static int lua_sha256_done(lua_State *L) { SHA256_CTX *ctx; ctx = luaL_checkudata(L, 1, SHA256_META); memset(ctx, 0, sizeof(*ctx)); return (0); } /* * Create object obj which accumulates the state of the sha256 digest * for its contents and any subsequent obj:update call. It takes zero * or 1 arguments. */ static int lua_sha256(lua_State *L) { SHA256_CTX *ctx; int top; /* We take 0 or 1 args */ top = lua_gettop(L); // data -- data if (top > 1) { lua_pushnil(L); return (1); } ctx = lua_newuserdata(L, sizeof(*ctx)); // data -- data ctx SHA256_Init(ctx); if (top == 1) { size_t len; const unsigned char *data; data = luaL_checklstring(L, 1, &len); SHA256_Update(ctx, data, len); } luaL_setmetatable(L, SHA256_META); // data ctx -- data ctx return (1); // data . ctx } /* * Setup the metatable to manage our userdata that we create in lua_sha256. We * request a finalization call with __gc so we can zero out the ctx buffer so * that we don't leak secrets if obj:digest or obj:hexdigest aren't called. */ static void register_metatable_sha256(lua_State *L) { luaL_newmetatable(L, SHA256_META); // -- meta lua_newtable(L); // meta -- meta tbl lua_pushcfunction(L, lua_sha256_update); // meta tbl -- meta tbl fn lua_setfield(L, -2, "update"); // meta tbl fn -- meta tbl lua_pushcfunction(L, lua_sha256_digest); // meta tbl -- meta tbl fn lua_setfield(L, -2, "digest"); // meta tbl fn -- meta tbl lua_pushcfunction(L, lua_sha256_hexdigest); // meta tbl -- meta tbl fn lua_setfield(L, -2, "hexdigest"); // meta tbl fn -- meta tbl /* Associate tbl with metatable */ lua_setfield(L, -2, "__index"); // meta tbl -- meta lua_pushcfunction(L, lua_sha256_done); // meta -- meta fn lua_setfield(L, -2, "__gc"); // meta fn -- meta lua_pop(L, 1); // meta -- } #define REG_SIMPLE(n) { #n, lua_ ## n } static const struct luaL_Reg hashlib[] = { REG_SIMPLE(sha256), { NULL, NULL }, }; #undef REG_SIMPLE int luaopen_hash(lua_State *L) { register_metatable_sha256(L); luaL_newlib(L, hashlib); return 1; } +#ifndef _STANDALONE FLUA_MODULE(hash); +#endif diff --git a/libexec/flua/linit_flua.c b/libexec/flua/linit_flua.c index e5e38353ec9b..bb3748daefb4 100644 --- a/libexec/flua/linit_flua.c +++ b/libexec/flua/linit_flua.c @@ -1,99 +1,92 @@ /* ** $Id: linit.c,v 1.39.1.1 2017/04/19 17:20:42 roberto Exp $ ** Initialization of libraries for lua.c and other clients ** See Copyright Notice in lua.h */ #define linit_c #define LUA_LIB /* ** If you embed Lua in your program and need to open the standard ** libraries, call luaL_openlibs in your program. If you need a ** different set of libraries, copy this file to your project and edit ** it to suit your needs. ** ** You can also *preload* libraries, so that a later 'require' can ** open the library, which is already linked to the application. ** For that, do the following code: ** ** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); ** lua_pushcfunction(L, luaopen_modname); ** lua_setfield(L, -2, modname); ** lua_pop(L, 1); // remove PRELOAD table */ #include "lprefix.h" #include #include #include "lua.h" #include "lualib.h" #include "lauxlib.h" -#include "lfs.h" -#include "lposix.h" -#include "lfbsd.h" #include "bootstrap.h" /* ** these libs are loaded by lua.c and are readily available to any Lua ** program */ static const luaL_Reg loadedlibs[] = { {"_G", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, {LUA_COLIBNAME, luaopen_coroutine}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_DBLIBNAME, luaopen_debug}, #if defined(LUA_COMPAT_BITLIB) {LUA_BITLIBNAME, luaopen_bit32}, #endif - /* FreeBSD Extensions */ - {"lfs", luaopen_lfs}, - {"posix", luaopen_posix}, - {"fbsd", luaopen_fbsd}, {NULL, NULL} }; #ifdef BOOTSTRAPPING static void __attribute__((constructor)) flua_init_env(void) { /* * This happens in the middle of luaopen_package(). We could move it into * flua_setup_mods(), but it seems better to avoid its timing being so * important that it would break some of our bootstrap modules if someone * were to reorder things. */ if (getenv("LUA_PATH") == NULL) setenv("LUA_PATH", BOOTSTRAP_FLUA_PATH, 1); } static void flua_setup_mods (lua_State *L) { const luaL_Reg **flib; SET_FOREACH(flib, FLUA_MODULE_SETNAME) { luaL_requiref(L, (*flib)->name, (*flib)->func, 1); lua_pop(L, 1); /* remove lib */ } }; #endif LUALIB_API void luaL_openlibs (lua_State *L) { const luaL_Reg *lib; /* "require" functions from 'loadedlibs' and set results to global table */ for (lib = loadedlibs; lib->func; lib++) { luaL_requiref(L, lib->name, lib->func, 1); lua_pop(L, 1); /* remove lib */ } #ifdef BOOTSTRAPPING flua_setup_mods(L); #endif } diff --git a/libexec/flua/lposix/Makefile b/libexec/flua/lposix/Makefile new file mode 100644 index 000000000000..92321d51be9a --- /dev/null +++ b/libexec/flua/lposix/Makefile @@ -0,0 +1,5 @@ +SHLIB_NAME= posix.so +WARNS?= 3 + +.include "Makefile.inc" +.include diff --git a/libexec/flua/lposix/Makefile.inc b/libexec/flua/lposix/Makefile.inc new file mode 100644 index 000000000000..499e6779e84d --- /dev/null +++ b/libexec/flua/lposix/Makefile.inc @@ -0,0 +1,2 @@ +.PATH: ${.PARSEDIR} +SRCS+= lposix.c diff --git a/libexec/flua/modules/lposix.c b/libexec/flua/lposix/lposix.c similarity index 99% rename from libexec/flua/modules/lposix.c rename to libexec/flua/lposix/lposix.c index 75cdd345aeaa..430bb6f28baf 100644 --- a/libexec/flua/modules/lposix.c +++ b/libexec/flua/lposix/lposix.c @@ -1,699 +1,704 @@ /*- * Copyright (c) 2019, 2023 Kyle Evans * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include "lauxlib.h" #include "lposix.h" +#include "bootstrap.h" + static void enforce_max_args(lua_State *L, int max) { int narg; narg = lua_gettop(L); luaL_argcheck(L, narg <= max, max + 1, "too many arguments"); } /* * Minimal implementation of luaposix needed for internal FreeBSD bits. */ static int lua__exit(lua_State *L) { int code; enforce_max_args(L, 1); code = luaL_checkinteger(L, 1); _exit(code); } static int lua_basename(lua_State *L) { char *inpath, *outpath; enforce_max_args(L, 1); inpath = strdup(luaL_checkstring(L, 1)); if (inpath == NULL) { lua_pushnil(L); lua_pushstring(L, strerror(ENOMEM)); lua_pushinteger(L, ENOMEM); return (3); } outpath = basename(inpath); lua_pushstring(L, outpath); free(inpath); return (1); } static int lua_chmod(lua_State *L) { const char *path; mode_t mode; enforce_max_args(L, 2); path = luaL_checkstring(L, 1); mode = (mode_t)luaL_checkinteger(L, 2); if (chmod(path, mode) == -1) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } lua_pushinteger(L, 0); return (1); } static int lua_chown(lua_State *L) { const char *path; uid_t owner = (uid_t)-1; gid_t group = (gid_t)-1; int error; enforce_max_args(L, 3); path = luaL_checkstring(L, 1); if (lua_isinteger(L, 2)) owner = (uid_t)lua_tointeger(L, 2); else if (lua_isstring(L, 2)) { char buf[4096]; struct passwd passwd, *pwd; error = getpwnam_r(lua_tostring(L, 2), &passwd, buf, sizeof(buf), &pwd); if (error == 0) owner = pwd->pw_uid; else return (luaL_argerror(L, 2, lua_pushfstring(L, "unknown user %s", lua_tostring(L, 2)))); } else if (!lua_isnoneornil(L, 2)) { const char *type = luaL_typename(L, 2); return (luaL_argerror(L, 2, lua_pushfstring(L, "integer or string expected, got %s", type))); } if (lua_isinteger(L, 3)) group = (gid_t)lua_tointeger(L, 3); else if (lua_isstring(L, 3)) { char buf[4096]; struct group gr, *grp; error = getgrnam_r(lua_tostring(L, 3), &gr, buf, sizeof(buf), &grp); if (error == 0) group = grp->gr_gid; else return (luaL_argerror(L, 3, lua_pushfstring(L, "unknown group %s", lua_tostring(L, 3)))); } else if (!lua_isnoneornil(L, 3)) { const char *type = luaL_typename(L, 3); return (luaL_argerror(L, 3, lua_pushfstring(L, "integer or string expected, got %s", type))); } if (chown(path, owner, group) == -1) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } lua_pushinteger(L, 0); return (1); } static int lua_pclose(lua_State *L) { int error, fd; enforce_max_args(L, 1); fd = luaL_checkinteger(L, 1); if (fd < 0) { error = EBADF; goto err; } if (close(fd) == 0) { lua_pushinteger(L, 0); return (1); } error = errno; err: lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } static int lua_dup2(lua_State *L) { int error, oldd, newd; enforce_max_args(L, 2); oldd = luaL_checkinteger(L, 1); if (oldd < 0) { error = EBADF; goto err; } newd = luaL_checkinteger(L, 2); if (newd < 0) { error = EBADF; goto err; } error = dup2(oldd, newd); if (error >= 0) { lua_pushinteger(L, error); return (1); } error = errno; err: lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } static int lua_execp(lua_State *L) { int argc, error; const char *file; const char **argv; enforce_max_args(L, 2); file = luaL_checkstring(L, 1); luaL_checktype(L, 2, LUA_TTABLE); lua_len(L, 2); argc = lua_tointeger(L, -1); /* * Use lua_newuserdatauv() to allocate a scratch buffer that is tracked * and freed by lua's GC. This avoid any chance of a leak if a lua error * is raised later in this function (e.g. by luaL_argerror()). * The (argc + 2) size gives enough space in the buffer for argv[0] and * the terminating NULL. */ argv = lua_newuserdatauv(L, (argc + 2) * sizeof(char *), 0); /* * Sequential tables in lua start at index 1 by convention. * If there happens to be a string at index 0, use that to * override the default argv[0]. This matches the lposix API. */ lua_pushinteger(L, 0); lua_gettable(L, 2); argv[0] = lua_tostring(L, -1); if (argv[0] == NULL) { argv[0] = file; } for (int i = 1; i <= argc; i++) { lua_pushinteger(L, i); lua_gettable(L, 2); argv[i] = lua_tostring(L, -1); if (argv[i] == NULL) { luaL_argerror(L, 2, "argv table must contain only strings"); } } argv[argc + 1] = NULL; execvp(file, (char **)argv); error = errno; lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } static int lua_fnmatch(lua_State *L) { const char *pattern, *string; int flags; enforce_max_args(L, 3); pattern = luaL_checkstring(L, 1); string = luaL_checkstring(L, 2); flags = luaL_optinteger(L, 3, 0); lua_pushinteger(L, fnmatch(pattern, string, flags)); return (1); } static int lua_uname(lua_State *L) { struct utsname name; int error; enforce_max_args(L, 0); error = uname(&name); if (error != 0) { error = errno; lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } lua_newtable(L); #define setkv(f) do { \ lua_pushstring(L, name.f); \ lua_setfield(L, -2, #f); \ } while (0) setkv(sysname); setkv(nodename); setkv(release); setkv(version); setkv(machine); #undef setkv return (1); } static int lua_dirname(lua_State *L) { char *inpath, *outpath; enforce_max_args(L, 1); inpath = strdup(luaL_checkstring(L, 1)); if (inpath == NULL) { lua_pushnil(L); lua_pushstring(L, strerror(ENOMEM)); lua_pushinteger(L, ENOMEM); return (3); } outpath = dirname(inpath); lua_pushstring(L, outpath); free(inpath); return (1); } static int lua_fork(lua_State *L) { pid_t pid; enforce_max_args(L, 0); pid = fork(); if (pid < 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } lua_pushinteger(L, pid); return (1); } static int lua_getpid(lua_State *L) { enforce_max_args(L, 0); lua_pushinteger(L, getpid()); return (1); } static int lua_pipe(lua_State *L) { int error, fd[2]; enforce_max_args(L, 0); error = pipe(fd); if (error != 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (1); } lua_pushinteger(L, fd[0]); lua_pushinteger(L, fd[1]); return (2); } static int lua_read(lua_State *L) { char *buf; ssize_t ret; size_t sz; int error, fd; enforce_max_args(L, 2); fd = luaL_checkinteger(L, 1); sz = luaL_checkinteger(L, 2); if (fd < 0) { error = EBADF; goto err; } buf = malloc(sz); if (buf == NULL) goto err; /* * For 0-byte reads, we'll still push the empty string and let the * caller deal with EOF to match lposix semantics. */ ret = read(fd, buf, sz); if (ret >= 0) lua_pushlstring(L, buf, ret); else if (ret < 0) error = errno; /* Save to avoid clobber by free() */ free(buf); if (error != 0) goto err; /* Just the string pushed. */ return (1); err: lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } static int lua_realpath(lua_State *L) { const char *inpath; char *outpath; enforce_max_args(L, 1); inpath = luaL_checkstring(L, 1); outpath = realpath(inpath, NULL); if (outpath == NULL) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } lua_pushstring(L, outpath); free(outpath); return (1); } static int lua_wait(lua_State *L) { pid_t pid; int options, status; enforce_max_args(L, 2); pid = luaL_optinteger(L, 1, -1); options = luaL_optinteger(L, 2, 0); status = 0; pid = waitpid(pid, &status, options); if (pid < 0) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return (3); } lua_pushinteger(L, pid); if (pid == 0) { lua_pushliteral(L, "running"); return (2); } if (WIFCONTINUED(status)) { lua_pushliteral(L, "continued"); return (2); } else if(WIFSTOPPED(status)) { lua_pushliteral(L, "stopped"); lua_pushinteger(L, WSTOPSIG(status)); return (3); } else if (WIFEXITED(status)) { lua_pushliteral(L, "exited"); lua_pushinteger(L, WEXITSTATUS(status)); return (3); } else if (WIFSIGNALED(status)) { lua_pushliteral(L, "killed"); lua_pushinteger(L, WTERMSIG(status)); return (3); } return (1); } static int lua_write(lua_State *L) { const char *buf; size_t bufsz, sz; ssize_t ret; off_t offset; int error, fd; enforce_max_args(L, 4); fd = luaL_checkinteger(L, 1); if (fd < 0) { error = EBADF; goto err; } buf = luaL_checkstring(L, 2); bufsz = lua_rawlen(L, 2); sz = luaL_optinteger(L, 3, bufsz); offset = luaL_optinteger(L, 4, 0); if ((size_t)offset > bufsz || offset + sz > bufsz) { lua_pushnil(L); lua_pushfstring(L, "write: invalid access offset %zu, size %zu in a buffer size %zu", offset, sz, bufsz); lua_pushinteger(L, EINVAL); return (3); } ret = write(fd, buf + offset, sz); if (ret < 0) { error = errno; goto err; } lua_pushinteger(L, ret); return (1); err: lua_pushnil(L); lua_pushstring(L, strerror(error)); lua_pushinteger(L, error); return (3); } #define REG_DEF(n, func) { #n, func } #define REG_SIMPLE(n) REG_DEF(n, lua_ ## n) static const struct luaL_Reg libgenlib[] = { REG_SIMPLE(basename), REG_SIMPLE(dirname), { NULL, NULL }, }; static const struct luaL_Reg stdliblib[] = { REG_SIMPLE(realpath), { NULL, NULL }, }; static const struct luaL_Reg fnmatchlib[] = { REG_SIMPLE(fnmatch), { NULL, NULL }, }; static const struct luaL_Reg sys_statlib[] = { REG_SIMPLE(chmod), { NULL, NULL }, }; static const struct luaL_Reg sys_utsnamelib[] = { REG_SIMPLE(uname), { NULL, NULL }, }; static const struct luaL_Reg sys_waitlib[] = { REG_SIMPLE(wait), {NULL, NULL}, }; static const struct luaL_Reg unistdlib[] = { REG_SIMPLE(_exit), REG_SIMPLE(chown), REG_DEF(close, lua_pclose), REG_SIMPLE(dup2), REG_SIMPLE(execp), REG_SIMPLE(fork), REG_SIMPLE(getpid), REG_SIMPLE(pipe), REG_SIMPLE(read), REG_SIMPLE(write), { NULL, NULL }, }; #undef REG_SIMPLE #undef REG_DEF static int luaopen_posix_libgen(lua_State *L) { luaL_newlib(L, libgenlib); return (1); } static int luaopen_posix_stdlib(lua_State *L) { luaL_newlib(L, stdliblib); return (1); } static int luaopen_posix_fnmatch(lua_State *L) { luaL_newlib(L, fnmatchlib); #define setkv(f) do { \ lua_pushinteger(L, f); \ lua_setfield(L, -2, #f); \ } while (0) setkv(FNM_PATHNAME); setkv(FNM_NOESCAPE); setkv(FNM_NOMATCH); setkv(FNM_PERIOD); #undef setkv return 1; } static int luaopen_posix_sys_stat(lua_State *L) { luaL_newlib(L, sys_statlib); return (1); } static int luaopen_posix_sys_utsname(lua_State *L) { luaL_newlib(L, sys_utsnamelib); return 1; } static int luaopen_posix_sys_wait(lua_State *L) { luaL_newlib(L, sys_waitlib); #define lua_pushflag(L, flag) do { \ lua_pushinteger(L, flag); \ lua_setfield(L, -2, #flag); \ } while(0) /* Only these two exported by lposix */ lua_pushflag(L, WNOHANG); lua_pushflag(L, WUNTRACED); lua_pushflag(L, WCONTINUED); lua_pushflag(L, WSTOPPED); #ifdef WTRAPPED lua_pushflag(L, WTRAPPED); #endif lua_pushflag(L, WEXITED); lua_pushflag(L, WNOWAIT); #undef lua_pushflag return (1); } static int luaopen_posix_unistd(lua_State *L) { luaL_newlib(L, unistdlib); return (1); } int luaopen_posix(lua_State *L) { lua_newtable(L); /* posix */ luaL_requiref(L, "posix.fnmatch", luaopen_posix_fnmatch, 0); lua_setfield(L, -2, "fnmatch"); luaL_requiref(L, "posix.libgen", luaopen_posix_libgen, 0); lua_setfield(L, -2, "libgen"); luaL_requiref(L, "posix.stdlib", luaopen_posix_stdlib, 0); lua_setfield(L, -2, "stdlib"); lua_newtable(L); /* posix.sys */ luaL_requiref(L, "posix.sys.stat", luaopen_posix_sys_stat, 0); lua_setfield(L, -2, "stat"); luaL_requiref(L, "posix.sys.utsname", luaopen_posix_sys_utsname, 0); lua_setfield(L, -2, "utsname"); luaL_requiref(L, "posix.sys.wait", luaopen_posix_sys_wait, 0); lua_setfield(L, -2, "wait"); lua_setfield(L, -2, "sys"); luaL_requiref(L, "posix.unistd", luaopen_posix_unistd, 0); lua_setfield(L, -2, "unistd"); return (1); } + +/* Only this one needed in our bootstrap set, it will load the others. */ +FLUA_MODULE(posix); diff --git a/libexec/flua/modules/lposix.h b/libexec/flua/lposix/lposix.h similarity index 100% rename from libexec/flua/modules/lposix.h rename to libexec/flua/lposix/lposix.h diff --git a/stand/liblua/Makefile b/stand/liblua/Makefile index ce7eb89fe494..b1c34ec0a466 100644 --- a/stand/liblua/Makefile +++ b/stand/liblua/Makefile @@ -1,48 +1,48 @@ .include .PATH: ${LUASRC} .PATH: ${LIBLUASRC} .include "${BOOTSRC}/lua.mk" LIB= lua INTERNALLIB= # Core Lua. SRCS= lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c \ lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c \ ltm.c lundump.c lvm.c lzio.c SRCS+= lauxlib.c lbaselib.c lstrlib.c loadlib.c # These aren't yet included, but link now, omitting them saves 15k #SRCS+= lcorolib.c ldblib.c lutf8lib.c # These aren't yet compatible with the boot environment, and some may never be #SRCS+= lbitlib.c liolib.c lmathlib.c loslib.c ltablib.c # Our utilities. SRCS+= lerrno.c lpager.c lstd.c lutils.c SRCS+= gfx_utils.c -.PATH: ${FLUASRC}/modules +.PATH: ${FLUASRC}/lfs SRCS+= lfs.c .PATH: ${FLUALIB}/libhash SRCS+= lhash.c WARNS?= 3 CFLAGS+= -DLUA_PATH=\"${LUAPATH}\" -DLUA_PATH_DEFAULT=\"${LUAPATH}/\?.lua\" CFLAGS+= -ffreestanding -nostdlib -DLUA_USE_POSIX CFLAGS+= -fno-stack-protector -D__BSD_VISIBLE CFLAGS+= -I${BOOTSRC}/include -I${LIBLUASRC} -I${LUASRC} -I${LDRSRC} CFLAGS.gfx_utils.c+= -I${SRCTOP}/sys/teken -I${SRCTOP}/contrib/pnglite CFLAGS.lhash.c+= -I${FLUALIB}/libhash -I${SRCTOP}/sys/crypto/sha2 .if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0 CFLAGS+= -fPIC .endif .include "${BOOTSRC}/veriexec.mk" .include diff --git a/stand/loader.mk b/stand/loader.mk index 4073e523e552..e26ba1401912 100644 --- a/stand/loader.mk +++ b/stand/loader.mk @@ -1,203 +1,203 @@ .PATH: ${LDRSRC} ${BOOTSRC}/libsa CFLAGS+=-I${LDRSRC} SRCS+= boot.c commands.c console.c devopen.c interp.c SRCS+= interp_backslash.c interp_parse.c ls.c misc.c SRCS+= modinfo.c SRCS+= module.c nvstore.c pnglite.c tslog.c CFLAGS.module.c += -I$(SRCTOP)/sys/teken -I${SRCTOP}/contrib/pnglite .PATH: ${SRCTOP}/contrib/pnglite CFLAGS.pnglite.c+= -I${SRCTOP}/contrib/pnglite CFLAGS.pnglite.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib .if ${MACHINE} == "i386" || ${MACHINE_CPUARCH} == "amd64" SRCS+= load_elf32.c load_elf32_obj.c reloc_elf32.c SRCS+= load_elf64.c load_elf64_obj.c reloc_elf64.c .elif ${MACHINE_CPUARCH} == "aarch64" SRCS+= load_elf64.c reloc_elf64.c .elif ${MACHINE_CPUARCH} == "arm" SRCS+= load_elf32.c reloc_elf32.c .elif ${MACHINE_CPUARCH} == "powerpc" SRCS+= load_elf32.c reloc_elf32.c SRCS+= load_elf64.c reloc_elf64.c SRCS+= metadata.c .elif ${MACHINE_CPUARCH} == "riscv" SRCS+= load_elf64.c reloc_elf64.c SRCS+= metadata.c .endif # # LOADER_*_SUPPORT variables are used to subset the boot loader in the various # configurations each platform supports. These are typically used to omit broken # options, or to size optimize for space constrained instances. These are set in # loader Makefiles (which include loader.mk) to control which subset of features # are enabled. These cannot generally be set in src.conf since that would affect # all loaders, but also not all loaders are setup for overrides like that and # not all combinations of the following have been tested or even work. Sometimes # non-default values won't work due to buggy support for that component being # optional. # # LOADER_BZIP2_SUPPORT Add support for bzip2 compressed files # LOADER_CD9660_SUPPORT Add support for iso9660 filesystems # LOADER_DISK_SUPPORT Adds support for disks and mounting filesystems on it # LOADER_EXT2FS_SUPPORT Add support for ext2 Linux filesystems # LOADER_GPT_SUPPORT Add support for GPT partitions # LOADER_GZIP_SUPPORT Add support for gzip compressed files # LOADER_INSTALL_SUPPORT Add support for booting off of installl ISOs # LOADER_MBR_SUPPORT Add support for MBR partitions # LOADER_MSDOS_SUPPORT Add support for FAT filesystems # LOADER_NET_SUPPORT Adds networking support (useless w/o net drivers sometimes) # LOADER_NFS_SUPPORT Add NFS support # LOADER_TFTP_SUPPORT Add TFTP support # LOADER_UFS_SUPPORT Add support for UFS filesystems # LOADER_ZFS_SUPPORT Add support for ZFS filesystems # .if ${LOADER_DISK_SUPPORT:Uyes} == "yes" CFLAGS.part.c+= -DHAVE_MEMCPY -I${SRCTOP}/sys/contrib/zlib SRCS+= disk.c part.c vdisk.c .endif .if ${LOADER_NET_SUPPORT:Uno} == "yes" SRCS+= dev_net.c .endif .if defined(HAVE_BCACHE) SRCS+= bcache.c .endif .if defined(MD_IMAGE_SIZE) CFLAGS+= -DMD_IMAGE_SIZE=${MD_IMAGE_SIZE} SRCS+= md.c .else CLEANFILES+= md.o .endif # Machine-independent ISA PnP .if defined(HAVE_ISABUS) SRCS+= isapnp.c .endif .if defined(HAVE_PNP) SRCS+= pnp.c .endif .if ${LOADER_INTERP} == "lua" SRCS+= interp_lua.c .include "${BOOTSRC}/lua.mk" LDR_INTERP= ${LIBLUA} LDR_INTERP32= ${LIBLUA32} -CFLAGS.interp_lua.c= -DLUA_PATH=\"${LUAPATH}\" -I${FLUASRC}/modules +CFLAGS.interp_lua.c= -DLUA_PATH=\"${LUAPATH}\" -I${FLUASRC}/lfs .elif ${LOADER_INTERP} == "4th" SRCS+= interp_forth.c .include "${BOOTSRC}/ficl.mk" LDR_INTERP= ${LIBFICL} LDR_INTERP32= ${LIBFICL32} .elif ${LOADER_INTERP} == "simp" SRCS+= interp_simple.c .else .error Unknown interpreter ${LOADER_INTERP} .endif .if defined(BOOT_PROMPT_123) CFLAGS+= -DBOOT_PROMPT_123 .endif .if defined(LOADER_INSTALL_SUPPORT) SRCS+= install.c .endif # Filesystem support .if ${LOADER_CD9660_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_CD9660_SUPPORT .endif .if ${LOADER_EXT2FS_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_EXT2FS_SUPPORT .endif .if ${LOADER_MSDOS_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_MSDOS_SUPPORT .endif .if ${LOADER_UFS_SUPPORT:Uyes} == "yes" CFLAGS+= -DLOADER_UFS_SUPPORT .endif # Compression .if ${LOADER_GZIP_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_GZIP_SUPPORT .endif .if ${LOADER_BZIP2_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_BZIP2_SUPPORT .endif # Network related things .if ${LOADER_NET_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_NET_SUPPORT .endif .if ${LOADER_NFS_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_NFS_SUPPORT .endif .if ${LOADER_TFTP_SUPPORT:Uno} == "yes" CFLAGS+= -DLOADER_TFTP_SUPPORT .endif # Partition support .if ${LOADER_GPT_SUPPORT:Uyes} == "yes" CFLAGS+= -DLOADER_GPT_SUPPORT .endif .if ${LOADER_MBR_SUPPORT:Uyes} == "yes" CFLAGS+= -DLOADER_MBR_SUPPORT .endif .if ${HAVE_ZFS:Uno} == "yes" CFLAGS+= -DLOADER_ZFS_SUPPORT CFLAGS+= -I${ZFSSRC} CFLAGS+= -I${SYSDIR}/cddl/boot/zfs CFLAGS+= -I${SYSDIR}/cddl/contrib/opensolaris/uts/common SRCS+= zfs_cmd.c .endif LIBFICL= ${BOOTOBJ}/ficl/libficl.a .if ${MACHINE} == "i386" LIBFICL32= ${LIBFICL} .else LIBFICL32= ${BOOTOBJ}/ficl32/libficl.a .endif LIBLUA= ${BOOTOBJ}/liblua/liblua.a .if ${MACHINE} == "i386" LIBLUA32= ${LIBLUA} .else LIBLUA32= ${BOOTOBJ}/liblua32/liblua.a .endif CLEANFILES+= vers.c VERSION_FILE?= ${.CURDIR}/version .if ${MK_REPRODUCIBLE_BUILD} != no REPRO_FLAG= -r .endif vers.c: ${LDRSRC}/newvers.sh ${VERSION_FILE} sh ${LDRSRC}/newvers.sh ${REPRO_FLAG} ${VERSION_FILE} \ ${NEWVERSWHAT} .if ${MK_LOADER_VERBOSE} != "no" CFLAGS+= -DELF_VERBOSE .endif # Each loader variant defines their own help filename. Optional or # build-specific commands are included by augmenting HELP_FILES. .if !defined(HELP_FILENAME) .error Define HELP_FILENAME before including loader.mk .endif HELP_FILES+= ${LDRSRC}/help.common CFLAGS+= -DHELP_FILENAME=\"${HELP_FILENAME}\" .if ${INSTALL_LOADER_HELP_FILE:Uyes} == "yes" CLEANFILES+= ${HELP_FILENAME} FILES+= ${HELP_FILENAME} .endif ${HELP_FILENAME}: ${HELP_FILES} cat ${HELP_FILES} | awk -f ${LDRSRC}/merge_help.awk > ${.TARGET}