Update to 4.11.0.1
[platform/upstream/rpm.git] / lib / legacy.c
index 709a925..422c2b0 100644 (file)
@@ -4,17 +4,13 @@
 
 #include "system.h"
 
-#include <rpm/rpmlib.h>
+#include <rpm/header.h>
 #include <rpm/rpmmacro.h>
 #include <rpm/rpmstring.h>
 #include <rpm/rpmfi.h>
 #include <rpm/rpmds.h>
-#include "lib/legacy.h"
-#include "debug.h"
-
-#define alloca_strdup(_s)      strcpy(alloca(strlen(_s)+1), (_s))
 
-int _noDirTokens = 0;
+#include "debug.h"
 
 static int dncmp(const void * a, const void * b)
 {
@@ -23,19 +19,14 @@ static int dncmp(const void * a, const void * b)
     return strcmp(*first, *second);
 }
 
-void compressFilelist(Header h)
+static void compressFilelist(Header h)
 {
-    HGE_t hge = (HGE_t)headerGetEntryMinMemory;
-    HAE_t hae = (HAE_t)headerAddEntry;
-    HRE_t hre = (HRE_t)headerRemoveEntry;
-    HFD_t hfd = headerFreeData;
-    char ** fileNames;
-    const char ** dirNames;
+    struct rpmtd_s fileNames;
+    char ** dirNames;
     const char ** baseNames;
     uint32_t * dirIndexes;
-    rpm_tagtype_t fnt;
-    rpm_count_t count, i;
-    int xx;
+    rpm_count_t count;
+    int i;
     int dirIndex = -1;
 
     /*
@@ -45,48 +36,57 @@ void compressFilelist(Header h)
      */
 
     if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
-       xx = hre(h, RPMTAG_OLDFILENAMES);
+       headerDel(h, RPMTAG_OLDFILENAMES);
        return;         /* Already converted. */
     }
 
-    if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
-       return;         /* no file list */
-    if (fileNames == NULL || count <= 0)
+    if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM)) 
+       return;
+    count = rpmtdCount(&fileNames);
+    if (count < 1) 
        return;
 
