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.
27 #include "opkg_conf.h"
29 #include "opkg_message.h"
32 #include "pkg_parse.h"
33 #include "sprintf_alloc.h"
35 #include "file_util.h"
36 #include "libbb/libbb.h"
37 #include "opkg_utils.h"
38 #include "opkg_defines.h"
39 #include "opkg_download.h"
40 #include "opkg_install.h"
41 #include "opkg_upgrade.h"
42 #include "opkg_remove.h"
43 #include "opkg_configure.h"
49 char *version
= pkg_version_str_alloc(pkg
);
51 printf("%s - %s - %s\n", pkg
->name
, version
, pkg
->description
);
53 printf("%s - %s\n", pkg
->name
, version
);
57 int opkg_state_changed
;
60 write_status_files_if_changed(void)
62 if (opkg_state_changed
&& !conf
->noaction
) {
63 opkg_msg(INFO
, "Writing status file.\n");
64 opkg_conf_write_status_files();
65 pkg_write_changed_filelists();
67 opkg_msg(DEBUG
, "Nothing to be done.\n");
72 sigint_handler(int sig
)
75 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
76 write_status_files_if_changed();
81 opkg_update_cmd(int argc
, char **argv
)
87 pkg_src_list_elt_t
*iter
;
91 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
93 if (! file_is_dir(lists_dir
)) {
94 if (file_exists(lists_dir
)) {
95 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
100 err
= file_mkdir_hier(lists_dir
, 0755);
109 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
110 if (mkdtemp (tmp
) == NULL
) {
111 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
116 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
117 char *url
, *list_file_name
;
119 src
= (pkg_src_t
*)iter
->data
;
121 if (src
->extra_data
) /* debian style? */
122 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
123 src
->gzip
? "Packages.gz" : "Packages");
125 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
127 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
132 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
133 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
);
135 opkg_msg(NOTICE
, "Inflating %s.\n", url
);
136 in
= fopen (tmp_file_name
, "r");
137 out
= fopen (list_file_name
, "w");
146 unlink (tmp_file_name
);
150 err
= opkg_download(url
, list_file_name
, NULL
, NULL
);
154 opkg_msg(NOTICE
, "Updated list of available packages in %s.\n",
158 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
159 if (conf
->check_signature
) {
160 /* download detached signitures to verify the package lists */
161 /* get the url for the sig file */
162 if (src
->extra_data
) /* debian style? */
163 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
166 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
168 /* create temporary file for it */
171 /* Put the signature in the right place */
172 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
174 err
= opkg_download(url
, tmp_file_name
, NULL
, NULL
);
177 opkg_msg(NOTICE
, "Signature check failed.\n");
179 err
= opkg_verify_file (list_file_name
, tmp_file_name
);
181 opkg_msg(NOTICE
, "Signature check passed.\n");
183 opkg_msg(NOTICE
, "Signature check failed.\n");
186 /* The signature was wrong so delete it */
187 opkg_msg(NOTICE
, "Remove wrong Signature file.\n");
188 unlink (tmp_file_name
);
189 unlink (list_file_name
);
191 /* We shouldn't unlink the signature ! */
192 // unlink (tmp_file_name);
193 free (tmp_file_name
);
199 free(list_file_name
);
209 struct opkg_intercept
215 typedef struct opkg_intercept
*opkg_intercept_t
;
217 static opkg_intercept_t
218 opkg_prep_intercepts(void)
220 opkg_intercept_t ctx
;
223 ctx
= xcalloc(1, sizeof (*ctx
));
224 ctx
->oldpath
= xstrdup(getenv("PATH"));
225 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
226 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
228 if (mkdtemp(ctx
->statedir
) == NULL
) {
229 opkg_perror(ERROR
,"Failed to make temp dir %s", ctx
->statedir
);
237 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
238 setenv("PATH", newpath
, 1);
245 opkg_finalize_intercepts(opkg_intercept_t ctx
)
250 setenv ("PATH", ctx
->oldpath
, 1);
253 dir
= opendir (ctx
->statedir
);
256 while (de
= readdir (dir
), de
!= NULL
) {
259 if (de
->d_name
[0] == '.')
262 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
263 if (access (path
, X_OK
) == 0) {
264 const char *argv
[] = {"sh", "-c", path
, NULL
};
271 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
274 free (ctx
->statedir
);
280 /* For package pkg do the following: If it is already visited, return. If not,
281 add it in visited list and recurse to its deps. Finally, add it to ordered
283 pkg_vec all contains all available packages in repos.
284 pkg_vec visited contains packages already visited by this function, and is
285 used to end recursion and avoid an infinite loop on graph cycles.
286 pkg_vec ordered will finally contain the ordered set of packages.
289 opkg_recurse_pkgs_in_order(pkg_t
*pkg
, pkg_vec_t
*all
,
290 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
295 compound_depend_t
* compound_depend
;
296 depend_t
** possible_satisfiers
;
297 abstract_pkg_t
*abpkg
;
298 abstract_pkg_t
**dependents
;
300 /* If it's just an available package, that is, not installed and not even
302 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
303 would do here. However, if there is an intermediate node (pkg) that is
304 configured and installed between two unpacked packages, the latter
305 won't be properly reordered, unless all installed/unpacked pkgs are
307 if (pkg
->state_status
== SS_NOT_INSTALLED
)
310 /* If the package has already been visited (by this function), skip it */
311 for(j
= 0; j
< visited
->len
; j
++)
312 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
313 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n", pkg
->name
);
317 pkg_vec_insert(visited
, pkg
);
319 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
320 pkg
->recommends_count
+ pkg
->suggests_count
;
322 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
324 /* Iterate over all the dependencies of pkg. For each one, find a package
325 that is either installed or unpacked and satisfies this dependency.
326 (there should only be one such package per dependency installed or
327 unpacked). Then recurse to the dependency package */
328 for (j
=0; j
< count
; j
++) {
329 compound_depend
= &pkg
->depends
[j
];
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
&& dependents
[l
] != NULL
) {
337 opkg_msg(DEBUG
, "Descending on pkg %s.\n",
338 dependents
[l
]->name
);
340 /* find whether dependent l is installed or unpacked,
341 * and then find which package in the list satisfies it */
342 for(m
= 0; m
< all
->len
; m
++) {
344 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
345 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
346 opkg_recurse_pkgs_in_order(dep
, all
,
348 /* Stop the outer loop */
349 l
= abpkg
->provided_by
->len
;
350 /* break from the inner loop */
359 /* When all recursions from this node down, are over, and all
360 dependencies have been added in proper order in the ordered array, add
361 also the package pkg to ordered array */
362 pkg_vec_insert(ordered
, pkg
);
369 opkg_configure_packages(char *pkg_name
)
371 pkg_vec_t
*all
, *ordered
, *visited
;
377 opkg_msg(INFO
, "Configuring unpacked packages.\n");
379 all
= pkg_vec_alloc();
381 pkg_hash_fetch_available(all
);
383 /* Reorder pkgs in order to be configured according to the Depends: tag
385 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
386 ordered
= pkg_vec_alloc();
387 visited
= pkg_vec_alloc();
388 for(i
= 0; i
< all
->len
; i
++) {
390 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
393 ic
= opkg_prep_intercepts();
399 for(i
= 0; i
< ordered
->len
; i
++) {
400 pkg
= ordered
->pkgs
[i
];
402 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
405 if (pkg
->state_status
== SS_UNPACKED
) {
406 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
407 r
= opkg_configure(pkg
);
409 pkg
->state_status
= SS_INSTALLED
;
410 pkg
->parent
->state_status
= SS_INSTALLED
;
411 pkg
->state_flag
&= ~SF_PREFER
;
412 opkg_state_changed
++;
419 if (opkg_finalize_intercepts (ic
))
424 pkg_vec_free(ordered
);
425 pkg_vec_free(visited
);
431 opkg_remove_cmd(int argc
, char **argv
);
434 opkg_install_cmd(int argc
, char **argv
)
440 if (conf
->force_reinstall
) {
441 int saved_force_depends
= conf
->force_depends
;
442 conf
->force_depends
= 1;
443 (void)opkg_remove_cmd(argc
, argv
);
444 conf
->force_depends
= saved_force_depends
;
445 conf
->force_reinstall
= 0;
448 signal(SIGINT
, sigint_handler
);
451 * Now scan through package names and install
453 for (i
=0; i
< argc
; i
++) {
456 opkg_msg(DEBUG2
, "%s\n", arg
);
457 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
460 pkg_info_preinstall_check();
462 for (i
=0; i
< argc
; i
++) {
464 if (opkg_install_by_name(arg
)) {
465 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
470 if (opkg_configure_packages(NULL
))
473 write_status_files_if_changed();
479 opkg_upgrade_cmd(int argc
, char **argv
)
485 signal(SIGINT
, sigint_handler
);
488 for (i
=0; i
< argc
; i
++) {
491 if (opkg_prepare_url_for_install(arg
, &arg
))
494 pkg_info_preinstall_check();
496 for (i
=0; i
< argc
; i
++) {
498 if (conf
->restrict_to_default_dest
) {
499 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
502 opkg_msg(NOTICE
, "Package %s not installed in %s.\n",
503 argv
[i
], conf
->default_dest
->name
);
507 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
510 if (opkg_upgrade_pkg(pkg
))
513 if (opkg_install_by_name(arg
))
518 pkg_vec_t
*installed
= pkg_vec_alloc();
520 pkg_info_preinstall_check();
522 pkg_hash_fetch_all_installed(installed
);
523 for (i
= 0; i
< installed
->len
; i
++) {
524 pkg
= installed
->pkgs
[i
];
525 if (opkg_upgrade_pkg(pkg
))
528 pkg_vec_free(installed
);
531 if (opkg_configure_packages(NULL
))
534 write_status_files_if_changed();
540 opkg_download_cmd(int argc
, char **argv
)
546 pkg_info_preinstall_check();
547 for (i
= 0; i
< argc
; i
++) {
550 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
552 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
556 if (opkg_download_pkg(pkg
, "."))
560 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
562 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
563 pkg
->name
, pkg
->local_filename
);
572 opkg_list_cmd(int argc
, char **argv
)
575 pkg_vec_t
*available
;
577 char *pkg_name
= NULL
;
582 available
= pkg_vec_alloc();
583 pkg_hash_fetch_available(available
);
584 pkg_vec_sort(available
, pkg_compare_names
);
585 for (i
=0; i
< available
->len
; i
++) {
586 pkg
= available
->pkgs
[i
];
587 /* if we have package name or pattern and pkg does not match, then skip it */
588 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
592 pkg_vec_free(available
);
599 opkg_list_installed_cmd(int argc
, char **argv
)
602 pkg_vec_t
*available
;
604 char *pkg_name
= NULL
;
609 available
= pkg_vec_alloc();
610 pkg_hash_fetch_all_installed(available
);
611 pkg_vec_sort(available
, pkg_compare_names
);
612 for (i
=0; i
< available
->len
; i
++) {
613 pkg
= available
->pkgs
[i
];
614 /* if we have package name or pattern and pkg does not match, then skip it */
615 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
620 pkg_vec_free(available
);
626 opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
629 pkg_vec_t
*available
;
631 char *pkg_name
= NULL
;
632 conffile_list_elt_t
*iter
;
638 available
= pkg_vec_alloc();
639 pkg_hash_fetch_all_installed(available
);
640 pkg_vec_sort(available
, pkg_compare_names
);
641 for (i
=0; i
< available
->len
; i
++) {
642 pkg
= available
->pkgs
[i
];
643 /* if we have package name or pattern and pkg does not match, then skip it */
644 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
646 if (nv_pair_list_empty(&pkg
->conffiles
))
648 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
649 cf
= (conffile_t
*)iter
->data
;
650 if (cf
->name
&& cf
->value
&& conffile_has_been_modified(cf
))
651 printf("%s\n", cf
->name
);
654 pkg_vec_free(available
);
659 opkg_list_upgradable_cmd(int argc
, char **argv
)
661 struct active_list
*head
= prepare_upgrade_list();
662 struct active_list
*node
=NULL
;
663 pkg_t
*_old_pkg
, *_new_pkg
;
665 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
666 _old_pkg
= list_entry(node
, pkg_t
, list
);
667 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(_old_pkg
->name
);
668 if (_new_pkg
== NULL
)
670 old_v
= pkg_version_str_alloc(_old_pkg
);
671 new_v
= pkg_version_str_alloc(_new_pkg
);
672 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
676 active_list_head_delete(head
);
681 opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
684 pkg_vec_t
*available
;
686 char *pkg_name
= NULL
;
692 available
= pkg_vec_alloc();
694 pkg_hash_fetch_all_installed(available
);
696 pkg_hash_fetch_available(available
);
698 for (i
=0; i
< available
->len
; i
++) {
699 pkg
= available
->pkgs
[i
];
700 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
704 pkg_formatted_info(stdout
, pkg
);
706 if (conf
->verbosity
>= NOTICE
) {
707 conffile_list_elt_t
*iter
;
708 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
709 conffile_t
*cf
= (conffile_t
*)iter
->data
;
710 int modified
= conffile_has_been_modified(cf
);
712 opkg_msg(INFO
, "conffile=%s md5sum=%s modified=%d.\n",
713 cf
->name
, cf
->value
, modified
);
717 pkg_vec_free(available
);
723 opkg_info_cmd(int argc
, char **argv
)
725 return opkg_info_status_cmd(argc
, argv
, 0);
729 opkg_status_cmd(int argc
, char **argv
)
731 return opkg_info_status_cmd(argc
, argv
, 1);
735 opkg_configure_cmd(int argc
, char **argv
)
738 char *pkg_name
= NULL
;
743 err
= opkg_configure_packages(pkg_name
);
745 write_status_files_if_changed();
751 opkg_remove_cmd(int argc
, char **argv
)
753 int i
, a
, done
, err
= 0;
755 pkg_t
*pkg_to_remove
;
756 pkg_vec_t
*available
;
760 signal(SIGINT
, sigint_handler
);
762 pkg_info_preinstall_check();
764 available
= pkg_vec_alloc();
765 pkg_hash_fetch_all_installed(available
);
767 for (i
=0; i
<argc
; i
++) {
768 for (a
=0; a
<available
->len
; a
++) {
769 pkg
= available
->pkgs
[a
];
770 if (fnmatch(argv
[i
], pkg
->name
, 0)) {
773 if (conf
->restrict_to_default_dest
) {
774 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(
778 pkg_to_remove
= pkg_hash_fetch_installed_by_name(pkg
->name
);
781 if (pkg_to_remove
== NULL
) {
782 opkg_msg(ERROR
, "Package %s is not installed.\n", pkg
->name
);
785 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
786 opkg_msg(ERROR
, "Package %s not installed.\n", pkg
->name
);
790 if (opkg_remove_pkg(pkg_to_remove
, 0))
797 pkg_vec_free(available
);
800 opkg_msg(NOTICE
, "No packages removed.\n");
802 write_status_files_if_changed();
807 opkg_flag_cmd(int argc
, char **argv
)
811 const char *flags
= argv
[0];
813 signal(SIGINT
, sigint_handler
);
815 for (i
=1; i
< argc
; i
++) {
816 if (conf
->restrict_to_default_dest
) {
817 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
820 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
824 opkg_msg(ERROR
, "Package %s is not installed.\n", argv
[i
]);
827 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
828 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
829 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
833 * Useful if a package is installed in an offline_root, and
834 * should be configured by opkg-cl configure at a later date.
836 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
837 pkg
->state_status
= pkg_state_status_from_str(flags
);
840 opkg_state_changed
++;
841 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
845 write_status_files_if_changed();
850 opkg_files_cmd(int argc
, char **argv
)
854 str_list_elt_t
*iter
;
861 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
863 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
867 files
= pkg_get_installed_files(pkg
);
868 pkg_version
= pkg_version_str_alloc(pkg
);
870 printf("Package %s (%s) is installed on %s and has the following files:\n",
871 pkg
->name
, pkg_version
, pkg
->dest
->name
);
873 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
874 printf("%s\n", (char *)iter
->data
);
877 pkg_free_installed_files(pkg
);
883 opkg_depends_cmd(int argc
, char **argv
)
887 pkg_vec_t
*available_pkgs
;
888 compound_depend_t
*cdep
;
892 pkg_info_preinstall_check();
894 available_pkgs
= pkg_vec_alloc();
896 pkg_hash_fetch_available(available_pkgs
);
898 pkg_hash_fetch_all_installed(available_pkgs
);
900 for (i
=0; i
<argc
; i
++) {
901 for (j
=0; j
<available_pkgs
->len
; j
++) {
902 pkg
= available_pkgs
->pkgs
[j
];
904 if (fnmatch(argv
[i
], pkg
->name
, 0) != 0)
907 depends_count
= pkg
->depends_count
+
908 pkg
->pre_depends_count
+
909 pkg
->recommends_count
+
912 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
914 for (k
=0; k
<depends_count
; k
++) {
915 cdep
= &pkg
->depends
[k
];
917 if (cdep
->type
!= DEPEND
)
920 str
= pkg_depend_str(pkg
, k
);
921 opkg_msg(NOTICE
, "\t%s\n", str
);
928 pkg_vec_free(available_pkgs
);
933 pkg_mark_provides(pkg_t
*pkg
)
935 int provides_count
= pkg
->provides_count
;
936 abstract_pkg_t
**provides
= pkg
->provides
;
938 pkg
->parent
->state_flag
|= SF_MARKED
;
939 for (i
= 0; i
< provides_count
; i
++) {
940 provides
[i
]->state_flag
|= SF_MARKED
;
945 enum what_field_type
{
955 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
, int argc
, char **argv
)
957 depend_t
*possibility
;
958 compound_depend_t
*cdep
;
959 pkg_vec_t
*available_pkgs
;
963 const char *rel_str
= NULL
;
966 switch (what_field_type
) {
967 case DEPEND
: rel_str
= "depends on"; break;
968 case CONFLICTS
: rel_str
= "conflicts with"; break;
969 case SUGGEST
: rel_str
= "suggests"; break;
970 case RECOMMEND
: rel_str
= "recommends"; break;
974 available_pkgs
= pkg_vec_alloc();
977 pkg_hash_fetch_available(available_pkgs
);
979 pkg_hash_fetch_all_installed(available_pkgs
);
981 /* mark the root set */
982 pkg_vec_clear_marks(available_pkgs
);
983 opkg_msg(NOTICE
, "Root set:\n");
984 for (i
= 0; i
< argc
; i
++)
985 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
987 for (i
= 0; i
< available_pkgs
->len
; i
++) {
988 pkg
= available_pkgs
->pkgs
[i
];
989 if (pkg
->state_flag
& SF_MARKED
) {
990 /* mark the parent (abstract) package */
991 pkg_mark_provides(pkg
);
992 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
996 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1000 for (j
=0; j
<available_pkgs
->len
; j
++) {
1002 pkg
= available_pkgs
->pkgs
[j
];
1003 count
= ((what_field_type
== CONFLICTS
)
1004 ? pkg
->conflicts_count
1005 : pkg
->pre_depends_count
+
1006 pkg
->depends_count
+
1007 pkg
->recommends_count
+
1008 pkg
->suggests_count
);
1010 /* skip this package if it is already marked */
1011 if (pkg
->parent
->state_flag
& SF_MARKED
)
1014 for (k
=0; k
<count
; k
++) {
1015 cdep
= (what_field_type
== CONFLICTS
)
1016 ? &pkg
->conflicts
[k
]
1019 if (what_field_type
!= cdep
->type
)
1022 for (l
=0; l
<cdep
->possibility_count
; l
++) {
1023 possibility
= cdep
->possibilities
[l
];
1025 if ((possibility
->pkg
->state_flag
1030 /* mark the depending package so we
1031 * won't visit it again */
1032 pkg
->state_flag
|= SF_MARKED
;
1033 pkg_mark_provides(pkg
);
1036 ver
= pkg_version_str_alloc(pkg
);
1037 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1041 possibility
->pkg
->name
);
1043 if (possibility
->version
) {
1044 opkg_msg(NOTICE
, " (%s%s)",
1045 constraint_to_str(possibility
->constraint
),
1046 possibility
->version
);
1048 if (!pkg_dependence_satisfiable(possibility
))
1051 opkg_message(NOTICE
, "\n");
1058 } while (changed
&& recursive
);
1060 pkg_vec_free(available_pkgs
);
1066 opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1068 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1072 opkg_whatdepends_cmd(int argc
, char **argv
)
1074 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1078 opkg_whatsuggests_cmd(int argc
, char **argv
)
1080 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1084 opkg_whatrecommends_cmd(int argc
, char **argv
)
1086 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1090 opkg_whatconflicts_cmd(int argc
, char **argv
)
1092 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1096 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
, char **argv
)
1100 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1101 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1104 pkg_info_preinstall_check();
1106 if (conf
->query_all
)
1107 pkg_hash_fetch_available(available_pkgs
);
1109 pkg_hash_fetch_all_installed(available_pkgs
);
1110 for (i
= 0; i
< argc
; i
++) {
1111 const char *target
= argv
[i
];
1114 opkg_msg(NOTICE
, "What %s %s\n",
1116 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1117 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1119 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1120 for (k
= 0; k
< count
; k
++) {
1121 abstract_pkg_t
*apkg
=
1122 ((what_field_type
== WHATPROVIDES
)
1124 : pkg
->replaces
[k
]);
1125 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1126 opkg_msg(NOTICE
, " %s", pkg
->name
);
1127 if (strcmp(target
, apkg
->name
) != 0)
1128 opkg_msg(NOTICE
, "\t%s %s\n",
1129 rel_str
, apkg
->name
);
1130 opkg_message(NOTICE
, "\n");
1135 pkg_vec_free(available_pkgs
);
1141 opkg_whatprovides_cmd(int argc
, char **argv
)
1143 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1147 opkg_whatreplaces_cmd(int argc
, char **argv
)
1149 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1153 opkg_search_cmd(int argc
, char **argv
)
1157 pkg_vec_t
*installed
;
1159 str_list_t
*installed_files
;
1160 str_list_elt_t
*iter
;
1161 char *installed_file
;
1167 installed
= pkg_vec_alloc();
1168 pkg_hash_fetch_all_installed(installed
);
1169 pkg_vec_sort(installed
, pkg_compare_names
);
1171 for (i
=0; i
< installed
->len
; i
++) {
1172 pkg
= installed
->pkgs
[i
];
1174 installed_files
= pkg_get_installed_files(pkg
);
1176 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1177 installed_file
= (char *)iter
->data
;
1178 if (fnmatch(argv
[0], installed_file
, 0)==0)
1182 pkg_free_installed_files(pkg
);
1185 pkg_vec_free(installed
);
1191 opkg_compare_versions_cmd(int argc
, char **argv
)
1194 /* this is a bit gross */
1196 parse_version(&p1
, argv
[0]);
1197 parse_version(&p2
, argv
[2]);
1198 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1201 "opkg compare_versions <v1> <op> <v2>\n"
1202 "<op> is one of <= >= << >> =\n");
1208 opkg_print_architecture_cmd(int argc
, char **argv
)
1210 nv_pair_list_elt_t
*l
;
1212 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1213 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1214 printf("arch %s %s\n", nv
->name
, nv
->value
);
1220 /* XXX: CLEANUP: The usage strings should be incorporated into this
1221 array for easier maintenance */
1222 static opkg_cmd_t cmds
[] = {
1223 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1224 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1225 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
, PFM_SOURCE
},
1226 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1227 {"list-installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
, PFM_SOURCE
},
1228 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1229 {"list-upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
, PFM_SOURCE
},
1230 {"list_changed_conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1231 {"list-changed-conffiles", 0, (opkg_cmd_fun_t
)opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1232 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
, 0},
1233 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1234 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1235 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1236 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1237 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1238 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1239 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1240 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1241 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1242 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1243 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1244 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1245 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1246 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1247 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1248 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1249 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1250 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1251 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1252 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1253 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1254 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
, PFM_DESCRIPTION
|PFM_SOURCE
},
1258 opkg_cmd_find(const char *name
)
1262 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1264 for (i
=0; i
< num_cmds
; i
++) {
1266 if (strcmp(name
, cmd
->name
) == 0)
1274 opkg_cmd_exec(opkg_cmd_t
*cmd
, int argc
, const char **argv
)
1276 return (cmd
->fun
)(argc
, argv
);