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