[Rpm-maint] [PATCH] Add API to add arbitrary tags to headers saved to rpmdb

Jeff Johnson n3npq at me.com
Fri Apr 13 14:42:58 UTC 2018



> On Apr 13, 2018, at 3:49 AM, Aleksei Nikiforov <darktemplar at altlinux.org> wrote:
> 
> ---
> lib/depends.c        | 23 +++++++++++++++++------
> lib/rpmte.c          | 28 +++++++++++++++++++++++++---
> lib/rpmte_internal.h |  3 ++-
> lib/rpmts.h          | 30 ++++++++++++++++++++++++++++++
> lib/verify.c         |  2 +-
> 5 files changed, 75 insertions(+), 11 deletions(-)
> 

So instead of just a single char value saved and added, you are using a header as a tag bag to be appended. I suppose that is progress, but it's all kinda gross overkill for tags that rpm itself neither needs nor uses.

Instead of drilling an additional argument throughout the rpmte API, the 2 new top level *WithTags() routines can just do the headerLink() into the rpmte object.

> diff --git a/lib/depends.c b/lib/depends.c
> index fc413a9..60282d0 100644
> --- a/lib/depends.c
> +++ b/lib/depends.c
> @@ -123,7 +123,7 @@ static int removePackage(rpmts ts, Header h, rpmte depends)
>    return 0;
>     }
> 
> -    p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL);
> +    p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, NULL);
>     if (p == NULL)
>    return 1;
> 
> @@ -410,7 +410,7 @@ rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types)
> }
> 
> static int addPackage(rpmts ts, Header h,
> -            fnpyKey key, int op, rpmRelocation * relocs)
> +            fnpyKey key, int op, rpmRelocation * relocs, Header tags)
> {
>     tsMembers tsmem = rpmtsMembers(ts);
>     rpm_color_t tscolor = rpmtsColor(ts);
> @@ -435,7 +435,7 @@ static int addPackage(rpmts ts, Header h,
>        goto exit;
>     }
> 
> -    p = rpmteNew(ts, h, TR_ADDED, key, relocs);
> +    p = rpmteNew(ts, h, TR_ADDED, key, relocs, tags);
>     if (p == NULL) {
>    ec = 1;
>    goto exit;
> @@ -487,19 +487,30 @@ exit:
> int rpmtsAddInstallElement(rpmts ts, Header h,
>            fnpyKey key, int upgrade, rpmRelocation * relocs)
> {
> +    return rpmtsAddInstallElementWithTags(ts, h, key, upgrade, relocs, NULL);
> +}
> +
> +int rpmtsAddReinstallElement(rpmts ts, Header h, fnpyKey key)
> +{
> +    return rpmtsAddReinstallElementWithTags(ts, h, key, NULL);
> +}
> +
> +int rpmtsAddInstallElementWithTags(rpmts ts, Header h,
> +    fnpyKey key, int upgrade, rpmRelocation * relocs, Header tags)
> +{
>     int op = (upgrade == 0) ? RPMTE_INSTALL : RPMTE_UPGRADE;
>     if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL)
>    return 1;
> -    return addPackage(ts, h, key, op, relocs);
> +    return addPackage(ts, h, key, op, relocs, tags);
> }
> 
> -int rpmtsAddReinstallElement(rpmts ts, Header h, fnpyKey key)
> +int rpmtsAddReinstallElementWithTags(rpmts ts, Header h, fnpyKey key, Header tags)
> {
>     if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL)
>    return 1;
>     /* TODO: pull relocations from installed package */
>     /* TODO: should reinstall of non-installed package fail? */
> -    return addPackage(ts, h, key, RPMTE_REINSTALL, NULL);
> +    return addPackage(ts, h, key, RPMTE_REINSTALL, NULL, tags);
> }
> 
> int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset)
> diff --git a/lib/rpmte.c b/lib/rpmte.c
> index f05c2e2..3ed9f48 100644
> --- a/lib/rpmte.c
> +++ b/lib/rpmte.c
> @@ -77,6 +77,8 @@ struct rpmte_s {
>     int transscripts;        /*!< pre/posttrans script existence */
>     int failed;            /*!< (parent) install/erase failed */
> 
> +    Header extra_tags;        /*! extra tags to be saved */
> +
>     rpmfs fs;
> };
> 
> @@ -122,8 +124,9 @@ static rpmfiles getFiles(rpmte p, Header h)
>  * @param h        header
>  * @param key        (TR_ADDED) package retrieval key (e.g. file name)
>  * @param relocs    (TR_ADDED) package file relocations
> + * @param tags        additional tags to be saved
>  */
> -static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
> +static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs, Header tags)
> {
>     rpmstrPool tspool = rpmtsPool(p->ts);
>     struct rpmtd_s bnames;
> @@ -197,6 +200,8 @@ static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
>     if (p->type == TR_ADDED)
>    p->pkgFileSize = headerGetNumber(h, RPMTAG_LONGSIGSIZE) + 96 + 256;
> 
> +    p->extra_tags = headerLink(tags);
> +
>     rc = 0;
> 
> exit:
> @@ -224,6 +229,7 @@ rpmte rpmteFree(rpmte te)
>    free(te->NEVR);
>    free(te->NEVRA);
> 
> +    headerFree(te->extra_tags);
>    fdFree(te->fd);
>    rpmfiFree(te->fi);
>    rpmfilesFree(te->files);
> @@ -239,13 +245,13 @@ rpmte rpmteFree(rpmte te)
> }
> 
> rpmte rpmteNew(rpmts ts, Header h, rpmElementType type, fnpyKey key,
> -           rpmRelocation * relocs)
> +           rpmRelocation * relocs, Header tags)
> {
>     rpmte p = xcalloc(1, sizeof(*p));
>     p->ts = ts;
>     p->type = type;
> 
> -    if (addTE(p, h, key, relocs)) {
> +    if (addTE(p, h, key, relocs, tags)) {
>    rpmteFree(p);
>    return NULL;
>     }
> @@ -564,6 +570,9 @@ static int rpmteOpen(rpmte te, int reload_fi)
> {
>     int rc = 0; /* assume failure */
>     Header h = NULL;
> +    HeaderIterator h_iter;
> +    struct rpmtd_s td;
> +
>     if (te == NULL || te->ts == NULL || rpmteFailed(te))
>    goto exit;
> 
> @@ -586,6 +595,19 @@ static int rpmteOpen(rpmte te, int reload_fi)
>        rc = 1;
>    }
>    
> +    if (te->extra_tags != NULL)
> +    {
> +        h_iter = headerInitIterator(te->extra_tags);
> +
> +        while (headerNext(h_iter, &td))
> +        {
> +            headerPut(h, &td, HEADERPUT_DEFAULT);
> +            rpmtdFreeData(&td);
> +        }

There need to be (at least) checks on type and tagno, as well as limiting the merge so that existing tags are not just blindly replaced.

Headers with immutable regions are more complicated than "tag bags".

> +
> +        headerFreeIterator(h_iter);
> +    }
> +
>    rpmteSetHeader(te, h);
>    headerFree(h);
>     }
> diff --git a/lib/rpmte_internal.h b/lib/rpmte_internal.h
> index 464f476..14bc612 100644
> --- a/lib/rpmte_internal.h
> +++ b/lib/rpmte_internal.h
> @@ -34,11 +34,12 @@ extern "C" {
>  * @param type        TR_ADDED/TR_REMOVED
>  * @param key        (TR_ADDED) package retrieval key (e.g. file name)
>  * @param relocs    (TR_ADDED) package file relocations
> + * @param tags        additional tags to be saved
>  * @return        new transaction element
>  */
> RPM_GNUC_INTERNAL
> rpmte rpmteNew(rpmts ts, Header h, rpmElementType type, fnpyKey key,
> -           rpmRelocation * relocs);
> +           rpmRelocation * relocs, Header tags);
> 

Why does rpmteNew need to have an added argument?

> /** \ingroup rpmte
>  * Destroy a transaction element.
> diff --git a/lib/rpmts.h b/lib/rpmts.h
> index 5231c80..3836f84 100644
> --- a/lib/rpmts.h
> +++ b/lib/rpmts.h
> @@ -572,6 +572,36 @@ int rpmtsAddInstallElement(rpmts ts, Header h,
> int rpmtsAddReinstallElement(rpmts ts, Header h, const fnpyKey key);
> 
> /** \ingroup rpmts
> + * Add package to be installed to transaction set.
> + *
> + * The transaction set is checked for duplicate package names.
> + * If found, the package with the "newest" EVR will be replaced.
> + *
> + * @param ts        transaction set
> + * @param h        header
> + * @param key        package retrieval key (e.g. file name)
> + * @param upgrade    is package being upgraded?
> + * @param relocs    package file relocations
> + * @param tags        additional tags to be saved
> + * @return        0 on success, 1 on I/O error, 2 needs capabilities
> + */
> +int rpmtsAddInstallElementWithTags(rpmts ts, Header h,
> +        const fnpyKey key, int upgrade,
> +        rpmRelocation * relocs,
> +        Header tags);
> +
> +/** \ingroup rpmts
> + * Add package to be reinstalled to transaction set.
> + *
> + * @param ts        transaction set
> + * @param h        header
> + * @param key        package retrieval key (e.g. file name)
> + * @param tags        additional tags to be saved
> + * @return        0 on success
> + */
> +int rpmtsAddReinstallElementWithTags(rpmts ts, Header h, const fnpyKey key, Header tags);
> +
> +/** \ingroup rpmts
>  * Add package to be erased to transaction set.
>  * @param ts        transaction set
>  * @param h        header
> diff --git a/lib/verify.c b/lib/verify.c
> index 1a8ce8d..83f1106 100644
> --- a/lib/verify.c
> +++ b/lib/verify.c
> @@ -297,7 +297,7 @@ static int rpmVerifyScript(rpmts ts, Header h)
> 
>     if (headerIsEntry(h, RPMTAG_VERIFYSCRIPT)) {
>    /* fake up a erasure transaction element */
> -    rpmte p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL);
> +    rpmte p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, NULL);
> 
>    if (p != NULL) {
>        rpmteSetHeader(p, h);
> -- 

Changing verify.c is rather pointless here.

Write some test cases if you wish to see this interface added.

You will quickly find that:
1) only CHAR typed tags are going to "work".
2) attempts to replace existing tags in the immutable region are likely going to have unusual behaviors.

Hth

73 de Jeff
> 2.10.5
> 
> _______________________________________________
> Rpm-maint mailing list
> Rpm-maint at lists.rpm.org
> http://lists.rpm.org/mailman/listinfo/rpm-maint


More information about the Rpm-maint mailing list