when configure with --disable-gpg, no message complain about the signature stuff.
[project/opkg-lede.git] / libopkg / opkg_cmd.c
1 /* opkg_cmd.c - the opkg package management system
2
3 Carl D. Worth
4
5 Copyright (C) 2001 University of Southern California
6
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.
11
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.
16 */
17
18
19 #include "includes.h"
20 #include <dirent.h>
21 #include <glob.h>
22
23 #include "opkg_conf.h"
24 #include "opkg_cmd.h"
25 #include "opkg_message.h"
26 #include "pkg.h"
27 #include "pkg_dest.h"
28 #include "pkg_parse.h"
29 #include "sprintf_alloc.h"
30 #include "pkg.h"
31 #include "file_util.h"
32 #include "str_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
36
37 #include <fnmatch.h>
38
39
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"
46
47 #include "libopkg.h"
48 static void *p_userdata = NULL;
49
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_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
73 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
74 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
75 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
76 static int pkg_mark_provides(pkg_t *pkg);
77
78 /* XXX: CLEANUP: The usage strings should be incorporated into this
79 array for easier maintenance */
80 static opkg_cmd_t cmds[] = {
81 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
82 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
83 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
84 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
85 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
86 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
87 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
88 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
89 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
90 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
91 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
92 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
93 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
94 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
95 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
96 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
97 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
98 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
99 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
102 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
103 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
104 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
105 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
106 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
107 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
108 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
109 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
110 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
111 };
112
113 int opkg_state_changed;
114 static void write_status_files_if_changed(opkg_conf_t *conf)
115 {
116 if (opkg_state_changed && !conf->noaction) {
117 opkg_message(conf, OPKG_INFO,
118 " writing status file\n");
119 opkg_conf_write_status_files(conf);
120 pkg_write_changed_filelists(conf);
121 } else {
122 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
123 }
124 }
125
126
127 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
128
129 opkg_cmd_t *opkg_cmd_find(const char *name)
130 {
131 int i;
132 opkg_cmd_t *cmd;
133
134 for (i=0; i < num_cmds; i++) {
135 cmd = &cmds[i];
136 if (strcmp(name, cmd->name) == 0) {
137 return cmd;
138 }
139 }
140
141 return NULL;
142 }
143
144 void opkg_print_error_list (opkg_conf_t *conf)
145 {
146 if ( error_list ) {
147 reverse_error_list(&error_list);
148
149 printf ("Collected errors:\n");
150 /* Here we print the errors collected and free the list */
151 while (error_list != NULL) {
152 printf (" * %s", error_list->errmsg);
153 error_list = error_list->next;
154
155 }
156 free_error_list();
157 }
158
159 }
160
161 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
162 {
163 int result;
164 p_userdata = userdata;
165
166
167 result = (cmd->fun)(conf, argc, argv);
168
169 if ( result != 0 && !error_list) {
170 opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
171 }
172
173 opkg_print_error_list (conf);
174
175 p_userdata = NULL;
176 return result;
177 }
178
179 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
180 {
181 char *tmp;
182 int err;
183 int failures;
184 char *lists_dir;
185 pkg_src_list_elt_t *iter;
186 pkg_src_t *src;
187
188
189 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
190
191 if (! file_is_dir(lists_dir)) {
192 if (file_exists(lists_dir)) {
193 opkg_message(conf, OPKG_ERROR,
194 "%s: ERROR: %s exists, but is not a directory\n",
195 __FUNCTION__, lists_dir);
196 free(lists_dir);
197 return EINVAL;
198 }
199 err = file_mkdir_hier(lists_dir, 0755);
200 if (err) {
201 opkg_message(conf, OPKG_ERROR,
202 "%s: ERROR: failed to make directory %s: %s\n",
203 __FUNCTION__, lists_dir, strerror(errno));
204 free(lists_dir);
205 return EINVAL;
206 }
207 }
208
209 failures = 0;
210
211
212 tmp = strdup ("/tmp/opkg.XXXXXX");
213
214 if (mkdtemp (tmp) == NULL) {
215 perror ("mkdtemp");
216 failures++;
217 }
218
219
220 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
221 char *url, *list_file_name;
222
223 src = (pkg_src_t *)iter->data;
224
225 if (src->extra_data) /* debian style? */
226 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
227 src->gzip ? "Packages.gz" : "Packages");
228 else
229 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
230
231 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
232 if (src->gzip) {
233 char *tmp_file_name;
234 FILE *in, *out;
235
236 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
237 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
238 if (err == 0) {
239 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
240 in = fopen (tmp_file_name, "r");
241 out = fopen (list_file_name, "w");
242 if (in && out)
243 unzip (in, out);
244 else
245 err = 1;
246 if (in)
247 fclose (in);
248 if (out)
249 fclose (out);
250 unlink (tmp_file_name);
251 }
252 } else
253 err = opkg_download(conf, url, list_file_name, NULL, NULL);
254 if (err) {
255 failures++;
256 } else {
257 opkg_message(conf, OPKG_NOTICE,
258 "Updated list of available packages in %s\n",
259 list_file_name);
260 }
261 free(url);
262
263 #ifdef HAVE_GPGME
264 /* download detached signitures to verify the package lists */
265 /* get the url for the sig file */
266 if (src->extra_data) /* debian style? */
267 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
268 "Packages.sig");
269 else
270 sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
271
272 /* create temporary file for it */
273 char *tmp_file_name;
274
275 sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig");
276
277 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
278 if (err) {
279 failures++;
280 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
281 } else {
282 int err;
283 err = opkg_verify_file (conf, list_file_name, tmp_file_name);
284 if (err == 0)
285 opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
286 else
287 opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
288 }
289 unlink (tmp_file_name);
290 free (tmp_file_name);
291 free (url);
292 #else
293 // Do nothing
294 #endif
295 free(list_file_name);
296 }
297 rmdir (tmp);
298 free (tmp);
299 free(lists_dir);
300
301 return failures;
302 }
303
304
305 struct opkg_intercept
306 {
307 char *oldpath;
308 char *statedir;
309 };
310
311 typedef struct opkg_intercept *opkg_intercept_t;
312
313 static opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
314 {
315 opkg_intercept_t ctx;
316 char *oldpath;
317 char *newpath;
318 int gen;
319
320 ctx = calloc (1, sizeof (*ctx));
321 oldpath = getenv ("PATH");
322 if (oldpath) {
323 ctx->oldpath = strdup (oldpath);
324 } else {
325 ctx->oldpath = 0;
326 }
327
328
329 sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
330 setenv ("PATH", newpath, 1);
331 free (newpath);
332
333 gen = 0;
334 retry:
335 sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
336 if (mkdir (ctx->statedir, 0770) < 0) {
337 if (errno == EEXIST) {
338 free (ctx->statedir);
339 gen++;
340 goto retry;
341 }
342 perror (ctx->statedir);
343 return NULL;
344 }
345 setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
346 return ctx;
347 }
348
349 static int opkg_finalize_intercepts(opkg_intercept_t ctx)
350 {
351 char *cmd;
352 DIR *dir;
353 int err = 0;
354
355 if (ctx->oldpath) {
356 setenv ("PATH", ctx->oldpath, 1);
357 free (ctx->oldpath);
358 } else {
359 unsetenv("PATH");
360 }
361
362 dir = opendir (ctx->statedir);
363 if (dir) {
364 struct dirent *de;
365 while (de = readdir (dir), de != NULL) {
366 char *path;
367
368 if (de->d_name[0] == '.')
369 continue;
370
371 sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
372 if (access (path, X_OK) == 0) {
373 if (system (path)) {
374 err = errno;
375 perror (de->d_name);
376 }
377 }
378 free (path);
379 }
380 } else
381 perror (ctx->statedir);
382
383 sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
384 err = system (cmd);
385 free (cmd);
386
387 free (ctx->statedir);
388 free (ctx);
389
390 return err;
391 }
392
393 /* For package pkg do the following: If it is already visited, return. If not,
394 add it in visited list and recurse to its deps. Finally, add it to ordered
395 list.
396 pkg_vec all contains all available packages in repos.
397 pkg_vec visited contains packages already visited by this function, and is
398 used to end recursion and avoid an infinite loop on graph cycles.
399 pkg_vec ordered will finally contain the ordered set of packages.
400 */
401 static int opkg_recurse_pkgs_in_order(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *all,
402 pkg_vec_t *visited, pkg_vec_t *ordered)
403 {
404 int j,k,l,m;
405 int count;
406 pkg_t *dep;
407 compound_depend_t * compound_depend;
408 depend_t ** possible_satisfiers;
409 abstract_pkg_t *abpkg;
410 abstract_pkg_t **dependents;
411
412 /* If it's just an available package, that is, not installed and not even
413 unpacked, skip it */
414 /* XXX: This is probably an overkill, since a state_status != SS_UNPACKED
415 would do here. However, if there is an intermediate node (pkg) that is
416 configured and installed between two unpacked packages, the latter
417 won't be properly reordered, unless all installed/unpacked pkgs are
418 checked */
419 if (pkg->state_status == SS_NOT_INSTALLED)
420 return 0;
421
422 /* If the package has already been visited (by this function), skip it */
423 for(j = 0; j < visited->len; j++)
424 if ( ! strcmp(visited->pkgs[j]->name, pkg->name)) {
425 opkg_message(conf, OPKG_INFO,
426 " pkg: %s already visited\n", pkg->name);
427 return 0;
428 }
429
430 pkg_vec_insert(visited, pkg);
431
432 count = pkg->pre_depends_count + pkg->depends_count + \
433 pkg->recommends_count + pkg->suggests_count;
434
435 opkg_message(conf, OPKG_INFO,
436 " pkg: %s\n", pkg->name);
437
438 /* Iterate over all the dependencies of pkg. For each one, find a package
439 that is either installed or unpacked and satisfies this dependency.
440 (there should only be one such package per dependency installed or
441 unpacked). Then recurse to the dependency package */
442 for (j=0; j < count ; j++) {
443 compound_depend = &pkg->depends[j];
444 possible_satisfiers = compound_depend->possibilities;
445 for (k=0; k < compound_depend->possibility_count ; k++) {
446 abpkg = possible_satisfiers[k]->pkg;
447 dependents = abpkg->provided_by->pkgs;
448 l = 0;
449 if (dependents != NULL)
450 while (dependents [l] != NULL && l < abpkg->provided_by->len) {
451 opkg_message(conf, OPKG_INFO,
452 " Descending on pkg: %s\n",
453 dependents [l]->name);
454
455 /* find whether dependent l is installed or unpacked,
456 * and then find which package in the list satisfies it */
457 for(m = 0; m < all->len; m++) {
458 dep = all->pkgs[m];
459 if ( dep->state_status != SS_NOT_INSTALLED)
460 if ( ! strcmp(dep->name, dependents[l]->name)) {
461 opkg_recurse_pkgs_in_order(conf, dep, all,
462 visited, ordered);
463 /* Stop the outer loop */
464 l = abpkg->provided_by->len;
465 /* break from the inner loop */
466 break;
467 }
468 }
469 l++;
470 }
471 }
472 }
473
474 /* When all recursions from this node down, are over, and all
475 dependencies have been added in proper order in the ordered array, add
476 also the package pkg to ordered array */
477 pkg_vec_insert(ordered, pkg);
478
479 return 0;
480
481 }
482
483 static int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
484 {
485 pkg_vec_t *all, *ordered, *visited;
486 int i;
487 pkg_t *pkg;
488 opkg_intercept_t ic;
489 int r, err = 0;
490
491 opkg_message(conf, OPKG_INFO,
492 "Configuring unpacked packages\n");
493 fflush( stdout );
494
495 all = pkg_vec_alloc();
496
497 pkg_hash_fetch_available(&conf->pkg_hash, all);
498
499 /* Reorder pkgs in order to be configured according to the Depends: tag
500 order */
501 opkg_message(conf, OPKG_INFO,
502 "Reordering packages before configuring them...\n");
503 ordered = pkg_vec_alloc();
504 visited = pkg_vec_alloc();
505 for(i = 0; i < all->len; i++) {
506 pkg = all->pkgs[i];
507 opkg_recurse_pkgs_in_order(conf, pkg, all, visited, ordered);
508 }
509
510
511 ic = opkg_prep_intercepts (conf);
512
513 for(i = 0; i < all->len; i++) {
514 pkg = all->pkgs[i];
515
516 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
517 continue;
518
519 if (pkg->state_status == SS_UNPACKED) {
520 opkg_message(conf, OPKG_NOTICE,
521 "Configuring %s\n", pkg->name);
522 fflush( stdout );
523 r = opkg_configure(conf, pkg);
524 if (r == 0) {
525 pkg->state_status = SS_INSTALLED;
526 pkg->parent->state_status = SS_INSTALLED;
527 pkg->state_flag &= ~SF_PREFER;
528 } else {
529 if (!err)
530 err = r;
531 }
532 }
533 }
534
535 r = opkg_finalize_intercepts (ic);
536 if (r && !err)
537 err = r;
538
539 pkg_vec_free(all);
540 pkg_vec_free(ordered);
541 pkg_vec_free(visited);
542
543 return err;
544 }
545
546 static opkg_conf_t *global_conf;
547
548 static void sigint_handler(int sig)
549 {
550 signal(sig, SIG_DFL);
551 opkg_message(NULL, OPKG_NOTICE,
552 "opkg: interrupted. writing out status database\n");
553 write_status_files_if_changed(global_conf);
554 exit(128 + sig);
555 }
556
557 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
558 {
559 int i;
560 char *arg;
561 int err=0;
562
563 global_conf = conf;
564 signal(SIGINT, sigint_handler);
565
566 /*
567 * Now scan through package names and install
568 */
569 for (i=0; i < argc; i++) {
570 arg = argv[i];
571
572 opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s \n",arg );
573 err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
574 if (err != EINVAL && err != 0)
575 return err;
576 }
577 pkg_info_preinstall_check(conf);
578
579 for (i=0; i < argc; i++) {
580 arg = argv[i];
581 err = opkg_install_by_name(conf, arg);
582 if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
583 opkg_message(conf, OPKG_ERROR,
584 "Cannot find package %s.\n",
585 arg);
586 }
587 }
588
589 /* recheck to verify that all dependences are satisfied */
590 if (0) opkg_satisfy_all_dependences(conf);
591
592 opkg_configure_packages(conf, NULL);
593
594 write_status_files_if_changed(conf);
595
596 return err;
597 }
598
599 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
600 {
601 int i;
602 pkg_t *pkg;
603 int err;
604
605 global_conf = conf;
606 signal(SIGINT, sigint_handler);
607
608 if (argc) {
609 for (i=0; i < argc; i++) {
610 char *arg = argv[i];
611
612 err = opkg_prepare_url_for_install(conf, arg, &arg);
613 if (err != EINVAL && err != 0)
614 return err;
615 }
616 pkg_info_preinstall_check(conf);
617
618 for (i=0; i < argc; i++) {
619 char *arg = argv[i];
620 if (conf->restrict_to_default_dest) {
621 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
622 argv[i],
623 conf->default_dest);
624 if (pkg == NULL) {
625 opkg_message(conf, OPKG_NOTICE,
626 "Package %s not installed in %s\n",
627 argv[i], conf->default_dest->name);
628 continue;
629 }
630 } else {
631 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
632 argv[i]);
633 }
634 if (pkg)
635 opkg_upgrade_pkg(conf, pkg);
636 else {
637 opkg_install_by_name(conf, arg);
638 }
639 }
640 } else {
641 pkg_vec_t *installed = pkg_vec_alloc();
642
643 pkg_info_preinstall_check(conf);
644
645 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
646 for (i = 0; i < installed->len; i++) {
647 pkg = installed->pkgs[i];
648 opkg_upgrade_pkg(conf, pkg);
649 }
650 pkg_vec_free(installed);
651 }
652
653 /* recheck to verify that all dependences are satisfied */
654 if (0) opkg_satisfy_all_dependences(conf);
655
656 opkg_configure_packages(conf, NULL);
657
658 write_status_files_if_changed(conf);
659
660 return 0;
661 }
662
663 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
664 {
665 int i, err;
666 char *arg;
667 pkg_t *pkg;
668
669 pkg_info_preinstall_check(conf);
670 for (i = 0; i < argc; i++) {
671 arg = argv[i];
672
673 pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg, &err);
674 if (pkg == NULL) {
675 opkg_message(conf, OPKG_ERROR,
676 "Cannot find package %s.\n"
677 "Check the spelling or perhaps run 'opkg update'\n",
678 arg);
679 continue;
680 }
681
682 err = opkg_download_pkg(conf, pkg, ".");
683
684 if (err) {
685 opkg_message(conf, OPKG_ERROR,
686 "Failed to download %s\n", pkg->name);
687 } else {
688 opkg_message(conf, OPKG_NOTICE,
689 "Downloaded %s as %s\n",
690 pkg->name, pkg->local_filename);
691 }
692 }
693
694 return 0;
695 }
696
697
698 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
699 {
700 int i ;
701 pkg_vec_t *available;
702 pkg_t *pkg;
703 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
704 char *newline;
705 char *pkg_name = NULL;
706 char *version_str;
707
708 if (argc > 0) {
709 pkg_name = argv[0];
710 }
711 available = pkg_vec_alloc();
712 pkg_hash_fetch_available(&conf->pkg_hash, available);
713 pkg_vec_sort(available, pkg_compare_names);
714 for (i=0; i < available->len; i++) {
715 pkg = available->pkgs[i];
716 /* if we have package name or pattern and pkg does not match, then skip it */
717 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
718 continue;
719 if (pkg->description) {
720 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
721 } else {
722 desc_short[0] = '\0';
723 }
724 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
725 newline = strchr(desc_short, '\n');
726 if (newline) {
727 *newline = '\0';
728 }
729 if (opkg_cb_list) {
730 version_str = pkg_version_str_alloc(pkg);
731 opkg_cb_list(pkg->name,desc_short,
732 version_str,
733 pkg->state_status,
734 p_userdata);
735 free(version_str);
736 }
737 }
738 pkg_vec_free(available);
739
740 return 0;
741 }
742
743
744 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
745 {
746 int i ;
747 pkg_vec_t *available;
748 pkg_t *pkg;
749 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
750 char *newline;
751 char *pkg_name = NULL;
752 char *version_str;
753
754 if (argc > 0) {
755 pkg_name = argv[0];
756 }
757 available = pkg_vec_alloc();
758 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
759 pkg_vec_sort(available, pkg_compare_names);
760 for (i=0; i < available->len; i++) {
761 pkg = available->pkgs[i];
762 /* if we have package name or pattern and pkg does not match, then skip it */
763 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
764 continue;
765 if (pkg->description) {
766 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
767 } else {
768 desc_short[0] = '\0';
769 }
770 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
771 newline = strchr(desc_short, '\n');
772 if (newline) {
773 *newline = '\0';
774 }
775 if (opkg_cb_list) {
776 version_str = pkg_version_str_alloc(pkg);
777 opkg_cb_list(pkg->name,desc_short,
778 version_str,
779 pkg->state_status,
780 p_userdata);
781 free(version_str);
782 }
783 }
784
785 return 0;
786 }
787
788 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
789 {
790 struct active_list *head = prepare_upgrade_list(conf);
791 struct active_list *node=NULL;
792 pkg_t *_old_pkg, *_new_pkg;
793 char *old_v, *new_v;
794 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
795 _old_pkg = list_entry(node, pkg_t, list);
796 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
797 old_v = pkg_version_str_alloc(_old_pkg);
798 new_v = pkg_version_str_alloc(_new_pkg);
799 if (opkg_cb_list)
800 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
801 free(old_v);
802 free(new_v);
803 }
804 active_list_head_delete(head);
805 return 0;
806 }
807
808 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
809 {
810 int i;
811 pkg_vec_t *available;
812 pkg_t *pkg;
813 char *pkg_name = NULL;
814 char **pkg_fields = NULL;
815 int n_fields = 0;
816 char *buff ;
817
818 if (argc > 0) {
819 pkg_name = argv[0];
820 }
821 if (argc > 1) {
822 pkg_fields = &argv[1];
823 n_fields = argc - 1;
824 }
825
826 available = pkg_vec_alloc();
827 if (installed_only)
828 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
829 else
830 pkg_hash_fetch_available(&conf->pkg_hash, available);
831 for (i=0; i < available->len; i++) {
832 pkg = available->pkgs[i];
833 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
834 continue;
835 }
836
837 buff = pkg_formatted_info(pkg);
838 if ( buff ) {
839 if (opkg_cb_status) opkg_cb_status(pkg->name,
840 pkg->state_status,
841 buff,
842 p_userdata);
843 /*
844 We should not forget that actually the pointer is allocated.
845 We need to free it :) ( Thanks florian for seeing the error )
846 */
847 free(buff);
848 }
849 if (conf->verbosity > 1) {
850 conffile_list_elt_t *iter;
851 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
852 conffile_t *cf = (conffile_t *)iter->data;
853 int modified = conffile_has_been_modified(conf, cf);
854 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
855 cf->name, cf->value, modified);
856 }
857 }
858 }
859 pkg_vec_free(available);
860
861 return 0;
862 }
863
864 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
865 {
866 return opkg_info_status_cmd(conf, argc, argv, 0);
867 }
868
869 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
870 {
871 return opkg_info_status_cmd(conf, argc, argv, 1);
872 }
873
874 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
875 {
876
877 int err;
878 if (argc > 0) {
879 char *pkg_name = NULL;
880
881 pkg_name = argv[0];
882
883 err = opkg_configure_packages (conf, pkg_name);
884
885 } else {
886 err = opkg_configure_packages (conf, NULL);
887 }
888
889 write_status_files_if_changed(conf);
890
891 return err;
892 }
893
894 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
895 {
896 int i, err;
897 char *globpattern;
898 glob_t globbuf;
899
900 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
901 err = glob(globpattern, 0, NULL, &globbuf);
902 free(globpattern);
903 if (err) {
904 return 0;
905 }
906
907 opkg_message(conf, OPKG_NOTICE,
908 "The following packages in %s will now be installed.\n",
909 conf->pending_dir);
910 for (i = 0; i < globbuf.gl_pathc; i++) {
911 opkg_message(conf, OPKG_NOTICE,
912 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
913 }
914 opkg_message(conf, OPKG_NOTICE, "\n");
915 for (i = 0; i < globbuf.gl_pathc; i++) {
916 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
917 if (err == 0) {
918 err = unlink(globbuf.gl_pathv[i]);
919 if (err) {
920 opkg_message(conf, OPKG_ERROR,
921 "%s: ERROR: failed to unlink %s: %s\n",
922 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
923 return err;
924 }
925 }
926 }
927 globfree(&globbuf);
928
929 return err;
930 }
931
932 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
933 {
934 int i,a,done;
935 pkg_t *pkg;
936 pkg_t *pkg_to_remove;
937 pkg_vec_t *available;
938 char *pkg_name = NULL;
939 global_conf = conf;
940 signal(SIGINT, sigint_handler);
941
942 // ENH: Add the "no pkg removed" just in case.
943
944 done = 0;
945
946 pkg_info_preinstall_check(conf);
947 if ( argc > 0 ) {
948 available = pkg_vec_alloc();
949 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
950 for (i=0; i < argc; i++) {
951 pkg_name = calloc(1, strlen(argv[i])+2);
952 strcpy(pkg_name,argv[i]);
953 for (a=0; a < available->len; a++) {
954 pkg = available->pkgs[a];
955 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
956 continue;
957 }
958 if (conf->restrict_to_default_dest) {
959 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
960 pkg->name,
961 conf->default_dest);
962 } else {
963 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
964 }
965
966 if (pkg == NULL) {
967 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
968 continue;
969 }
970 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
971 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
972 continue;
973 }
974 opkg_remove_pkg(conf, pkg_to_remove,0);
975 done = 1;
976 }
977 free (pkg_name);
978 }
979 pkg_vec_free(available);
980 } else {
981 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
982 int i;
983 int flagged_pkg_count = 0;
984 int removed;
985
986 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
987
988 for (i = 0; i < installed_pkgs->len; i++) {
989 pkg_t *pkg = installed_pkgs->pkgs[i];
990 if (pkg->state_flag & SF_USER) {
991 flagged_pkg_count++;
992 } else {
993 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
994 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
995 }
996 }
997 if (!flagged_pkg_count) {
998 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
999 "so refusing to uninstall unflagged non-leaf packages\n");
1000 return 0;
1001 }
1002
1003 /* find packages not flagged SF_USER (i.e., installed to
1004 * satisfy a dependence) and not having any dependents, and
1005 * remove them */
1006 do {
1007 removed = 0;
1008 for (i = 0; i < installed_pkgs->len; i++) {
1009 pkg_t *pkg = installed_pkgs->pkgs[i];
1010 if (!(pkg->state_flag & SF_USER)
1011 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1012 removed++;
1013 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1014 opkg_remove_pkg(conf, pkg,0);
1015 done = 1;
1016 }
1017 }
1018 } while (removed);
1019 pkg_vec_free(installed_pkgs);
1020 }
1021
1022 if ( done == 0 )
1023 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1024
1025 write_status_files_if_changed(conf);
1026 return 0;
1027 }
1028
1029 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1030 {
1031 int i;
1032 pkg_t *pkg;
1033
1034 global_conf = conf;
1035 signal(SIGINT, sigint_handler);
1036
1037 pkg_info_preinstall_check(conf);
1038
1039 for (i=0; i < argc; i++) {
1040 if (conf->restrict_to_default_dest) {
1041 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1042 argv[i],
1043 conf->default_dest);
1044 } else {
1045 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1046 }
1047
1048 if (pkg == NULL) {
1049 opkg_message(conf, OPKG_ERROR,
1050 "Package %s is not installed.\n", argv[i]);
1051 continue;
1052 }
1053 opkg_purge_pkg(conf, pkg);
1054 }
1055
1056 write_status_files_if_changed(conf);
1057 return 0;
1058 }
1059
1060 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1061 {
1062 int i;
1063 pkg_t *pkg;
1064 const char *flags = argv[0];
1065
1066 global_conf = conf;
1067 signal(SIGINT, sigint_handler);
1068
1069 for (i=1; i < argc; i++) {
1070 if (conf->restrict_to_default_dest) {
1071 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1072 argv[i],
1073 conf->default_dest);
1074 } else {
1075 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1076 }
1077
1078 if (pkg == NULL) {
1079 opkg_message(conf, OPKG_ERROR,
1080 "Package %s is not installed.\n", argv[i]);
1081 continue;
1082 }
1083 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1084 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1085 pkg->state_flag = pkg_state_flag_from_str(flags);
1086 }
1087 /* pb_ asked this feature 03292004 */
1088 /* Actually I will use only this two, but this is an open for various status */
1089 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1090 pkg->state_status = pkg_state_status_from_str(flags);
1091 }
1092 opkg_state_changed++;
1093 opkg_message(conf, OPKG_NOTICE,
1094 "Setting flags for package %s to %s\n",
1095 pkg->name, flags);
1096 }
1097
1098 write_status_files_if_changed(conf);
1099 return 0;
1100 }
1101
1102 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1103 {
1104 pkg_t *pkg;
1105 str_list_t *installed_files;
1106 str_list_elt_t *iter;
1107 char *pkg_version;
1108 size_t buff_len = 8192;
1109 size_t used_len;
1110 char *buff ;
1111
1112 buff = (char *)calloc(1, buff_len);
1113 if ( buff == NULL ) {
1114 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1115 return ENOMEM;
1116 }
1117
1118 if (argc < 1) {
1119 return EINVAL;
1120 }
1121
1122 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1123 argv[0]);
1124 if (pkg == NULL) {
1125 opkg_message(conf, OPKG_ERROR,
1126 "Package %s not installed.\n", argv[0]);
1127 return 0;
1128 }
1129
1130 installed_files = pkg_get_installed_files(pkg);
1131 pkg_version = pkg_version_str_alloc(pkg);
1132
1133 if (buff) {
1134 try_again:
1135 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1136 pkg->name, pkg_version, pkg->dest->name) + 1;
1137 if (used_len > buff_len) {
1138 buff_len *= 2;
1139 buff = realloc (buff, buff_len);
1140 goto try_again;
1141 }
1142 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1143 used_len += strlen (iter->data) + 1;
1144 while (buff_len <= used_len) {
1145 buff_len *= 2;
1146 buff = realloc (buff, buff_len);
1147 }
1148 strncat(buff, iter->data, buff_len);
1149 strncat(buff, "\n", buff_len);
1150 }
1151 if (opkg_cb_list) opkg_cb_list(pkg->name,
1152 buff,
1153 pkg_version_str_alloc(pkg),
1154 pkg->state_status,
1155 p_userdata);
1156 free(buff);
1157 }
1158
1159 free(pkg_version);
1160 pkg_free_installed_files(pkg);
1161
1162 return 0;
1163 }
1164
1165 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1166 {
1167
1168 if (argc > 0) {
1169 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1170 const char *rel_str = "depends on";
1171 int i;
1172
1173 pkg_info_preinstall_check(conf);
1174
1175 if (conf->query_all)
1176 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1177 else
1178 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1179 for (i = 0; i < argc; i++) {
1180 const char *target = argv[i];
1181 int j;
1182
1183 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1184
1185 for (j = 0; j < available_pkgs->len; j++) {
1186 pkg_t *pkg = available_pkgs->pkgs[j];
1187 if (fnmatch(target, pkg->name, 0) == 0) {
1188 int k;
1189 int count = pkg->depends_count + pkg->pre_depends_count;
1190 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1191 target, pkg->architecture, rel_str);
1192 for (k = 0; k < count; k++) {
1193 compound_depend_t *cdepend = &pkg->depends[k];
1194 int l;
1195 for (l = 0; l < cdepend->possibility_count; l++) {
1196 depend_t *possibility = cdepend->possibilities[l];
1197 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1198 if (conf->verbosity > 0) {
1199 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1200 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1201 if (possibility->version) {
1202 char *typestr = NULL;
1203 switch (possibility->constraint) {
1204 case NONE: typestr = "none"; break;
1205 case EARLIER: typestr = "<"; break;
1206 case EARLIER_EQUAL: typestr = "<="; break;
1207 case EQUAL: typestr = "="; break;
1208 case LATER_EQUAL: typestr = ">="; break;
1209 case LATER: typestr = ">"; break;
1210 }
1211 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1212 }
1213 // free(ver);
1214 }
1215 opkg_message(conf, OPKG_ERROR, "\n");
1216 }
1217 }
1218 }
1219 }
1220 }
1221 pkg_vec_free(available_pkgs);
1222 }
1223 return 0;
1224 }
1225
1226 enum what_field_type {
1227 WHATDEPENDS,
1228 WHATCONFLICTS,
1229 WHATPROVIDES,
1230 WHATREPLACES,
1231 WHATRECOMMENDS,
1232 WHATSUGGESTS
1233 };
1234
1235 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1236 {
1237
1238 if (argc > 0) {
1239 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1240 const char *rel_str = NULL;
1241 int i;
1242 int changed;
1243
1244 switch (what_field_type) {
1245 case WHATDEPENDS: rel_str = "depends on"; break;
1246 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1247 case WHATSUGGESTS: rel_str = "suggests"; break;
1248 case WHATRECOMMENDS: rel_str = "recommends"; break;
1249 case WHATPROVIDES: rel_str = "provides"; break;
1250 case WHATREPLACES: rel_str = "replaces"; break;
1251 }
1252
1253 if (conf->query_all)
1254 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1255 else
1256 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1257
1258 /* mark the root set */
1259 pkg_vec_clear_marks(available_pkgs);
1260 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1261 for (i = 0; i < argc; i++) {
1262 const char *dependee_pattern = argv[i];
1263 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1264 }
1265 for (i = 0; i < available_pkgs->len; i++) {
1266 pkg_t *pkg = available_pkgs->pkgs[i];
1267 if (pkg->state_flag & SF_MARKED) {
1268 /* mark the parent (abstract) package */
1269 pkg_mark_provides(pkg);
1270 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1271 }
1272 }
1273
1274 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1275 do {
1276 int j;
1277 changed = 0;
1278
1279 for (j = 0; j < available_pkgs->len; j++) {
1280 pkg_t *pkg = available_pkgs->pkgs[j];
1281 int k;
1282 int count = ((what_field_type == WHATCONFLICTS)
1283 ? pkg->conflicts_count
1284 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1285 /* skip this package if it is already marked */
1286 if (pkg->parent->state_flag & SF_MARKED) {
1287 continue;
1288 }
1289 for (k = 0; k < count; k++) {
1290 compound_depend_t *cdepend =
1291 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1292 int l;
1293 for (l = 0; l < cdepend->possibility_count; l++) {
1294 depend_t *possibility = cdepend->possibilities[l];
1295 if (possibility->pkg->state_flag & SF_MARKED) {
1296 /* mark the depending package so we won't visit it again */
1297 pkg->state_flag |= SF_MARKED;
1298 pkg_mark_provides(pkg);
1299 changed++;
1300
1301 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1302 if (conf->verbosity > 0) {
1303 char *ver = pkg_version_str_alloc(pkg);
1304 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1305 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1306 if (possibility->version) {
1307 char *typestr = NULL;
1308 switch (possibility->constraint) {
1309 case NONE: typestr = "none"; break;
1310 case EARLIER: typestr = "<"; break;
1311 case EARLIER_EQUAL: typestr = "<="; break;
1312 case EQUAL: typestr = "="; break;
1313 case LATER_EQUAL: typestr = ">="; break;
1314 case LATER: typestr = ">"; break;
1315 }
1316 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1317 }
1318 free(ver);
1319 if (!pkg_dependence_satisfiable(conf, possibility))
1320 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1321 }
1322 opkg_message(conf, OPKG_NOTICE, "\n");
1323 goto next_package;
1324 }
1325 }
1326 }
1327 next_package:
1328 ;
1329 }
1330 } while (changed && recursive);
1331 pkg_vec_free(available_pkgs);
1332 }
1333
1334 return 0;
1335 }
1336
1337 static int pkg_mark_provides(pkg_t *pkg)
1338 {
1339 int provides_count = pkg->provides_count;
1340 abstract_pkg_t **provides = pkg->provides;
1341 int i;
1342 pkg->parent->state_flag |= SF_MARKED;
1343 for (i = 0; i < provides_count; i++) {
1344 provides[i]->state_flag |= SF_MARKED;
1345 }
1346 return 0;
1347 }
1348
1349 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1350 {
1351 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1352 }
1353 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1354 {
1355 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1356 }
1357
1358 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1359 {
1360 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1361 }
1362
1363 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1364 {
1365 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1366 }
1367
1368 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1369 {
1370 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1371 }
1372
1373 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1374 {
1375
1376 if (argc > 0) {
1377 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1378 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1379 int i;
1380
1381 pkg_info_preinstall_check(conf);
1382
1383 if (conf->query_all)
1384 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1385 else
1386 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1387 for (i = 0; i < argc; i++) {
1388 const char *target = argv[i];
1389 int j;
1390
1391 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1392 rel_str, target);
1393 for (j = 0; j < available_pkgs->len; j++) {
1394 pkg_t *pkg = available_pkgs->pkgs[j];
1395 int k;
1396 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1397 for (k = 0; k < count; k++) {
1398 abstract_pkg_t *apkg =
1399 ((what_field_type == WHATPROVIDES)
1400 ? pkg->provides[k]
1401 : pkg->replaces[k]);
1402 if (fnmatch(target, apkg->name, 0) == 0) {
1403 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1404 if (strcmp(target, apkg->name) != 0)
1405 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1406 opkg_message(conf, OPKG_ERROR, "\n");
1407 }
1408 }
1409 }
1410 }
1411 pkg_vec_free(available_pkgs);
1412 }
1413 return 0;
1414 }
1415
1416 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1417 {
1418 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1419 }
1420
1421 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1422 {
1423 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1424 }
1425
1426 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1427 {
1428 int i;
1429
1430 pkg_vec_t *installed;
1431 pkg_t *pkg;
1432 str_list_t *installed_files;
1433 str_list_elt_t *iter;
1434 char *installed_file;
1435
1436 if (argc < 1) {
1437 return EINVAL;
1438 }
1439
1440 installed = pkg_vec_alloc();
1441 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1442 pkg_vec_sort(installed, pkg_compare_names);
1443
1444 for (i=0; i < installed->len; i++) {
1445 pkg = installed->pkgs[i];
1446
1447 installed_files = pkg_get_installed_files(pkg);
1448
1449 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1450 installed_file = (char *)iter->data;
1451 if (fnmatch(argv[0], installed_file, 0)==0) {
1452 if (opkg_cb_list) opkg_cb_list(pkg->name,
1453 installed_file,
1454 pkg_version_str_alloc(pkg),
1455 pkg->state_status, p_userdata);
1456 }
1457 }
1458
1459 pkg_free_installed_files(pkg);
1460 }
1461
1462 pkg_vec_free(installed);
1463
1464 return 0;
1465 }
1466
1467 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1468 {
1469 if (argc == 3) {
1470 /* this is a bit gross */
1471 struct pkg p1, p2;
1472 parseVersion(&p1, argv[0]);
1473 parseVersion(&p2, argv[2]);
1474 return pkg_version_satisfied(&p1, &p2, argv[1]);
1475 } else {
1476 opkg_message(conf, OPKG_ERROR,
1477 "opkg compare_versions <v1> <op> <v2>\n"
1478 "<op> is one of <= >= << >> =\n");
1479 return -1;
1480 }
1481 }
1482
1483 #ifndef HOST_CPU_STR
1484 #define HOST_CPU_STR__(X) #X
1485 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1486 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1487 #endif
1488
1489 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1490 {
1491 nv_pair_list_elt_t *l;
1492
1493 list_for_each_entry(l, &conf->arch_list.head, node) {
1494 nv_pair_t *nv = (nv_pair_t *)l->data;
1495 printf("arch %s %s\n", nv->name, nv->value);
1496 }
1497 return 0;
1498 }
1499
1500