373 lines
9.8 KiB
C
373 lines
9.8 KiB
C
|
/*
|
||
|
* distromatic - tool for RPM based repositories
|
||
|
*
|
||
|
* Copyright (C) 2004-2006 by Silvan Calarco <silvan.calarco@mambasoft.it>
|
||
|
* Copyright (C) 2006 by Davide Madrisan <davide.madrisan@gmail.com>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it under
|
||
|
* the terms of version 2 of the GNU General Public License as published by the
|
||
|
* Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
* ANY WARRANTY, to the extent permitted by law; without even the implied
|
||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
* See the GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License along with
|
||
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#if HAVE_STRING_H
|
||
|
# if !STDC_HEADERS && HAVE_MEMORY_H
|
||
|
# include <memory.h>
|
||
|
# endif
|
||
|
# include <string.h>
|
||
|
#endif
|
||
|
#if HAVE_STRINGS_H
|
||
|
# include <strings.h>
|
||
|
#endif
|
||
|
|
||
|
#include <fcntl.h>
|
||
|
|
||
|
#ifndef H_RPMLIB
|
||
|
# include <rpm/rpmlib.h>
|
||
|
#endif
|
||
|
|
||
|
#if RPM_VERSION >= 0x040100
|
||
|
#include <rpm/rpmts.h>
|
||
|
#else
|
||
|
#define rpmReadPackageFile(a,b,c,d) rpmReadPackageHeader(b,d,0,NULL,NULL)
|
||
|
#endif
|
||
|
|
||
|
#if RPM_VERSION >= 0x040409
|
||
|
#ifndef H_RPMEVR
|
||
|
#include <rpm/rpmevr.h>
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#include <zlib.h>
|
||
|
#include <libiberty.h>
|
||
|
#include "functions.h"
|
||
|
|
||
|
#ifndef RPMFUNCTIONS_H
|
||
|
# include "rpmfunctions.h"
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* static int getPackageInfo(
|
||
|
* Header h, char **name, char **version, char **release,
|
||
|
* char **summary); */
|
||
|
static rpmts ts;
|
||
|
|
||
|
unsigned int checkVersionWithFlags(const char* cmp1, uint_32 flags, const char* cmp2) {
|
||
|
|
||
|
struct EVR_s evr1, evr2;
|
||
|
int vercmp = 0;
|
||
|
|
||
|
rpmEVRparse(cmp1, &evr1);
|
||
|
rpmEVRparse(cmp2, &evr2);
|
||
|
|
||
|
if (strlen(evr1.F[RPMEVR_E]) && strlen(evr2.F[RPMEVR_E])) vercmp=rpmvercmp(evr1.F[RPMEVR_E], evr2.F[RPMEVR_E]);
|
||
|
else if (strlen(evr2.F[RPMEVR_E])) vercmp = -1;
|
||
|
else if (strlen(evr1.F[RPMEVR_E])) vercmp = 1;
|
||
|
|
||
|
if (!vercmp) vercmp=rpmvercmp(evr1.F[RPMEVR_V], evr2.F[RPMEVR_V]);
|
||
|
if (!vercmp && strlen(evr1.F[RPMEVR_R]) && strlen(evr2.F[RPMEVR_R])) vercmp=rpmvercmp(evr1.F[RPMEVR_R], evr2.F[RPMEVR_R]);
|
||
|
|
||
|
if ((vercmp == 0) && (flags & RPMSENSE_EQUAL)) return 1;
|
||
|
else if ((vercmp == 1) && (flags & RPMSENSE_LESS)) return 1;
|
||
|
else if ((vercmp == -1) && (flags & RPMSENSE_GREATER)) return 1;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* get header from a file descriptor of a YUM compressed header file */
|
||
|
int
|
||
|
getHeader(char *headerFile, Header * h)
|
||
|
{
|
||
|
char buffer[HEADERS_BUFFER_SIZE];
|
||
|
int len;
|
||
|
|
||
|
/* check if file is a compressed header or a RPM/SRPM */
|
||
|
if (!strcmp(&headerFile[strlen(headerFile) - 4], ".hdr")) {
|
||
|
gzFile gzIn;
|
||
|
gzIn = gzopen(headerFile, "r");
|
||
|
|
||
|
if (gzIn == NULL) {
|
||
|
return 1;
|
||
|
} /* can't gzopen file */
|
||
|
|
||
|
len = gzread(gzIn, buffer, HEADERS_BUFFER_SIZE);
|
||
|
gzclose(gzIn);
|
||
|
|
||
|
/* header file is bigger than buffer */
|
||
|
if (len >= HEADERS_BUFFER_SIZE) {
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
*h = headerLoad(buffer);
|
||
|
} else {
|
||
|
FD_t fd;
|
||
|
|
||
|
fd = Fopen(headerFile, "r");
|
||
|
|
||
|
if (fd == NULL || Ferror(fd)) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int rc;
|
||
|
|
||
|
#if RPM_VERSION >= 0x040100
|
||
|
rc = rpmReadPackageFile(ts, fd, headerFile, h);
|
||
|
if (rc != RPMRC_OK && rc != RPMRC_NOTTRUSTED && rc != RPMRC_NOKEY) {
|
||
|
/* fprintf(stderr, "Error: Failed reading file %s", headerFile); */
|
||
|
#else
|
||
|
rc = rpmReadPackageHeader(fd, h, NULL, NULL, NULL);
|
||
|
if (rc != 0) {
|
||
|
#endif
|
||
|
return 1;
|
||
|
}
|
||
|
fdClose(fd);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char *
|
||
|
headerGetStringEntry(Header h, const int tag)
|
||
|
{
|
||
|
char *st = NULL;
|
||
|
|
||
|
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
||
|
|
||
|
he->tag = tag;
|
||
|
if (headerGet(h, he, 0) && he->t == RPM_STRING_TYPE && he->c == 1)
|
||
|
st = xstrdup(he->p.str);
|
||
|
else
|
||
|
st = NULL;
|
||
|
|
||
|
//printf(" headerGetStringEntry tag:%d st:%s\n", he->tag, st);
|
||
|
he->p.ptr = _free(he->p.ptr);
|
||
|
return st;
|
||
|
}
|
||
|
|
||
|
char **
|
||
|
headerGetStringArrayEntry(Header h, const int tag, int* count)
|
||
|
{
|
||
|
char **st;
|
||
|
|
||
|
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
||
|
|
||
|
he->tag = tag;
|
||
|
if (headerGet(h, he, 0) && he->t == RPM_STRING_ARRAY_TYPE && he->c >= 1) {
|
||
|
*count = he->c;
|
||
|
st = dupnargv(he->p.ptr, he->c);
|
||
|
} else {
|
||
|
*count = 0;
|
||
|
st = NULL;
|
||
|
}
|
||
|
//unsigned int i;
|
||
|
//for (i=0; i < he->c; i++) {
|
||
|
//fprintf(stderr," headerGetStringArrayEntry tag:%d string %d/%d:%s\n", he->tag, i+1, he->c, st[i]);
|
||
|
//}
|
||
|
he->p.ptr = _free(he->p.ptr);
|
||
|
return st;
|
||
|
}
|
||
|
|
||
|
long long headerGetUIntEntry(Header h, const int tag) {
|
||
|
|
||
|
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
||
|
unsigned long long ret = -1;
|
||
|
|
||
|
he->tag = tag;
|
||
|
if (headerGet(h, he, 0) && he->c == 1) {
|
||
|
switch (he->t) {
|
||
|
case RPM_UINT8_TYPE:
|
||
|
ret = *he->p.ui8p;
|
||
|
break;
|
||
|
case RPM_UINT16_TYPE:
|
||
|
ret = *he->p.ui16p;
|
||
|
break;
|
||
|
case RPM_UINT32_TYPE:
|
||
|
ret = *he->p.ui32p;
|
||
|
break;
|
||
|
case RPM_UINT64_TYPE:
|
||
|
ret = *he->p.ui64p;
|
||
|
break;
|
||
|
default:
|
||
|
ret = -1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//fprintf(stderr," headerGetUIntEntry tag:%d uint %lld\n", he->tag, ret);
|
||
|
|
||
|
he->p.ptr = _free(he->p.ptr);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void *headerGetUIntArrayEntry(Header h, const int tag, int *count) {
|
||
|
|
||
|
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
||
|
void *ret = NULL;
|
||
|
|
||
|
he->tag = tag;
|
||
|
if (headerGet(h, he, 0) && he->c >= 1) {
|
||
|
*count = he->c;
|
||
|
switch (he->t) {
|
||
|
case RPM_UINT8_TYPE:
|
||
|
ret = memndup(he->p.ui8p, he->c * sizeof(he->p.ui8p));
|
||
|
break;
|
||
|
case RPM_UINT16_TYPE:
|
||
|
ret = memndup(he->p.ui16p, he->c * sizeof(he->p.ui16p));
|
||
|
break;
|
||
|
case RPM_UINT32_TYPE:
|
||
|
ret = memndup(he->p.ui32p, he->c * sizeof(he->p.ui32p));
|
||
|
//int i;
|
||
|
//for (i=0; i<he->c; i++) {
|
||
|
// printf("%d ",((int_32 *)ret)[i]);
|
||
|
//}
|
||
|
break;
|
||
|
case RPM_UINT64_TYPE:
|
||
|
ret = memndup(he->p.ui64p, he->c * sizeof(he->p.ui64p));
|
||
|
break;
|
||
|
default:
|
||
|
ret = NULL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//unsigned int i;
|
||
|
//for (i=0; i < he->c; i++) {
|
||
|
//fprintf(stderr," headerGetUIntArrayEntry tag:%d value:%ld\n", he->tag, ((rpmuint32_t*)ret)[i]);
|
||
|
//}
|
||
|
he->p.ptr = _free(he->p.ptr);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getPackageRequires(Header h, char ***requirename, uint_32 **requireflags,
|
||
|
char ***requireversion, int *requirecount)
|
||
|
{
|
||
|
*requirename = headerGetStringArrayEntry(h, RPMTAG_REQUIRENAME, requirecount);
|
||
|
*requireflags = headerGetUIntArrayEntry(h, RPMTAG_REQUIREFLAGS, requirecount);
|
||
|
*requireversion = headerGetStringArrayEntry(h, RPMTAG_REQUIREVERSION, requirecount);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getPackageProvides(Header h, char ***providename, uint_32 **provideflags,
|
||
|
char ***provideversion, int *providecount)
|
||
|
{
|
||
|
*providename = headerGetStringArrayEntry(h, RPMTAG_PROVIDENAME, providecount);
|
||
|
*provideflags = headerGetUIntArrayEntry(h, RPMTAG_PROVIDEFLAGS, providecount);
|
||
|
*provideversion = headerGetStringArrayEntry(h, RPMTAG_PROVIDEVERSION, providecount);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getPackageObsoletes(Header h, char ***obsoletename, uint_32 **obsoleteflags,
|
||
|
char ***obsoleteversion, int *obsoletecount)
|
||
|
{
|
||
|
*obsoletename = headerGetStringArrayEntry(h, RPMTAG_OBSOLETENAME, obsoletecount);
|
||
|
*obsoleteflags = headerGetUIntArrayEntry(h, RPMTAG_OBSOLETEFLAGS, obsoletecount);
|
||
|
*obsoleteversion = headerGetStringArrayEntry(h, RPMTAG_OBSOLETEVERSION, obsoletecount);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
getPackageFilenames(Header h, int **dirindexes,
|
||
|
char ***dirnames, int *dirnamescount,
|
||
|
char ***basenames, int *filenamescount)
|
||
|
{
|
||
|
int count;
|
||
|
|
||
|
/* note: I assume that basenamecount == dirindexescount */
|
||
|
*dirindexes = headerGetUIntArrayEntry(h, RPMTAG_DIRINDEXES, &count);
|
||
|
*dirnames = headerGetStringArrayEntry(h, RPMTAG_DIRNAMES, dirnamescount);
|
||
|
*basenames = headerGetStringArrayEntry(h, RPMTAG_BASENAMES, filenamescount);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int rpmnamecmp(char *filename1, char *filename2, int checkver) {
|
||
|
int end1=0, end2=0, f, i;
|
||
|
char c1,c2;
|
||
|
|
||
|
f=0;
|
||
|
|
||
|
/* find name end position assuming a "name-version-release" scheme */
|
||
|
for (i = strlen(filename1)-1; (i > 0) && (f < 2); i--) {
|
||
|
if (filename1[i] == '-') {
|
||
|
f++;
|
||
|
end1=i-1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
f=0;
|
||
|
for (i = strlen(filename2)-1; (i > 0) && (f < 2); i--) {
|
||
|
if (filename2[i] == '-') {
|
||
|
f++;
|
||
|
end2=i-1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* make comparison, case insensitive */
|
||
|
for (i=0; (i <= end1) && (i <= end2); i++) {
|
||
|
c1=filename1[i];
|
||
|
c2=filename2[i];
|
||
|
if ((c1 >= 'A') && (c1 <= 'Z')) c1=c1+'a'-'A';
|
||
|
if ((c2 >= 'A') && (c2 <= 'Z')) c2=c2+'a'-'A';
|
||
|
if (c1 < c2) return -1;
|
||
|
else if (c1 > c2) return 1;
|
||
|
}
|
||
|
|
||
|
if (end1 < end2) return -1;
|
||
|
else if (end1 > end2) return 1;
|
||
|
|
||
|
/* same name, sort by version */
|
||
|
if (checkver)
|
||
|
i=rpmvercmp(&filename2[i+1],&filename1[i+1]) * -1;
|
||
|
else
|
||
|
i=0;
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
int scanrpmnamecmp(const struct dirent **f1, const struct dirent **f2) {
|
||
|
return rpmnamecmp((char*)(*f1)->d_name,(char*)(*f2)->d_name,1);
|
||
|
}
|
||
|
|
||
|
char* printrpmversion(char *s, int bufsize, long epoch, char *version, char *release) {
|
||
|
|
||
|
if (strcmp(release,"")) {
|
||
|
if (epoch)
|
||
|
snprintf(s,bufsize,"%ld:%s-%s",epoch,version,release);
|
||
|
else
|
||
|
snprintf(s,bufsize,"%s-%s",version,release);
|
||
|
} else {
|
||
|
if (epoch)
|
||
|
snprintf(s,bufsize,"%ld:%s",epoch,version);
|
||
|
else
|
||
|
snprintf(s,bufsize,"%s",version);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
void rpminit() {
|
||
|
#if RPM_VERSION >= 0x040100
|
||
|
rpmReadConfigFiles(NULL, NULL);
|
||
|
ts = rpmtsCreate();
|
||
|
// rpmtsSetVSFlags(ts, (rpmVSFlags_e)-1);
|
||
|
#endif
|
||
|
}
|