[Rpm-maint] [PATCH 11/18] Parse new policy requires header and check policy dependencies

Steve Lawrence slawrence at tresys.com
Wed Dec 23 20:57:31 UTC 2009


After a policy set has been prepared (rpmpolsPrepare), a call to
rpmpolsCheckDeps will determine if PolicyReuqires: dependencies are met.
This function only checks against packages currently installed.

Also, PolicyRequires are merged into Requires, so if normal dependency
checks pass, we know the PolicyRequries packages will be installed by the
end of the transaction.
---
 lib/rpmds.c       |    4 +++
 lib/rpmpol.c      |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rpmpol.h      |   17 ++++++++++++++++
 lib/rpmte.c       |    6 +++++
 lib/rpmtypes.h    |    3 +-
 lib/transaction.c |    5 ++++
 6 files changed, 90 insertions(+), 1 deletions(-)

diff --git a/lib/rpmds.c b/lib/rpmds.c
index 3f92ab8..2178f7f 100644
--- a/lib/rpmds.c
+++ b/lib/rpmds.c
@@ -54,6 +54,10 @@ static int dsType(rpmTag tag,
 	t = "Requires";
 	evr = RPMTAG_REQUIREVERSION;
 	f = RPMTAG_REQUIREFLAGS;
+    } else if (tag == RPMTAG_POLICYREQUIRENAME) {
+	t = "PolicyRequires";
+	evr = RPMTAG_POLICYREQUIREVERSION;
+	f = RPMTAG_POLICYREQUIREFLAGS;
     } else if (tag == RPMTAG_CONFLICTNAME) {
 	t = "Conflicts";
 	evr = RPMTAG_CONFLICTVERSION;
diff --git a/lib/rpmpol.c b/lib/rpmpol.c
index 893f487..c69677f 100644
--- a/lib/rpmpol.c
+++ b/lib/rpmpol.c
@@ -85,6 +85,7 @@ rpmpol rpmpolFree(rpmpol pol)
 	pol->names = _free(pol->names);
 	pol->flags = _free(pol->flags);
 	pol->actions = _free(pol->actions);
+	pol->requires = rpmdsFree(pol->requires);
 
 	if(pol->types) {
 		for (i = 0; i < pol->count; i++) {
@@ -203,6 +204,7 @@ rpmpol rpmpolNew(Header h)
 	pol->flags = flags.data;
 	pol->types = typeslist;
 	pol->obsoletes = obslist;
+	pol->requires = rpmdsNew(h, RPMTAG_POLICYREQUIRENAME, 0);
 	pol->actions = xcalloc(pol->count, sizeof(*pol->actions));
 	for (i = 0; i < pol->count; i++) {
 		pol->actions[i] = RPMPOL_ACTION_IGNORE;
@@ -337,6 +339,11 @@ void rpmpolSetAction(rpmpol pol, rpmpolAction action)
 	}
 }
 
+rpmds rpmpolGetRequires(const rpmpol pol)
+{
+    return pol ? pol->requires : NULL;
+}
+
 rpm_time_t rpmpolGetTime(const rpmpol pol)
 {
 	return pol ? pol->time : 0;
@@ -1033,6 +1040,55 @@ exit:
 	return rc;
 }
 
+rpmRC rpmpolsCheckDeps(rpmpols ps, rpmdb db)
+{
+	unsigned int i;
+
+	if (!ps || !db) {
+		return RPMRC_FAIL;
+	}
+
+	for (i = 0; i < ps->count; i++) {
+		rpmpol pol = ps->pols[i];
+
+		int policyIgnored = 1;
+		rpmpolInitIterator(pol);
+		while (rpmpolNext(pol) >= 0) {
+			rpmpolAction action = rpmpolGetAction(pol);
+			if (action == RPMPOL_ACTION_INSTALL || action == RPMPOL_ACTION_UPGRADE) {
+				policyIgnored = 0;
+				break;
+			}
+		}
+		if (policyIgnored) {
+			continue;
+		}
+
+		rpmds req = rpmpolGetRequires(pol);
+		rpmdsInit(req);
+		while (rpmdsNext(req) >= 0) {
+			Header h;
+			int depMet = 0;
+			rpmdbMatchIterator mi = rpmdbInitIterator(db, RPMTAG_PROVIDENAME, rpmdsN(req), 0);
+			while ((h = rpmdbNextIterator(mi)) != NULL) {
+				if (rpmdsAnyMatchesDep(h, req, 0)) {
+					depMet = 1;
+					break;
+				}
+			}
+			mi = rpmdbFreeIterator(mi);
+			if (!depMet) {
+				goto missing;
+			}
+		}
+	}
+
+	return RPMRC_OK;
+
+missing:
+	return RPMRC_MISSINGDEPS;
+}
+
 rpmRC rpmpolsSaveState(rpmpols ps, rpmdb db, rpm_tid_t tid)
 {
 	Header h;
diff --git a/lib/rpmpol.h b/lib/rpmpol.h
index 144a99f..a06ac74 100644
--- a/lib/rpmpol.h
+++ b/lib/rpmpol.h
@@ -139,6 +139,14 @@ rpmpolAction rpmpolGetAction(const rpmpol pol);
 RPM_GNUC_INTERNAL
 void rpmpolSetAction(rpmpol pol, rpmpolAction action);
 
+/*
+ * Get the requires dependency set for the policy
+ * @param pol	policy set
+ * @return		policy requires dependency set
+ */
+RPM_GNUC_INTERNAL
+rpmds rpmpolGetRequires(const rpmpol pol);
+
 /** \ingroup rpmpol
  * Get the time the policy was installed
  * @param pol	policy set
@@ -316,6 +324,15 @@ RPM_GNUC_INTERNAL
 rpmRC rpmpolsPrepare(rpmpols ps, rpmdb db);
 
 /** \ingroup rpmpol
+ * Perform dependency checks of installed/upgraded policies
+ * @param ps	rpm policy set
+ * @param db	rpm database
+ * @return		RPMRC_OK on success, RPMRC_FAIL if missing deps
+ */
+RPM_GNUC_INTERNAL
+rpmRC rpmpolsCheckDeps(rpmpols ps, rpmdb db);
+
+/** \ingroup rpmpol
  * Write the policy set to the rpm database
  * @param ps	rpm policy set
  * @param db	rpm database
diff --git a/lib/rpmte.c b/lib/rpmte.c
index a749994..899bd99 100644
--- a/lib/rpmte.c
+++ b/lib/rpmte.c
@@ -291,6 +291,12 @@ static void addTE(rpmts ts, rpmte p, Header h,
 
     rpmteColorDS(p, RPMTAG_PROVIDENAME);
     rpmteColorDS(p, RPMTAG_REQUIRENAME);
+
+    if (p->policies && rpmtsSELinuxEnabled(ts) && !(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOLICY)) {
+		rpmds polreqs = rpmdsNew(h, RPMTAG_POLICYREQUIRENAME, 0);
+		rpmdsMerge(&p->requires, polreqs);
+		rpmdsFree(polreqs);
+    }
     return;
 }
 
diff --git a/lib/rpmtypes.h b/lib/rpmtypes.h
index 8ba0df8..70fbe16 100644
--- a/lib/rpmtypes.h
+++ b/lib/rpmtypes.h
@@ -92,7 +92,8 @@ typedef	enum rpmRC_e {
     RPMRC_NOTFOUND	= 1,	/*!< Generic not found code. */
     RPMRC_FAIL		= 2,	/*!< Generic failure code. */
     RPMRC_NOTTRUSTED	= 3,	/*!< Signature is OK, but key is not trusted. */
-    RPMRC_NOKEY		= 4	/*!< Public key is unavailable. */
+    RPMRC_NOKEY		= 4,	/*!< Public key is unavailable. */
+    RPMRC_MISSINGDEPS	= 5	/*!< Missing dependencies error code. */
 } rpmRC;
 
 #ifdef __cplusplus
diff --git a/lib/transaction.c b/lib/transaction.c
index 89d1324..5f0549d 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -1191,6 +1191,11 @@ static rpmRC rpmtsLoadPolicy(rpmts ts)
 		goto err;
 	}
 
+	rc = rpmpolsCheckDeps(ps, rpmtsGetRdb(ts));
+	if (rc != RPMRC_OK) {
+		goto err;
+	}
+
 	rc = rpmpolsInstall(ps, ts);
 	if (rc != RPMRC_OK) {
 		goto err;
-- 
1.6.0.6



More information about the Rpm-maint mailing list