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