only add pkg_vec_sort when needed
[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 pkg_vec_sort(available, pkg_compare_names);
715 for (i=0; i < available->len; i++) {
716 pkg = available->pkgs[i];
717 /* if we have package name or pattern and pkg does not match, then skip it */
718 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
719 continue;
720 if (pkg->description) {
721 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
722 } else {
723 desc_short[0] = '\0';
724 }
725 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
726 newline = strchr(desc_short, '\n');
727 if (newline) {
728 *newline = '\0';
729 }
730 if (opkg_cb_list) {
731 version_str = pkg_version_str_alloc(pkg);
732 opkg_cb_list(pkg->name,desc_short,
733 version_str,
734 pkg->state_status,
735 p_userdata);
736 free(version_str);
737 }
738 }
739 pkg_vec_free(available);
740
741 return 0;
742 }
743
744
745 static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
746 {
747 int i ;
748 pkg_vec_t *available;
749 pkg_t *pkg;
750 char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
751 char *newline;
752 char *pkg_name = NULL;
753 char *version_str;
754
755 if (argc > 0) {
756 pkg_name = argv[0];
757 }
758 available = pkg_vec_alloc();
759 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
760 pkg_vec_sort(available, pkg_compare_names);
761 for (i=0; i < available->len; i++) {
762 pkg = available->pkgs[i];
763 /* if we have package name or pattern and pkg does not match, then skip it */
764 if (pkg_name && fnmatch(pkg_name, pkg->name, 0))
765 continue;
766 if (pkg->description) {
767 strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
768 } else {
769 desc_short[0] = '\0';
770 }
771 desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
772 newline = strchr(desc_short, '\n');
773 if (newline) {
774 *newline = '\0';
775 }
776 if (opkg_cb_list) {
777 version_str = pkg_version_str_alloc(pkg);
778 opkg_cb_list(pkg->name,desc_short,
779 version_str,
780 pkg->state_status,
781 p_userdata);
782 free(version_str);
783 }
784 }
785
786 return 0;
787 }
788
789 static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv)
790 {
791 struct active_list *head = prepare_upgrade_list(conf);
792 struct active_list *node=NULL;
793 pkg_t *_old_pkg, *_new_pkg;
794 char *old_v, *new_v;
795 for (node = active_list_next(head, head); node;node = active_list_next(head,node)) {
796 _old_pkg = list_entry(node, pkg_t, list);
797 _new_pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, _old_pkg->name, NULL);
798 old_v = pkg_version_str_alloc(_old_pkg);
799 new_v = pkg_version_str_alloc(_new_pkg);
800 if (opkg_cb_list)
801 opkg_cb_list(_old_pkg->name, new_v, old_v, _old_pkg->state_status, p_userdata);
802 free(old_v);
803 free(new_v);
804 }
805 active_list_head_delete(head);
806 return 0;
807 }
808
809 static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
810 {
811 int i;
812 pkg_vec_t *available;
813 pkg_t *pkg;
814 char *pkg_name = NULL;
815 char **pkg_fields = NULL;
816 int n_fields = 0;
817 char *buff ;
818
819 if (argc > 0) {
820 pkg_name = argv[0];
821 }
822 if (argc > 1) {
823 pkg_fields = &argv[1];
824 n_fields = argc - 1;
825 }
826
827 available = pkg_vec_alloc();
828 if (installed_only)
829 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
830 else
831 pkg_hash_fetch_available(&conf->pkg_hash, available);
832 for (i=0; i < available->len; i++) {
833 pkg = available->pkgs[i];
834 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
835 continue;
836 }
837
838 buff = pkg_formatted_info(pkg);
839 if ( buff ) {
840 if (opkg_cb_status) opkg_cb_status(pkg->name,
841 pkg->state_status,
842 buff,
843 p_userdata);
844 /*
845 We should not forget that actually the pointer is allocated.
846 We need to free it :) ( Thanks florian for seeing the error )
847 */
848 free(buff);
849 }
850 if (conf->verbosity > 1) {
851 conffile_list_elt_t *iter;
852 for (iter = pkg->conffiles.head; iter; iter = iter->next) {
853 conffile_t *cf = iter->data;
854 int modified = conffile_has_been_modified(conf, cf);
855 opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
856 cf->name, cf->value, modified);
857 }
858 }
859 }
860 pkg_vec_free(available);
861
862 return 0;
863 }
864
865 static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
866 {
867 return opkg_info_status_cmd(conf, argc, argv, 0);
868 }
869
870 static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
871 {
872 return opkg_info_status_cmd(conf, argc, argv, 1);
873 }
874
875 static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
876 {
877
878 int err;
879 if (argc > 0) {
880 char *pkg_name = NULL;
881
882 pkg_name = argv[0];
883
884 err = opkg_configure_packages (conf, pkg_name);
885
886 } else {
887 err = opkg_configure_packages (conf, NULL);
888 }
889
890 write_status_files_if_changed(conf);
891
892 return err;
893 }
894
895 static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
896 {
897 int i, err;
898 char *globpattern;
899 glob_t globbuf;
900
901 sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
902 err = glob(globpattern, 0, NULL, &globbuf);
903 free(globpattern);
904 if (err) {
905 return 0;
906 }
907
908 opkg_message(conf, OPKG_NOTICE,
909 "The following packages in %s will now be installed.\n",
910 conf->pending_dir);
911 for (i = 0; i < globbuf.gl_pathc; i++) {
912 opkg_message(conf, OPKG_NOTICE,
913 "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
914 }
915 opkg_message(conf, OPKG_NOTICE, "\n");
916 for (i = 0; i < globbuf.gl_pathc; i++) {
917 err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
918 if (err == 0) {
919 err = unlink(globbuf.gl_pathv[i]);
920 if (err) {
921 opkg_message(conf, OPKG_ERROR,
922 "%s: ERROR: failed to unlink %s: %s\n",
923 __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
924 return err;
925 }
926 }
927 }
928 globfree(&globbuf);
929
930 return err;
931 }
932
933 static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
934 {
935 int i,a,done;
936 pkg_t *pkg;
937 pkg_t *pkg_to_remove;
938 pkg_vec_t *available;
939 char *pkg_name = NULL;
940 global_conf = conf;
941 signal(SIGINT, sigint_handler);
942
943 // ENH: Add the "no pkg removed" just in case.
944
945 done = 0;
946
947 pkg_info_preinstall_check(conf);
948 if ( argc > 0 ) {
949 available = pkg_vec_alloc();
950 pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
951 for (i=0; i < argc; i++) {
952 pkg_name = calloc(1, strlen(argv[i])+2);
953 strcpy(pkg_name,argv[i]);
954 for (a=0; a < available->len; a++) {
955 pkg = available->pkgs[a];
956 if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
957 continue;
958 }
959 if (conf->restrict_to_default_dest) {
960 pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
961 pkg->name,
962 conf->default_dest);
963 } else {
964 pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
965 }
966
967 if (pkg == NULL) {
968 opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
969 continue;
970 }
971 if (pkg->state_status == SS_NOT_INSTALLED) { // Added the control, so every already removed package could be skipped
972 opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
973 continue;
974 }
975 opkg_remove_pkg(conf, pkg_to_remove,0);
976 done = 1;
977 }
978 free (pkg_name);
979 }
980 pkg_vec_free(available);
981 } else {
982 pkg_vec_t *installed_pkgs = pkg_vec_alloc();
983 int i;
984 int flagged_pkg_count = 0;
985 int removed;
986
987 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
988
989 for (i = 0; i < installed_pkgs->len; i++) {
990 pkg_t *pkg = installed_pkgs->pkgs[i];
991 if (pkg->state_flag & SF_USER) {
992 flagged_pkg_count++;
993 } else {
994 if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
995 opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
996 }
997 }
998 if (!flagged_pkg_count) {
999 opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
1000 "so refusing to uninstall unflagged non-leaf packages\n");
1001 return 0;
1002 }
1003
1004 /* find packages not flagged SF_USER (i.e., installed to
1005 * satisfy a dependence) and not having any dependents, and
1006 * remove them */
1007 do {
1008 removed = 0;
1009 for (i = 0; i < installed_pkgs->len; i++) {
1010 pkg_t *pkg = installed_pkgs->pkgs[i];
1011 if (!(pkg->state_flag & SF_USER)
1012 && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
1013 removed++;
1014 opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
1015 opkg_remove_pkg(conf, pkg,0);
1016 done = 1;
1017 }
1018 }
1019 } while (removed);
1020 pkg_vec_free(installed_pkgs);
1021 }
1022
1023 if ( done == 0 )
1024 opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
1025
1026 write_status_files_if_changed(conf);
1027 return 0;
1028 }
1029
1030 static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
1031 {
1032 int i;
1033 pkg_t *pkg;
1034
1035 global_conf = conf;
1036 signal(SIGINT, sigint_handler);
1037
1038 pkg_info_preinstall_check(conf);
1039
1040 for (i=0; i < argc; i++) {
1041 if (conf->restrict_to_default_dest) {
1042 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1043 argv[i],
1044 conf->default_dest);
1045 } else {
1046 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1047 }
1048
1049 if (pkg == NULL) {
1050 opkg_message(conf, OPKG_ERROR,
1051 "Package %s is not installed.\n", argv[i]);
1052 continue;
1053 }
1054 opkg_purge_pkg(conf, pkg);
1055 }
1056
1057 write_status_files_if_changed(conf);
1058 return 0;
1059 }
1060
1061 static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
1062 {
1063 int i;
1064 pkg_t *pkg;
1065 const char *flags = argv[0];
1066
1067 global_conf = conf;
1068 signal(SIGINT, sigint_handler);
1069
1070 for (i=1; i < argc; i++) {
1071 if (conf->restrict_to_default_dest) {
1072 pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
1073 argv[i],
1074 conf->default_dest);
1075 } else {
1076 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
1077 }
1078
1079 if (pkg == NULL) {
1080 opkg_message(conf, OPKG_ERROR,
1081 "Package %s is not installed.\n", argv[i]);
1082 continue;
1083 }
1084 if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
1085 ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
1086 pkg->state_flag = pkg_state_flag_from_str(flags);
1087 }
1088 /* pb_ asked this feature 03292004 */
1089 /* Actually I will use only this two, but this is an open for various status */
1090 if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
1091 pkg->state_status = pkg_state_status_from_str(flags);
1092 }
1093 opkg_state_changed++;
1094 opkg_message(conf, OPKG_NOTICE,
1095 "Setting flags for package %s to %s\n",
1096 pkg->name, flags);
1097 }
1098
1099 write_status_files_if_changed(conf);
1100 return 0;
1101 }
1102
1103 static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
1104 {
1105 pkg_t *pkg;
1106 str_list_t *installed_files;
1107 str_list_elt_t *iter;
1108 char *pkg_version;
1109 size_t buff_len = 8192;
1110 size_t used_len;
1111 char *buff ;
1112
1113 buff = (char *)calloc(1, buff_len);
1114 if ( buff == NULL ) {
1115 fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
1116 return ENOMEM;
1117 }
1118
1119 if (argc < 1) {
1120 return EINVAL;
1121 }
1122
1123 pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
1124 argv[0]);
1125 if (pkg == NULL) {
1126 opkg_message(conf, OPKG_ERROR,
1127 "Package %s not installed.\n", argv[0]);
1128 return 0;
1129 }
1130
1131 installed_files = pkg_get_installed_files(pkg);
1132 pkg_version = pkg_version_str_alloc(pkg);
1133
1134 if (buff) {
1135 try_again:
1136 used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
1137 pkg->name, pkg_version, pkg->dest->name) + 1;
1138 if (used_len > buff_len) {
1139 buff_len *= 2;
1140 buff = realloc (buff, buff_len);
1141 goto try_again;
1142 }
1143 for (iter = installed_files->head; iter; iter = iter->next) {
1144 used_len += strlen (iter->data) + 1;
1145 while (buff_len <= used_len) {
1146 buff_len *= 2;
1147 buff = realloc (buff, buff_len);
1148 }
1149 strncat(buff, iter->data, buff_len);
1150 strncat(buff, "\n", buff_len);
1151 }
1152 if (opkg_cb_list) opkg_cb_list(pkg->name,
1153 buff,
1154 pkg_version_str_alloc(pkg),
1155 pkg->state_status,
1156 p_userdata);
1157 free(buff);
1158 }
1159
1160 free(pkg_version);
1161 pkg_free_installed_files(pkg);
1162
1163 return 0;
1164 }
1165
1166 static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
1167 {
1168
1169 if (argc > 0) {
1170 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1171 const char *rel_str = "depends on";
1172 int i;
1173
1174 pkg_info_preinstall_check(conf);
1175
1176 if (conf->query_all)
1177 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1178 else
1179 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1180 for (i = 0; i < argc; i++) {
1181 const char *target = argv[i];
1182 int j;
1183
1184 opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
1185
1186 for (j = 0; j < available_pkgs->len; j++) {
1187 pkg_t *pkg = available_pkgs->pkgs[j];
1188 if (fnmatch(target, pkg->name, 0) == 0) {
1189 int k;
1190 int count = pkg->depends_count + pkg->pre_depends_count;
1191 opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
1192 target, pkg->architecture, rel_str);
1193 for (k = 0; k < count; k++) {
1194 compound_depend_t *cdepend = &pkg->depends[k];
1195 int l;
1196 for (l = 0; l < cdepend->possibility_count; l++) {
1197 depend_t *possibility = cdepend->possibilities[l];
1198 opkg_message(conf, OPKG_ERROR, " %s", possibility->pkg->name);
1199 if (conf->verbosity > 0) {
1200 // char *ver = abstract_pkg_version_str_alloc(possibility->pkg);
1201 opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
1202 if (possibility->version) {
1203 char *typestr = NULL;
1204 switch (possibility->constraint) {
1205 case NONE: typestr = "none"; break;
1206 case EARLIER: typestr = "<"; break;
1207 case EARLIER_EQUAL: typestr = "<="; break;
1208 case EQUAL: typestr = "="; break;
1209 case LATER_EQUAL: typestr = ">="; break;
1210 case LATER: typestr = ">"; break;
1211 }
1212 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1213 }
1214 // free(ver);
1215 }
1216 opkg_message(conf, OPKG_ERROR, "\n");
1217 }
1218 }
1219 }
1220 }
1221 }
1222 pkg_vec_free(available_pkgs);
1223 }
1224 return 0;
1225 }
1226
1227 enum what_field_type {
1228 WHATDEPENDS,
1229 WHATCONFLICTS,
1230 WHATPROVIDES,
1231 WHATREPLACES,
1232 WHATRECOMMENDS,
1233 WHATSUGGESTS
1234 };
1235
1236 static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
1237 {
1238
1239 if (argc > 0) {
1240 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1241 const char *rel_str = NULL;
1242 int i;
1243 int changed;
1244
1245 switch (what_field_type) {
1246 case WHATDEPENDS: rel_str = "depends on"; break;
1247 case WHATCONFLICTS: rel_str = "conflicts with"; break;
1248 case WHATSUGGESTS: rel_str = "suggests"; break;
1249 case WHATRECOMMENDS: rel_str = "recommends"; break;
1250 case WHATPROVIDES: rel_str = "provides"; break;
1251 case WHATREPLACES: rel_str = "replaces"; break;
1252 }
1253
1254 if (conf->query_all)
1255 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1256 else
1257 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1258
1259 /* mark the root set */
1260 pkg_vec_clear_marks(available_pkgs);
1261 opkg_message(conf, OPKG_NOTICE, "Root set:\n");
1262 for (i = 0; i < argc; i++) {
1263 const char *dependee_pattern = argv[i];
1264 pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
1265 }
1266 for (i = 0; i < available_pkgs->len; i++) {
1267 pkg_t *pkg = available_pkgs->pkgs[i];
1268 if (pkg->state_flag & SF_MARKED) {
1269 /* mark the parent (abstract) package */
1270 pkg_mark_provides(pkg);
1271 opkg_message(conf, OPKG_NOTICE, " %s\n", pkg->name);
1272 }
1273 }
1274
1275 opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
1276 do {
1277 int j;
1278 changed = 0;
1279
1280 for (j = 0; j < available_pkgs->len; j++) {
1281 pkg_t *pkg = available_pkgs->pkgs[j];
1282 int k;
1283 int count = ((what_field_type == WHATCONFLICTS)
1284 ? pkg->conflicts_count
1285 : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
1286 /* skip this package if it is already marked */
1287 if (pkg->parent->state_flag & SF_MARKED) {
1288 continue;
1289 }
1290 for (k = 0; k < count; k++) {
1291 compound_depend_t *cdepend =
1292 (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
1293 int l;
1294 for (l = 0; l < cdepend->possibility_count; l++) {
1295 depend_t *possibility = cdepend->possibilities[l];
1296 if (possibility->pkg->state_flag & SF_MARKED) {
1297 /* mark the depending package so we won't visit it again */
1298 pkg->state_flag |= SF_MARKED;
1299 pkg_mark_provides(pkg);
1300 changed++;
1301
1302 opkg_message(conf, OPKG_NOTICE, " %s", pkg->name);
1303 if (conf->verbosity > 0) {
1304 char *ver = pkg_version_str_alloc(pkg);
1305 opkg_message(conf, OPKG_NOTICE, " %s", ver);
1306 opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
1307 if (possibility->version) {
1308 char *typestr = NULL;
1309 switch (possibility->constraint) {
1310 case NONE: typestr = "none"; break;
1311 case EARLIER: typestr = "<"; break;
1312 case EARLIER_EQUAL: typestr = "<="; break;
1313 case EQUAL: typestr = "="; break;
1314 case LATER_EQUAL: typestr = ">="; break;
1315 case LATER: typestr = ">"; break;
1316 }
1317 opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
1318 }
1319 free(ver);
1320 if (!pkg_dependence_satisfiable(conf, possibility))
1321 opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
1322 }
1323 opkg_message(conf, OPKG_NOTICE, "\n");
1324 goto next_package;
1325 }
1326 }
1327 }
1328 next_package:
1329 ;
1330 }
1331 } while (changed && recursive);
1332 pkg_vec_free(available_pkgs);
1333 }
1334
1335 return 0;
1336 }
1337
1338 static int pkg_mark_provides(pkg_t *pkg)
1339 {
1340 int provides_count = pkg->provides_count;
1341 abstract_pkg_t **provides = pkg->provides;
1342 int i;
1343 pkg->parent->state_flag |= SF_MARKED;
1344 for (i = 0; i < provides_count; i++) {
1345 provides[i]->state_flag |= SF_MARKED;
1346 }
1347 return 0;
1348 }
1349
1350 static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
1351 {
1352 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
1353 }
1354 static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
1355 {
1356 return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
1357 }
1358
1359 static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
1360 {
1361 return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
1362 }
1363
1364 static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
1365 {
1366 return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
1367 }
1368
1369 static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
1370 {
1371 return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
1372 }
1373
1374 static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
1375 {
1376
1377 if (argc > 0) {
1378 pkg_vec_t *available_pkgs = pkg_vec_alloc();
1379 const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
1380 int i;
1381
1382 pkg_info_preinstall_check(conf);
1383
1384 if (conf->query_all)
1385 pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
1386 else
1387 pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
1388 for (i = 0; i < argc; i++) {
1389 const char *target = argv[i];
1390 int j;
1391
1392 opkg_message(conf, OPKG_ERROR, "What %s %s\n",
1393 rel_str, target);
1394 for (j = 0; j < available_pkgs->len; j++) {
1395 pkg_t *pkg = available_pkgs->pkgs[j];
1396 int k;
1397 int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
1398 for (k = 0; k < count; k++) {
1399 abstract_pkg_t *apkg =
1400 ((what_field_type == WHATPROVIDES)
1401 ? pkg->provides[k]
1402 : pkg->replaces[k]);
1403 if (fnmatch(target, apkg->name, 0) == 0) {
1404 opkg_message(conf, OPKG_ERROR, " %s", pkg->name);
1405 if (strcmp(target, apkg->name) != 0)
1406 opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
1407 opkg_message(conf, OPKG_ERROR, "\n");
1408 }
1409 }
1410 }
1411 }
1412 pkg_vec_free(available_pkgs);
1413 }
1414 return 0;
1415 }
1416
1417 static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
1418 {
1419 return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
1420 }
1421
1422 static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
1423 {
1424 return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
1425 }
1426
1427 static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
1428 {
1429 int i;
1430
1431 pkg_vec_t *installed;
1432 pkg_t *pkg;
1433 str_list_t *installed_files;
1434 str_list_elt_t *iter;
1435 char *installed_file;
1436
1437 if (argc < 1) {
1438 return EINVAL;
1439 }
1440
1441 installed = pkg_vec_alloc();
1442 pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
1443 pkg_vec_sort(installed, pkg_compare_names);
1444
1445 for (i=0; i < installed->len; i++) {
1446 pkg = installed->pkgs[i];
1447
1448 installed_files = pkg_get_installed_files(pkg);
1449
1450 for (iter = installed_files->head; iter; iter = iter->next) {
1451 installed_file = iter->data;
1452 if (fnmatch(argv[0], installed_file, 0)==0) {
1453 if (opkg_cb_list) opkg_cb_list(pkg->name,
1454 installed_file,
1455 pkg_version_str_alloc(pkg),
1456 pkg->state_status, p_userdata);
1457 }
1458 }
1459
1460 pkg_free_installed_files(pkg);
1461 }
1462
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