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