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