-    dirNames = alloca(sizeof(*dirNames) * count);      /* worst case */
-    baseNames = alloca(sizeof(*dirNames) * count);
-    dirIndexes = alloca(sizeof(*dirIndexes) * count);
-
-    if (fileNames[0][0] != '/') {
-       /* HACK. Source RPM, so just do things differently */
-       dirIndex = 0;
-       dirNames[dirIndex] = "";
-       for (i = 0; i < count; i++) {
-           dirIndexes[i] = dirIndex;
-           baseNames[i] = fileNames[i];
+    dirNames = xmalloc(sizeof(*dirNames) * count);     /* worst case */
+    baseNames = xmalloc(sizeof(*dirNames) * count);
+    dirIndexes = xmalloc(sizeof(*dirIndexes) * count);
+
+    /* HACK. Source RPM, so just do things differently */
+    {  const char *fn = rpmtdGetString(&fileNames);
+       if (fn && *fn != '/') {
+           dirIndex = 0;
+           dirNames[dirIndex] = xstrdup("");
+           while ((i = rpmtdNext(&fileNames)) >= 0) {
+               dirIndexes[i] = dirIndex;
+               baseNames[i] = rpmtdGetString(&fileNames);
+           }
+           goto exit;
        }
-       goto exit;
     }
 
-    for (i = 0; i < count; i++) {
-       const char ** needle;
+    /* 
+     * XXX EVIL HACK, FIXME:
+     * This modifies (and then restores) a const string from rpmtd
+     * through basename retrieved from strrchr() which silently 
+     * casts away const on return.
+     */
+    while ((i = rpmtdNext(&fileNames)) >= 0) {
+       char ** needle;
        char savechar;
        char * baseName;
-       int len;
+       size_t len;
+       char *filename = (char *) rpmtdGetString(&fileNames); /* HACK HACK */
 
-       if (fileNames[i] == NULL)       /* XXX can't happen */
+       if (filename == NULL)   /* XXX can't happen */
            continue;
-       baseName = strrchr(fileNames[i], '/') + 1;
-       len = baseName - fileNames[i];
+       baseName = strrchr(filename, '/') + 1;
+       len = baseName - filename;
        needle = dirNames;
        savechar = *baseName;
        *baseName = '\0';
        if (dirIndex < 0 ||
-           (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
-           char *s = alloca(len + 1);
-           memcpy(s, fileNames[i], len + 1);
-           s[len] = '\0';
+           (needle = bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
+           char *s = xmalloc(len + 1);
+           rstrlcpy(s, filename, len + 1);
            dirIndexes[i] = ++dirIndex;
            dirNames[dirIndex] = s;
        } else
@@ -98,151 +98,101 @@ void compressFilelist(Header h)
 
 exit:
     if (count > 0) {
-       xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
-       xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
-                       baseNames, count);
-       xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
-                       dirNames, (rpm_count_t) dirIndex + 1);
+       headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
+       headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
+       headerPutStringArray(h, RPMTAG_DIRNAMES, 
+                            (const char **) dirNames, dirIndex + 1);
     }
 
-    fileNames = hfd(fileNames, fnt);
+    rpmtdFreeData(&fileNames);
+    for (i = 0; i <= dirIndex; i++) {
+       free(dirNames[i]);
+    }
+    free(dirNames);
+    free(baseNames);
+    free(dirIndexes);
 
-    xx = hre(h, RPMTAG_OLDFILENAMES);
+    headerDel(h, RPMTAG_OLDFILENAMES);
 }
 
-void expandFilelist(Header h)
+static void expandFilelist(Header h)
 {
-    HAE_t hae = (HAE_t)headerAddEntry;
-    HRE_t hre = (HRE_t)headerRemoveEntry;
-    const char ** fileNames = NULL;
-    rpm_count_t count = 0;
-    int xx;
+    struct rpmtd_s filenames;
 
     if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
-       rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
-       if (fileNames == NULL || count <= 0)
+       (void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT);
+       if (rpmtdCount(&filenames) < 1)
            return;
-       xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
-                       fileNames, count);
-       fileNames = _free(fileNames);
+       rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
+       headerPut(h, &filenames, HEADERPUT_DEFAULT);
+       rpmtdFreeData(&filenames);
     }
 
-    xx = hre(h, RPMTAG_DIRNAMES);
-    xx = hre(h, RPMTAG_BASENAMES);
-    xx = hre(h, RPMTAG_DIRINDEXES);
+    (void) headerDel(h, RPMTAG_DIRNAMES);
+    (void) headerDel(h, RPMTAG_BASENAMES);
+    (void) headerDel(h, RPMTAG_DIRINDEXES);
 }
 
 /*
  * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
  * Retrofit an explicit "Provides: name = epoch:version-release.
  */
-void providePackageNVR(Header h)
+static void providePackageNVR(Header h)
 {
-    HGE_t hge = (HGE_t)headerGetEntryMinMemory;
-    HFD_t hfd = headerFreeData;
-    const char *name, *version, *release;
-    int32_t * epoch;
-    const char *pEVR;
-    char *p;
-    int32_t pFlags = RPMSENSE_EQUAL;
-    const char ** provides = NULL;
-    const char ** providesEVR = NULL;
-    rpm_tagtype_t pnt, pvt;
-    int32_t * provideFlags = NULL;
-    rpm_count_t providesCount, i;
-    int xx;
+    const char *name = headerGetString(h, RPMTAG_NAME);
+    char *pEVR = headerGetAsString(h, RPMTAG_EVR);
+    rpmsenseFlags pFlags = RPMSENSE_EQUAL;
     int bingo = 1;
+    struct rpmtd_s pnames;
+    rpmds hds, nvrds;
 
     /* Generate provides for this package name-version-release. */
-    xx = headerNVR(h, &name, &version, &release);
-    if (!(name && version && release))
+    if (!(name && pEVR))
        return;
-    pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
-    *p = '\0';
-    if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
-       sprintf(p, "%d:", *epoch);
-       while (*p != '\0')
-           p++;
-    }
-    (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
 
     /*
      * Rpm prior to 3.0.3 does not have versioned provides.
      * If no provides at all are available, we can just add.
      */
-    if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
+    if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) {
        goto exit;
+    }
 
     /*
      * Otherwise, fill in entries on legacy packages.
      */
-    if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
-       for (i = 0; i < providesCount; i++) {
-           char * vdummy = "";
-           int32_t fdummy = RPMSENSE_ANY;
-           xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
-                       &vdummy, 1);
-           xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
-                       &fdummy, 1);
+    if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) {
+       while (rpmtdNext(&pnames) >= 0) {
+           rpmsenseFlags fdummy = RPMSENSE_ANY;
+
+           headerPutString(h, RPMTAG_PROVIDEVERSION, "");
+           headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
        }
        goto exit;
     }
 
