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.
23 #include "opkg_conf.h"
25 #include "opkg_message.h"
28 #include "pkg_parse.h"
29 #include "sprintf_alloc.h"
31 #include "file_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
40 #include "opkg_download.h"
41 #include "opkg_install.h"
42 #include "opkg_upgrade.h"
43 #include "opkg_remove.h"
44 #include "opkg_configure.h"
45 #include "opkg_message.h"
48 static void *p_userdata
= NULL
;
50 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
51 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
52 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
53 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
54 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
55 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
56 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
57 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
58 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
59 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
60 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
61 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
62 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
63 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
64 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
65 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
66 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
67 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
68 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
69 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
70 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
71 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
72 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
73 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
74 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
75 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
76 static int pkg_mark_provides(pkg_t
*pkg
);
78 /* XXX: CLEANUP: The usage strings should be incorporated into this
79 array for easier maintenance */
80 static opkg_cmd_t cmds
[] = {
81 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
},
82 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
},
83 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
},
84 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
},
85 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
},
86 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
87 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
88 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
89 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
90 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
91 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
92 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
93 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
94 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
95 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
96 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
97 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
98 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
99 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
100 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
101 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
102 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
103 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
104 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
105 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
106 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
107 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
108 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
109 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
110 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
113 int opkg_state_changed
;
114 static void write_status_files_if_changed(opkg_conf_t
*conf
)
116 if (opkg_state_changed
&& !conf
->noaction
) {
117 opkg_message(conf
, OPKG_INFO
,
118 " writing status file\n");
119 opkg_conf_write_status_files(conf
);
120 pkg_write_changed_filelists(conf
);
122 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
127 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
129 opkg_cmd_t
*opkg_cmd_find(const char *name
)
134 for (i
=0; i
< num_cmds
; i
++) {
136 if (strcmp(name
, cmd
->name
) == 0) {
144 void opkg_print_error_list (opkg_conf_t
*conf
)
147 reverse_error_list(&error_list
);
149 printf ("Collected errors:\n");
150 /* Here we print the errors collected and free the list */
151 while (error_list
!= NULL
) {
152 printf (" * %s", error_list
->errmsg
);
153 error_list
= error_list
->next
;
161 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
164 p_userdata
= userdata
;
167 result
= (cmd
->fun
)(conf
, argc
, argv
);
169 if ( result
!= 0 && !error_list
) {
170 opkg_message(conf
, OPKG_NOTICE
, "An error occurred, return value: %d.\n", result
);
173 opkg_print_error_list (conf
);
179 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
185 pkg_src_list_elt_t
*iter
;
189 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
191 if (! file_is_dir(lists_dir
)) {
192 if (file_exists(lists_dir
)) {
193 opkg_message(conf
, OPKG_ERROR
,
194 "%s: ERROR: %s exists, but is not a directory\n",
195 __FUNCTION__
, lists_dir
);
199 err
= file_mkdir_hier(lists_dir
, 0755);
201 opkg_message(conf
, OPKG_ERROR
,
202 "%s: ERROR: failed to make directory %s: %s\n",
203 __FUNCTION__
, lists_dir
, strerror(errno
));
212 tmp
= strdup ("/tmp/opkg.XXXXXX");
214 if (mkdtemp (tmp
) == NULL
) {
220 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
221 char *url
, *list_file_name
;
223 src
= (pkg_src_t
*)iter
->data
;
225 if (src
->extra_data
) /* debian style? */
226 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
227 src
->gzip
? "Packages.gz" : "Packages");
229 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
231 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
236 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
237 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
239 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
240 in
= fopen (tmp_file_name
, "r");
241 out
= fopen (list_file_name
, "w");
250 unlink (tmp_file_name
);
253 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
257 opkg_message(conf
, OPKG_NOTICE
,
258 "Updated list of available packages in %s\n",
262 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
263 if (conf
->check_signature
) {
264 /* download detached signitures to verify the package lists */
265 /* get the url for the sig file */
266 if (src
->extra_data
) /* debian style? */
267 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
270 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
272 /* create temporary file for it */
275 /* Put the signature in the right place */
276 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
278 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
281 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
284 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
286 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
288 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
290 /* We shouldn't unlink the signature ! */
291 // unlink (tmp_file_name);
292 free (tmp_file_name
);
298 free(list_file_name
);
308 struct opkg_intercept
314 typedef struct opkg_intercept
*opkg_intercept_t
;
316 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
318 opkg_intercept_t ctx
;
323 ctx
= calloc (1, sizeof (*ctx
));
324 oldpath
= getenv ("PATH");
326 ctx
->oldpath
= strdup (oldpath
);
332 sprintf_alloc (&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
333 setenv ("PATH", newpath
, 1);
338 sprintf_alloc (&ctx
->statedir
, "/tmp/opkg-intercept-%d-%d", getpid (), gen
);
339 if (mkdir (ctx
->statedir
, 0770) < 0) {
340 if (errno
== EEXIST
) {
341 free (ctx
->statedir
);
345 perror (ctx
->statedir
);
348 setenv ("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
352 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
359 setenv ("PATH", ctx
->oldpath
, 1);
365 dir
= opendir (ctx
->statedir
);
368 while (de
= readdir (dir
), de
!= NULL
) {
371 if (de
->d_name
[0] == '.')
374 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
375 if (access (path
, X_OK
) == 0) {
385 perror (ctx
->statedir
);
387 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
391 free (ctx
->statedir
);
397 /* For package pkg do the following: If it is already visited, return. If not,
398 add it in visited list and recurse to its deps. Finally, add it to ordered
400 pkg_vec all contains all available packages in repos.
401 pkg_vec visited contains packages already visited by this function, and is
402 used to end recursion and avoid an infinite loop on graph cycles.
403 pkg_vec ordered will finally contain the ordered set of packages.
405 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
406 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
411 compound_depend_t
* compound_depend
;
412 depend_t
** possible_satisfiers
;
413 abstract_pkg_t
*abpkg
;
414 abstract_pkg_t
**dependents
;
416 /* If it's just an available package, that is, not installed and not even
418 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
419 would do here. However, if there is an intermediate node (pkg) that is
420 configured and installed between two unpacked packages, the latter
421 won't be properly reordered, unless all installed/unpacked pkgs are
423 if (pkg
->state_status
== SS_NOT_INSTALLED
)
426 /* If the package has already been visited (by this function), skip it */
427 for(j
= 0; j
< visited
->len
; j
++)
428 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
429 opkg_message(conf
, OPKG_INFO
,
430 " pkg: %s already visited\n", pkg
->name
);
434 pkg_vec_insert(visited
, pkg
);
436 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
437 pkg
->recommends_count
+ pkg
->suggests_count
;
439 opkg_message(conf
, OPKG_INFO
,
440 " pkg: %s\n", pkg
->name
);
442 /* Iterate over all the dependencies of pkg. For each one, find a package
443 that is either installed or unpacked and satisfies this dependency.
444 (there should only be one such package per dependency installed or
445 unpacked). Then recurse to the dependency package */
446 for (j
=0; j
< count
; j
++) {
447 compound_depend
= &pkg
->depends
[j
];
448 possible_satisfiers
= compound_depend
->possibilities
;
449 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
450 abpkg
= possible_satisfiers
[k
]->pkg
;
451 dependents
= abpkg
->provided_by
->pkgs
;
453 if (dependents
!= NULL
)
454 while (dependents
[l
] != NULL
&& l
< abpkg
->provided_by
->len
) {
455 opkg_message(conf
, OPKG_INFO
,
456 " Descending on pkg: %s\n",
457 dependents
[l
]->name
);
459 /* find whether dependent l is installed or unpacked,
460 * and then find which package in the list satisfies it */
461 for(m
= 0; m
< all
->len
; m
++) {
463 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
464 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
465 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
467 /* Stop the outer loop */
468 l
= abpkg
->provided_by
->len
;
469 /* break from the inner loop */
478 /* When all recursions from this node down, are over, and all
479 dependencies have been added in proper order in the ordered array, add
480 also the package pkg to ordered array */
481 pkg_vec_insert(ordered
, pkg
);
487 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
489 pkg_vec_t
*all
, *ordered
, *visited
;
495 opkg_message(conf
, OPKG_INFO
,
496 "Configuring unpacked packages\n");
499 all
= pkg_vec_alloc();
501 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
503 /* Reorder pkgs in order to be configured according to the Depends: tag
505 opkg_message(conf
, OPKG_INFO
,
506 "Reordering packages before configuring them...\n");
507 ordered
= pkg_vec_alloc();
508 visited
= pkg_vec_alloc();
509 for(i
= 0; i
< all
->len
; i
++) {
511 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
515 ic
= opkg_prep_intercepts (conf
);
517 for(i
= 0; i
< all
->len
; i
++) {
520 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
523 if (pkg
->state_status
== SS_UNPACKED
) {
524 opkg_message(conf
, OPKG_NOTICE
,
525 "Configuring %s\n", pkg
->name
);
527 r
= opkg_configure(conf
, pkg
);
529 pkg
->state_status
= SS_INSTALLED
;
530 pkg
->parent
->state_status
= SS_INSTALLED
;
531 pkg
->state_flag
&= ~SF_PREFER
;
539 r
= opkg_finalize_intercepts (ic
);
544 pkg_vec_free(ordered
);
545 pkg_vec_free(visited
);
550 static opkg_conf_t
*global_conf
;
552 static void sigint_handler(int sig
)
554 signal(sig
, SIG_DFL
);
555 opkg_message(NULL
, OPKG_NOTICE
,
556 "opkg: interrupted. writing out status database\n");
557 write_status_files_if_changed(global_conf
);
561 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
568 signal(SIGINT
, sigint_handler
);
571 * Now scan through package names and install
573 for (i
=0; i
< argc
; i
++) {
576 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
577 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
578 if (err
!= EINVAL
&& err
!= 0)
581 pkg_info_preinstall_check(conf
);
583 for (i
=0; i
< argc
; i
++) {
585 err
= opkg_install_by_name(conf
, arg
);
586 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
587 opkg_message(conf
, OPKG_ERROR
,
588 "Cannot find package %s.\n",
593 /* recheck to verify that all dependences are satisfied */
594 if (0) opkg_satisfy_all_dependences(conf
);
596 opkg_configure_packages(conf
, NULL
);
598 write_status_files_if_changed(conf
);
603 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
610 signal(SIGINT
, sigint_handler
);
613 for (i
=0; i
< argc
; i
++) {
616 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
617 if (err
!= EINVAL
&& err
!= 0)
620 pkg_info_preinstall_check(conf
);
622 for (i
=0; i
< argc
; i
++) {
624 if (conf
->restrict_to_default_dest
) {
625 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
629 opkg_message(conf
, OPKG_NOTICE
,
630 "Package %s not installed in %s\n",
631 argv
[i
], conf
->default_dest
->name
);
635 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
639 opkg_upgrade_pkg(conf
, pkg
);
641 opkg_install_by_name(conf
, arg
);
645 pkg_vec_t
*installed
= pkg_vec_alloc();
647 pkg_info_preinstall_check(conf
);
649 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
650 for (i
= 0; i
< installed
->len
; i
++) {
651 pkg
= installed
->pkgs
[i
];
652 opkg_upgrade_pkg(conf
, pkg
);
654 pkg_vec_free(installed
);
657 /* recheck to verify that all dependences are satisfied */
658 if (0) opkg_satisfy_all_dependences(conf
);
660 opkg_configure_packages(conf
, NULL
);
662 write_status_files_if_changed(conf
);
667 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
673 pkg_info_preinstall_check(conf
);
674 for (i
= 0; i
< argc
; i
++) {
677 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
679 opkg_message(conf
, OPKG_ERROR
,
680 "Cannot find package %s.\n"
681 "Check the spelling or perhaps run 'opkg update'\n",
686 err
= opkg_download_pkg(conf
, pkg
, ".");
689 opkg_message(conf
, OPKG_ERROR
,
690 "Failed to download %s\n", pkg
->name
);
692 opkg_message(conf
, OPKG_NOTICE
,
693 "Downloaded %s as %s\n",
694 pkg
->name
, pkg
->local_filename
);
702 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
705 pkg_vec_t
*available
;
707 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
709 char *pkg_name
= NULL
;
715 available
= pkg_vec_alloc();
716 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
717 pkg_vec_sort(available
, pkg_compare_names
);
718 for (i
=0; i
< available
->len
; i
++) {
719 pkg
= available
->pkgs
[i
];
720 /* if we have package name or pattern and pkg does not match, then skip it */
721 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
723 if (pkg
->description
) {
724 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
726 desc_short
[0] = '\0';
728 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
729 newline
= strchr(desc_short
, '\n');
734 version_str
= pkg_version_str_alloc(pkg
);
735 opkg_cb_list(pkg
->name
,desc_short
,
742 pkg_vec_free(available
);
748 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
751 pkg_vec_t
*available
;
753 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
755 char *pkg_name
= NULL
;
761 available
= pkg_vec_alloc();
762 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
763 pkg_vec_sort(available
, pkg_compare_names
);
764 for (i
=0; i
< available
->len
; i
++) {
765 pkg
= available
->pkgs
[i
];
766 /* if we have package name or pattern and pkg does not match, then skip it */
767 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
769 if (pkg
->description
) {
770 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
772 desc_short
[0] = '\0';
774 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
775 newline
= strchr(desc_short
, '\n');
780 version_str
= pkg_version_str_alloc(pkg
);
781 opkg_cb_list(pkg
->name
,desc_short
,
792 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
794 struct active_list
*head
= prepare_upgrade_list(conf
);
795 struct active_list
*node
=NULL
;
796 pkg_t
*_old_pkg
, *_new_pkg
;
798 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
799 _old_pkg
= list_entry(node
, pkg_t
, list
);
800 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, _old_pkg
->name
, NULL
);
801 old_v
= pkg_version_str_alloc(_old_pkg
);
802 new_v
= pkg_version_str_alloc(_new_pkg
);
804 opkg_cb_list(_old_pkg
->name
, new_v
, old_v
, _old_pkg
->state_status
, p_userdata
);
808 active_list_head_delete(head
);
812 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
815 pkg_vec_t
*available
;
817 char *pkg_name
= NULL
;
818 char **pkg_fields
= NULL
;
826 pkg_fields
= &argv
[1];
830 available
= pkg_vec_alloc();
832 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
834 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
835 for (i
=0; i
< available
->len
; i
++) {
836 pkg
= available
->pkgs
[i
];
837 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
841 buff
= pkg_formatted_info(pkg
);
843 if (opkg_cb_status
) opkg_cb_status(pkg
->name
,
848 We should not forget that actually the pointer is allocated.
849 We need to free it :) ( Thanks florian for seeing the error )
854 if (conf
->verbosity
> 1) {
855 conffile_list_elt_t
*iter
;
856 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
857 conffile_t
*cf
= (conffile_t
*)iter
->data
;
858 int modified
= conffile_has_been_modified(conf
, cf
);
859 opkg_message(conf
, OPKG_NOTICE
, "conffile=%s md5sum=%s modified=%d\n",
860 cf
->name
, cf
->value
, modified
);
864 pkg_vec_free(available
);
869 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
871 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
874 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
876 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
879 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
884 char *pkg_name
= NULL
;
888 err
= opkg_configure_packages (conf
, pkg_name
);
891 err
= opkg_configure_packages (conf
, NULL
);
894 write_status_files_if_changed(conf
);
899 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
905 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
906 err
= glob(globpattern
, 0, NULL
, &globbuf
);
912 opkg_message(conf
, OPKG_NOTICE
,
913 "The following packages in %s will now be installed.\n",
915 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
916 opkg_message(conf
, OPKG_NOTICE
,
917 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
919 opkg_message(conf
, OPKG_NOTICE
, "\n");
920 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
921 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
923 err
= unlink(globbuf
.gl_pathv
[i
]);
925 opkg_message(conf
, OPKG_ERROR
,
926 "%s: ERROR: failed to unlink %s: %s\n",
927 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
937 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
941 pkg_t
*pkg_to_remove
;
942 pkg_vec_t
*available
;
943 char *pkg_name
= NULL
;
945 signal(SIGINT
, sigint_handler
);
947 // ENH: Add the "no pkg removed" just in case.
951 pkg_info_preinstall_check(conf
);
953 available
= pkg_vec_alloc();
954 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
955 for (i
=0; i
< argc
; i
++) {
956 pkg_name
= calloc(1, strlen(argv
[i
])+2);
957 strcpy(pkg_name
,argv
[i
]);
958 for (a
=0; a
< available
->len
; a
++) {
959 pkg
= available
->pkgs
[a
];
960 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
963 if (conf
->restrict_to_default_dest
) {
964 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
968 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
972 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
975 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
976 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
979 opkg_remove_pkg(conf
, pkg_to_remove
,0);
984 pkg_vec_free(available
);
986 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
988 int flagged_pkg_count
= 0;
991 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
993 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
994 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
995 if (pkg
->state_flag
& SF_USER
) {
998 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
999 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
1002 if (!flagged_pkg_count
) {
1003 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
1004 "so refusing to uninstall unflagged non-leaf packages\n");
1008 /* find packages not flagged SF_USER (i.e., installed to
1009 * satisfy a dependence) and not having any dependents, and
1013 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
1014 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
1015 if (!(pkg
->state_flag
& SF_USER
)
1016 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
1018 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
1019 opkg_remove_pkg(conf
, pkg
,0);
1024 pkg_vec_free(installed_pkgs
);
1028 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
1030 write_status_files_if_changed(conf
);
1034 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1040 signal(SIGINT
, sigint_handler
);
1042 pkg_info_preinstall_check(conf
);
1044 for (i
=0; i
< argc
; i
++) {
1045 if (conf
->restrict_to_default_dest
) {
1046 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1048 conf
->default_dest
);
1050 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1054 opkg_message(conf
, OPKG_ERROR
,
1055 "Package %s is not installed.\n", argv
[i
]);
1058 opkg_purge_pkg(conf
, pkg
);
1061 write_status_files_if_changed(conf
);
1065 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1069 const char *flags
= argv
[0];
1072 signal(SIGINT
, sigint_handler
);
1074 for (i
=1; i
< argc
; i
++) {
1075 if (conf
->restrict_to_default_dest
) {
1076 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1078 conf
->default_dest
);
1080 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1084 opkg_message(conf
, OPKG_ERROR
,
1085 "Package %s is not installed.\n", argv
[i
]);
1088 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1089 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1090 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1092 /* pb_ asked this feature 03292004 */
1093 /* Actually I will use only this two, but this is an open for various status */
1094 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1095 pkg
->state_status
= pkg_state_status_from_str(flags
);
1097 opkg_state_changed
++;
1098 opkg_message(conf
, OPKG_NOTICE
,
1099 "Setting flags for package %s to %s\n",
1103 write_status_files_if_changed(conf
);
1107 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1110 str_list_t
*installed_files
;
1111 str_list_elt_t
*iter
;
1113 size_t buff_len
= 8192;
1117 buff
= (char *)calloc(1, buff_len
);
1118 if ( buff
== NULL
) {
1119 fprintf( stderr
,"%s: Unable to allocate memory \n",__FUNCTION__
);
1127 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1130 opkg_message(conf
, OPKG_ERROR
,
1131 "Package %s not installed.\n", argv
[0]);
1135 installed_files
= pkg_get_installed_files(pkg
);
1136 pkg_version
= pkg_version_str_alloc(pkg
);
1140 used_len
= snprintf(buff
, buff_len
, "Package %s (%s) is installed on %s and has the following files:\n",
1141 pkg
->name
, pkg_version
, pkg
->dest
->name
) + 1;
1142 if (used_len
> buff_len
) {
1144 buff
= realloc (buff
, buff_len
);
1147 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1148 used_len
+= strlen (iter
->data
) + 1;
1149 while (buff_len
<= used_len
) {
1151 buff
= realloc (buff
, buff_len
);
1153 strncat(buff
, iter
->data
, buff_len
);
1154 strncat(buff
, "\n", buff_len
);
1156 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1158 pkg_version_str_alloc(pkg
),
1165 pkg_free_installed_files(pkg
);
1170 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1174 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1175 const char *rel_str
= "depends on";
1178 pkg_info_preinstall_check(conf
);
1180 if (conf
->query_all
)
1181 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1183 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1184 for (i
= 0; i
< argc
; i
++) {
1185 const char *target
= argv
[i
];
1188 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1190 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1191 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1192 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1194 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1195 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1196 target
, pkg
->architecture
, rel_str
);
1197 for (k
= 0; k
< count
; k
++) {
1198 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1200 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1201 depend_t
*possibility
= cdepend
->possibilities
[l
];
1202 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1203 if (conf
->verbosity
> 0) {
1204 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1205 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1206 if (possibility
->version
) {
1207 char *typestr
= NULL
;
1208 switch (possibility
->constraint
) {
1209 case NONE
: typestr
= "none"; break;
1210 case EARLIER
: typestr
= "<"; break;
1211 case EARLIER_EQUAL
: typestr
= "<="; break;
1212 case EQUAL
: typestr
= "="; break;
1213 case LATER_EQUAL
: typestr
= ">="; break;
1214 case LATER
: typestr
= ">"; break;
1216 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1220 opkg_message(conf
, OPKG_ERROR
, "\n");
1226 pkg_vec_free(available_pkgs
);
1231 enum what_field_type
{
1240 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1244 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1245 const char *rel_str
= NULL
;
1249 switch (what_field_type
) {
1250 case WHATDEPENDS
: rel_str
= "depends on"; break;
1251 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1252 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1253 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1254 case WHATPROVIDES
: rel_str
= "provides"; break;
1255 case WHATREPLACES
: rel_str
= "replaces"; break;
1258 if (conf
->query_all
)
1259 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1261 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1263 /* mark the root set */
1264 pkg_vec_clear_marks(available_pkgs
);
1265 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1266 for (i
= 0; i
< argc
; i
++) {
1267 const char *dependee_pattern
= argv
[i
];
1268 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1270 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1271 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1272 if (pkg
->state_flag
& SF_MARKED
) {
1273 /* mark the parent (abstract) package */
1274 pkg_mark_provides(pkg
);
1275 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1279 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1284 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1285 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1287 int count
= ((what_field_type
== WHATCONFLICTS
)
1288 ? pkg
->conflicts_count
1289 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1290 /* skip this package if it is already marked */
1291 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1294 for (k
= 0; k
< count
; k
++) {
1295 compound_depend_t
*cdepend
=
1296 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1298 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1299 depend_t
*possibility
= cdepend
->possibilities
[l
];
1300 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1301 /* mark the depending package so we won't visit it again */
1302 pkg
->state_flag
|= SF_MARKED
;
1303 pkg_mark_provides(pkg
);
1306 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1307 if (conf
->verbosity
> 0) {
1308 char *ver
= pkg_version_str_alloc(pkg
);
1309 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1310 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1311 if (possibility
->version
) {
1312 char *typestr
= NULL
;
1313 switch (possibility
->constraint
) {
1314 case NONE
: typestr
= "none"; break;
1315 case EARLIER
: typestr
= "<"; break;
1316 case EARLIER_EQUAL
: typestr
= "<="; break;
1317 case EQUAL
: typestr
= "="; break;
1318 case LATER_EQUAL
: typestr
= ">="; break;
1319 case LATER
: typestr
= ">"; break;
1321 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1324 if (!pkg_dependence_satisfiable(conf
, possibility
))
1325 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1327 opkg_message(conf
, OPKG_NOTICE
, "\n");
1335 } while (changed
&& recursive
);
1336 pkg_vec_free(available_pkgs
);
1342 static int pkg_mark_provides(pkg_t
*pkg
)
1344 int provides_count
= pkg
->provides_count
;
1345 abstract_pkg_t
**provides
= pkg
->provides
;
1347 pkg
->parent
->state_flag
|= SF_MARKED
;
1348 for (i
= 0; i
< provides_count
; i
++) {
1349 provides
[i
]->state_flag
|= SF_MARKED
;
1354 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1356 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1358 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1360 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1363 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1365 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1368 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1370 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1373 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1375 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1378 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1382 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1383 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1386 pkg_info_preinstall_check(conf
);
1388 if (conf
->query_all
)
1389 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1391 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1392 for (i
= 0; i
< argc
; i
++) {
1393 const char *target
= argv
[i
];
1396 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1398 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1399 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1401 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1402 for (k
= 0; k
< count
; k
++) {
1403 abstract_pkg_t
*apkg
=
1404 ((what_field_type
== WHATPROVIDES
)
1406 : pkg
->replaces
[k
]);
1407 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1408 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1409 if (strcmp(target
, apkg
->name
) != 0)
1410 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1411 opkg_message(conf
, OPKG_ERROR
, "\n");
1416 pkg_vec_free(available_pkgs
);
1421 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1423 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1426 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1428 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1431 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1435 pkg_vec_t
*installed
;
1437 str_list_t
*installed_files
;
1438 str_list_elt_t
*iter
;
1439 char *installed_file
;
1445 installed
= pkg_vec_alloc();
1446 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1447 pkg_vec_sort(installed
, pkg_compare_names
);
1449 for (i
=0; i
< installed
->len
; i
++) {
1450 pkg
= installed
->pkgs
[i
];
1452 installed_files
= pkg_get_installed_files(pkg
);
1454 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1455 installed_file
= (char *)iter
->data
;
1456 if (fnmatch(argv
[0], installed_file
, 0)==0) {
1457 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1459 pkg_version_str_alloc(pkg
),
1460 pkg
->state_status
, p_userdata
);
1464 pkg_free_installed_files(pkg
);
1467 pkg_vec_free(installed
);
1472 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1475 /* this is a bit gross */
1477 parseVersion(&p1
, argv
[0]);
1478 parseVersion(&p2
, argv
[2]);
1479 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1481 opkg_message(conf
, OPKG_ERROR
,
1482 "opkg compare_versions <v1> <op> <v2>\n"
1483 "<op> is one of <= >= << >> =\n");
1488 #ifndef HOST_CPU_STR
1489 #define HOST_CPU_STR__(X) #X
1490 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1491 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1494 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1496 nv_pair_list_elt_t
*l
;
1498 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1499 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1500 printf("arch %s %s\n", nv
->name
, nv
->value
);