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
|
|
|
|
2001-10-22 05:43:32 +08:00
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
static int dncmp(const void * a, const void * b)
|
|
|
|
{
|
|
|
|
const char *const * first = a;
|
|
|
|
const char *const * second = b;
|
|
|
|
return strcmp(*first, *second);
|
|
|
|
}
|
|
|
|
|
2008-10-10 20:59:38 +08:00
|
|
|
static void compressFilelist(Header h)
|
2001-10-22 05:43:32 +08:00
|
|
|
{
|
2008-05-26 16:42:57 +08:00
|
|
|
struct rpmtd_s fileNames;
|
2008-04-29 20:08:47 +08:00
|
|
|
char ** dirNames;
|
2001-10-22 05:43:32 +08:00
|
|
|
const char ** baseNames;
|
2007-10-26 19:24:14 +08:00
|
|
|
uint32_t * dirIndexes;
|
2008-05-26 16:42:57 +08:00
|
|
|
rpm_count_t count;
|
2011-03-04 18:45:06 +08:00
|
|
|
int i;
|
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)) {
|
2011-03-04 18:45:06 +08:00
|
|
|
headerDel(h, RPMTAG_OLDFILENAMES);
|
2001-10-22 05:43:32 +08:00
|
|
|
return; /* Already converted. */
|
|
|
|
}
|
|
|
|
|
2008-05-26 16:42:57 +08:00
|
|
|
if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM))
|
|
|
|
return;
|
|
|
|
count = rpmtdCount(&fileNames);
|
|
|
|
if (count < 1)
|
2001-10-22 05:43:32 +08:00
|
|
|
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
|
|
|
|
2008-06-26 18:59:06 +08:00
|
|
|
/* 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;
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-21 18:29:01 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2008-05-26 16:42:57 +08:00
|
|
|
while ((i = rpmtdNext(&fileNames)) >= 0) {
|
2008-04-29 20:08:47 +08:00
|
|
|
char ** needle;
|
2001-10-22 05:43:32 +08:00
|
|
|
char savechar;
|
|
|
|
char * baseName;
|
2008-01-02 19:55:16 +08:00
|
|
|
size_t len;
|
2010-09-21 18:29:01 +08:00
|
|
|
char *filename = (char *) rpmtdGetString(&fileNames); /* HACK HACK */
|
2001-10-22 05:43:32 +08:00
|
|
|
|
2008-05-26 16:42:57 +08:00
|
|
|
if (filename == NULL) /* XXX can't happen */
|
2001-10-22 05:43:32 +08:00
|
|
|
continue;
|
2008-05-26 16:42:57 +08:00
|
|
|
baseName = strrchr(filename, '/') + 1;
|
|
|
|
len = baseName - filename;
|
2001-10-22 05:43:32 +08:00
|
|
|
needle = dirNames;
|
|
|
|
savechar = *baseName;
|
|
|
|
*baseName = '\0';
|
|
|
|
if (dirIndex < 0 ||
|
2008-06-26 18:59:06 +08:00
|
|
|
(needle = bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
|
2008-04-29 20:08:47 +08:00
|
|
|
char *s = xmalloc(len + 1);
|
2008-05-26 16:42:57 +08:00
|
|
|
rstrlcpy(s, filename, len + 1);
|
2001-10-22 05:43:32 +08:00
|
|
|
dirIndexes[i] = ++dirIndex;
|
|
|
|
dirNames[dirIndex] = s;
|
|
|
|
} else
|
|
|
|
dirIndexes[i] = needle - dirNames;
|
|
|
|
|
|
|
|
*baseName = savechar;
|
|
|
|
baseNames[i] = baseName;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (count > 0) {
|
2008-06-19 20:48:31 +08:00
|
|
|
headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
|
|
|
|
headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
|
|
|
|
headerPutStringArray(h, RPMTAG_DIRNAMES,
|
|
|
|
(const char **) dirNames, dirIndex + 1);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
|
2008-05-26 16:42:57 +08:00
|
|
|
rpmtdFreeData(&fileNames);
|
2008-04-29 20:08:47 +08:00
|
|
|
for (i = 0; i <= dirIndex; i++) {
|
|
|
|
free(dirNames[i]);
|
|
|
|
}
|
2008-01-02 22:18:55 +08:00
|
|
|
free(dirNames);
|
|
|
|
free(baseNames);
|
|
|
|
free(dirIndexes);
|
2001-10-22 05:43:32 +08:00
|
|
|
|
2011-03-04 18:45:06 +08:00
|
|
|
headerDel(h, RPMTAG_OLDFILENAMES);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
|
2008-10-10 20:59:38 +08:00
|
|
|
static void expandFilelist(Header h)
|
2001-10-22 05:43:32 +08:00
|
|
|
{
|
2008-05-26 16:13:30 +08:00
|
|
|
struct rpmtd_s filenames;
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
|
2008-05-26 16:13:30 +08:00
|
|
|
(void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT);
|
|
|
|
if (rpmtdCount(&filenames) < 1)
|
2001-10-22 05:43:32 +08:00
|
|
|
return;
|
2008-05-26 16:13:30 +08:00
|
|
|
rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
|
|
|
|
headerPut(h, &filenames, HEADERPUT_DEFAULT);
|
|
|
|
rpmtdFreeData(&filenames);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
|
2008-06-17 14:07:37 +08:00
|
|
|
(void) headerDel(h, RPMTAG_DIRNAMES);
|
|
|
|
(void) headerDel(h, RPMTAG_BASENAMES);
|
|
|
|
(void) headerDel(h, RPMTAG_DIRINDEXES);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
|
|
|
|
* Retrofit an explicit "Provides: name = epoch:version-release.
|
|
|
|
*/
|
2008-04-10 21:07:47 +08:00
|
|
|
static void providePackageNVR(Header h)
|
2001-10-22 05:43:32 +08:00
|
|
|
{
|
2009-09-02 17:06:34 +08:00
|
|
|
const char *name = headerGetString(h, RPMTAG_NAME);
|
|
|
|
char *pEVR = headerGetAsString(h, RPMTAG_EVR);
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags pFlags = RPMSENSE_EQUAL;
|
2001-10-22 05:43:32 +08:00
|
|
|
int bingo = 1;
|
2008-06-13 17:23:46 +08:00
|
|
|
struct rpmtd_s pnames;
|
|
|
|
rpmds hds, nvrds;
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
/* Generate provides for this package name-version-release. */
|
2008-04-09 15:37:34 +08:00
|
|
|
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.
|
|
|
|
*/
|
2008-06-13 17:23:46 +08:00
|
|
|
if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) {
|
2001-10-22 05:43:32 +08:00
|
|
|
goto exit;
|
2008-06-13 17:23:46 +08:00
|
|
|
}
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, fill in entries on legacy packages.
|
|
|
|
*/
|
2008-06-13 17:23:46 +08:00
|
|
|
if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) {
|
|
|
|
while (rpmtdNext(&pnames) >= 0) {
|
2008-01-30 22:04:40 +08:00
|
|
|
rpmsenseFlags fdummy = RPMSENSE_ANY;
|
2008-06-18 16:32:59 +08:00
|
|
|
|
2008-06-19 20:48:31 +08:00
|
|
|
headerPutString(h, RPMTAG_PROVIDEVERSION, "");
|
|
|
|
headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2008-06-13 17:23:46 +08:00
|
|
|
/* see if we already have this provide */
|
2008-10-30 20:07:29 +08:00
|
|
|
hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
|
2008-06-13 17:23:46 +08:00
|
|
|
nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags);
|
|
|
|
if (rpmdsFind(hds, nvrds) >= 0) {
|
2001-10-22 05:43:32 +08:00
|
|
|
bingo = 0;
|
|
|
|
}
|
2008-06-13 17:23:46 +08:00
|
|
|
rpmdsFree(hds);
|
|
|
|
rpmdsFree(nvrds);
|
|
|
|
|
2001-10-22 05:43:32 +08:00
|
|
|
|
|
|
|
exit:
|
|
|
|
if (bingo) {
|
2008-06-19 20:48:31 +08:00
|
|
|
headerPutString(h, RPMTAG_PROVIDENAME, name);
|
2009-09-02 17:06:34 +08:00
|
|
|
headerPutString(h, RPMTAG_PROVIDEVERSION, pEVR);
|
2008-06-19 20:48:31 +08:00
|
|
|
headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pFlags, 1);
|
2001-10-22 05:43:32 +08:00
|
|
|
}
|
2008-06-13 17:23:46 +08:00
|
|
|
rpmtdFreeData(&pnames);
|
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
|
|
|
|
2008-10-10 20:59:38 +08:00
|
|
|
static void legacyRetrofit(Header h)
|
2001-10-25 09:36:32 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
2009-01-30 14:28:57 +08:00
|
|
|
/* Retrofit "Provide: name = EVR" for binary packages. */
|
|
|
|
if (!headerIsSource(h)) {
|
2001-10-25 09:36:32 +08:00
|
|
|
providePackageNVR(h);
|
|
|
|
}
|
|
|
|
}
|
2008-10-10 20:53:12 +08:00
|
|
|
|
2010-11-17 14:46:21 +08:00
|
|
|
int headerConvert(Header h, int op)
|
2008-10-10 20:53:12 +08:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
};
|
2009-12-22 18:30:45 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerRemoveEntry(Header h, rpm_tag_t tag)
|
2009-12-22 18:30:45 +08:00
|
|
|
{
|
|
|
|
return headerDel(h, tag);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
static void *_headerFreeData(rpm_data_t data, rpm_tagtype_t type)
|
2009-12-22 18:30:45 +08:00
|
|
|
{
|
|
|
|
if (data) {
|
|
|
|
if (type == RPM_FORCEFREE_TYPE ||
|
|
|
|
type == RPM_STRING_ARRAY_TYPE ||
|
|
|
|
type == RPM_I18NSTRING_TYPE ||
|
|
|
|
type == RPM_BIN_TYPE)
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
void * headerFreeData(rpm_data_t data, rpm_tagtype_t type)
|
2009-12-22 18:30:45 +08:00
|
|
|
{
|
|
|
|
return _headerFreeData(data, type);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
void * headerFreeTag(Header h, rpm_data_t data, rpm_tagtype_t type)
|
2009-12-22 18:30:45 +08:00
|
|
|
{
|
|
|
|
return _headerFreeData(data, type);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
static int headerGetWrap(Header h, rpm_tag_t tag,
|
|
|
|
rpm_tagtype_t * type,
|
2009-12-22 18:30:45 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerGetEntry(Header h, rpm_tag_t tag,
|
|
|
|
rpm_tagtype_t * type,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_data_t * p,
|
|
|
|
rpm_count_t * c)
|
|
|
|
{
|
|
|
|
return headerGetWrap(h, tag, type, p, c, HEADERGET_DEFAULT);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerGetEntryMinMemory(Header h, rpm_tag_t tag,
|
|
|
|
rpm_tagtype_t * type,
|
2009-12-22 18:30:45 +08:00
|
|
|
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 */
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerGetRawEntry(Header h, rpm_tag_t tag, rpm_tagtype_t * type, rpm_data_t * p,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_count_t * c);
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerGetRawEntry(Header h, rpm_tag_t tag, rpm_tagtype_t * type, rpm_data_t * p,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_count_t * c)
|
|
|
|
{
|
|
|
|
if (p == NULL)
|
|
|
|
return headerIsEntry(h, tag);
|
|
|
|
|
|
|
|
return headerGetWrap(h, tag, type, p, c, HEADERGET_RAW);
|
|
|
|
}
|
|
|
|
|
|
|
|
int headerNextIterator(HeaderIterator hi,
|
2010-10-22 14:55:49 +08:00
|
|
|
rpm_tag_t * tag,
|
|
|
|
rpm_tagtype_t * type,
|
2009-12-22 18:30:45 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerModifyEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
|
2009-12-22 18:30:45 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
static int headerPutWrap(Header h, rpm_tag_t tag, rpm_tagtype_t type,
|
2009-12-22 18:30:45 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerAddOrAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_constdata_t p, rpm_count_t c)
|
|
|
|
{
|
|
|
|
return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerAppendEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_constdata_t p, rpm_count_t c)
|
|
|
|
{
|
|
|
|
return headerPutWrap(h, tag, type, p, c, HEADERPUT_APPEND);
|
|
|
|
}
|
|
|
|
|
2010-10-22 14:55:49 +08:00
|
|
|
int headerAddEntry(Header h, rpm_tag_t tag, rpm_tagtype_t type,
|
2009-12-22 18:30:45 +08:00
|
|
|
rpm_constdata_t p, rpm_count_t c)
|
|
|
|
{
|
|
|
|
return headerPutWrap(h, tag, type, p, c, HEADERPUT_DEFAULT);
|
|
|
|
}
|
|
|
|
#undef _RPM_4_4_COMPAT
|