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