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
);
165 if (opkg_download(url
, list_file_name
, NULL
, NULL
, 0)) {
168 opkg_msg(NOTICE
, "Updated list of available packages in %s.\n",
172 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
173 if (conf
->check_signature
) {
174 /* download detached signitures to verify the package lists */
175 /* get the url for the sig file */
176 if (src
->extra_data
) /* debian style? */
177 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
180 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
182 /* create temporary file for it */
185 /* Put the signature in the right place */
186 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
188 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
, 0);
191 opkg_msg(NOTICE
, "Signature check failed.\n");
193 err
= opkg_verify_file (list_file_name
, tmp_file_name
);
195 opkg_msg(NOTICE
, "Signature check passed.\n");
197 opkg_msg(NOTICE
, "Signature check failed.\n");
200 /* The signature was wrong so delete it */
201 opkg_msg(NOTICE
, "Remove wrong Signature file.\n");
202 unlink (tmp_file_name
);
203 unlink (list_file_name
);
205 /* We shouldn't unlink the signature ! */
206 // unlink (tmp_file_name);
207 free (tmp_file_name
);
213 free(list_file_name
);
223 struct opkg_intercept
229 typedef struct opkg_intercept
*opkg_intercept_t
;
231 static opkg_intercept_t
232 opkg_prep_intercepts(void)
234 opkg_intercept_t ctx
;
237 ctx
= xcalloc(1, sizeof (*ctx
));
238 ctx
->oldpath
= xstrdup(getenv("PATH"));
239 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
240 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
242 if (mkdtemp(ctx
->statedir
) == NULL
) {
243 opkg_perror(ERROR
,"Failed to make temp dir %s", ctx
->statedir
);
251 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
252 setenv("PATH", newpath
, 1);
259 opkg_finalize_intercepts(opkg_intercept_t ctx
)
264 setenv ("PATH", ctx
->oldpath
, 1);
267 dir
= opendir (ctx
->statedir
);
270 while (de
= readdir (dir
), de
!= NULL
) {
273 if (de
->d_name
[0] == '.')
276 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
277 if (access (path
, X_OK
) == 0) {
278 const char *argv
[] = {"sh", "-c", path
, NULL
};
285 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
288 free (ctx
->statedir
);
294 /* For package pkg do the following: If it is already visited, return. If not,
295 add it in visited list and recurse to its deps. Finally, add it to ordered
297 pkg_vec all contains all available packages in repos.
298 pkg_vec visited contains packages already visited by this function, and is
299 used to end recursion and avoid an infinite loop on graph cycles.
300 pkg_vec ordered will finally contain the ordered set of packages.
303 opkg_recurse_pkgs_in_order(pkg_t
*pkg
, pkg_vec_t
*all
,
304 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
309 compound_depend_t
* compound_depend
;
310 depend_t
** possible_satisfiers
;
311 abstract_pkg_t
*abpkg
;
312 abstract_pkg_t
**dependents
;
314 /* If it's just an available package, that is, not installed and not even
316 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
317 would do here. However, if there is an intermediate node (pkg) that is
318 configured and installed between two unpacked packages, the latter
319 won't be properly reordered, unless all installed/unpacked pkgs are
321 if (pkg
->state_status
== SS_NOT_INSTALLED
)
324 /* If the package has already been visited (by this function), skip it */
325 for(j
= 0; j
< visited
->len
; j
++)
326 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
327 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n", pkg
->name
);
331 pkg_vec_insert(visited
, pkg
);
333 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
334 pkg
->recommends_count
+ pkg
->suggests_count
;
336 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
338 /* Iterate over all the dependencies of pkg. For each one, find a package
339 that is either installed or unpacked and satisfies this dependency.
340 (there should only be one such package per dependency installed or
341 unpacked). Then recurse to the dependency package */
342 for (j
=0; j
< count
; j
++) {
343 compound_depend
= &pkg
->depends
[j
];
344 possible_satisfiers
= compound_depend
->possibilities
;
345 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
346 abpkg
= possible_satisfiers
[k
]->pkg
;
347 dependents
= abpkg
->provided_by
->pkgs
;
349 if (dependents
!= NULL
)
350 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
351 opkg_msg(DEBUG
, "Descending on pkg %s.\n",
352 dependents
[l
]->name
);
354 /* find whether dependent l is installed or unpacked,
355 * and then find which package in the list satisfies it */
356 for(m
= 0; m
< all
->len
; m
++) {
358 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
359 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
360 opkg_recurse_pkgs_in_order(dep
, all
,
362 /* Stop the outer loop */
363 l
= abpkg
->provided_by
->len
;
364 /* break from the inner loop */
373 /* When all recursions from this node down, are over, and all
374 dependencies have been added in proper order in the ordered array, add
375 also the package pkg to ordered array */
376 pkg_vec_insert(ordered
, pkg
);
383 opkg_configure_packages(char *pkg_name
)
385 pkg_vec_t
*all
, *ordered
, *visited
;
391 opkg_msg(INFO
, "Configuring unpacked packages.\n");
393 all
= pkg_vec_alloc();
395 pkg_hash_fetch_available(all
);
397 /* Reorder pkgs in order to be configured according to the Depends: tag
399 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
400 ordered
= pkg_vec_alloc();
401 visited
= pkg_vec_alloc();
402 for(i
= 0; i
< all
->len
; i
++) {
404 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
407 ic
= opkg_prep_intercepts();
413 for(i
= 0; i
< ordered
->len
; i
++) {
414 pkg
= ordered
->pkgs
[i
];
416 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
419 if (pkg
->state_status
== SS_UNPACKED
) {
420 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
421 r
= opkg_configure(pkg
);
423 pkg
->state_status
= SS_INSTALLED
;
424 pkg
->parent
->state_status
= SS_INSTALLED
;
425 pkg
->state_flag
&= ~SF_PREFER
;
426 opkg_state_changed
++;
433 if (opkg_finalize_intercepts (ic
))
438 pkg_vec_free(ordered
);
439 pkg_vec_free(visited
);
445 opkg_remove_cmd(int argc
, char **argv
);
448 opkg_install_cmd(int argc
, char **argv
)
454 if (conf
->force_reinstall
) {
455 int saved_force_depends
= conf
->force_depends
;
456 conf
->force_depends
= 1;
457 (void)opkg_remove_cmd(argc
, argv
);
458 conf
->force_depends
= saved_force_depends
;
459 conf
->force_reinstall
= 0;
462 signal(SIGINT
, sigint_handler
);
465 * Now scan through package names and install
467 for (i
=0; i
< argc
; i
++) {
470 opkg_msg(DEBUG2
, "%s\n", arg
);
471 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
474 pkg_info_preinstall_check();
476 for (i
=0; i
< argc
; i
++) {
478 if (opkg_install_by_name(arg
)) {
479 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
484 if (opkg_configure_packages(NULL
))
487 write_status_files_if_changed();
493 opkg_upgrade_cmd(int argc
, char **argv
)
499 signal(SIGINT
, sigint_handler
);
502 for (i
=0; i
< argc
; i
++) {
505 if (opkg_prepare_url_for_install(arg
, &arg
))
508 pkg_info_preinstall_check();
510 for (i
=0; i
< argc
; i
++) {
512 if (conf
->restrict_to_default_dest
) {
513 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
516 opkg_msg(NOTICE
, "Package %s not installed in %s.\n",
517 argv
[i
], conf
->default_dest
->name
);
521 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
524 if (opkg_upgrade_pkg(pkg
))
527 if (opkg_install_by_name(arg
))
533 if (opkg_configure_packages(NULL
))
536 write_status_files_if_changed();
542 opkg_download_cmd(int argc
, char **argv
)
548 pkg_info_preinstall_check();
549 for (i
= 0; i
< argc
; i
++) {
552 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
554 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
558 if (opkg_download_pkg(pkg
, "."))
562 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
564 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
565 pkg
->name
, pkg
->local_filename
);
574 opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
577 pkg_vec_t
*available
;
579 char *pkg_name
= NULL
;
584 available
= pkg_vec_alloc();
585 pkg_hash_fetch_available(available
);
586 pkg_vec_sort(available
, pkg_compare_names
);
587 for (i
=0; i
< available
->len
; i
++) {
588 pkg
= available
->pkgs
[i
];
589 /* if we have package name or pattern and pkg does not match, then skip it */
590 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
) &&
591 (!use_desc
|| !pkg
->description
|| fnmatch(pkg_name
, pkg
->description
, conf
->nocase
)))
595 pkg_vec_free(available
);
601 opkg_list_cmd(int argc
, char **argv
)
603 return opkg_list_find_cmd(argc
, argv
, 0);
607 opkg_find_cmd(int argc
, char **argv
)
609 return opkg_list_find_cmd(argc
, argv
, 1);
614 opkg_list_installed_cmd(int argc
, char **argv
)
617 pkg_vec_t
*available
;
619 char *pkg_name
= NULL
;
624 available
= pkg_vec_alloc();
625 pkg_hash_fetch_all_installed(available
);
626 pkg_vec_sort(available
, pkg_compare_names
);
627 for (i
=0; i
< available
->len
; i
++) {
628 pkg
= available
->pkgs
[i
];
629 /* if we have package name or pattern and pkg does not match, then skip it */
630 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
635 pkg_vec_free(available
);
641 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
644 pkg_vec_t
*available
;
646 char *pkg_name
= NULL
;
647 conffile_list_elt_t
*iter
;
653 available
= pkg_vec_alloc();
654 pkg_hash_fetch_all_installed(available
);
655 pkg_vec_sort(available
, pkg_compare_names
);
656 for (i
=0; i
< available
->len
; i
++) {
657 pkg
= available
->pkgs
[i
];
658 /* if we have package name or pattern and pkg does not match, then skip it */
659 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
661 if (nv_pair_list_empty(&pkg
->conffiles
))
663 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
664 cf
= (conffile_t
*)iter
->data
;
665 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
666 printf("%s\n", cf
->name
);
669 pkg_vec_free(available
);
674 opkg_list_upgradable_cmd(int argc
, char **argv
)
676 struct active_list
*head
= prepare_upgrade_list();
677 struct active_list
*node
=NULL
;
678 pkg_t
*_old_pkg
, *_new_pkg
;
680 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
681 _old_pkg
= list_entry(node
, pkg_t
, list
);
682 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
683 if (_new_pkg
== NULL
)
685 old_v
= pkg_version_str_alloc(_old_pkg
);
686 new_v
= pkg_version_str_alloc(_new_pkg
);
687 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
691 active_list_head_delete(head
);
696 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
699 pkg_vec_t
*available
;
701 char *pkg_name
= NULL
;
707 available
= pkg_vec_alloc();
709 pkg_hash_fetch_all_installed(available
);
711 pkg_hash_fetch_available(available
);
713 for (i
=0; i
< available
->len
; i
++) {
714 pkg
= available
->pkgs
[i
];
715 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
719 pkg_formatted_info(stdout
, pkg
);
721 if (conf
->verbosity
>= NOTICE
) {
722 conffile_list_elt_t
*iter
;
723 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
724 conffile_t
*cf
= (conffile_t
*)iter
->data
;
725 int modified
= conffile_has_been_modified(cf
);
727 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
728 cf
->name
, cf
->value
, modified
);
732 pkg_vec_free(available
);
738 opkg_info_cmd(int argc
, char **argv
)
740 return opkg_info_status_cmd(argc
, argv
, 0);
744 opkg_status_cmd(int argc
, char **argv
)
746 return opkg_info_status_cmd(argc
, argv
, 1);
750 opkg_configure_cmd(int argc
, char **argv
)
753 char *pkg_name
= NULL
;
758 err
= opkg_configure_packages(pkg_name
);
760 write_status_files_if_changed();
766 opkg_remove_cmd(int argc
, char **argv
)
768 int i
, a
, done
, err
= 0;
770 pkg_t
*pkg_to_remove
;
771 pkg_vec_t
*available
;
775 signal(SIGINT
, sigint_handler
);
777 pkg_info_preinstall_check();
779 available
= pkg_vec_alloc();
780 pkg_hash_fetch_all_installed(available
);
782 for (i
=0; i
<argc
; i
++) {
783 for (a
=0; a
<available
->len
; a
++) {
784 pkg
= available
->pkgs
[a
];
785 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
788 if (conf
->restrict_to_default_dest
) {
789 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
793 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
796 if (pkg_to_remove
== NULL
) {
797 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
800 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
801 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
805 if (opkg_remove_pkg(pkg_to_remove
, 0))
812 pkg_vec_free(available
);
815 opkg_msg(NOTICE
, "No packages removed.\n");
817 write_status_files_if_changed();
822 opkg_flag_cmd(int argc
, char **argv
)
826 const char *flags
= argv
[0];
828 signal(SIGINT
, sigint_handler
);
830 for (i
=1; i
< argc
; i
++) {
831 if (conf
->restrict_to_default_dest
) {
832 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
835 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
839 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
842 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
843 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
844 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
848 * Useful if a package is installed in an offline_root, and
849 * should be configured by opkg-cl configure at a later date.
851 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
852 pkg
->state_status
= pkg_state_status_from_str(flags
);
855 opkg_state_changed
++;
856 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
860 write_status_files_if_changed();
865 opkg_files_cmd(int argc
, char **argv
)
869 str_list_elt_t
*iter
;
876 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
878 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
882 files
= pkg_get_installed_files(pkg
);
883 pkg_version
= pkg_version_str_alloc(pkg
);
885 printf("Package %s (%s) is installed on %s and has the following files:\n",
886 pkg
->name
, pkg_version
, pkg
->dest
->name
);
888 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
889 printf("%s\n", (char *)iter
->data
);
892 pkg_free_installed_files(pkg
);
898 opkg_depends_cmd(int argc
, char **argv
)
902 pkg_vec_t
*available_pkgs
;
903 compound_depend_t
*cdep
;
907 pkg_info_preinstall_check();
909 available_pkgs
= pkg_vec_alloc();
911 pkg_hash_fetch_available(available_pkgs
);
913 pkg_hash_fetch_all_installed(available_pkgs
);
915 for (i
=0; i
<argc
; i
++) {
916 for (j
=0; j
<available_pkgs
->len
; j
++) {
917 pkg
= available_pkgs
->pkgs
[j
];
919 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
922 depends_count
= pkg
->depends_count
+
923 pkg
->pre_depends_count
+
924 pkg
->recommends_count
+
927 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
929 for (k
=0; k
<depends_count
; k
++) {
930 cdep
= &pkg
->depends
[k
];
932 if (cdep
->type
!= DEPEND
)
935 str
= pkg_depend_str(pkg
, k
);
936 opkg_msg(NOTICE
, "\t%s\n", str
);
943 pkg_vec_free(available_pkgs
);
948 pkg_mark_provides(pkg_t
*pkg
)
950 int provides_count
= pkg
->provides_count
;
951 abstract_pkg_t
**provides
= pkg
->provides
;
953 pkg
->parent
->state_flag
|= SF_MARKED
;
954 for (i
= 0; i
< provides_count
; i
++) {
955 provides
[i
]->state_flag
|= SF_MARKED
;
960 enum what_field_type
{
970 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
972 depend_t
*possibility
;
973 compound_depend_t
*cdep
;
974 pkg_vec_t
*available_pkgs
;
978 const char *rel_str
= NULL
;
981 switch (what_field_type
) {
982 case DEPEND
: rel_str
= "depends on"; break;
983 case CONFLICTS
: rel_str
= "conflicts with"; break;
984 case SUGGEST
: rel_str
= "suggests"; break;
985 case RECOMMEND
: rel_str
= "recommends"; break;
989 available_pkgs
= pkg_vec_alloc();
992 pkg_hash_fetch_available(available_pkgs
);
994 pkg_hash_fetch_all_installed(available_pkgs
);
996 /* mark the root set */
997 pkg_vec_clear_marks(available_pkgs
);
998 opkg_msg(NOTICE
, "Root set:\n");
999 for (i
= 0; i
< argc
; i
++)
1000 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1002 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1003 pkg
= available_pkgs
->pkgs
[i
];
1004 if (pkg
->state_flag
& SF_MARKED
) {
1005 /* mark the parent (abstract) package */
1006 pkg_mark_provides(pkg
);
1007 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1011 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1015 for (j
=0; j
<available_pkgs
->len
; j
++) {
1017 pkg
= available_pkgs
->pkgs
[j
];
1018 count
= ((what_field_type
== CONFLICTS
)
1019 ? pkg
->conflicts_count
1020 : pkg
->pre_depends_count
+
1021 pkg
->depends_count
+
1022 pkg
->recommends_count
+
1023 pkg
->suggests_count
);
1025 /* skip this package if it is already marked */
1026 if (pkg
->parent
->state_flag
& SF_MARKED
)
1029 for (k
=0; k
<count
; k
++) {
1030 cdep
= (what_field_type
== CONFLICTS
)
1031 ? &pkg
->conflicts
[k
]
1034 if (what_field_type
!= cdep
->type
)
1037 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1038 possibility
= cdep
->possibilities
[l
];
1040 if ((possibility
->pkg
->state_flag
1045 /* mark the depending package so we
1046 * won't visit it again */
1047 pkg
->state_flag
|= SF_MARKED
;
1048 pkg_mark_provides(pkg
);
1051 ver
= pkg_version_str_alloc(pkg
);
1052 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1056 possibility
->pkg
->name
);
1058 if (possibility
->version
) {
1059 opkg_msg(NOTICE
, " (%s%s)",
1060 constraint_to_str(possibility
->constraint
),
1061 possibility
->version
);
1063 if (!pkg_dependence_satisfiable(possibility
))
1066 opkg_message(NOTICE
, "\n");
1073 } while (changed
&& recursive
);
1075 pkg_vec_free(available_pkgs
);
1081 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1083 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1087 opkg_whatdepends_cmd(int argc
, char **argv
)
1089 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1093 opkg_whatsuggests_cmd(int argc
, char **argv
)
1095 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1099 opkg_whatrecommends_cmd(int argc
, char **argv
)
1101 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1105 opkg_whatconflicts_cmd(int argc
, char **argv
)
1107 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1111 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1115 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1116 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1119 pkg_info_preinstall_check();
1121 if (conf
->query_all
)
1122 pkg_hash_fetch_available(available_pkgs
);
1124 pkg_hash_fetch_all_installed(available_pkgs
);
1125 for (i
= 0; i
< argc
; i
++) {
1126 const char *target
= argv
[i
];
1129 opkg_msg(NOTICE
, "What %s %s\n",
1131 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1132 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1134 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1135 for (k
= 0; k
< count
; k
++) {
1136 abstract_pkg_t
*apkg
=
1137 ((what_field_type
== WHATPROVIDES
)
1139 : pkg
->replaces
[k
]);
1140 if (fnmatch(target
, apkg
->name
, conf
->nocase
) == 0) {
1141 opkg_msg(NOTICE
, " %s", pkg
->name
);
1142 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
) : strcmp(target
, apkg
->name
)) != 0)
1143 opkg_msg(NOTICE
, "\t%s %s\n",
1144 rel_str
, apkg
->name
);
1145 opkg_message(NOTICE
, "\n");
1150 pkg_vec_free(available_pkgs
);
1156 opkg_whatprovides_cmd(int argc
, char **argv
)
1158 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1162 opkg_whatreplaces_cmd(int argc
, char **argv
)
1164 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1168 opkg_search_cmd(int argc
, char **argv
)
1172 pkg_vec_t
*installed
;
1174 str_list_t
*installed_files
;
1175 str_list_elt_t
*iter
;
1176 char *installed_file
;
1182 installed
= pkg_vec_alloc();
1183 pkg_hash_fetch_all_installed(installed
);
1184 pkg_vec_sort(installed
, pkg_compare_names
);
1186 for (i
=0; i
< installed
->len
; i
++) {
1187 pkg
= installed
->pkgs
[i
];
1189 installed_files
= pkg_get_installed_files(pkg
);
1191 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1192 installed_file
= (char *)iter
->data
;
1193 if (fnmatch(argv
[0], installed_file
, conf
->nocase
)==0)
1197 pkg_free_installed_files(pkg
);
1200 pkg_vec_free(installed
);
1206 opkg_compare_versions_cmd(int argc
, char **argv
)
1209 /* this is a bit gross */
1211 parse_version(&p1
, argv
[0]);
1212 parse_version(&p2
, argv
[2]);
1213 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1216 "opkg compare_versions <v1> <op> <v2>\n"
1217 "<op> is one of <= >= << >> =\n");
1223 opkg_print_architecture_cmd(int argc
, char **argv
)
1225 nv_pair_list_elt_t
*l
;
1227 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1228 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1229 printf("arch %s %s\n", nv
->name
, nv
->value
);
1235 /* XXX: CLEANUP: The usage strings should be incorporated into this
1236 array for easier maintenance */
1237 static opkg_cmd_t cmds
[] = {
1238 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1239 {"upgrade", 1, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1240 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1241 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1242 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1243 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1244 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1245 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1246 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1247 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1248 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1249 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1250 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1251 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1252 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1253 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1254 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1255 {"find", 1, (opkg_cmd_fun_t
)opkg_find_cmd
, PFM_SOURCE
},
1256 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1257 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1258 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1259 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1260 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1261 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1262 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1263 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1264 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1265 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1266 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1267 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1268 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1269 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1270 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1274 opkg_cmd_find(const char *name
)
1278 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1280 for (i
=0; i
< num_cmds
; i
++) {
1282 if (strcmp(name
, cmd
->name
) == 0)
1290 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1292 return (cmd
->fun
)(argc
, argv
);