2001-10-22 05:43:32 +08:00
|
|
|
/**
|
2007-12-04 00:39:56 +08:00
|
|
|
* \file lib/legacy.c
|
2001-10-22 05:43:32 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "system.h"
|
2002-06-20 10:19:21 +08:00
|
|
|
|
2008-02-03 22:24:07 +08:00
|
|
|
#include <rpm/header.h>
|
2007-12-08 20:02:32 +08:00
|
|
|
#include <rpm/rpmmacro.h>
|
|
|
|
#include <rpm/rpmstring.h>
|
|
|
|
#include <rpm/rpmfi.h>
|
|
|
|
#include <rpm/rpmds.h>
|
2008-01-30 23:05:29 +08:00
|
|
|
|
2007-11-27 17:34:23 +08:00
|
|
|
#include "lib/legacy.h"
|
2008-01-30 23:05:29 +08:00
|
|
|
|
2001-10-22 05:43:32 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
2001-10-25 09:36:32 +08:00
|
|
|
#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
|
|
|
|
|
2001-10-22 05:43:32 +08:00
|
|
|
int _noDirTokens = 0;
|
|
|
|
|
|
|
|
static int dncmp(const void * a, const void * b)
|
|
|
|
{
|
|
|
|
const char *const * first = a;
|
|
|
|
const char *const * second = b;
|
|
|
|
return strcmp(*first, *second);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
const char ** baseNames;
|
2007-10-26 19:24:14 +08:00
|
|
|
uint32_t * dirIndexes;
|
2008-02-05 22:14:34 +08:00
|
|
|
rpmTagType fnt;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t count, i;
|
|
|
|
int xx;
|
2001-10-22 05:43:32 +08:00
|
|
|
int dirIndex = -1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This assumes the file list is already sorted, and begins with a
|
|
|
|
* single '/'. That assumption isn't critical, but it makes things go
|
|
|
|
* a bit faster.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
|
|
|
|
xx = hre(h, RPMTAG_OLDFILENAMES);
|
|
|
|
return; /* Already converted. */
|
|
|
|
}
|
|
|
|
|
2007-12-19 18:05:56 +08:00
|
|
|
if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (rpm_data_t *) &fileNames, &count))
|
2001-10-22 05:43:32 +08:00
|
|
|
return; /* no file list */
|
|
|
|
if (fileNames == NULL || count <= 0)
|
|
|
|
return;
|
|
|
|
|
2008-01-02 22:18:55 +08:00
|
|
|
dirNames = xmalloc(sizeof(*dirNames) * count); /* worst case */
|
|
|
|
baseNames = xmalloc(sizeof(*dirNames) * count);
|
|
|
|
dirIndexes = xmalloc(sizeof(*dirIndexes) * count);
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
const char ** needle;
|
|
|
|
char savechar;
|
|
|
|
char * baseName;
|
2008-01-02 19:55:16 +08:00
|
|
|
size_t len;
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
if (fileNames[i] == NULL) /* XXX can't happen */
|
|
|
|
continue;
|
|
|
|
baseName = strrchr(fileNames[i], '/') + 1;
|
|
|
|
len = baseName - fileNames[i];
|
|
|
|
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';
|
|
|
|
dirIndexes[i] = ++dirIndex;
|
|
|
|
dirNames[dirIndex] = s;
|
|
|
|
} else
|
|
|
|
dirIndexes[i] = needle - dirNames;
|
|
|
|
|
|
|
|
*baseName = savechar;
|
|
|
|
baseNames[i] = baseName;
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2007-12-14 00:16:39 +08:00
|
|
|
dirNames, (rpm_count_t) dirIndex + 1);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
fileNames = hfd(fileNames, fnt);
|
2008-01-02 22:18:55 +08:00
|
|
|
free(dirNames);
|
|
|
|
free(baseNames);
|
|
|
|
free(dirIndexes);
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
xx = hre(h, RPMTAG_OLDFILENAMES);
|
|
|
|
}
|
|
|
|
|
|
|
|
void expandFilelist(Header h)
|
|
|
|
{
|
|
|
|
HAE_t hae = (HAE_t)headerAddEntry;
|
|
|
|
HRE_t hre = (HRE_t)headerRemoveEntry;
|
|
|
|
const char ** fileNames = NULL;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t count = 0;
|
2001-10-22 05:43:32 +08:00
|
|
|
int xx;
|
|
|
|
|
|
|
|
if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
|
2002-12-19 06:54:00 +08:00
|
|
|
rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
|
2001-10-22 05:43:32 +08:00
|
|
|
if (fileNames == NULL || count <= 0)
|
|
|
|
return;
|
|
|
|
xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
|
|
|
|
fileNames, count);
|
|
|
|
fileNames = _free(fileNames);
|
|
|
|
}
|
|
|
|
|
|
|
|
xx = hre(h, RPMTAG_DIRNAMES);
|
|
|
|
xx = hre(h, RPMTAG_BASENAMES);
|
|
|
|
xx = hre(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)
|
|
|
|
{
|
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
|
|
HFD_t hfd = headerFreeData;
|
2008-04-09 15:37:34 +08:00
|
|
|
const char *name;
|
|
|
|
char *pEVR;
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags pFlags = RPMSENSE_EQUAL;
|
2001-10-22 05:43:32 +08:00
|
|
|
const char ** provides = NULL;
|
|
|
|
const char ** providesEVR = NULL;
|
2008-02-05 22:14:34 +08:00
|
|
|
rpmTagType pnt, pvt;
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags * provideFlags = NULL;
|
2007-12-13 15:25:10 +08:00
|
|
|
rpm_count_t providesCount, i;
|
|
|
|
int xx;
|
2001-10-22 05:43:32 +08:00
|
|
|
int bingo = 1;
|
|
|
|
|
|
|
|
/* Generate provides for this package name-version-release. */
|
2008-04-09 15:37:34 +08:00
|
|
|
pEVR = headerGetEVR(h, &name);
|
|
|
|
if (!(name && pEVR))
|
2001-10-22 05:43:32 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rpm prior to 3.0.3 does not have versioned provides.
|
|
|
|
* If no provides at all are available, we can just add.
|
|
|
|
*/
|
2007-12-19 18:05:56 +08:00
|
|
|
if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (rpm_data_t *) &provides, &providesCount))
|
2001-10-22 05:43:32 +08:00
|
|
|
goto exit;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, fill in entries on legacy packages.
|
|
|
|
*/
|
2007-12-19 18:05:56 +08:00
|
|
|
if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (rpm_data_t *) &providesEVR, NULL)) {
|
2001-10-22 05:43:32 +08:00
|
|
|
for (i = 0; i < providesCount; i++) {
|
2007-12-14 21:17:59 +08:00
|
|
|
const char * vdummy = "";
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags fdummy = RPMSENSE_ANY;
|
2001-10-22 05:43:32 +08:00
|
|
|
xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
|
|
|
|
&vdummy, 1);
|
|
|
|
xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
|
|
|
|
&fdummy, 1);
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2007-12-19 18:05:56 +08:00
|
|
|
xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (rpm_data_t *) &provideFlags, NULL);
|
2001-10-22 05:43:32 +08:00
|
|
|
|
2007-09-12 00:37:03 +08:00
|
|
|
/* LCL: providesEVR is not NULL */
|
2001-10-22 05:43:32 +08:00
|
|
|
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;
|
|
|
|
bingo = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2008-04-09 15:37:34 +08:00
|
|
|
free(pEVR);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
2001-10-25 09:36:32 +08:00
|
|
|
|
2007-11-07 19:21:06 +08:00
|
|
|
void legacyRetrofit(Header h)
|
2001-10-25 09:36:32 +08:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
|
|
|
|
/*
|
2003-12-30 21:14:49 +08:00
|
|
|
* We switched the way we do relocatable packages. We fix some of
|
2001-10-25 09:36:32 +08:00
|
|
|
* 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.
|
|
|
|
*/
|
2007-12-19 18:05:56 +08:00
|
|
|
if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (rpm_data_t *) &prefix, NULL))
|
2001-10-25 09:36:32 +08:00
|
|
|
{
|
|
|
|
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
|
|
|
|
* speed boost (very nice). Go ahead and convert old headers to
|
|
|
|
* the new style (this is a noop for new headers).
|
|
|
|
*/
|
2007-11-07 19:21:06 +08:00
|
|
|
compressFilelist(h);
|
2001-10-25 09:36:32 +08:00
|
|
|
|
|
|
|
/* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
|
2007-12-02 01:29:57 +08:00
|
|
|
if (headerIsSource(h)) {
|
2007-10-26 19:24:14 +08:00
|
|
|
int32_t one = 1;
|
2001-10-25 09:36:32 +08:00
|
|
|
if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
|
|
|
|
(void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
|
|
|
|
&one, 1);
|
2007-11-07 19:21:06 +08:00
|
|
|
} else {
|
2001-10-25 09:36:32 +08:00
|
|
|
/* Retrofit "Provide: name = EVR" for binary packages. */
|
|
|
|
providePackageNVR(h);
|
|
|
|
}
|
|
|
|
}
|