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 int opkg_cli_argc
= 0;
45 char **opkg_cli_argv
= NULL
;
47 static void print_pkg(pkg_t
* pkg
)
49 char *version
= pkg_version_str_alloc(pkg
);
50 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
52 char *tmp
, *tmpname
= NULL
;
54 if (conf
->strip_abi
&&
55 (abiver
= pkg_get_string(pkg
, PKG_ABIVERSION
)) &&
56 (strlen(pkg
->name
) > strlen(abiver
))) {
57 tmpname
= strdup(pkg
->name
);
58 tmp
= &tmpname
[strlen(tmpname
) - strlen(abiver
)];
59 if (!strncmp(abiver
, tmp
, strlen(abiver
)))
63 printf("%s - %s", tmpname
?tmpname
:pkg
->name
, version
);
69 printf(" - %lu", (unsigned long) pkg_get_int(pkg
, PKG_SIZE
));
71 printf(" - %s", description
);
76 int opkg_state_changed
;
78 static void write_status_files_if_changed(void)
80 if (opkg_state_changed
&& !conf
->noaction
) {
81 opkg_msg(INFO
, "Writing status file.\n");
82 opkg_conf_write_status_files();
83 pkg_write_changed_filelists();
85 opkg_msg(DEBUG
, "Nothing to be done.\n");
89 static void sigint_handler(int sig
)
92 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
93 write_status_files_if_changed();
97 static int opkg_update_cmd(int argc
, char **argv
)
102 int pkglist_dl_error
;
104 pkg_src_list_elt_t
*iter
;
107 sprintf_alloc(&lists_dir
, "%s",
108 conf
->restrict_to_default_dest
? conf
->default_dest
->
109 lists_dir
: conf
->lists_dir
);
111 if (!file_is_dir(lists_dir
)) {
112 if (file_exists(lists_dir
)) {
113 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
118 err
= file_mkdir_hier(lists_dir
, 0755);
127 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
128 if (mkdtemp(tmp
) == NULL
) {
129 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
133 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
;
134 iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
135 char *url
, *list_file_name
;
137 src
= (pkg_src_t
*) iter
->data
;
139 sprintf_alloc(&url
, "%s/%s", src
->value
,
140 src
->gzip
? "Packages.gz" : "Packages");
142 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
143 pkglist_dl_error
= 0;
144 if (opkg_download(url
, list_file_name
, 0)) {
146 pkglist_dl_error
= 1;
148 "*** Failed to download the package list from %s\n\n",
152 "Updated list of available packages in %s\n",
156 #if defined(HAVE_USIGN)
157 if (pkglist_dl_error
== 0 && conf
->check_signature
) {
158 /* download detached signitures to verify the package lists */
159 /* get the url for the sig file */
160 sprintf_alloc(&url
, "%s/%s", src
->value
,
163 /* create temporary file for it */
166 /* Put the signature in the right place */
167 sprintf_alloc(&tmp_file_name
, "%s/%s.sig", lists_dir
,
170 err
= opkg_download(url
, tmp_file_name
, 0);
174 "Signature file download failed.\n");
177 opkg_verify_file(list_file_name
,
181 "Signature check passed.\n");
184 "Signature check failed.\n");
186 if (err
&& !conf
->force_signature
) {
187 /* The signature was wrong so delete it */
189 "Remove wrong Signature file.\n");
190 unlink(tmp_file_name
);
191 unlink(list_file_name
);
193 /* We shouldn't unlink the signature ! */
194 // unlink (tmp_file_name);
201 free(list_file_name
);
210 struct opkg_intercept
{
215 typedef struct opkg_intercept
*opkg_intercept_t
;
217 static opkg_intercept_t
opkg_prep_intercepts(void)
219 opkg_intercept_t ctx
;
222 ctx
= xcalloc(1, sizeof(*ctx
));
223 ctx
->oldpath
= xstrdup(getenv("PATH"));
225 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
,
226 ctx
->oldpath
? ctx
->oldpath
: PATH_SPEC
);
228 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
231 if (mkdtemp(ctx
->statedir
) == NULL
) {
232 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
243 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
244 setenv("PATH", newpath
, 1);
250 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
256 setenv("PATH", ctx
->oldpath
, 1);
263 dir
= opendir(ctx
->statedir
);
266 while (de
= readdir(dir
), de
!= NULL
) {
269 if (de
->d_name
[0] == '.')
272 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
274 if (access(path
, X_OK
) == 0) {
275 const char *argv
[] = { "/bin/sh", "-c", path
, NULL
};
282 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
291 /* For package pkg do the following: If it is already visited, return. If not,
292 add it in visited list and recurse to its deps. Finally, add it to ordered
294 pkg_vec all contains all available packages in repos.
295 pkg_vec visited contains packages already visited by this function, and is
296 used to end recursion and avoid an infinite loop on graph cycles.
297 pkg_vec ordered will finally contain the ordered set of packages.
300 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
301 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
305 compound_depend_t
*compound_depend
;
306 depend_t
**possible_satisfiers
;
307 abstract_pkg_t
*abpkg
;
308 abstract_pkg_t
**dependents
;
310 /* If it's just an available package, that is, not installed and not even
312 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
313 would do here. However, if there is an intermediate node (pkg) that is
314 configured and installed between two unpacked packages, the latter
315 won't be properly reordered, unless all installed/unpacked pkgs are
317 if (pkg
->state_status
== SS_NOT_INSTALLED
)
320 /* If the package has already been visited (by this function), skip it */
321 for (j
= 0; j
< visited
->len
; j
++)
322 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
323 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
328 pkg_vec_insert(visited
, pkg
);
330 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
332 /* Iterate over all the dependencies of pkg. For each one, find a package
333 that is either installed or unpacked and satisfies this dependency.
334 (there should only be one such package per dependency installed or
335 unpacked). Then recurse to the dependency package */
336 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
337 possible_satisfiers
= compound_depend
->possibilities
;
338 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
339 abpkg
= possible_satisfiers
[k
]->pkg
;
340 dependents
= abpkg
->provided_by
->pkgs
;
342 if (dependents
!= NULL
)
343 while (l
< abpkg
->provided_by
->len
344 && dependents
[l
] != NULL
) {
346 "Descending on pkg %s.\n",
347 dependents
[l
]->name
);
349 /* find whether dependent l is installed or unpacked,
350 * and then find which package in the list satisfies it */
351 for (m
= 0; m
< all
->len
; m
++) {
353 if (dep
->state_status
!=
359 opkg_recurse_pkgs_in_order
363 /* Stop the outer loop */
367 /* break from the inner loop */
376 /* When all recursions from this node down, are over, and all
377 dependencies have been added in proper order in the ordered array, add
378 also the package pkg to ordered array */
379 pkg_vec_insert(ordered
, pkg
);
385 static int opkg_configure_packages(char *pkg_name
)
387 pkg_vec_t
*all
, *ordered
, *visited
;
393 opkg_msg(INFO
, "Configuring unpacked packages.\n");
395 all
= pkg_vec_alloc();
397 pkg_hash_fetch_available(all
);
399 /* Reorder pkgs in order to be configured according to the Depends: tag
401 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
402 ordered
= pkg_vec_alloc();
403 visited
= pkg_vec_alloc();
404 for (i
= 0; i
< all
->len
; i
++) {
406 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
409 ic
= opkg_prep_intercepts();
415 for (i
= 0; i
< ordered
->len
; i
++) {
416 pkg
= ordered
->pkgs
[i
];
418 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
421 if (pkg
->state_status
== SS_UNPACKED
) {
422 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
423 r
= opkg_configure(pkg
);
425 pkg
->state_status
= SS_INSTALLED
;
426 pkg
->parent
->state_status
= SS_INSTALLED
;
427 pkg
->state_flag
&= ~SF_PREFER
;
428 opkg_state_changed
++;
435 if (opkg_finalize_intercepts(ic
))
440 pkg_vec_free(ordered
);
441 pkg_vec_free(visited
);
446 static int opkg_remove_cmd(int argc
, char **argv
);
448 static int opkg_install_cmd(int argc
, char **argv
)
454 signal(SIGINT
, sigint_handler
);
457 * Now scan through package names and install
459 for (i
= 0; i
< argc
; i
++) {
462 opkg_msg(DEBUG2
, "%s\n", arg
);
463 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
467 pkg_hash_load_package_details();
468 pkg_hash_load_status_files(NULL
, NULL
);
470 if (conf
->force_reinstall
) {
471 int saved_force_depends
= conf
->force_depends
;
472 conf
->force_depends
= 1;
473 (void)opkg_remove_cmd(argc
, argv
);
474 conf
->force_depends
= saved_force_depends
;
475 conf
->force_reinstall
= 0;
478 pkg_info_preinstall_check();
480 for (i
= 0; i
< argc
; i
++) {
482 if (opkg_install_by_name(arg
)) {
483 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
488 if (opkg_configure_packages(NULL
))
491 write_status_files_if_changed();
496 static int opkg_upgrade_cmd(int argc
, char **argv
)
502 signal(SIGINT
, sigint_handler
);
505 for (i
= 0; i
< argc
; i
++) {
508 if (opkg_prepare_url_for_install(arg
, &arg
))
511 pkg_info_preinstall_check();
513 for (i
= 0; i
< argc
; i
++) {
515 if (conf
->restrict_to_default_dest
) {
517 pkg_hash_fetch_installed_by_name_dest(argv
523 "Package %s not installed in %s.\n",
525 conf
->default_dest
->name
);
529 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
532 if (opkg_upgrade_pkg(pkg
))
535 if (opkg_install_by_name(arg
))
541 if (opkg_configure_packages(NULL
))
544 write_status_files_if_changed();
549 static int opkg_download_cmd(int argc
, char **argv
)
555 pkg_info_preinstall_check();
556 for (i
= 0; i
< argc
; i
++) {
559 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
561 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
565 if (opkg_download_pkg(pkg
, "."))
569 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
571 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
572 pkg
->name
, pkg_get_string(pkg
, PKG_LOCAL_FILENAME
));
579 struct opkg_list_find_cmd_item
{
586 struct opkg_list_find_cmd_args
{
590 struct opkg_list_find_cmd_item
**items
;
594 static void opkg_list_find_cmd_cb(pkg_t
*pkg
, void *priv
)
596 struct opkg_list_find_cmd_args
*args
= priv
;
597 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
598 char *version
= pkg_version_str_alloc(pkg
);
599 struct opkg_list_find_cmd_item
*item
;
600 char *nameptr
, *versionptr
, *descriptionptr
, *tmp
;
604 /* if we have package name or pattern and pkg does not match, then skip it */
605 if (args
->pkg_name
&& fnmatch(args
->pkg_name
, pkg
->name
, conf
->nocase
) &&
606 (!args
->use_desc
|| !description
607 || fnmatch(args
->pkg_name
, description
, conf
->nocase
)))
610 if (args
->set_status
) {
611 for (i
= 0; i
< args
->n_items
; i
++) {
612 if (!strcmp(args
->items
[i
]->name
, pkg
->name
)) {
620 item
= calloc_a(sizeof(*item
),
621 &nameptr
, strlen(pkg
->name
) + 1,
622 &versionptr
, strlen(version
) + 1,
623 &descriptionptr
, description
? strlen(description
) + 1 : 0);
625 item
->name
= strcpy(nameptr
, pkg
->name
);
627 if (conf
->strip_abi
&&
628 (abiver
= pkg_get_string(pkg
, PKG_ABIVERSION
)) &&
629 (strlen(item
->name
) > strlen(abiver
))) {
630 tmp
= &item
->name
[strlen(item
->name
) - strlen(abiver
)];
631 if (!strncmp(abiver
, tmp
, strlen(abiver
)))
635 item
->size
= pkg_get_int(pkg
, PKG_SIZE
);
636 item
->version
= strcpy(versionptr
, version
);
637 item
->description
= description
? strcpy(descriptionptr
, description
) : NULL
;
639 args
->items
= xrealloc(args
->items
, sizeof(item
) * (args
->n_items
+ 1));
640 args
->items
[args
->n_items
++] = item
;
649 static int opkg_list_find_cmd_sort(const void *a
, const void *b
)
651 const struct opkg_list_find_cmd_item
*pkg_a
= *(const struct opkg_list_find_cmd_item
**)a
;
652 const struct opkg_list_find_cmd_item
*pkg_b
= *(const struct opkg_list_find_cmd_item
**)b
;
653 return strcmp(pkg_a
->name
, pkg_b
->name
);
656 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
659 struct opkg_list_find_cmd_args args
= {
660 .use_desc
= use_desc
,
661 .pkg_name
= (argc
> 0) ? argv
[0] : NULL
665 pkg_hash_load_feeds(SF_NEED_DETAIL
, opkg_list_find_cmd_cb
, &args
);
668 pkg_hash_load_status_files(opkg_list_find_cmd_cb
, &args
);
670 if (args
.n_items
> 1)
671 qsort(args
.items
, args
.n_items
, sizeof(args
.items
[0]),
672 opkg_list_find_cmd_sort
);
674 for (i
= 0; i
< args
.n_items
; i
++) {
677 args
.items
[i
]->version
);
680 printf(" - %lu", (unsigned long) args
.items
[i
]->size
);
682 if (args
.items
[i
]->description
)
683 printf(" - %s", args
.items
[i
]->description
);
695 static int opkg_list_cmd(int argc
, char **argv
)
697 return opkg_list_find_cmd(argc
, argv
, 0);
700 static int opkg_find_cmd(int argc
, char **argv
)
702 return opkg_list_find_cmd(argc
, argv
, 1);
705 static int opkg_list_installed_cmd(int argc
, char **argv
)
708 pkg_vec_t
*available
;
710 char *pkg_name
= NULL
;
715 available
= pkg_vec_alloc();
716 pkg_hash_fetch_all_installed(available
);
717 pkg_vec_sort(available
, pkg_compare_names
);
718 for (i
= 0; i
< available
->len
; i
++) {
719 pkg
= available
->pkgs
[i
];
720 /* if we have package name or pattern and pkg does not match, then skip it */
721 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
726 pkg_vec_free(available
);
731 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
734 pkg_vec_t
*available
;
736 char *pkg_name
= NULL
;
737 conffile_list_elt_t
*iter
;
744 available
= pkg_vec_alloc();
745 pkg_hash_fetch_all_installed(available
);
746 pkg_vec_sort(available
, pkg_compare_names
);
747 for (i
= 0; i
< available
->len
; i
++) {
748 pkg
= available
->pkgs
[i
];
749 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
750 /* if we have package name or pattern and pkg does not match, then skip it */
751 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
753 if (!cl
|| nv_pair_list_empty(cl
))
755 for (iter
= nv_pair_list_first(cl
); iter
;
756 iter
= nv_pair_list_next(cl
, iter
)) {
757 cf
= (conffile_t
*) iter
->data
;
758 if (cf
->name
&& cf
->value
759 && conffile_has_been_modified(cf
))
760 printf("%s\n", cf
->name
);
763 pkg_vec_free(available
);
767 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
769 struct active_list
*head
= prepare_upgrade_list();
770 struct active_list
*node
= NULL
;
771 pkg_t
*_old_pkg
, *_new_pkg
;
773 for (node
= active_list_next(head
, head
); node
;
774 node
= active_list_next(head
, node
)) {
775 _old_pkg
= node
->pkg
;
777 pkg_hash_fetch_best_installation_candidate_by_name
779 if (_new_pkg
== NULL
)
781 old_v
= pkg_version_str_alloc(_old_pkg
);
782 new_v
= pkg_version_str_alloc(_new_pkg
);
783 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
787 active_list_head_delete(head
);
791 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
794 pkg_vec_t
*available
;
796 char *pkg_name
= NULL
;
803 available
= pkg_vec_alloc();
805 pkg_hash_fetch_all_installed(available
);
807 pkg_hash_fetch_available(available
);
809 for (i
= 0; i
< available
->len
; i
++) {
810 pkg
= available
->pkgs
[i
];
811 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
815 pkg_formatted_info(stdout
, pkg
);
817 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
819 if (conf
->verbosity
>= NOTICE
&& cl
) {
820 conffile_list_elt_t
*iter
;
821 for (iter
= nv_pair_list_first(cl
); iter
;
822 iter
= nv_pair_list_next(cl
, iter
)) {
823 conffile_t
*cf
= (conffile_t
*) iter
->data
;
824 int modified
= conffile_has_been_modified(cf
);
827 "conffile=%s md5sum=%s modified=%d.\n",
828 cf
->name
, cf
->value
, modified
);
832 pkg_vec_free(available
);
837 static int opkg_info_cmd(int argc
, char **argv
)
839 return opkg_info_status_cmd(argc
, argv
, 0);
842 static int opkg_status_cmd(int argc
, char **argv
)
844 return opkg_info_status_cmd(argc
, argv
, 1);
847 static int opkg_configure_cmd(int argc
, char **argv
)
850 char *pkg_name
= NULL
;
855 err
= opkg_configure_packages(pkg_name
);
857 write_status_files_if_changed();
862 static int opkg_remove_cmd(int argc
, char **argv
)
864 int i
, a
, done
, err
= 0;
866 pkg_t
*pkg_to_remove
;
867 pkg_vec_t
*available
;
871 signal(SIGINT
, sigint_handler
);
873 pkg_info_preinstall_check();
875 available
= pkg_vec_alloc();
876 pkg_hash_fetch_all_installed(available
);
878 for (i
= 0; i
< argc
; i
++) {
879 for (a
= 0; a
< available
->len
; a
++) {
880 pkg
= available
->pkgs
[a
];
881 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
884 if (conf
->restrict_to_default_dest
) {
886 pkg_hash_fetch_installed_by_name_dest(pkg
->
892 pkg_hash_fetch_installed_by_name(pkg
->name
);
895 if (pkg_to_remove
== NULL
) {
897 "Package %s is not installed.\n",
901 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
902 opkg_msg(ERROR
, "Package %s not installed.\n",
907 if (opkg_remove_pkg(pkg_to_remove
, 0))
914 pkg_vec_free(available
);
917 opkg_msg(NOTICE
, "No packages removed.\n");
919 write_status_files_if_changed();
923 static int opkg_flag_cmd(int argc
, char **argv
)
927 const char *flags
= argv
[0];
929 signal(SIGINT
, sigint_handler
);
931 for (i
= 1; i
< argc
; i
++) {
932 if (conf
->restrict_to_default_dest
) {
933 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
937 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
941 opkg_msg(ERROR
, "Package %s is not installed.\n",
945 if ((strcmp(flags
, "hold") == 0)
946 || (strcmp(flags
, "noprune") == 0)
947 || (strcmp(flags
, "user") == 0)
948 || (strcmp(flags
, "ok") == 0)) {
949 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
953 * Useful if a package is installed in an offline_root, and
954 * should be configured by opkg-cl configure at a later date.
956 if ((strcmp(flags
, "installed") == 0)
957 || (strcmp(flags
, "unpacked") == 0)) {
958 pkg
->state_status
= pkg_state_status_from_str(flags
);
961 opkg_state_changed
++;
962 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
966 write_status_files_if_changed();
970 static int opkg_files_cmd(int argc
, char **argv
)
974 str_list_elt_t
*iter
;
981 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
983 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
987 files
= pkg_get_installed_files(pkg
);
988 pkg_version
= pkg_version_str_alloc(pkg
);
991 ("Package %s (%s) is installed on %s and has the following files:\n",
992 pkg
->name
, pkg_version
, pkg
->dest
->name
);
994 for (iter
= str_list_first(files
); iter
;
995 iter
= str_list_next(files
, iter
))
996 printf("%s\n", (char *)iter
->data
);
999 pkg_free_installed_files(pkg
);
1004 static int opkg_depends_cmd(int argc
, char **argv
)
1007 pkg_vec_t
*available_pkgs
;
1008 compound_depend_t
*cdep
;
1012 pkg_info_preinstall_check();
1014 available_pkgs
= pkg_vec_alloc();
1015 if (conf
->query_all
)
1016 pkg_hash_fetch_available(available_pkgs
);
1018 pkg_hash_fetch_all_installed(available_pkgs
);
1020 for (i
= 0; i
< argc
; i
++) {
1021 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1022 pkg
= available_pkgs
->pkgs
[j
];
1024 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
1027 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
1029 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
1030 if (cdep
->type
!= DEPEND
)
1033 str
= pkg_depend_str(pkg
, k
);
1034 opkg_msg(NOTICE
, "\t%s\n", str
);
1041 pkg_vec_free(available_pkgs
);
1045 static int pkg_mark_provides(pkg_t
* pkg
)
1047 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
1049 pkg
->parent
->state_flag
|= SF_MARKED
;
1051 while (provider
&& *provider
) {
1052 (*provider
)->state_flag
|= SF_MARKED
;
1059 enum what_field_type
{
1069 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
1070 int argc
, char **argv
)
1072 depend_t
*possibility
;
1073 compound_depend_t
*cdep
, *deps
;
1074 pkg_vec_t
*available_pkgs
;
1078 const char *rel_str
= NULL
;
1081 switch (what_field_type
) {
1083 rel_str
= "depends on";
1086 rel_str
= "conflicts with";
1089 rel_str
= "suggests";
1092 rel_str
= "recommends";
1098 available_pkgs
= pkg_vec_alloc();
1100 if (conf
->query_all
)
1101 pkg_hash_fetch_available(available_pkgs
);
1103 pkg_hash_fetch_all_installed(available_pkgs
);
1105 /* mark the root set */
1106 pkg_vec_clear_marks(available_pkgs
);
1107 opkg_msg(NOTICE
, "Root set:\n");
1108 for (i
= 0; i
< argc
; i
++)
1109 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1111 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1112 pkg
= available_pkgs
->pkgs
[i
];
1113 if (pkg
->state_flag
& SF_MARKED
) {
1114 /* mark the parent (abstract) package */
1115 pkg_mark_provides(pkg
);
1116 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1120 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1124 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1126 pkg
= available_pkgs
->pkgs
[j
];
1128 count = ((what_field_type == CONFLICTS)
1129 ? pkg->conflicts_count
1130 : pkg->pre_depends_count +
1131 pkg->depends_count +
1132 pkg->recommends_count + pkg->suggests_count);
1135 /* skip this package if it is already marked */
1136 if (pkg
->parent
->state_flag
& SF_MARKED
)
1139 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1141 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1142 if (what_field_type
!= cdep
->type
)
1145 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1146 possibility
= cdep
->possibilities
[l
];
1148 if ((possibility
->pkg
->state_flag
1153 /* mark the depending package so we
1154 * won't visit it again */
1155 pkg
->state_flag
|= SF_MARKED
;
1156 pkg_mark_provides(pkg
);
1159 ver
= pkg_version_str_alloc(pkg
);
1160 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1164 possibility
->pkg
->name
);
1166 if (possibility
->version
) {
1167 opkg_msg(NOTICE
, " (%s%s)",
1171 possibility
->version
);
1173 if (!pkg_dependence_satisfiable
1177 opkg_message(NOTICE
, "\n");
1184 } while (changed
&& recursive
);
1186 pkg_vec_free(available_pkgs
);
1191 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1193 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1196 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1198 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1201 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1203 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1206 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1208 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1211 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1213 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1217 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1220 abstract_pkg_t
*apkg
, **abpkgs
;
1223 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1224 const char *rel_str
=
1225 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1228 pkg_info_preinstall_check();
1230 if (conf
->query_all
)
1231 pkg_hash_fetch_available(available_pkgs
);
1233 pkg_hash_fetch_all_installed(available_pkgs
);
1234 for (i
= 0; i
< argc
; i
++) {
1235 const char *target
= argv
[i
];
1238 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1239 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1240 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1241 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1243 while (abpkgs
&& *abpkgs
) {
1246 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1249 opkg_msg(NOTICE
, " %s", pkg
->name
);
1251 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1252 : strcmp(target
, apkg
->name
)))
1253 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1255 opkg_message(NOTICE
, "\n");
1259 pkg_vec_free(available_pkgs
);
1264 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1266 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1269 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1271 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1274 static int opkg_search_cmd(int argc
, char **argv
)
1278 pkg_vec_t
*installed
;
1280 str_list_t
*installed_files
;
1281 str_list_elt_t
*iter
;
1282 char *installed_file
;
1288 installed
= pkg_vec_alloc();
1289 pkg_hash_fetch_all_installed(installed
);
1290 pkg_vec_sort(installed
, pkg_compare_names
);
1292 for (i
= 0; i
< installed
->len
; i
++) {
1293 pkg
= installed
->pkgs
[i
];
1295 installed_files
= pkg_get_installed_files(pkg
);
1297 for (iter
= str_list_first(installed_files
); iter
;
1298 iter
= str_list_next(installed_files
, iter
)) {
1299 installed_file
= (char *)iter
->data
;
1300 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1304 pkg_free_installed_files(pkg
);
1307 pkg_vec_free(installed
);
1312 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1318 /* this is a bit gross */
1321 parse_version(p1
, argv
[0]);
1322 parse_version(p2
, argv
[2]);
1323 rc
= pkg_version_satisfied(p1
, p2
, argv
[1]);
1331 "opkg compare_versions <v1> <op> <v2>\n"
1332 "<op> is one of <= >= << >> =\n");
1337 static int opkg_print_architecture_cmd(int argc
, char **argv
)
1339 nv_pair_list_elt_t
*l
;
1341 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1342 nv_pair_t
*nv
= (nv_pair_t
*) l
->data
;
1343 printf("arch %s %s\n", nv
->name
, nv
->value
);
1348 /* XXX: CLEANUP: The usage strings should be incorporated into this
1349 array for easier maintenance */
1350 static opkg_cmd_t cmds
[] = {
1351 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1352 PFM_DESCRIPTION
| PFM_SOURCE
},
1353 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1354 PFM_DESCRIPTION
| PFM_SOURCE
},
1355 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1356 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1358 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1360 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1362 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1364 {"list_changed_conffiles", 0,
1365 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1366 {"list-changed-conffiles", 0,
1367 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1368 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1369 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1370 PFM_DESCRIPTION
| PFM_SOURCE
},
1371 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1372 PFM_DESCRIPTION
| PFM_SOURCE
},
1373 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1374 PFM_DESCRIPTION
| PFM_SOURCE
},
1375 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1376 PFM_DESCRIPTION
| PFM_SOURCE
},
1377 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1378 PFM_DESCRIPTION
| PFM_SOURCE
},
1379 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1380 PFM_DESCRIPTION
| PFM_SOURCE
},
1381 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1382 PFM_DESCRIPTION
| PFM_SOURCE
},
1383 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1384 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1385 PFM_DESCRIPTION
| PFM_SOURCE
},
1386 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1387 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1388 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1389 PFM_DESCRIPTION
| PFM_SOURCE
},
1390 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1391 PFM_DESCRIPTION
| PFM_SOURCE
},
1392 {"print-installation-architecture", 0,
1393 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1394 PFM_DESCRIPTION
| PFM_SOURCE
},
1395 {"print_installation_architecture", 0,
1396 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1397 PFM_DESCRIPTION
| PFM_SOURCE
},
1398 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1399 PFM_DESCRIPTION
| PFM_SOURCE
},
1400 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1401 PFM_DESCRIPTION
| PFM_SOURCE
},
1402 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1403 PFM_DESCRIPTION
| PFM_SOURCE
},
1404 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1405 PFM_DESCRIPTION
| PFM_SOURCE
},
1406 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1407 PFM_DESCRIPTION
| PFM_SOURCE
},
1408 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1409 PFM_DESCRIPTION
| PFM_SOURCE
},
1410 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1411 PFM_DESCRIPTION
| PFM_SOURCE
},
1412 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1413 PFM_DESCRIPTION
| PFM_SOURCE
},
1416 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1420 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1422 for (i
= 0; i
< num_cmds
; i
++) {
1424 if (strcmp(name
, cmd
->name
) == 0)
1431 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1433 opkg_cli_argc
= argc
;
1434 opkg_cli_argv
= argv
;
1435 return (cmd
->fun
) (argc
, argv
);