8e56bfc386d55cd8db4bb742f144adc4cf134fda
[platform/upstream/rpm.git] / lib / rpmlead.c
1 /** \ingroup lead
2  * \file lib/rpmlead.c
3  */
4
5 #include "system.h"
6
7 #include <errno.h>
8 #include <netinet/in.h>
9
10 #include <rpm/rpmlib.h>         /* rpmGetOs/ArchInfo() */
11 #include <rpm/rpmlog.h>
12 #include <rpm/rpmstring.h>
13
14 #include "lib/signature.h"
15 #include "lib/header_internal.h"        /* Freadall() */
16 #include "lib/rpmlead.h"
17
18 #include "debug.h"
19
20 static unsigned char const lead_magic[] = {
21     RPMLEAD_MAGIC0, RPMLEAD_MAGIC1, RPMLEAD_MAGIC2, RPMLEAD_MAGIC3
22 };
23
24 /** \ingroup lead
25  * The lead data structure.
26  * The lead needs to be 8 byte aligned.
27  * @deprecated The lead (except for signature_type) is legacy.
28  * @todo Don't use any information from lead.
29  */
30 struct rpmlead_s {
31     unsigned char magic[4];
32     unsigned char major;
33     unsigned char minor;
34     short type;
35     short archnum;
36     char name[66];
37     short osnum;
38     short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
39     char reserved[16];      /*!< Pad to 96 bytes -- 8 byte aligned! */
40 };
41
42 rpmlead rpmLeadFromHeader(Header h)
43 {
44     rpmlead l = NULL;
45
46     if (h != NULL) {
47         int archnum, osnum;
48         char * nevr = headerGetAsString(h, RPMTAG_NEVR);
49
50         /* FIXME: should grab these from header instead (RhBug:717898) */
51         rpmGetArchInfo(NULL, &archnum);
52         rpmGetOsInfo(NULL, &osnum);
53
54         l = xcalloc(1, sizeof(*l));
55         l->major = 3;
56         l->minor = 0;
57         l->archnum = archnum;
58         l->osnum = osnum;
59         l->signature_type = RPMSIGTYPE_HEADERSIG;
60         l->type = (headerIsSource(h) ? 1 : 0);
61
62         memcpy(l->magic, lead_magic, sizeof(l->magic));
63         rstrlcpy(l->name, nevr, sizeof(l->name));
64
65         free(nevr);
66     }
67
68     return l;
69 }
70
71 rpmlead rpmLeadFree(rpmlead lead)
72 {
73     free(lead);
74     return NULL;
75 }
76
77 /* The lead needs to be 8 byte aligned */
78 rpmRC rpmLeadWrite(FD_t fd, rpmlead lead)
79 {
80     rpmRC rc = RPMRC_FAIL;
81
82     if (lead != NULL) {
83         struct rpmlead_s l;
84         memcpy(&l, lead, sizeof(l));
85         
86         l.type = htons(lead->type);
87         l.archnum = htons(lead->archnum);
88         l.osnum = htons(lead->osnum);
89         l.signature_type = htons(lead->signature_type);
90             
91         if (Fwrite(&l, 1, sizeof(l), fd) == sizeof(l))
92             rc = RPMRC_OK;
93     }
94     return rc;
95 }
96
97 static rpmRC rpmLeadCheck(rpmlead lead, char **msg)
98 {
99     if (memcmp(lead->magic, lead_magic, sizeof(lead_magic))) {
100         *msg = xstrdup(_("not an rpm package"));
101         return RPMRC_NOTFOUND;
102     }
103     if (lead->signature_type != RPMSIGTYPE_HEADERSIG) {
104         *msg = xstrdup(_("illegal signature type"));
105         return RPMRC_FAIL;
106     }
107     if (lead->major < 3 || lead->major > 4) {
108         *msg = xstrdup(_("unsupported RPM package version"));
109         return RPMRC_FAIL;
110     }
111     return RPMRC_OK;
112 }
113
114 rpmRC rpmLeadRead(FD_t fd, rpmlead *lead, int *type, char **emsg)
115 {
116     rpmRC rc = RPMRC_OK;
117     struct rpmlead_s l;
118     char *err = NULL;
119
120     memset(&l, 0, sizeof(l));
121     if (Freadall(fd, &l, sizeof(l)) != sizeof(l)) {
122         if (Ferror(fd)) {
123             rasprintf(&err, _("read failed: %s (%d)\n"), Fstrerror(fd), errno);
124             rc = RPMRC_FAIL;
125         } else {
126             err = xstrdup(_("not an rpm package\n"));
127             rc = RPMRC_NOTFOUND;
128         }
129     } else {
130         l.type = ntohs(l.type);
131         l.archnum = ntohs(l.archnum);
132         l.osnum = ntohs(l.osnum);
133         l.signature_type = ntohs(l.signature_type);
134         rc = rpmLeadCheck(&l, &err);
135     }
136
137     if (rc == RPMRC_OK) {
138         if (lead != NULL) {
139             *lead = xmalloc(sizeof(l));
140             memcpy(*lead, &l, sizeof(l));
141         }
142         if (type != NULL)
143             *type = l.type;
144     } else {
145         if (emsg != NULL)
146             *emsg = err;
147         else
148             free(err);
149     }
150
151     return rc;
152 }