~ubuntu-branches/ubuntu/edgy/rpm/edgy

« back to all changes in this revision

Viewing changes to build/pack.c

  • Committer: Bazaar Package Importer
  • Author(s): Joey Hess
  • Date: 2002-01-22 20:56:57 UTC
  • Revision ID: james.westby@ubuntu.com-20020122205657-l74j50mr9z8ofcl5
Tags: upstream-4.0.3
ImportĀ upstreamĀ versionĀ 4.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** \ingroup rpmbuild
 
2
 * \file build/pack.c
 
3
 *  Assemble components of an RPM package.
 
4
 */
 
5
 
 
6
#include "system.h"
 
7
 
 
8
#include <rpmio_internal.h>
 
9
#include <rpmbuild.h>
 
10
#include "buildio.h"
 
11
 
 
12
#include "misc.h"
 
13
#include "signature.h"
 
14
#include "rpmlead.h"
 
15
#include "debug.h"
 
16
 
 
17
/*@-redecl@*/
 
18
extern int _noDirTokens;
 
19
/*@=redecl@*/
 
20
 
 
21
/*@access StringBuf @*/ /* compared with NULL */
 
22
/*@access TFI_t @*/     /* compared with NULL */
 
23
/*@access Header @*/    /* compared with NULL */
 
24
/*@access FD_t @*/      /* compared with NULL */
 
25
/*@access CSA_t @*/
 
26
 
 
27
/**
 
28
 */
 
29
static inline int genSourceRpmName(Spec spec)
 
30
        /*@modifies spec->sourceRpmName @*/
 
31
{
 
32
    if (spec->sourceRpmName == NULL) {
 
33
        const char *name, *version, *release;
 
34
        char fileName[BUFSIZ];
 
35
 
 
36
        (void) headerNVR(spec->packages->header, &name, &version, &release);
 
37
        sprintf(fileName, "%s-%s-%s.%ssrc.rpm", name, version, release,
 
38
            spec->noSource ? "no" : "");
 
39
        spec->sourceRpmName = xstrdup(fileName);
 
40
    }
 
41
 
 
42
    return 0;
 
43
}
 
44
 
 
45
/**
 
46
 * @todo Create transaction set *much* earlier.
 
47
 */
 
48
static int cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
 
49
                const char * fmodeMacro)
 
50
        /*@modifies fdo, csa, fileSystem @*/
 
51
{
 
52
    const char * rootDir = "/";
 
53
    rpmdb rpmdb = NULL;
 
54
    rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
 
55
    TFI_t fi = csa->cpioList;
 
56
    const char *failedFile = NULL;
 
57
    FD_t cfd;
 
58
    int rc, ec;
 
59
 
 
60
    {   const char *fmode = rpmExpand(fmodeMacro, NULL);
 
61
        if (!(fmode && fmode[0] == 'w'))
 
62
            fmode = xstrdup("w9.gzdio");
 
63
        /*@-nullpass@*/
 
64
        (void) Fflush(fdo);
 
65
        cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
 
66
        /*@=nullpass@*/
 
67
        fmode = _free(fmode);
 
68
    }
 
69
    if (cfd == NULL)
 
70
        return 1;
 
71
 
 
72
    rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, cfd,
 
73
                &csa->cpioArchiveSize, &failedFile);
 
74
    (void) Fclose(cfd);
 
75
    ec = fsmTeardown(fi->fsm);
 
76
    if (!rc) rc = ec;
 
77
 
 
78
    if (rc) {
 
79
        if (failedFile)
 
80
            rpmError(RPMERR_CPIO, _("create archive failed on file %s: %s\n"),
 
81
                failedFile, cpioStrerror(rc));
 
82
        else
 
83
            rpmError(RPMERR_CPIO, _("create archive failed: %s\n"),
 
84
                cpioStrerror(rc));
 
85
      rc = 1;
 
86
    }
 
87
 
 
88
    failedFile = _free(failedFile);
 
89
    ts = rpmtransFree(ts);
 
90
 
 
91
    return rc;
 
92
}
 
93
 
 
94
/**
 
95
 */
 
96
static int cpio_copy(FD_t fdo, CSA_t csa)
 
97
        /*@modifies fdo, csa, fileSystem @*/
 
