Fix --force-reinstall by removing special case code. Just remove the pkg first.
[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
47 print_pkg(pkg_t *pkg)
48 {
49 char *version = pkg_version_str_alloc(pkg);
50 if (pkg->description)
51 printf("%s - %s - %s\n", pkg->name, version, pkg->description);
52 else
53 printf("%s - %s\n", pkg->name, version);
54 free(version);
55 }
56
57 int opkg_state_changed;
58
59 static void
60 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
72 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
81 opkg_update_cmd(int argc, char **argv)
82 {
83 char *tmp;
84 int err;
85 int failures;
86 char *lists_dir;
87 pkg_src_list_elt_t *iter;
88 pkg_src_t *src;
89
90
91 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->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
116 for (iter = void_list_first(&conf->pkg_src_list); iter; 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) /* debian style? */
122 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
123 src->gzip ? "Packages.gz" : "Packages");
124 else
125 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
126
127 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
128 if (src->gzip) {
129 char *tmp_file_name;
130 FILE *in, *out;
131
132 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
133 err = opkg_download(url, tmp_file_name, NULL, NULL);
134 if (err == 0) {
135 opkg_msg(NOTICE, "Inflating %s.\n", url);
136 in = fopen (tmp_file_name, "r");
137 out = fopen (list_file_name, "w");
138 if (in && out)
139 unzip (in, out);
140 else
141 err = 1;
142 if (in)
143 fclose (in);
144 if (out)
145 fclose (out);
146 unlink (tmp_file_name);
147 }
148 free(tmp_file_name);
149 } else
150 err = opkg_download(url, list_file_name, NULL, NULL);
151 if (err) {
152 failures++;
153 } else {
154 opkg_msg(NOTICE, "Updated list of available packages in %s.\n",
155 list_file_name);
156 }
157 free(url);
158 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
159 if (conf->check_signature) {
160 /* download detached signitures to verify the package lists */
161 /* get the url for the sig file */
162 if (src->extra_data) /* debian style? */
163 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
164 "Packages.sig");
165 else
166 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
167
168 /* create temporary file for it */
169 char *tmp_file_name;
170
171 /* Put the signature in the right place */
172 sprintf_alloc (&tmp_file_name, "%s/%s.sig", lists_dir, src->name);
173
174 err = opkg_download(url, tmp_file_name, NULL, NULL);
175 if (err) {
176 failures++;
177 opkg_msg(NOTICE, "Signature check failed.\n");
178 } else {
179 err = opkg_verify_file (list_file_name, tmp_file_name);
180 if (err == 0)
181 opkg_msg(NOTICE, "Signature check passed.\n");
182 else
183 opkg_msg(NOTICE, "Signature check failed.\n");
184 }
185 /* We shouldn't unlink the signature ! */
186 // unlink (tmp_file_name);
187 free (tmp_file_name);
188 free (url);
189 }
190 #else
191 // Do nothing
192 #endif
193 free(list_file_name);
194 }
195 rmdir (tmp);
196 free (tmp);
197 free(lists_dir);
198
199 return failures;
200 }
201
202
203 struct opkg_intercept
204 {
205 char *oldpath;
206 char *statedir;
207 };
208
209 typedef struct opkg_intercept *opkg_intercept_t;
210
211 static opkg_intercept_t
212 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", 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
239 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, 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", pkg->name);
308 return 0;
309 }
310
311 pkg_vec_insert(visited, pkg);
312
313 count = pkg->pre_depends_count + pkg->depends_count + \
314 pkg->recommends_count + pkg->suggests_count;
315
316 opkg_msg(DEBUG, "pkg %s.\n", pkg->name);
317
318 /* Iterate over all the dependencies of pkg. For each one, find a package
319 that is either installed or unpacked and satisfies this dependency.
320 (there should only be one such package per dependency installed or
321 unpacked). Then recurse to the dependency package */
322 for (j=0; j < count ; j++) {
323 compound_depend = &pkg->depends[j];
324 possible_satisfiers = compound_depend->possibilities;
325 for (k=0; k < compound_depend->possibility_count ; k++) {
326 abpkg = possible_satisfiers[k]->pkg;
327 dependents = abpkg->provided_by->pkgs;
328 l = 0;
329 if (dependents != NULL)
330 while (l < abpkg->provided_by->len && dependents[l] != NULL) {
331 opkg_msg(DEBUG, "Descending on pkg %s.\n",
332 dependents [l]->name);
333
334 /* find whether dependent l is installed or unpacked,
335 * and then find which package in the list satisfies it */
336 for(m = 0; m < all->len; m++) {
337 dep = all->pkgs[m];
338 if ( dep->state_status != SS_NOT_INSTALLED)
339 if ( ! strcmp(dep->name, dependents[l]->name)) {
340 opkg_recurse_pkgs_in_order(dep, all,
341 visited, ordered);
342 /* Stop the outer loop */
343 l = abpkg->provided_by->len;
344 /* break from the inner loop */
345 break;
346 }
347 }
348 l++;
349 }
350 }
351 }
352
353 /* When all recursions from this node down, are over, and all
354 dependencies have been added in proper order in the ordered array, add
355 also the package pkg to ordered array */
356 pkg_vec_insert(ordered, pkg);
357
358 return 0;
359
360 }
361
362 static int
363 opkg_configure_packages(char *pkg_name)
364 {
365 pkg_vec_t *all, *ordered, *visited;
366 int i;
367 pkg_t *pkg;
368 opkg_intercept_t ic;
369 int r, err = 0;
370
371 opkg_msg(INFO, "Configuring unpacked packages.\n");
372
373 all = pkg_vec_alloc();
374
375 pkg_hash_fetch_available(all);
376
377 /* Reorder pkgs in order to be configured according to the Depends: tag
378 order */
379 opkg_msg(INFO, "Reordering packages before configuring them...\n");
380 ordered = pkg_vec_alloc();
381 visited = pkg_vec_alloc();
382 for(i = 0; i < all->len; i++) {
383 pkg = all->pkgs[i];
384 opkg_recurse_pkgs_in_order(pkg, all, visited, ordered);
385 }
386
387 ic = opkg_prep_intercepts();
388 if (ic == NULL) {
389 err = -1;
390 goto error;
391 }
392
393 for(i = 0; i < ordered->len; i++) {
394 pkg = ordered->pkgs[i];
395
396 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
397 continue;
398
399 if (pkg->state_status == SS_UNPACKED) {
400 opkg_msg(NOTICE, "Configuring %s.\n", pkg->name);
401 r = opkg_configure(pkg);
402 if (r == 0) {
403 pkg->state_status = SS_INSTALLED;
404 pkg->parent->state_status = SS_INSTALLED;
405 pkg->state_flag &= ~SF_PREFER;
406 opkg_state_changed++;
407 } else {
408 if (!err)
409 err = r;
410 }
411 }
412 }
413
414 r = opkg_finalize_intercepts (ic);
415 if (r && !err)
416 err = r;
417
418 error:
419 pkg_vec_free(all);
420 pkg_vec_free(ordered);
421 pkg_vec_free(visited);
422
423 return err;
424 }
425
426 static int
427 opkg_remove_cmd(int argc, char **argv);
428
429 static int
430 opkg_install_cmd(int argc, char **argv)
431 {
432 int i, r;
433 char *arg;
434 int err=0;
435
436 if (conf->force_reinstall) {
437 int saved_force_depends = conf->force_depends;
438 conf->force_depends = 1;
439 (void)opkg_remove_cmd(argc, argv);
440 conf->force_depends = saved_force_depends;
441 conf->force_reinstall = 0;
442 }
443
444 signal(SIGINT, sigint_handler);
445
446 /*
447 * Now scan through package names and install
448 */
449 for (i=0; i < argc; i++) {
450 arg = argv[i];
451
452 opkg_msg(DEBUG2, "%s\n", arg);
453 err = opkg_prepare_url_for_install(arg, &argv[i]);
454 if (err)
455 return err;
456 }
457 pkg_info_preinstall_check();
458
459 for (i=0; i < argc; i++) {
460 arg = argv[i];
461 err = opkg_install_by_name(arg);
462 if (err) {
463 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
464 }
465 }
466
467 r = opkg_configure_packages(NULL);
468 if (!err)
469 err = r;
470
471 write_status_files_if_changed();
472
473 return err;
474 }
475
476 static int
477 opkg_upgrade_cmd(int argc, char **argv)
478 {
479 int i, r;
480 pkg_t *pkg;
481 int err;
482
483 signal(SIGINT, sigint_handler);
484
485 if (argc) {
486 for (i=0; i < argc; i++) {
487 char *arg = argv[i];
488
489 err = opkg_prepare_url_for_install(arg, &arg);
490 if (err)
491 return err;
492 }
493 pkg_info_preinstall_check();
494
495 for (i=0; i < argc; i++) {
496 char *arg = argv[i];
497 if (conf->restrict_to_default_dest) {
498 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
499 conf->default_dest);
500 if (pkg == NULL) {
501 opkg_msg(NOTICE, "Package %s not installed in %s.\n",
502 argv[i], conf->default_dest->name);
503 continue;
504 }
505 } else {
506 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
507 }
508 if (pkg)
509 opkg_upgrade_pkg(pkg);
510 else {
511 opkg_install_by_name(arg);
512 }
513 }
514 } else {
515 pkg_vec_t *installed = pkg_vec_alloc();
516
517 pkg_info_preinstall_check();
518
519 pkg_hash_fetch_all_installed(installed);
520 for (i = 0; i < installed->len; i++) {
521 pkg = installed->pkgs[i];
522 opkg_upgrade_pkg(pkg);
523 }
524 pkg_vec_free(installed);
525 }
526
527 r = opkg_configure_packages(NULL);
528 if (!err)
529 err = r;
530
531 write_status_files_if_changed();
532
533 return 0;
534 }
535
536 static int
537 opkg_download_cmd(int argc, char **argv)
538 {
539 int i, err = 0;
540 char *arg;
541 pkg_t *pkg;
542
543 pkg_info_preinstall_check();
544 for (i = 0; i < argc; i++) {
545 arg = argv[i];
546
547 pkg = pkg_hash_fetch_best_installation_candidate_by_name(arg);
548 if (pkg == NULL) {
549 opkg_msg(ERROR, "Cannot find package %s.\n", arg);
550 continue;
551 }
552
553 err = opkg_download_pkg(pkg, ".");
554
555 if (err) {
556 opkg_msg(ERROR, "Failed to download %s.\n", pkg->name);
557 } else {
558 opkg_msg(NOTICE, "Downloaded %s as %s.\n",
559 pkg->name, pkg->local_filename);
560 }
561 }
562
563 return err;
564 }
565
566
567 static int
568 opkg_list_cmd(int argc, char **argv)
569 {
570 int i;
571 pkg_vec_t *available;
572 pkg_t *pkg;
573 char *pkg_name = NULL;
574
575 if (argc > 0) {
576 pkg_name = argv[0];
577 }
578 available = pkg_vec_alloc();
579 pkg_hash_fetch_available(available);
580 pkg_vec_sort(available, pkg_compare_names);
581 for (i=0; i < available->len; i++) {
582 pkg = available->pkgs[i];
583 /* if we have package name or pattern and pkg does not match, then skip it */
584 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
585 continue;
586 print_pkg(pkg);
587 }
588 pkg_vec_free(available);
589
590 return 0;
591 }
592
593
594 static int
595 opkg_list_installed_cmd(int argc, char **argv)
596 {
597 int i ;
598 pkg_vec_t *available;
599 pkg_t *pkg;
600 char *pkg_name = NULL;
601
602 if (argc > 0) {
603 pkg_name = argv[0];
604 }
605 available = pkg_vec_alloc();
606 pkg_hash_fetch_all_installed(available);
607 pkg_vec_sort(available, pkg_compare_names);
608 for (i=0; i < available->len; i++) {
609 pkg = available->pkgs[i];
610 /* if we have package name or pattern and pkg does not match, then skip it */
611 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
612 continue;
613 print_pkg(pkg);
614 }
615
616 pkg_vec_free(available);
617
618 return 0;
619 }
620
621 static int
622 opkg_list_upgradable_cmd(int argc, char **argv)
623 {
624 struct active_list *head = prepare_upgrade_list();
625 struct active_list *node=NULL;
626 pkg_t *_old_pkg, *_new_pkg;
627 char *old_v, *new_v;
628 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
629 _old_pkg = list_entry(node, pkg_t, list);
630 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg->name);
631 if (_new_pkg == NULL)
632 continue;
633 old_v = pkg_version_str_alloc(_old_pkg);
634 new_v = pkg_version_str_alloc(_new_pkg);
635 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
636 free(old_v);
637 free(new_v);
638 }
639 active_list_head_delete(head);
640 return 0;
641 }
642
643 static int
644 opkg_info_status_cmd(int argc, char **argv, int installed_only)
645 {
646 int i;
647 pkg_vec_t *available;
648 pkg_t *pkg;
649 char *pkg_name = NULL;
650
651 if (argc > 0) {
652 pkg_name = argv[0];
653 }
654
655 available = pkg_vec_alloc();
656 if (installed_only)
657 pkg_hash_fetch_all_installed(available);
658 else
659 pkg_hash_fetch_available(available);
660
661 for (i=0; i < available->len; i++) {
662 pkg = available->pkgs[i];
663 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
664 continue;
665 }
666
667 pkg_formatted_info(stdout, pkg);
668
669 if (conf->verbosity >= NOTICE) {
670 conffile_list_elt_t *iter;
671 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
672 conffile_t *cf = (conffile_t *)iter->data;
673 int modified = conffile_has_been_modified(cf);
674 if (cf->value)
675 opkg_msg(INFO, "conffile=%s md5sum=%s modified=%d.\n",
676 cf->name, cf->value, modified);
677 }
678 }
679 }
680 pkg_vec_free(available);
681
682 return 0;
683 }
684
685 static int
686 opkg_info_cmd(int argc, char **argv)
687 {
688 return opkg_info_status_cmd(argc, argv, 0);
689 }
690
691 static int
692 opkg_status_cmd(int argc, char **argv)
693 {
694 return opkg_info_status_cmd(argc, argv, 1);
695 }
696
697 static int
698 opkg_configure_cmd(int argc, char **argv)
699 {
700 int err;
701 char *pkg_name = NULL;
702
703 if (argc > 0)
704 pkg_name = argv[0];
705
706 err = opkg_configure_packages(pkg_name);
707
708 write_status_files_if_changed();
709
710 return err;
711 }
712
713 static int
714 opkg_remove_cmd(int argc, char **argv)
715 {
716 int i, a, done, r, err = 0;
717 pkg_t *pkg;
718 pkg_t *pkg_to_remove;
719 pkg_vec_t *available;
720
721 done = 0;
722
723 signal(SIGINT, sigint_handler);
724
725 pkg_info_preinstall_check();
726
727 available = pkg_vec_alloc();
728 pkg_hash_fetch_all_installed(available);
729
730 for (i=0; i<argc; i++) {
731 for (a=0; a<available->len; a++) {
732 pkg = available->pkgs[a];
733 if (fnmatch(argv[i], pkg->name, 0)) {
734 continue;
735 }
736 if (conf->restrict_to_default_dest) {
737 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(
738 pkg->name,
739 conf->default_dest);
740 } else {
741 pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name);
742 }
743
744 if (pkg_to_remove == NULL) {
745 opkg_msg(ERROR, "Package %s is not installed.\n", pkg->name);
746 continue;
747 }
748 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
749 opkg_msg(ERROR, "Package %s not installed.\n", pkg->name);
750 continue;
751 }
752 r = opkg_remove_pkg(pkg_to_remove, 0);
753 if (!err)
754 err = r;
755
756 done = 1;
757 }
758 }
759
760 pkg_vec_free(available);
761
762 if (done == 0)
763 opkg_msg(NOTICE, "No packages removed.\n");
764
765 write_status_files_if_changed();
766 return err;
767 }
768
769 static int
770 opkg_flag_cmd(int argc, char **argv)
771 {
772 int i;
773 pkg_t *pkg;
774 const char *flags = argv[0];
775
776 signal(SIGINT, sigint_handler);
777
778 for (i=1; i < argc; i++) {
779 if (conf->restrict_to_default_dest) {
780 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
781 conf->default_dest);
782 } else {
783 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
784 }
785
786 if (pkg == NULL) {
787 opkg_msg(ERROR, "Package %s is not installed.\n", argv[i]);
788 continue;
789 }
790 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
791 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
792 pkg->state_flag = pkg_state_flag_from_str(flags);
793 }
794
795 /*
796 * Useful if a package is installed in an offline_root, and
797 * should be configured by opkg-cl configure at a later date.
798 */
799 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
800 pkg->state_status = pkg_state_status_from_str(flags);
801 }
802
803 opkg_state_changed++;
804 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
805 pkg->name, flags);
806 }
807
808 write_status_files_if_changed();
809 return 0;
810 }
811
812 static int
813 opkg_files_cmd(int argc, char **argv)
814 {
815 pkg_t *pkg;
816 str_list_t *files;
817 str_list_elt_t *iter;
818 char *pkg_version;
819
820 if (argc < 1) {
821 return -1;
822 }
823
824 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
825 if (pkg == NULL) {
826 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
827 return 0;
828 }
829
830 files = pkg_get_installed_files(pkg);
831 pkg_version = pkg_version_str_alloc(pkg);
832
833 printf("Package %s (%s) is installed on %s and has the following files:\n",
834 pkg->name, pkg_version, pkg->dest->name);
835
836 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
837 printf("%s\n", (char *)iter->data);
838
839 free(pkg_version);
840 pkg_free_installed_files(pkg);
841
842 return 0;
843 }
844
845 static int
846 opkg_depends_cmd(int argc, char **argv)
847 {
848 int i, j, k;
849 int depends_count;
850 pkg_vec_t *available_pkgs;
851 compound_depend_t *cdep;
852 pkg_t *pkg;
853 char *str;
854
855 pkg_info_preinstall_check();
856
857 available_pkgs = pkg_vec_alloc();
858 if (conf->query_all)
859 pkg_hash_fetch_available(available_pkgs);
860 else
861 pkg_hash_fetch_all_installed(available_pkgs);
862
863 for (i=0; i<argc; i++) {
864 for (j=0; j<available_pkgs->len; j++) {
865 pkg = available_pkgs->pkgs[j];
866
867 if (fnmatch(argv[i], pkg->name, 0) != 0)
868 continue;
869
870 depends_count = pkg->depends_count +
871 pkg->pre_depends_count +
872 pkg->recommends_count +
873 pkg->suggests_count;
874
875 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
876
877 for (k=0; k<depends_count; k++) {
878 cdep = &pkg->depends[k];
879
880 if (cdep->type != DEPEND)
881 continue;
882
883 str = pkg_depend_str(pkg, k);
884 opkg_msg(NOTICE, "\t%s\n", str);
885 free(str);
886 }
887
888 }
889 }
890
891 pkg_vec_free(available_pkgs);
892 return 0;
893 }
894
895 static int
896 pkg_mark_provides(pkg_t *pkg)
897 {
898 int provides_count = pkg->provides_count;
899 abstract_pkg_t **provides = pkg->provides;
900 int i;
901 pkg->parent->state_flag |= SF_MARKED;
902 for (i = 0; i < provides_count; i++) {
903 provides[i]->state_flag |= SF_MARKED;
904 }
905 return 0;
906 }
907
908 enum what_field_type {
909 WHATDEPENDS,
910 WHATCONFLICTS,
911 WHATPROVIDES,
912 WHATREPLACES,
913 WHATRECOMMENDS,
914 WHATSUGGESTS
915 };
916
917 static int
918 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive, int argc, char **argv)
919 {
920 depend_t *possibility;
921 compound_depend_t *cdep;
922 pkg_vec_t *available_pkgs;
923 pkg_t *pkg;
924 int i, j, k, l;
925 int changed, count;
926 const char *rel_str = NULL;
927 char *ver;
928
929 switch (what_field_type) {
930 case DEPEND: rel_str = "depends on"; break;
931 case CONFLICTS: rel_str = "conflicts with"; break;
932 case SUGGEST: rel_str = "suggests"; break;
933 case RECOMMEND: rel_str = "recommends"; break;
934 default: return -1;
935 }
936
937 available_pkgs = pkg_vec_alloc();
938
939 if (conf->query_all)
940 pkg_hash_fetch_available(available_pkgs);
941 else
942 pkg_hash_fetch_all_installed(available_pkgs);
943
944 /* mark the root set */
945 pkg_vec_clear_marks(available_pkgs);
946 opkg_msg(NOTICE, "Root set:\n");
947 for (i = 0; i < argc; i++)
948 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
949
950 for (i = 0; i < available_pkgs->len; i++) {
951 pkg = available_pkgs->pkgs[i];
952 if (pkg->state_flag & SF_MARKED) {
953 /* mark the parent (abstract) package */
954 pkg_mark_provides(pkg);
955 opkg_msg(NOTICE, " %s\n", pkg->name);
956 }
957 }
958
959 opkg_msg(NOTICE, "What %s root set\n", rel_str);
960 do {
961 changed = 0;
962
963 for (j=0; j<available_pkgs->len; j++) {
964
965 pkg = available_pkgs->pkgs[j];
966 count = ((what_field_type == CONFLICTS)
967 ? pkg->conflicts_count
968 : pkg->pre_depends_count +
969 pkg->depends_count +
970 pkg->recommends_count +
971 pkg->suggests_count);
972
973 /* skip this package if it is already marked */
974 if (pkg->parent->state_flag & SF_MARKED)
975 continue;
976
977 for (k=0; k<count; k++) {
978 cdep = (what_field_type == CONFLICTS)
979 ? &pkg->conflicts[k]
980 : &pkg->depends[k];
981
982 if (what_field_type != cdep->type)
983 continue;
984
985 for (l=0; l<cdep->possibility_count; l++) {
986 possibility = cdep->possibilities[l];
987
988 if ((possibility->pkg->state_flag
989 & SF_MARKED)
990 != SF_MARKED)
991 continue;
992
993 /* mark the depending package so we
994 * won't visit it again */
995 pkg->state_flag |= SF_MARKED;
996 pkg_mark_provides(pkg);
997 changed++;
998
999 ver = pkg_version_str_alloc(pkg);
1000 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1001 pkg->name,
1002 ver,
1003 rel_str,
1004 possibility->pkg->name);
1005 free(ver);
1006 if (possibility->version) {
1007 opkg_msg(NOTICE, " (%s%s)",
1008 constraint_to_str(possibility->constraint),
1009 possibility->version);
1010 }
1011 if (!pkg_dependence_satisfiable(possibility))
1012 opkg_msg(NOTICE,
1013 " unsatisfiable");
1014 opkg_msg(NOTICE, "\n");
1015 goto next_package;
1016 }
1017 }
1018 next_package:
1019 ;
1020 }
1021 } while (changed && recursive);
1022
1023 pkg_vec_free(available_pkgs);
1024
1025 return 0;
1026 }
1027
1028 static int
1029 opkg_whatdepends_recursively_cmd(int argc, char **argv)
1030 {
1031 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1032 }
1033
1034 static int
1035 opkg_whatdepends_cmd(int argc, char **argv)
1036 {
1037 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1038 }
1039
1040 static int
1041 opkg_whatsuggests_cmd(int argc, char **argv)
1042 {
1043 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1044 }
1045
1046 static int
1047 opkg_whatrecommends_cmd(int argc, char **argv)
1048 {
1049 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1050 }
1051
1052 static int
1053 opkg_whatconflicts_cmd(int argc, char **argv)
1054 {
1055 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1056 }
1057
1058 static int
1059 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc, char **argv)
1060 {
1061
1062 if (argc > 0) {
1063 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1064 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1065 int i;
1066
1067 pkg_info_preinstall_check();
1068
1069 if (conf->query_all)
1070 pkg_hash_fetch_available(available_pkgs);
1071 else
1072 pkg_hash_fetch_all_installed(available_pkgs);
1073 for (i = 0; i < argc; i++) {
1074 const char *target = argv[i];
1075 int j;
1076
1077 opkg_msg(NOTICE, "What %s %s\n",
1078 rel_str, target);
1079 for (j = 0; j < available_pkgs->len; j++) {
1080 pkg_t *pkg = available_pkgs->pkgs[j];
1081 int k;
1082 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1083 for (k = 0; k < count; k++) {
1084 abstract_pkg_t *apkg =
1085 ((what_field_type == WHATPROVIDES)
1086 ? pkg->provides[k]
1087 : pkg->replaces[k]);
1088 if (fnmatch(target, apkg->name, 0) == 0) {
1089 opkg_msg(NOTICE, " %s", pkg->name);
1090 if (strcmp(target, apkg->name) != 0)
1091 opkg_msg(NOTICE, "\t%s %s\n",
1092 rel_str, apkg->name);
1093 opkg_msg(NOTICE, "\n");
1094 }
1095 }
1096 }
1097 }
1098 pkg_vec_free(available_pkgs);
1099 }
1100 return 0;
1101 }
1102
1103 static int
1104 opkg_whatprovides_cmd(int argc, char **argv)
1105 {
1106 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1107 }
1108
1109 static int
1110 opkg_whatreplaces_cmd(int argc, char **argv)
1111 {
1112 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1113 }
1114
1115 static int
1116 opkg_search_cmd(int argc, char **argv)
1117 {
1118 int i;
1119
1120 pkg_vec_t *installed;
1121 pkg_t *pkg;
1122 str_list_t *installed_files;
1123 str_list_elt_t *iter;
1124 char *installed_file;
1125
1126 if (argc < 1) {
1127 return -1;
1128 }
1129
1130 installed = pkg_vec_alloc();
1131 pkg_hash_fetch_all_installed(installed);
1132 pkg_vec_sort(installed, pkg_compare_names);
1133
1134 for (i=0; i < installed->len; i++) {
1135 pkg = installed->pkgs[i];
1136
1137 installed_files = pkg_get_installed_files(pkg);
1138
1139 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1140 installed_file = (char *)iter->data;
1141 if (fnmatch(argv[0], installed_file, 0)==0)
1142 print_pkg(pkg);
1143 }
1144
1145 pkg_free_installed_files(pkg);
1146 }
1147
1148 pkg_vec_free(installed);
1149
1150 return 0;
1151 }
1152
1153 static int
1154 opkg_compare_versions_cmd(int argc, char **argv)
1155 {
1156 if (argc == 3) {
1157 /* this is a bit gross */
1158 struct pkg p1, p2;
1159 parse_version(&p1, argv[0]);
1160 parse_version(&p2, argv[2]);
1161 return pkg_version_satisfied(&p1, &p2, argv[1]);
1162 } else {
1163 opkg_msg(ERROR,
1164 "opkg compare_versions <v1> <op> <v2>\n"
1165 "<op> is one of <= >= << >> =\n");
1166 return -1;
1167 }
1168 }
1169
1170 static int
1171 opkg_print_architecture_cmd(int argc, char **argv)
1172 {
1173 nv_pair_list_elt_t *l;
1174
1175 list_for_each_entry(l, &conf->arch_list.head, node) {
1176 nv_pair_t *nv = (nv_pair_t *)l->data;
1177 printf("arch %s %s\n", nv->name, nv->value);
1178 }
1179 return 0;
1180 }
1181
1182
1183 /* XXX: CLEANUP: The usage strings should be incorporated into this
1184 array for easier maintenance */
1185 static opkg_cmd_t cmds[] = {
1186 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1187 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1188 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE},
1189 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1190 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1191 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1192 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1193 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd, 0},
1194 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1195 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1196 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1197 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1198 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1199 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1200 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1201 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1202 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1203 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1204 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1205 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1206 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1207 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1208 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1209 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1210 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1211 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1212 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1213 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1214 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1215 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1216 };
1217
1218 opkg_cmd_t *
1219 opkg_cmd_find(const char *name)
1220 {
1221 int i;
1222 opkg_cmd_t *cmd;
1223 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1224
1225 for (i=0; i < num_cmds; i++) {
1226 cmd = &cmds[i];
1227 if (strcmp(name, cmd->name) == 0)
1228 return cmd;
1229 }
1230
1231 return NULL;
1232 }
1233
1234 int
1235 opkg_cmd_exec(opkg_cmd_t *cmd, int argc, const char **argv)
1236 {
1237 return (cmd->fun)(argc, argv);
1238 }