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         strcpy(buf, rpmio_flags);
00483         buf[s - rpmio_flags] = '\0';
00484         (void) headerAddEntry(h, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, buf+1, 1);
00485     }
00486 
00487     /* Create and add the cookie */
00488     if (cookie) {
00489         sprintf(buf, "%s %d", buildHost(), (int) (*getBuildTime()));
00490         *cookie = xstrdup(buf);
00491         (void) headerAddEntry(h, RPMTAG_COOKIE, RPM_STRING_TYPE, *cookie, 1);
00492     }
00493     
00494     /* Reallocate the header into one contiguous region. */
00495     h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
00496     if (h == NULL) {    /* XXX can't happen */
00497         rc = RPMERR_RELOAD;
00498         rpmError(RPMERR_RELOAD, _("Unable to create immutable header region.\n"));
00499         goto exit;
00500     }
00501     /* Re-reference reallocated header. */
00502     *hdrp = headerLink(h);
00503 
00504     /*
00505      * Write the header+archive into a temp file so that the size of
00506      * archive (after compression) can be added to the header.
00507      */
00508     if (makeTempFile(NULL, &sigtarget, &fd)) {
00509         rc = RPMERR_CREATE;
00510         rpmError(RPMERR_CREATE, _("Unable to open temp file.\n"));
00511         goto exit;
00512     }
00513 
00514     fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00515     if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
00516         rc = RPMERR_NOSPACE;
00517         rpmError(RPMERR_NOSPACE, _("Unable to write temp header\n"));
00518     } else { /* Write the archive and get the size */
00519         (void) Fflush(fd);
00520         fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
00521         if (csa->cpioList != NULL) {
00522             rc = cpio_doio(fd, h, csa, rpmio_flags);
00523         } else if (Fileno(csa->cpioFdIn) >= 0) {
00524             rc = cpio_copy(fd, csa);
00525         } else {
00526             rc = RPMERR_BADARG;
00527             rpmError(RPMERR_BADARG, _("Bad CSA data\n"));
00528         }
00529     }
00530     rpmio_flags = _free(rpmio_flags);
00531 
00532     if (rc)
00533         goto exit;
00534 
00535 #ifdef  DYING
00536     /*
00537      * Set the actual archive size, and rewrite the header.
00538      * This used to be done using headerModifyEntry(), but now that headers
00539      * have regions, the value is scribbled directly into the header data
00540      * area. Some new scheme for adding the final archive size will have
00541      * to be devised if headerGetEntryMinMemory() ever changes to return
00542      * a pointer to memory not in the region, probably by appending
00543      * the archive size to the header region rather than including the
00544      * archive size within the header region.
00545      */
00546     if (Fileno(csa->cpioFdIn) < 0) {
00547         HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00548         int_32 * archiveSize;
00549         if (hge(h, RPMTAG_ARCHIVESIZE, NULL, (void *)&archiveSize, NULL))
00550             *archiveSize = csa->cpioArchiveSize;
00551     }
00552 
00553     (void) Fflush(fd);
00554     if (Fseek(fd, 0, SEEK_SET) == -1) {
00555         rc = RPMERR_FSEEK;
00556         rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
00557                         sigtarget, Fstrerror(fd));
00558     }
00559 
00560     fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00561     if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
00562         rc = RPMERR_NOSPACE;
00563         rpmError(RPMERR_NOSPACE, _("Unable to write final header\n"));
00564     }
00565     (void) Fflush(fd);
00566     fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
00567 #endif
00568 
00569     (void) Fclose(fd);
00570     fd = NULL;
00571     (void) Unlink(fileName);
00572 
00573     if (rc)
00574         goto exit;
00575 
00576     /* Generate the signature */
00577     (void) fflush(stdout);
00578     sig = rpmNewSignature();
00579     (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
00580     (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
00581 
00582     if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
00583         rpmMessage(RPMMESS_NORMAL, _("Generating signature: %d\n"), sigtag);
00584         (void) rpmAddSignature(sig, sigtarget, sigtag, passPhrase);
00585     }
00586     
00587     if (SHA1) {
00588         (void) headerAddEntry(sig, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1);
00589         SHA1 = _free(SHA1);
00590     }
00591 
00592     {   int_32 payloadSize = csa->cpioArchiveSize;
00593         (void) headerAddEntry(sig, RPMSIGTAG_PAYLOADSIZE, RPM_INT32_TYPE,
00594                         &payloadSize, 1);
00595     }
00596 
00597     /* Reallocate the signature into one contiguous region. */
00598     sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
00599     if (sig == NULL) {  /* XXX can't happen */
00600         rc = RPMERR_RELOAD;
00601         rpmError(RPMERR_RELOAD, _("Unable to reload signature header.\n"));
00602         goto exit;
00603     }
00604 
00605     /* Open the output file */
00606     fd = Fopen(fileName, "w.ufdio");
00607     if (fd == NULL || Ferror(fd)) {
00608         rc = RPMERR_CREATE;
00609         rpmError(RPMERR_CREATE, _("Could not open %s: %s\n"),
00610                 fileName, Fstrerror(fd));
00611         goto exit;
00612     }
00613 
00614     /* Write the lead section into the package. */
00615     {   int archnum = -1;
00616         int osnum = -1;
00617         struct rpmlead lead;
00618 
00619         if (Fileno(csa->cpioFdIn) < 0) {
00620 #ifndef DYING
00621             rpmGetArchInfo(NULL, &archnum);
00622             rpmGetOsInfo(NULL, &osnum);
00623 #endif
00624         } else if (csa->lead != NULL) {
00625             archnum = csa->lead->archnum;
00626             osnum = csa->lead->osnum;
00627         }
00628 
00629         memset(&lead, 0, sizeof(lead));
00630         lead.major = rpmLeadVersion();
00631         lead.minor = 0;
00632         lead.type = type;
00633         lead.archnum = archnum;
00634         lead.osnum = osnum;
00635         lead.signature_type = RPMSIGTYPE_HEADERSIG;
00636 
00637         {   const char *name, *version, *release;
00638             (void) headerNVR(h, &name, &version, &release);
00639             sprintf(buf, "%s-%s-%s", name, version, release);
00640             strncpy(lead.name, buf, sizeof(lead.name));
00641         }
00642 
00643         if (writeLead(fd, &lead) != RPMRC_OK) {
00644             rc = RPMERR_NOSPACE;
00645             rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
00646                  Fstrerror(fd));
00647             goto exit;
00648         }
00649     }
00650 
00651     /* Write the signature section into the package. */
00652     rc = rpmWriteSignature(fd, sig);
00653     if (rc)
00654         goto exit;
00655 
00656     /* Append the header and archive */
00657     ifd = Fopen(sigtarget, "r.ufdio");
00658     if (ifd == NULL || Ferror(ifd)) {
00659         rc = RPMERR_READ;
00660         rpmError(RPMERR_READ, _("Unable to open sigtarget %s: %s\n"),
00661                 sigtarget, Fstrerror(ifd));
00662         goto exit;
00663     }
00664 
00665     /* Add signatures to header, and write header into the package. */
00666     /* XXX header+payload digests/signatures might be checked again here. */
00667     {   Header nh = headerRead(ifd, HEADER_MAGIC_YES);
00668 
00669         if (nh == NULL) {
00670             rc = RPMERR_READ;
00671             rpmError(RPMERR_READ, _("Unable to read header from %s: %s\n"),
00672                         sigtarget, Fstrerror(ifd));
00673             goto exit;
00674         }
00675 
00676 #ifdef  NOTYET
00677         (void) headerMergeLegacySigs(nh, sig);
00678 #endif
00679 
00680         rc = headerWrite(fd, nh, HEADER_MAGIC_YES);
00681         nh = headerFree(nh);
00682 
00683         if (rc) {
00684             rc = RPMERR_NOSPACE;
00685             rpmError(RPMERR_NOSPACE, _("Unable to write header to %s: %s\n"),
00686                         fileName, Fstrerror(fd));
00687             goto exit;
00688         }
00689     }
00690         
00691     /* Write the payload into the package. */
00692     while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
00693         if (count == -1) {
00694             rc = RPMERR_READ;
00695             rpmError(RPMERR_READ, _("Unable to read payload from %s: %s\n"),
00696                      sigtarget, Fstrerror(ifd));
00697             goto exit;
00698         }
00699         if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
00700             rc = RPMERR_NOSPACE;
00701             rpmError(RPMERR_NOSPACE, _("Unable to write payload to %s: %s\n"),
00702                      fileName, Fstrerror(fd));
00703             goto exit;
00704         }
00705     }
00706     rc = 0;
00707 
00708 exit:
00709     SHA1 = _free(SHA1);
00710     h = headerFree(h);
00711 
00712     /* XXX Fish the pkgid out of the signature header. */
00713     if (sig != NULL && pkgidp != NULL) {
00714         int_32 tagType;
00715         unsigned char * MD5 = NULL;
00716         int_32 c;
00717         int xx;
00718         xx = headerGetEntry(sig, RPMSIGTAG_MD5, &tagType, (void **)&MD5, &c);
00719         if (tagType == RPM_BIN_TYPE && MD5 != NULL && c == 16)
00720             *pkgidp = MD5;
00721     }
00722 
00723     sig = rpmFreeSignature(sig);
00724     if (ifd) {
00725         (void) Fclose(ifd);
00726         ifd = NULL;
00727     }
00728     if (fd) {
00729         (void) Fclose(fd);
00730         fd = NULL;
00731     }
00732     if (sigtarget) {
00733         (void) Unlink(sigtarget);
00734         sigtarget = _free(sigtarget);
00735     }
00736 
00737     if (rc == 0)
00738         rpmMessage(RPMMESS_NORMAL, _("Wrote: %s\n"), fileName);
00739     else
00740         (void) Unlink(fileName);
00741 
00742     return rc;
00743 }
00744 /*@=boundswrite@*/
00745 
00746 /*@unchecked@*/
00747 static int_32 copyTags[] = {
00748     RPMTAG_CHANGELOGTIME,
00749     RPMTAG_CHANGELOGNAME,
00750     RPMTAG_CHANGELOGTEXT,
00751     0
00752 };
00753 
00754 /*@-boundswrite@*/
00755 int packageBinaries(Spec spec)
00756 {
00757     struct cpioSourceArchive_s csabuf;
00758     CSA_t csa = &csabuf;
00759     int rc;
00760     const char *errorString;
00761     Package pkg;
00762 
00763     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00764         const char *fn;
00765 
00766         if (pkg->fileList == NULL)
00767             continue;
00768 
00769         if ((rc = processScriptFiles(spec, pkg)))
00770             return rc;
00771         
00772         if (spec->cookie) {
00773             (void) headerAddEntry(pkg->header, RPMTAG_COOKIE,
00774                            RPM_STRING_TYPE, spec->cookie, 1);
00775         }
00776 
00777         /* Copy changelog from src rpm */
00778         headerCopyTags(spec->packages->header, pkg->header, copyTags);
00779         
00780         (void) headerAddEntry(pkg->header, RPMTAG_RPMVERSION,
00781                        RPM_STRING_TYPE, VERSION, 1);
00782         (void) headerAddEntry(pkg->header, RPMTAG_BUILDHOST,
00783                        RPM_STRING_TYPE, buildHost(), 1);
00784         (void) headerAddEntry(pkg->header, RPMTAG_BUILDTIME,
00785                        RPM_INT32_TYPE, getBuildTime(), 1);
00786 
00787         providePackageNVR(pkg->header);
00788 
00789     {   const char * optflags = rpmExpand("%{optflags}", NULL);
00790         (void) headerAddEntry(pkg->header, RPMTAG_OPTFLAGS, RPM_STRING_TYPE,
00791                         optflags, 1);
00792         optflags = _free(optflags);
00793     }
00794 
00795         (void) genSourceRpmName(spec);
00796         (void) headerAddEntry(pkg->header, RPMTAG_SOURCERPM, RPM_STRING_TYPE,
00797                        spec->sourceRpmName, 1);
00798         if (spec->sourcePkgId != NULL) {
00799         (void) headerAddEntry(pkg->header, RPMTAG_SOURCEPKGID, RPM_BIN_TYPE,
00800                        spec->sourcePkgId, 16);
00801         }
00802         
00803         {   const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
00804             char *binRpm, *binDir;
00805             binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
00806                                rpmHeaderFormats, &errorString);
00807             binFormat = _free(binFormat);
00808             if (binRpm == NULL) {
00809                 const char *name;
00810                 (void) headerNVR(pkg->header, &name, NULL, NULL);
00811                 rpmError(RPMERR_BADFILENAME, _("Could not generate output "
00812                      "filename for package %s: %s\n"), name, errorString);
00813                 return RPMERR_BADFILENAME;
00814             }
00815             fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
00816             if ((binDir = strchr(binRpm, '/')) != NULL) {
00817                 struct stat st;
00818                 const char *dn;
00819                 *binDir = '\0';
00820                 dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
00821                 if (Stat(dn, &st) < 0) {
00822                     switch(errno) {
00823                     case  ENOENT:
00824                         if (Mkdir(dn, 0755) == 0)
00825                             /*@switchbreak@*/ break;
00826                         /*@fallthrough@*/
00827                     default:
00828                         rpmError(RPMERR_BADFILENAME,_("cannot create %s: %s\n"),
00829                             dn, strerror(errno));
00830                         /*@switchbreak@*/ break;
00831                     }
00832                 }
00833                 dn = _free(dn);
00834             }
00835             binRpm = _free(binRpm);
00836         }
00837 
00838         memset(csa, 0, sizeof(*csa));
00839         csa->cpioArchiveSize = 0;
00840         /*@-type@*/ /* LCL: function typedefs */
00841         csa->cpioFdIn = fdNew("init (packageBinaries)");
00842         /*@-assignexpose -newreftrans@*/
00843         csa->cpioList = rpmfiLink(pkg->cpioList, "packageBinaries");
00844         /*@=assignexpose =newreftrans@*/
00845 
00846         rc = writeRPM(&pkg->header, NULL, fn, RPMLEAD_BINARY,
00847                     csa, spec->passPhrase, NULL);
00848 
00849         csa->cpioList = rpmfiFree(csa->cpioList);
00850         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
00851         /*@=type@*/
00852         fn = _free(fn);
00853         if (rc)
00854             return rc;
00855     }
00856     
00857     return 0;
00858 }
00859 /*@=boundswrite@*/
00860 
00861 /*@-boundswrite@*/
00862 int packageSources(Spec spec)
00863 {
00864     struct cpioSourceArchive_s csabuf;
00865     CSA_t csa = &csabuf;
00866     int rc;
00867 
00868     /* Add some cruft */
00869     (void) headerAddEntry(spec->sourceHeader, RPMTAG_RPMVERSION,
00870                    RPM_STRING_TYPE, VERSION, 1);
00871     (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDHOST,
00872                    RPM_STRING_TYPE, buildHost(), 1);
00873     (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDTIME,
00874                    RPM_INT32_TYPE, getBuildTime(), 1);
00875 
00876     (void) genSourceRpmName(spec);
00877 
00878     spec->cookie = _free(spec->cookie);
00879     
00880     /* XXX this should be %_srpmdir */
00881     {   const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
00882 
00883         memset(csa, 0, sizeof(*csa));
00884         csa->cpioArchiveSize = 0;
00885         /*@-type@*/ /* LCL: function typedefs */
00886         csa->cpioFdIn = fdNew("init (packageSources)");
00887         /*@-assignexpose -newreftrans@*/
00888         csa->cpioList = rpmfiLink(spec->sourceCpioList, "packageSources");
00889         /*@=assignexpose =newreftrans@*/
00890 
00891         spec->sourcePkgId = NULL;
00892         rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn, RPMLEAD_SOURCE,
00893                 csa, spec->passPhrase, &(spec->cookie));
00894 
00895         csa->cpioList = rpmfiFree(csa->cpioList);
00896         csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
00897         /*@=type@*/
00898         fn = _free(fn);
00899     }
00900     return rc;
00901 }
00902 /*@=boundswrite@*/

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2