rpm 5.3.7

build/pack.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmio_internal.h>     /* XXX fdGetFp, fdInitDigest, fdFiniDigest */
00009 #include <rpmcb.h>
00010 #include <argv.h>
00011 
00012 #include <rpmtypes.h>
00013 #include <rpmtag.h>
00014 
00015 #include <pkgio.h>
00016 #include "signature.h"          /* XXX rpmTempFile */
00017 
00018 #define _RPMFI_INTERNAL         /* XXX fi->fsm */
00019 #define _RPMEVR_INTERNAL        /* XXX RPMSENSE_ANY */
00020 #define _RPMTAG_INTERNAL
00021 #include <rpmbuild.h>
00022 
00023 #include "rpmfi.h"
00024 #include "fsm.h"
00025 
00026 #include <rpmversion.h>
00027 #include "buildio.h"
00028 
00029 #include "debug.h"
00030 
00031 /*@access rpmts @*/
00032 /*@access rpmfi @*/     /* compared with NULL */
00033 /*@access Header @*/    /* compared with NULL */
00034 /*@access FD_t @*/      /* compared with NULL */
00035 /*@access CSA_t @*/
00036 
00040 static rpmRC cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
00041                 const char * payload_format, const char * fmodeMacro)
00042         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00043         /*@modifies fdo, csa, rpmGlobalMacroContext,
00044                 fileSystem, internalState @*/
00045 {
00046     rpmts ts = rpmtsCreate();
00047     rpmfi fi = csa->fi;
00048     const char *failedFile = NULL;
00049     FD_t cfd;
00050     rpmRC rc = RPMRC_OK;
00051     int xx;
00052 
00053     {   const char *fmode = rpmExpand(fmodeMacro, NULL);
00054         if (!(fmode && fmode[0] == 'w'))
00055             fmode = xstrdup("w9.gzdio");
00056         /*@-nullpass@*/
00057         (void) Fflush(fdo);
00058         cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
00059         /*@=nullpass@*/
00060         fmode = _free(fmode);
00061     }
00062     if (cfd == NULL)
00063         return RPMRC_FAIL;
00064 
00065     xx = fsmSetup(fi->fsm, IOSM_PKGBUILD, payload_format, ts, fi, cfd,
00066                 &csa->cpioArchiveSize, &failedFile);
00067     if (xx)
00068         rc = RPMRC_FAIL;
00069     (void) Fclose(cfd);
00070     xx = fsmTeardown(fi->fsm);
00071     if (rc == RPMRC_OK && xx) rc = RPMRC_FAIL;
00072 
00073     if (rc) {
00074         const char * msg = iosmStrerror(rc);
00075         if (failedFile)
00076             rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
00077                 failedFile, msg);
00078         else
00079             rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), msg);
00080         msg = _free(msg);
00081         rc = RPMRC_FAIL;
00082     }
00083 
00084     failedFile = _free(failedFile);
00085     (void)rpmtsFree(ts); 
00086     ts = NULL;
00087 
00088     return rc;
00089 }
00090 
00093 static rpmRC cpio_copy(FD_t fdo, CSA_t csa)
00094         /*@globals fileSystem, internalState @*/
00095         /*@modifies fdo, csa, fileSystem, internalState @*/
00096 {
00097     char buf[BUFSIZ];
00098     size_t nb;
00099 
00100     while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
00101         if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
00102             rpmlog(RPMLOG_ERR, _("cpio_copy write failed: %s\n"),
00103                         Fstrerror(fdo));
00104             return RPMRC_FAIL;
00105         }
00106         csa->cpioArchiveSize += nb;
00107     }
00108     if (Ferror(csa->cpioFdIn)) {
00109         rpmlog(RPMLOG_ERR, _("cpio_copy read failed: %s\n"),
00110                 Fstrerror(csa->cpioFdIn));
00111         return RPMRC_FAIL;
00112     }
00113     return RPMRC_OK;
00114 }
00115 
00118 static /*@only@*/ /*@null@*/ rpmiob addFileToTagAux(Spec spec,
00119                 const char * file, /*@only@*/ rpmiob iob)
00120         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00121         /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
00122 {
00123     char buf[BUFSIZ];
00124     const char * fn = buf;
00125     FILE * f;
00126     FD_t fd;
00127 
00128     fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);
00129 
00130     fd = Fopen(fn, "r.fdio");
00131     if (fn != buf) fn = _free(fn);
00132     if (fd == NULL || Ferror(fd)) {
00133         iob = rpmiobFree(iob);
00134         return NULL;
00135     }
00136     /*@-type@*/ /* FIX: cast? */
00137     if ((f = fdGetFp(fd)) != NULL)
00138     /*@=type@*/
00139     while (fgets(buf, (int)sizeof(buf), f)) {
00140         /* XXX display fn in error msg */
00141         if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
00142             rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
00143             iob = rpmiobFree(iob);
00144             break;
00145         }
00146         iob = rpmiobAppend(iob, buf, 0);
00147     }
00148     (void) Fclose(fd);
00149 
00150     return iob;
00151 }
00152 
00155 static int addFileToTag(Spec spec, const char * file, Header h, rpmTag tag)
00156         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00157         /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
00158 {
00159     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00160     rpmiob iob = rpmiobNew(0);
00161     int xx;
00162 
00163     he->tag = tag;
00164     xx = headerGet(h, he, 0);
00165     if (xx) {
00166         iob = rpmiobAppend(iob, he->p.str, 1);
00167         xx = headerDel(h, he, 0);
00168     }
00169     he->p.ptr = _free(he->p.ptr);
00170 
00171     if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
00172         return 1;
00173     
00174     he->tag = tag;
00175     he->t = RPM_STRING_TYPE;
00176     he->p.str = rpmiobStr(iob);
00177     he->c = 1;
00178     xx = headerPut(h, he, 0);
00179 
00180     iob = rpmiobFree(iob);
00181     return 0;
00182 }
00183 
00186 static int addFileToArrayTag(Spec spec, const char *file, Header h, rpmTag tag)
00187         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00188         /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState  @*/
00189 {
00190     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00191     rpmiob iob = rpmiobNew(0);
00192     const char *s;
00193     int xx;
00194 
00195     if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
00196         return 1;
00197 
00198     s = rpmiobStr(iob);
00199 
00200     he->tag = tag;
00201     he->t = RPM_STRING_ARRAY_TYPE;
00202     he->p.argv = &s;
00203     he->c = 1;
00204     he->append = 1;
00205     xx = headerPut(h, he, 0);
00206     he->append = 0;
00207 
00208     iob = rpmiobFree(iob);
00209     return 0;
00210 }
00211 
00212 rpmRC processScriptFiles(Spec spec, Package pkg)
00213         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00214         /*@modifies pkg->header, rpmGlobalMacroContext,
00215                 fileSystem, internalState @*/
00216 {
00217     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00218     struct TriggerFileEntry *p;
00219     int xx;
00220     
00221     if (pkg->preInFile) {
00222         if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
00223             rpmlog(RPMLOG_ERR,
00224                      _("Could not open PreIn file: %s\n"), pkg->preInFile);
00225             return RPMRC_FAIL;
00226         }
00227     }
00228     if (pkg->preUnFile) {
00229         if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
00230             rpmlog(RPMLOG_ERR,
00231                      _("Could not open PreUn file: %s\n"), pkg->preUnFile);
00232             return RPMRC_FAIL;
00233         }
00234     }
00235     if (pkg->preTransFile) {
00236         if (addFileToTag(spec, pkg->preTransFile, pkg->header, RPMTAG_PRETRANS)) {
00237             rpmlog(RPMLOG_ERR,
00238                      _("Could not open PreTrans file: %s\n"), pkg->preTransFile);
00239             return RPMRC_FAIL;
00240         }
00241     }
00242     if (pkg->postInFile) {
00243         if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
00244             rpmlog(RPMLOG_ERR,
00245                      _("Could not open PostIn file: %s\n"), pkg->postInFile);
00246             return RPMRC_FAIL;
00247         }
00248     }
00249     if (pkg->postUnFile) {
00250         if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
00251             rpmlog(RPMLOG_ERR,
00252                      _("Could not open PostUn file: %s\n"), pkg->postUnFile);
00253             return RPMRC_FAIL;
00254         }
00255     }
00256     if (pkg->postTransFile) {
00257         if (addFileToTag(spec, pkg->postTransFile, pkg->header, RPMTAG_POSTTRANS)) {
00258             rpmlog(RPMLOG_ERR,
00259                      _("Could not open PostTrans file: %s\n"), pkg->postTransFile);
00260             return RPMRC_FAIL;
00261         }
00262     }
00263     if (pkg->verifyFile) {
00264         if (addFileToTag(spec, pkg->verifyFile, pkg->header,
00265                          RPMTAG_VERIFYSCRIPT)) {
00266             rpmlog(RPMLOG_ERR,
00267                      _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
00268             return RPMRC_FAIL;
00269         }
00270     }
00271 
00272     if (pkg->sanityCheckFile) {
00273         if (addFileToTag(spec, pkg->sanityCheckFile, pkg->header, RPMTAG_SANITYCHECK)) {
00274             rpmlog(RPMLOG_ERR, _("Could not open Test file: %s\n"), pkg->sanityCheckFile);
00275             return RPMRC_FAIL;
00276         }
00277     }
00278 
00279     for (p = pkg->triggerFiles; p != NULL; p = p->next) {
00280         he->tag = RPMTAG_TRIGGERSCRIPTPROG;
00281         he->t = RPM_STRING_ARRAY_TYPE;
00282         he->p.argv = (const char **)&p->prog;   /* XXX NOCAST */
00283         he->c = 1;
00284         he->append = 1;
00285         xx = headerPut(pkg->header, he, 0);
00286         he->append = 0;
00287         if (p->script) {
00288             he->tag = RPMTAG_TRIGGERSCRIPTS;
00289             he->t = RPM_STRING_ARRAY_TYPE;
00290             he->p.argv = (const char **)&p->script;     /* XXX NOCAST */
00291             he->c = 1;
00292             he->append = 1;
00293             xx = headerPut(pkg->header, he, 0);
00294             he->append = 0;
00295         } else if (p->fileName) {
00296             if (addFileToArrayTag(spec, p->fileName, pkg->header,
00297                                   RPMTAG_TRIGGERSCRIPTS)) {
00298                 rpmlog(RPMLOG_ERR,
00299                          _("Could not open Trigger script file: %s\n"),
00300                          p->fileName);
00301                 return RPMRC_FAIL;
00302             }
00303         } else {
00304             /*@observer@*/
00305             static const char *bull = "";
00306             he->tag = RPMTAG_TRIGGERSCRIPTS;
00307             he->t = RPM_STRING_ARRAY_TYPE;
00308             he->p.argv = &bull;
00309             he->c = 1;
00310             he->append = 1;
00311             xx = headerPut(pkg->header, he, 0);
00312             he->append = 0;
00313         }
00314     }
00315 
00316     return RPMRC_OK;
00317 }
00318 
00319 #if defined(DEAD)
00320 int readRPM(const char *fileName, Spec *specp, void * l,
00321                 Header *sigs, CSA_t csa)
00322 {
00323     const char * msg = "";
00324     FD_t fdi;
00325     Spec spec;
00326     rpmRC rc;
00327 
00328     fdi = (fileName != NULL)
00329         ? Fopen(fileName, "r.fdio")
00330         : fdDup(STDIN_FILENO);
00331 
00332     if (fdi == NULL || Ferror(fdi)) {
00333         rpmlog(RPMLOG_ERR, _("readRPM: open %s: %s\n"),
00334                 (fileName ? fileName : "<stdin>"),
00335                 Fstrerror(fdi));
00336         if (fdi) (void) Fclose(fdi);
00337         return RPMRC_FAIL;
00338     }
00339 
00340     {   const char item[] = "Lead";
00341         size_t nl = rpmpkgSizeof(item, NULL);
00342 
00343         if (nl == 0) {
00344             rc = RPMRC_FAIL;
00345             msg = xstrdup("item size is zero");
00346         } else {
00347             l = xcalloc(1, nl);         /* XXX memory leak */
00348             msg = NULL;
00349             rc = rpmpkgRead(item, fdi, l, &msg);
00350         }
00351     }
00352 
00353     if (rc != RPMRC_OK) {
00354         rpmlog(RPMLOG_ERR, _("readRPM: read %s: %s\n"),
00355                 (fileName ? fileName : "<stdin>"), msg);
00356         msg = _free(msg);
00357         return RPMRC_FAIL;
00358     }
00359     msg = _free(msg);
00360     /*@=sizeoftype@*/
00361 
00362     /* XXX FIXME: EPIPE on <stdin> */
00363     if (Fseek(fdi, 0, SEEK_SET) == -1) {
00364         rpmlog(RPMLOG_ERR, _("%s: Fseek failed: %s\n"),
00365                         (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
00366         return RPMRC_FAIL;
00367     }
00368 
00369     /* Reallocate build data structures */
00370     spec = newSpec();
00371     spec->packages = newPackage(spec);
00372 
00373     /* XXX the header just allocated will be allocated again */
00374     (void)headerFree(spec->packages->header);
00375     spec->packages->header = NULL;
00376 
00377     /* Read the rpm lead, signatures, and header */
00378     {   rpmts ts = rpmtsCreate();
00379 
00380         /* XXX W2DO? pass fileName? */
00381         /*@-mustmod@*/      /* LCL: segfault */
00382         rc = rpmReadPackageFile(ts, fdi, "readRPM",
00383                          &spec->packages->header);
00384         /*@=mustmod@*/
00385 
00386         (void)rpmtsFree(ts); 
00387         ts = NULL;
00388 
00389         if (sigs) *sigs = NULL;                 /* XXX HACK */
00390     }
00391 
00392     switch (rc) {
00393     case RPMRC_OK:
00394     case RPMRC_NOKEY:
00395     case RPMRC_NOTTRUSTED:
00396         break;
00397     case RPMRC_NOTFOUND:
00398         rpmlog(RPMLOG_ERR, _("readRPM: %s is not an RPM package\n"),
00399                 (fileName ? fileName : "<stdin>"));
00400         return RPMRC_FAIL;
00401     case RPMRC_FAIL:
00402     default:
00403         rpmlog(RPMLOG_ERR, _("readRPM: reading header from %s\n"),
00404                 (fileName ? fileName : "<stdin>"));
00405         return RPMRC_FAIL;
00406         /*@notreached@*/ break;
00407     }
00408 
00409     if (specp)
00410         *specp = spec;
00411     else
00412         spec = freeSpec(spec);
00413 
00414     if (csa != NULL)
00415         csa->cpioFdIn = fdi;
00416     else
00417         (void) Fclose(fdi);
00418 
00419     return 0;
00420 }
00421 #endif
00422 
00423 #if defined(DEAD)
00424 #define RPMPKGVERSION_MIN       30004
00425 #define RPMPKGVERSION_MAX       40003
00426 /*@unchecked@*/
00427 static int rpmpkg_version = -1;
00428 
00429 static int rpmLeadVersion(void)
00430         /*@globals rpmpkg_version, rpmGlobalMacroContext, h_errno @*/
00431         /*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
00432 {
00433     int rpmlead_version;
00434 
00435     /* Intitialize packaging version from macro configuration. */
00436     if (rpmpkg_version < 0) {
00437         rpmpkg_version = rpmExpandNumeric("%{_package_version}");
00438         if (rpmpkg_version < RPMPKGVERSION_MIN)
00439             rpmpkg_version = RPMPKGVERSION_MIN;
00440         if (rpmpkg_version > RPMPKGVERSION_MAX)
00441             rpmpkg_version = RPMPKGVERSION_MAX;
00442     }
00443 
00444     rpmlead_version = rpmpkg_version / 10000;
00445     /* XXX silly sanity check. */
00446     if (rpmlead_version < 3 || rpmlead_version > 4)
00447         rpmlead_version = 3;
00448     return rpmlead_version;
00449 }
00450 #endif
00451 
00452 void providePackageNVR(Header h)
00453 {
00454     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00455     const char *N, *V, *R;
00456 #ifdef RPM_VENDOR_MANDRIVA
00457     const char *D;
00458     int gotD;
00459 #endif
00460     rpmuint32_t E;
00461     int gotE;
00462     const char *pEVR;
00463     char *p;
00464     rpmuint32_t pFlags = RPMSENSE_EQUAL;
00465     const char ** provides = NULL;
00466     const char ** providesEVR = NULL;
00467     rpmuint32_t * provideFlags = NULL;
00468     int providesCount;
00469     int bingo = 1;
00470     size_t nb;
00471     int xx;
00472     int i;
00473 
00474     /* Generate provides for this package N-V-R. */
00475     xx = headerNEVRA(h, &N, NULL, &V, &R, NULL);
00476     if (!(N && V && R))
00477         return;
00478 
00479     nb = 21 + strlen(V) + 1 + strlen(R) + 1;
00480 #ifdef  RPM_VENDOR_MANDRIVA
00481     he->tag = RPMTAG_DISTEPOCH;
00482     gotD = headerGet(h, he, 0);
00483     D = (he->p.str ? he->p.str : NULL);
00484     nb += (gotD ? strlen(D) + 1 : 0);
00485 #endif
00486     pEVR = p = alloca(nb);
00487     *p = '\0';
00488     he->tag = RPMTAG_EPOCH;
00489     gotE = headerGet(h, he, 0);
00490     E = (he->p.ui32p ? he->p.ui32p[0] : 0);
00491     he->p.ptr = _free(he->p.ptr);
00492     if (gotE) {
00493         sprintf(p, "%d:", E);
00494         p += strlen(p);
00495     }
00496     p = stpcpy( stpcpy( stpcpy(p, V) , "-") , R);
00497 #ifdef  RPM_VENDOR_MANDRIVA
00498     if (gotD) {
00499         p = stpcpy( stpcpy( p, ":"), D);
00500         D = _free(D);
00501     }
00502 #endif
00503     V = _free(V);
00504     R = _free(R);
00505 
00506     /*
00507      * Rpm prior to 3.0.3 does not have versioned provides.
00508      * If no provides at all are available, we can just add.
00509      */
00510     he->tag = RPMTAG_PROVIDENAME;
00511 /*@-nullstate@*/
00512     xx = headerGet(h, he, 0);
00513 /*@=nullstate@*/
00514     provides = he->p.argv;
00515     providesCount = he->c;
00516     if (!xx)
00517         goto exit;
00518 
00519     /*
00520      * Otherwise, fill in entries on legacy packages.
00521      */
00522     he->tag = RPMTAG_PROVIDEVERSION;
00523 /*@-nullstate@*/
00524     xx = headerGet(h, he, 0);
00525 /*@=nullstate@*/
00526     providesEVR = he->p.argv;
00527     if (!xx) {
00528         for (i = 0; i < providesCount; i++) {
00529             /*@observer@*/
00530             static const char * vdummy = "";
00531             static rpmsenseFlags fdummy = RPMSENSE_ANY;
00532 
00533             he->tag = RPMTAG_PROVIDEVERSION;
00534             he->t = RPM_STRING_ARRAY_TYPE;
00535             he->p.argv = &vdummy;
00536             he->c = 1;
00537             he->append = 1;
00538 /*@-nullstate@*/
00539             xx = headerPut(h, he, 0);
00540 /*@=nullstate@*/
00541             he->append = 0;
00542 
00543             he->tag = RPMTAG_PROVIDEFLAGS;
00544             he->t = RPM_UINT32_TYPE;
00545             he->p.ui32p = (void *) &fdummy;
00546             he->c = 1;
00547             he->append = 1;
00548 /*@-nullstate@*/
00549             xx = headerPut(h, he, 0);
00550 /*@=nullstate@*/
00551             he->append = 0;
00552         }
00553         goto exit;
00554     }
00555 
00556     he->tag = RPMTAG_PROVIDEFLAGS;
00557 /*@-nullstate@*/
00558     xx = headerGet(h, he, 0);
00559 /*@=nullstate@*/
00560     provideFlags = he->p.ui32p;
00561 
00562     /*@-nullderef@*/    /* LCL: providesEVR is not NULL */
00563     if (provides && providesEVR && provideFlags)
00564     for (i = 0; i < providesCount; i++) {
00565         if (!(provides[i] && providesEVR[i]))
00566             continue;
00567         if (!(provideFlags[i] == RPMSENSE_EQUAL &&
00568             !strcmp(N, provides[i]) && !strcmp(pEVR, providesEVR[i])))
00569             continue;
00570         bingo = 0;
00571         break;
00572     }
00573     /*@=nullderef@*/
00574 
00575 exit:
00576 /*@-usereleased@*/
00577     provides = _free(provides);
00578     providesEVR = _free(providesEVR);
00579     provideFlags = _free(provideFlags);
00580 /*@=usereleased@*/
00581 
00582     if (bingo) {
00583         he->tag = RPMTAG_PROVIDENAME;
00584         he->t = RPM_STRING_ARRAY_TYPE;
00585         he->p.argv = &N;
00586         he->c = 1;
00587         he->append = 1;
00588 /*@-nullstate@*/
00589         xx = headerPut(h, he, 0);
00590 /*@=nullstate@*/
00591         he->append = 0;
00592 
00593         he->tag = RPMTAG_PROVIDEVERSION;
00594         he->t = RPM_STRING_ARRAY_TYPE;
00595         he->p.argv = &pEVR;
00596         he->c = 1;
00597         he->append = 1;
00598 /*@-nullstate@*/
00599         xx = headerPut(h, he, 0);
00600 /*@=nullstate@*/
00601         he->append = 0;
00602 
00603         he->tag = RPMTAG_PROVIDEFLAGS;
00604         he->t = RPM_UINT32_TYPE;
00605         he->p.ui32p = &pFlags;
00606         he->c = 1;
00607         he->append = 1;
00608 /*@-nullstate@*/
00609         xx = headerPut(h, he, 0);
00610 /*@=nullstate@*/
00611         he->append = 0;
00612     }
00613     N = _free(N);
00614 }
00615 
00621 static
00622 unsigned char nibble(char c)
00623         /*@*/
00624 {
00625     if (c >= '0' && c <= '9')
00626         return (unsigned char) (c - '0');
00627     if (c >= 'A' && c <= 'F')
00628         return (unsigned char)((int)(c - 'A') + 10);
00629     if (c >= 'a' && c <= 'f')
00630         return (unsigned char)((int)(c - 'a') + 10);
00631     return (unsigned char) '\0';
00632 }
00633 
00634 rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char * fn,
00635                 CSA_t csa, char * passPhrase, const char ** cookie, void * _dig)
00636 
00637 {
00638     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00639     FD_t fd = NULL;
00640     FD_t ifd = NULL;
00641 pgpDig dig = _dig;
00642     rpmuint32_t sigtag;
00643     const char * sigtarget;
00644     const char * rpmio_flags = NULL;
00645     const char * payload_format = NULL;
00646     const char * SHA1 = NULL;
00647     const char * msg = NULL;
00648     char * s;
00649     char buf[BUFSIZ];
00650     Header h;
00651     Header sigh = NULL;
00652     int addsig = 0;
00653     int isSource;
00654     rpmRC rc = RPMRC_OK;
00655     size_t nbr;
00656     size_t nbw;
00657     int xx;
00658 
00659     /* Transfer header reference form *hdrp to h. */
00660     h = headerLink(*hdrp);
00661 
00662     (void)headerFree(*hdrp);
00663     *hdrp = NULL;
00664 
00665     if (pkgidp)
00666         *pkgidp = NULL;
00667 
00668     /* Save payload information */
00669     isSource =
00670         (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
00671          headerIsEntry(h, RPMTAG_ARCH) != 0);
00672     if (isSource) {
00673         payload_format = rpmExpand("%{?_source_payload_format}", NULL);
00674         rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
00675     } else {
00676         payload_format = rpmExpand("%{?_binary_payload_format}", NULL);
00677         rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
00678     }
00679 
00680     if (!(payload_format && *payload_format)) {
00681         payload_format = _free(payload_format);
00682         payload_format = xstrdup("cpio");
00683     }
00684     if (!(rpmio_flags && *rpmio_flags)) {
00685         rpmio_flags = _free(rpmio_flags);
00686         rpmio_flags = xstrdup("w9.gzdio");
00687     }
00688     s = strchr(rpmio_flags, '.');
00689     if (s) {
00690 
00691         if (payload_format) {
00692             if (!strcmp(payload_format, "tar")
00693              || !strcmp(payload_format, "ustar")) {
00694                 /* XXX addition to header is too late to be displayed/sorted. */
00695                 /* Add prereq on rpm version that understands tar payloads */
00696                 (void) rpmlibNeedsFeature(h, "PayloadIsUstar", "4.4.4-1");
00697             }
00698 #if defined(SUPPORT_AR_PAYLOADS)
00699             if (!strcmp(payload_format, "ar")) {
00700                 /* XXX addition to header is too late to be displayed/sorted. */
00701                 /* Add prereq on rpm version that understands tar payloads */
00702                 (void) rpmlibNeedsFeature(h, "PayloadIsAr", "5.1-1");
00703             }
00704 #endif
00705 
00706             he->tag = RPMTAG_PAYLOADFORMAT;
00707             he->t = RPM_STRING_TYPE;
00708             he->p.str = payload_format;
00709             he->c = 1;
00710             xx = headerPut(h, he, 0);
00711         }
00712 
00713         /* XXX addition to header is too late to be displayed/sorted. */
00714         if (s[1] == 'g' && s[2] == 'z') {
00715             he->tag = RPMTAG_PAYLOADCOMPRESSOR;
00716             he->t = RPM_STRING_TYPE;
00717             he->p.str = xstrdup("gzip");
00718             he->c = 1;
00719             xx = headerPut(h, he, 0);
00720             he->p.ptr = _free(he->p.ptr);
00721         } else if (s[1] == 'b' && s[2] == 'z') {
00722             he->tag = RPMTAG_PAYLOADCOMPRESSOR;
00723             he->t = RPM_STRING_TYPE;
00724             he->p.str = xstrdup("bzip2");
00725             he->c = 1;
00726             xx = headerPut(h, he, 0);
00727             he->p.ptr = _free(he->p.ptr);
00728         } else if (s[1] == 'l' && s[2] == 'z') {
00729             he->tag = RPMTAG_PAYLOADCOMPRESSOR;
00730             he->t = RPM_STRING_TYPE;
00731             he->p.str = xstrdup("lzma");
00732             he->c = 1;
00733             xx = headerPut(h, he, 0);
00734             he->p.ptr = _free(he->p.ptr);
00735             (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
00736         } else if (s[1] == 'x' && s[2] == 'z') {
00737             he->tag = RPMTAG_PAYLOADCOMPRESSOR;
00738             he->t = RPM_STRING_TYPE;
00739             he->p.str = xstrdup("xz");
00740             he->c = 1;
00741             xx = headerPut(h, he, 0);
00742             he->p.ptr = _free(he->p.ptr);
00743             (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
00744         }
00745         strcpy(buf, rpmio_flags);
00746         buf[s - rpmio_flags] = '\0';
00747 
00748         he->tag = RPMTAG_PAYLOADFLAGS;
00749         he->t = RPM_STRING_TYPE;
00750         he->p.str = buf+1;
00751         he->c = 1;
00752         xx = headerPut(h, he, 0);
00753     }
00754     s = NULL;
00755 
00756     /* Create and add the cookie */
00757     if (cookie) {
00758         sprintf(buf, "%s %u", buildHost(), (unsigned) (*getBuildTime()));
00759         *cookie = xstrdup(buf);         /* XXX memory leak */
00760         he->tag = RPMTAG_COOKIE;
00761         he->t = RPM_STRING_TYPE;
00762         he->p.str = *cookie;
00763         he->c = 1;
00764         xx = headerPut(h, he, 0);
00765     }
00766 
00767     /* Add the non-repudiable public key (skip if --sign was specified) */
00768     if (!addsig && dig && dig->pub && dig->publen > 0) {
00769         rpmuint8_t atype = PGPARMOR_PUBKEY;
00770         s = pgpArmorWrap(atype, dig->pub, dig->publen);
00771 assert(s);
00772         he->tag = (rpmTag) RPMTAG_PUBKEYS;
00773         he->t = RPM_STRING_ARRAY_TYPE;
00774         he->p.argv = (const char **) &s;
00775         he->c = 1;
00776         he->append = 1;
00777         xx = headerPut(h, he, 0);
00778         he->append = 0;
00779         s = _free(s);
00780     }
00781 
00782     /* Reallocate the header into one contiguous region. */
00783     h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
00784     if (h == NULL) {    /* XXX can't happen */
00785         rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
00786         rc = RPMRC_FAIL;
00787         goto exit;
00788     }
00789     /* Re-reference reallocated header. */
00790     *hdrp = headerLink(h);
00791 
00792     /*
00793      * Write the header+archive into a temp file so that the size of
00794      * archive (after compression) can be added to the header.
00795      */
00796     sigtarget = NULL;
00797     if (rpmTempFile(NULL, &sigtarget, &fd)) {
00798         rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
00799         rc = RPMRC_FAIL;
00800         goto exit;
00801     }
00802 
00803     /* Write the header to a temp file, computing header SHA1 on the fly. */
00804     fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00805 assert(fd->ndigests == 1);
00806     {   const char item[] = "Header";
00807         msg = NULL;
00808         rc = rpmpkgWrite(item, fd, h, &msg);
00809         if (rc != RPMRC_OK) {
00810             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
00811                 (msg && *msg ? msg : "write failed\n"));
00812             msg = _free(msg);
00813             rc = RPMRC_FAIL;
00814             goto exit;
00815         }
00816         msg = _free(msg);
00817         (void) Fflush(fd);
00818     }
00819 
00820     {   /* XXX Dupe the header SHA1 for the RFC 2440/4880 signature. */
00821         DIGEST_CTX ctx = (dig ? rpmDigestDup(fd->digests[0]) : NULL);
00822 pgpDigParams sigp = pgpGetSignature(dig);
00823 
00824         /* Finalize the header SHA1. */
00825         /* XXX FIXME: get binary octets, not ASCII. */
00826         fdFiniDigest(fd, PGPHASHALGO_SHA1, &SHA1, NULL, 1);
00827 
00828 sigp->hash_algo = PGPHASHALGO_SHA1;             /* XXX DSA assumed */
00829 sigp->signhash16[0] = (rpmuint8_t) (nibble(SHA1[0]) << 4) | nibble(SHA1[1]);
00830 sigp->signhash16[1] = (rpmuint8_t) (nibble(SHA1[2]) << 4) | nibble(SHA1[3]);
00831 
00832         /* Sign the header SHA1. */
00833         if (ctx)
00834             rpmbcExportSignature(dig, ctx);
00835 
00836     }
00837 
00838     /* Append the payload to the temp file. */
00839     if (csa->fi != NULL)
00840         rc = cpio_doio(fd, h, csa, payload_format, rpmio_flags);
00841     else if (Fileno(csa->cpioFdIn) >= 0)
00842         rc = cpio_copy(fd, csa);
00843     else
00844 assert(0);
00845 
00846     rpmio_flags = _free(rpmio_flags);
00847     payload_format = _free(payload_format);
00848     if (rc != RPMRC_OK)
00849         goto exit;
00850 
00851     (void) Fclose(fd);
00852     fd = NULL;
00853     (void) Unlink(fn);
00854 
00855     /* Generate the signature */
00856     (void) fflush(stdout);
00857     sigh = headerNew();
00858     (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_SIZE, passPhrase);
00859     (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_MD5, passPhrase);
00860 
00861     sigtag = RPMSIGTAG_GPG;
00862     addsig = (passPhrase && passPhrase[0]);
00863 
00864     if (addsig) {
00865         rpmlog(RPMLOG_NOTICE, _("Generating signature: %d\n"), sigtag);
00866         (void) rpmAddSignature(sigh, sigtarget, sigtag, passPhrase);
00867     }
00868     else if (dig && dig->sig && dig->siglen > 0) {
00869         he->tag = (rpmTag) RPMSIGTAG_DSA;       /* XXX DSA assumed */
00870         he->t = RPM_BIN_TYPE;
00871         he->p.ptr = (void *) dig->sig;
00872         he->c = dig->siglen;
00873         xx = headerPut(sigh, he, 0);
00874         dig->sig = _free(dig->sig);             /* XXX lazily instead? */
00875         dig->siglen = 0;
00876     }
00877     
00878     if (SHA1) {
00879         he->tag = (rpmTag) RPMSIGTAG_SHA1;
00880         he->t = RPM_STRING_TYPE;
00881         he->p.str = SHA1;
00882         he->c = 1;
00883         xx = headerPut(sigh, he, 0);
00884         SHA1 = _free(SHA1);
00885     }
00886 
00887     {   rpmuint32_t payloadSize = csa->cpioArchiveSize;
00888         he->tag = (rpmTag) RPMSIGTAG_PAYLOADSIZE;
00889         he->t = RPM_UINT32_TYPE;
00890         he->p.ui32p = &payloadSize;
00891         he->c = 1;
00892         xx = headerPut(sigh, he, 0);
00893     }
00894 
00895     /* Reallocate the signature header into one contiguous region. */
00896     sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
00897     if (sigh == NULL) { /* XXX can't happen */
00898         rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
00899         rc = RPMRC_FAIL;
00900         goto exit;
00901     }
00902 
00903     /* Pad the signature header to put the metadata header at known offset. */
00904     {   size_t slen = 0;
00905         void * uh = headerUnload(sigh, &slen);
00906         static const size_t align = 1024;
00907         size_t nb = align - 96 - 16 - 16;
00908         rpmuint8_t * b;
00909 
00910         uh = _free(uh);
00911 assert(slen < nb);
00912         nb -= slen;
00913         b = memset(alloca(nb), 0, nb);
00914         he->tag = (rpmTag) RPMSIGTAG_PADDING;
00915         he->t = RPM_BIN_TYPE;
00916         he->p.ui8p = b;
00917         he->c = nb;
00918         xx = headerPut(sigh, he, 0);
00919         sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
00920 assert(sigh != NULL);
00921     }
00922 
00923     /* Open the output file */
00924     fd = Fopen(fn, "w.fdio");
00925     if (fd == NULL || Ferror(fd)) {
00926         rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
00927                 fn, Fstrerror(fd));
00928         rc = RPMRC_FAIL;
00929         goto exit;
00930     }
00931 
00932     /* Write the lead section into the package. */
00933     {   const char item[] = "Lead";
00934         size_t nl = rpmpkgSizeof(item, NULL);
00935 
00936         msg = NULL;
00937         if (nl == 0)
00938             rc = RPMRC_FAIL;
00939         else {
00940             void * l = memset(alloca(nl), 0, nl);
00941             const char *N, *V, *R;
00942             (void) headerNEVRA(h, &N, NULL, &V, &R, NULL);
00943             sprintf(buf, "%s-%s-%s", N, V, R);
00944             N = _free(N);
00945             V = _free(V);
00946             R = _free(R);
00947             msg = buf;
00948             rc = rpmpkgWrite(item, fd, l, &msg);
00949         }
00950 
00951         if (rc != RPMRC_OK) {
00952             rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
00953                  Fstrerror(fd));
00954             rc = RPMRC_FAIL;
00955             goto exit;
00956         }
00957     }
00958 
00959     /* Write the signature section into the package. */
00960     {   const char item[] = "Signature";
00961 
00962         msg = NULL;
00963         rc = rpmpkgWrite(item, fd, sigh, &msg);
00964         if (rc != RPMRC_OK) {
00965             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
00966                 (msg && *msg ? msg : "write failed\n"));
00967             msg = _free(msg);
00968             rc = RPMRC_FAIL;
00969             goto exit;
00970         }
00971         msg = _free(msg);
00972     }
00973 
00974     /* Append the header and archive */
00975     ifd = Fopen(sigtarget, "r.fdio");
00976     if (ifd == NULL || Ferror(ifd)) {
00977         rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
00978                 sigtarget, Fstrerror(ifd));
00979         rc = RPMRC_FAIL;
00980         goto exit;
00981     }
00982 
00983     /* Add signatures to header, and write header into the package. */
00984     {   const char item[] = "Header";
00985         Header nh = NULL;
00986 
00987         msg = NULL;
00988         rc = rpmpkgRead(item, ifd, &nh, &msg);
00989         if (rc != RPMRC_OK) {
00990             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
00991                 (msg && *msg ? msg : "read failed\n"));
00992             msg = _free(msg);
00993             rc = RPMRC_FAIL;
00994             goto exit;
00995         }
00996         msg = _free(msg);
00997 
00998 #ifdef  NOTYET
00999         (void) headerMergeLegacySigs(nh, sigh);
01000 #endif
01001 
01002         msg = NULL;
01003         rc = rpmpkgWrite(item, fd, nh, &msg);
01004         (void)headerFree(nh);
01005         nh = NULL;
01006         if (rc != RPMRC_OK) {
01007             rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
01008                 (msg && *msg ? msg : "write failed\n"));
01009             msg = _free(msg);
01010             rc = RPMRC_FAIL;
01011             goto exit;
01012         }
01013         msg = _free(msg);
01014     }
01015         
01016     /* Write the payload into the package. */
01017     while ((nbr = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
01018         if (Ferror(ifd)) {
01019             rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
01020                      sigtarget, Fstrerror(ifd));
01021             rc = RPMRC_FAIL;
01022             goto exit;
01023         }
01024         nbw = (int)Fwrite(buf, sizeof(buf[0]), nbr, fd);
01025         if (nbr != nbw || Ferror(fd)) {
01026             rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
01027                      fn, Fstrerror(fd));
01028             rc = RPMRC_FAIL;
01029             goto exit;
01030         }
01031     }
01032     rc = RPMRC_OK;
01033 
01034 exit:
01035     SHA1 = _free(SHA1);
01036     (void)headerFree(h);
01037     h = NULL;
01038 
01039     /* XXX Fish the pkgid out of the signature header. */
01040     if (sigh != NULL && pkgidp != NULL) {
01041         he->tag = (rpmTag) RPMSIGTAG_MD5;
01042         xx = headerGet(sigh, he, 0);
01043         if (he->t == RPM_BIN_TYPE && he->p.ptr != NULL && he->c == 16)
01044             *pkgidp = he->p.ui8p;               /* XXX memory leak */
01045     }
01046 
01047     (void)headerFree(sigh);
01048     sigh = NULL;
01049     if (ifd) {
01050         (void) Fclose(ifd);
01051         ifd = NULL;
01052     }
01053     if (fd) {
01054         (void) Fclose(fd);
01055         fd = NULL;
01056     }
01057     if (sigtarget) {
01058         (void) Unlink(sigtarget);
01059         sigtarget = _free(sigtarget);
01060     }
01061 
01062     if (rc == RPMRC_OK)
01063         rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fn);
01064     else
01065         (void) Unlink(fn);
01066 
01067     return rc;
01068 }
01069 
01070 static int rpmlibMarkers(Header h)
01071         /*@modifies h @*/
01072 {
01073     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01074     rpmuint32_t val;
01075     int xx;
01076 
01077     he->tag = RPMTAG_RPMVERSION;
01078     he->t = RPM_STRING_TYPE;
01079     he->p.str = xstrdup(VERSION);
01080     he->c = 1;
01081     xx = headerPut(h, he, 0);
01082     he->p.ptr = _free(he->p.ptr);
01083 
01084   if (!(_rpmbuildFlags & 4)) {
01085     val = (rpmuint32_t)rpmlibTimestamp();
01086     he->tag = RPMTAG_RPMLIBTIMESTAMP;
01087     he->t = RPM_UINT32_TYPE;
01088     he->p.ui32p = &val;
01089     he->c = 1;
01090     xx = headerPut(h, he, 0);
01091 
01092     val = (rpmuint32_t)rpmlibVendor();
01093     he->tag = RPMTAG_RPMLIBVENDOR;
01094     he->t = RPM_UINT32_TYPE;
01095     he->p.ui32p = &val;
01096     he->c = 1;
01097     xx = headerPut(h, he, 0);
01098 
01099     val = (rpmuint32_t)rpmlibVersion();
01100     he->tag = RPMTAG_RPMLIBVERSION;
01101     he->t = RPM_UINT32_TYPE;
01102     he->p.ui32p = &val;
01103     he->c = 1;
01104     xx = headerPut(h, he, 0);
01105   }
01106 
01107     he->tag = RPMTAG_BUILDHOST;
01108     he->t = RPM_STRING_TYPE;
01109     he->p.str = buildHost();
01110     he->c = 1;
01111     xx = headerPut(h, he, 0);
01112 
01113     he->tag = RPMTAG_BUILDTIME;
01114     he->t = RPM_UINT32_TYPE;
01115     he->p.ui32p = getBuildTime();
01116     he->c = 1;
01117     xx = headerPut(h, he, 0);
01118 
01119     return 0;
01120 }
01121 
01122 /*@unchecked@*/
01123 static rpmTag copyTags[] = {
01124     RPMTAG_CHANGELOGTIME,
01125     RPMTAG_CHANGELOGNAME,
01126     RPMTAG_CHANGELOGTEXT,
01127     0
01128 };
01129 
01130 rpmRC packageBinaries(Spec spec)
01131 {
01132     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01133     struct cpioSourceArchive_s csabuf;
01134     CSA_t csa = &csabuf;
01135     const char *errorString;
01136     Package pkg;
01137     rpmRC rc = RPMRC_OK;        /* assume success */
01138     int xx;
01139 
01140     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
01141         const char *fn;
01142 
01143         if (pkg->fileList == NULL)
01144             continue;
01145 
01146         if (spec->cookie) {
01147             he->tag = RPMTAG_COOKIE;
01148             he->t = RPM_STRING_TYPE;
01149             he->p.str = spec->cookie;
01150             he->c = 1;
01151             xx = headerPut(pkg->header, he, 0);
01152         }
01153 
01154         /* Copy changelog from src rpm */
01155         headerCopyTags(spec->packages->header, pkg->header, copyTags);
01156 
01157         /* Add rpmlib markers for tracking. */
01158         (void) rpmlibMarkers(pkg->header);
01159         
01160         he->tag = RPMTAG_OPTFLAGS;
01161         he->t = RPM_STRING_TYPE;
01162         he->p.str = rpmExpand("%{optflags}", NULL);
01163         he->c = 1;
01164         xx = headerPut(pkg->header, he, 0);
01165         he->p.ptr = _free(he->p.ptr);
01166 
01167 if (!(_rpmbuildFlags & 4)) {
01168         if (spec->sourcePkgId != NULL) {
01169             he->tag = RPMTAG_SOURCEPKGID;
01170             he->t = RPM_BIN_TYPE;
01171             he->p.ptr = spec->sourcePkgId;
01172             he->c = 16;
01173             xx = headerPut(pkg->header, he, 0);
01174         }
01175 }
01176         
01177         {   const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
01178             char *binRpm, *binDir;
01179             binRpm = headerSprintf(pkg->header, binFormat, NULL,
01180                                rpmHeaderFormats, &errorString);
01181             binFormat = _free(binFormat);
01182             if (binRpm == NULL) {
01183                 he->tag = RPMTAG_NVRA;
01184                 xx = headerGet(pkg->header, he, 0);
01185                 rpmlog(RPMLOG_ERR, _("Could not generate output "
01186                      "filename for package %s: %s\n"), he->p.str, errorString);
01187                 he->p.ptr = _free(he->p.ptr);
01188                 rc = RPMRC_FAIL;
01189                 goto exit;
01190             }
01191             fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
01192             if ((binDir = strchr(binRpm, '/')) != NULL) {
01193                 struct stat st;
01194                 const char *dn;
01195                 *binDir = '\0';
01196                 dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
01197                 if (Stat(dn, &st) < 0) {
01198                     switch(errno) {
01199                     case  ENOENT:
01200                         if (rpmioMkpath(dn, 0755, -1, -1) == 0)
01201                             /*@switchbreak@*/ break;
01202                         /*@fallthrough@*/
01203                     default:
01204                         rpmlog(RPMLOG_ERR,_("cannot create %s: %s\n"),
01205                             dn, strerror(errno));
01206                         /*@switchbreak@*/ break;
01207                     }
01208                 }
01209                 dn = _free(dn);
01210             }
01211             binRpm = _free(binRpm);
01212         }
01213 
01214         memset(csa, 0, sizeof(*csa));
01215         csa->cpioArchiveSize = 0;
01216         /*@-type@*/ /* LCL: function typedefs */
01217 /*@-onlytrans@*/
01218         csa->cpioFdIn = fdNew("init (packageBinaries)");
01219 /*@=onlytrans@*/
01220 /*@-assignexpose -newreftrans@*/
01221         csa->fi = rpmfiLink(pkg->fi, "packageBinaries");
01222 /*@=assignexpose =newreftrans@*/
01223 assert(csa->fi != NULL);
01224 
01225         rc = writeRPM(&pkg->header, NULL, fn,
01226                     csa, spec->passPhrase, NULL, spec->dig);
01227 
01228 /*@-onlytrans@*/
01229         csa->fi->te = _free(csa->fi->te);       /* XXX memory leak */
01230 /*@=onlytrans@*/
01231         csa->fi = rpmfiFree(csa->fi);
01232 /*@-nullpass -onlytrans -refcounttrans @*/
01233         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
01234 /*@=nullpass =onlytrans =refcounttrans @*/
01235         /*@=type@*/
01236         fn = _free(fn);
01237         if (rc)
01238             goto exit;
01239     }
01240     
01241 exit:
01242 
01243     return rc;
01244 }
01245 
01246 rpmRC packageSources(Spec spec)
01247 {
01248     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01249     struct cpioSourceArchive_s csabuf;
01250     CSA_t csa = &csabuf;
01251     rpmRC rc;
01252     int xx;
01253 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
01254     rpmuint32_t val;
01255 #endif
01256 
01257     /* Add rpmlib markers for tracking. */
01258     (void) rpmlibMarkers(spec->sourceHeader);
01259 
01260 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
01261     /* Mark package as a SRPM for backward compatibility with RPM < 4.4.6 */
01262     he->tag = RPMTAG_SOURCEPACKAGE;
01263     he->t = RPM_UINT32_TYPE;
01264     val = 1;
01265     he->p.ui32p = &val;
01266     he->c = 1;
01267     xx = headerPut(spec->sourceHeader, he, 0);
01268 #endif
01269 
01270     /* Add build scriptlet status/time (if any) to SRPM's. */
01271     {   int ix;
01272         for (ix = 0; ix < RPMSCRIPT_MAX; ix++) {
01273             if (spec->sstates[ix] == 0)
01274                 continue;
01275             if (spec->smetrics[ix] == 0)
01276                 continue;
01277             break;
01278         }
01279         if (ix >= 0 && ix < RPMSCRIPT_MAX) {
01280             he->tag = RPMTAG_SCRIPTSTATES;
01281             he->t = RPM_UINT32_TYPE;
01282             he->p.ui32p = spec->sstates;
01283             he->c = RPMSCRIPT_MAX;
01284             xx = headerPut(spec->sourceHeader, he, 0);
01285             he->tag = RPMTAG_SCRIPTMETRICS;
01286             he->t = RPM_UINT32_TYPE;
01287             he->p.ui32p = spec->smetrics;
01288             he->c = RPMSCRIPT_MAX;
01289             xx = headerPut(spec->sourceHeader, he, 0);
01290         }
01291     }
01292         
01293     /* Add macros used during build to SRPM's. */
01294     {   const char ** av = NULL;
01295         (void)rpmGetMacroEntries(NULL, NULL, 1, &av);
01296         if (av != NULL && av[0] != NULL) {
01297             he->tag = RPMTAG_BUILDMACROS;
01298             he->t = RPM_STRING_ARRAY_TYPE;
01299             he->p.argv = av;
01300             he->c = argvCount(av);
01301             xx = headerPut(spec->sourceHeader, he, 0);
01302         }
01303 /*@-nullstate@*/
01304         av = argvFree(av);
01305 /*@=nullstate@*/
01306     }
01307 
01308     spec->cookie = _free(spec->cookie);
01309     
01310     /* XXX this should be %_srpmdir */
01311     {   const char *srcrpmdir = rpmGetPath("%{_srcrpmdir}/", NULL);
01312         const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
01313 
01314         rc = rpmioMkpath(srcrpmdir, 0755, -1, -1);
01315 
01316         memset(csa, 0, sizeof(*csa));
01317         csa->cpioArchiveSize = 0;
01318         /*@-type@*/ /* LCL: function typedefs */
01319 /*@-onlytrans@*/
01320         csa->cpioFdIn = fdNew("init (packageSources)");
01321 /*@=onlytrans@*/
01322 /*@-assignexpose -newreftrans@*/
01323         csa->fi = rpmfiLink(spec->fi, "packageSources");
01324 /*@=assignexpose =newreftrans@*/
01325 #ifdef  DYING
01326 assert(csa->fi != NULL);
01327 #else
01328         if (csa->fi == NULL)    /* XXX segfault avoidance */
01329             return RPMRC_FAIL;
01330 #endif
01331 
01332         spec->sourcePkgId = NULL;
01333         rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn,
01334                 csa, spec->passPhrase, &spec->cookie, spec->dig);
01335 
01336 /*@-onlytrans@*/
01337         csa->fi->te = _free(csa->fi->te);       /* XXX memory leak */
01338 /*@=onlytrans@*/
01339         csa->fi = rpmfiFree(csa->fi);
01340 /*@-nullpass -onlytrans -refcounttrans @*/
01341         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
01342 /*@=nullpass =onlytrans =refcounttrans @*/
01343         /*@=type@*/
01344         srcrpmdir = _free(srcrpmdir);
01345         fn = _free(fn);
01346     }
01347 
01348     rc = (rc ? RPMRC_FAIL : RPMRC_OK);
01349 
01350     return rc;
01351 }