diff options
author | niemeyer <devnull@localhost> | 2004-03-16 21:58:25 +0000 |
---|---|---|
committer | niemeyer <devnull@localhost> | 2004-03-16 21:58:25 +0000 |
commit | 73260d956c54a3d95aa7d367c09ed3e2cb2a2a00 (patch) | |
tree | 420516b3d6568f1e09364f6fd59c6c1849da0b43 /lib | |
parent | 55f77d61d72a3993436db9a8eefec9eaa7fb61ae (diff) | |
download | librpm-tizen-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.tar.gz librpm-tizen-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.tar.bz2 librpm-tizen-73260d956c54a3d95aa7d367c09ed3e2cb2a2a00.zip |
- Implemented support for internal Lua scripts.
- Implemented %pretrans and %posttrans script slots.
Changed files:
Makefile.am configure.ac build/pack.c build/parseScript.c
build/parseSpec.c build/rpmbuild.h build/rpmspec.h
lib/Makefile.am lib/psm.c lib/rpmlib.h lib/rpmlibprov.c
lib/rpmts.c lib/rpmts.h lib/transaction.c
Added files:
lib/rpmlua.c lib/rpmlua.h lua/*
CVS patchset: 7175
CVS date: 2004/03/16 21:58:25
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 7 | ||||
-rw-r--r-- | lib/psm.c | 5 | ||||
-rw-r--r-- | lib/rpmlib.h | 4 | ||||
-rw-r--r-- | lib/rpmlibprov.c | 3 | ||||
-rw-r--r-- | lib/rpmlua.c | 253 | ||||
-rw-r--r-- | lib/rpmlua.h | 31 | ||||
-rw-r--r-- | lib/rpmts.c | 5 | ||||
-rw-r--r-- | lib/rpmts.h | 4 | ||||
-rw-r--r-- | lib/transaction.c | 109 |
9 files changed, 418 insertions, 3 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 317659eba..37c503a4a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,6 +11,8 @@ INCLUDES = -I. \ -I$(top_srcdir)/rpmio \ @WITH_BEECRYPT_INCLUDE@ \ -I$(top_srcdir)/popt \ + -I$(top_builddir)/lua/include \ + -I$(top_builddir)/lua/local \ @INCPATH@ EXTRA_DIST = getdate.y @@ -20,7 +22,7 @@ pkginc_HEADERS = \ misc.h rpmcli.h rpmlib.h \ rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h noinst_HEADERS = \ - cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h + cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h rpmlua.h mylibs = librpm.la LIBS = @@ -36,11 +38,12 @@ librpm_la_SOURCES = \ rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpminstall.c \ rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \ rpmvercmp.c signature.c stringbuf.c transaction.c \ - verify.c rpmlock.c + verify.c rpmlock.c rpmlua.c librpm_la_LDFLAGS = -release 4.3 $(LDFLAGS) \ $(top_builddir)/rpmdb/librpmdb.la \ $(top_builddir)/rpmio/librpmio.la \ $(top_builddir)/popt/libpopt.la \ + $(top_builddir)/lua/liblua.la \ @WITH_SELINUX_LIB@ getdate.c: getdate.y @@ -618,6 +618,11 @@ static rpmRC runScript(rpmpsm psm, Header h, const char * sln, if (progArgv == NULL && script == NULL) return rc; + if (progArgv && strcmp(progArgv[0], "<lua>") == 0) { + return rpmluaRunScript(ts->lua, h, sln, progArgc, progArgv, + script, arg1, arg2); + } + psm->sq.reaper = 1; /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */ diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 4573b4447..00d26c966 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -419,6 +419,10 @@ typedef enum rpmTag_e { RPMTAG_FSCONTEXTS = 1148, /*!< extension */ RPMTAG_RECONTEXTS = 1149, /*!< extension */ RPMTAG_POLICIES = 1150, /*!< selinux *.te policy file. */ + RPMTAG_PRETRANS = 1151, + RPMTAG_POSTTRANS = 1152, + RPMTAG_PRETRANSPROG = 1153, + RPMTAG_POSTTRANSPROG = 1154, /*@-enummemuse@*/ RPMTAG_FIRSTFREE_TAG /*!< internal */ /*@=enummemuse@*/ diff --git a/lib/rpmlibprov.c b/lib/rpmlibprov.c index b26ede4b0..3c377c523 100644 --- a/lib/rpmlibprov.c +++ b/lib/rpmlibprov.c @@ -51,6 +51,9 @@ static struct rpmlibProvides_s rpmlibProvides[] = { { "rpmlib(ConcurrentAccess)", "4.1-1", ( RPMSENSE_EQUAL), N_("package scriptlets may access the rpm database while installing.") }, + { "rpmlib(BuiltinLuaScripts)", "4.2.2-1", + ( RPMSENSE_EQUAL), + N_("internal support for lua scripts.") }, { NULL, NULL, 0, NULL } }; diff --git a/lib/rpmlua.c b/lib/rpmlua.c new file mode 100644 index 000000000..48f8ca6eb --- /dev/null +++ b/lib/rpmlua.c @@ -0,0 +1,253 @@ +#include "system.h" +#include "rpmlib.h" +#include <rpmmacro.h> +#include <rpmurl.h> + +#include <lua.h> +#include <lualib.h> +#include <lauxlib.h> +#include <lposix.h> +#include <lrexlib.h> + +#include <unistd.h> + +#define _RPMLUA_INTERNAL +#include "rpmlua.h" + +static int luaopen_rpm(lua_State *L); + +rpmlua rpmluaNew() +{ + rpmlua lua = (rpmlua) xcalloc(1, sizeof(struct rpmlua_s)); + lua_State *L = lua_open(); + const luaL_reg lualibs[] = { + {"base", luaopen_base}, + {"table", luaopen_table}, + {"io", luaopen_io}, + {"string", luaopen_string}, + {"debug", luaopen_debug}, + {"loadlib", luaopen_loadlib}, + {"posix", luaopen_posix}, + {"rex", luaopen_rex}, + {"rpm", luaopen_rpm}, + {NULL, NULL}, + }; + const luaL_reg *lib = lualibs; + for (; lib->name; lib++) { + lib->func(L); + lua_settop(L, 0); + } + lua_pushliteral(L, "LUA_PATH"); + lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua"); + lua_rawset(L, LUA_GLOBALSINDEX); + lua->L = L; + return lua; +} + +void *rpmluaFree(rpmlua lua) +{ + if (lua) { + if (lua->L) lua_close(lua->L); + free(lua); + } + return NULL; +} + +void rpmluaSetTS(rpmlua lua, rpmts ts) +{ + lua->ts = ts; +} + +rpmRC rpmluaCheckScript(rpmlua lua, const char *script, const char *name) +{ + lua_State *L = lua->L; + rpmRC rc = RPMRC_OK; + if (!name) + name = "<lua>"; + if (luaL_loadbuffer(L, script, strlen(script), name) != 0) { + rpmError(RPMERR_SCRIPT, + _("invalid syntax in lua scriptlet: %s\n"), + lua_tostring(L, -1)); + rc = RPMRC_FAIL; + } + lua_pop(L, 1); /* Error or chunk. */ + return rc; +} + +rpmRC rpmluaRunScript(rpmlua lua, Header h, const char *sln, + int progArgc, const char **progArgv, + const char *script, int arg1, int arg2) +{ + lua_State *L = lua->L; + int rootFd = -1; + const char *n, *v, *r; + rpmRC rc = RPMRC_OK; + int i; + int xx; + if (!L) { + rpmError(RPMERR_SCRIPT, + _("internal lua interpreter not available\n")); + rc = RPMRC_FAIL; + goto exit; + } + xx = headerNVR(h, &n, &v, &r); + if (luaL_loadbuffer(L, script, strlen(script), "<lua>") != 0) { + rpmError(RPMERR_SCRIPT, + _("%s(%s-%s-%s) lua scriptlet failed loading: %s\n"), + sln, n, v, r, lua_tostring(L, -1)); + lua_pop(L, 1); + rc = RPMRC_FAIL; + goto exit; + } + + if (lua->ts && !rpmtsChrootDone(lua->ts)) { + const char *rootDir = rpmtsRootDir(lua->ts); + if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')) { + chdir("/"); + rootFd = open(".", O_RDONLY, 0); + if (rootFd >= 0) { + chroot(rootDir); + rpmtsSetChrootDone(lua->ts, 1); + } + } + } + + /* Create arg variable */ + lua_pushliteral(L, "arg"); + lua_newtable(L); + i = 0; + if (progArgv) { + while (i < progArgc && progArgv[i]) { + lua_pushstring(L, progArgv[i]); + lua_rawseti(L, -2, ++i); + } + } + if (arg1 >= 0) { + lua_pushnumber(L, arg1); + lua_rawseti(L, -2, ++i); + } + if (arg2 >= 0) { + lua_pushnumber(L, arg2); + lua_rawseti(L, -2, ++i); + } + lua_rawset(L, LUA_GLOBALSINDEX); + + if (lua_pcall(L, 0, 0, 0) != 0) { + rpmError(RPMERR_SCRIPT, _("%s(%s-%s-%s) lua scriptlet failed: %s\n"), + sln, n, v, r, lua_tostring(L, -1)); + lua_pop(L, 1); + rc = RPMRC_FAIL; + } + + /* Remove 'arg' global. */ + lua_pushliteral(L, "arg"); + lua_pushnil(L); + lua_rawset(L, LUA_GLOBALSINDEX); + + if (rootFd >= 0) { + fchdir(rootFd); + close(rootFd); + chroot("."); + rpmtsSetChrootDone(lua->ts, 0); + } + +exit: + return rc; +} + +/* From lua.c */ +static int rpmluaReadline(lua_State *l, const char *prompt) { + static char buffer[1024]; + if (prompt) { + fputs(prompt, stdout); + fflush(stdout); + } + if (fgets(buffer, sizeof(buffer), stdin) == NULL) { + return 0; /* read fails */ + } else { + lua_pushstring(l, buffer); + return 1; + } +} + +/* Based on lua.c */ +static void _rpmluaInteractive(lua_State *L) +{ + fputs("\n", stdout); + printf("RPM Interactive %s Interpreter\n", LUA_VERSION); + for (;;) { + if (rpmluaReadline(L, "> ") == 0) + break; + if (lua_tostring(L, -1)[0] == '=') { + lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1); + lua_remove(L, -2); + } + int rc = 0; + for (;;) { + rc = luaL_loadbuffer(L, lua_tostring(L, -1), + lua_strlen(L, -1), "<lua>"); + if (rc == LUA_ERRSYNTAX && + strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) { + if (rpmluaReadline(L, ">> ") == 0) + break; + lua_remove(L, -2); // Remove error + lua_concat(L, 2); + continue; + } + break; + } + if (rc == 0) + rc = lua_pcall(L, 0, 0, 0); + if (rc != 0) { + fprintf(stderr, "%s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } + lua_pop(L, 1); // Remove line + } + fputs("\n", stdout); +} + +void rpmluaInteractive(rpmlua lua) +{ + _rpmluaInteractive(lua->L); +} + +/* ------------------------------------------------------------------ */ +/* Lua API */ + +static int rpm_expand(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + lua_pushstring(L, rpmExpand(str, NULL)); + return 1; +} + +static int rpm_define(lua_State *L) +{ + const char *str = luaL_checkstring(L, 1); + rpmDefineMacro(NULL, str, 0); + return 0; +} + +static int rpm_interactive(lua_State *L) +{ + _rpmluaInteractive(L); + return 0; +} + +static const luaL_reg rpmlib[] = { + {"expand", rpm_expand}, + {"define", rpm_define}, + {"interactive", rpm_interactive}, + {NULL, NULL} +}; + +static int luaopen_rpm(lua_State *L) +{ + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_openlib(L, "rpm", rpmlib, 0); + return 0; +} + +/* vim:sts=4:sw=4 +*/ diff --git a/lib/rpmlua.h b/lib/rpmlua.h new file mode 100644 index 000000000..724ce039a --- /dev/null +++ b/lib/rpmlua.h @@ -0,0 +1,31 @@ +#ifndef RPMLUA_H +#define RPMLUA_H + +#if defined(_RPMLUA_INTERNAL) + +#include "rpmts.h" + +#include <lua.h> + +struct rpmlua_s { + lua_State *L; + rpmts ts; +}; + +#endif /* _RPMLUA_INTERNAL */ + +typedef struct rpmlua_s * rpmlua; + +rpmlua rpmluaNew(void); +void *rpmluaFree(rpmlua lua); +void rpmluaSetTS(rpmlua lua, rpmts ts); +rpmRC rpmluaCheckScript(rpmlua lua, const char *script, const char *name); +rpmRC rpmluaRunScript(rpmlua lua, Header h, const char *sln, + int progArgc, const char **progArgv, + const char *script, int arg1, int arg2); +void rpmluaInteractive(rpmlua lua); + +#endif /* RPMLUA_H */ + +/* vim:sts=4:sw=4 +*/ diff --git a/lib/rpmts.c b/lib/rpmts.c index 6b38cc770..1a6e3fbd0 100644 --- a/lib/rpmts.c +++ b/lib/rpmts.c @@ -796,6 +796,8 @@ rpmts rpmtsFree(rpmts ts) if (ts->nrefs > 1) return rpmtsUnlink(ts, "tsCreate"); + ts->lua = rpmluaFree(ts->lua); + /*@-nullstate@*/ /* FIX: partial annotations */ rpmtsEmpty(ts); /*@=nullstate@*/ @@ -1509,6 +1511,9 @@ rpmts rpmtsCreate(void) */ ts->score = NULL; + ts->lua = rpmluaNew(); + rpmluaSetTS(ts->lua, ts); + ts->nrefs = 0; return rpmtsLink(ts, "tsCreate"); diff --git a/lib/rpmts.h b/lib/rpmts.h index b5e898407..3d0341bf6 100644 --- a/lib/rpmts.h +++ b/lib/rpmts.h @@ -96,6 +96,7 @@ typedef enum rpmtsOpX_e { #include "rpmhash.h" /* XXX hashTable */ #include "rpmal.h" /* XXX availablePackage/relocateFileList ,*/ +#include "rpmlua.h" /* XXX lua state */ /********************** * Transaction Scores * @@ -318,6 +319,9 @@ struct rpmts_s { Spec spec; /*!< Spec file control structure. */ rpmtsScore score; /*!< Transaction Score (autorollback). */ + + rpmlua lua; + /*@refs@*/ int nrefs; /*!< Reference count. */ }; diff --git a/lib/transaction.c b/lib/transaction.c index faa02feed..a035cc638 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -1140,6 +1140,66 @@ rpmMessage(RPMMESS_DEBUG, _("sanity checking %d elements\n"), rpmtsNElements(ts) } pi = rpmtsiFree(pi); + + /* Run pre-transaction scripts, but only if there are no known + * problems up to this point. */ + if (!((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) + || (ts->probs->numProblems && + (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) { + rpmMessage(RPMMESS_DEBUG, _("running pre-transaction scripts\n")); + pi = rpmtsiInit(ts); + while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { + if ((fi = rpmtsiFi(pi)) == NULL) + continue; /* XXX can't happen */ + + p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, + rpmteKey(p), ts->notifyData); + p->h = NULL; + if (rpmteFd(p) != NULL) { + rpmVSFlags ovsflags = rpmtsVSFlags(ts); + rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD; + rpmRC rpmrc; + ovsflags = rpmtsSetVSFlags(ts, vsflags); + rpmrc = rpmReadPackageFile(ts, rpmteFd(p), + rpmteNEVR(p), &p->h); + vsflags = rpmtsSetVSFlags(ts, ovsflags); + switch (rpmrc) { + default: + /*@-noeffectuncon@*/ /* FIX: notify annotations */ + p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, + 0, 0, + rpmteKey(p), ts->notifyData); + /*@=noeffectuncon@*/ + p->fd = NULL; + /*@innerbreak@*/ break; + case RPMRC_NOTTRUSTED: + case RPMRC_NOKEY: + case RPMRC_OK: + /*@innerbreak@*/ break; + } + } + + if (rpmteFd(p) != NULL) { + fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1); + if (fi != NULL) { /* XXX can't happen */ + fi->te = p; + p->fi = fi; + } + psm = rpmpsmNew(ts, p, p->fi); + psm->scriptTag = RPMTAG_PRETRANS; + psm->progTag = RPMTAG_PRETRANSPROG; + xx = rpmpsmStage(psm, PSM_SCRIPT); + psm = rpmpsmFree(psm); + + (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, + rpmteKey(p), ts->notifyData); + p->fd = NULL; + p->h = headerFree(p->h); + } + } + pi = rpmtsiFree(pi); + } + /* =============================================== * Initialize transaction element file info for package: */ @@ -1389,7 +1449,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n")); */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (ts->probs->numProblems && - (okProbs != NULL || rpmpsTrim(ts->probs, okProbs))) + (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))) ) { rpmtsFreeLock(lock); @@ -1776,6 +1836,53 @@ assert(psm != NULL); rpmtsFree(rollbackTransaction); } + rpmMessage(RPMMESS_DEBUG, _("running post-transaction scripts\n")); + pi = rpmtsiInit(ts); + while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { + p->fd = ts->notify(p->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, + rpmteKey(p), ts->notifyData); + p->h = NULL; + if (rpmteFd(p) != NULL) { + rpmVSFlags ovsflags = rpmtsVSFlags(ts); + rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD; + rpmRC rpmrc; + ovsflags = rpmtsSetVSFlags(ts, vsflags); + rpmrc = rpmReadPackageFile(ts, rpmteFd(p), + rpmteNEVR(p), &p->h); + vsflags = rpmtsSetVSFlags(ts, ovsflags); + switch (rpmrc) { + default: + p->fd = ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, + 0, 0, rpmteKey(p), ts->notifyData); + p->fd = NULL; + break; + case RPMRC_NOTTRUSTED: + case RPMRC_NOKEY: + case RPMRC_OK: + break; + } + } + + if (rpmteFd(p) != NULL) { + fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, 1); + if (fi != NULL) { /* XXX can't happen */ + fi->te = p; + p->fi = fi; + } + psm = rpmpsmNew(ts, p, p->fi); + psm->scriptTag = RPMTAG_POSTTRANS; + psm->progTag = RPMTAG_POSTTRANSPROG; + xx = rpmpsmStage(psm, PSM_SCRIPT); + psm = rpmpsmFree(psm); + + (void) ts->notify(p->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, + rpmteKey(p), ts->notifyData); + p->fd = NULL; + p->h = headerFree(p->h); + } + } + pi = rpmtsiFree(pi); + rpmtsFreeLock(lock); /*@-nullstate@*/ /* FIX: ts->flList may be NULL */ |