Main Page Modules Data Structures File List Data Fields Globals Related Pages

# build/pack.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio_internal.h>
    00009 #include <rpmbuild.h>
    00010
    00011 #include "rpmps.h"
    00012
    00013 #include "cpio.h"
    00014 #include "fsm.h"
    00015 #include "psm.h"
    00016
    00017 #define _RPMFI_INTERNAL         /* XXX fi->fsm */
    00018 #include "rpmfi.h"
    00019 #include "rpmts.h"
    00020
    00021 #include "buildio.h"
    00022
    00023 #include "legacy.h"     /* XXX providePackageNVR */
    00024 #include "signature.h"
    00025 #include "rpmlead.h"
    00026 #include "debug.h"
    00027
    00028 /*@access rpmts @*/
    00029 /*@access rpmfi @*/     /* compared with NULL */
    00030 /*@access Header @*/    /* compared with NULL */
    00031 /*@access FD_t @*/      /* compared with NULL */
    00032 /*@access StringBuf @*/ /* compared with NULL */
    00033 /*@access CSA_t @*/
    00034
    00037 static inline int genSourceRpmName(Spec spec)
    00038         /*@modifies spec->sourceRpmName @*/
    00039 {
    00040     if (spec->sourceRpmName == NULL) {
    00041         const char *name, *version, *release;
    00042         char fileName[BUFSIZ];
    00043
    00044         (void) headerNVR(spec->packages->header, &name, &version, &release);
    00045         sprintf(fileName, "%s-%s-%s.%ssrc.rpm", name, version, release,
    00046             spec->noSource ? "no" : "");
    00047         spec->sourceRpmName = xstrdup(fileName);
    00048     }
    00049
    00050     return 0;
    00051 }
    00052
    00056 static int cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
    00057                 const char * fmodeMacro)
    00058         /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
    00059         /*@modifies fdo, csa, rpmGlobalMacroContext,
    00060                 fileSystem, internalState @*/
    00061 {
    00062     rpmts ts = rpmtsCreate();
    00063     rpmfi fi = csa->cpioList;
    00064     const char *failedFile = NULL;
    00065     FD_t cfd;
    00066     int rc, ec;
    00067
    00068 /*@-boundsread@*/
    00069     {   const char *fmode = rpmExpand(fmodeMacro, NULL);
    00070         if (!(fmode && fmode[0] == 'w'))
    00071             fmode = xstrdup("w9.gzdio");
    00072         /*@-nullpass@*/
    00073         (void) Fflush(fdo);
    00074         cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
    00075         /*@=nullpass@*/
    00076         fmode = _free(fmode);
    00077     }
    00078 /*@=boundsread@*/
    00079     if (cfd == NULL)
    00080         return 1;
    00081
    00082     rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, cfd,
    00083                 &csa->cpioArchiveSize, &failedFile);
    00084     (void) Fclose(cfd);
    00085     ec = fsmTeardown(fi->fsm);
    00086     if (!rc) rc = ec;
    00087
    00088     if (rc) {
    00089         if (failedFile)
    00090             rpmError(RPMERR_CPIO, _("create archive failed on file %s: %s\n"),
    00091                 failedFile, cpioStrerror(rc));
    00092         else
    00093             rpmError(RPMERR_CPIO, _("create archive failed: %s\n"),
    00094                 cpioStrerror(rc));
    00095       rc = 1;
    00096     }
    00097
    00098     failedFile = _free(failedFile);
    00099     ts = rpmtsFree(ts);
    00100
    00101     return rc;
    00102 }
    00103
    00106 static int cpio_copy(FD_t fdo, CSA_t csa)
    00107         /*@globals fileSystem, internalState @*/
    00108         /*@modifies fdo, csa, fileSystem, internalState @*/
    00109 {
    00110     char buf[BUFSIZ];
    00111     size_t nb;
    00112
    00113     while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
    00114         if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
    00115             rpmError(RPMERR_CPIO, _("cpio_copy write failed: %s\n"),
    00116                         Fstrerror(fdo));
    00117             return 1;
    00118         }
    00119         csa->cpioArchiveSize += nb;
    00120     }
    00121     if (Ferror(csa->cpioFdIn)) {
    00122         rpmError(RPMERR_CPIO, _("cpio_copy read failed: %s\n"),
    00123                 Fstrerror(csa->cpioFdIn));
    00124         return 1;
    00125     }
    00126     return 0;
    00127 }
    00128
    00131 static /*@only@*/ /*@null@*/ StringBuf addFileToTagAux(Spec spec,
    00132                 const char * file, /*@only@*/ StringBuf sb)
    00133         /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
    00134         /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
    00135 {
    00136     char buf[BUFSIZ];
    00137     const char * fn = buf;
    00138     FILE * f;
    00139     FD_t fd;
    00140
    00141     /* XXX use rpmGenPath(rootdir, "%{_buildir}/%{_buildsubdir}/", file) */
    00142     fn = rpmGetPath("%{_builddir}/", spec->buildSubdir, "/", file, NULL);
    00143
    00144     fd = Fopen(fn, "r.ufdio");
    00145     if (fn != buf) fn = _free(fn);
    00146     if (fd == NULL || Ferror(fd)) {
    00147         sb = freeStringBuf(sb);
    00148         return NULL;
    00149     }
    00150     /*@-type@*/ /* FIX: cast? */
    00151     if ((f = fdGetFp(fd)) != NULL)
    00152     /*@=type@*/
    00153     while (fgets(buf, sizeof(buf), f)) {
    00154         /* XXX display fn in error msg */
    00155         if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
    00156             rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
    00157             sb = freeStringBuf(sb);
    00158             break;
    00159         }
    00160         appendStringBuf(sb, buf);
    00161     }
    00162     (void) Fclose(fd);
    00163
    00164     return sb;
    00165 }
    00166
    00169 static int addFileToTag(Spec spec, const char * file, Header h, int tag)
    00170         /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
    00171         /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
    00172 {
    00173     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00174     StringBuf sb = newStringBuf();
    00175     char *s;
    00176
    00177     if (hge(h, tag, NULL, (void **)&s, NULL)) {
    00178         appendLineStringBuf(sb, s);
    00179         (void) headerRemoveEntry(h, tag);
    00180     }
    00181
    00182     if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
    00183         return 1;
    00184
    00185     (void) headerAddEntry(h, tag, RPM_STRING_TYPE, getStringBuf(sb), 1);
    00186
    00187     sb = freeStringBuf(sb);
    00188     return 0;
    00189 }
    00190
    00193 static int addFileToArrayTag(Spec spec, const char *file, Header h, int tag)
    00194         /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
    00195         /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState  @*/
    00196 {
    00197     StringBuf sb = newStringBuf();
    00198     char *s;
    00199
    00200     if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
    00201         return 1;
    00202
    00203     s = getStringBuf(sb);
    00204     (void) headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, &s, 1);
    00205
    00206     sb = freeStringBuf(sb);
    00207     return 0;
    00208 }
    00209
    00212 static int processScriptFiles(Spec spec, Package pkg)
    00213         /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
    00214         /*@modifies pkg->header, rpmGlobalMacroContext,
    00215                 fileSystem, internalState @*/
    00216 {
    00217     struct TriggerFileEntry *p;
    00218
    00219     if (pkg->preInFile) {
    00220         if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
    00221             rpmError(RPMERR_BADFILENAME,
    00222                      _("Could not open PreIn file: %s\n"), pkg->preInFile);
    00223             return RPMERR_BADFILENAME;
    00224         }
    00225     }
    00226     if (pkg->preUnFile) {
    00227         if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
    00228             rpmError(RPMERR_BADFILENAME,
    00229                      _("Could not open PreUn file: %s\n"), pkg->preUnFile);
    00230             return RPMERR_BADFILENAME;
    00231         }
    00232     }
    00233     if (pkg->postInFile) {
    00234         if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
    00235             rpmError(RPMERR_BADFILENAME,
    00236                      _("Could not open PostIn file: %s\n"), pkg->postInFile);
    00237             return RPMERR_BADFILENAME;
    00238         }
    00239     }
    00240     if (pkg->postUnFile) {
    00241         if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
    00242             rpmError(RPMERR_BADFILENAME,
    00243                      _("Could not open PostUn file: %s\n"), pkg->postUnFile);
    00244             return RPMERR_BADFILENAME;
    00245         }
    00246     }
    00247     if (pkg->verifyFile) {
    00248         if (addFileToTag(spec, pkg->verifyFile, pkg->header,
    00249                          RPMTAG_VERIFYSCRIPT)) {
    00250             rpmError(RPMERR_BADFILENAME,
    00251                      _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
    00252             return RPMERR_BADFILENAME;
    00253         }
    00254     }
    00255
    00256     for (p = pkg->triggerFiles; p != NULL; p = p->next) {
    00257         (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTPROG,
    00258                                RPM_STRING_ARRAY_TYPE, &(p->prog), 1);
    00259         if (p->script) {
    00260             (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTS,
    00261                                    RPM_STRING_ARRAY_TYPE, &(p->script), 1);
    00262         } else if (p->fileName) {
    00263             if (addFileToArrayTag(spec, p->fileName, pkg->header,
    00264                                   RPMTAG_TRIGGERSCRIPTS)) {
    00265                 rpmError(RPMERR_BADFILENAME,
    00266                          _("Could not open Trigger script file: %s\n"),
    00267                          p->fileName);
    00268                 return RPMERR_BADFILENAME;
    00269             }
    00270         } else {
    00271             /* This is dumb.  When the header supports NULL string */
    00272             /* this will go away.                                  */
    00273             char *bull = "";
    00274             (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTS,
    00275                                    RPM_STRING_ARRAY_TYPE, &bull, 1);
    00276         }
    00277     }
    00278
    00279     return 0;
    00280 }
    00281
    00282 /*@-boundswrite@*/
    00283 int readRPM(const char *fileName, Spec *specp, struct rpmlead *lead,
    00284                 Header *sigs, CSA_t csa)
    00285 {
    00286     FD_t fdi;
    00287     Spec spec;
    00288     rpmRC rc;
    00289
    00290     fdi = (fileName != NULL)
    00291         ? Fopen(fileName, "r.ufdio")
    00292         : fdDup(STDIN_FILENO);
    00293
    00294     if (fdi == NULL || Ferror(fdi)) {
    00295         rpmError(RPMERR_BADMAGIC, _("readRPM: open %s: %s\n"),
    00296                 (fileName ? fileName : "<stdin>"),
    00297                 Fstrerror(fdi));
    00298         if (fdi) (void) Fclose(fdi);
    00299         return RPMERR_BADMAGIC;
    00300     }
    00301
    00302     /* Get copy of lead */
    00303     /*@-sizeoftype@*/
    00304     if ((rc = Fread(lead, sizeof(char), sizeof(*lead), fdi)) != sizeof(*lead)) {
    00305         rpmError(RPMERR_BADMAGIC, _("readRPM: read %s: %s\n"),
    00306                 (fileName ? fileName : "<stdin>"),
    00307                 Fstrerror(fdi));
    00308         return RPMERR_BADMAGIC;
    00309     }
    00310     /*@=sizeoftype@*/
    00311
    00312     /* XXX FIXME: EPIPE on <stdin> */
    00313     if (Fseek(fdi, 0, SEEK_SET) == -1) {
    00314         rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
    00315                         (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
    00316         return RPMERR_FSEEK;
    00317     }
    00318
    00319     /* Reallocate build data structures */
    00320     spec = newSpec();
    00321     spec->packages = newPackage(spec);
    00322
    00323     /* XXX the header just allocated will be allocated again */
    00324     spec->packages->header = headerFree(spec->packages->header);
    00325
    00326     /* Read the rpm lead, signatures, and header */
    00327     {   rpmts ts = rpmtsCreate();
    00328
    00329         /* XXX W2DO? pass fileName? */
    00330         /*@-mustmod@*/      /* LCL: segfault */
    00331         rc = rpmReadPackageFile(ts, fdi, "readRPM",
    00332                          &spec->packages->header);
    00333         /*@=mustmod@*/
    00334
    00335         ts = rpmtsFree(ts);
    00336
    00337         if (sigs) *sigs = NULL;                 /* XXX HACK */
    00338     }
    00339
    00340     switch (rc) {
    00341     case RPMRC_OK:
    00342     case RPMRC_NOKEY:
    00343     case RPMRC_NOTTRUSTED:
    00344         break;
    00345     case RPMRC_NOTFOUND:
    00346         rpmError(RPMERR_BADMAGIC, _("readRPM: %s is not an RPM package\n"),
    00347                 (fileName ? fileName : "<stdin>"));
    00348         return RPMERR_BADMAGIC;
    00349     case RPMRC_FAIL:
    00350     default:
    00351         rpmError(RPMERR_BADMAGIC, _("readRPM: reading header from %s\n"),
    00352                 (fileName ? fileName : "<stdin>"));
    00353         return RPMERR_BADMAGIC;
    00354         /*@notreached@*/ break;
    00355     }
    00356
    00357     /*@-branchstate@*/
    00358     if (specp)
    00359         *specp = spec;
    00360     else
    00361         spec = freeSpec(spec);
    00362     /*@=branchstate@*/
    00363
    00364     if (csa != NULL)
    00365         csa->cpioFdIn = fdi;
    00366     else
    00367         (void) Fclose(fdi);
    00368
    00369     return 0;
    00370 }
    00371 /*@=boundswrite@*/
    00372
    00373 #ifdef  DYING
    00374 /*@unchecked@*/
    00375 static unsigned char header_magic[8] = {
    00376         0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
    00377 };
    00378 #endif
    00379
    00380 #define RPMPKGVERSION_MIN       30004
    00381 #define RPMPKGVERSION_MAX       40003
    00382 /*@unchecked@*/
    00383 static int rpmpkg_version = -1;
    00384
    00385 static int rpmLeadVersion(void)
    00386         /*@globals rpmpkg_version, rpmGlobalMacroContext @*/
    00387         /*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
    00388 {
    00389     int rpmlead_version;
    00390
    00391     /* Intitialize packaging version from macro configuration. */
    00392     if (rpmpkg_version < 0) {
    00393         rpmpkg_version = rpmExpandNumeric("%{_package_version}");
    00394         if (rpmpkg_version < RPMPKGVERSION_MIN)
    00395             rpmpkg_version = RPMPKGVERSION_MIN;
    00396         if (rpmpkg_version > RPMPKGVERSION_MAX)
    00397             rpmpkg_version = RPMPKGVERSION_MAX;
    00398     }
    00399
    00400     rpmlead_version = rpmpkg_version / 10000;
    00401     if (_noDirTokens || (rpmlead_version < 3 || rpmlead_version > 4))
    00402         rpmlead_version = 3;
    00403     return rpmlead_version;
    00404 }
    00405
    00406 /*@-boundswrite@*/
    00407 int writeRPM(Header *hdrp, const char *fileName, int type,
    00408                     CSA_t csa, char *passPhrase, const char **cookie)
    00409 {
    00410     FD_t fd = NULL;
    00411     FD_t ifd = NULL;
    00412     int_32 count, sigtag;
    00413     const char * sigtarget;
    00414     const char * rpmio_flags = NULL;
    00415     const char * SHA1 = NULL;
    00416     char *s;
    00417     char buf[BUFSIZ];
    00418     Header h;
    00419     Header sig = NULL;
    00420     int rc = 0;
    00421
    00422     /* Transfer header reference form *hdrp to h. */
    00423     h = headerLink(*hdrp);
    00424     *hdrp = headerFree(*hdrp);
    00425
    00426 #ifdef  DYING
    00427     if (Fileno(csa->cpioFdIn) < 0) {
    00428         csa->cpioArchiveSize = 0;
    00429         /* Add a bogus archive size to the Header */
    00430         (void) headerAddEntry(h, RPMTAG_ARCHIVESIZE, RPM_INT32_TYPE,
    00431                 &csa->cpioArchiveSize, 1);
    00432     }
    00433 #endif
    00434
    00435     /* Binary packages now have explicit Provides: name = version-release. */
    00436     if (type == RPMLEAD_BINARY)
    00437         providePackageNVR(h);
    00438
    00439     /* Save payload information */
    00440     /*@-branchstate@*/
    00441     switch(type) {
    00442     case RPMLEAD_SOURCE:
    00443         rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
    00444         break;
    00445     case RPMLEAD_BINARY:
    00446         rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
    00447         break;
    00448     }
    00449     /*@=branchstate@*/
    00450     if (!(rpmio_flags && *rpmio_flags)) {
    00451         rpmio_flags = _free(rpmio_flags);
    00452         rpmio_flags = xstrdup("w9.gzdio");
    00453     }
    00454     s = strchr(rpmio_flags, '.');
    00455     if (s) {
    00456         (void) headerAddEntry(h, RPMTAG_PAYLOADFORMAT, RPM_STRING_TYPE, "cpio", 1);
    00457         if (s[1] == 'g' && s[2] == 'z')
    00458             (void) headerAddEntry(h, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE,
    00459                 "gzip", 1);
    00460         if (s[1] == 'b' && s[2] == 'z') {
    00461             (void) headerAddEntry(h, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE,
    00462                 "bzip2", 1);
    00463             /* Add prereq on rpm version that understands bzip2 payloads */
    00464             (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1");
    00465         }
    00466         strcpy(buf, rpmio_flags);
    00467         buf[s - rpmio_flags] = '\0';
    00468         (void) headerAddEntry(h, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, buf+1, 1);
    00469     }
    00470
    00471     /* Create and add the cookie */
    00472     if (cookie) {
    00473         sprintf(buf, "%s %d", buildHost(), (int) (*getBuildTime()));
    00474         *cookie = xstrdup(buf);
    00475         (void) headerAddEntry(h, RPMTAG_COOKIE, RPM_STRING_TYPE, *cookie, 1);
    00476     }
    00477
    00478     /* Reallocate the header into one contiguous region. */
    00479     h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
    00480     if (h == NULL) {    /* XXX can't happen */
    00481         rc = RPMERR_RELOAD;
    00482         rpmError(RPMERR_RELOAD, _("Unable to create immutable header region.\n"));
    00483         goto exit;
    00484     }
    00485     /* Re-reference reallocated header. */
    00486     *hdrp = headerLink(h);
    00487
    00488     /*
    00489      * Write the header+archive into a temp file so that the size of
    00490      * archive (after compression) can be added to the header.
    00491      */
    00492     if (makeTempFile(NULL, &sigtarget, &fd)) {
    00493         rc = RPMERR_CREATE;
    00494         rpmError(RPMERR_CREATE, _("Unable to open temp file.\n"));
    00495         goto exit;
    00496     }
    00497
    00498     fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
    00499     if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
    00500         rc = RPMERR_NOSPACE;
    00501         rpmError(RPMERR_NOSPACE, _("Unable to write temp header\n"));
    00502     } else { /* Write the archive and get the size */
    00503         (void) Fflush(fd);
    00504         fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
    00505         if (csa->cpioList != NULL) {
    00506             rc = cpio_doio(fd, h, csa, rpmio_flags);
    00507         } else if (Fileno(csa->cpioFdIn) >= 0) {
    00508             rc = cpio_copy(fd, csa);
    00509         } else {
    00510             rc = RPMERR_BADARG;
    00511             rpmError(RPMERR_BADARG, _("Bad CSA data\n"));
    00512         }
    00513     }
    00514     rpmio_flags = _free(rpmio_flags);
    00515
    00516     if (rc)
    00517         goto exit;
    00518
    00519 #ifdef  DYING
    00520     /*
    00521      * Set the actual archive size, and rewrite the header.
    00522      * This used to be done using headerModifyEntry(), but now that headers
    00523      * have regions, the value is scribbled directly into the header data
    00524      * area. Some new scheme for adding the final archive size will have
    00525      * to be devised if headerGetEntryMinMemory() ever changes to return
    00526      * a pointer to memory not in the region, probably by appending
    00527      * the archive size to the header region rather than including the
    00528      * archive size within the header region.
    00529      */
    00530     if (Fileno(csa->cpioFdIn) < 0) {
    00531         HGE_t hge = (HGE_t)headerGetEntryMinMemory;
    00532         int_32 * archiveSize;
    00533         if (hge(h, RPMTAG_ARCHIVESIZE, NULL, (void *)&archiveSize, NULL))
    00534             *archiveSize = csa->cpioArchiveSize;
    00535     }
    00536
    00537     (void) Fflush(fd);
    00538     if (Fseek(fd, 0, SEEK_SET) == -1) {
    00539         rc = RPMERR_FSEEK;
    00540         rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
    00541                         sigtarget, Fstrerror(fd));
    00542     }
    00543
    00544     fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
    00545     if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
    00546         rc = RPMERR_NOSPACE;
    00547         rpmError(RPMERR_NOSPACE, _("Unable to write final header\n"));
    00548     }
    00549     (void) Fflush(fd);
    00550     fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
    00551 #endif
    00552
    00553     (void) Fclose(fd);
    00554     fd = NULL;
    00555     (void) Unlink(fileName);
    00556
    00557     if (rc)
    00558         goto exit;
    00559
    00560     /* Generate the signature */
    00561     (void) fflush(stdout);
    00562     sig = rpmNewSignature();
    00563     (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
    00564     (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
    00565
    00566     if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
    00567         rpmMessage(RPMMESS_NORMAL, _("Generating signature: %d\n"), sigtag);
    00568         (void) rpmAddSignature(sig, sigtarget, sigtag, passPhrase);
    00569     }
    00570
    00571     if (SHA1) {
    00572         (void) headerAddEntry(sig, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1);
    00573         SHA1 = _free(SHA1);
    00574     }
    00575
    00576     {   int_32 payloadSize = csa->cpioArchiveSize;
    00577         (void) headerAddEntry(sig, RPMSIGTAG_PAYLOADSIZE, RPM_INT32_TYPE,
    00578                         &payloadSize, 1);
    00579     }
    00580
    00581     /* Reallocate the signature into one contiguous region. */
    00582     sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
    00583     if (sig == NULL) {  /* XXX can't happen */
    00584         rc = RPMERR_RELOAD;
    00585         rpmError(RPMERR_RELOAD, _("Unable to reload signature header.\n"));
    00586         goto exit;
    00587     }
    00588
    00589     /* Open the output file */
    00590     fd = Fopen(fileName, "w.ufdio");
    00591     if (fd == NULL || Ferror(fd)) {
    00592         rc = RPMERR_CREATE;
    00593         rpmError(RPMERR_CREATE, _("Could not open %s: %s\n"),
    00594                 fileName, Fstrerror(fd));
    00595         goto exit;
    00596     }
    00597
    00598     /* Write the lead section into the package. */
    00599     {   int archnum = -1;
    00600         int osnum = -1;
    00601         struct rpmlead lead;
    00602
    00603         if (Fileno(csa->cpioFdIn) < 0) {
    00604 #ifndef DYING
    00605             rpmGetArchInfo(NULL, &archnum);
    00606             rpmGetOsInfo(NULL, &osnum);
    00607 #endif
    00608         } else if (csa->lead != NULL) {
    00609             archnum = csa->lead->archnum;
    00610             osnum = csa->lead->osnum;
    00611         }
    00612
    00613         memset(&lead, 0, sizeof(lead));
    00614         lead.major = rpmLeadVersion();
    00615         lead.minor = 0;
    00616         lead.type = type;
    00617         lead.archnum = archnum;
    00618         lead.osnum = osnum;
    00619         lead.signature_type = RPMSIGTYPE_HEADERSIG;
    00620
    00621         {   const char *name, *version, *release;
    00622             (void) headerNVR(h, &name, &version, &release);
    00623             sprintf(buf, "%s-%s-%s", name, version, release);
    00624             strncpy(lead.name, buf, sizeof(lead.name));
    00625         }
    00626
    00627         if (writeLead(fd, &lead) != RPMRC_OK) {
    00628             rc = RPMERR_NOSPACE;
    00629             rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
    00630                  Fstrerror(fd));
    00631             goto exit;
    00632         }
    00633     }
    00634
    00635     /* Write the signature section into the package. */
    00636     rc = rpmWriteSignature(fd, sig);
    00637     if (rc)
    00638         goto exit;
    00639
    00640     /* Append the header and archive */
    00641     ifd = Fopen(sigtarget, "r.ufdio");
    00642     if (ifd == NULL || Ferror(ifd)) {
    00643         rc = RPMERR_READ;
    00644         rpmError(RPMERR_READ, _("Unable to open sigtarget %s: %s\n"),
    00645                 sigtarget, Fstrerror(ifd));
    00646         goto exit;
    00647     }
    00648
    00649     /* Add signatures to header, and write header into the package. */
    00650     /* XXX header+payload digests/signatures might be checked again here. */
    00651     {   Header nh = headerRead(ifd, HEADER_MAGIC_YES);
    00652
    00653         if (nh == NULL) {
    00654             rc = RPMERR_READ;
    00655             rpmError(RPMERR_READ, _("Unable to read header from %s: %s\n"),
    00656                         sigtarget, Fstrerror(ifd));
    00657             goto exit;
    00658         }
    00659
    00660 #ifdef  NOTYET
    00661         (void) headerMergeLegacySigs(nh, sig);
    00662 #endif
    00663
    00664         rc = headerWrite(fd, nh, HEADER_MAGIC_YES);
    00665         nh = headerFree(nh);
    00666
    00667         if (rc) {
    00668             rc = RPMERR_NOSPACE;
    00669             rpmError(RPMERR_NOSPACE, _("Unable to write header to %s: %s\n"),
    00670                         fileName, Fstrerror(fd));
    00671             goto exit;
    00672         }
    00673     }
    00674
    00675     /* Write the payload into the package. */
    00676     while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
    00677         if (count == -1) {
    00678             rc = RPMERR_READ;
    00679             rpmError(RPMERR_READ, _("Unable to read payload from %s: %s\n"),
    00680                      sigtarget, Fstrerror(ifd));
    00681             goto exit;
    00682         }
    00683         if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
    00684             rc = RPMERR_NOSPACE;
    00685             rpmError(RPMERR_NOSPACE, _("Unable to write payload to %s: %s\n"),
    00686                      fileName, Fstrerror(fd));
    00687             goto exit;
    00688         }
    00689     }
    00690     rc = 0;
    00691
    00692 exit:
    00693     SHA1 = _free(SHA1);
    00694     h = headerFree(h);
    00695     sig = rpmFreeSignature(sig);
    00696     if (ifd) {
    00697         (void) Fclose(ifd);
    00698         ifd = NULL;
    00699     }
    00700     if (fd) {
    00701         (void) Fclose(fd);
    00702         fd = NULL;
    00703     }
    00704     if (sigtarget) {
    00705         (void) Unlink(sigtarget);
    00706         sigtarget = _free(sigtarget);
    00707     }
    00708
    00709     if (rc == 0)
    00710         rpmMessage(RPMMESS_NORMAL, _("Wrote: %s\n"), fileName);
    00711     else
    00712         (void) Unlink(fileName);
    00713
    00714     return rc;
    00715 }
    00716 /*@=boundswrite@*/
    00717
    00718 /*@unchecked@*/
    00719 static int_32 copyTags[] = {
    00720     RPMTAG_CHANGELOGTIME,
    00721     RPMTAG_CHANGELOGNAME,
    00722     RPMTAG_CHANGELOGTEXT,
    00723     0
    00724 };
    00725
    00726 /*@-boundswrite@*/
    00727 int packageBinaries(Spec spec)
    00728 {
    00729     struct cpioSourceArchive_s csabuf;
    00730     CSA_t csa = &csabuf;
    00731     int rc;
    00732     const char *errorString;
    00733     Package pkg;
    00734
    00735     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
    00736         const char *fn;
    00737
    00738         if (pkg->fileList == NULL)
    00739             continue;
    00740
    00741         if ((rc = processScriptFiles(spec, pkg)))
    00742             return rc;
    00743
    00744         if (spec->cookie) {
    00745             (void) headerAddEntry(pkg->header, RPMTAG_COOKIE,
    00746                            RPM_STRING_TYPE, spec->cookie, 1);
    00747         }
    00748
    00749         /* Copy changelog from src rpm */
    00750         headerCopyTags(spec->packages->header, pkg->header, copyTags);
    00751
    00752         (void) headerAddEntry(pkg->header, RPMTAG_RPMVERSION,
    00753                        RPM_STRING_TYPE, VERSION, 1);
    00754         (void) headerAddEntry(pkg->header, RPMTAG_BUILDHOST,
    00755                        RPM_STRING_TYPE, buildHost(), 1);
    00756         (void) headerAddEntry(pkg->header, RPMTAG_BUILDTIME,
    00757                        RPM_INT32_TYPE, getBuildTime(), 1);
    00758
    00759         providePackageNVR(pkg->header);
    00760
    00761     {   const char * optflags = rpmExpand("%{optflags}", NULL);
    00762         (void) headerAddEntry(pkg->header, RPMTAG_OPTFLAGS, RPM_STRING_TYPE,
    00763                         optflags, 1);
    00764         optflags = _free(optflags);
    00765     }
    00766
    00767         (void) genSourceRpmName(spec);
    00768         (void) headerAddEntry(pkg->header, RPMTAG_SOURCERPM, RPM_STRING_TYPE,
    00769                        spec->sourceRpmName, 1);
    00770
    00771         {   const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
    00772             char *binRpm, *binDir;
    00773             binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
    00774                                rpmHeaderFormats, &errorString);
    00775             binFormat = _free(binFormat);
    00776             if (binRpm == NULL) {
    00777                 const char *name;
    00778                 (void) headerNVR(pkg->header, &name, NULL, NULL);
    00779                 rpmError(RPMERR_BADFILENAME, _("Could not generate output "
    00780                      "filename for package %s: %s\n"), name, errorString);
    00781                 return RPMERR_BADFILENAME;
    00782             }
    00783             fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
    00784             if ((binDir = strchr(binRpm, '/')) != NULL) {
    00785                 struct stat st;
    00786                 const char *dn;
    00787                 *binDir = '\0';
    00788                 dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
    00789                 if (Stat(dn, &st) < 0) {
    00790                     switch(errno) {
    00791                     case  ENOENT:
    00792                         if (Mkdir(dn, 0755) == 0)
    00793                             /*@switchbreak@*/ break;
    00794                         /*@fallthrough@*/
    00795                     default:
    00796                         rpmError(RPMERR_BADFILENAME,_("cannot create %s: %s\n"),
    00797                             dn, strerror(errno));
    00798                         /*@switchbreak@*/ break;
    00799                     }
    00800                 }
    00801                 dn = _free(dn);
    00802             }
    00803             binRpm = _free(binRpm);
    00804         }
    00805
    00806         memset(csa, 0, sizeof(*csa));
    00807         csa->cpioArchiveSize = 0;
    00808         /*@-type@*/ /* LCL: function typedefs */
    00809         csa->cpioFdIn = fdNew("init (packageBinaries)");
    00810         /*@-assignexpose -newreftrans@*/
    00811 /*@i@*/ csa->cpioList = pkg->cpioList;
    00812         /*@=assignexpose =newreftrans@*/
    00813
    00814         rc = writeRPM(&pkg->header, fn, RPMLEAD_BINARY,
    00815                     csa, spec->passPhrase, NULL);
    00816         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
    00817         /*@=type@*/
    00818         fn = _free(fn);
    00819         if (rc)
    00820             return rc;
    00821     }
    00822
    00823     return 0;
    00824 }
    00825 /*@=boundswrite@*/
    00826
    00827 /*@-boundswrite@*/
    00828 int packageSources(Spec spec)
    00829 {
    00830     struct cpioSourceArchive_s csabuf;
    00831     CSA_t csa = &csabuf;
    00832     int rc;
    00833
    00834     /* Add some cruft */
    00835     (void) headerAddEntry(spec->sourceHeader, RPMTAG_RPMVERSION,
    00836                    RPM_STRING_TYPE, VERSION, 1);
    00837     (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDHOST,
    00838                    RPM_STRING_TYPE, buildHost(), 1);
    00839     (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDTIME,
    00840                    RPM_INT32_TYPE, getBuildTime(), 1);
    00841
    00842     (void) genSourceRpmName(spec);
    00843
    00844     spec->cookie = _free(spec->cookie);
    00845
    00846     /* XXX this should be %_srpmdir */
    00847     {   const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
    00848
    00849         memset(csa, 0, sizeof(*csa));
    00850         csa->cpioArchiveSize = 0;
    00851         /*@-type@*/ /* LCL: function typedefs */
    00852         csa->cpioFdIn = fdNew("init (packageSources)");
    00853         /*@-assignexpose -newreftrans@*/
    00854 /*@i@*/ csa->cpioList = spec->sourceCpioList;
    00855         /*@=assignexpose =newreftrans@*/
    00856
    00857         rc = writeRPM(&spec->sourceHeader, fn, RPMLEAD_SOURCE,
    00858                 csa, spec->passPhrase, &(spec->cookie));
    00859         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
    00860         /*@=type@*/
    00861         fn = _free(fn);
    00862     }
    00863     return rc;
    00864 }
    00865 /*@=boundswrite@*/