1 /* opkg_cmd.c - the opkg package management system 2 3 Carl D. Worth 4 5 Copyright (C) 2001 University of Southern California 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 <dirent.h> 20 #include <glob.h> 21 #include <fnmatch.h> 22 #include <signal.h> 23 #include <unistd.h> 24 25 #include "opkg_conf.h" 26 #include "opkg_cmd.h" 27 #include "opkg_message.h" 28 #include "pkg.h" 29 #include "pkg_dest.h" 30 #include "pkg_parse.h" 31 #include "sprintf_alloc.h" 32 #include "pkg.h" 33 #include "file_util.h" 34 #include "libbb/libbb.h" 35 #include "opkg_utils.h" 36 #include "opkg_defines.h" 37 #include "opkg_download.h" 38 #include "opkg_install.h" 39 #include "opkg_upgrade.h" 40 #include "opkg_remove.h" 41 #include "opkg_configure.h" 42 #include "xsystem.h" 43 44 int opkg_cli_argc = 0; 45 const char **opkg_cli_argv = NULL; 46 47 static void print_pkg(pkg_t * pkg) 48 { 49 char *version = pkg_version_str_alloc(pkg); 50 char *description = pkg_get_string(pkg, PKG_DESCRIPTION); 51 const char *abiver; 52 char *tmp, *tmpname = NULL; 53 54 if (conf->strip_abi && 55 (abiver = pkg_get_string(pkg, PKG_ABIVERSION)) && 56 (strlen(pkg->name) > strlen(abiver))) { 57 tmpname = strdup(pkg->name); 58 tmp = &tmpname[strlen(tmpname) - strlen(abiver)]; 59 if (!strncmp(abiver, tmp, strlen(abiver))) 60 *tmp = '\0'; 61 }; 62 63 printf("%s - %s", tmpname?tmpname:pkg->name, version); 64 65 if (tmpname) 66 free(tmpname); 67 68 if (conf->size) 69 printf(" - %lu", (unsigned long) pkg_get_int(pkg, PKG_SIZE)); 70 if (description) 71 printf(" - %s", description); 72 printf("\n"); 73 free(version); 74 } 75 76 int opkg_state_changed; 77 78 static void write_status_files_if_changed(void) 79 { 80 if (opkg_state_changed && !conf->noaction) { 81 opkg_msg(INFO, "Writing status file.\n"); 82 opkg_conf_write_status_files(); 83 pkg_write_changed_filelists(); 84 } else { 85 opkg_msg(DEBUG, "Nothing to be done.\n"); 86 } 87 } 88 89 static void sigint_handler(int sig) 90 { 91 signal(sig, SIG_DFL); 92 opkg_msg(NOTICE, "Interrupted. Writing out status database.\n"); 93 write_status_files_if_changed(); 94 exit(128 + sig); 95 } 96 97 static int opkg_update_cmd(int argc, char **argv) 98 { 99 char *tmp; 100 int err; 101 int failures; 102 int pkglist_dl_error; 103 char *lists_dir; 104 pkg_src_list_elt_t *iter; 105 pkg_src_t *src; 106 107 sprintf_alloc(&lists_dir, "%s", 108 conf->restrict_to_default_dest ? conf->default_dest-> 109 lists_dir : conf->lists_dir); 110 111 if (!file_is_dir(lists_dir)) { 112 if (file_exists(lists_dir)) { 113 opkg_msg(ERROR, "%s exists, but is not a directory.\n", 114 lists_dir); 115 free(lists_dir); 116 return -1; 117 } 118 err = file_mkdir_hier(lists_dir, 0755); 119 if (err) { 120 free(lists_dir); 121 return -1; 122 } 123 } 124 125 failures = 0; 126 127 sprintf_alloc(&tmp, "%s/update-XXXXXX", conf->tmp_dir); 128 if (mkdtemp(tmp) == NULL) { 129 opkg_perror(ERROR, "Failed to make temp dir %s", conf->tmp_dir); 130 return -1; 131 } 132 133 for (iter = void_list_first(&conf->pkg_src_list); iter; 134 iter = void_list_next(&conf->pkg_src_list, iter)) { 135 char *url, *list_file_name; 136 137 src = (pkg_src_t *) iter->data; 138 139 sprintf_alloc(&url, "%s/%s", src->value, 140 src->gzip ? "Packages.gz" : "Packages"); 141 142 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name); 143 pkglist_dl_error = 0; 144 if (opkg_download(url, list_file_name, 0)) { 145 failures++; 146 pkglist_dl_error = 1; 147 opkg_msg(NOTICE, 148 "*** Failed to download the package list from %s\n\n", 149 url); 150 } else { 151 opkg_msg(NOTICE, 152 "Updated list of available packages in %s\n", 153 list_file_name); 154 } 155 free(url); 156 #if defined(HAVE_USIGN) 157 if (pkglist_dl_error == 0 && conf->check_signature) { 158 /* download detached signitures to verify the package lists */ 159 /* get the url for the sig file */ 160 sprintf_alloc(&url, "%s/%s", src->value, 161 "Packages.sig"); 162 163 /* create temporary file for it */ 164 char *tmp_file_name; 165 166 /* Put the signature in the right place */ 167 sprintf_alloc(&tmp_file_name, "%s/%s.sig", lists_dir, 168 src->name); 169 170 err = opkg_download(url, tmp_file_name, 0); 171 if (err) { 172 failures++; 173 opkg_msg(NOTICE, 174 "Signature file download failed.\n"); 175 } else { 176 err = 177 opkg_verify_file(list_file_name, 178 tmp_file_name); 179 if (err == 0) 180 opkg_msg(NOTICE, 181 "Signature check passed.\n"); 182 else 183 opkg_msg(NOTICE, 184 "Signature check failed.\n"); 185 } 186 if (err && !conf->force_signature) { 187 /* The signature was wrong so delete it */ 188 opkg_msg(NOTICE, 189 "Remove wrong Signature file.\n"); 190 unlink(tmp_file_name); 191 unlink(list_file_name); 192 } 193 /* We shouldn't unlink the signature ! */ 194 // unlink (tmp_file_name); 195 free(tmp_file_name); 196 free(url); 197 } 198 #else 199 // Do nothing 200 #endif 201 free(list_file_name); 202 } 203 rmdir(tmp); 204 free(tmp); 205 free(lists_dir); 206 207 return failures; 208 } 209 210 struct opkg_intercept { 211 char *oldpath; 212 char *statedir; 213 }; 214 215 typedef struct opkg_intercept *opkg_intercept_t; 216 217 static opkg_intercept_t opkg_prep_intercepts(void) 218 { 219 opkg_intercept_t ctx; 220 char *newpath; 221 222 ctx = xcalloc(1, sizeof(*ctx)); 223 ctx->oldpath = xstrdup(getenv("PATH")); 224 225 sprintf_alloc(&newpath, "%s/opkg/intercept:%s", DATADIR, 226 ctx->oldpath ? ctx->oldpath : PATH_SPEC); 227 228 sprintf_alloc(&ctx->statedir, "%s/opkg-intercept-XXXXXX", 229 conf->tmp_dir); 230 231 if (mkdtemp(ctx->statedir) == NULL) { 232 opkg_perror(ERROR, "Failed to make temp dir %s", ctx->statedir); 233 234 if (ctx->oldpath) 235 free(ctx->oldpath); 236 237 free(ctx->statedir); 238 free(newpath); 239 free(ctx); 240 return NULL; 241 } 242 243 setenv("OPKG_INTERCEPT_DIR", ctx->statedir, 1); 244 setenv("PATH", newpath, 1); 245 free(newpath); 246 247 return ctx; 248 } 249 250 static int opkg_finalize_intercepts(opkg_intercept_t ctx) 251 { 252 DIR *dir; 253 int err = 0; 254 255 if (ctx->oldpath) { 256 setenv("PATH", ctx->oldpath, 1); 257 free(ctx->oldpath); 258 } 259 else { 260 unsetenv("PATH"); 261 } 262 263 dir = opendir(ctx->statedir); 264 if (dir) { 265 struct dirent *de; 266 while (de = readdir(dir), de != NULL) { 267 char *path; 268 269 if (de->d_name[0] == '.') 270 continue; 271 272 sprintf_alloc(&path, "%s/%s", ctx->statedir, 273 de->d_name); 274 if (access(path, X_OK) == 0) { 275 const char *argv[] = { "/bin/sh", "-c", path, NULL }; 276 xsystem(argv); 277 } 278 free(path); 279 } 280 closedir(dir); 281 } else 282 opkg_perror(ERROR, "Failed to open dir %s", ctx->statedir); 283 284 rm_r(ctx->statedir); 285 free(ctx->statedir); 286 free(ctx); 287 288 return err; 289 } 290 291 /* For package pkg do the following: If it is already visited, return. If not, 292 add it in visited list and recurse to its deps. Finally, add it to ordered 293 list. 294 pkg_vec all contains all available packages in repos. 295 pkg_vec visited contains packages already visited by this function, and is 296 used to end recursion and avoid an infinite loop on graph cycles. 297 pkg_vec ordered will finally contain the ordered set of packages. 298 */ 299 static int 300 opkg_recurse_pkgs_in_order(pkg_t * pkg, pkg_vec_t * all, 301 pkg_vec_t * visited, pkg_vec_t * ordered) 302 { 303 int j, k, l, m; 304 pkg_t *dep; 305 compound_depend_t *compound_depend; 306 depend_t **possible_satisfiers; 307 abstract_pkg_t *abpkg; 308 abstract_pkg_t **dependents; 309 310 /* If it's just an available package, that is, not installed and not even 311 unpacked, skip it */ 312 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED 313 would do here. However, if there is an intermediate node (pkg) that is 314 configured and installed between two unpacked packages, the latter 315 won't be properly reordered, unless all installed/unpacked pkgs are 316 checked */ 317 if (pkg->state_status == SS_NOT_INSTALLED) 318 return 0; 319 320 /* If the package has already been visited (by this function), skip it */ 321 for (j = 0; j < visited->len; j++) 322 if (!strcmp(visited->pkgs[j]->name, pkg->name)) { 323 opkg_msg(DEBUG, "pkg %s already visited, skipping.\n", 324 pkg->name); 325 return 0; 326 } 327 328 pkg_vec_insert(visited, pkg); 329 330 opkg_msg(DEBUG, "pkg %s.\n", pkg->name); 331 332 /* Iterate over all the dependencies of pkg. For each one, find a package 333 that is either installed or unpacked and satisfies this dependency. 334 (there should only be one such package per dependency installed or 335 unpacked). Then recurse to the dependency package */ 336 for (compound_depend = pkg_get_ptr(pkg, PKG_DEPENDS); compound_depend && compound_depend->type; compound_depend++) { 337 possible_satisfiers = compound_depend->possibilities; 338 for (k = 0; k < compound_depend->possibility_count; k++) { 339 abpkg = possible_satisfiers[k]->pkg; 340 dependents = abpkg->provided_by->pkgs; 341 l = 0; 342 if (dependents != NULL) 343 while (l < abpkg->provided_by->len 344 && dependents[l] != NULL) { 345 opkg_msg(DEBUG, 346 "Descending on pkg %s.\n", 347 dependents[l]->name); 348 349 /* find whether dependent l is installed or unpacked, 350 * and then find which package in the list satisfies it */ 351 for (m = 0; m < all->len; m++) { 352 dep = all->pkgs[m]; 353 if (dep->state_status != 354 SS_NOT_INSTALLED) 355 if (!strcmp 356 (dep->name, 357 dependents[l]-> 358 name)) { 359 opkg_recurse_pkgs_in_order 360 (dep, all, 361 visited, 362 ordered); 363 /* Stop the outer loop */ 364 l = abpkg-> 365 provided_by-> 366 len; 367 /* break from the inner loop */ 368 break; 369 } 370 } 371 l++; 372 } 373 } 374 } 375 376 /* When all recursions from this node down, are over, and all 377 dependencies have been added in proper order in the ordered array, add 378 also the package pkg to ordered array */ 379 pkg_vec_insert(ordered, pkg); 380 381 return 0; 382 383 } 384 385 static int opkg_configure_packages(char *pkg_name) 386 { 387 pkg_vec_t *all, *ordered, *visited; 388 int i; 389 pkg_t *pkg; 390 opkg_intercept_t ic; 391 int r, err = 0; 392 393 opkg_msg(INFO, "Configuring unpacked packages.\n"); 394 395 all = pkg_vec_alloc(); 396 397 pkg_hash_fetch_available(all); 398 399 /* Reorder pkgs in order to be configured according to the Depends: tag 400 order */ 401 opkg_msg(INFO, "Reordering packages before configuring them...\n"); 402 ordered = pkg_vec_alloc(); 403 visited = pkg_vec_alloc(); 404 for (i = 0; i < all->len; i++) { 405 pkg = all->pkgs[i]; 406 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered); 407 } 408 409 ic = opkg_prep_intercepts(); 410 if (ic == NULL) { 411 err = -1; 412 goto error; 413 } 414 415 for (i = 0; i < ordered->len; i++) { 416 pkg = ordered->pkgs[i]; 417 418 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) 419 continue; 420 421 if (pkg->state_status == SS_UNPACKED) { 422 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name); 423 r = opkg_configure(pkg); 424 if (r == 0) { 425 pkg->state_status = SS_INSTALLED; 426 pkg->parent->state_status = SS_INSTALLED; 427 pkg->state_flag &= ~SF_PREFER; 428 opkg_state_changed++; 429 } else { 430 err = -1; 431 } 432 } 433 } 434 435 if (opkg_finalize_intercepts(ic)) 436 err = -1; 437 438 error: 439 pkg_vec_free(all); 440 pkg_vec_free(ordered); 441 pkg_vec_free(visited); 442 443 return err; 444 } 445 446 static int opkg_remove_cmd(int argc, char **argv); 447 448 static int opkg_install_cmd(int argc, char **argv) 449 { 450 int i; 451 char *arg; 452 int err = 0; 453 454 signal(SIGINT, sigint_handler); 455 456 /* 457 * Now scan through package names and install 458 */ 459 for (i = 0; i < argc; i++) { 460 arg = argv[i]; 461 462 opkg_msg(DEBUG2, "%s\n", arg); 463 if (opkg_prepare_url_for_install(arg, &argv[i])) 464 return -1; 465 } 466 467 pkg_hash_load_package_details(); 468 pkg_hash_load_status_files(NULL, NULL); 469 470 if (conf->force_reinstall) { 471 int saved_force_depends = conf->force_depends; 472 conf->force_depends = 1; 473 (void)opkg_remove_cmd(argc, argv); 474 conf->force_depends = saved_force_depends; 475 conf->force_reinstall = 0; 476 } 477 478 pkg_info_preinstall_check(); 479 480 for (i = 0; i < argc; i++) { 481 arg = argv[i]; 482 if (opkg_install_by_name(arg)) { 483 opkg_msg(ERROR, "Cannot install package %s.\n", arg); 484 err = -1; 485 } 486 } 487 488 if (opkg_configure_packages(NULL)) 489 err = -1; 490 491 write_status_files_if_changed(); 492 493 return err; 494 } 495 496 static int opkg_upgrade_cmd(int argc, char **argv) 497 { 498 int i; 499 pkg_t *pkg; 500 int err = 0; 501 502 signal(SIGINT, sigint_handler); 503 504 if (argc) { 505 for (i = 0; i < argc; i++) { 506 char *arg = argv[i]; 507 508 if (opkg_prepare_url_for_install(arg, &arg)) 509 return -1; 510 } 511 pkg_info_preinstall_check(); 512 513 for (i = 0; i < argc; i++) { 514 char *arg = argv[i]; 515 if (conf->restrict_to_default_dest) { 516 pkg = 517 pkg_hash_fetch_installed_by_name_dest(argv 518 [i], 519 conf-> 520 default_dest); 521 if (pkg == NULL) { 522 opkg_msg(NOTICE, 523 "Package %s not installed in %s.\n", 524 argv[i], 525 conf->default_dest->name); 526 continue; 527 } 528 } else { 529 pkg = pkg_hash_fetch_installed_by_name(argv[i]); 530 } 531 if (pkg) { 532 if (opkg_upgrade_pkg(pkg)) 533 err = -1; 534 } else { 535 if (opkg_install_by_name(arg)) 536 err = -1; 537 } 538 } 539 } 540 541 if (opkg_configure_packages(NULL)) 542 err = -1; 543 544 write_status_files_if_changed(); 545 546 return err; 547 } 548 549 static int opkg_download_cmd(int argc, char **argv) 550 { 551 int i, err = 0; 552 char *arg; 553 pkg_t *pkg; 554 555 pkg_info_preinstall_check(); 556 for (i = 0; i < argc; i++) { 557 arg = argv[i]; 558 559 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg); 560 if (pkg == NULL) { 561 opkg_msg(ERROR, "Cannot find package %s.\n", arg); 562 continue; 563 } 564 565 if (opkg_download_pkg(pkg, ".")) 566 err = -1; 567 568 if (err) { 569 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name); 570 } else { 571 opkg_msg(NOTICE, "Downloaded %s as %s.\n", 572 pkg->name, pkg_get_string(pkg, PKG_LOCAL_FILENAME)); 573 } 574 } 575 576 return err; 577 } 578 579 struct opkg_list_find_cmd_item { 580 int size; 581 char *name; 582 char *version; 583 char *description; 584 }; 585 586 struct opkg_list_find_cmd_args { 587 int use_desc; 588 int set_status; 589 char *pkg_name; 590 struct opkg_list_find_cmd_item **items; 591 size_t n_items; 592 }; 593 594 static void opkg_list_find_cmd_cb(pkg_t *pkg, void *priv) 595 { 596 struct opkg_list_find_cmd_args *args = priv; 597 char *description = pkg_get_string(pkg, PKG_DESCRIPTION); 598 char *version = pkg_version_str_alloc(pkg); 599 struct opkg_list_find_cmd_item *item; 600 char *nameptr, *versionptr, *descriptionptr, *tmp; 601 const char *abiver; 602 int i, found = 0; 603 604 /* if we have package name or pattern and pkg does not match, then skip it */ 605 if (args->pkg_name && fnmatch(args->pkg_name, pkg->name, conf->nocase) && 606 (!args->use_desc || !description 607 || fnmatch(args->pkg_name, description, conf->nocase))) 608 goto out; 609 610 if (args->set_status) { 611 for (i = 0; i < args->n_items; i++) { 612 if (!strcmp(args->items[i]->name, pkg->name)) { 613 found = 1; 614 break; 615 } 616 } 617 } 618 619 if (!found) { 620 item = calloc_a(sizeof(*item), 621 &nameptr, strlen(pkg->name) + 1, 622 &versionptr, strlen(version) + 1, 623 &descriptionptr, description ? strlen(description) + 1 : 0); 624 625 item->name = strcpy(nameptr, pkg->name); 626 627 if (conf->strip_abi && 628 (abiver = pkg_get_string(pkg, PKG_ABIVERSION)) && 629 (strlen(item->name) > strlen(abiver))) { 630 tmp = &item->name[strlen(item->name) - strlen(abiver)]; 631 if (!strncmp(abiver, tmp, strlen(abiver))) 632 *tmp = '\0'; 633 }; 634 635 item->size = pkg_get_int(pkg, PKG_SIZE); 636 item->version = strcpy(versionptr, version); 637 item->description = description ? strcpy(descriptionptr, description) : NULL; 638 639 args->items = xrealloc(args->items, sizeof(item) * (args->n_items + 1)); 640 args->items[args->n_items++] = item; 641 } 642 643 out: 644 pkg_deinit(pkg); 645 free(pkg); 646 free(version); 647 } 648 649 static int opkg_list_find_cmd_sort(const void *a, const void *b) 650 { 651 const struct opkg_list_find_cmd_item *pkg_a = *(const struct opkg_list_find_cmd_item **)a; 652 const struct opkg_list_find_cmd_item *pkg_b = *(const struct opkg_list_find_cmd_item **)b; 653 return strcmp(pkg_a->name, pkg_b->name); 654 } 655 656 static int opkg_list_find_cmd(int argc, char **argv, int use_desc) 657 { 658 int i; 659 struct opkg_list_find_cmd_args args = { 660 .use_desc = use_desc, 661 .pkg_name = (argc > 0) ? argv[0] : NULL 662 }; 663 664 args.set_status = 0; 665 pkg_hash_load_feeds(SF_NEED_DETAIL, opkg_list_find_cmd_cb, &args); 666 667 args.set_status = 1; 668 pkg_hash_load_status_files(opkg_list_find_cmd_cb, &args); 669 670 if (args.n_items > 1) 671 qsort(args.items, args.n_items, sizeof(args.items[0]), 672 opkg_list_find_cmd_sort); 673 674 for (i = 0; i < args.n_items; i++) { 675 printf("%s - %s", 676 args.items[i]->name, 677 args.items[i]->version); 678 679 if (conf->size) 680 printf(" - %lu", (unsigned long) args.items[i]->size); 681 682 if (args.items[i]->description) 683 printf(" - %s", args.items[i]->description); 684 685 printf("\n"); 686 687 free(args.items[i]); 688 } 689 690 free(args.items); 691 692 return 0; 693 } 694 695 static int opkg_list_cmd(int argc, char **argv) 696 { 697 return opkg_list_find_cmd(argc, argv, 0); 698 } 699 700 static int opkg_find_cmd(int argc, char **argv) 701 { 702 return opkg_list_find_cmd(argc, argv, 1); 703 } 704 705 static int opkg_list_installed_cmd(int argc, char **argv) 706 { 707 int i; 708 pkg_vec_t *available; 709 pkg_t *pkg; 710 char *pkg_name = NULL; 711 712 if (argc > 0) { 713 pkg_name = argv[0]; 714 } 715 available = pkg_vec_alloc(); 716 pkg_hash_fetch_all_installed(available); 717 pkg_vec_sort(available, pkg_compare_names); 718 for (i = 0; i < available->len; i++) { 719 pkg = available->pkgs[i]; 720 /* if we have package name or pattern and pkg does not match, then skip it */ 721 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) 722 continue; 723 print_pkg(pkg); 724 } 725 726 pkg_vec_free(available); 727 728 return 0; 729 } 730 731 static int opkg_list_changed_conffiles_cmd(int argc, char **argv) 732 { 733 int i; 734 pkg_vec_t *available; 735 pkg_t *pkg; 736 char *pkg_name = NULL; 737 conffile_list_elt_t *iter; 738 conffile_list_t *cl; 739 conffile_t *cf; 740 741 if (argc > 0) { 742 pkg_name = argv[0]; 743 } 744 available = pkg_vec_alloc(); 745 pkg_hash_fetch_all_installed(available); 746 pkg_vec_sort(available, pkg_compare_names); 747 for (i = 0; i < available->len; i++) { 748 pkg = available->pkgs[i]; 749 cl = pkg_get_ptr(pkg, PKG_CONFFILES); 750 /* if we have package name or pattern and pkg does not match, then skip it */ 751 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) 752 continue; 753 if (!cl || nv_pair_list_empty(cl)) 754 continue; 755 for (iter = nv_pair_list_first(cl); iter; 756 iter = nv_pair_list_next(cl, iter)) { 757 cf = (conffile_t *) iter->data; 758 if (cf->name && cf->value 759 && conffile_has_been_modified(cf)) 760 printf("%s\n", cf->name); 761 } 762 } 763 pkg_vec_free(available); 764 return 0; 765 } 766 767 static int opkg_list_upgradable_cmd(int argc, char **argv) 768 { 769 struct active_list *head = prepare_upgrade_list(); 770 struct active_list *node = NULL; 771 pkg_t *_old_pkg, *_new_pkg; 772 char *old_v, *new_v; 773 for (node = active_list_next(head, head); node; 774 node = active_list_next(head, node)) { 775 _old_pkg = node->pkg; 776 _new_pkg = 777 pkg_hash_fetch_best_installation_candidate_by_name 778 (_old_pkg->name); 779 if (_new_pkg == NULL) 780 continue; 781 old_v = pkg_version_str_alloc(_old_pkg); 782 new_v = pkg_version_str_alloc(_new_pkg); 783 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v); 784 free(old_v); 785 free(new_v); 786 } 787 active_list_head_delete(head); 788 return 0; 789 } 790 791 static int opkg_info_status_cmd(int argc, char **argv, int installed_only) 792 { 793 int i; 794 pkg_vec_t *available; 795 pkg_t *pkg; 796 char *pkg_name = NULL; 797 conffile_list_t *cl; 798 799 if (argc > 0) { 800 pkg_name = argv[0]; 801 } 802 803 available = pkg_vec_alloc(); 804 if (installed_only) 805 pkg_hash_fetch_all_installed(available); 806 else 807 pkg_hash_fetch_available(available); 808 809 for (i = 0; i < available->len; i++) { 810 pkg = available->pkgs[i]; 811 if (pkg_name && fnmatch(pkg_name, pkg->name, conf->nocase)) { 812 continue; 813 } 814 815 pkg_formatted_info(stdout, pkg); 816 817 cl = pkg_get_ptr(pkg, PKG_CONFFILES); 818 819 if (conf->verbosity >= NOTICE && cl) { 820 conffile_list_elt_t *iter; 821 for (iter = nv_pair_list_first(cl); iter; 822 iter = nv_pair_list_next(cl, iter)) { 823 conffile_t *cf = (conffile_t *) iter->data; 824 int modified = conffile_has_been_modified(cf); 825 if (cf->value) 826 opkg_msg(INFO, 827 "conffile=%s md5sum=%s modified=%d.\n", 828 cf->name, cf->value, modified); 829 } 830 } 831 } 832 pkg_vec_free(available); 833 834 return 0; 835 } 836 837 static int opkg_info_cmd(int argc, char **argv) 838 { 839 return opkg_info_status_cmd(argc, argv, 0); 840 } 841 842 static int opkg_status_cmd(int argc, char **argv) 843 { 844 return opkg_info_status_cmd(argc, argv, 1); 845 } 846 847 static int opkg_configure_cmd(int argc, char **argv) 848 { 849 int err; 850 char *pkg_name = NULL; 851 852 if (argc > 0) 853 pkg_name = argv[0]; 854 855 err = opkg_configure_packages(pkg_name); 856 857 write_status_files_if_changed(); 858 859 return err; 860 } 861 862 static int opkg_remove_cmd(int argc, char **argv) 863 { 864 int i, a, done, err = 0; 865 pkg_t *pkg; 866 pkg_t *pkg_to_remove; 867 pkg_vec_t *available; 868 869 done = 0; 870 871 signal(SIGINT, sigint_handler); 872 873 pkg_info_preinstall_check(); 874 875 available = pkg_vec_alloc(); 876 pkg_hash_fetch_all_installed(available); 877 878 for (i = 0; i < argc; i++) { 879 for (a = 0; a < available->len; a++) { 880 pkg = available->pkgs[a]; 881 if (fnmatch(argv[i], pkg->name, conf->nocase)) { 882 continue; 883 } 884 if (conf->restrict_to_default_dest) { 885 pkg_to_remove = 886 pkg_hash_fetch_installed_by_name_dest(pkg-> 887 name, 888 conf-> 889 default_dest); 890 } else { 891 pkg_to_remove = 892 pkg_hash_fetch_installed_by_name(pkg->name); 893 } 894 895 if (pkg_to_remove == NULL) { 896 opkg_msg(ERROR, 897 "Package %s is not installed.\n", 898 pkg->name); 899 continue; 900 } 901 if (pkg->state_status == SS_NOT_INSTALLED) { 902 opkg_msg(ERROR, "Package %s not installed.\n", 903 pkg->name); 904 continue; 905 } 906 907 if (opkg_remove_pkg(pkg_to_remove, 0)) 908 err = -1; 909 else 910 done = 1; 911 } 912 } 913 914 pkg_vec_free(available); 915 916 if (done == 0) 917 opkg_msg(NOTICE, "No packages removed.\n"); 918 919 write_status_files_if_changed(); 920 return err; 921 } 922 923 static int opkg_flag_cmd(int argc, char **argv) 924 { 925 int i; 926 pkg_t *pkg; 927 const char *flags = argv[0]; 928 929 signal(SIGINT, sigint_handler); 930 931 for (i = 1; i < argc; i++) { 932 if (conf->restrict_to_default_dest) { 933 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i], 934 conf-> 935 default_dest); 936 } else { 937 pkg = pkg_hash_fetch_installed_by_name(argv[i]); 938 } 939 940 if (pkg == NULL) { 941 opkg_msg(ERROR, "Package %s is not installed.\n", 942 argv[i]); 943 continue; 944 } 945 if ((strcmp(flags, "hold") == 0) 946 || (strcmp(flags, "noprune") == 0) 947 || (strcmp(flags, "user") == 0) 948 || (strcmp(flags, "ok") == 0)) { 949 pkg->state_flag = pkg_state_flag_from_str(flags); 950 } 951 952 /* 953 * Useful if a package is installed in an offline_root, and 954 * should be configured by opkg-cl configure at a later date. 955 */ 956 if ((strcmp(flags, "installed") == 0) 957 || (strcmp(flags, "unpacked") == 0)) { 958 pkg->state_status = pkg_state_status_from_str(flags); 959 } 960 961 opkg_state_changed++; 962 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n", 963 pkg->name, flags); 964 } 965 966 write_status_files_if_changed(); 967 return 0; 968 } 969 970 static int opkg_files_cmd(int argc, char **argv) 971 { 972 pkg_t *pkg; 973 str_list_t *files; 974 str_list_elt_t *iter; 975 char *pkg_version; 976 977 if (argc < 1) { 978 return -1; 979 } 980 981 pkg = pkg_hash_fetch_installed_by_name(argv[0]); 982 if (pkg == NULL) { 983 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]); 984 return 0; 985 } 986 987 files = pkg_get_installed_files(pkg); 988 pkg_version = pkg_version_str_alloc(pkg); 989 990 printf 991 ("Package %s (%s) is installed on %s and has the following files:\n", 992 pkg->name, pkg_version, pkg->dest->name); 993 994 for (iter = str_list_first(files); iter; 995 iter = str_list_next(files, iter)) 996 printf("%s\n", (char *)iter->data); 997 998 free(pkg_version); 999 pkg_free_installed_files(pkg); 1000 1001 return 0; 1002 } 1003 1004 static int opkg_depends_cmd(int argc, char **argv) 1005 { 1006 int i, j, k; 1007 pkg_vec_t *available_pkgs; 1008 compound_depend_t *cdep; 1009 pkg_t *pkg; 1010 char *str; 1011 1012 pkg_info_preinstall_check(); 1013 1014 available_pkgs = pkg_vec_alloc(); 1015 if (conf->query_all) 1016 pkg_hash_fetch_available(available_pkgs); 1017 else 1018 pkg_hash_fetch_all_installed(available_pkgs); 1019 1020 for (i = 0; i < argc; i++) { 1021 for (j = 0; j < available_pkgs->len; j++) { 1022 pkg = available_pkgs->pkgs[j]; 1023 1024 if (fnmatch(argv[i], pkg->name, conf->nocase) != 0) 1025 continue; 1026 1027 opkg_msg(NOTICE, "%s depends on:\n", pkg->name); 1028 1029 for (k = 0, cdep = pkg_get_ptr(pkg, PKG_DEPENDS); cdep && cdep->type; k++, cdep++) { 1030 if (cdep->type != DEPEND) 1031 continue; 1032 1033 str = pkg_depend_str(pkg, k); 1034 opkg_msg(NOTICE, "\t%s\n", str); 1035 free(str); 1036 } 1037 1038 } 1039 } 1040 1041 pkg_vec_free(available_pkgs); 1042 return 0; 1043 } 1044 1045 static int pkg_mark_provides(pkg_t * pkg) 1046 { 1047 abstract_pkg_t **provider = pkg_get_ptr(pkg, PKG_PROVIDES); 1048 1049 pkg->parent->state_flag |= SF_MARKED; 1050 1051 while (provider && *provider) { 1052 (*provider)->state_flag |= SF_MARKED; 1053 provider++; 1054 } 1055 1056 return 0; 1057 } 1058 1059 enum what_field_type { 1060 WHATDEPENDS, 1061 WHATCONFLICTS, 1062 WHATPROVIDES, 1063 WHATREPLACES, 1064 WHATRECOMMENDS, 1065 WHATSUGGESTS 1066 }; 1067 1068 static int 1069 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive, 1070 int argc, char **argv) 1071 { 1072 depend_t *possibility; 1073 compound_depend_t *cdep, *deps; 1074 pkg_vec_t *available_pkgs; 1075 pkg_t *pkg; 1076 int i, j, l; 1077 int changed; 1078 const char *rel_str = NULL; 1079 char *ver; 1080 1081 switch (what_field_type) { 1082 case DEPEND: 1083 rel_str = "depends on"; 1084 break; 1085 case CONFLICTS: 1086 rel_str = "conflicts with"; 1087 break; 1088 case SUGGEST: 1089 rel_str = "suggests"; 1090 break; 1091 case RECOMMEND: 1092 rel_str = "recommends"; 1093 break; 1094 default: 1095 return -1; 1096 } 1097 1098 available_pkgs = pkg_vec_alloc(); 1099 1100 if (conf->query_all) 1101 pkg_hash_fetch_available(available_pkgs); 1102 else 1103 pkg_hash_fetch_all_installed(available_pkgs); 1104 1105 /* mark the root set */ 1106 pkg_vec_clear_marks(available_pkgs); 1107 opkg_msg(NOTICE, "Root set:\n"); 1108 for (i = 0; i < argc; i++) 1109 pkg_vec_mark_if_matches(available_pkgs, argv[i]); 1110 1111 for (i = 0; i < available_pkgs->len; i++) { 1112 pkg = available_pkgs->pkgs[i]; 1113 if (pkg->state_flag & SF_MARKED) { 1114 /* mark the parent (abstract) package */ 1115 pkg_mark_provides(pkg); 1116 opkg_msg(NOTICE, " %s\n", pkg->name); 1117 } 1118 } 1119 1120 opkg_msg(NOTICE, "What %s root set\n", rel_str); 1121 do { 1122 changed = 0; 1123 1124 for (j = 0; j < available_pkgs->len; j++) { 1125 1126 pkg = available_pkgs->pkgs[j]; 1127 /* 1128 count = ((what_field_type == CONFLICTS) 1129 ? pkg->conflicts_count 1130 : pkg->pre_depends_count + 1131 pkg->depends_count + 1132 pkg->recommends_count + pkg->suggests_count); 1133 */ 1134 1135 /* skip this package if it is already marked */ 1136 if (pkg->parent->state_flag & SF_MARKED) 1137 continue; 1138 1139 deps = pkg_get_ptr(pkg, (what_field_type == CONFLICTS) ? PKG_CONFLICTS : PKG_DEPENDS); 1140 1141 for (cdep = deps; cdep && cdep->type; cdep++) { 1142 if (what_field_type != cdep->type) 1143 continue; 1144 1145 for (l = 0; l < cdep->possibility_count; l++) { 1146 possibility = cdep->possibilities[l]; 1147 1148 if ((possibility->pkg->state_flag 1149 & SF_MARKED) 1150 != SF_MARKED) 1151 continue; 1152 1153 /* mark the depending package so we 1154 * won't visit it again */ 1155 pkg->state_flag |= SF_MARKED; 1156 pkg_mark_provides(pkg); 1157 changed++; 1158 1159 ver = pkg_version_str_alloc(pkg); 1160 opkg_msg(NOTICE, "\t%s %s\t%s %s", 1161 pkg->name, 1162 ver, 1163 rel_str, 1164 possibility->pkg->name); 1165 free(ver); 1166 if (possibility->version) { 1167 opkg_msg(NOTICE, " (%s%s)", 1168 constraint_to_str 1169 (possibility-> 1170 constraint), 1171 possibility->version); 1172 } 1173 if (!pkg_dependence_satisfiable 1174 (possibility)) 1175 opkg_msg(NOTICE, 1176 " unsatisfiable"); 1177 opkg_message(NOTICE, "\n"); 1178 goto next_package; 1179 } 1180 } 1181 next_package: 1182 ; 1183 } 1184 } while (changed && recursive); 1185 1186 pkg_vec_free(available_pkgs); 1187 1188 return 0; 1189 } 1190 1191 static int opkg_whatdepends_recursively_cmd(int argc, char **argv) 1192 { 1193 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv); 1194 } 1195 1196 static int opkg_whatdepends_cmd(int argc, char **argv) 1197 { 1198 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv); 1199 } 1200 1201 static int opkg_whatsuggests_cmd(int argc, char **argv) 1202 { 1203 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv); 1204 } 1205 1206 static int opkg_whatrecommends_cmd(int argc, char **argv) 1207 { 1208 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv); 1209 } 1210 1211 static int opkg_whatconflicts_cmd(int argc, char **argv) 1212 { 1213 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv); 1214 } 1215 1216 static int 1217 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc, 1218 char **argv) 1219 { 1220 abstract_pkg_t *apkg, **abpkgs; 1221 1222 if (argc > 0) { 1223 pkg_vec_t *available_pkgs = pkg_vec_alloc(); 1224 const char *rel_str = 1225 (what_field_type == WHATPROVIDES ? "provides" : "replaces"); 1226 int i; 1227 1228 pkg_info_preinstall_check(); 1229 1230 if (conf->query_all) 1231 pkg_hash_fetch_available(available_pkgs); 1232 else 1233 pkg_hash_fetch_all_installed(available_pkgs); 1234 for (i = 0; i < argc; i++) { 1235 const char *target = argv[i]; 1236 int j; 1237 1238 opkg_msg(NOTICE, "What %s %s\n", rel_str, target); 1239 for (j = 0; j < available_pkgs->len; j++) { 1240 pkg_t *pkg = available_pkgs->pkgs[j]; 1241 abpkgs = pkg_get_ptr(pkg, (what_field_type == WHATPROVIDES) ? PKG_PROVIDES : PKG_REPLACES); 1242 1243 while (abpkgs && *abpkgs) { 1244 apkg = *abpkgs++; 1245 1246 if (fnmatch(target, apkg->name, conf->nocase)) 1247 continue; 1248 1249 opkg_msg(NOTICE, " %s", pkg->name); 1250 1251 if ((conf->nocase ? strcasecmp(target, apkg->name) 1252 : strcmp(target, apkg->name))) 1253 opkg_msg(NOTICE, "\t%s %s\n", rel_str, apkg->name); 1254 1255 opkg_message(NOTICE, "\n"); 1256 } 1257 } 1258 } 1259 pkg_vec_free(available_pkgs); 1260 } 1261 return 0; 1262 } 1263 1264 static int opkg_whatprovides_cmd(int argc, char **argv) 1265 { 1266 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv); 1267 } 1268 1269 static int opkg_whatreplaces_cmd(int argc, char **argv) 1270 { 1271 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv); 1272 } 1273 1274 static int opkg_search_cmd(int argc, char **argv) 1275 { 1276 int i; 1277 1278 pkg_vec_t *installed; 1279 pkg_t *pkg; 1280 str_list_t *installed_files; 1281 str_list_elt_t *iter; 1282 char *installed_file; 1283 1284 if (argc < 1) { 1285 return -1; 1286 } 1287 1288 installed = pkg_vec_alloc(); 1289 pkg_hash_fetch_all_installed(installed); 1290 pkg_vec_sort(installed, pkg_compare_names); 1291 1292 for (i = 0; i < installed->len; i++) { 1293 pkg = installed->pkgs[i]; 1294 1295 installed_files = pkg_get_installed_files(pkg); 1296 1297 for (iter = str_list_first(installed_files); iter; 1298 iter = str_list_next(installed_files, iter)) { 1299 installed_file = (char *)iter->data; 1300 if (fnmatch(argv[0], installed_file, conf->nocase) == 0) 1301 print_pkg(pkg); 1302 } 1303 1304 pkg_free_installed_files(pkg); 1305 } 1306 1307 pkg_vec_free(installed); 1308 1309 return 0; 1310 } 1311 1312 static int opkg_compare_versions_cmd(int argc, char **argv) 1313 { 1314 int rc; 1315 pkg_t *p1, *p2; 1316 1317 if (argc == 3) { 1318 /* this is a bit gross */ 1319 p1 = pkg_new(); 1320 p2 = pkg_new(); 1321 parse_version(p1, argv[0]); 1322 parse_version(p2, argv[2]); 1323 rc = pkg_version_satisfied(p1, p2, argv[1]); 1324 pkg_deinit(p1); 1325 pkg_deinit(p2); 1326 free(p1); 1327 free(p2); 1328 return rc ? 0 : 1; 1329 } else { 1330 opkg_msg(ERROR, 1331 "opkg compare_versions <v1> <op> <v2>\n" 1332 "<op> is one of <= >= << >> =\n"); 1333 return -1; 1334 } 1335 } 1336 1337 static int opkg_print_architecture_cmd(int argc, char **argv) 1338 { 1339 nv_pair_list_elt_t *l; 1340 1341 list_for_each_entry(l, &conf->arch_list.head, node) { 1342 nv_pair_t *nv = (nv_pair_t *) l->data; 1343 printf("arch %s %s\n", nv->name, nv->value); 1344 } 1345 return 0; 1346 } 1347 1348 /* XXX: CLEANUP: The usage strings should be incorporated into this 1349 array for easier maintenance */ 1350 static opkg_cmd_t cmds[] = { 1351 {"update", 0, (opkg_cmd_fun_t) opkg_update_cmd, 1352 PFM_DESCRIPTION | PFM_SOURCE}, 1353 {"upgrade", 1, (opkg_cmd_fun_t) opkg_upgrade_cmd, 1354 PFM_DESCRIPTION | PFM_SOURCE}, 1355 {"list", 0, (opkg_cmd_fun_t) opkg_list_cmd, PFM_SOURCE}, 1356 {"list_installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd, 1357 PFM_SOURCE}, 1358 {"list-installed", 0, (opkg_cmd_fun_t) opkg_list_installed_cmd, 1359 PFM_SOURCE}, 1360 {"list_upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd, 1361 PFM_SOURCE}, 1362 {"list-upgradable", 0, (opkg_cmd_fun_t) opkg_list_upgradable_cmd, 1363 PFM_SOURCE}, 1364 {"list_changed_conffiles", 0, 1365 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE}, 1366 {"list-changed-conffiles", 0, 1367 (opkg_cmd_fun_t) opkg_list_changed_conffiles_cmd, PFM_SOURCE}, 1368 {"info", 0, (opkg_cmd_fun_t) opkg_info_cmd, 0}, 1369 {"flag", 1, (opkg_cmd_fun_t) opkg_flag_cmd, 1370 PFM_DESCRIPTION | PFM_SOURCE}, 1371 {"status", 0, (opkg_cmd_fun_t) opkg_status_cmd, 1372 PFM_DESCRIPTION | PFM_SOURCE}, 1373 {"install", 1, (opkg_cmd_fun_t) opkg_install_cmd, 1374 PFM_DESCRIPTION | PFM_SOURCE}, 1375 {"remove", 1, (opkg_cmd_fun_t) opkg_remove_cmd, 1376 PFM_DESCRIPTION | PFM_SOURCE}, 1377 {"configure", 0, (opkg_cmd_fun_t) opkg_configure_cmd, 1378 PFM_DESCRIPTION | PFM_SOURCE}, 1379 {"files", 1, (opkg_cmd_fun_t) opkg_files_cmd, 1380 PFM_DESCRIPTION | PFM_SOURCE}, 1381 {"search", 1, (opkg_cmd_fun_t) opkg_search_cmd, 1382 PFM_DESCRIPTION | PFM_SOURCE}, 1383 {"find", 1, (opkg_cmd_fun_t) opkg_find_cmd, PFM_SOURCE}, 1384 {"download", 1, (opkg_cmd_fun_t) opkg_download_cmd, 1385 PFM_DESCRIPTION | PFM_SOURCE}, 1386 {"compare_versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd, 0}, 1387 {"compare-versions", 1, (opkg_cmd_fun_t) opkg_compare_versions_cmd, 0}, 1388 {"print-architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd, 1389 PFM_DESCRIPTION | PFM_SOURCE}, 1390 {"print_architecture", 0, (opkg_cmd_fun_t) opkg_print_architecture_cmd, 1391 PFM_DESCRIPTION | PFM_SOURCE}, 1392 {"print-installation-architecture", 0, 1393 (opkg_cmd_fun_t) opkg_print_architecture_cmd, 1394 PFM_DESCRIPTION | PFM_SOURCE}, 1395 {"print_installation_architecture", 0, 1396 (opkg_cmd_fun_t) opkg_print_architecture_cmd, 1397 PFM_DESCRIPTION | PFM_SOURCE}, 1398 {"depends", 1, (opkg_cmd_fun_t) opkg_depends_cmd, 1399 PFM_DESCRIPTION | PFM_SOURCE}, 1400 {"whatdepends", 1, (opkg_cmd_fun_t) opkg_whatdepends_cmd, 1401 PFM_DESCRIPTION | PFM_SOURCE}, 1402 {"whatdependsrec", 1, (opkg_cmd_fun_t) opkg_whatdepends_recursively_cmd, 1403 PFM_DESCRIPTION | PFM_SOURCE}, 1404 {"whatrecommends", 1, (opkg_cmd_fun_t) opkg_whatrecommends_cmd, 1405 PFM_DESCRIPTION | PFM_SOURCE}, 1406 {"whatsuggests", 1, (opkg_cmd_fun_t) opkg_whatsuggests_cmd, 1407 PFM_DESCRIPTION | PFM_SOURCE}, 1408 {"whatprovides", 1, (opkg_cmd_fun_t) opkg_whatprovides_cmd, 1409 PFM_DESCRIPTION | PFM_SOURCE}, 1410 {"whatreplaces", 1, (opkg_cmd_fun_t) opkg_whatreplaces_cmd, 1411 PFM_DESCRIPTION | PFM_SOURCE}, 1412 {"whatconflicts", 1, (opkg_cmd_fun_t) opkg_whatconflicts_cmd, 1413 PFM_DESCRIPTION | PFM_SOURCE}, 1414 }; 1415 1416 opkg_cmd_t *opkg_cmd_find(const char *name) 1417 { 1418 int i; 1419 opkg_cmd_t *cmd; 1420 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t); 1421 1422 for (i = 0; i < num_cmds; i++) { 1423 cmd = &cmds[i]; 1424 if (strcmp(name, cmd->name) == 0) 1425 return cmd; 1426 } 1427 1428 return NULL; 1429 } 1430 1431 int opkg_cmd_exec(opkg_cmd_t * cmd, int argc, const char **argv) 1432 { 1433 opkg_cli_argc = argc; 1434 opkg_cli_argv = argv; 1435 return (cmd->fun) (argc, argv); 1436 } 1437
This page was automatically generated by LXR 0.3.1. • OpenWrt