Don't print the function name when just outputting a \n.
[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 err = -1;
409 }
410 }
411 }
412
413 if (opkg_finalize_intercepts (ic))
414 err = -1;
415
416 error:
417 pkg_vec_free(all);
418 pkg_vec_free(ordered);
419 pkg_vec_free(visited);
420
421 return err;
422 }
423
424 static int
425 opkg_remove_cmd(int argc, char **argv);
426
427 static int
428 opkg_install_cmd(int argc, char **argv)
429 {
430 int i;
431 char *arg;
432 int err = 0;
433
434 if (conf->force_reinstall) {
435 int saved_force_depends = conf->force_depends;
436 conf->force_depends = 1;
437 (void)opkg_remove_cmd(argc, argv);
438 conf->force_depends = saved_force_depends;
439 conf->force_reinstall = 0;
440 }
441
442 signal(SIGINT, sigint_handler);
443
444 /*
445 * Now scan through package names and install
446 */
447 for (i=0; i < argc; i++) {
448 arg = argv[i];
449
450 opkg_msg(DEBUG2, "%s\n", arg);
451 if (opkg_prepare_url_for_install(arg, &argv[i]))
452 return -1;
453 }
454 pkg_info_preinstall_check();
455
456 for (i=0; i < argc; i++) {
457 arg = argv[i];
458 if (opkg_install_by_name(arg)) {
459 opkg_msg(ERROR, "Cannot install package %s.\n", arg);
460 err = -1;
461 }
462 }
463
464 if (opkg_configure_packages(NULL))
465 err = -1;
466
467 write_status_files_if_changed();
468
469 return err;
470 }
471
472 static int
473 opkg_upgrade_cmd(int argc, char **argv)
474 {
475 int i;
476 pkg_t *pkg;
477 int err = 0;
478
479 signal(SIGINT, sigint_handler);
480
481 if (argc) {
482 for (i=0; i < argc; i++) {
483 char *arg = argv[i];
484
485 if (opkg_prepare_url_for_install(arg, &arg))
486 return -1;
487 }
488 pkg_info_preinstall_check();
489
490 for (i=0; i < argc; i++) {
491 char *arg = argv[i];
492 if (conf->restrict_to_default_dest) {
493 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
494 conf->default_dest);
495 if (pkg == NULL) {
496 opkg_msg(NOTICE, "Package %s not installed in %s.\n",
497 argv[i], conf->default_dest->name);
498 continue;
499 }
500 } else {
501 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
502 }
503 if (pkg) {
504 if (opkg_upgrade_pkg(pkg))
505 err = -1;
506 } else {
507 if (opkg_install_by_name(arg))
508 err = -1;
509 }
510 }
511 } else {
512 pkg_vec_t *installed = pkg_vec_alloc();
513
514 pkg_info_preinstall_check();
515
516 pkg_hash_fetch_all_installed(installed);
517 for (i = 0; i < installed->len; i++) {
518 pkg = installed->pkgs[i];
519 if (opkg_upgrade_pkg(pkg))
520 err = -1;
521 }
522 pkg_vec_free(installed);
523 }
524
525 if (opkg_configure_packages(NULL))
526 err = -1;
527
528 write_status_files_if_changed();
529
530 return err;
531 }
532
533 static int
534 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->local_filename);
558 }
559 }
560
561 return err;
562 }
563
564
565 static int
566 opkg_list_cmd(int argc, char **argv)
567 {
568 int i;
569 pkg_vec_t *available;
570 pkg_t *pkg;
571 char *pkg_name = NULL;
572
573 if (argc > 0) {
574 pkg_name = argv[0];
575 }
576 available = pkg_vec_alloc();
577 pkg_hash_fetch_available(available);
578 pkg_vec_sort(available, pkg_compare_names);
579 for (i=0; i < available->len; i++) {
580 pkg = available->pkgs[i];
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, 0))
583 continue;
584 print_pkg(pkg);
585 }
586 pkg_vec_free(available);
587
588 return 0;
589 }
590
591
592 static int
593 opkg_list_installed_cmd(int argc, char **argv)
594 {
595 int i ;
596 pkg_vec_t *available;
597 pkg_t *pkg;
598 char *pkg_name = NULL;
599
600 if (argc > 0) {
601 pkg_name = argv[0];
602 }
603 available = pkg_vec_alloc();
604 pkg_hash_fetch_all_installed(available);
605 pkg_vec_sort(available, pkg_compare_names);
606 for (i=0; i < available->len; i++) {
607 pkg = available->pkgs[i];
608 /* if we have package name or pattern and pkg does not match, then skip it */
609 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
610 continue;
611 print_pkg(pkg);
612 }
613
614 pkg_vec_free(available);
615
616 return 0;
617 }
618
619 static int
620 opkg_list_changed_conffiles_cmd(int argc, char **argv)
621 {
622 int i ;
623 pkg_vec_t *available;
624 pkg_t *pkg;
625 char *pkg_name = NULL;
626 conffile_list_elt_t *iter;
627 conffile_t *cf;
628
629 if (argc > 0) {
630 pkg_name = argv[0];
631 }
632 available = pkg_vec_alloc();
633 pkg_hash_fetch_all_installed(available);
634 pkg_vec_sort(available, pkg_compare_names);
635 for (i=0; i < available->len; i++) {
636 pkg = available->pkgs[i];
637 /* if we have package name or pattern and pkg does not match, then skip it */
638 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
639 continue;
640 if (nv_pair_list_empty(&pkg->conffiles))
641 continue;
642 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
643 cf = (conffile_t *)iter->data;
644 if (cf->name && cf->value && conffile_has_been_modified(cf))
645 printf("%s\n", cf->name);
646 }
647 }
648 pkg_vec_free(available);
649 return 0;
650 }
651
652 static int
653 opkg_list_upgradable_cmd(int argc, char **argv)
654 {
655 struct active_list *head = prepare_upgrade_list();
656 struct active_list *node=NULL;
657 pkg_t *_old_pkg, *_new_pkg;
658 char *old_v, *new_v;
659 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
660 _old_pkg = list_entry(node, pkg_t, list);
661 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg->name);
662 if (_new_pkg == NULL)
663 continue;
664 old_v = pkg_version_str_alloc(_old_pkg);
665 new_v = pkg_version_str_alloc(_new_pkg);
666 printf("%s - %s - %s\n", _old_pkg->name, old_v, new_v);
667 free(old_v);
668 free(new_v);
669 }
670 active_list_head_delete(head);
671 return 0;
672 }
673
674 static int
675 opkg_info_status_cmd(int argc, char **argv, int installed_only)
676 {
677 int i;
678 pkg_vec_t *available;
679 pkg_t *pkg;
680 char *pkg_name = NULL;
681
682 if (argc > 0) {
683 pkg_name = argv[0];
684 }
685
686 available = pkg_vec_alloc();
687 if (installed_only)
688 pkg_hash_fetch_all_installed(available);
689 else
690 pkg_hash_fetch_available(available);
691
692 for (i=0; i < available->len; i++) {
693 pkg = available->pkgs[i];
694 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
695 continue;
696 }
697
698 pkg_formatted_info(stdout, pkg);
699
700 if (conf->verbosity >= NOTICE) {
701 conffile_list_elt_t *iter;
702 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
703 conffile_t *cf = (conffile_t *)iter->data;
704 int modified = conffile_has_been_modified(cf);
705 if (cf->value)
706 opkg_msg(INFO, "conffile=%s md5sum=%s modified=%d.\n",
707 cf->name, cf->value, modified);
708 }
709 }
710 }
711 pkg_vec_free(available);
712
713 return 0;
714 }
715
716 static int
717 opkg_info_cmd(int argc, char **argv)
718 {
719 return opkg_info_status_cmd(argc, argv, 0);
720 }
721
722 static int
723 opkg_status_cmd(int argc, char **argv)
724 {
725 return opkg_info_status_cmd(argc, argv, 1);
726 }
727
728 static int
729 opkg_configure_cmd(int argc, char **argv)
730 {
731 int err;
732 char *pkg_name = NULL;
733
734 if (argc > 0)
735 pkg_name = argv[0];
736
737 err = opkg_configure_packages(pkg_name);
738
739 write_status_files_if_changed();
740
741 return err;
742 }
743
744 static int
745 opkg_remove_cmd(int argc, char **argv)
746 {
747 int i, a, done, err = 0;
748 pkg_t *pkg;
749 pkg_t *pkg_to_remove;
750 pkg_vec_t *available;
751
752 done = 0;
753
754 signal(SIGINT, sigint_handler);
755
756 pkg_info_preinstall_check();
757
758 available = pkg_vec_alloc();
759 pkg_hash_fetch_all_installed(available);
760
761 for (i=0; i<argc; i++) {
762 for (a=0; a<available->len; a++) {
763 pkg = available->pkgs[a];
764 if (fnmatch(argv[i], pkg->name, 0)) {
765 continue;
766 }
767 if (conf->restrict_to_default_dest) {
768 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(
769 pkg->name,
770 conf->default_dest);
771 } else {
772 pkg_to_remove = pkg_hash_fetch_installed_by_name(pkg->name);
773 }
774
775 if (pkg_to_remove == NULL) {
776 opkg_msg(ERROR, "Package %s is not installed.\n", pkg->name);
777 continue;
778 }
779 if (pkg->state_status == SS_NOT_INSTALLED) {
780 opkg_msg(ERROR, "Package %s not installed.\n", pkg->name);
781 continue;
782 }
783
784 if (opkg_remove_pkg(pkg_to_remove, 0))
785 err = -1;
786 else
787 done = 1;
788 }
789 }
790
791 pkg_vec_free(available);
792
793 if (done == 0)
794 opkg_msg(NOTICE, "No packages removed.\n");
795
796 write_status_files_if_changed();
797 return err;
798 }
799
800 static int
801 opkg_flag_cmd(int argc, char **argv)
802 {
803 int i;
804 pkg_t *pkg;
805 const char *flags = argv[0];
806
807 signal(SIGINT, sigint_handler);
808
809 for (i=1; i < argc; i++) {
810 if (conf->restrict_to_default_dest) {
811 pkg = pkg_hash_fetch_installed_by_name_dest(argv[i],
812 conf->default_dest);
813 } else {
814 pkg = pkg_hash_fetch_installed_by_name(argv[i]);
815 }
816
817 if (pkg == NULL) {
818 opkg_msg(ERROR, "Package %s is not installed.\n", argv[i]);
819 continue;
820 }
821 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
822 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
823 pkg->state_flag = pkg_state_flag_from_str(flags);
824 }
825
826 /*
827 * Useful if a package is installed in an offline_root, and
828 * should be configured by opkg-cl configure at a later date.
829 */
830 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
831 pkg->state_status = pkg_state_status_from_str(flags);
832 }
833
834 opkg_state_changed++;
835 opkg_msg(NOTICE, "Setting flags for package %s to %s.\n",
836 pkg->name, flags);
837 }
838
839 write_status_files_if_changed();
840 return 0;
841 }
842
843 static int
844 opkg_files_cmd(int argc, char **argv)
845 {
846 pkg_t *pkg;
847 str_list_t *files;
848 str_list_elt_t *iter;
849 char *pkg_version;
850
851 if (argc < 1) {
852 return -1;
853 }
854
855 pkg = pkg_hash_fetch_installed_by_name(argv[0]);
856 if (pkg == NULL) {
857 opkg_msg(ERROR, "Package %s not installed.\n", argv[0]);
858 return 0;
859 }
860
861 files = pkg_get_installed_files(pkg);
862 pkg_version = pkg_version_str_alloc(pkg);
863
864 printf("Package %s (%s) is installed on %s and has the following files:\n",
865 pkg->name, pkg_version, pkg->dest->name);
866
867 for (iter=str_list_first(files); iter; iter=str_list_next(files, iter))
868 printf("%s\n", (char *)iter->data);
869
870 free(pkg_version);
871 pkg_free_installed_files(pkg);
872
873 return 0;
874 }
875
876 static int
877 opkg_depends_cmd(int argc, char **argv)
878 {
879 int i, j, k;
880 int depends_count;
881 pkg_vec_t *available_pkgs;
882 compound_depend_t *cdep;
883 pkg_t *pkg;
884 char *str;
885
886 pkg_info_preinstall_check();
887
888 available_pkgs = pkg_vec_alloc();
889 if (conf->query_all)
890 pkg_hash_fetch_available(available_pkgs);
891 else
892 pkg_hash_fetch_all_installed(available_pkgs);
893
894 for (i=0; i<argc; i++) {
895 for (j=0; j<available_pkgs->len; j++) {
896 pkg = available_pkgs->pkgs[j];
897
898 if (fnmatch(argv[i], pkg->name, 0) != 0)
899 continue;
900
901 depends_count = pkg->depends_count +
902 pkg->pre_depends_count +
903 pkg->recommends_count +
904 pkg->suggests_count;
905
906 opkg_msg(NOTICE, "%s depends on:\n", pkg->name);
907
908 for (k=0; k<depends_count; k++) {
909 cdep = &pkg->depends[k];
910
911 if (cdep->type != DEPEND)
912 continue;
913
914 str = pkg_depend_str(pkg, k);
915 opkg_msg(NOTICE, "\t%s\n", str);
916 free(str);
917 }
918
919 }
920 }
921
922 pkg_vec_free(available_pkgs);
923 return 0;
924 }
925
926 static int
927 pkg_mark_provides(pkg_t *pkg)
928 {
929 int provides_count = pkg->provides_count;
930 abstract_pkg_t **provides = pkg->provides;
931 int i;
932 pkg->parent->state_flag |= SF_MARKED;
933 for (i = 0; i < provides_count; i++) {
934 provides[i]->state_flag |= SF_MARKED;
935 }
936 return 0;
937 }
938
939 enum what_field_type {
940 WHATDEPENDS,
941 WHATCONFLICTS,
942 WHATPROVIDES,
943 WHATREPLACES,
944 WHATRECOMMENDS,
945 WHATSUGGESTS
946 };
947
948 static int
949 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type, int recursive, int argc, char **argv)
950 {
951 depend_t *possibility;
952 compound_depend_t *cdep;
953 pkg_vec_t *available_pkgs;
954 pkg_t *pkg;
955 int i, j, k, l;
956 int changed, count;
957 const char *rel_str = NULL;
958 char *ver;
959
960 switch (what_field_type) {
961 case DEPEND: rel_str = "depends on"; break;
962 case CONFLICTS: rel_str = "conflicts with"; break;
963 case SUGGEST: rel_str = "suggests"; break;
964 case RECOMMEND: rel_str = "recommends"; break;
965 default: return -1;
966 }
967
968 available_pkgs = pkg_vec_alloc();
969
970 if (conf->query_all)
971 pkg_hash_fetch_available(available_pkgs);
972 else
973 pkg_hash_fetch_all_installed(available_pkgs);
974
975 /* mark the root set */
976 pkg_vec_clear_marks(available_pkgs);
977 opkg_msg(NOTICE, "Root set:\n");
978 for (i = 0; i < argc; i++)
979 pkg_vec_mark_if_matches(available_pkgs, argv[i]);
980
981 for (i = 0; i < available_pkgs->len; i++) {
982 pkg = available_pkgs->pkgs[i];
983 if (pkg->state_flag & SF_MARKED) {
984 /* mark the parent (abstract) package */
985 pkg_mark_provides(pkg);
986 opkg_msg(NOTICE, " %s\n", pkg->name);
987 }
988 }
989
990 opkg_msg(NOTICE, "What %s root set\n", rel_str);
991 do {
992 changed = 0;
993
994 for (j=0; j<available_pkgs->len; j++) {
995
996 pkg = available_pkgs->pkgs[j];
997 count = ((what_field_type == CONFLICTS)
998 ? pkg->conflicts_count
999 : pkg->pre_depends_count +
1000 pkg->depends_count +
1001 pkg->recommends_count +
1002 pkg->suggests_count);
1003
1004 /* skip this package if it is already marked */
1005 if (pkg->parent->state_flag & SF_MARKED)
1006 continue;
1007
1008 for (k=0; k<count; k++) {
1009 cdep = (what_field_type == CONFLICTS)
1010 ? &pkg->conflicts[k]
1011 : &pkg->depends[k];
1012
1013 if (what_field_type != cdep->type)
1014 continue;
1015
1016 for (l=0; l<cdep->possibility_count; l++) {
1017 possibility = cdep->possibilities[l];
1018
1019 if ((possibility->pkg->state_flag
1020 & SF_MARKED)
1021 != SF_MARKED)
1022 continue;
1023
1024 /* mark the depending package so we
1025 * won't visit it again */
1026 pkg->state_flag |= SF_MARKED;
1027 pkg_mark_provides(pkg);
1028 changed++;
1029
1030 ver = pkg_version_str_alloc(pkg);
1031 opkg_msg(NOTICE, "\t%s %s\t%s %s",
1032 pkg->name,
1033 ver,
1034 rel_str,
1035 possibility->pkg->name);
1036 free(ver);
1037 if (possibility->version) {
1038 opkg_msg(NOTICE, " (%s%s)",
1039 constraint_to_str(possibility->constraint),
1040 possibility->version);
1041 }
1042 if (!pkg_dependence_satisfiable(possibility))
1043 opkg_msg(NOTICE,
1044 " unsatisfiable");
1045 opkg_message(NOTICE, "\n");
1046 goto next_package;
1047 }
1048 }
1049 next_package:
1050 ;
1051 }
1052 } while (changed && recursive);
1053
1054 pkg_vec_free(available_pkgs);
1055
1056 return 0;
1057 }
1058
1059 static int
1060 opkg_whatdepends_recursively_cmd(int argc, char **argv)
1061 {
1062 return opkg_what_depends_conflicts_cmd(DEPEND, 1, argc, argv);
1063 }
1064
1065 static int
1066 opkg_whatdepends_cmd(int argc, char **argv)
1067 {
1068 return opkg_what_depends_conflicts_cmd(DEPEND, 0, argc, argv);
1069 }
1070
1071 static int
1072 opkg_whatsuggests_cmd(int argc, char **argv)
1073 {
1074 return opkg_what_depends_conflicts_cmd(SUGGEST, 0, argc, argv);
1075 }
1076
1077 static int
1078 opkg_whatrecommends_cmd(int argc, char **argv)
1079 {
1080 return opkg_what_depends_conflicts_cmd(RECOMMEND, 0, argc, argv);
1081 }
1082
1083 static int
1084 opkg_whatconflicts_cmd(int argc, char **argv)
1085 {
1086 return opkg_what_depends_conflicts_cmd(CONFLICTS, 0, argc, argv);
1087 }
1088
1089 static int
1090 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type, int argc, char **argv)
1091 {
1092
1093 if (argc > 0) {
1094 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1095 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1096 int i;
1097
1098 pkg_info_preinstall_check();
1099
1100 if (conf->query_all)
1101 pkg_hash_fetch_available(available_pkgs);
1102 else
1103 pkg_hash_fetch_all_installed(available_pkgs);
1104 for (i = 0; i < argc; i++) {
1105 const char *target = argv[i];
1106 int j;
1107
1108 opkg_msg(NOTICE, "What %s %s\n",
1109 rel_str, target);
1110 for (j = 0; j < available_pkgs->len; j++) {
1111 pkg_t *pkg = available_pkgs->pkgs[j];
1112 int k;
1113 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1114 for (k = 0; k < count; k++) {
1115 abstract_pkg_t *apkg =
1116 ((what_field_type == WHATPROVIDES)
1117 ? pkg->provides[k]
1118 : pkg->replaces[k]);
1119 if (fnmatch(target, apkg->name, 0) == 0) {
1120 opkg_msg(NOTICE, " %s", pkg->name);
1121 if (strcmp(target, apkg->name) != 0)
1122 opkg_msg(NOTICE, "\t%s %s\n",
1123 rel_str, apkg->name);
1124 opkg_message(NOTICE, "\n");
1125 }
1126 }
1127 }
1128 }
1129 pkg_vec_free(available_pkgs);
1130 }
1131 return 0;
1132 }
1133
1134 static int
1135 opkg_whatprovides_cmd(int argc, char **argv)
1136 {
1137 return opkg_what_provides_replaces_cmd(WHATPROVIDES, argc, argv);
1138 }
1139
1140 static int
1141 opkg_whatreplaces_cmd(int argc, char **argv)
1142 {
1143 return opkg_what_provides_replaces_cmd(WHATREPLACES, argc, argv);
1144 }
1145
1146 static int
1147 opkg_search_cmd(int argc, char **argv)
1148 {
1149 int i;
1150
1151 pkg_vec_t *installed;
1152 pkg_t *pkg;
1153 str_list_t *installed_files;
1154 str_list_elt_t *iter;
1155 char *installed_file;
1156
1157 if (argc < 1) {
1158 return -1;
1159 }
1160
1161 installed = pkg_vec_alloc();
1162 pkg_hash_fetch_all_installed(installed);
1163 pkg_vec_sort(installed, pkg_compare_names);
1164
1165 for (i=0; i < installed->len; i++) {
1166 pkg = installed->pkgs[i];
1167
1168 installed_files = pkg_get_installed_files(pkg);
1169
1170 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1171 installed_file = (char *)iter->data;
1172 if (fnmatch(argv[0], installed_file, 0)==0)
1173 print_pkg(pkg);
1174 }
1175
1176 pkg_free_installed_files(pkg);
1177 }
1178
1179 pkg_vec_free(installed);
1180
1181 return 0;
1182 }
1183
1184 static int
1185 opkg_compare_versions_cmd(int argc, char **argv)
1186 {
1187 if (argc == 3) {
1188 /* this is a bit gross */
1189 struct pkg p1, p2;
1190 parse_version(&p1, argv[0]);
1191 parse_version(&p2, argv[2]);
1192 return pkg_version_satisfied(&p1, &p2, argv[1]);
1193 } else {
1194 opkg_msg(ERROR,
1195 "opkg compare_versions <v1> <op> <v2>\n"
1196 "<op> is one of <= >= << >> =\n");
1197 return -1;
1198 }
1199 }
1200
1201 static int
1202 opkg_print_architecture_cmd(int argc, char **argv)
1203 {
1204 nv_pair_list_elt_t *l;
1205
1206 list_for_each_entry(l, &conf->arch_list.head, node) {
1207 nv_pair_t *nv = (nv_pair_t *)l->data;
1208 printf("arch %s %s\n", nv->name, nv->value);
1209 }
1210 return 0;
1211 }
1212
1213
1214 /* XXX: CLEANUP: The usage strings should be incorporated into this
1215 array for easier maintenance */
1216 static opkg_cmd_t cmds[] = {
1217 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1218 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1219 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE},
1220 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1221 {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE},
1222 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1223 {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE},
1224 {"list_changed_conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1225 {"list-changed-conffiles", 0, (opkg_cmd_fun_t)opkg_list_changed_conffiles_cmd, PFM_SOURCE},
1226 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd, 0},
1227 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1228 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1229 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1230 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1231 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1232 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1233 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1234 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1235 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1236 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1237 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1238 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1239 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1240 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1241 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1242 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1243 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1244 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1245 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1246 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1247 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1248 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd, PFM_DESCRIPTION|PFM_SOURCE},
1249 };
1250
1251 opkg_cmd_t *
1252 opkg_cmd_find(const char *name)
1253 {
1254 int i;
1255 opkg_cmd_t *cmd;
1256 int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
1257
1258 for (i=0; i < num_cmds; i++) {
1259 cmd = &cmds[i];
1260 if (strcmp(name, cmd->name) == 0)
1261 return cmd;
1262 }
1263
1264 return NULL;
1265 }
1266
1267 int
1268 opkg_cmd_exec(opkg_cmd_t *cmd, int argc, const char **argv)
1269 {
1270 return (cmd->fun)(argc, argv);
1271 }