[Rpm-maint] [PATCH 3/6] Add new %sepolicy section to the spec file format

Steve Lawrence slawrence at tresys.com
Mon Aug 30 20:32:29 UTC 2010


The %sepolicy section is used to describe SELinux policy to be included
in a package. It's syntax is similar to other sections (%files, %pre,
%post, etc.) in that you can provide a string and -n after the
declaration to specify policy should be added to a subpackage.

For example:

%sepolicy
 # policy in this section will be added to the main package

%sepolicy foo
 # policy in this section will be added to the '<mainpackage>-foo' subpackage

%sepolicy -n bar
 # policy in this section will be added to the 'bar' subpackage

The %sepolicy section contains zero or more %semodule directives, with the
following format:

%semodule [OPTIONS] path/to/module.pp

The available options are:

-b, --base
	The module is a base module

-n, --name=NAME
	The name of the module. If not given, assumes the name is the basename of
	the module file with file extensions removed.

-t, --types=TYPES
	One or more comma-separated strings specifying which policy types the
	module can work with. To explicitly state that a module can work with any
	policy type, "default" can be specified as the value. If not specified,
	assumes the module can work with any policy type, and assigns the types as
	"default".

Below is an example of this new format:

  %sepolicy
  %semodule -n foo -t mls policy/foo.pp
  %semodule -n bar -t strict,targeted,mls -b policy/bar.pp

This also adds new header tags to store the new information:
 RPMTAG_POLICYNAMES        (string array)
 RPMTAG_POLICYTYPES        (string array)
 RPMTAG_POLICYTYPESINDEXES (uint32 array)
 RPMTAG_POLICYFLAGS        (uint32 array)

The index of NAMES and FLAGS maps directly to the index of RPMTAG_POLICIES.
However, because a single policy can have multiple types, the mapping for
TYPES is not direct. For this, the index maps to TYPESINDEXES, which
contains the index of the policy that the type maps to. This is similar to
how DIRINDEXES is used to map DIRNAMES and BASENAMES. As an example, the
previous %sepolicy section would have the following header tags:

RPMTAG_POLICIES:
 0: <foo.pp data, base64 encoded>
 1: <bar.pp data, base64 encoded>

RPMTAG_POLICYNAMES:
 0: foo
 1: bar

RPMTAG_POLICYFLAGS:
 0: 0
 1: 1	# assumes flag 1 == BASE

RPMTAG_POILCYTYPES:        RPMTAG_POLICYTYPESINDEXES:
 0: mls                     0: 0
 1: strict                  1: 1
 2: targeted                2: 1
 3: mls                     3: 1
---
 Makefile.am               |    1 +
 build/Makefile.am         |    1 +
 build/build.c             |    4 +
 build/parsePolicies.c     |   91 +++++++++++++
 build/parseSpec.c         |    5 +
 build/policies.c          |  320 +++++++++++++++++++++++++++++++++++++++++++++
 build/rpmbuild_internal.h |   20 +++-
 build/rpmspec.h           |    1 +
 build/spec.c              |    2 +
 lib/rpmpol.h              |   24 ++++
 lib/rpmtag.h              |    4 +
 preinstall.am             |    4 +
 tests/rpmgeneral.at       |    4 +
 13 files changed, 480 insertions(+), 1 deletions(-)
 create mode 100644 build/parsePolicies.c
 create mode 100644 build/policies.c
 create mode 100644 lib/rpmpol.h

diff --git a/Makefile.am b/Makefile.am
index 798549a..dfee933 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -59,6 +59,7 @@ pkginclude_HEADERS += lib/rpmlib.h
 pkginclude_HEADERS += lib/rpmds.h
 pkginclude_HEADERS += lib/rpmfi.h
 pkginclude_HEADERS += lib/rpmlegacy.h
+pkginclude_HEADERS += lib/rpmpol.h
 pkginclude_HEADERS += lib/rpmps.h
 pkginclude_HEADERS += lib/rpmprob.h
 pkginclude_HEADERS += lib/rpmtag.h
diff --git a/build/Makefile.am b/build/Makefile.am
index 36f3d63..a168413 100644
--- a/build/Makefile.am
+++ b/build/Makefile.am
@@ -13,6 +13,7 @@ librpmbuild_la_SOURCES = \
 	parseBuildInstallClean.c parseChangelog.c parseDescription.c \
 	parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \
 	parseSpec.c poptBT.c reqprov.c rpmfc.c spec.c fts.h fts.c \
