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
, 0))
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
))
555 pkg_vec_t
*installed
= pkg_vec_alloc();
557 pkg_info_preinstall_check();
559 pkg_hash_fetch_all_installed(installed
);
560 for (i
= 0; i
< installed
->len
; i
++) {
561 pkg
= installed
->pkgs
[i
];
562 if (opkg_upgrade_pkg(pkg
))
565 pkg_vec_free(installed
);
568 if (opkg_configure_packages(NULL
))
571 write_status_files_if_changed();
577 opkg_download_cmd(int argc
, char **argv
)
583 pkg_info_preinstall_check();
584 for (i
= 0; i
< argc
; i
++) {
587 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
589 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
593 if (opkg_download_pkg(pkg
, "."))
597 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
599 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
600 pkg
->name
, pkg
->local_filename
);
609 opkg_list_cmd(int argc
, char **argv
)
612 pkg_vec_t
*available
;
614 char *pkg_name
= NULL
;
619 available
= pkg_vec_alloc();
620 pkg_hash_fetch_available(available
);
621 pkg_vec_sort(available
, pkg_compare_names
);
622 for (i
=0; i
< available
->len
; i
++) {
623 pkg
= available
->pkgs
[i
];
624 /* if we have package name or pattern and pkg does not match, then skip it */
625 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
629 pkg_vec_free(available
);
636 opkg_list_installed_cmd(int argc
, char **argv
)
639 pkg_vec_t
*available
;
641 char *pkg_name
= NULL
;
646 available
= pkg_vec_alloc();
647 pkg_hash_fetch_all_installed(available
);
648 pkg_vec_sort(available
, pkg_compare_names
);
649 for (i
=0; i
< available
->len
; i
++) {
650 pkg
= available
->pkgs
[i
];
651 /* if we have package name or pattern and pkg does not match, then skip it */
652 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
657 pkg_vec_free(available
);
663 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
666 pkg_vec_t
*available
;
668 char *pkg_name
= NULL
;
669 conffile_list_elt_t
*iter
;
675 available
= pkg_vec_alloc();
676 pkg_hash_fetch_all_installed(available
);
677 pkg_vec_sort(available
, pkg_compare_names
);
678 for (i
=0; i
< available
->len
; i
++) {
679 pkg
= available
->pkgs
[i
];
680 /* if we have package name or pattern and pkg does not match, then skip it */
681 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
683 if (nv_pair_list_empty(&pkg
->conffiles
))
685 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
686 cf
= (conffile_t
*)iter
->data
;
687 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
688 printf("%s\n", cf
->name
);
691 pkg_vec_free(available
);
696 opkg_list_upgradable_cmd(int argc
, char **argv
)
698 struct active_list
*head
= prepare_upgrade_list();
699 struct active_list
*node
=NULL
;
700 pkg_t
*_old_pkg
, *_new_pkg
;
702 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
703 _old_pkg
= list_entry(node
, pkg_t
, list
);
704 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
705 if (_new_pkg
== NULL
)
707 old_v
= pkg_version_str_alloc(_old_pkg
);
708 new_v
= pkg_version_str_alloc(_new_pkg
);
709 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
713 active_list_head_delete(head
);
718 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
721 pkg_vec_t
*available
;
723 char *pkg_name
= NULL
;
729 available
= pkg_vec_alloc();
731 pkg_hash_fetch_all_installed(available
);
733 pkg_hash_fetch_available(available
);
735 for (i
=0; i
< available
->len
; i
++) {
736 pkg
= available
->pkgs
[i
];
737 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
741 pkg_formatted_info(stdout
, pkg
);
743 if (conf
->verbosity
>= NOTICE
) {
744 conffile_list_elt_t
*iter
;
745 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
746 conffile_t
*cf
= (conffile_t
*)iter
->data
;
747 int modified
= conffile_has_been_modified(cf
);
749 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
750 cf
->name
, cf
->value
, modified
);
754 pkg_vec_free(available
);
760 opkg_info_cmd(int argc
, char **argv
)
762 return opkg_info_status_cmd(argc
, argv
, 0);
766 opkg_status_cmd(int argc
, char **argv
)
768 return opkg_info_status_cmd(argc
, argv
, 1);
772 opkg_configure_cmd(int argc
, char **argv
)
775 char *pkg_name
= NULL
;
780 err
= opkg_configure_packages(pkg_name
);
782 write_status_files_if_changed();
788 opkg_remove_cmd(int argc
, char **argv
)
790 int i
, a
, done
, err
= 0;
792 pkg_t
*pkg_to_remove
;
793 pkg_vec_t
*available
;
797 signal(SIGINT
, sigint_handler
);
799 pkg_info_preinstall_check();
801 available
= pkg_vec_alloc();
802 pkg_hash_fetch_all_installed(available
);
804 for (i
=0; i
<argc
; i
++) {
805 for (a
=0; a
<available
->len
; a
++) {
806 pkg
= available
->pkgs
[a
];
807 if (fnmatch(argv
[i
], pkg
->name
, 0)) {
810 if (conf
->restrict_to_default_dest
) {
811 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
815 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
818 if (pkg_to_remove
== NULL
) {
819 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
822 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
823 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
827 if (opkg_remove_pkg(pkg_to_remove
, 0))
834 pkg_vec_free(available
);
837 opkg_msg(NOTICE
, "No packages removed.\n");
839 write_status_files_if_changed();
844 opkg_flag_cmd(int argc
, char **argv
)
848 const char *flags
= argv
[0];
850 signal(SIGINT
, sigint_handler
);
852 for (i
=1; i
< argc
; i
++) {
853 if (conf
->restrict_to_default_dest
) {
854 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
857 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
861 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
864 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
865 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
866 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
870 * Useful if a package is installed in an offline_root, and
871 * should be configured by opkg-cl configure at a later date.
873 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
874 pkg
->state_status
= pkg_state_status_from_str(flags
);
877 opkg_state_changed
++;
878 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
882 write_status_files_if_changed();
887 opkg_files_cmd(int argc
, char **argv
)
891 str_list_elt_t
*iter
;
898 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
900 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
904 files
= pkg_get_installed_files(pkg
);
905 pkg_version
= pkg_version_str_alloc(pkg
);
907 printf("Package %s (%s) is installed on %s and has the following files:\n",
908 pkg
->name
, pkg_version
, pkg
->dest
->name
);
910 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
911 printf("%s\n", (char *)iter
->data
);
914 pkg_free_installed_files(pkg
);
920 opkg_depends_cmd(int argc
, char **argv
)
924 pkg_vec_t
*available_pkgs
;
925 compound_depend_t
*cdep
;
929 pkg_info_preinstall_check();
931 available_pkgs
= pkg_vec_alloc();
933 pkg_hash_fetch_available(available_pkgs
);
935 pkg_hash_fetch_all_installed(available_pkgs
);
937 for (i
=0; i
<argc
; i
++) {
938 for (j
=0; j
<available_pkgs
->len
; j
++) {
939 pkg
= available_pkgs
->pkgs
[j
];
941 if (fnmatch(argv
[i
], pkg
->name
, 0) != 0)
944 depends_count
= pkg
->depends_count
+
945 pkg
->pre_depends_count
+
946 pkg
->recommends_count
+
949 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
951 for (k
=0; k
<depends_count
; k
++) {
952 cdep
= &pkg
->depends
[k
];
954 if (cdep
->type
!= DEPEND
)
957 str
= pkg_depend_str(pkg
, k
);
958 opkg_msg(NOTICE
, "\t%s\n", str
);
965 pkg_vec_free(available_pkgs
);
970 pkg_mark_provides(pkg_t
*pkg
)
972 int provides_count
= pkg
->provides_count
;
973 abstract_pkg_t
**provides
= pkg
->provides
;
975 pkg
->parent
->state_flag
|= SF_MARKED
;
976 for (i
= 0; i
< provides_count
; i
++) {
977 provides
[i
]->state_flag
|= SF_MARKED
;
982 enum what_field_type
{
992 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
994 depend_t
*possibility
;
995 compound_depend_t
*cdep
;
996 pkg_vec_t
*available_pkgs
;
1000 const char *rel_str
= NULL
;
1003 switch (what_field_type
) {
1004 case DEPEND
: rel_str
= "depends on"; break;
1005 case CONFLICTS
: rel_str
= "conflicts with"; break;
1006 case SUGGEST
: rel_str
= "suggests"; break;
1007 case RECOMMEND
: rel_str
= "recommends"; break;
1011 available_pkgs
= pkg_vec_alloc();
1013 if (conf
->query_all
)
1014 pkg_hash_fetch_available(available_pkgs
);
1016 pkg_hash_fetch_all_installed(available_pkgs
);
1018 /* mark the root set */
1019 pkg_vec_clear_marks(available_pkgs
);
1020 opkg_msg(NOTICE
, "Root set:\n");
1021 for (i
= 0; i
< argc
; i
++)
1022 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1024 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1025 pkg
= available_pkgs
->pkgs
[i
];
1026 if (pkg
->state_flag
& SF_MARKED
) {
1027 /* mark the parent (abstract) package */
1028 pkg_mark_provides(pkg
);
1029 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1033 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1037 for (j
=0; j
<available_pkgs
->len
; j
++) {
1039 pkg
= available_pkgs
->pkgs
[j
];
1040 count
= ((what_field_type
== CONFLICTS
)
1041 ? pkg
->conflicts_count
1042 : pkg
->pre_depends_count
+
1043 pkg
->depends_count
+
1044 pkg
->recommends_count
+
1045 pkg
->suggests_count
);
1047 /* skip this package if it is already marked */
1048 if (pkg
->parent
->state_flag
& SF_MARKED
)
1051 for (k
=0; k
<count
; k
++) {
1052 cdep
= (what_field_type
== CONFLICTS
)
1053 ? &pkg
->conflicts
[k
]
1056 if (what_field_type
!= cdep
->type
)
1059 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1060 possibility
= cdep
->possibilities
[l
];
1062 if ((possibility
->pkg
->state_flag
1067 /* mark the depending package so we
1068 * won't visit it again */
1069 pkg
->state_flag
|= SF_MARKED
;
1070 pkg_mark_provides(pkg
);
1073 ver
= pkg_version_str_alloc(pkg
);
1074 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1078 possibility
->pkg
->name
);
1080 if (possibility
->version
) {
1081 opkg_msg(NOTICE
, " (%s%s)",
1082 constraint_to_str(possibility
->constraint
),
1083 possibility
->version
);
1085 if (!pkg_dependence_satisfiable(possibility
))
1088 opkg_message(NOTICE
, "\n");
1095 } while (changed
&& recursive
);
1097 pkg_vec_free(available_pkgs
);
1103 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1105 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1109 opkg_whatdepends_cmd(int argc
, char **argv
)
1111 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1115 opkg_whatsuggests_cmd(int argc
, char **argv
)
1117 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1121 opkg_whatrecommends_cmd(int argc
, char **argv
)
1123 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1127 opkg_whatconflicts_cmd(int argc
, char **argv
)
1129 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1133 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1137 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1138 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1141 pkg_info_preinstall_check();
1143 if (conf
->query_all
)
1144 pkg_hash_fetch_available(available_pkgs
);
1146 pkg_hash_fetch_all_installed(available_pkgs
);
1147 for (i
= 0; i
< argc
; i
++) {
1148 const char *target
= argv
[i
];
1151 opkg_msg(NOTICE
, "What %s %s\n",
1153 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1154 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1156 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1157 for (k
= 0; k
< count
; k
++) {
1158 abstract_pkg_t
*apkg
=
1159 ((what_field_type
== WHATPROVIDES
)
1161 : pkg
->replaces
[k
]);
1162 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1163 opkg_msg(NOTICE
, " %s", pkg
->name
);
1164 if (strcmp(target
, apkg
->name
) != 0)
1165 opkg_msg(NOTICE
, "\t%s %s\n",
1166 rel_str
, apkg
->name
);
1167 opkg_message(NOTICE
, "\n");
1172 pkg_vec_free(available_pkgs
);
1178 opkg_whatprovides_cmd(int argc
, char **argv
)
1180 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1184 opkg_whatreplaces_cmd(int argc
, char **argv
)
1186 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1190 opkg_search_cmd(int argc
, char **argv
)
1194 pkg_vec_t
*installed
;
1196 str_list_t
*installed_files
;
1197 str_list_elt_t
*iter
;
1198 char *installed_file
;
1204 installed
= pkg_vec_alloc();
1205 pkg_hash_fetch_all_installed(installed
);
1206 pkg_vec_sort(installed
, pkg_compare_names
);
1208 for (i
=0; i
< installed
->len
; i
++) {
1209 pkg
= installed
->pkgs
[i
];
1211 installed_files
= pkg_get_installed_files(pkg
);
1213 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1214 installed_file
= (char *)iter
->data
;
1215 if (fnmatch(argv
[0], installed_file
, 0)==0)
1219 pkg_free_installed_files(pkg
);
1222 pkg_vec_free(installed
);
1228 opkg_compare_versions_cmd(int argc
, char **argv
)
1231 /* this is a bit gross */
1233 parse_version(&p1
, argv
[0]);
1234 parse_version(&p2
, argv
[2]);
1235 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1238 "opkg compare_versions <v1> <op> <v2>\n"
1239 "<op> is one of <= >= << >> =\n");
1245 opkg_print_architecture_cmd(int argc
, char **argv
)
1247 nv_pair_list_elt_t
*l
;
1249 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1250 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1251 printf("arch %s %s\n", nv
->name
, nv
->value
);
1257 /* XXX: CLEANUP: The usage strings should be incorporated into this
1258 array for easier maintenance */
1259 static opkg_cmd_t cmds
[] = {
1260 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1261 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1262 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1263 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1264 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1265 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1266 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1267 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1268 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1269 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1270 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1271 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1272 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1273 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1274 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1275 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1276 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1277 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1278 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1279 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1280 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1281 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1282 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1283 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1284 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1285 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1286 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1287 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1288 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1289 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1290 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1291 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1295 opkg_cmd_find(const char *name
)
1299 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1301 for (i
=0; i
< num_cmds
; i
++) {
1303 if (strcmp(name
, cmd
->name
) == 0)
1311 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1313 return (cmd
->fun
)(argc
, argv
);