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