1 /* opkg_cmd.c - the opkg package management system
5 Copyright (C) 2001 University of Southern California
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
24 #include "opkg_conf.h"
26 #include "opkg_message.h"
29 #include "pkg_parse.h"
30 #include "sprintf_alloc.h"
32 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
42 #include "opkg_message.h"
46 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
47 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
48 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
49 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
50 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
51 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
52 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
53 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
54 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
55 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
56 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
57 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
58 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
59 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
60 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
61 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
62 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
63 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
64 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
65 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
66 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
67 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
68 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
69 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
70 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
71 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
);
72 static int pkg_mark_provides(pkg_t
*pkg
);
74 /* XXX: CLEANUP: The usage strings should be incorporated into this
75 array for easier maintenance */
76 static opkg_cmd_t cmds
[] = {
77 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
},
78 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
},
79 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
},
80 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
},
81 {"list_upgradable", 0, (opkg_cmd_fun_t
)opkg_list_upgradable_cmd
},
82 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
83 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
84 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
85 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
86 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
87 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
88 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
89 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
90 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
91 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
92 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
93 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
94 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
95 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
96 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
97 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
98 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
99 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
100 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
101 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
102 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
103 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
104 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
105 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
106 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
109 static void print_pkg(pkg_t
*pkg
)
111 char *version
= pkg_version_str_alloc(pkg
);
112 if (pkg
->description
)
113 printf("%s - %s - %s\n", pkg
->name
, version
, pkg
->description
);
115 printf("%s - %s\n", pkg
->name
, version
);
119 int opkg_state_changed
;
120 static void write_status_files_if_changed(opkg_conf_t
*conf
)
122 if (opkg_state_changed
&& !conf
->noaction
) {
123 opkg_message(conf
, OPKG_INFO
,
124 " writing status file\n");
125 opkg_conf_write_status_files(conf
);
126 pkg_write_changed_filelists(conf
);
128 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
133 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
135 opkg_cmd_t
*opkg_cmd_find(const char *name
)
140 for (i
=0; i
< num_cmds
; i
++) {
142 if (strcmp(name
, cmd
->name
) == 0) {
150 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
154 result
= (cmd
->fun
)(conf
, argc
, argv
);
162 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
168 pkg_src_list_elt_t
*iter
;
172 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
174 if (! file_is_dir(lists_dir
)) {
175 if (file_exists(lists_dir
)) {
176 opkg_message(conf
, OPKG_ERROR
,
177 "%s: ERROR: %s exists, but is not a directory\n",
178 __FUNCTION__
, lists_dir
);
182 err
= file_mkdir_hier(lists_dir
, 0755);
184 opkg_message(conf
, OPKG_ERROR
,
185 "%s: ERROR: failed to make directory %s: %s\n",
186 __FUNCTION__
, lists_dir
, strerror(errno
));
194 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
195 if (mkdtemp (tmp
) == NULL
) {
201 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
; iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
202 char *url
, *list_file_name
;
204 src
= (pkg_src_t
*)iter
->data
;
206 if (src
->extra_data
) /* debian style? */
207 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
208 src
->gzip
? "Packages.gz" : "Packages");
210 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
212 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
217 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
218 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
220 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
221 in
= fopen (tmp_file_name
, "r");
222 out
= fopen (list_file_name
, "w");
231 unlink (tmp_file_name
);
235 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
239 opkg_message(conf
, OPKG_NOTICE
,
240 "Updated list of available packages in %s\n",
244 #if defined(HAVE_GPGME) || defined(HAVE_OPENSSL)
245 if (conf
->check_signature
) {
246 /* download detached signitures to verify the package lists */
247 /* get the url for the sig file */
248 if (src
->extra_data
) /* debian style? */
249 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
252 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
254 /* create temporary file for it */
257 /* Put the signature in the right place */
258 sprintf_alloc (&tmp_file_name
, "%s/%s.sig", lists_dir
, src
->name
);
260 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
263 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
266 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
268 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
270 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
272 /* We shouldn't unlink the signature ! */
273 // unlink (tmp_file_name);
274 free (tmp_file_name
);
280 free(list_file_name
);
290 struct opkg_intercept
296 typedef struct opkg_intercept
*opkg_intercept_t
;
298 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
300 opkg_intercept_t ctx
;
303 ctx
= xcalloc(1, sizeof (*ctx
));
304 ctx
->oldpath
= xstrdup(getenv("PATH"));
305 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
306 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX", conf
->tmp_dir
);
308 if (mkdtemp(ctx
->statedir
) == NULL
) {
309 fprintf(stderr
, "%s: mkdtemp: %s\n", __FUNCTION__
, strerror(errno
));
317 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
318 setenv("PATH", newpath
, 1);
324 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
330 setenv ("PATH", ctx
->oldpath
, 1);
333 dir
= opendir (ctx
->statedir
);
336 while (de
= readdir (dir
), de
!= NULL
) {
339 if (de
->d_name
[0] == '.')
342 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
343 if (access (path
, X_OK
) == 0) {
350 perror (ctx
->statedir
);
352 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
356 free (ctx
->statedir
);
362 /* For package pkg do the following: If it is already visited, return. If not,
363 add it in visited list and recurse to its deps. Finally, add it to ordered
365 pkg_vec all contains all available packages in repos.
366 pkg_vec visited contains packages already visited by this function, and is
367 used to end recursion and avoid an infinite loop on graph cycles.
368 pkg_vec ordered will finally contain the ordered set of packages.
370 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
371 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
376 compound_depend_t
* compound_depend
;
377 depend_t
** possible_satisfiers
;
378 abstract_pkg_t
*abpkg
;
379 abstract_pkg_t
**dependents
;
381 /* If it's just an available package, that is, not installed and not even
383 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
384 would do here. However, if there is an intermediate node (pkg) that is
385 configured and installed between two unpacked packages, the latter
386 won't be properly reordered, unless all installed/unpacked pkgs are
388 if (pkg
->state_status
== SS_NOT_INSTALLED
)
391 /* If the package has already been visited (by this function), skip it */
392 for(j
= 0; j
< visited
->len
; j
++)
393 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
394 opkg_message(conf
, OPKG_INFO
,
395 " pkg: %s already visited\n", pkg
->name
);
399 pkg_vec_insert(visited
, pkg
);
401 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
402 pkg
->recommends_count
+ pkg
->suggests_count
;
404 opkg_message(conf
, OPKG_INFO
,
405 " pkg: %s\n", pkg
->name
);
407 /* Iterate over all the dependencies of pkg. For each one, find a package
408 that is either installed or unpacked and satisfies this dependency.
409 (there should only be one such package per dependency installed or
410 unpacked). Then recurse to the dependency package */
411 for (j
=0; j
< count
; j
++) {
412 compound_depend
= &pkg
->depends
[j
];
413 possible_satisfiers
= compound_depend
->possibilities
;
414 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
415 abpkg
= possible_satisfiers
[k
]->pkg
;
416 dependents
= abpkg
->provided_by
->pkgs
;
418 if (dependents
!= NULL
)
419 while (l
< abpkg
->provided_by
->len
&& dependents
[l
] != NULL
) {
420 opkg_message(conf
, OPKG_INFO
,
421 " Descending on pkg: %s\n",
422 dependents
[l
]->name
);
424 /* find whether dependent l is installed or unpacked,
425 * and then find which package in the list satisfies it */
426 for(m
= 0; m
< all
->len
; m
++) {
428 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
429 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
430 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
432 /* Stop the outer loop */
433 l
= abpkg
->provided_by
->len
;
434 /* break from the inner loop */
443 /* When all recursions from this node down, are over, and all
444 dependencies have been added in proper order in the ordered array, add
445 also the package pkg to ordered array */
446 pkg_vec_insert(ordered
, pkg
);
452 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
454 pkg_vec_t
*all
, *ordered
, *visited
;
460 opkg_message(conf
, OPKG_INFO
,
461 "Configuring unpacked packages\n");
464 all
= pkg_vec_alloc();
466 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
468 /* Reorder pkgs in order to be configured according to the Depends: tag
470 opkg_message(conf
, OPKG_INFO
,
471 "Reordering packages before configuring them...\n");
472 ordered
= pkg_vec_alloc();
473 visited
= pkg_vec_alloc();
474 for(i
= 0; i
< all
->len
; i
++) {
476 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
479 ic
= opkg_prep_intercepts (conf
);
485 for(i
= 0; i
< all
->len
; i
++) {
488 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
491 if (pkg
->state_status
== SS_UNPACKED
) {
492 opkg_message(conf
, OPKG_NOTICE
,
493 "Configuring %s\n", pkg
->name
);
495 r
= opkg_configure(conf
, pkg
);
497 pkg
->state_status
= SS_INSTALLED
;
498 pkg
->parent
->state_status
= SS_INSTALLED
;
499 pkg
->state_flag
&= ~SF_PREFER
;
507 r
= opkg_finalize_intercepts (ic
);
513 pkg_vec_free(ordered
);
514 pkg_vec_free(visited
);
519 static opkg_conf_t
*global_conf
;
521 static void sigint_handler(int sig
)
523 signal(sig
, SIG_DFL
);
524 opkg_message(NULL
, OPKG_NOTICE
,
525 "opkg: interrupted. writing out status database\n");
526 write_status_files_if_changed(global_conf
);
530 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
537 signal(SIGINT
, sigint_handler
);
540 * Now scan through package names and install
542 for (i
=0; i
< argc
; i
++) {
545 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
546 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
547 if (err
!= EINVAL
&& err
!= 0)
550 pkg_info_preinstall_check(conf
);
552 for (i
=0; i
< argc
; i
++) {
554 err
= opkg_install_by_name(conf
, arg
);
555 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
556 opkg_message(conf
, OPKG_ERROR
,
557 "Cannot find package %s.\n",
562 opkg_configure_packages(conf
, NULL
);
564 write_status_files_if_changed(conf
);
569 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
576 signal(SIGINT
, sigint_handler
);
579 for (i
=0; i
< argc
; i
++) {
582 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
583 if (err
!= EINVAL
&& err
!= 0)
586 pkg_info_preinstall_check(conf
);
588 for (i
=0; i
< argc
; i
++) {
590 if (conf
->restrict_to_default_dest
) {
591 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
595 opkg_message(conf
, OPKG_NOTICE
,
596 "Package %s not installed in %s\n",
597 argv
[i
], conf
->default_dest
->name
);
601 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
605 opkg_upgrade_pkg(conf
, pkg
);
607 opkg_install_by_name(conf
, arg
);
611 pkg_vec_t
*installed
= pkg_vec_alloc();
613 pkg_info_preinstall_check(conf
);
615 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
616 for (i
= 0; i
< installed
->len
; i
++) {
617 pkg
= installed
->pkgs
[i
];
618 opkg_upgrade_pkg(conf
, pkg
);
620 pkg_vec_free(installed
);
623 opkg_configure_packages(conf
, NULL
);
625 write_status_files_if_changed(conf
);
630 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
636 pkg_info_preinstall_check(conf
);
637 for (i
= 0; i
< argc
; i
++) {
640 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
642 opkg_message(conf
, OPKG_ERROR
,
643 "Cannot find package %s.\n"
644 "Check the spelling or perhaps run 'opkg update'\n",
649 err
= opkg_download_pkg(conf
, pkg
, ".");
652 opkg_message(conf
, OPKG_ERROR
,
653 "Failed to download %s\n", pkg
->name
);
655 opkg_message(conf
, OPKG_NOTICE
,
656 "Downloaded %s as %s\n",
657 pkg
->name
, pkg
->local_filename
);
665 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
668 pkg_vec_t
*available
;
670 char *pkg_name
= NULL
;
675 available
= pkg_vec_alloc();
676 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
677 pkg_vec_sort(available
, pkg_compare_names
);
678 for (i
=0; i
< available
->len
; i
++) {
679 pkg
= available
->pkgs
[i
];
680 /* if we have package name or pattern and pkg does not match, then skip it */
681 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
685 pkg_vec_free(available
);
691 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
694 pkg_vec_t
*available
;
696 char *pkg_name
= NULL
;
701 available
= pkg_vec_alloc();
702 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
703 pkg_vec_sort(available
, pkg_compare_names
);
704 for (i
=0; i
< available
->len
; i
++) {
705 pkg
= available
->pkgs
[i
];
706 /* if we have package name or pattern and pkg does not match, then skip it */
707 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
712 pkg_vec_free(available
);
717 static int opkg_list_upgradable_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
719 struct active_list
*head
= prepare_upgrade_list(conf
);
720 struct active_list
*node
=NULL
;
721 pkg_t
*_old_pkg
, *_new_pkg
;
723 for (node
= active_list_next(head
, head
); node
;node
= active_list_next(head
,node
)) {
724 _old_pkg
= list_entry(node
, pkg_t
, list
);
725 _new_pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, _old_pkg
->name
, NULL
);
726 old_v
= pkg_version_str_alloc(_old_pkg
);
727 new_v
= pkg_version_str_alloc(_new_pkg
);
728 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
732 active_list_head_delete(head
);
736 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
739 pkg_vec_t
*available
;
741 char *pkg_name
= NULL
;
747 available
= pkg_vec_alloc();
749 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
751 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
753 for (i
=0; i
< available
->len
; i
++) {
754 pkg
= available
->pkgs
[i
];
755 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
759 pkg_formatted_info(stdout
, pkg
);
761 if (conf
->verbosity
> 1) {
762 conffile_list_elt_t
*iter
;
763 for (iter
= nv_pair_list_first(&pkg
->conffiles
); iter
; iter
= nv_pair_list_next(&pkg
->conffiles
, iter
)) {
764 conffile_t
*cf
= (conffile_t
*)iter
->data
;
765 int modified
= conffile_has_been_modified(conf
, cf
);
767 opkg_message(conf
, OPKG_NOTICE
,
768 "conffile=%s md5sum=%s modified=%d\n",
769 cf
->name
, cf
->value
, modified
);
773 pkg_vec_free(available
);
778 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
780 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
783 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
785 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
788 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
793 char *pkg_name
= NULL
;
797 err
= opkg_configure_packages (conf
, pkg_name
);
800 err
= opkg_configure_packages (conf
, NULL
);
803 write_status_files_if_changed(conf
);
808 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
814 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
815 err
= glob(globpattern
, 0, NULL
, &globbuf
);
821 opkg_message(conf
, OPKG_NOTICE
,
822 "The following packages in %s will now be installed.\n",
824 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
825 opkg_message(conf
, OPKG_NOTICE
,
826 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
828 opkg_message(conf
, OPKG_NOTICE
, "\n");
829 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
830 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
832 err
= unlink(globbuf
.gl_pathv
[i
]);
834 opkg_message(conf
, OPKG_ERROR
,
835 "%s: ERROR: failed to unlink %s: %s\n",
836 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
846 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
850 pkg_t
*pkg_to_remove
;
851 pkg_vec_t
*available
;
852 char *pkg_name
= NULL
;
854 signal(SIGINT
, sigint_handler
);
856 // ENH: Add the "no pkg removed" just in case.
860 pkg_info_preinstall_check(conf
);
862 available
= pkg_vec_alloc();
863 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
864 for (i
=0; i
< argc
; i
++) {
865 pkg_name
= xcalloc(1, strlen(argv
[i
])+2);
866 strcpy(pkg_name
,argv
[i
]);
867 for (a
=0; a
< available
->len
; a
++) {
868 pkg
= available
->pkgs
[a
];
869 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
872 if (conf
->restrict_to_default_dest
) {
873 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
877 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
880 if (pkg_to_remove
== NULL
) {
881 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
884 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
885 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
888 opkg_remove_pkg(conf
, pkg_to_remove
,0);
893 pkg_vec_free(available
);
895 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
897 int flagged_pkg_count
= 0;
900 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
902 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
903 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
904 if (pkg
->state_flag
& SF_USER
) {
907 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
908 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
911 if (!flagged_pkg_count
) {
912 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
913 "so refusing to uninstall unflagged non-leaf packages\n");
917 /* find packages not flagged SF_USER (i.e., installed to
918 * satisfy a dependence) and not having any dependents, and
922 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
923 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
924 if (!(pkg
->state_flag
& SF_USER
)
925 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
927 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
928 opkg_remove_pkg(conf
, pkg
,0);
933 pkg_vec_free(installed_pkgs
);
937 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
939 write_status_files_if_changed(conf
);
943 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
949 signal(SIGINT
, sigint_handler
);
951 pkg_info_preinstall_check(conf
);
953 for (i
=0; i
< argc
; i
++) {
954 if (conf
->restrict_to_default_dest
) {
955 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
959 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
963 opkg_message(conf
, OPKG_ERROR
,
964 "Package %s is not installed.\n", argv
[i
]);
967 opkg_purge_pkg(conf
, pkg
);
970 write_status_files_if_changed(conf
);
974 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
978 const char *flags
= argv
[0];
981 signal(SIGINT
, sigint_handler
);
983 for (i
=1; i
< argc
; i
++) {
984 if (conf
->restrict_to_default_dest
) {
985 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
989 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
993 opkg_message(conf
, OPKG_ERROR
,
994 "Package %s is not installed.\n", argv
[i
]);
997 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
998 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
999 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1001 /* pb_ asked this feature 03292004 */
1002 /* Actually I will use only this two, but this is an open for various status */
1003 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1004 pkg
->state_status
= pkg_state_status_from_str(flags
);
1006 opkg_state_changed
++;
1007 opkg_message(conf
, OPKG_NOTICE
,
1008 "Setting flags for package %s to %s\n",
1012 write_status_files_if_changed(conf
);
1016 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1020 str_list_elt_t
*iter
;
1027 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1030 opkg_message(conf
, OPKG_ERROR
,
1031 "Package %s not installed.\n", argv
[0]);
1035 files
= pkg_get_installed_files(pkg
);
1036 pkg_version
= pkg_version_str_alloc(pkg
);
1038 printf("Package %s (%s) is installed on %s and has the following files:\n",
1039 pkg
->name
, pkg_version
, pkg
->dest
->name
);
1041 for (iter
=str_list_first(files
); iter
; iter
=str_list_next(files
, iter
))
1042 printf("%s\n", (char *)iter
->data
);
1045 pkg_free_installed_files(pkg
);
1050 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1054 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1055 const char *rel_str
= "depends on";
1058 pkg_info_preinstall_check(conf
);
1060 if (conf
->query_all
)
1061 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1063 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1064 for (i
= 0; i
< argc
; i
++) {
1065 const char *target
= argv
[i
];
1068 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1070 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1071 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1072 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1074 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1075 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1076 target
, pkg
->architecture
, rel_str
);
1077 for (k
= 0; k
< count
; k
++) {
1078 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1080 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1081 depend_t
*possibility
= cdepend
->possibilities
[l
];
1082 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1083 if (conf
->verbosity
> 0) {
1084 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1085 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1086 if (possibility
->version
) {
1087 char *typestr
= NULL
;
1088 switch (possibility
->constraint
) {
1089 case NONE
: typestr
= "none"; break;
1090 case EARLIER
: typestr
= "<"; break;
1091 case EARLIER_EQUAL
: typestr
= "<="; break;
1092 case EQUAL
: typestr
= "="; break;
1093 case LATER_EQUAL
: typestr
= ">="; break;
1094 case LATER
: typestr
= ">"; break;
1096 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1100 opkg_message(conf
, OPKG_ERROR
, "\n");
1106 pkg_vec_free(available_pkgs
);
1111 enum what_field_type
{
1120 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1124 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1125 const char *rel_str
= NULL
;
1129 switch (what_field_type
) {
1130 case WHATDEPENDS
: rel_str
= "depends on"; break;
1131 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1132 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1133 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1134 case WHATPROVIDES
: rel_str
= "provides"; break;
1135 case WHATREPLACES
: rel_str
= "replaces"; break;
1138 if (conf
->query_all
)
1139 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1141 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1143 /* mark the root set */
1144 pkg_vec_clear_marks(available_pkgs
);
1145 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1146 for (i
= 0; i
< argc
; i
++) {
1147 const char *dependee_pattern
= argv
[i
];
1148 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1150 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1151 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1152 if (pkg
->state_flag
& SF_MARKED
) {
1153 /* mark the parent (abstract) package */
1154 pkg_mark_provides(pkg
);
1155 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1159 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1164 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1165 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1167 int count
= ((what_field_type
== WHATCONFLICTS
)
1168 ? pkg
->conflicts_count
1169 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1170 /* skip this package if it is already marked */
1171 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1174 for (k
= 0; k
< count
; k
++) {
1175 compound_depend_t
*cdepend
=
1176 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1178 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1179 depend_t
*possibility
= cdepend
->possibilities
[l
];
1180 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1181 /* mark the depending package so we won't visit it again */
1182 pkg
->state_flag
|= SF_MARKED
;
1183 pkg_mark_provides(pkg
);
1186 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1187 if (conf
->verbosity
> 0) {
1188 char *ver
= pkg_version_str_alloc(pkg
);
1189 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1190 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1191 if (possibility
->version
) {
1192 char *typestr
= NULL
;
1193 switch (possibility
->constraint
) {
1194 case NONE
: typestr
= "none"; break;
1195 case EARLIER
: typestr
= "<"; break;
1196 case EARLIER_EQUAL
: typestr
= "<="; break;
1197 case EQUAL
: typestr
= "="; break;
1198 case LATER_EQUAL
: typestr
= ">="; break;
1199 case LATER
: typestr
= ">"; break;
1201 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1204 if (!pkg_dependence_satisfiable(conf
, possibility
))
1205 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1207 opkg_message(conf
, OPKG_NOTICE
, "\n");
1215 } while (changed
&& recursive
);
1216 pkg_vec_free(available_pkgs
);
1222 static int pkg_mark_provides(pkg_t
*pkg
)
1224 int provides_count
= pkg
->provides_count
;
1225 abstract_pkg_t
**provides
= pkg
->provides
;
1227 pkg
->parent
->state_flag
|= SF_MARKED
;
1228 for (i
= 0; i
< provides_count
; i
++) {
1229 provides
[i
]->state_flag
|= SF_MARKED
;
1234 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1236 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1238 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1240 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1243 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1245 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1248 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1250 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1253 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1255 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1258 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1262 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1263 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1266 pkg_info_preinstall_check(conf
);
1268 if (conf
->query_all
)
1269 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1271 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1272 for (i
= 0; i
< argc
; i
++) {
1273 const char *target
= argv
[i
];
1276 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1278 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1279 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1281 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1282 for (k
= 0; k
< count
; k
++) {
1283 abstract_pkg_t
*apkg
=
1284 ((what_field_type
== WHATPROVIDES
)
1286 : pkg
->replaces
[k
]);
1287 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1288 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1289 if (strcmp(target
, apkg
->name
) != 0)
1290 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1291 opkg_message(conf
, OPKG_ERROR
, "\n");
1296 pkg_vec_free(available_pkgs
);
1301 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1303 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1306 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1308 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1311 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1315 pkg_vec_t
*installed
;
1317 str_list_t
*installed_files
;
1318 str_list_elt_t
*iter
;
1319 char *installed_file
;
1325 installed
= pkg_vec_alloc();
1326 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1327 pkg_vec_sort(installed
, pkg_compare_names
);
1329 for (i
=0; i
< installed
->len
; i
++) {
1330 pkg
= installed
->pkgs
[i
];
1332 installed_files
= pkg_get_installed_files(pkg
);
1334 for (iter
= str_list_first(installed_files
); iter
; iter
= str_list_next(installed_files
, iter
)) {
1335 installed_file
= (char *)iter
->data
;
1336 if (fnmatch(argv
[0], installed_file
, 0)==0)
1340 pkg_free_installed_files(pkg
);
1343 pkg_vec_free(installed
);
1348 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1351 /* this is a bit gross */
1353 parseVersion(&p1
, argv
[0]);
1354 parseVersion(&p2
, argv
[2]);
1355 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1357 opkg_message(conf
, OPKG_ERROR
,
1358 "opkg compare_versions <v1> <op> <v2>\n"
1359 "<op> is one of <= >= << >> =\n");
1364 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1366 nv_pair_list_elt_t
*l
;
1368 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1369 nv_pair_t
*nv
= (nv_pair_t
*)l
->data
;
1370 printf("arch %s %s\n", nv
->name
, nv
->value
);