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