lib/package.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #include <netinet/in.h>
00008 
00009 #include <rpmio_internal.h>
00010 #include <rpmlib.h>
00011 
00012 #include "rpmts.h"
00013 #include "rpmevr.h"
00014 
00015 #include "misc.h"       /* XXX stripTrailingChar() */
00016 #include "rpmlead.h"
00017 
00018 #include "header_internal.h"    /* XXX headerCheck */
00019 #include "signature.h"
00020 #include "debug.h"
00021 
00022 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
00023 
00024 /*@access pgpDig @*/
00025 /*@access pgpDigParams @*/
00026 /*@access Header @*/            /* XXX compared with NULL */
00027 /*@access entryInfo @*/         /* XXX headerCheck */
00028 /*@access indexEntry @*/        /* XXX headerCheck */
00029 /*@access FD_t @*/              /* XXX stealing digests */
00030 
00031 /*@unchecked@*/
00032 static int _print_pkts = 0;
00033 
00034 /*@unchecked@*/
00035 static unsigned int nkeyids_max = 256;
00036 /*@unchecked@*/
00037 static unsigned int nkeyids = 0;
00038 /*@unchecked@*/
00039 static unsigned int nextkeyid  = 0;
00040 /*@unchecked@*/ /*@only@*/ /*@null@*/
00041 static unsigned int * keyids;
00042 
00043 /*@unchecked@*/
00044 static unsigned char header_magic[8] = {
00045         0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00046 };
00047 
00051 /*@observer@*/ /*@unchecked@*/
00052 static int typeAlign[16] =  {
00053     1,  
00054     1,  
00055     1,  
00056     2,  
00057     4,  
00058     8,  
00059     1,  
00060     1,  
00061     1,  
00062     1,  
00063     0,
00064     0,
00065     0,
00066     0,
00067     0,
00068     0
00069 };
00070 
00075 #define hdrchkTags(_ntags)      ((_ntags) & 0xffff0000)
00076 
00080 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
00081 
00086 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
00087 
00091 #define hdrchkAlign(_type, _off)        ((_off) & (typeAlign[_type]-1))
00092 
00096 #define hdrchkRange(_dl, _off)          ((_off) < 0 || (_off) > (_dl))
00097 
00098 /*@-boundsread@*/
00099 static int dncmp(const void * a, const void * b)
00100        /*@*/
00101 {
00102     const char *const * first = a;
00103     const char *const * second = b;
00104     return strcmp(*first, *second);
00105 }
00106 /*@=boundsread@*/
00107 
00108 /*@-bounds@*/
00113 static void compressFilelist(Header h)
00114         /*@modifies h @*/
00115 {
00116     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00117     HAE_t hae = (HAE_t)headerAddEntry;
00118     HRE_t hre = (HRE_t)headerRemoveEntry;
00119     HFD_t hfd = headerFreeData;
00120     char ** fileNames;
00121     const char ** dirNames;
00122     const char ** baseNames;
00123     int_32 * dirIndexes;
00124     rpmTagType fnt;
00125     int count;
00126     int i, xx;
00127     int dirIndex = -1;
00128 
00129     /*
00130      * This assumes the file list is already sorted, and begins with a
00131      * single '/'. That assumption isn't critical, but it makes things go
00132      * a bit faster.
00133      */
00134 
00135     if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00136         xx = hre(h, RPMTAG_OLDFILENAMES);
00137         return;         /* Already converted. */
00138     }
00139 
00140     if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00141         return;         /* no file list */
00142     if (fileNames == NULL || count <= 0)
00143         return;
00144 
00145     dirNames = alloca(sizeof(*dirNames) * count);       /* worst case */
00146     baseNames = alloca(sizeof(*dirNames) * count);
00147     dirIndexes = alloca(sizeof(*dirIndexes) * count);
00148 
00149     if (fileNames[0][0] != '/') {
00150         /* HACK. Source RPM, so just do things differently */
00151         dirIndex = 0;
00152         dirNames[dirIndex] = "";
00153         for (i = 0; i < count; i++) {
00154             dirIndexes[i] = dirIndex;
00155             baseNames[i] = fileNames[i];
00156         }
00157         goto exit;
00158     }
00159 
00160     /*@-branchstate@*/
00161     for (i = 0; i < count; i++) {
00162         const char ** needle;
00163         char savechar;
00164         char * baseName;
00165         int len;
00166 
00167         if (fileNames[i] == NULL)       /* XXX can't happen */
00168             continue;
00169         baseName = strrchr(fileNames[i], '/') + 1;
00170         len = baseName - fileNames[i];
00171         needle = dirNames;
00172         savechar = *baseName;
00173         *baseName = '\0';
00174 /*@-compdef@*/
00175         if (dirIndex < 0 ||
00176             (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00177             char *s = alloca(len + 1);
00178             memcpy(s, fileNames[i], len + 1);
00179             s[len] = '\0';
00180             dirIndexes[i] = ++dirIndex;
00181             dirNames[dirIndex] = s;
00182         } else
00183             dirIndexes[i] = needle - dirNames;
00184 /*@=compdef@*/
00185 
00186         *baseName = savechar;
00187         baseNames[i] = baseName;
00188     }
00189     /*@=branchstate@*/
00190 
00191 exit:
00192     if (count > 0) {
00193         xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00194         xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00195                         baseNames, count);
00196         xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00197                         dirNames, dirIndex + 1);
00198     }
00199 
00200     fileNames = hfd(fileNames, fnt);
00201 
00202     xx = hre(h, RPMTAG_OLDFILENAMES);
00203 }
00204 /*@=bounds@*/
00205 
00206 /* rpm v3 compatibility */
00207 static void rpm3to4(Header h) {
00208     char * rpmversion;
00209     int_32 rpmversion_type;
00210 
00211     (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type);
00212 
00213     if ((!rpmversion) || rpmversion[0] < '4') {
00214         int *epoch;
00215         const char * name, *version, *release;
00216         const char *pEVR;
00217         char *p;
00218         int_32 pFlags = RPMSENSE_EQUAL;
00219 
00220         if (headerNVR(h, &name, &version, &release) == 0) {
00221             pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00222             *p = '\0';
00223             if (headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00224                 sprintf(p, "%d:", *epoch);
00225                 while (*p != '\0')
00226                 p++;
00227             }
00228             (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00229 
00230             headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE, &name, 1);
00231             headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, &pFlags, 1);
00232             headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, &pEVR, 1);
00233         }
00234         compressFilelist(h);
00235     }
00236     headerFreeTag(h, (void *) rpmversion, rpmversion_type);
00237     return;
00238 }
00239 
00240 void headerMergeLegacySigs(Header h, const Header sigh)
00241 {
00242     HFD_t hfd = (HFD_t) headerFreeData;
00243     HAE_t hae = (HAE_t) headerAddEntry;
00244     HeaderIterator hi;
00245     int_32 tag, type, count;
00246     const void * ptr;
00247     int xx;
00248 
00249     for (hi = headerInitIterator(sigh);
00250         headerNextIterator(hi, &tag, &type, &ptr, &count);
00251         ptr = hfd(ptr, type))
00252     {
00253         switch (tag) {
00254         /* XXX Translate legacy signature tag values. */
00255         case RPMSIGTAG_SIZE:
00256             tag = RPMTAG_SIGSIZE;
00257             /*@switchbreak@*/ break;
00258         case RPMSIGTAG_LEMD5_1:
00259             tag = RPMTAG_SIGLEMD5_1;
00260             /*@switchbreak@*/ break;
00261         case RPMSIGTAG_PGP:
00262             tag = RPMTAG_SIGPGP;
00263             /*@switchbreak@*/ break;
00264         case RPMSIGTAG_LEMD5_2:
00265             tag = RPMTAG_SIGLEMD5_2;
00266             /*@switchbreak@*/ break;
00267         case RPMSIGTAG_MD5:
00268             tag = RPMTAG_SIGMD5;
00269             /*@switchbreak@*/ break;
00270         case RPMSIGTAG_GPG:
00271             tag = RPMTAG_SIGGPG;
00272             /*@switchbreak@*/ break;
00273         case RPMSIGTAG_PGP5:
00274             tag = RPMTAG_SIGPGP5;
00275             /*@switchbreak@*/ break;
00276         case RPMSIGTAG_PAYLOADSIZE:
00277             tag = RPMTAG_ARCHIVESIZE;
00278             /*@switchbreak@*/ break;
00279         case RPMSIGTAG_SHA1:
00280         case RPMSIGTAG_DSA:
00281         case RPMSIGTAG_RSA:
00282         default:
00283             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00284                 continue;
00285             /*@switchbreak@*/ break;
00286         }
00287         if (ptr == NULL) continue;      /* XXX can't happen */
00288         if (!headerIsEntry(h, tag)) {
00289             if (hdrchkType(type))
00290                 continue;
00291             if (count < 0 || hdrchkData(count))
00292                 continue;
00293             switch(type) {
00294             case RPM_NULL_TYPE:
00295                 continue;
00296                 /*@notreached@*/ /*@switchbreak@*/ break;
00297             case RPM_CHAR_TYPE:
00298             case RPM_INT8_TYPE:
00299             case RPM_INT16_TYPE:
00300             case RPM_INT32_TYPE:
00301                 if (count != 1)
00302                     continue;
00303                 /*@switchbreak@*/ break;
00304             case RPM_STRING_TYPE:
00305             case RPM_BIN_TYPE:
00306                 if (count >= 16*1024)
00307                     continue;
00308                 /*@switchbreak@*/ break;
00309             case RPM_STRING_ARRAY_TYPE:
00310             case RPM_I18NSTRING_TYPE:
00311                 continue;
00312                 /*@notreached@*/ /*@switchbreak@*/ break;
00313             }
00314             xx = hae(h, tag, type, ptr, count);
00315         }
00316     }
00317     hi = headerFreeIterator(hi);
00318 }
00319 
00320 Header headerRegenSigHeader(const Header h, int noArchiveSize)
00321 {
00322     HFD_t hfd = (HFD_t) headerFreeData;
00323     Header sigh = rpmNewSignature();
00324     HeaderIterator hi;
00325     int_32 tag, stag, type, count;
00326     const void * ptr;
00327     int xx;
00328 
00329     for (hi = headerInitIterator(h);
00330         headerNextIterator(hi, &tag, &type, &ptr, &count);
00331         ptr = hfd(ptr, type))
00332     {
00333         switch (tag) {
00334         /* XXX Translate legacy signature tag values. */
00335         case RPMTAG_SIGSIZE:
00336             stag = RPMSIGTAG_SIZE;
00337             /*@switchbreak@*/ break;
00338         case RPMTAG_SIGLEMD5_1:
00339             stag = RPMSIGTAG_LEMD5_1;
00340             /*@switchbreak@*/ break;
00341         case RPMTAG_SIGPGP:
00342             stag = RPMSIGTAG_PGP;
00343             /*@switchbreak@*/ break;
00344         case RPMTAG_SIGLEMD5_2:
00345             stag = RPMSIGTAG_LEMD5_2;
00346             /*@switchbreak@*/ break;
00347         case RPMTAG_SIGMD5:
00348             stag = RPMSIGTAG_MD5;
00349             /*@switchbreak@*/ break;
00350         case RPMTAG_SIGGPG:
00351             stag = RPMSIGTAG_GPG;
00352             /*@switchbreak@*/ break;
00353         case RPMTAG_SIGPGP5:
00354             stag = RPMSIGTAG_PGP5;
00355             /*@switchbreak@*/ break;
00356         case RPMTAG_ARCHIVESIZE:
00357             /* XXX rpm-4.1 and later has archive size in signature header. */
00358             if (noArchiveSize)
00359                 continue;
00360             stag = RPMSIGTAG_PAYLOADSIZE;
00361             /*@switchbreak@*/ break;
00362         case RPMTAG_SHA1HEADER:
00363         case RPMTAG_DSAHEADER:
00364         case RPMTAG_RSAHEADER:
00365         default:
00366             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00367                 continue;
00368             stag = tag;
00369             /*@switchbreak@*/ break;
00370         }
00371         if (ptr == NULL) continue;      /* XXX can't happen */
00372         if (!headerIsEntry(sigh, stag))
00373             xx = headerAddEntry(sigh, stag, type, ptr, count);
00374     }
00375     hi = headerFreeIterator(hi);
00376     return sigh;
00377 }
00378 
00384 static int rpmtsStashKeyid(rpmts ts)
00385         /*@globals nextkeyid, nkeyids, keyids @*/
00386         /*@modifies nextkeyid, nkeyids, keyids @*/
00387 {
00388     const void * sig = rpmtsSig(ts);
00389     pgpDig dig = rpmtsDig(ts);
00390     pgpDigParams sigp = rpmtsSignature(ts);
00391     unsigned int keyid;
00392     int i;
00393 
00394     if (sig == NULL || dig == NULL || sigp == NULL)
00395         return 0;
00396 
00397     keyid = pgpGrab(sigp->signid+4, 4);
00398     if (keyid == 0)
00399         return 0;
00400 
00401     if (keyids != NULL)
00402     for (i = 0; i < nkeyids; i++) {
00403 /*@-boundsread@*/
00404         if (keyid == keyids[i])
00405             return 1;
00406 /*@=boundsread@*/
00407     }
00408 
00409     if (nkeyids < nkeyids_max) {
00410         nkeyids++;
00411         keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
00412     }
00413 /*@-boundswrite@*/
00414     if (keyids)         /* XXX can't happen */
00415         keyids[nextkeyid] = keyid;
00416 /*@=boundswrite@*/
00417     nextkeyid++;
00418     nextkeyid %= nkeyids_max;
00419 
00420     return 0;
00421 }
00422 
00423 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
00424 {
00425 /*@-castexpose@*/
00426     entryInfo pe = (entryInfo) pev;
00427 /*@=castexpose@*/
00428     entryInfo info = iv;
00429     int i;
00430 
00431 /*@-boundsread@*/
00432     for (i = 0; i < il; i++) {
00433         info->tag = ntohl(pe[i].tag);
00434         info->type = ntohl(pe[i].type);
00435         info->offset = ntohl(pe[i].offset);
00436         if (negate)
00437             info->offset = -info->offset;
00438         info->count = ntohl(pe[i].count);
00439 
00440         if (hdrchkType(info->type))
00441             return i;
00442         if (hdrchkAlign(info->type, info->offset))
00443             return i;
00444         if (!negate && hdrchkRange(dl, info->offset))
00445             return i;
00446         if (hdrchkData(info->count))
00447             return i;
00448 
00449     }
00450 /*@=boundsread@*/
00451     return -1;
00452 }
00453 
00467 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00468 {
00469     pgpDig dig;
00470     unsigned char buf[8*BUFSIZ];
00471     int_32 * ei = (int_32 *) uh;
00472 /*@-boundsread@*/
00473     int_32 il = ntohl(ei[0]);
00474     int_32 dl = ntohl(ei[1]);
00475 /*@-castexpose@*/
00476     entryInfo pe = (entryInfo) &ei[2];
00477 /*@=castexpose@*/
00478 /*@=boundsread@*/
00479     int_32 ildl[2];
00480     int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00481     unsigned char * dataStart = (unsigned char *) (pe + il);
00482     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00483     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00484     const void * sig = NULL;
00485     const char * b;
00486     rpmVSFlags vsflags = rpmtsVSFlags(ts);
00487     int siglen = 0;
00488     int blen;
00489     size_t nb;
00490     int_32 ril = 0;
00491     unsigned char * regionEnd = NULL;
00492     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00493     int xx;
00494     int i;
00495     static int hclvl;
00496 
00497     hclvl++;
00498 /*@-boundswrite@*/
00499     buf[0] = '\0';
00500 /*@=boundswrite@*/
00501 
00502     /* Is the blob the right size? */
00503     if (uc > 0 && pvlen != uc) {
00504         (void) snprintf(buf, sizeof(buf),
00505                 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
00506                 (int)uc, (int)il, (int)dl);
00507         goto exit;
00508     }
00509 
00510     /* Check (and convert) the 1st tag element. */
00511     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00512     if (xx != -1) {
00513         (void) snprintf(buf, sizeof(buf),
00514                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00515                 0, entry->info.tag, entry->info.type,
00516                 entry->info.offset, entry->info.count);
00517         goto exit;
00518     }
00519 
00520     /* Is there an immutable header region tag? */
00521 /*@-sizeoftype@*/
00522     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00523        && entry->info.type == RPM_BIN_TYPE
00524        && entry->info.count == REGION_TAG_COUNT))
00525     {
00526         rc = RPMRC_NOTFOUND;
00527         goto exit;
00528     }
00529 /*@=sizeoftype@*/
00530 
00531     /* Is the offset within the data area? */
00532     if (entry->info.offset >= dl) {
00533         (void) snprintf(buf, sizeof(buf),
00534                 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
00535                 entry->info.tag, entry->info.type,
00536                 entry->info.offset, entry->info.count);
00537         goto exit;
00538     }
00539 
00540     /* Is there an immutable header region tag trailer? */
00541     regionEnd = dataStart + entry->info.offset;
00542 /*@-sizeoftype@*/
00543 /*@-bounds@*/
00544     (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00545 /*@=bounds@*/
00546     regionEnd += REGION_TAG_COUNT;
00547 
00548     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00549     if (xx != -1 ||
00550         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00551        && entry->info.type == RPM_BIN_TYPE
00552        && entry->info.count == REGION_TAG_COUNT))
00553     {
00554         (void) snprintf(buf, sizeof(buf),
00555                 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00556                 entry->info.tag, entry->info.type,
00557                 entry->info.offset, entry->info.count);
00558         goto exit;
00559     }
00560 /*@=sizeoftype@*/
00561 /*@-boundswrite@*/
00562     memset(info, 0, sizeof(*info));
00563 /*@=boundswrite@*/
00564 
00565     /* Is the no. of tags in the region less than the total no. of tags? */
00566     ril = entry->info.offset/sizeof(*pe);
00567     if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00568         (void) snprintf(buf, sizeof(buf),
00569                 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00570         goto exit;
00571     }
00572 
00573     /* Find a header-only digest/signature tag. */
00574     for (i = ril; i < il; i++) {
00575         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00576         if (xx != -1) {
00577             (void) snprintf(buf, sizeof(buf),
00578                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00579                 i, entry->info.tag, entry->info.type,
00580                 entry->info.offset, entry->info.count);
00581             goto exit;
00582         }
00583 
00584         switch (entry->info.tag) {
00585         case RPMTAG_SHA1HEADER:
00586             if (vsflags & RPMVSF_NOSHA1HEADER)
00587                 /*@switchbreak@*/ break;
00588             blen = 0;
00589 /*@-boundsread@*/
00590             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00591                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00592                     /*@innerbreak@*/ break;
00593                 blen++;
00594             }
00595             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00596             {
00597                 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
00598                 goto exit;
00599             }
00600 /*@=boundsread@*/
00601             if (info->tag == 0) {
00602 /*@-boundswrite@*/
00603                 *info = entry->info;    /* structure assignment */
00604 /*@=boundswrite@*/
00605                 siglen = blen + 1;
00606             }
00607             /*@switchbreak@*/ break;
00608         case RPMTAG_RSAHEADER:
00609             if (vsflags & RPMVSF_NORSAHEADER)
00610                 /*@switchbreak@*/ break;
00611             if (entry->info.type != RPM_BIN_TYPE) {
00612                 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
00613                 goto exit;
00614             }
00615 /*@-boundswrite@*/
00616             *info = entry->info;        /* structure assignment */
00617 /*@=boundswrite@*/
00618             siglen = info->count;
00619             /*@switchbreak@*/ break;
00620         case RPMTAG_DSAHEADER:
00621             if (vsflags & RPMVSF_NODSAHEADER)
00622                 /*@switchbreak@*/ break;
00623             if (entry->info.type != RPM_BIN_TYPE) {
00624                 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00625                 goto exit;
00626             }
00627 /*@-boundswrite@*/
00628             *info = entry->info;        /* structure assignment */
00629 /*@=boundswrite@*/
00630             siglen = info->count;
00631             /*@switchbreak@*/ break;
00632         default:
00633             /*@switchbreak@*/ break;
00634         }
00635     }
00636     rc = RPMRC_NOTFOUND;
00637 
00638 exit:
00639     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
00640     if (rc != RPMRC_NOTFOUND) {
00641 /*@-boundswrite@*/
00642         buf[sizeof(buf)-1] = '\0';
00643         if (msg) *msg = xstrdup(buf);
00644 /*@=boundswrite@*/
00645         hclvl--;
00646         return rc;
00647     }
00648 
00649     /* If no header-only digest/signature, then do simple sanity check. */
00650     if (info->tag == 0) {
00651 verifyinfo_exit:
00652         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00653         if (xx != -1) {
00654             (void) snprintf(buf, sizeof(buf),
00655                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00656                 xx+1, entry->info.tag, entry->info.type,
00657                 entry->info.offset, entry->info.count);
00658             rc = RPMRC_FAIL;
00659         } else {
00660             (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00661             rc = RPMRC_OK;
00662         }
00663 /*@-boundswrite@*/
00664         buf[sizeof(buf)-1] = '\0';
00665         if (msg) *msg = xstrdup(buf);
00666 /*@=boundswrite@*/
00667         hclvl--;
00668         return rc;
00669     }
00670 
00671     /* Verify header-only digest/signature. */
00672     dig = rpmtsDig(ts);
00673     if (dig == NULL)
00674         goto verifyinfo_exit;
00675     dig->nbytes = 0;
00676 
00677 /*@-boundsread@*/
00678     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00679 /*@=boundsread@*/
00680     (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00681 
00682     switch (info->tag) {
00683     case RPMTAG_RSAHEADER:
00684         /* Parse the parameters from the OpenPGP packets that will be needed. */
00685         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00686         if (dig->signature.version != 3 && dig->signature.version != 4) {
00687             rpmMessage(RPMMESS_WARNING,
00688                 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00689                 dig->signature.version);
00690             rpmtsCleanDig(ts);
00691             goto verifyinfo_exit;
00692         }
00693 
00694         ildl[0] = htonl(ril);
00695         ildl[1] = (regionEnd - dataStart);
00696         ildl[1] = htonl(ildl[1]);
00697 
00698         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00699         dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00700 
00701         b = (unsigned char *) header_magic;
00702         nb = sizeof(header_magic);
00703         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00704         dig->nbytes += nb;
00705 
00706         b = (unsigned char *) ildl;
00707         nb = sizeof(ildl);
00708         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00709         dig->nbytes += nb;
00710 
00711         b = (unsigned char *) pe;
00712         nb = (htonl(ildl[0]) * sizeof(*pe));
00713         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00714         dig->nbytes += nb;
00715 
00716         b = (unsigned char *) dataStart;
00717         nb = htonl(ildl[1]);
00718         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00719         dig->nbytes += nb;
00720         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00721 
00722         break;
00723     case RPMTAG_DSAHEADER:
00724         /* Parse the parameters from the OpenPGP packets that will be needed. */
00725         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00726         if (dig->signature.version != 3 && dig->signature.version != 4) {
00727             rpmMessage(RPMMESS_WARNING,
00728                 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00729                 dig->signature.version);
00730             rpmtsCleanDig(ts);
00731             goto verifyinfo_exit;
00732         }
00733         /*@fallthrough@*/
00734     case RPMTAG_SHA1HEADER:
00735 /*@-boundswrite@*/
00736         ildl[0] = htonl(ril);
00737         ildl[1] = (regionEnd - dataStart);
00738         ildl[1] = htonl(ildl[1]);
00739 /*@=boundswrite@*/
00740 
00741         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00742         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00743 
00744         b = (unsigned char *) header_magic;
00745         nb = sizeof(header_magic);
00746         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00747         dig->nbytes += nb;
00748 
00749         b = (unsigned char *) ildl;
00750         nb = sizeof(ildl);
00751         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00752         dig->nbytes += nb;
00753 
00754         b = (unsigned char *) pe;
00755         nb = (htonl(ildl[0]) * sizeof(*pe));
00756         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00757         dig->nbytes += nb;
00758 
00759         b = (unsigned char *) dataStart;
00760         nb = htonl(ildl[1]);
00761         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00762         dig->nbytes += nb;
00763         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00764 
00765         break;
00766     default:
00767         sig = _free(sig);
00768         break;
00769     }
00770 
00771 /*@-boundswrite@*/
00772     buf[0] = '\0';
00773 /*@=boundswrite@*/
00774     rc = rpmVerifySignature(ts, buf);
00775 
00776 /*@-boundswrite@*/
00777     buf[sizeof(buf)-1] = '\0';
00778     if (msg) *msg = xstrdup(buf);
00779 /*@=boundswrite@*/
00780 
00781     /* XXX headerCheck can recurse, free info only at top level. */
00782     if (hclvl == 1)
00783         rpmtsCleanDig(ts);
00784     if (info->tag == RPMTAG_SHA1HEADER)
00785         sig = _free(sig);
00786     hclvl--;
00787     return rc;
00788 }
00789 
00790 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00791 {
00792     char buf[BUFSIZ];
00793     int_32 block[4];
00794     int_32 il;
00795     int_32 dl;
00796     int_32 * ei = NULL;
00797     size_t uc;
00798     int_32 nb;
00799     Header h = NULL;
00800     const char * origin = NULL;
00801     rpmRC rc = RPMRC_FAIL;              /* assume failure */
00802     int xx;
00803 
00804 /*@-boundswrite@*/
00805     buf[0] = '\0';
00806 
00807     if (hdrp)
00808         *hdrp = NULL;
00809     if (msg)
00810         *msg = NULL;
00811 /*@=boundswrite@*/
00812 
00813     memset(block, 0, sizeof(block));
00814     if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00815         (void) snprintf(buf, sizeof(buf),
00816                 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00817         goto exit;
00818     }
00819     if (memcmp(block, header_magic, sizeof(header_magic))) {
00820         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00821         goto exit;
00822     }
00823 /*@-boundsread@*/
00824     il = ntohl(block[2]);
00825 /*@=boundsread@*/
00826     if (hdrchkTags(il)) {
00827         (void) snprintf(buf, sizeof(buf),
00828                 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00829 
00830         goto exit;
00831     }
00832 /*@-boundsread@*/
00833     dl = ntohl(block[3]);
00834 /*@=boundsread@*/
00835     if (hdrchkData(dl)) {
00836         (void) snprintf(buf, sizeof(buf),
00837                 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00838         goto exit;
00839     }
00840 
00841 /*@-sizeoftype@*/
00842     nb = (il * sizeof(struct entryInfo_s)) + dl;
00843 /*@=sizeoftype@*/
00844     uc = sizeof(il) + sizeof(dl) + nb;
00845     ei = xmalloc(uc);
00846 /*@-bounds@*/
00847     ei[0] = block[2];
00848     ei[1] = block[3];
00849     if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00850         (void) snprintf(buf, sizeof(buf),
00851                 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00852         goto exit;
00853     }
00854 /*@=bounds@*/
00855 
00856     /* Sanity check header tags */
00857     rc = headerCheck(ts, ei, uc, msg);
00858     if (rc != RPMRC_OK)
00859         goto exit;
00860 
00861     /* OK, blob looks sane, load the header. */
00862     h = headerLoad(ei);
00863     if (h == NULL) {
00864         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00865         goto exit;
00866     }
00867     h->flags |= HEADERFLAG_ALLOCATED;
00868     ei = NULL;  /* XXX will be freed with header */
00869 
00870     /* Save the opened path as the header origin. */
00871     origin = fdGetOPath(fd);
00872     if (origin != NULL)
00873         (void) headerSetOrigin(h, origin);
00874     
00875 exit:
00876 /*@-boundswrite@*/
00877     if (hdrp && h && rc == RPMRC_OK)
00878         *hdrp = headerLink(h);
00879 /*@=boundswrite@*/
00880     ei = _free(ei);
00881     h = headerFree(h);
00882 
00883 /*@-boundswrite@*/
00884     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00885         buf[sizeof(buf)-1] = '\0';
00886         *msg = xstrdup(buf);
00887     }
00888 /*@=boundswrite@*/
00889 
00890     return rc;
00891 }
00892 
00893 /*@-bounds@*/   /* LCL: segfault */
00894 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00895 {
00896     pgpDig dig;
00897     byte buf[8*BUFSIZ];
00898     ssize_t count;
00899     struct rpmlead * l = alloca(sizeof(*l));
00900     Header sigh = NULL;
00901     int_32 sigtag;
00902     int_32 sigtype;
00903     const void * sig;
00904     int_32 siglen;
00905     rpmtsOpX opx;
00906     size_t nb;
00907     Header h = NULL;
00908     const char * msg;
00909     rpmVSFlags vsflags;
00910     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00911     rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
00912     int xx;
00913     int i;
00914 
00915     if (hdrp) *hdrp = NULL;
00916 
00917 #ifdef  DYING
00918     {   struct stat st;
00919 /*@-boundswrite@*/
00920         memset(&st, 0, sizeof(st));
00921 /*@=boundswrite@*/
00922         (void) fstat(Fileno(fd), &st);
00923         /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
00924         if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00925             rc = RPMRC_NOTFOUND;
00926             goto exit;
00927         }
00928     }
00929 #endif
00930 
00931     /* Snapshot current I/O counters (cached persistent I/O reuses counters) */
00932     (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
00933 
00934     memset(l, 0, sizeof(*l));
00935     rc = readLead(fd, l);
00936     if (rc != RPMRC_OK)
00937         goto exit;
00938 
00939     switch (l->major) {
00940     case 1:
00941         rpmError(RPMERR_NEWPACKAGE,
00942             _("packaging version 1 is not supported by this version of RPM\n"));
00943         rc = RPMRC_NOTFOUND;
00944         goto exit;
00945         /*@notreached@*/ break;
00946     case 2:
00947     case 3:
00948     case 4:
00949         break;
00950     default:
00951         rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00952                 "is supported by this version of RPM\n"));
00953         rc = RPMRC_NOTFOUND;
00954         goto exit;
00955         /*@notreached@*/ break;
00956     }
00957 
00958     /* Read the signature header. */
00959     msg = NULL;
00960     rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00961     switch (rc) {
00962     default:
00963         rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00964                 (msg && *msg ? msg : "\n"));
00965         msg = _free(msg);
00966         goto exit;
00967         /*@notreached@*/ break;
00968     case RPMRC_OK:
00969         if (sigh == NULL) {
00970             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00971             rc = RPMRC_FAIL;
00972             goto exit;
00973         }
00974         break;
00975     }
00976     msg = _free(msg);
00977 
00978 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
00979 
00980     /*
00981      * Figger the most effective available signature.
00982      * Prefer signatures over digests, then header-only over header+payload.
00983      * DSA will be preferred over RSA if both exist because tested first.
00984      * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
00985      */
00986     sigtag = 0;
00987     opx = 0;
00988     vsflags = rpmtsVSFlags(ts);
00989     if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
00990         sigtag = RPMSIGTAG_DSA;
00991     } else
00992     if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
00993         sigtag = RPMSIGTAG_RSA;
00994     } else
00995     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00996         headerIsEntry(sigh, RPMSIGTAG_GPG))
00997     {
00998         sigtag = RPMSIGTAG_GPG;
00999         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
01000         opx = RPMTS_OP_SIGNATURE;
01001     } else
01002     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
01003         headerIsEntry(sigh, RPMSIGTAG_PGP))
01004     {
01005         sigtag = RPMSIGTAG_PGP;
01006         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
01007         opx = RPMTS_OP_SIGNATURE;
01008     } else
01009     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
01010         sigtag = RPMSIGTAG_SHA1;
01011     } else
01012     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
01013         headerIsEntry(sigh, RPMSIGTAG_MD5))
01014     {
01015         sigtag = RPMSIGTAG_MD5;
01016         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
01017         opx = RPMTS_OP_DIGEST;
01018     }
01019 
01020     /* Read the metadata, computing digest(s) on the fly. */
01021     h = NULL;
01022     msg = NULL;
01023 
01024     /* XXX stats will include header i/o and setup overhead. */
01025     /* XXX repackaged packages have appended tags, legacy dig/sig check fails */
01026     if (opx > 0)
01027         (void) rpmswEnter(rpmtsOp(ts, opx), 0);
01028 /*@-type@*/     /* XXX arrow access of non-pointer (FDSTAT_t) */
01029     nb = -fd->stats->ops[FDSTAT_READ].bytes;
01030     rc = rpmReadHeader(ts, fd, &h, &msg);
01031     nb += fd->stats->ops[FDSTAT_READ].bytes;
01032 /*@=type@*/
01033     if (opx > 0)
01034         (void) rpmswExit(rpmtsOp(ts, opx), nb);
01035 
01036     if (rc != RPMRC_OK || h == NULL) {
01037         rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
01038                 (msg && *msg ? msg : "\n"));
01039         msg = _free(msg);
01040         goto exit;
01041     }
01042     msg = _free(msg);
01043 
01044     /* Any digests or signatures to check? */
01045     if (sigtag == 0) {
01046         rc = RPMRC_OK;
01047         goto exit;
01048     }
01049 
01050     dig = rpmtsDig(ts);
01051     if (dig == NULL) {
01052         rc = RPMRC_FAIL;
01053         goto exit;
01054     }
01055     dig->nbytes = 0;
01056 
01057     /* Retrieve the tag parameters from the signature header. */
01058     sig = NULL;
01059     xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
01060     if (sig == NULL) {
01061         rc = RPMRC_FAIL;
01062         goto exit;
01063     }
01064     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
01065 
01066     switch (sigtag) {
01067     case RPMSIGTAG_RSA:
01068         /* Parse the parameters from the OpenPGP packets that will be needed. */
01069         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01070         if (dig->signature.version != 3 && dig->signature.version != 4) {
01071             rpmMessage(RPMMESS_WARNING,
01072                 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01073                 dig->signature.version);
01074             rc = RPMRC_OK;      /* XXX return header w/o verify */
01075             goto exit;
01076         }
01077     {   void * uh = NULL;
01078         int_32 uht;
01079         int_32 uhc;
01080 
01081         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01082             break;
01083         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01084         dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
01085         (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
01086         dig->nbytes += sizeof(header_magic);
01087         (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
01088         dig->nbytes += uhc;
01089         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01090         rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;  /* XXX one too many */
01091         uh = headerFreeData(uh, uht);
01092     }   break;
01093     case RPMSIGTAG_DSA:
01094         /* Parse the parameters from the OpenPGP packets that will be needed. */
01095         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01096         if (dig->signature.version != 3 && dig->signature.version != 4) {
01097             rpmMessage(RPMMESS_WARNING,
01098                 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01099                 dig->signature.version);
01100             rc = RPMRC_OK;      /* XXX return header w/o verify */
01101             goto exit;
01102         }
01103         /*@fallthrough@*/
01104     case RPMSIGTAG_SHA1:
01105     {   void * uh = NULL;
01106         int_32 uht;
01107         int_32 uhc;
01108 
01109         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01110             break;
01111         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01112         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
01113         (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
01114         dig->nbytes += sizeof(header_magic);
01115         (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
01116         dig->nbytes += uhc;
01117         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01118         if (sigtag == RPMSIGTAG_SHA1)
01119             rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;      /* XXX one too many */
01120         uh = headerFreeData(uh, uht);
01121     }   break;
01122     case RPMSIGTAG_GPG:
01123     case RPMSIGTAG_PGP5:        /* XXX legacy */
01124     case RPMSIGTAG_PGP:
01125         /* Parse the parameters from the OpenPGP packets that will be needed. */
01126         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01127 
01128         if (dig->signature.version != 3 && dig->signature.version != 4) {
01129             rpmMessage(RPMMESS_WARNING,
01130                 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01131                 dig->signature.version);
01132             rc = RPMRC_OK;      /* XXX return header w/o verify */
01133             goto exit;
01134         }
01135         /*@fallthrough@*/
01136     case RPMSIGTAG_MD5:
01137         /* Legacy signatures need the compressed payload in the digest too. */
01138         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01139         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
01140             dig->nbytes += count;
01141         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01142         rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;  /* XXX one too many */
01143         dig->nbytes += nb;      /* XXX include size of header blob. */
01144         if (count < 0) {
01145             rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
01146                                         fn, Fstrerror(fd));
01147             rc = RPMRC_FAIL;
01148             goto exit;
01149         }
01150 
01151         /* XXX Steal the digest-in-progress from the file handle. */
01152         for (i = fd->ndigests - 1; i >= 0; i--) {
01153             FDDIGEST_t fddig = fd->digests + i;
01154             if (fddig->hashctx != NULL)
01155             switch (fddig->hashalgo) {
01156             case PGPHASHALGO_MD5:
01157                 dig->md5ctx = fddig->hashctx;
01158                 fddig->hashctx = NULL;
01159                 /*@switchbreak@*/ break;
01160             case PGPHASHALGO_SHA1:
01161             case PGPHASHALGO_RIPEMD160:
01162 #if HAVE_BEECRYPT_API_H
01163             case PGPHASHALGO_SHA256:
01164             case PGPHASHALGO_SHA384:
01165             case PGPHASHALGO_SHA512:
01166 #endif
01167                 dig->sha1ctx = fddig->hashctx;
01168                 fddig->hashctx = NULL;
01169                 /*@switchbreak@*/ break;
01170             default:
01171                 /*@switchbreak@*/ break;
01172             }
01173         }
01174         break;
01175     }
01176 
01179 /*@-boundswrite@*/
01180     buf[0] = '\0';
01181 /*@=boundswrite@*/
01182     rc = rpmVerifySignature(ts, buf);
01183     switch (rc) {
01184     case RPMRC_OK:              /* Signature is OK. */
01185         rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01186         break;
01187     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
01188     case RPMRC_NOKEY:           /* Public key is unavailable. */
01189         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
01190     {   int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01191         rpmMessage(lvl, "%s: %s", fn, buf);
01192     }   break;
01193     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
01194         rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01195         break;
01196     default:
01197     case RPMRC_FAIL:            /* Signature does not verify. */
01198         rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01199         break;
01200     }
01201 
01202 exit:
01203     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01204 
01205         /* Append (and remap) signature tags to the metadata. */
01206         headerMergeLegacySigs(h, sigh);
01207 
01208     rpm3to4(h);
01209 
01210         /* Bump reference count for return. */
01211 /*@-boundswrite@*/
01212         *hdrp = headerLink(h);
01213 /*@=boundswrite@*/
01214     }
01215     h = headerFree(h);
01216 
01217     /* Accumulate time reading package header. */
01218     (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
01219                 fdstat_op(fd, FDSTAT_READ));
01220     (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
01221                 opsave);
01222 
01223     rpmtsCleanDig(ts);
01224     sigh = rpmFreeSignature(sigh);
01225     return rc;
01226 }
01227 /*@=bounds@*/

Generated on Mon Aug 3 15:18:58 2009 for rpm by  doxygen 1.5.1