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

Generated on Fri Feb 22 15:15:32 2008 for rpm by  doxygen 1.5.2