+	parsePolicies.c policies.c \
 	rpmbuild_internal.h rpmbuild_misc.h
 
 librpmbuild_la_LDFLAGS = -version-info 1:0:0
diff --git a/build/build.c b/build/build.c
index 64c4d6c..d029534 100644
--- a/build/build.c
+++ b/build/build.c
@@ -260,6 +260,10 @@ rpmRC buildSpec(rpmts ts, rpmSpec spec, int what, int test)
 	    (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
 		goto exit;
 
+	if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY)) &&
+	    (rc = processBinaryPolicies(spec, test)))
+		goto exit;
+
 	if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
 	    (rc = packageSources(spec)))
 		return rc;
diff --git a/build/parsePolicies.c b/build/parsePolicies.c
new file mode 100644
index 0000000..c66d82f
--- /dev/null
+++ b/build/parsePolicies.c
@@ -0,0 +1,91 @@
+/** \ingroup rpmbuild
+ * \file build/parsePolicies.c
+ *  Parse %policies section from spec file.
+ */
+
+#include "system.h"
+
+#include <rpm/header.h>
+#include <rpm/rpmbuild.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+#include "build/rpmbuild_internal.h"
+#include "debug.h"
+
+int parsePolicies(rpmSpec spec)
+{
+    int nextPart, res = PART_ERROR;
+    Package pkg;
+    int rc, argc;
+    int arg;
+    const char **argv = NULL;
+    const char *name = NULL;
+    int flag = PART_SUBNAME;
+    poptContext optCon = NULL;
+
+    struct poptOption optionsTable[] = {
+	{NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL},
+	{0, 0, 0, 0, 0, NULL, NULL}
+    };
+
+    if ((rc = poptParseArgvString(spec->line, &argc, &argv))) {
+	rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%policies: %s\n"),
+	       spec->lineNum, poptStrerror(rc));
+	goto exit;
+    }
+
+    optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+    while ((arg = poptGetNextOpt(optCon)) > 0) {
+	if (arg == 'n') {
+	    flag = PART_NAME;
+	}
+    }
+
+    if (arg < -1) {
+	rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"),
+	       spec->lineNum,
+	       poptBadOption(optCon, POPT_BADOPTION_NOALIAS), spec->line);
+	goto exit;
+    }
+
+    if (poptPeekArg(optCon)) {
+	if (name == NULL)
+	    name = poptGetArg(optCon);
+	if (poptPeekArg(optCon)) {
+	    rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"),
+		   spec->lineNum, spec->line);
+	    goto exit;
+	}
+    }
+
+    if (lookupPackage(spec, name, flag, &pkg)) {
+	rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"),
+	       spec->lineNum, spec->line);
+	goto exit;
+    }
+
+    pkg->policyList = newStringBuf();
+
+    if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
+	nextPart = PART_NONE;
+    } else if (rc < 0) {
+	goto exit;
+    } else {
+	while (!(nextPart = isPart(spec->line))) {
+	    appendLineStringBuf(pkg->policyList, spec->line);
+	    if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
+		nextPart = PART_NONE;
+		break;
+	    } else if (rc < 0) {
+		goto exit;
+	    }
+	}
+    }
+    res = nextPart;
+
+  exit:
+    argv = _free(argv);
+    optCon = poptFreeContext(optCon);
+
+    return res;
+}
diff --git a/build/parseSpec.c b/build/parseSpec.c
index 6078e0e..38ba5e2 100644
--- a/build/parseSpec.c
+++ b/build/parseSpec.c
@@ -57,6 +57,7 @@ static const struct PartRec {
     { PART_TRIGGERIN,     LEN_AND_STR("%triggerin")},
     { PART_TRIGGERIN,     LEN_AND_STR("%trigger")},
     { PART_VERIFYSCRIPT,  LEN_AND_STR("%verifyscript")},
+    { PART_POLICIES,      LEN_AND_STR("%sepolicy")},
     {0, 0, 0}
 };
 
