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