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