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.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #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"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
47 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
48 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
49 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
50 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
51 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
52 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
53 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
54 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
55 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
56 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
57 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
58 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
59 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
60 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
61 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
62 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
63 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
64 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
65 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
66 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
67 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
68 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
69 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
70 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
71 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
72 static int pkg_mark_provides(pkg_t
*pkg
);
74 /* XXX: CLEANUP: The usage strings should be incorporated into this
75 array for easier maintenance */
76 static opkg_cmd_t cmds
[] = {
77 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
},
78 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
},
79 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
},
80 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
},
81 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
},
82 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
83 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
84 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
85 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
86 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
87 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
88 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
89 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
90 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
91 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
92 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
93 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
94 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
95 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
96 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
97 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
98 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
99 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
100 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
101 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
102 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
103 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
104 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
105 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
106 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
109 static void print_pkg(pkg_t
*pkg
)
111 char *version
= pkg_version_str_alloc(pkg
);
112 if (pkg
->description
)
113 printf("%s - %s - %s\n", pkg
->name
, version
, pkg
->description
);
115 printf("%s - %s\n", pkg
->name
, version
);
119 int opkg_state_changed
;
120 static void write_status_files_if_changed(opkg_conf_t
*conf
)
122 if (opkg_state_changed
&& !conf
->noaction
) {
123 opkg_message(conf
, OPKG_INFO
,
124 " writing status file\n");
125 opkg_conf_write_status_files(conf
);
126 pkg_write_changed_filelists(conf
);
128 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
133 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
135 opkg_cmd_t
*opkg_cmd_find(const char *name
)
140 for (i
=0; i
< num_cmds
; i
++) {
142 if (strcmp(name
, cmd
->name
) == 0) {
150 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
154 result
= (cmd
->fun
)(conf
, argc
, argv
);
162 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
168 pkg_src_list_elt_t
*iter
;
172 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
174 if (! file_is_dir(lists_dir
)) {
175 if (file_exists(lists_dir
)) {
176 opkg_message(conf
, OPKG_ERROR
,
177 "%s: ERROR: %s exists, but is not a directory\n",
178 __FUNCTION__
, lists_dir
);
182 err
= file_mkdir_hier(lists_dir
, 0755);
184 opkg_message(conf
, OPKG_ERROR
,
185 "%s: ERROR: failed to make directory %s: %s\n",
186 __FUNCTION__
, lists_dir
, strerror(errno
));
194 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
195 if (mkdtemp (tmp
) == NULL
) {
201 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
202 char *url
, *list_file_name
;
204 src
= (pkg_src_t
*)iter
->data
;
206 if (src
->extra_data
) /* debian style? */
207 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
208 src
->gzip
? "Packages.gz" : "Packages");
210 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
212 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
217 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
218 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
220 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
221 in
= fopen (tmp_file_name
, "r");
222 out
= fopen (list_file_name
, "w");
231 unlink (tmp_file_name
);
235 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
239 opkg_message(conf
, OPKG_NOTICE
,
240 "Updated list of available packages in %s\n",
244 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
245 if (conf
->check_signature
) {
246 /* download detached signitures to verify the package lists */
247 /* get the url for the sig file */
248 if (src
->extra_data
) /* debian style? */
249 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
252 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
254 /* create temporary file for it */
257 /* Put the signature in the right place */
258 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
260 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
263 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
266 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
268 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
270 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
272 /* We shouldn't unlink the signature ! */
273 // unlink (tmp_file_name);
274 free (tmp_file_name
);
280 free(list_file_name
);
290 struct opkg_intercept
296 typedef struct opkg_intercept
*opkg_intercept_t
;
298 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
300 opkg_intercept_t ctx
;
303 ctx
= xcalloc(1, sizeof (*ctx
));
304 ctx
->oldpath
= xstrdup(getenv("PATH"));
305 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
306 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
308 if (mkdtemp(ctx
->statedir
) == NULL
) {
309 fprintf(stderr
, "%s: mkdtemp: %s\n", __FUNCTION__
, strerror(errno
));
317 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
318 setenv("PATH", newpath
, 1);
324 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
329 setenv ("PATH", ctx
->oldpath
, 1);
332 dir
= opendir (ctx
->statedir
);
335 while (de
= readdir (dir
), de
!= NULL
) {
338 if (de
->d_name
[0] == '.')
341 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
342 if (access (path
, X_OK
) == 0) {
349 perror (ctx
->statedir
);
352 free (ctx
->statedir
);
358 /* For package pkg do the following: If it is already visited, return. If not,
359 add it in visited list and recurse to its deps. Finally, add it to ordered
361 pkg_vec all contains all available packages in repos.
362 pkg_vec visited contains packages already visited by this function, and is
363 used to end recursion and avoid an infinite loop on graph cycles.
364 pkg_vec ordered will finally contain the ordered set of packages.
366 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
367 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
372 compound_depend_t
* compound_depend
;
373 depend_t
** possible_satisfiers
;
374 abstract_pkg_t
*abpkg
;
375 abstract_pkg_t
**dependents
;
377 /* If it's just an available package, that is, not installed and not even
379 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
380 would do here. However, if there is an intermediate node (pkg) that is
381 configured and installed between two unpacked packages, the latter
382 won't be properly reordered, unless all installed/unpacked pkgs are
384 if (pkg
->state_status
== SS_NOT_INSTALLED
)
387 /* If the package has already been visited (by this function), skip it */
388 for(j
= 0; j
< visited
->len
; j
++)
389 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
390 opkg_message(conf
, OPKG_INFO
,
391 " pkg: %s already visited\n", pkg
->name
);
395 pkg_vec_insert(visited
, pkg
);
397 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
398 pkg
->recommends_count
+ pkg
->suggests_count
;
400 opkg_message(conf
, OPKG_INFO
,
401 " pkg: %s\n", pkg
->name
);
403 /* Iterate over all the dependencies of pkg. For each one, find a package
404 that is either installed or unpacked and satisfies this dependency.
405 (there should only be one such package per dependency installed or
406 unpacked). Then recurse to the dependency package */
407 for (j
=0; j
< count
; j
++) {
408 compound_depend
= &pkg
->depends
[j
];
409 possible_satisfiers
= compound_depend
->possibilities
;
410 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
411 abpkg
= possible_satisfiers
[k
]->pkg
;
412 dependents
= abpkg
->provided_by
->pkgs
;
414 if (dependents
!= NULL
)
415 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
416 opkg_message(conf
, OPKG_INFO
,
417 " Descending on pkg: %s\n",
418 dependents
[l
]->name
);
420 /* find whether dependent l is installed or unpacked,
421 * and then find which package in the list satisfies it */
422 for(m
= 0; m
< all
->len
; m
++) {
424 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
425 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
426 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
428 /* Stop the outer loop */
429 l
= abpkg
->provided_by
->len
;
430 /* break from the inner loop */
439 /* When all recursions from this node down, are over, and all
440 dependencies have been added in proper order in the ordered array, add
441 also the package pkg to ordered array */
442 pkg_vec_insert(ordered
, pkg
);
448 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
450 pkg_vec_t
*all
, *ordered
, *visited
;
456 opkg_message(conf
, OPKG_INFO
,
457 "Configuring unpacked packages\n");
460 all
= pkg_vec_alloc();
462 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
464 /* Reorder pkgs in order to be configured according to the Depends: tag
466 opkg_message(conf
, OPKG_INFO
,
467 "Reordering packages before configuring them...\n");
468 ordered
= pkg_vec_alloc();
469 visited
= pkg_vec_alloc();
470 for(i
= 0; i
< all
->len
; i
++) {
472 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
475 ic
= opkg_prep_intercepts (conf
);
481 for(i
= 0; i
< all
->len
; i
++) {
484 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
487 if (pkg
->state_status
== SS_UNPACKED
) {
488 opkg_message(conf
, OPKG_NOTICE
,
489 "Configuring %s\n", pkg
->name
);
491 r
= opkg_configure(conf
, pkg
);
493 pkg
->state_status
= SS_INSTALLED
;
494 pkg
->parent
->state_status
= SS_INSTALLED
;
495 pkg
->state_flag
&= ~SF_PREFER
;
503 r
= opkg_finalize_intercepts (ic
);
509 pkg_vec_free(ordered
);
510 pkg_vec_free(visited
);
515 static opkg_conf_t
*global_conf
;
517 static void sigint_handler(int sig
)
519 signal(sig
, SIG_DFL
);
520 opkg_message(NULL
, OPKG_NOTICE
,
521 "opkg: interrupted. writing out status database\n");
522 write_status_files_if_changed(global_conf
);
526 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
533 signal(SIGINT
, sigint_handler
);
536 * Now scan through package names and install
538 for (i
=0; i
< argc
; i
++) {
541 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
542 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
543 if (err
!= EINVAL
&& err
!= 0)
546 pkg_info_preinstall_check(conf
);
548 for (i
=0; i
< argc
; i
++) {
550 err
= opkg_install_by_name(conf
, arg
);
551 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
552 opkg_message(conf
, OPKG_ERROR
,
553 "Cannot find package %s.\n",
558 opkg_configure_packages(conf
, NULL
);
560 write_status_files_if_changed(conf
);
565 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
572 signal(SIGINT
, sigint_handler
);
575 for (i
=0; i
< argc
; i
++) {
578 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
579 if (err
!= EINVAL
&& err
!= 0)
582 pkg_info_preinstall_check(conf
);
584 for (i
=0; i
< argc
; i
++) {
586 if (conf
->restrict_to_default_dest
) {
587 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
591 opkg_message(conf
, OPKG_NOTICE
,
592 "Package %s not installed in %s\n",
593 argv
[i
], conf
->default_dest
->name
);
597 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
601 opkg_upgrade_pkg(conf
, pkg
);
603 opkg_install_by_name(conf
, arg
);
607 pkg_vec_t
*installed
= pkg_vec_alloc();
609 pkg_info_preinstall_check(conf
);
611 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
612 for (i
= 0; i
< installed
->len
; i
++) {
613 pkg
= installed
->pkgs
[i
];
614 opkg_upgrade_pkg(conf
, pkg
);
616 pkg_vec_free(installed
);
619 opkg_configure_packages(conf
, NULL
);
621 write_status_files_if_changed(conf
);
626 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
632 pkg_info_preinstall_check(conf
);
633 for (i
= 0; i
< argc
; i
++) {
636 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
638 opkg_message(conf
, OPKG_ERROR
,
639 "Cannot find package %s.\n"
640 "Check the spelling or perhaps run 'opkg update'\n",
645 err
= opkg_download_pkg(conf
, pkg
, ".");
648 opkg_message(conf
, OPKG_ERROR
,
649 "Failed to download %s\n", pkg
->name
);
651 opkg_message(conf
, OPKG_NOTICE
,
652 "Downloaded %s as %s\n",
653 pkg
->name
, pkg
->local_filename
);
661 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
664 pkg_vec_t
*available
;
666 char *pkg_name
= NULL
;
671 available
= pkg_vec_alloc();
672 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
673 pkg_vec_sort(available
, pkg_compare_names
);
674 for (i
=0; i
< available
->len
; i
++) {
675 pkg
= available
->pkgs
[i
];
676 /* if we have package name or pattern and pkg does not match, then skip it */
677 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
681 pkg_vec_free(available
);
687 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
690 pkg_vec_t
*available
;
692 char *pkg_name
= NULL
;
697 available
= pkg_vec_alloc();
698 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
699 pkg_vec_sort(available
, pkg_compare_names
);
700 for (i
=0; i
< available
->len
; i
++) {
701 pkg
= available
->pkgs
[i
];
702 /* if we have package name or pattern and pkg does not match, then skip it */
703 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
708 pkg_vec_free(available
);
713 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
715 struct active_list
*head
= prepare_upgrade_list(conf
);
716 struct active_list
*node
=NULL
;
717 pkg_t
*_old_pkg
, *_new_pkg
;
719 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
720 _old_pkg
= list_entry(node
, pkg_t
, list
);
721 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, _old_pkg
->name
, NULL
);
722 old_v
= pkg_version_str_alloc(_old_pkg
);
723 new_v
= pkg_version_str_alloc(_new_pkg
);
724 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
728 active_list_head_delete(head
);
732 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
735 pkg_vec_t
*available
;
737 char *pkg_name
= NULL
;
743 available
= pkg_vec_alloc();
745 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
747 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
749 for (i
=0; i
< available
->len
; i
++) {
750 pkg
= available
->pkgs
[i
];
751 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
755 pkg_formatted_info(stdout
, pkg
);
757 if (conf
->verbosity
>= OPKG_NOTICE
) {
758 conffile_list_elt_t
*iter
;
759 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
760 conffile_t
*cf
= (conffile_t
*)iter
->data
;
761 int modified
= conffile_has_been_modified(conf
, cf
);
763 opkg_message(conf
, OPKG_NOTICE
,
764 "conffile=%s md5sum=%s modified=%d\n",
765 cf
->name
, cf
->value
, modified
);
769 pkg_vec_free(available
);
774 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
776 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
779 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
781 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
784 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
789 char *pkg_name
= NULL
;
793 err
= opkg_configure_packages (conf
, pkg_name
);
796 err
= opkg_configure_packages (conf
, NULL
);
799 write_status_files_if_changed(conf
);
804 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
810 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
811 err
= glob(globpattern
, 0, NULL
, &globbuf
);
817 opkg_message(conf
, OPKG_NOTICE
,
818 "The following packages in %s will now be installed.\n",
820 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
821 opkg_message(conf
, OPKG_NOTICE
,
822 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
824 opkg_message(conf
, OPKG_NOTICE
, "\n");
825 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
826 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
828 err
= unlink(globbuf
.gl_pathv
[i
]);
830 opkg_message(conf
, OPKG_ERROR
,
831 "%s: ERROR: failed to unlink %s: %s\n",
832 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
842 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
846 pkg_t
*pkg_to_remove
;
847 pkg_vec_t
*available
;
848 char *pkg_name
= NULL
;
850 signal(SIGINT
, sigint_handler
);
852 // ENH: Add the "no pkg removed" just in case.
856 pkg_info_preinstall_check(conf
);
858 available
= pkg_vec_alloc();
859 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
860 for (i
=0; i
< argc
; i
++) {
861 pkg_name
= xcalloc(1, strlen(argv
[i
])+2);
862 strcpy(pkg_name
,argv
[i
]);
863 for (a
=0; a
< available
->len
; a
++) {
864 pkg
= available
->pkgs
[a
];
865 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
868 if (conf
->restrict_to_default_dest
) {
869 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
873 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
876 if (pkg_to_remove
== NULL
) {
877 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
880 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
881 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
884 opkg_remove_pkg(conf
, pkg_to_remove
,0);
889 pkg_vec_free(available
);
891 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
893 int flagged_pkg_count
= 0;
896 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
898 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
899 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
900 if (pkg
->state_flag
& SF_USER
) {
903 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
904 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
907 if (!flagged_pkg_count
) {
908 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
909 "so refusing to uninstall unflagged non-leaf packages\n");
913 /* find packages not flagged SF_USER (i.e., installed to
914 * satisfy a dependence) and not having any dependents, and
918 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
919 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
920 if (!(pkg
->state_flag
& SF_USER
)
921 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
923 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
924 opkg_remove_pkg(conf
, pkg
,0);
929 pkg_vec_free(installed_pkgs
);
933 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
935 write_status_files_if_changed(conf
);
939 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
945 signal(SIGINT
, sigint_handler
);
947 pkg_info_preinstall_check(conf
);
949 for (i
=0; i
< argc
; i
++) {
950 if (conf
->restrict_to_default_dest
) {
951 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
955 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
959 opkg_message(conf
, OPKG_ERROR
,
960 "Package %s is not installed.\n", argv
[i
]);
963 opkg_purge_pkg(conf
, pkg
);
966 write_status_files_if_changed(conf
);
970 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
974 const char *flags
= argv
[0];
977 signal(SIGINT
, sigint_handler
);
979 for (i
=1; i
< argc
; i
++) {
980 if (conf
->restrict_to_default_dest
) {
981 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
985 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
989 opkg_message(conf
, OPKG_ERROR
,
990 "Package %s is not installed.\n", argv
[i
]);
993 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
994 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
995 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
997 /* pb_ asked this feature 03292004 */
998 /* Actually I will use only this two, but this is an open for various status */
999 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1000 pkg
->state_status
= pkg_state_status_from_str(flags
);
1002 opkg_state_changed
++;
1003 opkg_message(conf
, OPKG_NOTICE
,
1004 "Setting flags for package %s to %s\n",
1008 write_status_files_if_changed(conf
);
1012 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1016 str_list_elt_t
*iter
;
1023 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1026 opkg_message(conf
, OPKG_ERROR
,
1027 "Package %s not installed.\n", argv
[0]);
1031 files
= pkg_get_installed_files(pkg
);
1032 pkg_version
= pkg_version_str_alloc(pkg
);
1034 printf("Package %s (%s) is installed on %s and has the following files:\n",
1035 pkg
->name
, pkg_version
, pkg
->dest
->name
);
1037 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
1038 printf("%s\n", (char *)iter
->data
);
1041 pkg_free_installed_files(pkg
);
1046 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1050 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1051 const char *rel_str
= "depends on";
1054 pkg_info_preinstall_check(conf
);
1056 if (conf
->query_all
)
1057 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1059 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1060 for (i
= 0; i
< argc
; i
++) {
1061 const char *target
= argv
[i
];
1064 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1066 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1067 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1068 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1070 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1071 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1072 target
, pkg
->architecture
, rel_str
);
1073 for (k
= 0; k
< count
; k
++) {
1074 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1076 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1077 depend_t
*possibility
= cdepend
->possibilities
[l
];
1078 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1079 if (conf
->verbosity
>= OPKG_NOTICE
) {
1080 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1081 if (possibility
->version
) {
1082 char *typestr
= NULL
;
1083 switch (possibility
->constraint
) {
1084 case NONE
: typestr
= "none"; break;
1085 case EARLIER
: typestr
= "<"; break;
1086 case EARLIER_EQUAL
: typestr
= "<="; break;
1087 case EQUAL
: typestr
= "="; break;
1088 case LATER_EQUAL
: typestr
= ">="; break;
1089 case LATER
: typestr
= ">"; break;
1091 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1094 opkg_message(conf
, OPKG_ERROR
, "\n");
1100 pkg_vec_free(available_pkgs
);
1105 enum what_field_type
{
1114 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1118 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1119 const char *rel_str
= NULL
;
1123 switch (what_field_type
) {
1124 case WHATDEPENDS
: rel_str
= "depends on"; break;
1125 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1126 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1127 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1128 case WHATPROVIDES
: rel_str
= "provides"; break;
1129 case WHATREPLACES
: rel_str
= "replaces"; break;
1132 if (conf
->query_all
)
1133 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1135 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1137 /* mark the root set */
1138 pkg_vec_clear_marks(available_pkgs
);
1139 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1140 for (i
= 0; i
< argc
; i
++) {
1141 const char *dependee_pattern
= argv
[i
];
1142 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1144 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1145 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1146 if (pkg
->state_flag
& SF_MARKED
) {
1147 /* mark the parent (abstract) package */
1148 pkg_mark_provides(pkg
);
1149 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1153 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1158 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1159 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1161 int count
= ((what_field_type
== WHATCONFLICTS
)
1162 ? pkg
->conflicts_count
1163 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1164 /* skip this package if it is already marked */
1165 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1168 for (k
= 0; k
< count
; k
++) {
1169 compound_depend_t
*cdepend
=
1170 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1172 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1173 depend_t
*possibility
= cdepend
->possibilities
[l
];
1174 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1175 /* mark the depending package so we won't visit it again */
1176 pkg
->state_flag
|= SF_MARKED
;
1177 pkg_mark_provides(pkg
);
1180 if (conf
->verbosity
>= OPKG_NOTICE
) {
1181 char *ver
= pkg_version_str_alloc(pkg
);
1182 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1183 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1184 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1185 if (possibility
->version
) {
1186 char *typestr
= NULL
;
1187 switch (possibility
->constraint
) {
1188 case NONE
: typestr
= "none"; break;
1189 case EARLIER
: typestr
= "<"; break;
1190 case EARLIER_EQUAL
: typestr
= "<="; break;
1191 case EQUAL
: typestr
= "="; break;
1192 case LATER_EQUAL
: typestr
= ">="; break;
1193 case LATER
: typestr
= ">"; break;
1195 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1198 if (!pkg_dependence_satisfiable(conf
, possibility
))
1199 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1201 opkg_message(conf
, OPKG_NOTICE
, "\n");
1209 } while (changed
&& recursive
);
1210 pkg_vec_free(available_pkgs
);
1216 static int pkg_mark_provides(pkg_t
*pkg
)
1218 int provides_count
= pkg
->provides_count
;
1219 abstract_pkg_t
**provides
= pkg
->provides
;
1221 pkg
->parent
->state_flag
|= SF_MARKED
;
1222 for (i
= 0; i
< provides_count
; i
++) {
1223 provides
[i
]->state_flag
|= SF_MARKED
;
1228 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1230 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1232 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1234 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1237 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1239 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1242 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1244 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1247 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1249 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1252 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1256 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1257 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1260 pkg_info_preinstall_check(conf
);
1262 if (conf
->query_all
)
1263 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1265 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1266 for (i
= 0; i
< argc
; i
++) {
1267 const char *target
= argv
[i
];
1270 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1272 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1273 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1275 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1276 for (k
= 0; k
< count
; k
++) {
1277 abstract_pkg_t
*apkg
=
1278 ((what_field_type
== WHATPROVIDES
)
1280 : pkg
->replaces
[k
]);
1281 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1282 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1283 if (strcmp(target
, apkg
->name
) != 0)
1284 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1285 opkg_message(conf
, OPKG_ERROR
, "\n");
1290 pkg_vec_free(available_pkgs
);
1295 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1297 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1300 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1302 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1305 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1309 pkg_vec_t
*installed
;
1311 str_list_t
*installed_files
;
1312 str_list_elt_t
*iter
;
1313 char *installed_file
;
1319 installed
= pkg_vec_alloc();
1320 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1321 pkg_vec_sort(installed
, pkg_compare_names
);
1323 for (i
=0; i
< installed
->len
; i
++) {
1324 pkg
= installed
->pkgs
[i
];
1326 installed_files
= pkg_get_installed_files(pkg
);
1328 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1329 installed_file
= (char *)iter
->data
;
1330 if (fnmatch(argv
[0], installed_file
, 0)==0)
1334 pkg_free_installed_files(pkg
);
1337 pkg_vec_free(installed
);
1342 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1345 /* this is a bit gross */
1347 parse_version(&p1
, argv
[0]);
1348 parse_version(&p2
, argv
[2]);
1349 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1351 opkg_message(conf
, OPKG_ERROR
,
1352 "opkg compare_versions <v1> <op> <v2>\n"
1353 "<op> is one of <= >= << >> =\n");
1358 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1360 nv_pair_list_elt_t
*l
;
1362 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1363 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1364 printf("arch %s %s\n", nv
->name
, nv
->value
);