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