[Rpm-maint] [PATCH 05/12] Add rpmpol struct and helper functions
Steve Lawrence
slawrence at tresys.com
Thu Oct 22 18:25:42 UTC 2009
The rpmpol struct is essentially a list of policies extracted from a
single package. It contains an iterator and getters to get the necessary
information.
---
lib/Makefile.am | 2 +-
lib/rpmpol.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/rpmpol.h | 158 ++++++++++++++++++++++
lib/rpmtypes.h | 1 +
4 files changed, 550 insertions(+), 1 deletions(-)
create mode 100644 lib/rpmpol.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 1467a55..cf28b54 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -27,7 +27,7 @@ librpm_la_SOURCES = \
cpio.c cpio.h depends.c order.c formats.c tagexts.c fs.c fsm.c fsm.h \
manifest.c manifest.h misc.c package.c \
poptALL.c poptI.c poptQV.c psm.c psm.h query.c \
- rpmal.c rpmal.h rpmchecksig.c rpmds.c rpmfi.c rpmfi_internal.h rpmgi.c \
+ rpmal.c rpmal.h rpmchecksig.c rpmds.c rpmfi.c rpmfi_internal.h rpmgi.c rpmpol.c \
rpminstall.c rpmts_internal.h \
rpmlead.c rpmlead.h rpmps.c rpmrc.c \
rpmte.c rpmte_internal.h rpmts.c \
diff --git a/lib/rpmpol.c b/lib/rpmpol.c
new file mode 100644
index 0000000..5198bb1
--- /dev/null
+++ b/lib/rpmpol.c
@@ -0,0 +1,390 @@
+/** \ingroup rpmdep
+ * \file lib/rpmpol.c
+ */
+#include "system.h"
+
+#include <rpm/rpmtypes.h>
+#include <rpm/rpmlib.h>
+#include <rpm/rpmpol.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+
+#include "rpmio/base64.h"
+
+#include "debug.h"
+
+/**
+ * Package policy set.
+ */
+struct rpmpol_s {
+ char ** data; /*!< policy data */
+ char ** names; /*!< policy names */
+ ARGV_t * types; /*!< policy types */
+ ARGV_t * obsoletes; /*!< policy obsoletes */
+ rpmpolFlags * flags; /*!< policy flags */
+ rpmpolAction * actions; /*!< install, upgrade, remove, ignore */
+ int count; /*!< number of policies */
+ int nrefs; /*!< reference counting */
+ int index; /*!< index for iterator */
+};
+
+rpmpol rpmpolUnlink(rpmpol pol)
+{
+ if (pol) {
+ pol->nrefs--;
+ }
+ return NULL;
+}
+
+rpmpol rpmpolLink(rpmpol pol)
+{
+ if (pol) {
+ pol->nrefs++;
+ }
+ return pol;
+}
+
+rpmpol rpmpolFree(rpmpol pol)
+{
+ int i;
+
+ if (pol == NULL) {
+ return NULL;
+ }
+
+ if (pol->nrefs > 1) {
+ return rpmpolUnlink(pol);
+ }
+
+ pol->data = _free(pol->data);
+ pol->names = _free(pol->names);
+ pol->flags = _free(pol->flags);
+ pol->actions = _free(pol->actions);
+
+ if(pol->types) {
+ for (i = 0; i < pol->count; i++) {
+ argvFree(pol->types[i]);
+ }
+ pol->types = _free(pol->types);
+ }
+
+ if (pol->obsoletes) {
+ for (i = 0; i < pol->count; i++) {
+ argvFree(pol->obsoletes[i]);
+ }
+ pol->obsoletes = _free(pol->obsoletes);
+ }
+
+ rpmpolUnlink(pol);
+ pol = _free(pol);
+ return NULL;
+}
+
+rpmpol rpmpolNew(Header h)
+{
+ rpmpol pol = NULL;
+ struct rpmtd_s policies, names, types, typesidx, flags, obsoletes, obsoletesby;
+ ARGV_t * obslist = NULL;
+ ARGV_t * typeslist = NULL;
+ int count;
+ int i;
+
+ rpmtdReset(&policies);
+ rpmtdReset(&names);
+ rpmtdReset(&types);
+ rpmtdReset(&typesidx);
+ rpmtdReset(&flags);
+ rpmtdReset(&obsoletes);
+ rpmtdReset(&obsoletesby);
+
+ if (!headerIsEntry(h, RPMTAG_POLICIES)) {
+ goto err;
+ }
+
+ if (!headerGet(h, RPMTAG_POLICIES, &policies, HEADERGET_ALLOC | HEADERGET_ARGV)) {
+ goto err;
+ }
+
+ count = rpmtdCount(&policies);
+ if (count <= 0) {
+ goto err;
+ }
+
+ if (!headerGet(h, RPMTAG_POLICYNAMES, &names, HEADERGET_ALLOC | HEADERGET_ARGV) ||
+ rpmtdCount(&names) != count) {
+ goto err;
+ }
+
+ if (!headerGet(h, RPMTAG_POLICYFLAGS, &flags, HEADERGET_ALLOC) ||
+ rpmtdCount(&flags) != count) {
+ goto err;
+ }
+
+ typeslist = xcalloc(count, sizeof(*typeslist));
+ if (headerIsEntry(h, RPMTAG_POLICYTYPES)) {
+ uint32_t index;
+
+ if (!headerGet(h, RPMTAG_POLICYTYPES, &types, HEADERGET_ALLOC | HEADERGET_ARGV)) {
+ goto err;
+ }
+
+ if (!headerGet(h, RPMTAG_POLICYTYPESINDEXES, &typesidx, HEADERGET_ALLOC) ||
+ rpmtdCount(&types) != rpmtdCount(&typesidx)) {
+ goto err;
+ }
+
+ for (i = 0; i < rpmtdCount(&types); i++) {
+ index = ((uint32_t*)typesidx.data)[i];
+ if (index < 0 || index >= count) {
+ goto err;
+ }
+ argvAdd(&typeslist[index], ((char**)types.data)[i]);
+ }
+
+ rpmtdFreeData(&types);
+ rpmtdFreeData(&typesidx);
+ }
+
+ obslist = xcalloc(count, sizeof(*obslist));
+ if (headerIsEntry(h, RPMTAG_POLICYOBSOLETES)) {
+ uint32_t index;
+
+ if (!headerGet(h, RPMTAG_POLICYOBSOLETES, &obsoletes, HEADERGET_ALLOC | HEADERGET_ARGV)) {
+ goto err;
+ }
+
+ if (!headerGet(h, RPMTAG_POLICYOBSOLETESBY, &obsoletesby, HEADERGET_ALLOC) ||
+ rpmtdCount(&obsoletes) != rpmtdCount(&obsoletesby)) {
+ goto err;
+ }
+
+ for (i = 0; i < rpmtdCount(&obsoletes); i++) {
+ index = ((uint32_t*)obsoletesby.data)[i];
+ if (index < 0 || index >= count) {
+ goto err;
+ }
+ argvAdd(&obslist[index], ((char**)obsoletes.data)[i]);
+ }
+
+ rpmtdFreeData(&obsoletes);
+ rpmtdFreeData(&obsoletesby);
+ }
+
+ pol = xcalloc(1, sizeof(*pol));
+ pol->count = count;
+ pol->index = -1;
+ pol->data = policies.data;
+ pol->names = names.data;
+ pol->flags = flags.data;
+ pol->types = typeslist;
+ pol->obsoletes = obslist;
+ pol->actions = xcalloc(pol->count, sizeof(*pol->actions));
+ for (i = 0; i < pol->count; i++) {
+ pol->actions[i] = RPMPOL_ACTION_IGNORE;
+ }
+
+ pol = rpmpolLink(pol);
+
+ return pol;
+
+ err:
+ rpmtdFreeData(&policies);
+ rpmtdFreeData(&names);
+ rpmtdFreeData(&flags);
+ rpmtdFreeData(&types);
+ rpmtdFreeData(&typesidx);
+ rpmtdFreeData(&obsoletes);
+ rpmtdFreeData(&obsoletesby);
+ if (typeslist) {
+ for (i = 0; i < count; i++) {
+ argvFree(typeslist[i]);
+ }
+ typeslist = _free(typeslist);
+ }
+
+ if (obslist) {
+ for (i = 0; i < count; i++) {
+ argvFree(obslist[i]);
+ }
+ obslist = _free(obslist);
+ }
+
+ return NULL;
+}
+
+rpmpol rpmpolInitIterator(rpmpol pol)
+{
+ if (pol) {
+ pol->index = -1;
+ }
+
+ return pol;
+}
+
+int rpmpolIsValidIndex(const rpmpol pol)
+{
+ return (pol && pol->index >= 0 && pol->index < pol->count);
+}
+
+int rpmpolNext(rpmpol pol)
+{
+ int i = -1;
+
+ if (pol) {
+ pol->index++;
+ if (rpmpolIsValidIndex(pol)) {
+ i = pol->index;
+ } else {
+ pol->index = pol->count;
+ }
+ }
+
+ return i;
+}
+
+int rpmpolCount(rpmpol pol)
+{
+ return pol ? pol->count : -1;
+}
+
+const char *rpmpolGetData(const rpmpol pol)
+{
+ if (pol && pol->data && rpmpolIsValidIndex(pol)) {
+ return pol->data[pol->index];
+ }
+
+ return NULL;
+}
+
+const char *rpmpolGetName(const rpmpol pol)
+{
+ if (pol && pol->names && rpmpolIsValidIndex(pol)) {
+ return pol->names[pol->index];
+ }
+
+ return NULL;
+}
+
+ARGV_const_t rpmpolGetTypes(const rpmpol pol)
+{
+ if (pol && pol->types && rpmpolIsValidIndex(pol)) {
+ return pol->types[pol->index];
+ }
+
+ return NULL;
+}
+
+rpmpolFlags rpmpolGetFlags(const rpmpol pol)
+{
+ if (pol && pol->flags && rpmpolIsValidIndex(pol)) {
+ return pol->flags[pol->index];
+ }
+
+ return 0;
+}
+
+ARGV_const_t rpmpolGetObsoletes(const rpmpol pol)
+{
+ if (pol && pol->obsoletes && rpmpolIsValidIndex(pol)) {
+ return pol->obsoletes[pol->index];
+ }
+
+ return NULL;
+}
+
+rpmpolAction rpmpolGetAction(const rpmpol pol)
+{
+ if (pol && pol->actions && rpmpolIsValidIndex(pol)) {
+ return pol->actions[pol->index];
+ }
+
+ return 0;
+}
+
+void rpmpolSetAction(rpmpol pol, rpmpolAction action)
+{
+ if (pol && pol->actions && rpmpolIsValidIndex(pol)) {
+ pol->actions[pol->index] = action;
+ }
+}
+
+int rpmpolHasType(const rpmpol pol, const char * type)
+{
+ ARGV_const_t types;
+
+ if (!pol || !type) {
+ return 0;
+ }
+
+ for (types = rpmpolGetTypes(pol); types && *types; types++) {
+ if (rstreq(*types, type) || rstreq(*types, RPMPOL_TYPE_DEFAULT)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void rpmpolRemove(rpmpol pol)
+{
+ if (!pol || !rpmpolIsValidIndex(pol)) {
+ return;
+ }
+
+ int i = pol->index;
+ argvFree(pol->types[i]);
+ argvFree(pol->obsoletes[i]);
+
+ for (; i < pol->count - 1; i++) {
+ pol->data[i] = pol->data[i + 1];
+ pol->names[i] = pol->names[i + 1];
+ pol->flags[i] = pol->flags[i + 1];
+ pol->actions[i] = pol->actions[i + 1];
+ pol->types[i] = pol->types[i + 1];
+ pol->obsoletes[i] = pol->obsoletes[i + 1];
+ }
+ pol->count--;
+ /* set the index to the previous element, so that a call to
+ * rpmpolNext after the remove will do the right thing */
+ pol->index--;
+}
+
+rpmRC rpmpolWritePolicy(const rpmpol pol, char ** path)
+{
+ char * tmppath = NULL;
+ FD_t fd = NULL;
+ char * policy = NULL;
+ size_t policylen;
+ int rc = RPMRC_FAIL;
+ const char * data;
+
+ data = rpmpolGetData(pol);
+ if (data == NULL) {
+ goto exit;
+ }
+
+ if (b64decode(data, (void**)&policy, &policylen) != 0) {
+ rpmlog(RPMLOG_ERR, _("Failed to decode policy\n"));
+ goto exit;
+ }
+
+ fd = rpmMkTempFile(NULL, &tmppath);
+ if (fd == NULL || Ferror(fd)) {
+ rpmlog(RPMLOG_ERR, _("Failed to create temporary file %s\n"), tmppath);
+ goto exit;
+ }
+
+ if (!Fwrite(policy, sizeof(*policy), policylen, fd)) {
+ rpmlog(RPMLOG_ERR, _("Failed to write policy to file %s\n"), tmppath);
+ goto exit;
+ }
+
+ *path = tmppath;
+ rc = RPMRC_OK;
+
+exit:
+ if (fd) Fclose(fd);
+ _free(policy);
+ if (rc != RPMRC_OK) _free(tmppath);
+
+ return rc;
+}
diff --git a/lib/rpmpol.h b/lib/rpmpol.h
index ee74a84..ca5e5e4 100644
--- a/lib/rpmpol.h
+++ b/lib/rpmpol.h
@@ -6,10 +6,19 @@
* Structure(s) used for policy sets.
*/
+#include <rpm/rpmtypes.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+typedef enum rpmpolAction_e {
+ RPMPOL_ACTION_IGNORE = 0,
+ RPMPOL_ACTION_INSTALL = 1,
+ RPMPOL_ACTION_UPGRADE = 2,
+ RPMPOL_ACTION_REMOVE = 3
+} rpmpolAction;
+
typedef enum rpmpolFlags_e {
RPMPOL_FLAG_NONE = 0,
RPMPOL_FLAG_BASE = (1 << 0)
@@ -17,6 +26,155 @@ typedef enum rpmpolFlags_e {
#define RPMPOL_TYPE_DEFAULT "default"
+/** \ingroup rpmpol
+ * Unreference a policy set instance.
+ * @param pol policy set
+ * @return NULL always
+ */
+RPM_GNUC_INTERNAL
+rpmpol rpmpolUnlink(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Reference a policy set instance.
+ * @param pol policy set
+ * @return new policy set reference
+ */
+RPM_GNUC_INTERNAL
+rpmpol rpmpolLink(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Destroy a policy set.
+ * @param pol policy set
+ * @return NULL always
+ */
+RPM_GNUC_INTERNAL
+rpmpol rpmpolFree(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Create a new policy set.
+ * @param h header
+ * @return new policy set
+ */
+RPM_GNUC_INTERNAL
+rpmpol rpmpolNew(Header h);
+
+/** \ingroup rpmpol
+ * Create policy element iterator.
+ * @param pol policy set
+ * @return policy set
+ */
+RPM_GNUC_INTERNAL
+rpmpol rpmpolInitIterator(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return index of next policy element.
+ * @param pol policy set
+ * @return next index of policy set, -1 on termination
+ */
+RPM_GNUC_INTERNAL
+int rpmpolNext(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return policy set count.
+ * @param pol policy set
+ * @return current count
+ */
+RPM_GNUC_INTERNAL
+int rpmpolCount(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy data.
+ * @param pol policy set
+ * @return current policy data, NULL on invalid
+ */
+RPM_GNUC_INTERNAL
+const char *rpmpolGetData(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy name.
+ * @param pol policy set
+ * @return current policy name, NULL on invalid
+ */
+RPM_GNUC_INTERNAL
+const char *rpmpolGetName(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy types
+ * @param pol policy set
+ * @return current policy types, NULL on invalid
+ */
+RPM_GNUC_INTERNAL
+ARGV_const_t rpmpolGetTypes(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy flags.
+ * @param pol policy set
+ * @return current policy flags
+ */
+RPM_GNUC_INTERNAL
+rpmpolFlags rpmpolGetFlags(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy obsoletes.
+ * @param pol policy set
+ * @return currnt policy obsoletes
+ */
+RPM_GNUC_INTERNAL
+ARGV_const_t rpmpolGetObsoletes(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Return current policy action.
+ * @param pol policy set
+ * @return current policy action, -1 on invalid
+ */
+RPM_GNUC_INTERNAL
+rpmpolAction rpmpolGetAction(const rpmpol pol);
+
+/** \ingroup rpmpol
+ * Set current policy action.
+ * @param action action to set
+ * @param pol policy set
+ */
+RPM_GNUC_INTERNAL
+void rpmpolSetAction(rpmpol pol, rpmpolAction action);
+
+/** \ingroup rpmpol
+ * Determine if a policy has a type
+ * @param pol policy set
+ * @param type policy type
+ * @return 1 if type pol has type, 0 otherwise
+ */
+RPM_GNUC_INTERNAL
+int rpmpolHasType(const rpmpol pol, const char * type);
+
+/** \ingroup rpmpol
+ * Remove the current element from a policy set
+ * Note: This sets the index to the previous element. rpmpolNext or rpmpolInitIterator
+ * should be called after a remove before any rpmpol[Get,Set] functions are called
+ * @param pol policy set
+ * @return current count
+ */
+RPM_GNUC_INTERNAL
+void rpmpolRemove(rpmpol pol);
+
+/** \ingroup rpmpol
+ * Write current policy to a temporary file.
+ * @param pol policy set
+ * @param path path to file created, or unchanged if RPMRC_OK is not returned.
+ * If RPMRC_OK is returned, the caller must free path
+ * @return RPMRC_OK on success, RPMRC_FAILED on failure
+ */
+RPM_GNUC_INTERNAL
+rpmRC rpmpolWritePolicy(const rpmpol pol, char ** path);
+
+/** \ingroup rpmpol
+ * Determine if the current policy index if valid
+ * @param pol policy set
+ * @return 1 if index is valid, 0 otherwise
+ */
+RPM_GNUC_INTERNAL
+int rpmpolIsValidIndex(const rpmpol pol);
+
#ifdef __cplusplus
}
diff --git a/lib/rpmtypes.h b/lib/rpmtypes.h
index 99a28e2..2736d97 100644
--- a/lib/rpmtypes.h
+++ b/lib/rpmtypes.h
@@ -61,6 +61,7 @@ typedef struct rpmte_s * rpmte;
typedef struct rpmds_s * rpmds;
typedef struct rpmfi_s * rpmfi;
typedef struct rpmdb_s * rpmdb;
+typedef struct rpmpol_s * rpmpol;
typedef struct rpmdbMatchIterator_s * rpmdbMatchIterator;
typedef const void * fnpyKey;
typedef void * rpmCallbackData;
--
1.6.0.6
More information about the Rpm-maint
mailing list