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

Generated on Sun Oct 26 13:01:57 2003 for rpm by doxygen1.2.18