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