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.
25 #include "opkg_conf.h"
27 #include "opkg_message.h"
30 #include "pkg_parse.h"
31 #include "sprintf_alloc.h"
33 #include "file_util.h"
34 #include "libbb/libbb.h"
35 #include "opkg_utils.h"
36 #include "opkg_defines.h"
37 #include "opkg_download.h"
38 #include "opkg_install.h"
39 #include "opkg_upgrade.h"
40 #include "opkg_remove.h"
41 #include "opkg_configure.h"
44 static void print_pkg(pkg_t
* pkg
)
46 char *version
= pkg_version_str_alloc(pkg
);
47 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
48 printf("%s - %s", pkg
->name
, version
);
50 printf(" - %lu", (unsigned long) pkg_get_int(pkg
, PKG_SIZE
));
52 printf(" - %s", description
);
57 int opkg_state_changed
;
59 static void write_status_files_if_changed(void)
61 if (opkg_state_changed
&& !conf
->noaction
) {
62 opkg_msg(INFO
, "Writing status file.\n");
63 opkg_conf_write_status_files();
64 pkg_write_changed_filelists();
66 opkg_msg(DEBUG
, "Nothing to be done.\n");
70 static void sigint_handler(int sig
)
73 opkg_msg(NOTICE
, "Interrupted. Writing out status database.\n");
74 write_status_files_if_changed();
78 static int opkg_update_cmd(int argc
, char **argv
)
85 pkg_src_list_elt_t
*iter
;
88 sprintf_alloc(&lists_dir
, "%s",
89 conf
->restrict_to_default_dest
? conf
->default_dest
->
90 lists_dir
: conf
->lists_dir
);
92 if (!file_is_dir(lists_dir
)) {
93 if (file_exists(lists_dir
)) {
94 opkg_msg(ERROR
, "%s exists, but is not a directory.\n",
99 err
= file_mkdir_hier(lists_dir
, 0755);
108 sprintf_alloc(&tmp
, "%s/update-XXXXXX", conf
->tmp_dir
);
109 if (mkdtemp(tmp
) == NULL
) {
110 opkg_perror(ERROR
, "Failed to make temp dir %s", conf
->tmp_dir
);
114 for (iter
= void_list_first(&conf
->pkg_src_list
); iter
;
115 iter
= void_list_next(&conf
->pkg_src_list
, iter
)) {
116 char *url
, *list_file_name
;
118 src
= (pkg_src_t
*) iter
->data
;
120 if (src
->extra_data
&& strcmp(src
->extra_data
, "__dummy__ "))
123 if (src
->extra_data
) /* debian style? */
124 sprintf_alloc(&url
, "%s/%s/%s", src
->value
,
126 src
->gzip
? "Packages.gz" : "Packages");
128 sprintf_alloc(&url
, "%s/%s", src
->value
,
129 src
->gzip
? "Packages.gz" : "Packages");
131 sprintf_alloc(&list_file_name
, "%s/%s", lists_dir
, src
->name
);
132 pkglist_dl_error
= 0;
133 if (opkg_download(url
, list_file_name
, 0)) {
135 pkglist_dl_error
= 1;
137 "*** Failed to download the package list from %s\n\n",
141 "Updated list of available packages in %s\n",
145 #if defined(HAVE_USIGN)
146 if (pkglist_dl_error
== 0 && conf
->check_signature
) {
147 /* download detached signitures to verify the package lists */
148 /* get the url for the sig file */
149 if (src
->extra_data
) /* debian style? */
150 sprintf_alloc(&url
, "%s/%s/%s", src
->value
,
151 src
->extra_data
, "Packages.sig");
153 sprintf_alloc(&url
, "%s/%s", src
->value
,
156 /* create temporary file for it */
159 /* Put the signature in the right place */
160 sprintf_alloc(&tmp_file_name
, "%s/%s.sig", lists_dir
,
163 err
= opkg_download(url
, tmp_file_name
, 0);
167 "Signature file download failed.\n");
170 opkg_verify_file(list_file_name
,
174 "Signature check passed.\n");
177 "Signature check failed.\n");
179 if (err
&& !conf
->force_signature
) {
180 /* The signature was wrong so delete it */
182 "Remove wrong Signature file.\n");
183 unlink(tmp_file_name
);
184 unlink(list_file_name
);
186 /* We shouldn't unlink the signature ! */
187 // unlink (tmp_file_name);
194 free(list_file_name
);
203 struct opkg_intercept
{
208 typedef struct opkg_intercept
*opkg_intercept_t
;
210 static opkg_intercept_t
opkg_prep_intercepts(void)
212 opkg_intercept_t ctx
;
215 ctx
= xcalloc(1, sizeof(*ctx
));
216 ctx
->oldpath
= xstrdup(getenv("PATH"));
218 sprintf_alloc(&newpath
, "%s/opkg/intercept:%s", DATADIR
,
219 ctx
->oldpath
? ctx
->oldpath
: PATH_SPEC
);
221 sprintf_alloc(&ctx
->statedir
, "%s/opkg-intercept-XXXXXX",
224 if (mkdtemp(ctx
->statedir
) == NULL
) {
225 opkg_perror(ERROR
, "Failed to make temp dir %s", ctx
->statedir
);
236 setenv("OPKG_INTERCEPT_DIR", ctx
->statedir
, 1);
237 setenv("PATH", newpath
, 1);
243 static int opkg_finalize_intercepts(opkg_intercept_t ctx
)
249 setenv("PATH", ctx
->oldpath
, 1);
256 dir
= opendir(ctx
->statedir
);
259 while (de
= readdir(dir
), de
!= NULL
) {
262 if (de
->d_name
[0] == '.')
265 sprintf_alloc(&path
, "%s/%s", ctx
->statedir
,
267 if (access(path
, X_OK
) == 0) {
268 const char *argv
[] = { "/bin/sh", "-c", path
, NULL
};
275 opkg_perror(ERROR
, "Failed to open dir %s", ctx
->statedir
);
284 /* For package pkg do the following: If it is already visited, return. If not,
285 add it in visited list and recurse to its deps. Finally, add it to ordered
287 pkg_vec all contains all available packages in repos.
288 pkg_vec visited contains packages already visited by this function, and is
289 used to end recursion and avoid an infinite loop on graph cycles.
290 pkg_vec ordered will finally contain the ordered set of packages.
293 opkg_recurse_pkgs_in_order(pkg_t
* pkg
, pkg_vec_t
* all
,
294 pkg_vec_t
* visited
, pkg_vec_t
* ordered
)
298 compound_depend_t
*compound_depend
;
299 depend_t
**possible_satisfiers
;
300 abstract_pkg_t
*abpkg
;
301 abstract_pkg_t
**dependents
;
303 /* If it's just an available package, that is, not installed and not even
305 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
306 would do here. However, if there is an intermediate node (pkg) that is
307 configured and installed between two unpacked packages, the latter
308 won't be properly reordered, unless all installed/unpacked pkgs are
310 if (pkg
->state_status
== SS_NOT_INSTALLED
)
313 /* If the package has already been visited (by this function), skip it */
314 for (j
= 0; j
< visited
->len
; j
++)
315 if (!strcmp(visited
->pkgs
[j
]->name
, pkg
->name
)) {
316 opkg_msg(DEBUG
, "pkg %s already visited, skipping.\n",
321 pkg_vec_insert(visited
, pkg
);
323 opkg_msg(DEBUG
, "pkg %s.\n", pkg
->name
);
325 /* Iterate over all the dependencies of pkg. For each one, find a package
326 that is either installed or unpacked and satisfies this dependency.
327 (there should only be one such package per dependency installed or
328 unpacked). Then recurse to the dependency package */
329 for (compound_depend
= pkg_get_ptr(pkg
, PKG_DEPENDS
); compound_depend
&& compound_depend
->type
; compound_depend
++) {
330 possible_satisfiers
= compound_depend
->possibilities
;
331 for (k
= 0; k
< compound_depend
->possibility_count
; k
++) {
332 abpkg
= possible_satisfiers
[k
]->pkg
;
333 dependents
= abpkg
->provided_by
->pkgs
;
335 if (dependents
!= NULL
)
336 while (l
< abpkg
->provided_by
->len
337 && dependents
[l
] != NULL
) {
339 "Descending on pkg %s.\n",
340 dependents
[l
]->name
);
342 /* find whether dependent l is installed or unpacked,
343 * and then find which package in the list satisfies it */
344 for (m
= 0; m
< all
->len
; m
++) {
346 if (dep
->state_status
!=
352 opkg_recurse_pkgs_in_order
356 /* Stop the outer loop */
360 /* break from the inner loop */
369 /* When all recursions from this node down, are over, and all
370 dependencies have been added in proper order in the ordered array, add
371 also the package pkg to ordered array */
372 pkg_vec_insert(ordered
, pkg
);
378 static int opkg_configure_packages(char *pkg_name
)
380 pkg_vec_t
*all
, *ordered
, *visited
;
386 opkg_msg(INFO
, "Configuring unpacked packages.\n");
388 all
= pkg_vec_alloc();
390 pkg_hash_fetch_available(all
);
392 /* Reorder pkgs in order to be configured according to the Depends: tag
394 opkg_msg(INFO
, "Reordering packages before configuring them...\n");
395 ordered
= pkg_vec_alloc();
396 visited
= pkg_vec_alloc();
397 for (i
= 0; i
< all
->len
; i
++) {
399 opkg_recurse_pkgs_in_order(pkg
, all
, visited
, ordered
);
402 ic
= opkg_prep_intercepts();
408 for (i
= 0; i
< ordered
->len
; i
++) {
409 pkg
= ordered
->pkgs
[i
];
411 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
414 if (pkg
->state_status
== SS_UNPACKED
) {
415 opkg_msg(NOTICE
, "Configuring %s.\n", pkg
->name
);
416 r
= opkg_configure(pkg
);
418 pkg
->state_status
= SS_INSTALLED
;
419 pkg
->parent
->state_status
= SS_INSTALLED
;
420 pkg
->state_flag
&= ~SF_PREFER
;
421 opkg_state_changed
++;
428 if (opkg_finalize_intercepts(ic
))
433 pkg_vec_free(ordered
);
434 pkg_vec_free(visited
);
439 static int opkg_remove_cmd(int argc
, char **argv
);
441 static int opkg_install_cmd(int argc
, char **argv
)
447 signal(SIGINT
, sigint_handler
);
450 * Now scan through package names and install
452 for (i
= 0; i
< argc
; i
++) {
455 opkg_msg(DEBUG2
, "%s\n", arg
);
456 if (opkg_prepare_url_for_install(arg
, &argv
[i
]))
460 pkg_hash_load_package_details();
461 pkg_hash_load_status_files(NULL
, NULL
);
463 if (conf
->force_reinstall
) {
464 int saved_force_depends
= conf
->force_depends
;
465 conf
->force_depends
= 1;
466 (void)opkg_remove_cmd(argc
, argv
);
467 conf
->force_depends
= saved_force_depends
;
468 conf
->force_reinstall
= 0;
471 pkg_info_preinstall_check();
473 for (i
= 0; i
< argc
; i
++) {
475 if (opkg_install_by_name(arg
)) {
476 opkg_msg(ERROR
, "Cannot install package %s.\n", arg
);
481 if (opkg_configure_packages(NULL
))
484 write_status_files_if_changed();
489 static int opkg_upgrade_cmd(int argc
, char **argv
)
495 signal(SIGINT
, sigint_handler
);
498 for (i
= 0; i
< argc
; i
++) {
501 if (opkg_prepare_url_for_install(arg
, &arg
))
504 pkg_info_preinstall_check();
506 for (i
= 0; i
< argc
; i
++) {
508 if (conf
->restrict_to_default_dest
) {
510 pkg_hash_fetch_installed_by_name_dest(argv
516 "Package %s not installed in %s.\n",
518 conf
->default_dest
->name
);
522 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
525 if (opkg_upgrade_pkg(pkg
))
528 if (opkg_install_by_name(arg
))
534 if (opkg_configure_packages(NULL
))
537 write_status_files_if_changed();
542 static int opkg_download_cmd(int argc
, char **argv
)
548 pkg_info_preinstall_check();
549 for (i
= 0; i
< argc
; i
++) {
552 pkg
= pkg_hash_fetch_best_installation_candidate_by_name(arg
);
554 opkg_msg(ERROR
, "Cannot find package %s.\n", arg
);
558 if (opkg_download_pkg(pkg
, "."))
562 opkg_msg(ERROR
, "Failed to download %s.\n", pkg
->name
);
564 opkg_msg(NOTICE
, "Downloaded %s as %s.\n",
565 pkg
->name
, pkg_get_string(pkg
, PKG_LOCAL_FILENAME
));
572 struct opkg_list_find_cmd_item
{
579 struct opkg_list_find_cmd_args
{
583 struct opkg_list_find_cmd_item
**items
;
587 static void opkg_list_find_cmd_cb(pkg_t
*pkg
, void *priv
)
589 struct opkg_list_find_cmd_args
*args
= priv
;
590 char *description
= pkg_get_string(pkg
, PKG_DESCRIPTION
);
591 char *version
= pkg_version_str_alloc(pkg
);
592 struct opkg_list_find_cmd_item
*item
;
593 char *nameptr
, *versionptr
, *descriptionptr
;
596 /* if we have package name or pattern and pkg does not match, then skip it */
597 if (args
->pkg_name
&& fnmatch(args
->pkg_name
, pkg
->name
, conf
->nocase
) &&
598 (!args
->use_desc
|| !description
599 || fnmatch(args
->pkg_name
, description
, conf
->nocase
)))
602 if (args
->set_status
) {
603 for (i
= 0; i
< args
->n_items
; i
++) {
604 if (!strcmp(args
->items
[i
]->name
, pkg
->name
)) {
612 item
= calloc_a(sizeof(*item
),
613 &nameptr
, strlen(pkg
->name
) + 1,
614 &versionptr
, strlen(version
) + 1,
615 &descriptionptr
, description
? strlen(description
) + 1 : 0);
617 item
->name
= strcpy(nameptr
, pkg
->name
);
618 item
->size
= pkg_get_int(pkg
, PKG_SIZE
);
619 item
->version
= strcpy(versionptr
, version
);
620 item
->description
= description
? strcpy(descriptionptr
, description
) : NULL
;
622 args
->items
= xrealloc(args
->items
, sizeof(item
) * (args
->n_items
+ 1));
623 args
->items
[args
->n_items
++] = item
;
632 static int opkg_list_find_cmd_sort(const void *a
, const void *b
)
634 const struct opkg_list_find_cmd_item
*pkg_a
= *(const struct opkg_list_find_cmd_item
**)a
;
635 const struct opkg_list_find_cmd_item
*pkg_b
= *(const struct opkg_list_find_cmd_item
**)b
;
636 return strcmp(pkg_a
->name
, pkg_b
->name
);
639 static int opkg_list_find_cmd(int argc
, char **argv
, int use_desc
)
642 struct opkg_list_find_cmd_args args
= {
643 .use_desc
= use_desc
,
644 .pkg_name
= (argc
> 0) ? argv
[0] : NULL
648 pkg_hash_load_feeds(SF_NEED_DETAIL
, opkg_list_find_cmd_cb
, &args
);
651 pkg_hash_load_status_files(opkg_list_find_cmd_cb
, &args
);
653 if (args
.n_items
> 1)
654 qsort(args
.items
, args
.n_items
, sizeof(args
.items
[0]),
655 opkg_list_find_cmd_sort
);
657 for (i
= 0; i
< args
.n_items
; i
++) {
660 args
.items
[i
]->version
);
663 printf(" - %lu", (unsigned long) args
.items
[i
]->size
);
665 if (args
.items
[i
]->description
)
666 printf(" - %s", args
.items
[i
]->description
);
678 static int opkg_list_cmd(int argc
, char **argv
)
680 return opkg_list_find_cmd(argc
, argv
, 0);
683 static int opkg_find_cmd(int argc
, char **argv
)
685 return opkg_list_find_cmd(argc
, argv
, 1);
688 static int opkg_list_installed_cmd(int argc
, char **argv
)
691 pkg_vec_t
*available
;
693 char *pkg_name
= NULL
;
698 available
= pkg_vec_alloc();
699 pkg_hash_fetch_all_installed(available
);
700 pkg_vec_sort(available
, pkg_compare_names
);
701 for (i
= 0; i
< available
->len
; i
++) {
702 pkg
= available
->pkgs
[i
];
703 /* if we have package name or pattern and pkg does not match, then skip it */
704 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
709 pkg_vec_free(available
);
714 static int opkg_list_changed_conffiles_cmd(int argc
, char **argv
)
717 pkg_vec_t
*available
;
719 char *pkg_name
= NULL
;
720 conffile_list_elt_t
*iter
;
727 available
= pkg_vec_alloc();
728 pkg_hash_fetch_all_installed(available
);
729 pkg_vec_sort(available
, pkg_compare_names
);
730 for (i
= 0; i
< available
->len
; i
++) {
731 pkg
= available
->pkgs
[i
];
732 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
733 /* if we have package name or pattern and pkg does not match, then skip it */
734 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
))
736 if (!cl
|| nv_pair_list_empty(cl
))
738 for (iter
= nv_pair_list_first(cl
); iter
;
739 iter
= nv_pair_list_next(cl
, iter
)) {
740 cf
= (conffile_t
*) iter
->data
;
741 if (cf
->name
&& cf
->value
742 && conffile_has_been_modified(cf
))
743 printf("%s\n", cf
->name
);
746 pkg_vec_free(available
);
750 static int opkg_list_upgradable_cmd(int argc
, char **argv
)
752 struct active_list
*head
= prepare_upgrade_list();
753 struct active_list
*node
= NULL
;
754 pkg_t
*_old_pkg
, *_new_pkg
;
756 for (node
= active_list_next(head
, head
); node
;
757 node
= active_list_next(head
, node
)) {
758 _old_pkg
= node
->pkg
;
760 pkg_hash_fetch_best_installation_candidate_by_name
762 if (_new_pkg
== NULL
)
764 old_v
= pkg_version_str_alloc(_old_pkg
);
765 new_v
= pkg_version_str_alloc(_new_pkg
);
766 printf("%s - %s - %s\n", _old_pkg
->name
, old_v
, new_v
);
770 active_list_head_delete(head
);
774 static int opkg_info_status_cmd(int argc
, char **argv
, int installed_only
)
777 pkg_vec_t
*available
;
779 char *pkg_name
= NULL
;
786 available
= pkg_vec_alloc();
788 pkg_hash_fetch_all_installed(available
);
790 pkg_hash_fetch_available(available
);
792 for (i
= 0; i
< available
->len
; i
++) {
793 pkg
= available
->pkgs
[i
];
794 if (pkg_name
&& fnmatch(pkg_name
, pkg
->name
, conf
->nocase
)) {
798 pkg_formatted_info(stdout
, pkg
);
800 cl
= pkg_get_ptr(pkg
, PKG_CONFFILES
);
802 if (conf
->verbosity
>= NOTICE
&& cl
) {
803 conffile_list_elt_t
*iter
;
804 for (iter
= nv_pair_list_first(cl
); iter
;
805 iter
= nv_pair_list_next(cl
, iter
)) {
806 conffile_t
*cf
= (conffile_t
*) iter
->data
;
807 int modified
= conffile_has_been_modified(cf
);
810 "conffile=%s md5sum=%s modified=%d.\n",
811 cf
->name
, cf
->value
, modified
);
815 pkg_vec_free(available
);
820 static int opkg_info_cmd(int argc
, char **argv
)
822 return opkg_info_status_cmd(argc
, argv
, 0);
825 static int opkg_status_cmd(int argc
, char **argv
)
827 return opkg_info_status_cmd(argc
, argv
, 1);
830 static int opkg_configure_cmd(int argc
, char **argv
)
833 char *pkg_name
= NULL
;
838 err
= opkg_configure_packages(pkg_name
);
840 write_status_files_if_changed();
845 static int opkg_remove_cmd(int argc
, char **argv
)
847 int i
, a
, done
, err
= 0;
849 pkg_t
*pkg_to_remove
;
850 pkg_vec_t
*available
;
854 signal(SIGINT
, sigint_handler
);
856 pkg_info_preinstall_check();
858 available
= pkg_vec_alloc();
859 pkg_hash_fetch_all_installed(available
);
861 for (i
= 0; i
< argc
; i
++) {
862 for (a
= 0; a
< available
->len
; a
++) {
863 pkg
= available
->pkgs
[a
];
864 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
)) {
867 if (conf
->restrict_to_default_dest
) {
869 pkg_hash_fetch_installed_by_name_dest(pkg
->
875 pkg_hash_fetch_installed_by_name(pkg
->name
);
878 if (pkg_to_remove
== NULL
) {
880 "Package %s is not installed.\n",
884 if (pkg
->state_status
== SS_NOT_INSTALLED
) {
885 opkg_msg(ERROR
, "Package %s not installed.\n",
890 if (opkg_remove_pkg(pkg_to_remove
, 0))
897 pkg_vec_free(available
);
900 opkg_msg(NOTICE
, "No packages removed.\n");
902 write_status_files_if_changed();
906 static int opkg_flag_cmd(int argc
, char **argv
)
910 const char *flags
= argv
[0];
912 signal(SIGINT
, sigint_handler
);
914 for (i
= 1; i
< argc
; i
++) {
915 if (conf
->restrict_to_default_dest
) {
916 pkg
= pkg_hash_fetch_installed_by_name_dest(argv
[i
],
920 pkg
= pkg_hash_fetch_installed_by_name(argv
[i
]);
924 opkg_msg(ERROR
, "Package %s is not installed.\n",
928 if ((strcmp(flags
, "hold") == 0)
929 || (strcmp(flags
, "noprune") == 0)
930 || (strcmp(flags
, "user") == 0)
931 || (strcmp(flags
, "ok") == 0)) {
932 pkg
->state_flag
= pkg_state_flag_from_str(flags
);
936 * Useful if a package is installed in an offline_root, and
937 * should be configured by opkg-cl configure at a later date.
939 if ((strcmp(flags
, "installed") == 0)
940 || (strcmp(flags
, "unpacked") == 0)) {
941 pkg
->state_status
= pkg_state_status_from_str(flags
);
944 opkg_state_changed
++;
945 opkg_msg(NOTICE
, "Setting flags for package %s to %s.\n",
949 write_status_files_if_changed();
953 static int opkg_files_cmd(int argc
, char **argv
)
957 str_list_elt_t
*iter
;
964 pkg
= pkg_hash_fetch_installed_by_name(argv
[0]);
966 opkg_msg(ERROR
, "Package %s not installed.\n", argv
[0]);
970 files
= pkg_get_installed_files(pkg
);
971 pkg_version
= pkg_version_str_alloc(pkg
);
974 ("Package %s (%s) is installed on %s and has the following files:\n",
975 pkg
->name
, pkg_version
, pkg
->dest
->name
);
977 for (iter
= str_list_first(files
); iter
;
978 iter
= str_list_next(files
, iter
))
979 printf("%s\n", (char *)iter
->data
);
982 pkg_free_installed_files(pkg
);
987 static int opkg_depends_cmd(int argc
, char **argv
)
990 pkg_vec_t
*available_pkgs
;
991 compound_depend_t
*cdep
;
995 pkg_info_preinstall_check();
997 available_pkgs
= pkg_vec_alloc();
999 pkg_hash_fetch_available(available_pkgs
);
1001 pkg_hash_fetch_all_installed(available_pkgs
);
1003 for (i
= 0; i
< argc
; i
++) {
1004 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1005 pkg
= available_pkgs
->pkgs
[j
];
1007 if (fnmatch(argv
[i
], pkg
->name
, conf
->nocase
) != 0)
1010 opkg_msg(NOTICE
, "%s depends on:\n", pkg
->name
);
1012 for (k
= 0, cdep
= pkg_get_ptr(pkg
, PKG_DEPENDS
); cdep
&& cdep
->type
; k
++, cdep
++) {
1013 if (cdep
->type
!= DEPEND
)
1016 str
= pkg_depend_str(pkg
, k
);
1017 opkg_msg(NOTICE
, "\t%s\n", str
);
1024 pkg_vec_free(available_pkgs
);
1028 static int pkg_mark_provides(pkg_t
* pkg
)
1030 abstract_pkg_t
**provider
= pkg_get_ptr(pkg
, PKG_PROVIDES
);
1032 pkg
->parent
->state_flag
|= SF_MARKED
;
1034 while (provider
&& *provider
) {
1035 (*provider
)->state_flag
|= SF_MARKED
;
1042 enum what_field_type
{
1052 opkg_what_depends_conflicts_cmd(enum depend_type what_field_type
, int recursive
,
1053 int argc
, char **argv
)
1055 depend_t
*possibility
;
1056 compound_depend_t
*cdep
, *deps
;
1057 pkg_vec_t
*available_pkgs
;
1061 const char *rel_str
= NULL
;
1064 switch (what_field_type
) {
1066 rel_str
= "depends on";
1069 rel_str
= "conflicts with";
1072 rel_str
= "suggests";
1075 rel_str
= "recommends";
1081 available_pkgs
= pkg_vec_alloc();
1083 if (conf
->query_all
)
1084 pkg_hash_fetch_available(available_pkgs
);
1086 pkg_hash_fetch_all_installed(available_pkgs
);
1088 /* mark the root set */
1089 pkg_vec_clear_marks(available_pkgs
);
1090 opkg_msg(NOTICE
, "Root set:\n");
1091 for (i
= 0; i
< argc
; i
++)
1092 pkg_vec_mark_if_matches(available_pkgs
, argv
[i
]);
1094 for (i
= 0; i
< available_pkgs
->len
; i
++) {
1095 pkg
= available_pkgs
->pkgs
[i
];
1096 if (pkg
->state_flag
& SF_MARKED
) {
1097 /* mark the parent (abstract) package */
1098 pkg_mark_provides(pkg
);
1099 opkg_msg(NOTICE
, " %s\n", pkg
->name
);
1103 opkg_msg(NOTICE
, "What %s root set\n", rel_str
);
1107 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1109 pkg
= available_pkgs
->pkgs
[j
];
1111 count = ((what_field_type == CONFLICTS)
1112 ? pkg->conflicts_count
1113 : pkg->pre_depends_count +
1114 pkg->depends_count +
1115 pkg->recommends_count + pkg->suggests_count);
1118 /* skip this package if it is already marked */
1119 if (pkg
->parent
->state_flag
& SF_MARKED
)
1122 deps
= pkg_get_ptr(pkg
, (what_field_type
== CONFLICTS
) ? PKG_CONFLICTS
: PKG_DEPENDS
);
1124 for (cdep
= deps
; cdep
&& cdep
->type
; cdep
++) {
1125 if (what_field_type
!= cdep
->type
)
1128 for (l
= 0; l
< cdep
->possibility_count
; l
++) {
1129 possibility
= cdep
->possibilities
[l
];
1131 if ((possibility
->pkg
->state_flag
1136 /* mark the depending package so we
1137 * won't visit it again */
1138 pkg
->state_flag
|= SF_MARKED
;
1139 pkg_mark_provides(pkg
);
1142 ver
= pkg_version_str_alloc(pkg
);
1143 opkg_msg(NOTICE
, "\t%s %s\t%s %s",
1147 possibility
->pkg
->name
);
1149 if (possibility
->version
) {
1150 opkg_msg(NOTICE
, " (%s%s)",
1154 possibility
->version
);
1156 if (!pkg_dependence_satisfiable
1160 opkg_message(NOTICE
, "\n");
1167 } while (changed
&& recursive
);
1169 pkg_vec_free(available_pkgs
);
1174 static int opkg_whatdepends_recursively_cmd(int argc
, char **argv
)
1176 return opkg_what_depends_conflicts_cmd(DEPEND
, 1, argc
, argv
);
1179 static int opkg_whatdepends_cmd(int argc
, char **argv
)
1181 return opkg_what_depends_conflicts_cmd(DEPEND
, 0, argc
, argv
);
1184 static int opkg_whatsuggests_cmd(int argc
, char **argv
)
1186 return opkg_what_depends_conflicts_cmd(SUGGEST
, 0, argc
, argv
);
1189 static int opkg_whatrecommends_cmd(int argc
, char **argv
)
1191 return opkg_what_depends_conflicts_cmd(RECOMMEND
, 0, argc
, argv
);
1194 static int opkg_whatconflicts_cmd(int argc
, char **argv
)
1196 return opkg_what_depends_conflicts_cmd(CONFLICTS
, 0, argc
, argv
);
1200 opkg_what_provides_replaces_cmd(enum what_field_type what_field_type
, int argc
,
1203 abstract_pkg_t
*apkg
, **abpkgs
;
1206 pkg_vec_t
*available_pkgs
= pkg_vec_alloc();
1207 const char *rel_str
=
1208 (what_field_type
== WHATPROVIDES
? "provides" : "replaces");
1211 pkg_info_preinstall_check();
1213 if (conf
->query_all
)
1214 pkg_hash_fetch_available(available_pkgs
);
1216 pkg_hash_fetch_all_installed(available_pkgs
);
1217 for (i
= 0; i
< argc
; i
++) {
1218 const char *target
= argv
[i
];
1221 opkg_msg(NOTICE
, "What %s %s\n", rel_str
, target
);
1222 for (j
= 0; j
< available_pkgs
->len
; j
++) {
1223 pkg_t
*pkg
= available_pkgs
->pkgs
[j
];
1224 abpkgs
= pkg_get_ptr(pkg
, (what_field_type
== WHATPROVIDES
) ? PKG_PROVIDES
: PKG_REPLACES
);
1226 while (abpkgs
&& *abpkgs
) {
1229 if (fnmatch(target
, apkg
->name
, conf
->nocase
))
1232 opkg_msg(NOTICE
, " %s", pkg
->name
);
1234 if ((conf
->nocase
? strcasecmp(target
, apkg
->name
)
1235 : strcmp(target
, apkg
->name
)))
1236 opkg_msg(NOTICE
, "\t%s %s\n", rel_str
, apkg
->name
);
1238 opkg_message(NOTICE
, "\n");
1242 pkg_vec_free(available_pkgs
);
1247 static int opkg_whatprovides_cmd(int argc
, char **argv
)
1249 return opkg_what_provides_replaces_cmd(WHATPROVIDES
, argc
, argv
);
1252 static int opkg_whatreplaces_cmd(int argc
, char **argv
)
1254 return opkg_what_provides_replaces_cmd(WHATREPLACES
, argc
, argv
);
1257 static int opkg_search_cmd(int argc
, char **argv
)
1261 pkg_vec_t
*installed
;
1263 str_list_t
*installed_files
;
1264 str_list_elt_t
*iter
;
1265 char *installed_file
;
1271 installed
= pkg_vec_alloc();
1272 pkg_hash_fetch_all_installed(installed
);
1273 pkg_vec_sort(installed
, pkg_compare_names
);
1275 for (i
= 0; i
< installed
->len
; i
++) {
1276 pkg
= installed
->pkgs
[i
];
1278 installed_files
= pkg_get_installed_files(pkg
);
1280 for (iter
= str_list_first(installed_files
); iter
;
1281 iter
= str_list_next(installed_files
, iter
)) {
1282 installed_file
= (char *)iter
->data
;
1283 if (fnmatch(argv
[0], installed_file
, conf
->nocase
) == 0)
1287 pkg_free_installed_files(pkg
);
1290 pkg_vec_free(installed
);
1295 static int opkg_compare_versions_cmd(int argc
, char **argv
)
1301 /* this is a bit gross */
1304 parse_version(p1
, argv
[0]);
1305 parse_version(p2
, argv
[2]);
1306 rc
= pkg_version_satisfied(p1
, p2
, argv
[1]);
1314 "opkg compare_versions <v1> <op> <v2>\n"
1315 "<op> is one of <= >= << >> =\n");
1320 static int opkg_print_architecture_cmd(int argc
, char **argv
)
1322 nv_pair_list_elt_t
*l
;
1324 list_for_each_entry(l
, &conf
->arch_list
.head
, node
) {
1325 nv_pair_t
*nv
= (nv_pair_t
*) l
->data
;
1326 printf("arch %s %s\n", nv
->name
, nv
->value
);
1331 /* XXX: CLEANUP: The usage strings should be incorporated into this
1332 array for easier maintenance */
1333 static opkg_cmd_t cmds
[] = {
1334 {"update", 0, (opkg_cmd_fun_t
) opkg_update_cmd
,
1335 PFM_DESCRIPTION
| PFM_SOURCE
},
1336 {"upgrade", 1, (opkg_cmd_fun_t
) opkg_upgrade_cmd
,
1337 PFM_DESCRIPTION
| PFM_SOURCE
},
1338 {"list", 0, (opkg_cmd_fun_t
) opkg_list_cmd
, PFM_SOURCE
},
1339 {"list_installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1341 {"list-installed", 0, (opkg_cmd_fun_t
) opkg_list_installed_cmd
,
1343 {"list_upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1345 {"list-upgradable", 0, (opkg_cmd_fun_t
) opkg_list_upgradable_cmd
,
1347 {"list_changed_conffiles", 0,
1348 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1349 {"list-changed-conffiles", 0,
1350 (opkg_cmd_fun_t
) opkg_list_changed_conffiles_cmd
, PFM_SOURCE
},
1351 {"info", 0, (opkg_cmd_fun_t
) opkg_info_cmd
, 0},
1352 {"flag", 1, (opkg_cmd_fun_t
) opkg_flag_cmd
,
1353 PFM_DESCRIPTION
| PFM_SOURCE
},
1354 {"status", 0, (opkg_cmd_fun_t
) opkg_status_cmd
,
1355 PFM_DESCRIPTION
| PFM_SOURCE
},
1356 {"install", 1, (opkg_cmd_fun_t
) opkg_install_cmd
,
1357 PFM_DESCRIPTION
| PFM_SOURCE
},
1358 {"remove", 1, (opkg_cmd_fun_t
) opkg_remove_cmd
,
1359 PFM_DESCRIPTION
| PFM_SOURCE
},
1360 {"configure", 0, (opkg_cmd_fun_t
) opkg_configure_cmd
,
1361 PFM_DESCRIPTION
| PFM_SOURCE
},
1362 {"files", 1, (opkg_cmd_fun_t
) opkg_files_cmd
,
1363 PFM_DESCRIPTION
| PFM_SOURCE
},
1364 {"search", 1, (opkg_cmd_fun_t
) opkg_search_cmd
,
1365 PFM_DESCRIPTION
| PFM_SOURCE
},
1366 {"find", 1, (opkg_cmd_fun_t
) opkg_find_cmd
, PFM_SOURCE
},
1367 {"download", 1, (opkg_cmd_fun_t
) opkg_download_cmd
,
1368 PFM_DESCRIPTION
| PFM_SOURCE
},
1369 {"compare_versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1370 {"compare-versions", 1, (opkg_cmd_fun_t
) opkg_compare_versions_cmd
, 0},
1371 {"print-architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1372 PFM_DESCRIPTION
| PFM_SOURCE
},
1373 {"print_architecture", 0, (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1374 PFM_DESCRIPTION
| PFM_SOURCE
},
1375 {"print-installation-architecture", 0,
1376 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1377 PFM_DESCRIPTION
| PFM_SOURCE
},
1378 {"print_installation_architecture", 0,
1379 (opkg_cmd_fun_t
) opkg_print_architecture_cmd
,
1380 PFM_DESCRIPTION
| PFM_SOURCE
},
1381 {"depends", 1, (opkg_cmd_fun_t
) opkg_depends_cmd
,
1382 PFM_DESCRIPTION
| PFM_SOURCE
},
1383 {"whatdepends", 1, (opkg_cmd_fun_t
) opkg_whatdepends_cmd
,
1384 PFM_DESCRIPTION
| PFM_SOURCE
},
1385 {"whatdependsrec", 1, (opkg_cmd_fun_t
) opkg_whatdepends_recursively_cmd
,
1386 PFM_DESCRIPTION
| PFM_SOURCE
},
1387 {"whatrecommends", 1, (opkg_cmd_fun_t
) opkg_whatrecommends_cmd
,
1388 PFM_DESCRIPTION
| PFM_SOURCE
},
1389 {"whatsuggests", 1, (opkg_cmd_fun_t
) opkg_whatsuggests_cmd
,
1390 PFM_DESCRIPTION
| PFM_SOURCE
},
1391 {"whatprovides", 1, (opkg_cmd_fun_t
) opkg_whatprovides_cmd
,
1392 PFM_DESCRIPTION
| PFM_SOURCE
},
1393 {"whatreplaces", 1, (opkg_cmd_fun_t
) opkg_whatreplaces_cmd
,
1394 PFM_DESCRIPTION
| PFM_SOURCE
},
1395 {"whatconflicts", 1, (opkg_cmd_fun_t
) opkg_whatconflicts_cmd
,
1396 PFM_DESCRIPTION
| PFM_SOURCE
},
1399 opkg_cmd_t
*opkg_cmd_find(const char *name
)
1403 int num_cmds
= sizeof(cmds
) / sizeof(opkg_cmd_t
);
1405 for (i
= 0; i
< num_cmds
; i
++) {
1407 if (strcmp(name
, cmd
->name
) == 0)
1414 int opkg_cmd_exec(opkg_cmd_t
* cmd
, int argc
, const char **argv
)
1416 return (cmd
->fun
) (argc
, argv
);