98
{
 
99
    char buf[BUFSIZ];
 
100
    size_t nb;
 
101
 
 
102
    while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
 
103
        if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
 
104
            rpmError(RPMERR_CPIO, _("cpio_copy write failed: %s\n"),
 
105
                        Fstrerror(fdo));
 
106
            return 1;
 
107
        }
 
108
        csa->cpioArchiveSize += nb;
 
109
    }
 
110
    if (Ferror(csa->cpioFdIn)) {
 
111
        rpmError(RPMERR_CPIO, _("cpio_copy read failed: %s\n"),
 
112
                Fstrerror(csa->cpioFdIn));
 
113
        return 1;
 
114
    }
 
115
    return 0;
 
116
}
 
117
 
 
118
/**
 
119
 */
 
120
static /*@only@*/ /*@null@*/ StringBuf addFileToTagAux(Spec spec,
 
121
                const char * file, /*@only@*/ StringBuf sb)
 
122
        /*@modifies fileSystem @*/
 
123
{
 
124
    char buf[BUFSIZ];
 
125
    const char * fn = buf;
 
126
    FILE * f;
 
127
    FD_t fd;
 
128
 
 
129
    /* XXX use rpmGenPath(rootdir, "%{_buildir}/%{_buildsubdir}/", file) */
 
130
    fn = rpmGetPath("%{_builddir}/", spec->buildSubdir, "/", file, NULL);
 
131
 
 
132
    fd = Fopen(fn, "r.ufdio");
 
133
    if (fn != buf) fn = _free(fn);
 
134
    if (fd == NULL || Ferror(fd)) {
 
135
        sb = freeStringBuf(sb);
 
136
        return NULL;
 
137
    }
 
138
    if ((f = fdGetFp(fd)) != NULL)
 
139
    while (fgets(buf, sizeof(buf), f)) {
 
140
        /* XXX display fn in error msg */
 
141
        if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
 
142
            rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
 
143
            sb = freeStringBuf(sb);
 
144
            break;
 
145
        }
 
146
        appendStringBuf(sb, buf);
 
147
    }
 
148
    (void) Fclose(fd);
 
149
 
 
150
    return sb;
 
151
}
 
152
 
 
153
/**
 
154
 */
 
155
static int addFileToTag(Spec spec, const char * file, Header h, int tag)
 
156
        /*@modifies h, fileSystem @*/
 
157
{
 
158
    HGE_t hge = (HGE_t)headerGetEntryMinMemory;
 
159
    StringBuf sb = newStringBuf();
 
160
    char *s;
 
161
 
 
162
    if (hge(h, tag, NULL, (void **)&s, NULL)) {
 
163
        appendLineStringBuf(sb, s);
 
164
        (void) headerRemoveEntry(h, tag);
 
165
    }
 
166
 
 
167
    if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
 
168
        return 1;
 
169
    
 
170
    (void) headerAddEntry(h, tag, RPM_STRING_TYPE, getStringBuf(sb), 1);
 
171
 
 
172
    sb = freeStringBuf(sb);
 
173
    return 0;
 
174
}
 
175
 
 
176
/**
 
177
 */
 
178
static int addFileToArrayTag(Spec spec, const char *file, Header h, int tag)
 
179
        /*@modifies h, fileSystem @*/
 
180
{
 
181
    StringBuf sb = newStringBuf();
 
182
    char *s;
 
183
 
 
184
    if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
 
185
        return 1;
 
186
 
 
187
    s = getStringBuf(sb);
 
188
    (void) headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, &s, 1);
 
189
 
 
190
    sb = freeStringBuf(sb);
 
191
    return 0;
 
192
}
 
193
 
 
194
/**
 
195
 */
 
196
static int processScriptFiles(Spec spec, Package pkg)
 
197
        /*@modifies pkg->header, fileSystem @*/
 
198
{
 
199
    struct TriggerFileEntry *p;
 
200
    
 
201
    if (pkg->preInFile) {
 
202
        if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
 
203
            rpmError(RPMERR_BADFILENAME,
 
204
                     _("Could not open PreIn file: %s\n"), pkg->preInFile);
 
205
            return RPMERR_BADFILENAME;
 
206
        }
 
207
    }
 
208
    if (pkg->preUnFile) {
 
209
        if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
 
210
            rpmError(RPMERR_BADFILENAME,
 
211
                     _("Could not open PreUn file: %s\n"), pkg->preUnFile);
 
212
            return RPMERR_BADFILENAME;
 
213
        }
 
