From fe5362ef809874996febb2eb0aa89877ee1f74fd Mon Sep 17 00:00:00 2001 From: jbj Date: Tue, 17 Jul 2001 20:01:46 +0000 Subject: [PATCH] - python: "seal" immutable region for legacy headers in rhnUnload() . - python: add poptmodule.so bindings. CVS patchset: 4951 CVS date: 2001/07/17 20:01:46 --- CHANGES | 2 + lib/verify.c | 8 +- python/Makefile.am | 8 +- python/Makefile.in | 20 +- python/poptmodule.c | 668 ++++++++++++++++++++++++++++++++++++++++++++++++++++ python/rpmmodule.c | 9 +- rpm.spec.in | 1 + 7 files changed, 702 insertions(+), 14 deletions(-) create mode 100644 python/poptmodule.c diff --git a/CHANGES b/CHANGES index 0dc132c..595da4e 100644 --- a/CHANGES +++ b/CHANGES @@ -175,6 +175,8 @@ - python: bind rhnUnload differently. - fix: rescusitate --querytags. - fix: short aliases broken (#49213). + - python: "seal" immutable region for legacy headers in rhnUnload() . + - python: add poptmodule.so bindings. 4.0 -> 4.0.[12] - add doxygen and lclint annotations most everywhere. diff --git a/lib/verify.c b/lib/verify.c index 84b9b94..4f79692 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -347,11 +347,7 @@ int rpmVerifyDigest(Header h) rpmDigestUpdate(ctx, uh, uhc); rpmDigestFinal(ctx, (void **)&digest, &digestlen, 1); - if (digest) { /* XXX can't happen */ - if (strcmp(hdigest, digest)) { - ec = 1; - } - } + ec = (digest == NULL || strcmp(hdigest, digest)) ? 1 : 0; digest = _free(digest); } @@ -572,7 +568,7 @@ int rpmVerify(QVA_t qva, rpmQVSources source, const char * arg) break; /*@fallthrough@*/ default: - if (rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644)) + if ((rc = rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644)) != 0) return 1; break; } diff --git a/python/Makefile.am b/python/Makefile.am index 997126a..d29aa99 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -21,9 +21,12 @@ mylibs= \ LDADD = pythondir = $(prefix)/lib/python1.5/site-packages -python_PROGRAMS = rpmmodule.so +python_PROGRAMS = rpmmodule.so poptmodule.so + rpmmodule_so_SOURCES = rpmmodule_so_LDFLAGS = $(mylibs) $(LIBS) -shared -Wl,-soname,rpmmodule.so +poptmodule_so_SOURCES = poptmodule.c +poptmodule_so_LDFLAGS = $(mylibs) $(LIBS) -shared -Wl,-soname,poptmodule.so noinst_LTLIBRARIES = librpmmodule.la librpmmodule_la_SOURCES = rpmmodule.c hash.c upgrade.c @@ -31,6 +34,9 @@ librpmmodule_la_SOURCES = rpmmodule.c hash.c upgrade.c rpmmodule.so: $(librpmmodule_la_OBJECTS) $(LINK) -o $@ $^ $(rpmmodule_so_LDFLAGS) +poptmodule.so: $(poptmodule_so_OBJECTS) + $(LINK) -o $@ $^ $(poptmodule_so_LDFLAGS) + .PHONY: lclint lclint: lclint $(DEFS) $(INCLUDES) $(librpmmodule_la_SOURCES) diff --git a/python/Makefile.in b/python/Makefile.in index 6dde63f..a0168e0 100644 --- a/python/Makefile.in +++ b/python/Makefile.in @@ -194,9 +194,12 @@ mylibs = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmdb/librpmdb.la $(t LDADD = pythondir = $(prefix)/lib/python1.5/site-packages -python_PROGRAMS = rpmmodule.so +python_PROGRAMS = rpmmodule.so poptmodule.so + rpmmodule_so_SOURCES = rpmmodule_so_LDFLAGS = $(mylibs) $(LIBS) -shared -Wl,-soname,rpmmodule.so +poptmodule_so_SOURCES = poptmodule.c +poptmodule_so_LDFLAGS = $(mylibs) $(LIBS) -shared -Wl,-soname,poptmodule.so noinst_LTLIBRARIES = librpmmodule.la librpmmodule_la_SOURCES = rpmmodule.c hash.c upgrade.c @@ -212,12 +215,15 @@ LDFLAGS = @LDFLAGS@ librpmmodule_la_LDFLAGS = librpmmodule_la_LIBADD = librpmmodule_la_OBJECTS = rpmmodule.lo hash.lo upgrade.lo -python_PROGRAMS = rpmmodule.so +python_PROGRAMS = rpmmodule.so poptmodule.so PROGRAMS = $(python_PROGRAMS) rpmmodule_so_OBJECTS = rpmmodule_so_LDADD = $(LDADD) rpmmodule_so_DEPENDENCIES = +poptmodule_so_OBJECTS = poptmodule.$(OBJEXT) +poptmodule_so_LDADD = $(LDADD) +poptmodule_so_DEPENDENCIES = CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -230,9 +236,10 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) TAR = gtar GZIP_ENV = --best -DEP_FILES = .deps/hash.P .deps/rpmmodule.P .deps/upgrade.P -SOURCES = $(librpmmodule_la_SOURCES) $(rpmmodule_so_SOURCES) -OBJECTS = $(librpmmodule_la_OBJECTS) $(rpmmodule_so_OBJECTS) +DEP_FILES = .deps/hash.P .deps/poptmodule.P .deps/rpmmodule.P \ +.deps/upgrade.P +SOURCES = $(librpmmodule_la_SOURCES) $(rpmmodule_so_SOURCES) $(poptmodule_so_SOURCES) +OBJECTS = $(librpmmodule_la_OBJECTS) $(rpmmodule_so_OBJECTS) $(poptmodule_so_OBJECTS) all: all-redirect .SUFFIXES: @@ -487,6 +494,9 @@ mostlyclean distclean maintainer-clean rpmmodule.so: $(librpmmodule_la_OBJECTS) $(LINK) -o $@ $^ $(rpmmodule_so_LDFLAGS) +poptmodule.so: $(poptmodule_so_OBJECTS) + $(LINK) -o $@ $^ $(poptmodule_so_LDFLAGS) + .PHONY: lclint lclint: lclint $(DEFS) $(INCLUDES) $(librpmmodule_la_SOURCES) diff --git a/python/poptmodule.c b/python/poptmodule.c new file mode 100644 index 0000000..bac4883 --- /dev/null +++ b/python/poptmodule.c @@ -0,0 +1,668 @@ +/* + * + * + * + */ + +#define PY_POPT_VERSION "0.1" + +static const char *rcs_id = "$Id: poptmodule.c,v 1.2 2001/07/17 20:01:46 jbj Exp $"; + +static const char *module_doc = "Python bindings for the popt library + +The popt library provides useful command-line parsing functions. +The latest version of the popt library is distributed with rpm +and is always available from ftp://ftp.rpm.org/pub/rpm/dist"; + +#include +#include + +#define DEBUG 1 + +#if defined(DEBUG) +#define debug(x, y) { printf("%s: %s\n", x, y); } +#else +#define debug(x, y) {} +#endif + +/* Functins and datatypes needed for the context object */ +typedef struct poptContext_s { + PyObject_HEAD; + struct poptOption *options; + int optionsNo; + poptContext ctx; + /* The index of the option retrieved with getNextOpt()*/ + int opt; +} poptContextObject; + +/* Misc functions */ +void __printPopt(struct poptOption *opts) +{ + printf("+++++++++++\n"); + printf("Long name: %s\n", opts->longName); + printf("Short name: %c\n", opts->shortName); + printf("argInfo: %d\n", opts->argInfo); + printf("Val: %d\n", opts->val); + printf("-----------\n"); +} + +static PyObject * __poptOptionValue2PyObject(const struct poptOption *option) +{ + if (option == NULL) { + /* This shouldn't really happen */ + PyErr_SetString(PyExc_ValueError, "expected a poptOption, got null"); + return NULL; + } + if (option->arg == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + switch(option->argInfo) { + case POPT_ARG_INCLUDE_TABLE: + /* Do nothing */ + Py_INCREF(Py_None); + return Py_None; + case POPT_ARG_STRING: + if (*(char **)(option->arg) == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(*(char **)(option->arg)); + break; + case POPT_ARG_DOUBLE: + return PyFloat_FromDouble(*(double *)(option->arg)); + break; + case POPT_ARG_LONG: + return PyInt_FromLong(*(long *)(option->arg)); + break; + case POPT_ARG_NONE: + case POPT_ARG_VAL: + return PyInt_FromLong(*(int *)(option->arg)); + break; + } + /* This shouldn't really happen */ + PyErr_BadInternalCall(); + return NULL; +} + +static PyObject * ctxReset(poptContextObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + poptResetContext(self->ctx); + self->opt = -1; + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * ctxGetNextOpt(poptContextObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + self->opt = poptGetNextOpt(self->ctx); + return PyInt_FromLong(self->opt); +} + +static PyObject * ctxGetOptArg(poptContextObject *self, PyObject *args) +{ + const char *opt; + if (!PyArg_ParseTuple(args, "")) + return NULL; + opt = poptGetOptArg(self->ctx); + if (opt == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(opt); +} + +static PyObject * ctxGetArg(poptContextObject *self, PyObject *args) +{ + const char *arg; + if (!PyArg_ParseTuple(args, "")) + return NULL; + arg = poptGetArg(self->ctx); + if (arg == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(arg); +} + +static PyObject * ctxPeekArg(poptContextObject *self, PyObject *args) +{ + const char *arg; + if (!PyArg_ParseTuple(args, "")) + return NULL; + arg = poptPeekArg(self->ctx); + if (arg == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(arg); +} + +static PyObject * ctxGetArgs(poptContextObject *self, PyObject *argsFoo) +{ + const char **args; + PyObject *list; + int size, i; + if (!PyArg_ParseTuple(argsFoo, "")) + return NULL; + args = poptGetArgs(self->ctx); + if (args == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + /* Compute the list size */ + for (size = 0; args[size]; size++); + /* Create the list */ + list = PyList_New(size); + if (list == NULL) + return NULL; + for (i = 0; i < size; i++) + PyList_SetItem(list, i, PyString_FromString(args[i])); + return list; +} + +static PyObject * ctxBadOption(poptContextObject *self, PyObject *args) +{ + int flags = 0; + const char *badOption; + if (!PyArg_ParseTuple(args, "|i", &flags)) + return NULL; + badOption = poptBadOption(self->ctx, flags); + if (badOption == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + return PyString_FromString(badOption); +} + +static PyObject * ctxReadDefaultConfig(poptContextObject *self, PyObject *args) +{ + int flags = 0; + if (!PyArg_ParseTuple(args, "|i", &flags)) + return NULL; + return PyInt_FromLong(poptReadDefaultConfig(self->ctx, flags)); +} + +static PyObject * ctxReadConfigFile(poptContextObject *self, PyObject *args) +{ + const char *filename; + if (!PyArg_ParseTuple(args, "s", &filename)) + return NULL; + return PyInt_FromLong(poptReadConfigFile(self->ctx, filename)); +} + +static PyObject * ctxSetOtherOptionHelp(poptContextObject *self, PyObject *args) +{ + const char *option; + if (!PyArg_ParseTuple(args, "s", &option)) + return NULL; + poptSetOtherOptionHelp(self->ctx, option); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * ctxPrintHelp(poptContextObject *self, PyObject *args) +{ + FILE *f; + int flags = 0; + PyObject *file; + if (!PyArg_ParseTuple(args, "|O!i", &PyFile_Type, &file, &flags)) + return NULL; + if (file == Py_None) + f = stderr; + else { + f = PyFile_AsFile(file); + if (f == NULL) + return NULL; + } + poptPrintHelp(self->ctx, f, flags); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * ctxPrintUsage(poptContextObject *self, PyObject *args) +{ + FILE *f; + int flags = 0; + PyObject *file; + if (!PyArg_ParseTuple(args, "|O!i", &PyFile_Type, &file, &flags)) + return NULL; + if (file == Py_None) + f = stderr; + else { + f = PyFile_AsFile(file); + if (f == NULL) + return NULL; + } + poptPrintUsage(self->ctx, f, flags); + Py_INCREF(Py_None); + return Py_None; +} + +/* XXX addAlias */ +/* XXX stuffArgs */ +/* XXX callbackType */ + +/*******************************/ +/* Added ctxGetOptValues */ +/*******************************/ +/* Builds a list of values corresponding to each option */ +static PyObject * ctxGetOptValues(poptContextObject *self, PyObject *args) +{ + PyObject *list; + int i; + if (!PyArg_ParseTuple(args, "")) + return NULL; + /* Create the list */ + list = PyList_New(self->optionsNo); + if (list == NULL) + return NULL; + for (i = 0; i < self->optionsNo; i++) { + PyObject *item; + item = __poptOptionValue2PyObject(self->options + i); + item = __poptOptionValue2PyObject(self->options + i); + if (item == NULL) + return NULL; + PyList_SetItem(list, i, item); + } + return list; +} + +static PyObject * ctxGetOptValue(poptContextObject *self, PyObject *args) +{ + int i; + if (!PyArg_ParseTuple(args, "")) + return NULL; + if (self->opt < 0) { + /* No processing */ + Py_INCREF(Py_None); + return Py_None; + } + /* Look for the option that returned this value */ + for (i = 0; i < self->optionsNo; i++) + if (self->options[i].val == self->opt) { + /* Cool, this is the one */ + return __poptOptionValue2PyObject(self->options + i); + } + /* Not found */ + Py_INCREF(Py_None); + return Py_None; +} + +static struct PyMethodDef ctxMethods[] = { + {"reset", (PyCFunction)ctxReset, METH_VARARGS}, + {"getNextOpt", (PyCFunction)ctxGetNextOpt, METH_VARARGS}, + {"getOptArg", (PyCFunction)ctxGetOptArg, METH_VARARGS}, + {"getArg", (PyCFunction)ctxGetArg, METH_VARARGS}, + {"peekArg", (PyCFunction)ctxPeekArg, METH_VARARGS}, + {"getArgs", (PyCFunction)ctxGetArgs, METH_VARARGS}, + {"badOption", (PyCFunction)ctxBadOption, METH_VARARGS}, + {"readDefaultConfig", (PyCFunction)ctxReadDefaultConfig, METH_VARARGS}, + {"readConfigFile", (PyCFunction)ctxReadConfigFile, METH_VARARGS}, + {"setOtherOptionHelp", (PyCFunction)ctxSetOtherOptionHelp, METH_VARARGS}, + {"printHelp", (PyCFunction)ctxPrintHelp, METH_VARARGS}, + {"printUsage", (PyCFunction)ctxPrintUsage, METH_VARARGS}, + /* + {"addAlias", (PyCFunction)ctxAddAlias}, + {"stuffArgs", (PyCFunction)ctxStuffArgs}, + {"callbackType", (PyCFunction)ctxCallbackType}, + */ + {"getOptValues", (PyCFunction)ctxGetOptValues, METH_VARARGS}, + {"getOptValue", (PyCFunction)ctxGetOptValue, METH_VARARGS}, + {NULL, NULL} +}; + +static PyObject * ctxGetAttr(poptContextObject *s, char *name) +{ + return Py_FindMethod(ctxMethods, (PyObject *)s, name); +} + +static void ctxDealloc(poptContextObject *self, PyObject *args) +{ + if (self->options != NULL) { + int i; + for (i = 0; i < self->optionsNo; i++) { + struct poptOption *o = self->options + i; + if (o->argInfo != POPT_ARG_INCLUDE_TABLE && o->arg) + free(o->arg); + } + free(self->options); + self->options = NULL; + } + poptFreeContext(self->ctx); + PyMem_DEL(self); +} + +static PyTypeObject poptContextType = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "poptContext", /* tp_name */ + sizeof(poptContextObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)ctxDealloc, /* tp_dealloc */ + (printfunc)NULL, /* tp_print */ + (getattrfunc)ctxGetAttr, /* tp_getattr */ + (setattrfunc)NULL, /* tp_setattr */ + (cmpfunc)NULL, /* tp_compare */ + (reprfunc)NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL /* tp_as_mapping */ +}; + +/* Functions and datatypes needed for the popt module */ + +#define AUTOHELP "autohelp" +static const struct poptOption __autohelp[] = { + POPT_AUTOHELP + POPT_TABLEEND +}; + +/* Misc functions */ +int __setPoptOption(PyObject *list, struct poptOption *opt) +{ + int listSize; + PyObject *o; + const char *s; + int objsize; + /* Look for autohelp stuff first */ + if (PyString_Check(list)) { + if (!strcmp(AUTOHELP, PyString_AsString(list))) { + /* Autohelp */ + *opt = __autohelp[0]; + return 1; + } + PyErr_SetString(PyExc_TypeError, "Expected list or autohelp"); + return 0; + } + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "List expected"); + return 0; + } + listSize = PyList_Size(list); + if (listSize < 3) { + PyErr_SetString(PyExc_ValueError, "List is too short"); + return 0; + } + + /* longName */ + o = PyList_GetItem(list, 0); + /* Sanity check */ + if (!PyString_Check(o)) { + PyErr_SetString(PyExc_TypeError, "Long name should be a string"); + return 0; + } + opt->longName = PyString_AsString(o); + + /* shortName */ + o = PyList_GetItem(list, 1); + /* Sanity check */ + if (!PyString_Check(o)) { + PyErr_SetString(PyExc_TypeError, "Short name should be a string"); + return 0; + } + s = PyString_AsString(o); + if (strlen(s) != 1) { + PyErr_SetString(PyExc_ValueError, "Short name too short"); + return 0; + } + opt->shortName = s[0]; + + /* argInfo */ + o = PyList_GetItem(list, 2); + /* Sanity check */ + if (!PyInt_Check(o)) { + PyErr_SetString(PyExc_TypeError, "argInfo is not an int"); + return 0; + } + opt->argInfo = PyInt_AsLong(o); + + /* Initialize the rest of the arguments with safe defaults */ + switch(opt->argInfo) { + case POPT_ARG_STRING: + objsize = sizeof(char *); + break; + case POPT_ARG_DOUBLE: + objsize = sizeof(double); + break; + case POPT_ARG_NONE: + case POPT_ARG_VAL: + objsize = sizeof(int); + break; + case POPT_ARG_LONG: + objsize = sizeof(long); + break; + default: + PyErr_SetString(PyExc_ValueError, "Wrong value for argInfo"); + return 0; + } + opt->arg = (void *)malloc(objsize); + if (opt->arg == NULL) { + PyErr_NoMemory(); + return 0; + } + memset(opt->arg, '\0', objsize); + opt->val = 0; + opt->descrip = NULL; + opt->argDescrip = NULL; + /* If nothing left, end the stuff here */ + if (listSize == 3) + return 1; + + /* val */ + o = PyList_GetItem(list, 3); + /* Sanity check */ + if (o == Py_None) + opt->val = 0; + else + if (!PyInt_Check(o)) { + PyErr_SetString(PyExc_TypeError, "Val should be int or None"); + return 0; + } + opt->val = PyInt_AsLong(o); + /* If nothing left, end the stuff here */ + if (listSize == 4) + return 1; + + /* descrip */ + o = PyList_GetItem(list, 4); + /* Sanity check */ + if (!PyString_Check(o) && o != Py_None) + /* XXX FIXME raise exception */ + return 0; + if (o == Py_None) + opt->descrip = NULL; + else + opt->descrip = PyString_AsString(o); + /* If nothing left, end the stuff here */ + if (listSize == 5) + return 1; + + /* argDescrip */ + o = PyList_GetItem(list, 5); + /* Sanity check */ + if (!PyString_Check(o) && o != Py_None) + /* XXX FIXME raise exception */ + return 0; + if (o == Py_None) + opt->argDescrip = NULL; + else + opt->argDescrip = PyString_AsString(o); + return 1; +} + +struct poptOption * __getPoptOptions(PyObject *list, int *count) +{ + int listSize, item, totalmem; + struct poptOption *opts; + struct poptOption sentinel = POPT_TABLEEND; + if (!PyList_Check(list)) { + PyErr_SetString(PyExc_TypeError, "List expected"); + return NULL; + } + listSize = PyList_Size(list); + /* Malloc exactly the size of the list */ + totalmem = (1 + listSize) * sizeof(struct poptOption); + opts = (struct poptOption *)malloc(totalmem); + if (opts == NULL) { + PyErr_NoMemory(); + return NULL; + } + memset(opts, '\0', totalmem); + for (item = 0; item < listSize; item++) { + int ret; + /* Retrieve the item */ + PyObject *o = PyList_GetItem(list, item); + ret = __setPoptOption(o, opts + item); + if (ret == 0) { + /* XXX FIXME raise exception */ + return NULL; + } + //__printPopt(opts + item); + } + /* Sentinel */ + opts[listSize] = sentinel; + *count = listSize; + return opts; +} + +char ** __getArgv(PyObject *list, int *argc) +{ + int listSize, item, totalmem; + char **argv; + if (!PyList_Check(list)) + /* XXX FIXME raise exception */ + return NULL; + listSize = PyList_Size(list); + /* Malloc exactly the size of the list */ + totalmem = (1 + listSize) * sizeof(char *); + argv = (char **)malloc(totalmem); + if (argv == NULL) + /* XXX FIXME raise exception */ + return NULL; + memset(argv, '\0', totalmem); + for (item = 0; item < listSize; item++) { + /* Retrieve the item */ + PyObject *o = PyList_GetItem(list, item); + if (!PyString_Check(o)) + /* XXX FIXME raise exception */ + return NULL; + argv[item] = PyString_AsString(o); + //debug("getArgv", argv[item]); + } + /* Sentinel */ + argv[listSize] = NULL; + *argc = listSize; + return argv; +} + + +static PyObject * getContext(PyObject *self, PyObject *args) +{ + const char *name; + PyObject *a, *o; + char **argv; + int argc, count, flags = 0; + struct poptOption *opts; + poptContextObject *c; + /* We should receive name, argv and a list */ + if (!PyArg_ParseTuple(args, "zO!O!|i", &name, &PyList_Type, &a, + &PyList_Type, &o, &flags)) + return NULL; + /* Parse argv */ + argv = __getArgv(a, &argc); + /* Parse opts */ + opts = __getPoptOptions(o, &count); + if (opts == NULL) + /* Presumably they've set the exception at a previous level */ + return NULL; + // XXX + c = PyObject_NEW(poptContextObject, &poptContextType); + c->options = opts; + c->optionsNo = count; + c->opt = -1; + c->ctx = poptGetContext(name, argc, (const char **)argv, opts, flags); + return (PyObject *)c; +} + +struct _pyIntConstant { + char *name; + const int value; +}; + +static PyObject * _strerror(PyObject *self, PyObject *args) +{ + int error; + if (!PyArg_ParseTuple(args, "i", &error)) { + return NULL; + } + return PyString_FromString(poptStrerror(error)); +} + +/* Methods for the popt module */ +static struct PyMethodDef poptModuleMethods[] = { + {"getContext", (PyCFunction)getContext}, + {"strerror", (PyCFunction)_strerror}, + {NULL, NULL} +}; + +#define ADD_INT(NAME) {#NAME, NAME} +static const struct _pyIntConstant intConstants[] = { + /* Arg info */ + ADD_INT(POPT_ARG_NONE), + ADD_INT(POPT_ARG_STRING), + {"POPT_ARG_INT", POPT_ARG_LONG}, + ADD_INT(POPT_ARG_VAL), + {"POPT_ARG_FLOAT", POPT_ARG_DOUBLE}, + + ADD_INT(POPT_ARGFLAG_OR), + ADD_INT(POPT_ARGFLAG_AND), + ADD_INT(POPT_ARGFLAG_XOR), + ADD_INT(POPT_ARGFLAG_NOT), + ADD_INT(POPT_ARGFLAG_ONEDASH), + ADD_INT(POPT_ARGFLAG_DOC_HIDDEN), + ADD_INT(POPT_ARGFLAG_OPTIONAL), + /* Context flags*/ + ADD_INT(POPT_CONTEXT_NO_EXEC), + ADD_INT(POPT_CONTEXT_KEEP_FIRST), + ADD_INT(POPT_CONTEXT_POSIXMEHARDER), + /* Errors */ + ADD_INT(POPT_ERROR_NOARG), + ADD_INT(POPT_ERROR_BADOPT), + ADD_INT(POPT_ERROR_OPTSTOODEEP), + ADD_INT(POPT_ERROR_BADQUOTE), + ADD_INT(POPT_ERROR_BADNUMBER), + ADD_INT(POPT_ERROR_OVERFLOW), + ADD_INT(POPT_ERROR_ERRNO), + /* Misc */ + ADD_INT(POPT_BADOPTION_NOALIAS), + {NULL} +}; + +void initpopt() +{ + PyObject *dict, *module; + const struct _pyIntConstant *c; + module = Py_InitModule3("popt", poptModuleMethods, module_doc); + /* Init the constants */ + dict = PyModule_GetDict(module); + PyDict_SetItemString(dict, "__version__", + PyString_FromString(PY_POPT_VERSION)); + PyDict_SetItemString(dict, "cvsid", PyString_FromString(rcs_id)); + for (c = intConstants; c->name; c++) { + PyObject *val = PyInt_FromLong(c->value); + PyDict_SetItemString(dict, c->name, val); + Py_DECREF(val); + } + /* Add the autohelp stuff */ + { + PyObject *val = PyString_FromString(AUTOHELP); + PyDict_SetItemString(dict, "POPT_AUTOHELP", val); + Py_DECREF(val); + } +} + diff --git a/python/rpmmodule.c b/python/rpmmodule.c index 254b633..8a0d22e 100644 --- a/python/rpmmodule.c +++ b/python/rpmmodule.c @@ -1863,8 +1863,13 @@ static PyObject * rhnUnload(PyObject * self, PyObject * args) { h = headerLink(s->h); /* Legacy headers are forced into immutable region. */ - if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) - h = headerReload(h, RPMTAG_HEADERIMMUTABLE); + if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { + Header nh = headerReload(h, RPMTAG_HEADERIMMUTABLE); + /* XXX Another unload/load cycle to "seal" the immutable region. */ + uh = headerUnload(nh); + headerFree(nh); + h = headerLoad(uh); + } /* All headers have SHA1 digest, compute and add if necessary. */ if (!headerIsEntry(h, RPMTAG_SHA1HEADER)) { diff --git a/rpm.spec.in b/rpm.spec.in index 5f98d6c..175b8b4 100644 --- a/rpm.spec.in +++ b/rpm.spec.in @@ -381,6 +381,7 @@ fi %files python %defattr(-,root,root) %{__prefix}/lib/python1.5/site-packages/rpmmodule.so +%{__prefix}/lib/python1.5/site-packages/poptmodule.so %endif %files devel -- 2.7.4