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