mirror of
https://abf.rosa.ru/djam/rpm.git
synced 2025-02-23 10:23:04 +00:00
370 lines
8.8 KiB
Diff
370 lines
8.8 KiB
Diff
--- rpm-5.4.7/rpmdb/package.c.rpmv3~ 2012-04-12 13:08:29.214493302 +0200
|
|
+++ rpm-5.4.7/rpmdb/package.c 2012-04-12 16:33:05.021039135 +0200
|
|
@@ -19,6 +19,8 @@
|
|
|
|
#include "rpmts.h"
|
|
|
|
+#define _RPMEVR_INTERNAL
|
|
+#include <rpmevr.h>
|
|
#include "debug.h"
|
|
|
|
#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
|
|
@@ -79,6 +81,349 @@ static int pgpStashKeyid(pgpDig dig)
|
|
}
|
|
#endif
|
|
|
|
+/*@-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@*/
|
|
+/**
|
|
+ * Convert absolute path tag to (dirname,basename,dirindex) tags.
|
|
+ * @param h header
|
|
+ */
|
|
+static void compressFilelist(Header h)
|
|
+ /*@modifies h @*/
|
|
+{
|
|
+ HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
|
+
|
|
+ char ** fileNames;
|
|
+ const char ** dirNames;
|
|
+ const char ** baseNames;
|
|
+ int32_t * 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)) {
|
|
+ he->tag = RPMTAG_OLDFILENAMES;
|
|
+ headerDel(h, he, 0);
|
|
+ return; /* Already converted. */
|
|
+ }
|
|
+
|
|
+ he->tag = RPMTAG_OLDFILENAMES;
|
|
+ if (!headerGet(h, he, 0))
|
|
+ return;
|
|
+
|
|
+ fileNames = he->p.ptr;
|
|
+ if (he->c <= 0)
|
|
+ return;
|
|
+ count = he->c;
|
|
+
|
|
+ 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) {
|
|
+
|
|
+ he->tag = RPMTAG_DIRINDEXES;
|
|
+ if (headerGet(h, he, 0))
|
|
+ dirIndexes = he->p.ptr;
|
|
+ he->tag = RPMTAG_BASENAMES;
|
|
+ if (headerGet(h, he, 0))
|
|
+ baseNames = he->p.ptr;
|
|
+ he->tag = RPMTAG_DIRNAMES;
|
|
+ if (headerGet(h, he, 0))
|
|
+ dirNames = he->p.ptr;
|
|
+
|
|
+ he->tag = RPMTAG_DIRINDEXES;
|
|
+ he->t = RPM_UINT32_TYPE;
|
|
+ he->p.ptr = dirIndexes;
|
|
+ he->c = count;
|
|
+ headerPut(h, he, 0);
|
|
+
|
|
+ he->tag = RPMTAG_BASENAMES;
|
|
+ he->t = RPM_STRING_ARRAY_TYPE;
|
|
+ he->p.ptr = baseNames;
|
|
+ he->c = count;
|
|
+ headerPut(h, he, 0);
|
|
+
|
|
+ he->tag = RPMTAG_DIRNAMES;
|
|
+ he->t = RPM_STRING_ARRAY_TYPE;
|
|
+ he->p.ptr = dirNames;
|
|
+ he->c = dirIndex +1;
|
|
+ headerPut(h,he,0);
|
|
+ }
|
|
+
|
|
+ fileNames = _free(fileNames);
|
|
+
|
|
+ he->tag = RPMTAG_OLDFILENAMES;
|
|
+ headerDel(h, he, 0);
|
|
+
|
|
+}
|
|
+/*@=bounds@*/
|
|
+
|
|
+/* copied verbatim from build/pack.c */
|
|
+static void providePackageNVR(Header h)
|
|
+{
|
|
+ HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
|
+ const char *N, *V, *R;
|
|
+#ifdef RPM_VENDOR_MANDRIVA
|
|
+ const char *D;
|
|
+ int gotD;
|
|
+#endif
|
|
+ rpmuint32_t E;
|
|
+ int gotE;
|
|
+ const char *pEVR;
|
|
+ char *p;
|
|
+ rpmuint32_t pFlags = RPMSENSE_EQUAL;
|
|
+ const char ** provides = NULL;
|
|
+ const char ** providesEVR = NULL;
|
|
+ rpmuint32_t * provideFlags = NULL;
|
|
+ int providesCount;
|
|
+ int bingo = 1;
|
|
+ size_t nb;
|
|
+ int xx;
|
|
+ int i;
|
|
+
|
|
+ /* Generate provides for this package N-V-R. */
|
|
+ xx = headerNEVRA(h, &N, NULL, &V, &R, NULL);
|
|
+ if (!(N && V && R))
|
|
+ return;
|
|
+
|
|
+ nb = 21 + strlen(V) + 1 + strlen(R) + 1;
|
|
+#ifdef RPM_VENDOR_MANDRIVA
|
|
+ he->tag = RPMTAG_DISTEPOCH;
|
|
+ gotD = headerGet(h, he, 0);
|
|
+ D = (he->p.str ? he->p.str : NULL);
|
|
+ nb += (gotD ? strlen(D) + 1 : 0);
|
|
+#endif
|
|
+ pEVR = p = alloca(nb);
|
|
+ *p = '\0';
|
|
+ he->tag = RPMTAG_EPOCH;
|
|
+ gotE = headerGet(h, he, 0);
|
|
+ E = (he->p.ui32p ? he->p.ui32p[0] : 0);
|
|
+ he->p.ptr = _free(he->p.ptr);
|
|
+ if (gotE) {
|
|
+ sprintf(p, "%d:", E);
|
|
+ p += strlen(p);
|
|
+ }
|
|
+ p = stpcpy( stpcpy( stpcpy(p, V) , "-") , R);
|
|
+#ifdef RPM_VENDOR_MANDRIVA
|
|
+ if (gotD) {
|
|
+ p = stpcpy( stpcpy( p, ":"), D);
|
|
+ D = _free(D);
|
|
+ //(void) rpmlibNeedsFeature(h, "DistEpoch", "5.4.7-1");
|
|
+ }
|
|
+#endif
|
|
+ V = _free(V);
|
|
+ R = _free(R);
|
|
+
|
|
+ /*
|
|
+ * Rpm prior to 3.0.3 does not have versioned provides.
|
|
+ * If no provides at all are available, we can just add.
|
|
+ */
|
|
+ he->tag = RPMTAG_PROVIDENAME;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerGet(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ provides = he->p.argv;
|
|
+ providesCount = he->c;
|
|
+ if (!xx)
|
|
+ goto exit;
|
|
+
|
|
+ /*
|
|
+ * Otherwise, fill in entries on legacy packages.
|
|
+ */
|
|
+ he->tag = RPMTAG_PROVIDEVERSION;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerGet(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ providesEVR = he->p.argv;
|
|
+ if (!xx) {
|
|
+ for (i = 0; i < providesCount; i++) {
|
|
+ /*@observer@*/
|
|
+ static const char * vdummy = "";
|
|
+ static rpmsenseFlags fdummy = RPMSENSE_ANY;
|
|
+
|
|
+ he->tag = RPMTAG_PROVIDEVERSION;
|
|
+ he->t = RPM_STRING_ARRAY_TYPE;
|
|
+ he->p.argv = &vdummy;
|
|
+ he->c = 1;
|
|
+ he->append = 1;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerPut(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ he->append = 0;
|
|
+
|
|
+ he->tag = RPMTAG_PROVIDEFLAGS;
|
|
+ he->t = RPM_UINT32_TYPE;
|
|
+ he->p.ui32p = (void *) &fdummy;
|
|
+ he->c = 1;
|
|
+ he->append = 1;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerPut(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ he->append = 0;
|
|
+ }
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ he->tag = RPMTAG_PROVIDEFLAGS;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerGet(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ provideFlags = he->p.ui32p;
|
|
+
|
|
+ /*@-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(N, provides[i]) && !strcmp(pEVR, providesEVR[i])))
|
|
+ continue;
|
|
+ bingo = 0;
|
|
+ break;
|
|
+ }
|
|
+ /*@=nullderef@*/
|
|
+
|
|
+exit:
|
|
+/*@-usereleased@*/
|
|
+ provides = _free(provides);
|
|
+ providesEVR = _free(providesEVR);
|
|
+ provideFlags = _free(provideFlags);
|
|
+/*@=usereleased@*/
|
|
+
|
|
+ if (bingo) {
|
|
+ he->tag = RPMTAG_PROVIDENAME;
|
|
+ he->t = RPM_STRING_ARRAY_TYPE;
|
|
+ he->p.argv = &N;
|
|
+ he->c = 1;
|
|
+ he->append = 1;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerPut(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ he->append = 0;
|
|
+
|
|
+ /* XXX succeeds only at allocating the necessary appended space,
|
|
+ * not copying to it..? */
|
|
+ xx = headerGet(h, he, 0);
|
|
+ he->p.argv[providesCount] = N;
|
|
+ xx = headerPut(h, he, 0);
|
|
+ _free(he->p.ptr);
|
|
+
|
|
+ he->tag = RPMTAG_PROVIDEVERSION;
|
|
+ he->t = RPM_STRING_ARRAY_TYPE;
|
|
+ he->p.argv = &pEVR;
|
|
+ he->c = 1;
|
|
+ he->append = 1;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerPut(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ he->append = 0;
|
|
+
|
|
+ he->tag = RPMTAG_PROVIDEFLAGS;
|
|
+ he->t = RPM_UINT32_TYPE;
|
|
+ he->p.ui32p = &pFlags;
|
|
+ he->c = 1;
|
|
+ he->append = 1;
|
|
+/*@-nullstate@*/
|
|
+ xx = headerPut(h, he, 0);
|
|
+/*@=nullstate@*/
|
|
+ he->append = 0;
|
|
+ }
|
|
+ N = _free(N);
|
|
+}
|
|
+
|
|
+static void add_RPMTAG_SOURCERPM(Header h)
|
|
+{
|
|
+ if (!headerIsEntry(h, RPMTAG_SOURCERPM) && !headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) {
|
|
+ /* we have no way to know if this is a srpm or an rpm with no SOURCERPM */
|
|
+ /* but since this is an old v3 rpm, we suppose it's not a srpm */
|
|
+ HE_t he = (HE_t)memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
|
+
|
|
+ he->tag = RPMTAG_SOURCERPM;
|
|
+ he->t = RPM_STRING_TYPE;
|
|
+ he->p.str = "\0";
|
|
+ he->c = 1;
|
|
+ headerPut(h, he, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* rpm v3 compatibility */
|
|
+static void rpm3to4(Header h) {
|
|
+ const char * rpmversion = NULL;
|
|
+ HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
|
|
+
|
|
+ he->tag = RPMTAG_RPMVERSION;
|
|
+ if (headerGet(h, he, 0)) {
|
|
+ rpmversion = he->p.str;
|
|
+ }
|
|
+
|
|
+ if ((!rpmversion) || rpmversion[0] < '4') {
|
|
+ add_RPMTAG_SOURCERPM(h);
|
|
+ providePackageNVR(h);
|
|
+ compressFilelist(h);
|
|
+ }
|
|
+ rpmversion = _free(rpmversion);
|
|
+ return;
|
|
+}
|
|
+
|
|
/*@-mods@*/
|
|
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
|
|
{
|
|
@@ -383,6 +728,8 @@ exit:
|
|
/* Append (and remap) signature tags to the metadata. */
|
|
headerMergeLegacySigs(h, sigh);
|
|
|
|
+ rpm3to4(h);
|
|
+
|
|
/* Bump reference count for return. */
|
|
*hdrp = headerLink(h);
|
|
}
|