summaryrefslogtreecommitdiff
path: root/lib/rpmlead.c
blob: e5e02b196ec9d40a1424d92ddc75be93155363bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/** \ingroup lead
 * \file lib/rpmlead.c
 */

#include "system.h"

#include <errno.h>
#include <netinet/in.h>

#include <rpm/rpmlib.h>		/* rpmGetOs/ArchInfo() */
#include <rpm/rpmlog.h>
#include <rpm/rpmstring.h>

#include "lib/signature.h"
#include "lib/header_internal.h"	/* Freadall() */
#include "lib/rpmlead.h"

#include "debug.h"

/* A long time ago in a galaxy far far away, signatures were not in a header */
#define RPMSIGTYPE_HEADERSIG 5

static unsigned char const lead_magic[] = {
    RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
};

/** \ingroup lead
 * The lead data structure.
 * The lead needs to be 8 byte aligned.
 * @deprecated The lead (except for signature_type) is legacy.
 * @todo Don't use any information from lead.
 */
struct rpmlead_s {
    unsigned char magic[4];
    unsigned char major;
    unsigned char minor;
    short type;
    short archnum;
    char name[66];
    short osnum;
    short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
    char reserved[16];      /*!< Pad to 96 bytes -- 8 byte aligned! */
};

static int rpmLeadFromHeader(Header h, struct rpmlead_s *l)
{
    if (h != NULL) {
	int archnum, osnum;
	char * nevr = headerGetAsString(h, RPMTAG_NEVR);

	/* FIXME: should grab these from header instead (RhBug:717898) */
	rpmGetArchInfo(NULL, &archnum);
	rpmGetOsInfo(NULL, &osnum);

	l->major = 3;
	l->minor = 0;
	l->archnum = archnum;
	l->osnum = osnum;
	l->signature_type = RPMSIGTYPE_HEADERSIG;
	l->type = (headerIsSource(h) ? 1 : 0);

	memcpy(l->magic, lead_magic, sizeof(l->magic));
	rstrlcpy(l->name, nevr, sizeof(l->name));

	free(nevr);
    }

    return (h != NULL);
}

/* The lead needs to be 8 byte aligned */
rpmRC rpmLeadWrite(FD_t fd, Header h)
{
    rpmRC rc = RPMRC_FAIL;
    struct rpmlead_s l;

    if (rpmLeadFromHeader(h, &l)) {
	
	l.type = htons(l.type);
	l.archnum = htons(l.archnum);
	l.osnum = htons(l.osnum);
	l.signature_type = htons(l.signature_type);
	    
	if (Fwrite(&l, 1, sizeof(l), fd) == sizeof(l))
	    rc = RPMRC_OK;
    }

    return rc;
}

static rpmRC rpmLeadCheck(struct rpmlead_s *lead, char **msg)
{
    if (memcmp(lead->magic, lead_magic, sizeof(lead_magic))) {
	*msg = xstrdup(_("not an rpm package"));
	return RPMRC_NOTFOUND;
    }
    if (lead->signature_type != RPMSIGTYPE_HEADERSIG) {
	*msg = xstrdup(_("illegal signature type"));
	return RPMRC_FAIL;
    }
    if (lead->major < 3 || lead->major > 4) {
	*msg = xstrdup(_("unsupported RPM package version"));
	return RPMRC_FAIL;
    }
    return RPMRC_OK;
}

rpmRC rpmLeadRead(FD_t fd, int *type, char **emsg)
{
    rpmRC rc = RPMRC_OK;
    struct rpmlead_s l;
    char *err = NULL;

    memset(&l, 0, sizeof(l));
    if (Freadall(fd, &l, sizeof(l)) != sizeof(l)) {
	if (Ferror(fd)) {
	    rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno);
	    rc = RPMRC_FAIL;
	} else {
	    err = xstrdup(_("not an rpm package\n"));
	    rc = RPMRC_NOTFOUND;
	}
    } else {
	l.type = ntohs(l.type);
	l.archnum = ntohs(l.archnum);
	l.osnum = ntohs(l.osnum);
	l.signature_type = ntohs(l.signature_type);
	rc = rpmLeadCheck(&l, &err);
    }

    if (rc == RPMRC_OK) {
	if (type != NULL)
	    *type = l.type;
    } else {
	if (emsg != NULL)
	    *emsg = err;
	else
	    free(err);
    }

    return rc;
}