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