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

pack.c

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

Generated on Mon Mar 5 13:30:21 2007 for rpm by  doxygen 1.4.4