214
    }
 
215
    if (pkg->postInFile) {
 
216
        if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
 
217
            rpmError(RPMERR_BADFILENAME,
 
218
                     _("Could not open PostIn file: %s\n"), pkg->postInFile);
 
219
            return RPMERR_BADFILENAME;
 
220
        }
 
221
    }
 
222
    if (pkg->postUnFile) {
 
223
        if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
 
224
            rpmError(RPMERR_BADFILENAME,
 
225
                     _("Could not open PostUn file: %s\n"), pkg->postUnFile);
 
226
            return RPMERR_BADFILENAME;
 
227
        }
 
228
    }
 
229
    if (pkg->verifyFile) {
 
230
        if (addFileToTag(spec, pkg->verifyFile, pkg->header,
 
231
                         RPMTAG_VERIFYSCRIPT)) {
 
232
            rpmError(RPMERR_BADFILENAME,
 
233
                     _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
 
234
            return RPMERR_BADFILENAME;
 
235
        }
 
236
    }
 
237
 
 
238
    for (p = pkg->triggerFiles; p != NULL; p = p->next) {
 
239
        (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTPROG,
 
240
                               RPM_STRING_ARRAY_TYPE, &(p->prog), 1);
 
241
        if (p->script) {
 
242
            (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTS,
 
243
                                   RPM_STRING_ARRAY_TYPE, &(p->script), 1);
 
244
        } else if (p->fileName) {
 
245
            if (addFileToArrayTag(spec, p->fileName, pkg->header,
 
246
                                  RPMTAG_TRIGGERSCRIPTS)) {
 
247
                rpmError(RPMERR_BADFILENAME,
 
248
                         _("Could not open Trigger script file: %s\n"),
 
249
                         p->fileName);
 
250
                return RPMERR_BADFILENAME;
 
251
            }
 
252
        } else {
 
253
            /* This is dumb.  When the header supports NULL string */
 
254
            /* this will go away.                                  */
 
255
            char *bull = "";
 
256
            (void) headerAddOrAppendEntry(pkg->header, RPMTAG_TRIGGERSCRIPTS,
 
257
                                   RPM_STRING_ARRAY_TYPE, &bull, 1);
 
258
        }
 
259
    }
 
260
 
 
261
    return 0;
 
262
}
 
263
 
 
264
int readRPM(const char *fileName, Spec *specp, struct rpmlead *lead,
 
265
                Header *sigs, CSA_t csa)
 
