summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorniemeyer <devnull@localhost>2004-03-16 21:58:25 +0000
committerniemeyer <devnull@localhost>2004-03-16 21:58:25 +0000
commit73260d956c54a3d95aa7d367c09ed3e2cb2a2a00 (patch)
tree420516b3d6568f1e09364f6fd59c6c1849da0b43 /lib
parent55f77d61d72a3993436db9a8eefec9eaa7fb61ae (diff)
downloadlibrpm-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.am7
-rw-r--r--lib/psm.c5
-rw-r--r--lib/rpmlib.h4
-rw-r--r--lib/rpmlibprov.c3
-rw-r--r--lib/rpmlua.c253
-rw-r--r--lib/rpmlua.h31
-rw-r--r--lib/rpmts.c5
-rw-r--r--lib/rpmts.h4
-rw-r--r--lib/transaction.c109
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
diff --git a/lib/psm.c b/lib/psm.c
index c51105585..a01b8e4cb 100644
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -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 */