Using arbitrary tags in packages likely needs a little explanation
until someplace to document the mess can be identified.
Arbitrary tags are alphabetic strings contained in the macro
%_arbitrary tags.
Here's what is currently configured by default macros:
#
# Colon separated list of permitted arbitrary tag names
%_arbitrary_tags Foo:Bar:Baz
To build a package with an arbitrary tag, one simply adds, say,
Foo: foo value
The string "Foo" is canonicalized, run through a sha-1 digest,
and the least significant 30 bits are OR'd with 0x40000000
to generate the tagno to be used to save the string value in a header.
It's easier to show an example than to explain.
I've built the time package including these lines in time.spec:
Foo: foo string
Bar: bar string
Baz: baz string
After building, the arbitrary tag content can be verified using --yaml
(or --xml if you wish). Here's what should be displayed (as soon
as I fix headerSprintf --yaml/--xml with unknown tags again again):
Tag_0x47d21531: baz string
Tag_0x64087297: bar string
Tag_0x690929d2: foo string
All arbitrary tags whose string name(s) are known can be displayed in
the usual
fashion using --queryformat:
$ rpm -qp --qf '%{foo}\n%{bar}\n%{baz}\n' time-1.7-30.i386.rpm
foo string
bar string
baz string
The arbitrary tag implementation is largely complete but I expect to
have to add
1) a convention to use "Tag_0x12345678" as an alternative nickname
for accessing arbitrary tags when the original string is unknown.
2) a generalization to string arrays by mentioning identical
arbitrary
tags multiple times
Foo: this is the 1st value
Foo: this is the 2nd value
Foo: this is the 3rd value
3) generalizations to handle non-string types either by coercion
prefix hints
(as YAML does), or by implicit typing rules, e.g. digit strings
will automagically
use RPM_UINT32_TYPE to store the value, are both relatively
simple possibilities.
1) and 2) are likely to happen this week, dunno about 3) yet, the
problem
of coerced/implicit typing likely needs some further thought before
committing
to an implementation.
Enjoy!
73 de Jeff
On Dec 2, 2007, at 6:06 PM, Jeff Johnson wrote:
> RPM Package Manager, CVS Repository
> http://rpm5.org/cvs/
>
> ______________________________________________________________________
> ______
>
> Server: rpm5.org Name: Jeff Johnson
> Root: /v/rpm/cvs Email: jbj@rpm5.org
> Module: rpm Date: 03-Dec-2007
> 00:06:03
> Branch: HEAD Handle: 2007120223060101
>
> Modified files:
> rpm CHANGES
> rpm/build parsePreamble.c
> rpm/rpmdb hdrfmt.c rpmtag.h tagname.c
> rpm/rpmio argv.c argv.h librpmio.vers
>
> Log:
> - using tagValue instead permits queries of arbitrary tags.
> - do binary, not linear, search for tag name/type/value.
> - lazy arbitrary tag array initialization in rpmTags methods
> instead.
>
> Summary:
> Revision Changes Path
> 1.1908 +3 -0 rpm/CHANGES
> 2.151 +4 -19 rpm/build/parsePreamble.c
> 1.48 +13 -3 rpm/rpmdb/hdrfmt.c
> 1.20 +8 -5 rpm/rpmdb/rpmtag.h
> 1.20 +45 -7 rpm/rpmdb/tagname.c
> 1.9 +7 -0 rpm/rpmio/argv.c
> 1.6 +10 -1 rpm/rpmio/argv.h
> 2.20 +1 -0 rpm/rpmio/librpmio.vers
>
> ______________________________________________________________________
> ______
>
> patch -p0 <<'@@ .'
> Index: rpm/CHANGES
>
> ======================================================================
> ======
> $ cvs diff -u -r1.1907 -r1.1908 CHANGES
> --- rpm/CHANGES 2 Dec 2007 20:51:49 -0000 1.1907
> +++ rpm/CHANGES 2 Dec 2007 23:06:01 -0000 1.1908
> @@ -1,6 +1,9 @@
> 5.0a4 -> 5.0b1:
>
> 5.0a3 -> 5.0a4:
> + - jbj: using tagValue instead permits queries of arbitrary
> tags.
> + - jbj: do binary, not linear, search for tag name/type/value.
> + - jbj: lazy arbitrary tag array initialization in rpmTags
> methods instead.
> - jbj: eliminate hard-wired static nameBuf for tag strings.
> - rse: provide RPM version in API via macros RPM_
> {VERSION,TIMESTAMP,VENDOR} and functions rpm_
> {version,timestamp,vendor}
> - jbj: pkgio: hdlist readers need RPMRC_NOTFOUND EOF indicator.
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/build/parsePreamble.c
>
> ======================================================================
> ======
> $ cvs diff -u -r2.150 -r2.151 parsePreamble.c
> --- rpm/build/parsePreamble.c 30 Nov 2007 04:51:30 -0000 2.150
> +++ rpm/build/parsePreamble.c 2 Dec 2007 23:06:01 -0000 2.151
> @@ -8,6 +8,7 @@
> #include <rpmio_internal.h>
>
> #define _RPMEVR_INTERNAL
> +#define _RPMTAG_INTERNAL /* XXX rpmTags->aTags */
> #include <rpmbuild.h>
> #include "debug.h"
>
> @@ -874,13 +875,6 @@
> /*@=nullassign@*/
> };
>
> -static int argvStrcasecmp(const void * a, const void * b)
> -{
> - ARGstr_t astr = *(ARGV_t)a;
> - ARGstr_t bstr = *(ARGV_t)b;
> - return xstrcasecmp(astr, bstr);
> -}
> -
> /**
> */
> /*@-boundswrite@*/
> @@ -909,20 +903,11 @@
>
> /* Search for arbitrary tags. */
> if (tagp && p->token == NULL) {
> - static ARGV_t aTags = NULL;
> - static int oneshot = 0;
> + ARGV_t aTags = NULL;
> int rc = 1; /* assume failure */
>
> - if (!oneshot) {
> - s = rpmExpand("%{?_arbitrary_tags}", NULL);
> - if (s && *s) {
> - (void) argvSplit(&aTags, s, ":");
> - if (aTags)
> - (void) argvSort(aTags, NULL);
> - }
> - s = _free(s);
> - oneshot++;
> - }
> + (void) tagName(0); /* XXX force arbitrary tags to be
> initialized. */
> + aTags = rpmTags->aTags;
> if (aTags != NULL && aTags[0] != NULL) {
> ARGV_t av;
> s = tagCanonicalize(spec->line);
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmdb/hdrfmt.c
>
> ======================================================================
> ======
> $ cvs diff -u -r1.47 -r1.48 hdrfmt.c
> --- rpm/rpmdb/hdrfmt.c 26 Nov 2007 21:05:57 -0000 1.47
> +++ rpm/rpmdb/hdrfmt.c 2 Dec 2007 23:06:02 -0000 1.48
> @@ -2047,7 +2047,6 @@
>
> /**
> * Return tag name from value.
> - * @todo bsearch on sorted value table.
> * @param tbl tag table
> * @param val tag value to find
> * @retval *typep tag type (or NULL)
> @@ -2058,10 +2057,18 @@
> /*@null@*/ uint32_t *typep)
> /*@modifies *typep @*/
> {
> - static char name[128];
> + static char name[128]; /* XXX Ick. */
> const char * s;
> char *t;
>
> + /* XXX Use bsearch on the "normal" rpmTagTable lookup. */
> + if (tbl == NULL || tbl == rpmTagTable) {
> + s = tagName(val);
> + if (s != NULL && typep != NULL)
> + *typep = tagType(val);
> + return s;
> + }
> +
> for (; tbl->name != NULL; tbl++) {
> if (tbl->val == val)
> break;
> @@ -2081,7 +2088,6 @@
>
> /**
> * Return tag value from name.
> - * @todo bsearch on sorted name table.
> * @param tbl tag table
> * @param name tag name to find
> * @return tag value, 0 on not found
> @@ -2089,6 +2095,10 @@
> static uint32_t myTagValue(headerTagTableEntry tbl, const char *
> name)
> /*@*/
> {
> + /* XXX Use bsearch on the "normal" rpmTagTable lookup. */
> + if (tbl == NULL || tbl == rpmTagTable)
> + return tagValue(name);
> +
> for (; tbl->name != NULL; tbl++) {
> if (!xstrcasecmp(tbl->name, name))
> return tbl->val;
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmdb/rpmtag.h
>
> ======================================================================
> ======
> $ cvs diff -u -r1.19 -r1.20 rpmtag.h
> --- rpm/rpmdb/rpmtag.h 29 Nov 2007 19:15:18 -0000 1.19
> +++ rpm/rpmdb/rpmtag.h 2 Dec 2007 23:06:02 -0000 1.20
> @@ -499,6 +499,7 @@
> */
> #if !defined(SWIG)
> struct headerTagIndices_s {
> +/*@relnull@*/
> int (*loadIndex) (headerTagTableEntry ** ipp, int * np,
> int (*cmp) (const void * avp, const void * bvp))
> /*@ modifies *ipp, *np */; /*!< Load sorted tag index. */
> @@ -508,23 +509,25 @@
> int (*byNameCmp) (const void * avp, const void * bvp)
> /*@*/; /*!< Compare entries by name. */
> rpmTag (*tagValue) (const char * name)
> - /*@*/; /* Return value from name. */
> + /*@*/; /*!< Return value from name. */
> /*@relnull@*/
> headerTagTableEntry * byValue; /*!< rpmTag's sorted by
> value. */
> int byValueSize; /*!< No. of entries. */
> int (*byValueCmp) (const void * avp, const void * bvp)
> /*@*/; /*!< Compare entries by value. */
> const char * (*tagName) (rpmTag value)
> - /*@*/; /* Return name from value. */
> + /*@*/; /*!< Return name from value. */
> rpmTag (*tagType) (rpmTag value)
> - /*@*/; /* Return type from value. */
> + /*@*/; /*!< Return type from value. */
> + size_t nameBufLen; /*!< No. bytes allocated for nameBuf. */
> + const char ** aTags; /*!< Arbitrary tags array (ARGV_t) */
> /*@owned@*/ /*@relnull@*/
> char * nameBuf; /* Name buffer. */
> /*@only@*/
> char * (*tagCanonicalize) (const char * s)
> - /*@*/; /* Canonicalize an arbitrary string. */
> + /*@*/; /*!< Canonicalize arbitrary string. */
> rpmTag (*tagGenerate) (const char * s)
> - /*@*/; /* Generate value from name. */
> + /*@*/; /*!< Generate tag from string. */
> };
> #endif
> #endif /* _RPMTAG_INTERNAL */
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmdb/tagname.c
>
> ======================================================================
> ======
> $ cvs diff -u -r1.19 -r1.20 tagname.c
> --- rpm/rpmdb/tagname.c 2 Dec 2007 20:51:49 -0000 1.19
> +++ rpm/rpmdb/tagname.c 2 Dec 2007 23:06:02 -0000 1.20
> @@ -5,6 +5,8 @@
> #include "system.h"
>
> #include <rpmio_internal.h> /* XXX DIGEST_CTX, xtolower,
> xstrcasecmp */
> +#include <rpmmacro.h>
> +#include <argv.h>
> #define _RPMTAG_INTERNAL
> #include <rpmtag.h>
> #include "debug.h"
> @@ -13,6 +15,33 @@
> /*@access headerTagIndices @*/
>
> /**
> + * Load/sort arbitrary tags.
> + * @retval *argvp arbitrary tag array
> + * @return 0 always
> + */
> +static int tagLoadATags(ARGV_t * argvp,
> + int (*cmp) (const void * avp, const void * bvp))
> + /*@modifies *ipp, *np @*/
> +{
> + ARGV_t aTags = NULL;
> + char * s = rpmExpand("%{?_arbitrary_tags}", NULL);
> +
> + if (s && *s)
> + (void) argvSplit(&aTags, s, ":");
> + else
> + aTags = xcalloc(1, sizeof(*aTags));
> + if (aTags && aTags[0])
> + (void) argvSort(aTags, cmp);
> + s = _free(s);
> +
> + if (argvp)
> + *argvp = aTags;
> + else
> + aTags = argvFree(aTags);
> + return 0;
> +}
> +
> +/**
> * Compare tag table entries by name.
> * @param *avp tag table entry a
> * @param *bvp tag table entry b
> @@ -56,7 +85,7 @@
> /*@modifies *ipp, *np @*/
> {
> headerTagTableEntry tte, *ip;
> - int n = 0;
> + size_t n = 0;
>
> ip = xcalloc(rpmTagTableSize, sizeof(*ip));
> n = 0;
> @@ -135,7 +164,7 @@
> tagLoadIndex,
> NULL, 0, tagCmpName, _tagValue,
> NULL, 0, tagCmpValue, _tagName, _tagType,
> - NULL, _tagCanonicalize, _tagGenerate
> + 256, NULL, NULL, _tagCanonicalize, _tagGenerate
> };
>
> /*@-compmempass@*/
> @@ -145,17 +174,21 @@
>
> static const char * _tagName(rpmTag tag)
> {
> - static size_t nameBufLen = 256;
> char * nameBuf;
> headerTagTableEntry t;
> int comparison, i, l, u;
> int xx;
> char *s;
>
> + if (_rpmTags.aTags == NULL)
> + xx = tagLoadATags(&_rpmTags.aTags, NULL);
> if (_rpmTags.byValue == NULL)
> - xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
> tagCmpValue);
> + xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
> + tagCmpValue);
> + if (_rpmTags.nameBufLen == 0)
> + _rpmTags.nameBufLen = 256;
> if (_rpmTags.nameBuf == NULL)
> - _rpmTags.nameBuf = xcalloc(1, nameBufLen);
> + _rpmTags.nameBuf = xcalloc(1, _rpmTags.nameBufLen);
> nameBuf = _rpmTags.nameBuf;
>
> switch (tag) {
> @@ -217,8 +250,8 @@
> }
> t = _rpmTags.byValue[i];
> s = (*_rpmTags.tagCanonicalize) (t->name);
> - strncpy(nameBuf, s, nameBufLen);
> - nameBuf[nameBufLen-1] = '\0';
> + strncpy(nameBuf, s, _rpmTags.nameBufLen);
> + nameBuf[_rpmTags.nameBufLen-1] = '\0';
> s = _free(s);
> /*@loopbreak@*/ break;
> }
> @@ -234,6 +267,8 @@
> int comparison, i, l, u;
> int xx;
>
> + if (_rpmTags.aTags == NULL)
> + xx = tagLoadATags(&_rpmTags.aTags, NULL);
> if (_rpmTags.byValue == NULL)
> xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize,
> tagCmpValue);
>
> @@ -302,6 +337,8 @@
> if (!xstrcasecmp(tagstr, "Ftswalk"))
> return RPMDBI_FTSWALK;
>
> + if (_rpmTags.aTags == NULL)
> + xx = tagLoadATags(&_rpmTags.aTags, NULL);
> if (_rpmTags.byName == NULL)
> xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize,
> tagCmpName);
> if (_rpmTags.byName == NULL)
> @@ -364,6 +401,7 @@
> _rpmTags->nameBuf = _free(_rpmTags->nameBuf);
> _rpmTags->byName = _free(_rpmTags->byName);
> _rpmTags->byValue = _free(_rpmTags->byValue);
> + _rpmTags->aTags = argvFree(_rpmTags->aTags);
> }
> }
>
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmio/argv.c
>
> ======================================================================
> ======
> $ cvs diff -u -r1.8 -r1.9 argv.c
> --- rpm/rpmio/argv.c 30 Nov 2007 04:51:30 -0000 1.8
> +++ rpm/rpmio/argv.c 2 Dec 2007 23:06:02 -0000 1.9
> @@ -86,6 +86,13 @@
> return strcmp(astr, bstr);
> }
>
> +int argvStrcasecmp(const void * a, const void * b)
> +{
> + ARGstr_t astr = *(ARGV_t)a;
> + ARGstr_t bstr = *(ARGV_t)b;
> + return xstrcasecmp(astr, bstr);
> +}
> +
> int argvSort(ARGV_t argv, int (*compar)(const void *, const void
> *))
> {
> if (compar == NULL)
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmio/argv.h
>
> ======================================================================
> ======
> $ cvs diff -u -r1.5 -r1.6 argv.h
> --- rpm/rpmio/argv.h 3 Nov 2007 23:44:04 -0000 1.5
> +++ rpm/rpmio/argv.h 2 Dec 2007 23:06:02 -0000 1.6
> @@ -83,7 +83,7 @@
> /*@*/;
>
> /**
> - * Compare argv arrays (qsort/bsearch).
> + * Compare argv arrays using strcmp (qsort/bsearch).
> * @param a 1st instance address
> * @param b 2nd instance address
> * @return result of comparison
> @@ -94,6 +94,15 @@
> /*@=exportlocal@*/
>
> /**
> + * Compare argv arrays using strcasecmp (qsort/bsearch).
> + * @param a 1st instance address
> + * @param b 2nd instance address
> + * @return result of comparison
> + */
> +int argvStrcasecmp(const void * a, const void * b)
> + /*@*/;
> +
> +/**
> * Sort an argv array.
> * @param argv argv array
> * @param compar strcmp-like comparison function, or NULL for
> argvCmp()
> @@ .
> patch -p0 <<'@@ .'
> Index: rpm/rpmio/librpmio.vers
>
> ======================================================================
> ======
> $ cvs diff -u -r2.19 -r2.20 librpmio.vers
> --- rpm/rpmio/librpmio.vers 22 Nov 2007 17:55:29 -0000 2.19
> +++ rpm/rpmio/librpmio.vers 2 Dec 2007 23:06:02 -0000 2.20
> @@ -20,6 +20,7 @@
> argvSearch;
> argvSort;
> argvSplit;
> + argvStrcasecmp;
> avClosedir;
> _av_debug;
> avmagicdir;
> @@ .
> ______________________________________________________________________
> RPM Package Manager http://rpm5.org
> CVS Sources Repository rpm-cvs@rpm5.org
Received on Mon Dec 3 00:38:08 2007