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