@@ -603,6 +604,10 @@ int parseSpec(rpmts ts, const char *specFile, const char *rootDir,
 	    parsePart = parseFiles(spec);
 	    break;
 
+	case PART_POLICIES:
+	    parsePart = parsePolicies(spec);
+	    break;
+
 	case PART_NONE:		/* XXX avoid gcc whining */
 	case PART_LAST:
 	case PART_BUILDARCHITECTURES:
diff --git a/build/policies.c b/build/policies.c
new file mode 100644
index 0000000..8874494
--- /dev/null
+++ b/build/policies.c
@@ -0,0 +1,320 @@
+/** \ingroup rpmbuild
+ * \file build/policies.c
+ *  The post-build, packaging of policies
+ */
+
+#include "system.h"
+
+#include <rpm/rpmbuild.h>
+#include <rpm/argv.h>
+#include <rpm/rpmlog.h>
+#include <rpm/rpmpol.h>
+
+#include "rpmio/rpmio_internal.h"
+#include "build/rpmbuild_internal.h"
+#include "rpmio/base64.h"
+
+#include "debug.h"
+
+typedef struct ModuleRec_s {
+    char *path;
+    char *data;
+    char *name;
+    ARGV_t types;
+    uint32_t flags;
+} *ModuleRec;
+
+static rpmRC writeModuleToHeader(ModuleRec mod, Package pkg)
+{
+    int rc = RPMRC_FAIL;
+    ARGV_t av;
+    uint32_t count;
+    struct rpmtd_s policies;
+    struct rpmtd_s policynames;
+    struct rpmtd_s policyflags;
+    struct rpmtd_s policytypes;
+    struct rpmtd_s policytypesidx;
+    rpmtdReset(&policies);
+    rpmtdReset(&policynames);
+    rpmtdReset(&policyflags);
+    rpmtdReset(&policytypes);
+    rpmtdReset(&policytypesidx);
+
+    if (!mod || !pkg) {
+	goto exit;
+    }
+
+    /* check for duplicates */
+    if (headerIsEntry(pkg->header, RPMTAG_POLICYNAMES)) {
+	int typeCount;
+	const char *name;
+	char *type;
+	int i;
+	int idx;
+
+	headerGet(pkg->header, RPMTAG_POLICYNAMES, &policynames, HEADERGET_MINMEM);
+	headerGet(pkg->header, RPMTAG_POLICYFLAGS, &policyflags, HEADERGET_ARGV | HEADERGET_MINMEM);
+	headerGet(pkg->header, RPMTAG_POLICYTYPES, &policytypes, HEADERGET_ARGV | HEADERGET_MINMEM);
+	headerGet(pkg->header, RPMTAG_POLICYTYPESINDEXES, &policytypesidx, HEADERGET_ARGV | HEADERGET_MINMEM);
+	typeCount = rpmtdCount(&policytypes);
+
+	while ((name = rpmtdNextString(&policynames))) {
+	    int overlappingtypes = 0;
+
+	    idx = rpmtdGetIndex(&policynames);
+
+	    for (i = 0; i < typeCount; i++) {
+		if (((int *) policytypesidx.data)[i] != idx) {
+		    continue;
+		}
+
+		type = ((char **) policytypes.data)[i];
+
+		if (rstreq(type, RPMPOL_TYPE_DEFAULT) ||
+		    argvSearch(mod->types, type, NULL) ||
+		    argvSearch(mod->types, RPMPOL_TYPE_DEFAULT, NULL)) {
+		    overlappingtypes = 1;
+		    break;
+		}
+	    }
+
+	    if (!overlappingtypes) {
+		continue;
+	    }
+
+	    if (rstreq(mod->name, name)) {
+		rpmlog(RPMLOG_ERR, _("Policy module '%s' duplicated with overlapping types\n"), name);
+		goto exit;
+	    }
+
+	    if ((mod->flags && RPMPOL_FLAG_BASE) &&
+		(((int *) policyflags.data)[idx] & RPMPOL_FLAG_BASE)) {
+		rpmlog(RPMLOG_ERR, _("Base modules '%s' and '%s' have overlapping types\n"), mod->name, name);
+		goto exit;
+	    }
+	}
+    }
+
+    if (headerIsEntry(pkg->header, RPMTAG_POLICIES)) {
+	if (!headerGet(pkg->header, RPMTAG_POLICIES, &policies, HEADERGET_MINMEM)) {
+	    rpmlog(RPMLOG_ERR, _("Failed to get policies from header\n"));
+	    goto exit;
+	}
+	count = rpmtdCount(&policies);
+    } else {
+	count = 0;
+    }
+
+    /* save everything to the header */
+    headerPutString(pkg->header, RPMTAG_POLICIES, mod->data);
+    headerPutString(pkg->header, RPMTAG_POLICYNAMES, mod->name);
+    headerPutUint32(pkg->header, RPMTAG_POLICYFLAGS, &mod->flags, 1);
+
+    for (av = mod->types; av && *av; av++) {
+	headerPutString(pkg->header, RPMTAG_POLICYTYPES, *av);
+	headerPutUint32(pkg->header, RPMTAG_POLICYTYPESINDEXES, &count, 1);
+    }
+
+    rc = RPMRC_OK;
+
+  exit:
+
+    rpmtdFreeData(&policies);
+    rpmtdFreeData(&policynames);
+    rpmtdFreeData(&policyflags);
+    rpmtdFreeData(&policytypes);
+    rpmtdFreeData(&policytypesidx);
+
+    return rc;
+}
+
+static ModuleRec freeModule(ModuleRec mod)
+{
+    if (mod) {
+	_free(mod->path);
+	_free(mod->data);
+	_free(mod->name);
+	argvFree(mod->types);
+	_free(mod);
+    }
+
+    return NULL;
+}
+
+static ModuleRec newModule(const char *path, const char *name,
+			   const char *types, uint32_t flags)
+{
+    ModuleRec mod;
+    uint8_t *raw = NULL;
+    ssize_t rawlen = 0;
+    const char *buildDir = "%{_builddir}/%{?buildsubdir}/";
+
+    if (!path) {
+	rpmlog(RPMLOG_ERR, _("%%semodule requires a file path\n"));
+	return NULL;
+    }
+
+    mod = xcalloc(1, sizeof(*mod));
+
+    mod->path = rpmGenPath(buildDir, NULL, path);
+
+    if ((rpmioSlurp(mod->path, &raw, &rawlen)) != 0 || raw == NULL) {
+	rpmlog(RPMLOG_ERR, _("Failed to read  policy file: %s\n"),
+	       mod->path);
+	goto err;
+    }
+
+    mod->data = b64encode(raw, rawlen, -1);
+    if (!mod->data) {
+	rpmlog(RPMLOG_ERR, _("Failed to encode policy file: %s\n"),
+	       mod->path);
+	goto err;
+    }
+
+    if (name) {
+	mod->name = xstrdup(name);
+    } else {
+	/* assume base name (minus extension) if name is not given */
+	char *tmp = xstrdup(mod->path);
+	char *bname = basename(tmp);
+	char *end = strchr(bname, '.');
+	if (end)
+	    *end = '\0';
+	if (strlen(bname) > 0) {
+	    mod->name = xstrdup(bname);
+	} else {
+	    rpmlog(RPMLOG_ERR, _("Failed to determine a policy name: %s\n"),
+		   mod->path);
+	    _free(tmp);
+	    goto err;
+	}
+	_free(tmp);
+    }
+
+    if (types) {
+	mod->types = argvSplitString(types, ",", ARGV_SKIPEMPTY);
+	argvSort(mod->types, NULL);
+	if (argvSearch(mod->types, RPMPOL_TYPE_DEFAULT, NULL) && argvCount(mod->types) > 1) {
+	    rpmlog(RPMLOG_WARNING, _("'%s' type given with other types in %%semodule %s. Compacting types to '%s'.\n"),
+		   RPMPOL_TYPE_DEFAULT, mod->path, RPMPOL_TYPE_DEFAULT);
+	    mod->types = argvFree(mod->types);
+	    argvAdd(&mod->types, RPMPOL_TYPE_DEFAULT);
+	}
+    } else {
+	argvAdd(&mod->types, RPMPOL_TYPE_DEFAULT);
+    }
+
+    mod->flags = flags;
+
+    return mod;
+
+  err:
+    freeModule(mod);
+    return NULL;
+}
+
+static rpmRC processPolicies(rpmSpec spec, Package pkg, int test)
+{
+    const char *path = NULL;
+    char *name = NULL;
+    char *types = NULL;
+    uint32_t flags = 0;
+    poptContext optCon = NULL;
+
+    ARGV_t policies = NULL;
+    ARGV_t pol;
+    rpmRC rc = RPMRC_FAIL;
+
+    struct poptOption optionsTable[] = {
+	{"name",  'n', POPT_ARG_STRING, &name,  'n', NULL, NULL},
+	{"types", 't', POPT_ARG_STRING, &types, 't', NULL, NULL},
+	{"base",  'b', POPT_ARGFLAG_OR, &flags, RPMPOL_FLAG_BASE, NULL, NULL},
+	POPT_TABLEEND
+    };
+
+    if (!spec || !pkg) {
+	goto exit;
+    }
+
+    argvSplit(&policies, getStringBuf(pkg->policyList), "\n");
+    for (pol = policies; *pol != NULL; pol++) {
+	ModuleRec mod;
+	char *line = *pol;
+	const char **argv = NULL;
+	int argc = 0;
+	int err;
+
+	if ((err = poptParseArgvString(line, &argc, &argv))) {
+	    rpmlog(RPMLOG_ERR, _("Error parsing %s: %s\n"),
+		   line, poptStrerror(err));
+	    goto exit;
+	}
+
+	if (!rstreq(argv[0], "%semodule")) {
+	    rpmlog(RPMLOG_ERR, _("Expecting %%semodule tag: %s\n"), line);
+	    goto exit;
+	}
+
+	optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+	while (poptGetNextOpt(optCon) > 0) {
+	}
+
+	path = poptGetArg(optCon);
+	if (!path) {
+	    rpmlog(RPMLOG_ERR, _("Missing module path in line: %s\n"),
+		   line);
+	    goto exit;
+	}
+
+	if (poptPeekArg(optCon)) {
+	    rpmlog(RPMLOG_ERR, _("Too many arguments in line: %s\n"),
+		   line);
+	    goto exit;
+	}
+
+	mod = newModule(path, name, types, flags);
+	if (!mod) {
+	    goto exit;
+	}
+
+	if (writeModuleToHeader(mod, pkg) != RPMRC_OK) {
+	    freeModule(mod);
+	    goto exit;
+	}
+
+	freeModule(mod);
+    }
+
+    rc = RPMRC_OK;
+
+  exit:
+    argvFree(policies);
+
+    return rc;
+}
+
+int processBinaryPolicies(rpmSpec spec, int test)
+{
+    Package pkg;
+    int rc = RPMRC_OK;
+    char *nvr;
+
+#if WITH_SELINUX
+    for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
+	if (pkg->policyList == NULL) {
+	    continue;
+	}
+
+	nvr = headerGetAsString(pkg->header, RPMTAG_NVRA);
+	rpmlog(RPMLOG_NOTICE, _("Processing policies: %s\n"), nvr);
+	free(nvr);
+
+	if (processPolicies(spec, pkg, test) != RPMRC_OK) {
+	    rc = RPMRC_FAIL;
+	    break;
+	}
+    }
+#endif
+
+    return rc;
+}
diff --git a/build/rpmbuild_internal.h b/build/rpmbuild_internal.h
index 2c63a12..d3fa724 100644
--- a/build/rpmbuild_internal.h
+++ b/build/rpmbuild_internal.h
@@ -70,7 +70,8 @@ typedef enum rpmParseState_e {
     PART_BUILDARCHITECTURES= 29+PART_BASE,/*!< */ 
     PART_TRIGGERPOSTUN  = 30+PART_BASE, /*!< */ 
     PART_TRIGGERPREIN   = 31+PART_BASE, /*!< */ 
-    PART_LAST           = 32+PART_BASE  /*!< */ 
+    PART_POLICIES       = 32+PART_BASE, /*!< */
+    PART_LAST           = 33+PART_BASE  /*!< */
 } rpmParseState; 
 
 
