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_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 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
85 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
86 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
87 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
88 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
89 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
90 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
91 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
92 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
93 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
94 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
95 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
96 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
97 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
98 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
99 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
100 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
101 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
102 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
103 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
104 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
105 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
106 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
107 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
108 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
111 int opkg_state_changed
;
112 static void write_status_files_if_changed(opkg_conf_t
*conf
)
114 if (opkg_state_changed
&& !conf
->noaction
) {
115 opkg_message(conf
, OPKG_INFO
,
116 " writing status file\n");
117 opkg_conf_write_status_files(conf
);
118 pkg_write_changed_filelists(conf
);
120 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
125 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
127 opkg_cmd_t
*opkg_cmd_find(const char *name
)
132 for (i
=0; i
< num_cmds
; i
++) {
134 if (strcmp(name
, cmd
->name
) == 0) {
142 void opkg_print_error_list (opkg_conf_t
*conf
)
145 reverse_error_list(&error_list
);
147 printf ("Collected errors:\n");
148 /* Here we print the errors collected and free the list */
149 while (error_list
!= NULL
) {
150 printf (" * %s", error_list
->errmsg
);
151 error_list
= error_list
->next
;
154 free_error_list(&error_list
);
159 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
162 p_userdata
= userdata
;
165 result
= (cmd
->fun
)(conf
, argc
, argv
);
167 if ( result
!= 0 && !error_list
) {
168 opkg_message(conf
, OPKG_NOTICE
, "An error ocurred, return value: %d.\n", result
);
171 opkg_print_error_list (conf
);
177 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
183 pkg_src_list_elt_t
*iter
;
187 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
189 if (! file_is_dir(lists_dir
)) {
190 if (file_exists(lists_dir
)) {
191 opkg_message(conf
, OPKG_ERROR
,
192 "%s: ERROR: %s exists, but is not a directory\n",
193 __FUNCTION__
, lists_dir
);
197 err
= file_mkdir_hier(lists_dir
, 0755);
199 opkg_message(conf
, OPKG_ERROR
,
200 "%s: ERROR: failed to make directory %s: %s\n",
201 __FUNCTION__
, lists_dir
, strerror(errno
));
210 tmp
= strdup ("/tmp/opkg.XXXXXX");
212 if (mkdtemp (tmp
) == NULL
) {
218 for (iter
= conf
->pkg_src_list
.head
; iter
; iter
= iter
->next
) {
219 char *url
, *list_file_name
;
223 if (src
->extra_data
) /* debian style? */
224 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
225 src
->gzip
? "Packages.gz" : "Packages");
227 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
229 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
234 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
235 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
237 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
238 in
= fopen (tmp_file_name
, "r");
239 out
= fopen (list_file_name
, "w");
248 unlink (tmp_file_name
);
251 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
255 opkg_message(conf
, OPKG_NOTICE
,
256 "Updated list of available packages in %s\n",
262 /* download detached signitures to verify the package lists */
263 /* get the url for the sig file */
264 if (src
->extra_data
) /* debian style? */
265 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
268 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
270 /* create temporary file for it */
273 sprintf_alloc (&tmp_file_name
, "%s/%s", tmp
, "Packages.sig");
275 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
278 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
281 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
283 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
285 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
287 unlink (tmp_file_name
);
288 free (tmp_file_name
);
291 opkg_message (conf
, OPKG_NOTICE
, "Signature check for %s skipped "
292 "because GPG support was not enabled in this build\n", src
->name
);
294 free(list_file_name
);
304 struct opkg_intercept
310 typedef struct opkg_intercept
*opkg_intercept_t
;
312 static opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
314 opkg_intercept_t ctx
;
319 ctx
= malloc (sizeof (*ctx
));
320 oldpath
= getenv ("PATH");
322 ctx
->oldpath
= strdup (oldpath
);
328 sprintf_alloc (&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
329 setenv ("PATH", newpath
, 1);
334 sprintf_alloc (&ctx
->statedir
, "/tmp/opkg-intercept-%d-%d", getpid (), gen
);
335 if (mkdir (ctx
->statedir
, 0770) < 0) {
336 if (errno
== EEXIST
) {
337 free (ctx
->statedir
);
341 perror (ctx
->statedir
);
344 setenv ("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
348 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
355 setenv ("PATH", ctx
->oldpath
, 1);
361 dir
= opendir (ctx
->statedir
);
364 while (de
= readdir (dir
), de
!= NULL
) {
367 if (de
->d_name
[0] == '.')
370 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
371 if (access (path
, X_OK
) == 0) {
380 perror (ctx
->statedir
);
382 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
386 free (ctx
->statedir
);
392 /* For package pkg do the following: If it is already visited, return. If not,
393 add it in visited list and recurse to its deps. Finally, add it to ordered
395 pkg_vec all contains all available packages in repos.
396 pkg_vec visited contains packages already visited by this function, and is
397 used to end recursion and avoid an infinite loop on graph cycles.
398 pkg_vec ordered will finally contain the ordered set of packages.
400 static int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
401 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
406 compound_depend_t
* compound_depend
;
407 depend_t
** possible_satisfiers
;
408 abstract_pkg_t
*abpkg
;
409 abstract_pkg_t
**dependents
;
411 /* If it's just an available package, that is, not installed and not even
413 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
414 would do here. However, if there is an intermediate node (pkg) that is
415 configured and installed between two unpacked packages, the latter
416 won't be properly reordered, unless all installed/unpacked pkgs are
418 if (pkg
->state_status
== SS_NOT_INSTALLED
)
421 /* If the package has already been visited (by this function), skip it */
422 for(j
= 0; j
< visited
->len
; j
++)
423 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
424 opkg_message(conf
, OPKG_INFO
,
425 " pkg: %s already visited\n", pkg
->name
);
429 pkg_vec_insert(visited
, pkg
);
431 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
432 pkg
->recommends_count
+ pkg
->suggests_count
;
434 opkg_message(conf
, OPKG_INFO
,
435 " pkg: %s\n", pkg
->name
);
437 /* Iterate over all the dependencies of pkg. For each one, find a package
438 that is either installed or unpacked and satisfies this dependency.
439 (there should only be one such package per dependency installed or
440 unpacked). Then recurse to the dependency package */
441 for (j
=0; j
< count
; j
++) {
442 compound_depend
= &pkg
->depends
[j
];
443 possible_satisfiers
= compound_depend
->possibilities
;
444 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
445 abpkg
= possible_satisfiers
[k
]->pkg
;
446 dependents
= abpkg
->provided_by
->pkgs
;
448 if (dependents
!= NULL
)
449 while (dependents
[l
] != NULL
&& l
< abpkg
->provided_by
->len
) {
450 opkg_message(conf
, OPKG_INFO
,
451 " Descending on pkg: %s\n",
452 dependents
[l
]->name
);
454 /* find whether dependent l is installed or unpacked,
455 * and then find which package in the list satisfies it */
456 for(m
= 0; m
< all
->len
; m
++) {
458 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
459 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
460 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
462 /* Stop the outer loop */
463 l
= abpkg
->provided_by
->len
;
464 /* break from the inner loop */
473 /* When all recursions from this node down, are over, and all
474 dependencies have been added in proper order in the ordered array, add
475 also the package pkg to ordered array */
476 pkg_vec_insert(ordered
, pkg
);
482 static int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
484 pkg_vec_t
*all
, *ordered
, *visited
;
490 opkg_message(conf
, OPKG_INFO
,
491 "Configuring unpacked packages\n");
494 all
= pkg_vec_alloc();
496 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
498 /* Reorder pkgs in order to be configured according to the Depends: tag
500 opkg_message(conf
, OPKG_INFO
,
501 "Reordering packages before configuring them...\n");
502 ordered
= pkg_vec_alloc();
503 visited
= pkg_vec_alloc();
504 for(i
= 0; i
< all
->len
; i
++) {
506 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
510 ic
= opkg_prep_intercepts (conf
);
512 for(i
= 0; i
< all
->len
; i
++) {
515 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
518 if (pkg
->state_status
== SS_UNPACKED
) {
519 opkg_message(conf
, OPKG_NOTICE
,
520 "Configuring %s\n", pkg
->name
);
522 r
= opkg_configure(conf
, pkg
);
524 pkg
->state_status
= SS_INSTALLED
;
525 pkg
->parent
->state_status
= SS_INSTALLED
;
526 pkg
->state_flag
&= ~SF_PREFER
;
534 r
= opkg_finalize_intercepts (ic
);
539 pkg_vec_free(ordered
);
540 pkg_vec_free(visited
);
545 static opkg_conf_t
*global_conf
;
547 static void sigint_handler(int sig
)
549 signal(sig
, SIG_DFL
);
550 opkg_message(NULL
, OPKG_NOTICE
,
551 "opkg: interrupted. writing out status database\n");
552 write_status_files_if_changed(global_conf
);
556 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
563 signal(SIGINT
, sigint_handler
);
566 * Now scan through package names and install
568 for (i
=0; i
< argc
; i
++) {
571 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
572 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
573 if (err
!= EINVAL
&& err
!= 0)
576 pkg_info_preinstall_check(conf
);
578 for (i
=0; i
< argc
; i
++) {
580 err
= opkg_install_by_name(conf
, arg
);
581 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
582 opkg_message(conf
, OPKG_ERROR
,
583 "Cannot find package %s.\n",
588 /* recheck to verify that all dependences are satisfied */
589 if (0) opkg_satisfy_all_dependences(conf
);
591 opkg_configure_packages(conf
, NULL
);
593 write_status_files_if_changed(conf
);
598 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
605 signal(SIGINT
, sigint_handler
);
608 for (i
=0; i
< argc
; i
++) {
611 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
612 if (err
!= EINVAL
&& err
!= 0)
615 pkg_info_preinstall_check(conf
);
617 for (i
=0; i
< argc
; i
++) {
619 if (conf
->restrict_to_default_dest
) {
620 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
624 opkg_message(conf
, OPKG_NOTICE
,
625 "Package %s not installed in %s\n",
626 argv
[i
], conf
->default_dest
->name
);
630 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
634 opkg_upgrade_pkg(conf
, pkg
);
636 opkg_install_by_name(conf
, arg
);
640 pkg_vec_t
*installed
= pkg_vec_alloc();
642 pkg_info_preinstall_check(conf
);
644 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
645 for (i
= 0; i
< installed
->len
; i
++) {
646 pkg
= installed
->pkgs
[i
];
647 opkg_upgrade_pkg(conf
, pkg
);
649 pkg_vec_free(installed
);
652 /* recheck to verify that all dependences are satisfied */
653 if (0) opkg_satisfy_all_dependences(conf
);
655 opkg_configure_packages(conf
, NULL
);
657 write_status_files_if_changed(conf
);
662 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
668 pkg_info_preinstall_check(conf
);
669 for (i
= 0; i
< argc
; i
++) {
672 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
674 opkg_message(conf
, OPKG_ERROR
,
675 "Cannot find package %s.\n"
676 "Check the spelling or perhaps run 'opkg update'\n",
681 err
= opkg_download_pkg(conf
, pkg
, ".");
684 opkg_message(conf
, OPKG_ERROR
,
685 "Failed to download %s\n", pkg
->name
);
687 opkg_message(conf
, OPKG_NOTICE
,
688 "Downloaded %s as %s\n",
689 pkg
->name
, pkg
->local_filename
);
697 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
700 pkg_vec_t
*available
;
702 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
704 char *pkg_name
= NULL
;
710 available
= pkg_vec_alloc();
711 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
712 for (i
=0; i
< available
->len
; i
++) {
713 pkg
= available
->pkgs
[i
];
714 /* if we have package name or pattern and pkg does not match, then skip it */
715 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
717 if (pkg
->description
) {
718 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
720 desc_short
[0] = '\0';
722 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
723 newline
= strchr(desc_short
, '\n');
728 version_str
= pkg_version_str_alloc(pkg
);
729 opkg_cb_list(pkg
->name
,desc_short
,
736 pkg_vec_free(available
);
742 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
745 pkg_vec_t
*available
;
747 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
749 char *pkg_name
= NULL
;
755 available
= pkg_vec_alloc();
756 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
757 for (i
=0; i
< available
->len
; i
++) {
758 pkg
= available
->pkgs
[i
];
759 /* if we have package name or pattern and pkg does not match, then skip it */
760 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
762 if (pkg
->description
) {
763 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
765 desc_short
[0] = '\0';
767 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
768 newline
= strchr(desc_short
, '\n');
773 version_str
= pkg_version_str_alloc(pkg
);
774 opkg_cb_list(pkg
->name
,desc_short
,
785 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
788 pkg_vec_t
*available
;
790 char *pkg_name
= NULL
;
791 char **pkg_fields
= NULL
;
793 char *buff
; // = (char *)malloc(1);
799 pkg_fields
= &argv
[1];
803 available
= pkg_vec_alloc();
805 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
807 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
808 for (i
=0; i
< available
->len
; i
++) {
809 pkg
= available
->pkgs
[i
];
810 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
814 buff
= pkg_formatted_info(pkg
);
816 if (opkg_cb_status
) opkg_cb_status(pkg
->name
,
821 We should not forget that actually the pointer is allocated.
822 We need to free it :) ( Thanks florian for seeing the error )
826 if (conf
->verbosity
> 1) {
827 conffile_list_elt_t
*iter
;
828 for (iter
= pkg
->conffiles
.head
; iter
; iter
= iter
->next
) {
829 conffile_t
*cf
= iter
->data
;
830 int modified
= conffile_has_been_modified(conf
, cf
);
831 opkg_message(conf
, OPKG_NOTICE
, "conffile=%s md5sum=%s modified=%d\n",
832 cf
->name
, cf
->value
, modified
);
836 pkg_vec_free(available
);
841 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
843 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
846 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
848 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
851 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
856 char *pkg_name
= NULL
;
860 err
= opkg_configure_packages (conf
, pkg_name
);
863 err
= opkg_configure_packages (conf
, NULL
);
866 write_status_files_if_changed(conf
);
871 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
877 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
878 err
= glob(globpattern
, 0, NULL
, &globbuf
);
884 opkg_message(conf
, OPKG_NOTICE
,
885 "The following packages in %s will now be installed.\n",
887 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
888 opkg_message(conf
, OPKG_NOTICE
,
889 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
891 opkg_message(conf
, OPKG_NOTICE
, "\n");
892 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
893 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
895 err
= unlink(globbuf
.gl_pathv
[i
]);
897 opkg_message(conf
, OPKG_ERROR
,
898 "%s: ERROR: failed to unlink %s: %s\n",
899 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
909 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
913 pkg_t
*pkg_to_remove
;
914 pkg_vec_t
*available
;
915 char *pkg_name
= NULL
;
917 signal(SIGINT
, sigint_handler
);
919 // ENH: Add the "no pkg removed" just in case.
923 pkg_info_preinstall_check(conf
);
925 available
= pkg_vec_alloc();
926 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
927 for (i
=0; i
< argc
; i
++) {
928 pkg_name
= malloc(strlen(argv
[i
])+2);
929 strcpy(pkg_name
,argv
[i
]);
930 for (a
=0; a
< available
->len
; a
++) {
931 pkg
= available
->pkgs
[a
];
932 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
935 if (conf
->restrict_to_default_dest
) {
936 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
940 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
944 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
947 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
948 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
951 opkg_remove_pkg(conf
, pkg_to_remove
,0);
956 pkg_vec_free(available
);
958 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
960 int flagged_pkg_count
= 0;
963 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
965 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
966 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
967 if (pkg
->state_flag
& SF_USER
) {
970 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
971 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
974 if (!flagged_pkg_count
) {
975 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
976 "so refusing to uninstall unflagged non-leaf packages\n");
980 /* find packages not flagged SF_USER (i.e., installed to
981 * satisfy a dependence) and not having any dependents, and
985 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
986 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
987 if (!(pkg
->state_flag
& SF_USER
)
988 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
990 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
991 opkg_remove_pkg(conf
, pkg
,0);
996 pkg_vec_free(installed_pkgs
);
1000 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
1002 write_status_files_if_changed(conf
);
1006 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1012 signal(SIGINT
, sigint_handler
);
1014 pkg_info_preinstall_check(conf
);
1016 for (i
=0; i
< argc
; i
++) {
1017 if (conf
->restrict_to_default_dest
) {
1018 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1020 conf
->default_dest
);
1022 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1026 opkg_message(conf
, OPKG_ERROR
,
1027 "Package %s is not installed.\n", argv
[i
]);
1030 opkg_purge_pkg(conf
, pkg
);
1033 write_status_files_if_changed(conf
);
1037 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1041 const char *flags
= argv
[0];
1044 signal(SIGINT
, sigint_handler
);
1046 for (i
=1; i
< argc
; i
++) {
1047 if (conf
->restrict_to_default_dest
) {
1048 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1050 conf
->default_dest
);
1052 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1056 opkg_message(conf
, OPKG_ERROR
,
1057 "Package %s is not installed.\n", argv
[i
]);
1060 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1061 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1062 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1064 /* pb_ asked this feature 03292004 */
1065 /* Actually I will use only this two, but this is an open for various status */
1066 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1067 pkg
->state_status
= pkg_state_status_from_str(flags
);
1069 opkg_state_changed
++;
1070 opkg_message(conf
, OPKG_NOTICE
,
1071 "Setting flags for package %s to %s\n",
1075 write_status_files_if_changed(conf
);
1079 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1082 str_list_t
*installed_files
;
1083 str_list_elt_t
*iter
;
1085 size_t buff_len
= 8192;
1089 buff
= (char *)malloc(buff_len
);
1090 if ( buff
== NULL
) {
1091 fprintf( stderr
,"%s: Unable to allocate memory \n",__FUNCTION__
);
1099 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1102 opkg_message(conf
, OPKG_ERROR
,
1103 "Package %s not installed.\n", argv
[0]);
1107 installed_files
= pkg_get_installed_files(pkg
);
1108 pkg_version
= pkg_version_str_alloc(pkg
);
1112 used_len
= snprintf(buff
, buff_len
, "Package %s (%s) is installed on %s and has the following files:\n",
1113 pkg
->name
, pkg_version
, pkg
->dest
->name
) + 1;
1114 if (used_len
> buff_len
) {
1116 buff
= realloc (buff
, buff_len
);
1119 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1120 used_len
+= strlen (iter
->data
) + 1;
1121 while (buff_len
<= used_len
) {
1123 buff
= realloc (buff
, buff_len
);
1125 strncat(buff
, iter
->data
, buff_len
);
1126 strncat(buff
, "\n", buff_len
);
1128 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1130 pkg_version_str_alloc(pkg
),
1137 pkg_free_installed_files(pkg
);
1142 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1146 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1147 const char *rel_str
= "depends on";
1150 pkg_info_preinstall_check(conf
);
1152 if (conf
->query_all
)
1153 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1155 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1156 for (i
= 0; i
< argc
; i
++) {
1157 const char *target
= argv
[i
];
1160 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1162 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1163 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1164 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1166 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1167 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1168 target
, pkg
->architecture
, rel_str
);
1169 for (k
= 0; k
< count
; k
++) {
1170 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1172 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1173 depend_t
*possibility
= cdepend
->possibilities
[l
];
1174 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1175 if (conf
->verbosity
> 0) {
1176 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1177 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1178 if (possibility
->version
) {
1179 char *typestr
= NULL
;
1180 switch (possibility
->constraint
) {
1181 case NONE
: typestr
= "none"; break;
1182 case EARLIER
: typestr
= "<"; break;
1183 case EARLIER_EQUAL
: typestr
= "<="; break;
1184 case EQUAL
: typestr
= "="; break;
1185 case LATER_EQUAL
: typestr
= ">="; break;
1186 case LATER
: typestr
= ">"; break;
1188 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1192 opkg_message(conf
, OPKG_ERROR
, "\n");
1198 pkg_vec_free(available_pkgs
);
1203 enum what_field_type
{
1212 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1216 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1217 const char *rel_str
= NULL
;
1221 switch (what_field_type
) {
1222 case WHATDEPENDS
: rel_str
= "depends on"; break;
1223 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1224 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1225 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1226 case WHATPROVIDES
: rel_str
= "provides"; break;
1227 case WHATREPLACES
: rel_str
= "replaces"; break;
1230 if (conf
->query_all
)
1231 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1233 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1235 /* mark the root set */
1236 pkg_vec_clear_marks(available_pkgs
);
1237 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1238 for (i
= 0; i
< argc
; i
++) {
1239 const char *dependee_pattern
= argv
[i
];
1240 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1242 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1243 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1244 if (pkg
->state_flag
& SF_MARKED
) {
1245 /* mark the parent (abstract) package */
1246 pkg_mark_provides(pkg
);
1247 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1251 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1256 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1257 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1259 int count
= ((what_field_type
== WHATCONFLICTS
)
1260 ? pkg
->conflicts_count
1261 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1262 /* skip this package if it is already marked */
1263 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1266 for (k
= 0; k
< count
; k
++) {
1267 compound_depend_t
*cdepend
=
1268 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1270 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1271 depend_t
*possibility
= cdepend
->possibilities
[l
];
1272 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1273 /* mark the depending package so we won't visit it again */
1274 pkg
->state_flag
|= SF_MARKED
;
1275 pkg_mark_provides(pkg
);
1278 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1279 if (conf
->verbosity
> 0) {
1280 char *ver
= pkg_version_str_alloc(pkg
);
1281 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1282 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1283 if (possibility
->version
) {
1284 char *typestr
= NULL
;
1285 switch (possibility
->constraint
) {
1286 case NONE
: typestr
= "none"; break;
1287 case EARLIER
: typestr
= "<"; break;
1288 case EARLIER_EQUAL
: typestr
= "<="; break;
1289 case EQUAL
: typestr
= "="; break;
1290 case LATER_EQUAL
: typestr
= ">="; break;
1291 case LATER
: typestr
= ">"; break;
1293 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1296 if (!pkg_dependence_satisfiable(conf
, possibility
))
1297 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1299 opkg_message(conf
, OPKG_NOTICE
, "\n");
1307 } while (changed
&& recursive
);
1308 pkg_vec_free(available_pkgs
);
1314 static int pkg_mark_provides(pkg_t
*pkg
)
1316 int provides_count
= pkg
->provides_count
;
1317 abstract_pkg_t
**provides
= pkg
->provides
;
1319 pkg
->parent
->state_flag
|= SF_MARKED
;
1320 for (i
= 0; i
< provides_count
; i
++) {
1321 provides
[i
]->state_flag
|= SF_MARKED
;
1326 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1328 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1330 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1332 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1335 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1337 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1340 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1342 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1345 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1347 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1350 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1354 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1355 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1358 pkg_info_preinstall_check(conf
);
1360 if (conf
->query_all
)
1361 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1363 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1364 for (i
= 0; i
< argc
; i
++) {
1365 const char *target
= argv
[i
];
1368 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1370 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1371 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1373 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1374 for (k
= 0; k
< count
; k
++) {
1375 abstract_pkg_t
*apkg
=
1376 ((what_field_type
== WHATPROVIDES
)
1378 : pkg
->replaces
[k
]);
1379 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1380 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1381 if (strcmp(target
, apkg
->name
) != 0)
1382 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1383 opkg_message(conf
, OPKG_ERROR
, "\n");
1388 pkg_vec_free(available_pkgs
);
1393 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1395 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1398 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1400 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1403 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1407 pkg_vec_t
*installed
;
1409 str_list_t
*installed_files
;
1410 str_list_elt_t
*iter
;
1411 char *installed_file
;
1417 installed
= pkg_vec_alloc();
1418 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1420 for (i
=0; i
< installed
->len
; i
++) {
1421 pkg
= installed
->pkgs
[i
];
1423 installed_files
= pkg_get_installed_files(pkg
);
1425 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1426 installed_file
= iter
->data
;
1427 if (fnmatch(argv
[0], installed_file
, 0)==0) {
1428 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1430 pkg_version_str_alloc(pkg
),
1431 pkg
->state_status
, p_userdata
);
1435 pkg_free_installed_files(pkg
);
1438 /* XXX: CLEANUP: It's not obvious from the name of
1439 pkg_hash_fetch_all_installed that we need to call
1440 pkg_vec_free to avoid a memory leak. */
1441 pkg_vec_free(installed
);
1446 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1449 /* this is a bit gross */
1451 parseVersion(&p1
, argv
[0]);
1452 parseVersion(&p2
, argv
[2]);
1453 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1455 opkg_message(conf
, OPKG_ERROR
,
1456 "opkg compare_versions <v1> <op> <v2>\n"
1457 "<op> is one of <= >= << >> =\n");
1462 #ifndef HOST_CPU_STR
1463 #define HOST_CPU_STR__(X) #X
1464 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1465 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1468 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1470 nv_pair_list_elt_t
*l
;
1472 l
= conf
->arch_list
.head
;
1474 nv_pair_t
*nv
= l
->data
;
1475 printf("arch %s %s\n", nv
->name
, nv
->value
);