266
{
 
267
    FD_t fdi;
 
268
    Spec spec;
 
269
    rpmRC rc;
 
270
 
 
271
    fdi = (fileName != NULL)
 
272
        ? Fopen(fileName, "r.ufdio")
 
273
        : fdDup(STDIN_FILENO);
 
274
 
 
275
    if (fdi == NULL || Ferror(fdi)) {
 
276
        rpmError(RPMERR_BADMAGIC, _("readRPM: open %s: %s\n"),
 
277
                (fileName ? fileName : "<stdin>"),
 
278
                Fstrerror(fdi));
 
279
        if (fdi) (void) Fclose(fdi);
 
280
        return RPMERR_BADMAGIC;
 
281
    }
 
282
 
 
283
    /* Get copy of lead */
 
284
    if ((rc = Fread(lead, sizeof(char), sizeof(*lead), fdi)) != sizeof(*lead)) {
 
285
        rpmError(RPMERR_BADMAGIC, _("readRPM: read %s: %s\n"),
 
286
                (fileName ? fileName : "<stdin>"),
 
287
                Fstrerror(fdi));
 
288
        return RPMERR_BADMAGIC;
 
289
    }
 
290
 
 
291
    /* XXX FIXME: EPIPE on <stdin> */
 
292
    if (Fseek(fdi, 0, SEEK_SET) == -1) {
 
293
        rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
 
294
                        (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
 
295
        return RPMERR_FSEEK;
 
296
    }
 
297
 
 
298
    /* Reallocate build data structures */
 
299
    spec = newSpec();
 
300
    spec->packages = newPackage(spec);
 
301
 
 
302
    /* XXX the header just allocated will be allocated again */
 
303
    spec->packages->header = headerFree(spec->packages->header);
 
304
 
 
305
   /* Read the rpm lead, signatures, and header */
 
306
    rc = rpmReadPackageInfo(fdi, sigs, &spec->packages->header);
 
307
    switch (rc) {
 
308
    case RPMRC_BADMAGIC:
 
309
        rpmError(RPMERR_BADMAGIC, _("readRPM: %s is not an RPM package\n"),
 
310
                (fileName ? fileName : "<stdin>"));
 
311
        return RPMERR_BADMAGIC;
 
312
    case RPMRC_OK:
 
313
        break;
 
314
    case RPMRC_FAIL:
 
315
    case RPMRC_BADSIZE:
 
316
    case RPMRC_SHORTREAD:
 
317
    default:
 
318
        rpmError(RPMERR_BADMAGIC, _("readRPM: reading header from %s\n"),
 
319
                (fileName ? fileName : "<stdin>"));
 
320
        return RPMERR_BADMAGIC;
 
321
        /*@notreached@*/ break;
 
322
    }
 
323
 
 
324
    if (specp)
 
325
        *specp = spec;
 
326
    else
 
327
        spec = freeSpec(spec);
 
328
 
 
329
    if (csa != NULL)
 
330
        csa->cpioFdIn = fdi;
 
331
    else
 
332
        (void) Fclose(fdi);
 
333
 
 
334
    return 0;
 
335
}
 
336
 
 
337
static unsigned char header_magic[8] = {
 
338
        0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
 
339
};
 
340
 
 
341
#define RPMPKGVERSION_MIN       30004
 
342
#define RPMPKGVERSION_MAX       40003
 
343
static int rpmpkg_version = -1;
 
344
 
 
345
static int rpmLeadVersion(void)
 
346
{
 
347
    int rpmlead_version;
 
348
 
 
349
    /* Intitialize packaging version from macro configuration. */
 
350
    if (rpmpkg_version < 0) {
 
351
        rpmpkg_version = rpmExpandNumeric("%{_package_version}");
 
352
        if (rpmpkg_version < RPMPKGVERSION_MIN)
 
353
            rpmpkg_version = RPMPKGVERSION_MIN;
 
354
        if (rpmpkg_version > RPMPKGVERSION_MAX)
 
355
            rpmpkg_version = RPMPKGVERSION_MAX;
 
356
    }
 
357
 
 
358
    rpmlead_version = rpmpkg_version / 10000;
 
359
    if (_noDirTokens || (rpmlead_version < 3 || rpmlead_version > 4))
 
360
        rpmlead_version = 3;
 
361
    return rpmlead_version;
 
362
}
 
363
 
 
364
int writeRPM(Header *hdrp, const char *fileName, int type,
 
365
                    CSA_t csa, char *passPhrase, const char **cookie)
 
366
{
 
367
    FD_t fd = NULL;
 
368
    FD_t ifd = NULL;
 
369
    int count, sigtype;
 
370
    const char * sigtarget;
 
371
    const char * rpmio_flags = NULL;
 
372
    const char * sha1 = NULL;
 
373
    char *s;
 
374
    char buf[BUFSIZ];
 
375
    Header h;
 
376
    Header sig = NULL;
 
377
    int rc = 0;
 
378
 
 
379
    /* Transfer header reference form *hdrp to h. */
 
380
    h = headerLink(*hdrp);
 
381
    *hdrp = headerFree(*hdrp);
 
382
 
 
383
    if (Fileno(csa->cpioFdIn) < 0) {
 
384
        csa->cpioArchiveSize = 0;
 
385
        /* Add a bogus archive size to the Header */
 
386
        (void) headerAddEntry(h, RPMTAG_ARCHIVESIZE, RPM_INT32_TYPE,
 
387
                &csa->cpioArchiveSize, 1);
 
388
    }
 
389
 
 
390
    /* Binary packages now have explicit Provides: name = version-release. */
 
391
    if (type == RPMLEAD_BINARY)
 
392
        providePackageNVR(h);
 
393
 
 
394
    /* Save payload information */
 
395
    switch(type) {
 
396
    case RPMLEAD_SOURCE:
 
397
        rpmio_flags = rpmExpand("%{?_source_payload:%{_source_payload}}", NULL);
 
398
        break;
 
399
    case RPMLEAD_BINARY:
 
400
        rpmio_flags = rpmExpand("%{?_binary_payload:%{_binary_payload}}", NULL);
 
401
        break;
 
402
    }
 
403
    if (!(rpmio_flags && *rpmio_flags)) {
 
404
        rpmio_flags = _free(rpmio_flags);
 
405
        rpmio_flags = xstrdup("w9.gzdio");
 
406
    }
 
407
    s = strchr(rpmio_flags, '.');
 
408
    if (s) {
 
409
        (void) headerAddEntry(h, RPMTAG_PAYLOADFORMAT, RPM_STRING_TYPE, "cpio", 1);
 
410
        if (s[1] == 'g' && s[2] == 'z')
 
411
            (void) headerAddEntry(h, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE,
 
412
                "gzip", 1);
 
413
        if (s[1] == 'b' && s[2] == 'z') {
 
414
            (void) headerAddEntry(h, RPMTAG_PAYLOADCOMPRESSOR, RPM_STRING_TYPE,
 
415
                "bzip2", 1);
 
416
            /* Add prereq on rpm version that understands bzip2 payloads */
 
417
            (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1");
 
418
        }
 
419
        strcpy(buf, rpmio_flags);
 
420
        buf[s - rpmio_flags] = '\0';
 
421
        (void) headerAddEntry(h, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, buf+1, 1);
 
422
    }
 
423
 
 
424
    /* Create and add the cookie */
 
425
    if (cookie) {
 
426
        sprintf(buf, "%s %d", buildHost(), (int) time(NULL));
 
427
        *cookie = xstrdup(buf);
 
428
        (void) headerAddEntry(h, RPMTAG_COOKIE, RPM_STRING_TYPE, *cookie, 1);
 
429
    }
 
430
    
 
431
    /* Reallocate the header into one contiguous region. */
 
432
    h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
 
433
    if (h == NULL) {    /* XXX can't happen */
 
434
        rc = RPMERR_RELOAD;
 
435
        rpmError(RPMERR_RELOAD, _("Unable to create immutable header region.\n"));
 
436
        goto exit;
 
437
    }
 
438
    /* Re-reference reallocated header. */
 
439
    *hdrp = headerLink(h);
 
440
 
 
441
    /*
 
442
     * Write the header+archive into a temp file so that the size of
 
443
     * archive (after compression) can be added to the header.
 
444
     */
 
445
    if (makeTempFile(NULL, &sigtarget, &fd)) {
 
446
        rc = RPMERR_CREATE;
 
447
        rpmError(RPMERR_CREATE, _("Unable to open temp file.\n"));
 
448
        goto exit;
 
449
    }
 
450
 
 
451
    if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
 
452
        rc = RPMERR_NOSPACE;
 
453
        rpmError(RPMERR_NOSPACE, _("Unable to write temp header\n"));
 
454
    } else { /* Write the archive and get the size */
 
455
        if (csa->cpioList != NULL) {
 
456
            rc = cpio_doio(fd, h, csa, rpmio_flags);
 
457
        } else if (Fileno(csa->cpioFdIn) >= 0) {
 
458
            rc = cpio_copy(fd, csa);
 
459
        } else {
 
460
            rc = RPMERR_BADARG;
 
461
            rpmError(RPMERR_BADARG, _("Bad CSA data\n"));
 
462
        }
 
463
    }
 
464
    rpmio_flags = _free(rpmio_flags);
 
465
 
 
466
    if (rc)
 
467
        goto exit;
 
468
 
 
469
    /*
 
470
     * Set the actual archive size, and rewrite the header.
 
471
     * This used to be done using headerModifyEntry(), but now that headers
 
472
     * have regions, the value is scribbled directly into the header data
 
473
     * area. Some new scheme for adding the final archive size will have
 
474
     * to be devised if headerGetEntryMinMemory() ever changes to return
 
475
     * a pointer to memory not in the region, probably by appending
 
476
     * the archive size to the header region rather than including the
 
477
     * archive size within the header region.
 
478
     */
 
479
    if (Fileno(csa->cpioFdIn) < 0) {
 
480
        HGE_t hge = (HGE_t)headerGetEntryMinMemory;
 
481
        int_32 * archiveSize;
 
482
        if (hge(h, RPMTAG_ARCHIVESIZE, NULL, (void *)&archiveSize, NULL))
 
483
            *archiveSize = csa->cpioArchiveSize;
 
484
    }
 
485
 
 
486
    (void) Fflush(fd);
 
487
    if (Fseek(fd, sizeof(header_magic), SEEK_SET) == -1) {
 
488
        rc = RPMERR_FSEEK;
 
489
        rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
 
490
                        sigtarget, Fstrerror(fd));
 
491
    }
 
492
 
 
493
    fdInitSHA1(fd, 0);
 
494
    if (headerWrite(fd, h, HEADER_MAGIC_NO)) {
 
495
        rc = RPMERR_NOSPACE;
 
496
        rpmError(RPMERR_NOSPACE, _("Unable to write final header\n"));
 
497
    }
 
498
    (void) Fflush(fd);
 
499
    fdFiniSHA1(fd, (void **)&sha1, NULL, 1);
 
500
 
 
501
    (void) Fclose(fd);
 
502
    fd = NULL;
 
503
    (void) Unlink(fileName);
 
504
 
 
505
    if (rc)
 
506
        goto exit;
 
507
 
 
508
    /* Generate the signature */
 
509
    (void) fflush(stdout);
 
510
    sig = rpmNewSignature();
 
511
    (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
 
512
    (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
 
513
    if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
 
514
        rpmMessage(RPMMESS_NORMAL, _("Generating signature: %d\n"), sigtype);
 
515
        (void) rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
 
516
    }
 
517
    
 
518
    if (sha1) {
 
519
        (void) headerAddEntry(sig, RPMTAG_SHA1HEADER, RPM_STRING_TYPE, sha1, 1);
 
520
        sha1 = _free(sha1);
 
521
    }
 
522
 
 
523
    /* Reallocate the signature into one contiguous region. */
 
524
    sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
 
525
    if (sig == NULL) {  /* XXX can't happen */
 
526
        rc = RPMERR_RELOAD;
 
527
        rpmError(RPMERR_RELOAD, _("Unable to reload signature header.\n"));
 
528
        goto exit;
 
529
    }
 
530
 
 
531
    /* Open the output file */
 
532
    fd = Fopen(fileName, "w.ufdio");
 
533
    if (fd == NULL || Ferror(fd)) {
 
534
        rc = RPMERR_CREATE;
 
535
        rpmError(RPMERR_CREATE, _("Could not open %s: %s\n"),
 
536
                fileName, Fstrerror(fd));
 
537
        goto exit;
 
538
    }
 
539
 
 
540
    /* Write the lead section into the package. */
 
541
    {   int archnum = -1;
 
542
        int osnum = -1;
 
543
        struct rpmlead lead;
 
544
 
 
545
        if (Fileno(csa->cpioFdIn) < 0) {
 
546
#ifndef DYING
 
547
            rpmGetArchInfo(NULL, &archnum);
 
548
            rpmGetOsInfo(NULL, &osnum);
 
549
#endif
 
550
        } else if (csa->lead != NULL) {
 
551
            archnum = csa->lead->archnum;
 
552
            osnum = csa->lead->osnum;
 
553
        }
 
554
 
 
555
        memset(&lead, 0, sizeof(lead));
 
556
        lead.major = rpmLeadVersion();
 
557
        lead.minor = 0;
 
558
        lead.type = type;
 
559
        lead.archnum = archnum;
 
560
        lead.osnum = osnum;
 
561
        lead.signature_type = RPMSIGTYPE_HEADERSIG;
 
562
 
 
563
        {   const char *name, *version, *release;
 
564
            (void) headerNVR(h, &name, &version, &release);
 
565
            sprintf(buf, "%s-%s-%s", name, version, release);
 
566
            strncpy(lead.name, buf, sizeof(lead.name));
 
567
        }
 
568
 
 
569
        if (writeLead(fd, &lead)) {
 
570
            rc = RPMERR_NOSPACE;
 
571
            rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
 
572
                 Fstrerror(fd));
 
573
            goto exit;
 
574
        }
 
575
    }
 
576
 
 
577
    /* Write the signature section into the package. */
 
578
    rc = rpmWriteSignature(fd, sig);
 
579
    if (rc)
 
580
        goto exit;
 
581
 
 
582
    /* Append the header and archive */
 
583
    ifd = Fopen(sigtarget, "r.ufdio");
 
584
    if (ifd == NULL || Ferror(ifd)) {
 
585
        rc = RPMERR_READ;
 
586
        rpmError(RPMERR_READ, _("Unable to open sigtarget %s: %s\n"),
 
587
                sigtarget, Fstrerror(ifd));
 
588
        goto exit;
 
589
    }
 
590
 
 
591
    /* Add signatures to header, and write header into the package. */
 
592
    {   Header nh = headerRead(ifd, HEADER_MAGIC_YES);
 
593
 
 
594
        if (nh == NULL) {
 
595
            rc = RPMERR_READ;
 
596
            rpmError(RPMERR_READ, _("Unable to read header from %s: %s\n"),
 
597
                        sigtarget, Fstrerror(ifd));
 
598
            goto exit;
 
599
        }
 
600
 
 
601
#ifdef  NOTYET
 
602
        (void) headerMergeLegacySigs(nh, sig);
 
603
#endif
 
604
 
 
605
        rc = headerWrite(fd, nh, HEADER_MAGIC_YES);
 
606
        nh = headerFree(nh);
 
607
 
 
608
        if (rc) {
 
609
            rc = RPMERR_NOSPACE;
 
610
            rpmError(RPMERR_NOSPACE, _("Unable to write header to %s: %s\n"),
 
611
                        fileName, Fstrerror(fd));
 
612
            goto exit;
 
613
        }
 
614
    }
 
615
        
 
616
    /* Write the payload into the package. */
 
617
    while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
 
618
        if (count == -1) {
 
619
            rc = RPMERR_READ;
 
620
            rpmError(RPMERR_READ, _("Unable to read payload from %s: %s\n"),
 
621
                     sigtarget, Fstrerror(ifd));
 
622
            goto exit;
 
623
        }
 
624
        if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
 
625
            rc = RPMERR_NOSPACE;
 
626
            rpmError(RPMERR_NOSPACE, _("Unable to write payload to %s: %s\n"),
 
627
                     fileName, Fstrerror(fd));
 
628
            goto exit;
 
629
        }
 
