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

build/pack.c

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

Generated on Wed Sep 4 12:49:49 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002