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