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"
32 #include "pkg_parse.h"
33 #include "sprintf_alloc.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"
49 char *version
= pkg_version_str_alloc(pkg
);
50 printf("%s - %s", pkg
->name
, version
);
52 printf(" - %lu", pkg
->size
);
54 printf(" - %s", pkg
->description
);
59 int opkg_state_changed
;
62 write_status_files_if_changed(void)
64 if (opkg_state_changed
&& !conf
->noaction
) {
65 opkg_msg(INFO
, "Writing status file.\n");
66 opkg_conf_write_status_files();
67 pkg_write_changed_filelists();
69 opkg_msg(DEBUG
, "Nothing to be done.\n");
74 sigint_handler(int sig
)
77 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
78 write_status_files_if_changed();
83 opkg_update_cmd(int argc
, char **argv
)
89 pkg_src_list_elt_t
*iter
;
93 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
95 if (! file_is_dir(lists_dir
)) {
96 if (file_exists(lists_dir
)) {
97 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
102 err
= file_mkdir_hier(lists_dir
, 0755);
111 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
112 if (mkdtemp (tmp
) == NULL
) {
113 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
118 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
119 char *url
, *list_file_name
;
121 src
= (pkg_src_t
*)iter
->data
;
123 if (src
->extra_data
&& strcmp(src
->extra_data
, "__dummy__ "))
126 if (src
->extra_data
) /* debian style? */
127 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
128 src
->gzip
? "Packages.gz" : "Packages");
130 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
132 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
133 if (opkg_download(url
, list_file_name
, NULL
, NULL
, 0)) {
136 opkg_msg(NOTICE
, "Updated list of available packages in %s.\n",
140 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL) || defined(HAVE_USIGN)
141 if (conf
->check_signature
) {
142 /* download detached signitures to verify the package lists */
143 /* get the url for the sig file */
144 if (src
->extra_data
) /* debian style? */
145 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
148 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
150 /* create temporary file for it */
153 /* Put the signature in the right place */
154 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
156 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
, 0);
159 opkg_msg(NOTICE
, "Signature check failed.\n");
161 err
= opkg_verify_file (list_file_name
, tmp_file_name
);
163 opkg_msg(NOTICE
, "Signature check passed.\n");
165 opkg_msg(NOTICE
, "Signature check failed.\n");
167 if (err
&& !conf
->force_signature
) {
168 /* The signature was wrong so delete it */
169 opkg_msg(NOTICE
, "Remove wrong Signature file.\n");
170 unlink (tmp_file_name
);
171 unlink (list_file_name
);
173 /* We shouldn't unlink the signature ! */
174 // unlink (tmp_file_name);
175 free (tmp_file_name
);
181 free(list_file_name
);
191 struct opkg_intercept
197 typedef struct opkg_intercept
*opkg_intercept_t
;
199 static opkg_intercept_t
200 opkg_prep_intercepts(void)
202 opkg_intercept_t ctx
;
205 ctx
= xcalloc(1, sizeof (*ctx
));
206 ctx
->oldpath
= xstrdup(getenv("PATH"));
207 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
208 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
210 if (mkdtemp(ctx
->statedir
) == NULL
) {
211 opkg_perror(ERROR
,"Failed to make temp dir %s", ctx
->statedir
);
219 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
220 setenv("PATH", newpath
, 1);
227 opkg_finalize_intercepts(opkg_intercept_t ctx
)
232 setenv ("PATH", ctx
->oldpath
, 1);
235 dir
= opendir (ctx
->statedir
);
238 while (de
= readdir (dir
), de
!= NULL
) {
241 if (de
->d_name
[0] == '.')
244 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
245 if (access (path
, X_OK
) == 0) {
246 const char *argv
[] = {"sh", "-c", path
, NULL
};
253 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
256 free (ctx
->statedir
);
262 /* For package pkg do the following: If it is already visited, return. If not,
263 add it in visited list and recurse to its deps. Finally, add it to ordered
265 pkg_vec all contains all available packages in repos.
266 pkg_vec visited contains packages already visited by this function, and is
267 used to end recursion and avoid an infinite loop on graph cycles.
268 pkg_vec ordered will finally contain the ordered set of packages.
271 opkg_recurse_pkgs_in_order(pkg_t
*pkg
, pkg_vec_t
*all
,
272 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
277 compound_depend_t
* compound_depend
;
278 depend_t
** possible_satisfiers
;
279 abstract_pkg_t
*abpkg
;
280 abstract_pkg_t
**dependents
;
282 /* If it's just an available package, that is, not installed and not even
284 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
285 would do here. However, if there is an intermediate node (pkg) that is
286 configured and installed between two unpacked packages, the latter
287 won't be properly reordered, unless all installed/unpacked pkgs are
289 if (pkg
->state_status
== SS_NOT_INSTALLED
)
292 /* If the package has already been visited (by this function), skip it */
293 for(j
= 0; j
< visited
->len
; j
++)
294 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
295 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n", pkg
->name
);
299 pkg_vec_insert(visited
, pkg
);
301 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
302 pkg
->recommends_count
+ pkg
->suggests_count
;
304 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
306 /* Iterate over all the dependencies of pkg. For each one, find a package
307 that is either installed or unpacked and satisfies this dependency.
308 (there should only be one such package per dependency installed or
309 unpacked). Then recurse to the dependency package */
310 for (j
=0; j
< count
; j
++) {
311 compound_depend
= &pkg
->depends
[j
];
312 possible_satisfiers
= compound_depend
->possibilities
;
313 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
314 abpkg
= possible_satisfiers
[k
]->pkg
;
315 dependents
= abpkg
->provided_by
->pkgs
;
317 if (dependents
!= NULL
)
318 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
319 opkg_msg(DEBUG
, "Descending on pkg %s.\n",
320 dependents
[l
]->name
);
322 /* find whether dependent l is installed or unpacked,
323 * and then find which package in the list satisfies it */
324 for(m
= 0; m
< all
->len
; m
++) {
326 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
327 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
328 opkg_recurse_pkgs_in_order(dep
, all
,
330 /* Stop the outer loop */
331 l
= abpkg
->provided_by
->len
;
332 /* break from the inner loop */
341 /* When all recursions from this node down, are over, and all
342 dependencies have been added in proper order in the ordered array, add
343 also the package pkg to ordered array */
344 pkg_vec_insert(ordered
, pkg
);
351 opkg_configure_packages(char *pkg_name
)
353 pkg_vec_t
*all
, *ordered
, *visited
;
359 opkg_msg(INFO
, "Configuring unpacked packages.\n");
361 all
= pkg_vec_alloc();
363 pkg_hash_fetch_available(all
);
365 /* Reorder pkgs in order to be configured according to the Depends: tag
367 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
368 ordered
= pkg_vec_alloc();
369 visited
= pkg_vec_alloc();
370 for(i
= 0; i
< all
->len
; i
++) {
372 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
375 ic
= opkg_prep_intercepts();
381 for(i
= 0; i
< ordered
->len
; i
++) {
382 pkg
= ordered
->pkgs
[i
];
384 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
387 if (pkg
->state_status
== SS_UNPACKED
) {
388 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
389 r
= opkg_configure(pkg
);
391 pkg
->state_status
= SS_INSTALLED
;
392 pkg
->parent
->state_status
= SS_INSTALLED
;
393 pkg
->state_flag
&= ~SF_PREFER
;
394 opkg_state_changed
++;
401 if (opkg_finalize_intercepts (ic
))
406 pkg_vec_free(ordered
);
407 pkg_vec_free(visited
);
413 opkg_remove_cmd(int argc
, char **argv
);
416 opkg_install_cmd(int argc
, char **argv
)
422 if (conf
->force_reinstall
) {
423 int saved_force_depends
= conf
->force_depends
;
424 conf
->force_depends
= 1;
425 (void)opkg_remove_cmd(argc
, argv
);
426 conf
->force_depends
= saved_force_depends
;
427 conf
->force_reinstall
= 0;
430 signal(SIGINT
, sigint_handler
);
433 * Now scan through package names and install
435 for (i
=0; i
< argc
; i
++) {
438 opkg_msg(DEBUG2
, "%s\n", arg
);
439 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
442 pkg_info_preinstall_check();
444 for (i
=0; i
< argc
; i
++) {
446 if (opkg_install_by_name(arg
)) {
447 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
452 if (opkg_configure_packages(NULL
))
455 write_status_files_if_changed();
461 opkg_upgrade_cmd(int argc
, char **argv
)
467 signal(SIGINT
, sigint_handler
);
470 for (i
=0; i
< argc
; i
++) {
473 if (opkg_prepare_url_for_install(arg
, &arg
))
476 pkg_info_preinstall_check();
478 for (i
=0; i
< argc
; i
++) {
480 if (conf
->restrict_to_default_dest
) {
481 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
484 opkg_msg(NOTICE
, "Package %s not installed in %s.\n",
485 argv
[i
], conf
->default_dest
->name
);
489 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
492 if (opkg_upgrade_pkg(pkg
))
495 if (opkg_install_by_name(arg
))
501 if (opkg_configure_packages(NULL
))
504 write_status_files_if_changed();
510 opkg_download_cmd(int argc
, char **argv
)
516 pkg_info_preinstall_check();
517 for (i
= 0; i
< argc
; i
++) {
520 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
522 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
526 if (opkg_download_pkg(pkg
, "."))
530 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
532 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
533 pkg
->name
, pkg
->local_filename
);
542 opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
545 pkg_vec_t
*available
;
547 char *pkg_name
= NULL
;
552 available
= pkg_vec_alloc();
553 pkg_hash_fetch_available(available
);
554 pkg_vec_sort(available
, pkg_compare_names
);
555 for (i
=0; i
< available
->len
; i
++) {
556 pkg
= available
->pkgs
[i
];
557 /* if we have package name or pattern and pkg does not match, then skip it */
558 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
) &&
559 (!use_desc
|| !pkg
->description
|| fnmatch(pkg_name
, pkg
->description
, conf
->nocase
)))
563 pkg_vec_free(available
);
569 opkg_list_cmd(int argc
, char **argv
)
571 return opkg_list_find_cmd(argc
, argv
, 0);
575 opkg_find_cmd(int argc
, char **argv
)
577 return opkg_list_find_cmd(argc
, argv
, 1);
582 opkg_list_installed_cmd(int argc
, char **argv
)
585 pkg_vec_t
*available
;
587 char *pkg_name
= NULL
;
592 available
= pkg_vec_alloc();
593 pkg_hash_fetch_all_installed(available
);
594 pkg_vec_sort(available
, pkg_compare_names
);
595 for (i
=0; i
< available
->len
; i
++) {
596 pkg
= available
->pkgs
[i
];
597 /* if we have package name or pattern and pkg does not match, then skip it */
598 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
603 pkg_vec_free(available
);
609 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
612 pkg_vec_t
*available
;
614 char *pkg_name
= NULL
;
615 conffile_list_elt_t
*iter
;
621 available
= pkg_vec_alloc();
622 pkg_hash_fetch_all_installed(available
);
623 pkg_vec_sort(available
, pkg_compare_names
);
624 for (i
=0; i
< available
->len
; i
++) {
625 pkg
= available
->pkgs
[i
];
626 /* if we have package name or pattern and pkg does not match, then skip it */
627 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
629 if (nv_pair_list_empty(&pkg
->conffiles
))
631 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
632 cf
= (conffile_t
*)iter
->data
;
633 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
634 printf("%s\n", cf
->name
);
637 pkg_vec_free(available
);
642 opkg_list_upgradable_cmd(int argc
, char **argv
)
644 struct active_list
*head
= prepare_upgrade_list();
645 struct active_list
*node
=NULL
;
646 pkg_t
*_old_pkg
, *_new_pkg
;
648 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
649 _old_pkg
= list_entry(node
, pkg_t
, list
);
650 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
651 if (_new_pkg
== NULL
)
653 old_v
= pkg_version_str_alloc(_old_pkg
);
654 new_v
= pkg_version_str_alloc(_new_pkg
);
655 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
659 active_list_head_delete(head
);
664 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
667 pkg_vec_t
*available
;
669 char *pkg_name
= NULL
;
675 available
= pkg_vec_alloc();
677 pkg_hash_fetch_all_installed(available
);
679 pkg_hash_fetch_available(available
);
681 for (i
=0; i
< available
->len
; i
++) {
682 pkg
= available
->pkgs
[i
];
683 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
687 pkg_formatted_info(stdout
, pkg
);
689 if (conf
->verbosity
>= NOTICE
) {
690 conffile_list_elt_t
*iter
;
691 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
692 conffile_t
*cf
= (conffile_t
*)iter
->data
;
693 int modified
= conffile_has_been_modified(cf
);
695 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
696 cf
->name
, cf
->value
, modified
);
700 pkg_vec_free(available
);
706 opkg_info_cmd(int argc
, char **argv
)
708 return opkg_info_status_cmd(argc
, argv
, 0);
712 opkg_status_cmd(int argc
, char **argv
)
714 return opkg_info_status_cmd(argc
, argv
, 1);
718 opkg_configure_cmd(int argc
, char **argv
)
721 char *pkg_name
= NULL
;
726 err
= opkg_configure_packages(pkg_name
);
728 write_status_files_if_changed();
734 opkg_remove_cmd(int argc
, char **argv
)
736 int i
, a
, done
, err
= 0;
738 pkg_t
*pkg_to_remove
;
739 pkg_vec_t
*available
;
743 signal(SIGINT
, sigint_handler
);
745 pkg_info_preinstall_check();
747 available
= pkg_vec_alloc();
748 pkg_hash_fetch_all_installed(available
);
750 for (i
=0; i
<argc
; i
++) {
751 for (a
=0; a
<available
->len
; a
++) {
752 pkg
= available
->pkgs
[a
];
753 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
756 if (conf
->restrict_to_default_dest
) {
757 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
761 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
764 if (pkg_to_remove
== NULL
) {
765 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
768 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
769 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
773 if (opkg_remove_pkg(pkg_to_remove
, 0))
780 pkg_vec_free(available
);
783 opkg_msg(NOTICE
, "No packages removed.\n");
785 write_status_files_if_changed();
790 opkg_flag_cmd(int argc
, char **argv
)
794 const char *flags
= argv
[0];
796 signal(SIGINT
, sigint_handler
);
798 for (i
=1; i
< argc
; i
++) {
799 if (conf
->restrict_to_default_dest
) {
800 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
803 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
807 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
810 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
811 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
812 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
816 * Useful if a package is installed in an offline_root, and
817 * should be configured by opkg-cl configure at a later date.
819 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
820 pkg
->state_status
= pkg_state_status_from_str(flags
);
823 opkg_state_changed
++;
824 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
828 write_status_files_if_changed();
833 opkg_files_cmd(int argc
, char **argv
)
837 str_list_elt_t
*iter
;
844 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
846 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
850 files
= pkg_get_installed_files(pkg
);
851 pkg_version
= pkg_version_str_alloc(pkg
);
853 printf("Package %s (%s) is installed on %s and has the following files:\n",
854 pkg
->name
, pkg_version
, pkg
->dest
->name
);
856 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
857 printf("%s\n", (char *)iter
->data
);
860 pkg_free_installed_files(pkg
);
866 opkg_depends_cmd(int argc
, char **argv
)
870 pkg_vec_t
*available_pkgs
;
871 compound_depend_t
*cdep
;
875 pkg_info_preinstall_check();
877 available_pkgs
= pkg_vec_alloc();
879 pkg_hash_fetch_available(available_pkgs
);
881 pkg_hash_fetch_all_installed(available_pkgs
);
883 for (i
=0; i
<argc
; i
++) {
884 for (j
=0; j
<available_pkgs
->len
; j
++) {
885 pkg
= available_pkgs
->pkgs
[j
];
887 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
890 depends_count
= pkg
->depends_count
+
891 pkg
->pre_depends_count
+
892 pkg
->recommends_count
+
895 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
897 for (k
=0; k
<depends_count
; k
++) {
898 cdep
= &pkg
->depends
[k
];
900 if (cdep
->type
!= DEPEND
)
903 str
= pkg_depend_str(pkg
, k
);
904 opkg_msg(NOTICE
, "\t%s\n", str
);
911 pkg_vec_free(available_pkgs
);
916 pkg_mark_provides(pkg_t
*pkg
)
918 int provides_count
= pkg
->provides_count
;
919 abstract_pkg_t
**provides
= pkg
->provides
;
921 pkg
->parent
->state_flag
|= SF_MARKED
;
922 for (i
= 0; i
< provides_count
; i
++) {
923 provides
[i
]->state_flag
|= SF_MARKED
;
928 enum what_field_type
{
938 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
940 depend_t
*possibility
;
941 compound_depend_t
*cdep
;
942 pkg_vec_t
*available_pkgs
;
946 const char *rel_str
= NULL
;
949 switch (what_field_type
) {
950 case DEPEND
: rel_str
= "depends on"; break;
951 case CONFLICTS
: rel_str
= "conflicts with"; break;
952 case SUGGEST
: rel_str
= "suggests"; break;
953 case RECOMMEND
: rel_str
= "recommends"; break;
957 available_pkgs
= pkg_vec_alloc();
960 pkg_hash_fetch_available(available_pkgs
);
962 pkg_hash_fetch_all_installed(available_pkgs
);
964 /* mark the root set */
965 pkg_vec_clear_marks(available_pkgs
);
966 opkg_msg(NOTICE
, "Root set:\n");
967 for (i
= 0; i
< argc
; i
++)
968 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
970 for (i
= 0; i
< available_pkgs
->len
; i
++) {
971 pkg
= available_pkgs
->pkgs
[i
];
972 if (pkg
->state_flag
& SF_MARKED
) {
973 /* mark the parent (abstract) package */
974 pkg_mark_provides(pkg
);
975 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
979 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
983 for (j
=0; j
<available_pkgs
->len
; j
++) {
985 pkg
= available_pkgs
->pkgs
[j
];
986 count
= ((what_field_type
== CONFLICTS
)
987 ? pkg
->conflicts_count
988 : pkg
->pre_depends_count
+
990 pkg
->recommends_count
+
991 pkg
->suggests_count
);
993 /* skip this package if it is already marked */
994 if (pkg
->parent
->state_flag
& SF_MARKED
)
997 for (k
=0; k
<count
; k
++) {
998 cdep
= (what_field_type
== CONFLICTS
)
1002 if (what_field_type
!= cdep
->type
)
1005 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1006 possibility
= cdep
->possibilities
[l
];
1008 if ((possibility
->pkg
->state_flag
1013 /* mark the depending package so we
1014 * won't visit it again */
1015 pkg
->state_flag
|= SF_MARKED
;
1016 pkg_mark_provides(pkg
);
1019 ver
= pkg_version_str_alloc(pkg
);
1020 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1024 possibility
->pkg
->name
);
1026 if (possibility
->version
) {
1027 opkg_msg(NOTICE
, " (%s%s)",
1028 constraint_to_str(possibility
->constraint
),
1029 possibility
->version
);
1031 if (!pkg_dependence_satisfiable(possibility
))
1034 opkg_message(NOTICE
, "\n");
1041 } while (changed
&& recursive
);
1043 pkg_vec_free(available_pkgs
);
1049 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1051 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1055 opkg_whatdepends_cmd(int argc
, char **argv
)
1057 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1061 opkg_whatsuggests_cmd(int argc
, char **argv
)
1063 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1067 opkg_whatrecommends_cmd(int argc
, char **argv
)
1069 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1073 opkg_whatconflicts_cmd(int argc
, char **argv
)
1075 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1079 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1083 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1084 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1087 pkg_info_preinstall_check();
1089 if (conf
->query_all
)
1090 pkg_hash_fetch_available(available_pkgs
);
1092 pkg_hash_fetch_all_installed(available_pkgs
);
1093 for (i
= 0; i
< argc
; i
++) {
1094 const char *target
= argv
[i
];
1097 opkg_msg(NOTICE
, "What %s %s\n",
1099 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1100 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1102 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1103 for (k
= 0; k
< count
; k
++) {
1104 abstract_pkg_t
*apkg
=
1105 ((what_field_type
== WHATPROVIDES
)
1107 : pkg
->replaces
[k
]);
1108 if (fnmatch(target
, apkg
->name
, conf
->nocase
) == 0) {
1109 opkg_msg(NOTICE
, " %s", pkg
->name
);
1110 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
) : strcmp(target
, apkg
->name
)) != 0)
1111 opkg_msg(NOTICE
, "\t%s %s\n",
1112 rel_str
, apkg
->name
);
1113 opkg_message(NOTICE
, "\n");
1118 pkg_vec_free(available_pkgs
);
1124 opkg_whatprovides_cmd(int argc
, char **argv
)
1126 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1130 opkg_whatreplaces_cmd(int argc
, char **argv
)
1132 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1136 opkg_search_cmd(int argc
, char **argv
)
1140 pkg_vec_t
*installed
;
1142 str_list_t
*installed_files
;
1143 str_list_elt_t
*iter
;
1144 char *installed_file
;
1150 installed
= pkg_vec_alloc();
1151 pkg_hash_fetch_all_installed(installed
);
1152 pkg_vec_sort(installed
, pkg_compare_names
);
1154 for (i
=0; i
< installed
->len
; i
++) {
1155 pkg
= installed
->pkgs
[i
];
1157 installed_files
= pkg_get_installed_files(pkg
);
1159 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1160 installed_file
= (char *)iter
->data
;
1161 if (fnmatch(argv
[0], installed_file
, conf
->nocase
)==0)
1165 pkg_free_installed_files(pkg
);
1168 pkg_vec_free(installed
);
1174 opkg_compare_versions_cmd(int argc
, char **argv
)
1177 /* this is a bit gross */
1179 parse_version(&p1
, argv
[0]);
1180 parse_version(&p2
, argv
[2]);
1181 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1184 "opkg compare_versions <v1> <op> <v2>\n"
1185 "<op> is one of <= >= << >> =\n");
1191 opkg_print_architecture_cmd(int argc
, char **argv
)
1193 nv_pair_list_elt_t
*l
;
1195 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1196 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1197 printf("arch %s %s\n", nv
->name
, nv
->value
);
1203 /* XXX: CLEANUP: The usage strings should be incorporated into this
1204 array for easier maintenance */
1205 static opkg_cmd_t cmds
[] = {
1206 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1207 {"upgrade", 1, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1208 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1209 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1210 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1211 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1212 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1213 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1214 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1215 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1216 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1217 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1218 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1219 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1220 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1221 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1222 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1223 {"find", 1, (opkg_cmd_fun_t
)opkg_find_cmd
, PFM_SOURCE
},
1224 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1225 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1226 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1227 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1228 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1229 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1230 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1231 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1232 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1233 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1234 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1235 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1236 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1237 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1238 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1242 opkg_cmd_find(const char *name
)
1246 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1248 for (i
=0; i
< num_cmds
; i
++) {
1250 if (strcmp(name
, cmd
->name
) == 0)
1258 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1260 return (cmd
->fun
)(argc
, argv
);