/* * distromatic - tool for RPM based repositories * * Copyright (C) 2004-2006 by Silvan Calarco * Copyright (C) 2006 by Davide Madrisan * * 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 # endif # include #endif #if HAVE_STRINGS_H # include #endif #include #ifndef H_RPMLIB # include #endif #if RPM_VERSION >= 0x040100 #include #else #define rpmReadPackageFile(a,b,c,d) rpmReadPackageHeader(b,d,0,NULL,NULL) #endif #if RPM_VERSION >= 0x040409 #ifndef H_RPMEVR #include #endif #endif #include #include #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; ic; 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 }