1 /* pkg_depends.c - the opkg package management system 2 3 Steven M. Ayer 4 5 Copyright (C) 2002 Compaq Computer Corporation 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2, or (at 10 your option) any later version. 11 12 This program is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 */ 17 18 #include <stdio.h> 19 #include <ctype.h> 20 21 #include "pkg.h" 22 #include "opkg_utils.h" 23 #include "pkg_hash.h" 24 #include "opkg_message.h" 25 #include "pkg_parse.h" 26 #include "hash_table.h" 27 #include "libbb/libbb.h" 28 29 static int parseDepends(compound_depend_t * compound_depend, char *depend_str, enum depend_type type); 30 static depend_t *depend_init(void); 31 static char **add_unresolved_dep(pkg_t * pkg, char **the_lost, int ref_ndx); 32 static char **merge_unresolved(char **oldstuff, char **newstuff); 33 static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg); 34 35 static int pkg_installed_and_constraint_satisfied(pkg_t * pkg, void *cdata) 36 { 37 depend_t *depend = (depend_t *) cdata; 38 if ((pkg->state_status == SS_INSTALLED 39 || pkg->state_status == SS_UNPACKED) 40 && version_constraints_satisfied(depend, pkg)) 41 return 1; 42 else 43 return 0; 44 } 45 46 static int pkg_constraint_satisfied(pkg_t * pkg, void *cdata) 47 { 48 depend_t *depend = (depend_t *) cdata; 49 if (version_constraints_satisfied(depend, pkg)) 50 return 1; 51 else 52 return 0; 53 } 54 55 /* returns ndependencies or negative error value */ 56 int 57 pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied, 58 char ***unresolved, int pre_check) 59 { 60 pkg_t *satisfier_entry_pkg; 61 int i, j, k; 62 int found; 63 char **the_lost; 64 abstract_pkg_t *ab_pkg; 65 compound_depend_t *compound_depend; 66 char *check; 67 68 /* 69 * this is a setup to check for redundant/cyclic dependency checks, 70 * which are marked at the abstract_pkg level 71 */ 72 if (!(ab_pkg = pkg->parent)) { 73 opkg_msg(ERROR, "Internal error, with pkg %s.\n", pkg->name); 74 *unresolved = NULL; 75 return 0; 76 } 77 78 if(pre_check) { 79 check = &ab_pkg->pre_dependencies_checked; 80 } else { 81 check = &ab_pkg->dependencies_checked; 82 } 83 84 if (*check) { /* avoid duplicate or cyclic checks */ 85 *unresolved = NULL; 86 return 0; 87 } else { 88 /* mark it for subsequent visits */ 89 *check = 1; 90 } 91 92 compound_depend = pkg_get_ptr(pkg, PKG_DEPENDS); 93 94 if (!compound_depend || !compound_depend->type) { 95 *unresolved = NULL; 96 return 0; 97 } 98 99 the_lost = NULL; 100 101 /* foreach dependency */ 102 for (i = 0; compound_depend && compound_depend->type; compound_depend++, i++) { 103 depend_t **possible_satisfiers = 104 compound_depend->possibilities;; 105 found = 0; 106 satisfier_entry_pkg = NULL; 107 108 if (compound_depend->type == GREEDY_DEPEND) { 109 /* foreach possible satisfier */ 110 for (j = 0; j < compound_depend->possibility_count; j++) { 111 /* foreach provided_by, which includes the abstract_pkg itself */ 112 abstract_pkg_t *abpkg = possible_satisfiers[j]->pkg; 113 abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by; 114 int nposs = ab_provider_vec->len; 115 abstract_pkg_t **ab_providers = ab_provider_vec->pkgs; 116 int l; 117 for (l = 0; l < nposs; l++) { 118 pkg_vec_t *test_vec = ab_providers[l]->pkgs; 119 /* if no depends on this one, try the first package that Provides this one */ 120 if (!test_vec) { /* no pkg_vec hooked up to the abstract_pkg! (need another feed?) */ 121 continue; 122 } 123 124 /* cruise this possiblity's pkg_vec looking for an installed version */ 125 for (k = 0; k < test_vec->len; k++) { 126 pkg_t *pkg_scout = test_vec->pkgs[k]; 127 /* not installed, and not already known about? */ 128 if ((pkg_scout->state_want != SW_INSTALL) 129 && !(pre_check ? pkg_scout->parent->pre_dependencies_checked : pkg_scout->parent->dependencies_checked) 130 && !is_pkg_in_pkg_vec(unsatisfied, pkg_scout)) { 131 char **newstuff = NULL; 132 int rc; 133 pkg_vec_t *tmp_vec = pkg_vec_alloc(); 134 /* check for not-already-installed dependencies */ 135 rc = pkg_hash_fetch_unsatisfied_dependencies( 136 pkg_scout, tmp_vec, &newstuff, pre_check); 137 if (newstuff == NULL) { 138 int m; 139 int ok = 1; 140 for (m = 0; m < rc; m++) { 141 pkg_t *p = tmp_vec->pkgs[m]; 142 if (p->state_want == SW_INSTALL) 143 continue; 144 opkg_msg(DEBUG, 145 "Not installing %s due" 146 " to requirement for %s.\n", 147 pkg_scout->name, p->name); 148 ok = 0; 149 break; 150 } 151 pkg_vec_free(tmp_vec); 152 if (ok) { 153 /* mark this one for installation */ 154 opkg_msg(NOTICE, 155 "Adding satisfier for greedy" 156 " dependence %s.\n", 157 pkg_scout->name); 158 pkg_vec_insert(unsatisfied, pkg_scout); 159 } 160 } else { 161 opkg_msg(DEBUG, 162 "Not installing %s due to " 163 "broken depends.\n", 164 pkg_scout->name); 165 free(newstuff); 166 } 167 } 168 } 169 } 170 } 171 172 continue; 173 } 174 175 /* foreach possible satisfier, look for installed package */ 176 for (j = 0; j < compound_depend->possibility_count; j++) { 177 /* foreach provided_by, which includes the abstract_pkg itself */ 178 depend_t *dependence_to_satisfy = possible_satisfiers[j]; 179 abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg; 180 pkg_t *satisfying_pkg = 181 pkg_hash_fetch_best_installation_candidate(satisfying_apkg, 182 pkg_installed_and_constraint_satisfied, 183 dependence_to_satisfy, 1); 184 /* Being that I can't test constraing in pkg_hash, I will test it here */ 185 if (satisfying_pkg != NULL) { 186 if (!pkg_installed_and_constraint_satisfied 187 (satisfying_pkg, dependence_to_satisfy)) { 188 satisfying_pkg = NULL; 189 } 190 } 191 opkg_msg(DEBUG, "satisfying_pkg=%p\n", satisfying_pkg); 192 if (satisfying_pkg != NULL) { 193 found = 1; 194 break; 195 } 196 197 } 198 /* if nothing installed matches, then look for uninstalled satisfier */ 199 if (!found) { 200 /* foreach possible satisfier, look for installed package */ 201 for (j = 0; j < compound_depend->possibility_count; j++) { 202 /* foreach provided_by, which includes the abstract_pkg itself */ 203 depend_t *dependence_to_satisfy = possible_satisfiers[j]; 204 abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg; 205 pkg_t *satisfying_pkg = 206 pkg_hash_fetch_best_installation_candidate(satisfying_apkg, 207 pkg_constraint_satisfied, dependence_to_satisfy, 1); 208 /* Being that I can't test constraing in pkg_hash, I will test it here too */ 209 if (satisfying_pkg != NULL) { 210 if (!pkg_constraint_satisfied(satisfying_pkg, 211 dependence_to_satisfy)) { 212 satisfying_pkg = NULL; 213 } 214 } 215 216 /* user request overrides package recommendation */ 217 if (satisfying_pkg != NULL 218 && (compound_depend->type == RECOMMEND 219 || compound_depend->type == SUGGEST) 220 && (satisfying_pkg->state_want == SW_DEINSTALL 221 || satisfying_pkg->state_want == SW_PURGE)) { 222 opkg_msg(NOTICE, 223 "%s: ignoring recommendation for " 224 "%s at user request\n", 225 pkg->name, satisfying_pkg->name); 226 continue; 227 } 228 229 opkg_msg(DEBUG, "satisfying_pkg=%p\n", 230 satisfying_pkg); 231 if (satisfying_pkg != NULL) { 232 satisfier_entry_pkg = satisfying_pkg; 233 break; 234 } 235 } 236 } 237 238 /* we didn't find one, add something to the unsatisfied vector */ 239 if (!found) { 240 if (!satisfier_entry_pkg) { 241 /* failure to meet recommendations is not an error */ 242 if (compound_depend->type != RECOMMEND 243 && compound_depend->type != SUGGEST) 244 the_lost = add_unresolved_dep(pkg, the_lost, i); 245 else 246 opkg_msg(NOTICE, 247 "%s: unsatisfied recommendation for %s\n", 248 pkg->name, 249 compound_depend->possibilities[0]->pkg->name); 250 } else { 251 if (compound_depend->type == SUGGEST) { 252 /* just mention it politely */ 253 opkg_msg(NOTICE, 254 "package %s suggests installing %s\n", 255 pkg->name, satisfier_entry_pkg->name); 256 } else { 257 char **newstuff = NULL; 258 259 if (satisfier_entry_pkg != pkg && 260 !is_pkg_in_pkg_vec(unsatisfied, satisfier_entry_pkg)) 261 { 262 pkg_hash_fetch_unsatisfied_dependencies( 263 satisfier_entry_pkg, unsatisfied, &newstuff, pre_check); 264 pkg_vec_insert(unsatisfied, satisfier_entry_pkg); 265 the_lost = merge_unresolved(the_lost, newstuff); 266 if (newstuff) 267 free(newstuff); 268 } 269 } 270 } 271 } 272 } 273 *unresolved = the_lost; 274 275 return unsatisfied->len; 276 } 277 278 /*checking for conflicts !in replaces 279 If a packages conflicts with another but is also replacing it, I should not consider it a 280 really conflicts 281 returns 0 if conflicts <> replaces or 1 if conflicts == replaces 282 */ 283 static int is_pkg_a_replaces(pkg_t * pkg_scout, pkg_t * pkg) 284 { 285 abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES); 286 287 if (!replaces || !*replaces) 288 return 0; 289 290 while (*replaces) { 291 if (strcmp(pkg_scout->name, (*replaces)->name) == 0) { // Found 292 opkg_msg(DEBUG2, "Seems I've found a replace %s %s\n", 293 pkg_scout->name, (*replaces)->name); 294 return 1; 295 } 296 replaces++; 297 } 298 299 return 0; 300 } 301 302 pkg_vec_t *pkg_hash_fetch_conflicts(pkg_t * pkg) 303 { 304 pkg_vec_t *installed_conflicts, *test_vec; 305 compound_depend_t *conflicts, *conflict; 306 depend_t **possible_satisfiers; 307 depend_t *possible_satisfier; 308 int j, k; 309 abstract_pkg_t *ab_pkg; 310 pkg_t **pkg_scouts; 311 pkg_t *pkg_scout; 312 313 /* 314 * this is a setup to check for redundant/cyclic dependency checks, 315 * which are marked at the abstract_pkg level 316 */ 317 if (!(ab_pkg = pkg->parent)) { 318 opkg_msg(ERROR, "Internal error: %s not in hash table\n", 319 pkg->name); 320 return (pkg_vec_t *) NULL; 321 } 322 323 conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS); 324 if (!conflicts) { 325 return (pkg_vec_t *) NULL; 326 } 327 installed_conflicts = pkg_vec_alloc(); 328 329 /* foreach conflict */ 330 for (conflict = conflicts; conflict->type; conflict++ ) { 331 possible_satisfiers = conflicts->possibilities; 332 333 /* foreach possible satisfier */ 334 for (j = 0; j < conflicts->possibility_count; j++) { 335 possible_satisfier = possible_satisfiers[j]; 336 if (!possible_satisfier) 337 opkg_msg(ERROR, 338 "Internal error: possible_satisfier=NULL\n"); 339 if (!possible_satisfier->pkg) 340 opkg_msg(ERROR, 341 "Internal error: possible_satisfier->pkg=NULL\n"); 342 test_vec = possible_satisfier->pkg->pkgs; 343 if (test_vec) { 344 /* pkg_vec found, it is an actual package conflict 345 * cruise this possiblity's pkg_vec looking for an installed version */ 346 pkg_scouts = test_vec->pkgs; 347 for (k = 0; k < test_vec->len; k++) { 348 pkg_scout = pkg_scouts[k]; 349 if (!pkg_scout) { 350 opkg_msg(ERROR, 351 "Internal error: pkg_scout=NULL\n"); 352 continue; 353 } 354 if ((pkg_scout->state_status == SS_INSTALLED 355 || pkg_scout->state_want == SW_INSTALL) 356 && version_constraints_satisfied(possible_satisfier, 357 pkg_scout) 358 && !is_pkg_a_replaces(pkg_scout, pkg)) { 359 if (!is_pkg_in_pkg_vec(installed_conflicts, 360 pkg_scout)) { 361 pkg_vec_insert(installed_conflicts, pkg_scout); 362 } 363 } 364 } 365 } 366 } 367 conflicts++; 368 } 369 370 if (installed_conflicts->len) 371 return installed_conflicts; 372 pkg_vec_free(installed_conflicts); 373 return (pkg_vec_t *) NULL; 374 } 375 376 int version_constraints_satisfied(depend_t * depends, pkg_t * pkg) 377 { 378 pkg_t *temp; 379 int comparison; 380 381 if (depends->constraint == NONE) 382 return 1; 383 384 temp = pkg_new(); 385 386 parse_version(temp, depends->version); 387 388 comparison = pkg_compare_versions(pkg, temp); 389 390 pkg_deinit(temp); 391 free(temp); 392 393 if ((depends->constraint == EARLIER) && (comparison < 0)) 394 return 1; 395 else if ((depends->constraint == LATER) && (comparison > 0)) 396 return 1; 397 else if (comparison == 0) 398 return 1; 399 else if ((depends->constraint == LATER_EQUAL) && (comparison >= 0)) 400 return 1; 401 else if ((depends->constraint == EARLIER_EQUAL) && (comparison <= 0)) 402 return 1; 403 404 return 0; 405 } 406 407 int pkg_dependence_satisfiable(depend_t * depend) 408 { 409 abstract_pkg_t *apkg = depend->pkg; 410 abstract_pkg_vec_t *provider_apkgs = apkg->provided_by; 411 int n_providers = provider_apkgs->len; 412 abstract_pkg_t **apkgs = provider_apkgs->pkgs; 413 pkg_vec_t *pkg_vec; 414 int n_pkgs; 415 int i; 416 int j; 417 418 for (i = 0; i < n_providers; i++) { 419 abstract_pkg_t *papkg = apkgs[i]; 420 pkg_vec = papkg->pkgs; 421 if (pkg_vec) { 422 n_pkgs = pkg_vec->len; 423 for (j = 0; j < n_pkgs; j++) { 424 pkg_t *pkg = pkg_vec->pkgs[j]; 425 if (version_constraints_satisfied(depend, pkg)) { 426 return 1; 427 } 428 } 429 } 430 } 431 return 0; 432 } 433 434 static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg) 435 { 436 int i; 437 char *arch1, *arch2; 438 pkg_t **pkgs = vec->pkgs; 439 arch1 = pkg_get_architecture(pkg); 440 441 for (i = 0; i < vec->len; i++) { 442 arch2 = pkg_get_architecture(*(pkgs + i)); 443 444 if ((strcmp(pkg->name, (*(pkgs + i))->name) == 0) 445 && (pkg_compare_versions(pkg, *(pkgs + i)) == 0) 446 && (strcmp(arch1, arch2) == 0)) 447 return 1; 448 } 449 return 0; 450 } 451 452 /** 453 * pkg_replaces returns 1 if pkg->replaces contains one of replacee's provides and 0 454 * otherwise. 455 */ 456 int pkg_replaces(pkg_t * pkg, pkg_t * replacee) 457 { 458 abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES); 459 abstract_pkg_t **provides = pkg_get_ptr(replacee, PKG_PROVIDES); 460 abstract_pkg_t **r, **p; 461 462 for (r = replaces; r && *r; r++) 463 for (p = provides; p && *p; p++) 464 if (*r == *p) 465 return 1; 466 467 return 0; 468 } 469 470 /** 471 * pkg_conflicts_abstract returns 1 if pkg->conflicts contains conflictee and 0 472 * otherwise. 473 */ 474 int pkg_conflicts_abstract(pkg_t * pkg, abstract_pkg_t * conflictee) 475 { 476 int i, j; 477 compound_depend_t *conflicts; 478 479 for (conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; conflicts && conflicts[i].type; i++) 480 for (j = 0; j < conflicts[i].possibility_count; j++) 481 if (conflicts[i].possibilities[j]->pkg == conflictee) 482 return 1; 483 484 return 0; 485 } 486 487 /** 488 * pkg_conflicts returns 1 if pkg->conflicts contains one of 489 * conflictee's provides and 0 otherwise. 490 */ 491 int pkg_conflicts(pkg_t * pkg, pkg_t * conflictee) 492 { 493 int i, j; 494 compound_depend_t *conflicts; 495 abstract_pkg_t **provider; 496 497 for (conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; conflicts && conflicts[i].type; i++) 498 for (j = 0; j < conflicts[i].possibility_count; j++) 499 for (provider = pkg_get_ptr(conflictee, PKG_PROVIDES); provider && *provider; provider++) 500 if (conflicts[i].possibilities[j]->pkg == *provider) 501 return 1; 502 503 return 0; 504 } 505 506 static char **merge_unresolved(char **oldstuff, char **newstuff) 507 { 508 int oldlen = 0, newlen = 0; 509 char **result; 510 int i, j; 511 512 if (!newstuff) 513 return oldstuff; 514 515 while (oldstuff && oldstuff[oldlen]) 516 oldlen++; 517 while (newstuff && newstuff[newlen]) 518 newlen++; 519 520 result = xrealloc(oldstuff, sizeof(char *) * (oldlen + newlen + 1)); 521 522 for (i = oldlen, j = 0; i < (oldlen + newlen); i++, j++) 523 *(result + i) = *(newstuff + j); 524 525 *(result + i) = NULL; 526 527 return result; 528 } 529 530 /* 531 * a kinda kludgy way to back out depends str from two different arrays (reg'l'r 'n pre) 532 * this is null terminated, no count is carried around 533 */ 534 char **add_unresolved_dep(pkg_t * pkg, char **the_lost, int ref_ndx) 535 { 536 int count; 537 char **resized; 538 539 count = 0; 540 while (the_lost && the_lost[count]) 541 count++; 542 543 count++; /* need one to hold the null */ 544 resized = xrealloc(the_lost, sizeof(char *) * (count + 1)); 545 resized[count - 1] = pkg_depend_str(pkg, ref_ndx); 546 resized[count] = NULL; 547 548 return resized; 549 } 550 551 static void flag_related_packages(pkg_t *pkg, int state_flags) 552 { 553 int i, j; 554 compound_depend_t *deps; 555 556 for (deps = pkg_get_ptr(pkg, PKG_DEPENDS), i = 0; deps && deps[i].type; i++) 557 for (j = 0; j < deps[i].possibility_count; j++) { 558 if ((deps[i].possibilities[j]->pkg->state_flag & state_flags) != state_flags) { 559 opkg_msg(DEBUG, "propagating pkg flag to dependent abpkg %s\n", 560 deps[i].possibilities[j]->pkg->name); 561 deps[i].possibilities[j]->pkg->state_flag |= state_flags; 562 } 563 } 564 565 for (deps = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; deps && deps[i].type; i++) 566 for (j = 0; j < deps[i].possibility_count; j++) { 567 if ((deps[i].possibilities[j]->pkg->state_flag & state_flags) != state_flags) { 568 opkg_msg(DEBUG, "propagating pkg flag to conflicting abpkg %s\n", 569 deps[i].possibilities[j]->pkg->name); 570 deps[i].possibilities[j]->pkg->state_flag |= state_flags; 571 } 572 } 573 } 574 575 abstract_pkg_t **init_providelist(pkg_t *pkg, int *count) 576 { 577 abstract_pkg_t *ab_pkg; 578 abstract_pkg_t **provides = pkg_get_ptr(pkg, PKG_PROVIDES); 579 580 if (!provides) { 581 provides = calloc(2, sizeof(abstract_pkg_t *)); 582 583 if (!provides) { 584 if (count) 585 *count = 0; 586 587 return NULL; 588 } 589 590 ab_pkg = ensure_abstract_pkg_by_name(pkg->name); 591 592 if (!ab_pkg->pkgs) 593 ab_pkg->pkgs = pkg_vec_alloc(); 594 595 if (!abstract_pkg_vec_contains(ab_pkg->provided_by, ab_pkg)) 596 abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg); 597 598 provides[0] = ab_pkg; 599 provides[1] = NULL; 600 601 if (count) 602 *count = 2; 603 604 pkg_set_ptr(pkg, PKG_PROVIDES, provides); 605 } 606 else if (count) { 607 for (*count = 1; *provides; provides++) { 608 if (pkg->state_flag & SF_NEED_DETAIL) { 609 if (!((*provides)->state_flag & SF_NEED_DETAIL)) { 610 opkg_msg(DEBUG, "propagating pkg flag to provided abpkg %s\n", 611 (*provides)->name); 612 (*provides)->state_flag |= SF_NEED_DETAIL; 613 } 614 } 615 (*count)++; 616 } 617 } 618 619 flag_related_packages(pkg, SF_NEED_DETAIL); 620 621 return provides; 622 } 623 624 void parse_providelist(pkg_t *pkg, char *list) 625 { 626 int count = 0; 627 char *item, *tok; 628 abstract_pkg_t *ab_pkg, *provided_abpkg, **tmp, **provides; 629 630 provides = init_providelist(pkg, &count); 631 ab_pkg = ensure_abstract_pkg_by_name(pkg->name); 632 633 if (!provides || !ab_pkg) 634 return; 635 636 for (item = strtok_r(list, ", ", &tok); item; 637 count++, item = strtok_r(NULL, ", ", &tok)) { 638 tmp = realloc(provides, sizeof(abstract_pkg_t *) * (count + 1)); 639 640 if (!tmp) 641 break; 642 643 provided_abpkg = ensure_abstract_pkg_by_name(item); 644 645 if (provided_abpkg->state_flag & SF_NEED_DETAIL) { 646 if (!(ab_pkg->state_flag & SF_NEED_DETAIL)) { 647 opkg_msg(DEBUG, "propagating provided abpkg flag to " 648 "provider abpkg %s\n", ab_pkg->name); 649 ab_pkg->state_flag |= SF_NEED_DETAIL; 650 } 651 } 652 653 if (!abstract_pkg_vec_contains(provided_abpkg->provided_by, ab_pkg)) 654 abstract_pkg_vec_insert(provided_abpkg->provided_by, ab_pkg); 655 656 provides = tmp; 657 provides[count - 1] = provided_abpkg; 658 } 659 660 provides[count - 1] = NULL; 661 662 pkg_set_ptr(pkg, PKG_PROVIDES, provides); 663 } 664 665 void parse_replacelist(pkg_t *pkg, char *list) 666 { 667 int count; 668 char *item, *tok; 669 abstract_pkg_t *ab_pkg, *old_abpkg, **tmp, **replaces = NULL; 670 671 ab_pkg = ensure_abstract_pkg_by_name(pkg->name); 672 673 if (!ab_pkg->pkgs) 674 ab_pkg->pkgs = pkg_vec_alloc(); 675 676 abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg); 677 678 for (count = 1, item = strtok_r(list, ", ", &tok); item; 679 count++, item = strtok_r(NULL, ", ", &tok)) { 680 tmp = realloc(replaces, sizeof(abstract_pkg_t *) * (count + 1)); 681 682 if (!tmp) 683 break; 684 685 old_abpkg = ensure_abstract_pkg_by_name(item); 686 687 if (pkg->state_flag & SF_NEED_DETAIL) { 688 if (!(old_abpkg->state_flag & SF_NEED_DETAIL)) { 689 opkg_msg(DEBUG, "propagating pkg flag to replaced abpkg %s\n", 690 old_abpkg->name); 691 old_abpkg->state_flag |= SF_NEED_DETAIL; 692 } 693 } 694 695 if (!old_abpkg->replaced_by) 696 old_abpkg->replaced_by = abstract_pkg_vec_alloc(); 697 698 /* if a package pkg both replaces and conflicts old_abpkg, 699 * then add it to the replaced_by vector so that old_abpkg 700 * will be upgraded to ab_pkg automatically */ 701 if (pkg_conflicts_abstract(pkg, old_abpkg)) { 702 if (!abstract_pkg_vec_contains(old_abpkg->replaced_by, ab_pkg)) 703 abstract_pkg_vec_insert(old_abpkg->replaced_by, ab_pkg); 704 } 705 706 replaces = tmp; 707 replaces[count - 1] = old_abpkg; 708 } 709 710 if (!replaces) 711 return; 712 713 replaces[count - 1] = NULL; 714 715 pkg_set_ptr(pkg, PKG_REPLACES, replaces); 716 } 717 718 void buildProvides(abstract_pkg_t * ab_pkg, pkg_t * pkg) 719 { 720 #if 0 721 int i; 722 723 /* every pkg provides itself */ 724 pkg->provides_count++; 725 abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg); 726 pkg->provides = xcalloc(pkg->provides_count, sizeof(abstract_pkg_t *)); 727 pkg->provides[0] = ab_pkg; 728 for (i = 1; i < pkg->provides_count; i++) { 729 abstract_pkg_t *provided_abpkg = 730 ensure_abstract_pkg_by_name(pkg->provides_str[i - 1]); 731 free(pkg->provides_str[i - 1]); 732 733 pkg->provides[i] = provided_abpkg; 734 735 abstract_pkg_vec_insert(provided_abpkg->provided_by, ab_pkg); 736 } 737 if (pkg->provides_str) 738 free(pkg->provides_str); 739 #endif 740 } 741 742 void buildConflicts(pkg_t * pkg) 743 { 744 /* 745 int i; 746 compound_depend_t *conflicts, *conflict; 747 748 if (!pkg->conflicts_count) 749 return; 750 751 conflicts = pkg->conflicts = 752 xcalloc(pkg->conflicts_count, sizeof(compound_depend_t)); 753 for (i = 0; i < pkg->conflicts_count; i++) { 754 conflicts->type = CONFLICTS; 755 parseDepends(conflicts, pkg->conflicts_str[i]); 756 free(pkg->conflicts_str[i]); 757 conflicts++; 758 } 759 if (pkg->conflicts_str) 760 free(pkg->conflicts_str); 761 */ 762 } 763 764 void buildReplaces(abstract_pkg_t * ab_pkg, pkg_t * pkg) 765 { 766 #if 0 767 int i; 768 769 if (!pkg->replaces_count) 770 return; 771 772 pkg->replaces = xcalloc(pkg->replaces_count, sizeof(abstract_pkg_t *)); 773 774 for (i = 0; i < pkg->replaces_count; i++) { 775 abstract_pkg_t *old_abpkg = 776 ensure_abstract_pkg_by_name(pkg->replaces_str[i]); 777 778 pkg->replaces[i] = old_abpkg; 779 free(pkg->replaces_str[i]); 780 781 if (!old_abpkg->replaced_by) 782 old_abpkg->replaced_by = abstract_pkg_vec_alloc(); 783 /* if a package pkg both replaces and conflicts old_abpkg, 784 * then add it to the replaced_by vector so that old_abpkg 785 * will be upgraded to ab_pkg automatically */ 786 if (pkg_conflicts_abstract(pkg, old_abpkg)) 787 abstract_pkg_vec_insert(old_abpkg->replaced_by, ab_pkg); 788 } 789 790 if (pkg->replaces_str) 791 free(pkg->replaces_str); 792 #endif 793 } 794 795 void parse_deplist(pkg_t *pkg, enum depend_type type, char *list) 796 { 797 int id, count; 798 char *item, *tok; 799 compound_depend_t *tmp, *deps; 800 801 switch (type) 802 { 803 case DEPEND: 804 case PREDEPEND: 805 case RECOMMEND: 806 case SUGGEST: 807 case GREEDY_DEPEND: 808 id = PKG_DEPENDS; 809 break; 810 811 case CONFLICTS: 812 id = PKG_CONFLICTS; 813 break; 814 815 default: 816 return; 817 } 818 819 deps = pkg_get_ptr(pkg, id); 820 821 for (tmp = deps, count = 1; tmp && tmp->type; tmp++) 822 count++; 823 824 for (item = strtok_r(list, ",", &tok); item; item = strtok_r(NULL, ",", &tok), count++) { 825 tmp = realloc(deps, sizeof(compound_depend_t) * (count + 1)); 826 827 if (!tmp) 828 break; 829 830 deps = tmp; 831 832 memset(deps + count - 1, 0, sizeof(compound_depend_t)); 833 parseDepends(deps + count - 1, item, type); 834 } 835 836 if (!deps) 837 return; 838 839 memset(deps + count - 1, 0, sizeof(compound_depend_t)); 840 pkg_set_ptr(pkg, id, deps); 841 } 842 843 void buildDepends(pkg_t * pkg) 844 { 845 #if 0 846 unsigned int count; 847 int i; 848 compound_depend_t *depends; 849 850 if (! 851 (count = 852 pkg->pre_depends_count + pkg->depends_count + 853 pkg->recommends_count + pkg->suggests_count)) 854 return; 855 856 depends = pkg->depends = xcalloc(count, sizeof(compound_depend_t)); 857 858 for (i = 0; i < pkg->pre_depends_count; i++) { 859 parseDepends(depends, pkg->pre_depends_str[i]); 860 free(pkg->pre_depends_str[i]); 861 depends->type = PREDEPEND; 862 depends++; 863 } 864 if (pkg->pre_depends_str) 865 free(pkg->pre_depends_str); 866 867 for (i = 0; i < pkg->depends_count; i++) { 868 parseDepends(depends, pkg->depends_str[i]); 869 free(pkg->depends_str[i]); 870 depends++; 871 } 872 if (pkg->depends_str) 873 free(pkg->depends_str); 874 875 for (i = 0; i < pkg->recommends_count; i++) { 876 parseDepends(depends, pkg->recommends_str[i]); 877 free(pkg->recommends_str[i]); 878 depends->type = RECOMMEND; 879 depends++; 880 } 881 if (pkg->recommends_str) 882 free(pkg->recommends_str); 883 884 for (i = 0; i < pkg->suggests_count; i++) { 885 parseDepends(depends, pkg->suggests_str[i]); 886 free(pkg->suggests_str[i]); 887 depends->type = SUGGEST; 888 depends++; 889 } 890 if (pkg->suggests_str) 891 free(pkg->suggests_str); 892 893 #endif 894 } 895 896 const char *constraint_to_str(enum version_constraint c) 897 { 898 switch (c) { 899 case NONE: 900 return ""; 901 case EARLIER: 902 return "< "; 903 case EARLIER_EQUAL: 904 return "<= "; 905 case EQUAL: 906 return "= "; 907 case LATER_EQUAL: 908 return ">= "; 909 case LATER: 910 return "> "; 911 } 912 913 return ""; 914 } 915 916 /* 917 * Returns a printable string for pkg's dependency at the specified idx. The 918 * resultant string must be passed to free() by the caller. 919 */ 920 char *pkg_depend_str(pkg_t * pkg, int idx) 921 { 922 int i; 923 unsigned int len; 924 char *str; 925 compound_depend_t *cdep = NULL, *p; 926 depend_t *dep; 927 928 for (i = 0, p = pkg_get_ptr(pkg, PKG_DEPENDS); p && p->type; i++, p++) 929 if (i == idx) { 930 cdep = p; 931 break; 932 } 933 934 if (!cdep) 935 return NULL; 936 937 len = 0; 938 939 /* calculate string length */ 940 for (i = 0; i < cdep->possibility_count; i++) { 941 dep = cdep->possibilities[i]; 942 943 if (i != 0) 944 len += 3; /* space, pipe, space */ 945 946 len += strlen(dep->pkg->name); 947 948 if (dep->version) { 949 len += 2; /* space, left parenthesis */ 950 len += 3; /* constraint string (<=, >=, etc), space */ 951 len += strlen(dep->version); 952 len += 1; /* right parenthesis */ 953 } 954 } 955 956 str = xmalloc(len + 1); /* +1 for the NULL terminator */ 957 str[0] = '\0'; 958 959 for (i = 0; i < cdep->possibility_count; i++) { 960 dep = cdep->possibilities[i]; 961 962 if (i != 0) 963 strncat(str, " | ", len); 964 965 strncat(str, dep->pkg->name, len); 966 967 if (dep->version) { 968 strncat(str, " (", len); 969 strncat(str, constraint_to_str(dep->constraint), len); 970 strncat(str, dep->version, len); 971 strncat(str, ")", len); 972 } 973 } 974 975 return str; 976 } 977 978 void buildDependedUponBy(pkg_t * pkg, abstract_pkg_t * ab_pkg) 979 { 980 compound_depend_t *depends; 981 int othercount; 982 int j; 983 abstract_pkg_t *ab_depend; 984 abstract_pkg_t **temp; 985 986 for (depends = pkg_get_ptr(pkg, PKG_DEPENDS); depends && depends->type; depends++) { 987 if (depends->type != PREDEPEND 988 && depends->type != DEPEND && depends->type != RECOMMEND) 989 continue; 990 for (j = 0; j < depends->possibility_count; j++) { 991 ab_depend = depends->possibilities[j]->pkg; 992 if (!ab_depend->depended_upon_by) { 993 ab_depend->depended_upon_by = 994 xcalloc(1, sizeof(abstract_pkg_t *)); 995 } 996 997 temp = ab_depend->depended_upon_by; 998 othercount = 1; 999 while (*temp) { 1000 temp++; 1001 othercount++; 1002 } 1003 *temp = ab_pkg; 1004 1005 ab_depend->depended_upon_by = 1006 xrealloc(ab_depend->depended_upon_by, 1007 (othercount + 1008 1) * sizeof(abstract_pkg_t *)); 1009 1010 /* the array may have been moved by realloc */ 1011 temp = ab_depend->depended_upon_by + othercount; 1012 *temp = NULL; 1013 } 1014 } 1015 } 1016 1017 static depend_t *depend_init(void) 1018 { 1019 depend_t *d = xcalloc(1, sizeof(depend_t)); 1020 d->constraint = NONE; 1021 d->version = NULL; 1022 d->pkg = NULL; 1023 1024 return d; 1025 } 1026 1027 static int parseDepends(compound_depend_t * compound_depend, char *depend_str, enum depend_type type) 1028 { 1029 int i; 1030 char *depend, *name, *vstr, *rest, *tok = NULL; 1031 depend_t **possibilities = NULL, **tmp; 1032 1033 compound_depend->type = type; 1034 1035 for (i = 0, depend = strtok_r(depend_str, "|", &tok); depend; i++, depend = strtok_r(NULL, "|", &tok)) { 1036 name = strtok(depend, " "); 1037 rest = strtok(NULL, "\n"); 1038 1039 tmp = realloc(possibilities, sizeof(tmp) * (i + 1)); 1040 1041 if (!tmp) 1042 return -1; 1043 1044 possibilities = tmp; 1045 possibilities[i] = depend_init(); 1046 possibilities[i]->pkg = ensure_abstract_pkg_by_name(name); 1047 1048 if (rest && *rest == '(') { 1049 vstr = strtok(rest + 1, ")"); 1050 1051 if (!strncmp(vstr, "<<", 2)) { 1052 possibilities[i]->constraint = EARLIER; 1053 vstr += 2; 1054 } else if (!strncmp(vstr, "<=", 2)) { 1055 possibilities[i]->constraint = EARLIER_EQUAL; 1056 vstr += 2; 1057 } else if (!strncmp(vstr, ">=", 2)) { 1058 possibilities[i]->constraint = LATER_EQUAL; 1059 vstr += 2; 1060 } else if (!strncmp(vstr, ">>", 2)) { 1061 possibilities[i]->constraint = LATER; 1062 vstr += 2; 1063 } else if (!strncmp(vstr, "=", 1)) { 1064 possibilities[i]->constraint = EQUAL; 1065 vstr++; 1066 } 1067 /* should these be here to support deprecated designations; dpkg does */ 1068 else if (!strncmp(vstr, "<", 1)) { 1069 possibilities[i]->constraint = EARLIER_EQUAL; 1070 vstr++; 1071 } else if (!strncmp(vstr, ">", 1)) { 1072 possibilities[i]->constraint = LATER_EQUAL; 1073 vstr++; 1074 } 1075 1076 possibilities[i]->version = trim_xstrdup(vstr); 1077 rest = strtok(NULL, " "); 1078 } 1079 else { 1080 rest = strtok(rest, " "); 1081 } 1082 1083 if (rest && *rest == '*') 1084 compound_depend->type = GREEDY_DEPEND; 1085 } 1086 1087 compound_depend->possibility_count = i; 1088 compound_depend->possibilities = possibilities; 1089 1090 return 0; 1091 } 1092 1093 compound_depend_t *pkg_get_depends(pkg_t *pkg, enum depend_type type) 1094 { 1095 compound_depend_t *dep; 1096 1097 for (dep = pkg_get_ptr(pkg, PKG_DEPENDS); dep && dep->type; dep++) 1098 if (type == UNSPEC || dep->type == type) 1099 return dep; 1100 1101 return NULL; 1102 } 1103
This page was automatically generated by LXR 0.3.1. • OpenWrt