@@ -143,6 +144,14 @@ RPM_GNUC_INTERNAL
 int parseFiles(rpmSpec spec);
 
 /** \ingroup rpmbuild
+ * Parse %%sepolicy section of a spec file.
+ * @param spec		spec file control structure
+ * @return		>= 0 next rpmParseState, < 0 on error
+ */
+RPM_GNUC_INTERNAL
+int parsePolicies(rpmSpec spec);
+
+/** \ingroup rpmbuild
  * Parse tags from preamble of a spec file.
  * @param spec		spec file control structure
  * @param initialPackage
@@ -256,6 +265,15 @@ RPM_GNUC_INTERNAL
 int processBinaryFiles(rpmSpec spec, int installSpecialDoc, int test);
 
 /** \ingroup rpmbuild
+ * Post-build processing for policies in binary package(s).
+ * @param spec		spec file control structure
+ * @param test		don't execute scripts or package if testing
+ * @return		0 on success
+ */
+RPM_GNUC_INTERNAL
+int processBinaryPolicies(rpmSpec spec, int test);
+
+/** \ingroup rpmbuild
  * Post-build processing for source package.
  * @param spec		spec file control structure
  * @return		0 on success
diff --git a/build/rpmspec.h b/build/rpmspec.h
index cd57d0a..8b677a2 100644
--- a/build/rpmspec.h
+++ b/build/rpmspec.h
@@ -119,6 +119,7 @@ struct Package_s {
 
     StringBuf fileFile;
     StringBuf fileList;		/* If NULL, package will not be written */
