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_find_cmd(int argc
, char **argv
, int use_desc
)
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
) &&
614 (!use_desc
|| !pkg
->description
|| fnmatch(pkg_name
, pkg
->description
, conf
->nocase
)))
618 pkg_vec_free(available
);
624 opkg_list_cmd(int argc
, char **argv
)
626 return opkg_list_find_cmd(argc
, argv
, 0);
630 opkg_find_cmd(int argc
, char **argv
)
632 return opkg_list_find_cmd(argc
, argv
, 1);
637 opkg_list_installed_cmd(int argc
, char **argv
)
640 pkg_vec_t
*available
;
642 char *pkg_name
= NULL
;
647 available
= pkg_vec_alloc();
648 pkg_hash_fetch_all_installed(available
);
649 pkg_vec_sort(available
, pkg_compare_names
);
650 for (i
=0; i
< available
->len
; i
++) {
651 pkg
= available
->pkgs
[i
];
652 /* if we have package name or pattern and pkg does not match, then skip it */
653 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
658 pkg_vec_free(available
);
664 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
667 pkg_vec_t
*available
;
669 char *pkg_name
= NULL
;
670 conffile_list_elt_t
*iter
;
676 available
= pkg_vec_alloc();
677 pkg_hash_fetch_all_installed(available
);
678 pkg_vec_sort(available
, pkg_compare_names
);
679 for (i
=0; i
< available
->len
; i
++) {
680 pkg
= available
->pkgs
[i
];
681 /* if we have package name or pattern and pkg does not match, then skip it */
682 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
684 if (nv_pair_list_empty(&pkg
->conffiles
))
686 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
687 cf
= (conffile_t
*)iter
->data
;
688 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
689 printf("%s\n", cf
->name
);
692 pkg_vec_free(available
);
697 opkg_list_upgradable_cmd(int argc
, char **argv
)
699 struct active_list
*head
= prepare_upgrade_list();
700 struct active_list
*node
=NULL
;
701 pkg_t
*_old_pkg
, *_new_pkg
;
703 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
704 _old_pkg
= list_entry(node
, pkg_t
, list
);
705 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
706 if (_new_pkg
== NULL
)
708 old_v
= pkg_version_str_alloc(_old_pkg
);
709 new_v
= pkg_version_str_alloc(_new_pkg
);
710 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
714 active_list_head_delete(head
);
719 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
722 pkg_vec_t
*available
;
724 char *pkg_name
= NULL
;
730 available
= pkg_vec_alloc();
732 pkg_hash_fetch_all_installed(available
);
734 pkg_hash_fetch_available(available
);
736 for (i
=0; i
< available
->len
; i
++) {
737 pkg
= available
->pkgs
[i
];
738 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
742 pkg_formatted_info(stdout
, pkg
);
744 if (conf
->verbosity
>= NOTICE
) {
745 conffile_list_elt_t
*iter
;
746 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
747 conffile_t
*cf
= (conffile_t
*)iter
->data
;
748 int modified
= conffile_has_been_modified(cf
);
750 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
751 cf
->name
, cf
->value
, modified
);
755 pkg_vec_free(available
);
761 opkg_info_cmd(int argc
, char **argv
)
763 return opkg_info_status_cmd(argc
, argv
, 0);
767 opkg_status_cmd(int argc
, char **argv
)
769 return opkg_info_status_cmd(argc
, argv
, 1);
773 opkg_configure_cmd(int argc
, char **argv
)
776 char *pkg_name
= NULL
;
781 err
= opkg_configure_packages(pkg_name
);
783 write_status_files_if_changed();
789 opkg_remove_cmd(int argc
, char **argv
)
791 int i
, a
, done
, err
= 0;
793 pkg_t
*pkg_to_remove
;
794 pkg_vec_t
*available
;
798 signal(SIGINT
, sigint_handler
);
800 pkg_info_preinstall_check();
802 available
= pkg_vec_alloc();
803 pkg_hash_fetch_all_installed(available
);
805 for (i
=0; i
<argc
; i
++) {
806 for (a
=0; a
<available
->len
; a
++) {
807 pkg
= available
->pkgs
[a
];
808 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
811 if (conf
->restrict_to_default_dest
) {
812 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
816 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
819 if (pkg_to_remove
== NULL
) {
820 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
823 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
824 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
828 if (opkg_remove_pkg(pkg_to_remove
, 0))
835 pkg_vec_free(available
);
838 opkg_msg(NOTICE
, "No packages removed.\n");
840 write_status_files_if_changed();
845 opkg_flag_cmd(int argc
, char **argv
)
849 const char *flags
= argv
[0];
851 signal(SIGINT
, sigint_handler
);
853 for (i
=1; i
< argc
; i
++) {
854 if (conf
->restrict_to_default_dest
) {
855 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
858 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
862 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
865 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
866 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
867 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
871 * Useful if a package is installed in an offline_root, and
872 * should be configured by opkg-cl configure at a later date.
874 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
875 pkg
->state_status
= pkg_state_status_from_str(flags
);
878 opkg_state_changed
++;
879 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
883 write_status_files_if_changed();
888 opkg_files_cmd(int argc
, char **argv
)
892 str_list_elt_t
*iter
;
899 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
901 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
905 files
= pkg_get_installed_files(pkg
);
906 pkg_version
= pkg_version_str_alloc(pkg
);
908 printf("Package %s (%s) is installed on %s and has the following files:\n",
909 pkg
->name
, pkg_version
, pkg
->dest
->name
);
911 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
912 printf("%s\n", (char *)iter
->data
);
915 pkg_free_installed_files(pkg
);
921 opkg_depends_cmd(int argc
, char **argv
)
925 pkg_vec_t
*available_pkgs
;
926 compound_depend_t
*cdep
;
930 pkg_info_preinstall_check();
932 available_pkgs
= pkg_vec_alloc();
934 pkg_hash_fetch_available(available_pkgs
);
936 pkg_hash_fetch_all_installed(available_pkgs
);
938 for (i
=0; i
<argc
; i
++) {
939 for (j
=0; j
<available_pkgs
->len
; j
++) {
940 pkg
= available_pkgs
->pkgs
[j
];
942 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
945 depends_count
= pkg
->depends_count
+
946 pkg
->pre_depends_count
+
947 pkg
->recommends_count
+
950 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
952 for (k
=0; k
<depends_count
; k
++) {
953 cdep
= &pkg
->depends
[k
];
955 if (cdep
->type
!= DEPEND
)
958 str
= pkg_depend_str(pkg
, k
);
959 opkg_msg(NOTICE
, "\t%s\n", str
);
966 pkg_vec_free(available_pkgs
);
971 pkg_mark_provides(pkg_t
*pkg
)
973 int provides_count
= pkg
->provides_count
;
974 abstract_pkg_t
**provides
= pkg
->provides
;
976 pkg
->parent
->state_flag
|= SF_MARKED
;
977 for (i
= 0; i
< provides_count
; i
++) {
978 provides
[i
]->state_flag
|= SF_MARKED
;
983 enum what_field_type
{
993 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
995 depend_t
*possibility
;
996 compound_depend_t
*cdep
;
997 pkg_vec_t
*available_pkgs
;
1001 const char *rel_str
= NULL
;
1004 switch (what_field_type
) {
1005 case DEPEND
: rel_str
= "depends on"; break;
1006 case CONFLICTS
: rel_str
= "conflicts with"; break;
1007 case SUGGEST
: rel_str
= "suggests"; break;
1008 case RECOMMEND
: rel_str
= "recommends"; break;
1012 available_pkgs
= pkg_vec_alloc();
1014 if (conf
->query_all
)
1015 pkg_hash_fetch_available(available_pkgs
);
1017 pkg_hash_fetch_all_installed(available_pkgs
);
1019 /* mark the root set */
1020 pkg_vec_clear_marks(available_pkgs
);
1021 opkg_msg(NOTICE
, "Root set:\n");
1022 for (i
= 0; i
< argc
; i
++)
1023 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1025 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1026 pkg
= available_pkgs
->pkgs
[i
];
1027 if (pkg
->state_flag
& SF_MARKED
) {
1028 /* mark the parent (abstract) package */
1029 pkg_mark_provides(pkg
);
1030 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1034 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1038 for (j
=0; j
<available_pkgs
->len
; j
++) {
1040 pkg
= available_pkgs
->pkgs
[j
];
1041 count
= ((what_field_type
== CONFLICTS
)
1042 ? pkg
->conflicts_count
1043 : pkg
->pre_depends_count
+
1044 pkg
->depends_count
+
1045 pkg
->recommends_count
+
1046 pkg
->suggests_count
);
1048 /* skip this package if it is already marked */
1049 if (pkg
->parent
->state_flag
& SF_MARKED
)
1052 for (k
=0; k
<count
; k
++) {
1053 cdep
= (what_field_type
== CONFLICTS
)
1054 ? &pkg
->conflicts
[k
]
1057 if (what_field_type
!= cdep
->type
)
1060 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1061 possibility
= cdep
->possibilities
[l
];
1063 if ((possibility
->pkg
->state_flag
1068 /* mark the depending package so we
1069 * won't visit it again */
1070 pkg
->state_flag
|= SF_MARKED
;
1071 pkg_mark_provides(pkg
);
1074 ver
= pkg_version_str_alloc(pkg
);
1075 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1079 possibility
->pkg
->name
);
1081 if (possibility
->version
) {
1082 opkg_msg(NOTICE
, " (%s%s)",
1083 constraint_to_str(possibility
->constraint
),
1084 possibility
->version
);
1086 if (!pkg_dependence_satisfiable(possibility
))
1089 opkg_message(NOTICE
, "\n");
1096 } while (changed
&& recursive
);
1098 pkg_vec_free(available_pkgs
);
1104 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1106 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1110 opkg_whatdepends_cmd(int argc
, char **argv
)
1112 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1116 opkg_whatsuggests_cmd(int argc
, char **argv
)
1118 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1122 opkg_whatrecommends_cmd(int argc
, char **argv
)
1124 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1128 opkg_whatconflicts_cmd(int argc
, char **argv
)
1130 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1134 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1138 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1139 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1142 pkg_info_preinstall_check();
1144 if (conf
->query_all
)
1145 pkg_hash_fetch_available(available_pkgs
);
1147 pkg_hash_fetch_all_installed(available_pkgs
);
1148 for (i
= 0; i
< argc
; i
++) {
1149 const char *target
= argv
[i
];
1152 opkg_msg(NOTICE
, "What %s %s\n",
1154 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1155 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1157 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1158 for (k
= 0; k
< count
; k
++) {
1159 abstract_pkg_t
*apkg
=
1160 ((what_field_type
== WHATPROVIDES
)
1162 : pkg
->replaces
[k
]);
1163 if (fnmatch(target
, apkg
->name
, conf
->nocase
) == 0) {
1164 opkg_msg(NOTICE
, " %s", pkg
->name
);
1165 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
) : strcmp(target
, apkg
->name
)) != 0)
1166 opkg_msg(NOTICE
, "\t%s %s\n",
1167 rel_str
, apkg
->name
);
1168 opkg_message(NOTICE
, "\n");
1173 pkg_vec_free(available_pkgs
);
1179 opkg_whatprovides_cmd(int argc
, char **argv
)
1181 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1185 opkg_whatreplaces_cmd(int argc
, char **argv
)
1187 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1191 opkg_search_cmd(int argc
, char **argv
)
1195 pkg_vec_t
*installed
;
1197 str_list_t
*installed_files
;
1198 str_list_elt_t
*iter
;
1199 char *installed_file
;
1205 installed
= pkg_vec_alloc();
1206 pkg_hash_fetch_all_installed(installed
);
1207 pkg_vec_sort(installed
, pkg_compare_names
);
1209 for (i
=0; i
< installed
->len
; i
++) {
1210 pkg
= installed
->pkgs
[i
];
1212 installed_files
= pkg_get_installed_files(pkg
);
1214 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1215 installed_file
= (char *)iter
->data
;
1216 if (fnmatch(argv
[0], installed_file
, conf
->nocase
)==0)
1220 pkg_free_installed_files(pkg
);
1223 pkg_vec_free(installed
);
1229 opkg_compare_versions_cmd(int argc
, char **argv
)
1232 /* this is a bit gross */
1234 parse_version(&p1
, argv
[0]);
1235 parse_version(&p2
, argv
[2]);
1236 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1239 "opkg compare_versions <v1> <op> <v2>\n"
1240 "<op> is one of <= >= << >> =\n");
1246 opkg_print_architecture_cmd(int argc
, char **argv
)
1248 nv_pair_list_elt_t
*l
;
1250 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1251 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1252 printf("arch %s %s\n", nv
->name
, nv
->value
);
1258 /* XXX: CLEANUP: The usage strings should be incorporated into this
1259 array for easier maintenance */
1260 static opkg_cmd_t cmds
[] = {
1261 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1262 {"upgrade", 1, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1263 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1264 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1265 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1266 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1267 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1268 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1269 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1270 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1271 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1272 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1273 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1274 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1275 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1276 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1277 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1278 {"find", 1, (opkg_cmd_fun_t
)opkg_find_cmd
, PFM_SOURCE
},
1279 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1280 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1281 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1282 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1283 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1284 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1285 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1286 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1287 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1288 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1289 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1290 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1291 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1292 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1293 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1297 opkg_cmd_find(const char *name
)
1301 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1303 for (i
=0; i
< num_cmds
; i
++) {
1305 if (strcmp(name
, cmd
->name
) == 0)
1313 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1315 return (cmd
->fun
)(argc
, argv
);