#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)
{
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;
/*
*/
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
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
*/
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