rpm 5.2.1

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

- File List
- Globals

pack.c
Go to the documentation of this file.
1
6 #include "system.h"
7
8 #include <rpmio_internal.h> /* XXX fdGetFp, fdInitDigest, fdFiniDigest */
9 #include <rpmcb.h>
10 #include <argv.h>
11
12 #include <rpmtypes.h>
13 #include <rpmtag.h>
14
15 #include <pkgio.h>
16 #include "signature.h" /* XXX rpmTempFile */
17
18 #define _RPMFI_INTERNAL /* XXX fi->fsm */
19 #define _RPMEVR_INTERNAL /* XXX RPMSENSE_ANY */
20 #define _RPMTAG_INTERNAL
21 #include <rpmbuild.h>
22
23 #include "rpmfi.h"
24 #include "fsm.h"
25
26 #include <rpmversion.h>
27 #include "buildio.h"
28
29 #include "debug.h"
30
31 /*@access rpmts @*/
32 /*@access rpmfi @*/ /* compared with NULL */
33 /*@access Header @*/ /* compared with NULL */
34 /*@access FD_t @*/ /* compared with NULL */
35 /*@access CSA_t @*/
36
40 static rpmRC cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
41 const char * payload_format, const char * fmodeMacro)
42 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
43 /*@modifies fdo, csa, rpmGlobalMacroContext,
44 fileSystem, internalState @*/
45 {
46 rpmts ts = rpmtsCreate();
47 rpmfi fi = csa->cpioList;
48 const char *failedFile = NULL;
49 FD_t cfd;
50 rpmRC rc = RPMRC_OK;
51 int xx;
52
53 { const char *fmode = rpmExpand(fmodeMacro, NULL);
54 if (!(fmode && fmode[0] == 'w'))
55 fmode = xstrdup("w9.gzdio");
56 /*@-nullpass@*/
57 (void) Fflush(fdo);
58 cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
59 /*@=nullpass@*/
60 fmode = _free(fmode);
61 }
62 if (cfd == NULL)
63 return RPMRC_FAIL;
64
65 xx = fsmSetup(fi->fsm, IOSM_PKGBUILD, payload_format, ts, fi, cfd,
66 &csa->cpioArchiveSize, &failedFile);
67 if (xx)
68 rc = RPMRC_FAIL;
69 (void) Fclose(cfd);
70 xx = fsmTeardown(fi->fsm);
71 if (rc == RPMRC_OK && xx) rc = RPMRC_FAIL;
72
73 if (rc) {
74 const char * msg = iosmStrerror(rc);
75 if (failedFile)
76 rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
77 failedFile, msg);
78 else
79 rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), msg);
80 msg = _free(msg);
81 rc = RPMRC_FAIL;
82 }
83
84 failedFile = _free(failedFile);
85 (void)rpmtsFree(ts);
86 ts = NULL;
87
88 return rc;
89 }
90
93 static rpmRC cpio_copy(FD_t fdo, CSA_t csa)
94 /*@globals fileSystem, internalState @*/
95 /*@modifies fdo, csa, fileSystem, internalState @*/
96 {
97 char buf[BUFSIZ];
98 size_t nb;
99
100 while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
101 if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
102 rpmlog(RPMLOG_ERR, _("cpio_copy write failed: %s\n"),
103 Fstrerror(fdo));
104 return RPMRC_FAIL;
105 }
106 csa->cpioArchiveSize += nb;
107 }
108 if (Ferror(csa->cpioFdIn)) {
109 rpmlog(RPMLOG_ERR, _("cpio_copy read failed: %s\n"),
110 Fstrerror(csa->cpioFdIn));
111 return RPMRC_FAIL;
112 }
113 return RPMRC_OK;
114 }
115
118 static /*@only@*/ /*@null@*/ rpmiob addFileToTagAux(Spec spec,
119 const char * file, /*@only@*/ rpmiob iob)
120 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
121 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
122 {
123 char buf[BUFSIZ];
124 const char * fn = buf;
125 FILE * f;
126 FD_t fd;
127
128 fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);
129
130 fd = Fopen(fn, "r.fdio");
131 if (fn != buf) fn = _free(fn);
132 if (fd == NULL || Ferror(fd)) {
133 iob = rpmiobFree(iob);
134 return NULL;
135 }
136 /*@-type@*/ /* FIX: cast? */
137 if ((f = fdGetFp(fd)) != NULL)
138 /*@=type@*/
139 while (fgets(buf, (int)sizeof(buf), f)) {
140 /* XXX display fn in error msg */
141 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
142 rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
143 iob = rpmiobFree(iob);
144 break;
145 }
146 iob = rpmiobAppend(iob, buf, 0);
147 }
148 (void) Fclose(fd);
149
150 return iob;
151 }
152
155 static int addFileToTag(Spec spec, const char * file, Header h, rpmTag tag)
156 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
157 /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
158 {
159 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
160 rpmiob iob = rpmiobNew(0);
161 int xx;
162
163 he->tag = tag;
164 xx = headerGet(h, he, 0);
165 if (xx) {
166 iob = rpmiobAppend(iob, he->p.str, 1);
167 xx = headerDel(h, he, 0);
168 }
169 he->p.ptr = _free(he->p.ptr);
170
171 if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
172 return 1;
173
174 he->tag = tag;
175 he->t = RPM_STRING_TYPE;
176 he->p.str = rpmiobStr(iob);
177 he->c = 1;
178 xx = headerPut(h, he, 0);
179
180 iob = rpmiobFree(iob);
181 return 0;
182 }
183
186 static int addFileToArrayTag(Spec spec, const char *file, Header h, rpmTag tag)
187 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
188 /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
189 {
190 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
191 rpmiob iob = rpmiobNew(0);
192 const char *s;
193 int xx;
194
195 if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
196 return 1;
197
198 s = rpmiobStr(iob);
199
200 he->tag = tag;
201 he->t = RPM_STRING_ARRAY_TYPE;
202 he->p.argv = &s;
203 he->c = 1;
204 he->append = 1;
205 xx = headerPut(h, he, 0);
206 he->append = 0;
207
208 iob = rpmiobFree(iob);
209 return 0;
210 }
211
212 rpmRC processScriptFiles(Spec spec, Package pkg)
213 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
214 /*@modifies pkg->header, rpmGlobalMacroContext,
215 fileSystem, internalState @*/
216 {
217 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
218 struct TriggerFileEntry *p;
219 int xx;
220
221 if (pkg->preInFile) {
222 if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
223 rpmlog(RPMLOG_ERR,
224 _("Could not open PreIn file: %s\n"), pkg->preInFile);
225 return RPMRC_FAIL;
226 }
227 }
228 if (pkg->preUnFile) {
229 if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
230 rpmlog(RPMLOG_ERR,
231 _("Could not open PreUn file: %s\n"), pkg->preUnFile);
232 return RPMRC_FAIL;
233 }
234 }
235 if (pkg->preTransFile) {
236 if (addFileToTag(spec, pkg->preTransFile, pkg->header, RPMTAG_PRETRANS)) {
237 rpmlog(RPMLOG_ERR,
238 _("Could not open PreTrans file: %s\n"), pkg->preTransFile);
239 return RPMRC_FAIL;
240 }
241 }
242 if (pkg->postInFile) {
243 if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
244 rpmlog(RPMLOG_ERR,
245 _("Could not open PostIn file: %s\n"), pkg->postInFile);
246 return RPMRC_FAIL;
247 }
248 }
249 if (pkg->postUnFile) {
250 if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
251 rpmlog(RPMLOG_ERR,
252 _("Could not open PostUn file: %s\n"), pkg->postUnFile);
253 return RPMRC_FAIL;
254 }
255 }
256 if (pkg->postTransFile) {
257 if (addFileToTag(spec, pkg->postTransFile, pkg->header, RPMTAG_POSTTRANS)) {
258 rpmlog(RPMLOG_ERR,
259 _("Could not open PostTrans file: %s\n"), pkg->postTransFile);
260 return RPMRC_FAIL;
261 }
262 }
263 if (pkg->verifyFile) {
264 if (addFileToTag(spec, pkg->verifyFile, pkg->header,
265 RPMTAG_VERIFYSCRIPT)) {
266 rpmlog(RPMLOG_ERR,
267 _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
268 return RPMRC_FAIL;
269 }
270 }
271
272 if (pkg->sanityCheckFile) {
273 if (addFileToTag(spec, pkg->sanityCheckFile, pkg->header, RPMTAG_SANITYCHECK)) {
274 rpmlog(RPMLOG_ERR, _("Could not open Test file: %s\n"), pkg->sanityCheckFile);
275 return RPMRC_FAIL;
276 }
277 }
278
279 for (p = pkg->triggerFiles; p != NULL; p = p->next) {
280 he->tag = RPMTAG_TRIGGERSCRIPTPROG;
281 he->t = RPM_STRING_ARRAY_TYPE;
282 he->p.argv = (const char **)&p->prog; /* XXX NOCAST */
283 he->c = 1;
284 he->append = 1;
285 xx = headerPut(pkg->header, he, 0);
286 he->append = 0;
287 if (p->script) {
288 he->tag = RPMTAG_TRIGGERSCRIPTS;
289 he->t = RPM_STRING_ARRAY_TYPE;
290 he->p.argv = (const char **)&p->script; /* XXX NOCAST */
291 he->c = 1;
292 he->append = 1;
293 xx = headerPut(pkg->header, he, 0);
294 he->append = 0;
295 } else if (p->fileName) {
296 if (addFileToArrayTag(spec, p->fileName, pkg->header,
297 RPMTAG_TRIGGERSCRIPTS)) {
298 rpmlog(RPMLOG_ERR,
299 _("Could not open Trigger script file: %s\n"),
300 p->fileName);
301 return RPMRC_FAIL;
302 }
303 } else {
304 /*@observer@*/
305 static const char *bull = "";
306 he->tag = RPMTAG_TRIGGERSCRIPTS;
307 he->t = RPM_STRING_ARRAY_TYPE;
308 he->p.argv = &bull;
309 he->c = 1;
310 he->append = 1;
311 xx = headerPut(pkg->header, he, 0);
312 he->append = 0;
313 }
314 }
315
316 return RPMRC_OK;
317 }
318
319 #if defined(DEAD)
320 int readRPM(const char *fileName, Spec *specp, void * l,
321 Header *sigs, CSA_t csa)
322 {
323 const char * msg = "";
324 FD_t fdi;
325 Spec spec;
326 rpmRC rc;
327
328 fdi = (fileName != NULL)
329 ? Fopen(fileName, "r.fdio")
330 : fdDup(STDIN_FILENO);
331
332 if (fdi == NULL || Ferror(fdi)) {
333 rpmlog(RPMLOG_ERR, _("readRPM: open %s: %s\n"),
334 (fileName ? fileName : "<stdin>"),
335 Fstrerror(fdi));
336 if (fdi) (void) Fclose(fdi);
337 return RPMRC_FAIL;
338 }
339
340 { const char item[] = "Lead";
341 size_t nl = rpmpkgSizeof(item, NULL);
342
343 if (nl == 0) {
344 rc = RPMRC_FAIL;
345 msg = xstrdup("item size is zero");
346 } else {
347 l = xcalloc(1, nl); /* XXX memory leak */
348 msg = NULL;
349 rc = rpmpkgRead(item, fdi, l, &msg);
350 }
351 }
352
353 if (rc != RPMRC_OK) {
354 rpmlog(RPMLOG_ERR, _("readRPM: read %s: %s\n"),
355 (fileName ? fileName : "<stdin>"), msg);
356 msg = _free(msg);
357 return RPMRC_FAIL;
358 }
359 msg = _free(msg);
360 /*@=sizeoftype@*/
361
362 /* XXX FIXME: EPIPE on <stdin> */
363 if (Fseek(fdi, 0, SEEK_SET) == -1) {
364 rpmlog(RPMLOG_ERR, _("%s: Fseek failed: %s\n"),
365 (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
366 return RPMRC_FAIL;
367 }
368
369 /* Reallocate build data structures */
370 spec = newSpec();
371 spec->packages = newPackage(spec);
372
373 /* XXX the header just allocated will be allocated again */
374 (void)headerFree(spec->packages->header);
375 spec->packages->header = NULL;
376
377 /* Read the rpm lead, signatures, and header */
378 { rpmts ts = rpmtsCreate();
379
380 /* XXX W2DO? pass fileName? */
381 /*@-mustmod@*/ /* LCL: segfault */
382 rc = rpmReadPackageFile(ts, fdi, "readRPM",
383 &spec->packages->header);
384 /*@=mustmod@*/
385
386 (void)rpmtsFree(ts);
387 ts = NULL;
388
389 if (sigs) *sigs = NULL; /* XXX HACK */
390 }
391
392 switch (rc) {
393 case RPMRC_OK:
394 case RPMRC_NOKEY:
395 case RPMRC_NOTTRUSTED:
396 break;
397 case RPMRC_NOTFOUND:
398 rpmlog(RPMLOG_ERR, _("readRPM: %s is not an RPM package\n"),
399 (fileName ? fileName : "<stdin>"));
400 return RPMRC_FAIL;
401 case RPMRC_FAIL:
402 default:
403 rpmlog(RPMLOG_ERR, _("readRPM: reading header from %s\n"),
404 (fileName ? fileName : "<stdin>"));
405 return RPMRC_FAIL;
406 /*@notreached@*/ break;
407 }
408
409 if (specp)
410 *specp = spec;
411 else
412 spec = freeSpec(spec);
413
414 if (csa != NULL)
415 csa->cpioFdIn = fdi;
416 else
417 (void) Fclose(fdi);
418
419 return 0;
420 }
421 #endif
422
423 #if defined(DEAD)
424 #define RPMPKGVERSION_MIN 30004
425 #define RPMPKGVERSION_MAX 40003
426 /*@unchecked@*/
427 static int rpmpkg_version = -1;
428
429 static int rpmLeadVersion(void)
430 /*@globals rpmpkg_version, rpmGlobalMacroContext, h_errno @*/
431 /*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
432 {
433 int rpmlead_version;
434
435 /* Intitialize packaging version from macro configuration. */
436 if (rpmpkg_version < 0) {
437 rpmpkg_version = rpmExpandNumeric("%{_package_version}");
438 if (rpmpkg_version < RPMPKGVERSION_MIN)
439 rpmpkg_version = RPMPKGVERSION_MIN;
440 if (rpmpkg_version > RPMPKGVERSION_MAX)
441 rpmpkg_version = RPMPKGVERSION_MAX;
442 }
443
444 rpmlead_version = rpmpkg_version / 10000;
445 /* XXX silly sanity check. */
446 if (rpmlead_version < 3 || rpmlead_version > 4)
447 rpmlead_version = 3;
448 return rpmlead_version;
449 }
450 #endif
451
452 void providePackageNVR(Header h)
453 {
454 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
455 const char *N, *V, *R;
456 #ifdef RPM_VENDOR_MANDRIVA
457 const char *D;
458 int gotD;
459 #endif
460 rpmuint32_t E;
461 int gotE;
462 const char *pEVR;
463 char *p;
464 rpmuint32_t pFlags = RPMSENSE_EQUAL;
465 const char ** provides = NULL;
466 const char ** providesEVR = NULL;
467 rpmuint32_t * provideFlags = NULL;
468 int providesCount;
469 int bingo = 1;
470 size_t nb;
471 int xx;
472 int i;
473
474 /* Generate provides for this package N-V-R. */
475 xx = headerNEVRA(h, &N, NULL, &V, &R, NULL);
476 if (!(N && V && R))
477 return;
478
479 nb = 21 + strlen(V) + 1 + strlen(R) + 1;
480 #ifdef RPM_VENDOR_MANDRIVA
481 he->tag = RPMTAG_DISTEPOCH;
482 gotD = headerGet(h, he, 0);
483 D = (he->p.str ? he->p.str : NULL);
484 nb += (gotD ? strlen(D) + 1 : 0);
485 #endif
486 pEVR = p = alloca(nb);
487 *p = '\0';
488 he->tag = RPMTAG_EPOCH;
489 gotE = headerGet(h, he, 0);
490 E = (he->p.ui32p ? he->p.ui32p[0] : 0);
491 he->p.ptr = _free(he->p.ptr);
492 if (gotE) {
493 sprintf(p, "%d:", E);
494 p += strlen(p);
495 }
496 p = stpcpy( stpcpy( stpcpy(p, V) , "-") , R);
497 #ifdef RPM_VENDOR_MANDRIVA
498 if (gotD) {
499 p = stpcpy( stpcpy( p, ":"), D);
500 D = _free(D);
501 }
502 #endif
503 V = _free(V);
504 R = _free(R);
505
506 /*
507 * Rpm prior to 3.0.3 does not have versioned provides.
508 * If no provides at all are available, we can just add.
509 */
510 he->tag = RPMTAG_PROVIDENAME;
511 /*@-nullstate@*/
512 xx = headerGet(h, he, 0);
513 /*@=nullstate@*/
514 provides = he->p.argv;
515 providesCount = he->c;
516 if (!xx)
517 goto exit;
518
519 /*
520 * Otherwise, fill in entries on legacy packages.
521 */
522 he->tag = RPMTAG_PROVIDEVERSION;
523 /*@-nullstate@*/
524 xx = headerGet(h, he, 0);
525 /*@=nullstate@*/
526 providesEVR = he->p.argv;
527 if (!xx) {
528 for (i = 0; i < providesCount; i++) {
529 /*@observer@*/
530 static const char * vdummy = "";
531 static rpmsenseFlags fdummy = RPMSENSE_ANY;
532
533 he->tag = RPMTAG_PROVIDEVERSION;
534 he->t = RPM_STRING_ARRAY_TYPE;
535 he->p.argv = &vdummy;
536 he->c = 1;
537 he->append = 1;
538 /*@-nullstate@*/
539 xx = headerPut(h, he, 0);
540 /*@=nullstate@*/
541 he->append = 0;
542
543 he->tag = RPMTAG_PROVIDEFLAGS;
544 he->t = RPM_UINT32_TYPE;
545 he->p.ui32p = (rpmuint32_t *) &fdummy;
546 he->c = 1;
547 he->append = 1;
548 /*@-nullstate@*/
549 xx = headerPut(h, he, 0);
550 /*@=nullstate@*/
551 he->append = 0;
552 }
553 goto exit;
554 }
555
556 he->tag = RPMTAG_PROVIDEFLAGS;
557 /*@-nullstate@*/
558 xx = headerGet(h, he, 0);
559 /*@=nullstate@*/
560 provideFlags = he->p.ui32p;
561
562 /*@-nullderef@*/ /* LCL: providesEVR is not NULL */
563 if (provides && providesEVR && provideFlags)
564 for (i = 0; i < providesCount; i++) {
565 if (!(provides[i] && providesEVR[i]))
566 continue;
567 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
568 !strcmp(N, provides[i]) && !strcmp(pEVR, providesEVR[i])))
569 continue;
570 bingo = 0;
571 break;
572 }
573 /*@=nullderef@*/
574
575 exit:
576 /*@-usereleased@*/
577 provides = _free(provides);
578 providesEVR = _free(providesEVR);
579 provideFlags = _free(provideFlags);
580 /*@=usereleased@*/
581
582 if (bingo) {
583 he->tag = RPMTAG_PROVIDENAME;
584 he->t = RPM_STRING_ARRAY_TYPE;
585 he->p.argv = &N;
586 he->c = 1;
587 he->append = 1;
588 /*@-nullstate@*/
589 xx = headerPut(h, he, 0);
590 /*@=nullstate@*/
591 he->append = 0;
592
593 he->tag = RPMTAG_PROVIDEVERSION;
594 he->t = RPM_STRING_ARRAY_TYPE;
595 he->p.argv = &pEVR;
596 he->c = 1;
597 he->append = 1;
598 /*@-nullstate@*/
599 xx = headerPut(h, he, 0);
600 /*@=nullstate@*/
601 he->append = 0;
602
603 he->tag = RPMTAG_PROVIDEFLAGS;
604 he->t = RPM_UINT32_TYPE;
605 he->p.ui32p = &pFlags;
606 he->c = 1;
607 he->append = 1;
608 /*@-nullstate@*/
609 xx = headerPut(h, he, 0);
610 /*@=nullstate@*/
611 he->append = 0;
612 }
613 N = _free(N);
614 }
615
616 rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
617 CSA_t csa, char *passPhrase, const char **cookie)
618 {
619 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
620 FD_t fd = NULL;
621 FD_t ifd = NULL;
622 rpmuint32_t sigtag;
623 const char * sigtarget;
624 const char * rpmio_flags = NULL;
625 const char * payload_format = NULL;
626 const char * SHA1 = NULL;
627 const char * msg = NULL;
628 char *s;
629 char buf[BUFSIZ];
630 Header h;
631 Header sigh = NULL;
632 int addsig = 0;
633 int isSource;
634 rpmRC rc = RPMRC_OK;
635 size_t nbr;
636 size_t nbw;
637 int xx;
638
639 /* Transfer header reference form *hdrp to h. */
640 h = headerLink(*hdrp);
641 (void)headerFree(*hdrp);
642 *hdrp = NULL;
643
644 if (pkgidp)
645 *pkgidp = NULL;
646
647 /* Save payload information */
648 isSource =
649 (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
650 headerIsEntry(h, RPMTAG_ARCH) != 0);
651 if (isSource) {
652 payload_format = rpmExpand("%{?_source_payload_format}", NULL);
653 rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
654 } else {
655 payload_format = rpmExpand("%{?_binary_payload_format}", NULL);
656 rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
657 }
658
659 if (!(payload_format && *payload_format)) {
660 payload_format = _free(payload_format);
661 payload_format = xstrdup("cpio");
662 }
663 if (!(rpmio_flags && *rpmio_flags)) {
664 rpmio_flags = _free(rpmio_flags);
665 rpmio_flags = xstrdup("w9.gzdio");
666 }
667 s = strchr(rpmio_flags, '.');
668 if (s) {
669
670 if (payload_format) {
671 if (!strcmp(payload_format, "tar")
672 || !strcmp(payload_format, "ustar")) {
673 /* XXX addition to header is too late to be displayed/sorted. */
674 /* Add prereq on rpm version that understands tar payloads */
675 (void) rpmlibNeedsFeature(h, "PayloadIsUstar", "4.4.4-1");
676 }
677 #if defined(SUPPORT_AR_PAYLOADS)
678 if (!strcmp(payload_format, "ar")) {
679 /* XXX addition to header is too late to be displayed/sorted. */
680 /* Add prereq on rpm version that understands tar payloads */
681 (void) rpmlibNeedsFeature(h, "PayloadIsAr", "5.1-1");
682 }
683 #endif
684
685 he->tag = RPMTAG_PAYLOADFORMAT;
686 he->t = RPM_STRING_TYPE;
687 he->p.str = payload_format;
688 he->c = 1;
689 xx = headerPut(h, he, 0);
690 }
691
692 /* XXX addition to header is too late to be displayed/sorted. */
693 if (s[1] == 'g' && s[2] == 'z') {
694 he->tag = RPMTAG_PAYLOADCOMPRESSOR;
695 he->t = RPM_STRING_TYPE;
696 he->p.str = xstrdup("gzip");
697 he->c = 1;
698 xx = headerPut(h, he, 0);
699 he->p.ptr = _free(he->p.ptr);
700 } else if (s[1] == 'b' && s[2] == 'z') {
701 he->tag = RPMTAG_PAYLOADCOMPRESSOR;
702 he->t = RPM_STRING_TYPE;
703 he->p.str = xstrdup("bzip2");
704 he->c = 1;
705 xx = headerPut(h, he, 0);
706 he->p.ptr = _free(he->p.ptr);
707 } else if (s[1] == 'l' && s[2] == 'z') {
708 he->tag = RPMTAG_PAYLOADCOMPRESSOR;
709 he->t = RPM_STRING_TYPE;
710 he->p.str = xstrdup("lzma");
711 he->c = 1;
712 xx = headerPut(h, he, 0);
713 he->p.ptr = _free(he->p.ptr);
714 (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
715 } else if (s[1] == 'x' && s[2] == 'z') {
716 he->tag = RPMTAG_PAYLOADCOMPRESSOR;
717 he->t = RPM_STRING_TYPE;
718 he->p.str = xstrdup("xz");
719 he->c = 1;
720 xx = headerPut(h, he, 0);
721 he->p.ptr = _free(he->p.ptr);
722 (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
723 }
724 strcpy(buf, rpmio_flags);
725 buf[s - rpmio_flags] = '\0';
726
727 he->tag = RPMTAG_PAYLOADFLAGS;
728 he->t = RPM_STRING_TYPE;
729 he->p.str = buf+1;
730 he->c = 1;
731 xx = headerPut(h, he, 0);
732 }
733
734 /* Create and add the cookie */
735 if (cookie) {
736 sprintf(buf, "%s %u", buildHost(), (unsigned) (*getBuildTime()));
737 *cookie = xstrdup(buf); /* XXX memory leak */
738 he->tag = RPMTAG_COOKIE;
739 he->t = RPM_STRING_TYPE;
740 he->p.str = *cookie;
741 he->c = 1;
742 xx = headerPut(h, he, 0);
743 }
744
745 /* Reallocate the header into one contiguous region. */
746 h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
747 if (h == NULL) { /* XXX can't happen */
748 rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
749 rc = RPMRC_FAIL;
750 goto exit;
751 }
752 /* Re-reference reallocated header. */
753 *hdrp = headerLink(h);
754
755 /*
756 * Write the header+archive into a temp file so that the size of
757 * archive (after compression) can be added to the header.
758 */
759 sigtarget = NULL;
760 if (rpmTempFile(NULL, &sigtarget, &fd)) {
761 rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
762 rc = RPMRC_FAIL;
763 goto exit;
764 }
765
766 /* Write the header to a temp file, computing header SHA1 on the fly. */
767 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
768 { const char item[] = "Header";
769 msg = NULL;
770 rc = rpmpkgWrite(item, fd, h, &msg);
771 if (rc != RPMRC_OK) {
772 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
773 (msg && *msg ? msg : "write failed\n"));
774 msg = _free(msg);
775 rc = RPMRC_FAIL;
776 goto exit;
777 }
778 msg = _free(msg);
779 (void) Fflush(fd);
780 }
781 fdFiniDigest(fd, PGPHASHALGO_SHA1, &SHA1, NULL, 1);
782
783 /* Append the payload to the temp file. */
784 if (csa->cpioList != NULL)
785 rc = cpio_doio(fd, h, csa, payload_format, rpmio_flags);
786 else if (Fileno(csa->cpioFdIn) >= 0)
787 rc = cpio_copy(fd, csa);
788 else
789 assert(0);
790
791 rpmio_flags = _free(rpmio_flags);
792 payload_format = _free(payload_format);
793 if (rc != RPMRC_OK)
794 goto exit;
795
796 (void) Fclose(fd);
797 fd = NULL;
798 (void) Unlink(fileName);
799
800 /* Generate the signature */
801 (void) fflush(stdout);
802 sigh = headerNew();
803 (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_SIZE, passPhrase);
804 (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_MD5, passPhrase);
805
806 sigtag = RPMSIGTAG_GPG;
807 addsig = (passPhrase && passPhrase[0]);
808
809 if (addsig) {
810 rpmlog(RPMLOG_NOTICE, _("Generating signature: %d\n"), sigtag);
811 (void) rpmAddSignature(sigh, sigtarget, sigtag, passPhrase);
812 }
813
814 if (SHA1) {
815 he->tag = (rpmTag) RPMSIGTAG_SHA1;
816 he->t = RPM_STRING_TYPE;
817 he->p.str = SHA1;
818 he->c = 1;
819 xx = headerPut(sigh, he, 0);
820 SHA1 = _free(SHA1);
821 }
822
823 { rpmuint32_t payloadSize = csa->cpioArchiveSize;
824 he->tag = (rpmTag) RPMSIGTAG_PAYLOADSIZE;
825 he->t = RPM_UINT32_TYPE;
826 he->p.ui32p = &payloadSize;
827 he->c = 1;
828 xx = headerPut(sigh, he, 0);
829 }
830
831 /* Reallocate the signature into one contiguous region. */
832 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
833 if (sigh == NULL) { /* XXX can't happen */
834 rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
835 rc = RPMRC_FAIL;
836 goto exit;
837 }
838
839 /* Pad the signature header to put the metadata header at known offset. */
840 { size_t slen = 0;
841 void * uh = headerUnload(sigh, &slen);
842 static const size_t align = 1024;
843 size_t nb = align - 96 - 16 - 16;
844 rpmuint8_t * b;
845
846 uh = _free(uh);
847 assert(slen < nb);
848 nb -= slen;
849 b = memset(alloca(nb), 0, nb);
850 he->tag = (rpmTag) RPMSIGTAG_PADDING;
851 he->t = RPM_BIN_TYPE;
852 he->p.ui8p = b;
853 he->c = nb;
854 xx = headerPut(sigh, he, 0);
855 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
856 assert(sigh != NULL);
857 }
858
859 /* Open the output file */
860 fd = Fopen(fileName, "w.fdio");
861 if (fd == NULL || Ferror(fd)) {
862 rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
863 fileName, Fstrerror(fd));
864 rc = RPMRC_FAIL;
865 goto exit;
866 }
867
868 /* Write the lead section into the package. */
869 { const char item[] = "Lead";
870 size_t nl = rpmpkgSizeof(item, NULL);
871
872 msg = NULL;
873 if (nl == 0)
874 rc = RPMRC_FAIL;
875 else {
876 void * l = memset(alloca(nl), 0, nl);
877 const char *N, *V, *R;
878 (void) headerNEVRA(h, &N, NULL, &V, &R, NULL);
879 sprintf(buf, "%s-%s-%s", N, V, R);
880 N = _free(N);
881 V = _free(V);
882 R = _free(R);
883 msg = buf;
884 rc = rpmpkgWrite(item, fd, l, &msg);
885 }
886
887 if (rc != RPMRC_OK) {
888 rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
889 Fstrerror(fd));
890 rc = RPMRC_FAIL;
891 goto exit;
892 }
893 }
894
895 /* Write the signature section into the package. */
896 { const char item[] = "Signature";
897
898 msg = NULL;
899 rc = rpmpkgWrite(item, fd, sigh, &msg);
900 if (rc != RPMRC_OK) {
901 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fileName, item,
902 (msg && *msg ? msg : "write failed\n"));
903 msg = _free(msg);
904 rc = RPMRC_FAIL;
905 goto exit;
906 }
907 msg = _free(msg);
908 }
909
910 /* Append the header and archive */
911 ifd = Fopen(sigtarget, "r.fdio");
912 if (ifd == NULL || Ferror(ifd)) {
913 rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
914 sigtarget, Fstrerror(ifd));
915 rc = RPMRC_FAIL;
916 goto exit;
917 }
918
919 /* Add signatures to header, and write header into the package. */
920 { const char item[] = "Header";
921 Header nh = NULL;
922
923 msg = NULL;
924 rc = rpmpkgRead(item, ifd, &nh, &msg);
925 if (rc != RPMRC_OK) {
926 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
927 (msg && *msg ? msg : "read failed\n"));
928 msg = _free(msg);
929 rc = RPMRC_FAIL;
930 goto exit;
931 }
932 msg = _free(msg);
933
934 #ifdef NOTYET
935 (void) headerMergeLegacySigs(nh, sigh);
936 #endif
937
938 msg = NULL;
939 rc = rpmpkgWrite(item, fd, nh, &msg);
940 (void)headerFree(nh);
941 nh = NULL;
942 if (rc != RPMRC_OK) {
943 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fileName, item,
944 (msg && *msg ? msg : "write failed\n"));
945 msg = _free(msg);
946 rc = RPMRC_FAIL;
947 goto exit;
948 }
949 msg = _free(msg);
950 }
951
952 /* Write the payload into the package. */
953 while ((nbr = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
954 if (Ferror(ifd)) {
955 rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
956 sigtarget, Fstrerror(ifd));
957 rc = RPMRC_FAIL;
958 goto exit;
959 }
960 nbw = (int)Fwrite(buf, sizeof(buf[0]), nbr, fd);
961 if (nbr != nbw || Ferror(fd)) {
962 rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
963 fileName, Fstrerror(fd));
964 rc = RPMRC_FAIL;
965 goto exit;
966 }
967 }
968 rc = RPMRC_OK;
969
970 exit:
971 SHA1 = _free(SHA1);
972 (void)headerFree(h);
973 h = NULL;
974
975 /* XXX Fish the pkgid out of the signature header. */
976 if (sigh != NULL && pkgidp != NULL) {
977 he->tag = (rpmTag) RPMSIGTAG_MD5;
978 xx = headerGet(sigh, he, 0);
979 if (he->t == RPM_BIN_TYPE && he->p.ptr != NULL && he->c == 16)
980 *pkgidp = he->p.ui8p; /* XXX memory leak */
981 }
982
983 (void)headerFree(sigh);
984 sigh = NULL;
985 if (ifd) {
986 (void) Fclose(ifd);
987 ifd = NULL;
988 }
989 if (fd) {
990 (void) Fclose(fd);
991 fd = NULL;
992 }
993 if (sigtarget) {
994 (void) Unlink(sigtarget);
995 sigtarget = _free(sigtarget);
996 }
997
998 if (rc == RPMRC_OK)
999 rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
1000 else
1001 (void) Unlink(fileName);
1002
1003 return rc;
1004 }
1005
1006 static int rpmlibMarkers(Header h)
1007 /*@modifies h @*/
1008 {
1009 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1010 rpmuint32_t val;
1011 int xx;
1012
1013 he->tag = RPMTAG_RPMVERSION;
1014 he->t = RPM_STRING_TYPE;
1015 he->p.str = xstrdup(VERSION);
1016 he->c = 1;
1017 xx = headerPut(h, he, 0);
1018 he->p.ptr = _free(he->p.ptr);
1019
1020 if (!(_rpmbuildFlags & 4)) {
1021 val = (rpmuint32_t)rpmlibTimestamp();
1022 he->tag = RPMTAG_RPMLIBTIMESTAMP;
1023 he->t = RPM_UINT32_TYPE;
1024 he->p.ui32p = &val;
1025 he->c = 1;
1026 xx = headerPut(h, he, 0);
1027
1028 val = (rpmuint32_t)rpmlibVendor();
1029 he->tag = RPMTAG_RPMLIBVENDOR;
1030 he->t = RPM_UINT32_TYPE;
1031 he->p.ui32p = &val;
1032 he->c = 1;
1033 xx = headerPut(h, he, 0);
1034
1035 val = (rpmuint32_t)rpmlibVersion();
1036 he->tag = RPMTAG_RPMLIBVERSION;
1037 he->t = RPM_UINT32_TYPE;
1038 he->p.ui32p = &val;
1039 he->c = 1;
1040 xx = headerPut(h, he, 0);
1041 }
1042
1043 he->tag = RPMTAG_BUILDHOST;
1044 he->t = RPM_STRING_TYPE;
1045 he->p.str = buildHost();
1046 he->c = 1;
1047 xx = headerPut(h, he, 0);
1048
1049 he->tag = RPMTAG_BUILDTIME;
1050 he->t = RPM_UINT32_TYPE;
1051 he->p.ui32p = getBuildTime();
1052 he->c = 1;
1053 xx = headerPut(h, he, 0);
1054
1055 return 0;
1056 }
1057
1058 /*@unchecked@*/
1059 static rpmTag copyTags[] = {
1060 RPMTAG_CHANGELOGTIME,
1061 RPMTAG_CHANGELOGNAME,
1062 RPMTAG_CHANGELOGTEXT,
1063 0
1064 };
1065
1066 rpmRC packageBinaries(Spec spec)
1067 {
1068 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1069 struct cpioSourceArchive_s csabuf;
1070 CSA_t csa = &csabuf;
1071 const char *errorString;
1072 Package pkg;
1073 rpmRC rc;
1074 int xx;
1075
1076 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
1077 const char *fn;
1078
1079 if (pkg->fileList == NULL)
1080 continue;
1081
1082 if (spec->cookie) {
1083 he->tag = RPMTAG_COOKIE;
1084 he->t = RPM_STRING_TYPE;
1085 he->p.str = spec->cookie;
1086 he->c = 1;
1087 xx = headerPut(pkg->header, he, 0);
1088 }
1089
1090 /* Copy changelog from src rpm */
1091 headerCopyTags(spec->packages->header, pkg->header, copyTags);
1092
1093 /* Add rpmlib markers for tracking. */
1094 (void) rpmlibMarkers(pkg->header);
1095
1096 he->tag = RPMTAG_OPTFLAGS;
1097 he->t = RPM_STRING_TYPE;
1098 he->p.str = rpmExpand("%{optflags}", NULL);
1099 he->c = 1;
1100 xx = headerPut(pkg->header, he, 0);
1101 he->p.ptr = _free(he->p.ptr);
1102
1103 if (!(_rpmbuildFlags & 4)) {
1104 if (spec->sourcePkgId != NULL) {
1105 he->tag = RPMTAG_SOURCEPKGID;
1106 he->t = RPM_BIN_TYPE;
1107 he->p.ptr = spec->sourcePkgId;
1108 he->c = 16;
1109 xx = headerPut(pkg->header, he, 0);
1110 }
1111 }
1112
1113 { const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
1114 char *binRpm, *binDir;
1115 binRpm = headerSprintf(pkg->header, binFormat, NULL,
1116 rpmHeaderFormats, &errorString);
1117 binFormat = _free(binFormat);
1118 if (binRpm == NULL) {
1119 he->tag = RPMTAG_NVRA;
1120 xx = headerGet(pkg->header, he, 0);
1121 rpmlog(RPMLOG_ERR, _("Could not generate output "
1122 "filename for package %s: %s\n"), he->p.str, errorString);
1123 he->p.ptr = _free(he->p.ptr);
1124 /*@-usereleased@*/
1125 return RPMRC_FAIL;
1126 /*@=usereleased@*/
1127 }
1128 fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
1129 if ((binDir = strchr(binRpm, '/')) != NULL) {
1130 struct stat st;
1131 const char *dn;
1132 *binDir = '\0';
1133 dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
1134 if (Stat(dn, &st) < 0) {
1135 switch(errno) {
1136 case ENOENT:
1137 if (rpmioMkpath(dn, 0755, -1, -1) == 0)
1138 /*@switchbreak@*/ break;
1139 /*@fallthrough@*/
1140 default:
1141 rpmlog(RPMLOG_ERR,_("cannot create %s: %s\n"),
1142 dn, strerror(errno));
1143 /*@switchbreak@*/ break;
1144 }
1145 }
1146 dn = _free(dn);
1147 }
1148 binRpm = _free(binRpm);
1149 }
1150
1151 memset(csa, 0, sizeof(*csa));
1152 csa->cpioArchiveSize = 0;
1153 /*@-type@*/ /* LCL: function typedefs */
1154 /*@-onlytrans@*/
1155 csa->cpioFdIn = fdNew("init (packageBinaries)");
1156 /*@=onlytrans@*/
1157 /*@-assignexpose -newreftrans@*/
1158 csa->cpioList = rpmfiLink(pkg->cpioList, "packageBinaries");
1159 /*@=assignexpose =newreftrans@*/
1160 assert(csa->cpioList != NULL);
1161
1162 rc = writeRPM(&pkg->header, NULL, fn,
1163 csa, spec->passPhrase, NULL);
1164
1165 /*@-onlytrans@*/
1166 csa->cpioList->te = _free(csa->cpioList->te); /* XXX memory leak */
1167 /*@=onlytrans@*/
1168 csa->cpioList = rpmfiFree(csa->cpioList);
1169 /*@-nullpass -onlytrans -refcounttrans @*/
1170 csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
1171 /*@=nullpass =onlytrans =refcounttrans @*/
1172 /*@=type@*/
1173 fn = _free(fn);
1174 if (rc)
1175 return rc;
1176 }
1177
1178 return RPMRC_OK;
1179 }
1180
1181 rpmRC packageSources(Spec spec)
1182 {
1183 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1184 struct cpioSourceArchive_s csabuf;
1185 CSA_t csa = &csabuf;
1186 rpmRC rc;
1187 int xx;
1188 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
1189 rpmuint32_t val;
1190 #endif
1191
1192 /* Add rpmlib markers for tracking. */
1193 (void) rpmlibMarkers(spec->sourceHeader);
1194
1195 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
1196 /* Mark package as a SRPM for backward compatibility with RPM < 4.4.6 */
1197 he->tag = RPMTAG_SOURCEPACKAGE;
1198 he->t = RPM_UINT32_TYPE;
1199 val = 1;
1200 he->p.ui32p = &val;
1201 he->c = 1;
1202 xx = headerPut(spec->sourceHeader, he, 0);
1203 #endif
1204
1205 /* Add macros used during build to SRPM's. */
1206 { const char ** av = NULL;
1207 (void)rpmGetMacroEntries(NULL, NULL, 1, &av);
1208 if (av != NULL && av[0] != NULL) {
1209 he->tag = RPMTAG_BUILDMACROS;
1210 he->t = RPM_STRING_ARRAY_TYPE;
1211 he->p.argv = av;
1212 he->c = argvCount(av);
1213 xx = headerPut(spec->sourceHeader, he, 0);
1214 }
1215 /*@-nullstate@*/
1216 av = argvFree(av);
1217 /*@=nullstate@*/
1218 }
1219
1220 spec->cookie = _free(spec->cookie);
1221
1222 /* XXX this should be %_srpmdir */
1223 { const char *srcrpmdir = rpmGetPath("%{_srcrpmdir}/", NULL);
1224 const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
1225
1226 rc = rpmioMkpath(srcrpmdir, 0755, -1, -1);
1227
1228 memset(csa, 0, sizeof(*csa));
1229 csa->cpioArchiveSize = 0;
1230 /*@-type@*/ /* LCL: function typedefs */
1231 /*@-onlytrans@*/
1232 csa->cpioFdIn = fdNew("init (packageSources)");
1233 /*@=onlytrans@*/
1234 /*@-assignexpose -newreftrans@*/
1235 csa->cpioList = rpmfiLink(spec->sourceCpioList, "packageSources");
1236 /*@=assignexpose =newreftrans@*/
1237 assert(csa->cpioList != NULL);
1238
1239 spec->sourcePkgId = NULL;
1240 rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn,
1241 csa, spec->passPhrase, &(spec->cookie));
1242
1243 /*@-onlytrans@*/
1244 csa->cpioList->te = _free(csa->cpioList->te); /* XXX memory leak */
1245 /*@=onlytrans@*/
1246 csa->cpioList = rpmfiFree(csa->cpioList);
1247 /*@-nullpass -onlytrans -refcounttrans @*/
1248 csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
1249 /*@=nullpass =onlytrans =refcounttrans @*/
1250 /*@=type@*/
1251 srcrpmdir = _free(srcrpmdir);
1252 fn = _free(fn);
1253 }
1254
1255 return (rc ? RPMRC_FAIL : RPMRC_OK);
1256 }