| File: | lib/rpmds.c |
| Warning: | line 961, column 5 Value stored to 'i' 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)); |
| 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; |
Value stored to 'i' is never read | |
| 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 |