630
    }
 
631
    rc = 0;
 
632
 
 
633
exit:
 
634
    sha1 = _free(sha1);
 
635
    h = headerFree(h);
 
636
    sig = rpmFreeSignature(sig);
 
637
    if (ifd) {
 
638
        (void) Fclose(ifd);
 
639
        ifd = NULL;
 
640
    }
 
641
    if (fd) {
 
642
        (void) Fclose(fd);
 
643
        fd = NULL;
 
644
    }
 
645
    if (sigtarget) {
 
646
        (void) Unlink(sigtarget);
 
647
        sigtarget = _free(sigtarget);
 
648
    }
 
649
 
 
650
    if (rc == 0)
 
651
        rpmMessage(RPMMESS_NORMAL, _("Wrote: %s\n"), fileName);
 
652
    else
 
653
        (void) Unlink(fileName);
 
654
 
 
655
    return rc;
 
656
}
 
657
 
 
658
static int_32 copyTags[] = {
 
659
    RPMTAG_CHANGELOGTIME,
 
660
    RPMTAG_CHANGELOGNAME,
 
661
    RPMTAG_CHANGELOGTEXT,
 
662
    0
 
663
};
 
664
 
 
665
int packageBinaries(Spec spec)
 
666
{
 
667
    struct cpioSourceArchive_s csabuf;
 
668
    CSA_t csa = &csabuf;
 
669
    int rc;
 
670
    const char *errorString;
 
671
    Package pkg;
 
672
 
 
673
    for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
 
674
        const char *fn;
 
675
 
 
676
        if (pkg->fileList == NULL)
 
677
            continue;
 
678
 
 
679
        if ((rc = processScriptFiles(spec, pkg)))
 
680
            return rc;
 
681
        
 
682
        if (spec->cookie) {
 
683
            (void) headerAddEntry(pkg->header, RPMTAG_COOKIE,
 
684
                           RPM_STRING_TYPE, spec->cookie, 1);
 
685
        }
 
686
 
 
687
        /* Copy changelog from src rpm */
 
688
        headerCopyTags(spec->packages->header, pkg->header, copyTags);
 
689
        
 
690
        (void) headerAddEntry(pkg->header, RPMTAG_RPMVERSION,
 
691
                       RPM_STRING_TYPE, VERSION, 1);
 
692
        (void) headerAddEntry(pkg->header, RPMTAG_BUILDHOST,
 
693
                       RPM_STRING_TYPE, buildHost(), 1);
 
694
        (void) headerAddEntry(pkg->header, RPMTAG_BUILDTIME,
 
695
                       RPM_INT32_TYPE, getBuildTime(), 1);
 
696
 
 
697
        providePackageNVR(pkg->header);
 
698
 
 
699
    {   const char * optflags = rpmExpand("%{optflags}", NULL);
 
700
        (void) headerAddEntry(pkg->header, RPMTAG_OPTFLAGS, RPM_STRING_TYPE,
 
701
                        optflags, 1);
 
702
        optflags = _free(optflags);
 
703
    }
 
704
 
 
705
        (void) genSourceRpmName(spec);
 
706
        (void) headerAddEntry(pkg->header, RPMTAG_SOURCERPM, RPM_STRING_TYPE,
 
707
                       spec->sourceRpmName, 1);
 
708
        
 
709
        {   const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
 
710
            char *binRpm, *binDir;
 
711
            binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
 
712
                               rpmHeaderFormats, &errorString);
 
713
            binFormat = _free(binFormat);
 
714
            if (binRpm == NULL) {
 
715
                const char *name;
 
716
                (void) headerNVR(pkg->header, &name, NULL, NULL);
 
717
                rpmError(RPMERR_BADFILENAME, _("Could not generate output "
 
718
                     "filename for package %s: %s\n"), name, errorString);
 
719
                return RPMERR_BADFILENAME;
 
720
            }
 
721
            fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
 
722
            if ((binDir = strchr(binRpm, '/')) != NULL) {
 
723
                struct stat st;
 
724
                const char *dn;
 
725
                *binDir = '\0';
 
726
                dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
 
727
                if (Stat(dn, &st) < 0) {
 
728
                    switch(errno) {
 
729
                    case  ENOENT:
 
730
                        if (Mkdir(dn, 0755) == 0)
 
731
                            break;
 
732
                        /*@fallthrough@*/
 
733
                    default:
 
734
                        rpmError(RPMERR_BADFILENAME,_("cannot create %s: %s\n"),
 
735
                            dn, strerror(errno));
 
736
                        break;
 
737
                    }
 
738
                }
 
739
                dn = _free(dn);
 
740
            }
 
741
            binRpm = _free(binRpm);
 
742
        }
 
