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