1 /* opkg_hash.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 20 #include "hash_table.h" 21 #include "pkg.h" 22 #include "opkg_message.h" 23 #include "pkg_depends.h" 24 #include "pkg_vec.h" 25 #include "pkg_hash.h" 26 #include "parse_util.h" 27 #include "pkg_parse.h" 28 #include "opkg_utils.h" 29 #include "opkg_cmd.h" 30 #include "sprintf_alloc.h" 31 #include "file_util.h" 32 #include "libbb/libbb.h" 33 #include "libbb/gzip.h" 34 35 void pkg_hash_init(void) 36 { 37 hash_table_init("pkg-hash", &conf->pkg_hash, 38 OPKG_CONF_DEFAULT_HASH_LEN); 39 } 40 41 static void free_pkgs(const char *key, void *entry, void *data) 42 { 43 int i; 44 abstract_pkg_t *ab_pkg; 45 46 /* Each entry in the hash table is an abstract package, which contains 47 * a list of packages that provide the abstract package. 48 */ 49 50 ab_pkg = (abstract_pkg_t *) entry; 51 52 if (ab_pkg->pkgs) { 53 for (i = 0; i < ab_pkg->pkgs->len; i++) { 54 pkg_deinit(ab_pkg->pkgs->pkgs[i]); 55 free(ab_pkg->pkgs->pkgs[i]); 56 } 57 } 58 59 abstract_pkg_vec_free(ab_pkg->provided_by); 60 abstract_pkg_vec_free(ab_pkg->replaced_by); 61 pkg_vec_free(ab_pkg->pkgs); 62 free(ab_pkg->depended_upon_by); 63 free(ab_pkg->name); 64 free(ab_pkg); 65 } 66 67 void pkg_hash_deinit(void) 68 { 69 hash_table_foreach(&conf->pkg_hash, free_pkgs, NULL); 70 hash_table_deinit(&conf->pkg_hash); 71 } 72 73 int 74 pkg_hash_add_from_file(const char *file_name, 75 pkg_src_t * src, pkg_dest_t * dest, int is_status_file, int state_flags, 76 void (*cb)(pkg_t *, void *), void *priv) 77 { 78 pkg_t *pkg; 79 FILE *fp; 80 char *buf; 81 const size_t len = 4096; 82 int ret = 0; 83 struct gzip_handle zh; 84 85 if (src && src->gzip) { 86 fp = gzip_fdopen(&zh, file_name); 87 } else { 88 fp = fopen(file_name, "r"); 89 } 90 91 if (fp == NULL) { 92 opkg_perror(ERROR, "Failed to open %s", file_name); 93 return -1; 94 } 95 96 buf = xmalloc(len); 97 98 do { 99 pkg = pkg_new(); 100 pkg->src = src; 101 pkg->dest = dest; 102 pkg->state_flag |= state_flags; 103 104 ret = parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, 0, 105 &buf, len); 106 107 if (pkg->name == NULL) { 108 /* probably just a blank line */ 109 ret = 1; 110 } 111 112 if (ret) { 113 pkg_deinit(pkg); 114 free(pkg); 115 if (ret == -1) 116 break; 117 if (ret == 1) 118 /* Probably a blank line, continue parsing. */ 119 ret = 0; 120 continue; 121 } 122 123 if (!(pkg->state_flag & SF_NEED_DETAIL)) { 124 //opkg_msg(DEBUG, "Package %s is unrelated, ignoring.\n", pkg->name); 125 pkg_deinit(pkg); 126 free(pkg); 127 continue; 128 } 129 130 if (!pkg_get_architecture(pkg) || !pkg_get_arch_priority(pkg)) { 131 char *version_str = pkg_version_str_alloc(pkg); 132 opkg_msg(NOTICE, "Package %s version %s has no " 133 "valid architecture, ignoring.\n", 134 pkg->name, version_str); 135 free(version_str); 136 continue; 137 } 138 139 if (cb) 140 cb(pkg, priv); 141 else 142 hash_insert_pkg(pkg, is_status_file); 143 144 } while (!feof(fp)); 145 146 free(buf); 147 fclose(fp); 148 149 if (src && src->gzip) 150 gzip_close(&zh); 151 152 return ret; 153 } 154 155 /* 156 * Load in feed files from the cached "src" and/or "src/gz" locations. 157 */ 158 int pkg_hash_load_feeds(int state_flags, void (*cb)(pkg_t *, void *), void *priv) 159 { 160 pkg_src_list_elt_t *iter; 161 pkg_src_t *src; 162 char *list_file, *lists_dir; 163 164 opkg_msg(INFO, "\n"); 165 166 lists_dir = conf->restrict_to_default_dest ? 167 conf->default_dest->lists_dir : conf->lists_dir; 168 169 for (iter = void_list_first(&conf->pkg_src_list); iter; 170 iter = void_list_next(&conf->pkg_src_list, iter)) { 171 172 src = (pkg_src_t *) iter->data; 173 174 sprintf_alloc(&list_file, "%s/%s", lists_dir, src->name); 175 176 if (file_exists(list_file)) { 177 if (pkg_hash_add_from_file(list_file, src, NULL, 0, state_flags, cb, priv)) { 178 free(list_file); 179 return -1; 180 } 181 } 182 free(list_file); 183 } 184 185 return 0; 186 } 187 188 /* 189 * Load in status files from the configured "dest"s. 190 */ 191 int pkg_hash_load_status_files(void (*cb)(pkg_t *, void *), void *priv) 192 { 193 pkg_dest_list_elt_t *iter; 194 pkg_dest_t *dest; 195 196 opkg_msg(INFO, "\n"); 197 198 for (iter = void_list_first(&conf->pkg_dest_list); iter; 199 iter = void_list_next(&conf->pkg_dest_list, iter)) { 200 201 dest = (pkg_dest_t *) iter->data; 202 203 if (file_exists(dest->status_file_name)) { 204 if (pkg_hash_add_from_file 205 (dest->status_file_name, NULL, dest, 1, SF_NEED_DETAIL, cb, priv)) 206 return -1; 207 } 208 } 209 210 return 0; 211 } 212 213 static void 214 pkg_hash_load_package_details_helper(const char *pkg_name, void *entry, void *data) 215 { 216 int *count = data; 217 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry; 218 219 if (ab_pkg->state_flag & SF_NEED_DETAIL) { 220 if (ab_pkg->state_flag & SF_MARKED) { 221 opkg_msg(DEBUG, "skipping already seen flagged abpkg %s\n", 222 ab_pkg->name); 223 return; 224 } 225 226 opkg_msg(DEBUG, "found yet incomplete flagged abpkg %s\n", 227 ab_pkg->name); 228 229 (*count)++; 230 ab_pkg->state_flag |= SF_MARKED; 231 } 232 } 233 234 int pkg_hash_load_package_details(void) 235 { 236 int n_need_detail; 237 238 while (1) { 239 pkg_hash_load_feeds(0, NULL, NULL); 240 241 n_need_detail = 0; 242 hash_table_foreach(&conf->pkg_hash, pkg_hash_load_package_details_helper, &n_need_detail); 243 244 if (n_need_detail > 0) 245 opkg_msg(DEBUG, "Found %d packages requiring details, reloading feeds\n", n_need_detail); 246 else 247 break; 248 } 249 250 return 0; 251 } 252 253 static int 254 pkg_hash_check_unresolved(pkg_t *maybe) 255 { 256 char **unresolved = NULL; 257 char **tmp; 258 pkg_vec_t *depends; 259 int res = 0; 260 261 depends = pkg_vec_alloc(); 262 pkg_hash_fetch_unsatisfied_dependencies(maybe, depends, &unresolved, 1); 263 264 if (unresolved) { 265 res = 1; 266 tmp = unresolved; 267 while (*tmp) { 268 opkg_msg(ERROR, "cannot find dependency %s for %s\n", *tmp, maybe->name); 269 free(*(tmp++)); 270 } 271 free(unresolved); 272 } 273 pkg_vec_free(depends); 274 275 return res; 276 } 277 278 pkg_t *pkg_hash_fetch_best_installation_candidate(abstract_pkg_t * apkg, 279 int (*constraint_fcn) (pkg_t * 280 pkg, 281 void 282 *cdata), 283 void *cdata, int quiet) 284 { 285 int i, j; 286 int nprovides = 0; 287 int nmatching = 0; 288 int wrong_arch_found = 0; 289 int arch_priority; 290 int good_pkg_score = 0; 291 pkg_vec_t *matching_pkgs; 292 abstract_pkg_vec_t *matching_apkgs; 293 abstract_pkg_vec_t *provided_apkg_vec; 294 abstract_pkg_t **provided_apkgs; 295 abstract_pkg_vec_t *providers; 296 pkg_t *latest_installed_parent = NULL; 297 pkg_t *latest_matching = NULL; 298 pkg_t *priorized_matching = NULL; 299 pkg_t *held_pkg = NULL; 300 pkg_t *good_pkg_by_name = NULL; 301 302 if (apkg == NULL || apkg->provided_by == NULL 303 || (apkg->provided_by->len == 0)) 304 return NULL; 305 306 matching_pkgs = pkg_vec_alloc(); 307 matching_apkgs = abstract_pkg_vec_alloc(); 308 providers = abstract_pkg_vec_alloc(); 309 310 opkg_msg(DEBUG, "Best installation candidate for %s:\n", apkg->name); 311 312 provided_apkg_vec = apkg->provided_by; 313 nprovides = provided_apkg_vec->len; 314 provided_apkgs = provided_apkg_vec->pkgs; 315 if (nprovides > 1) 316 opkg_msg(DEBUG, "apkg=%s nprovides=%d.\n", apkg->name, 317 nprovides); 318 319 /* accumulate all the providers */ 320 for (i = 0; i < nprovides; i++) { 321 abstract_pkg_t *provider_apkg = provided_apkgs[i]; 322 opkg_msg(DEBUG, "Adding %s to providers.\n", 323 provider_apkg->name); 324 abstract_pkg_vec_insert(providers, provider_apkg); 325 } 326 nprovides = providers->len; 327 328 for (i = 0; i < nprovides; i++) { 329 abstract_pkg_t *provider_apkg = 330 abstract_pkg_vec_get(providers, i); 331 abstract_pkg_t *replacement_apkg = NULL; 332 pkg_vec_t *vec; 333 334 if (provider_apkg->replaced_by 335 && provider_apkg->replaced_by->len) { 336 replacement_apkg = provider_apkg->replaced_by->pkgs[0]; 337 if (provider_apkg->replaced_by->len > 1) { 338 opkg_msg(NOTICE, "Multiple replacers for %s, " 339 "using first one (%s).\n", 340 provider_apkg->name, 341 replacement_apkg->name); 342 } 343 } 344 345 if (replacement_apkg) 346 opkg_msg(DEBUG, 347 "replacement_apkg=%s for provider_apkg=%s.\n", 348 replacement_apkg->name, provider_apkg->name); 349 350 if (replacement_apkg && (replacement_apkg != provider_apkg)) { 351 if (abstract_pkg_vec_contains 352 (providers, replacement_apkg)) 353 continue; 354 else 355 provider_apkg = replacement_apkg; 356 } 357 358 if (!(vec = provider_apkg->pkgs)) { 359 opkg_msg(DEBUG, "No pkgs for provider_apkg %s.\n", 360 provider_apkg->name); 361 continue; 362 } 363 364 /* now check for supported architecture */ 365 { 366 int max_count = 0; 367 368 /* count packages matching max arch priority and keep track of last one */ 369 for (j = 0; j < vec->len; j++) { 370 pkg_t *maybe = vec->pkgs[j]; 371 arch_priority = pkg_get_arch_priority(maybe); 372 373 opkg_msg(DEBUG, 374 "%s arch=%s arch_priority=%d version=%s.\n", 375 maybe->name, pkg_get_architecture(maybe), 376 arch_priority, pkg_get_string(maybe, PKG_VERSION)); 377 /* We make sure not to add the same package twice. Need to search for the reason why 378 they show up twice sometimes. */ 379 if ((arch_priority > 0) 380 && 381 (!pkg_vec_contains(matching_pkgs, maybe))) { 382 if (!pkg_hash_check_unresolved(maybe)) { 383 max_count++; 384 abstract_pkg_vec_insert(matching_apkgs, 385 maybe->parent); 386 pkg_vec_insert(matching_pkgs, maybe); 387 } 388 } 389 } 390 391 if (vec->len > 0 && matching_pkgs->len < 1) 392 wrong_arch_found = 1; 393 } 394 } 395 396 if (matching_pkgs->len < 1) { 397 if (wrong_arch_found) 398 opkg_msg(ERROR, "Packages for %s found, but" 399 " incompatible with the architectures configured\n", 400 apkg->name); 401 pkg_vec_free(matching_pkgs); 402 abstract_pkg_vec_free(matching_apkgs); 403 abstract_pkg_vec_free(providers); 404 return NULL; 405 } 406 407 if (matching_pkgs->len > 1) 408 pkg_vec_sort(matching_pkgs, 409 pkg_name_version_and_architecture_compare); 410 if (matching_apkgs->len > 1) 411 abstract_pkg_vec_sort(matching_apkgs, abstract_pkg_name_compare); 412 413 for (i = 0; i < matching_pkgs->len; i++) { 414 pkg_t *matching = matching_pkgs->pkgs[i]; 415 if (constraint_fcn(matching, cdata)) { 416 int score = 1; 417 if (strcmp(matching->name, apkg->name) == 0) 418 score++; 419 420 for (j = 0; j < opkg_cli_argc; ++j) { 421 if (!strcmp(matching->name, opkg_cli_argv[j])) { 422 score++; 423 break; 424 } 425 } 426 427 opkg_msg(DEBUG, "Candidate: %s %s (score %d).\n", 428 matching->name, pkg_get_string(matching, PKG_VERSION), 429 score); 430 if (score < good_pkg_score) 431 continue; 432 433 good_pkg_by_name = matching; 434 good_pkg_score = score; 435 /* It has been provided by hand, so it is what user want */ 436 if (matching->provided_by_hand == 1) 437 break; 438 } 439 } 440 441 for (i = 0; i < matching_pkgs->len; i++) { 442 pkg_t *matching = matching_pkgs->pkgs[i]; 443 latest_matching = matching; 444 if (matching->parent->state_status == SS_INSTALLED 445 || matching->parent->state_status == SS_UNPACKED) 446 latest_installed_parent = matching; 447 if (matching->state_flag & (SF_HOLD | SF_PREFER)) { 448 if (held_pkg) 449 opkg_msg(NOTICE, 450 "Multiple packages (%s and %s) providing" 451 " same name marked HOLD or PREFER. " 452 "Using latest.\n", held_pkg->name, 453 matching->name); 454 held_pkg = matching; 455 } 456 } 457 458 if (!good_pkg_by_name && !held_pkg && !latest_installed_parent 459 && matching_apkgs->len > 1 && !quiet) { 460 int prio = 0; 461 for (i = 0; i < matching_pkgs->len; i++) { 462 pkg_t *matching = matching_pkgs->pkgs[i]; 463 arch_priority = pkg_get_arch_priority(matching); 464 if (arch_priority > prio) { 465 priorized_matching = matching; 466 prio = arch_priority; 467 opkg_msg(DEBUG, "Match %s with priority %i.\n", 468 matching->name, prio); 469 } 470 } 471 472 } 473 474 if (conf->verbosity >= INFO && matching_apkgs->len > 1) { 475 opkg_msg(INFO, "%d matching pkgs for apkg=%s:\n", 476 matching_pkgs->len, apkg->name); 477 for (i = 0; i < matching_pkgs->len; i++) { 478 pkg_t *matching = matching_pkgs->pkgs[i]; 479 opkg_msg(INFO, "%s %s %s\n", 480 matching->name, pkg_get_string(matching, PKG_VERSION), 481 pkg_get_architecture(matching)); 482 } 483 } 484 485 nmatching = matching_apkgs->len; 486 487 pkg_vec_free(matching_pkgs); 488 abstract_pkg_vec_free(matching_apkgs); 489 abstract_pkg_vec_free(providers); 490 491 if (good_pkg_by_name) { /* We found a good candidate, we will install it */ 492 return good_pkg_by_name; 493 } 494 if (held_pkg) { 495 opkg_msg(INFO, "Using held package %s.\n", held_pkg->name); 496 return held_pkg; 497 } 498 if (latest_installed_parent) { 499 opkg_msg(INFO, 500 "Using latest version of installed package %s.\n", 501 latest_installed_parent->name); 502 return latest_installed_parent; 503 } 504 if (priorized_matching) { 505 opkg_msg(INFO, "Using priorized matching %s %s %s.\n", 506 priorized_matching->name, pkg_get_string(priorized_matching, PKG_VERSION), 507 pkg_get_architecture(priorized_matching)); 508 return priorized_matching; 509 } 510 if (nmatching > 1) { 511 opkg_msg(INFO, "No matching pkg out of %d matching_apkgs.\n", 512 nmatching); 513 return NULL; 514 } 515 if (latest_matching) { 516 opkg_msg(INFO, "Using latest matching %s %s %s.\n", 517 latest_matching->name, pkg_get_string(latest_matching, PKG_VERSION), 518 pkg_get_architecture(latest_matching)); 519 return latest_matching; 520 } 521 return NULL; 522 } 523 524 static int pkg_name_constraint_fcn(pkg_t * pkg, void *cdata) 525 { 526 const char *name = (const char *)cdata; 527 528 if (strcmp(pkg->name, name) == 0) 529 return 1; 530 else 531 return 0; 532 } 533 534 static pkg_vec_t *pkg_vec_fetch_by_name(const char *pkg_name) 535 { 536 abstract_pkg_t *ab_pkg; 537 538 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name))) 539 return NULL; 540 541 if (ab_pkg->pkgs) 542 return ab_pkg->pkgs; 543 544 if (ab_pkg->provided_by) { 545 abstract_pkg_t *abpkg = 546 abstract_pkg_vec_get(ab_pkg->provided_by, 0); 547 if (abpkg != NULL) 548 return abpkg->pkgs; 549 else 550 return ab_pkg->pkgs; 551 } 552 553 return NULL; 554 } 555 556 pkg_t *pkg_hash_fetch_best_installation_candidate_by_name(const char *name) 557 { 558 abstract_pkg_t *apkg = NULL; 559 560 if (!(apkg = abstract_pkg_fetch_by_name(name))) 561 return NULL; 562 563 return pkg_hash_fetch_best_installation_candidate(apkg, 564 pkg_name_constraint_fcn, 565 apkg->name, 0); 566 } 567 568 pkg_t *pkg_hash_fetch_by_name_version(const char *pkg_name, const char *version) 569 { 570 pkg_vec_t *vec; 571 int i; 572 char *version_str = NULL; 573 574 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) 575 return NULL; 576 577 for (i = 0; i < vec->len; i++) { 578 version_str = pkg_version_str_alloc(vec->pkgs[i]); 579 if (!strcmp(version_str, version)) { 580 free(version_str); 581 break; 582 } 583 free(version_str); 584 } 585 586 if (i == vec->len) 587 return NULL; 588 589 return vec->pkgs[i]; 590 } 591 592 pkg_t *pkg_hash_fetch_installed_by_name_dest(const char *pkg_name, 593 pkg_dest_t * dest) 594 { 595 pkg_vec_t *vec; 596 int i; 597 598 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) { 599 return NULL; 600 } 601 602 for (i = 0; i < vec->len; i++) 603 if ((vec->pkgs[i]->state_status == SS_INSTALLED 604 || vec->pkgs[i]->state_status == SS_UNPACKED) 605 && vec->pkgs[i]->dest == dest) { 606 return vec->pkgs[i]; 607 } 608 609 return NULL; 610 } 611 612 pkg_t *pkg_hash_fetch_installed_by_name(const char *pkg_name) 613 { 614 pkg_vec_t *vec; 615 int i; 616 617 if (!(vec = pkg_vec_fetch_by_name(pkg_name))) { 618 return NULL; 619 } 620 621 for (i = 0; i < vec->len; i++) { 622 if (vec->pkgs[i]->state_status == SS_INSTALLED 623 || vec->pkgs[i]->state_status == SS_UNPACKED) { 624 return vec->pkgs[i]; 625 } 626 } 627 628 return NULL; 629 } 630 631 static void 632 pkg_hash_fetch_available_helper(const char *pkg_name, void *entry, void *data) 633 { 634 int j; 635 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry; 636 pkg_vec_t *all = (pkg_vec_t *) data; 637 pkg_vec_t *pkg_vec = ab_pkg->pkgs; 638 639 if (!pkg_vec) 640 return; 641 642 for (j = 0; j < pkg_vec->len; j++) { 643 pkg_t *pkg = pkg_vec->pkgs[j]; 644 pkg_vec_insert(all, pkg); 645 } 646 } 647 648 void pkg_hash_fetch_available(pkg_vec_t * all) 649 { 650 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_available_helper, 651 all); 652 } 653 654 static void 655 pkg_hash_fetch_all_installed_helper(const char *pkg_name, void *entry, 656 void *data) 657 { 658 abstract_pkg_t *ab_pkg = (abstract_pkg_t *) entry; 659 pkg_vec_t *all = (pkg_vec_t *) data; 660 pkg_vec_t *pkg_vec = ab_pkg->pkgs; 661 int j; 662 663 if (!pkg_vec) 664 return; 665 666 for (j = 0; j < pkg_vec->len; j++) { 667 pkg_t *pkg = pkg_vec->pkgs[j]; 668 if (pkg->state_status == SS_INSTALLED 669 || pkg->state_status == SS_UNPACKED) 670 pkg_vec_insert(all, pkg); 671 } 672 } 673 674 void pkg_hash_fetch_all_installed(pkg_vec_t * all) 675 { 676 hash_table_foreach(&conf->pkg_hash, pkg_hash_fetch_all_installed_helper, 677 all); 678 } 679 680 /* 681 * This assumes that the abstract pkg doesn't exist. 682 */ 683 static abstract_pkg_t *add_new_abstract_pkg_by_name(const char *pkg_name) 684 { 685 abstract_pkg_t *ab_pkg; 686 687 ab_pkg = abstract_pkg_new(); 688 689 ab_pkg->name = xstrdup(pkg_name); 690 hash_table_insert(&conf->pkg_hash, pkg_name, ab_pkg); 691 692 return ab_pkg; 693 } 694 695 abstract_pkg_t *ensure_abstract_pkg_by_name(const char *pkg_name) 696 { 697 abstract_pkg_t *ab_pkg; 698 699 if (!(ab_pkg = abstract_pkg_fetch_by_name(pkg_name))) 700 ab_pkg = add_new_abstract_pkg_by_name(pkg_name); 701 702 return ab_pkg; 703 } 704 705 void hash_insert_pkg(pkg_t * pkg, int set_status) 706 { 707 abstract_pkg_t *ab_pkg; 708 709 ab_pkg = ensure_abstract_pkg_by_name(pkg->name); 710 if (!ab_pkg->pkgs) 711 ab_pkg->pkgs = pkg_vec_alloc(); 712 713 if (pkg->state_status == SS_INSTALLED) { 714 ab_pkg->state_status = SS_INSTALLED; 715 } else if (pkg->state_status == SS_UNPACKED) { 716 ab_pkg->state_status = SS_UNPACKED; 717 } 718 719 buildDepends(pkg); 720 721 buildProvides(ab_pkg, pkg); 722 723 init_providelist(pkg, NULL); 724 725 /* Need to build the conflicts graph before replaces for correct 726 * calculation of replaced_by relation. 727 */ 728 buildConflicts(pkg); 729 730 buildReplaces(ab_pkg, pkg); 731 732 buildDependedUponBy(pkg, ab_pkg); 733 734 pkg_vec_insert_merge(ab_pkg->pkgs, pkg, set_status); 735 pkg->parent = ab_pkg; 736 } 737 738 static const char *strip_offline_root(const char *file_name) 739 { 740 unsigned int len; 741 742 if (conf->offline_root) { 743 len = strlen(conf->offline_root); 744 if (strncmp(file_name, conf->offline_root, len) == 0) 745 file_name += len; 746 } 747 748 return file_name; 749 } 750 751 void file_hash_remove(const char *file_name) 752 { 753 file_name = strip_offline_root(file_name); 754 hash_table_remove(&conf->file_hash, file_name); 755 } 756 757 pkg_t *file_hash_get_file_owner(const char *file_name) 758 { 759 file_name = strip_offline_root(file_name); 760 return hash_table_get(&conf->file_hash, file_name); 761 } 762 763 void file_hash_set_file_owner(const char *file_name, pkg_t * owning_pkg) 764 { 765 pkg_t *old_owning_pkg; 766 int file_name_len = strlen(file_name); 767 768 if (file_name[file_name_len - 1] == '/') 769 return; 770 771 file_name = strip_offline_root(file_name); 772 773 old_owning_pkg = hash_table_get(&conf->file_hash, file_name); 774 hash_table_insert(&conf->file_hash, file_name, owning_pkg); 775 776 if (old_owning_pkg) { 777 pkg_get_installed_files(old_owning_pkg); 778 str_list_remove_elt(old_owning_pkg->installed_files, file_name); 779 pkg_free_installed_files(old_owning_pkg); 780 781 /* mark this package to have its filelist written */ 782 old_owning_pkg->state_flag |= SF_FILELIST_CHANGED; 783 owning_pkg->state_flag |= SF_FILELIST_CHANGED; 784 } 785 } 786
This page was automatically generated by LXR 0.3.1. • OpenWrt