adding check_signature config
[project/opkg-lede.git] / libopkg / opkg_cmd.c
1 /* opkg_cmd.c - the opkg package management system
2
3 Carl D. Worth
4
5 Copyright (C) 2001 University of Southern California
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16 */
17
18
19 #include "includes.h"
20 #include <dirent.h>
21 #include <glob.h>
22
23 #include "opkg_conf.h"
24 #include "opkg_cmd.h"
25 #include "opkg_message.h"
26 #include "pkg.h"
27 #include "pkg_dest.h"
28 #include "pkg_parse.h"
29 #include "sprintf_alloc.h"
30 #include "pkg.h"
31 #include "file_util.h"
32 #include "str_util.h"
33 #include "libbb/libbb.h"
34 #include "opkg_utils.h"
35 #include "opkg_defines.h"
36
37 #include <fnmatch.h>
38
39
40 #include "opkg_download.h"
41 #include "opkg_install.h"
42 #include "opkg_upgrade.h"
43 #include "opkg_remove.h"
44 #include "opkg_configure.h"
45 #include "opkg_message.h"
46
47 #include "libopkg.h"
48 static void *p_userdata = NULL;
49
50 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
51 static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
52 static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
53 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
54 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
55 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
56 static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
57 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
58 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv);
59 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
60 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
61 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
62 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
63 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
64 static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
65 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
66 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
67 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
68 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
69 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
70 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
71 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
72 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
73 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
74 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
75 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
76 static int pkg_mark_provides(pkg_t *pkg);
77
78 /* XXX: CLEANUP: The usage strings should be incorporated into this
79 array for easier maintenance */
80 static opkg_cmd_t cmds[] = {
81 {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd},
82 {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
83 {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
84 {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
85 {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd},
86 {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
87 {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
88 {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
89 {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
90 {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
91 {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
92 {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
93 {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
94 {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
95 {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
96 {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
97 {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
98 {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
99 {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
100 {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
101 {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
102 {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
103 {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
104 {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
105 {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
106 {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
107 {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
108 {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
109 {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
110 {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
111 };
112
113 int opkg_state_changed;
114 static void write_status_files_if_changed(opkg_conf_t *conf)
115 {
116 if (opkg_state_changed && !conf->noaction) {
117 opkg_message(conf, OPKG_INFO,
118 " writing status file\n");
119 opkg_conf_write_status_files(conf);
120 pkg_write_changed_filelists(conf);
121 } else {
122 opkg_message(conf, OPKG_DEBUG, "Nothing to be done\n");
123 }
124 }
125
126
127 static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
128
129 opkg_cmd_t *opkg_cmd_find(const char *name)
130 {
131 int i;
132 opkg_cmd_t *cmd;
133
134 for (i=0; i < num_cmds; i++) {
135 cmd = &cmds[i];
136 if (strcmp(name, cmd->name) == 0) {
137 return cmd;
138 }
139 }
140
141 return NULL;
142 }
143
144 void opkg_print_error_list (opkg_conf_t *conf)
145 {
146 if ( error_list ) {
147 reverse_error_list(&error_list);
148
149 printf ("Collected errors:\n");
150 /* Here we print the errors collected and free the list */
151 while (error_list != NULL) {
152 printf (" * %s", error_list->errmsg);
153 error_list = error_list->next;
154
155 }
156 free_error_list();
157 }
158
159 }
160
161 int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
162 {
163 int result;
164 p_userdata = userdata;
165
166
167 result = (cmd->fun)(conf, argc, argv);
168
169 if ( result != 0 && !error_list) {
170 opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
171 }
172
173 opkg_print_error_list (conf);
174
175 p_userdata = NULL;
176 return result;
177 }
178
179 static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
180 {
181 char *tmp;
182 int err;
183 int failures;
184 char *lists_dir;
185 pkg_src_list_elt_t *iter;
186 pkg_src_t *src;
187
188
189 sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
190
191 if (! file_is_dir(lists_dir)) {
192 if (file_exists(lists_dir)) {
193 opkg_message(conf, OPKG_ERROR,
194 "%s: ERROR: %s exists, but is not a directory\n",
195 __FUNCTION__, lists_dir);
196 free(lists_dir);
197 return EINVAL;
198 }
199 err = file_mkdir_hier(lists_dir, 0755);
200 if (err) {
201 opkg_message(conf, OPKG_ERROR,
202 "%s: ERROR: failed to make directory %s: %s\n",
203 __FUNCTION__, lists_dir, strerror(errno));
204 free(lists_dir);
205 return EINVAL;
206 }
207 }
208
209 failures = 0;
210
211
212 tmp = strdup ("/tmp/opkg.XXXXXX");
213
214 if (mkdtemp (tmp) == NULL) {
215 perror ("mkdtemp");
216 failures++;
217 }
218
219
220 for (iter = void_list_first(&conf->pkg_src_list); iter; iter = void_list_next(&conf->pkg_src_list, iter)) {
221 char *url, *list_file_name;
222
223 src = (pkg_src_t *)iter->data;
224
225 if (src->extra_data) /* debian style? */
226 sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
227 src->gzip ? "Packages.gz" : "Packages");
228 else
229 sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
230
231 sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
232 if (src->gzip) {
233 char *tmp_file_name;
234 FILE *in, *out;
235
236 sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
237 err = opkg_download(conf, url, tmp_file_name, NULL, NULL);
238 if (err == 0) {
239 opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
240 in = fopen (tmp_file_name, "r");
241 out = fopen (list_file_name, "w");
242 if (in && out)
243 unzip (in, out);
244 else
245 err = 1;
246 if (in)
247 fclose (in);
248 if (out)
249 fclose (out);
250 unlink (tmp_file_name);
251 }
252 } else
253 err = opkg_download(conf, url, list_file_name, NULL, NULL);
254 if (err) {
255 failures++;
256 } else {
257 opkg_message(conf, OPKG_NOTICE,
258 "Updated list of available packages in %s\n",
259 list_file_name);
260 }
261 free(url);
262
263 #ifdef HAVE_GPGME
264 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 ;
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 }
851 if (conf->verbosity > 1) {
852 conffile_list_elt_t *iter;
853 for (iter = nv_pair_list_first(&pkg->conffiles); iter; iter = nv_pair_list_next(&pkg->conffiles, iter)) {
854 conffile_t *cf = (conffile_t *)iter->data;
855 int modified = conffile_has_been_modified(conf, cf);
856 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
857 cf->name, cf->value, modified);
858 }
859 }
860 }
861 pkg_vec_free(available);
862
863 return 0;
864 }
865
866 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
867 {
868 return opkg_info_status_cmd(conf, argc, argv, 0);
869 }
870
871 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
872 {
873 return opkg_info_status_cmd(conf, argc, argv, 1);
874 }
875
876 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
877 {
878
879 int err;
880 if (argc > 0) {
881 char *pkg_name = NULL;
882
883 pkg_name = argv[0];
884
885 err = opkg_configure_packages (conf, pkg_name);
886
887 } else {
888 err = opkg_configure_packages (conf, NULL);
889 }
890
891 write_status_files_if_changed(conf);
892
893 return err;
894 }
895
896 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
897 {
898 int i, err;
899 char *globpattern;
900 glob_t globbuf;
901
902 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
903 err = glob(globpattern, 0, NULL, &globbuf);
904 free(globpattern);
905 if (err) {
906 return 0;
907 }
908
909 opkg_message(conf, OPKG_NOTICE,
910 "The following packages in %s will now be installed.\n",
911 conf->pending_dir);
912 for (i = 0; i < globbuf.gl_pathc; i++) {
913 opkg_message(conf, OPKG_NOTICE,
914 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
915 }
916 opkg_message(conf, OPKG_NOTICE, "\n");
917 for (i = 0; i < globbuf.gl_pathc; i++) {
918 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
919 if (err == 0) {
920 err = unlink(globbuf.gl_pathv[i]);
921 if (err) {
922 opkg_message(conf, OPKG_ERROR,
923 "%s: ERROR: failed to unlink %s: %s\n",
924 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
925 return err;
926 }
927 }
928 }
929 globfree(&globbuf);
930
931 return err;
932 }
933
934 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
935 {
936 int i,a,done;
937 pkg_t *pkg;
938 pkg_t *pkg_to_remove;
939 pkg_vec_t *available;
940 char *pkg_name = NULL;
941 global_conf = conf;
942 signal(SIGINT, sigint_handler);
943
944 // ENH: Add the "no pkg removed" just in case.
945
946 done = 0;
947
948 pkg_info_preinstall_check(conf);
949 if ( argc > 0 ) {
950 available = pkg_vec_alloc();
951 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
952 for (i=0; i < argc; i++) {
953 pkg_name = calloc(1, strlen(argv[i])+2);
954 strcpy(pkg_name,argv[i]);
955 for (a=0; a < available->len; a++) {
956 pkg = available->pkgs[a];
957 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
958 continue;
959 }
960 if (conf->restrict_to_default_dest) {
961 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
962 pkg->name,
963 conf->default_dest);
964 } else {
965 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
966 }
967
968 if (pkg == NULL) {
969 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
970 continue;
971 }
972 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
973 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
974 continue;
975 }
976 opkg_remove_pkg(conf, pkg_to_remove,0);
977 done = 1;
978 }
979 free (pkg_name);
980 }
981 pkg_vec_free(available);
982 } else {
983 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
984 int i;
985 int flagged_pkg_count = 0;
986 int removed;
987
988 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
989
990 for (i = 0; i < installed_pkgs->len; i++) {
991 pkg_t *pkg = installed_pkgs->pkgs[i];
992 if (pkg->state_flag & SF_USER) {
993 flagged_pkg_count++;
994 } else {
995 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
996 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
997 }
998 }
999 if (!flagged_pkg_count) {
1000 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1001 "so refusing to uninstall unflagged non-leaf packages\n");
1002 return 0;
1003 }
1004
1005 /* find packages not flagged SF_USER (i.e., installed to
1006 * satisfy a dependence) and not having any dependents, and
1007 * remove them */
1008 do {
1009 removed = 0;
1010 for (i = 0; i < installed_pkgs->len; i++) {
1011 pkg_t *pkg = installed_pkgs->pkgs[i];
1012 if (!(pkg->state_flag & SF_USER)
1013 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1014 removed++;
1015 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1016 opkg_remove_pkg(conf, pkg,0);
1017 done = 1;
1018 }
1019 }
1020 } while (removed);
1021 pkg_vec_free(installed_pkgs);
1022 }
1023
1024 if ( done == 0 )
1025 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1026
1027 write_status_files_if_changed(conf);
1028 return 0;
1029 }
1030
1031 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1032 {
1033 int i;
1034 pkg_t *pkg;
1035
1036 global_conf = conf;
1037 signal(SIGINT, sigint_handler);
1038
1039 pkg_info_preinstall_check(conf);
1040
1041 for (i=0; i < argc; i++) {
1042 if (conf->restrict_to_default_dest) {
1043 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1044 argv[i],
1045 conf->default_dest);
1046 } else {
1047 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1048 }
1049
1050 if (pkg == NULL) {
1051 opkg_message(conf, OPKG_ERROR,
1052 "Package %s is not installed.\n", argv[i]);
1053 continue;
1054 }
1055 opkg_purge_pkg(conf, pkg);
1056 }
1057
1058 write_status_files_if_changed(conf);
1059 return 0;
1060 }
1061
1062 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1063 {
1064 int i;
1065 pkg_t *pkg;
1066 const char *flags = argv[0];
1067
1068 global_conf = conf;
1069 signal(SIGINT, sigint_handler);
1070
1071 for (i=1; i < argc; i++) {
1072 if (conf->restrict_to_default_dest) {
1073 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1074 argv[i],
1075 conf->default_dest);
1076 } else {
1077 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1078 }
1079
1080 if (pkg == NULL) {
1081 opkg_message(conf, OPKG_ERROR,
1082 "Package %s is not installed.\n", argv[i]);
1083 continue;
1084 }
1085 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1086 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1087 pkg->state_flag = pkg_state_flag_from_str(flags);
1088 }
1089 /* pb_ asked this feature 03292004 */
1090 /* Actually I will use only this two, but this is an open for various status */
1091 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1092 pkg->state_status = pkg_state_status_from_str(flags);
1093 }
1094 opkg_state_changed++;
1095 opkg_message(conf, OPKG_NOTICE,
1096 "Setting flags for package %s to %s\n",
1097 pkg->name, flags);
1098 }
1099
1100 write_status_files_if_changed(conf);
1101 return 0;
1102 }
1103
1104 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1105 {
1106 pkg_t *pkg;
1107 str_list_t *installed_files;
1108 str_list_elt_t *iter;
1109 char *pkg_version;
1110 size_t buff_len = 8192;
1111 size_t used_len;
1112 char *buff ;
1113
1114 buff = (char *)calloc(1, buff_len);
1115 if ( buff == NULL ) {
1116 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1117 return ENOMEM;
1118 }
1119
1120 if (argc < 1) {
1121 return EINVAL;
1122 }
1123
1124 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1125 argv[0]);
1126 if (pkg == NULL) {
1127 opkg_message(conf, OPKG_ERROR,
1128 "Package %s not installed.\n", argv[0]);
1129 return 0;
1130 }
1131
1132 installed_files = pkg_get_installed_files(pkg);
1133 pkg_version = pkg_version_str_alloc(pkg);
1134
1135 if (buff) {
1136 try_again:
1137 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1138 pkg->name, pkg_version, pkg->dest->name) + 1;
1139 if (used_len > buff_len) {
1140 buff_len *= 2;
1141 buff = realloc (buff, buff_len);
1142 goto try_again;
1143 }
1144 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1145 used_len += strlen (iter->data) + 1;
1146 while (buff_len <= used_len) {
1147 buff_len *= 2;
1148 buff = realloc (buff, buff_len);
1149 }
1150 strncat(buff, iter->data, buff_len);
1151 strncat(buff, "\n", buff_len);
1152 }
1153 if (opkg_cb_list) opkg_cb_list(pkg->name,
1154 buff,
1155 pkg_version_str_alloc(pkg),
1156 pkg->state_status,
1157 p_userdata);
1158 free(buff);
1159 }
1160
1161 free(pkg_version);
1162 pkg_free_installed_files(pkg);
1163
1164 return 0;
1165 }
1166
1167 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1168 {
1169
1170 if (argc > 0) {
1171 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1172 const char *rel_str = "depends on";
1173 int i;
1174
1175 pkg_info_preinstall_check(conf);
1176
1177 if (conf->query_all)
1178 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1179 else
1180 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1181 for (i = 0; i < argc; i++) {
1182 const char *target = argv[i];
1183 int j;
1184
1185 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1186
1187 for (j = 0; j < available_pkgs->len; j++) {
1188 pkg_t *pkg = available_pkgs->pkgs[j];
1189 if (fnmatch(target, pkg->name, 0) == 0) {
1190 int k;
1191 int count = pkg->depends_count + pkg->pre_depends_count;
1192 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1193 target, pkg->architecture, rel_str);
1194 for (k = 0; k < count; k++) {
1195 compound_depend_t *cdepend = &pkg->depends[k];
1196 int l;
1197 for (l = 0; l < cdepend->possibility_count; l++) {
1198 depend_t *possibility = cdepend->possibilities[l];
1199 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1200 if (conf->verbosity > 0) {
1201 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1202 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1203 if (possibility->version) {
1204 char *typestr = NULL;
1205 switch (possibility->constraint) {
1206 case NONE: typestr = "none"; break;
1207 case EARLIER: typestr = "<"; break;
1208 case EARLIER_EQUAL: typestr = "<="; break;
1209 case EQUAL: typestr = "="; break;
1210 case LATER_EQUAL: typestr = ">="; break;
1211 case LATER: typestr = ">"; break;
1212 }
1213 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1214 }
1215 // free(ver);
1216 }
1217 opkg_message(conf, OPKG_ERROR, "\n");
1218 }
1219 }
1220 }
1221 }
1222 }
1223 pkg_vec_free(available_pkgs);
1224 }
1225 return 0;
1226 }
1227
1228 enum what_field_type {
1229 WHATDEPENDS,
1230 WHATCONFLICTS,
1231 WHATPROVIDES,
1232 WHATREPLACES,
1233 WHATRECOMMENDS,
1234 WHATSUGGESTS
1235 };
1236
1237 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1238 {
1239
1240 if (argc > 0) {
1241 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1242 const char *rel_str = NULL;
1243 int i;
1244 int changed;
1245
1246 switch (what_field_type) {
1247 case WHATDEPENDS: rel_str = "depends on"; break;
1248 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1249 case WHATSUGGESTS: rel_str = "suggests"; break;
1250 case WHATRECOMMENDS: rel_str = "recommends"; break;
1251 case WHATPROVIDES: rel_str = "provides"; break;
1252 case WHATREPLACES: rel_str = "replaces"; break;
1253 }
1254
1255 if (conf->query_all)
1256 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1257 else
1258 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1259
1260 /* mark the root set */
1261 pkg_vec_clear_marks(available_pkgs);
1262 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1263 for (i = 0; i < argc; i++) {
1264 const char *dependee_pattern = argv[i];
1265 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1266 }
1267 for (i = 0; i < available_pkgs->len; i++) {
1268 pkg_t *pkg = available_pkgs->pkgs[i];
1269 if (pkg->state_flag & SF_MARKED) {
1270 /* mark the parent (abstract) package */
1271 pkg_mark_provides(pkg);
1272 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1273 }
1274 }
1275
1276 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1277 do {
1278 int j;
1279 changed = 0;
1280
1281 for (j = 0; j < available_pkgs->len; j++) {
1282 pkg_t *pkg = available_pkgs->pkgs[j];
1283 int k;
1284 int count = ((what_field_type == WHATCONFLICTS)
1285 ? pkg->conflicts_count
1286 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1287 /* skip this package if it is already marked */
1288 if (pkg->parent->state_flag & SF_MARKED) {
1289 continue;
1290 }
1291 for (k = 0; k < count; k++) {
1292 compound_depend_t *cdepend =
1293 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1294 int l;
1295 for (l = 0; l < cdepend->possibility_count; l++) {
1296 depend_t *possibility = cdepend->possibilities[l];
1297 if (possibility->pkg->state_flag & SF_MARKED) {
1298 /* mark the depending package so we won't visit it again */
1299 pkg->state_flag |= SF_MARKED;
1300 pkg_mark_provides(pkg);
1301 changed++;
1302
1303 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1304 if (conf->verbosity > 0) {
1305 char *ver = pkg_version_str_alloc(pkg);
1306 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1307 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1308 if (possibility->version) {
1309 char *typestr = NULL;
1310 switch (possibility->constraint) {
1311 case NONE: typestr = "none"; break;
1312 case EARLIER: typestr = "<"; break;
1313 case EARLIER_EQUAL: typestr = "<="; break;
1314 case EQUAL: typestr = "="; break;
1315 case LATER_EQUAL: typestr = ">="; break;
1316 case LATER: typestr = ">"; break;
1317 }
1318 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1319 }
1320 free(ver);
1321 if (!pkg_dependence_satisfiable(conf, possibility))
1322 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1323 }
1324 opkg_message(conf, OPKG_NOTICE, "\n");
1325 goto next_package;
1326 }
1327 }
1328 }
1329 next_package:
1330 ;
1331 }
1332 } while (changed && recursive);
1333 pkg_vec_free(available_pkgs);
1334 }
1335
1336 return 0;
1337 }
1338
1339 static int pkg_mark_provides(pkg_t *pkg)
1340 {
1341 int provides_count = pkg->provides_count;
1342 abstract_pkg_t **provides = pkg->provides;
1343 int i;
1344 pkg->parent->state_flag |= SF_MARKED;
1345 for (i = 0; i < provides_count; i++) {
1346 provides[i]->state_flag |= SF_MARKED;
1347 }
1348 return 0;
1349 }
1350
1351 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1352 {
1353 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1354 }
1355 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1356 {
1357 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1358 }
1359
1360 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1361 {
1362 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1363 }
1364
1365 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1366 {
1367 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1368 }
1369
1370 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1371 {
1372 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1373 }
1374
1375 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1376 {
1377
1378 if (argc > 0) {
1379 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1380 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1381 int i;
1382
1383 pkg_info_preinstall_check(conf);
1384
1385 if (conf->query_all)
1386 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1387 else
1388 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1389 for (i = 0; i < argc; i++) {
1390 const char *target = argv[i];
1391 int j;
1392
1393 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1394 rel_str, target);
1395 for (j = 0; j < available_pkgs->len; j++) {
1396 pkg_t *pkg = available_pkgs->pkgs[j];
1397 int k;
1398 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1399 for (k = 0; k < count; k++) {
1400 abstract_pkg_t *apkg =
1401 ((what_field_type == WHATPROVIDES)
1402 ? pkg->provides[k]
1403 : pkg->replaces[k]);
1404 if (fnmatch(target, apkg->name, 0) == 0) {
1405 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1406 if (strcmp(target, apkg->name) != 0)
1407 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1408 opkg_message(conf, OPKG_ERROR, "\n");
1409 }
1410 }
1411 }
1412 }
1413 pkg_vec_free(available_pkgs);
1414 }
1415 return 0;
1416 }
1417
1418 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1419 {
1420 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1421 }
1422
1423 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1424 {
1425 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1426 }
1427
1428 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1429 {
1430 int i;
1431
1432 pkg_vec_t *installed;
1433 pkg_t *pkg;
1434 str_list_t *installed_files;
1435 str_list_elt_t *iter;
1436 char *installed_file;
1437
1438 if (argc < 1) {
1439 return EINVAL;
1440 }
1441
1442 installed = pkg_vec_alloc();
1443 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1444 pkg_vec_sort(installed, pkg_compare_names);
1445
1446 for (i=0; i < installed->len; i++) {
1447 pkg = installed->pkgs[i];
1448
1449 installed_files = pkg_get_installed_files(pkg);
1450
1451 for (iter = str_list_first(installed_files); iter; iter = str_list_next(installed_files, iter)) {
1452 installed_file = (char *)iter->data;
1453 if (fnmatch(argv[0], installed_file, 0)==0) {
1454 if (opkg_cb_list) opkg_cb_list(pkg->name,
1455 installed_file,
1456 pkg_version_str_alloc(pkg),
1457 pkg->state_status, p_userdata);
1458 }
1459 }
1460
1461 pkg_free_installed_files(pkg);
1462 }
1463
1464 pkg_vec_free(installed);
1465
1466 return 0;
1467 }
1468
1469 static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
1470 {
1471 if (argc == 3) {
1472 /* this is a bit gross */
1473 struct pkg p1, p2;
1474 parseVersion(&p1, argv[0]);
1475 parseVersion(&p2, argv[2]);
1476 return pkg_version_satisfied(&p1, &p2, argv[1]);
1477 } else {
1478 opkg_message(conf, OPKG_ERROR,
1479 "opkg compare_versions <v1> <op> <v2>\n"
1480 "<op> is one of <= >= << >> =\n");
1481 return -1;
1482 }
1483 }
1484
1485 #ifndef HOST_CPU_STR
1486 #define HOST_CPU_STR__(X) #X
1487 #define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
1488 #define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
1489 #endif
1490
1491 static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
1492 {
1493 nv_pair_list_elt_t *l;
1494
1495 list_for_each_entry(l, &conf->arch_list.head, node) {
1496 nv_pair_t *nv = (nv_pair_t *)l->data;
1497 printf("arch %s %s\n", nv->name, nv->value);
1498 }
1499 return 0;
1500 }
1501
1502