Implement lua scripts with support for standard and posix libraries.
1.1 --- a/configure.ac Thu Jan 22 22:54:45 2009 +0000
1.2 +++ b/configure.ac Thu Feb 05 22:43:29 2009 +0000
1.3 @@ -202,6 +202,27 @@
1.4 AC_DEFINE([HAVE_RPMLIB], [1], [Define if you have librpm])])
1.5 AC_SUBST(RPM_LIBS)
1.6 AM_CONDITIONAL([HAVE_RPMLIB], [test -n "$RPM_LIBS"])
1.7 +
1.8 +AC_ARG_WITH([lua],
1.9 + [AS_HELP_STRING([--without-lua], [disable support for lua])],
1.10 + [],
1.11 + [with_lua=yes])
1.12 +
1.13 +LUA_CFLAGS=
1.14 +LUA_LIBS=
1.15 +AS_IF([test "x$with_lua" != xno],
1.16 + [PKG_CHECK_MODULES(LUA, [lua])
1.17 + REQUIREMENTS="$REQUIREMENTS lua"
1.18 + AC_DEFINE([HAVE_LUA], [1], [Define if you have lua])
1.19 + AC_PATH_PROG(LUA, [lua], [no])
1.20 + AS_IF([test "x$LUA" = xno],
1.21 + [AC_MSG_ERROR([Can't find lua program. Please install lua-devel or use --without-lua.])])
1.22 + AC_DEFINE_UNQUOTED([LUA_BINARY], ["$LUA"],
1.23 + [Define to the location of the lua binary])])
1.24 +AC_SUBST(LUA_CFLAGS)
1.25 +AC_SUBST(LUA_LIBS)
1.26 +AM_CONDITIONAL([HAVE_LUA], [test "x$with_lua" != xno])
1.27 +
1.28 AC_SUBST(REQUIREMENTS)
1.29
1.30 if test "x$GCC" = "xyes"; then
2.1 --- a/librazor/Makefile.am Thu Jan 22 22:54:45 2009 +0000
2.2 +++ b/librazor/Makefile.am Thu Feb 05 22:43:29 2009 +0000
2.3 @@ -12,6 +12,9 @@
2.4 -DPACKAGE_LIB_DIR=\""$(libdir)"\"
2.5
2.6 lib_LTLIBRARIES = librazor.la
2.7 +if HAVE_LUA
2.8 + check_PROGRAMS = test-lua
2.9 +endif
2.10
2.11 librazorincludedir = $(includedir)/razor
2.12
2.13 @@ -31,7 +34,22 @@
2.14 merger.c \
2.15 transaction.c
2.16
2.17 -librazor_la_LIBADD = $(ZLIB_LIBS) ../gl/libgnu.la $(EXTRA_LIBS)
2.18 +if HAVE_LUA
2.19 + librazor_la_SOURCES += lua.c
2.20 +endif
2.21 +
2.22 +librazor_la_LIBADD = $(ZLIB_LIBS) $(LUA_LIBS) ../gl/libgnu.la $(EXTRA_LIBS)
2.23 +
2.24 +if HAVE_LUA
2.25 + test_lua_SOURCES = test-lua.c
2.26 + test_lua_LDADD = lua.lo util.lo $(LUA_LIBS) ../gl/libgnu.la \
2.27 + $(EXTRA_LIBS)
2.28 +
2.29 + TESTS = test-lua
2.30 +endif
2.31 +
2.32 +EXTRA_DIST = \
2.33 + test.lua
2.34
2.35 clean-local :
2.36 rm -f *~
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/librazor/lua.c Thu Feb 05 22:43:29 2009 +0000
3.3 @@ -0,0 +1,361 @@
3.4 +/*
3.5 + * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
3.6 + *
3.7 + * This program is free software; you can redistribute it and/or modify
3.8 + * it under the terms of the GNU General Public License as published by
3.9 + * the Free Software Foundation; either version 2 of the License, or
3.10 + * (at your option) any later version.
3.11 + *
3.12 + * This program is distributed in the hope that it will be useful,
3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.15 + * GNU General Public License for more details.
3.16 + *
3.17 + * You should have received a copy of the GNU General Public License along
3.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
3.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
3.20 + */
3.21 +
3.22 +#include "config.h"
3.23 +
3.24 +#include <stdlib.h>
3.25 +#include <string.h>
3.26 +#include <stdio.h>
3.27 +#include <errno.h>
3.28 +#include <sys/stat.h>
3.29 +#include <sys/types.h>
3.30 +#include <lua.h>
3.31 +#include <lualib.h>
3.32 +#include <lauxlib.h>
3.33 +
3.34 +#include "razor.h"
3.35 +#include "razor-internal.h"
3.36 +
3.37 +#define MAX_ARGS 2
3.38 +
3.39 +#define ARG_FLAG_OPT 0x1
3.40 +#define ARG_FLAG_BYPASS 0x2
3.41 +
3.42 +#define ARG(flags, swtch, index, type) \
3.43 + ((flags) << 26 | (swtch) << 21 | \
3.44 + (index) << 16 | type)
3.45 +#define ARG_FLAGS(arg) ((unsigned)(arg) >> 26)
3.46 +#define ARG_SWTCH(arg) ((unsigned)(arg) >> 21 & 0x1F)
3.47 +#define ARG_INDEX(arg) ((unsigned)(arg) >> 16 & 0x1F)
3.48 +#define ARG_TYPE(arg) ((unsigned)(arg) & 0xFFFF)
3.49 +
3.50 +#define ARG_NONE 0
3.51 +#define ARG_STRING(n) ARG(0, 0, n, LUA_TSTRING)
3.52 +#define ARG_OPT_STRING(n) ARG(ARG_FLAG_OPT, 0, n, LUA_TSTRING)
3.53 +#define ARG_BYP_STRING(n, s) ARG(ARG_FLAG_BYPASS, s, n, LUA_TSTRING)
3.54 +
3.55 +struct razor_proxy {
3.56 + char *table, *name;
3.57 + int result;
3.58 + unsigned args[MAX_ARGS];
3.59 +};
3.60 +
3.61 +static struct razor_proxy proxy[] = {
3.62 + { NULL, "dofile", LUA_TNONE, { ARG_STRING(1) } },
3.63 + { NULL, "loadfile", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.64 + { "io", "input", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.65 + { "io", "output", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.66 + { "io", "lines", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.67 + { "io", "open", LUA_TNONE, { ARG_STRING(1) } },
3.68 + { "io", "popen", LUA_TNONE, { ARG_STRING(1) } },
3.69 + /*
3.70 + * Note: We do not proxy os.execute
3.71 + * We can't do it properly (there is no way to distinguish filenames
3.72 + * in arguments from any other strings) so it's better not to try.
3.73 + * Scripts that attempt to be portable should use posix.exec[p]
3.74 + */
3.75 + { "os", "remove", LUA_TNONE, { ARG_STRING(1) } },
3.76 + { "os", "rename", LUA_TNONE, { ARG_STRING(1), ARG_STRING(2) } },
3.77 + /*
3.78 + * Note: We do not proxy os.tmpname
3.79 + * It should never be used. scripts should use io.tmpfile instead
3.80 + * if the rather limited functionality it provides suffices. The
3.81 + * proper solution is to implement posix.mkstemp
3.82 + */
3.83 + { "posix", "access", LUA_TNONE, { ARG_STRING(1) } },
3.84 + { "posix", "chdir", LUA_TNONE, { ARG_STRING(1) } },
3.85 + { "posix", "chmod", LUA_TNONE, { ARG_STRING(1) } },
3.86 + { "posix", "chown", LUA_TNONE, { ARG_STRING(1) } },
3.87 + { "posix", "dir", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.88 + { "posix", "exec", LUA_TNONE, { ARG_STRING(1) } },
3.89 + { "posix", "execp", LUA_TNONE, { ARG_STRING(1) } },
3.90 + { "posix", "files", LUA_TNONE, { ARG_OPT_STRING(1) } },
3.91 + { "posix", "getcwd", LUA_TSTRING, { ARG_NONE } },
3.92 + { "posix", "glob", LUA_TTABLE, { ARG_STRING(1) } },
3.93 + { "posix", "link", LUA_TNONE, { ARG_BYP_STRING(1, 3), ARG_STRING(2) } },
3.94 + { "posix", "mkdir", LUA_TNONE, { ARG_STRING(1) } },
3.95 + { "posix", "mkfifo", LUA_TNONE, { ARG_STRING(1) } },
3.96 + { "posix", "pathconf", LUA_TNONE, { ARG_STRING(1) } },
3.97 + { "posix", "readlink", LUA_TNONE, { ARG_STRING(1) } },
3.98 + { "posix", "rmdir", LUA_TNONE, { ARG_STRING(1) } },
3.99 + { "posix", "stat", LUA_TNONE, { ARG_STRING(1) } },
3.100 + { "posix", "unlink", LUA_TNONE, { ARG_STRING(1) } },
3.101 + { "posix", "utime", LUA_TNONE, { ARG_STRING(1) } },
3.102 +};
3.103 +
3.104 +static lua_CFunction execp_handler;
3.105 +
3.106 +struct razor_lua {
3.107 + const char *root;
3.108 + lua_CFunction handler[ARRAY_SIZE(proxy)];
3.109 +};
3.110 +
3.111 +static void *alloc_lua(void *user_data, void *ptr, size_t osize, size_t nsize)
3.112 +{
3.113 + if (!nsize) {
3.114 + free(ptr);
3.115 + return NULL;
3.116 + } else
3.117 + return realloc(ptr, nsize);
3.118 +}
3.119 +
3.120 +static int proxy_execp(lua_State *L)
3.121 +{
3.122 + int r, n, err, got_eacces = 0;
3.123 + char *file = strdup(luaL_checkstring(L, 1));
3.124 + char *exe;
3.125 + const char *s, *e, *path;
3.126 + struct razor_lua *rl;
3.127 +
3.128 + if (*file == '\0' || strchr(file, '/')) {
3.129 + r = execp_handler(L);
3.130 + free(file);
3.131 + return r;
3.132 + }
3.133 +
3.134 + (void)lua_getallocf(L, (void **)&rl);
3.135 +
3.136 + path = getenv("PATH");
3.137 + if (!path)
3.138 + path = ":/bin:/usr/bin";
3.139 +
3.140 + s = path;
3.141 + for (;;) {
3.142 + e = strchr(s, ':');
3.143 + if (!e)
3.144 + e = s + strlen(s);
3.145 + if (*s == '/') {
3.146 + n = strlen(rl->root);
3.147 + exe = malloc(n + (e - s) + 1 + strlen(file) + 1);
3.148 + memcpy(exe, rl->root, n);
3.149 + memcpy(exe + n, s, e - s);
3.150 + n += e - s;
3.151 + exe[n++] = '/';
3.152 + strcpy(exe + n, file);
3.153 + } else if (e != s) {
3.154 + exe = malloc((e - s) + 1 + strlen(file) + 1);
3.155 + memcpy(exe, s, e - s);
3.156 + n = e - s;
3.157 + exe[n++] = '/';
3.158 + strcpy(exe + n, file);
3.159 + } else {
3.160 + /* Ensure exe contains a slash to avoid PATH search */
3.161 + exe = malloc(2 + strlen(file) + 1);
3.162 + exe[0] = '.';
3.163 + exe[1] = '/';
3.164 + strcpy(exe + 2, file);
3.165 + }
3.166 + lua_pushstring(L, exe);
3.167 + lua_replace(L, 1);
3.168 + free(exe);
3.169 + n = lua_gettop(L);
3.170 + r = execp_handler(L);
3.171 +
3.172 + err = lua_tointeger(L, -1);
3.173 + switch (err) {
3.174 + case EACCES:
3.175 + got_eacces = 1;
3.176 + /* Fall through */
3.177 + case ENOENT:
3.178 + case ESTALE:
3.179 + case ENOTDIR:
3.180 + case ENODEV:
3.181 + case ETIMEDOUT:
3.182 + lua_pop(L, lua_gettop(L) - n);
3.183 + break;
3.184 + default:
3.185 + free(file);
3.186 + return r;
3.187 + }
3.188 +
3.189 + if (*e)
3.190 + s = e + 1;
3.191 + else
3.192 + break;
3.193 + }
3.194 +
3.195 + if (got_eacces)
3.196 + err = EACCES;
3.197 +
3.198 + lua_pushnil(L);
3.199 + lua_pushfstring(L, "%s: %s", file, strerror(err));
3.200 + lua_pushinteger(L, err);
3.201 +
3.202 + free(file);
3.203 + return 3;
3.204 +}
3.205 +
3.206 +static int real2fake(lua_State *L, struct razor_lua *rl, int indx)
3.207 +{
3.208 + const char *path;
3.209 +
3.210 + if (indx < 0)
3.211 + indx += lua_gettop(L) + 1;
3.212 +
3.213 + if (lua_type(L, indx) == LUA_TSTRING) {
3.214 + path = lua_tostring(L, indx);
3.215 + if (path && !strncmp(path, rl->root, strlen(rl->root)) &&
3.216 + (path[strlen(rl->root)] == '/' || !path[strlen(rl->root)])) {
3.217 + lua_pushstring(L, path + strlen(rl->root));
3.218 + lua_replace(L, indx);
3.219 + return 1;
3.220 + }
3.221 + }
3.222 +
3.223 + return 0;
3.224 +}
3.225 +
3.226 +static int proxy_handler(lua_State *L)
3.227 +{
3.228 + int i, retval, cond;
3.229 + unsigned arg;
3.230 + const char *path;
3.231 + struct razor_lua *rl;
3.232 + int method = lua_tointeger(L, lua_upvalueindex(1));
3.233 + struct razor_proxy *rp = proxy + method;
3.234 +
3.235 + (void)lua_getallocf(L, (void **)&rl);
3.236 +
3.237 + for(i = 0; i < MAX_ARGS; i++) {
3.238 + arg = rp->args[i];
3.239 + if (arg == ARG_NONE)
3.240 + continue;
3.241 + switch (ARG_TYPE(arg)) {
3.242 + case LUA_TSTRING:
3.243 + if (ARG_FLAGS(arg) & ARG_FLAG_BYPASS)
3.244 + cond = !lua_toboolean(L, ARG_SWTCH(arg));
3.245 + else
3.246 + cond = 1;
3.247 + if (ARG_FLAGS(arg) & ARG_FLAG_OPT) {
3.248 + if (lua_isstring(L, ARG_INDEX(arg)))
3.249 + path = lua_tostring(L, ARG_INDEX(arg));
3.250 + else
3.251 + path = NULL;
3.252 + } else
3.253 + path = luaL_checkstring(L, ARG_INDEX(arg));
3.254 + if (cond && path && *path == '/') {
3.255 + lua_pushfstring(L, "%s%s", rl->root, path);
3.256 + lua_replace(L, ARG_INDEX(arg));
3.257 + }
3.258 + break;
3.259 + default:
3.260 + lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
3.261 + ARG_TYPE(arg));
3.262 + lua_error(L);
3.263 + }
3.264 + }
3.265 +
3.266 + retval = rl->handler[method](L);
3.267 +
3.268 + if (rp->result != LUA_TNONE && !lua_isnil(L, 1)) {
3.269 + switch (rp->result) {
3.270 + case LUA_TNONE:
3.271 + break;
3.272 + case LUA_TSTRING:
3.273 + real2fake(L, rl, -1);
3.274 + break;
3.275 + case LUA_TTABLE:
3.276 + lua_pushnil(L);
3.277 + while (lua_next(L, -2)) {
3.278 + if (real2fake(L, rl, -1)) {
3.279 + i = lua_tonumber(L, -2);
3.280 + lua_rawseti(L, -3, i);
3.281 + } else
3.282 + lua_pop(L, 1);
3.283 + }
3.284 + break;
3.285 + default:
3.286 + lua_pushfstring(L, "razor proxy: Unhandled type (%d)",
3.287 + rp->result);
3.288 + lua_error(L);
3.289 + }
3.290 + }
3.291 +
3.292 + return retval;
3.293 +}
3.294 +
3.295 +int run_lua_script(const char *root, const char *name, const char *body,
3.296 + ssize_t len)
3.297 +{
3.298 + int i, n;
3.299 + lua_State *L;
3.300 + struct razor_lua rl;
3.301 +
3.302 + if (root && strcmp(root, "/"))
3.303 + rl.root = root;
3.304 + else
3.305 + rl.root = NULL;
3.306 +
3.307 + L = lua_newstate(alloc_lua, &rl);
3.308 + luaL_openlibs(L);
3.309 + lua_getglobal(L, "require");
3.310 + lua_pushstring(L, "posix");
3.311 + if (lua_pcall(L, 1, 1, 0)) {
3.312 + fprintf(stderr, "lua posix: %s\n", lua_tostring(L, -1));
3.313 + lua_pop(L, 1);
3.314 + lua_close(L);
3.315 + return -1;
3.316 + }
3.317 +
3.318 + if (rl.root)
3.319 + for(i = 0; i < ARRAY_SIZE(proxy); i++) {
3.320 + if (proxy[i].table) {
3.321 + lua_getglobal(L, proxy[i].table);
3.322 + n = lua_gettop(L);
3.323 + } else
3.324 + n = LUA_GLOBALSINDEX;
3.325 + lua_getfield(L, n, proxy[i].name);
3.326 + rl.handler[i] = lua_tocfunction(L, -1);
3.327 + lua_getfenv(L, -1);
3.328 + lua_remove(L, -2);
3.329 + if (proxy[i].table &&
3.330 + !strcmp(proxy[i].table, "posix") &&
3.331 + !strcmp(proxy[i].name, "execp")) {
3.332 + execp_handler = rl.handler[i];
3.333 + rl.handler[i] = proxy_execp;
3.334 + }
3.335 + lua_pushinteger(L, i);
3.336 + lua_pushcclosure(L, proxy_handler, 1);
3.337 + lua_pushvalue(L, -2);
3.338 + lua_setfenv(L, -2);
3.339 + lua_setfield(L, n, proxy[i].name);
3.340 + if (proxy[i].table)
3.341 + lua_pop(L, 2);
3.342 + else
3.343 + lua_pop(L, 1);
3.344 + }
3.345 +
3.346 + if (len < 0)
3.347 + len = strlen(body);
3.348 +
3.349 + if (luaL_loadbuffer(L, body, len, name)) {
3.350 + fprintf(stderr, "failed to load lua script\n");
3.351 + lua_close(L);
3.352 + return -1;
3.353 + }
3.354 +
3.355 + if (lua_pcall(L, 0, 0, 0)) {
3.356 + fprintf(stderr, "lua script failed: %s\n", lua_tostring(L, -1));
3.357 + lua_pop(L, 1);
3.358 + lua_close(L);
3.359 + return -1;
3.360 + }
3.361 +
3.362 + lua_close(L);
3.363 + return 0;
3.364 +}
4.1 --- a/librazor/razor-internal.h Thu Jan 22 22:54:45 2009 +0000
4.2 +++ b/librazor/razor-internal.h Thu Feb 05 22:43:29 2009 +0000
4.3 @@ -218,6 +218,9 @@
4.4 struct razor_set *
4.5 razor_merger_finish(struct razor_merger *merger);
4.6
4.7 +int run_lua_script(const char *root, const char *name, const char *body,
4.8 + ssize_t len);
4.9 +
4.10 /* Utility functions */
4.11
4.12 void
5.1 --- a/librazor/rpm.c Thu Jan 22 22:54:45 2009 +0000
5.2 +++ b/librazor/rpm.c Thu Feb 05 22:43:29 2009 +0000
5.3 @@ -742,9 +742,12 @@
5.4 {
5.5 #if HAVE_CHROOT
5.6 int pid, status, fd[2];
5.7 -#else
5.8 +#if HAVE_LUA
5.9 + int save_root, retval;
5.10 +#endif
5.11 +#else /* HAVE_CHROOT */
5.12 FILE *fp;
5.13 -#endif
5.14 +#endif /* HAVE_CHROOT */
5.15 const char *script = NULL, *program = NULL;
5.16
5.17 program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
5.18 @@ -764,6 +767,50 @@
5.19 #else
5.20 program = "/bin/sh";
5.21 #endif
5.22 + } else if (!strcmp(program, "<lua>")) {
5.23 +#if HAVE_LUA
5.24 + const char *name;
5.25 +
5.26 + switch(script_tag) {
5.27 + case RPMTAG_PREIN:
5.28 + name = "%pre";
5.29 + break;
5.30 + case RPMTAG_POSTIN:
5.31 + name = "%post";
5.32 + break;
5.33 + case RPMTAG_PREUN:
5.34 + name = "%preun";
5.35 + break;
5.36 + case RPMTAG_POSTUN:
5.37 + name = "%postun";
5.38 + break;
5.39 + default:
5.40 + name = "script";
5.41 + break;
5.42 + }
5.43 +#if HAVE_CHROOT
5.44 + if (geteuid() == 0) {
5.45 + save_root = open("/", O_RDONLY, 0);
5.46 + if (chroot(installer->root) < 0) {
5.47 + fprintf(stderr, "failed to chroot to %s: %s\n",
5.48 + installer->root, strerror(errno));
5.49 + exit(-1);
5.50 + }
5.51 + retval = run_lua_script(NULL, name, script, -1);
5.52 + fchdir(save_root);
5.53 + close(save_root);
5.54 + chroot(".");
5.55 + } else
5.56 +#endif
5.57 + {
5.58 + retval = run_lua_script(installer->root, name, script,
5.59 + -1);
5.60 + }
5.61 + return retval;
5.62 +#else /* HAVE_LUA */
5.63 + fprintf(stderr, "lua not available to run script\n");
5.64 + return -1;
5.65 +#endif /* HAVE_LUA */
5.66 }
5.67
5.68 #if HAVE_CHROOT
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/librazor/test-lua.c Thu Feb 05 22:43:29 2009 +0000
6.3 @@ -0,0 +1,102 @@
6.4 +/*
6.5 + * Copyright (C) 2009 J. Ali Harlow <ali@juiblex.co.uk>
6.6 + *
6.7 + * This program is free software; you can redistribute it and/or modify
6.8 + * it under the terms of the GNU General Public License as published by
6.9 + * the Free Software Foundation; either version 2 of the License, or
6.10 + * (at your option) any later version.
6.11 + *
6.12 + * This program is distributed in the hope that it will be useful,
6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 + * GNU General Public License for more details.
6.16 + *
6.17 + * You should have received a copy of the GNU General Public License along
6.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
6.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6.20 + */
6.21 +
6.22 +#include "config.h"
6.23 +
6.24 +#include <stdlib.h>
6.25 +#include <stdio.h>
6.26 +#include <string.h>
6.27 +#include <sys/types.h>
6.28 +#include <sys/stat.h>
6.29 +#include <dirent.h>
6.30 +#include <unistd.h>
6.31 +#include <math.h>
6.32 +#include "razor-internal.h"
6.33 +
6.34 +/*
6.35 + * This kludge is to work around an apparent bug in Fedora 10's lua package
6.36 + * (it appears to require libm but not to include a DT_NEEDED).
6.37 + */
6.38 +
6.39 +void (*kludge)() = (void (*)())sin;
6.40 +
6.41 +static void recursive_remove(const char *directory)
6.42 +{
6.43 + DIR *dp;
6.44 + struct dirent *dirp;
6.45 + char *buf;
6.46 +
6.47 + dp = opendir(directory);
6.48 + while((dirp = readdir(dp))) {
6.49 + if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) {
6.50 + buf = malloc(strlen(directory) + strlen(dirp->d_name)
6.51 + + 2);
6.52 + sprintf(buf, "%s/%s", directory, dirp->d_name);
6.53 + if (remove(buf) < 0)
6.54 + recursive_remove(buf);
6.55 + free(buf);
6.56 + }
6.57 + }
6.58 +
6.59 + rmdir(directory);
6.60 +}
6.61 +
6.62 +int main(int argc, char *argv[])
6.63 +{
6.64 + char root[] = "/tmp/razor.XXXXXX";
6.65 + int r;
6.66 + void *script;
6.67 + size_t len;
6.68 + char *s, *test_file;
6.69 + FILE *fp;
6.70 +
6.71 + if (argc > 2) {
6.72 + fprintf(stderr, "usage: %s [TESTS-FILE]\n", argv[0]);
6.73 + exit(1);
6.74 + }
6.75 + if (argc == 2)
6.76 + test_file = argv[1];
6.77 + else
6.78 + test_file = "test.lua";
6.79 +
6.80 + if (!mkdtemp(root)) {
6.81 + perror(root);
6.82 + exit(1);
6.83 + }
6.84 +
6.85 + s = malloc(strlen(root) + strlen("/testfile") + 1);
6.86 + strcpy(s, root);
6.87 + strcat(s, "/testfile");
6.88 + fp = fopen(s, "w");
6.89 + if (!fp) {
6.90 + perror(s);
6.91 + exit(1);
6.92 + }
6.93 + fprintf(fp, "#!" LUA_BINARY "\n"
6.94 + "print('Abracadabra!')\n");
6.95 + fchmod(fileno(fp), S_IRUSR | S_IWUSR | S_IXUSR);
6.96 + fclose(fp);
6.97 + free(s);
6.98 +
6.99 + script = razor_file_get_contents(test_file, &len);
6.100 + r = run_lua_script(root, test_file, script, len);
6.101 + razor_file_free_contents(script, len);
6.102 +
6.103 + recursive_remove(root);
6.104 + exit(r ? 1 : 0);
6.105 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/librazor/test.lua Thu Feb 05 22:43:29 2009 +0000
7.3 @@ -0,0 +1,60 @@
7.4 +dofile("/testfile")
7.5 +assert(loadfile("/testfile"))
7.6 +assert(io.input("/testfile"))
7.7 +assert(io.output("/file1"))
7.8 +file = assert(io.open("/file1", "w"))
7.9 +assert(io.input(file))
7.10 +assert(io.output(file))
7.11 +file:write("Hello world\n")
7.12 +file:close()
7.13 +assert(io.input())
7.14 +assert(io.output())
7.15 +for line in assert(io.lines("/file1")) do
7.16 + assert(line == "Hello world")
7.17 +end
7.18 +file, err = io.popen("/testfile", "r")
7.19 +if file == nil then
7.20 + assert(string.find(err, " not supported") == 1)
7.21 +else
7.22 + assert(file:read() == "Abracadabra!")
7.23 + file:close();
7.24 +end
7.25 +assert(os.rename("/file1","/file2"))
7.26 +assert(os.remove("/file2"))
7.27 +assert(posix.mkdir("/testdir"))
7.28 +assert(posix.stat("/testdir"))
7.29 +assert(posix.chdir("/testdir"))
7.30 +assert(posix.getcwd() == "/testdir")
7.31 +assert(posix.mkdir("dir1"))
7.32 +assert(posix.link("/testdir/dir1", "/testdir/link", true))
7.33 +assert(posix.readlink("/testdir/link") == "/testdir/dir1")
7.34 +assert(posix.unlink("/testdir/link"))
7.35 +assert(posix.link("/testfile", "/testdir/magic", false))
7.36 +assert(posix.chmod("/testfile","a+x"))
7.37 +assert(posix.access("/testfile","x"))
7.38 +pid = posix.fork()
7.39 +if pid == 0 then
7.40 + assert(posix.exec("/testfile"))
7.41 +else
7.42 + posix.wait(pid)
7.43 +end
7.44 +assert(posix.chdir("/"))
7.45 +posix.setenv("PATH","/bin:/usr/bin:/testdir",true)
7.46 +pid = posix.fork()
7.47 +if pid == 0 then
7.48 + assert(posix.execp("magic"))
7.49 +else
7.50 + posix.wait(pid)
7.51 +end
7.52 +assert(posix.utime("/testfile"))
7.53 +assert(posix.pathconf("/testdir/magic"))
7.54 +assert(posix.mkfifo("/testdir/fifo"))
7.55 +assert(posix.dir())
7.56 +assert(posix.dir("/testdir"))
7.57 +assert(posix.files())
7.58 +assert(posix.files("/testdir"))
7.59 +for _,f in pairs(posix.glob("/testdir/*")) do
7.60 + assert(string.find(f, "/testdir/") == 1)
7.61 +end
7.62 +assert(posix.rmdir("/testdir/dir1"))
7.63 +assert(posix.chown("/testfile",-1,-1))
8.1 --- a/src/Makefile.am Thu Jan 22 22:54:45 2009 +0000
8.2 +++ b/src/Makefile.am Thu Feb 05 22:43:29 2009 +0000
8.3 @@ -1,6 +1,7 @@
8.4 ## Process this file with automake to produce Makefile.in
8.5
8.6 INCLUDES = \
8.7 + $(LUA_CFLAGS) \
8.8 $(CURL_CFLAGS) \
8.9 $(EXPAT_CFLAGS) \
8.10 $(RPM_CFLAGS) \
8.11 @@ -22,7 +23,7 @@
8.12 if HAVE_RPMLIB
8.13 razor_SOURCES += import-rpmdb.c
8.14 endif
8.15 -razor_LDADD = $(RPM_LIBS) $(EXPAT_LIBS) $(CURL_LIBS) $(top_builddir)/librazor/librazor.la $(top_builddir)/gl/libgnu.la $(EXTRA_LIBS)
8.16 +razor_LDADD = $(RPM_LIBS) $(EXPAT_LIBS) $(CURL_LIBS) $(LUA_LIBS) $(top_builddir)/librazor/librazor.la $(top_builddir)/gl/libgnu.la $(EXTRA_LIBS)
8.17
8.18 rpm_SOURCES = rpm.c
8.19 rpm_LDADD = $(top_builddir)/librazor/librazor.la $(EXTRA_LIBS)
9.1 --- a/test/Makefile.am Thu Jan 22 22:54:45 2009 +0000
9.2 +++ b/test/Makefile.am Thu Feb 05 22:43:29 2009 +0000
9.3 @@ -1,16 +1,23 @@
9.4 ## Process this file with automake to produce Makefile.in
9.5
9.6 check_SCRIPTS = relocate
9.7 +if HAVE_LUA
9.8 + check_SCRIPTS += lua
9.9 +endif
9.10
9.11 relocate: relocate.sh primary.xml.gz
9.12 cp $(srcdir)/relocate.sh relocate
9.13
9.14 -primary.xml.gz: zsh.spec zip.spec zap.spec Makefile
9.15 +lua: lua.sh primary.xml.gz
9.16 + cp $(srcdir)/lua.sh lua
9.17 +
9.18 +primary.xml.gz: zsh.spec zip.spec zap.spec filesystem.spec Makefile
9.19 rm -rf rpmbuild rpms repodata
9.20 mkdir -p rpmbuild/BUILD rpmbuild/RPMS
9.21 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zap.spec
9.22 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zip.spec
9.23 rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/zsh.spec
9.24 + rpmbuild --define "_topdir `pwd`/rpmbuild" -bb $(srcdir)/filesystem.spec
9.25 mkdir rpms
9.26 mv rpmbuild/RPMS/noarch/*.rpm rpms
9.27 rm -rf rpmbuild
9.28 @@ -23,6 +30,8 @@
9.29 zap.spec \
9.30 zip.spec \
9.31 zsh.spec \
9.32 + filesystem.spec \
9.33 + lua.sh \
9.34 relocate.sh
9.35
9.36 clean-local :
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/test/filesystem.spec Thu Feb 05 22:43:29 2009 +0000
10.3 @@ -0,0 +1,38 @@
10.4 +Name: filesystem
10.5 +Summary: Test package
10.6 +Group: Test
10.7 +License: GPL
10.8 +Version: 1
10.9 +Release: 1
10.10 +BuildArch: noarch
10.11 +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
10.12 +
10.13 +%description
10.14 +Test package
10.15 +
10.16 +%prep
10.17 +
10.18 +%build
10.19 +
10.20 +%install
10.21 +mkdir %{buildroot}
10.22 +mkdir -p %{buildroot}%{_sysconfdir}
10.23 +mkdir -p %{buildroot}/{%{_bindir},%{_libdir},%{_includedir}}
10.24 +mkdir -p %{buildroot}/media
10.25 +
10.26 +%clean
10.27 +rm -rf %{buildroot}
10.28 +
10.29 +%post -p <lua>
10.30 +function mkdir_missing(dir)
10.31 + if posix.stat(dir) == nil then
10.32 + posix.mkdir(dir)
10.33 + end
10.34 +end
10.35 +mkdir_missing("/media/cdrom")
10.36 +
10.37 +%files
10.38 +%defattr(0755,root,root)
10.39 +/etc
10.40 +%{_prefix}
10.41 +%dir /media
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/test/lua.sh Thu Feb 05 22:43:29 2009 +0000
11.3 @@ -0,0 +1,28 @@
11.4 +#!/bin/sh
11.5 +check_filesystem()
11.6 +{
11.7 + if [ ! -e "$RAZOR_ROOT$1" ]; then
11.8 + echo $1: Not in filesystem >&2
11.9 + exit 1
11.10 + fi
11.11 +}
11.12 +check_file()
11.13 +{
11.14 + ../src/razor list-files | grep -x "$1" > /dev/null
11.15 + if [ $? -ne 0 ]; then
11.16 + echo $1: Not in database >&2
11.17 + exit 1
11.18 + fi
11.19 + check_filesystem "$1"
11.20 +}
11.21 +export RAZOR_ROOT=`mktemp -dt` || exit 1
11.22 +../src/razor init || exit 1
11.23 +export YUM_URL="file://localhost/`pwd`"
11.24 +../src/razor import-yum || exit 1
11.25 +../src/razor install filesystem || exit 1
11.26 +check_file /etc
11.27 +check_file /usr/bin
11.28 +check_file /usr/lib
11.29 +check_file /usr/include
11.30 +check_filesystem /media/cdrom
11.31 +rm -rf "$RAZOR_ROOT"