distromatic/src/rpmfunctions.c
2011-04-27 21:50:52 +02:00

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
}