1 /* opkg_cmd.c - the opkg package management system
5 Copyright (C) 2001 University of Southern California
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.
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.
27 #include "opkg_conf.h"
29 #include "opkg_message.h"
33 #include "pkg_parse.h"
34 #include "sprintf_alloc.h"
36 #include "file_util.h"
37 #include "libbb/libbb.h"
38 #include "opkg_utils.h"
39 #include "opkg_defines.h"
40 #include "opkg_download.h"
41 #include "opkg_install.h"
42 #include "opkg_upgrade.h"
43 #include "opkg_remove.h"
44 #include "opkg_configure.h"
50 char *version
= pkg_version_str_alloc(pkg
);
52 printf("%s - %s - %s\n", pkg
->name
, version
, pkg
->description
);
54 printf("%s - %s\n", pkg
->name
, version
);
58 int opkg_state_changed
;
61 write_status_files_if_changed(void)
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();
68 opkg_msg(DEBUG
, "Nothing to be done.\n");
73 sigint_handler(int sig
)
76 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
77 write_status_files_if_changed();
82 opkg_update_cmd(int argc
, char **argv
)
88 pkg_src_list_elt_t
*iter
;
92 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
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",
101 err
= file_mkdir_hier(lists_dir
, 0755);
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
);
117 for (iter
= void_list_first(&conf
->dist_src_list
); iter
; iter
= void_list_next(&conf
->dist_src_list
, iter
)) {
118 char *url
, *list_file_name
;
120 src
= (pkg_src_t
*)iter
->data
;
122 sprintf_alloc(&url
, "%s/dists/%s/Release", src
->value
, src
->name
);
124 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
125 err
= opkg_download(url
, list_file_name
, NULL
, NULL
, 0);
127 opkg_msg(NOTICE
, "Downloaded release files for dist %s.\n",
129 release_t
*release
= release_new();
130 err
= release_init_from_file(release
, list_file_name
);
132 if (!release_comps_supported(release
, src
->extra_data
))
136 err
= release_download(release
, src
, lists_dir
, tmp
);
138 release_deinit(release
);
140 unlink(list_file_name
);
146 free(list_file_name
);
150 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
151 char *url
, *list_file_name
;
153 src
= (pkg_src_t
*)iter
->data
;
155 if (src
->extra_data
&& strcmp(src
->extra_data
, "__dummy__ "))
158 if (src
->extra_data
) /* debian style? */
159 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
160 src
->gzip
? "Packages.gz" : "Packages");
162 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
164 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
169 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
170 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
, 0);
172 opkg_msg(NOTICE
, "Inflating %s.\n", url
);
173 in
= fopen (tmp_file_name
, "r");
174 out
= fopen (list_file_name
, "w");
183 unlink (tmp_file_name
);
187 err
= opkg_download(url
, list_file_name
, NULL
, NULL
, 0);
191 opkg_msg(NOTICE
, "Updated list of available packages in %s.\n",
195 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
196 if (conf
->check_signature
) {
197 /* download detached signitures to verify the package lists */
198 /* get the url for the sig file */
199 if (src
->extra_data
) /* debian style? */
200 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
203 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
205 /* create temporary file for it */
208 /* Put the signature in the right place */
209 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
211 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
, 0);
214 opkg_msg(NOTICE
, "Signature check failed.\n");
216 err
= opkg_verify_file (list_file_name
, tmp_file_name
);
218 opkg_msg(NOTICE
, "Signature check passed.\n");
220 opkg_msg(NOTICE
, "Signature check failed.\n");
223 /* The signature was wrong so delete it */
224 opkg_msg(NOTICE
, "Remove wrong Signature file.\n");
225 unlink (tmp_file_name
);
226 unlink (list_file_name
);
228 /* We shouldn't unlink the signature ! */
229 // unlink (tmp_file_name);
230 free (tmp_file_name
);
236 free(list_file_name
);
246 struct opkg_intercept
252 typedef struct opkg_intercept
*opkg_intercept_t
;
254 static opkg_intercept_t
255 opkg_prep_intercepts(void)
257 opkg_intercept_t ctx
;
260 ctx
= xcalloc(1, sizeof (*ctx
));
261 ctx
->oldpath
= xstrdup(getenv("PATH"));
262 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
263 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
265 if (mkdtemp(ctx
->statedir
) == NULL
) {
266 opkg_perror(ERROR
,"Failed to make temp dir %s", ctx
->statedir
);
274 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
275 setenv("PATH", newpath
, 1);
282 opkg_finalize_intercepts(opkg_intercept_t ctx
)
287 setenv ("PATH", ctx
->oldpath
, 1);
290 dir
= opendir (ctx
->statedir
);
293 while (de
= readdir (dir
), de
!= NULL
) {
296 if (de
->d_name
[0] == '.')
299 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
300 if (access (path
, X_OK
) == 0) {
301 const char *argv
[] = {"sh", "-c", path
, NULL
};
308 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
311 free (ctx
->statedir
);
317 /* For package pkg do the following: If it is already visited, return. If not,
318 add it in visited list and recurse to its deps. Finally, add it to ordered
320 pkg_vec all contains all available packages in repos.
321 pkg_vec visited contains packages already visited by this function, and is
322 used to end recursion and avoid an infinite loop on graph cycles.
323 pkg_vec ordered will finally contain the ordered set of packages.
326 opkg_recurse_pkgs_in_order(pkg_t
*pkg
, pkg_vec_t
*all
,
327 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
332 compound_depend_t
* compound_depend
;
333 depend_t
** possible_satisfiers
;
334 abstract_pkg_t
*abpkg
;
335 abstract_pkg_t
**dependents
;
337 /* If it's just an available package, that is, not installed and not even
339 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
340 would do here. However, if there is an intermediate node (pkg) that is
341 configured and installed between two unpacked packages, the latter
342 won't be properly reordered, unless all installed/unpacked pkgs are
344 if (pkg
->state_status
== SS_NOT_INSTALLED
)
347 /* If the package has already been visited (by this function), skip it */
348 for(j
= 0; j
< visited
->len
; j
++)
349 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
350 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n", pkg
->name
);
354 pkg_vec_insert(visited
, pkg
);
356 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
357 pkg
->recommends_count
+ pkg
->suggests_count
;
359 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
361 /* Iterate over all the dependencies of pkg. For each one, find a package
362 that is either installed or unpacked and satisfies this dependency.
363 (there should only be one such package per dependency installed or
364 unpacked). Then recurse to the dependency package */
365 for (j
=0; j
< count
; j
++) {
366 compound_depend
= &pkg
->depends
[j
];
367 possible_satisfiers
= compound_depend
->possibilities
;
368 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
369 abpkg
= possible_satisfiers
[k
]->pkg
;
370 dependents
= abpkg
->provided_by
->pkgs
;
372 if (dependents
!= NULL
)
373 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
374 opkg_msg(DEBUG
, "Descending on pkg %s.\n",
375 dependents
[l
]->name
);
377 /* find whether dependent l is installed or unpacked,
378 * and then find which package in the list satisfies it */
379 for(m
= 0; m
< all
->len
; m
++) {
381 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
382 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
383 opkg_recurse_pkgs_in_order(dep
, all
,
385 /* Stop the outer loop */
386 l
= abpkg
->provided_by
->len
;
387 /* break from the inner loop */
396 /* When all recursions from this node down, are over, and all
397 dependencies have been added in proper order in the ordered array, add
398 also the package pkg to ordered array */
399 pkg_vec_insert(ordered
, pkg
);
406 opkg_configure_packages(char *pkg_name
)
408 pkg_vec_t
*all
, *ordered
, *visited
;
414 opkg_msg(INFO
, "Configuring unpacked packages.\n");
416 all
= pkg_vec_alloc();
418 pkg_hash_fetch_available(all
);
420 /* Reorder pkgs in order to be configured according to the Depends: tag
422 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
423 ordered
= pkg_vec_alloc();
424 visited
= pkg_vec_alloc();
425 for(i
= 0; i
< all
->len
; i
++) {
427 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
430 ic
= opkg_prep_intercepts();
436 for(i
= 0; i
< ordered
->len
; i
++) {
437 pkg
= ordered
->pkgs
[i
];
439 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
442 if (pkg
->state_status
== SS_UNPACKED
) {
443 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
444 r
= opkg_configure(pkg
);
446 pkg
->state_status
= SS_INSTALLED
;
447 pkg
->parent
->state_status
= SS_INSTALLED
;
448 pkg
->state_flag
&= ~SF_PREFER
;
449 opkg_state_changed
++;
456 if (opkg_finalize_intercepts (ic
))
461 pkg_vec_free(ordered
);
462 pkg_vec_free(visited
);
468 opkg_remove_cmd(int argc
, char **argv
);
471 opkg_install_cmd(int argc
, char **argv
)
477 if (conf
->force_reinstall
) {
478 int saved_force_depends
= conf
->force_depends
;
479 conf
->force_depends
= 1;
480 (void)opkg_remove_cmd(argc
, argv
);
481 conf
->force_depends
= saved_force_depends
;
482 conf
->force_reinstall
= 0;
485 signal(SIGINT
, sigint_handler
);
488 * Now scan through package names and install
490 for (i
=0; i
< argc
; i
++) {
493 opkg_msg(DEBUG2
, "%s\n", arg
);
494 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
497 pkg_info_preinstall_check();
499 for (i
=0; i
< argc
; i
++) {
501 if (opkg_install_by_name(arg
)) {
502 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
507 if (opkg_configure_packages(NULL
))
510 write_status_files_if_changed();
516 opkg_upgrade_cmd(int argc
, char **argv
)
522 signal(SIGINT
, sigint_handler
);
525 for (i
=0; i
< argc
; i
++) {
528 if (opkg_prepare_url_for_install(arg
, &arg
))
531 pkg_info_preinstall_check();
533 for (i
=0; i
< argc
; i
++) {
535 if (conf
->restrict_to_default_dest
) {
536 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
539 opkg_msg(NOTICE
, "Package %s not installed in %s.\n",
540 argv
[i
], conf
->default_dest
->name
);
544 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
547 if (opkg_upgrade_pkg(pkg
))
550 if (opkg_install_by_name(arg
))
556 if (opkg_configure_packages(NULL
))
559 write_status_files_if_changed();
565 opkg_download_cmd(int argc
, char **argv
)
571 pkg_info_preinstall_check();
572 for (i
= 0; i
< argc
; i
++) {
575 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
577 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
581 if (opkg_download_pkg(pkg
, "."))
585 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
587 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
588 pkg
->name
, pkg
->local_filename
);
597 opkg_list_cmd(int argc
, char **argv
)
600 pkg_vec_t
*available
;
602 char *pkg_name
= NULL
;
607 available
= pkg_vec_alloc();
608 pkg_hash_fetch_available(available
);
609 pkg_vec_sort(available
, pkg_compare_names
);
610 for (i
=0; i
< available
->len
; i
++) {
611 pkg
= available
->pkgs
[i
];
612 /* if we have package name or pattern and pkg does not match, then skip it */
613 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
617 pkg_vec_free(available
);
624 opkg_list_installed_cmd(int argc
, char **argv
)
627 pkg_vec_t
*available
;
629 char *pkg_name
= NULL
;
634 available
= pkg_vec_alloc();
635 pkg_hash_fetch_all_installed(available
);
636 pkg_vec_sort(available
, pkg_compare_names
);
637 for (i
=0; i
< available
->len
; i
++) {
638 pkg
= available
->pkgs
[i
];
639 /* if we have package name or pattern and pkg does not match, then skip it */
640 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
645 pkg_vec_free(available
);
651 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
654 pkg_vec_t
*available
;
656 char *pkg_name
= NULL
;
657 conffile_list_elt_t
*iter
;
663 available
= pkg_vec_alloc();
664 pkg_hash_fetch_all_installed(available
);
665 pkg_vec_sort(available
, pkg_compare_names
);
666 for (i
=0; i
< available
->len
; i
++) {
667 pkg
= available
->pkgs
[i
];
668 /* if we have package name or pattern and pkg does not match, then skip it */
669 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
671 if (nv_pair_list_empty(&pkg
->conffiles
))
673 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
674 cf
= (conffile_t
*)iter
->data
;
675 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
676 printf("%s\n", cf
->name
);
679 pkg_vec_free(available
);
684 opkg_list_upgradable_cmd(int argc
, char **argv
)
686 struct active_list
*head
= prepare_upgrade_list();
687 struct active_list
*node
=NULL
;
688 pkg_t
*_old_pkg
, *_new_pkg
;
690 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
691 _old_pkg
= list_entry(node
, pkg_t
, list
);
692 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
693 if (_new_pkg
== NULL
)
695 old_v
= pkg_version_str_alloc(_old_pkg
);
696 new_v
= pkg_version_str_alloc(_new_pkg
);
697 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
701 active_list_head_delete(head
);
706 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
709 pkg_vec_t
*available
;
711 char *pkg_name
= NULL
;
717 available
= pkg_vec_alloc();
719 pkg_hash_fetch_all_installed(available
);
721 pkg_hash_fetch_available(available
);
723 for (i
=0; i
< available
->len
; i
++) {
724 pkg
= available
->pkgs
[i
];
725 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
729 pkg_formatted_info(stdout
, pkg
);
731 if (conf
->verbosity
>= NOTICE
) {
732 conffile_list_elt_t
*iter
;
733 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
734 conffile_t
*cf
= (conffile_t
*)iter
->data
;
735 int modified
= conffile_has_been_modified(cf
);
737 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
738 cf
->name
, cf
->value
, modified
);
742 pkg_vec_free(available
);
748 opkg_info_cmd(int argc
, char **argv
)
750 return opkg_info_status_cmd(argc
, argv
, 0);
754 opkg_status_cmd(int argc
, char **argv
)
756 return opkg_info_status_cmd(argc
, argv
, 1);
760 opkg_configure_cmd(int argc
, char **argv
)
763 char *pkg_name
= NULL
;
768 err
= opkg_configure_packages(pkg_name
);
770 write_status_files_if_changed();
776 opkg_remove_cmd(int argc
, char **argv
)
778 int i
, a
, done
, err
= 0;
780 pkg_t
*pkg_to_remove
;
781 pkg_vec_t
*available
;
785 signal(SIGINT
, sigint_handler
);
787 pkg_info_preinstall_check();
789 available
= pkg_vec_alloc();
790 pkg_hash_fetch_all_installed(available
);
792 for (i
=0; i
<argc
; i
++) {
793 for (a
=0; a
<available
->len
; a
++) {
794 pkg
= available
->pkgs
[a
];
795 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
798 if (conf
->restrict_to_default_dest
) {
799 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
803 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
806 if (pkg_to_remove
== NULL
) {
807 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
810 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
811 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
815 if (opkg_remove_pkg(pkg_to_remove
, 0))
822 pkg_vec_free(available
);
825 opkg_msg(NOTICE
, "No packages removed.\n");
827 write_status_files_if_changed();
832 opkg_flag_cmd(int argc
, char **argv
)
836 const char *flags
= argv
[0];
838 signal(SIGINT
, sigint_handler
);
840 for (i
=1; i
< argc
; i
++) {
841 if (conf
->restrict_to_default_dest
) {
842 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
845 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
849 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
852 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
853 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
854 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
858 * Useful if a package is installed in an offline_root, and
859 * should be configured by opkg-cl configure at a later date.
861 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
862 pkg
->state_status
= pkg_state_status_from_str(flags
);
865 opkg_state_changed
++;
866 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
870 write_status_files_if_changed();
875 opkg_files_cmd(int argc
, char **argv
)
879 str_list_elt_t
*iter
;
886 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
888 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
892 files
= pkg_get_installed_files(pkg
);
893 pkg_version
= pkg_version_str_alloc(pkg
);
895 printf("Package %s (%s) is installed on %s and has the following files:\n",
896 pkg
->name
, pkg_version
, pkg
->dest
->name
);
898 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
899 printf("%s\n", (char *)iter
->data
);
902 pkg_free_installed_files(pkg
);
908 opkg_depends_cmd(int argc
, char **argv
)
912 pkg_vec_t
*available_pkgs
;
913 compound_depend_t
*cdep
;
917 pkg_info_preinstall_check();
919 available_pkgs
= pkg_vec_alloc();
921 pkg_hash_fetch_available(available_pkgs
);
923 pkg_hash_fetch_all_installed(available_pkgs
);
925 for (i
=0; i
<argc
; i
++) {
926 for (j
=0; j
<available_pkgs
->len
; j
++) {
927 pkg
= available_pkgs
->pkgs
[j
];
929 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
932 depends_count
= pkg
->depends_count
+
933 pkg
->pre_depends_count
+
934 pkg
->recommends_count
+
937 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
939 for (k
=0; k
<depends_count
; k
++) {
940 cdep
= &pkg
->depends
[k
];
942 if (cdep
->type
!= DEPEND
)
945 str
= pkg_depend_str(pkg
, k
);
946 opkg_msg(NOTICE
, "\t%s\n", str
);
953 pkg_vec_free(available_pkgs
);
958 pkg_mark_provides(pkg_t
*pkg
)
960 int provides_count
= pkg
->provides_count
;
961 abstract_pkg_t
**provides
= pkg
->provides
;
963 pkg
->parent
->state_flag
|= SF_MARKED
;
964 for (i
= 0; i
< provides_count
; i
++) {
965 provides
[i
]->state_flag
|= SF_MARKED
;
970 enum what_field_type
{
980 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
982 depend_t
*possibility
;
983 compound_depend_t
*cdep
;
984 pkg_vec_t
*available_pkgs
;
988 const char *rel_str
= NULL
;
991 switch (what_field_type
) {
992 case DEPEND
: rel_str
= "depends on"; break;
993 case CONFLICTS
: rel_str
= "conflicts with"; break;
994 case SUGGEST
: rel_str
= "suggests"; break;
995 case RECOMMEND
: rel_str
= "recommends"; break;
999 available_pkgs
= pkg_vec_alloc();
1001 if (conf
->query_all
)
1002 pkg_hash_fetch_available(available_pkgs
);
1004 pkg_hash_fetch_all_installed(available_pkgs
);
1006 /* mark the root set */
1007 pkg_vec_clear_marks(available_pkgs
);
1008 opkg_msg(NOTICE
, "Root set:\n");
1009 for (i
= 0; i
< argc
; i
++)
1010 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1012 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1013 pkg
= available_pkgs
->pkgs
[i
];
1014 if (pkg
->state_flag
& SF_MARKED
) {
1015 /* mark the parent (abstract) package */
1016 pkg_mark_provides(pkg
);
1017 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1021 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1025 for (j
=0; j
<available_pkgs
->len
; j
++) {
1027 pkg
= available_pkgs
->pkgs
[j
];
1028 count
= ((what_field_type
== CONFLICTS
)
1029 ? pkg
->conflicts_count
1030 : pkg
->pre_depends_count
+
1031 pkg
->depends_count
+
1032 pkg
->recommends_count
+
1033 pkg
->suggests_count
);
1035 /* skip this package if it is already marked */
1036 if (pkg
->parent
->state_flag
& SF_MARKED
)
1039 for (k
=0; k
<count
; k
++) {
1040 cdep
= (what_field_type
== CONFLICTS
)
1041 ? &pkg
->conflicts
[k
]
1044 if (what_field_type
!= cdep
->type
)
1047 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1048 possibility
= cdep
->possibilities
[l
];
1050 if ((possibility
->pkg
->state_flag
1055 /* mark the depending package so we
1056 * won't visit it again */
1057 pkg
->state_flag
|= SF_MARKED
;
1058 pkg_mark_provides(pkg
);
1061 ver
= pkg_version_str_alloc(pkg
);
1062 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1066 possibility
->pkg
->name
);
1068 if (possibility
->version
) {
1069 opkg_msg(NOTICE
, " (%s%s)",
1070 constraint_to_str(possibility
->constraint
),
1071 possibility
->version
);
1073 if (!pkg_dependence_satisfiable(possibility
))
1076 opkg_message(NOTICE
, "\n");
1083 } while (changed
&& recursive
);
1085 pkg_vec_free(available_pkgs
);
1091 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1093 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1097 opkg_whatdepends_cmd(int argc
, char **argv
)
1099 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1103 opkg_whatsuggests_cmd(int argc
, char **argv
)
1105 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1109 opkg_whatrecommends_cmd(int argc
, char **argv
)
1111 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1115 opkg_whatconflicts_cmd(int argc
, char **argv
)
1117 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1121 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1125 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1126 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1129 pkg_info_preinstall_check();
1131 if (conf
->query_all
)
1132 pkg_hash_fetch_available(available_pkgs
);
1134 pkg_hash_fetch_all_installed(available_pkgs
);
1135 for (i
= 0; i
< argc
; i
++) {
1136 const char *target
= argv
[i
];
1139 opkg_msg(NOTICE
, "What %s %s\n",
1141 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1142 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1144 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1145 for (k
= 0; k
< count
; k
++) {
1146 abstract_pkg_t
*apkg
=
1147 ((what_field_type
== WHATPROVIDES
)
1149 : pkg
->replaces
[k
]);
1150 if (fnmatch(target
, apkg
->name
, conf
->nocase
) == 0) {
1151 opkg_msg(NOTICE
, " %s", pkg
->name
);
1152 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
) : strcmp(target
, apkg
->name
)) != 0)
1153 opkg_msg(NOTICE
, "\t%s %s\n",
1154 rel_str
, apkg
->name
);
1155 opkg_message(NOTICE
, "\n");
1160 pkg_vec_free(available_pkgs
);
1166 opkg_whatprovides_cmd(int argc
, char **argv
)
1168 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1172 opkg_whatreplaces_cmd(int argc
, char **argv
)
1174 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1178 opkg_search_cmd(int argc
, char **argv
)
1182 pkg_vec_t
*installed
;
1184 str_list_t
*installed_files
;
1185 str_list_elt_t
*iter
;
1186 char *installed_file
;
1192 installed
= pkg_vec_alloc();
1193 pkg_hash_fetch_all_installed(installed
);
1194 pkg_vec_sort(installed
, pkg_compare_names
);
1196 for (i
=0; i
< installed
->len
; i
++) {
1197 pkg
= installed
->pkgs
[i
];
1199 installed_files
= pkg_get_installed_files(pkg
);
1201 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1202 installed_file
= (char *)iter
->data
;
1203 if (fnmatch(argv
[0], installed_file
, conf
->nocase
)==0)
1207 pkg_free_installed_files(pkg
);
1210 pkg_vec_free(installed
);
1216 opkg_compare_versions_cmd(int argc
, char **argv
)
1219 /* this is a bit gross */
1221 parse_version(&p1
, argv
[0]);
1222 parse_version(&p2
, argv
[2]);
1223 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1226 "opkg compare_versions <v1> <op> <v2>\n"
1227 "<op> is one of <= >= << >> =\n");
1233 opkg_print_architecture_cmd(int argc
, char **argv
)
1235 nv_pair_list_elt_t
*l
;
1237 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1238 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1239 printf("arch %s %s\n", nv
->name
, nv
->value
);
1245 /* XXX: CLEANUP: The usage strings should be incorporated into this
1246 array for easier maintenance */
1247 static opkg_cmd_t cmds
[] = {
1248 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1249 {"upgrade", 1, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1250 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1251 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1252 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1253 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1254 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1255 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1256 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1257 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1258 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1259 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1260 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1261 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1262 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1263 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1264 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1265 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1266 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1267 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1268 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1269 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1270 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1271 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1272 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1273 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1274 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1275 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1276 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1277 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1278 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1279 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1283 opkg_cmd_find(const char *name
)
1287 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1289 for (i
=0; i
< num_cmds
; i
++) {
1291 if (strcmp(name
, cmd
->name
) == 0)
1299 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1301 return (cmd
->fun
)(argc
, argv
);