[Rpm-maint] [PATCH 05/19] Add rpmpol struct and helper functions

Steve Lawrence slawrence at tresys.com
Tue Feb 2 20:25:08 UTC 2010


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    |  394 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rpmpol.h    |  161 ++++++++++++++++++++++
 lib/rpmtypes.h  |    1 +
 4 files changed, 557 insertions(+), 1 deletions(-)
 create mode 100644 lib/rpmpol.c

diff --git a/lib/Makefile.am b/lib/Makefile.am
index 61f45c5..3971b27 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -26,7 +26,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..de692fe
--- /dev/null
+++ b/lib/rpmpol.c
@@ -0,0 +1,394 @@
+/** \ingroup rpmdep
+ * \file lib/rpmpol.c
+ */
+
+#include "system.h"
+
+#if WITH_SELINUX
+
+#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;
+}
+#endif				/* WITH_SELINUX */
diff --git a/lib/rpmpol.h b/lib/rpmpol.h
index ee74a84..c3b78cb 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,8 +26,160 @@ typedef enum rpmpolFlags_e {
 
 #define RPMPOL_TYPE_DEFAULT "default"
 
+#if WITH_SELINUX
+
+/** \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
 }
 #endif
+#endif				/* WITH_SELINUX */
 #endif				/* H_rpmpol */
diff --git a/lib/rpmtypes.h b/lib/rpmtypes.h
index 07533f7..6a7b5ec 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 struct rpmtsi_s * rpmtsi;
 
-- 
1.6.2.5



More information about the Rpm-maint mailing list