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
);
76 /* XXX: CLEANUP: The usage strings should be incorporated into this
77 array for easier maintenance */
78 static opkg_cmd_t cmds
[] = {
79 {"update", 0, (opkg_cmd_fun_t
)opkg_update_cmd
},
80 {"upgrade", 0, (opkg_cmd_fun_t
)opkg_upgrade_cmd
},
81 {"list", 0, (opkg_cmd_fun_t
)opkg_list_cmd
},
82 {"list_installed", 0, (opkg_cmd_fun_t
)opkg_list_installed_cmd
},
83 {"info", 0, (opkg_cmd_fun_t
)opkg_info_cmd
},
84 {"flag", 1, (opkg_cmd_fun_t
)opkg_flag_cmd
},
85 {"status", 0, (opkg_cmd_fun_t
)opkg_status_cmd
},
86 {"install_pending", 0, (opkg_cmd_fun_t
)opkg_install_pending_cmd
},
87 {"install", 1, (opkg_cmd_fun_t
)opkg_install_cmd
},
88 {"remove", 1, (opkg_cmd_fun_t
)opkg_remove_cmd
},
89 {"purge", 1, (opkg_cmd_fun_t
)opkg_purge_cmd
},
90 {"configure", 0, (opkg_cmd_fun_t
)opkg_configure_cmd
},
91 {"files", 1, (opkg_cmd_fun_t
)opkg_files_cmd
},
92 {"search", 1, (opkg_cmd_fun_t
)opkg_search_cmd
},
93 {"download", 1, (opkg_cmd_fun_t
)opkg_download_cmd
},
94 {"compare_versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
95 {"compare-versions", 1, (opkg_cmd_fun_t
)opkg_compare_versions_cmd
},
96 {"print-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
97 {"print_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
98 {"print-installation-architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
99 {"print_installation_architecture", 0, (opkg_cmd_fun_t
)opkg_print_architecture_cmd
},
100 {"depends", 1, (opkg_cmd_fun_t
)opkg_depends_cmd
},
101 {"whatdepends", 1, (opkg_cmd_fun_t
)opkg_whatdepends_cmd
},
102 {"whatdependsrec", 1, (opkg_cmd_fun_t
)opkg_whatdepends_recursively_cmd
},
103 {"whatrecommends", 1, (opkg_cmd_fun_t
)opkg_whatrecommends_cmd
},
104 {"whatsuggests", 1, (opkg_cmd_fun_t
)opkg_whatsuggests_cmd
},
105 {"whatprovides", 1, (opkg_cmd_fun_t
)opkg_whatprovides_cmd
},
106 {"whatreplaces", 1, (opkg_cmd_fun_t
)opkg_whatreplaces_cmd
},
107 {"whatconflicts", 1, (opkg_cmd_fun_t
)opkg_whatconflicts_cmd
},
110 int opkg_state_changed
;
111 static void write_status_files_if_changed(opkg_conf_t
*conf
)
113 if (opkg_state_changed
&& !conf
->noaction
) {
114 opkg_message(conf
, OPKG_INFO
,
115 " writing status file\n");
116 opkg_conf_write_status_files(conf
);
117 pkg_write_changed_filelists(conf
);
119 opkg_message(conf
, OPKG_DEBUG
, "Nothing to be done\n");
124 static int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
126 opkg_cmd_t
*opkg_cmd_find(const char *name
)
131 for (i
=0; i
< num_cmds
; i
++) {
133 if (strcmp(name
, cmd
->name
) == 0) {
141 int opkg_cmd_exec(opkg_cmd_t
*cmd
, opkg_conf_t
*conf
, int argc
, const char **argv
, void *userdata
)
144 p_userdata
= userdata
;
147 result
= (cmd
->fun
)(conf
, argc
, argv
);
149 if ( result
!= 0 && !error_list
) {
150 opkg_message(conf
, OPKG_NOTICE
, "An error ocurred, return value: %d.\n", result
);
154 reverse_error_list(&error_list
);
156 opkg_message(conf
, OPKG_NOTICE
, "Collected errors:\n");
157 /* Here we print the errors collected and free the list */
158 while (error_list
!= NULL
) {
159 opkg_message(conf
, OPKG_NOTICE
, " * %s", error_list
->errmsg
);
160 error_list
= error_list
->next
;
163 free_error_list(&error_list
);
171 static int opkg_update_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
177 pkg_src_list_elt_t
*iter
;
181 sprintf_alloc(&lists_dir
, "%s", conf
->restrict_to_default_dest
? conf
->default_dest
->lists_dir
: conf
->lists_dir
);
183 if (! file_is_dir(lists_dir
)) {
184 if (file_exists(lists_dir
)) {
185 opkg_message(conf
, OPKG_ERROR
,
186 "%s: ERROR: %s exists, but is not a directory\n",
187 __FUNCTION__
, lists_dir
);
191 err
= file_mkdir_hier(lists_dir
, 0755);
193 opkg_message(conf
, OPKG_ERROR
,
194 "%s: ERROR: failed to make directory %s: %s\n",
195 __FUNCTION__
, lists_dir
, strerror(errno
));
204 tmp
= strdup ("/tmp/opkg.XXXXXX");
206 if (mkdtemp (tmp
) == NULL
) {
212 for (iter
= conf
->pkg_src_list
.head
; iter
; iter
= iter
->next
) {
213 char *url
, *list_file_name
;
217 if (src
->extra_data
) /* debian style? */
218 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
219 src
->gzip
? "Packages.gz" : "Packages");
221 sprintf_alloc(&url
, "%s/%s", src
->value
, src
->gzip
? "Packages.gz" : "Packages");
223 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
228 sprintf_alloc (&tmp_file_name
, "%s/%s.gz", tmp
, src
->name
);
229 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
231 opkg_message (conf
, OPKG_NOTICE
, "Inflating %s\n", url
);
232 in
= fopen (tmp_file_name
, "r");
233 out
= fopen (list_file_name
, "w");
242 unlink (tmp_file_name
);
245 err
= opkg_download(conf
, url
, list_file_name
, NULL
, NULL
);
249 opkg_message(conf
, OPKG_NOTICE
,
250 "Updated list of available packages in %s\n",
256 /* download detached signitures to verify the package lists */
257 /* get the url for the sig file */
258 if (src
->extra_data
) /* debian style? */
259 sprintf_alloc(&url
, "%s/%s/%s", src
->value
, src
->extra_data
,
262 sprintf_alloc(&url
, "%s/%s", src
->value
, "Packages.sig");
264 /* create temporary file for it */
267 sprintf_alloc (&tmp_file_name
, "%s/%s", tmp
, "Packages.sig");
269 err
= opkg_download(conf
, url
, tmp_file_name
, NULL
, NULL
);
272 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
275 err
= opkg_verify_file (conf
, list_file_name
, tmp_file_name
);
277 opkg_message (conf
, OPKG_NOTICE
, "Signature check passed\n");
279 opkg_message (conf
, OPKG_NOTICE
, "Signature check failed\n");
281 unlink (tmp_file_name
);
282 free (tmp_file_name
);
285 opkg_message (conf
, OPKG_NOTICE
, "Signiture check for %s skipped "
286 "because GPG support was not enabled in this build\n", src
->name
);
288 free(list_file_name
);
298 /* scan the args passed and cache the local filenames of the packages */
299 int opkg_multiple_files_scan(opkg_conf_t
*conf
, int argc
, char **argv
)
305 * First scan through package names/urls
306 * For any urls, download the packages and install in database.
307 * For any files, install package info in database.
309 for (i
= 0; i
< argc
; i
++) {
310 char *filename
= argv
[i
];
311 //char *tmp = basename (tmp);
312 //int tmplen = strlen (tmp);
314 //if (strcmp (tmp + (tmplen - strlen (OPKG_PKG_EXTENSION)), OPKG_PKG_EXTENSION) != 0)
316 //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0)
319 opkg_message(conf
, OPKG_DEBUG2
, "Debug mfs: %s \n",filename
);
321 err
= opkg_prepare_url_for_install(conf
, filename
, &argv
[i
]);
328 struct opkg_intercept
334 typedef struct opkg_intercept
*opkg_intercept_t
;
336 opkg_intercept_t
opkg_prep_intercepts(opkg_conf_t
*conf
)
338 opkg_intercept_t ctx
;
342 ctx
= malloc (sizeof (*ctx
));
343 ctx
->oldpath
= strdup (getenv ("PATH"));
345 sprintf_alloc (&newpath
, "%s/opkg/intercept:%s", DATADIR
, ctx
->oldpath
);
346 setenv ("PATH", newpath
, 1);
351 sprintf_alloc (&ctx
->statedir
, "/tmp/opkg-intercept-%d-%d", getpid (), gen
);
352 if (mkdir (ctx
->statedir
, 0770) < 0) {
353 if (errno
== EEXIST
) {
354 free (ctx
->statedir
);
358 perror (ctx
->statedir
);
361 setenv ("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
365 int opkg_finalize_intercepts(opkg_intercept_t ctx
)
371 setenv ("PATH", ctx
->oldpath
, 1);
374 dir
= opendir (ctx
->statedir
);
377 while (de
= readdir (dir
), de
!= NULL
) {
380 if (de
->d_name
[0] == '.')
383 sprintf_alloc (&path
, "%s/%s", ctx
->statedir
, de
->d_name
);
384 if (access (path
, X_OK
) == 0) {
393 perror (ctx
->statedir
);
395 sprintf_alloc (&cmd
, "rm -rf %s", ctx
->statedir
);
399 free (ctx
->statedir
);
405 /* For package pkg do the following: If it is already visited, return. If not,
406 add it in visited list and recurse to its deps. Finally, add it to ordered
408 pkg_vec all contains all available packages in repos.
409 pkg_vec visited contains packages already visited by this function, and is
410 used to end recursion and avoid an infinite loop on graph cycles.
411 pkg_vec ordered will finally contain the ordered set of packages.
413 int opkg_recurse_pkgs_in_order(opkg_conf_t
*conf
, pkg_t
*pkg
, pkg_vec_t
*all
,
414 pkg_vec_t
*visited
, pkg_vec_t
*ordered
)
419 compound_depend_t
* compound_depend
;
420 depend_t
** possible_satisfiers
;
421 abstract_pkg_t
*abpkg
;
422 abstract_pkg_t
**dependents
;
424 /* If it's just an available package, that is, not installed and not even
426 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
427 would do here. However, if there is an intermediate node (pkg) that is
428 configured and installed between two unpacked packages, the latter
429 won't be properly reordered, unless all installed/unpacked pkgs are
431 if (pkg
->state_status
== SS_NOT_INSTALLED
)
434 /* If the package has already been visited (by this function), skip it */
435 for(j
= 0; j
< visited
->len
; j
++)
436 if ( ! strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
437 opkg_message(conf
, OPKG_INFO
,
438 " pkg: %s already visited\n", pkg
->name
);
442 pkg_vec_insert(visited
, pkg
);
444 count
= pkg
->pre_depends_count
+ pkg
->depends_count
+ \
445 pkg
->recommends_count
+ pkg
->suggests_count
;
447 opkg_message(conf
, OPKG_INFO
,
448 " pkg: %s\n", pkg
->name
);
450 /* Iterate over all the dependencies of pkg. For each one, find a package
451 that is either installed or unpacked and satisfies this dependency.
452 (there should only be one such package per dependency installed or
453 unpacked). Then recurse to the dependency package */
454 for (j
=0; j
< count
; j
++) {
455 compound_depend
= &pkg
->depends
[j
];
456 possible_satisfiers
= compound_depend
->possibilities
;
457 for (k
=0; k
< compound_depend
->possibility_count
; k
++) {
458 abpkg
= possible_satisfiers
[k
]->pkg
;
459 dependents
= abpkg
->provided_by
->pkgs
;
461 if (dependents
!= NULL
)
462 while (dependents
[l
] != NULL
&& l
< abpkg
->provided_by
->len
) {
463 opkg_message(conf
, OPKG_INFO
,
464 " Descending on pkg: %s\n",
465 dependents
[l
]->name
);
467 /* find whether dependent l is installed or unpacked,
468 * and then find which package in the list satisfies it */
469 for(m
= 0; m
< all
->len
; m
++) {
471 if ( dep
->state_status
!= SS_NOT_INSTALLED
)
472 if ( ! strcmp(dep
->name
, dependents
[l
]->name
)) {
473 opkg_recurse_pkgs_in_order(conf
, dep
, all
,
475 /* Stop the outer loop */
476 l
= abpkg
->provided_by
->len
;
477 /* break from the inner loop */
486 /* When all recursions from this node down, are over, and all
487 dependencies have been added in proper order in the ordered array, add
488 also the package pkg to ordered array */
489 pkg_vec_insert(ordered
, pkg
);
495 int opkg_configure_packages(opkg_conf_t
*conf
, char *pkg_name
)
497 pkg_vec_t
*all
, *ordered
, *visited
;
503 opkg_message(conf
, OPKG_INFO
,
504 "Configuring unpacked packages\n");
507 all
= pkg_vec_alloc();
509 pkg_hash_fetch_available(&conf
->pkg_hash
, all
);
511 /* Reorder pkgs in order to be configured according to the Depends: tag
513 opkg_message(conf
, OPKG_INFO
,
514 "Reordering packages before configuring them...\n");
515 ordered
= pkg_vec_alloc();
516 visited
= pkg_vec_alloc();
517 for(i
= 0; i
< all
->len
; i
++) {
519 opkg_recurse_pkgs_in_order(conf
, pkg
, all
, visited
, ordered
);
523 ic
= opkg_prep_intercepts (conf
);
525 for(i
= 0; i
< all
->len
; i
++) {
528 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
531 if (pkg
->state_status
== SS_UNPACKED
) {
532 opkg_message(conf
, OPKG_NOTICE
,
533 "Configuring %s\n", pkg
->name
);
535 r
= opkg_configure(conf
, pkg
);
537 pkg
->state_status
= SS_INSTALLED
;
538 pkg
->parent
->state_status
= SS_INSTALLED
;
539 pkg
->state_flag
&= ~SF_PREFER
;
547 r
= opkg_finalize_intercepts (ic
);
552 pkg_vec_free(ordered
);
553 pkg_vec_free(visited
);
558 static opkg_conf_t
*global_conf
;
560 static void sigint_handler(int sig
)
562 signal(sig
, SIG_DFL
);
563 opkg_message(NULL
, OPKG_NOTICE
,
564 "opkg: interrupted. writing out status database\n");
565 write_status_files_if_changed(global_conf
);
569 static int opkg_install_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
576 signal(SIGINT
, sigint_handler
);
579 * Now scan through package names and install
581 for (i
=0; i
< argc
; i
++) {
584 opkg_message(conf
, OPKG_DEBUG2
, "Debug install_cmd: %s \n",arg
);
585 err
= opkg_prepare_url_for_install(conf
, arg
, &argv
[i
]);
586 if (err
!= EINVAL
&& err
!= 0)
589 pkg_info_preinstall_check(conf
);
591 for (i
=0; i
< argc
; i
++) {
593 err
= opkg_install_by_name(conf
, arg
);
594 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
595 opkg_message(conf
, OPKG_ERROR
,
596 "Cannot find package %s.\n",
601 /* recheck to verify that all dependences are satisfied */
602 if (0) opkg_satisfy_all_dependences(conf
);
604 opkg_configure_packages(conf
, NULL
);
606 write_status_files_if_changed(conf
);
611 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
618 signal(SIGINT
, sigint_handler
);
621 for (i
=0; i
< argc
; i
++) {
624 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
625 if (err
!= EINVAL
&& err
!= 0)
628 pkg_info_preinstall_check(conf
);
630 for (i
=0; i
< argc
; i
++) {
632 if (conf
->restrict_to_default_dest
) {
633 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
637 opkg_message(conf
, OPKG_NOTICE
,
638 "Package %s not installed in %s\n",
639 argv
[i
], conf
->default_dest
->name
);
643 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
647 opkg_upgrade_pkg(conf
, pkg
);
649 opkg_install_by_name(conf
, arg
);
653 pkg_vec_t
*installed
= pkg_vec_alloc();
655 pkg_info_preinstall_check(conf
);
657 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
658 for (i
= 0; i
< installed
->len
; i
++) {
659 pkg
= installed
->pkgs
[i
];
660 opkg_upgrade_pkg(conf
, pkg
);
662 pkg_vec_free(installed
);
665 /* recheck to verify that all dependences are satisfied */
666 if (0) opkg_satisfy_all_dependences(conf
);
668 opkg_configure_packages(conf
, NULL
);
670 write_status_files_if_changed(conf
);
675 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
681 pkg_info_preinstall_check(conf
);
682 for (i
= 0; i
< argc
; i
++) {
685 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
, &err
);
687 opkg_message(conf
, OPKG_ERROR
,
688 "Cannot find package %s.\n"
689 "Check the spelling or perhaps run 'opkg update'\n",
694 err
= opkg_download_pkg(conf
, pkg
, ".");
697 opkg_message(conf
, OPKG_ERROR
,
698 "Failed to download %s\n", pkg
->name
);
700 opkg_message(conf
, OPKG_NOTICE
,
701 "Downloaded %s as %s\n",
702 pkg
->name
, pkg
->local_filename
);
710 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
713 pkg_vec_t
*available
;
715 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
717 char *pkg_name
= NULL
;
723 available
= pkg_vec_alloc();
724 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
725 for (i
=0; i
< available
->len
; i
++) {
726 pkg
= available
->pkgs
[i
];
727 /* if we have package name or pattern and pkg does not match, then skip it */
728 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
730 if (pkg
->description
) {
731 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
733 desc_short
[0] = '\0';
735 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
736 newline
= strchr(desc_short
, '\n');
741 version_str
= pkg_version_str_alloc(pkg
);
742 opkg_cb_list(pkg
->name
,desc_short
,
749 pkg_vec_free(available
);
755 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
758 pkg_vec_t
*available
;
760 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
762 char *pkg_name
= NULL
;
768 available
= pkg_vec_alloc();
769 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
770 for (i
=0; i
< available
->len
; i
++) {
771 pkg
= available
->pkgs
[i
];
772 /* if we have package name or pattern and pkg does not match, then skip it */
773 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
775 if (pkg
->description
) {
776 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
778 desc_short
[0] = '\0';
780 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
781 newline
= strchr(desc_short
, '\n');
786 version_str
= pkg_version_str_alloc(pkg
);
787 opkg_cb_list(pkg
->name
,desc_short
,
798 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
801 pkg_vec_t
*available
;
803 char *pkg_name
= NULL
;
804 char **pkg_fields
= NULL
;
806 char *buff
; // = (char *)malloc(1);
812 pkg_fields
= &argv
[1];
816 available
= pkg_vec_alloc();
818 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
820 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
821 for (i
=0; i
< available
->len
; i
++) {
822 pkg
= available
->pkgs
[i
];
823 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
827 buff
= pkg_formatted_info(pkg
);
829 if (opkg_cb_status
) opkg_cb_status(pkg
->name
,
834 We should not forget that actually the pointer is allocated.
835 We need to free it :) ( Thanks florian for seeing the error )
839 if (conf
->verbosity
> 1) {
840 conffile_list_elt_t
*iter
;
841 for (iter
= pkg
->conffiles
.head
; iter
; iter
= iter
->next
) {
842 conffile_t
*cf
= iter
->data
;
843 int modified
= conffile_has_been_modified(conf
, cf
);
844 opkg_message(conf
, OPKG_NOTICE
, "conffile=%s md5sum=%s modified=%d\n",
845 cf
->name
, cf
->value
, modified
);
849 pkg_vec_free(available
);
854 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
856 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
859 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
861 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
864 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
869 char *pkg_name
= NULL
;
873 err
= opkg_configure_packages (conf
, pkg_name
);
876 err
= opkg_configure_packages (conf
, NULL
);
879 write_status_files_if_changed(conf
);
884 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
890 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
891 err
= glob(globpattern
, 0, NULL
, &globbuf
);
897 opkg_message(conf
, OPKG_NOTICE
,
898 "The following packages in %s will now be installed.\n",
900 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
901 opkg_message(conf
, OPKG_NOTICE
,
902 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
904 opkg_message(conf
, OPKG_NOTICE
, "\n");
905 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
906 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
908 err
= unlink(globbuf
.gl_pathv
[i
]);
910 opkg_message(conf
, OPKG_ERROR
,
911 "%s: ERROR: failed to unlink %s: %s\n",
912 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
922 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
926 pkg_t
*pkg_to_remove
;
927 pkg_vec_t
*available
;
928 char *pkg_name
= NULL
;
930 signal(SIGINT
, sigint_handler
);
932 // ENH: Add the "no pkg removed" just in case.
936 available
= pkg_vec_alloc();
937 pkg_info_preinstall_check(conf
);
939 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
940 for (i
=0; i
< argc
; i
++) {
941 pkg_name
= malloc(strlen(argv
[i
])+2);
942 strcpy(pkg_name
,argv
[i
]);
943 for (a
=0; a
< available
->len
; a
++) {
944 pkg
= available
->pkgs
[a
];
945 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
948 if (conf
->restrict_to_default_dest
) {
949 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
953 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
957 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
960 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
961 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
964 opkg_remove_pkg(conf
, pkg_to_remove
,0);
969 pkg_vec_free(available
);
971 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
973 int flagged_pkg_count
= 0;
976 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
978 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
979 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
980 if (pkg
->state_flag
& SF_USER
) {
983 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
984 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
987 if (!flagged_pkg_count
) {
988 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
989 "so refusing to uninstall unflagged non-leaf packages\n");
993 /* find packages not flagged SF_USER (i.e., installed to
994 * satisfy a dependence) and not having any dependents, and
998 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
999 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
1000 if (!(pkg
->state_flag
& SF_USER
)
1001 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
1003 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
1004 opkg_remove_pkg(conf
, pkg
,0);
1009 pkg_vec_free(installed_pkgs
);
1013 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
1015 write_status_files_if_changed(conf
);
1019 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1025 signal(SIGINT
, sigint_handler
);
1027 pkg_info_preinstall_check(conf
);
1029 for (i
=0; i
< argc
; i
++) {
1030 if (conf
->restrict_to_default_dest
) {
1031 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1033 conf
->default_dest
);
1035 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1039 opkg_message(conf
, OPKG_ERROR
,
1040 "Package %s is not installed.\n", argv
[i
]);
1043 opkg_purge_pkg(conf
, pkg
);
1046 write_status_files_if_changed(conf
);
1050 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1054 const char *flags
= argv
[0];
1057 signal(SIGINT
, sigint_handler
);
1059 for (i
=1; i
< argc
; i
++) {
1060 if (conf
->restrict_to_default_dest
) {
1061 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1063 conf
->default_dest
);
1065 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1069 opkg_message(conf
, OPKG_ERROR
,
1070 "Package %s is not installed.\n", argv
[i
]);
1073 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1074 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1075 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1077 /* pb_ asked this feature 03292004 */
1078 /* Actually I will use only this two, but this is an open for various status */
1079 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1080 pkg
->state_status
= pkg_state_status_from_str(flags
);
1082 opkg_state_changed
++;
1083 opkg_message(conf
, OPKG_NOTICE
,
1084 "Setting flags for package %s to %s\n",
1088 write_status_files_if_changed(conf
);
1092 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1095 str_list_t
*installed_files
;
1096 str_list_elt_t
*iter
;
1098 size_t buff_len
= 8192;
1102 buff
= (char *)malloc(buff_len
);
1103 if ( buff
== NULL
) {
1104 fprintf( stderr
,"%s: Unable to allocate memory \n",__FUNCTION__
);
1112 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1115 opkg_message(conf
, OPKG_ERROR
,
1116 "Package %s not installed.\n", argv
[0]);
1120 installed_files
= pkg_get_installed_files(pkg
);
1121 pkg_version
= pkg_version_str_alloc(pkg
);
1125 used_len
= snprintf(buff
, buff_len
, "Package %s (%s) is installed on %s and has the following files:\n",
1126 pkg
->name
, pkg_version
, pkg
->dest
->name
) + 1;
1127 if (used_len
> buff_len
) {
1129 buff
= realloc (buff
, buff_len
);
1132 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1133 used_len
+= strlen (iter
->data
) + 1;
1134 while (buff_len
<= used_len
) {
1136 buff
= realloc (buff
, buff_len
);
1138 strncat(buff
, iter
->data
, buff_len
);
1139 strncat(buff
, "\n", buff_len
);
1141 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1143 pkg_version_str_alloc(pkg
),
1150 pkg_free_installed_files(pkg
);
1155 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1159 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1160 const char *rel_str
= "depends on";
1163 pkg_info_preinstall_check(conf
);
1165 if (conf
->query_all
)
1166 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1168 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1169 for (i
= 0; i
< argc
; i
++) {
1170 const char *target
= argv
[i
];
1173 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1175 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1176 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1177 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1179 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1180 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1181 target
, pkg
->architecture
, rel_str
);
1182 for (k
= 0; k
< count
; k
++) {
1183 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1185 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1186 depend_t
*possibility
= cdepend
->possibilities
[l
];
1187 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1188 if (conf
->verbosity
> 0) {
1189 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1190 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
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
);
1205 opkg_message(conf
, OPKG_ERROR
, "\n");
1211 pkg_vec_free(available_pkgs
);
1216 enum what_field_type
{
1225 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1229 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1230 const char *rel_str
= NULL
;
1234 switch (what_field_type
) {
1235 case WHATDEPENDS
: rel_str
= "depends on"; break;
1236 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1237 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1238 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1239 case WHATPROVIDES
: rel_str
= "provides"; break;
1240 case WHATREPLACES
: rel_str
= "replaces"; break;
1243 if (conf
->query_all
)
1244 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1246 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1248 /* mark the root set */
1249 pkg_vec_clear_marks(available_pkgs
);
1250 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1251 for (i
= 0; i
< argc
; i
++) {
1252 const char *dependee_pattern
= argv
[i
];
1253 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1255 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1256 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1257 if (pkg
->state_flag
& SF_MARKED
) {
1258 /* mark the parent (abstract) package */
1259 pkg_mark_provides(pkg
);
1260 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1264 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1269 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1270 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1272 int count
= ((what_field_type
== WHATCONFLICTS
)
1273 ? pkg
->conflicts_count
1274 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1275 /* skip this package if it is already marked */
1276 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1279 for (k
= 0; k
< count
; k
++) {
1280 compound_depend_t
*cdepend
=
1281 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1283 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1284 depend_t
*possibility
= cdepend
->possibilities
[l
];
1285 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1286 /* mark the depending package so we won't visit it again */
1287 pkg
->state_flag
|= SF_MARKED
;
1288 pkg_mark_provides(pkg
);
1291 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1292 if (conf
->verbosity
> 0) {
1293 char *ver
= pkg_version_str_alloc(pkg
);
1294 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1295 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1296 if (possibility
->version
) {
1297 char *typestr
= NULL
;
1298 switch (possibility
->constraint
) {
1299 case NONE
: typestr
= "none"; break;
1300 case EARLIER
: typestr
= "<"; break;
1301 case EARLIER_EQUAL
: typestr
= "<="; break;
1302 case EQUAL
: typestr
= "="; break;
1303 case LATER_EQUAL
: typestr
= ">="; break;
1304 case LATER
: typestr
= ">"; break;
1306 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1309 if (!pkg_dependence_satisfiable(conf
, possibility
))
1310 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1312 opkg_message(conf
, OPKG_NOTICE
, "\n");
1320 } while (changed
&& recursive
);
1321 pkg_vec_free(available_pkgs
);
1327 int pkg_mark_provides(pkg_t
*pkg
)
1329 int provides_count
= pkg
->provides_count
;
1330 abstract_pkg_t
**provides
= pkg
->provides
;
1332 pkg
->parent
->state_flag
|= SF_MARKED
;
1333 for (i
= 0; i
< provides_count
; i
++) {
1334 provides
[i
]->state_flag
|= SF_MARKED
;
1339 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1341 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1343 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1345 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1348 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1350 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1353 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1355 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1358 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1360 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1363 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1367 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1368 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1371 pkg_info_preinstall_check(conf
);
1373 if (conf
->query_all
)
1374 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1376 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1377 for (i
= 0; i
< argc
; i
++) {
1378 const char *target
= argv
[i
];
1381 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1383 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1384 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1386 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1387 for (k
= 0; k
< count
; k
++) {
1388 abstract_pkg_t
*apkg
=
1389 ((what_field_type
== WHATPROVIDES
)
1391 : pkg
->replaces
[k
]);
1392 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1393 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1394 if (strcmp(target
, apkg
->name
) != 0)
1395 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1396 opkg_message(conf
, OPKG_ERROR
, "\n");
1401 pkg_vec_free(available_pkgs
);
1406 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1408 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1411 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1413 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1416 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1420 pkg_vec_t
*installed
;
1422 str_list_t
*installed_files
;
1423 str_list_elt_t
*iter
;
1424 char *installed_file
;
1430 installed
= pkg_vec_alloc();
1431 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1433 for (i
=0; i
< installed
->len
; i
++) {
1434 pkg
= installed
->pkgs
[i
];
1436 installed_files
= pkg_get_installed_files(pkg
);
1438 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1439 installed_file
= iter
->data
;
1440 if (fnmatch(argv
[0], installed_file
, 0)==0) {
1441 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1443 pkg_version_str_alloc(pkg
),
1444 pkg
->state_status
, p_userdata
);
1448 pkg_free_installed_files(pkg
);
1451 /* XXX: CLEANUP: It's not obvious from the name of
1452 pkg_hash_fetch_all_installed that we need to call
1453 pkg_vec_free to avoid a memory leak. */
1454 pkg_vec_free(installed
);
1459 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1462 /* this is a bit gross */
1464 parseVersion(&p1
, argv
[0]);
1465 parseVersion(&p2
, argv
[2]);
1466 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1468 opkg_message(conf
, OPKG_ERROR
,
1469 "opkg compare_versions <v1> <op> <v2>\n"
1470 "<op> is one of <= >= << >> =\n");
1475 #ifndef HOST_CPU_STR
1476 #define HOST_CPU_STR__(X) #X
1477 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1478 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1481 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1483 nv_pair_list_elt_t
*l
;
1485 l
= conf
->arch_list
.head
;
1487 nv_pair_t
*nv
= l
->data
;
1488 printf("arch %s %s\n", nv
->name
, nv
->value
);