+    StringBuf policyList;
 
     Package next;
 };
diff --git a/build/spec.c b/build/spec.c
index 9299807..92136fc 100644
--- a/build/spec.c
+++ b/build/spec.c
@@ -100,6 +100,7 @@ Package newPackage(rpmSpec spec)
     p->autoProv = 1;
     p->autoReq = 1;
     p->fileList = newStringBuf();
+    p->policyList = NULL;
 
     if (spec->packages == NULL) {
 	spec->packages = p;
@@ -129,6 +130,7 @@ static Package freePackage(Package pkg)
     pkg->ds = rpmdsFree(pkg->ds);
     pkg->fileList = freeStringBuf(pkg->fileList);
     pkg->fileFile = freeStringBuf(pkg->fileFile);
+    pkg->policyList = freeStringBuf(pkg->policyList);
     if (pkg->cpioList) {
 	rpmfi fi = pkg->cpioList;
 	pkg->cpioList = NULL;
diff --git a/lib/rpmpol.h b/lib/rpmpol.h
new file mode 100644
index 0000000..ee74a84
--- /dev/null
+++ b/lib/rpmpol.h
@@ -0,0 +1,24 @@
+#ifndef H_RPMPOL
+#define H_RPMPOL
+
+/** \ingroup rpmpol
+ * \file lib/rpmpol.h
+ * Structure(s) used for policy sets.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum rpmpolFlags_e {
+	RPMPOL_FLAG_NONE = 0,
+	RPMPOL_FLAG_BASE = (1 << 0)
+} rpmpolFlags;
+
+#define RPMPOL_TYPE_DEFAULT "default"
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif				/* H_rpmpol */
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 3aaebfa..8ff371f 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -297,6 +297,10 @@ typedef enum rpmTag_e {
     RPMTAG_TRIGGERSCRIPTFLAGS	= 5027, /* i[] */
     RPMTAG_FILESTATUS		= 5028, /* i[] extension */
     RPMTAG_COLLECTIONS		= 5029, /* s[] list of collections */
+    RPMTAG_POLICYNAMES		= 5030,	/* s[] */
+    RPMTAG_POLICYTYPES		= 5031,	/* s[] */
+    RPMTAG_POLICYTYPESINDEXES	= 5032,	/* i[] */
+    RPMTAG_POLICYFLAGS		= 5033,	/* i[] */
 
     RPMTAG_FIRSTFREE_TAG	/*!< internal */
 } rpmTag;
diff --git a/preinstall.am b/preinstall.am
index 7f64837..39cf3f8 100644
--- a/preinstall.am
+++ b/preinstall.am
@@ -78,6 +78,10 @@ include/rpm/rpmlegacy.h: lib/rpmlegacy.h include/rpm/$(dirstamp)
 	$(INSTALL_DATA) $(top_srcdir)/lib/rpmlegacy.h include/rpm/rpmlegacy.h
 BUILT_SOURCES += include/rpm/rpmlegacy.h
 CLEANFILES += include/rpm/rpmlegacy.h
+include/rpm/rpmpol.h: lib/rpmpol.h include/rpm/$(dirstamp)
+	$(INSTALL_DATA) $(top_srcdir)/lib/rpmpol.h include/rpm/rpmpol.h
+BUILT_SOURCES += include/rpm/rpmpol.h
+CLEANFILES += include/rpm/rpmpol.h
 include/rpm/rpmps.h: lib/rpmps.h include/rpm/$(dirstamp)
 	$(INSTALL_DATA) $(top_srcdir)/lib/rpmps.h include/rpm/rpmps.h
 BUILT_SOURCES += include/rpm/rpmps.h
diff --git a/tests/rpmgeneral.at b/tests/rpmgeneral.at
index 4c33f29..8f7c03e 100644
--- a/tests/rpmgeneral.at
+++ b/tests/rpmgeneral.at
@@ -181,6 +181,10 @@ PAYLOADFORMAT
 PKGID
 PLATFORM
 POLICIES
+POLICYFLAGS
+POLICYNAMES
+POLICYTYPES
+POLICYTYPESINDEXES
 POSTIN
 POSTINFLAGS
 POSTINPROG
-- 
1.6.2.5



More information about the Rpm-maint mailing list