]>
Commit | Line | Data |
---|---|---|
13127796 | 1 | /* |
47fbaa2a | 2 | * Copyright (c) 2007-2018, SUSE Inc. |
13127796 MS |
3 | * |
4 | * This program is licensed under the BSD license, read LICENSE.BSD | |
5 | * for further information | |
6 | */ | |
7 | ||
8f8a9ed5 | 8 | /* |
a00b22fc | 9 | * repo_rpmdb |
60aa6d90 | 10 | * |
a00b22fc | 11 | * convert rpm db to repo |
60aa6d90 | 12 | * |
8f8a9ed5 KK |
13 | */ |
14 | ||
15 | #include <sys/types.h> | |
c49cb71a | 16 | #include <sys/stat.h> |
8f8a9ed5 KK |
17 | #include <limits.h> |
18 | #include <fcntl.h> | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
3bf73c63 | 22 | #include <unistd.h> |
18399c39 | 23 | #include <assert.h> |
c349c5cd | 24 | #include <stdint.h> |
5702cc43 | 25 | #include <errno.h> |
8f8a9ed5 | 26 | |
7173e5d6 MS |
27 | #ifdef ENABLE_RPMDB |
28 | ||
94ab2d2f MS |
29 | #include <rpm/rpmio.h> |
30 | #include <rpm/rpmpgp.h> | |
c349c5cd | 31 | #ifndef RPM5 |
99ceec3e | 32 | #include <rpm/header.h> |
c349c5cd | 33 | #endif |
97075a7d MS |
34 | #include <rpm/rpmdb.h> |
35 | ||
7173e5d6 MS |
36 | #endif |
37 | ||
8f8a9ed5 | 38 | #include "pool.h" |
cdd0e992 | 39 | #include "repo.h" |
8f8a9ed5 | 40 | #include "hash.h" |
555a08b2 | 41 | #include "util.h" |
87bfd053 | 42 | #include "queue.h" |
6df0daf4 | 43 | #include "chksum.h" |
a00b22fc | 44 | #include "repo_rpmdb.h" |
843dc7e1 | 45 | #include "repo_solv.h" |
434eaa3a MS |
46 | #ifdef ENABLE_COMPLEX_DEPS |
47 | #include "pool_parserpmrichdep.h" | |
48 | #endif | |
8f8a9ed5 | 49 | |
a415136a | 50 | /* 3: added triggers */ |
939c487e | 51 | /* 4: fixed triggers */ |
a8e47f15 | 52 | /* 5: fixed checksum copying */ |
40f549a3 | 53 | /* 6: add SOLVABLE_PREREQ_IGNOREINST support */ |
f92572e8 MS |
54 | /* 7: fix bug in ignoreinst logic */ |
55 | #define RPMDB_COOKIE_VERSION 7 | |
c49cb71a | 56 | |
8f8a9ed5 KK |
57 | #define TAG_NAME 1000 |
58 | #define TAG_VERSION 1001 | |
59 | #define TAG_RELEASE 1002 | |
60 | #define TAG_EPOCH 1003 | |
61 | #define TAG_SUMMARY 1004 | |
62 | #define TAG_DESCRIPTION 1005 | |
63 | #define TAG_BUILDTIME 1006 | |
5f696409 | 64 | #define TAG_BUILDHOST 1007 |
a8c85b1c | 65 | #define TAG_INSTALLTIME 1008 |
f9935ae5 | 66 | #define TAG_SIZE 1009 |
5f696409 | 67 | #define TAG_DISTRIBUTION 1010 |
8f8a9ed5 | 68 | #define TAG_VENDOR 1011 |
a8c85b1c | 69 | #define TAG_LICENSE 1014 |
5f696409 | 70 | #define TAG_PACKAGER 1015 |
c49cb71a | 71 | #define TAG_GROUP 1016 |
06429cda | 72 | #define TAG_URL 1020 |
8f8a9ed5 | 73 | #define TAG_ARCH 1022 |
c49cb71a MS |
74 | #define TAG_FILESIZES 1028 |
75 | #define TAG_FILEMODES 1030 | |
3e003c06 MS |
76 | #define TAG_FILEMD5S 1035 |
77 | #define TAG_FILELINKTOS 1036 | |
55f5371d | 78 | #define TAG_FILEFLAGS 1037 |
3bf73c63 | 79 | #define TAG_SOURCERPM 1044 |
8f8a9ed5 KK |
80 | #define TAG_PROVIDENAME 1047 |
81 | #define TAG_REQUIREFLAGS 1048 | |
82 | #define TAG_REQUIRENAME 1049 | |
83 | #define TAG_REQUIREVERSION 1050 | |
3bf73c63 MS |
84 | #define TAG_NOSOURCE 1051 |
85 | #define TAG_NOPATCH 1052 | |
8f8a9ed5 KK |
86 | #define TAG_CONFLICTFLAGS 1053 |
87 | #define TAG_CONFLICTNAME 1054 | |
88 | #define TAG_CONFLICTVERSION 1055 | |
a415136a MS |
89 | #define TAG_TRIGGERNAME 1066 |
90 | #define TAG_TRIGGERVERSION 1067 | |
91 | #define TAG_TRIGGERFLAGS 1068 | |
b6c702b3 MS |
92 | #define TAG_CHANGELOGTIME 1080 |
93 | #define TAG_CHANGELOGNAME 1081 | |
94 | #define TAG_CHANGELOGTEXT 1082 | |
8f8a9ed5 | 95 | #define TAG_OBSOLETENAME 1090 |
7a93753b MS |
96 | #define TAG_FILEDEVICES 1095 |
97 | #define TAG_FILEINODES 1096 | |
70570cd4 | 98 | #define TAG_SOURCEPACKAGE 1106 |
8f8a9ed5 KK |
99 | #define TAG_PROVIDEFLAGS 1112 |
100 | #define TAG_PROVIDEVERSION 1113 | |
101 | #define TAG_OBSOLETEFLAGS 1114 | |
102 | #define TAG_OBSOLETEVERSION 1115 | |
103 | #define TAG_DIRINDEXES 1116 | |
104 | #define TAG_BASENAMES 1117 | |
105 | #define TAG_DIRNAMES 1118 | |
554e6cf2 | 106 | #define TAG_PAYLOADFORMAT 1124 |
f9935ae5 | 107 | #define TAG_PATCHESNAME 1133 |
f8393a70 | 108 | #define TAG_FILECOLORS 1140 |
f9935ae5 MS |
109 | #define TAG_OLDSUGGESTSNAME 1156 |
110 | #define TAG_OLDSUGGESTSVERSION 1157 | |
111 | #define TAG_OLDSUGGESTSFLAGS 1158 | |
112 | #define TAG_OLDENHANCESNAME 1159 | |
113 | #define TAG_OLDENHANCESVERSION 1160 | |
114 | #define TAG_OLDENHANCESFLAGS 1161 | |
8f8a9ed5 | 115 | |
b69427b4 MS |
116 | /* rpm5 tags */ |
117 | #define TAG_DISTEPOCH 1218 | |
118 | ||
119 | /* rpm4 tags */ | |
120 | #define TAG_LONGFILESIZES 5008 | |
121 | #define TAG_LONGSIZE 5009 | |
f9935ae5 MS |
122 | #define TAG_RECOMMENDNAME 5046 |
123 | #define TAG_RECOMMENDVERSION 5047 | |
124 | #define TAG_RECOMMENDFLAGS 5048 | |
125 | #define TAG_SUGGESTNAME 5049 | |
126 | #define TAG_SUGGESTVERSION 5050 | |
127 | #define TAG_SUGGESTFLAGS 5051 | |
128 | #define TAG_SUPPLEMENTNAME 5052 | |
129 | #define TAG_SUPPLEMENTVERSION 5053 | |
130 | #define TAG_SUPPLEMENTFLAGS 5054 | |
131 | #define TAG_ENHANCENAME 5055 | |
132 | #define TAG_ENHANCEVERSION 5056 | |
133 | #define TAG_ENHANCEFLAGS 5057 | |
b69427b4 | 134 | |
966d89be MS |
135 | /* signature tags */ |
136 | #define TAG_SIGBASE 256 | |
137 | #define TAG_SIGMD5 (TAG_SIGBASE + 5) | |
138 | #define TAG_SHA1HEADER (TAG_SIGBASE + 13) | |
ae214a65 | 139 | #define TAG_SHA256HEADER (TAG_SIGBASE + 17) |
966d89be | 140 | |
5ed9867b MS |
141 | #define SIGTAG_SIZE 1000 |
142 | #define SIGTAG_PGP 1002 /* RSA signature */ | |
143 | #define SIGTAG_MD5 1004 /* header+payload md5 checksum */ | |
144 | #define SIGTAG_GPG 1005 /* DSA signature */ | |
145 | ||
8f8a9ed5 KK |
146 | #define DEP_LESS (1 << 1) |
147 | #define DEP_GREATER (1 << 2) | |
148 | #define DEP_EQUAL (1 << 3) | |
149 | #define DEP_STRONG (1 << 27) | |
ad7116d3 MS |
150 | #define DEP_PRE_IN ((1 << 6) | (1 << 9) | (1 << 10)) |
151 | #define DEP_PRE_UN ((1 << 6) | (1 << 11) | (1 << 12)) | |
8f8a9ed5 | 152 | |
ae214a65 | 153 | #define FILEFLAG_GHOST (1 << 6) |
55f5371d | 154 | |
8f8a9ed5 | 155 | |
78a876b1 | 156 | /* some limits to guard against corrupt rpms */ |
311ac7e2 MS |
157 | /* dsize limits taken from rpm's lib/header.c */ |
158 | #define MAX_SIG_CNT 0x10000 | |
159 | #define MAX_SIG_DSIZE 0x4000000 | |
78a876b1 | 160 | |
311ac7e2 MS |
161 | #define MAX_HDR_CNT 0x10000 |
162 | #define MAX_HDR_DSIZE 0x10000000 | |
8f8a9ed5 | 163 | |
ae214a65 MS |
164 | |
165 | #ifndef ENABLE_RPMPKG_LIBRPM | |
166 | ||
8f8a9ed5 KK |
167 | typedef struct rpmhead { |
168 | int cnt; | |
78a876b1 | 169 | unsigned int dcnt; |
8f8a9ed5 KK |
170 | unsigned char *dp; |
171 | unsigned char data[1]; | |
172 | } RpmHead; | |
173 | ||
5ed9867b MS |
174 | |
175 | static inline unsigned char * | |
176 | headfindtag(RpmHead *h, int tag) | |
3bf73c63 MS |
177 | { |
178 | unsigned int i; | |
179 | unsigned char *d, taga[4]; | |
3bf73c63 MS |
180 | d = h->dp - 16; |
181 | taga[0] = tag >> 24; | |
182 | taga[1] = tag >> 16; | |
183 | taga[2] = tag >> 8; | |
184 | taga[3] = tag; | |
185 | for (i = 0; i < h->cnt; i++, d -= 16) | |
186 | if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) | |
5ed9867b | 187 | return d; |
3bf73c63 MS |
188 | return 0; |
189 | } | |
190 | ||
5ed9867b MS |
191 | static int |
192 | headexists(RpmHead *h, int tag) | |
193 | { | |
194 | return headfindtag(h, tag) ? 1 : 0; | |
195 | } | |
196 | ||
350209a4 | 197 | static uint32_t * |
c49cb71a | 198 | headint32array(RpmHead *h, int tag, int *cnt) |
8f8a9ed5 | 199 | { |
350209a4 MS |
200 | uint32_t *r; |
201 | unsigned int i, o; | |
5ed9867b | 202 | unsigned char *d = headfindtag(h, tag); |
8f8a9ed5 | 203 | |
5ed9867b | 204 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) |
8f8a9ed5 KK |
205 | return 0; |
206 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
207 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 208 | if (o > h->dcnt || i > h->dcnt || o + 4 * i > h->dcnt) |
8f8a9ed5 KK |
209 | return 0; |
210 | d = h->dp + o; | |
350209a4 | 211 | r = solv_calloc(i ? i : 1, sizeof(uint32_t)); |
8f8a9ed5 KK |
212 | if (cnt) |
213 | *cnt = i; | |
214 | for (o = 0; o < i; o++, d += 4) | |
215 | r[o] = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; | |
216 | return r; | |
217 | } | |
218 | ||
5ed9867b | 219 | /* returns the first entry of an integer array */ |
350209a4 | 220 | static uint32_t |
c49cb71a MS |
221 | headint32(RpmHead *h, int tag) |
222 | { | |
223 | unsigned int i, o; | |
5ed9867b | 224 | unsigned char *d = headfindtag(h, tag); |
c49cb71a | 225 | |
5ed9867b | 226 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) |
c49cb71a MS |
227 | return 0; |
228 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
229 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 230 | if (i == 0 || o > h->dcnt || i > h->dcnt || o + 4 * i > h->dcnt) |
c49cb71a MS |
231 | return 0; |
232 | d = h->dp + o; | |
233 | return d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; | |
234 | } | |
235 | ||
350209a4 | 236 | static uint64_t * |
b188af05 MS |
237 | headint64array(RpmHead *h, int tag, int *cnt) |
238 | { | |
350209a4 | 239 | uint64_t *r; |
b188af05 | 240 | unsigned int i, o; |
b188af05 MS |
241 | unsigned char *d = headfindtag(h, tag); |
242 | ||
243 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 5) | |
244 | return 0; | |
245 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
246 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 247 | if (o > h->dcnt || i > h->dcnt || o + 8 * i > h->dcnt) |
b188af05 MS |
248 | return 0; |
249 | d = h->dp + o; | |
350209a4 | 250 | r = solv_calloc(i ? i : 1, sizeof(uint64_t)); |
b188af05 MS |
251 | if (cnt) |
252 | *cnt = i; | |
253 | for (o = 0; o < i; o++, d += 8) | |
254 | { | |
350209a4 MS |
255 | uint32_t x = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; |
256 | r[o] = (uint64_t)x << 32 | (uint32_t)(d[4] << 24 | d[5] << 16 | d[6] << 8 | d[7]); | |
b188af05 MS |
257 | } |
258 | return r; | |
259 | } | |
260 | ||
b69427b4 | 261 | /* returns the first entry of an 64bit integer array */ |
350209a4 | 262 | static uint64_t |
b69427b4 MS |
263 | headint64(RpmHead *h, int tag) |
264 | { | |
350209a4 | 265 | uint32_t x; |
b69427b4 MS |
266 | unsigned int i, o; |
267 | unsigned char *d = headfindtag(h, tag); | |
350209a4 | 268 | |
b69427b4 MS |
269 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 5) |
270 | return 0; | |
271 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
272 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 273 | if (i == 0 || o > h->dcnt || i > h->dcnt || o + 8 * i > h->dcnt) |
b69427b4 MS |
274 | return 0; |
275 | d = h->dp + o; | |
350209a4 MS |
276 | x = d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]; |
277 | return (uint64_t)x << 32 | (uint32_t)(d[4] << 24 | d[5] << 16 | d[6] << 8 | d[7]); | |
b69427b4 MS |
278 | } |
279 | ||
350209a4 | 280 | static uint16_t * |
c49cb71a MS |
281 | headint16array(RpmHead *h, int tag, int *cnt) |
282 | { | |
350209a4 MS |
283 | uint16_t *r; |
284 | unsigned int i, o; | |
5ed9867b | 285 | unsigned char *d = headfindtag(h, tag); |
c49cb71a | 286 | |
5ed9867b | 287 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3) |
c49cb71a MS |
288 | return 0; |
289 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
290 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 291 | if (o > h->dcnt || i > h->dcnt || o + 2 * i > h->dcnt) |
c49cb71a MS |
292 | return 0; |
293 | d = h->dp + o; | |
350209a4 | 294 | r = solv_calloc(i ? i : 1, sizeof(uint16_t)); |
c49cb71a MS |
295 | if (cnt) |
296 | *cnt = i; | |
297 | for (o = 0; o < i; o++, d += 2) | |
298 | r[o] = d[0] << 8 | d[1]; | |
299 | return r; | |
300 | } | |
301 | ||
8f8a9ed5 KK |
302 | static char * |
303 | headstring(RpmHead *h, int tag) | |
304 | { | |
5ed9867b MS |
305 | unsigned int o; |
306 | unsigned char *d = headfindtag(h, tag); | |
c49cb71a | 307 | /* 6: STRING, 9: I18NSTRING */ |
5ed9867b | 308 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9)) |
8f8a9ed5 KK |
309 | return 0; |
310 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
5ed9867b MS |
311 | if (o >= h->dcnt) |
312 | return 0; | |
8f8a9ed5 KK |
313 | return (char *)h->dp + o; |
314 | } | |
315 | ||
316 | static char ** | |
317 | headstringarray(RpmHead *h, int tag, int *cnt) | |
318 | { | |
319 | unsigned int i, o; | |
5ed9867b | 320 | unsigned char *d = headfindtag(h, tag); |
8f8a9ed5 KK |
321 | char **r; |
322 | ||
5ed9867b | 323 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8) |
8f8a9ed5 KK |
324 | return 0; |
325 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
326 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 MS |
327 | if (o > h->dcnt || i > h->dcnt) |
328 | return 0; | |
09f29f70 | 329 | r = solv_calloc(i ? i : 1, sizeof(char *)); |
8f8a9ed5 KK |
330 | if (cnt) |
331 | *cnt = i; | |
332 | d = h->dp + o; | |
333 | for (o = 0; o < i; o++) | |
334 | { | |
335 | r[o] = (char *)d; | |
336 | if (o + 1 < i) | |
337 | d += strlen((char *)d) + 1; | |
338 | if (d >= h->dp + h->dcnt) | |
339 | { | |
09f29f70 | 340 | solv_free(r); |
8f8a9ed5 KK |
341 | return 0; |
342 | } | |
343 | } | |
344 | return r; | |
345 | } | |
346 | ||
5ed9867b MS |
347 | static unsigned char * |
348 | headbinary(RpmHead *h, int tag, unsigned int *sizep) | |
349 | { | |
350 | unsigned int i, o; | |
351 | unsigned char *d = headfindtag(h, tag); | |
352 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 7) | |
353 | return 0; | |
354 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
355 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
78a876b1 | 356 | if (o > h->dcnt || i > h->dcnt || o + i > h->dcnt) |
5ed9867b MS |
357 | return 0; |
358 | if (sizep) | |
359 | *sizep = i; | |
360 | return h->dp + o; | |
361 | } | |
362 | ||
6c8ee8bc MS |
363 | static int |
364 | headissourceheuristic(RpmHead *h) | |
365 | { | |
366 | unsigned int i, o; | |
367 | unsigned char *d = headfindtag(h, TAG_DIRNAMES); | |
368 | if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8) | |
369 | return 0; | |
370 | o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; | |
371 | i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; | |
372 | return i == 1 && o < h->dcnt && !h->dp[o] ? 1 : 0; | |
373 | } | |
374 | ||
ae214a65 MS |
375 | static inline void |
376 | headfree(RpmHead *h) | |
377 | { | |
378 | solv_free(h); | |
379 | } | |
380 | ||
381 | #else | |
382 | ||
383 | typedef struct headerToken_s RpmHead; | |
384 | ||
385 | static int | |
386 | headexists(RpmHead *h, int tag) | |
387 | { | |
388 | return headerIsEntry(h, tag); | |
389 | } | |
390 | ||
391 | static void *headget(RpmHead *h, int tag, int *cnt, int alloc) | |
392 | { | |
393 | struct rpmtd_s td; | |
394 | if (!headerGet(h, tag, &td, alloc ? HEADERGET_ALLOC : HEADERGET_MINMEM)) | |
395 | return 0; | |
396 | if (cnt) | |
397 | *cnt = td.count; | |
398 | return td.data; | |
399 | } | |
400 | ||
350209a4 | 401 | static uint32_t * |
ae214a65 MS |
402 | headint32array(RpmHead *h, int tag, int *cnt) |
403 | { | |
404 | return headget(h, tag, cnt, 1); | |
405 | } | |
406 | ||
350209a4 | 407 | static uint32_t |
ae214a65 MS |
408 | headint32(RpmHead *h, int tag) |
409 | { | |
350209a4 | 410 | uint32_t *arr = headget(h, tag, 0, 0); |
ae214a65 MS |
411 | return arr ? arr[0] : 0; |
412 | } | |
413 | ||
350209a4 | 414 | static uint64_t * |
ae214a65 MS |
415 | headint64array(RpmHead *h, int tag, int *cnt) |
416 | { | |
417 | return headget(h, tag, cnt, 1); | |
418 | } | |
419 | ||
420 | /* returns the first entry of an 64bit integer array */ | |
350209a4 | 421 | static uint64_t |
ae214a65 MS |
422 | headint64(RpmHead *h, int tag) |
423 | { | |
350209a4 | 424 | uint64_t *arr = headget(h, tag, 0, 0); |
ae214a65 MS |
425 | return arr ? arr[0] : 0; |
426 | } | |
427 | ||
350209a4 | 428 | static uint16_t * |
ae214a65 MS |
429 | headint16array(RpmHead *h, int tag, int *cnt) |
430 | { | |
350209a4 | 431 | return headget(h, tag, cnt, 1); |
ae214a65 MS |
432 | } |
433 | ||
434 | static char * | |
435 | headstring(RpmHead *h, int tag) | |
436 | { | |
437 | return headget(h, tag, 0, 0); | |
438 | } | |
439 | ||
440 | static char ** | |
441 | headstringarray(RpmHead *h, int tag, int *cnt) | |
442 | { | |
443 | return headget(h, tag, cnt, 1); | |
444 | } | |
445 | ||
446 | static unsigned char * | |
447 | headbinary(RpmHead *h, int tag, unsigned int *sizep) | |
448 | { | |
d000c03e MS |
449 | unsigned char *b = headget(h, tag, (int *)sizep, 0); |
450 | if (b && sizep && (tag == TAG_SIGMD5 || tag == SIGTAG_MD5) && *sizep > 16) { | |
451 | /* due to a bug in rpm the count may be bigger if HEADERIMPORT_FAST is used */ | |
452 | *sizep = 16; | |
453 | } | |
454 | return b; | |
ae214a65 MS |
455 | } |
456 | ||
457 | static int | |
458 | headissourceheuristic(RpmHead *h) | |
459 | { | |
545fd9a1 MS |
460 | struct rpmtd_s td; |
461 | int issource; | |
462 | if (!headerGet(h, TAG_DIRNAMES, &td, HEADERGET_MINMEM)) | |
463 | return 0; | |
464 | issource = td.count == 1 && td.data && ((char **)td.data)[0] && !((char **)td.data)[0][0]; | |
465 | rpmtdFreeData(&td); | |
8e1dcb6e | 466 | return issource; |
ae214a65 MS |
467 | } |
468 | ||
ae214a65 MS |
469 | static inline void |
470 | headfree(RpmHead *h) | |
471 | { | |
472 | headerFree(h); | |
473 | } | |
474 | ||
475 | #endif | |
476 | ||
8f8a9ed5 KK |
477 | static char *headtoevr(RpmHead *h) |
478 | { | |
c49cb71a | 479 | unsigned int epoch; |
8f8a9ed5 KK |
480 | char *version, *v; |
481 | char *release; | |
482 | char *evr; | |
18f4ce31 | 483 | char *distepoch; |
8f8a9ed5 KK |
484 | |
485 | version = headstring(h, TAG_VERSION); | |
486 | release = headstring(h, TAG_RELEASE); | |
c49cb71a | 487 | epoch = headint32(h, TAG_EPOCH); |
8f8a9ed5 | 488 | if (!version || !release) |
545fd9a1 | 489 | return 0; |
0a712a6a | 490 | for (v = version; *v >= '0' && *v <= '9'; v++) |
8f8a9ed5 | 491 | ; |
8f8a9ed5 KK |
492 | if (epoch || (v != version && *v == ':')) |
493 | { | |
494 | char epochbuf[11]; /* 32bit decimal will fit in */ | |
495 | sprintf(epochbuf, "%u", epoch); | |
09f29f70 | 496 | evr = solv_malloc(strlen(epochbuf) + 1 + strlen(version) + 1 + strlen(release) + 1); |
8f8a9ed5 KK |
497 | sprintf(evr, "%s:%s-%s", epochbuf, version, release); |
498 | } | |
499 | else | |
500 | { | |
09f29f70 | 501 | evr = solv_malloc(strlen(version) + 1 + strlen(release) + 1); |
8f8a9ed5 KK |
502 | sprintf(evr, "%s-%s", version, release); |
503 | } | |
18f4ce31 MS |
504 | distepoch = headstring(h, TAG_DISTEPOCH); |
505 | if (distepoch && *distepoch) | |
506 | { | |
507 | int l = strlen(evr); | |
508 | evr = solv_realloc(evr, l + strlen(distepoch) + 2); | |
509 | evr[l++] = ':'; | |
510 | strcpy(evr + l, distepoch); | |
511 | } | |
8f8a9ed5 KK |
512 | return evr; |
513 | } | |
514 | ||
b1346980 MS |
515 | |
516 | static void | |
517 | setutf8string(Repodata *repodata, Id handle, Id tag, const char *str) | |
518 | { | |
c7bfd937 | 519 | if (str[solv_validutf8(str)]) |
b1346980 | 520 | { |
c7bfd937 MS |
521 | char *ustr = solv_latin1toutf8(str); /* not utf8, assume latin1 */ |
522 | repodata_set_str(repodata, handle, tag, ustr); | |
523 | solv_free(ustr); | |
b1346980 | 524 | } |
c7bfd937 MS |
525 | else |
526 | repodata_set_str(repodata, handle, tag, str); | |
b1346980 MS |
527 | } |
528 | ||
6afc1750 | 529 | static int |
1f12b8b2 | 530 | ignq_sortcmp(const void *va, const void *vb, void *dp) |
6afc1750 | 531 | { |
1f12b8b2 MS |
532 | int r = *(Id *)va - *(Id *)vb; |
533 | if (!r) | |
534 | r = ((Id *)va)[1] - ((Id *)vb)[1]; | |
535 | return r; | |
6afc1750 MS |
536 | } |
537 | ||
5ed9867b MS |
538 | /* |
539 | * strong: 0: ignore strongness | |
540 | * 1: filter to strong | |
541 | * 2: filter to weak | |
542 | */ | |
8f8a9ed5 | 543 | static unsigned int |
1f12b8b2 | 544 | makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int flags, Queue *ignq) |
8f8a9ed5 KK |
545 | { |
546 | char **n, **v; | |
350209a4 | 547 | uint32_t *f; |
8f8a9ed5 | 548 | int i, cc, nc, vc, fc; |
1f12b8b2 | 549 | int haspre, premask, has_ign; |
8f8a9ed5 KK |
550 | unsigned int olddeps; |
551 | Id *ida; | |
f9935ae5 | 552 | int strong = 0; |
8f8a9ed5 KK |
553 | |
554 | n = headstringarray(rpmhead, tagn, &nc); | |
f9935ae5 MS |
555 | if (!n) |
556 | { | |
557 | switch (tagn) | |
558 | { | |
559 | case TAG_SUGGESTNAME: | |
560 | tagn = TAG_OLDSUGGESTSNAME; | |
561 | tagv = TAG_OLDSUGGESTSVERSION; | |
562 | tagf = TAG_OLDSUGGESTSFLAGS; | |
563 | strong = -1; | |
564 | break; | |
565 | case TAG_ENHANCENAME: | |
566 | tagn = TAG_OLDENHANCESNAME; | |
567 | tagv = TAG_OLDENHANCESVERSION; | |
568 | tagf = TAG_OLDENHANCESFLAGS; | |
569 | strong = -1; | |
570 | break; | |
571 | case TAG_RECOMMENDNAME: | |
572 | tagn = TAG_OLDSUGGESTSNAME; | |
573 | tagv = TAG_OLDSUGGESTSVERSION; | |
574 | tagf = TAG_OLDSUGGESTSFLAGS; | |
575 | strong = 1; | |
576 | break; | |
577 | case TAG_SUPPLEMENTNAME: | |
578 | tagn = TAG_OLDENHANCESNAME; | |
579 | tagv = TAG_OLDENHANCESVERSION; | |
580 | tagf = TAG_OLDENHANCESFLAGS; | |
581 | strong = 1; | |
582 | break; | |
583 | default: | |
584 | return 0; | |
585 | } | |
586 | n = headstringarray(rpmhead, tagn, &nc); | |
587 | } | |
4c3003d9 | 588 | if (!n || !nc) |
8f8a9ed5 | 589 | return 0; |
4c3003d9 | 590 | vc = fc = 0; |
8f8a9ed5 | 591 | v = headstringarray(rpmhead, tagv, &vc); |
c49cb71a | 592 | f = headint32array(rpmhead, tagf, &fc); |
4c3003d9 | 593 | if (!v || !f || nc != vc || nc != fc) |
8f8a9ed5 | 594 | { |
cc687652 | 595 | char *pkgname = rpm_query(rpmhead, 0); |
52dcb04b | 596 | pool_error(pool, 0, "bad dependency entries for %s: %d %d %d", pkgname ? pkgname : "<NULL>", nc, vc, fc); |
cc687652 | 597 | solv_free(pkgname); |
4c3003d9 MS |
598 | solv_free(n); |
599 | solv_free(v); | |
600 | solv_free(f); | |
5702cc43 | 601 | return 0; |
8f8a9ed5 KK |
602 | } |
603 | ||
604 | cc = nc; | |
5ed9867b | 605 | haspre = 0; /* add no prereq marker */ |
f9935ae5 MS |
606 | premask = tagn == TAG_REQUIRENAME ? DEP_PRE_IN | DEP_PRE_UN : 0; |
607 | if ((flags & RPM_ADD_NO_RPMLIBREQS) || strong) | |
8f8a9ed5 | 608 | { |
5ed9867b | 609 | /* we do filtering */ |
8f8a9ed5 KK |
610 | cc = 0; |
611 | for (i = 0; i < nc; i++) | |
5ed9867b | 612 | { |
f9935ae5 | 613 | if (strong && (f[i] & DEP_STRONG) != (strong < 0 ? 0 : DEP_STRONG)) |
5ed9867b | 614 | continue; |
f9935ae5 | 615 | if ((flags & RPM_ADD_NO_RPMLIBREQS) != 0) |
5ed9867b MS |
616 | if (!strncmp(n[i], "rpmlib(", 7)) |
617 | continue; | |
ad7116d3 | 618 | if ((f[i] & premask) != 0) |
5ed9867b MS |
619 | haspre = 1; |
620 | cc++; | |
621 | } | |
8f8a9ed5 | 622 | } |
f9935ae5 | 623 | else if (premask) |
8f8a9ed5 | 624 | { |
5ed9867b | 625 | /* no filtering, just look for the first prereq */ |
8f8a9ed5 | 626 | for (i = 0; i < nc; i++) |
ad7116d3 | 627 | if ((f[i] & premask) != 0) |
8f8a9ed5 KK |
628 | { |
629 | haspre = 1; | |
630 | break; | |
631 | } | |
632 | } | |
8f8a9ed5 KK |
633 | if (cc == 0) |
634 | { | |
09f29f70 MS |
635 | solv_free(n); |
636 | solv_free(v); | |
637 | solv_free(f); | |
8f8a9ed5 KK |
638 | return 0; |
639 | } | |
ad7116d3 | 640 | cc += haspre; /* add slot for the prereq marker */ |
a00b22fc DMV |
641 | olddeps = repo_reserve_ids(repo, 0, cc); |
642 | ida = repo->idarraydata + olddeps; | |
6afc1750 | 643 | |
1f12b8b2 | 644 | has_ign = 0; |
8f8a9ed5 KK |
645 | for (i = 0; ; i++) |
646 | { | |
434eaa3a | 647 | Id id; |
8f8a9ed5 KK |
648 | if (i == nc) |
649 | { | |
650 | if (haspre != 1) | |
651 | break; | |
5ed9867b | 652 | haspre = 2; /* pass two: prereqs */ |
8f8a9ed5 KK |
653 | i = 0; |
654 | *ida++ = SOLVABLE_PREREQMARKER; | |
655 | } | |
f9935ae5 | 656 | if (strong && (f[i] & DEP_STRONG) != (strong < 0 ? 0 : DEP_STRONG)) |
8f8a9ed5 | 657 | continue; |
f9935ae5 MS |
658 | if (haspre) |
659 | { | |
660 | if (haspre == 1 && (f[i] & premask) != 0) | |
661 | continue; | |
662 | if (haspre == 2 && (f[i] & premask) == 0) | |
663 | continue; | |
664 | } | |
665 | if ((flags & RPM_ADD_NO_RPMLIBREQS) != 0) | |
5ed9867b MS |
666 | if (!strncmp(n[i], "rpmlib(", 7)) |
667 | continue; | |
434eaa3a | 668 | #ifdef ENABLE_COMPLEX_DEPS |
4782bc05 | 669 | if ((f[i] & (DEP_LESS|DEP_EQUAL|DEP_GREATER)) == 0 && n[i][0] == '(') |
434eaa3a MS |
670 | { |
671 | id = pool_parserpmrichdep(pool, n[i]); | |
672 | if (id) | |
673 | *ida++ = id; | |
674 | else | |
675 | cc--; | |
676 | continue; | |
677 | } | |
678 | #endif | |
679 | id = pool_str2id(pool, n[i], 1); | |
8f8a9ed5 KK |
680 | if (f[i] & (DEP_LESS|DEP_GREATER|DEP_EQUAL)) |
681 | { | |
434eaa3a | 682 | Id evr; |
f9935ae5 | 683 | int fl = 0; |
8f8a9ed5 | 684 | if ((f[i] & DEP_LESS) != 0) |
f9935ae5 | 685 | fl |= REL_LT; |
8f8a9ed5 | 686 | if ((f[i] & DEP_EQUAL) != 0) |
f9935ae5 | 687 | fl |= REL_EQ; |
8f8a9ed5 | 688 | if ((f[i] & DEP_GREATER) != 0) |
f9935ae5 | 689 | fl |= REL_GT; |
8f8a9ed5 | 690 | if (v[i][0] == '0' && v[i][1] == ':' && v[i][2]) |
e2a47f38 | 691 | evr = pool_str2id(pool, v[i] + 2, 1); |
8f8a9ed5 | 692 | else |
e2a47f38 | 693 | evr = pool_str2id(pool, v[i], 1); |
434eaa3a | 694 | id = pool_rel2id(pool, id, evr, fl, 1); |
8f8a9ed5 | 695 | } |
434eaa3a | 696 | *ida++ = id; |
6afc1750 MS |
697 | if (haspre == 2 && ignq) |
698 | { | |
1f12b8b2 MS |
699 | int is_ign = (f[i] & DEP_PRE_IN) != 0 && (f[i] & DEP_PRE_UN) == 0 ? 1 : 0; |
700 | has_ign |= is_ign; | |
701 | queue_push2(ignq, id, is_ign); | |
6afc1750 | 702 | } |
8f8a9ed5 KK |
703 | } |
704 | *ida++ = 0; | |
a00b22fc | 705 | repo->idarraysize += cc + 1; |
09f29f70 MS |
706 | solv_free(n); |
707 | solv_free(v); | |
708 | solv_free(f); | |
f92572e8 | 709 | if (ignq && ignq->count) |
1f12b8b2 | 710 | { |
f92572e8 MS |
711 | int j = 0; |
712 | if (has_ign && ignq->count == 2) | |
713 | j = 1; | |
714 | else if (has_ign) | |
1f12b8b2 | 715 | { |
f92572e8 MS |
716 | Id id, lastid = 0; |
717 | ||
718 | solv_sort(ignq->elements, ignq->count / 2, sizeof(Id) * 2, ignq_sortcmp, 0); | |
719 | for (i = j = 0; i < ignq->count; i += 2) | |
720 | { | |
721 | id = ignq->elements[i]; | |
722 | if (id != lastid && ignq->elements[i + 1] > 0) | |
723 | ignq->elements[j++] = id; | |
724 | lastid = id; | |
725 | } | |
1f12b8b2 MS |
726 | } |
727 | queue_truncate(ignq, j); | |
728 | } | |
8f8a9ed5 KK |
729 | return olddeps; |
730 | } | |
731 | ||
6eaa5f7c MS |
732 | static Id |
733 | repodata_str2dir_rooted(Repodata *data, char *str, int create) | |
734 | { | |
735 | char buf[256], *bp; | |
736 | int l = strlen(str); | |
737 | Id id; | |
738 | ||
739 | if (l + 2 <= sizeof(buf)) | |
740 | bp = buf; | |
741 | else | |
742 | bp = solv_malloc(l + 2); | |
743 | bp[0] = '/'; | |
744 | strcpy(bp + 1, str); | |
745 | id = repodata_str2dir(data, bp, create); | |
746 | if (bp != buf) | |
747 | solv_free(bp); | |
748 | return id; | |
749 | } | |
8f8a9ed5 | 750 | |
c49cb71a | 751 | static void |
350209a4 | 752 | adddudata(Repodata *data, Id handle, RpmHead *rpmhead, char **dn, uint32_t *di, int fc, int dc) |
c49cb71a | 753 | { |
b309e4bd | 754 | Id did; |
c49cb71a | 755 | int i, fszc; |
350209a4 MS |
756 | unsigned int *fkb, *fn; |
757 | uint64_t *fsz64; | |
758 | uint32_t *fsz, *fino; | |
759 | uint16_t *fm; | |
7a93753b | 760 | unsigned int inotest[256], inotestok; |
c49cb71a | 761 | |
7a93753b MS |
762 | if (!fc) |
763 | return; | |
b188af05 MS |
764 | if ((fsz64 = headint64array(rpmhead, TAG_LONGFILESIZES, &fszc)) != 0) |
765 | { | |
766 | /* convert to kbyte */ | |
767 | fsz = solv_malloc2(fszc, sizeof(*fsz)); | |
768 | for (i = 0; i < fszc; i++) | |
769 | fsz[i] = fsz64[i] ? fsz64[i] / 1024 + 1 : 0; | |
770 | solv_free(fsz64); | |
771 | } | |
772 | else if ((fsz = headint32array(rpmhead, TAG_FILESIZES, &fszc)) != 0) | |
773 | { | |
774 | /* convert to kbyte */ | |
775 | for (i = 0; i < fszc; i++) | |
776 | if (fsz[i]) | |
777 | fsz[i] = fsz[i] / 1024 + 1; | |
778 | } | |
779 | else | |
780 | return; | |
781 | if (fc != fszc) | |
c49cb71a | 782 | { |
09f29f70 | 783 | solv_free(fsz); |
c49cb71a MS |
784 | return; |
785 | } | |
b188af05 | 786 | |
2746446e | 787 | /* stupid rpm records sizes of directories, so we have to check the mode */ |
c49cb71a MS |
788 | fm = headint16array(rpmhead, TAG_FILEMODES, &fszc); |
789 | if (!fm || fc != fszc) | |
790 | { | |
09f29f70 MS |
791 | solv_free(fsz); |
792 | solv_free(fm); | |
c49cb71a MS |
793 | return; |
794 | } | |
7a93753b MS |
795 | fino = headint32array(rpmhead, TAG_FILEINODES, &fszc); |
796 | if (!fino || fc != fszc) | |
797 | { | |
09f29f70 MS |
798 | solv_free(fsz); |
799 | solv_free(fm); | |
800 | solv_free(fino); | |
7a93753b MS |
801 | return; |
802 | } | |
b188af05 MS |
803 | |
804 | /* kill hardlinked entries */ | |
7a93753b MS |
805 | inotestok = 0; |
806 | if (fc < sizeof(inotest)) | |
807 | { | |
b188af05 | 808 | /* quick test just hashing the inode numbers */ |
7a93753b MS |
809 | memset(inotest, 0, sizeof(inotest)); |
810 | for (i = 0; i < fc; i++) | |
811 | { | |
812 | int off, bit; | |
813 | if (fsz[i] == 0 || !S_ISREG(fm[i])) | |
b188af05 | 814 | continue; /* does not matter */ |
7a93753b MS |
815 | off = (fino[i] >> 5) & (sizeof(inotest)/sizeof(*inotest) - 1); |
816 | bit = 1 << (fino[i] & 31); | |
817 | if ((inotest[off] & bit) != 0) | |
818 | break; | |
819 | inotest[off] |= bit; | |
820 | } | |
821 | if (i == fc) | |
b188af05 | 822 | inotestok = 1; /* no conflict found */ |
7a93753b MS |
823 | } |
824 | if (!inotestok) | |
825 | { | |
b188af05 | 826 | /* hardlinked files are possible, check ino/dev pairs */ |
7a93753b MS |
827 | unsigned int *fdev = headint32array(rpmhead, TAG_FILEDEVICES, &fszc); |
828 | unsigned int *fx, j; | |
829 | unsigned int mask, hash, hh; | |
830 | if (!fdev || fc != fszc) | |
831 | { | |
09f29f70 MS |
832 | solv_free(fsz); |
833 | solv_free(fm); | |
834 | solv_free(fdev); | |
835 | solv_free(fino); | |
7a93753b MS |
836 | return; |
837 | } | |
838 | mask = fc; | |
839 | while ((mask & (mask - 1)) != 0) | |
840 | mask = mask & (mask - 1); | |
841 | mask <<= 2; | |
842 | if (mask > sizeof(inotest)/sizeof(*inotest)) | |
09f29f70 | 843 | fx = solv_calloc(mask, sizeof(unsigned int)); |
7a93753b MS |
844 | else |
845 | { | |
846 | fx = inotest; | |
847 | memset(fx, 0, mask * sizeof(unsigned int)); | |
848 | } | |
849 | mask--; | |
850 | for (i = 0; i < fc; i++) | |
851 | { | |
852 | if (fsz[i] == 0 || !S_ISREG(fm[i])) | |
853 | continue; | |
854 | hash = (fino[i] + fdev[i] * 31) & mask; | |
855 | hh = 7; | |
856 | while ((j = fx[hash]) != 0) | |
857 | { | |
858 | if (fino[j - 1] == fino[i] && fdev[j - 1] == fdev[i]) | |
859 | { | |
860 | fsz[i] = 0; /* kill entry */ | |
861 | break; | |
862 | } | |
863 | hash = (hash + hh++) & mask; | |
864 | } | |
865 | if (!j) | |
866 | fx[hash] = i + 1; | |
867 | } | |
868 | if (fx != inotest) | |
09f29f70 MS |
869 | solv_free(fx); |
870 | solv_free(fdev); | |
7a93753b | 871 | } |
09f29f70 | 872 | solv_free(fino); |
b188af05 MS |
873 | |
874 | /* sum up inode count and kbytes for each directory */ | |
09f29f70 MS |
875 | fn = solv_calloc(dc, sizeof(unsigned int)); |
876 | fkb = solv_calloc(dc, sizeof(unsigned int)); | |
c49cb71a MS |
877 | for (i = 0; i < fc; i++) |
878 | { | |
ce1b09e0 | 879 | if (di[i] >= dc) |
20031e22 | 880 | continue; /* corrupt entry */ |
c49cb71a | 881 | fn[di[i]]++; |
2746446e MS |
882 | if (fsz[i] == 0 || !S_ISREG(fm[i])) |
883 | continue; | |
b188af05 | 884 | fkb[di[i]] += fsz[i]; |
c49cb71a | 885 | } |
09f29f70 MS |
886 | solv_free(fsz); |
887 | solv_free(fm); | |
c49cb71a | 888 | /* commit */ |
ce1b09e0 | 889 | for (i = 0; i < dc; i++) |
c49cb71a MS |
890 | { |
891 | if (!fn[i]) | |
892 | continue; | |
6eaa5f7c | 893 | if (dn[i][0] != '/') |
ce1b09e0 | 894 | { |
cab0d2bd | 895 | Solvable *s = data->repo->pool->solvables + handle; |
ce1b09e0 MS |
896 | if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) |
897 | did = repodata_str2dir(data, "/usr/src", 1); | |
898 | else | |
6eaa5f7c | 899 | did = repodata_str2dir_rooted(data, dn[i], 1); |
ce1b09e0 | 900 | } |
6eaa5f7c MS |
901 | else |
902 | did = repodata_str2dir(data, dn[i], 1); | |
b2fa614d | 903 | repodata_add_dirnumnum(data, handle, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]); |
c49cb71a | 904 | } |
09f29f70 MS |
905 | solv_free(fn); |
906 | solv_free(fkb); | |
c49cb71a MS |
907 | } |
908 | ||
6dfec0d0 MS |
909 | static int |
910 | is_filtered(const char *dir) | |
911 | { | |
912 | if (!dir) | |
913 | return 1; | |
914 | /* the dirs always have a trailing / in rpm */ | |
915 | if (strstr(dir, "bin/")) | |
916 | return 0; | |
917 | if (!strncmp(dir, "/etc/", 5)) | |
918 | return 0; | |
919 | if (!strcmp(dir, "/usr/lib/")) | |
920 | return 2; | |
921 | return 1; | |
922 | } | |
923 | ||
b309e4bd | 924 | static void |
6dfec0d0 | 925 | addfilelist(Repodata *data, Id handle, RpmHead *rpmhead, int flags) |
8f8a9ed5 KK |
926 | { |
927 | char **bn; | |
928 | char **dn; | |
350209a4 | 929 | uint32_t *di; |
8f8a9ed5 | 930 | int bnc, dnc, dic; |
676e1385 | 931 | int i; |
6eaa5f7c | 932 | Id did; |
350209a4 | 933 | uint32_t lastdii = -1; |
6dfec0d0 | 934 | int lastfiltered = 0; |
8f8a9ed5 | 935 | |
b2fa614d | 936 | if (!data) |
b309e4bd | 937 | return; |
8f8a9ed5 KK |
938 | bn = headstringarray(rpmhead, TAG_BASENAMES, &bnc); |
939 | if (!bn) | |
b309e4bd | 940 | return; |
8f8a9ed5 KK |
941 | dn = headstringarray(rpmhead, TAG_DIRNAMES, &dnc); |
942 | if (!dn) | |
943 | { | |
09f29f70 | 944 | solv_free(bn); |
b309e4bd | 945 | return; |
8f8a9ed5 | 946 | } |
c49cb71a | 947 | di = headint32array(rpmhead, TAG_DIRINDEXES, &dic); |
8f8a9ed5 KK |
948 | if (!di) |
949 | { | |
09f29f70 MS |
950 | solv_free(bn); |
951 | solv_free(dn); | |
b309e4bd | 952 | return; |
8f8a9ed5 KK |
953 | } |
954 | if (bnc != dic) | |
955 | { | |
52dcb04b | 956 | pool_error(data->repo->pool, 0, "bad filelist"); |
b309e4bd | 957 | return; |
8f8a9ed5 | 958 | } |
c49cb71a | 959 | |
b309e4bd | 960 | adddudata(data, handle, rpmhead, dn, di, bnc, dnc); |
c49cb71a | 961 | |
6eaa5f7c | 962 | did = -1; |
8f8a9ed5 KK |
963 | for (i = 0; i < bnc; i++) |
964 | { | |
b309e4bd | 965 | char *b = bn[i]; |
ce1b09e0 | 966 | |
6eaa5f7c | 967 | if (did < 0 || di[i] != lastdii) |
b309e4bd | 968 | { |
20031e22 MS |
969 | if (di[i] >= dnc) |
970 | continue; /* corrupt entry */ | |
6eaa5f7c | 971 | did = 0; |
6dfec0d0 MS |
972 | lastdii = di[i]; |
973 | if ((flags & RPM_ADD_FILTERED_FILELIST) != 0) | |
974 | { | |
975 | lastfiltered = is_filtered(dn[di[i]]); | |
976 | if (lastfiltered == 1) | |
977 | continue; | |
978 | } | |
6eaa5f7c MS |
979 | if (dn[lastdii][0] != '/') |
980 | did = repodata_str2dir_rooted(data, dn[lastdii], 1); | |
981 | else | |
982 | did = repodata_str2dir(data, dn[lastdii], 1); | |
c49cb71a | 983 | } |
6eaa5f7c MS |
984 | if (!b) |
985 | continue; | |
986 | if (*b == '/') /* work around rpm bug */ | |
b309e4bd | 987 | b++; |
6eaa5f7c MS |
988 | if (lastfiltered && (lastfiltered != 2 || strcmp(b, "sendmail"))) |
989 | continue; | |
b309e4bd | 990 | repodata_add_dirstr(data, handle, SOLVABLE_FILELIST, did, b); |
8f8a9ed5 | 991 | } |
09f29f70 MS |
992 | solv_free(bn); |
993 | solv_free(dn); | |
994 | solv_free(di); | |
8f8a9ed5 KK |
995 | } |
996 | ||
b6c702b3 MS |
997 | static void |
998 | addchangelog(Repodata *data, Id handle, RpmHead *rpmhead) | |
999 | { | |
1000 | char **cn; | |
1001 | char **cx; | |
350209a4 | 1002 | uint32_t *ct; |
7c8ab7d6 | 1003 | int i, cnc, cxc, ctc = 0; |
b6c702b3 MS |
1004 | Queue hq; |
1005 | ||
1006 | ct = headint32array(rpmhead, TAG_CHANGELOGTIME, &ctc); | |
1007 | cx = headstringarray(rpmhead, TAG_CHANGELOGTEXT, &cxc); | |
1008 | cn = headstringarray(rpmhead, TAG_CHANGELOGNAME, &cnc); | |
1009 | if (!ct || !cx || !cn || !ctc || ctc != cxc || ctc != cnc) | |
1010 | { | |
1011 | solv_free(ct); | |
1012 | solv_free(cx); | |
1013 | solv_free(cn); | |
1014 | return; | |
1015 | } | |
1016 | queue_init(&hq); | |
1017 | for (i = 0; i < ctc; i++) | |
1018 | { | |
1019 | Id h = repodata_new_handle(data); | |
1020 | if (ct[i]) | |
1021 | repodata_set_num(data, h, SOLVABLE_CHANGELOG_TIME, ct[i]); | |
1022 | if (cn[i]) | |
c7bfd937 | 1023 | setutf8string(data, h, SOLVABLE_CHANGELOG_AUTHOR, cn[i]); |
b6c702b3 | 1024 | if (cx[i]) |
c7bfd937 | 1025 | setutf8string(data, h, SOLVABLE_CHANGELOG_TEXT, cx[i]); |
b6c702b3 MS |
1026 | queue_push(&hq, h); |
1027 | } | |
1028 | for (i = 0; i < hq.count; i++) | |
1029 | repodata_add_flexarray(data, handle, SOLVABLE_CHANGELOG, hq.elements[i]); | |
1030 | queue_free(&hq); | |
1031 | solv_free(ct); | |
1032 | solv_free(cx); | |
1033 | solv_free(cn); | |
1034 | } | |
1035 | ||
9c424c73 | 1036 | static void |
8ce1a139 MS |
1037 | set_description_author(Repodata *data, Id handle, char *str) |
1038 | { | |
1039 | char *aut, *p; | |
1040 | for (aut = str; (aut = strchr(aut, '\n')) != 0; aut++) | |
1041 | if (!strncmp(aut, "\nAuthors:\n--------\n", 19)) | |
1042 | break; | |
1043 | if (aut) | |
1044 | { | |
1045 | /* oh my, found SUSE special author section */ | |
1046 | int l = aut - str; | |
1047 | str = solv_strdup(str); | |
1048 | aut = str + l; | |
1049 | str[l] = 0; | |
1050 | while (l > 0 && str[l - 1] == '\n') | |
1051 | str[--l] = 0; | |
1052 | if (l) | |
1053 | setutf8string(data, handle, SOLVABLE_DESCRIPTION, str); | |
1054 | p = aut + 19; | |
1055 | aut = str; /* copy over */ | |
1056 | while (*p == ' ' || *p == '\n') | |
1057 | p++; | |
1058 | while (*p) | |
1059 | { | |
1060 | if (*p == '\n') | |
1061 | { | |
1062 | *aut++ = *p++; | |
1063 | while (*p == ' ') | |
1064 | p++; | |
1065 | continue; | |
1066 | } | |
1067 | *aut++ = *p++; | |
1068 | } | |
1069 | while (aut != str && aut[-1] == '\n') | |
1070 | aut--; | |
1071 | *aut = 0; | |
1072 | if (*str) | |
1073 | setutf8string(data, handle, SOLVABLE_AUTHORS, str); | |
1074 | free(str); | |
1075 | } | |
1076 | else if (*str) | |
1077 | setutf8string(data, handle, SOLVABLE_DESCRIPTION, str); | |
1078 | } | |
b6c702b3 | 1079 | |
8f8a9ed5 | 1080 | static int |
49d6cbd2 | 1081 | rpmhead2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, int flags) |
8f8a9ed5 KK |
1082 | { |
1083 | char *name; | |
1084 | char *evr; | |
d1266cd2 | 1085 | char *sourcerpm; |
6afc1750 | 1086 | Queue ignq; |
1f12b8b2 | 1087 | Id ignqbuf[64]; |
8f8a9ed5 KK |
1088 | |
1089 | name = headstring(rpmhead, TAG_NAME); | |
6af0f8f8 | 1090 | if (!name) |
8f8a9ed5 | 1091 | { |
52dcb04b | 1092 | pool_error(pool, 0, "package has no name"); |
5702cc43 | 1093 | return 0; |
8f8a9ed5 | 1094 | } |
1ea5ac1c | 1095 | if (!(flags & RPMDB_KEEP_GPG_PUBKEY) && !strcmp(name, "gpg-pubkey")) |
6af0f8f8 MS |
1096 | return 0; |
1097 | s->name = pool_str2id(pool, name, 1); | |
d1266cd2 | 1098 | sourcerpm = headstring(rpmhead, TAG_SOURCERPM); |
6c8ee8bc | 1099 | if (sourcerpm || !(headexists(rpmhead, TAG_SOURCEPACKAGE) || headissourceheuristic(rpmhead))) |
e2a47f38 | 1100 | s->arch = pool_str2id(pool, headstring(rpmhead, TAG_ARCH), 1); |
3bf73c63 MS |
1101 | else |
1102 | { | |
1103 | if (headexists(rpmhead, TAG_NOSOURCE) || headexists(rpmhead, TAG_NOPATCH)) | |
1104 | s->arch = ARCH_NOSRC; | |
1105 | else | |
1106 | s->arch = ARCH_SRC; | |
1107 | } | |
8f8a9ed5 | 1108 | if (!s->arch) |
555a08b2 | 1109 | s->arch = ARCH_NOARCH; |
8f8a9ed5 | 1110 | evr = headtoevr(rpmhead); |
e2a47f38 | 1111 | s->evr = pool_str2id(pool, evr, 1); |
545fd9a1 | 1112 | solv_free(evr); |
e2a47f38 | 1113 | s->vendor = pool_str2id(pool, headstring(rpmhead, TAG_VENDOR), 1); |
8f8a9ed5 | 1114 | |
6afc1750 | 1115 | queue_init_buffer(&ignq, ignqbuf, sizeof(ignqbuf)/sizeof(*ignqbuf)); |
6afc1750 | 1116 | |
1f12b8b2 | 1117 | s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0, 0); |
7ada46e5 | 1118 | if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) |
e2a47f38 | 1119 | s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); |
1f12b8b2 MS |
1120 | s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, flags, &ignq); |
1121 | s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0, 0); | |
1122 | s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0, 0); | |
a00b22fc | 1123 | |
1f12b8b2 MS |
1124 | s->recommends = makedeps(pool, repo, rpmhead, TAG_RECOMMENDNAME, TAG_RECOMMENDVERSION, TAG_RECOMMENDFLAGS, 0, 0); |
1125 | s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTNAME, TAG_SUGGESTVERSION, TAG_SUGGESTFLAGS, 0, 0); | |
1126 | s->supplements = makedeps(pool, repo, rpmhead, TAG_SUPPLEMENTNAME, TAG_SUPPLEMENTVERSION, TAG_SUPPLEMENTFLAGS, 0, 0); | |
1127 | s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCENAME, TAG_ENHANCEVERSION, TAG_ENHANCEFLAGS, 0, 0); | |
f9935ae5 | 1128 | |
09b5fb29 | 1129 | repo_rewrite_suse_deps(s, 0); |
c49cb71a | 1130 | |
6afc1750 | 1131 | if (data && ignq.count) |
1f12b8b2 | 1132 | repodata_set_idarray(data, s - pool->solvables, SOLVABLE_PREREQ_IGNOREINST, &ignq); |
6afc1750 | 1133 | queue_free(&ignq); |
6afc1750 | 1134 | |
b2fa614d | 1135 | if (data) |
c49cb71a | 1136 | { |
1c20a14d | 1137 | Id handle; |
c49cb71a MS |
1138 | char *str; |
1139 | unsigned int u32; | |
b69427b4 | 1140 | unsigned long long u64; |
c49cb71a | 1141 | |
b2fa614d | 1142 | handle = s - pool->solvables; |
c49cb71a MS |
1143 | str = headstring(rpmhead, TAG_SUMMARY); |
1144 | if (str) | |
b2fa614d | 1145 | setutf8string(data, handle, SOLVABLE_SUMMARY, str); |
c49cb71a MS |
1146 | str = headstring(rpmhead, TAG_DESCRIPTION); |
1147 | if (str) | |
8ce1a139 | 1148 | set_description_author(data, handle, str); |
c49cb71a MS |
1149 | str = headstring(rpmhead, TAG_GROUP); |
1150 | if (str) | |
b2fa614d | 1151 | repodata_set_poolstr(data, handle, SOLVABLE_GROUP, str); |
a8c85b1c MS |
1152 | str = headstring(rpmhead, TAG_LICENSE); |
1153 | if (str) | |
b2fa614d | 1154 | repodata_set_poolstr(data, handle, SOLVABLE_LICENSE, str); |
06429cda MS |
1155 | str = headstring(rpmhead, TAG_URL); |
1156 | if (str) | |
b2fa614d | 1157 | repodata_set_str(data, handle, SOLVABLE_URL, str); |
5f696409 MS |
1158 | str = headstring(rpmhead, TAG_DISTRIBUTION); |
1159 | if (str) | |
b2fa614d | 1160 | repodata_set_poolstr(data, handle, SOLVABLE_DISTRIBUTION, str); |
5f696409 MS |
1161 | str = headstring(rpmhead, TAG_PACKAGER); |
1162 | if (str) | |
b2fa614d | 1163 | repodata_set_poolstr(data, handle, SOLVABLE_PACKAGER, str); |
966d89be MS |
1164 | if ((flags & RPM_ADD_WITH_PKGID) != 0) |
1165 | { | |
1166 | unsigned char *chksum; | |
1167 | unsigned int chksumsize; | |
1168 | chksum = headbinary(rpmhead, TAG_SIGMD5, &chksumsize); | |
1169 | if (chksum && chksumsize == 16) | |
1170 | repodata_set_bin_checksum(data, handle, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, chksum); | |
1171 | } | |
3d08e89c AK |
1172 | if ((flags & RPM_ADD_WITH_HDRID) != 0) |
1173 | { | |
1174 | str = headstring(rpmhead, TAG_SHA1HEADER); | |
521f1f58 MS |
1175 | if (str && strlen(str) == 40) |
1176 | repodata_set_checksum(data, handle, SOLVABLE_HDRID, REPOKEY_TYPE_SHA1, str); | |
1177 | else if (str && strlen(str) == 64) | |
1178 | repodata_set_checksum(data, handle, SOLVABLE_HDRID, REPOKEY_TYPE_SHA256, str); | |
3d08e89c | 1179 | } |
c49cb71a MS |
1180 | u32 = headint32(rpmhead, TAG_BUILDTIME); |
1181 | if (u32) | |
b2fa614d | 1182 | repodata_set_num(data, handle, SOLVABLE_BUILDTIME, u32); |
a8c85b1c MS |
1183 | u32 = headint32(rpmhead, TAG_INSTALLTIME); |
1184 | if (u32) | |
b2fa614d | 1185 | repodata_set_num(data, handle, SOLVABLE_INSTALLTIME, u32); |
b69427b4 MS |
1186 | u64 = headint64(rpmhead, TAG_LONGSIZE); |
1187 | if (u64) | |
1188 | repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, u64); | |
1189 | else | |
1190 | { | |
1191 | u32 = headint32(rpmhead, TAG_SIZE); | |
1192 | if (u32) | |
1193 | repodata_set_num(data, handle, SOLVABLE_INSTALLSIZE, u32); | |
1194 | } | |
d1266cd2 | 1195 | if (sourcerpm) |
6af0f8f8 | 1196 | repodata_set_sourcepkg(data, handle, sourcerpm); |
a415136a MS |
1197 | if ((flags & RPM_ADD_TRIGGERS) != 0) |
1198 | { | |
1f12b8b2 | 1199 | unsigned int ida = makedeps(pool, repo, rpmhead, TAG_TRIGGERNAME, TAG_TRIGGERVERSION, TAG_TRIGGERFLAGS, 0, 0); |
f8d56407 MS |
1200 | Id id, lastid = 0; |
1201 | for (lastid = 0; (id = repo->idarraydata[ida]) != 0; ida++, lastid = id) | |
1202 | if (id != lastid) | |
a415136a | 1203 | repodata_add_idarray(data, handle, SOLVABLE_TRIGGERS, id); |
a415136a | 1204 | } |
b309e4bd | 1205 | if ((flags & RPM_ADD_NO_FILELIST) == 0) |
6dfec0d0 | 1206 | addfilelist(data, handle, rpmhead, flags); |
b6c702b3 MS |
1207 | if ((flags & RPM_ADD_WITH_CHANGELOG) != 0) |
1208 | addchangelog(data, handle, rpmhead); | |
c49cb71a | 1209 | } |
8f8a9ed5 KK |
1210 | return 1; |
1211 | } | |
1212 | ||
7173e5d6 MS |
1213 | static inline unsigned int |
1214 | getu32(const unsigned char *dp) | |
1215 | { | |
1216 | return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3]; | |
1217 | } | |
1218 | ||
7a9c082b | 1219 | #ifdef ENABLE_RPMDB |
18399c39 | 1220 | |
7a9c082b MS |
1221 | struct rpmdbentry { |
1222 | Id rpmdbid; | |
1223 | Id nameoff; | |
1224 | }; | |
1225 | ||
1226 | #define ENTRIES_BLOCK 255 | |
1227 | #define NAMEDATA_BLOCK 1023 | |
18399c39 | 1228 | |
7a9c082b MS |
1229 | # ifdef ENABLE_RPMDB_LIBRPM |
1230 | # include "repo_rpmdb_librpm.h" | |
1231 | # else | |
1232 | # include "repo_rpmdb_bdb.h" | |
1233 | # endif | |
1234 | ||
1235 | #else | |
1236 | ||
1237 | /* dummy state just to store pool/rootdir and header data */ | |
691ceb7b | 1238 | struct rpmdbstate { |
9c424c73 | 1239 | Pool *pool; |
691ceb7b | 1240 | char *rootdir; |
18399c39 | 1241 | |
691ceb7b MS |
1242 | RpmHead *rpmhead; /* header storage space */ |
1243 | int rpmheadsize; | |
7a9c082b | 1244 | }; |
87bfd053 | 1245 | |
7173e5d6 | 1246 | #endif |
0eb816cc | 1247 | |
47fbaa2a MS |
1248 | |
1249 | #ifndef ENABLE_RPMPKG_LIBRPM | |
1250 | ||
aa4df21e MS |
1251 | static int |
1252 | headfromfp(struct rpmdbstate *state, const char *name, FILE *fp, unsigned char *lead, unsigned int cnt, unsigned int dsize, unsigned int pad, Chksum *chk1, Chksum *chk2) | |
47fbaa2a | 1253 | { |
aa4df21e | 1254 | RpmHead *rpmhead; |
47fbaa2a MS |
1255 | unsigned int len = 16 * cnt + dsize + pad; |
1256 | if (len + 1 > state->rpmheadsize) | |
1257 | { | |
aa4df21e | 1258 | state->rpmheadsize = len + 128; |
47fbaa2a MS |
1259 | state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize); |
1260 | } | |
aa4df21e MS |
1261 | rpmhead = state->rpmhead; |
1262 | if (fread(rpmhead->data, len, 1, fp) != 1) | |
2f95fad5 | 1263 | return pool_error(state->pool, 0, "%s: unexpected EOF", name); |
47fbaa2a | 1264 | if (chk1) |
aa4df21e | 1265 | solv_chksum_add(chk1, rpmhead->data, len); |
47fbaa2a | 1266 | if (chk2) |
aa4df21e MS |
1267 | solv_chksum_add(chk2, rpmhead->data, len); |
1268 | rpmhead->data[len] = 0; | |
1269 | rpmhead->cnt = cnt; | |
1270 | rpmhead->dcnt = dsize; | |
1271 | rpmhead->dp = rpmhead->data + cnt * 16; | |
47fbaa2a MS |
1272 | return 1; |
1273 | } | |
1274 | ||
aa4df21e MS |
1275 | #if defined(ENABLE_RPMDB_BYRPMHEADER) |
1276 | static void | |
1277 | headfromblob(struct rpmdbstate *state, const unsigned char *blob, unsigned int cnt, unsigned int dsize) | |
1278 | { | |
1279 | RpmHead *rpmhead; | |
1280 | unsigned int len = 16 * cnt + dsize; | |
1281 | if (len + 1 > state->rpmheadsize) | |
1282 | { | |
1283 | state->rpmheadsize = len + 128; | |
1284 | state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize); | |
1285 | } | |
1286 | rpmhead = state->rpmhead; | |
1287 | memcpy(rpmhead->data, blob, len); | |
1288 | rpmhead->data[len] = 0; | |
1289 | rpmhead->cnt = cnt; | |
1290 | rpmhead->dcnt = dsize; | |
1291 | rpmhead->dp = rpmhead->data + cnt * 16; | |
1292 | } | |
1293 | #endif | |
1294 | ||
47fbaa2a MS |
1295 | #else |
1296 | ||
aa4df21e MS |
1297 | static int |
1298 | headfromfp(struct rpmdbstate *state, const char *name, FILE *fp, unsigned char *lead, unsigned int cnt, unsigned int dsize, unsigned int pad, Chksum *chk1, Chksum *chk2) | |
47fbaa2a MS |
1299 | { |
1300 | unsigned int len = 16 * cnt + dsize + pad; | |
1301 | char *buf = solv_malloc(8 + len); | |
1302 | Header h; | |
1303 | memcpy(buf, lead + 8, 8); | |
1304 | if (fread(buf + 8, len, 1, fp) != 1) | |
1305 | { | |
1306 | solv_free(buf); | |
1307 | return pool_error(state->pool, 0, "%s: unexpected EOF", name); | |
1308 | } | |
1309 | if (chk1) | |
1310 | solv_chksum_add(chk1, buf + 8, len); | |
1311 | if (chk2) | |
1312 | solv_chksum_add(chk2, buf + 8, len); | |
1313 | h = headerImport(buf, 8 + len - pad, HEADERIMPORT_FAST); | |
1314 | if (!h) | |
1315 | { | |
1316 | solv_free(buf); | |
1317 | return pool_error(state->pool, 0, "%s: headerImport error", name); | |
1318 | } | |
1319 | if (state->rpmhead) | |
1320 | headfree(state->rpmhead); | |
1321 | state->rpmhead = h; | |
1322 | return 1; | |
1323 | } | |
1324 | ||
1325 | #endif | |
1326 | ||
ae214a65 MS |
1327 | static void |
1328 | freestate(struct rpmdbstate *state) | |
1329 | { | |
1330 | /* close down */ | |
ae214a65 MS |
1331 | #ifdef ENABLE_RPMDB |
1332 | if (state->pkgdbopened) | |
1333 | closepkgdb(state); | |
7a9c082b | 1334 | if (state->dbenvopened) |
ae214a65 MS |
1335 | closedbenv(state); |
1336 | #endif | |
1337 | if (state->rootdir) | |
1338 | solv_free(state->rootdir); | |
1339 | headfree(state->rpmhead); | |
1340 | } | |
1341 | ||
1342 | void * | |
1343 | rpm_state_create(Pool *pool, const char *rootdir) | |
1344 | { | |
1345 | struct rpmdbstate *state; | |
1346 | state = solv_calloc(1, sizeof(*state)); | |
1347 | state->pool = pool; | |
1348 | if (rootdir) | |
1349 | state->rootdir = solv_strdup(rootdir); | |
1350 | return state; | |
1351 | } | |
1352 | ||
1353 | void * | |
1354 | rpm_state_free(void *state) | |
1355 | { | |
aa4df21e MS |
1356 | if (state) |
1357 | freestate(state); | |
ae214a65 MS |
1358 | return solv_free(state); |
1359 | } | |
1360 | ||
1361 | ||
1362 | #ifdef ENABLE_RPMDB | |
1363 | ||
1364 | ||
691ceb7b MS |
1365 | /******************************************************************/ |
1366 | ||
691ceb7b MS |
1367 | static Offset |
1368 | copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) | |
1369 | { | |
1370 | int cc; | |
843dc7e1 | 1371 | Id *ida, *from; |
691ceb7b | 1372 | Offset ido; |
691ceb7b MS |
1373 | |
1374 | if (!fromoff) | |
1375 | return 0; | |
1376 | from = fromrepo->idarraydata + fromoff; | |
1377 | for (ida = from, cc = 0; *ida; ida++, cc++) | |
1378 | ; | |
1379 | if (cc == 0) | |
1380 | return 0; | |
1381 | ido = repo_reserve_ids(repo, 0, cc); | |
1382 | ida = repo->idarraydata + ido; | |
843dc7e1 | 1383 | memcpy(ida, from, (cc + 1) * sizeof(Id)); |
691ceb7b MS |
1384 | repo->idarraysize += cc + 1; |
1385 | return ido; | |
1386 | } | |
1387 | ||
691ceb7b MS |
1388 | struct solvable_copy_cbdata { |
1389 | Repodata *data; | |
1390 | Id handle; | |
1391 | Id subhandle; | |
1392 | Id *dircache; | |
1393 | }; | |
1394 | ||
1395 | static int | |
1396 | solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, KeyValue *kv) | |
1397 | { | |
1398 | struct solvable_copy_cbdata *cbdata = vcbdata; | |
691ceb7b MS |
1399 | Repodata *data = cbdata->data; |
1400 | Id handle = cbdata->handle; | |
691ceb7b | 1401 | |
72e8b9af | 1402 | switch (key->type) |
691ceb7b MS |
1403 | { |
1404 | case REPOKEY_TYPE_ID: | |
1405 | case REPOKEY_TYPE_CONSTANTID: | |
1406 | case REPOKEY_TYPE_IDARRAY: /* used for triggers */ | |
772a525a | 1407 | if (data->localpool || fromdata->localpool) |
72e8b9af | 1408 | kv->id = repodata_translate_id(data, fromdata, kv->id, 1); |
691ceb7b MS |
1409 | break; |
1410 | case REPOKEY_TYPE_DIRNUMNUMARRAY: | |
691ceb7b | 1411 | case REPOKEY_TYPE_DIRSTRARRAY: |
b19f33c9 | 1412 | kv->id = repodata_translate_dir(data, fromdata, kv->id, 1, fromdata->repodataid == 1 ? cbdata->dircache : 0); |
691ceb7b | 1413 | break; |
ac58625b MS |
1414 | case REPOKEY_TYPE_FIXARRAY: |
1415 | cbdata->handle = repodata_new_handle(data); | |
1416 | repodata_add_fixarray(data, handle, key->name, cbdata->handle); | |
1417 | repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); | |
1418 | cbdata->handle = handle; | |
1419 | return 0; | |
691ceb7b | 1420 | case REPOKEY_TYPE_FLEXARRAY: |
691ceb7b | 1421 | cbdata->handle = repodata_new_handle(data); |
ac58625b MS |
1422 | repodata_add_flexarray(data, handle, key->name, cbdata->handle); |
1423 | repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); | |
1424 | cbdata->handle = handle; | |
72e8b9af | 1425 | return 0; |
691ceb7b MS |
1426 | default: |
1427 | break; | |
1428 | } | |
72e8b9af | 1429 | repodata_set_kv(data, handle, key->name, key->type, kv); |
691ceb7b MS |
1430 | return 0; |
1431 | } | |
1432 | ||
1433 | static void | |
24112339 | 1434 | solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache, Id **oldkeyskip) |
691ceb7b | 1435 | { |
9ed44b97 | 1436 | int p, i; |
691ceb7b | 1437 | Repo *repo = s->repo; |
691ceb7b | 1438 | Pool *pool = repo->pool; |
843dc7e1 | 1439 | Repo *fromrepo = r->repo; |
691ceb7b | 1440 | struct solvable_copy_cbdata cbdata; |
24112339 | 1441 | Id *keyskip; |
691ceb7b MS |
1442 | |
1443 | /* copy solvable data */ | |
843dc7e1 MS |
1444 | s->name = r->name; |
1445 | s->evr = r->evr; | |
1446 | s->arch = r->arch; | |
1447 | s->vendor = r->vendor; | |
691ceb7b MS |
1448 | s->provides = copydeps(pool, repo, r->provides, fromrepo); |
1449 | s->requires = copydeps(pool, repo, r->requires, fromrepo); | |
18399c39 MS |
1450 | s->conflicts = copydeps(pool, repo, r->conflicts, fromrepo); |
1451 | s->obsoletes = copydeps(pool, repo, r->obsoletes, fromrepo); | |
1452 | s->recommends = copydeps(pool, repo, r->recommends, fromrepo); | |
1453 | s->suggests = copydeps(pool, repo, r->suggests, fromrepo); | |
1454 | s->supplements = copydeps(pool, repo, r->supplements, fromrepo); | |
1455 | s->enhances = copydeps(pool, repo, r->enhances, fromrepo); | |
18399c39 MS |
1456 | |
1457 | /* copy all attributes */ | |
72e8b9af | 1458 | if (!data || fromrepo->nrepodata < 2) |
18399c39 | 1459 | return; |
18399c39 | 1460 | cbdata.data = data; |
b2fa614d | 1461 | cbdata.handle = s - pool->solvables; |
b6c702b3 | 1462 | cbdata.subhandle = 0; |
0eb816cc | 1463 | cbdata.dircache = dircache; |
9ed44b97 | 1464 | p = r - fromrepo->pool->solvables; |
72e8b9af MS |
1465 | if (fromrepo->nrepodata == 2) |
1466 | { | |
1467 | Repodata *fromdata = repo_id2repodata(fromrepo, 1); | |
1468 | if (p >= fromdata->start && p < fromdata->end) | |
ac58625b | 1469 | repodata_search(fromdata, p, 0, 0, solvable_copy_cb, &cbdata); |
72e8b9af MS |
1470 | return; |
1471 | } | |
24112339 | 1472 | keyskip = repo_create_keyskip(repo, p, oldkeyskip); |
9ed44b97 MS |
1473 | FOR_REPODATAS(fromrepo, i, data) |
1474 | { | |
1c4b8b63 | 1475 | if (p >= data->start && p < data->end) |
ac58625b | 1476 | repodata_search_keyskip(data, p, 0, 0, keyskip, solvable_copy_cb, &cbdata); |
9ed44b97 | 1477 | } |
18399c39 | 1478 | } |
8f8a9ed5 | 1479 | |
691ceb7b | 1480 | /* used to sort entries by package name that got returned in some database order */ |
554e6cf2 | 1481 | static int |
a6ea1d8f | 1482 | rpmids_sort_cmp(const void *va, const void *vb, void *dp) |
554e6cf2 | 1483 | { |
691ceb7b MS |
1484 | struct rpmdbentry const *a = va, *b = vb; |
1485 | char *namedata = dp; | |
554e6cf2 | 1486 | int r; |
691ceb7b | 1487 | r = strcmp(namedata + a->nameoff, namedata + b->nameoff); |
554e6cf2 MS |
1488 | if (r) |
1489 | return r; | |
691ceb7b | 1490 | return a->rpmdbid - b->rpmdbid; |
554e6cf2 MS |
1491 | } |
1492 | ||
554e6cf2 | 1493 | static int |
a6ea1d8f | 1494 | pkgids_sort_cmp(const void *va, const void *vb, void *dp) |
554e6cf2 | 1495 | { |
a6ea1d8f MS |
1496 | Repo *repo = dp; |
1497 | Pool *pool = repo->pool; | |
554e6cf2 MS |
1498 | Solvable *a = pool->solvables + *(Id *)va; |
1499 | Solvable *b = pool->solvables + *(Id *)vb; | |
1500 | Id *rpmdbid; | |
1501 | ||
1502 | if (a->name != b->name) | |
e2a47f38 | 1503 | return strcmp(pool_id2str(pool, a->name), pool_id2str(pool, b->name)); |
a6ea1d8f MS |
1504 | rpmdbid = repo->rpmdbid; |
1505 | return rpmdbid[(a - pool->solvables) - repo->start] - rpmdbid[(b - pool->solvables) - repo->start]; | |
554e6cf2 MS |
1506 | } |
1507 | ||
1508 | static void | |
1509 | swap_solvables(Repo *repo, Repodata *data, Id pa, Id pb) | |
1510 | { | |
1511 | Pool *pool = repo->pool; | |
1512 | Solvable tmp; | |
1513 | ||
1514 | tmp = pool->solvables[pa]; | |
1515 | pool->solvables[pa] = pool->solvables[pb]; | |
1516 | pool->solvables[pb] = tmp; | |
1517 | if (repo->rpmdbid) | |
1518 | { | |
1519 | Id tmpid = repo->rpmdbid[pa - repo->start]; | |
1520 | repo->rpmdbid[pa - repo->start] = repo->rpmdbid[pb - repo->start]; | |
1521 | repo->rpmdbid[pb - repo->start] = tmpid; | |
1522 | } | |
1523 | /* only works if nothing is already internalized! */ | |
fb73073f MS |
1524 | if (data) |
1525 | repodata_swap_attrs(data, pa, pb); | |
554e6cf2 MS |
1526 | } |
1527 | ||
4ccae385 | 1528 | static void |
1c4b8b63 | 1529 | mkrpmdbcookie(struct stat *st, unsigned char *cookie, int flags) |
4ccae385 | 1530 | { |
1c4b8b63 | 1531 | int f = 0; |
4ccae385 MS |
1532 | memset(cookie, 0, 32); |
1533 | cookie[3] = RPMDB_COOKIE_VERSION; | |
1534 | memcpy(cookie + 16, &st->st_ino, sizeof(st->st_ino)); | |
1535 | memcpy(cookie + 24, &st->st_dev, sizeof(st->st_dev)); | |
1c4b8b63 MS |
1536 | if ((flags & RPM_ADD_WITH_PKGID) != 0) |
1537 | f |= 1; | |
1538 | if ((flags & RPM_ADD_WITH_HDRID) != 0) | |
1539 | f |= 2; | |
1540 | if ((flags & RPM_ADD_WITH_CHANGELOG) != 0) | |
1541 | f |= 4; | |
1542 | if ((flags & RPM_ADD_NO_FILELIST) == 0) | |
1543 | f |= 8; | |
1544 | if ((flags & RPM_ADD_NO_RPMLIBREQS) != 0) | |
1545 | cookie[1] = 1; | |
1546 | cookie[0] = f; | |
4ccae385 MS |
1547 | } |
1548 | ||
8f8a9ed5 | 1549 | /* |
a00b22fc | 1550 | * read rpm db as repo |
60aa6d90 | 1551 | * |
8f8a9ed5 KK |
1552 | */ |
1553 | ||
66e7a252 | 1554 | int |
765ead52 | 1555 | repo_add_rpmdb(Repo *repo, Repo *ref, int flags) |
8f8a9ed5 | 1556 | { |
ee168706 | 1557 | Pool *pool = repo->pool; |
4ccae385 | 1558 | struct stat packagesstat; |
b2fa614d MS |
1559 | unsigned char newcookie[32]; |
1560 | const unsigned char *oldcookie = 0; | |
1561 | Id oldcookietype = 0; | |
1562 | Repodata *data; | |
535f0f37 | 1563 | int count = 0, done = 0; |
691ceb7b MS |
1564 | struct rpmdbstate state; |
1565 | int i; | |
1566 | Solvable *s; | |
1567 | unsigned int now; | |
60aa6d90 | 1568 | |
09f29f70 | 1569 | now = solv_timems(0); |
691ceb7b MS |
1570 | memset(&state, 0, sizeof(state)); |
1571 | state.pool = pool; | |
ce72549c MS |
1572 | if (flags & REPO_USE_ROOTDIR) |
1573 | state.rootdir = solv_strdup(pool_get_rootdir(pool)); | |
8f8a9ed5 | 1574 | |
9bbaf91b | 1575 | data = repo_add_repodata(repo, flags); |
60aa6d90 | 1576 | |
843dc7e1 MS |
1577 | if (ref && !(ref->nsolvables && ref->rpmdbid && ref->pool == repo->pool)) |
1578 | { | |
1579 | if ((flags & RPMDB_EMPTY_REFREPO) != 0) | |
1580 | repo_empty(ref, 1); | |
1581 | ref = 0; | |
1582 | } | |
8f8a9ed5 | 1583 | |
bcedc982 MS |
1584 | if (!opendbenv(&state)) |
1585 | { | |
1586 | solv_free(state.rootdir); | |
1587 | return -1; | |
1588 | } | |
8f8a9ed5 | 1589 | |
4ccae385 | 1590 | /* XXX: should get ro lock of Packages database! */ |
24b4a943 | 1591 | if (stat_database(&state, "Packages", &packagesstat, 1)) |
4ccae385 | 1592 | { |
691ceb7b | 1593 | freestate(&state); |
d9e86c85 | 1594 | return -1; |
4ccae385 | 1595 | } |
1c4b8b63 | 1596 | mkrpmdbcookie(&packagesstat, newcookie, flags); |
b4385f9f | 1597 | repodata_set_bin_checksum(data, SOLVID_META, REPOSITORY_RPMDBCOOKIE, REPOKEY_TYPE_SHA256, newcookie); |
4ccae385 | 1598 | |
b2fa614d | 1599 | if (ref) |
b4385f9f | 1600 | oldcookie = repo_lookup_bin_checksum(ref, SOLVID_META, REPOSITORY_RPMDBCOOKIE, &oldcookietype); |
b2fa614d | 1601 | if (!ref || !oldcookie || oldcookietype != REPOKEY_TYPE_SHA256 || memcmp(oldcookie, newcookie, 32) != 0) |
8f8a9ed5 | 1602 | { |
0c6bd47a | 1603 | int solvstart = 0, solvend = 0; |
691ceb7b | 1604 | Id dbid; |
535f0f37 | 1605 | |
843dc7e1 MS |
1606 | if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) |
1607 | repo_empty(ref, 1); /* get it out of the way */ | |
535f0f37 | 1608 | if ((flags & RPMDB_REPORT_PROGRESS) != 0) |
ce72549c | 1609 | count = count_headers(&state); |
691ceb7b | 1610 | if (!openpkgdb(&state)) |
8f8a9ed5 | 1611 | { |
691ceb7b | 1612 | freestate(&state); |
5702cc43 | 1613 | return -1; |
8f8a9ed5 | 1614 | } |
ae214a65 | 1615 | if (pkgdb_cursor_open(&state)) |
8f8a9ed5 | 1616 | { |
691ceb7b | 1617 | freestate(&state); |
ae214a65 | 1618 | return -1; |
8f8a9ed5 | 1619 | } |
8f8a9ed5 | 1620 | i = 0; |
7a25bd3b | 1621 | s = 0; |
ae214a65 | 1622 | while ((dbid = pkgdb_cursor_getrpm(&state)) != 0) |
8f8a9ed5 | 1623 | { |
691ceb7b MS |
1624 | if (dbid == -1) |
1625 | { | |
ae214a65 | 1626 | pkgdb_cursor_close(&state); |
691ceb7b MS |
1627 | freestate(&state); |
1628 | return -1; | |
1629 | } | |
7a25bd3b | 1630 | if (!s) |
0c6bd47a MS |
1631 | { |
1632 | s = pool_id2solvable(pool, repo_add_solvable(repo)); | |
1633 | if (!solvstart) | |
1634 | solvstart = s - pool->solvables; | |
691ceb7b | 1635 | solvend = s - pool->solvables + 1; |
8f8a9ed5 | 1636 | } |
691ceb7b MS |
1637 | if (!repo->rpmdbid) |
1638 | repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); | |
f0a93ad1 | 1639 | repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; |
49d6cbd2 | 1640 | if (rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS)) |
7a25bd3b | 1641 | { |
7a25bd3b MS |
1642 | i++; |
1643 | s = 0; | |
1644 | } | |
1645 | else | |
1646 | { | |
19ff58e2 MM |
1647 | /* We can reuse this solvable, but make sure it's still |
1648 | associated with this repo. */ | |
1649 | memset(s, 0, sizeof(*s)); | |
1650 | s->repo = repo; | |
7a25bd3b | 1651 | } |
535f0f37 MS |
1652 | if ((flags & RPMDB_REPORT_PROGRESS) != 0) |
1653 | { | |
1654 | if (done < count) | |
1655 | done++; | |
1656 | if (done < count && (done - 1) * 100 / count != done * 100 / count) | |
09f29f70 | 1657 | pool_debug(pool, SOLV_ERROR, "%%%% %d\n", done * 100 / count); |
535f0f37 | 1658 | } |
7a25bd3b | 1659 | } |
ae214a65 | 1660 | pkgdb_cursor_close(&state); |
7a25bd3b MS |
1661 | if (s) |
1662 | { | |
1663 | /* oops, could not reuse. free it instead */ | |
a2bae081 | 1664 | s = solvable_free(s, 1); |
0c6bd47a | 1665 | solvend--; |
8f8a9ed5 | 1666 | } |
0c6bd47a MS |
1667 | /* now sort all solvables in the new solvstart..solvend block */ |
1668 | if (solvend - solvstart > 1) | |
554e6cf2 | 1669 | { |
691ceb7b | 1670 | Id *pkgids = solv_malloc2(solvend - solvstart, sizeof(Id)); |
0c6bd47a MS |
1671 | for (i = solvstart; i < solvend; i++) |
1672 | pkgids[i - solvstart] = i; | |
09f29f70 | 1673 | solv_sort(pkgids, solvend - solvstart, sizeof(Id), pkgids_sort_cmp, repo); |
554e6cf2 | 1674 | /* adapt order */ |
0c6bd47a | 1675 | for (i = solvstart; i < solvend; i++) |
554e6cf2 | 1676 | { |
0c6bd47a | 1677 | int j = pkgids[i - solvstart]; |
554e6cf2 | 1678 | while (j < i) |
0c6bd47a | 1679 | j = pkgids[i - solvstart] = pkgids[j - solvstart]; |
554e6cf2 | 1680 | if (j != i) |
b2fa614d | 1681 | swap_solvables(repo, data, i, j); |
554e6cf2 | 1682 | } |
09f29f70 | 1683 | solv_free(pkgids); |
554e6cf2 | 1684 | } |
8f8a9ed5 KK |
1685 | } |
1686 | else | |
1687 | { | |
b19f33c9 | 1688 | Id *dircache; |
24112339 | 1689 | Id *oldkeyskip = 0; |
691ceb7b MS |
1690 | struct rpmdbentry *entries = 0, *rp; |
1691 | int nentries = 0; | |
1692 | char *namedata = 0; | |
1693 | unsigned int refmask, h; | |
1694 | Id id, *refhash; | |
1695 | int res; | |
0eb816cc | 1696 | |
691ceb7b | 1697 | /* get ids of installed rpms */ |
0d887d16 | 1698 | entries = getinstalledrpmdbids(&state, "Name", 0, &nentries, &namedata, flags & RPMDB_KEEP_GPG_PUBKEY); |
691ceb7b | 1699 | if (!entries) |
8f8a9ed5 | 1700 | { |
691ceb7b | 1701 | freestate(&state); |
5702cc43 | 1702 | return -1; |
8f8a9ed5 | 1703 | } |
8f8a9ed5 | 1704 | |
691ceb7b MS |
1705 | /* sort by name */ |
1706 | if (nentries > 1) | |
1707 | solv_sort(entries, nentries, sizeof(*entries), rpmids_sort_cmp, namedata); | |
8f8a9ed5 | 1708 | |
554e6cf2 MS |
1709 | /* create hash from dbid to ref */ |
1710 | refmask = mkmask(ref->nsolvables); | |
09f29f70 | 1711 | refhash = solv_calloc(refmask + 1, sizeof(Id)); |
f0a93ad1 | 1712 | for (i = 0; i < ref->end - ref->start; i++) |
8f8a9ed5 | 1713 | { |
f0a93ad1 MS |
1714 | if (!ref->rpmdbid[i]) |
1715 | continue; | |
554e6cf2 MS |
1716 | h = ref->rpmdbid[i] & refmask; |
1717 | while (refhash[h]) | |
1718 | h = (h + 317) & refmask; | |
1719 | refhash[h] = i + 1; /* make it non-zero */ | |
8f8a9ed5 | 1720 | } |
60aa6d90 | 1721 | |
535f0f37 MS |
1722 | /* count the misses, they will cost us time */ |
1723 | if ((flags & RPMDB_REPORT_PROGRESS) != 0) | |
1724 | { | |
691ceb7b | 1725 | for (i = 0, rp = entries; i < nentries; i++, rp++) |
535f0f37 | 1726 | { |
535f0f37 MS |
1727 | if (refhash) |
1728 | { | |
691ceb7b | 1729 | Id dbid = rp->rpmdbid; |
535f0f37 MS |
1730 | h = dbid & refmask; |
1731 | while ((id = refhash[h])) | |
1732 | { | |
1733 | if (ref->rpmdbid[id - 1] == dbid) | |
1734 | break; | |
1735 | h = (h + 317) & refmask; | |
1736 | } | |
1737 | if (id) | |
1738 | continue; | |
1739 | } | |
1740 | count++; | |
1741 | } | |
1742 | } | |
7a25bd3b | 1743 | |
843dc7e1 MS |
1744 | if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) |
1745 | s = pool_id2solvable(pool, repo_add_solvable_block_before(repo, nentries, ref)); | |
1746 | else | |
1747 | s = pool_id2solvable(pool, repo_add_solvable_block(repo, nentries)); | |
f0a93ad1 MS |
1748 | if (!repo->rpmdbid) |
1749 | repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); | |
7a25bd3b | 1750 | |
b19f33c9 | 1751 | dircache = repodata_create_dirtranscache(data); |
691ceb7b | 1752 | for (i = 0, rp = entries; i < nentries; i++, rp++, s++) |
8f8a9ed5 | 1753 | { |
691ceb7b | 1754 | Id dbid = rp->rpmdbid; |
24112339 | 1755 | repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; |
8f8a9ed5 KK |
1756 | if (refhash) |
1757 | { | |
1758 | h = dbid & refmask; | |
1759 | while ((id = refhash[h])) | |
1760 | { | |
1761 | if (ref->rpmdbid[id - 1] == dbid) | |
1762 | break; | |
1763 | h = (h + 317) & refmask; | |
1764 | } | |
1765 | if (id) | |
1766 | { | |
1767 | Solvable *r = ref->pool->solvables + ref->start + (id - 1); | |
f0a93ad1 MS |
1768 | if (r->repo == ref) |
1769 | { | |
24112339 | 1770 | solvable_copy(s, r, data, dircache, &oldkeyskip); |
f0a93ad1 MS |
1771 | continue; |
1772 | } | |
8f8a9ed5 KK |
1773 | } |
1774 | } | |
49d6cbd2 | 1775 | res = getrpm_dbid(&state, dbid); |
691ceb7b | 1776 | if (res <= 0) |
8f8a9ed5 | 1777 | { |
691ceb7b | 1778 | if (!res) |
c8beaece | 1779 | pool_error(pool, -1, "inconsistent rpm database, key %d not found. run 'rpm --rebuilddb' to fix.", dbid); |
691ceb7b MS |
1780 | freestate(&state); |
1781 | solv_free(entries); | |
1782 | solv_free(namedata); | |
1783 | solv_free(refhash); | |
b19f33c9 | 1784 | dircache = repodata_free_dirtranscache(dircache); |
691ceb7b | 1785 | return -1; |
8f8a9ed5 | 1786 | } |
49d6cbd2 | 1787 | rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS); |
535f0f37 MS |
1788 | if ((flags & RPMDB_REPORT_PROGRESS) != 0) |
1789 | { | |
1790 | if (done < count) | |
1791 | done++; | |
1792 | if (done < count && (done - 1) * 100 / count != done * 100 / count) | |
09f29f70 | 1793 | pool_debug(pool, SOLV_ERROR, "%%%% %d\n", done * 100 / count); |
535f0f37 | 1794 | } |
8f8a9ed5 | 1795 | } |
b19f33c9 | 1796 | dircache = repodata_free_dirtranscache(dircache); |
8f8a9ed5 | 1797 | |
24112339 | 1798 | solv_free(oldkeyskip); |
691ceb7b MS |
1799 | solv_free(entries); |
1800 | solv_free(namedata); | |
1801 | solv_free(refhash); | |
843dc7e1 MS |
1802 | if (ref && (flags & RPMDB_EMPTY_REFREPO) != 0) |
1803 | repo_empty(ref, 1); | |
8f8a9ed5 | 1804 | } |
691ceb7b MS |
1805 | |
1806 | freestate(&state); | |
a9f18c80 MS |
1807 | if (!(flags & REPO_NO_INTERNALIZE)) |
1808 | repodata_internalize(data); | |
535f0f37 | 1809 | if ((flags & RPMDB_REPORT_PROGRESS) != 0) |
09f29f70 MS |
1810 | pool_debug(pool, SOLV_ERROR, "%%%% 100\n"); |
1811 | POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_rpmdb took %d ms\n", solv_timems(now)); | |
1812 | POOL_DEBUG(SOLV_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); | |
fb73073f | 1813 | POOL_DEBUG(SOLV_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", repodata_memused(data)/1024, repo->idarraysize / (int)(1024/sizeof(Id))); |
66e7a252 | 1814 | return 0; |
c49cb71a MS |
1815 | } |
1816 | ||
843dc7e1 MS |
1817 | int |
1818 | repo_add_rpmdb_reffp(Repo *repo, FILE *fp, int flags) | |
1819 | { | |
1820 | int res; | |
1821 | Repo *ref = 0; | |
1822 | ||
1823 | if (!fp) | |
1824 | return repo_add_rpmdb(repo, 0, flags); | |
1825 | ref = repo_create(repo->pool, "add_rpmdb_reffp"); | |
1826 | if (repo_add_solv(ref, fp, 0) != 0) | |
1827 | { | |
1828 | repo_free(ref, 1); | |
1829 | ref = 0; | |
1830 | } | |
1831 | if (ref && ref->start == ref->end) | |
1832 | { | |
1833 | repo_free(ref, 1); | |
1834 | ref = 0; | |
1835 | } | |
1836 | if (ref) | |
1837 | repo_disable_paging(ref); | |
1838 | res = repo_add_rpmdb(repo, ref, flags | RPMDB_EMPTY_REFREPO); | |
1839 | if (ref) | |
1840 | repo_free(ref, 1); | |
1841 | return res; | |
1842 | } | |
52e01fb8 | 1843 | |
7a9c082b | 1844 | #endif /* ENABLE_RPMDB */ |
7173e5d6 | 1845 | |
64af5496 MS |
1846 | Id |
1847 | repo_add_rpm(Repo *repo, const char *rpm, int flags) | |
3bf73c63 | 1848 | { |
47fbaa2a | 1849 | unsigned int sigdsize, sigcnt, sigpad, l; |
3bf73c63 MS |
1850 | Pool *pool = repo->pool; |
1851 | Solvable *s; | |
47fbaa2a | 1852 | struct rpmdbstate state; |
554e6cf2 | 1853 | char *payloadformat; |
3bf73c63 MS |
1854 | FILE *fp; |
1855 | unsigned char lead[4096]; | |
d7d93d0f | 1856 | int headerstart, headerend; |
a8c85b1c | 1857 | struct stat stb; |
b2fa614d | 1858 | Repodata *data; |
5ed9867b | 1859 | unsigned char pkgid[16]; |
966d89be MS |
1860 | unsigned char leadsigid[16]; |
1861 | unsigned char hdrid[32]; | |
1862 | int pkgidtype, leadsigidtype, hdridtype; | |
6df0daf4 | 1863 | Id chksumtype = 0; |
1aed650c MS |
1864 | Chksum *chksumh = 0; |
1865 | Chksum *leadsigchksumh = 0; | |
b2fa614d | 1866 | |
9bbaf91b | 1867 | data = repo_add_repodata(repo, flags); |
3bf73c63 | 1868 | |
6df0daf4 MS |
1869 | if ((flags & RPM_ADD_WITH_SHA256SUM) != 0) |
1870 | chksumtype = REPOKEY_TYPE_SHA256; | |
1871 | else if ((flags & RPM_ADD_WITH_SHA1SUM) != 0) | |
1872 | chksumtype = REPOKEY_TYPE_SHA1; | |
64af5496 | 1873 | |
47fbaa2a | 1874 | /* open rpm */ |
765ead52 | 1875 | if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, rpm) : rpm, "r")) == 0) |
3bf73c63 | 1876 | { |
64af5496 MS |
1877 | pool_error(pool, -1, "%s: %s", rpm, strerror(errno)); |
1878 | return 0; | |
1879 | } | |
1880 | if (fstat(fileno(fp), &stb)) | |
1881 | { | |
1882 | pool_error(pool, -1, "fstat: %s", strerror(errno)); | |
1883 | fclose(fp); | |
1884 | return 0; | |
1885 | } | |
47fbaa2a MS |
1886 | |
1887 | /* setup state */ | |
1888 | memset(&state, 0, sizeof(state)); | |
1889 | state.pool = pool; | |
1890 | ||
1891 | /* process lead */ | |
64af5496 MS |
1892 | if (chksumtype) |
1893 | chksumh = solv_chksum_create(chksumtype); | |
966d89be MS |
1894 | if ((flags & RPM_ADD_WITH_LEADSIGID) != 0) |
1895 | leadsigchksumh = solv_chksum_create(REPOKEY_TYPE_MD5); | |
64af5496 MS |
1896 | if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) |
1897 | { | |
1898 | pool_error(pool, -1, "%s: not a rpm", rpm); | |
98a75959 JR |
1899 | solv_chksum_free(leadsigchksumh, NULL); |
1900 | solv_chksum_free(chksumh, NULL); | |
64af5496 MS |
1901 | fclose(fp); |
1902 | return 0; | |
1903 | } | |
1904 | if (chksumh) | |
1905 | solv_chksum_add(chksumh, lead, 96 + 16); | |
966d89be MS |
1906 | if (leadsigchksumh) |
1907 | solv_chksum_add(leadsigchksumh, lead, 96 + 16); | |
47fbaa2a MS |
1908 | |
1909 | /* process signature header */ | |
64af5496 MS |
1910 | if (lead[78] != 0 || lead[79] != 5) |
1911 | { | |
1912 | pool_error(pool, -1, "%s: not a rpm v5 header", rpm); | |
98a75959 JR |
1913 | solv_chksum_free(leadsigchksumh, NULL); |
1914 | solv_chksum_free(chksumh, NULL); | |
64af5496 MS |
1915 | fclose(fp); |
1916 | return 0; | |
1917 | } | |
1918 | if (getu32(lead + 96) != 0x8eade801) | |
1919 | { | |
1920 | pool_error(pool, -1, "%s: bad signature header", rpm); | |
98a75959 JR |
1921 | solv_chksum_free(leadsigchksumh, NULL); |
1922 | solv_chksum_free(chksumh, NULL); | |
64af5496 MS |
1923 | fclose(fp); |
1924 | return 0; | |
1925 | } | |
1926 | sigcnt = getu32(lead + 96 + 8); | |
1927 | sigdsize = getu32(lead + 96 + 12); | |
78a876b1 | 1928 | if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE) |
64af5496 MS |
1929 | { |
1930 | pool_error(pool, -1, "%s: bad signature header", rpm); | |
98a75959 JR |
1931 | solv_chksum_free(leadsigchksumh, NULL); |
1932 | solv_chksum_free(chksumh, NULL); | |
64af5496 MS |
1933 | fclose(fp); |
1934 | return 0; | |
1935 | } | |
47fbaa2a MS |
1936 | sigpad = sigdsize & 7 ? 8 - (sigdsize & 7) : 0; |
1937 | headerstart = 96 + 16 + sigcnt * 16 + sigdsize + sigpad; | |
966d89be MS |
1938 | pkgidtype = leadsigidtype = hdridtype = 0; |
1939 | if ((flags & (RPM_ADD_WITH_PKGID | RPM_ADD_WITH_HDRID)) != 0) | |
64af5496 | 1940 | { |
aa4df21e | 1941 | if (!headfromfp(&state, rpm, fp, lead + 96, sigcnt, sigdsize, sigpad, chksumh, leadsigchksumh)) |
ae214a65 | 1942 | { |
98a75959 JR |
1943 | solv_chksum_free(leadsigchksumh, NULL); |
1944 | solv_chksum_free(chksumh, NULL); | |
ae214a65 MS |
1945 | fclose(fp); |
1946 | return 0; | |
1947 | } | |
966d89be MS |
1948 | if ((flags & RPM_ADD_WITH_PKGID) != 0) |
1949 | { | |
1950 | unsigned char *chksum; | |
1951 | unsigned int chksumsize; | |
47fbaa2a | 1952 | chksum = headbinary(state.rpmhead, SIGTAG_MD5, &chksumsize); |
966d89be MS |
1953 | if (chksum && chksumsize == 16) |
1954 | { | |
1955 | pkgidtype = REPOKEY_TYPE_MD5; | |
1956 | memcpy(pkgid, chksum, 16); | |
1957 | } | |
1958 | } | |
1959 | if ((flags & RPM_ADD_WITH_HDRID) != 0) | |
3bf73c63 | 1960 | { |
47fbaa2a | 1961 | const char *str = headstring(state.rpmhead, TAG_SHA1HEADER); |
966d89be MS |
1962 | if (str && strlen(str) == 40) |
1963 | { | |
1964 | if (solv_hex2bin(&str, hdrid, 20) == 20) | |
1965 | hdridtype = REPOKEY_TYPE_SHA1; | |
1966 | } | |
1967 | else if (str && strlen(str) == 64) | |
1968 | { | |
1969 | if (solv_hex2bin(&str, hdrid, 32) == 32) | |
1970 | hdridtype = REPOKEY_TYPE_SHA256; | |
1971 | } | |
3bf73c63 | 1972 | } |
64af5496 MS |
1973 | } |
1974 | else | |
1975 | { | |
1976 | /* just skip the signature header */ | |
47fbaa2a MS |
1977 | unsigned int len = sigcnt * 16 + sigdsize + sigpad; |
1978 | while (len) | |
3bf73c63 | 1979 | { |
47fbaa2a | 1980 | l = len > 4096 ? 4096 : len; |
64af5496 | 1981 | if (fread(lead, l, 1, fp) != 1) |
3bf73c63 | 1982 | { |
64af5496 | 1983 | pool_error(pool, -1, "%s: unexpected EOF", rpm); |
98a75959 JR |
1984 | solv_chksum_free(leadsigchksumh, NULL); |
1985 | solv_chksum_free(chksumh, NULL); | |
3bf73c63 | 1986 | fclose(fp); |
64af5496 | 1987 | return 0; |
3bf73c63 | 1988 | } |
6df0daf4 | 1989 | if (chksumh) |
64af5496 | 1990 | solv_chksum_add(chksumh, lead, l); |
966d89be MS |
1991 | if (leadsigchksumh) |
1992 | solv_chksum_add(leadsigchksumh, lead, l); | |
47fbaa2a | 1993 | len -= l; |
5ed9867b | 1994 | } |
64af5496 | 1995 | } |
966d89be MS |
1996 | if (leadsigchksumh) |
1997 | { | |
1998 | leadsigchksumh = solv_chksum_free(leadsigchksumh, leadsigid); | |
1999 | leadsigidtype = REPOKEY_TYPE_MD5; | |
2000 | } | |
47fbaa2a MS |
2001 | |
2002 | /* process main header */ | |
64af5496 MS |
2003 | if (fread(lead, 16, 1, fp) != 1) |
2004 | { | |
2005 | pool_error(pool, -1, "%s: unexpected EOF", rpm); | |
98a75959 | 2006 | solv_chksum_free(chksumh, NULL); |
3bf73c63 | 2007 | fclose(fp); |
64af5496 MS |
2008 | return 0; |
2009 | } | |
2010 | if (chksumh) | |
2011 | solv_chksum_add(chksumh, lead, 16); | |
2012 | if (getu32(lead) != 0x8eade801) | |
2013 | { | |
2014 | pool_error(pool, -1, "%s: bad header", rpm); | |
98a75959 | 2015 | solv_chksum_free(chksumh, NULL); |
64af5496 MS |
2016 | fclose(fp); |
2017 | return 0; | |
2018 | } | |
2019 | sigcnt = getu32(lead + 8); | |
2020 | sigdsize = getu32(lead + 12); | |
78a876b1 | 2021 | if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE) |
64af5496 MS |
2022 | { |
2023 | pool_error(pool, -1, "%s: bad header", rpm); | |
98a75959 | 2024 | solv_chksum_free(chksumh, NULL); |
64af5496 MS |
2025 | fclose(fp); |
2026 | return 0; | |
2027 | } | |
47fbaa2a | 2028 | headerend = headerstart + 16 + sigdsize + sigcnt * 16; |
ae214a65 | 2029 | |
aa4df21e | 2030 | if (!headfromfp(&state, rpm, fp, lead, sigcnt, sigdsize, 0, chksumh, 0)) |
ae214a65 | 2031 | { |
98a75959 | 2032 | solv_chksum_free(chksumh, NULL); |
ae214a65 MS |
2033 | fclose(fp); |
2034 | return 0; | |
2035 | } | |
47fbaa2a | 2036 | if (headexists(state.rpmhead, TAG_PATCHESNAME)) |
64af5496 MS |
2037 | { |
2038 | /* this is a patch rpm, ignore */ | |
2039 | pool_error(pool, -1, "%s: is patch rpm", rpm); | |
2040 | fclose(fp); | |
966d89be | 2041 | solv_chksum_free(chksumh, 0); |
47fbaa2a | 2042 | headfree(state.rpmhead); |
64af5496 MS |
2043 | return 0; |
2044 | } | |
47fbaa2a | 2045 | payloadformat = headstring(state.rpmhead, TAG_PAYLOADFORMAT); |
64af5496 MS |
2046 | if (payloadformat && !strcmp(payloadformat, "drpm")) |
2047 | { | |
2048 | /* this is a delta rpm */ | |
2049 | pool_error(pool, -1, "%s: is delta rpm", rpm); | |
2050 | fclose(fp); | |
966d89be | 2051 | solv_chksum_free(chksumh, 0); |
47fbaa2a | 2052 | headfree(state.rpmhead); |
64af5496 MS |
2053 | return 0; |
2054 | } | |
2055 | if (chksumh) | |
2056 | while ((l = fread(lead, 1, sizeof(lead), fp)) > 0) | |
2057 | solv_chksum_add(chksumh, lead, l); | |
2058 | fclose(fp); | |
2059 | s = pool_id2solvable(pool, repo_add_solvable(repo)); | |
47fbaa2a | 2060 | if (!rpmhead2solv(pool, repo, data, s, state.rpmhead, flags & ~(RPM_ADD_WITH_HDRID | RPM_ADD_WITH_PKGID))) |
64af5496 | 2061 | { |
a2bae081 | 2062 | s = solvable_free(s, 1); |
966d89be | 2063 | solv_chksum_free(chksumh, 0); |
47fbaa2a | 2064 | headfree(state.rpmhead); |
64af5496 MS |
2065 | return 0; |
2066 | } | |
7c4bf2cd MS |
2067 | if (!(flags & REPO_NO_LOCATION)) |
2068 | repodata_set_location(data, s - pool->solvables, 0, 0, rpm); | |
64af5496 MS |
2069 | if (S_ISREG(stb.st_mode)) |
2070 | repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size); | |
2071 | repodata_set_num(data, s - pool->solvables, SOLVABLE_HEADEREND, headerend); | |
966d89be MS |
2072 | if (pkgidtype) |
2073 | repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, pkgidtype, pkgid); | |
2074 | if (hdridtype) | |
2075 | repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_HDRID, hdridtype, hdrid); | |
2076 | if (leadsigidtype) | |
2077 | repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_LEADSIGID, leadsigidtype, leadsigid); | |
64af5496 MS |
2078 | if (chksumh) |
2079 | { | |
2080 | repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, chksumtype, solv_chksum_get(chksumh, 0)); | |
2081 | chksumh = solv_chksum_free(chksumh, 0); | |
2082 | } | |
47fbaa2a | 2083 | headfree(state.rpmhead); |
b2fa614d MS |
2084 | if (!(flags & REPO_NO_INTERNALIZE)) |
2085 | repodata_internalize(data); | |
64af5496 | 2086 | return s - pool->solvables; |
bbb81edb MS |
2087 | } |
2088 | ||
d5597d3b MS |
2089 | Id |
2090 | repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags) | |
2091 | { | |
2092 | Pool *pool = repo->pool; | |
2093 | Repodata *data; | |
2094 | RpmHead *rpmhead = rpmhandle; | |
2095 | Solvable *s; | |
2096 | char *payloadformat; | |
2097 | ||
2098 | data = repo_add_repodata(repo, flags); | |
2099 | if (headexists(rpmhead, TAG_PATCHESNAME)) | |
2100 | { | |
2101 | pool_error(pool, -1, "is a patch rpm"); | |
2102 | return 0; | |
2103 | } | |
2104 | payloadformat = headstring(rpmhead, TAG_PAYLOADFORMAT); | |
2105 | if (payloadformat && !strcmp(payloadformat, "drpm")) | |
2106 | { | |
2107 | /* this is a delta rpm */ | |
2108 | pool_error(pool, -1, "is a delta rpm"); | |
2109 | return 0; | |
2110 | } | |
2111 | s = pool_id2solvable(pool, repo_add_solvable(repo)); | |
49d6cbd2 | 2112 | if (!rpmhead2solv(pool, repo, data, s, rpmhead, flags)) |
d5597d3b | 2113 | { |
a2bae081 | 2114 | s = solvable_free(s, 1); |
d5597d3b MS |
2115 | return 0; |
2116 | } | |
2117 | if (!(flags & REPO_NO_INTERNALIZE)) | |
2118 | repodata_internalize(data); | |
2119 | return s - pool->solvables; | |
2120 | } | |
2121 | ||
3e003c06 MS |
2122 | static inline void |
2123 | linkhash(const char *lt, char *hash) | |
2124 | { | |
2125 | unsigned int r = 0; | |
2126 | const unsigned char *str = (const unsigned char *)lt; | |
2127 | int l, c; | |
2128 | ||
2129 | l = strlen(lt); | |
2130 | while ((c = *str++) != 0) | |
2131 | r += (r << 3) + c; | |
261b19e8 | 2132 | sprintf(hash, "%08x%08x%08x%08x", r, l, 0, 0); |
3e003c06 MS |
2133 | } |
2134 | ||
2135 | void | |
261b19e8 | 2136 | rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, struct filelistinfo *), void *cbdata) |
3e003c06 MS |
2137 | { |
2138 | RpmHead *rpmhead = rpmhandle; | |
2139 | char **bn; | |
2140 | char **dn; | |
2141 | char **md = 0; | |
2142 | char **lt = 0; | |
350209a4 MS |
2143 | uint32_t *di, diidx; |
2144 | uint32_t *co = 0; | |
2145 | uint32_t *ff = 0; | |
2146 | uint16_t *fm; | |
87bfd053 MS |
2147 | unsigned int lastdir; |
2148 | int lastdirl; | |
3e003c06 MS |
2149 | int cnt, dcnt, cnt2; |
2150 | int i, l1, l; | |
2151 | char *space = 0; | |
2152 | int spacen = 0; | |
261b19e8 MS |
2153 | char md5[33]; |
2154 | struct filelistinfo info; | |
3e003c06 MS |
2155 | |
2156 | dn = headstringarray(rpmhead, TAG_DIRNAMES, &dcnt); | |
2157 | if (!dn) | |
2158 | return; | |
2159 | if ((flags & RPM_ITERATE_FILELIST_ONLYDIRS) != 0) | |
2160 | { | |
2161 | for (i = 0; i < dcnt; i++) | |
261b19e8 | 2162 | (*cb)(cbdata, dn[i], 0); |
09f29f70 | 2163 | solv_free(dn); |
3e003c06 MS |
2164 | return; |
2165 | } | |
2166 | bn = headstringarray(rpmhead, TAG_BASENAMES, &cnt); | |
2167 | if (!bn) | |
2168 | { | |
09f29f70 | 2169 | solv_free(dn); |
3e003c06 MS |
2170 | return; |
2171 | } | |
2172 | di = headint32array(rpmhead, TAG_DIRINDEXES, &cnt2); | |
2173 | if (!di || cnt != cnt2) | |
2174 | { | |
09f29f70 MS |
2175 | solv_free(di); |
2176 | solv_free(bn); | |
2177 | solv_free(dn); | |
3e003c06 MS |
2178 | return; |
2179 | } | |
2180 | fm = headint16array(rpmhead, TAG_FILEMODES, &cnt2); | |
2181 | if (!fm || cnt != cnt2) | |
2182 | { | |
09f29f70 MS |
2183 | solv_free(fm); |
2184 | solv_free(di); | |
2185 | solv_free(bn); | |
2186 | solv_free(dn); | |
3e003c06 MS |
2187 | return; |
2188 | } | |
2189 | if ((flags & RPM_ITERATE_FILELIST_WITHMD5) != 0) | |
2190 | { | |
2191 | md = headstringarray(rpmhead, TAG_FILEMD5S, &cnt2); | |
2192 | if (!md || cnt != cnt2) | |
2193 | { | |
09f29f70 MS |
2194 | solv_free(md); |
2195 | solv_free(fm); | |
2196 | solv_free(di); | |
2197 | solv_free(bn); | |
2198 | solv_free(dn); | |
3e003c06 MS |
2199 | return; |
2200 | } | |
2201 | } | |
0686141a MS |
2202 | if ((flags & RPM_ITERATE_FILELIST_WITHCOL) != 0) |
2203 | { | |
2204 | co = headint32array(rpmhead, TAG_FILECOLORS, &cnt2); | |
de623fb8 | 2205 | if (co && cnt != cnt2) |
0686141a | 2206 | { |
09f29f70 MS |
2207 | solv_free(co); |
2208 | solv_free(md); | |
2209 | solv_free(fm); | |
2210 | solv_free(di); | |
2211 | solv_free(bn); | |
2212 | solv_free(dn); | |
0686141a MS |
2213 | return; |
2214 | } | |
2215 | } | |
55f5371d MS |
2216 | if ((flags & RPM_ITERATE_FILELIST_NOGHOSTS) != 0) |
2217 | { | |
2218 | ff = headint32array(rpmhead, TAG_FILEFLAGS, &cnt2); | |
2219 | if (!ff || cnt != cnt2) | |
2220 | { | |
09f29f70 MS |
2221 | solv_free(ff); |
2222 | solv_free(co); | |
2223 | solv_free(md); | |
2224 | solv_free(fm); | |
2225 | solv_free(di); | |
2226 | solv_free(bn); | |
2227 | solv_free(dn); | |
55f5371d MS |
2228 | return; |
2229 | } | |
2230 | } | |
87bfd053 MS |
2231 | lastdir = dcnt; |
2232 | lastdirl = 0; | |
261b19e8 | 2233 | memset(&info, 0, sizeof(info)); |
3e003c06 MS |
2234 | for (i = 0; i < cnt; i++) |
2235 | { | |
55f5371d MS |
2236 | if (ff && (ff[i] & FILEFLAG_GHOST) != 0) |
2237 | continue; | |
87bfd053 MS |
2238 | diidx = di[i]; |
2239 | if (diidx >= dcnt) | |
3e003c06 | 2240 | continue; |
87bfd053 | 2241 | l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]); |
3e003c06 MS |
2242 | l = l1 + strlen(bn[i]) + 1; |
2243 | if (l > spacen) | |
2244 | { | |
2245 | spacen = l + 16; | |
09f29f70 | 2246 | space = solv_realloc(space, spacen); |
3e003c06 | 2247 | } |
87bfd053 MS |
2248 | if (lastdir != diidx) |
2249 | { | |
2250 | strcpy(space, dn[diidx]); | |
2251 | lastdir = diidx; | |
2252 | lastdirl = l1; | |
2253 | } | |
3e003c06 | 2254 | strcpy(space + l1, bn[i]); |
261b19e8 MS |
2255 | info.diridx = diidx; |
2256 | info.dirlen = l1; | |
2257 | if (fm) | |
2258 | info.mode = fm[i]; | |
3e003c06 MS |
2259 | if (md) |
2260 | { | |
261b19e8 MS |
2261 | info.digest = md[i]; |
2262 | if (fm && S_ISLNK(fm[i])) | |
3e003c06 | 2263 | { |
261b19e8 | 2264 | info.digest = 0; |
3e003c06 MS |
2265 | if (!lt) |
2266 | { | |
2267 | lt = headstringarray(rpmhead, TAG_FILELINKTOS, &cnt2); | |
2268 | if (cnt != cnt2) | |
09f29f70 | 2269 | lt = solv_free(lt); |
3e003c06 MS |
2270 | } |
2271 | if (lt) | |
2272 | { | |
2273 | linkhash(lt[i], md5); | |
261b19e8 | 2274 | info.digest = md5; |
3e003c06 MS |
2275 | } |
2276 | } | |
261b19e8 | 2277 | if (!info.digest) |
0686141a | 2278 | { |
55f5371d | 2279 | sprintf(md5, "%08x%08x%08x%08x", (fm[i] >> 12) & 65535, 0, 0, 0); |
261b19e8 | 2280 | info.digest = md5; |
0686141a | 2281 | } |
3e003c06 | 2282 | } |
de623fb8 | 2283 | info.color = co ? co[i] : 0; |
261b19e8 | 2284 | (*cb)(cbdata, space, &info); |
3e003c06 | 2285 | } |
09f29f70 MS |
2286 | solv_free(space); |
2287 | solv_free(lt); | |
2288 | solv_free(md); | |
2289 | solv_free(fm); | |
2290 | solv_free(di); | |
2291 | solv_free(bn); | |
2292 | solv_free(dn); | |
2293 | solv_free(co); | |
2294 | solv_free(ff); | |
3e003c06 MS |
2295 | } |
2296 | ||
99ceec3e MS |
2297 | char * |
2298 | rpm_query(void *rpmhandle, Id what) | |
2299 | { | |
2300 | const char *name, *arch, *sourcerpm; | |
2301 | char *evr, *r; | |
2302 | int l; | |
2303 | ||
2304 | RpmHead *rpmhead = rpmhandle; | |
2305 | r = 0; | |
2306 | switch (what) | |
2307 | { | |
545fd9a1 | 2308 | case 0: /* return canonical name of rpm */ |
99ceec3e MS |
2309 | name = headstring(rpmhead, TAG_NAME); |
2310 | if (!name) | |
2311 | name = ""; | |
2312 | sourcerpm = headstring(rpmhead, TAG_SOURCERPM); | |
6c8ee8bc | 2313 | if (sourcerpm || !(headexists(rpmhead, TAG_SOURCEPACKAGE) || headissourceheuristic(rpmhead))) |
99ceec3e MS |
2314 | arch = headstring(rpmhead, TAG_ARCH); |
2315 | else | |
2316 | { | |
2317 | if (headexists(rpmhead, TAG_NOSOURCE) || headexists(rpmhead, TAG_NOPATCH)) | |
2318 | arch = "nosrc"; | |
2319 | else | |
2320 | arch = "src"; | |
2321 | } | |
2322 | if (!arch) | |
2323 | arch = "noarch"; | |
2324 | evr = headtoevr(rpmhead); | |
cc687652 | 2325 | l = strlen(name) + 1 + strlen(evr ? evr : "") + 1 + strlen(arch) + 1; |
09f29f70 | 2326 | r = solv_malloc(l); |
cc687652 MS |
2327 | sprintf(r, "%s-%s.%s", name, evr ? evr : "", arch); |
2328 | solv_free(evr); | |
99ceec3e MS |
2329 | break; |
2330 | case SOLVABLE_NAME: | |
2331 | name = headstring(rpmhead, TAG_NAME); | |
87c5e01c | 2332 | r = solv_strdup(name); |
99ceec3e | 2333 | break; |
83145da7 MS |
2334 | case SOLVABLE_SUMMARY: |
2335 | name = headstring(rpmhead, TAG_SUMMARY); | |
2336 | r = solv_strdup(name); | |
2337 | break; | |
2338 | case SOLVABLE_DESCRIPTION: | |
2339 | name = headstring(rpmhead, TAG_DESCRIPTION); | |
2340 | r = solv_strdup(name); | |
2341 | break; | |
99ceec3e MS |
2342 | case SOLVABLE_EVR: |
2343 | r = headtoevr(rpmhead); | |
2344 | break; | |
2345 | } | |
2346 | return r; | |
2347 | } | |
2348 | ||
83145da7 MS |
2349 | unsigned long long |
2350 | rpm_query_num(void *rpmhandle, Id what, unsigned long long notfound) | |
2351 | { | |
2352 | RpmHead *rpmhead = rpmhandle; | |
2353 | unsigned int u32; | |
2354 | ||
2355 | switch (what) | |
2356 | { | |
2357 | case SOLVABLE_INSTALLTIME: | |
2358 | u32 = headint32(rpmhead, TAG_INSTALLTIME); | |
2359 | return u32 ? u32 : notfound; | |
2360 | } | |
2361 | return notfound; | |
2362 | } | |
2363 | ||
7173e5d6 MS |
2364 | #ifdef ENABLE_RPMDB |
2365 | ||
94ab2d2f | 2366 | int |
a54b5750 | 2367 | rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queue *rpmdbidq) |
94ab2d2f | 2368 | { |
94ab2d2f MS |
2369 | struct rpmdbentry *entries; |
2370 | int nentries, i; | |
94ab2d2f | 2371 | |
0d887d16 | 2372 | entries = getinstalledrpmdbids(rpmstate, index ? index : "Name", match, &nentries, 0, 0); |
94ab2d2f | 2373 | if (rpmdbidq) |
bb4e122a MS |
2374 | { |
2375 | queue_empty(rpmdbidq); | |
2376 | for (i = 0; i < nentries; i++) | |
2377 | queue_push(rpmdbidq, entries[i].rpmdbid); | |
2378 | } | |
09f29f70 | 2379 | solv_free(entries); |
94ab2d2f | 2380 | return nentries; |
87bfd053 MS |
2381 | } |
2382 | ||
3e003c06 | 2383 | void * |
a54b5750 | 2384 | rpm_byrpmdbid(void *rpmstate, Id rpmdbid) |
3e003c06 | 2385 | { |
691ceb7b MS |
2386 | struct rpmdbstate *state = rpmstate; |
2387 | int r; | |
3e003c06 | 2388 | |
49d6cbd2 | 2389 | r = getrpm_dbid(state, rpmdbid); |
691ceb7b MS |
2390 | if (!r) |
2391 | pool_error(state->pool, 0, "header #%d not in database", rpmdbid); | |
2392 | return r <= 0 ? 0 : state->rpmhead; | |
3e003c06 | 2393 | } |
521b28a8 | 2394 | |
aa4df21e | 2395 | #endif /* ENABLE_RPMDB */ |
7173e5d6 | 2396 | |
3e003c06 | 2397 | void * |
a54b5750 | 2398 | rpm_byfp(void *rpmstate, FILE *fp, const char *name) |
3e003c06 | 2399 | { |
691ceb7b | 2400 | struct rpmdbstate *state = rpmstate; |
5769c724 | 2401 | unsigned int sigdsize, sigcnt, l; |
3e003c06 MS |
2402 | unsigned char lead[4096]; |
2403 | ||
3e003c06 MS |
2404 | if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) |
2405 | { | |
52dcb04b | 2406 | pool_error(state->pool, 0, "%s: not a rpm", name); |
3e003c06 MS |
2407 | return 0; |
2408 | } | |
2409 | if (lead[78] != 0 || lead[79] != 5) | |
2410 | { | |
52dcb04b | 2411 | pool_error(state->pool, 0, "%s: not a V5 header", name); |
3e003c06 MS |
2412 | return 0; |
2413 | } | |
47fbaa2a MS |
2414 | |
2415 | /* skip signature header */ | |
3e003c06 MS |
2416 | if (getu32(lead + 96) != 0x8eade801) |
2417 | { | |
52dcb04b | 2418 | pool_error(state->pool, 0, "%s: bad signature header", name); |
3e003c06 MS |
2419 | return 0; |
2420 | } | |
2421 | sigcnt = getu32(lead + 96 + 8); | |
2422 | sigdsize = getu32(lead + 96 + 12); | |
78a876b1 | 2423 | if (sigcnt >= MAX_SIG_CNT || sigdsize >= MAX_SIG_DSIZE) |
3e003c06 | 2424 | { |
52dcb04b | 2425 | pool_error(state->pool, 0, "%s: bad signature header", name); |
3e003c06 MS |
2426 | return 0; |
2427 | } | |
2428 | sigdsize += sigcnt * 16; | |
2429 | sigdsize = (sigdsize + 7) & ~7; | |
3e003c06 MS |
2430 | while (sigdsize) |
2431 | { | |
2432 | l = sigdsize > 4096 ? 4096 : sigdsize; | |
2433 | if (fread(lead, l, 1, fp) != 1) | |
2434 | { | |
52dcb04b | 2435 | pool_error(state->pool, 0, "%s: unexpected EOF", name); |
3e003c06 MS |
2436 | return 0; |
2437 | } | |
2438 | sigdsize -= l; | |
2439 | } | |
47fbaa2a | 2440 | |
3e003c06 MS |
2441 | if (fread(lead, 16, 1, fp) != 1) |
2442 | { | |
52dcb04b | 2443 | pool_error(state->pool, 0, "%s: unexpected EOF", name); |
3e003c06 MS |
2444 | return 0; |
2445 | } | |
2446 | if (getu32(lead) != 0x8eade801) | |
2447 | { | |
52dcb04b | 2448 | pool_error(state->pool, 0, "%s: bad header", name); |
3e003c06 MS |
2449 | return 0; |
2450 | } | |
2451 | sigcnt = getu32(lead + 8); | |
2452 | sigdsize = getu32(lead + 12); | |
78a876b1 | 2453 | if (sigcnt >= MAX_HDR_CNT || sigdsize >= MAX_HDR_DSIZE) |
3e003c06 | 2454 | { |
52dcb04b | 2455 | pool_error(state->pool, 0, "%s: bad header", name); |
3e003c06 MS |
2456 | return 0; |
2457 | } | |
aa4df21e | 2458 | if (!headfromfp(state, name, fp, lead, sigcnt, sigdsize, 0, 0, 0)) |
47fbaa2a MS |
2459 | return 0; |
2460 | return state->rpmhead; | |
3e003c06 MS |
2461 | } |
2462 | ||
ae214a65 | 2463 | #if defined(ENABLE_RPMDB_BYRPMHEADER) || defined(ENABLE_RPMDB_LIBRPM) |
d5597d3b | 2464 | |
99ceec3e | 2465 | void * |
a54b5750 | 2466 | rpm_byrpmh(void *rpmstate, Header h) |
99ceec3e | 2467 | { |
691ceb7b | 2468 | struct rpmdbstate *state = rpmstate; |
ae214a65 | 2469 | #ifndef ENABLE_RPMPKG_LIBRPM |
99ceec3e | 2470 | const unsigned char *uh; |
aa4df21e | 2471 | unsigned int dsize, cnt; |
99ceec3e | 2472 | |
ae214a65 MS |
2473 | if (!h) |
2474 | return 0; | |
c349c5cd | 2475 | #ifndef RPM5 |
99ceec3e | 2476 | uh = headerUnload(h); |
c349c5cd MS |
2477 | #else |
2478 | uh = headerUnload(h, NULL); | |
2479 | #endif | |
99ceec3e MS |
2480 | if (!uh) |
2481 | return 0; | |
aa4df21e MS |
2482 | cnt = getu32(uh); |
2483 | dsize = getu32(uh + 4); | |
2484 | if (cnt >= MAX_HDR_CNT || dsize >= MAX_HDR_DSIZE) | |
99ceec3e | 2485 | { |
aa4df21e MS |
2486 | free((void *)uh); |
2487 | return 0; | |
99ceec3e | 2488 | } |
aa4df21e | 2489 | headfromblob(state, uh + 8, cnt, dsize); |
99ceec3e | 2490 | free((void *)uh); |
ae214a65 MS |
2491 | #else |
2492 | if (!h) | |
2493 | return 0; | |
8bdcce1f MS |
2494 | if (state->rpmhead) |
2495 | headfree(state->rpmhead); | |
aa4df21e | 2496 | state->rpmhead = headerLink(h); |
ae214a65 | 2497 | #endif |
aa4df21e | 2498 | return state->rpmhead; |
99ceec3e MS |
2499 | } |
2500 | ||
7a9c082b | 2501 | #endif /* defined(ENABLE_RPMDB_BYRPMHEADER) || defined(ENABLE_RPMDB_LIBRPM) */ |
d5597d3b | 2502 |