File: | lib/rpmds.c |
Warning: | line 281, column 5 Value stored to 'ds' is never read |
1 | /** \ingroup rpmdep |
2 | * \file lib/rpmds.c |
3 | */ |
4 | #include "system.h" |
5 | |
6 | #include <rpm/rpmtypes.h> |
7 | #include <rpm/rpmlib.h> /* rpmvercmp */ |
8 | #include <rpm/rpmstring.h> |
9 | #include <rpm/rpmlog.h> |
10 | #include <rpm/rpmstrpool.h> |
11 | |
12 | #include "lib/rpmds_internal.h" |
13 | |
14 | #include "debug.h" |
15 | |
16 | int _rpmds_debug = 0; |
17 | |
18 | int _rpmds_nopromote = 1; |
19 | |
20 | /** |
21 | * A package dependency set. |
22 | */ |
23 | struct rpmds_s { |
24 | rpmstrPool pool; /*!< String pool. */ |
25 | const char * Type; /*!< Tag name. */ |
26 | char * DNEVR; /*!< Formatted dependency string. */ |
27 | rpmsid * N; /*!< Dependency name id's (pool) */ |
28 | rpmsid * EVR; /*!< Dependency EVR id's (pool) */ |
29 | rpmsenseFlags * Flags; /*!< Bit(s) identifying context/comparison. */ |
30 | rpm_color_t * Color; /*!< Bit(s) calculated from file color(s). */ |
31 | rpmTagVal tagN; /*!< Header tag. */ |
32 | int32_t Count; /*!< No. of elements */ |
33 | unsigned int instance; /*!< From rpmdb instance? */ |
34 | int i; /*!< Element index. */ |
35 | int nopromote; /*!< Don't promote Epoch: in rpmdsCompare()? */ |
36 | int nrefs; /*!< Reference count. */ |
37 | int *ti; /*!< Trigger index. */ |
38 | }; |
39 | |
40 | static int dsType(rpmTagVal tag, |
41 | const char ** Type, rpmTagVal * tagEVR, rpmTagVal * tagF, |
42 | rpmTagVal * tagTi) |
43 | { |
44 | int rc = 0; |
45 | const char *t = NULL((void*)0); |
46 | rpmTagVal evr = RPMTAG_NOT_FOUND; |
47 | rpmTagVal f = RPMTAG_NOT_FOUND; |
48 | rpmTagVal ti = RPMTAG_NOT_FOUND; |
49 | |
50 | if (tag == RPMTAG_PROVIDENAME) { |
51 | t = "Provides"; |
52 | evr = RPMTAG_PROVIDEVERSION; |
53 | f = RPMTAG_PROVIDEFLAGS; |
54 | } else if (tag == RPMTAG_REQUIRENAME) { |
55 | t = "Requires"; |
56 | evr = RPMTAG_REQUIREVERSION; |
57 | f = RPMTAG_REQUIREFLAGS; |
58 | } else if (tag == RPMTAG_SUPPLEMENTNAME) { |
59 | t = "Supplements"; |
60 | evr = RPMTAG_SUPPLEMENTVERSION; |
61 | f = RPMTAG_SUPPLEMENTFLAGS; |
62 | } else if (tag == RPMTAG_ENHANCENAME) { |
63 | t = "Enhances"; |
64 | evr = RPMTAG_ENHANCEVERSION; |
65 | f = RPMTAG_ENHANCEFLAGS; |
66 | } else if (tag == RPMTAG_RECOMMENDNAME) { |
67 | t = "Recommends"; |
68 | evr = RPMTAG_RECOMMENDVERSION; |
69 | f = RPMTAG_RECOMMENDFLAGS; |
70 | } else if (tag == RPMTAG_SUGGESTNAME) { |
71 | t = "Suggests"; |
72 | evr = RPMTAG_SUGGESTVERSION; |
73 | f = RPMTAG_SUGGESTFLAGS; |
74 | } else if (tag == RPMTAG_CONFLICTNAME) { |
75 | t = "Conflicts"; |
76 | evr = RPMTAG_CONFLICTVERSION; |
77 | f = RPMTAG_CONFLICTFLAGS; |
78 | } else if (tag == RPMTAG_OBSOLETENAME) { |
79 | t = "Obsoletes"; |
80 | evr = RPMTAG_OBSOLETEVERSION; |
81 | f = RPMTAG_OBSOLETEFLAGS; |
82 | } else if (tag == RPMTAG_ORDERNAME) { |
83 | t = "Order"; |
84 | evr = RPMTAG_ORDERVERSION; |
85 | f = RPMTAG_ORDERFLAGS; |
86 | } else if (tag == RPMTAG_TRIGGERNAME) { |
87 | t = "Trigger"; |
88 | evr = RPMTAG_TRIGGERVERSION; |
89 | f = RPMTAG_TRIGGERFLAGS; |
90 | ti = RPMTAG_TRIGGERINDEX; |
91 | } else if (tag == RPMTAG_OLDSUGGESTSNAME) { |
92 | t = "Oldsuggests"; |
93 | evr = RPMTAG_OLDSUGGESTSVERSION; |
94 | f = RPMTAG_OLDSUGGESTSFLAGS; |
95 | } else if (tag == RPMTAG_OLDENHANCESNAME) { |
96 | t = "Oldenhances"; |
97 | evr = RPMTAG_OLDENHANCESVERSION; |
98 | f = RPMTAG_OLDENHANCESFLAGS; |
99 | } else if (tag == RPMTAG_FILETRIGGERNAME) { |
100 | t = "FileTrigger"; |
101 | evr = RPMTAG_FILETRIGGERVERSION; |
102 | f = RPMTAG_FILETRIGGERFLAGS; |
103 | ti = RPMTAG_FILETRIGGERINDEX; |
104 | } else if (tag == RPMTAG_TRANSFILETRIGGERNAME) { |
105 | t = "TransFileTrigger"; |
106 | evr = RPMTAG_TRANSFILETRIGGERVERSION; |
107 | f = RPMTAG_TRANSFILETRIGGERFLAGS; |
108 | ti = RPMTAG_TRANSFILETRIGGERINDEX; |
109 | } else { |
110 | rc = 1; |
111 | } |
112 | if (Type) *Type = t; |
113 | if (tagEVR) *tagEVR = evr; |
114 | if (tagF) *tagF = f; |
115 | if (tagTi) *tagTi = ti; |
116 | return rc; |
117 | } |
118 | |
119 | static char tagNToChar(rpmTagVal tagN) |
120 | { |
121 | switch (tagN) { |
122 | default: |
123 | return 'R'; |
124 | break; |
125 | case RPMTAG_REQUIRENAME: |
126 | return 'R'; |
127 | break; |
128 | case RPMTAG_PROVIDENAME: |
129 | return 'P'; |
130 | break; |
131 | case RPMTAG_RECOMMENDNAME: |
132 | return 'r'; |
133 | break; |
134 | case RPMTAG_SUGGESTNAME: |
135 | return 's'; |
136 | break; |
137 | case RPMTAG_SUPPLEMENTNAME: |
138 | return 'S'; |
139 | break; |
140 | case RPMTAG_ENHANCENAME: |
141 | return 'e'; |
142 | break; |
143 | case RPMTAG_CONFLICTNAME: |
144 | return 'C'; |
145 | break; |
146 | case RPMTAG_OBSOLETENAME: |
147 | return 'O'; |
148 | break; |
149 | } |
150 | } |
151 | |
152 | rpmTagVal rpmdsDToTagN(char deptype) |
153 | { |
154 | rpmTagVal tagN = RPMTAG_REQUIRENAME; |
155 | switch (deptype) { |
156 | default: |
157 | tagN = RPMTAG_NOT_FOUND; |
158 | break; |
159 | case 'P': |
160 | tagN = RPMTAG_PROVIDENAME; |
161 | break; |
162 | case 'R': |
163 | tagN = RPMTAG_REQUIRENAME; |
164 | break; |
165 | case 'r': |
166 | tagN = RPMTAG_RECOMMENDNAME; |
167 | break; |
168 | case 's': |
169 | tagN = RPMTAG_SUGGESTNAME; |
170 | break; |
171 | case 'S': |
172 | tagN = RPMTAG_SUPPLEMENTNAME; |
173 | break; |
174 | case 'e': |
175 | tagN = RPMTAG_ENHANCENAME; |
176 | break; |
177 | case 'C': |
178 | tagN = RPMTAG_CONFLICTNAME; |
179 | break; |
180 | case 'O': |
181 | tagN = RPMTAG_OBSOLETENAME; |
182 | break; |
183 | } |
184 | return tagN; |
185 | } |
186 | |
187 | rpmsid rpmdsNIdIndex(rpmds ds, int i) |
188 | { |
189 | rpmsid id = 0; |
190 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->N != NULL((void*)0)) |
191 | id = ds->N[i]; |
192 | return id; |
193 | } |
194 | |
195 | rpmsid rpmdsEVRIdIndex(rpmds ds, int i) |
196 | { |
197 | rpmsid id = 0; |
198 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->EVR != NULL((void*)0)) |
199 | id = ds->EVR[i]; |
200 | return id; |
201 | } |
202 | const char * rpmdsNIndex(rpmds ds, int i) |
203 | { |
204 | const char * N = NULL((void*)0); |
205 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->N != NULL((void*)0)) |
206 | N = rpmstrPoolStr(ds->pool, ds->N[i]); |
207 | return N; |
208 | } |
209 | |
210 | const char * rpmdsEVRIndex(rpmds ds, int i) |
211 | { |
212 | const char * EVR = NULL((void*)0); |
213 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->EVR != NULL((void*)0)) |
214 | EVR = rpmstrPoolStr(ds->pool, ds->EVR[i]); |
215 | return EVR; |
216 | } |
217 | |
218 | rpmsenseFlags rpmdsFlagsIndex(rpmds ds, int i) |
219 | { |
220 | rpmsenseFlags Flags = 0; |
221 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->Flags != NULL((void*)0)) |
222 | Flags = ds->Flags[i]; |
223 | return Flags; |
224 | } |
225 | |
226 | int rpmdsTiIndex(rpmds ds, int i) |
227 | { |
228 | int ti = -1; |
229 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->ti != NULL((void*)0)) |
230 | ti = ds->ti[i]; |
231 | return ti; |
232 | } |
233 | |
234 | rpm_color_t rpmdsColorIndex(rpmds ds, int i) |
235 | { |
236 | rpm_color_t Color = 0; |
237 | if (ds != NULL((void*)0) && i >= 0 && i < ds->Count && ds->Color != NULL((void*)0)) |
238 | Color = ds->Color[i]; |
239 | return Color; |
240 | } |
241 | static rpmds rpmdsUnlink(rpmds ds) |
242 | { |
243 | if (ds) |
244 | ds->nrefs--; |
245 | return NULL((void*)0); |
246 | } |
247 | |
248 | rpmds rpmdsLink(rpmds ds) |
249 | { |
250 | if (ds) |
251 | ds->nrefs++; |
252 | return ds; |
253 | } |
254 | |
255 | rpmds rpmdsFree(rpmds ds) |
256 | { |
257 | rpmTagVal tagEVR, tagF, tagTi; |
258 | |
259 | if (ds == NULL((void*)0)) |
260 | return NULL((void*)0); |
261 | |
262 | if (ds->nrefs > 1) |
263 | return rpmdsUnlink(ds); |
264 | |
265 | if (dsType(ds->tagN, NULL((void*)0), &tagEVR, &tagF, &tagTi)) |
266 | return NULL((void*)0); |
267 | |
268 | if (ds->Count > 0) { |
269 | ds->N = _free(ds->N)rfree((ds->N)); |
270 | ds->EVR = _free(ds->EVR)rfree((ds->EVR)); |
271 | ds->Flags = _free(ds->Flags)rfree((ds->Flags)); |
272 | ds->ti = _free(ds->ti)rfree((ds->ti)); |
273 | } |
274 | |
275 | ds->pool = rpmstrPoolFree(ds->pool); |
276 | ds->DNEVR = _free(ds->DNEVR)rfree((ds->DNEVR)); |
277 | ds->Color = _free(ds->Color)rfree((ds->Color)); |
278 | |
279 | (void) rpmdsUnlink(ds); |
280 | memset(ds, 0, sizeof(*ds)); /* XXX trash and burn */ |
281 | ds = _free(ds)rfree((ds)); |
Value stored to 'ds' is never read | |
282 | return NULL((void*)0); |
283 | } |
284 | |
285 | static rpmds rpmdsCreate(rpmstrPool pool, |
286 | rpmTagVal tagN, const char * Type, int Count, |
287 | unsigned int instance) |
288 | { |
289 | rpmds ds = xcalloc(1, sizeof(*ds))rcalloc((1), (sizeof(*ds))); |
290 | |
291 | ds->pool = (pool != NULL((void*)0)) ? rpmstrPoolLink(pool) : rpmstrPoolCreate(); |
292 | ds->tagN = tagN; |
293 | ds->Type = Type; |
294 | ds->Count = Count; |
295 | ds->instance = instance; |
296 | ds->nopromote = _rpmds_nopromote; |
297 | ds->i = -1; |
298 | |
299 | return rpmdsLink(ds); |
300 | } |
301 | |
302 | rpmds rpmdsNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, int flags) |
303 | { |
304 | rpmTagVal tagEVR, tagF, tagTi; |
305 | rpmds ds = NULL((void*)0); |
306 | const char * Type; |
307 | struct rpmtd_s names; |
308 | if (dsType(tagN, &Type, &tagEVR, &tagF, &tagTi)) |
309 | goto exit; |
310 | |
311 | if (headerGet(h, tagN, &names, HEADERGET_MINMEM)) { |
312 | struct rpmtd_s evr, flags, tindices; |
313 | rpm_count_t count = rpmtdCount(&names); |
314 | |
315 | headerGet(h, tagEVR, &evr, HEADERGET_MINMEM); |
316 | if (evr.count && evr.count != count) { |
317 | rpmtdFreeData(&evr); |
318 | return NULL((void*)0); |
319 | } |
320 | |
321 | headerGet(h, tagF, &flags, HEADERGET_ALLOC); |
322 | if (flags.count && flags.count != count) { |
323 | rpmtdFreeData(&flags); |
324 | return NULL((void*)0); |
325 | } |
326 | |
327 | if (tagTi != RPMTAG_NOT_FOUND) { |
328 | headerGet(h, tagTi, &tindices, HEADERGET_ALLOC); |
329 | if (tindices.count && tindices.count != count) { |
330 | rpmtdFreeData(&tindices); |
331 | return NULL((void*)0); |
332 | } |
333 | } |
334 | |
335 | ds = rpmdsCreate(pool, tagN, Type, count, headerGetInstance(h)); |
336 | |
337 | ds->N = names.count ? rpmtdToPool(&names, ds->pool) : NULL((void*)0); |
338 | ds->EVR = evr.count ? rpmtdToPool(&evr, ds->pool): NULL((void*)0); |
339 | ds->Flags = flags.data; |
340 | if (tagTi != RPMTAG_NOT_FOUND) { |
341 | ds->ti = tindices.data; |
342 | } |
343 | |
344 | /* ensure rpmlib() requires always have RPMSENSE_RPMLIB flag set */ |
345 | if (tagN == RPMTAG_REQUIRENAME && ds->Flags) { |
346 | for (int i = 0; i < ds->Count; i++) { |
347 | if (!(rpmdsFlagsIndex(ds, i) & RPMSENSE_RPMLIB)) { |
348 | const char *N = rpmdsNIndex(ds, i); |
349 | if (rstreqn(N, "rpmlib(", sizeof("rpmlib(")-1)) |
350 | ds->Flags[i] |= RPMSENSE_RPMLIB; |
351 | } |
352 | } |
353 | } |
354 | rpmtdFreeData(&names); |
355 | rpmtdFreeData(&evr); |
356 | |
357 | /* freeze the pool to save memory, but only if private pool */ |
358 | if (ds->pool != pool) |
359 | rpmstrPoolFreeze(ds->pool, 0); |
360 | } |
361 | |
362 | exit: |
363 | return ds; |
364 | } |
365 | |
366 | rpmds rpmdsNew(Header h, rpmTagVal tagN, int flags) |
367 | { |
368 | return rpmdsNewPool(NULL((void*)0), h, tagN, flags); |
369 | } |
370 | |
371 | char * rpmdsNewDNEVR(const char * dspfx, const rpmds ds) |
372 | { |
373 | const char * N = rpmdsN(ds); |
374 | const char * EVR = rpmdsEVR(ds); |
375 | rpmsenseFlags Flags = rpmdsFlags(ds); |
376 | char * tbuf, * t; |
377 | size_t nb; |
378 | |
379 | nb = 0; |
380 | if (dspfx) nb += strlen(dspfx) + 1; |
381 | if (N) nb += strlen(N); |
382 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
383 | if (Flags & RPMSENSE_SENSEMASK15) { |
384 | if (nb) nb++; |
385 | if (Flags & RPMSENSE_LESS) nb++; |
386 | if (Flags & RPMSENSE_GREATER) nb++; |
387 | if (Flags & RPMSENSE_EQUAL) nb++; |
388 | } |
389 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
390 | if (EVR && *EVR) { |
391 | if (nb) nb++; |
392 | nb += strlen(EVR); |
393 | } |
394 | |
395 | t = tbuf = xmalloc(nb + 1)rmalloc((nb + 1)); |
396 | if (dspfx) { |
397 | t = stpcpy(t, dspfx); |
398 | *t++ = ' '; |
399 | } |
400 | if (N) |
401 | t = stpcpy(t, N); |
402 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
403 | if (Flags & RPMSENSE_SENSEMASK15) { |
404 | if (t != tbuf) *t++ = ' '; |
405 | if (Flags & RPMSENSE_LESS) *t++ = '<'; |
406 | if (Flags & RPMSENSE_GREATER) *t++ = '>'; |
407 | if (Flags & RPMSENSE_EQUAL) *t++ = '='; |
408 | } |
409 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
410 | if (EVR && *EVR) { |
411 | if (t != tbuf) *t++ = ' '; |
412 | t = stpcpy(t, EVR); |
413 | } |
414 | *t = '\0'; |
415 | return tbuf; |
416 | } |
417 | |
418 | static rpmds singleDSPool(rpmstrPool pool, rpmTagVal tagN, |
419 | rpmsid N, rpmsid EVR, rpmsenseFlags Flags, |
420 | unsigned int instance, rpm_color_t Color, |
421 | int triggerIndex) |
422 | { |
423 | rpmds ds = NULL((void*)0); |
424 | const char * Type; |
425 | rpmTagVal tagTi; |
426 | |
427 | if (dsType(tagN, &Type, NULL((void*)0), NULL((void*)0), &tagTi)) |
428 | goto exit; |
429 | |
430 | ds = rpmdsCreate(pool, tagN, Type, 1, instance); |
431 | |
432 | ds->N = xmalloc(1 * sizeof(*ds->N))rmalloc((1 * sizeof(*ds->N))); |
433 | ds->N[0] = N; |
434 | ds->EVR = xmalloc(1 * sizeof(*ds->EVR))rmalloc((1 * sizeof(*ds->EVR))); |
435 | ds->EVR[0] = EVR; |
436 | ds->Flags = xmalloc(sizeof(*ds->Flags))rmalloc((sizeof(*ds->Flags))); |
437 | ds->Flags[0] = Flags; |
438 | if (tagTi != RPMTAG_NOT_FOUND) { |
439 | ds->ti = xmalloc(sizeof(*ds->ti))rmalloc((sizeof(*ds->ti))); |
440 | ds->ti[0] = triggerIndex; |
441 | } |
442 | ds->i = 0; |
443 | if (Color) |
444 | rpmdsSetColor(ds, Color); |
445 | |
446 | exit: |
447 | return ds; |
448 | } |
449 | |
450 | static rpmds singleDS(rpmstrPool pool, rpmTagVal tagN, |
451 | const char * N, const char * EVR, |
452 | rpmsenseFlags Flags, unsigned int instance, |
453 | rpm_color_t Color, int triggerIndex) |
454 | { |
455 | rpmds ds = singleDSPool(pool, tagN, 0, 0, Flags, instance, Color, |
456 | triggerIndex); |
457 | if (ds) { |
458 | /* now that we have a pool, we can insert our N & EVR strings */ |
459 | ds->N[0] = rpmstrPoolId(ds->pool, N ? N : "", 1); |
460 | ds->EVR[0] = rpmstrPoolId(ds->pool, EVR ? EVR : "", 1); |
461 | /* freeze the pool to save memory, but only if private pool */ |
462 | if (ds->pool != pool) |
463 | rpmstrPoolFreeze(ds->pool, 0); |
464 | } |
465 | return ds; |
466 | } |
467 | |
468 | rpmds rpmdsThisPool(rpmstrPool pool, |
469 | Header h, rpmTagVal tagN, rpmsenseFlags Flags) |
470 | { |
471 | char *evr = headerGetAsString(h, RPMTAG_EVR); |
472 | rpmds ds = singleDS(pool, tagN, headerGetString(h, RPMTAG_NAME), |
473 | evr, Flags, headerGetInstance(h), 0, 0); |
474 | free(evr); |
475 | return ds; |
476 | } |
477 | |
478 | rpmds rpmdsThis(Header h, rpmTagVal tagN, rpmsenseFlags Flags) |
479 | { |
480 | return rpmdsThisPool(NULL((void*)0), h, tagN, Flags); |
481 | } |
482 | |
483 | rpmds rpmdsSinglePool(rpmstrPool pool,rpmTagVal tagN, |
484 | const char * N, const char * EVR, rpmsenseFlags Flags) |
485 | { |
486 | return singleDS(pool, tagN, N, EVR, Flags, 0, 0, 0); |
487 | } |
488 | |
489 | rpmds rpmdsSinglePoolTix(rpmstrPool pool,rpmTagVal tagN, |
490 | const char * N, const char * EVR, |
491 | rpmsenseFlags Flags, int triggerIndex) |
492 | { |
493 | return singleDS(pool, tagN, N, EVR, Flags, 0, 0, triggerIndex); |
494 | } |
495 | |
496 | rpmds rpmdsSingle(rpmTagVal tagN, const char * N, const char * EVR, rpmsenseFlags Flags) |
497 | { |
498 | return rpmdsSinglePool(NULL((void*)0), tagN, N, EVR, Flags); |
499 | } |
500 | |
501 | rpmds rpmdsCurrent(rpmds ds) |
502 | { |
503 | rpmds cds = NULL((void*)0); |
504 | int ti = -1; |
505 | if (ds != NULL((void*)0) && ds->i >= 0 && ds->i < ds->Count) { |
506 | if (ds->ti) |
507 | ti = ds->ti[ds->i]; |
508 | /* Using parent's pool so we can just use the same id's */ |
509 | cds = singleDSPool(ds->pool, ds->tagN, ds->N[ds->i], ds->EVR[ds->i], |
510 | rpmdsFlags(ds), ds->instance, rpmdsColor(ds), ti); |
511 | } |
512 | return cds; |
513 | } |
514 | |
515 | rpmds rpmdsFilterTi(rpmds ds, int ti) |
516 | { |
517 | int i, i2, tiCount = 0; |
518 | rpmds fds; |
519 | |
520 | if (ds == NULL((void*)0) || !ds->ti || !ds->Count) |
521 | return NULL((void*)0); |
522 | |
523 | for (i = 0; i < ds->Count; i++) { |
524 | if (ds->ti[i] == ti) |
525 | tiCount++; |
526 | } |
527 | |
528 | if (!tiCount) |
529 | return NULL((void*)0); |
530 | |
531 | fds = rpmdsCreate(ds->pool, ds->tagN, ds->Type, tiCount, ds->instance); |
532 | |
533 | fds->N = xmalloc(tiCount * sizeof(*fds->N))rmalloc((tiCount * sizeof(*fds->N))); |
534 | fds->EVR = xmalloc(tiCount * sizeof(*fds->EVR))rmalloc((tiCount * sizeof(*fds->EVR))); |
535 | fds->Flags = xmalloc(tiCount * sizeof(*fds->Flags))rmalloc((tiCount * sizeof(*fds->Flags))); |
536 | fds->ti = xmalloc(tiCount * sizeof(*fds->ti))rmalloc((tiCount * sizeof(*fds->ti))); |
537 | fds->i = -1; |
538 | |
539 | i2 = 0; |
540 | for (i = 0; i < ds->Count; i++) { |
541 | if (ds->ti[i] == ti) { |
542 | fds->N[i2] = ds->N[i]; |
543 | fds->EVR[i2] = ds->EVR[i]; |
544 | fds->Flags[i2] = ds->Flags[i]; |
545 | fds->ti[i2] = ds->ti[i]; |
546 | i2++; |
547 | } |
548 | } |
549 | |
550 | return fds; |
551 | } |
552 | |
553 | int rpmdsPutToHeader(rpmds ds, Header h) |
554 | { |
555 | rpmTagVal tagN = rpmdsTagN(ds); |
556 | rpmTagVal tagEVR = rpmdsTagEVR(ds); |
557 | rpmTagVal tagF = rpmdsTagF(ds); |
558 | rpmTagVal tagTi = rpmdsTagTi(ds); |
559 | if (!tagN) |
560 | return -1; |
561 | |
562 | rpmds pi = rpmdsInit(ds); |
563 | while (rpmdsNext(pi) >= 0) { |
564 | rpmsenseFlags flags = rpmdsFlags(pi); |
565 | uint32_t index = rpmdsTi(pi); |
566 | headerPutString(h, tagN, rpmdsN(pi)); |
567 | headerPutString(h, tagEVR, rpmdsEVR(pi)); |
568 | headerPutUint32(h, tagF, &flags, 1); |
569 | if (tagTi != RPMTAG_NOT_FOUND) { |
570 | headerPutUint32(h, tagTi, &index, 1); |
571 | } |
572 | } |
573 | return 0; |
574 | } |
575 | |
576 | int rpmdsCount(const rpmds ds) |
577 | { |
578 | return (ds != NULL((void*)0) ? ds->Count : 0); |
579 | } |
580 | |
581 | int rpmdsIx(const rpmds ds) |
582 | { |
583 | return (ds != NULL((void*)0) ? ds->i : -1); |
584 | } |
585 | |
586 | int rpmdsSetIx(rpmds ds, int ix) |
587 | { |
588 | int i = -1; |
589 | |
590 | if (ds != NULL((void*)0)) { |
591 | i = ds->i; |
592 | ds->i = ix; |
593 | ds->DNEVR = _free(ds->DNEVR)rfree((ds->DNEVR)); |
594 | } |
595 | return i; |
596 | } |
597 | |
598 | char rpmdsD(const rpmds ds) |
599 | { |
600 | if (ds != NULL((void*)0)) { |
601 | return tagNToChar(ds->tagN); |
602 | } else { |
603 | return '\0'; |
604 | } |
605 | } |
606 | |
607 | const char * rpmdsDNEVR(const rpmds ds) |
608 | { |
609 | const char * DNEVR = NULL((void*)0); |
610 | |
611 | if (ds != NULL((void*)0) && ds->i >= 0 && ds->i < ds->Count) { |
612 | if (ds->DNEVR == NULL((void*)0)) { |
613 | char t[2] = { tagNToChar(ds->tagN), '\0' }; |
614 | ds->DNEVR = rpmdsNewDNEVR(t, ds); |
615 | } |
616 | DNEVR = ds->DNEVR; |
617 | } |
618 | return DNEVR; |
619 | } |
620 | |
621 | rpmsid rpmdsNId(rpmds ds) |
622 | { |
623 | return (ds != NULL((void*)0)) ? rpmdsNIdIndex(ds, ds->i) : 0; |
624 | } |
625 | |
626 | rpmsid rpmdsEVRId(rpmds ds) |
627 | { |
628 | return (ds != NULL((void*)0)) ? rpmdsEVRIdIndex(ds, ds->i) : 0; |
629 | } |
630 | |
631 | const char * rpmdsN(const rpmds ds) |
632 | { |
633 | return (ds != NULL((void*)0)) ? rpmdsNIndex(ds, ds->i) : NULL((void*)0); |
634 | } |
635 | |
636 | const char * rpmdsEVR(const rpmds ds) |
637 | { |
638 | return (ds != NULL((void*)0)) ? rpmdsEVRIndex(ds, ds->i) : NULL((void*)0); |
639 | } |
640 | |
641 | rpmsenseFlags rpmdsFlags(const rpmds ds) |
642 | { |
643 | return (ds != NULL((void*)0)) ? rpmdsFlagsIndex(ds, ds->i) : 0; |
644 | } |
645 | |
646 | int rpmdsTi(const rpmds ds) |
647 | { |
648 | return (ds != NULL((void*)0)) ? rpmdsTiIndex(ds, ds->i) : 0; |
649 | } |
650 | |
651 | rpmTagVal rpmdsTagN(const rpmds ds) |
652 | { |
653 | rpmTagVal tagN = RPMTAG_NOT_FOUND; |
654 | |
655 | if (ds != NULL((void*)0)) |
656 | tagN = ds->tagN; |
657 | return tagN; |
658 | } |
659 | |
660 | rpmTagVal rpmdsTagEVR(const rpmds ds) |
661 | { |
662 | rpmTagVal tagEVR = RPMTAG_NOT_FOUND; |
663 | |
664 | if (ds != NULL((void*)0)) |
665 | dsType(ds->tagN, NULL((void*)0), &tagEVR, NULL((void*)0), NULL((void*)0)); |
666 | return tagEVR; |
667 | } |
668 | |
669 | rpmTagVal rpmdsTagF(const rpmds ds) |
670 | { |
671 | rpmTagVal tagF = RPMTAG_NOT_FOUND; |
672 | |
673 | if (ds != NULL((void*)0)) |
674 | dsType(ds->tagN, NULL((void*)0), NULL((void*)0), &tagF, NULL((void*)0)); |
675 | return tagF; |
676 | } |
677 | |
678 | rpmTagVal rpmdsTagTi(const rpmds ds) |
679 | { |
680 | rpmTagVal tagTi = RPMTAG_NOT_FOUND; |
681 | |
682 | if (ds != NULL((void*)0)) |
683 | dsType(ds->tagN, NULL((void*)0), NULL((void*)0), NULL((void*)0), &tagTi); |
684 | return tagTi; |
685 | } |
686 | |
687 | unsigned int rpmdsInstance(rpmds ds) |
688 | { |
689 | return (ds != NULL((void*)0)) ? ds->instance : 0; |
690 | } |
691 | |
692 | int rpmdsNoPromote(const rpmds ds) |
693 | { |
694 | int nopromote = 0; |
695 | |
696 | if (ds != NULL((void*)0)) |
697 | nopromote = ds->nopromote; |
698 | return nopromote; |
699 | } |
700 | |
701 | int rpmdsSetNoPromote(rpmds ds, int nopromote) |
702 | { |
703 | int onopromote = 0; |
704 | |
705 | if (ds != NULL((void*)0)) { |
706 | onopromote = ds->nopromote; |
707 | ds->nopromote = nopromote; |
708 | } |
709 | return onopromote; |
710 | } |
711 | |
712 | rpm_color_t rpmdsColor(const rpmds ds) |
713 | { |
714 | return (ds != NULL((void*)0)) ? rpmdsColorIndex(ds, ds->i) : 0; |
715 | } |
716 | |
717 | rpm_color_t rpmdsSetColor(const rpmds ds, rpm_color_t color) |
718 | { |
719 | rpm_color_t ocolor = 0; |
720 | |
721 | if (ds != NULL((void*)0) && ds->i >= 0 && ds->i < ds->Count) { |
722 | if (ds->Color == NULL((void*)0)) { |
723 | ds->Color = xcalloc(ds->Count, sizeof(*ds->Color))rcalloc((ds->Count), (sizeof(*ds->Color))); |
724 | } |
725 | ocolor = ds->Color[ds->i]; |
726 | ds->Color[ds->i] = color; |
727 | } |
728 | return ocolor; |
729 | } |
730 | |
731 | void rpmdsNotify(rpmds ds, const char * where, int rc) |
732 | { |
733 | const char *DNEVR; |
734 | |
735 | if (!rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG) )))) |
736 | return; |
737 | if (!(ds != NULL((void*)0) && ds->i >= 0 && ds->i < ds->Count)) |
738 | return; |
739 | if (!(ds->Type != NULL((void*)0) && (DNEVR = rpmdsDNEVR(ds)) != NULL((void*)0))) |
740 | return; |
741 | |
742 | rpmlog(RPMLOG_DEBUG, "%9s: %-45s %-s %s\n", ds->Type, |
743 | (rstreq(DNEVR, "cached") ? DNEVR : DNEVR+2), |
744 | (rc ? _("NO ")dcgettext ("rpm", "NO ", 5) : _("YES")dcgettext ("rpm", "YES", 5)), |
745 | (where != NULL((void*)0) ? where : "")); |
746 | } |
747 | |
748 | int rpmdsNext(rpmds ds) |
749 | { |
750 | int i = -1; |
751 | |
752 | if (ds != NULL((void*)0) && ++ds->i >= 0) { |
753 | if (ds->i < ds->Count) { |
754 | i = ds->i; |
755 | ds->DNEVR = _free(ds->DNEVR)rfree((ds->DNEVR)); |
756 | } else |
757 | ds->i = -1; |
758 | |
759 | if (_rpmds_debug < 0 && i != -1) |
760 | fprintf(stderrstderr, "*** ds %p\t%s[%d]: %s\n", ds, (ds->Type ? ds->Type : "?Type?"), i, (ds->DNEVR ? ds->DNEVR : "?DNEVR?")); |
761 | |
762 | } |
763 | |
764 | return i; |
765 | } |
766 | |
767 | rpmds rpmdsInit(rpmds ds) |
768 | { |
769 | if (ds != NULL((void*)0)) { |
770 | ds->i = -1; |
771 | ds->DNEVR = _free(ds->DNEVR)rfree((ds->DNEVR)); |
772 | } |
773 | return ds; |
774 | } |
775 | |
776 | static rpmds rpmdsDup(const rpmds ods) |
777 | { |
778 | rpmds ds = rpmdsCreate(ods->pool, ods->tagN, ods->Type, |
779 | ods->Count, ods->instance); |
780 | size_t nb; |
781 | |
782 | ds->i = ods->i; |
783 | ds->nopromote = ods->nopromote; |
784 | |
785 | nb = ds->Count * sizeof(*ds->N); |
786 | ds->N = memcpy(xmalloc(nb)rmalloc((nb)), ods->N, nb); |
787 | |
788 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
789 | if (ods->EVR) { |
790 | nb = ds->Count * sizeof(*ds->EVR); |
791 | ds->EVR = memcpy(xmalloc(nb)rmalloc((nb)), ods->EVR, nb); |
792 | } |
793 | |
794 | if (ods->Flags) { |
795 | nb = ds->Count * sizeof(*ds->Flags); |
796 | ds->Flags = memcpy(xmalloc(nb)rmalloc((nb)), ods->Flags, nb); |
797 | } |
798 | |
799 | if (ods->ti) { |
800 | nb = ds->Count * sizeof(*ds->ti); |
801 | ds->ti = memcpy(xmalloc(nb)rmalloc((nb)), ods->ti, nb); |
802 | } |
803 | |
804 | return ds; |
805 | |
806 | } |
807 | |
808 | static int doFind(rpmds ds, const rpmds ods, unsigned int *he) |
809 | { |
810 | int comparison; |
811 | const char *N, *ON = rpmdsN(ods); |
812 | const char *EVR, *OEVR = rpmdsEVR(ods); |
813 | rpmsenseFlags Flags, OFlags = rpmdsFlags(ods); |
814 | int index, Oindex = rpmdsTi(ods); |
815 | int rc = -1; /* assume not found */ |
816 | |
817 | if (ds == NULL((void*)0) || ods == NULL((void*)0)) |
818 | return -1; |
819 | |
820 | unsigned int l = 0; |
821 | unsigned int u = ds->Count; |
822 | while (l < u) { |
823 | ds->i = (l + u) / 2; |
824 | |
825 | N = rpmdsN(ds); |
826 | EVR = rpmdsEVR(ds); |
827 | Flags = rpmdsFlags(ds); |
828 | index = rpmdsTi(ds); |
829 | |
830 | comparison = strcmp(ON, N); |
831 | |
832 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
833 | if (comparison == 0 && OEVR && EVR) |
834 | comparison = strcmp(OEVR, EVR); |
835 | if (comparison == 0) |
836 | comparison = OFlags - Flags; |
837 | if (comparison == 0) |
838 | comparison = Oindex - index; |
839 | |
840 | if (comparison < 0) |
841 | u = ds->i; |
842 | else if (comparison > 0) |
843 | l = ds->i + 1; |
844 | else { |
845 | rc = ds->i; |
846 | break; |
847 | } |
848 | } |
849 | if (he) |
850 | *he = u; |
851 | return rc; |
852 | } |
853 | |
854 | int rpmdsFind(rpmds ds, const rpmds ods) |
855 | { |
856 | return doFind(ds, ods, NULL((void*)0)); |
857 | } |
858 | |
859 | int rpmdsMerge(rpmds * dsp, rpmds ods) |
860 | { |
861 | rpmds ds; |
862 | int save; |
863 | int ocount; |
864 | |
865 | if (dsp == NULL((void*)0) || ods == NULL((void*)0)) |
866 | return -1; |
867 | |
868 | ocount = rpmdsCount(*dsp); |
869 | |
870 | /* If not initialized yet, dup the 1st entry. */ |
871 | if (*dsp == NULL((void*)0)) { |
872 | save = ods->Count; |
873 | ods->Count = 1; |
874 | *dsp = rpmdsDup(ods); |
875 | ods->Count = save; |
876 | } |
877 | ds = *dsp; |
878 | if (ds == NULL((void*)0)) |
879 | return -1; |
880 | |
881 | /* Ensure EVR and Flags exist */ |
882 | if (ds->EVR == NULL((void*)0)) |
883 | ds->EVR = xcalloc(ds->Count, sizeof(*ds->EVR))rcalloc((ds->Count), (sizeof(*ds->EVR))); |
884 | if (ds->Flags == NULL((void*)0)) |
885 | ds->Flags = xcalloc(ds->Count, sizeof(*ds->Flags))rcalloc((ds->Count), (sizeof(*ds->Flags))); |
886 | if (ds->ti == NULL((void*)0) && ods->ti) { |
887 | int i; |
888 | ds->ti = xcalloc(ds->Count, sizeof(*ds->ti))rcalloc((ds->Count), (sizeof(*ds->ti))); |
889 | for (i = 0; i < ds->Count; i++) |
890 | ds->ti[i] = -1; |
891 | } |
892 | |
893 | /* |
894 | * Add new entries. |
895 | */ |
896 | save = ods->i; |
897 | ods = rpmdsInit(ods); |
898 | while (rpmdsNext(ods) >= 0) { |
899 | const char *OEVR; |
900 | unsigned int u; |
901 | /* |
902 | * If this entry is already present, don't bother. |
903 | */ |
904 | if (doFind(ds, ods, &u) >= 0) |
905 | continue; |
906 | |
907 | /* |
908 | * Insert new entry. Ensure pool is unfrozen to allow additions. |
909 | */ |
910 | rpmstrPoolUnfreeze(ds->pool); |
911 | ds->N = xrealloc(ds->N, (ds->Count+1) * sizeof(*ds->N))rrealloc((ds->N), ((ds->Count+1) * sizeof(*ds->N))); |
912 | if (u < ds->Count) { |
913 | memmove(ds->N + u + 1, ds->N + u, |
914 | (ds->Count - u) * sizeof(*ds->N)); |
915 | } |
916 | ds->N[u] = rpmstrPoolId(ds->pool, rpmdsN(ods), 1); |
917 | |
918 | ds->EVR = xrealloc(ds->EVR, (ds->Count+1) * sizeof(*ds->EVR))rrealloc((ds->EVR), ((ds->Count+1) * sizeof(*ds->EVR ))); |
919 | if (u < ds->Count) { |
920 | memmove(ds->EVR + u + 1, ds->EVR + u, |
921 | (ds->Count - u) * sizeof(*ds->EVR)); |
922 | } |
923 | OEVR = rpmdsEVR(ods); |
924 | ds->EVR[u] = rpmstrPoolId(ds->pool, OEVR ? OEVR : "", 1); |
925 | |
926 | ds->Flags = xrealloc(ds->Flags, (ds->Count+1) * sizeof(*ds->Flags))rrealloc((ds->Flags), ((ds->Count+1) * sizeof(*ds->Flags ))); |
927 | if (u < ds->Count) { |
928 | memmove(ds->Flags + u + 1, ds->Flags + u, |
929 | (ds->Count - u) * sizeof(*ds->Flags)); |
930 | } |
931 | ds->Flags[u] = rpmdsFlags(ods); |
932 | |
933 | if (ds->ti || ods->ti) { |
934 | ds->ti = xrealloc(ds->ti, (ds->Count+1) * sizeof(*ds->ti))rrealloc((ds->ti), ((ds->Count+1) * sizeof(*ds->ti)) ); |
935 | if (u < ds->Count) { |
936 | memmove(ds->ti + u + 1, ds->ti + u, |
937 | (ds->Count - u) * sizeof(*ds->ti)); |
938 | } |
939 | ds->ti[u] = rpmdsTi(ods); |
940 | } |
941 | |
942 | ds->i = ds->Count; |
943 | ds->Count++; |
944 | |
945 | } |
946 | ods->i = save; |
947 | return (ds->Count - ocount); |
948 | } |
949 | |
950 | |
951 | int rpmdsSearch(rpmds ds, rpmds ods) |
952 | { |
953 | int comparison; |
954 | int i, l, u; |
955 | const char *ON = rpmdsN(ods); |
956 | |
957 | if (ds == NULL((void*)0) || ods == NULL((void*)0)) |
958 | return -1; |
959 | |
960 | /* Binary search to find the [l,u) subset that contains N */ |
961 | i = -1; |
962 | l = 0; |
963 | u = ds->Count; |
964 | while (l < u) { |
965 | i = (l + u) / 2; |
966 | |
967 | comparison = strcmp(ON, rpmdsNIndex(ds, i)); |
968 | |
969 | if (comparison < 0) |
970 | u = i; |
971 | else if (comparison > 0) |
972 | l = i + 1; |
973 | else { |
974 | /* Set l to 1st member of set that contains N. */ |
975 | if (!rstreq(ON, rpmdsNIndex(ds, l))) |
976 | l = i; |
977 | while (l > 0 && rstreq(ON, rpmdsNIndex(ds, l-1))) |
978 | l--; |
979 | /* Set u to 1st member of set that does not contain N. */ |
980 | if (u >= ds->Count || !rstreq(ON, rpmdsNIndex(ds, u))) |
981 | u = i; |
982 | while (++u < ds->Count) { |
983 | if (!rstreq(ON, rpmdsNIndex(ds, u))) |
984 | break; |
985 | } |
986 | break; |
987 | } |
988 | } |
989 | |
990 | /* Check each member of [l,u) subset for ranges overlap. */ |
991 | i = -1; |
992 | if (l < u) { |
993 | int save = rpmdsSetIx(ds, l-1); |
994 | while ((l = rpmdsNext(ds)) >= 0 && (l < u)) { |
995 | if ((i = rpmdsCompare(ods, ds)) != 0) |
996 | break; |
997 | } |
998 | /* Return element index that overlaps, or -1. */ |
999 | if (i) |
1000 | i = rpmdsIx(ds); |
1001 | else { |
1002 | (void) rpmdsSetIx(ds, save); |
1003 | i = -1; |
1004 | } |
1005 | } |
1006 | return i; |
1007 | } |
1008 | /** |
1009 | * Split EVR into epoch, version, and release components. |
1010 | * @param evr [epoch:]version[-release] string |
1011 | * @retval *ep pointer to epoch |
1012 | * @retval *vp pointer to version |
1013 | * @retval *rp pointer to release |
1014 | */ |
1015 | static |
1016 | void parseEVR(char * evr, |
1017 | const char ** ep, |
1018 | const char ** vp, |
1019 | const char ** rp) |
1020 | { |
1021 | const char *epoch; |
1022 | const char *version; /* assume only version is present */ |
1023 | const char *release; |
1024 | char *s, *se; |
1025 | |
1026 | s = evr; |
1027 | while (*s && risdigit(*s)) s++; /* s points to epoch terminator */ |
1028 | se = strrchr(s, '-'); /* se points to version terminator */ |
1029 | |
1030 | if (*s == ':') { |
1031 | epoch = evr; |
1032 | *s++ = '\0'; |
1033 | version = s; |
1034 | if (*epoch == '\0') epoch = "0"; |
1035 | } else { |
1036 | epoch = NULL((void*)0); /* XXX disable epoch compare if missing */ |
1037 | version = evr; |
1038 | } |
1039 | if (se) { |
1040 | *se++ = '\0'; |
1041 | release = se; |
1042 | } else { |
1043 | release = NULL((void*)0); |
1044 | } |
1045 | |
1046 | if (ep) *ep = epoch; |
1047 | if (vp) *vp = version; |
1048 | if (rp) *rp = release; |
1049 | } |
1050 | |
1051 | static inline int rpmdsCompareEVR(const char *AEVR, uint32_t AFlags, |
1052 | const char *BEVR, uint32_t BFlags, |
1053 | int nopromote) |
1054 | { |
1055 | const char *aE, *aV, *aR, *bE, *bV, *bR; |
1056 | char *aEVR = xstrdup(AEVR)rstrdup((AEVR)); |
1057 | char *bEVR = xstrdup(BEVR)rstrdup((BEVR)); |
1058 | int sense = 0; |
1059 | int result = 0; |
1060 | |
1061 | parseEVR(aEVR, &aE, &aV, &aR); |
1062 | parseEVR(bEVR, &bE, &bV, &bR); |
1063 | |
1064 | /* Compare {A,B} [epoch:]version[-release] */ |
1065 | if (aE && *aE && bE && *bE) |
1066 | sense = rpmvercmp(aE, bE); |
1067 | else if (aE && *aE && atol(aE) > 0) { |
1068 | if (!nopromote) { |
1069 | sense = 0; |
1070 | } else |
1071 | sense = 1; |
1072 | } else if (bE && *bE && atol(bE) > 0) |
1073 | sense = -1; |
1074 | |
1075 | if (sense == 0) { |
1076 | sense = rpmvercmp(aV, bV); |
1077 | if (sense == 0) { |
1078 | if (aR && *aR && bR && *bR) { |
1079 | sense = rpmvercmp(aR, bR); |
1080 | } else { |
1081 | /* always matches if the side with no release has SENSE_EQUAL */ |
1082 | if ((aR && *aR && (BFlags & RPMSENSE_EQUAL)) || |
1083 | (bR && *bR && (AFlags & RPMSENSE_EQUAL))) { |
1084 | aEVR = _free(aEVR)rfree((aEVR)); |
1085 | bEVR = _free(bEVR)rfree((bEVR)); |
1086 | result = 1; |
1087 | goto exit; |
1088 | } |
1089 | } |
1090 | } |
1091 | } |
1092 | |
1093 | /* Detect overlap of {A,B} range. */ |
1094 | if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) { |
1095 | result = 1; |
1096 | } else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) { |
1097 | result = 1; |
1098 | } else if (sense == 0 && |
1099 | (((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) || |
1100 | ((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) || |
1101 | ((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) { |
1102 | result = 1; |
1103 | } |
1104 | |
1105 | exit: |
1106 | free(aEVR); |
1107 | free(bEVR); |
1108 | return result; |
1109 | } |
1110 | |
1111 | int rpmdsCompareIndex(rpmds A, int aix, rpmds B, int bix) |
1112 | { |
1113 | const char *AEVR, *BEVR; |
1114 | rpmsenseFlags AFlags, BFlags; |
1115 | int result; |
1116 | |
1117 | /* Different names don't overlap. */ |
1118 | if (!rpmstrPoolStreq(A->pool, rpmdsNIdIndex(A, aix), |
1119 | B->pool, rpmdsNIdIndex(B, bix))) { |
1120 | result = 0; |
1121 | goto exit; |
1122 | } |
1123 | |
1124 | /* XXX rpm prior to 3.0.2 did not always supply EVR and Flags. */ |
1125 | if (!(A->EVR && A->Flags && B->EVR && B->Flags)) { |
1126 | result = 1; |
1127 | goto exit; |
1128 | } |
1129 | |
1130 | /* Same name. If either A or B is an existence test, always overlap. */ |
1131 | AFlags = rpmdsFlagsIndex(A, aix); |
1132 | BFlags = rpmdsFlagsIndex(B, bix); |
1133 | if (!((AFlags & RPMSENSE_SENSEMASK15) && (BFlags & RPMSENSE_SENSEMASK15))) { |
1134 | result = 1; |
1135 | goto exit; |
1136 | } |
1137 | |
1138 | AEVR = rpmdsEVRIndex(A, aix); |
1139 | BEVR = rpmdsEVRIndex(B, bix); |
1140 | if (!(AEVR && *AEVR && BEVR && *BEVR)) { |
1141 | /* If either EVR is non-existent or empty, always overlap. */ |
1142 | result = 1; |
1143 | } else { |
1144 | /* Both AEVR and BEVR exist, compare [epoch:]version[-release]. */ |
1145 | result = rpmdsCompareEVR(AEVR, AFlags, BEVR, BFlags, B->nopromote); |
1146 | } |
1147 | |
1148 | exit: |
1149 | return result; |
1150 | } |
1151 | |
1152 | int rpmdsCompare(const rpmds A, const rpmds B) |
1153 | { |
1154 | return rpmdsCompareIndex(A, A->i, B, B->i); |
1155 | } |
1156 | |
1157 | int rpmdsMatches(rpmstrPool pool, Header h, int prix, |
1158 | rpmds req, int selfevr, int nopromote) |
1159 | { |
1160 | rpmds provides; |
1161 | rpmTagVal tag = RPMTAG_PROVIDENAME; |
1162 | int result = 0; |
1163 | |
1164 | /* Get provides information from header */ |
1165 | if (selfevr) |
1166 | provides = rpmdsThisPool(pool, h, tag, RPMSENSE_EQUAL); |
1167 | else |
1168 | provides = rpmdsNewPool(pool, h, tag, 0); |
1169 | |
1170 | rpmdsSetNoPromote(provides, nopromote); |
1171 | |
1172 | /* |
1173 | * For a self-provide and indexed provide, we only need one comparison. |
1174 | * Otherwise loop through the provides until match or end. |
1175 | */ |
1176 | if (prix >= 0 || selfevr) { |
1177 | if (prix >= 0) |
1178 | rpmdsSetIx(provides, prix); |
1179 | result = rpmdsCompare(provides, req); |
1180 | } else { |
1181 | provides = rpmdsInit(provides); |
1182 | while (rpmdsNext(provides) >= 0) { |
1183 | result = rpmdsCompare(provides, req); |
1184 | /* If this provide matches the require, we're done. */ |
1185 | if (result) |
1186 | break; |
1187 | } |
1188 | } |
1189 | |
1190 | rpmdsFree(provides); |
1191 | return result; |
1192 | } |
1193 | |
1194 | int rpmdsMatchesDep (const Header h, int ix, const rpmds req, int nopromote) |
1195 | { |
1196 | return rpmdsMatches(NULL((void*)0), h, ix, req, 0, nopromote); |
1197 | } |
1198 | |
1199 | int rpmdsAnyMatchesDep (const Header h, const rpmds req, int nopromote) |
1200 | { |
1201 | return rpmdsMatches(NULL((void*)0), h, -1, req, 0, nopromote); |
1202 | } |
1203 | |
1204 | int rpmdsNVRMatchesDep(const Header h, const rpmds req, int nopromote) |
1205 | { |
1206 | return rpmdsMatches(NULL((void*)0), h, -1, req, 1, nopromote); |
1207 | } |
1208 | |
1209 | /** |
1210 | */ |
1211 | struct rpmlibProvides_s { |
1212 | const char * featureName; |
1213 | const char * featureEVR; |
1214 | rpmsenseFlags featureFlags; |
1215 | const char * featureDescription; |
1216 | }; |
1217 | |
1218 | static const struct rpmlibProvides_s rpmlibProvides[] = { |
1219 | { "rpmlib(VersionedDependencies)", "3.0.3-1", |
1220 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1221 | N_("PreReq:, Provides:, and Obsoletes: dependencies support versions.")"PreReq:, Provides:, and Obsoletes: dependencies support versions." }, |
1222 | { "rpmlib(CompressedFileNames)", "3.0.4-1", |
1223 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1224 | N_("file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path.")"file name(s) stored as (dirName,baseName,dirIndex) tuple, not as path."}, |
1225 | #if HAVE_BZLIB_H1 |
1226 | { "rpmlib(PayloadIsBzip2)", "3.0.5-1", |
1227 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1228 | N_("package payload can be compressed using bzip2.")"package payload can be compressed using bzip2." }, |
1229 | #endif |
1230 | #if HAVE_LZMA_H1 |
1231 | { "rpmlib(PayloadIsXz)", "5.2-1", |
1232 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1233 | N_("package payload can be compressed using xz.")"package payload can be compressed using xz." }, |
1234 | { "rpmlib(PayloadIsLzma)", "4.4.2-1", |
1235 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1236 | N_("package payload can be compressed using lzma.")"package payload can be compressed using lzma." }, |
1237 | #endif |
1238 | { "rpmlib(PayloadFilesHavePrefix)", "4.0-1", |
1239 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1240 | N_("package payload file(s) have \"./\" prefix.")"package payload file(s) have \"./\" prefix." }, |
1241 | { "rpmlib(ExplicitPackageProvide)", "4.0-1", |
1242 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1243 | N_("package name-version-release is not implicitly provided.")"package name-version-release is not implicitly provided." }, |
1244 | { "rpmlib(HeaderLoadSortsTags)", "4.0.1-1", |
1245 | ( RPMSENSE_EQUAL), |
1246 | N_("header tags are always sorted after being loaded.")"header tags are always sorted after being loaded." }, |
1247 | { "rpmlib(ScriptletInterpreterArgs)", "4.0.3-1", |
1248 | ( RPMSENSE_EQUAL), |
1249 | N_("the scriptlet interpreter can use arguments from header.")"the scriptlet interpreter can use arguments from header." }, |
1250 | { "rpmlib(PartialHardlinkSets)", "4.0.4-1", |
1251 | ( RPMSENSE_EQUAL), |
1252 | N_("a hardlink file set may be installed without being complete.")"a hardlink file set may be installed without being complete." }, |
1253 | { "rpmlib(ConcurrentAccess)", "4.1-1", |
1254 | ( RPMSENSE_EQUAL), |
1255 | N_("package scriptlets may access the rpm database while installing.")"package scriptlets may access the rpm database while installing." }, |
1256 | #ifdef WITH_LUA1 |
1257 | { "rpmlib(BuiltinLuaScripts)", "4.2.2-1", |
1258 | ( RPMSENSE_EQUAL), |
1259 | N_("internal support for lua scripts.")"internal support for lua scripts." }, |
1260 | #endif |
1261 | { "rpmlib(FileDigests)", "4.6.0-1", |
1262 | ( RPMSENSE_EQUAL), |
1263 | N_("file digest algorithm is per package configurable")"file digest algorithm is per package configurable" }, |
1264 | #ifdef WITH_CAP |
1265 | { "rpmlib(FileCaps)", "4.6.1-1", |
1266 | ( RPMSENSE_EQUAL), |
1267 | N_("support for POSIX.1e file capabilities")"support for POSIX.1e file capabilities" }, |
1268 | #endif |
1269 | { "rpmlib(ScriptletExpansion)", "4.9.0-1", |
1270 | ( RPMSENSE_EQUAL), |
1271 | N_("package scriptlets can be expanded at install time.")"package scriptlets can be expanded at install time." }, |
1272 | { "rpmlib(TildeInVersions)", "4.10.0-1", |
1273 | ( RPMSENSE_EQUAL), |
1274 | N_("dependency comparison supports versions with tilde.")"dependency comparison supports versions with tilde." }, |
1275 | { "rpmlib(LargeFiles)", "4.12.0-1", |
1276 | ( RPMSENSE_EQUAL), |
1277 | N_("support files larger than 4GB")"support files larger than 4GB" }, |
1278 | { "rpmlib(RichDependencies)", "4.12.0-1", |
1279 | ( RPMSENSE_EQUAL), |
1280 | N_("support for rich dependencies.")"support for rich dependencies." }, |
1281 | #ifdef HAVE_ZSTD |
1282 | { "rpmlib(PayloadIsZstd)", "5.4.18-1", |
1283 | (RPMSENSE_RPMLIB|RPMSENSE_EQUAL), |
1284 | N_("package payload can be compressed using zstd.")"package payload can be compressed using zstd." }, |
1285 | #endif |
1286 | { NULL((void*)0), NULL((void*)0), 0, NULL((void*)0) } |
1287 | }; |
1288 | |
1289 | |
1290 | int rpmdsRpmlibPool(rpmstrPool pool, rpmds * dsp, const void * tblp) |
1291 | { |
1292 | const struct rpmlibProvides_s * rltblp = tblp; |
1293 | const struct rpmlibProvides_s * rlp; |
1294 | int rc = 0; |
1295 | |
1296 | if (rltblp == NULL((void*)0)) |
1297 | rltblp = rpmlibProvides; |
1298 | |
1299 | for (rlp = rltblp; rlp->featureName != NULL((void*)0) && rc >= 0; rlp++) { |
1300 | rpmds ds = rpmdsSinglePool(pool, RPMTAG_PROVIDENAME, rlp->featureName, |
1301 | rlp->featureEVR, rlp->featureFlags); |
1302 | rc = rpmdsMerge(dsp, ds); |
1303 | rpmdsFree(ds); |
1304 | } |
1305 | /* freeze the pool to save memory, but only if private pool */ |
1306 | if (*dsp && (*dsp)->pool != pool) |
1307 | rpmstrPoolFreeze((*dsp)->pool, 0); |
1308 | return (rc < 0) ? -1 : 0; |
1309 | } |
1310 | |
1311 | int rpmdsRpmlib(rpmds * dsp, const void * tblp) |
1312 | { |
1313 | return rpmdsRpmlibPool(NULL((void*)0), dsp, tblp); |
1314 | } |
1315 | |
1316 | rpmstrPool rpmdsPool(rpmds ds) |
1317 | { |
1318 | return (ds != NULL((void*)0)) ? ds->pool : NULL((void*)0); |
1319 | } |
1320 | |
1321 | rpmsenseFlags rpmSanitizeDSFlags(rpmTagVal tagN, rpmsenseFlags Flags) |
1322 | { |
1323 | rpmsenseFlags extra = RPMSENSE_ANY; |
1324 | switch (tagN) { |
1325 | case RPMTAG_PROVIDENAME: |
1326 | extra = Flags & RPMSENSE_FIND_PROVIDES; |
1327 | break; |
1328 | case RPMTAG_TRIGGERNAME: |
1329 | case RPMTAG_FILETRIGGERNAME: |
1330 | case RPMTAG_TRANSFILETRIGGERNAME: |
1331 | extra = Flags & RPMSENSE_TRIGGER(RPMSENSE_TRIGGERPREIN | RPMSENSE_TRIGGERIN | RPMSENSE_TRIGGERUN | RPMSENSE_TRIGGERPOSTUN); |
1332 | break; |
1333 | case RPMTAG_RECOMMENDNAME: |
1334 | case RPMTAG_SUGGESTNAME: |
1335 | case RPMTAG_SUPPLEMENTNAME: |
1336 | case RPMTAG_ENHANCENAME: |
1337 | case RPMTAG_REQUIRENAME: |
1338 | extra = Flags & (_ALL_REQUIRES_MASK( RPMSENSE_INTERP | RPMSENSE_SCRIPT_PRE | RPMSENSE_SCRIPT_POST | RPMSENSE_SCRIPT_PREUN | RPMSENSE_SCRIPT_POSTUN | RPMSENSE_SCRIPT_VERIFY | RPMSENSE_FIND_REQUIRES | RPMSENSE_RPMLIB | RPMSENSE_KEYRING | RPMSENSE_PRETRANS | RPMSENSE_POSTTRANS | RPMSENSE_PREREQ | RPMSENSE_MISSINGOK)); |
1339 | break; |
1340 | case RPMTAG_CONFLICTNAME: |
1341 | extra = Flags; |
1342 | break; |
1343 | default: |
1344 | break; |
1345 | } |
1346 | return (Flags & RPMSENSE_SENSEMASK15) | extra; |
1347 | } |
1348 | |
1349 | static struct ReqComp { |
1350 | const char * token; |
1351 | rpmsenseFlags sense; |
1352 | } const ReqComparisons[] = { |
1353 | { "<=", RPMSENSE_LESS | RPMSENSE_EQUAL}, |
1354 | { "=<", RPMSENSE_LESS | RPMSENSE_EQUAL}, |
1355 | { "<", RPMSENSE_LESS}, |
1356 | |
1357 | { "==", RPMSENSE_EQUAL}, |
1358 | { "=", RPMSENSE_EQUAL}, |
1359 | |
1360 | { ">=", RPMSENSE_GREATER | RPMSENSE_EQUAL}, |
1361 | { "=>", RPMSENSE_GREATER | RPMSENSE_EQUAL}, |
1362 | { ">", RPMSENSE_GREATER}, |
1363 | |
1364 | { NULL((void*)0), 0 }, |
1365 | }; |
1366 | |
1367 | rpmsenseFlags rpmParseDSFlags(const char *str, size_t len) |
1368 | { |
1369 | const struct ReqComp *rc; |
1370 | for (rc = ReqComparisons; rc->token != NULL((void*)0); rc++) |
1371 | if (len == strlen(rc->token) && rstreqn(str, rc->token, len)) |
1372 | return rc->sense; |
1373 | return 0; |
1374 | } |
1375 | |
1376 | static struct RichOpComp { |
1377 | const char * token; |
1378 | rpmrichOp op; |
1379 | } const RichOps[] = { |
1380 | { "and", RPMRICHOP_AND}, |
1381 | { "or", RPMRICHOP_OR}, |
1382 | { "if", RPMRICHOP_IF}, |
1383 | { "else", RPMRICHOP_ELSE}, |
1384 | { "with", RPMRICHOP_WITH}, |
1385 | { "without", RPMRICHOP_WITHOUT}, |
1386 | { NULL((void*)0), 0 }, |
1387 | }; |
1388 | |
1389 | int rpmdsIsRich(rpmds dep) |
1390 | { |
1391 | const char * n = rpmdsN(dep); |
1392 | return (n && n[0] == '('); |
1393 | } |
1394 | |
1395 | static rpmRC parseRichDepOp(const char **dstrp, rpmrichOp *opp, char **emsg) |
1396 | { |
1397 | const char *p = *dstrp, *pe = p; |
1398 | const struct RichOpComp *ro; |
1399 | |
1400 | while (*pe && !risspace(*pe) && *pe != ')') |
1401 | pe++; |
1402 | for (ro = RichOps; ro->token != NULL((void*)0); ro++) |
1403 | if (pe - p == strlen(ro->token) && rstreqn(p, ro->token, pe - p)) { |
1404 | *opp = ro->op; |
1405 | *dstrp = pe; |
1406 | return RPMRC_OK; |
1407 | } |
1408 | if (emsg) |
1409 | rasprintf(emsg, _("Unknown rich dependency op '%.*s'")dcgettext ("rpm", "Unknown rich dependency op '%.*s'", 5), (int)(pe - p), p); |
1410 | return RPMRC_FAIL; |
1411 | } |
1412 | |
1413 | const char *rpmrichOpStr(rpmrichOp op) |
1414 | { |
1415 | if (op == RPMRICHOP_SINGLE) |
1416 | return "SINGLE"; |
1417 | if (op == RPMRICHOP_AND) |
1418 | return "and"; |
1419 | if (op == RPMRICHOP_OR) |
1420 | return "or"; |
1421 | if (op == RPMRICHOP_IF) |
1422 | return "if"; |
1423 | if (op == RPMRICHOP_ELSE) |
1424 | return "else"; |
1425 | if (op == RPMRICHOP_WITH) |
1426 | return "with"; |
1427 | if (op == RPMRICHOP_WITHOUT) |
1428 | return "without"; |
1429 | return NULL((void*)0); |
1430 | } |
1431 | |
1432 | |
1433 | #define SKIPWHITE(_x){while (*(_x) && (risspace(*_x) || *(_x) == ',')) (_x )++;} {while (*(_x) && (risspace(*_x) || *(_x) == ',')) (_x)++;} |
1434 | #define SKIPNONWHITEX(_x){int bl = 0; while (*(_x) &&!(risspace(*_x) || *(_x) == ',' || (*(_x) == ')' && bl-- <= 0))) if (*(_x)++ == '(') bl++;}{int bl = 0; while (*(_x) &&!(risspace(*_x) || *(_x) == ',' || (*(_x) == ')' && bl-- <= 0))) if (*(_x)++ == '(') bl++;} |
1435 | |
1436 | static rpmRC parseSimpleDep(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata) |
1437 | { |
1438 | const char *p = *dstrp; |
1439 | const char *n, *e = 0; |
1440 | int nl, el = 0; |
1441 | rpmsenseFlags sense = 0; |
1442 | |
1443 | n = p; |
1444 | SKIPNONWHITEX(p){int bl = 0; while (*(p) &&!(risspace(*p) || *(p) == ',' || (*(p) == ')' && bl-- <= 0))) if (*(p)++ == '(' ) bl++;}; |
1445 | nl = p - n; |
1446 | if (nl == 0) { |
1447 | if (emsg) |
1448 | rasprintf(emsg, _("Name required")dcgettext ("rpm", "Name required", 5)); |
1449 | return RPMRC_FAIL; |
1450 | } |
1451 | SKIPWHITE(p){while (*(p) && (risspace(*p) || *(p) == ',')) (p)++; }; |
1452 | if (*p) { |
1453 | const char *pe = p; |
1454 | |
1455 | SKIPNONWHITEX(pe){int bl = 0; while (*(pe) &&!(risspace(*pe) || *(pe) == ',' || (*(pe) == ')' && bl-- <= 0))) if (*(pe)++ == '(') bl++;}; |
1456 | sense = rpmParseDSFlags(p, pe - p); |
1457 | if (sense) { |
1458 | p = pe; |
1459 | SKIPWHITE(p){while (*(p) && (risspace(*p) || *(p) == ',')) (p)++; }; |
1460 | e = p; |
1461 | SKIPNONWHITEX(p){int bl = 0; while (*(p) &&!(risspace(*p) || *(p) == ',' || (*(p) == ')' && bl-- <= 0))) if (*(p)++ == '(' ) bl++;}; |
1462 | el = p - e; |
1463 | } |
1464 | } |
1465 | if (e && el == 0) { |
1466 | if (emsg) |
1467 | rasprintf(emsg, _("Version required")dcgettext ("rpm", "Version required", 5)); |
1468 | return RPMRC_FAIL; |
1469 | } |
1470 | if (cb(cbdata, RPMRICH_PARSE_SIMPLE, n, nl, e, el, sense, RPMRICHOP_SINGLE, emsg) != RPMRC_OK) |
1471 | return RPMRC_FAIL; |
1472 | *dstrp = p; |
1473 | return RPMRC_OK; |
1474 | } |
1475 | |
1476 | static rpmRC rpmrichParseInternal(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata, int *nowithp) |
1477 | { |
1478 | const char *p = *dstrp, *pe; |
1479 | rpmrichOp op = RPMRICHOP_SINGLE, chainop = 0; |
1480 | int nowith = 0; |
1481 | |
1482 | if (cb(cbdata, RPMRICH_PARSE_ENTER, p, 0, 0, 0, 0, op, emsg) != RPMRC_OK) |
1483 | return RPMRC_FAIL; |
1484 | if (*p++ != '(') { |
1485 | if (emsg) |
1486 | rasprintf(emsg, _("Rich dependency does not start with '('")dcgettext ("rpm", "Rich dependency does not start with '('", 5 )); |
1487 | return RPMRC_FAIL; |
1488 | } |
1489 | for (;;) { |
1490 | SKIPWHITE(p){while (*(p) && (risspace(*p) || *(p) == ',')) (p)++; }; |
1491 | if (*p == ')') { |
1492 | if (emsg) { |
1493 | if (chainop) |
1494 | rasprintf(emsg, _("Missing argument to rich dependency op")dcgettext ("rpm", "Missing argument to rich dependency op", 5 )); |
1495 | else |
1496 | rasprintf(emsg, _("Empty rich dependency")dcgettext ("rpm", "Empty rich dependency", 5)); |
1497 | } |
1498 | return RPMRC_FAIL; |
1499 | } |
1500 | if (*p == '(') { |
1501 | if (rpmrichParseInternal(&p, emsg, cb, cbdata, &nowith) != RPMRC_OK) |
1502 | return RPMRC_FAIL; |
1503 | } else { |
1504 | if (parseSimpleDep(&p, emsg, cb, cbdata) != RPMRC_OK) |
1505 | return RPMRC_FAIL; |
1506 | } |
1507 | SKIPWHITE(p){while (*(p) && (risspace(*p) || *(p) == ',')) (p)++; }; |
1508 | if (!*p) { |
1509 | if (emsg) |
1510 | rasprintf(emsg, _("Unterminated rich dependency: %s")dcgettext ("rpm", "Unterminated rich dependency: %s", 5), *dstrp); |
1511 | return RPMRC_FAIL; |
1512 | } |
1513 | if (*p == ')') |
1514 | break; |
1515 | pe = p; |
1516 | if (parseRichDepOp(&pe, &op, emsg) != RPMRC_OK) |
1517 | return RPMRC_FAIL; |
1518 | if (op == RPMRICHOP_ELSE && chainop == RPMRICHOP_IF) |
1519 | chainop = 0; |
1520 | if (chainop && op != chainop) { |
1521 | if (emsg) |
1522 | rasprintf(emsg, _("Cannot chain different ops")dcgettext ("rpm", "Cannot chain different ops", 5)); |
1523 | return RPMRC_FAIL; |
1524 | } |
1525 | if (chainop && op != RPMRICHOP_AND && op != RPMRICHOP_OR && |
1526 | op != RPMRICHOP_WITH) { |
1527 | if (emsg) |
1528 | rasprintf(emsg, _("Can only chain and/or/with ops")dcgettext ("rpm", "Can only chain and/or/with ops", 5)); |
1529 | return RPMRC_FAIL; |
1530 | } |
1531 | if (cb(cbdata, RPMRICH_PARSE_OP, p, pe - p, 0, 0, 0, op, emsg) != RPMRC_OK) |
1532 | return RPMRC_FAIL; |
1533 | chainop = op; |
1534 | p = pe; |
1535 | if (nowithp && op != RPMRICHOP_WITH && op != RPMRICHOP_WITHOUT && op != RPMRICHOP_OR) |
1536 | *nowithp = 1; |
1537 | } |
1538 | if ((op == RPMRICHOP_WITH || op == RPMRICHOP_WITHOUT) && nowith) { |
1539 | if (emsg) |
1540 | rasprintf(emsg, _("Illegal ops in with/without")dcgettext ("rpm", "Illegal ops in with/without", 5)); |
1541 | return RPMRC_FAIL; |
1542 | } |
1543 | p++; |
1544 | if (cb(cbdata, RPMRICH_PARSE_LEAVE, *dstrp, p - *dstrp , 0, 0, 0, op, emsg) != RPMRC_OK) |
1545 | return RPMRC_FAIL; |
1546 | *dstrp = p; |
1547 | return RPMRC_OK; |
1548 | } |
1549 | |
1550 | rpmRC rpmrichParse(const char **dstrp, char **emsg, rpmrichParseFunction cb, void *cbdata) |
1551 | { |
1552 | return rpmrichParseInternal(dstrp, emsg, cb, cbdata, NULL((void*)0)); |
1553 | } |
1554 | |
1555 | struct rpmdsParseRichDepData { |
1556 | rpmds dep; |
1557 | rpmsenseFlags depflags; |
1558 | |
1559 | rpmds leftds; |
1560 | rpmds rightds; |
1561 | rpmrichOp op; |
1562 | |
1563 | int depth; |
1564 | const char *rightstart; |
1565 | int dochain; |
1566 | }; |
1567 | |
1568 | static rpmRC rpmdsParseRichDepCB(void *cbdata, rpmrichParseType type, |
1569 | const char *n, int nl, const char *e, int el, rpmsenseFlags sense, |
1570 | rpmrichOp op, char **emsg) { |
1571 | struct rpmdsParseRichDepData *data = cbdata; |
1572 | rpmds ds = 0; |
1573 | |
1574 | if (type == RPMRICH_PARSE_ENTER) |
1575 | data->depth++; |
1576 | else if (type == RPMRICH_PARSE_LEAVE) { |
1577 | if (--data->depth == 0 && data->dochain && data->rightstart) { |
1578 | /* chain op hack, construct a sub-ds from the right side of the chain */ |
1579 | char *right = xmalloc(n + nl - data->rightstart + 2)rmalloc((n + nl - data->rightstart + 2)); |
1580 | right[0] = '('; |
1581 | strncpy(right + 1, data->rightstart, n + nl - data->rightstart); |
1582 | right[n + nl - data->rightstart + 1] = 0; |
1583 | data->rightds = rpmdsFree(data->rightds); |
1584 | ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, data->depflags, 0, 0, 0); |
1585 | ds->N[0] = rpmstrPoolId(ds->pool, right, 1); |
1586 | ds->EVR[0] = rpmstrPoolId(ds->pool, "", 1); |
1587 | data->rightds = ds; |
1588 | free(right); |
1589 | } |
1590 | } |
1591 | if (data->depth != 1) |
1592 | return RPMRC_OK; /* we're only interested in top-level parsing */ |
1593 | if ((type == RPMRICH_PARSE_SIMPLE || type == RPMRICH_PARSE_LEAVE) && !data->dochain) { |
1594 | if (type == RPMRICH_PARSE_SIMPLE && data->dep->tagN == RPMTAG_REQUIRENAME && nl > 7 && |
1595 | rstreqn(n, "rpmlib(", sizeof("rpmlib(")-1)) |
1596 | sense |= RPMSENSE_RPMLIB; |
1597 | ds = singleDS(data->dep->pool, data->dep->tagN, 0, 0, sense | data->depflags, 0, 0, 0); |
1598 | ds->N[0] = rpmstrPoolIdn(ds->pool, n, nl, 1); |
1599 | ds->EVR[0] = rpmstrPoolIdn(ds->pool, e ? e : "", el, 1); |
1600 | if (!data->leftds) |
1601 | data->leftds = ds; |
1602 | else { |
1603 | data->rightds = ds; |
1604 | data->rightstart = n; |
1605 | } |
1606 | } |
1607 | if (type == RPMRICH_PARSE_OP) { |
1608 | if (data->op != RPMRICHOP_SINGLE) |
1609 | data->dochain = 1; /* this is a chained op */ |
1610 | else |
1611 | data->op = op; |
1612 | } |
1613 | return RPMRC_OK; |
1614 | } |
1615 | |
1616 | |
1617 | rpmRC rpmdsParseRichDep(rpmds dep, rpmds *leftds, rpmds *rightds, rpmrichOp *op, char **emsg) |
1618 | { |
1619 | rpmRC rc; |
1620 | struct rpmdsParseRichDepData data; |
1621 | const char *depstr = rpmdsN(dep); |
1622 | memset(&data, 0, sizeof(data)); |
1623 | data.dep = dep; |
1624 | data.op = RPMRICHOP_SINGLE; |
1625 | data.depflags = rpmdsFlags(dep) & ~(RPMSENSE_SENSEMASK15 | RPMSENSE_MISSINGOK); |
1626 | rc = rpmrichParse(&depstr, emsg, rpmdsParseRichDepCB, &data); |
1627 | if (rc == RPMRC_OK && *depstr) { |
1628 | if (emsg) |
1629 | rasprintf(emsg, _("Junk after rich dependency")dcgettext ("rpm", "Junk after rich dependency", 5)); |
1630 | rc = RPMRC_FAIL; |
1631 | } |
1632 | if (rc != RPMRC_OK) { |
1633 | rpmdsFree(data.leftds); |
1634 | rpmdsFree(data.rightds); |
1635 | } else { |
1636 | *leftds = data.leftds; |
1637 | *rightds = data.rightds; |
1638 | *op = data.op; |
1639 | } |
1640 | return rc; |
1641 | } |
1642 |