- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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