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