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
);
49 char *tmp
, *tmpname
= NULL
;
51 if (conf
->strip_abi
&&
52 (abiver
= pkg_get_string(pkg
, PKG_ABIVERSION
)) &&
53 (strlen(pkg
->name
) > strlen(abiver
))) {
54 tmpname
= strdup(pkg
->name
);
55 tmp
= &tmpname
[strlen(tmpname
) - strlen(abiver
)];
56 if (!strncmp(abiver
, tmp
, strlen(abiver
)))
60 printf("%s - %s", tmpname
?tmpname
:pkg
->name
, version
);
66 printf(" - %lu", (unsigned long) pkg_get_int(pkg
, PKG_SIZE
));
68 printf(" - %s", description
);
73 int opkg_state_changed
;
75 static void write_status_files_if_changed(void)
77 if (opkg_state_changed
&& !conf
->noaction
) {
78 opkg_msg(INFO
, "Writing status file.\n");
79 opkg_conf_write_status_files();
80 pkg_write_changed_filelists();
82 opkg_msg(DEBUG
, "Nothing to be done.\n");
86 static void sigint_handler(int sig
)
89 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
90 write_status_files_if_changed();
94 static int opkg_update_cmd(int argc
, char **argv
)
101 pkg_src_list_elt_t
*iter
;
104 sprintf_alloc(&lists_dir
, "%s",
105 conf
->restrict_to_default_dest
? conf
->default_dest
->
106 lists_dir
: conf
->lists_dir
);
108 if (!file_is_dir(lists_dir
)) {
109 if (file_exists(lists_dir
)) {
110 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
115 err
= file_mkdir_hier(lists_dir
, 0755);
124 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
125 if (mkdtemp(tmp
) == NULL
) {
126 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
130 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
;
131 iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
132 char *url
, *list_file_name
;
134 src
= (pkg_src_t
*) iter
->data
;
136 sprintf_alloc(&url
, "%s/%s", src
->value
,
137 src
->gzip
? "Packages.gz" : "Packages");
139 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
140 pkglist_dl_error
= 0;
141 if (opkg_download(url
, list_file_name
, 0)) {
143 pkglist_dl_error
= 1;
145 "*** Failed to download the package list from %s\n\n",
149 "Updated list of available packages in %s\n",
153 #if defined(HAVE_USIGN)
154 if (pkglist_dl_error
== 0 && conf
->check_signature
) {
155 /* download detached signitures to verify the package lists */
156 /* get the url for the sig file */
157 sprintf_alloc(&url
, "%s/%s", src
->value
,
160 /* create temporary file for it */
163 /* Put the signature in the right place */
164 sprintf_alloc(&tmp_file_name
, "%s/%s.sig", lists_dir
,
167 err
= opkg_download(url
, tmp_file_name
, 0);
171 "Signature file download failed.\n");
174 opkg_verify_file(list_file_name
,
178 "Signature check passed.\n");
181 "Signature check failed.\n");
183 if (err
&& !conf
->force_signature
) {
184 /* The signature was wrong so delete it */
186 "Remove wrong Signature file.\n");
187 unlink(tmp_file_name
);
188 unlink(list_file_name
);
190 /* We shouldn't unlink the signature ! */
191 // unlink (tmp_file_name);
198 free(list_file_name
);
207 struct opkg_intercept
{
212 typedef struct opkg_intercept
*opkg_intercept_t
;
214 static opkg_intercept_t
opkg_prep_intercepts(void)
216 opkg_intercept_t ctx
;
219 ctx
= xcalloc(1, sizeof(*ctx
));
220 ctx
->oldpath
= xstrdup(getenv("PATH"));
222 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
,
223 ctx
->oldpath
? ctx
->oldpath
: PATH_SPEC
);
225 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
228 if (mkdtemp(ctx
->statedir
) == NULL
) {
229 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
240 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
241 setenv("PATH", newpath
, 1);
247 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
253 setenv("PATH", ctx
->oldpath
, 1);
260 dir
= opendir(ctx
->statedir
);
263 while (de
= readdir(dir
), de
!= NULL
) {
266 if (de
->d_name
[0] == '.')
269 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
271 if (access(path
, X_OK
) == 0) {
272 const char *argv
[] = { "/bin/sh", "-c", path
, NULL
};
279 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
288 /* For package pkg do the following: If it is already visited, return. If not,
289 add it in visited list and recurse to its deps. Finally, add it to ordered
291 pkg_vec all contains all available packages in repos.
292 pkg_vec visited contains packages already visited by this function, and is
293 used to end recursion and avoid an infinite loop on graph cycles.
294 pkg_vec ordered will finally contain the ordered set of packages.
297 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
298 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
302 compound_depend_t
*compound_depend
;
303 depend_t
**possible_satisfiers
;
304 abstract_pkg_t
*abpkg
;
305 abstract_pkg_t
**dependents
;
307 /* If it's just an available package, that is, not installed and not even
309 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
310 would do here. However, if there is an intermediate node (pkg) that is
311 configured and installed between two unpacked packages, the latter
312 won't be properly reordered, unless all installed/unpacked pkgs are
314 if (pkg
->state_status
== SS_NOT_INSTALLED
)
317 /* If the package has already been visited (by this function), skip it */
318 for (j
= 0; j
< visited
->len
; j
++)
319 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
320 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
325 pkg_vec_insert(visited
, pkg
);
327 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
329 /* Iterate over all the dependencies of pkg. For each one, find a package
330 that is either installed or unpacked and satisfies this dependency.
331 (there should only be one such package per dependency installed or
332 unpacked). Then recurse to the dependency package */
333 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
334 possible_satisfiers
= compound_depend
->possibilities
;
335 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
336 abpkg
= possible_satisfiers
[k
]->pkg
;
337 dependents
= abpkg
->provided_by
->pkgs
;
339 if (dependents
!= NULL
)
340 while (l
< abpkg
->provided_by
->len
341 && dependents
[l
] != NULL
) {
343 "Descending on pkg %s.\n",
344 dependents
[l
]->name
);
346 /* find whether dependent l is installed or unpacked,
347 * and then find which package in the list satisfies it */
348 for (m
= 0; m
< all
->len
; m
++) {
350 if (dep
->state_status
!=
356 opkg_recurse_pkgs_in_order
360 /* Stop the outer loop */
364 /* break from the inner loop */
373 /* When all recursions from this node down, are over, and all
374 dependencies have been added in proper order in the ordered array, add
375 also the package pkg to ordered array */
376 pkg_vec_insert(ordered
, pkg
);
382 static int opkg_configure_packages(char *pkg_name
)
384 pkg_vec_t
*all
, *ordered
, *visited
;
390 opkg_msg(INFO
, "Configuring unpacked packages.\n");
392 all
= pkg_vec_alloc();
394 pkg_hash_fetch_available(all
);
396 /* Reorder pkgs in order to be configured according to the Depends: tag
398 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
399 ordered
= pkg_vec_alloc();
400 visited
= pkg_vec_alloc();
401 for (i
= 0; i
< all
->len
; i
++) {
403 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
406 ic
= opkg_prep_intercepts();
412 for (i
= 0; i
< ordered
->len
; i
++) {
413 pkg
= ordered
->pkgs
[i
];
415 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
418 if (pkg
->state_status
== SS_UNPACKED
) {
419 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
420 r
= opkg_configure(pkg
);
422 pkg
->state_status
= SS_INSTALLED
;
423 pkg
->parent
->state_status
= SS_INSTALLED
;
424 pkg
->state_flag
&= ~SF_PREFER
;
425 opkg_state_changed
++;
432 if (opkg_finalize_intercepts(ic
))
437 pkg_vec_free(ordered
);
438 pkg_vec_free(visited
);
443 static int opkg_remove_cmd(int argc
, char **argv
);
445 static int opkg_install_cmd(int argc
, char **argv
)
451 signal(SIGINT
, sigint_handler
);
454 * Now scan through package names and install
456 for (i
= 0; i
< argc
; i
++) {
459 opkg_msg(DEBUG2
, "%s\n", arg
);
460 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
464 pkg_hash_load_package_details();
465 pkg_hash_load_status_files(NULL
, NULL
);
467 if (conf
->force_reinstall
) {
468 int saved_force_depends
= conf
->force_depends
;
469 conf
->force_depends
= 1;
470 (void)opkg_remove_cmd(argc
, argv
);
471 conf
->force_depends
= saved_force_depends
;
472 conf
->force_reinstall
= 0;
475 pkg_info_preinstall_check();
477 for (i
= 0; i
< argc
; i
++) {
479 if (opkg_install_by_name(arg
)) {
480 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
485 if (opkg_configure_packages(NULL
))
488 write_status_files_if_changed();
493 static int opkg_upgrade_cmd(int argc
, char **argv
)
499 signal(SIGINT
, sigint_handler
);
502 for (i
= 0; i
< argc
; i
++) {
505 if (opkg_prepare_url_for_install(arg
, &arg
))
508 pkg_info_preinstall_check();
510 for (i
= 0; i
< argc
; i
++) {
512 if (conf
->restrict_to_default_dest
) {
514 pkg_hash_fetch_installed_by_name_dest(argv
520 "Package %s not installed in %s.\n",
522 conf
->default_dest
->name
);
526 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
529 if (opkg_upgrade_pkg(pkg
))
532 if (opkg_install_by_name(arg
))
538 if (opkg_configure_packages(NULL
))
541 write_status_files_if_changed();
546 static int opkg_download_cmd(int argc
, char **argv
)
552 pkg_info_preinstall_check();
553 for (i
= 0; i
< argc
; i
++) {
556 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
558 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
562 if (opkg_download_pkg(pkg
, "."))
566 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
568 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
569 pkg
->name
, pkg_get_string(pkg
, PKG_LOCAL_FILENAME
));
576 struct opkg_list_find_cmd_item
{
583 struct opkg_list_find_cmd_args
{
587 struct opkg_list_find_cmd_item
**items
;
591 static void opkg_list_find_cmd_cb(pkg_t
*pkg
, void *priv
)
593 struct opkg_list_find_cmd_args
*args
= priv
;
594 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
595 char *version
= pkg_version_str_alloc(pkg
);
596 struct opkg_list_find_cmd_item
*item
;
597 char *nameptr
, *versionptr
, *descriptionptr
, *tmp
;
601 /* if we have package name or pattern and pkg does not match, then skip it */
602 if (args
->pkg_name
&& fnmatch(args
->pkg_name
, pkg
->name
, conf
->nocase
) &&
603 (!args
->use_desc
|| !description
604 || fnmatch(args
->pkg_name
, description
, conf
->nocase
)))
607 if (args
->set_status
) {
608 for (i
= 0; i
< args
->n_items
; i
++) {
609 if (!strcmp(args
->items
[i
]->name
, pkg
->name
)) {
617 item
= calloc_a(sizeof(*item
),
618 &nameptr
, strlen(pkg
->name
) + 1,
619 &versionptr
, strlen(version
) + 1,
620 &descriptionptr
, description
? strlen(description
) + 1 : 0);
622 item
->name
= strcpy(nameptr
, pkg
->name
);
624 if (conf
->strip_abi
&&
625 (abiver
= pkg_get_string(pkg
, PKG_ABIVERSION
)) &&
626 (strlen(item
->name
) > strlen(abiver
))) {
627 tmp
= &item
->name
[strlen(item
->name
) - strlen(abiver
)];
628 if (!strncmp(abiver
, tmp
, strlen(abiver
)))
632 item
->size
= pkg_get_int(pkg
, PKG_SIZE
);
633 item
->version
= strcpy(versionptr
, version
);
634 item
->description
= description
? strcpy(descriptionptr
, description
) : NULL
;
636 args
->items
= xrealloc(args
->items
, sizeof(item
) * (args
->n_items
+ 1));
637 args
->items
[args
->n_items
++] = item
;
646 static int opkg_list_find_cmd_sort(const void *a
, const void *b
)
648 const struct opkg_list_find_cmd_item
*pkg_a
= *(const struct opkg_list_find_cmd_item
**)a
;
649 const struct opkg_list_find_cmd_item
*pkg_b
= *(const struct opkg_list_find_cmd_item
**)b
;
650 return strcmp(pkg_a
->name
, pkg_b
->name
);
653 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
656 struct opkg_list_find_cmd_args args
= {
657 .use_desc
= use_desc
,
658 .pkg_name
= (argc
> 0) ? argv
[0] : NULL
662 pkg_hash_load_feeds(SF_NEED_DETAIL
, opkg_list_find_cmd_cb
, &args
);
665 pkg_hash_load_status_files(opkg_list_find_cmd_cb
, &args
);
667 if (args
.n_items
> 1)
668 qsort(args
.items
, args
.n_items
, sizeof(args
.items
[0]),
669 opkg_list_find_cmd_sort
);
671 for (i
= 0; i
< args
.n_items
; i
++) {
674 args
.items
[i
]->version
);
677 printf(" - %lu", (unsigned long) args
.items
[i
]->size
);
679 if (args
.items
[i
]->description
)
680 printf(" - %s", args
.items
[i
]->description
);
692 static int opkg_list_cmd(int argc
, char **argv
)
694 return opkg_list_find_cmd(argc
, argv
, 0);
697 static int opkg_find_cmd(int argc
, char **argv
)
699 return opkg_list_find_cmd(argc
, argv
, 1);
702 static int opkg_list_installed_cmd(int argc
, char **argv
)
705 pkg_vec_t
*available
;
707 char *pkg_name
= NULL
;
712 available
= pkg_vec_alloc();
713 pkg_hash_fetch_all_installed(available
);
714 pkg_vec_sort(available
, pkg_compare_names
);
715 for (i
= 0; i
< available
->len
; i
++) {
716 pkg
= available
->pkgs
[i
];
717 /* if we have package name or pattern and pkg does not match, then skip it */
718 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
723 pkg_vec_free(available
);
728 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
731 pkg_vec_t
*available
;
733 char *pkg_name
= NULL
;
734 conffile_list_elt_t
*iter
;
741 available
= pkg_vec_alloc();
742 pkg_hash_fetch_all_installed(available
);
743 pkg_vec_sort(available
, pkg_compare_names
);
744 for (i
= 0; i
< available
->len
; i
++) {
745 pkg
= available
->pkgs
[i
];
746 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
747 /* if we have package name or pattern and pkg does not match, then skip it */
748 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
750 if (!cl
|| nv_pair_list_empty(cl
))
752 for (iter
= nv_pair_list_first(cl
); iter
;
753 iter
= nv_pair_list_next(cl
, iter
)) {
754 cf
= (conffile_t
*) iter
->data
;
755 if (cf
->name
&& cf
->value
756 && conffile_has_been_modified(cf
))
757 printf("%s\n", cf
->name
);
760 pkg_vec_free(available
);
764 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
766 struct active_list
*head
= prepare_upgrade_list();
767 struct active_list
*node
= NULL
;
768 pkg_t
*_old_pkg
, *_new_pkg
;
770 for (node
= active_list_next(head
, head
); node
;
771 node
= active_list_next(head
, node
)) {
772 _old_pkg
= node
->pkg
;
774 pkg_hash_fetch_best_installation_candidate_by_name
776 if (_new_pkg
== NULL
)
778 old_v
= pkg_version_str_alloc(_old_pkg
);
779 new_v
= pkg_version_str_alloc(_new_pkg
);
780 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
784 active_list_head_delete(head
);
788 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
791 pkg_vec_t
*available
;
793 char *pkg_name
= NULL
;
800 available
= pkg_vec_alloc();
802 pkg_hash_fetch_all_installed(available
);
804 pkg_hash_fetch_available(available
);
806 for (i
= 0; i
< available
->len
; i
++) {
807 pkg
= available
->pkgs
[i
];
808 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
812 pkg_formatted_info(stdout
, pkg
);
814 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
816 if (conf
->verbosity
>= NOTICE
&& cl
) {
817 conffile_list_elt_t
*iter
;
818 for (iter
= nv_pair_list_first(cl
); iter
;
819 iter
= nv_pair_list_next(cl
, iter
)) {
820 conffile_t
*cf
= (conffile_t
*) iter
->data
;
821 int modified
= conffile_has_been_modified(cf
);
824 "conffile=%s md5sum=%s modified=%d.\n",
825 cf
->name
, cf
->value
, modified
);
829 pkg_vec_free(available
);
834 static int opkg_info_cmd(int argc
, char **argv
)
836 return opkg_info_status_cmd(argc
, argv
, 0);
839 static int opkg_status_cmd(int argc
, char **argv
)
841 return opkg_info_status_cmd(argc
, argv
, 1);
844 static int opkg_configure_cmd(int argc
, char **argv
)
847 char *pkg_name
= NULL
;
852 err
= opkg_configure_packages(pkg_name
);
854 write_status_files_if_changed();
859 static int opkg_remove_cmd(int argc
, char **argv
)
861 int i
, a
, done
, err
= 0;
863 pkg_t
*pkg_to_remove
;
864 pkg_vec_t
*available
;
868 signal(SIGINT
, sigint_handler
);
870 pkg_info_preinstall_check();
872 available
= pkg_vec_alloc();
873 pkg_hash_fetch_all_installed(available
);
875 for (i
= 0; i
< argc
; i
++) {
876 for (a
= 0; a
< available
->len
; a
++) {
877 pkg
= available
->pkgs
[a
];
878 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
881 if (conf
->restrict_to_default_dest
) {
883 pkg_hash_fetch_installed_by_name_dest(pkg
->
889 pkg_hash_fetch_installed_by_name(pkg
->name
);
892 if (pkg_to_remove
== NULL
) {
894 "Package %s is not installed.\n",
898 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
899 opkg_msg(ERROR
, "Package %s not installed.\n",
904 if (opkg_remove_pkg(pkg_to_remove
, 0))
911 pkg_vec_free(available
);
914 opkg_msg(NOTICE
, "No packages removed.\n");
916 write_status_files_if_changed();
920 static int opkg_flag_cmd(int argc
, char **argv
)
924 const char *flags
= argv
[0];
926 signal(SIGINT
, sigint_handler
);
928 for (i
= 1; i
< argc
; i
++) {
929 if (conf
->restrict_to_default_dest
) {
930 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
934 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
938 opkg_msg(ERROR
, "Package %s is not installed.\n",
942 if ((strcmp(flags
, "hold") == 0)
943 || (strcmp(flags
, "noprune") == 0)
944 || (strcmp(flags
, "user") == 0)
945 || (strcmp(flags
, "ok") == 0)) {
946 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
950 * Useful if a package is installed in an offline_root, and
951 * should be configured by opkg-cl configure at a later date.
953 if ((strcmp(flags
, "installed") == 0)
954 || (strcmp(flags
, "unpacked") == 0)) {
955 pkg
->state_status
= pkg_state_status_from_str(flags
);
958 opkg_state_changed
++;
959 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
963 write_status_files_if_changed();
967 static int opkg_files_cmd(int argc
, char **argv
)
971 str_list_elt_t
*iter
;
978 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
980 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
984 files
= pkg_get_installed_files(pkg
);
985 pkg_version
= pkg_version_str_alloc(pkg
);
988 ("Package %s (%s) is installed on %s and has the following files:\n",
989 pkg
->name
, pkg_version
, pkg
->dest
->name
);
991 for (iter
= str_list_first(files
); iter
;
992 iter
= str_list_next(files
, iter
))
993 printf("%s\n", (char *)iter
->data
);
996 pkg_free_installed_files(pkg
);
1001 static int opkg_depends_cmd(int argc
, char **argv
)
1004 pkg_vec_t
*available_pkgs
;
1005 compound_depend_t
*cdep
;
1009 pkg_info_preinstall_check();
1011 available_pkgs
= pkg_vec_alloc();
1012 if (conf
->query_all
)
1013 pkg_hash_fetch_available(available_pkgs
);
1015 pkg_hash_fetch_all_installed(available_pkgs
);
1017 for (i
= 0; i
< argc
; i
++) {
1018 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1019 pkg
= available_pkgs
->pkgs
[j
];
1021 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
1024 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
1026 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
1027 if (cdep
->type
!= DEPEND
)
1030 str
= pkg_depend_str(pkg
, k
);
1031 opkg_msg(NOTICE
, "\t%s\n", str
);
1038 pkg_vec_free(available_pkgs
);
1042 static int pkg_mark_provides(pkg_t
* pkg
)
1044 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
1046 pkg
->parent
->state_flag
|= SF_MARKED
;
1048 while (provider
&& *provider
) {
1049 (*provider
)->state_flag
|= SF_MARKED
;
1056 enum what_field_type
{
1066 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
1067 int argc
, char **argv
)
1069 depend_t
*possibility
;
1070 compound_depend_t
*cdep
, *deps
;
1071 pkg_vec_t
*available_pkgs
;
1075 const char *rel_str
= NULL
;
1078 switch (what_field_type
) {
1080 rel_str
= "depends on";
1083 rel_str
= "conflicts with";
1086 rel_str
= "suggests";
1089 rel_str
= "recommends";
1095 available_pkgs
= pkg_vec_alloc();
1097 if (conf
->query_all
)
1098 pkg_hash_fetch_available(available_pkgs
);
1100 pkg_hash_fetch_all_installed(available_pkgs
);
1102 /* mark the root set */
1103 pkg_vec_clear_marks(available_pkgs
);
1104 opkg_msg(NOTICE
, "Root set:\n");
1105 for (i
= 0; i
< argc
; i
++)
1106 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1108 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1109 pkg
= available_pkgs
->pkgs
[i
];
1110 if (pkg
->state_flag
& SF_MARKED
) {
1111 /* mark the parent (abstract) package */
1112 pkg_mark_provides(pkg
);
1113 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1117 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1121 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1123 pkg
= available_pkgs
->pkgs
[j
];
1125 count = ((what_field_type == CONFLICTS)
1126 ? pkg->conflicts_count
1127 : pkg->pre_depends_count +
1128 pkg->depends_count +
1129 pkg->recommends_count + pkg->suggests_count);
1132 /* skip this package if it is already marked */
1133 if (pkg
->parent
->state_flag
& SF_MARKED
)
1136 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1138 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1139 if (what_field_type
!= cdep
->type
)
1142 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1143 possibility
= cdep
->possibilities
[l
];
1145 if ((possibility
->pkg
->state_flag
1150 /* mark the depending package so we
1151 * won't visit it again */
1152 pkg
->state_flag
|= SF_MARKED
;
1153 pkg_mark_provides(pkg
);
1156 ver
= pkg_version_str_alloc(pkg
);
1157 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1161 possibility
->pkg
->name
);
1163 if (possibility
->version
) {
1164 opkg_msg(NOTICE
, " (%s%s)",
1168 possibility
->version
);
1170 if (!pkg_dependence_satisfiable
1174 opkg_message(NOTICE
, "\n");
1181 } while (changed
&& recursive
);
1183 pkg_vec_free(available_pkgs
);
1188 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1190 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1193 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1195 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1198 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1200 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1203 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1205 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1208 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1210 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1214 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1217 abstract_pkg_t
*apkg
, **abpkgs
;
1220 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1221 const char *rel_str
=
1222 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1225 pkg_info_preinstall_check();
1227 if (conf
->query_all
)
1228 pkg_hash_fetch_available(available_pkgs
);
1230 pkg_hash_fetch_all_installed(available_pkgs
);
1231 for (i
= 0; i
< argc
; i
++) {
1232 const char *target
= argv
[i
];
1235 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1236 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1237 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1238 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1240 while (abpkgs
&& *abpkgs
) {
1243 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1246 opkg_msg(NOTICE
, " %s", pkg
->name
);
1248 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1249 : strcmp(target
, apkg
->name
)))
1250 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1252 opkg_message(NOTICE
, "\n");
1256 pkg_vec_free(available_pkgs
);
1261 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1263 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1266 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1268 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1271 static int opkg_search_cmd(int argc
, char **argv
)
1275 pkg_vec_t
*installed
;
1277 str_list_t
*installed_files
;
1278 str_list_elt_t
*iter
;
1279 char *installed_file
;
1285 installed
= pkg_vec_alloc();
1286 pkg_hash_fetch_all_installed(installed
);
1287 pkg_vec_sort(installed
, pkg_compare_names
);
1289 for (i
= 0; i
< installed
->len
; i
++) {
1290 pkg
= installed
->pkgs
[i
];
1292 installed_files
= pkg_get_installed_files(pkg
);
1294 for (iter
= str_list_first(installed_files
); iter
;
1295 iter
= str_list_next(installed_files
, iter
)) {
1296 installed_file
= (char *)iter
->data
;
1297 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1301 pkg_free_installed_files(pkg
);
1304 pkg_vec_free(installed
);
1309 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1315 /* this is a bit gross */
1318 parse_version(p1
, argv
[0]);
1319 parse_version(p2
, argv
[2]);
1320 rc
= pkg_version_satisfied(p1
, p2
, argv
[1]);
1328 "opkg compare_versions <v1> <op> <v2>\n"
1329 "<op> is one of <= >= << >> =\n");
1334 static int opkg_print_architecture_cmd(int argc
, char **argv
)
1336 nv_pair_list_elt_t
*l
;
1338 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1339 nv_pair_t
*nv
= (nv_pair_t
*) l
->data
;
1340 printf("arch %s %s\n", nv
->name
, nv
->value
);
1345 /* XXX: CLEANUP: The usage strings should be incorporated into this
1346 array for easier maintenance */
1347 static opkg_cmd_t cmds
[] = {
1348 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1349 PFM_DESCRIPTION
| PFM_SOURCE
},
1350 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1351 PFM_DESCRIPTION
| PFM_SOURCE
},
1352 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1353 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1355 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1357 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1359 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1361 {"list_changed_conffiles", 0,
1362 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1363 {"list-changed-conffiles", 0,
1364 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1365 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1366 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1367 PFM_DESCRIPTION
| PFM_SOURCE
},
1368 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1369 PFM_DESCRIPTION
| PFM_SOURCE
},
1370 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1371 PFM_DESCRIPTION
| PFM_SOURCE
},
1372 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1373 PFM_DESCRIPTION
| PFM_SOURCE
},
1374 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1375 PFM_DESCRIPTION
| PFM_SOURCE
},
1376 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1377 PFM_DESCRIPTION
| PFM_SOURCE
},
1378 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1379 PFM_DESCRIPTION
| PFM_SOURCE
},
1380 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1381 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1382 PFM_DESCRIPTION
| PFM_SOURCE
},
1383 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1384 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1385 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1386 PFM_DESCRIPTION
| PFM_SOURCE
},
1387 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1388 PFM_DESCRIPTION
| PFM_SOURCE
},
1389 {"print-installation-architecture", 0,
1390 (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 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1396 PFM_DESCRIPTION
| PFM_SOURCE
},
1397 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1398 PFM_DESCRIPTION
| PFM_SOURCE
},
1399 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1400 PFM_DESCRIPTION
| PFM_SOURCE
},
1401 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1402 PFM_DESCRIPTION
| PFM_SOURCE
},
1403 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1404 PFM_DESCRIPTION
| PFM_SOURCE
},
1405 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1406 PFM_DESCRIPTION
| PFM_SOURCE
},
1407 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1408 PFM_DESCRIPTION
| PFM_SOURCE
},
1409 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1410 PFM_DESCRIPTION
| PFM_SOURCE
},
1413 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1417 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1419 for (i
= 0; i
< num_cmds
; i
++) {
1421 if (strcmp(name
, cmd
->name
) == 0)
1428 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1430 return (cmd
->fun
) (argc
, argv
);