relocated _noDirTokens, compressFilelist, expandFilelist, providePackageNVR from lib to rpmdb
This commit is contained in:
parent
22a3b64b23
commit
eaef1aad45
296
lib/misc.c
296
lib/misc.c
@ -286,188 +286,6 @@ char * currentDirectory(void)
|
||||
return currDir;
|
||||
}
|
||||
|
||||
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;
|
||||
int_32 * dirIndexes;
|
||||
rpmTagType fnt;
|
||||
int count;
|
||||
int i;
|
||||
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)) {
|
||||
(void) hre(h, RPMTAG_OLDFILENAMES);
|
||||
return; /* Already converted. */
|
||||
}
|
||||
|
||||
if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
|
||||
return; /* no file list */
|
||||
if (fileNames == NULL || count <= 0)
|
||||
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];
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
const char ** needle;
|
||||
char savechar;
|
||||
char * baseName;
|
||||
int len;
|
||||
|
||||
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) {
|
||||
(void) hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
|
||||
(void) hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
|
||||
baseNames, count);
|
||||
(void) hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
|
||||
dirNames, dirIndex + 1);
|
||||
}
|
||||
|
||||
fileNames = hfd(fileNames, fnt);
|
||||
|
||||
(void) hre(h, RPMTAG_OLDFILENAMES);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is pretty straight-forward. The only thing that even resembles a trick
|
||||
* is getting all of this into a single xmalloc'd block.
|
||||
*/
|
||||
static void doBuildFileList(Header h, /*@out@*/ const char *** fileListPtr,
|
||||
/*@out@*/ int * fileCountPtr, rpmTag baseNameTag,
|
||||
rpmTag dirNameTag, rpmTag dirIndexesTag)
|
||||
/*@modifies *fileListPtr, *fileCountPtr @*/
|
||||
{
|
||||
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
||||
HFD_t hfd = headerFreeData;
|
||||
const char ** baseNames;
|
||||
const char ** dirNames;
|
||||
int * dirIndexes;
|
||||
int count;
|
||||
const char ** fileNames;
|
||||
int size;
|
||||
rpmTagType bnt, dnt;
|
||||
char * data;
|
||||
int i;
|
||||
|
||||
if (!hge(h, baseNameTag, &bnt, (void **) &baseNames, &count)) {
|
||||
if (fileListPtr) *fileListPtr = NULL;
|
||||
if (fileCountPtr) *fileCountPtr = 0;
|
||||
return; /* no file list */
|
||||
}
|
||||
|
||||
(void) hge(h, dirNameTag, &dnt, (void **) &dirNames, NULL);
|
||||
(void) hge(h, dirIndexesTag, NULL, (void **) &dirIndexes, &count);
|
||||
|
||||
size = sizeof(*fileNames) * count;
|
||||
for (i = 0; i < count; i++)
|
||||
size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
|
||||
|
||||
fileNames = xmalloc(size);
|
||||
data = ((char *) fileNames) + (sizeof(*fileNames) * count);
|
||||
for (i = 0; i < count; i++) {
|
||||
fileNames[i] = data;
|
||||
data = stpcpy( stpcpy(data, dirNames[dirIndexes[i]]), baseNames[i]);
|
||||
*data++ = '\0';
|
||||
}
|
||||
baseNames = hfd(baseNames, bnt);
|
||||
dirNames = hfd(dirNames, dnt);
|
||||
|
||||
if (fileListPtr)
|
||||
*fileListPtr = fileNames;
|
||||
else
|
||||
fileNames = _free(fileNames);
|
||||
if (fileCountPtr) *fileCountPtr = count;
|
||||
}
|
||||
|
||||
void expandFilelist(Header h)
|
||||
{
|
||||
HAE_t hae = (HAE_t)headerAddEntry;
|
||||
HRE_t hre = (HRE_t)headerRemoveEntry;
|
||||
const char ** fileNames = NULL;
|
||||
int count = 0;
|
||||
|
||||
if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
|
||||
doBuildFileList(h, &fileNames, &count, RPMTAG_BASENAMES,
|
||||
RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
|
||||
if (fileNames == NULL || count <= 0)
|
||||
return;
|
||||
(void) hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
|
||||
fileNames, count);
|
||||
fileNames = _free(fileNames);
|
||||
}
|
||||
|
||||
(void) hre(h, RPMTAG_DIRNAMES);
|
||||
(void) hre(h, RPMTAG_BASENAMES);
|
||||
(void) hre(h, RPMTAG_DIRINDEXES);
|
||||
}
|
||||
|
||||
|
||||
void rpmBuildFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
||||
{
|
||||
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_BASENAMES,
|
||||
RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
|
||||
}
|
||||
|
||||
void buildOrigFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
||||
{
|
||||
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_ORIGBASENAMES,
|
||||
RPMTAG_ORIGDIRNAMES, RPMTAG_ORIGDIRINDEXES);
|
||||
}
|
||||
|
||||
/* glob_pattern_p() taken from bash
|
||||
* Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
|
||||
*
|
||||
@ -704,117 +522,3 @@ int rpmPackageGetEntry( /*@unused@*/ void *leadp, Header sigs, Header h,
|
||||
|
||||
return headerGetEntry(sigs, sigtag, type, p, c);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
const char *name, *version, *release;
|
||||
int_32 * epoch;
|
||||
const char *pEVR;
|
||||
char *p;
|
||||
int_32 pFlags = RPMSENSE_EQUAL;
|
||||
const char ** provides = NULL;
|
||||
const char ** providesEVR = NULL;
|
||||
rpmTagType pnt, pvt;
|
||||
int_32 * provideFlags = NULL;
|
||||
int providesCount;
|
||||
int i;
|
||||
int bingo = 1;
|
||||
|
||||
/* Generate provides for this package name-version-release. */
|
||||
(void) headerNVR(h, &name, &version, &release);
|
||||
if (!(name && version && release))
|
||||
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))
|
||||
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 = "";
|
||||
int_32 fdummy = RPMSENSE_ANY;
|
||||
(void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
|
||||
&vdummy, 1);
|
||||
(void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
|
||||
&fdummy, 1);
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
(void) hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, 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;
|
||||
bingo = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
provides = hfd(provides, pnt);
|
||||
providesEVR = hfd(providesEVR, pvt);
|
||||
|
||||
if (bingo) {
|
||||
(void) headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
|
||||
&name, 1);
|
||||
(void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
|
||||
&pFlags, 1);
|
||||
(void) headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
|
||||
&pEVR, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int domd5(const char * fn, /*@out@*/ unsigned char * digest, int asAscii)
|
||||
/*@modifies digest, fileSystem @*/
|
||||
{
|
||||
int rc;
|
||||
FD_t fd = Fopen(fn, "r.ufdio");
|
||||
unsigned char buf[BUFSIZ];
|
||||
unsigned char * md5sum = NULL;
|
||||
size_t md5len;
|
||||
|
||||
if (fd == NULL || Ferror(fd)) {
|
||||
if (fd)
|
||||
(void) Fclose(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
||||
while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
|
||||
{};
|
||||
fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
|
||||
|
||||
if (Ferror(fd))
|
||||
rc = 1;
|
||||
(void) Fclose(fd);
|
||||
|
||||
if (!rc)
|
||||
memcpy(digest, md5sum, md5len);
|
||||
md5sum = _free(md5sum);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
514
rpmdb/legacy.c
Normal file
514
rpmdb/legacy.c
Normal file
@ -0,0 +1,514 @@
|
||||
/**
|
||||
* \file rpmdb/legacy.c
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#if HAVE_GELF_H
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#if !defined(DT_GNU_PRELINKED)
|
||||
#define DT_GNU_PRELINKED 0x6ffffdf5
|
||||
#endif
|
||||
#if !defined(DT_GNU_LIBLIST)
|
||||
#define DT_GNU_LIBLIST 0x6ffffef9
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_GELF_H */
|
||||
|
||||
#include "rpmio_internal.h"
|
||||
#include <rpmlib.h>
|
||||
#include <rpmmacro.h>
|
||||
#include "misc.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
|
||||
|
||||
/**
|
||||
* Open a file descriptor to verify file MD5 and size.
|
||||
* @param path file path
|
||||
* @retval pidp prelink helper pid or 0
|
||||
* @retval fsizep file size
|
||||
* @return -1 on error, otherwise, an open file descriptor
|
||||
*/
|
||||
static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
|
||||
/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
|
||||
/*@modifies *pidp, *fsizep, rpmGlobalMacroContext,
|
||||
fileSystem, internalState @*/
|
||||
{
|
||||
/*@only@*/
|
||||
static const char * cmd = NULL;
|
||||
static int initted = 0;
|
||||
int fdno;
|
||||
|
||||
if (!initted) {
|
||||
cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
|
||||
initted++;
|
||||
}
|
||||
|
||||
/*@-boundswrite@*/
|
||||
if (pidp) *pidp = 0;
|
||||
|
||||
if (fsizep) {
|
||||
struct stat sb, * st = &sb;
|
||||
if (stat(path, st) < 0)
|
||||
return -1;
|
||||
*fsizep = st->st_size;
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
fdno = open(path, O_RDONLY);
|
||||
if (fdno < 0)
|
||||
return fdno;
|
||||
|
||||
/*@-boundsread@*/
|
||||
if (!(cmd && *cmd))
|
||||
return fdno;
|
||||
/*@=boundsread@*/
|
||||
|
||||
#if HAVE_GELF_H && HAVE_LIBELF
|
||||
{ Elf *elf = NULL;
|
||||
Elf_Scn *scn = NULL;
|
||||
Elf_Data *data = NULL;
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Shdr shdr;
|
||||
GElf_Dyn dyn;
|
||||
int bingo;
|
||||
|
||||
(void) elf_version(EV_CURRENT);
|
||||
|
||||
/*@-evalorder@*/
|
||||
if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
|
||||
|| elf_kind(elf) != ELF_K_ELF
|
||||
|| gelf_getehdr(elf, &ehdr) == NULL
|
||||
|| !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
|
||||
goto exit;
|
||||
/*@=evalorder@*/
|
||||
|
||||
bingo = 0;
|
||||
/*@-branchstate -uniondef @*/
|
||||
while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
|
||||
(void) gelf_getshdr(scn, &shdr);
|
||||
if (shdr.sh_type != SHT_DYNAMIC)
|
||||
continue;
|
||||
while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
|
||||
int maxndx = data->d_size / shdr.sh_entsize;
|
||||
int ndx;
|
||||
|
||||
for (ndx = 0; ndx < maxndx; ++ndx) {
|
||||
(void) gelf_getdyn (data, ndx, &dyn);
|
||||
if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
|
||||
/*@innercontinue@*/ continue;
|
||||
bingo = 1;
|
||||
/*@innerbreak@*/ break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*@=branchstate =uniondef @*/
|
||||
|
||||
/*@-boundswrite@*/
|
||||
if (pidp != NULL && bingo) {
|
||||
int pipes[2];
|
||||
pid_t pid;
|
||||
int xx;
|
||||
|
||||
xx = close(fdno);
|
||||
pipes[0] = pipes[1] = -1;
|
||||
xx = pipe(pipes);
|
||||
if (!(pid = fork())) {
|
||||
const char ** av;
|
||||
int ac;
|
||||
xx = close(pipes[0]);
|
||||
xx = dup2(pipes[1], STDOUT_FILENO);
|
||||
xx = close(pipes[1]);
|
||||
if (!poptParseArgvString(cmd, &ac, &av)) {
|
||||
av[ac-1] = path;
|
||||
av[ac] = NULL;
|
||||
unsetenv("MALLOC_CHECK_");
|
||||
xx = execve(av[0], (char *const *)av+1, environ);
|
||||
}
|
||||
_exit(127);
|
||||
}
|
||||
*pidp = pid;
|
||||
fdno = pipes[0];
|
||||
xx = close(pipes[1]);
|
||||
}
|
||||
/*@=boundswrite@*/
|
||||
|
||||
exit:
|
||||
if (elf) (void) elf_end(elf);
|
||||
}
|
||||
#endif /* HAVE_GELF_H */
|
||||
|
||||
return fdno;
|
||||
}
|
||||
|
||||
int domd5(const char * fn, unsigned char * digest, int asAscii)
|
||||
{
|
||||
const char * path;
|
||||
urltype ut = urlPath(fn, &path);
|
||||
unsigned char * md5sum = NULL;
|
||||
size_t md5len;
|
||||
unsigned char buf[32*BUFSIZ];
|
||||
FD_t fd;
|
||||
size_t fsize = 0;
|
||||
pid_t pid = 0;
|
||||
int rc = 0;
|
||||
int fdno;
|
||||
int xx;
|
||||
|
||||
/*@-globs -internalglobs -mods @*/
|
||||
fdno = open_dso(path, &pid, &fsize);
|
||||
/*@=globs =internalglobs =mods @*/
|
||||
if (fdno < 0) {
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch(ut) {
|
||||
case URL_IS_PATH:
|
||||
case URL_IS_UNKNOWN:
|
||||
#if HAVE_MMAP
|
||||
if (pid == 0) {
|
||||
DIGEST_CTX ctx;
|
||||
void * mapped;
|
||||
|
||||
mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
|
||||
if (mapped == (void *)-1) {
|
||||
xx = close(fdno);
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef MADV_SEQUENTIAL
|
||||
xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
|
||||
xx = rpmDigestUpdate(ctx, mapped, fsize);
|
||||
xx = rpmDigestFinal(ctx, (void **)&md5sum, &md5len, asAscii);
|
||||
xx = munmap(mapped, fsize);
|
||||
xx = close(fdno);
|
||||
break;
|
||||
} /*@fallthrough@*/
|
||||
#endif
|
||||
default:
|
||||
/* Either use the pipe to prelink -y or open the URL. */
|
||||
fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
|
||||
(void) close(fdno);
|
||||
if (fd == NULL || Ferror(fd)) {
|
||||
rc = 1;
|
||||
if (fd != NULL)
|
||||
(void) Fclose(fd);
|
||||
break;
|
||||
}
|
||||
|
||||
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
|
||||
fsize = 0;
|
||||
while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
|
||||
fsize += rc;
|
||||
fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
|
||||
if (Ferror(fd))
|
||||
rc = 1;
|
||||
|
||||
(void) Fclose(fd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reap the prelink -y helper. */
|
||||
if (pid) {
|
||||
int status;
|
||||
(void) waitpid(pid, &status, 0);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status))
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
exit:
|
||||
/*@-boundswrite@*/
|
||||
if (!rc)
|
||||
memcpy(digest, md5sum, md5len);
|
||||
/*@=boundswrite@*/
|
||||
md5sum = _free(md5sum);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*@-exportheadervar@*/
|
||||
/*@unchecked@*/
|
||||
int _noDirTokens = 0;
|
||||
/*@=exportheadervar@*/
|
||||
|
||||
/*@-boundsread@*/
|
||||
static int dncmp(const void * a, const void * b)
|
||||
/*@*/
|
||||
{
|
||||
const char *const * first = a;
|
||||
const char *const * second = b;
|
||||
return strcmp(*first, *second);
|
||||
}
|
||||
/*@=boundsread@*/
|
||||
|
||||
/*@-bounds@*/
|
||||
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;
|
||||
int_32 * dirIndexes;
|
||||
rpmTagType fnt;
|
||||
int count;
|
||||
int i, xx;
|
||||
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. */
|
||||
}
|
||||
|
||||
if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
|
||||
return; /* no file list */
|
||||
if (fileNames == NULL || count <= 0)
|
||||
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];
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*@-branchstate@*/
|
||||
for (i = 0; i < count; i++) {
|
||||
const char ** needle;
|
||||
char savechar;
|
||||
char * baseName;
|
||||
int len;
|
||||
|
||||
if (fileNames[i] == NULL) /* XXX can't happen */
|
||||
continue;
|
||||
baseName = strrchr(fileNames[i], '/') + 1;
|
||||
len = baseName - fileNames[i];
|
||||
needle = dirNames;
|
||||
savechar = *baseName;
|
||||
*baseName = '\0';
|
||||
/*@-compdef@*/
|
||||
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;
|
||||
/*@=compdef@*/
|
||||
|
||||
*baseName = savechar;
|
||||
baseNames[i] = baseName;
|
||||
}
|
||||
/*@=branchstate@*/
|
||||
|
||||
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, dirIndex + 1);
|
||||
}
|
||||
|
||||
fileNames = hfd(fileNames, fnt);
|
||||
|
||||
xx = hre(h, RPMTAG_OLDFILENAMES);
|
||||
}
|
||||
/*@=bounds@*/
|
||||
|
||||
/*
|
||||
* This is pretty straight-forward. The only thing that even resembles a trick
|
||||
* is getting all of this into a single xmalloc'd block.
|
||||
*/
|
||||
static void doBuildFileList(Header h, /*@out@*/ const char *** fileListPtr,
|
||||
/*@out@*/ int * fileCountPtr, rpmTag baseNameTag,
|
||||
rpmTag dirNameTag, rpmTag dirIndexesTag)
|
||||
/*@modifies *fileListPtr, *fileCountPtr @*/
|
||||
{
|
||||
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
||||
HFD_t hfd = headerFreeData;
|
||||
const char ** baseNames;
|
||||
const char ** dirNames;
|
||||
int * dirIndexes;
|
||||
int count;
|
||||
const char ** fileNames;
|
||||
int size;
|
||||
rpmTagType bnt, dnt;
|
||||
char * data;
|
||||
int i;
|
||||
|
||||
if (!hge(h, baseNameTag, &bnt, (void **) &baseNames, &count)) {
|
||||
if (fileListPtr) *fileListPtr = NULL;
|
||||
if (fileCountPtr) *fileCountPtr = 0;
|
||||
return; /* no file list */
|
||||
}
|
||||
|
||||
(void) hge(h, dirNameTag, &dnt, (void **) &dirNames, NULL);
|
||||
(void) hge(h, dirIndexesTag, NULL, (void **) &dirIndexes, &count);
|
||||
|
||||
size = sizeof(*fileNames) * count;
|
||||
for (i = 0; i < count; i++)
|
||||
size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
|
||||
|
||||
fileNames = xmalloc(size);
|
||||
data = ((char *) fileNames) + (sizeof(*fileNames) * count);
|
||||
for (i = 0; i < count; i++) {
|
||||
fileNames[i] = data;
|
||||
data = stpcpy( stpcpy(data, dirNames[dirIndexes[i]]), baseNames[i]);
|
||||
*data++ = '\0';
|
||||
}
|
||||
baseNames = hfd(baseNames, bnt);
|
||||
dirNames = hfd(dirNames, dnt);
|
||||
|
||||
if (fileListPtr)
|
||||
*fileListPtr = fileNames;
|
||||
else
|
||||
fileNames = _free(fileNames);
|
||||
if (fileCountPtr) *fileCountPtr = count;
|
||||
}
|
||||
|
||||
void expandFilelist(Header h)
|
||||
{
|
||||
HAE_t hae = (HAE_t)headerAddEntry;
|
||||
HRE_t hre = (HRE_t)headerRemoveEntry;
|
||||
const char ** fileNames = NULL;
|
||||
int count = 0;
|
||||
|
||||
if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
|
||||
doBuildFileList(h, &fileNames, &count, RPMTAG_BASENAMES,
|
||||
RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
|
||||
if (fileNames == NULL || count <= 0)
|
||||
return;
|
||||
(void) hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
|
||||
fileNames, count);
|
||||
fileNames = _free(fileNames);
|
||||
}
|
||||
|
||||
(void) hre(h, RPMTAG_DIRNAMES);
|
||||
(void) hre(h, RPMTAG_BASENAMES);
|
||||
(void) hre(h, RPMTAG_DIRINDEXES);
|
||||
}
|
||||
|
||||
|
||||
void rpmBuildFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
||||
{
|
||||
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_BASENAMES,
|
||||
RPMTAG_DIRNAMES, RPMTAG_DIRINDEXES);
|
||||
}
|
||||
|
||||
void buildOrigFileList(Header h, const char *** fileListPtr, int * fileCountPtr)
|
||||
{
|
||||
doBuildFileList(h, fileListPtr, fileCountPtr, RPMTAG_ORIGBASENAMES,
|
||||
RPMTAG_ORIGDIRNAMES, RPMTAG_ORIGDIRINDEXES);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
const char *name, *version, *release;
|
||||
int_32 * epoch;
|
||||
const char *pEVR;
|
||||
char *p;
|
||||
int_32 pFlags = RPMSENSE_EQUAL;
|
||||
const char ** provides = NULL;
|
||||
const char ** providesEVR = NULL;
|
||||
rpmTagType pnt, pvt;
|
||||
int_32 * provideFlags = NULL;
|
||||
int providesCount;
|
||||
int i, xx;
|
||||
int bingo = 1;
|
||||
|
||||
/* Generate provides for this package name-version-release. */
|
||||
xx = headerNVR(h, &name, &version, &release);
|
||||
if (!(name && version && release))
|
||||
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))
|
||||
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 = "";
|
||||
int_32 fdummy = RPMSENSE_ANY;
|
||||
xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
|
||||
&vdummy, 1);
|
||||
xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
|
||||
&fdummy, 1);
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
||||
xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
|
||||
|
||||
/*@-nullderef@*/ /* 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;
|
||||
bingo = 0;
|
||||
break;
|
||||
}
|
||||
/*@=nullderef@*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user