build/pack.c

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

Generated on Fri May 25 21:18:11 2007 for rpm by  doxygen 1.5.2