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
, 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
, 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"));
218 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
,
219 ctx
->oldpath
? ctx
->oldpath
: PATH_SPEC
);
221 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
224 if (mkdtemp(ctx
->statedir
) == NULL
) {
225 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
236 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
237 setenv("PATH", newpath
, 1);
243 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
249 setenv("PATH", ctx
->oldpath
, 1);
256 dir
= opendir(ctx
->statedir
);
259 while (de
= readdir(dir
), de
!= NULL
) {
262 if (de
->d_name
[0] == '.')
265 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
267 if (access(path
, X_OK
) == 0) {
268 const char *argv
[] = { "/bin/sh", "-c", path
, NULL
};
275 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
284 /* For package pkg do the following: If it is already visited, return. If not,
285 add it in visited list and recurse to its deps. Finally, add it to ordered
287 pkg_vec all contains all available packages in repos.
288 pkg_vec visited contains packages already visited by this function, and is
289 used to end recursion and avoid an infinite loop on graph cycles.
290 pkg_vec ordered will finally contain the ordered set of packages.
293 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
294 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
298 compound_depend_t
*compound_depend
;
299 depend_t
**possible_satisfiers
;
300 abstract_pkg_t
*abpkg
;
301 abstract_pkg_t
**dependents
;
303 /* If it's just an available package, that is, not installed and not even
305 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
306 would do here. However, if there is an intermediate node (pkg) that is
307 configured and installed between two unpacked packages, the latter
308 won't be properly reordered, unless all installed/unpacked pkgs are
310 if (pkg
->state_status
== SS_NOT_INSTALLED
)
313 /* If the package has already been visited (by this function), skip it */
314 for (j
= 0; j
< visited
->len
; j
++)
315 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
316 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
321 pkg_vec_insert(visited
, pkg
);
323 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
325 /* Iterate over all the dependencies of pkg. For each one, find a package
326 that is either installed or unpacked and satisfies this dependency.
327 (there should only be one such package per dependency installed or
328 unpacked). Then recurse to the dependency package */
329 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
330 possible_satisfiers
= compound_depend
->possibilities
;
331 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
332 abpkg
= possible_satisfiers
[k
]->pkg
;
333 dependents
= abpkg
->provided_by
->pkgs
;
335 if (dependents
!= NULL
)
336 while (l
< abpkg
->provided_by
->len
337 && dependents
[l
] != NULL
) {
339 "Descending on pkg %s.\n",
340 dependents
[l
]->name
);
342 /* find whether dependent l is installed or unpacked,
343 * and then find which package in the list satisfies it */
344 for (m
= 0; m
< all
->len
; m
++) {
346 if (dep
->state_status
!=
352 opkg_recurse_pkgs_in_order
356 /* Stop the outer loop */
360 /* break from the inner loop */
369 /* When all recursions from this node down, are over, and all
370 dependencies have been added in proper order in the ordered array, add
371 also the package pkg to ordered array */
372 pkg_vec_insert(ordered
, pkg
);
378 static int opkg_configure_packages(char *pkg_name
)
380 pkg_vec_t
*all
, *ordered
, *visited
;
386 opkg_msg(INFO
, "Configuring unpacked packages.\n");
388 all
= pkg_vec_alloc();
390 pkg_hash_fetch_available(all
);
392 /* Reorder pkgs in order to be configured according to the Depends: tag
394 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
395 ordered
= pkg_vec_alloc();
396 visited
= pkg_vec_alloc();
397 for (i
= 0; i
< all
->len
; i
++) {
399 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
402 ic
= opkg_prep_intercepts();
408 for (i
= 0; i
< ordered
->len
; i
++) {
409 pkg
= ordered
->pkgs
[i
];
411 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
414 if (pkg
->state_status
== SS_UNPACKED
) {
415 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
416 r
= opkg_configure(pkg
);
418 pkg
->state_status
= SS_INSTALLED
;
419 pkg
->parent
->state_status
= SS_INSTALLED
;
420 pkg
->state_flag
&= ~SF_PREFER
;
421 opkg_state_changed
++;
428 if (opkg_finalize_intercepts(ic
))
433 pkg_vec_free(ordered
);
434 pkg_vec_free(visited
);
439 static int opkg_remove_cmd(int argc
, char **argv
);
441 static int opkg_install_cmd(int argc
, char **argv
)
447 signal(SIGINT
, sigint_handler
);
450 * Now scan through package names and install
452 for (i
= 0; i
< argc
; i
++) {
455 opkg_msg(DEBUG2
, "%s\n", arg
);
456 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
460 pkg_hash_load_package_details();
461 pkg_hash_load_status_files();
463 if (conf
->force_reinstall
) {
464 int saved_force_depends
= conf
->force_depends
;
465 conf
->force_depends
= 1;
466 (void)opkg_remove_cmd(argc
, argv
);
467 conf
->force_depends
= saved_force_depends
;
468 conf
->force_reinstall
= 0;
471 pkg_info_preinstall_check();
473 for (i
= 0; i
< argc
; i
++) {
475 if (opkg_install_by_name(arg
)) {
476 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
481 if (opkg_configure_packages(NULL
))
484 write_status_files_if_changed();
489 static int opkg_upgrade_cmd(int argc
, char **argv
)
495 signal(SIGINT
, sigint_handler
);
498 for (i
= 0; i
< argc
; i
++) {
501 if (opkg_prepare_url_for_install(arg
, &arg
))
504 pkg_info_preinstall_check();
506 for (i
= 0; i
< argc
; i
++) {
508 if (conf
->restrict_to_default_dest
) {
510 pkg_hash_fetch_installed_by_name_dest(argv
516 "Package %s not installed in %s.\n",
518 conf
->default_dest
->name
);
522 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
525 if (opkg_upgrade_pkg(pkg
))
528 if (opkg_install_by_name(arg
))
534 if (opkg_configure_packages(NULL
))
537 write_status_files_if_changed();
542 static int 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_get_string(pkg
, PKG_LOCAL_FILENAME
));
572 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
575 pkg_vec_t
*available
;
577 char *pkg_name
= NULL
;
583 available
= pkg_vec_alloc();
584 pkg_hash_fetch_available(available
);
585 pkg_vec_sort(available
, pkg_compare_names
);
586 for (i
= 0; i
< available
->len
; i
++) {
587 pkg
= available
->pkgs
[i
];
588 description
= use_desc
? pkg_get_string(pkg
, PKG_DESCRIPTION
) : NULL
;
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
|| !description
592 || fnmatch(pkg_name
, description
, conf
->nocase
)))
596 pkg_vec_free(available
);
601 static int opkg_list_cmd(int argc
, char **argv
)
603 return opkg_list_find_cmd(argc
, argv
, 0);
606 static int opkg_find_cmd(int argc
, char **argv
)
608 return opkg_list_find_cmd(argc
, argv
, 1);
611 static int opkg_list_installed_cmd(int argc
, char **argv
)
614 pkg_vec_t
*available
;
616 char *pkg_name
= NULL
;
621 available
= pkg_vec_alloc();
622 pkg_hash_fetch_all_installed(available
);
623 pkg_vec_sort(available
, pkg_compare_names
);
624 for (i
= 0; i
< available
->len
; i
++) {
625 pkg
= available
->pkgs
[i
];
626 /* if we have package name or pattern and pkg does not match, then skip it */
627 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
632 pkg_vec_free(available
);
637 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
640 pkg_vec_t
*available
;
642 char *pkg_name
= NULL
;
643 conffile_list_elt_t
*iter
;
650 available
= pkg_vec_alloc();
651 pkg_hash_fetch_all_installed(available
);
652 pkg_vec_sort(available
, pkg_compare_names
);
653 for (i
= 0; i
< available
->len
; i
++) {
654 pkg
= available
->pkgs
[i
];
655 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
656 /* if we have package name or pattern and pkg does not match, then skip it */
657 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
659 if (!cl
|| nv_pair_list_empty(cl
))
661 for (iter
= nv_pair_list_first(cl
); iter
;
662 iter
= nv_pair_list_next(cl
, iter
)) {
663 cf
= (conffile_t
*) iter
->data
;
664 if (cf
->name
&& cf
->value
665 && conffile_has_been_modified(cf
))
666 printf("%s\n", cf
->name
);
669 pkg_vec_free(available
);
673 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
675 struct active_list
*head
= prepare_upgrade_list();
676 struct active_list
*node
= NULL
;
677 pkg_t
*_old_pkg
, *_new_pkg
;
679 for (node
= active_list_next(head
, head
); node
;
680 node
= active_list_next(head
, node
)) {
681 _old_pkg
= node
->pkg
;
683 pkg_hash_fetch_best_installation_candidate_by_name
685 if (_new_pkg
== NULL
)
687 old_v
= pkg_version_str_alloc(_old_pkg
);
688 new_v
= pkg_version_str_alloc(_new_pkg
);
689 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
693 active_list_head_delete(head
);
697 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
700 pkg_vec_t
*available
;
702 char *pkg_name
= NULL
;
709 available
= pkg_vec_alloc();
711 pkg_hash_fetch_all_installed(available
);
713 pkg_hash_fetch_available(available
);
715 for (i
= 0; i
< available
->len
; i
++) {
716 pkg
= available
->pkgs
[i
];
717 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
721 pkg_formatted_info(stdout
, pkg
);
723 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
725 if (conf
->verbosity
>= NOTICE
&& cl
) {
726 conffile_list_elt_t
*iter
;
727 for (iter
= nv_pair_list_first(cl
); iter
;
728 iter
= nv_pair_list_next(cl
, iter
)) {
729 conffile_t
*cf
= (conffile_t
*) iter
->data
;
730 int modified
= conffile_has_been_modified(cf
);
733 "conffile=%s md5sum=%s modified=%d.\n",
734 cf
->name
, cf
->value
, modified
);
738 pkg_vec_free(available
);
743 static int opkg_info_cmd(int argc
, char **argv
)
745 return opkg_info_status_cmd(argc
, argv
, 0);
748 static int opkg_status_cmd(int argc
, char **argv
)
750 return opkg_info_status_cmd(argc
, argv
, 1);
753 static int opkg_configure_cmd(int argc
, char **argv
)
756 char *pkg_name
= NULL
;
761 err
= opkg_configure_packages(pkg_name
);
763 write_status_files_if_changed();
768 static int opkg_remove_cmd(int argc
, char **argv
)
770 int i
, a
, done
, err
= 0;
772 pkg_t
*pkg_to_remove
;
773 pkg_vec_t
*available
;
777 signal(SIGINT
, sigint_handler
);
779 pkg_info_preinstall_check();
781 available
= pkg_vec_alloc();
782 pkg_hash_fetch_all_installed(available
);
784 for (i
= 0; i
< argc
; i
++) {
785 for (a
= 0; a
< available
->len
; a
++) {
786 pkg
= available
->pkgs
[a
];
787 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
790 if (conf
->restrict_to_default_dest
) {
792 pkg_hash_fetch_installed_by_name_dest(pkg
->
798 pkg_hash_fetch_installed_by_name(pkg
->name
);
801 if (pkg_to_remove
== NULL
) {
803 "Package %s is not installed.\n",
807 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
808 opkg_msg(ERROR
, "Package %s not installed.\n",
813 if (opkg_remove_pkg(pkg_to_remove
, 0))
820 pkg_vec_free(available
);
823 opkg_msg(NOTICE
, "No packages removed.\n");
825 write_status_files_if_changed();
829 static int opkg_flag_cmd(int argc
, char **argv
)
833 const char *flags
= argv
[0];
835 signal(SIGINT
, sigint_handler
);
837 for (i
= 1; i
< argc
; i
++) {
838 if (conf
->restrict_to_default_dest
) {
839 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
843 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
847 opkg_msg(ERROR
, "Package %s is not installed.\n",
851 if ((strcmp(flags
, "hold") == 0)
852 || (strcmp(flags
, "noprune") == 0)
853 || (strcmp(flags
, "user") == 0)
854 || (strcmp(flags
, "ok") == 0)) {
855 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
859 * Useful if a package is installed in an offline_root, and
860 * should be configured by opkg-cl configure at a later date.
862 if ((strcmp(flags
, "installed") == 0)
863 || (strcmp(flags
, "unpacked") == 0)) {
864 pkg
->state_status
= pkg_state_status_from_str(flags
);
867 opkg_state_changed
++;
868 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
872 write_status_files_if_changed();
876 static int opkg_files_cmd(int argc
, char **argv
)
880 str_list_elt_t
*iter
;
887 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
889 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
893 files
= pkg_get_installed_files(pkg
);
894 pkg_version
= pkg_version_str_alloc(pkg
);
897 ("Package %s (%s) is installed on %s and has the following files:\n",
898 pkg
->name
, pkg_version
, pkg
->dest
->name
);
900 for (iter
= str_list_first(files
); iter
;
901 iter
= str_list_next(files
, iter
))
902 printf("%s\n", (char *)iter
->data
);
905 pkg_free_installed_files(pkg
);
910 static int opkg_depends_cmd(int argc
, char **argv
)
913 pkg_vec_t
*available_pkgs
;
914 compound_depend_t
*cdep
;
918 pkg_info_preinstall_check();
920 available_pkgs
= pkg_vec_alloc();
922 pkg_hash_fetch_available(available_pkgs
);
924 pkg_hash_fetch_all_installed(available_pkgs
);
926 for (i
= 0; i
< argc
; i
++) {
927 for (j
= 0; j
< available_pkgs
->len
; j
++) {
928 pkg
= available_pkgs
->pkgs
[j
];
930 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
933 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
935 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
936 if (cdep
->type
!= DEPEND
)
939 str
= pkg_depend_str(pkg
, k
);
940 opkg_msg(NOTICE
, "\t%s\n", str
);
947 pkg_vec_free(available_pkgs
);
951 static int pkg_mark_provides(pkg_t
* pkg
)
953 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
955 pkg
->parent
->state_flag
|= SF_MARKED
;
957 while (provider
&& *provider
) {
958 (*provider
)->state_flag
|= SF_MARKED
;
965 enum what_field_type
{
975 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
976 int argc
, char **argv
)
978 depend_t
*possibility
;
979 compound_depend_t
*cdep
, *deps
;
980 pkg_vec_t
*available_pkgs
;
984 const char *rel_str
= NULL
;
987 switch (what_field_type
) {
989 rel_str
= "depends on";
992 rel_str
= "conflicts with";
995 rel_str
= "suggests";
998 rel_str
= "recommends";
1004 available_pkgs
= pkg_vec_alloc();
1006 if (conf
->query_all
)
1007 pkg_hash_fetch_available(available_pkgs
);
1009 pkg_hash_fetch_all_installed(available_pkgs
);
1011 /* mark the root set */
1012 pkg_vec_clear_marks(available_pkgs
);
1013 opkg_msg(NOTICE
, "Root set:\n");
1014 for (i
= 0; i
< argc
; i
++)
1015 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1017 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1018 pkg
= available_pkgs
->pkgs
[i
];
1019 if (pkg
->state_flag
& SF_MARKED
) {
1020 /* mark the parent (abstract) package */
1021 pkg_mark_provides(pkg
);
1022 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1026 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1030 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1032 pkg
= available_pkgs
->pkgs
[j
];
1034 count = ((what_field_type == CONFLICTS)
1035 ? pkg->conflicts_count
1036 : pkg->pre_depends_count +
1037 pkg->depends_count +
1038 pkg->recommends_count + pkg->suggests_count);
1041 /* skip this package if it is already marked */
1042 if (pkg
->parent
->state_flag
& SF_MARKED
)
1045 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1047 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1048 if (what_field_type
!= cdep
->type
)
1051 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1052 possibility
= cdep
->possibilities
[l
];
1054 if ((possibility
->pkg
->state_flag
1059 /* mark the depending package so we
1060 * won't visit it again */
1061 pkg
->state_flag
|= SF_MARKED
;
1062 pkg_mark_provides(pkg
);
1065 ver
= pkg_version_str_alloc(pkg
);
1066 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1070 possibility
->pkg
->name
);
1072 if (possibility
->version
) {
1073 opkg_msg(NOTICE
, " (%s%s)",
1077 possibility
->version
);
1079 if (!pkg_dependence_satisfiable
1083 opkg_message(NOTICE
, "\n");
1090 } while (changed
&& recursive
);
1092 pkg_vec_free(available_pkgs
);
1097 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1099 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1102 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1104 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1107 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1109 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1112 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1114 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1117 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1119 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1123 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1126 abstract_pkg_t
*apkg
, **abpkgs
;
1129 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1130 const char *rel_str
=
1131 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1134 pkg_info_preinstall_check();
1136 if (conf
->query_all
)
1137 pkg_hash_fetch_available(available_pkgs
);
1139 pkg_hash_fetch_all_installed(available_pkgs
);
1140 for (i
= 0; i
< argc
; i
++) {
1141 const char *target
= argv
[i
];
1144 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1145 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1146 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1147 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1149 while (abpkgs
&& *abpkgs
) {
1152 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1155 opkg_msg(NOTICE
, " %s", pkg
->name
);
1157 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1158 : strcmp(target
, apkg
->name
)))
1159 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1161 opkg_message(NOTICE
, "\n");
1165 pkg_vec_free(available_pkgs
);
1170 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1172 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1175 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1177 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1180 static int opkg_search_cmd(int argc
, char **argv
)
1184 pkg_vec_t
*installed
;
1186 str_list_t
*installed_files
;
1187 str_list_elt_t
*iter
;
1188 char *installed_file
;
1194 installed
= pkg_vec_alloc();
1195 pkg_hash_fetch_all_installed(installed
);
1196 pkg_vec_sort(installed
, pkg_compare_names
);
1198 for (i
= 0; i
< installed
->len
; i
++) {
1199 pkg
= installed
->pkgs
[i
];
1201 installed_files
= pkg_get_installed_files(pkg
);
1203 for (iter
= str_list_first(installed_files
); iter
;
1204 iter
= str_list_next(installed_files
, iter
)) {
1205 installed_file
= (char *)iter
->data
;
1206 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1210 pkg_free_installed_files(pkg
);
1213 pkg_vec_free(installed
);
1218 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1221 /* this is a bit gross */
1223 parse_version(&p1
, argv
[0]);
1224 parse_version(&p2
, argv
[2]);
1225 return pkg_version_satisfied(&p1
, &p2
, argv
[1]) ? 0 : 1;
1228 "opkg compare_versions <v1> <op> <v2>\n"
1229 "<op> is one of <= >= << >> =\n");
1234 static int opkg_print_architecture_cmd(int argc
, char **argv
)
1236 nv_pair_list_elt_t
*l
;
1238 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1239 nv_pair_t
*nv
= (nv_pair_t
*) l
->data
;
1240 printf("arch %s %s\n", nv
->name
, nv
->value
);
1245 /* XXX: CLEANUP: The usage strings should be incorporated into this
1246 array for easier maintenance */
1247 static opkg_cmd_t cmds
[] = {
1248 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1249 PFM_DESCRIPTION
| PFM_SOURCE
},
1250 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1251 PFM_DESCRIPTION
| PFM_SOURCE
},
1252 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1253 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1255 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1257 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1259 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1261 {"list_changed_conffiles", 0,
1262 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1263 {"list-changed-conffiles", 0,
1264 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1265 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1266 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1267 PFM_DESCRIPTION
| PFM_SOURCE
},
1268 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1269 PFM_DESCRIPTION
| PFM_SOURCE
},
1270 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1271 PFM_DESCRIPTION
| PFM_SOURCE
},
1272 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1273 PFM_DESCRIPTION
| PFM_SOURCE
},
1274 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1275 PFM_DESCRIPTION
| PFM_SOURCE
},
1276 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1277 PFM_DESCRIPTION
| PFM_SOURCE
},
1278 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1279 PFM_DESCRIPTION
| PFM_SOURCE
},
1280 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1281 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1282 PFM_DESCRIPTION
| PFM_SOURCE
},
1283 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
,
1284 PFM_DESCRIPTION
| PFM_SOURCE
},
1285 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
,
1286 PFM_DESCRIPTION
| PFM_SOURCE
},
1287 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1288 PFM_DESCRIPTION
| PFM_SOURCE
},
1289 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1290 PFM_DESCRIPTION
| PFM_SOURCE
},
1291 {"print-installation-architecture", 0,
1292 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1293 PFM_DESCRIPTION
| PFM_SOURCE
},
1294 {"print_installation_architecture", 0,
1295 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1296 PFM_DESCRIPTION
| PFM_SOURCE
},
1297 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1298 PFM_DESCRIPTION
| PFM_SOURCE
},
1299 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1300 PFM_DESCRIPTION
| PFM_SOURCE
},
1301 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1302 PFM_DESCRIPTION
| PFM_SOURCE
},
1303 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1304 PFM_DESCRIPTION
| PFM_SOURCE
},
1305 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1306 PFM_DESCRIPTION
| PFM_SOURCE
},
1307 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1308 PFM_DESCRIPTION
| PFM_SOURCE
},
1309 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1310 PFM_DESCRIPTION
| PFM_SOURCE
},
1311 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1312 PFM_DESCRIPTION
| PFM_SOURCE
},
1315 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1319 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1321 for (i
= 0; i
< num_cmds
; i
++) {
1323 if (strcmp(name
, cmd
->name
) == 0)
1330 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1332 return (cmd
->fun
) (argc
, argv
);