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