743
 
 
744
        memset(csa, 0, sizeof(*csa));
 
745
        csa->cpioArchiveSize = 0;
 
746
        csa->cpioFdIn = fdNew("init (packageBinaries)");
 
747
        csa->cpioList = pkg->cpioList;
 
748
 
 
749
        rc = writeRPM(&pkg->header, fn, RPMLEAD_BINARY,
 
750
                    csa, spec->passPhrase, NULL);
 
751
        csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
 
752
        fn = _free(fn);
 
753
        if (rc)
 
754
            return rc;
 
755
    }
 
756
    
 
757
    return 0;
 
758
}
 
759
 
 
760
int packageSources(Spec spec)
 
761
{
 
762
    struct cpioSourceArchive_s csabuf;
 
763
    CSA_t csa = &csabuf;
 
764
    int rc;
 
765
 
 
766
    /* Add some cruft */
 
767
    (void) headerAddEntry(spec->sourceHeader, RPMTAG_RPMVERSION,
 
768
                   RPM_STRING_TYPE, VERSION, 1);
 
769
    (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDHOST,
 
770
                   RPM_STRING_TYPE, buildHost(), 1);
 
771
    (void) headerAddEntry(spec->sourceHeader, RPMTAG_BUILDTIME,
 
772
                   RPM_INT32_TYPE, getBuildTime(), 1);
 
773
 
 
774
    (void) genSourceRpmName(spec);
 
775
 
 
776
    spec->cookie = _free(spec->cookie);
 
777
    
 
778
    /* XXX this should be %_srpmdir */
 
779
    {   const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
 
780
 
 
781
        memset(csa, 0, sizeof(*csa));
 
782
        csa->cpioArchiveSize = 0;
 
783
        csa->cpioFdIn = fdNew("init (packageSources)");
 
784
        csa->cpioList = spec->sourceCpioList;
 
785
 
 
786
        rc = writeRPM(&spec->sourceHeader, fn, RPMLEAD_SOURCE,
 
787
                csa, spec->passPhrase, &(spec->cookie));
 
788
        csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
 
789
        fn = _free(fn);
 
790
    }
 
791
    return rc;
 
792
}