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 sprintf_alloc(&url
, "%s/%s", src
->value
,
121 src
->gzip
? "Packages.gz" : "Packages");
123 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
124 pkglist_dl_error
= 0;
125 if (opkg_download(url
, list_file_name
, 0)) {
127 pkglist_dl_error
= 1;
129 "*** Failed to download the package list from %s\n\n",
133 "Updated list of available packages in %s\n",
137 #if defined(HAVE_USIGN)
138 if (pkglist_dl_error
== 0 && conf
->check_signature
) {
139 /* download detached signitures to verify the package lists */
140 /* get the url for the sig file */
141 sprintf_alloc(&url
, "%s/%s", src
->value
,
144 /* create temporary file for it */
147 /* Put the signature in the right place */
148 sprintf_alloc(&tmp_file_name
, "%s/%s.sig", lists_dir
,
151 err
= opkg_download(url
, tmp_file_name
, 0);
155 "Signature file download failed.\n");
158 opkg_verify_file(list_file_name
,
162 "Signature check passed.\n");
165 "Signature check failed.\n");
167 if (err
&& !conf
->force_signature
) {
168 /* The signature was wrong so delete it */
170 "Remove wrong Signature file.\n");
171 unlink(tmp_file_name
);
172 unlink(list_file_name
);
174 /* We shouldn't unlink the signature ! */
175 // unlink (tmp_file_name);
182 free(list_file_name
);
191 struct opkg_intercept
{
196 typedef struct opkg_intercept
*opkg_intercept_t
;
198 static opkg_intercept_t
opkg_prep_intercepts(void)
200 opkg_intercept_t ctx
;
203 ctx
= xcalloc(1, sizeof(*ctx
));
204 ctx
->oldpath
= xstrdup(getenv("PATH"));
206 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
,
207 ctx
->oldpath
? ctx
->oldpath
: PATH_SPEC
);
209 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
212 if (mkdtemp(ctx
->statedir
) == NULL
) {
213 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
224 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
225 setenv("PATH", newpath
, 1);
231 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
237 setenv("PATH", ctx
->oldpath
, 1);
244 dir
= opendir(ctx
->statedir
);
247 while (de
= readdir(dir
), de
!= NULL
) {
250 if (de
->d_name
[0] == '.')
253 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
255 if (access(path
, X_OK
) == 0) {
256 const char *argv
[] = { "/bin/sh", "-c", path
, NULL
};
263 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
272 /* For package pkg do the following: If it is already visited, return. If not,
273 add it in visited list and recurse to its deps. Finally, add it to ordered
275 pkg_vec all contains all available packages in repos.
276 pkg_vec visited contains packages already visited by this function, and is
277 used to end recursion and avoid an infinite loop on graph cycles.
278 pkg_vec ordered will finally contain the ordered set of packages.
281 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
282 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
286 compound_depend_t
*compound_depend
;
287 depend_t
**possible_satisfiers
;
288 abstract_pkg_t
*abpkg
;
289 abstract_pkg_t
**dependents
;
291 /* If it's just an available package, that is, not installed and not even
293 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
294 would do here. However, if there is an intermediate node (pkg) that is
295 configured and installed between two unpacked packages, the latter
296 won't be properly reordered, unless all installed/unpacked pkgs are
298 if (pkg
->state_status
== SS_NOT_INSTALLED
)
301 /* If the package has already been visited (by this function), skip it */
302 for (j
= 0; j
< visited
->len
; j
++)
303 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
304 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
309 pkg_vec_insert(visited
, pkg
);
311 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
313 /* Iterate over all the dependencies of pkg. For each one, find a package
314 that is either installed or unpacked and satisfies this dependency.
315 (there should only be one such package per dependency installed or
316 unpacked). Then recurse to the dependency package */
317 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
318 possible_satisfiers
= compound_depend
->possibilities
;
319 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
320 abpkg
= possible_satisfiers
[k
]->pkg
;
321 dependents
= abpkg
->provided_by
->pkgs
;
323 if (dependents
!= NULL
)
324 while (l
< abpkg
->provided_by
->len
325 && dependents
[l
] != NULL
) {
327 "Descending on pkg %s.\n",
328 dependents
[l
]->name
);
330 /* find whether dependent l is installed or unpacked,
331 * and then find which package in the list satisfies it */
332 for (m
= 0; m
< all
->len
; m
++) {
334 if (dep
->state_status
!=
340 opkg_recurse_pkgs_in_order
344 /* Stop the outer loop */
348 /* break from the inner loop */
357 /* When all recursions from this node down, are over, and all
358 dependencies have been added in proper order in the ordered array, add
359 also the package pkg to ordered array */
360 pkg_vec_insert(ordered
, pkg
);
366 static int opkg_configure_packages(char *pkg_name
)
368 pkg_vec_t
*all
, *ordered
, *visited
;
374 opkg_msg(INFO
, "Configuring unpacked packages.\n");
376 all
= pkg_vec_alloc();
378 pkg_hash_fetch_available(all
);
380 /* Reorder pkgs in order to be configured according to the Depends: tag
382 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
383 ordered
= pkg_vec_alloc();
384 visited
= pkg_vec_alloc();
385 for (i
= 0; i
< all
->len
; i
++) {
387 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
390 ic
= opkg_prep_intercepts();
396 for (i
= 0; i
< ordered
->len
; i
++) {
397 pkg
= ordered
->pkgs
[i
];
399 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
402 if (pkg
->state_status
== SS_UNPACKED
) {
403 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
404 r
= opkg_configure(pkg
);
406 pkg
->state_status
= SS_INSTALLED
;
407 pkg
->parent
->state_status
= SS_INSTALLED
;
408 pkg
->state_flag
&= ~SF_PREFER
;
409 opkg_state_changed
++;
416 if (opkg_finalize_intercepts(ic
))
421 pkg_vec_free(ordered
);
422 pkg_vec_free(visited
);
427 static int opkg_remove_cmd(int argc
, char **argv
);
429 static int opkg_install_cmd(int argc
, char **argv
)
435 signal(SIGINT
, sigint_handler
);
438 * Now scan through package names and install
440 for (i
= 0; i
< argc
; i
++) {
443 opkg_msg(DEBUG2
, "%s\n", arg
);
444 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
448 pkg_hash_load_package_details();
449 pkg_hash_load_status_files(NULL
, NULL
);
451 if (conf
->force_reinstall
) {
452 int saved_force_depends
= conf
->force_depends
;
453 conf
->force_depends
= 1;
454 (void)opkg_remove_cmd(argc
, argv
);
455 conf
->force_depends
= saved_force_depends
;
456 conf
->force_reinstall
= 0;
459 pkg_info_preinstall_check();
461 for (i
= 0; i
< argc
; i
++) {
463 if (opkg_install_by_name(arg
)) {
464 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
469 if (opkg_configure_packages(NULL
))
472 write_status_files_if_changed();
477 static int opkg_upgrade_cmd(int argc
, char **argv
)
483 signal(SIGINT
, sigint_handler
);
486 for (i
= 0; i
< argc
; i
++) {
489 if (opkg_prepare_url_for_install(arg
, &arg
))
492 pkg_info_preinstall_check();
494 for (i
= 0; i
< argc
; i
++) {
496 if (conf
->restrict_to_default_dest
) {
498 pkg_hash_fetch_installed_by_name_dest(argv
504 "Package %s not installed in %s.\n",
506 conf
->default_dest
->name
);
510 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
513 if (opkg_upgrade_pkg(pkg
))
516 if (opkg_install_by_name(arg
))
522 if (opkg_configure_packages(NULL
))
525 write_status_files_if_changed();
530 static int opkg_download_cmd(int argc
, char **argv
)
536 pkg_info_preinstall_check();
537 for (i
= 0; i
< argc
; i
++) {
540 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
542 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
546 if (opkg_download_pkg(pkg
, "."))
550 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
552 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
553 pkg
->name
, pkg_get_string(pkg
, PKG_LOCAL_FILENAME
));
560 struct opkg_list_find_cmd_item
{
567 struct opkg_list_find_cmd_args
{
571 struct opkg_list_find_cmd_item
**items
;
575 static void opkg_list_find_cmd_cb(pkg_t
*pkg
, void *priv
)
577 struct opkg_list_find_cmd_args
*args
= priv
;
578 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
579 char *version
= pkg_version_str_alloc(pkg
);
580 struct opkg_list_find_cmd_item
*item
;
581 char *nameptr
, *versionptr
, *descriptionptr
;
584 /* if we have package name or pattern and pkg does not match, then skip it */
585 if (args
->pkg_name
&& fnmatch(args
->pkg_name
, pkg
->name
, conf
->nocase
) &&
586 (!args
->use_desc
|| !description
587 || fnmatch(args
->pkg_name
, description
, conf
->nocase
)))
590 if (args
->set_status
) {
591 for (i
= 0; i
< args
->n_items
; i
++) {
592 if (!strcmp(args
->items
[i
]->name
, pkg
->name
)) {
600 item
= calloc_a(sizeof(*item
),
601 &nameptr
, strlen(pkg
->name
) + 1,
602 &versionptr
, strlen(version
) + 1,
603 &descriptionptr
, description
? strlen(description
) + 1 : 0);
605 item
->name
= strcpy(nameptr
, pkg
->name
);
606 item
->size
= pkg_get_int(pkg
, PKG_SIZE
);
607 item
->version
= strcpy(versionptr
, version
);
608 item
->description
= description
? strcpy(descriptionptr
, description
) : NULL
;
610 args
->items
= xrealloc(args
->items
, sizeof(item
) * (args
->n_items
+ 1));
611 args
->items
[args
->n_items
++] = item
;
620 static int opkg_list_find_cmd_sort(const void *a
, const void *b
)
622 const struct opkg_list_find_cmd_item
*pkg_a
= *(const struct opkg_list_find_cmd_item
**)a
;
623 const struct opkg_list_find_cmd_item
*pkg_b
= *(const struct opkg_list_find_cmd_item
**)b
;
624 return strcmp(pkg_a
->name
, pkg_b
->name
);
627 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
630 struct opkg_list_find_cmd_args args
= {
631 .use_desc
= use_desc
,
632 .pkg_name
= (argc
> 0) ? argv
[0] : NULL
636 pkg_hash_load_feeds(SF_NEED_DETAIL
, opkg_list_find_cmd_cb
, &args
);
639 pkg_hash_load_status_files(opkg_list_find_cmd_cb
, &args
);
641 if (args
.n_items
> 1)
642 qsort(args
.items
, args
.n_items
, sizeof(args
.items
[0]),
643 opkg_list_find_cmd_sort
);
645 for (i
= 0; i
< args
.n_items
; i
++) {
648 args
.items
[i
]->version
);
651 printf(" - %lu", (unsigned long) args
.items
[i
]->size
);
653 if (args
.items
[i
]->description
)
654 printf(" - %s", args
.items
[i
]->description
);
666 static int opkg_list_cmd(int argc
, char **argv
)
668 return opkg_list_find_cmd(argc
, argv
, 0);
671 static int opkg_find_cmd(int argc
, char **argv
)
673 return opkg_list_find_cmd(argc
, argv
, 1);
676 static int opkg_list_installed_cmd(int argc
, char **argv
)
679 pkg_vec_t
*available
;
681 char *pkg_name
= NULL
;
686 available
= pkg_vec_alloc();
687 pkg_hash_fetch_all_installed(available
);
688 pkg_vec_sort(available
, pkg_compare_names
);
689 for (i
= 0; i
< available
->len
; i
++) {
690 pkg
= available
->pkgs
[i
];
691 /* if we have package name or pattern and pkg does not match, then skip it */
692 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
697 pkg_vec_free(available
);
702 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
705 pkg_vec_t
*available
;
707 char *pkg_name
= NULL
;
708 conffile_list_elt_t
*iter
;
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 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
721 /* if we have package name or pattern and pkg does not match, then skip it */
722 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
724 if (!cl
|| nv_pair_list_empty(cl
))
726 for (iter
= nv_pair_list_first(cl
); iter
;
727 iter
= nv_pair_list_next(cl
, iter
)) {
728 cf
= (conffile_t
*) iter
->data
;
729 if (cf
->name
&& cf
->value
730 && conffile_has_been_modified(cf
))
731 printf("%s\n", cf
->name
);
734 pkg_vec_free(available
);
738 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
740 struct active_list
*head
= prepare_upgrade_list();
741 struct active_list
*node
= NULL
;
742 pkg_t
*_old_pkg
, *_new_pkg
;
744 for (node
= active_list_next(head
, head
); node
;
745 node
= active_list_next(head
, node
)) {
746 _old_pkg
= node
->pkg
;
748 pkg_hash_fetch_best_installation_candidate_by_name
750 if (_new_pkg
== NULL
)
752 old_v
= pkg_version_str_alloc(_old_pkg
);
753 new_v
= pkg_version_str_alloc(_new_pkg
);
754 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
758 active_list_head_delete(head
);
762 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
765 pkg_vec_t
*available
;
767 char *pkg_name
= NULL
;
774 available
= pkg_vec_alloc();
776 pkg_hash_fetch_all_installed(available
);
778 pkg_hash_fetch_available(available
);
780 for (i
= 0; i
< available
->len
; i
++) {
781 pkg
= available
->pkgs
[i
];
782 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
786 pkg_formatted_info(stdout
, pkg
);
788 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
790 if (conf
->verbosity
>= NOTICE
&& cl
) {
791 conffile_list_elt_t
*iter
;
792 for (iter
= nv_pair_list_first(cl
); iter
;
793 iter
= nv_pair_list_next(cl
, iter
)) {
794 conffile_t
*cf
= (conffile_t
*) iter
->data
;
795 int modified
= conffile_has_been_modified(cf
);
798 "conffile=%s md5sum=%s modified=%d.\n",
799 cf
->name
, cf
->value
, modified
);
803 pkg_vec_free(available
);
808 static int opkg_info_cmd(int argc
, char **argv
)
810 return opkg_info_status_cmd(argc
, argv
, 0);
813 static int opkg_status_cmd(int argc
, char **argv
)
815 return opkg_info_status_cmd(argc
, argv
, 1);
818 static int opkg_configure_cmd(int argc
, char **argv
)
821 char *pkg_name
= NULL
;
826 err
= opkg_configure_packages(pkg_name
);
828 write_status_files_if_changed();
833 static int opkg_remove_cmd(int argc
, char **argv
)
835 int i
, a
, done
, err
= 0;
837 pkg_t
*pkg_to_remove
;
838 pkg_vec_t
*available
;
842 signal(SIGINT
, sigint_handler
);
844 pkg_info_preinstall_check();
846 available
= pkg_vec_alloc();
847 pkg_hash_fetch_all_installed(available
);
849 for (i
= 0; i
< argc
; i
++) {
850 for (a
= 0; a
< available
->len
; a
++) {
851 pkg
= available
->pkgs
[a
];
852 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
855 if (conf
->restrict_to_default_dest
) {
857 pkg_hash_fetch_installed_by_name_dest(pkg
->
863 pkg_hash_fetch_installed_by_name(pkg
->name
);
866 if (pkg_to_remove
== NULL
) {
868 "Package %s is not installed.\n",
872 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
873 opkg_msg(ERROR
, "Package %s not installed.\n",
878 if (opkg_remove_pkg(pkg_to_remove
, 0))
885 pkg_vec_free(available
);
888 opkg_msg(NOTICE
, "No packages removed.\n");
890 write_status_files_if_changed();
894 static int opkg_flag_cmd(int argc
, char **argv
)
898 const char *flags
= argv
[0];
900 signal(SIGINT
, sigint_handler
);
902 for (i
= 1; i
< argc
; i
++) {
903 if (conf
->restrict_to_default_dest
) {
904 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
908 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
912 opkg_msg(ERROR
, "Package %s is not installed.\n",
916 if ((strcmp(flags
, "hold") == 0)
917 || (strcmp(flags
, "noprune") == 0)
918 || (strcmp(flags
, "user") == 0)
919 || (strcmp(flags
, "ok") == 0)) {
920 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
924 * Useful if a package is installed in an offline_root, and
925 * should be configured by opkg-cl configure at a later date.
927 if ((strcmp(flags
, "installed") == 0)
928 || (strcmp(flags
, "unpacked") == 0)) {
929 pkg
->state_status
= pkg_state_status_from_str(flags
);
932 opkg_state_changed
++;
933 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
937 write_status_files_if_changed();
941 static int opkg_files_cmd(int argc
, char **argv
)
945 str_list_elt_t
*iter
;
952 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
954 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
958 files
= pkg_get_installed_files(pkg
);
959 pkg_version
= pkg_version_str_alloc(pkg
);
962 ("Package %s (%s) is installed on %s and has the following files:\n",
963 pkg
->name
, pkg_version
, pkg
->dest
->name
);
965 for (iter
= str_list_first(files
); iter
;
966 iter
= str_list_next(files
, iter
))
967 printf("%s\n", (char *)iter
->data
);
970 pkg_free_installed_files(pkg
);
975 static int opkg_depends_cmd(int argc
, char **argv
)
978 pkg_vec_t
*available_pkgs
;
979 compound_depend_t
*cdep
;
983 pkg_info_preinstall_check();
985 available_pkgs
= pkg_vec_alloc();
987 pkg_hash_fetch_available(available_pkgs
);
989 pkg_hash_fetch_all_installed(available_pkgs
);
991 for (i
= 0; i
< argc
; i
++) {
992 for (j
= 0; j
< available_pkgs
->len
; j
++) {
993 pkg
= available_pkgs
->pkgs
[j
];
995 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
998 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
1000 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
1001 if (cdep
->type
!= DEPEND
)
1004 str
= pkg_depend_str(pkg
, k
);
1005 opkg_msg(NOTICE
, "\t%s\n", str
);
1012 pkg_vec_free(available_pkgs
);
1016 static int pkg_mark_provides(pkg_t
* pkg
)
1018 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
1020 pkg
->parent
->state_flag
|= SF_MARKED
;
1022 while (provider
&& *provider
) {
1023 (*provider
)->state_flag
|= SF_MARKED
;
1030 enum what_field_type
{
1040 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
1041 int argc
, char **argv
)
1043 depend_t
*possibility
;
1044 compound_depend_t
*cdep
, *deps
;
1045 pkg_vec_t
*available_pkgs
;
1049 const char *rel_str
= NULL
;
1052 switch (what_field_type
) {
1054 rel_str
= "depends on";
1057 rel_str
= "conflicts with";
1060 rel_str
= "suggests";
1063 rel_str
= "recommends";
1069 available_pkgs
= pkg_vec_alloc();
1071 if (conf
->query_all
)
1072 pkg_hash_fetch_available(available_pkgs
);
1074 pkg_hash_fetch_all_installed(available_pkgs
);
1076 /* mark the root set */
1077 pkg_vec_clear_marks(available_pkgs
);
1078 opkg_msg(NOTICE
, "Root set:\n");
1079 for (i
= 0; i
< argc
; i
++)
1080 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1082 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1083 pkg
= available_pkgs
->pkgs
[i
];
1084 if (pkg
->state_flag
& SF_MARKED
) {
1085 /* mark the parent (abstract) package */
1086 pkg_mark_provides(pkg
);
1087 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1091 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1095 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1097 pkg
= available_pkgs
->pkgs
[j
];
1099 count = ((what_field_type == CONFLICTS)
1100 ? pkg->conflicts_count
1101 : pkg->pre_depends_count +
1102 pkg->depends_count +
1103 pkg->recommends_count + pkg->suggests_count);
1106 /* skip this package if it is already marked */
1107 if (pkg
->parent
->state_flag
& SF_MARKED
)
1110 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1112 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1113 if (what_field_type
!= cdep
->type
)
1116 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1117 possibility
= cdep
->possibilities
[l
];
1119 if ((possibility
->pkg
->state_flag
1124 /* mark the depending package so we
1125 * won't visit it again */
1126 pkg
->state_flag
|= SF_MARKED
;
1127 pkg_mark_provides(pkg
);
1130 ver
= pkg_version_str_alloc(pkg
);
1131 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1135 possibility
->pkg
->name
);
1137 if (possibility
->version
) {
1138 opkg_msg(NOTICE
, " (%s%s)",
1142 possibility
->version
);
1144 if (!pkg_dependence_satisfiable
1148 opkg_message(NOTICE
, "\n");
1155 } while (changed
&& recursive
);
1157 pkg_vec_free(available_pkgs
);
1162 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1164 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1167 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1169 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1172 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1174 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1177 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1179 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1182 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1184 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1188 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1191 abstract_pkg_t
*apkg
, **abpkgs
;
1194 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1195 const char *rel_str
=
1196 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1199 pkg_info_preinstall_check();
1201 if (conf
->query_all
)
1202 pkg_hash_fetch_available(available_pkgs
);
1204 pkg_hash_fetch_all_installed(available_pkgs
);
1205 for (i
= 0; i
< argc
; i
++) {
1206 const char *target
= argv
[i
];
1209 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1210 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1211 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1212 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1214 while (abpkgs
&& *abpkgs
) {
1217 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1220 opkg_msg(NOTICE
, " %s", pkg
->name
);
1222 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1223 : strcmp(target
, apkg
->name
)))
1224 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1226 opkg_message(NOTICE
, "\n");
1230 pkg_vec_free(available_pkgs
);
1235 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1237 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1240 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1242 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1245 static int opkg_search_cmd(int argc
, char **argv
)
1249 pkg_vec_t
*installed
;
1251 str_list_t
*installed_files
;
1252 str_list_elt_t
*iter
;
1253 char *installed_file
;
1259 installed
= pkg_vec_alloc();
1260 pkg_hash_fetch_all_installed(installed
);
1261 pkg_vec_sort(installed
, pkg_compare_names
);
1263 for (i
= 0; i
< installed
->len
; i
++) {
1264 pkg
= installed
->pkgs
[i
];
1266 installed_files
= pkg_get_installed_files(pkg
);
1268 for (iter
= str_list_first(installed_files
); iter
;
1269 iter
= str_list_next(installed_files
, iter
)) {
1270 installed_file
= (char *)iter
->data
;
1271 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1275 pkg_free_installed_files(pkg
);
1278 pkg_vec_free(installed
);
1283 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1289 /* this is a bit gross */
1292 parse_version(p1
, argv
[0]);
1293 parse_version(p2
, argv
[2]);
1294 rc
= pkg_version_satisfied(p1
, p2
, argv
[1]);
1302 "opkg compare_versions <v1> <op> <v2>\n"
1303 "<op> is one of <= >= << >> =\n");
1308 static int opkg_print_architecture_cmd(int argc
, char **argv
)
1310 nv_pair_list_elt_t
*l
;
1312 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1313 nv_pair_t
*nv
= (nv_pair_t
*) l
->data
;
1314 printf("arch %s %s\n", nv
->name
, nv
->value
);
1319 /* XXX: CLEANUP: The usage strings should be incorporated into this
1320 array for easier maintenance */
1321 static opkg_cmd_t cmds
[] = {
1322 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1323 PFM_DESCRIPTION
| PFM_SOURCE
},
1324 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1325 PFM_DESCRIPTION
| PFM_SOURCE
},
1326 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1327 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1329 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1331 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1333 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1335 {"list_changed_conffiles", 0,
1336 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1337 {"list-changed-conffiles", 0,
1338 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1339 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1340 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1341 PFM_DESCRIPTION
| PFM_SOURCE
},
1342 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1343 PFM_DESCRIPTION
| PFM_SOURCE
},
1344 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1345 PFM_DESCRIPTION
| PFM_SOURCE
},
1346 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1347 PFM_DESCRIPTION
| PFM_SOURCE
},
1348 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1349 PFM_DESCRIPTION
| PFM_SOURCE
},
1350 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1351 PFM_DESCRIPTION
| PFM_SOURCE
},
1352 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1353 PFM_DESCRIPTION
| PFM_SOURCE
},
1354 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1355 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1356 PFM_DESCRIPTION
| PFM_SOURCE
},
1357 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1358 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1359 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1360 PFM_DESCRIPTION
| PFM_SOURCE
},
1361 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1362 PFM_DESCRIPTION
| PFM_SOURCE
},
1363 {"print-installation-architecture", 0,
1364 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1365 PFM_DESCRIPTION
| PFM_SOURCE
},
1366 {"print_installation_architecture", 0,
1367 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1368 PFM_DESCRIPTION
| PFM_SOURCE
},
1369 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1370 PFM_DESCRIPTION
| PFM_SOURCE
},
1371 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1372 PFM_DESCRIPTION
| PFM_SOURCE
},
1373 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1374 PFM_DESCRIPTION
| PFM_SOURCE
},
1375 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1376 PFM_DESCRIPTION
| PFM_SOURCE
},
1377 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1378 PFM_DESCRIPTION
| PFM_SOURCE
},
1379 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1380 PFM_DESCRIPTION
| PFM_SOURCE
},
1381 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1382 PFM_DESCRIPTION
| PFM_SOURCE
},
1383 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1384 PFM_DESCRIPTION
| PFM_SOURCE
},
1387 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1391 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1393 for (i
= 0; i
< num_cmds
; i
++) {
1395 if (strcmp(name
, cmd
->name
) == 0)
1402 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1404 return (cmd
->fun
) (argc
, argv
);