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 ocurred, 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
= conf
->pkg_src_list
.head
; iter
; iter
= iter
->next
) {
221 char *url
, *list_file_name
;
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",
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 sprintf_alloc (&tmp_file_name
, "%s/%s", tmp
, "Packages.sig");
277 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
280 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
283 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
285 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
287 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
289 unlink (tmp_file_name
);
290 free (tmp_file_name
);
293 opkg_message (conf
, OPKG_NOTICE
, "Signature check for %s skipped "
294 "because GPG support was not enabled in this build\n", src
->name
);
296 free(list_file_name
);
306 struct opkg_intercept
312 typedef struct opkg_intercept
*opkg_intercept_t
;
314 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
316 opkg_intercept_t ctx
;
321 ctx
= calloc (1, sizeof (*ctx
));
322 oldpath
= getenv ("PATH");
324 ctx
->oldpath
= strdup (oldpath
);
330 sprintf_alloc (&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
331 setenv ("PATH", newpath
, 1);
336 sprintf_alloc (&ctx
->statedir
, "/tmp/opkg-intercept-%d-%d", getpid (), gen
);
337 if (mkdir (ctx
->statedir
, 0770) < 0) {
338 if (errno
== EEXIST
) {
339 free (ctx
->statedir
);
343 perror (ctx
->statedir
);
346 setenv ("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
350 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
357 setenv ("PATH", ctx
->oldpath
, 1);
363 dir
= opendir (ctx
->statedir
);
366 while (de
= readdir (dir
), de
!= NULL
) {
369 if (de
->d_name
[0] == '.')
372 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
373 if (access (path
, X_OK
) == 0) {
382 perror (ctx
->statedir
);
384 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
388 free (ctx
->statedir
);
394 /* For package pkg do the following: If it is already visited, return. If not,
395 add it in visited list and recurse to its deps. Finally, add it to ordered
397 pkg_vec all contains all available packages in repos.
398 pkg_vec visited contains packages already visited by this function, and is
399 used to end recursion and avoid an infinite loop on graph cycles.
400 pkg_vec ordered will finally contain the ordered set of packages.
402 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
403 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
408 compound_depend_t
* compound_depend
;
409 depend_t
** possible_satisfiers
;
410 abstract_pkg_t
*abpkg
;
411 abstract_pkg_t
**dependents
;
413 /* If it's just an available package, that is, not installed and not even
415 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
416 would do here. However, if there is an intermediate node (pkg) that is
417 configured and installed between two unpacked packages, the latter
418 won't be properly reordered, unless all installed/unpacked pkgs are
420 if (pkg
->state_status
== SS_NOT_INSTALLED
)
423 /* If the package has already been visited (by this function), skip it */
424 for(j
= 0; j
< visited
->len
; j
++)
425 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
426 opkg_message(conf
, OPKG_INFO
,
427 " pkg: %s already visited\n", pkg
->name
);
431 pkg_vec_insert(visited
, pkg
);
433 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
434 pkg
->recommends_count
+ pkg
->suggests_count
;
436 opkg_message(conf
, OPKG_INFO
,
437 " pkg: %s\n", pkg
->name
);
439 /* Iterate over all the dependencies of pkg. For each one, find a package
440 that is either installed or unpacked and satisfies this dependency.
441 (there should only be one such package per dependency installed or
442 unpacked). Then recurse to the dependency package */
443 for (j
=0; j
< count
; j
++) {
444 compound_depend
= &pkg
->depends
[j
];
445 possible_satisfiers
= compound_depend
->possibilities
;
446 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
447 abpkg
= possible_satisfiers
[k
]->pkg
;
448 dependents
= abpkg
->provided_by
->pkgs
;
450 if (dependents
!= NULL
)
451 while (dependents
[l
] != NULL
&& l
< abpkg
->provided_by
->len
) {
452 opkg_message(conf
, OPKG_INFO
,
453 " Descending on pkg: %s\n",
454 dependents
[l
]->name
);
456 /* find whether dependent l is installed or unpacked,
457 * and then find which package in the list satisfies it */
458 for(m
= 0; m
< all
->len
; m
++) {
460 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
461 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
462 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
464 /* Stop the outer loop */
465 l
= abpkg
->provided_by
->len
;
466 /* break from the inner loop */
475 /* When all recursions from this node down, are over, and all
476 dependencies have been added in proper order in the ordered array, add
477 also the package pkg to ordered array */
478 pkg_vec_insert(ordered
, pkg
);
484 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
486 pkg_vec_t
*all
, *ordered
, *visited
;
492 opkg_message(conf
, OPKG_INFO
,
493 "Configuring unpacked packages\n");
496 all
= pkg_vec_alloc();
498 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
500 /* Reorder pkgs in order to be configured according to the Depends: tag
502 opkg_message(conf
, OPKG_INFO
,
503 "Reordering packages before configuring them...\n");
504 ordered
= pkg_vec_alloc();
505 visited
= pkg_vec_alloc();
506 for(i
= 0; i
< all
->len
; i
++) {
508 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
512 ic
= opkg_prep_intercepts (conf
);
514 for(i
= 0; i
< all
->len
; i
++) {
517 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
520 if (pkg
->state_status
== SS_UNPACKED
) {
521 opkg_message(conf
, OPKG_NOTICE
,
522 "Configuring %s\n", pkg
->name
);
524 r
= opkg_configure(conf
, pkg
);
526 pkg
->state_status
= SS_INSTALLED
;
527 pkg
->parent
->state_status
= SS_INSTALLED
;
528 pkg
->state_flag
&= ~SF_PREFER
;
536 r
= opkg_finalize_intercepts (ic
);
541 pkg_vec_free(ordered
);
542 pkg_vec_free(visited
);
547 static opkg_conf_t
*global_conf
;
549 static void sigint_handler(int sig
)
551 signal(sig
, SIG_DFL
);
552 opkg_message(NULL
, OPKG_NOTICE
,
553 "opkg: interrupted. writing out status database\n");
554 write_status_files_if_changed(global_conf
);
558 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
565 signal(SIGINT
, sigint_handler
);
568 * Now scan through package names and install
570 for (i
=0; i
< argc
; i
++) {
573 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
574 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
575 if (err
!= EINVAL
&& err
!= 0)
578 pkg_info_preinstall_check(conf
);
580 for (i
=0; i
< argc
; i
++) {
582 err
= opkg_install_by_name(conf
, arg
);
583 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
584 opkg_message(conf
, OPKG_ERROR
,
585 "Cannot find package %s.\n",
590 /* recheck to verify that all dependences are satisfied */
591 if (0) opkg_satisfy_all_dependences(conf
);
593 opkg_configure_packages(conf
, NULL
);
595 write_status_files_if_changed(conf
);
600 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
607 signal(SIGINT
, sigint_handler
);
610 for (i
=0; i
< argc
; i
++) {
613 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
614 if (err
!= EINVAL
&& err
!= 0)
617 pkg_info_preinstall_check(conf
);
619 for (i
=0; i
< argc
; i
++) {
621 if (conf
->restrict_to_default_dest
) {
622 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
626 opkg_message(conf
, OPKG_NOTICE
,
627 "Package %s not installed in %s\n",
628 argv
[i
], conf
->default_dest
->name
);
632 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
636 opkg_upgrade_pkg(conf
, pkg
);
638 opkg_install_by_name(conf
, arg
);
642 pkg_vec_t
*installed
= pkg_vec_alloc();
644 pkg_info_preinstall_check(conf
);
646 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
647 for (i
= 0; i
< installed
->len
; i
++) {
648 pkg
= installed
->pkgs
[i
];
649 opkg_upgrade_pkg(conf
, pkg
);
651 pkg_vec_free(installed
);
654 /* recheck to verify that all dependences are satisfied */
655 if (0) opkg_satisfy_all_dependences(conf
);
657 opkg_configure_packages(conf
, NULL
);
659 write_status_files_if_changed(conf
);
664 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
670 pkg_info_preinstall_check(conf
);
671 for (i
= 0; i
< argc
; i
++) {
674 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
676 opkg_message(conf
, OPKG_ERROR
,
677 "Cannot find package %s.\n"
678 "Check the spelling or perhaps run 'opkg update'\n",
683 err
= opkg_download_pkg(conf
, pkg
, ".");
686 opkg_message(conf
, OPKG_ERROR
,
687 "Failed to download %s\n", pkg
->name
);
689 opkg_message(conf
, OPKG_NOTICE
,
690 "Downloaded %s as %s\n",
691 pkg
->name
, pkg
->local_filename
);
699 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
702 pkg_vec_t
*available
;
704 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
706 char *pkg_name
= NULL
;
712 available
= pkg_vec_alloc();
713 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
714 for (i
=0; i
< available
->len
; i
++) {
715 pkg
= available
->pkgs
[i
];
716 /* if we have package name or pattern and pkg does not match, then skip it */
717 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
719 if (pkg
->description
) {
720 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
722 desc_short
[0] = '\0';
724 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
725 newline
= strchr(desc_short
, '\n');
730 version_str
= pkg_version_str_alloc(pkg
);
731 opkg_cb_list(pkg
->name
,desc_short
,
738 pkg_vec_free(available
);
744 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
747 pkg_vec_t
*available
;
749 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
751 char *pkg_name
= NULL
;
757 available
= pkg_vec_alloc();
758 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
759 pkg_vec_sort(available
, pkg_compare_names
);
760 for (i
=0; i
< available
->len
; i
++) {
761 pkg
= available
->pkgs
[i
];
762 /* if we have package name or pattern and pkg does not match, then skip it */
763 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
765 if (pkg
->description
) {
766 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
768 desc_short
[0] = '\0';
770 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
771 newline
= strchr(desc_short
, '\n');
776 version_str
= pkg_version_str_alloc(pkg
);
777 opkg_cb_list(pkg
->name
,desc_short
,
788 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
790 struct active_list
*head
= prepare_upgrade_list(conf
);
791 struct active_list
*node
=NULL
;
792 pkg_t
*_old_pkg
, *_new_pkg
;
794 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
795 _old_pkg
= list_entry(node
, pkg_t
, list
);
796 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, _old_pkg
->name
, NULL
);
797 old_v
= pkg_version_str_alloc(_old_pkg
);
798 new_v
= pkg_version_str_alloc(_new_pkg
);
800 opkg_cb_list(_old_pkg
->name
, new_v
, old_v
, _old_pkg
->state_status
, p_userdata
);
804 active_list_head_delete(head
);
808 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
811 pkg_vec_t
*available
;
813 char *pkg_name
= NULL
;
814 char **pkg_fields
= NULL
;
822 pkg_fields
= &argv
[1];
826 available
= pkg_vec_alloc();
828 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
830 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
831 for (i
=0; i
< available
->len
; i
++) {
832 pkg
= available
->pkgs
[i
];
833 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
837 buff
= pkg_formatted_info(pkg
);
839 if (opkg_cb_status
) opkg_cb_status(pkg
->name
,
844 We should not forget that actually the pointer is allocated.
845 We need to free it :) ( Thanks florian for seeing the error )
849 if (conf
->verbosity
> 1) {
850 conffile_list_elt_t
*iter
;
851 for (iter
= pkg
->conffiles
.head
; iter
; iter
= iter
->next
) {
852 conffile_t
*cf
= iter
->data
;
853 int modified
= conffile_has_been_modified(conf
, cf
);
854 opkg_message(conf
, OPKG_NOTICE
, "conffile=%s md5sum=%s modified=%d\n",
855 cf
->name
, cf
->value
, modified
);
859 pkg_vec_free(available
);
864 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
866 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
869 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
871 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
874 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
879 char *pkg_name
= NULL
;
883 err
= opkg_configure_packages (conf
, pkg_name
);
886 err
= opkg_configure_packages (conf
, NULL
);
889 write_status_files_if_changed(conf
);
894 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
900 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
901 err
= glob(globpattern
, 0, NULL
, &globbuf
);
907 opkg_message(conf
, OPKG_NOTICE
,
908 "The following packages in %s will now be installed.\n",
910 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
911 opkg_message(conf
, OPKG_NOTICE
,
912 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
914 opkg_message(conf
, OPKG_NOTICE
, "\n");
915 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
916 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
918 err
= unlink(globbuf
.gl_pathv
[i
]);
920 opkg_message(conf
, OPKG_ERROR
,
921 "%s: ERROR: failed to unlink %s: %s\n",
922 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
932 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
936 pkg_t
*pkg_to_remove
;
937 pkg_vec_t
*available
;
938 char *pkg_name
= NULL
;
940 signal(SIGINT
, sigint_handler
);
942 // ENH: Add the "no pkg removed" just in case.
946 pkg_info_preinstall_check(conf
);
948 available
= pkg_vec_alloc();
949 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
950 for (i
=0; i
< argc
; i
++) {
951 pkg_name
= calloc(1, strlen(argv
[i
])+2);
952 strcpy(pkg_name
,argv
[i
]);
953 for (a
=0; a
< available
->len
; a
++) {
954 pkg
= available
->pkgs
[a
];
955 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
958 if (conf
->restrict_to_default_dest
) {
959 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
963 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
967 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
970 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
971 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
974 opkg_remove_pkg(conf
, pkg_to_remove
,0);
979 pkg_vec_free(available
);
981 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
983 int flagged_pkg_count
= 0;
986 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
988 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
989 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
990 if (pkg
->state_flag
& SF_USER
) {
993 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
994 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
997 if (!flagged_pkg_count
) {
998 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
999 "so refusing to uninstall unflagged non-leaf packages\n");
1003 /* find packages not flagged SF_USER (i.e., installed to
1004 * satisfy a dependence) and not having any dependents, and
1008 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
1009 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
1010 if (!(pkg
->state_flag
& SF_USER
)
1011 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
1013 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
1014 opkg_remove_pkg(conf
, pkg
,0);
1019 pkg_vec_free(installed_pkgs
);
1023 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
1025 write_status_files_if_changed(conf
);
1029 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1035 signal(SIGINT
, sigint_handler
);
1037 pkg_info_preinstall_check(conf
);
1039 for (i
=0; i
< argc
; i
++) {
1040 if (conf
->restrict_to_default_dest
) {
1041 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1043 conf
->default_dest
);
1045 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1049 opkg_message(conf
, OPKG_ERROR
,
1050 "Package %s is not installed.\n", argv
[i
]);
1053 opkg_purge_pkg(conf
, pkg
);
1056 write_status_files_if_changed(conf
);
1060 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1064 const char *flags
= argv
[0];
1067 signal(SIGINT
, sigint_handler
);
1069 for (i
=1; i
< argc
; i
++) {
1070 if (conf
->restrict_to_default_dest
) {
1071 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1073 conf
->default_dest
);
1075 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1079 opkg_message(conf
, OPKG_ERROR
,
1080 "Package %s is not installed.\n", argv
[i
]);
1083 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1084 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1085 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1087 /* pb_ asked this feature 03292004 */
1088 /* Actually I will use only this two, but this is an open for various status */
1089 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1090 pkg
->state_status
= pkg_state_status_from_str(flags
);
1092 opkg_state_changed
++;
1093 opkg_message(conf
, OPKG_NOTICE
,
1094 "Setting flags for package %s to %s\n",
1098 write_status_files_if_changed(conf
);
1102 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1105 str_list_t
*installed_files
;
1106 str_list_elt_t
*iter
;
1108 size_t buff_len
= 8192;
1112 buff
= (char *)calloc(1, buff_len
);
1113 if ( buff
== NULL
) {
1114 fprintf( stderr
,"%s: Unable to allocate memory \n",__FUNCTION__
);
1122 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1125 opkg_message(conf
, OPKG_ERROR
,
1126 "Package %s not installed.\n", argv
[0]);
1130 installed_files
= pkg_get_installed_files(pkg
);
1131 pkg_version
= pkg_version_str_alloc(pkg
);
1135 used_len
= snprintf(buff
, buff_len
, "Package %s (%s) is installed on %s and has the following files:\n",
1136 pkg
->name
, pkg_version
, pkg
->dest
->name
) + 1;
1137 if (used_len
> buff_len
) {
1139 buff
= realloc (buff
, buff_len
);
1142 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1143 used_len
+= strlen (iter
->data
) + 1;
1144 while (buff_len
<= used_len
) {
1146 buff
= realloc (buff
, buff_len
);
1148 strncat(buff
, iter
->data
, buff_len
);
1149 strncat(buff
, "\n", buff_len
);
1151 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1153 pkg_version_str_alloc(pkg
),
1160 pkg_free_installed_files(pkg
);
1165 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1169 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1170 const char *rel_str
= "depends on";
1173 pkg_info_preinstall_check(conf
);
1175 if (conf
->query_all
)
1176 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1178 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1179 for (i
= 0; i
< argc
; i
++) {
1180 const char *target
= argv
[i
];
1183 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1185 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1186 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1187 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1189 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1190 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1191 target
, pkg
->architecture
, rel_str
);
1192 for (k
= 0; k
< count
; k
++) {
1193 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1195 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1196 depend_t
*possibility
= cdepend
->possibilities
[l
];
1197 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1198 if (conf
->verbosity
> 0) {
1199 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1200 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1201 if (possibility
->version
) {
1202 char *typestr
= NULL
;
1203 switch (possibility
->constraint
) {
1204 case NONE
: typestr
= "none"; break;
1205 case EARLIER
: typestr
= "<"; break;
1206 case EARLIER_EQUAL
: typestr
= "<="; break;
1207 case EQUAL
: typestr
= "="; break;
1208 case LATER_EQUAL
: typestr
= ">="; break;
1209 case LATER
: typestr
= ">"; break;
1211 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1215 opkg_message(conf
, OPKG_ERROR
, "\n");
1221 pkg_vec_free(available_pkgs
);
1226 enum what_field_type
{
1235 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1239 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1240 const char *rel_str
= NULL
;
1244 switch (what_field_type
) {
1245 case WHATDEPENDS
: rel_str
= "depends on"; break;
1246 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1247 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1248 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1249 case WHATPROVIDES
: rel_str
= "provides"; break;
1250 case WHATREPLACES
: rel_str
= "replaces"; break;
1253 if (conf
->query_all
)
1254 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1256 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1258 /* mark the root set */
1259 pkg_vec_clear_marks(available_pkgs
);
1260 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1261 for (i
= 0; i
< argc
; i
++) {
1262 const char *dependee_pattern
= argv
[i
];
1263 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1265 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1266 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1267 if (pkg
->state_flag
& SF_MARKED
) {
1268 /* mark the parent (abstract) package */
1269 pkg_mark_provides(pkg
);
1270 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1274 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1279 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1280 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1282 int count
= ((what_field_type
== WHATCONFLICTS
)
1283 ? pkg
->conflicts_count
1284 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1285 /* skip this package if it is already marked */
1286 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1289 for (k
= 0; k
< count
; k
++) {
1290 compound_depend_t
*cdepend
=
1291 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1293 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1294 depend_t
*possibility
= cdepend
->possibilities
[l
];
1295 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1296 /* mark the depending package so we won't visit it again */
1297 pkg
->state_flag
|= SF_MARKED
;
1298 pkg_mark_provides(pkg
);
1301 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1302 if (conf
->verbosity
> 0) {
1303 char *ver
= pkg_version_str_alloc(pkg
);
1304 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1305 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1306 if (possibility
->version
) {
1307 char *typestr
= NULL
;
1308 switch (possibility
->constraint
) {
1309 case NONE
: typestr
= "none"; break;
1310 case EARLIER
: typestr
= "<"; break;
1311 case EARLIER_EQUAL
: typestr
= "<="; break;
1312 case EQUAL
: typestr
= "="; break;
1313 case LATER_EQUAL
: typestr
= ">="; break;
1314 case LATER
: typestr
= ">"; break;
1316 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1319 if (!pkg_dependence_satisfiable(conf
, possibility
))
1320 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1322 opkg_message(conf
, OPKG_NOTICE
, "\n");
1330 } while (changed
&& recursive
);
1331 pkg_vec_free(available_pkgs
);
1337 static int pkg_mark_provides(pkg_t
*pkg
)
1339 int provides_count
= pkg
->provides_count
;
1340 abstract_pkg_t
**provides
= pkg
->provides
;
1342 pkg
->parent
->state_flag
|= SF_MARKED
;
1343 for (i
= 0; i
< provides_count
; i
++) {
1344 provides
[i
]->state_flag
|= SF_MARKED
;
1349 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1351 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1353 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1355 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1358 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1360 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1363 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1365 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1368 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1370 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1373 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1377 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1378 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1381 pkg_info_preinstall_check(conf
);
1383 if (conf
->query_all
)
1384 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1386 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1387 for (i
= 0; i
< argc
; i
++) {
1388 const char *target
= argv
[i
];
1391 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1393 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1394 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1396 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1397 for (k
= 0; k
< count
; k
++) {
1398 abstract_pkg_t
*apkg
=
1399 ((what_field_type
== WHATPROVIDES
)
1401 : pkg
->replaces
[k
]);
1402 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1403 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1404 if (strcmp(target
, apkg
->name
) != 0)
1405 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1406 opkg_message(conf
, OPKG_ERROR
, "\n");
1411 pkg_vec_free(available_pkgs
);
1416 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1418 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1421 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1423 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1426 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1430 pkg_vec_t
*installed
;
1432 str_list_t
*installed_files
;
1433 str_list_elt_t
*iter
;
1434 char *installed_file
;
1440 installed
= pkg_vec_alloc();
1441 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1443 for (i
=0; i
< installed
->len
; i
++) {
1444 pkg
= installed
->pkgs
[i
];
1446 installed_files
= pkg_get_installed_files(pkg
);
1448 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1449 installed_file
= iter
->data
;
1450 if (fnmatch(argv
[0], installed_file
, 0)==0) {
1451 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1453 pkg_version_str_alloc(pkg
),
1454 pkg
->state_status
, p_userdata
);
1458 pkg_free_installed_files(pkg
);
1461 /* XXX: CLEANUP: It's not obvious from the name of
1462 pkg_hash_fetch_all_installed that we need to call
1463 pkg_vec_free to avoid a memory leak. */
1464 pkg_vec_free(installed
);
1469 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1472 /* this is a bit gross */
1474 parseVersion(&p1
, argv
[0]);
1475 parseVersion(&p2
, argv
[2]);
1476 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1478 opkg_message(conf
, OPKG_ERROR
,
1479 "opkg compare_versions <v1> <op> <v2>\n"
1480 "<op> is one of <= >= << >> =\n");
1485 #ifndef HOST_CPU_STR
1486 #define HOST_CPU_STR__(X) #X
1487 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1488 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1491 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1493 nv_pair_list_elt_t
*l
;
1495 l
= conf
->arch_list
.head
;
1497 nv_pair_t
*nv
= l
->data
;
1498 printf("arch %s %s\n", nv
->name
, nv
->value
);