-    xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
-
-       /* LCL: providesEVR is not NULL */
-    if (provides && providesEVR && provideFlags)
-    for (i = 0; i < providesCount; i++) {
-        if (!(provides[i] && providesEVR[i]))
-            continue;
-       if (!(provideFlags[i] == RPMSENSE_EQUAL &&
-           !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
-           continue;
+    /* see if we already have this provide */
+    hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
+    nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags);
+    if (rpmdsFind(hds, nvrds) >= 0) {
        bingo = 0;
-       break;
     }
+    rpmdsFree(hds);
+    rpmdsFree(nvrds);
+    
 
 exit:
-    provides = hfd(provides, pnt);
-    providesEVR = hfd(providesEVR, pvt);
-
     if (bingo) {
-       xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
-               &name, 1);
-       xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
-               &pFlags, 1);
-       xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
-               &pEVR, 1);
+       headerPutString(h, RPMTAG_PROVIDENAME, name);
+       headerPutString(h, RPMTAG_PROVIDEVERSION, pEVR);
+       headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pFlags, 1);
     }
+    rpmtdFreeData(&pnames);
+    free(pEVR);
 }
 
-void legacyRetrofit(Header h)
+static void legacyRetrofit(Header h)
 {
-    const char * prefix;
-
-    /*
-     * We don't use these entries (and rpm >= 2 never has) and they are
-     * pretty misleading. Let's just get rid of them so they don't confuse
-     * anyone.
-     */
-    if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
-       (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
-    if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
-       (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
-
-    /*
-     * We switched the way we do relocatable packages. We fix some of
-     * it up here, though the install code still has to be a bit 
-     * careful. This fixup makes queries give the new values though,
-     * which is quite handy.
-     */
-    if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &prefix, NULL))
-    {
-       const char * nprefix = stripTrailingChar(alloca_strdup(prefix), '/');
-       (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
-               &nprefix, 1); 
-    }
-
     /*
      * The file list was moved to a more compressed format which not
      * only saves memory (nice), but gives fingerprinting a nice, fat
@@ -251,14 +201,179 @@ void legacyRetrofit(Header h)
      */
      compressFilelist(h);
 
-    /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
-    if (headerIsSource(h)) {
-       int32_t one = 1;
-       if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
-           (void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
-                               &one, 1);
-    } else {
-       /* Retrofit "Provide: name = EVR" for binary packages. */
+    /* Retrofit "Provide: name = EVR" for binary packages. */
+    if (!headerIsSource(h)) {
        providePackageNVR(h);
     }
 }
+
+int headerConvert(Header h, int op)
+{
+    int rc = 1;
+
+    if (h == NULL)
+       return 0;
+
+    switch (op) {
+    case HEADERCONV_EXPANDFILELIST:
+       expandFilelist(h);
+       break;
+    case HEADERCONV_COMPRESSFILELIST:
+       compressFilelist(h);
+       break;
+    case HEADERCONV_RETROFIT_V3:
+       legacyRetrofit(h);
+       break;
+    default:
+       rc = 0;
+       break;
+    }
+    return rc;
+};
+
+/*
+ * Backwards compatibility wrappers for legacy interfaces.
+ * Remove these some day...
+ */
+#define _RPM_4_4_COMPAT
+#include <rpm/rpmlegacy.h>
+
+/* dumb macro to avoid 50 copies of this code while converting... */
+#define TDWRAP() \
+    if (type) \
+       *type = td.type; \
+    if (p) \
+       *p = td.data; \
+    else \
+       rpmtdFreeData(&td); \
+    if (c) \
+       *c = td.count
+
+int headerRemoveEntry(Header h, rpm_tag_t tag)
+{
+    return headerDel(h, tag);
+}
+
+static void *_headerFreeData(rpm_data_t data, rpm_tagtype_t type)
+{
+    if (data) {
+       if (type == RPM_FORCEFREE_TYPE ||
+           type == RPM_STRING_ARRAY_TYPE ||
+           type == RPM_I18NSTRING_TYPE ||
+           type == RPM_BIN_TYPE)
+               free(data);
+    }
+    return NULL;
+}
+
+void * headerFreeData(rpm_data_t data, rpm_tagtype_t type)
+{
+    return _headerFreeData(data, type);
+}
+
+void * headerFreeTag(Header h, rpm_data_t data, rpm_tagtype_t type)
+{
+    return _headerFreeData(data, type);
+}
+
+static int headerGetWrap(Header h, rpm_tag_t tag,
+               rpm_tagtype_t * type,
+               rpm_data_t * p,
+               rpm_count_t * c,
+               headerGetFlags flags)
+{
+    struct rpmtd_s td;
+    int rc;
+
+    rc = headerGet(h, tag, &td, flags);
+    TDWRAP();
+    return rc;
+}
+
+int headerGetEntry(Header h, rpm_tag_t tag,
+                       rpm_tagtype_t * type,
+                       rpm_data_t * p,
+                       rpm_count_t * c)
+{
+    return headerGetWrap(h, tag, type, p, c, HEADERGET_DEFAULT);
+}
+
+int headerGetEntryMinMemory(Header h, rpm_tag_t tag,
+                       rpm_tagtype_t * type,
+                       rpm_data_t * p,
+                       rpm_count_t * c)
+{
+    return headerGetWrap(h, tag, type, (rpm_data_t) p, c, HEADERGET_MINMEM);
+}
+
+/* XXX shut up compiler warning from missing prototype */
+int headerGetRawEntry(Header h, rpm_tag_t tag, rpm_tagtype_t * type, rpm_data_t * p,
+               rpm_count_t * c);
+
+int headerGetRawEntry(Header h, rpm_tag_t tag, rpm_tagtype_t * type, rpm_data_t * p,
+               rpm_count_t * c)
+{
+    if (p == NULL) 
+       return headerIsEntry(h, tag);
+
+    return headerGetWrap(h, tag, type, p, c, HEADERGET_RAW);
+}
+
+int headerNextIterator(HeaderIterator hi,
+               rpm_tag_t * tag,
+               rpm_tagtype_t * type,
+               rpm_data_t * p,
+               rpm_count_t * c)
+{
+    struct rpmtd_s td;
+    int rc;
+
+    rc = headerNext(hi, &td);
+    if (tag)
+       *tag = td.tag;
+    TDWRAP();
+    return rc;
+}
+
+int headerModifyEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
+                       rpm_constdata_t p, rpm_count_t c)
+{
+    struct rpmtd_s td = {
+       .tag = tag,
+       .type = type,
+       .data = (void *) p,
+       .count = c,
+    };
+    return headerMod(h, &td);
+}
+
+static int headerPutWrap(Header h, rpm_tag_t tag, rpm_tagtype_t type,
+               rpm_constdata_t p, rpm_count_t c, headerPutFlags flags)
+{
+    struct rpmtd_s td = {
+       .tag = tag,
+       .type = type,
+       .data = (void *) p,
+       .count = c,
+    };
+    return headerPut(h, &td, flags);
+}
+
+int headerAddOrAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
+               rpm_constdata_t p, rpm_count_t c)
+{
+    return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
+}
+
+int headerAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
+               rpm_constdata_t p, rpm_count_t c)
+{
+    return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
+}
+
+int headerAddEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
+               rpm_constdata_t p, rpm_count_t c)
+{
+    return headerPutWrap(h, tag, type, p, c, HEADERPUT_DEFAULT);
+}
+#undef _RPM_4_4_COMPAT