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_NOTICE
, "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
);
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 if (conf
->multiple_providers
)
594 err
= opkg_install_multi_by_name(conf
, arg
);
596 err
= opkg_install_by_name(conf
, arg
);
598 if (err
== OPKG_PKG_HAS_NO_CANDIDATE
) {
599 opkg_message(conf
, OPKG_ERROR
,
600 "Cannot find package %s.\n"
601 "Check the spelling or perhaps run 'opkg update'\n",
606 /* recheck to verify that all dependences are satisfied */
607 if (0) opkg_satisfy_all_dependences(conf
);
609 opkg_configure_packages(conf
, NULL
);
611 write_status_files_if_changed(conf
);
616 static int opkg_upgrade_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
623 signal(SIGINT
, sigint_handler
);
626 for (i
=0; i
< argc
; i
++) {
629 err
= opkg_prepare_url_for_install(conf
, arg
, &arg
);
630 if (err
!= EINVAL
&& err
!= 0)
633 pkg_info_preinstall_check(conf
);
635 for (i
=0; i
< argc
; i
++) {
637 if (conf
->restrict_to_default_dest
) {
638 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
642 opkg_message(conf
, OPKG_NOTICE
,
643 "Package %s not installed in %s\n",
644 argv
[i
], conf
->default_dest
->name
);
648 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
652 opkg_upgrade_pkg(conf
, pkg
);
654 opkg_install_by_name(conf
, arg
);
658 pkg_vec_t
*installed
= pkg_vec_alloc();
660 pkg_info_preinstall_check(conf
);
662 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
663 for (i
= 0; i
< installed
->len
; i
++) {
664 pkg
= installed
->pkgs
[i
];
665 opkg_upgrade_pkg(conf
, pkg
);
667 pkg_vec_free(installed
);
670 /* recheck to verify that all dependences are satisfied */
671 if (0) opkg_satisfy_all_dependences(conf
);
673 opkg_configure_packages(conf
, NULL
);
675 write_status_files_if_changed(conf
);
680 static int opkg_download_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
686 pkg_info_preinstall_check(conf
);
687 for (i
= 0; i
< argc
; i
++) {
690 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(conf
, arg
);
692 opkg_message(conf
, OPKG_ERROR
,
693 "Cannot find package %s.\n"
694 "Check the spelling or perhaps run 'opkg update'\n",
699 err
= opkg_download_pkg(conf
, pkg
, ".");
702 opkg_message(conf
, OPKG_ERROR
,
703 "Failed to download %s\n", pkg
->name
);
705 opkg_message(conf
, OPKG_NOTICE
,
706 "Downloaded %s as %s\n",
707 pkg
->name
, pkg
->local_filename
);
715 static int opkg_list_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
718 pkg_vec_t
*available
;
720 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
722 char *pkg_name
= NULL
;
728 available
= pkg_vec_alloc();
729 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
730 for (i
=0; i
< available
->len
; i
++) {
731 pkg
= available
->pkgs
[i
];
732 /* if we have package name or pattern and pkg does not match, then skip it */
733 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
735 if (pkg
->description
) {
736 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
738 desc_short
[0] = '\0';
740 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
741 newline
= strchr(desc_short
, '\n');
746 version_str
= pkg_version_str_alloc(pkg
);
747 opkg_cb_list(pkg
->name
,desc_short
,
754 pkg_vec_free(available
);
760 static int opkg_list_installed_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
763 pkg_vec_t
*available
;
765 char desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
];
767 char *pkg_name
= NULL
;
773 available
= pkg_vec_alloc();
774 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
775 for (i
=0; i
< available
->len
; i
++) {
776 pkg
= available
->pkgs
[i
];
777 /* if we have package name or pattern and pkg does not match, then skip it */
778 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0))
780 if (pkg
->description
) {
781 strncpy(desc_short
, pkg
->description
, OPKG_LIST_DESCRIPTION_LENGTH
);
783 desc_short
[0] = '\0';
785 desc_short
[OPKG_LIST_DESCRIPTION_LENGTH
- 1] = '\0';
786 newline
= strchr(desc_short
, '\n');
791 version_str
= pkg_version_str_alloc(pkg
);
792 opkg_cb_list(pkg
->name
,desc_short
,
803 static int opkg_info_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
, int installed_only
)
806 pkg_vec_t
*available
;
808 char *pkg_name
= NULL
;
809 char **pkg_fields
= NULL
;
811 char *buff
; // = (char *)malloc(1);
817 pkg_fields
= &argv
[1];
821 available
= pkg_vec_alloc();
823 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
825 pkg_hash_fetch_available(&conf
->pkg_hash
, available
);
826 for (i
=0; i
< available
->len
; i
++) {
827 pkg
= available
->pkgs
[i
];
828 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
832 buff
= pkg_formatted_info(pkg
);
834 if (opkg_cb_status
) opkg_cb_status(pkg
->name
,
839 We should not forget that actually the pointer is allocated.
840 We need to free it :) ( Thanks florian for seeing the error )
844 if (conf
->verbosity
> 1) {
845 conffile_list_elt_t
*iter
;
846 for (iter
= pkg
->conffiles
.head
; iter
; iter
= iter
->next
) {
847 conffile_t
*cf
= iter
->data
;
848 int modified
= conffile_has_been_modified(conf
, cf
);
849 opkg_message(conf
, OPKG_NOTICE
, "conffile=%s md5sum=%s modified=%d\n",
850 cf
->name
, cf
->value
, modified
);
854 pkg_vec_free(available
);
859 static int opkg_info_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
861 return opkg_info_status_cmd(conf
, argc
, argv
, 0);
864 static int opkg_status_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
866 return opkg_info_status_cmd(conf
, argc
, argv
, 1);
869 static int opkg_configure_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
874 char *pkg_name
= NULL
;
878 err
= opkg_configure_packages (conf
, pkg_name
);
881 err
= opkg_configure_packages (conf
, NULL
);
884 write_status_files_if_changed(conf
);
889 static int opkg_install_pending_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
895 sprintf_alloc(&globpattern
, "%s/*" OPKG_PKG_EXTENSION
, conf
->pending_dir
);
896 err
= glob(globpattern
, 0, NULL
, &globbuf
);
902 opkg_message(conf
, OPKG_NOTICE
,
903 "The following packages in %s will now be installed.\n",
905 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
906 opkg_message(conf
, OPKG_NOTICE
,
907 "%s%s", i
== 0 ? "" : " ", globbuf
.gl_pathv
[i
]);
909 opkg_message(conf
, OPKG_NOTICE
, "\n");
910 for (i
= 0; i
< globbuf
.gl_pathc
; i
++) {
911 err
= opkg_install_from_file(conf
, globbuf
.gl_pathv
[i
]);
913 err
= unlink(globbuf
.gl_pathv
[i
]);
915 opkg_message(conf
, OPKG_ERROR
,
916 "%s: ERROR: failed to unlink %s: %s\n",
917 __FUNCTION__
, globbuf
.gl_pathv
[i
], strerror(err
));
927 static int opkg_remove_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
931 pkg_t
*pkg_to_remove
;
932 pkg_vec_t
*available
;
933 char *pkg_name
= NULL
;
935 signal(SIGINT
, sigint_handler
);
937 // ENH: Add the "no pkg removed" just in case.
941 available
= pkg_vec_alloc();
942 pkg_info_preinstall_check(conf
);
944 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available
);
945 for (i
=0; i
< argc
; i
++) {
946 pkg_name
= malloc(strlen(argv
[i
])+2);
947 strcpy(pkg_name
,argv
[i
]);
948 for (a
=0; a
< available
->len
; a
++) {
949 pkg
= available
->pkgs
[a
];
950 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, 0)) {
953 if (conf
->restrict_to_default_dest
) {
954 pkg_to_remove
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
958 pkg_to_remove
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, pkg
->name
);
962 opkg_message(conf
, OPKG_ERROR
, "Package %s is not installed.\n", pkg
->name
);
965 if (pkg
->state_status
== SS_NOT_INSTALLED
) { // Added the control, so every already removed package could be skipped
966 opkg_message(conf
, OPKG_ERROR
, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg
->name
);
969 opkg_remove_pkg(conf
, pkg_to_remove
,0);
974 pkg_vec_free(available
);
976 pkg_vec_t
*installed_pkgs
= pkg_vec_alloc();
978 int flagged_pkg_count
= 0;
981 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed_pkgs
);
983 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
984 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
985 if (pkg
->state_flag
& SF_USER
) {
988 if (!pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
))
989 opkg_message(conf
, OPKG_NOTICE
, "Non-user leaf package: %s\n", pkg
->name
);
992 if (!flagged_pkg_count
) {
993 opkg_message(conf
, OPKG_NOTICE
, "No packages flagged as installed by user, \n"
994 "so refusing to uninstall unflagged non-leaf packages\n");
998 /* find packages not flagged SF_USER (i.e., installed to
999 * satisfy a dependence) and not having any dependents, and
1003 for (i
= 0; i
< installed_pkgs
->len
; i
++) {
1004 pkg_t
*pkg
= installed_pkgs
->pkgs
[i
];
1005 if (!(pkg
->state_flag
& SF_USER
)
1006 && !pkg_has_installed_dependents(conf
, pkg
->parent
, pkg
, NULL
)) {
1008 opkg_message(conf
, OPKG_NOTICE
, "Removing non-user leaf package %s\n");
1009 opkg_remove_pkg(conf
, pkg
,0);
1014 pkg_vec_free(installed_pkgs
);
1018 opkg_message(conf
, OPKG_NOTICE
, "No packages removed.\n");
1020 write_status_files_if_changed(conf
);
1024 static int opkg_purge_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1030 signal(SIGINT
, sigint_handler
);
1032 pkg_info_preinstall_check(conf
);
1034 for (i
=0; i
< argc
; i
++) {
1035 if (conf
->restrict_to_default_dest
) {
1036 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1038 conf
->default_dest
);
1040 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1044 opkg_message(conf
, OPKG_ERROR
,
1045 "Package %s is not installed.\n", argv
[i
]);
1048 opkg_purge_pkg(conf
, pkg
);
1051 write_status_files_if_changed(conf
);
1055 static int opkg_flag_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1059 const char *flags
= argv
[0];
1062 signal(SIGINT
, sigint_handler
);
1064 for (i
=1; i
< argc
; i
++) {
1065 if (conf
->restrict_to_default_dest
) {
1066 pkg
= pkg_hash_fetch_installed_by_name_dest(&conf
->pkg_hash
,
1068 conf
->default_dest
);
1070 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
, argv
[i
]);
1074 opkg_message(conf
, OPKG_ERROR
,
1075 "Package %s is not installed.\n", argv
[i
]);
1078 if (( strcmp(flags
,"hold")==0)||( strcmp(flags
,"noprune")==0)||
1079 ( strcmp(flags
,"user")==0)||( strcmp(flags
,"ok")==0)) {
1080 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
1082 /* pb_ asked this feature 03292004 */
1083 /* Actually I will use only this two, but this is an open for various status */
1084 if (( strcmp(flags
,"installed")==0)||( strcmp(flags
,"unpacked")==0)){
1085 pkg
->state_status
= pkg_state_status_from_str(flags
);
1087 opkg_state_changed
++;
1088 opkg_message(conf
, OPKG_NOTICE
,
1089 "Setting flags for package %s to %s\n",
1093 write_status_files_if_changed(conf
);
1097 static int opkg_files_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1100 str_list_t
*installed_files
;
1101 str_list_elt_t
*iter
;
1103 size_t buff_len
= 8192;
1107 buff
= (char *)malloc(buff_len
);
1108 if ( buff
== NULL
) {
1109 fprintf( stderr
,"%s: Unable to allocate memory \n",__FUNCTION__
);
1117 pkg
= pkg_hash_fetch_installed_by_name(&conf
->pkg_hash
,
1120 opkg_message(conf
, OPKG_ERROR
,
1121 "Package %s not installed.\n", argv
[0]);
1125 installed_files
= pkg_get_installed_files(pkg
);
1126 pkg_version
= pkg_version_str_alloc(pkg
);
1130 used_len
= snprintf(buff
, buff_len
, "Package %s (%s) is installed on %s and has the following files:\n",
1131 pkg
->name
, pkg_version
, pkg
->dest
->name
) + 1;
1132 if (used_len
> buff_len
) {
1134 buff
= realloc (buff
, buff_len
);
1137 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1138 used_len
+= strlen (iter
->data
) + 1;
1139 while (buff_len
<= used_len
) {
1141 buff
= realloc (buff
, buff_len
);
1143 strncat(buff
, iter
->data
, buff_len
);
1144 strncat(buff
, "\n", buff_len
);
1146 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1148 pkg_version_str_alloc(pkg
),
1155 pkg_free_installed_files(pkg
);
1160 static int opkg_depends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1164 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1165 const char *rel_str
= "depends on";
1168 pkg_info_preinstall_check(conf
);
1170 if (conf
->query_all
)
1171 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1173 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1174 for (i
= 0; i
< argc
; i
++) {
1175 const char *target
= argv
[i
];
1178 opkg_message(conf
, OPKG_ERROR
, "target=%s\n", target
);
1180 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1181 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1182 if (fnmatch(target
, pkg
->name
, 0) == 0) {
1184 int count
= pkg
->depends_count
+ pkg
->pre_depends_count
;
1185 opkg_message(conf
, OPKG_ERROR
, "What %s (arch=%s) %s\n",
1186 target
, pkg
->architecture
, rel_str
);
1187 for (k
= 0; k
< count
; k
++) {
1188 compound_depend_t
*cdepend
= &pkg
->depends
[k
];
1190 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1191 depend_t
*possibility
= cdepend
->possibilities
[l
];
1192 opkg_message(conf
, OPKG_ERROR
, " %s", possibility
->pkg
->name
);
1193 if (conf
->verbosity
> 0) {
1194 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1195 opkg_message(conf
, OPKG_NOTICE
, " %s", possibility
->version
);
1196 if (possibility
->version
) {
1197 char *typestr
= NULL
;
1198 switch (possibility
->constraint
) {
1199 case NONE
: typestr
= "none"; break;
1200 case EARLIER
: typestr
= "<"; break;
1201 case EARLIER_EQUAL
: typestr
= "<="; break;
1202 case EQUAL
: typestr
= "="; break;
1203 case LATER_EQUAL
: typestr
= ">="; break;
1204 case LATER
: typestr
= ">"; break;
1206 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1210 opkg_message(conf
, OPKG_ERROR
, "\n");
1216 pkg_vec_free(available_pkgs
);
1221 enum what_field_type
{
1230 static int opkg_what_depends_conflicts_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int recursive
, int argc
, char **argv
)
1234 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1235 const char *rel_str
= NULL
;
1239 switch (what_field_type
) {
1240 case WHATDEPENDS
: rel_str
= "depends on"; break;
1241 case WHATCONFLICTS
: rel_str
= "conflicts with"; break;
1242 case WHATSUGGESTS
: rel_str
= "suggests"; break;
1243 case WHATRECOMMENDS
: rel_str
= "recommends"; break;
1244 case WHATPROVIDES
: rel_str
= "provides"; break;
1245 case WHATREPLACES
: rel_str
= "replaces"; break;
1248 if (conf
->query_all
)
1249 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1251 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1253 /* mark the root set */
1254 pkg_vec_clear_marks(available_pkgs
);
1255 opkg_message(conf
, OPKG_NOTICE
, "Root set:\n");
1256 for (i
= 0; i
< argc
; i
++) {
1257 const char *dependee_pattern
= argv
[i
];
1258 pkg_vec_mark_if_matches(available_pkgs
, dependee_pattern
);
1260 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1261 pkg_t
*pkg
= available_pkgs
->pkgs
[i
];
1262 if (pkg
->state_flag
& SF_MARKED
) {
1263 /* mark the parent (abstract) package */
1264 pkg_mark_provides(pkg
);
1265 opkg_message(conf
, OPKG_NOTICE
, " %s\n", pkg
->name
);
1269 opkg_message(conf
, OPKG_NOTICE
, "What %s root set\n", rel_str
);
1274 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1275 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1277 int count
= ((what_field_type
== WHATCONFLICTS
)
1278 ? pkg
->conflicts_count
1279 : pkg
->pre_depends_count
+ pkg
->depends_count
+ pkg
->recommends_count
+ pkg
->suggests_count
);
1280 /* skip this package if it is already marked */
1281 if (pkg
->parent
->state_flag
& SF_MARKED
) {
1284 for (k
= 0; k
< count
; k
++) {
1285 compound_depend_t
*cdepend
=
1286 (what_field_type
== WHATCONFLICTS
) ? &pkg
->conflicts
[k
] : &pkg
->depends
[k
];
1288 for (l
= 0; l
< cdepend
->possibility_count
; l
++) {
1289 depend_t
*possibility
= cdepend
->possibilities
[l
];
1290 if (possibility
->pkg
->state_flag
& SF_MARKED
) {
1291 /* mark the depending package so we won't visit it again */
1292 pkg
->state_flag
|= SF_MARKED
;
1293 pkg_mark_provides(pkg
);
1296 opkg_message(conf
, OPKG_NOTICE
, " %s", pkg
->name
);
1297 if (conf
->verbosity
> 0) {
1298 char *ver
= pkg_version_str_alloc(pkg
);
1299 opkg_message(conf
, OPKG_NOTICE
, " %s", ver
);
1300 opkg_message(conf
, OPKG_NOTICE
, "\t%s %s", rel_str
, possibility
->pkg
->name
);
1301 if (possibility
->version
) {
1302 char *typestr
= NULL
;
1303 switch (possibility
->constraint
) {
1304 case NONE
: typestr
= "none"; break;
1305 case EARLIER
: typestr
= "<"; break;
1306 case EARLIER_EQUAL
: typestr
= "<="; break;
1307 case EQUAL
: typestr
= "="; break;
1308 case LATER_EQUAL
: typestr
= ">="; break;
1309 case LATER
: typestr
= ">"; break;
1311 opkg_message(conf
, OPKG_NOTICE
, " (%s %s)", typestr
, possibility
->version
);
1314 if (!pkg_dependence_satisfiable(conf
, possibility
))
1315 opkg_message(conf
, OPKG_NOTICE
, " unsatisfiable");
1317 opkg_message(conf
, OPKG_NOTICE
, "\n");
1325 } while (changed
&& recursive
);
1326 pkg_vec_free(available_pkgs
);
1332 int pkg_mark_provides(pkg_t
*pkg
)
1334 int provides_count
= pkg
->provides_count
;
1335 abstract_pkg_t
**provides
= pkg
->provides
;
1337 pkg
->parent
->state_flag
|= SF_MARKED
;
1338 for (i
= 0; i
< provides_count
; i
++) {
1339 provides
[i
]->state_flag
|= SF_MARKED
;
1344 static int opkg_whatdepends_recursively_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1346 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 1, argc
, argv
);
1348 static int opkg_whatdepends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1350 return opkg_what_depends_conflicts_cmd(conf
, WHATDEPENDS
, 0, argc
, argv
);
1353 static int opkg_whatsuggests_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1355 return opkg_what_depends_conflicts_cmd(conf
, WHATSUGGESTS
, 0, argc
, argv
);
1358 static int opkg_whatrecommends_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1360 return opkg_what_depends_conflicts_cmd(conf
, WHATRECOMMENDS
, 0, argc
, argv
);
1363 static int opkg_whatconflicts_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1365 return opkg_what_depends_conflicts_cmd(conf
, WHATCONFLICTS
, 0, argc
, argv
);
1368 static int opkg_what_provides_replaces_cmd(opkg_conf_t
*conf
, enum what_field_type what_field_type
, int argc
, char **argv
)
1372 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1373 const char *rel_str
= (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1376 pkg_info_preinstall_check(conf
);
1378 if (conf
->query_all
)
1379 pkg_hash_fetch_available(&conf
->pkg_hash
, available_pkgs
);
1381 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, available_pkgs
);
1382 for (i
= 0; i
< argc
; i
++) {
1383 const char *target
= argv
[i
];
1386 opkg_message(conf
, OPKG_ERROR
, "What %s %s\n",
1388 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1389 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1391 int count
= (what_field_type
== WHATPROVIDES
) ? pkg
->provides_count
: pkg
->replaces_count
;
1392 for (k
= 0; k
< count
; k
++) {
1393 abstract_pkg_t
*apkg
=
1394 ((what_field_type
== WHATPROVIDES
)
1396 : pkg
->replaces
[k
]);
1397 if (fnmatch(target
, apkg
->name
, 0) == 0) {
1398 opkg_message(conf
, OPKG_ERROR
, " %s", pkg
->name
);
1399 if (strcmp(target
, apkg
->name
) != 0)
1400 opkg_message(conf
, OPKG_ERROR
, "\t%s %s\n", rel_str
, apkg
->name
);
1401 opkg_message(conf
, OPKG_ERROR
, "\n");
1406 pkg_vec_free(available_pkgs
);
1411 static int opkg_whatprovides_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1413 return opkg_what_provides_replaces_cmd(conf
, WHATPROVIDES
, argc
, argv
);
1416 static int opkg_whatreplaces_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1418 return opkg_what_provides_replaces_cmd(conf
, WHATREPLACES
, argc
, argv
);
1421 static int opkg_search_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1425 pkg_vec_t
*installed
;
1427 str_list_t
*installed_files
;
1428 str_list_elt_t
*iter
;
1429 char *installed_file
;
1435 installed
= pkg_vec_alloc();
1436 pkg_hash_fetch_all_installed(&conf
->pkg_hash
, installed
);
1438 for (i
=0; i
< installed
->len
; i
++) {
1439 pkg
= installed
->pkgs
[i
];
1441 installed_files
= pkg_get_installed_files(pkg
);
1443 for (iter
= installed_files
->head
; iter
; iter
= iter
->next
) {
1444 installed_file
= iter
->data
;
1445 if (fnmatch(argv
[0], installed_file
, 0)==0) {
1446 if (opkg_cb_list
) opkg_cb_list(pkg
->name
,
1448 pkg_version_str_alloc(pkg
),
1449 pkg
->state_status
, p_userdata
);
1453 pkg_free_installed_files(pkg
);
1456 /* XXX: CLEANUP: It's not obvious from the name of
1457 pkg_hash_fetch_all_installed that we need to call
1458 pkg_vec_free to avoid a memory leak. */
1459 pkg_vec_free(installed
);
1464 static int opkg_compare_versions_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1467 /* this is a bit gross */
1469 parseVersion(&p1
, argv
[0]);
1470 parseVersion(&p2
, argv
[2]);
1471 return pkg_version_satisfied(&p1
, &p2
, argv
[1]);
1473 opkg_message(conf
, OPKG_ERROR
,
1474 "opkg compare_versions <v1> <op> <v2>\n"
1475 "<op> is one of <= >= << >> =\n");
1480 #ifndef HOST_CPU_STR
1481 #define HOST_CPU_STR__(X) #X
1482 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1483 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1486 static int opkg_print_architecture_cmd(opkg_conf_t
*conf
, int argc
, char **argv
)
1488 nv_pair_list_elt_t
*l
;
1490 l
= conf
->arch_list
.head
;
1492 nv_pair_t
*nv
= l
->data
;
1493 printf("arch %s %s\n", nv
->name
, nv
->value
);