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.
25 #include "opkg_conf.h"
27 #include "opkg_message.h"
30 #include "pkg_parse.h"
31 #include "sprintf_alloc.h"
33 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
44 static void print_pkg(pkg_t
* pkg
)
46 char *version
= pkg_version_str_alloc(pkg
);
47 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
48 printf("%s - %s", pkg
->name
, version
);
50 printf(" - %lu", (unsigned long) pkg_get_int(pkg
, PKG_SIZE
));
52 printf(" - %s", description
);
57 int opkg_state_changed
;
59 static void write_status_files_if_changed(void)
61 if (opkg_state_changed
&& !conf
->noaction
) {
62 opkg_msg(INFO
, "Writing status file.\n");
63 opkg_conf_write_status_files();
64 pkg_write_changed_filelists();
66 opkg_msg(DEBUG
, "Nothing to be done.\n");
70 static void sigint_handler(int sig
)
73 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
74 write_status_files_if_changed();
78 static int opkg_update_cmd(int argc
, char **argv
)
85 pkg_src_list_elt_t
*iter
;
88 sprintf_alloc(&lists_dir
, "%s",
89 conf
->restrict_to_default_dest
? conf
->default_dest
->
90 lists_dir
: conf
->lists_dir
);
92 if (!file_is_dir(lists_dir
)) {
93 if (file_exists(lists_dir
)) {
94 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
99 err
= file_mkdir_hier(lists_dir
, 0755);
108 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
109 if (mkdtemp(tmp
) == NULL
) {
110 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
114 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
;
115 iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
116 char *url
, *list_file_name
;
118 src
= (pkg_src_t
*) iter
->data
;
120 if (src
->extra_data
&& strcmp(src
->extra_data
, "__dummy__ "))
123 if (src
->extra_data
) /* debian style? */
124 sprintf_alloc(&url
, "%s/%s/%s", src
->value
,
126 src
->gzip
? "Packages.gz" : "Packages");
128 sprintf_alloc(&url
, "%s/%s", src
->value
,
129 src
->gzip
? "Packages.gz" : "Packages");
131 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
132 pkglist_dl_error
= 0;
133 if (opkg_download(url
, list_file_name
, NULL
, NULL
, 0)) {
135 pkglist_dl_error
= 1;
137 "*** Failed to download the package list from %s\n\n",
141 "Updated list of available packages in %s\n",
145 #if defined(HAVE_USIGN)
146 if (pkglist_dl_error
== 0 && conf
->check_signature
) {
147 /* download detached signitures to verify the package lists */
148 /* get the url for the sig file */
149 if (src
->extra_data
) /* debian style? */
150 sprintf_alloc(&url
, "%s/%s/%s", src
->value
,
151 src
->extra_data
, "Packages.sig");
153 sprintf_alloc(&url
, "%s/%s", src
->value
,
156 /* create temporary file for it */
159 /* Put the signature in the right place */
160 sprintf_alloc(&tmp_file_name
, "%s/%s.sig", lists_dir
,
163 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
, 0);
167 "Signature file download failed.\n");
170 opkg_verify_file(list_file_name
,
174 "Signature check passed.\n");
177 "Signature check failed.\n");
179 if (err
&& !conf
->force_signature
) {
180 /* The signature was wrong so delete it */
182 "Remove wrong Signature file.\n");
183 unlink(tmp_file_name
);
184 unlink(list_file_name
);
186 /* We shouldn't unlink the signature ! */
187 // unlink (tmp_file_name);
194 free(list_file_name
);
203 struct opkg_intercept
{
208 typedef struct opkg_intercept
*opkg_intercept_t
;
210 static opkg_intercept_t
opkg_prep_intercepts(void)
212 opkg_intercept_t ctx
;
215 ctx
= xcalloc(1, sizeof(*ctx
));
216 ctx
->oldpath
= xstrdup(getenv("PATH"));
217 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
218 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
221 if (mkdtemp(ctx
->statedir
) == NULL
) {
222 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
230 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
231 setenv("PATH", newpath
, 1);
237 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
242 setenv("PATH", ctx
->oldpath
, 1);
245 dir
= opendir(ctx
->statedir
);
248 while (de
= readdir(dir
), de
!= NULL
) {
251 if (de
->d_name
[0] == '.')
254 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
256 if (access(path
, X_OK
) == 0) {
257 const char *argv
[] = { "sh", "-c", path
, NULL
};
264 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
273 /* For package pkg do the following: If it is already visited, return. If not,
274 add it in visited list and recurse to its deps. Finally, add it to ordered
276 pkg_vec all contains all available packages in repos.
277 pkg_vec visited contains packages already visited by this function, and is
278 used to end recursion and avoid an infinite loop on graph cycles.
279 pkg_vec ordered will finally contain the ordered set of packages.
282 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
283 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
287 compound_depend_t
*compound_depend
;
288 depend_t
**possible_satisfiers
;
289 abstract_pkg_t
*abpkg
;
290 abstract_pkg_t
**dependents
;
292 /* If it's just an available package, that is, not installed and not even
294 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
295 would do here. However, if there is an intermediate node (pkg) that is
296 configured and installed between two unpacked packages, the latter
297 won't be properly reordered, unless all installed/unpacked pkgs are
299 if (pkg
->state_status
== SS_NOT_INSTALLED
)
302 /* If the package has already been visited (by this function), skip it */
303 for (j
= 0; j
< visited
->len
; j
++)
304 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
305 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
310 pkg_vec_insert(visited
, pkg
);
312 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
314 /* Iterate over all the dependencies of pkg. For each one, find a package
315 that is either installed or unpacked and satisfies this dependency.
316 (there should only be one such package per dependency installed or
317 unpacked). Then recurse to the dependency package */
318 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
319 possible_satisfiers
= compound_depend
->possibilities
;
320 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
321 abpkg
= possible_satisfiers
[k
]->pkg
;
322 dependents
= abpkg
->provided_by
->pkgs
;
324 if (dependents
!= NULL
)
325 while (l
< abpkg
->provided_by
->len
326 && dependents
[l
] != NULL
) {
328 "Descending on pkg %s.\n",
329 dependents
[l
]->name
);
331 /* find whether dependent l is installed or unpacked,
332 * and then find which package in the list satisfies it */
333 for (m
= 0; m
< all
->len
; m
++) {
335 if (dep
->state_status
!=
341 opkg_recurse_pkgs_in_order
345 /* Stop the outer loop */
349 /* break from the inner loop */
358 /* When all recursions from this node down, are over, and all
359 dependencies have been added in proper order in the ordered array, add
360 also the package pkg to ordered array */
361 pkg_vec_insert(ordered
, pkg
);
367 static int opkg_configure_packages(char *pkg_name
)
369 pkg_vec_t
*all
, *ordered
, *visited
;
375 opkg_msg(INFO
, "Configuring unpacked packages.\n");
377 all
= pkg_vec_alloc();
379 pkg_hash_fetch_available(all
);
381 /* Reorder pkgs in order to be configured according to the Depends: tag
383 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
384 ordered
= pkg_vec_alloc();
385 visited
= pkg_vec_alloc();
386 for (i
= 0; i
< all
->len
; i
++) {
388 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
391 ic
= opkg_prep_intercepts();
397 for (i
= 0; i
< ordered
->len
; i
++) {
398 pkg
= ordered
->pkgs
[i
];
400 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
403 if (pkg
->state_status
== SS_UNPACKED
) {
404 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
405 r
= opkg_configure(pkg
);
407 pkg
->state_status
= SS_INSTALLED
;
408 pkg
->parent
->state_status
= SS_INSTALLED
;
409 pkg
->state_flag
&= ~SF_PREFER
;
410 opkg_state_changed
++;
417 if (opkg_finalize_intercepts(ic
))
422 pkg_vec_free(ordered
);
423 pkg_vec_free(visited
);
428 static int opkg_remove_cmd(int argc
, char **argv
);
430 static int opkg_install_cmd(int argc
, char **argv
)
436 signal(SIGINT
, sigint_handler
);
439 * Now scan through package names and install
441 for (i
= 0; i
< argc
; i
++) {
444 opkg_msg(DEBUG2
, "%s\n", arg
);
445 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
449 pkg_hash_load_package_details();
450 pkg_hash_load_status_files();
452 if (conf
->force_reinstall
) {
453 int saved_force_depends
= conf
->force_depends
;
454 conf
->force_depends
= 1;
455 (void)opkg_remove_cmd(argc
, argv
);
456 conf
->force_depends
= saved_force_depends
;
457 conf
->force_reinstall
= 0;
460 pkg_info_preinstall_check();
462 for (i
= 0; i
< argc
; i
++) {
464 if (opkg_install_by_name(arg
)) {
465 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
470 if (opkg_configure_packages(NULL
))
473 write_status_files_if_changed();
478 static int opkg_upgrade_cmd(int argc
, char **argv
)
484 signal(SIGINT
, sigint_handler
);
487 for (i
= 0; i
< argc
; i
++) {
490 if (opkg_prepare_url_for_install(arg
, &arg
))
493 pkg_info_preinstall_check();
495 for (i
= 0; i
< argc
; i
++) {
497 if (conf
->restrict_to_default_dest
) {
499 pkg_hash_fetch_installed_by_name_dest(argv
505 "Package %s not installed in %s.\n",
507 conf
->default_dest
->name
);
511 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
514 if (opkg_upgrade_pkg(pkg
))
517 if (opkg_install_by_name(arg
))
523 if (opkg_configure_packages(NULL
))
526 write_status_files_if_changed();
531 static int opkg_download_cmd(int argc
, char **argv
)
537 pkg_info_preinstall_check();
538 for (i
= 0; i
< argc
; i
++) {
541 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
543 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
547 if (opkg_download_pkg(pkg
, "."))
551 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
553 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
554 pkg
->name
, pkg_get_string(pkg
, PKG_LOCAL_FILENAME
));
561 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
564 pkg_vec_t
*available
;
566 char *pkg_name
= NULL
;
572 available
= pkg_vec_alloc();
573 pkg_hash_fetch_available(available
);
574 pkg_vec_sort(available
, pkg_compare_names
);
575 for (i
= 0; i
< available
->len
; i
++) {
576 pkg
= available
->pkgs
[i
];
577 description
= use_desc
? pkg_get_string(pkg
, PKG_DESCRIPTION
) : NULL
;
578 /* if we have package name or pattern and pkg does not match, then skip it */
579 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
) &&
580 (!use_desc
|| !description
581 || fnmatch(pkg_name
, description
, conf
->nocase
)))
585 pkg_vec_free(available
);
590 static int opkg_list_cmd(int argc
, char **argv
)
592 return opkg_list_find_cmd(argc
, argv
, 0);
595 static int opkg_find_cmd(int argc
, char **argv
)
597 return opkg_list_find_cmd(argc
, argv
, 1);
600 static int opkg_list_installed_cmd(int argc
, char **argv
)
603 pkg_vec_t
*available
;
605 char *pkg_name
= NULL
;
610 available
= pkg_vec_alloc();
611 pkg_hash_fetch_all_installed(available
);
612 pkg_vec_sort(available
, pkg_compare_names
);
613 for (i
= 0; i
< available
->len
; i
++) {
614 pkg
= available
->pkgs
[i
];
615 /* if we have package name or pattern and pkg does not match, then skip it */
616 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
621 pkg_vec_free(available
);
626 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
629 pkg_vec_t
*available
;
631 char *pkg_name
= NULL
;
632 conffile_list_elt_t
*iter
;
639 available
= pkg_vec_alloc();
640 pkg_hash_fetch_all_installed(available
);
641 pkg_vec_sort(available
, pkg_compare_names
);
642 for (i
= 0; i
< available
->len
; i
++) {
643 pkg
= available
->pkgs
[i
];
644 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
645 /* if we have package name or pattern and pkg does not match, then skip it */
646 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
648 if (!cl
|| nv_pair_list_empty(cl
))
650 for (iter
= nv_pair_list_first(cl
); iter
;
651 iter
= nv_pair_list_next(cl
, iter
)) {
652 cf
= (conffile_t
*) iter
->data
;
653 if (cf
->name
&& cf
->value
654 && conffile_has_been_modified(cf
))
655 printf("%s\n", cf
->name
);
658 pkg_vec_free(available
);
662 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
664 struct active_list
*head
= prepare_upgrade_list();
665 struct active_list
*node
= NULL
;
666 pkg_t
*_old_pkg
, *_new_pkg
;
668 for (node
= active_list_next(head
, head
); node
;
669 node
= active_list_next(head
, node
)) {
670 _old_pkg
= node
->pkg
;
672 pkg_hash_fetch_best_installation_candidate_by_name
674 if (_new_pkg
== NULL
)
676 old_v
= pkg_version_str_alloc(_old_pkg
);
677 new_v
= pkg_version_str_alloc(_new_pkg
);
678 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
682 active_list_head_delete(head
);
686 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
689 pkg_vec_t
*available
;
691 char *pkg_name
= NULL
;
698 available
= pkg_vec_alloc();
700 pkg_hash_fetch_all_installed(available
);
702 pkg_hash_fetch_available(available
);
704 for (i
= 0; i
< available
->len
; i
++) {
705 pkg
= available
->pkgs
[i
];
706 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
710 pkg_formatted_info(stdout
, pkg
);
712 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
714 if (conf
->verbosity
>= NOTICE
&& cl
) {
715 conffile_list_elt_t
*iter
;
716 for (iter
= nv_pair_list_first(cl
); iter
;
717 iter
= nv_pair_list_next(cl
, iter
)) {
718 conffile_t
*cf
= (conffile_t
*) iter
->data
;
719 int modified
= conffile_has_been_modified(cf
);
722 "conffile=%s md5sum=%s modified=%d.\n",
723 cf
->name
, cf
->value
, modified
);
727 pkg_vec_free(available
);
732 static int opkg_info_cmd(int argc
, char **argv
)
734 return opkg_info_status_cmd(argc
, argv
, 0);
737 static int opkg_status_cmd(int argc
, char **argv
)
739 return opkg_info_status_cmd(argc
, argv
, 1);
742 static int opkg_configure_cmd(int argc
, char **argv
)
745 char *pkg_name
= NULL
;
750 err
= opkg_configure_packages(pkg_name
);
752 write_status_files_if_changed();
757 static int opkg_remove_cmd(int argc
, char **argv
)
759 int i
, a
, done
, err
= 0;
761 pkg_t
*pkg_to_remove
;
762 pkg_vec_t
*available
;
766 signal(SIGINT
, sigint_handler
);
768 pkg_info_preinstall_check();
770 available
= pkg_vec_alloc();
771 pkg_hash_fetch_all_installed(available
);
773 for (i
= 0; i
< argc
; i
++) {
774 for (a
= 0; a
< available
->len
; a
++) {
775 pkg
= available
->pkgs
[a
];
776 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
779 if (conf
->restrict_to_default_dest
) {
781 pkg_hash_fetch_installed_by_name_dest(pkg
->
787 pkg_hash_fetch_installed_by_name(pkg
->name
);
790 if (pkg_to_remove
== NULL
) {
792 "Package %s is not installed.\n",
796 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
797 opkg_msg(ERROR
, "Package %s not installed.\n",
802 if (opkg_remove_pkg(pkg_to_remove
, 0))
809 pkg_vec_free(available
);
812 opkg_msg(NOTICE
, "No packages removed.\n");
814 write_status_files_if_changed();
818 static int opkg_flag_cmd(int argc
, char **argv
)
822 const char *flags
= argv
[0];
824 signal(SIGINT
, sigint_handler
);
826 for (i
= 1; i
< argc
; i
++) {
827 if (conf
->restrict_to_default_dest
) {
828 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
832 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
836 opkg_msg(ERROR
, "Package %s is not installed.\n",
840 if ((strcmp(flags
, "hold") == 0)
841 || (strcmp(flags
, "noprune") == 0)
842 || (strcmp(flags
, "user") == 0)
843 || (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)
852 || (strcmp(flags
, "unpacked") == 0)) {
853 pkg
->state_status
= pkg_state_status_from_str(flags
);
856 opkg_state_changed
++;
857 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
861 write_status_files_if_changed();
865 static int 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
);
886 ("Package %s (%s) is installed on %s and has the following files:\n",
887 pkg
->name
, pkg_version
, pkg
->dest
->name
);
889 for (iter
= str_list_first(files
); iter
;
890 iter
= str_list_next(files
, iter
))
891 printf("%s\n", (char *)iter
->data
);
894 pkg_free_installed_files(pkg
);
899 static int 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 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
924 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
925 if (cdep
->type
!= DEPEND
)
928 str
= pkg_depend_str(pkg
, k
);
929 opkg_msg(NOTICE
, "\t%s\n", str
);
936 pkg_vec_free(available_pkgs
);
940 static int pkg_mark_provides(pkg_t
* pkg
)
942 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
944 pkg
->parent
->state_flag
|= SF_MARKED
;
946 while (provider
&& *provider
) {
947 (*provider
)->state_flag
|= SF_MARKED
;
954 enum what_field_type
{
964 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
965 int argc
, char **argv
)
967 depend_t
*possibility
;
968 compound_depend_t
*cdep
, *deps
;
969 pkg_vec_t
*available_pkgs
;
973 const char *rel_str
= NULL
;
976 switch (what_field_type
) {
978 rel_str
= "depends on";
981 rel_str
= "conflicts with";
984 rel_str
= "suggests";
987 rel_str
= "recommends";
993 available_pkgs
= pkg_vec_alloc();
996 pkg_hash_fetch_available(available_pkgs
);
998 pkg_hash_fetch_all_installed(available_pkgs
);
1000 /* mark the root set */
1001 pkg_vec_clear_marks(available_pkgs
);
1002 opkg_msg(NOTICE
, "Root set:\n");
1003 for (i
= 0; i
< argc
; i
++)
1004 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1006 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1007 pkg
= available_pkgs
->pkgs
[i
];
1008 if (pkg
->state_flag
& SF_MARKED
) {
1009 /* mark the parent (abstract) package */
1010 pkg_mark_provides(pkg
);
1011 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1015 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1019 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1021 pkg
= available_pkgs
->pkgs
[j
];
1023 count = ((what_field_type == CONFLICTS)
1024 ? pkg->conflicts_count
1025 : pkg->pre_depends_count +
1026 pkg->depends_count +
1027 pkg->recommends_count + pkg->suggests_count);
1030 /* skip this package if it is already marked */
1031 if (pkg
->parent
->state_flag
& SF_MARKED
)
1034 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1036 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1037 if (what_field_type
!= cdep
->type
)
1040 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1041 possibility
= cdep
->possibilities
[l
];
1043 if ((possibility
->pkg
->state_flag
1048 /* mark the depending package so we
1049 * won't visit it again */
1050 pkg
->state_flag
|= SF_MARKED
;
1051 pkg_mark_provides(pkg
);
1054 ver
= pkg_version_str_alloc(pkg
);
1055 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1059 possibility
->pkg
->name
);
1061 if (possibility
->version
) {
1062 opkg_msg(NOTICE
, " (%s%s)",
1066 possibility
->version
);
1068 if (!pkg_dependence_satisfiable
1072 opkg_message(NOTICE
, "\n");
1079 } while (changed
&& recursive
);
1081 pkg_vec_free(available_pkgs
);
1086 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1088 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1091 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1093 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1096 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1098 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1101 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1103 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1106 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1108 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1112 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1115 abstract_pkg_t
*apkg
, **abpkgs
;
1118 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1119 const char *rel_str
=
1120 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1123 pkg_info_preinstall_check();
1125 if (conf
->query_all
)
1126 pkg_hash_fetch_available(available_pkgs
);
1128 pkg_hash_fetch_all_installed(available_pkgs
);
1129 for (i
= 0; i
< argc
; i
++) {
1130 const char *target
= argv
[i
];
1133 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1134 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1135 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1136 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1138 while (abpkgs
&& *abpkgs
) {
1141 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1144 opkg_msg(NOTICE
, " %s", pkg
->name
);
1146 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1147 : strcmp(target
, apkg
->name
)))
1148 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1150 opkg_message(NOTICE
, "\n");
1154 pkg_vec_free(available_pkgs
);
1159 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1161 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1164 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1166 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1169 static int opkg_search_cmd(int argc
, char **argv
)
1173 pkg_vec_t
*installed
;
1175 str_list_t
*installed_files
;
1176 str_list_elt_t
*iter
;
1177 char *installed_file
;
1183 installed
= pkg_vec_alloc();
1184 pkg_hash_fetch_all_installed(installed
);
1185 pkg_vec_sort(installed
, pkg_compare_names
);
1187 for (i
= 0; i
< installed
->len
; i
++) {
1188 pkg
= installed
->pkgs
[i
];
1190 installed_files
= pkg_get_installed_files(pkg
);
1192 for (iter
= str_list_first(installed_files
); iter
;
1193 iter
= str_list_next(installed_files
, iter
)) {
1194 installed_file
= (char *)iter
->data
;
1195 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1199 pkg_free_installed_files(pkg
);
1202 pkg_vec_free(installed
);
1207 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1210 /* this is a bit gross */
1212 parse_version(&p1
, argv
[0]);
1213 parse_version(&p2
, argv
[2]);
1214 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1217 "opkg compare_versions <v1> <op> <v2>\n"
1218 "<op> is one of <= >= << >> =\n");
1223 static int 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
);
1234 /* XXX: CLEANUP: The usage strings should be incorporated into this
1235 array for easier maintenance */
1236 static opkg_cmd_t cmds
[] = {
1237 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1238 PFM_DESCRIPTION
| PFM_SOURCE
},
1239 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1240 PFM_DESCRIPTION
| PFM_SOURCE
},
1241 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1242 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1244 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1246 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1248 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1250 {"list_changed_conffiles", 0,
1251 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1252 {"list-changed-conffiles", 0,
1253 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1254 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1255 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1256 PFM_DESCRIPTION
| PFM_SOURCE
},
1257 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1258 PFM_DESCRIPTION
| PFM_SOURCE
},
1259 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1260 PFM_DESCRIPTION
| PFM_SOURCE
},
1261 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1262 PFM_DESCRIPTION
| PFM_SOURCE
},
1263 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1264 PFM_DESCRIPTION
| PFM_SOURCE
},
1265 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1266 PFM_DESCRIPTION
| PFM_SOURCE
},
1267 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1268 PFM_DESCRIPTION
| PFM_SOURCE
},
1269 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1270 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1271 PFM_DESCRIPTION
| PFM_SOURCE
},
1272 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
,
1273 PFM_DESCRIPTION
| PFM_SOURCE
},
1274 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
,
1275 PFM_DESCRIPTION
| PFM_SOURCE
},
1276 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1277 PFM_DESCRIPTION
| PFM_SOURCE
},
1278 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1279 PFM_DESCRIPTION
| PFM_SOURCE
},
1280 {"print-installation-architecture", 0,
1281 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1282 PFM_DESCRIPTION
| PFM_SOURCE
},
1283 {"print_installation_architecture", 0,
1284 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1285 PFM_DESCRIPTION
| PFM_SOURCE
},
1286 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1287 PFM_DESCRIPTION
| PFM_SOURCE
},
1288 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1289 PFM_DESCRIPTION
| PFM_SOURCE
},
1290 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1291 PFM_DESCRIPTION
| PFM_SOURCE
},
1292 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1293 PFM_DESCRIPTION
| PFM_SOURCE
},
1294 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1295 PFM_DESCRIPTION
| PFM_SOURCE
},
1296 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1297 PFM_DESCRIPTION
| PFM_SOURCE
},
1298 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1299 PFM_DESCRIPTION
| PFM_SOURCE
},
1300 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1301 PFM_DESCRIPTION
| PFM_SOURCE
},
1304 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1308 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1310 for (i
= 0; i
< num_cmds
; i
++) {
1312 if (strcmp(name
, cmd
->name
) == 0)
1319 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1321 return (cmd
->fun
) (argc
, argv
);