resetting manifest requested domain to floor
[platform/upstream/deltarpm.git] / rpmhead.c
1 /*
2  * Copyright (c) 2004 Michael Schroeder (mls@suse.de)
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <errno.h>
13
14 #include "rpmhead.h"
15 #include "util.h"
16
17
18 /****************************************************************
19  *
20  * rpm header
21  *
22  */
23
24 struct rpmhead *
25 readhead(int fd, int pad)
26 {
27   unsigned char intro[16];
28   int cnt, dcnt, l;
29   struct rpmhead *h;
30
31   l = xread(fd, intro, 16);
32   if (l == 0)
33     return 0;
34   if (l != 16)
35     {
36       fprintf(stderr, "header read error\n");
37       return 0;
38     }
39   if (intro[0] != 0x8e || intro[1] != 0xad || intro[2] != 0xe8 || intro[3] != 0x01)
40     {
41       fprintf(stderr, "bad header\n");
42       return 0;
43     }
44   cnt  = intro[8] << 24  | intro[9] << 16  | intro[10] << 8 | intro[11];
45   dcnt = intro[12] << 24 | intro[13] << 16 | intro[14] << 8 | intro[15];
46   if ((dcnt & 7) && pad)
47     dcnt += 8 - (dcnt & 7);
48   h = xmalloc(sizeof(*h) + cnt * 16 + dcnt);
49   memcpy(h->intro, intro, 16);
50   if (xread(fd, h->data, cnt * 16 + dcnt) != cnt * 16 + dcnt)
51     {
52       fprintf(stderr, "header read error\n");
53       free(h);
54       return 0;
55     }
56   h->cnt = cnt;
57   h->dcnt = dcnt;
58   h->dp = h->data + cnt * 16;
59   return h;
60 }
61
62 struct rpmhead *
63 readhead_buf(unsigned char *buf, int len, int pad)
64 {
65   int cnt, dcnt;
66   struct rpmhead *h;
67
68   if (len < 16)
69     {
70       fprintf(stderr, "bad header\n");
71       return 0;
72     }
73   if (buf[0] != 0x8e || buf[1] != 0xad || buf[2] != 0xe8 || buf[3] != 0x01)
74     {
75       fprintf(stderr, "bad header\n");
76       return 0;
77     }
78   cnt  = buf[8] << 24  | buf[9] << 16  | buf[10] << 8 | buf[11];
79   dcnt = buf[12] << 24 | buf[13] << 16 | buf[14] << 8 | buf[15];
80   if ((dcnt & 7) && pad)
81     dcnt += 8 - (dcnt & 7);
82   if (len < 16 + cnt * 16 + dcnt)
83     {
84       fprintf(stderr, "bad header\n");
85       return 0;
86     }
87   h = xmalloc(sizeof(*h) + cnt * 16 + dcnt);
88   memcpy(h->intro, buf, 16);
89   memcpy(h->data, buf + 16, cnt * 16 + dcnt);
90   h->cnt = cnt;
91   h->dcnt = dcnt;
92   h->dp = h->data + cnt * 16;
93   return h;
94 }
95
96 unsigned int *
97 headint32(struct rpmhead *h, int tag, int *cnt)
98 {
99   unsigned int i, o, *r;
100   unsigned char *d, taga[4];
101
102   d = h->data;
103   taga[0] = tag >> 24;
104   taga[1] = tag >> 16;
105   taga[2] = tag >> 8;
106   taga[3] = tag;
107   for (i = 0; i < h->cnt; i++, d += 16)
108     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
109       break;
110   if (i >= h->cnt)
111     return 0;
112   if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4)
113     return 0;
114   o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
115   i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
116   if (o + 4 * i > h->dcnt)
117     return 0;
118   d = h->dp + o;
119   r = xmalloc2(i ? i : 1, sizeof(unsigned int));
120   if (cnt)
121     *cnt = i;
122   for (o = 0; o < i; o++, d += 4)
123     r[o] = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3];
124   return r;
125 }
126
127 unsigned int *
128 headint16(struct rpmhead *h, int tag, int *cnt)
129 {
130   unsigned int i, o, *r;
131   unsigned char *d, taga[4];
132
133   d = h->data;
134   taga[0] = tag >> 24;
135   taga[1] = tag >> 16;
136   taga[2] = tag >> 8;
137   taga[3] = tag;
138   for (i = 0; i < h->cnt; i++, d += 16)
139     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
140       break;
141   if (i >= h->cnt)
142     return 0;
143   if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3)
144     return 0;
145   o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
146   i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
147   if (o + 2 * i > h->dcnt)
148     return 0;
149   d = h->dp + o;
150   r = xmalloc2(i ? i : 1, sizeof(unsigned int));
151   if (cnt)
152     *cnt = i;
153   for (o = 0; o < i; o++, d += 2)
154     r[o] = d[0] << 8 | d[1];
155   return r;
156 }
157
158 char *
159 headstring(struct rpmhead *h, int tag)
160 {
161   unsigned int i, o;
162   unsigned char *d, taga[4];
163   d = h->data;
164   taga[0] = tag >> 24;
165   taga[1] = tag >> 16;
166   taga[2] = tag >> 8;
167   taga[3] = tag;
168   for (i = 0; i < h->cnt; i++, d += 16)
169     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
170       break;
171   if (i >= h->cnt)
172     return 0;
173   if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 6)
174     return 0;
175   o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
176   return (char *)h->dp + o;
177 }
178
179 char **
180 headstringarray(struct rpmhead *h, int tag, int *cnt)
181 {
182   unsigned int i, o;
183   unsigned char *d, taga[4];
184   char **r;
185
186   d = h->data;
187   taga[0] = tag >> 24;
188   taga[1] = tag >> 16;
189   taga[2] = tag >> 8;
190   taga[3] = tag;
191   for (i = 0; i < h->cnt; i++, d += 16)
192     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
193       break;
194   if (i >= h->cnt)
195     return 0;
196   if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8)
197     return 0;
198   o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
199   i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
200   r = xmalloc2(i ? i : 1, sizeof(char *));
201   if (cnt)
202     *cnt = i;
203   d = h->dp + o;
204   for (o = 0; o < i; o++)
205     {
206       r[o] = (char *)d;
207       if (o + 1 < i)
208         d += strlen((char *)d) + 1;
209       if (d >= h->dp + h->dcnt)
210         {
211           free(r);
212           return 0;
213         }
214     }
215   return r;
216 }
217
218 unsigned char *
219 headbin(struct rpmhead *h, int tag, int len)
220 {
221   unsigned int i, o;
222   unsigned char *d, taga[4];
223   d = h->data;
224   taga[0] = tag >> 24;
225   taga[1] = tag >> 16;
226   taga[2] = tag >> 8;
227   taga[3] = tag;
228   for (i = 0; i < h->cnt; i++, d += 16)
229     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
230       break;
231   if (i >= h->cnt)
232     return 0;
233   if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 7)
234     return 0;
235   i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
236   if (len != i)
237     return 0;
238   o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
239   return (unsigned char *)h->dp + o;
240 }
241
242 int
243 headtagtype(struct rpmhead *h, int tag)
244 {
245   unsigned int i;
246   unsigned char *d, taga[4];
247   d = h->data;
248   taga[0] = tag >> 24;
249   taga[1] = tag >> 16;
250   taga[2] = tag >> 8;
251   taga[3] = tag;
252   for (i = 0; i < h->cnt; i++, d += 16)
253     if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
254       return d[4] << 24 | d[5] << 16 | d[6] << 8 | d[7];
255   return 0;
256 }
257
258 char **
259 headexpandfilelist(struct rpmhead *h, int *cnt)
260 {
261   char **filenames;
262   char **basenames, **dirnames;
263   char *cp;
264   unsigned int *diridx;
265   int i, l;
266
267   filenames = headstringarray(h, TAG_FILENAMES, cnt);
268   if (filenames)
269     return filenames;
270   basenames = headstringarray(h, TAG_BASENAMES, cnt);
271   dirnames = headstringarray(h, TAG_DIRNAMES, (int *)0);
272   diridx = headint32(h, TAG_DIRINDEXES, (int *)0);
273   if (!basenames || !dirnames || !diridx)
274     {
275       *cnt = 0;
276       return 0;
277     }
278   l = 0;
279   for (i = 0; i < *cnt; i++)
280     l += strlen(dirnames[diridx[i]]) + strlen(basenames[i]) + 1;
281   filenames = xmalloc(*cnt * sizeof(char *) + l);
282   cp = (char *)(filenames + *cnt);
283   for (i = 0; i < *cnt; i++)
284     {
285       sprintf(cp, "%s%s", dirnames[diridx[i]], basenames[i]);
286       filenames[i] = cp;
287       cp += strlen(cp) + 1;
288     }
289   free(basenames);
290   free(dirnames);
291   free(diridx);
292   return filenames;
293 }
294
295 char *headtonevr(struct rpmhead *h)
296 {
297   char *name;
298   unsigned int *epoch; 
299   char *version;
300   char *release;
301   char *nevr;
302   int epochcnt = 0;
303
304   name = headstring(h, TAG_NAME);
305   version  = headstring(h, TAG_VERSION);
306   release  = headstring(h, TAG_RELEASE);
307   epoch = headint32(h, TAG_EPOCH, &epochcnt);
308   if (!name || !version || !release)
309     {
310       fprintf(stderr, "headtonevr: bad rpm header\n");
311       exit(1);
312     }
313   if (epoch && epochcnt)
314     {
315       char epochbuf[11];        /* 32bit decimal will fit in */
316       sprintf(epochbuf, "%u", *epoch);
317       nevr = xmalloc(strlen(name) + 1 + strlen(epochbuf) + 1 + strlen(version) + 1 + strlen(release) + 1);
318       sprintf(nevr, "%s-%s:%s-%s", name, epochbuf, version, release);
319     }
320   else
321     {
322       nevr = xmalloc(strlen(name) + 1 + strlen(version) + 1 + strlen(release) + 1);
323       sprintf(nevr, "%s-%s-%s", name, version, release);
324     }
325   if (epoch)
326     free(epoch);
327   return nevr;
328 }