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"
49 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
50 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
51 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
52 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
53 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
54 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
55 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
56 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
57 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
58 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
59 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
60 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
61 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
62 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
63 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
64 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
65 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
66 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
67 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
68 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
69 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
70 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
71 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
72 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
73 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
74 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
75 static int pkg_mark_provides(pkg_t
*pkg
);
77 /* XXX: CLEANUP: The usage strings should be incorporated into this
78 array for easier maintenance */
79 static opkg_cmd_t cmds
[] = {
80 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
},
81 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
},
82 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
},
83 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
},
84 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
},
85 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
86 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
87 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
88 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
89 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
90 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
91 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
92 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
93 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
94 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
95 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
96 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
97 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
98 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
99 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
100 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
101 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
102 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
103 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
104 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
105 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
106 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
107 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
108 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
109 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
112 static void print_pkg(pkg_t
*pkg
)
114 char *version
= pkg_version_str_alloc(pkg
);
115 if (pkg
->description
)
116 printf("%s - %s - %s\n", pkg
->name
, version
, pkg
->description
);
118 printf("%s - %s\n", pkg
->name
, version
);
122 int opkg_state_changed
;
123 static void write_status_files_if_changed(opkg_conf_t
*conf
)
125 if (opkg_state_changed
&& !conf
->noaction
) {
126 opkg_message(conf
, OPKG_INFO
,
127 " writing status file\n");
128 opkg_conf_write_status_files(conf
);
129 pkg_write_changed_filelists(conf
);
131 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
136 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
138 opkg_cmd_t
*opkg_cmd_find(const char *name
)
143 for (i
=0; i
< num_cmds
; i
++) {
145 if (strcmp(name
, cmd
->name
) == 0) {
153 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
157 result
= (cmd
->fun
)(conf
, argc
, argv
);
165 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
171 pkg_src_list_elt_t
*iter
;
175 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
177 if (! file_is_dir(lists_dir
)) {
178 if (file_exists(lists_dir
)) {
179 opkg_message(conf
, OPKG_ERROR
,
180 "%s: ERROR: %s exists, but is not a directory\n",
181 __FUNCTION__
, lists_dir
);
185 err
= file_mkdir_hier(lists_dir
, 0755);
187 opkg_message(conf
, OPKG_ERROR
,
188 "%s: ERROR: failed to make directory %s: %s\n",
189 __FUNCTION__
, lists_dir
, strerror(errno
));
197 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
198 if (mkdtemp (tmp
) == NULL
) {
204 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
205 char *url
, *list_file_name
;
207 src
= (pkg_src_t
*)iter
->data
;
209 if (src
->extra_data
) /* debian style? */
210 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
211 src
->gzip
? "Packages.gz" : "Packages");
213 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
215 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
220 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
221 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
223 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
224 in
= fopen (tmp_file_name
, "r");
225 out
= fopen (list_file_name
, "w");
234 unlink (tmp_file_name
);
238 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
242 opkg_message(conf
, OPKG_NOTICE
,
243 "Updated list of available packages in %s\n",
247 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
248 if (conf
->check_signature
) {
249 /* download detached signitures to verify the package lists */
250 /* get the url for the sig file */
251 if (src
->extra_data
) /* debian style? */
252 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
255 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
257 /* create temporary file for it */
260 /* Put the signature in the right place */
261 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
263 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
266 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
269 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
271 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
273 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
275 /* We shouldn't unlink the signature ! */
276 // unlink (tmp_file_name);
277 free (tmp_file_name
);
283 free(list_file_name
);
293 struct opkg_intercept
299 typedef struct opkg_intercept
*opkg_intercept_t
;
301 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
303 opkg_intercept_t ctx
;
306 ctx
= xcalloc(1, sizeof (*ctx
));
307 ctx
->oldpath
= xstrdup(getenv("PATH"));
308 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
309 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
311 if (mkdtemp(ctx
->statedir
) == NULL
) {
312 fprintf(stderr
, "%s: mkdtemp: %s\n", __FUNCTION__
, strerror(errno
));
320 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
321 setenv("PATH", newpath
, 1);
327 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
333 setenv ("PATH", ctx
->oldpath
, 1);
336 dir
= opendir (ctx
->statedir
);
339 while (de
= readdir (dir
), de
!= NULL
) {
342 if (de
->d_name
[0] == '.')
345 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
346 if (access (path
, X_OK
) == 0) {
356 perror (ctx
->statedir
);
358 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
362 free (ctx
->statedir
);
368 /* For package pkg do the following: If it is already visited, return. If not,
369 add it in visited list and recurse to its deps. Finally, add it to ordered
371 pkg_vec all contains all available packages in repos.
372 pkg_vec visited contains packages already visited by this function, and is
373 used to end recursion and avoid an infinite loop on graph cycles.
374 pkg_vec ordered will finally contain the ordered set of packages.
376 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
377 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
382 compound_depend_t
* compound_depend
;
383 depend_t
** possible_satisfiers
;
384 abstract_pkg_t
*abpkg
;
385 abstract_pkg_t
**dependents
;
387 /* If it's just an available package, that is, not installed and not even
389 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
390 would do here. However, if there is an intermediate node (pkg) that is
391 configured and installed between two unpacked packages, the latter
392 won't be properly reordered, unless all installed/unpacked pkgs are
394 if (pkg
->state_status
== SS_NOT_INSTALLED
)
397 /* If the package has already been visited (by this function), skip it */
398 for(j
= 0; j
< visited
->len
; j
++)
399 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
400 opkg_message(conf
, OPKG_INFO
,
401 " pkg: %s already visited\n", pkg
->name
);
405 pkg_vec_insert(visited
, pkg
);
407 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
408 pkg
->recommends_count
+ pkg
->suggests_count
;
410 opkg_message(conf
, OPKG_INFO
,
411 " pkg: %s\n", pkg
->name
);
413 /* Iterate over all the dependencies of pkg. For each one, find a package
414 that is either installed or unpacked and satisfies this dependency.
415 (there should only be one such package per dependency installed or
416 unpacked). Then recurse to the dependency package */
417 for (j
=0; j
< count
; j
++) {
418 compound_depend
= &pkg
->depends
[j
];
419 possible_satisfiers
= compound_depend
->possibilities
;
420 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
421 abpkg
= possible_satisfiers
[k
]->pkg
;
422 dependents
= abpkg
->provided_by
->pkgs
;
424 if (dependents
!= NULL
)
425 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
426 opkg_message(conf
, OPKG_INFO
,
427 " Descending on pkg: %s\n",
428 dependents
[l
]->name
);
430 /* find whether dependent l is installed or unpacked,
431 * and then find which package in the list satisfies it */
432 for(m
= 0; m
< all
->len
; m
++) {
434 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
435 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
436 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
438 /* Stop the outer loop */
439 l
= abpkg
->provided_by
->len
;
440 /* break from the inner loop */
449 /* When all recursions from this node down, are over, and all
450 dependencies have been added in proper order in the ordered array, add
451 also the package pkg to ordered array */
452 pkg_vec_insert(ordered
, pkg
);
458 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
460 pkg_vec_t
*all
, *ordered
, *visited
;
466 opkg_message(conf
, OPKG_INFO
,
467 "Configuring unpacked packages\n");
470 all
= pkg_vec_alloc();
472 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
474 /* Reorder pkgs in order to be configured according to the Depends: tag
476 opkg_message(conf
, OPKG_INFO
,
477 "Reordering packages before configuring them...\n");
478 ordered
= pkg_vec_alloc();
479 visited
= pkg_vec_alloc();
480 for(i
= 0; i
< all
->len
; i
++) {
482 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
485 ic
= opkg_prep_intercepts (conf
);
489 for(i
= 0; i
< all
->len
; i
++) {
492 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
495 if (pkg
->state_status
== SS_UNPACKED
) {
496 opkg_message(conf
, OPKG_NOTICE
,
497 "Configuring %s\n", pkg
->name
);
499 r
= opkg_configure(conf
, pkg
);
501 pkg
->state_status
= SS_INSTALLED
;
502 pkg
->parent
->state_status
= SS_INSTALLED
;
503 pkg
->state_flag
&= ~SF_PREFER
;
511 r
= opkg_finalize_intercepts (ic
);
516 pkg_vec_free(ordered
);
517 pkg_vec_free(visited
);
522 static opkg_conf_t
*global_conf
;
524 static void sigint_handler(int sig
)
526 signal(sig
, SIG_DFL
);
527 opkg_message(NULL
, OPKG_NOTICE
,
528 "opkg: interrupted. writing out status database\n");
529 write_status_files_if_changed(global_conf
);
533 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
540 signal(SIGINT
, sigint_handler
);
543 * Now scan through package names and install
545 for (i
=0; i
< argc
; i
++) {
548 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
549 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
550 if (err
!= EINVAL
&& err
!= 0)
553 pkg_info_preinstall_check(conf
);
555 for (i
=0; i
< argc
; i
++) {
557 err
= opkg_install_by_name(conf
, arg
);
558 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
559 opkg_message(conf
, OPKG_ERROR
,
560 "Cannot find package %s.\n",
565 opkg_configure_packages(conf
, NULL
);
567 write_status_files_if_changed(conf
);
572 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
579 signal(SIGINT
, sigint_handler
);
582 for (i
=0; i
< argc
; i
++) {
585 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
586 if (err
!= EINVAL
&& err
!= 0)
589 pkg_info_preinstall_check(conf
);
591 for (i
=0; i
< argc
; i
++) {
593 if (conf
->restrict_to_default_dest
) {
594 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
598 opkg_message(conf
, OPKG_NOTICE
,
599 "Package %s not installed in %s\n",
600 argv
[i
], conf
->default_dest
->name
);
604 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
608 opkg_upgrade_pkg(conf
, pkg
);
610 opkg_install_by_name(conf
, arg
);
614 pkg_vec_t
*installed
= pkg_vec_alloc();
616 pkg_info_preinstall_check(conf
);
618 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
619 for (i
= 0; i
< installed
->len
; i
++) {
620 pkg
= installed
->pkgs
[i
];
621 opkg_upgrade_pkg(conf
, pkg
);
623 pkg_vec_free(installed
);
626 opkg_configure_packages(conf
, NULL
);
628 write_status_files_if_changed(conf
);
633 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
639 pkg_info_preinstall_check(conf
);
640 for (i
= 0; i
< argc
; i
++) {
643 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
645 opkg_message(conf
, OPKG_ERROR
,
646 "Cannot find package %s.\n"
647 "Check the spelling or perhaps run 'opkg update'\n",
652 err
= opkg_download_pkg(conf
, pkg
, ".");
655 opkg_message(conf
, OPKG_ERROR
,
656 "Failed to download %s\n", pkg
->name
);
658 opkg_message(conf
, OPKG_NOTICE
,
659 "Downloaded %s as %s\n",
660 pkg
->name
, pkg
->local_filename
);
668 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
671 pkg_vec_t
*available
;
673 char *pkg_name
= NULL
;
678 available
= pkg_vec_alloc();
679 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
680 pkg_vec_sort(available
, pkg_compare_names
);
681 for (i
=0; i
< available
->len
; i
++) {
682 pkg
= available
->pkgs
[i
];
683 /* if we have package name or pattern and pkg does not match, then skip it */
684 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
688 pkg_vec_free(available
);
694 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
697 pkg_vec_t
*available
;
699 char *pkg_name
= NULL
;
704 available
= pkg_vec_alloc();
705 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
706 pkg_vec_sort(available
, pkg_compare_names
);
707 for (i
=0; i
< available
->len
; i
++) {
708 pkg
= available
->pkgs
[i
];
709 /* if we have package name or pattern and pkg does not match, then skip it */
710 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
715 pkg_vec_free(available
);
720 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
722 struct active_list
*head
= prepare_upgrade_list(conf
);
723 struct active_list
*node
=NULL
;
724 pkg_t
*_old_pkg
, *_new_pkg
;
726 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
727 _old_pkg
= list_entry(node
, pkg_t
, list
);
728 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, _old_pkg
->name
, NULL
);
729 old_v
= pkg_version_str_alloc(_old_pkg
);
730 new_v
= pkg_version_str_alloc(_new_pkg
);
731 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
735 active_list_head_delete(head
);
739 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
742 pkg_vec_t
*available
;
744 char *pkg_name
= NULL
;
750 available
= pkg_vec_alloc();
752 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
754 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
756 for (i
=0; i
< available
->len
; i
++) {
757 pkg
= available
->pkgs
[i
];
758 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
762 pkg_formatted_info(stdout
, pkg
);
764 if (conf
->verbosity
> 1) {
765 conffile_list_elt_t
*iter
;
766 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
767 conffile_t
*cf
= (conffile_t
*)iter
->data
;
768 int modified
= conffile_has_been_modified(conf
, cf
);
770 opkg_message(conf
, OPKG_NOTICE
,
771 "conffile=%s md5sum=%s modified=%d\n",
772 cf
->name
, cf
->value
, modified
);
776 pkg_vec_free(available
);
781 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
783 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
786 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
788 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
791 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
796 char *pkg_name
= NULL
;
800 err
= opkg_configure_packages (conf
, pkg_name
);
803 err
= opkg_configure_packages (conf
, NULL
);
806 write_status_files_if_changed(conf
);
811 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
817 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
818 err
= glob(globpattern
, 0, NULL
, &globbuf
);
824 opkg_message(conf
, OPKG_NOTICE
,
825 "The following packages in %s will now be installed.\n",
827 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
828 opkg_message(conf
, OPKG_NOTICE
,
829 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
831 opkg_message(conf
, OPKG_NOTICE
, "\n");
832 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
833 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
835 err
= unlink(globbuf
.gl_pathv
[i
]);
837 opkg_message(conf
, OPKG_ERROR
,
838 "%s: ERROR: failed to unlink %s: %s\n",
839 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
849 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
853 pkg_t
*pkg_to_remove
;
854 pkg_vec_t
*available
;
855 char *pkg_name
= NULL
;
857 signal(SIGINT
, sigint_handler
);
859 // ENH: Add the "no pkg removed" just in case.
863 pkg_info_preinstall_check(conf
);
865 available
= pkg_vec_alloc();
866 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
867 for (i
=0; i
< argc
; i
++) {
868 pkg_name
= xcalloc(1, strlen(argv
[i
])+2);
869 strcpy(pkg_name
,argv
[i
]);
870 for (a
=0; a
< available
->len
; a
++) {
871 pkg
= available
->pkgs
[a
];
872 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
875 if (conf
->restrict_to_default_dest
) {
876 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
880 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
883 if (pkg_to_remove
== NULL
) {
884 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
887 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
888 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
891 opkg_remove_pkg(conf
, pkg_to_remove
,0);
896 pkg_vec_free(available
);
898 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
900 int flagged_pkg_count
= 0;
903 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
905 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
906 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
907 if (pkg
->state_flag
& SF_USER
) {
910 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
911 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
914 if (!flagged_pkg_count
) {
915 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
916 "so refusing to uninstall unflagged non-leaf packages\n");
920 /* find packages not flagged SF_USER (i.e., installed to
921 * satisfy a dependence) and not having any dependents, and
925 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
926 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
927 if (!(pkg
->state_flag
& SF_USER
)
928 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
930 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
931 opkg_remove_pkg(conf
, pkg
,0);
936 pkg_vec_free(installed_pkgs
);
940 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
942 write_status_files_if_changed(conf
);
946 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
952 signal(SIGINT
, sigint_handler
);
954 pkg_info_preinstall_check(conf
);
956 for (i
=0; i
< argc
; i
++) {
957 if (conf
->restrict_to_default_dest
) {
958 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
962 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
966 opkg_message(conf
, OPKG_ERROR
,
967 "Package %s is not installed.\n", argv
[i
]);
970 opkg_purge_pkg(conf
, pkg
);
973 write_status_files_if_changed(conf
);
977 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
981 const char *flags
= argv
[0];
984 signal(SIGINT
, sigint_handler
);
986 for (i
=1; i
< argc
; i
++) {
987 if (conf
->restrict_to_default_dest
) {
988 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
992 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
996 opkg_message(conf
, OPKG_ERROR
,
997 "Package %s is not installed.\n", argv
[i
]);
1000 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1001 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1002 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1004 /* pb_ asked this feature 03292004 */
1005 /* Actually I will use only this two, but this is an open for various status */
1006 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1007 pkg
->state_status
= pkg_state_status_from_str(flags
);
1009 opkg_state_changed
++;
1010 opkg_message(conf
, OPKG_NOTICE
,
1011 "Setting flags for package %s to %s\n",
1015 write_status_files_if_changed(conf
);
1019 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1023 str_list_elt_t
*iter
;
1030 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1033 opkg_message(conf
, OPKG_ERROR
,
1034 "Package %s not installed.\n", argv
[0]);
1038 files
= pkg_get_installed_files(pkg
);
1039 pkg_version
= pkg_version_str_alloc(pkg
);
1041 printf("Package %s (%s) is installed on %s and has the following files:\n",
1042 pkg
->name
, pkg_version
, pkg
->dest
->name
);
1044 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
1045 printf("%s\n", (char *)iter
->data
);
1048 pkg_free_installed_files(pkg
);
1053 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1057 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1058 const char *rel_str
= "depends on";
1061 pkg_info_preinstall_check(conf
);
1063 if (conf
->query_all
)
1064 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1066 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1067 for (i
= 0; i
< argc
; i
++) {
1068 const char *target
= argv
[i
];
1071 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1073 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1074 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1075 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1077 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1078 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1079 target
, pkg
->architecture
, rel_str
);
1080 for (k
= 0; k
< count
; k
++) {
1081 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1083 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1084 depend_t
*possibility
= cdepend
->possibilities
[l
];
1085 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1086 if (conf
->verbosity
> 0) {
1087 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1088 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1089 if (possibility
->version
) {
1090 char *typestr
= NULL
;
1091 switch (possibility
->constraint
) {
1092 case NONE
: typestr
= "none"; break;
1093 case EARLIER
: typestr
= "<"; break;
1094 case EARLIER_EQUAL
: typestr
= "<="; break;
1095 case EQUAL
: typestr
= "="; break;
1096 case LATER_EQUAL
: typestr
= ">="; break;
1097 case LATER
: typestr
= ">"; break;
1099 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1103 opkg_message(conf
, OPKG_ERROR
, "\n");
1109 pkg_vec_free(available_pkgs
);
1114 enum what_field_type
{
1123 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1127 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1128 const char *rel_str
= NULL
;
1132 switch (what_field_type
) {
1133 case WHATDEPENDS
: rel_str
= "depends on"; break;
1134 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1135 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1136 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1137 case WHATPROVIDES
: rel_str
= "provides"; break;
1138 case WHATREPLACES
: rel_str
= "replaces"; break;
1141 if (conf
->query_all
)
1142 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1144 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1146 /* mark the root set */
1147 pkg_vec_clear_marks(available_pkgs
);
1148 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1149 for (i
= 0; i
< argc
; i
++) {
1150 const char *dependee_pattern
= argv
[i
];
1151 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1153 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1154 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1155 if (pkg
->state_flag
& SF_MARKED
) {
1156 /* mark the parent (abstract) package */
1157 pkg_mark_provides(pkg
);
1158 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1162 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1167 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1168 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1170 int count
= ((what_field_type
== WHATCONFLICTS
)
1171 ? pkg
->conflicts_count
1172 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1173 /* skip this package if it is already marked */
1174 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1177 for (k
= 0; k
< count
; k
++) {
1178 compound_depend_t
*cdepend
=
1179 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1181 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1182 depend_t
*possibility
= cdepend
->possibilities
[l
];
1183 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1184 /* mark the depending package so we won't visit it again */
1185 pkg
->state_flag
|= SF_MARKED
;
1186 pkg_mark_provides(pkg
);
1189 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1190 if (conf
->verbosity
> 0) {
1191 char *ver
= pkg_version_str_alloc(pkg
);
1192 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1193 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1194 if (possibility
->version
) {
1195 char *typestr
= NULL
;
1196 switch (possibility
->constraint
) {
1197 case NONE
: typestr
= "none"; break;
1198 case EARLIER
: typestr
= "<"; break;
1199 case EARLIER_EQUAL
: typestr
= "<="; break;
1200 case EQUAL
: typestr
= "="; break;
1201 case LATER_EQUAL
: typestr
= ">="; break;
1202 case LATER
: typestr
= ">"; break;
1204 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1207 if (!pkg_dependence_satisfiable(conf
, possibility
))
1208 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1210 opkg_message(conf
, OPKG_NOTICE
, "\n");
1218 } while (changed
&& recursive
);
1219 pkg_vec_free(available_pkgs
);
1225 static int pkg_mark_provides(pkg_t
*pkg
)
1227 int provides_count
= pkg
->provides_count
;
1228 abstract_pkg_t
**provides
= pkg
->provides
;
1230 pkg
->parent
->state_flag
|= SF_MARKED
;
1231 for (i
= 0; i
< provides_count
; i
++) {
1232 provides
[i
]->state_flag
|= SF_MARKED
;
1237 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1239 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1241 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1243 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1246 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1248 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1251 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1253 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1256 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1258 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1261 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1265 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1266 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1269 pkg_info_preinstall_check(conf
);
1271 if (conf
->query_all
)
1272 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1274 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1275 for (i
= 0; i
< argc
; i
++) {
1276 const char *target
= argv
[i
];
1279 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1281 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1282 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1284 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1285 for (k
= 0; k
< count
; k
++) {
1286 abstract_pkg_t
*apkg
=
1287 ((what_field_type
== WHATPROVIDES
)
1289 : pkg
->replaces
[k
]);
1290 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1291 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1292 if (strcmp(target
, apkg
->name
) != 0)
1293 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1294 opkg_message(conf
, OPKG_ERROR
, "\n");
1299 pkg_vec_free(available_pkgs
);
1304 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1306 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1309 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1311 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1314 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1318 pkg_vec_t
*installed
;
1320 str_list_t
*installed_files
;
1321 str_list_elt_t
*iter
;
1322 char *installed_file
;
1328 installed
= pkg_vec_alloc();
1329 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1330 pkg_vec_sort(installed
, pkg_compare_names
);
1332 for (i
=0; i
< installed
->len
; i
++) {
1333 pkg
= installed
->pkgs
[i
];
1335 installed_files
= pkg_get_installed_files(pkg
);
1337 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1338 installed_file
= (char *)iter
->data
;
1339 if (fnmatch(argv
[0], installed_file
, 0)==0)
1343 pkg_free_installed_files(pkg
);
1346 pkg_vec_free(installed
);
1351 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1354 /* this is a bit gross */
1356 parseVersion(&p1
, argv
[0]);
1357 parseVersion(&p2
, argv
[2]);
1358 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1360 opkg_message(conf
, OPKG_ERROR
,
1361 "opkg compare_versions <v1> <op> <v2>\n"
1362 "<op> is one of <= >= << >> =\n");
1367 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1369 nv_pair_list_elt_t
*l
;
1371 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1372 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1373 printf("arch %s %s\n", nv
->name
, nv
->value
);