src/main.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Aug 23 11:13:48 2014 +0100 (2014-08-23)
changeset 440 48204dea0b9f
parent 425 0c8bdd8dc942
child 442 c4bcba8023a9
permissions -rw-r--r--
Remove INTLLIBS from librazor_la_LIBADD.

This partially reverts 611c84a3f4b4538a65d186050608c17adbf17770.
It's not clear what motivated the initial inclusion of INTLLIBS
here since the net effect is only seen in librazor.la and not
in razor.pc and librazor.la is not normally packaged. Certainly
neither the static nor the dynamic versions of librazor currently
use libintl. At best this would cause the linker to search a
static libintl for undefined symbols without finding any; at worse
it causes a static build of plover using librazor.la to fail if
no static version of libintl is installed.
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009, 2011-2012  J. Ali Harlow <ali@juiblex.co.uk>
     5  *
     6  * This program is free software; you can redistribute it and/or modify
     7  * it under the terms of the GNU General Public License as published by
     8  * the Free Software Foundation; either version 2 of the License, or
     9  * (at your option) any later version.
    10  *
    11  * This program is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along
    17  * with this program; if not, write to the Free Software Foundation, Inc.,
    18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  */
    20 
    21 #define _GNU_SOURCE
    22 
    23 #include "config.h"
    24 
    25 #include <stdlib.h>
    26 #include <stddef.h>
    27 #include <stdio.h>
    28 #include <stdint.h>
    29 #include <string.h>
    30 #include <sys/stat.h>
    31 #include <unistd.h>
    32 #include <fcntl.h>
    33 #include <dirent.h>
    34 #include <limits.h>
    35 #ifdef HAVE_CURL
    36 #include <curl/curl.h>
    37 #endif
    38 #include <fnmatch.h>
    39 #include <errno.h>
    40 #include "razor.h"
    41 
    42 static const char system_repo_filename[] = "system.rzdb";
    43 static const char next_repo_filename[] = "system-next.rzdb";
    44 static const char rawhide_repo_filename[] = "rawhide.rzdb";
    45 static const char *install_root = "";
    46 static const char *repo_filename = system_repo_filename;
    47 static const char *yum_url;
    48 
    49 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    50 
    51 static int
    52 update_packages(struct razor_transaction *trans,
    53 		struct razor_install_iterator *ii, struct razor_set *system,
    54 		struct razor_set *next, struct razor_atomic *atomic,
    55 		struct razor_relocations *relocations,
    56 		enum razor_stage_type stage);
    57 static int
    58 update_system(struct razor_root *root, struct razor_relocations *relocations,
    59 	      struct razor_transaction *trans, struct razor_set *next,
    60 	      const char *verb);
    61 
    62 static struct razor_package_iterator *
    63 create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[])
    64 {
    65 	struct razor_package_query *query;
    66 	struct razor_package_iterator *iter;
    67 	struct razor_package *package;
    68 	const char *name, *pattern;
    69 	int i, count;
    70 
    71 	if (argc == 0)
    72 		return razor_package_iterator_create(set);
    73 
    74 	query = razor_package_query_create(set);
    75 
    76 	for (i = 0; i < argc; i++) {
    77 		iter = razor_package_iterator_create(set);
    78 		pattern = argv[i];
    79 		count = 0;
    80 		while (razor_package_iterator_next(iter, &package,
    81 						   RAZOR_DETAIL_NAME, &name,
    82 						   RAZOR_DETAIL_LAST)) {
    83 			if (fnmatch(pattern, name, 0) != 0)
    84 				continue;
    85 
    86 			razor_package_query_add_package(query, package);
    87 			count++;
    88 		}
    89 		razor_package_iterator_destroy(iter);
    90 
    91 		if (count == 0)
    92 			fprintf(stderr,
    93 				"no package matches \"%s\"\n", pattern);
    94 	}
    95 
    96 	return razor_package_query_finish(query);
    97 }
    98 
    99 #define LIST_PACKAGES_ONLY_NAMES 0x01
   100 
   101 static void
   102 list_packages(struct razor_package_iterator *iter, uint32_t flags)
   103 {
   104 	struct razor_package *package;
   105 	const char *name, *version, *arch;
   106 
   107 	while (razor_package_iterator_next(iter, &package,
   108 					   RAZOR_DETAIL_NAME, &name,
   109 					   RAZOR_DETAIL_VERSION, &version,
   110 					   RAZOR_DETAIL_ARCH, &arch,
   111 					   RAZOR_DETAIL_LAST)) {
   112 		if (flags & LIST_PACKAGES_ONLY_NAMES)
   113 			printf("%s\n", name);
   114 		else
   115 			printf("%s-%s.%s\n", name, version, arch);
   116 	}
   117 }
   118 
   119 static int
   120 command_list(int argc, const char *argv[])
   121 {
   122 	struct razor_package_iterator *pi;
   123 	struct razor_error *error = NULL;
   124 	struct razor_set *set;
   125 	uint32_t flags = 0;
   126 	int i = 0;
   127 
   128 	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   129 		flags |= LIST_PACKAGES_ONLY_NAMES;
   130 		i++;
   131 	}
   132 
   133 	set = razor_root_open_read_only(install_root, &error);
   134 	if (set == NULL) {
   135 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   136 		razor_error_free(error);
   137 		return 1;
   138 	}
   139 
   140 	pi = create_iterator_from_argv(set, argc - i, argv + i);
   141 	list_packages(pi, flags);
   142 	razor_package_iterator_destroy(pi);
   143 	razor_set_unref(set);
   144 
   145 	return 0;
   146 }
   147 
   148 static void
   149 list_package_properties(struct razor_set *set,
   150 			struct razor_package *package, uint32_t type)
   151 {
   152 	struct razor_property_iterator *pi;
   153 	struct razor_property *property;
   154 	const char *name, *version;
   155 	uint32_t flags;
   156 
   157 	pi = razor_property_iterator_create(set, package);
   158 	while (razor_property_iterator_next(pi, &property,
   159 					    &name, &flags, &version)) {
   160 		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
   161 			continue;
   162 		printf("%s", name);
   163 		if (version[0] != '\0')
   164 			printf(" %s %s",
   165 			       razor_property_relation_to_string(property),
   166 			       version);
   167 
   168 		if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
   169 			printf(" [");
   170 			if (flags & RAZOR_PROPERTY_PRE)
   171 				printf(" pre");
   172 			if (flags & RAZOR_PROPERTY_POST)
   173 				printf(" post");
   174 			if (flags & RAZOR_PROPERTY_PREUN)
   175 				printf(" preun");
   176 			if (flags & RAZOR_PROPERTY_POSTUN)
   177 				printf(" postun");
   178 			printf(" ]");
   179 		}
   180 		printf("\n");
   181 	}
   182 	razor_property_iterator_destroy(pi);
   183 }
   184 
   185 static int
   186 list_properties(int argc, const char *argv[], uint32_t type)
   187 {
   188 	struct razor_set *set;
   189 	struct razor_error *error = NULL;
   190 	struct razor_package *package;
   191 	struct razor_package_iterator *pi;
   192 	const char *name, *version, *arch;
   193 
   194 	set = razor_root_open_read_only(install_root, &error);
   195 	if (set == NULL) {
   196 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   197 		razor_error_free(error);
   198 		return 1;
   199 	}
   200 
   201 	pi = create_iterator_from_argv(set, argc, argv);
   202 	while (razor_package_iterator_next(pi, &package,
   203 					   RAZOR_DETAIL_NAME, &name,
   204 					   RAZOR_DETAIL_VERSION, &version,
   205 					   RAZOR_DETAIL_ARCH, &arch,
   206 					   RAZOR_DETAIL_LAST))
   207 		list_package_properties(set, package, type);
   208 	razor_package_iterator_destroy(pi);
   209 	razor_set_unref(set);
   210 
   211 	return 0;
   212 }
   213 
   214 static int
   215 command_list_requires(int argc, const char *argv[])
   216 {
   217 	return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES);
   218 }
   219 
   220 static int
   221 command_list_provides(int argc, const char *argv[])
   222 {
   223 	return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES);
   224 }
   225 
   226 static int
   227 command_list_obsoletes(int argc, const char *argv[])
   228 {
   229 	return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES);
   230 }
   231 
   232 static int
   233 command_list_conflicts(int argc, const char *argv[])
   234 {
   235 	return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS);
   236 }
   237 
   238 static int
   239 command_list_scripts(int argc, const char *argv[])
   240 {
   241 	struct razor_set *set;
   242 	struct razor_error *error = NULL;
   243 	struct razor_package *package;
   244 	struct razor_package_iterator *pi;
   245 	const char *preunprog, *preun, *postunprog, *postun;
   246 
   247 	set = razor_root_open_read_only(install_root, &error);
   248 	if (set == NULL) {
   249 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   250 		razor_error_free(error);
   251 		return 1;
   252 	}
   253 
   254 	pi = create_iterator_from_argv(set, argc, argv);
   255 	while (razor_package_iterator_next(pi, &package,
   256 					   RAZOR_DETAIL_PREUNPROG, &preunprog,
   257 					   RAZOR_DETAIL_PREUN, &preun,
   258 					   RAZOR_DETAIL_POSTUNPROG, &postunprog,
   259 					   RAZOR_DETAIL_POSTUN, &postun,
   260 					   RAZOR_DETAIL_LAST)) {
   261 		if (preun && *preun) {
   262 			printf("preuninstall scriptlet");
   263 			if (preunprog && *preunprog)
   264 				printf(" (using %s)",preunprog);
   265 			printf(":\n%s\n",preun);
   266 		}
   267 		if (postun && *postun) {
   268 			printf("postuninstall scriptlet");
   269 			if (postunprog && *postunprog)
   270 				printf(" (using %s)",postunprog);
   271 			printf(":\n%s\n",postun);
   272 		}
   273 	}
   274 	razor_package_iterator_destroy(pi);
   275 	razor_set_unref(set);
   276 
   277 	return 0;
   278 }
   279 
   280 static int
   281 command_list_files(int argc, const char *argv[])
   282 {
   283 	struct razor_error *error = NULL;
   284 	struct razor_set *set;
   285 
   286 	set = razor_root_open_read_only(install_root, &error);
   287 	if (set == NULL) {
   288 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   289 		razor_error_free(error);
   290 		return 1;
   291 	}
   292 
   293 	razor_set_list_files(set, argv[0]);
   294 	razor_set_unref(set);
   295 
   296 	return 0;
   297 }
   298 
   299 static int
   300 command_list_file_packages(int argc, const char *argv[])
   301 {
   302 	struct razor_error *error = NULL;
   303 	struct razor_set *set;
   304 	struct razor_package_iterator *pi;
   305 
   306 	set = razor_root_open_read_only(install_root, &error);
   307 	if (set == NULL) {
   308 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   309 		razor_error_free(error);
   310 		return 1;
   311 	}
   312 
   313 	pi = razor_package_iterator_create_for_file(set, argv[0]);
   314 	list_packages(pi, 0);
   315 	razor_package_iterator_destroy(pi);
   316 
   317 	razor_set_unref(set);
   318 
   319 	return 0;
   320 }
   321 
   322 static int
   323 command_list_package_files(int argc, const char *argv[])
   324 {
   325 	struct razor_error *error = NULL;
   326 	struct razor_set *set;
   327 	struct razor_package_iterator *pi;
   328 	struct razor_package *package;
   329 	const char *name, *version, *arch;
   330 
   331 	set = razor_root_open_read_only(install_root, &error);
   332 	if (set == NULL) {
   333 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   334 		razor_error_free(error);
   335 		return 1;
   336 	}
   337 
   338 	pi = create_iterator_from_argv(set, argc, argv);
   339 	while (razor_package_iterator_next(pi, &package,
   340 					   RAZOR_DETAIL_NAME, &name,
   341 					   RAZOR_DETAIL_VERSION, &version,
   342 					   RAZOR_DETAIL_ARCH, &arch,
   343 					   RAZOR_DETAIL_LAST))
   344 		razor_set_list_package_files(set, package);
   345 	razor_package_iterator_destroy(pi);
   346 
   347 	razor_set_unref(set);
   348 
   349 	return 0;
   350 }
   351 
   352 static int
   353 list_property_packages(const char *ref_name,
   354 		       const char *ref_version,
   355 		       uint32_t type)
   356 {
   357 	struct razor_error *error = NULL;
   358 	struct razor_set *set;
   359 	struct razor_property *property;
   360 	struct razor_property_iterator *prop_iter;
   361 	struct razor_package_iterator *pkg_iter;
   362 	const char *name, *version;
   363 	uint32_t flags;
   364 
   365 	if (ref_name == NULL)
   366 		return 0;
   367 
   368 	set = razor_root_open_read_only(install_root, &error);
   369 	if (set == NULL) {
   370 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   371 		razor_error_free(error);
   372 		return 1;
   373 	}
   374 
   375 	prop_iter = razor_property_iterator_create(set, NULL);
   376 	while (razor_property_iterator_next(prop_iter, &property,
   377 					    &name, &flags, &version)) {
   378 		if (strcmp(ref_name, name) != 0)
   379 			continue;
   380 		if (ref_version &&
   381 		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
   382 		    strcmp(ref_version, version) != 0)
   383 			continue;
   384 		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
   385 			continue;
   386 
   387 		pkg_iter =
   388 			razor_package_iterator_create_for_property(set,
   389 								   property);
   390 		list_packages(pkg_iter, 0);
   391 		razor_package_iterator_destroy(pkg_iter);
   392 	}
   393 	razor_property_iterator_destroy(prop_iter);
   394 
   395 	razor_set_unref(set);
   396 
   397 	return 0;
   398 }
   399 
   400 static int
   401 command_what_requires(int argc, const char *argv[])
   402 {
   403 	return list_property_packages(argv[0], argv[1],
   404 				      RAZOR_PROPERTY_REQUIRES);
   405 }
   406 
   407 static int
   408 command_what_provides(int argc, const char *argv[])
   409 {
   410 	return list_property_packages(argv[0], argv[1],
   411 				      RAZOR_PROPERTY_PROVIDES);
   412 }
   413 
   414 static int
   415 show_progress(void *clientp,
   416 	      double dltotal, double dlnow, double ultotal, double ulnow)
   417 {
   418 	const char *file = clientp;
   419 
   420 	if (!dlnow < dltotal)
   421 		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
   422 			file, (int) dlnow / 1024, (int) dltotal / 1024);
   423 
   424 	return 0;
   425 }
   426 
   427 static int
   428 download_if_missing(const char *url, const char *file)
   429 {
   430 #ifndef HAVE_CURL
   431 	return 1;
   432 #else
   433 	CURL *curl;
   434 	struct stat buf;
   435 	char error[256];
   436 	FILE *fp;
   437 	CURLcode res;
   438 	long response;
   439 
   440 	curl = curl_easy_init();
   441 	if (curl == NULL)
   442 		return 1;
   443 
   444 	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
   445 	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
   446 	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
   447 	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
   448 
   449 	if (stat(file, &buf) < 0) {
   450 		fp = fopen(file, "wb");
   451 		if (fp == NULL) {
   452 			fprintf(stderr,
   453 				"failed to open %s for writing\n", file);
   454 			return -1;
   455 		}
   456 		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
   457 		curl_easy_setopt(curl, CURLOPT_URL, url);
   458 		res = curl_easy_perform(curl);
   459 		fclose(fp);
   460 		if (res != CURLE_OK) {
   461 			fprintf(stderr, "curl error: %s\n", error);
   462 			unlink(file);
   463 			return -1;
   464 		}
   465 		res = curl_easy_getinfo(curl,
   466 					CURLINFO_RESPONSE_CODE, &response);
   467 		if (res != CURLE_OK) {
   468 			fprintf(stderr, "curl error: %s\n", error);
   469                         unlink(file);
   470                         return -1;
   471 		}
   472 		if (response != 200) {
   473 			fprintf(stderr, " - failed %ld\n", response);
   474                         unlink(file);
   475                         return -1;
   476 		}
   477 		fprintf(stderr, "\n");
   478 	}
   479 
   480 	curl_easy_cleanup(curl);
   481 
   482 	return 0;
   483 #endif	/* HAVE_CURL */
   484 }
   485 
   486 #define YUM_URL "http://download.fedora.redhat.com" \
   487 	"/pub/fedora/linux/development/i386/os"
   488 
   489 static int
   490 command_import_yum(int argc, const char *argv[])
   491 {
   492 	int retval;
   493 	struct razor_set *set;
   494 	struct razor_atomic *atomic;
   495 	char buffer[512];
   496 
   497 	printf("downloading from %s.\n", yum_url);
   498 	snprintf(buffer, sizeof buffer,
   499 		 "%s/repodata/primary.xml.gz", yum_url);
   500 	if (download_if_missing(buffer, "primary.xml.gz") < 0)
   501 		return -1;
   502 	snprintf(buffer, sizeof buffer,
   503 		 "%s/repodata/filelists.xml.gz", yum_url);
   504 	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
   505 		return -1;
   506 
   507 	set = razor_set_create_from_yum();
   508 	if (set == NULL)
   509 		return 1;
   510 	atomic = razor_atomic_open("Yum import repository");
   511 	razor_set_write(set, atomic, rawhide_repo_filename, RAZOR_SECTION_ALL);
   512 	retval = razor_atomic_commit(atomic);
   513 	razor_set_unref(set);
   514 	if (retval)
   515 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
   516 	else
   517 		printf("wrote %s\n", rawhide_repo_filename);
   518 	razor_atomic_destroy(atomic);
   519 
   520 	return retval;
   521 }
   522 
   523 #if HAVE_RPMLIB
   524 static int
   525 command_import_rpmdb(int argc, const char *argv[])
   526 {
   527 	struct razor_set *set;
   528 	struct razor_root *root;
   529 	struct razor_error *error = NULL;
   530 	struct razor_atomic *atomic;
   531 	int retval;
   532 
   533 	root = razor_root_open(install_root, &error);
   534 	if (root == NULL) {
   535 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   536 		razor_error_free(error);
   537 		return 1;
   538 	}
   539 
   540 	set = razor_set_create_from_rpmdb();
   541 	if (set == NULL)
   542 		return 1;
   543 
   544 	atomic = razor_atomic_open("Import RPM database");
   545 
   546 	retval = razor_root_update(root, set, atomic);
   547 
   548 	if (retval)
   549 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
   550 
   551 	razor_atomic_destroy(atomic);
   552 
   553 	razor_root_close(root);
   554 
   555 	return retval;
   556 }
   557 #endif
   558 
   559 static int
   560 mark_packages_for_update(struct razor_transaction *trans,
   561 			 struct razor_set *set, const char *pattern)
   562 {
   563 	struct razor_package_iterator *pi;
   564 	struct razor_package *package;
   565 	const char *name;
   566 	int matches = 0;
   567 
   568 	pi = razor_package_iterator_create(set);
   569 	while (razor_package_iterator_next(pi, &package,
   570 					   RAZOR_DETAIL_NAME, &name,
   571 					   RAZOR_DETAIL_LAST)) {
   572 		if (pattern && fnmatch(pattern, name, 0) == 0) {
   573 			razor_transaction_update_package(trans, package);
   574 			matches++;
   575 		}
   576 	}
   577 	razor_package_iterator_destroy(pi);
   578 
   579 	return matches;
   580 }
   581 
   582 static int
   583 mark_packages_for_removal(struct razor_transaction *trans,
   584 			  struct razor_set *set, const char *pattern)
   585 {
   586 	struct razor_package_iterator *pi;
   587 	struct razor_package *package;
   588 	const char *name;
   589 	int matches = 0;
   590 
   591 	pi = razor_package_iterator_create(set);
   592 	while (razor_package_iterator_next(pi, &package,
   593 					   RAZOR_DETAIL_NAME, &name,
   594 					   RAZOR_DETAIL_LAST)) {
   595 		if (pattern && fnmatch(pattern, name, 0) == 0) {
   596 			razor_transaction_remove_package(trans, package);
   597 			matches++;
   598 		}
   599 	}
   600 	razor_package_iterator_destroy(pi);
   601 
   602 	return matches;
   603 }
   604 
   605 static int
   606 command_remove(int argc, const char *argv[])
   607 {
   608 	struct razor_set *system, *upstream, *next;
   609 	struct razor_transaction *trans;
   610 	struct razor_error *error = NULL;
   611 	struct razor_root *root;
   612 	int i, retval;
   613 
   614 	root = razor_root_open(install_root, &error);
   615 	if (root == NULL) {
   616 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   617 		razor_error_free(error);
   618 		return 1;
   619 	}
   620 
   621 	system = razor_root_get_system_set(root);
   622 	upstream = razor_set_create_without_root();
   623 	trans = razor_transaction_create(system, upstream);
   624 	razor_set_unref(upstream);
   625 	for (i = 0; i < argc; i++) {
   626 		if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
   627 			fprintf(stderr, "no match for %s\n", argv[i]);
   628 			razor_transaction_destroy(trans);
   629 			razor_root_close(root);
   630 			return 1;
   631 		}
   632 	}
   633 
   634 	razor_transaction_resolve(trans);
   635 	retval = razor_transaction_describe(trans);
   636 	if (retval) {
   637 		razor_transaction_destroy(trans);
   638 		razor_root_close(root);
   639 		return 1;
   640 	}
   641 
   642 	next = razor_transaction_commit(trans);
   643 
   644 	retval = update_system(root, NULL, trans, next, "Remove");
   645 
   646 	razor_transaction_destroy(trans);
   647 	razor_root_close(root);
   648 	razor_set_unref(next);
   649 
   650 	return retval;
   651 }
   652 
   653 static void
   654 print_diff(enum razor_diff_action action,
   655 	   struct razor_package *package,
   656 	   const char *name,
   657 	   const char *version,
   658 	   const char *arch,
   659 	   void *data)
   660 {
   661 	if (action == RAZOR_DIFF_ACTION_ADD)
   662 		printf("install %s-%s.%s\n", name, version, arch);
   663 	if (action == RAZOR_DIFF_ACTION_REMOVE)
   664 		printf("remove %s-%s.%s\n", name, version, arch);
   665 }
   666 
   667 static int
   668 command_diff(int argc, const char *argv[])
   669 {
   670 	struct razor_error *error = NULL;
   671 	struct razor_set *set, *updated;
   672 
   673 	set = razor_root_open_read_only(install_root, &error);
   674 	if (set)
   675 		updated = razor_set_open(rawhide_repo_filename, 0, &error);
   676 	else
   677 		updated = NULL;
   678 	if (updated == NULL) {
   679 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   680 		razor_error_free(error);
   681 		if (set)
   682 			razor_set_unref(set);
   683 		return 1;
   684 	}
   685 
   686 	razor_set_diff(set, updated, print_diff, NULL);
   687 
   688 	razor_set_unref(set);
   689 	razor_set_unref(updated);
   690 
   691 	return 0;
   692 }
   693 
   694 static int
   695 command_import_rpms(int argc, const char *argv[])
   696 {
   697 	DIR *dir;
   698 	struct dirent *de;
   699 	struct razor_importer *importer;
   700 	struct razor_set *set;
   701 	struct razor_rpm *rpm;
   702 	struct razor_error *error=NULL;
   703 	struct razor_atomic *atomic;
   704 	int len, imported_count = 0;
   705 	char filename[256];
   706 	const char *dirname = argv[0];
   707 	int retval;
   708 
   709 	if (dirname == NULL) {
   710 		fprintf(stderr, "usage: razor import-rpms DIR\n");
   711 		return -1;
   712 	}
   713 
   714 	dir = opendir(dirname);
   715 	if (dir == NULL) {
   716 		fprintf(stderr, "couldn't read dir %s\n", dirname);
   717 		return -1;
   718 	}
   719 
   720 	importer = razor_importer_create();
   721 
   722 	while (de = readdir(dir), de != NULL) {
   723 		len = strlen(de->d_name);
   724 		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
   725 			continue;
   726 		snprintf(filename, sizeof filename,
   727 			 "%s/%s", dirname, de->d_name);
   728 		rpm = razor_rpm_open(filename, &error);
   729 		if (rpm == NULL) {
   730 			fprintf(stderr, "%s\n", razor_error_get_msg(error));
   731 			razor_error_free(error);
   732 			error=NULL;
   733 			continue;
   734 		}
   735 		if (razor_importer_add_rpm(importer, rpm)) {
   736 			fprintf(stderr, "couldn't import %s\n", filename);
   737 			break;
   738 		}
   739 		razor_rpm_close(rpm);
   740 
   741 		printf("\rimporting %d", ++imported_count);
   742 		fflush(stdout);
   743 	}
   744 
   745 	if (de != NULL) {
   746 		razor_importer_destroy(importer);
   747 		return -1;
   748 	}
   749 
   750 	printf("\nsaving\n");
   751 	set = razor_importer_finish(importer);
   752 
   753 	atomic = razor_atomic_open("Update system database");
   754 	razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
   755 	razor_set_unref(set);
   756 	retval = razor_atomic_commit(atomic);
   757 	if (retval)
   758 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
   759 	else
   760 		printf("wrote %s\n", repo_filename);
   761 	razor_atomic_destroy(atomic);
   762 
   763 	return retval;
   764 }
   765 
   766 static char *
   767 rpm_filename(const char *name, const char *version, const char *arch)
   768 {
   769  	const char *v;
   770  
   771  	/* Skip epoch */
   772 	v = strchr(version, ':');
   773  	if (v != NULL)
   774  		v = v + 1;
   775  	else
   776 		v = version;
   777 
   778 	return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
   779 }
   780 
   781 static int
   782 download_packages(struct razor_set *system, struct razor_set *next)
   783 {
   784 	struct razor_install_iterator *ii;
   785 	struct razor_package *package;
   786 	enum razor_install_action action;
   787 	const char *name, *version, *arch;
   788 	char *file, *url, *s;
   789 	int errors = 0, count;
   790 
   791 	ii = razor_set_create_install_iterator(system, next);
   792 	while (razor_install_iterator_next(ii, &package, &action, &count)) {
   793 		if (action != RAZOR_INSTALL_ACTION_ADD)
   794 			continue;
   795 
   796 		razor_package_get_details(next, package,
   797 					  RAZOR_DETAIL_NAME, &name,
   798 					  RAZOR_DETAIL_VERSION, &version,
   799 					  RAZOR_DETAIL_ARCH, &arch,
   800 					  RAZOR_DETAIL_LAST);
   801 		
   802 		s = rpm_filename(name, version, arch);
   803 		url = razor_concat(yum_url, "/Packages/", s, NULL);
   804 		file = razor_concat("rpms/", s, NULL);
   805 		free(s);
   806 		if (download_if_missing(url, file) < 0)
   807 			errors++;
   808 		free(file);
   809 		free(url);
   810 	}
   811 	razor_install_iterator_destroy(ii);
   812 
   813 	if (errors > 0) {
   814 		fprintf(stderr, "failed to download %d packages\n", errors);
   815                 return -1;
   816         }
   817 
   818 	return 0;
   819 }
   820 
   821 static struct razor_set *
   822 relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
   823 		  struct razor_relocations *relocations)
   824 {
   825 	int i;
   826 	struct razor_importer *importer;
   827 	struct razor_property_iterator *prop_iter;
   828 	struct razor_package_iterator *pkg_iter;
   829  	struct razor_file_iterator *file_iter;
   830  	struct razor_package *package;
   831 	struct razor_property *property;
   832 	struct razor_rpm *rpm;
   833 	struct razor_error *error=NULL;
   834 	const char *name, *version, *arch, *summary, *desc, *url, *license;
   835 	const char *preunprog, *preun, *postunprog, *postun;
   836 	const char *install_prefix;
   837 	const char *const *prefixes;
   838 	char *file, *s;
   839 	uint32_t flags;
   840 
   841 	importer = razor_importer_create();
   842 	pkg_iter = razor_package_iterator_create(set);
   843 
   844 	while (razor_package_iterator_next(pkg_iter, &package,
   845 					   RAZOR_DETAIL_NAME, &name,
   846 					   RAZOR_DETAIL_VERSION, &version,
   847 					   RAZOR_DETAIL_ARCH, &arch,
   848 					   RAZOR_DETAIL_SUMMARY, &summary,
   849 					   RAZOR_DETAIL_DESCRIPTION, &desc,
   850 					   RAZOR_DETAIL_URL, &url,
   851 					   RAZOR_DETAIL_LICENSE, &license,
   852 					   RAZOR_DETAIL_PREUNPROG, &preunprog,
   853 					   RAZOR_DETAIL_PREUN, &preun,
   854 					   RAZOR_DETAIL_POSTUNPROG, &postunprog,
   855 					   RAZOR_DETAIL_POSTUN, &postun,
   856 					   RAZOR_DETAIL_LAST)) {
   857 		s = rpm_filename(name, version, arch);
   858 		file = razor_concat("rpms/", s, NULL);
   859 		free(s);
   860 		rpm = razor_rpm_open(file, &error);
   861 		free(file);
   862 		if (rpm == NULL) {
   863 			razor_atomic_abort(atomic, razor_error_get_msg(error));
   864 			razor_error_free(error);
   865 			razor_package_iterator_destroy(pkg_iter);
   866 			razor_importer_destroy(importer);
   867 			return NULL;
   868 		}
   869 
   870 		razor_relocations_set_rpm(relocations, rpm);
   871 
   872 		razor_importer_begin_package(importer, name, version, arch);
   873 		razor_importer_add_details(importer,
   874 					   summary, desc, url, license);
   875 
   876 		razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
   877 				      RAZOR_DETAIL_LAST);
   878 		for (i = 0; prefixes && prefixes[i]; i++) {
   879 			install_prefix = razor_relocations_apply(relocations,
   880 								 prefixes[i]);
   881 			razor_importer_add_install_prefix(importer,
   882 							  install_prefix);
   883 		}
   884 
   885 		razor_rpm_close(rpm);
   886 
   887 		prop_iter = razor_property_iterator_create(set, package);
   888 		while (razor_property_iterator_next(prop_iter, &property,
   889 						    &name, &flags, &version))
   890 			razor_importer_add_property(importer,
   891 						    name, flags, version);
   892 		razor_property_iterator_destroy(prop_iter);
   893 
   894 		file_iter = razor_file_iterator_create(set, package, 0);
   895 		while (razor_file_iterator_next(file_iter, &name)) {
   896 			name = razor_relocations_apply(relocations, name);
   897 			razor_importer_add_file(importer, name);
   898 		}
   899 		razor_file_iterator_destroy(file_iter);
   900 
   901 		razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
   902 					  preunprog, preun);
   903 		razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
   904 					  postunprog, postun);
   905 
   906 		razor_importer_finish_package(importer);
   907 	}
   908 
   909 	razor_package_iterator_destroy(pkg_iter);
   910 	return razor_importer_finish(importer);
   911 }
   912 
   913 static int
   914 install_package(struct razor_transaction *trans, struct razor_set *set,
   915 		struct razor_atomic *atomic, struct razor_package *package,
   916 		struct razor_relocations *relocations, int install_count,
   917 		enum razor_stage_type stage)
   918 {
   919 	int retval;
   920 	const char *name, *version, *arch;
   921 	char *file, *s;
   922 	struct razor_rpm *rpm;
   923 	struct razor_error *error=NULL;
   924 
   925 	razor_package_get_details(set, package,
   926 				  RAZOR_DETAIL_NAME, &name,
   927 				  RAZOR_DETAIL_VERSION, &version,
   928 				  RAZOR_DETAIL_ARCH, &arch,
   929 				  RAZOR_DETAIL_LAST);
   930 
   931 	if (stage & RAZOR_STAGE_SCRIPTS_PRE)
   932 		printf("install %s-%s\n", name, version);
   933 
   934 	s = rpm_filename(name, version, arch);
   935 	file = razor_concat("rpms/", s, NULL);
   936 	free(s);
   937 	rpm = razor_rpm_open(file, &error);
   938 	free(file);
   939 	if (rpm == NULL) {
   940 		razor_atomic_abort(atomic, razor_error_get_msg(error));
   941 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
   942 		razor_error_free(error);
   943 		return -1;
   944 	}
   945 	if (relocations)
   946 		razor_rpm_set_relocations(rpm, relocations);
   947 	razor_transaction_fixup_package(trans, package, rpm);
   948 	retval = razor_rpm_install(rpm, atomic, install_root, install_count,
   949 				   stage);
   950 	if (retval < 0) {
   951 		s = rpm_filename(name, version, arch);
   952 		fprintf(stderr, "%s: %s\n", s,
   953 			razor_atomic_get_error_msg(atomic));
   954 		free(s);
   955 	}
   956 	razor_rpm_close(rpm);
   957 	return retval;
   958 }
   959 
   960 /*
   961  * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
   962  * is met (in which case the action is consumed).
   963  */
   964 static int
   965 update_packages(struct razor_transaction *trans,
   966 		struct razor_install_iterator *ii, struct razor_set *system,
   967 		struct razor_set *next, struct razor_atomic *atomic,
   968 		struct razor_relocations *relocations,
   969 		enum razor_stage_type stage)
   970 {
   971 	struct razor_package *package;
   972 	enum razor_install_action action;
   973 	int retval = 0, count;
   974 
   975 	while (!retval && razor_install_iterator_next(ii, &package, &action,
   976 						      &count)) {
   977 		if (action == RAZOR_INSTALL_ACTION_ADD) {
   978 			if (install_package(trans, next, atomic, package,
   979 					    relocations, count, stage))
   980 				retval = -1;
   981 		} else if (action == RAZOR_INSTALL_ACTION_REMOVE) {
   982 			if (razor_package_remove(system, next, atomic, package,
   983 						 install_root, count, stage))
   984 				retval = -1;
   985 		} else if (action == RAZOR_INSTALL_ACTION_COMMIT)
   986 				retval = 1;
   987 	}
   988 
   989 	return retval;
   990 }
   991 
   992 static int
   993 update_system(struct razor_root *root, struct razor_relocations *relocations,
   994 	      struct razor_transaction *trans, struct razor_set *next,
   995 	      const char *verb)
   996 {
   997 	struct razor_set *system, *set;
   998 	struct razor_atomic *atomic;
   999 	struct razor_install_iterator *ii;
  1000 	int r, retval = 0;
  1001 	char *description;
  1002 	size_t pos;
  1003 
  1004 	description = razor_concat(verb, " packages", NULL);
  1005 
  1006 	system = razor_set_ref(razor_root_get_system_set(root));
  1007 
  1008 	ii = razor_set_create_install_iterator(system, next);
  1009 
  1010 	do {
  1011 		pos = razor_install_iterator_tell(ii);
  1012 
  1013 		atomic = razor_atomic_open(description);
  1014 
  1015 		r = update_packages(trans, ii, system, next, atomic,
  1016 				    relocations, RAZOR_STAGE_SCRIPTS_PRE);
  1017 		if (r < 0) {
  1018 			fprintf(stderr, "%s aborted\n", verb);
  1019 			retval = r;
  1020 		} else {
  1021 			razor_install_iterator_seek(ii, pos);
  1022 			r = update_packages(trans, ii, system, next, atomic,
  1023 					    relocations, RAZOR_STAGE_FILES);
  1024 
  1025 			if (r == 1) {
  1026 				set = razor_install_iterator_commit_set(ii);
  1027 				razor_root_update(root, set, atomic);
  1028 				razor_set_unref(set);
  1029 			} else if (r == 0)
  1030 				razor_root_update(root, next, atomic);
  1031 
  1032 			retval = razor_atomic_commit(atomic);
  1033 			if (retval)
  1034 				fprintf(stderr, "%s\n",
  1035 					razor_atomic_get_error_msg(atomic));
  1036 			else {
  1037 				razor_install_iterator_seek(ii, pos);
  1038 				update_packages(trans, ii, system, next,
  1039 						atomic, relocations,
  1040 						RAZOR_STAGE_SCRIPTS_POST);
  1041 			}
  1042 		}
  1043 
  1044 		razor_atomic_destroy(atomic);
  1045 	} while(!retval && r == 1);
  1046 
  1047 	razor_set_unref(system);
  1048 
  1049 	free(description);
  1050 
  1051 	return retval;
  1052 }
  1053 
  1054 static int
  1055 command_install_or_update(int argc, const char *argv[], int do_update)
  1056 {
  1057 	struct razor_relocations *relocations = NULL;
  1058 	struct razor_set *system, *upstream, *next, *set;
  1059 	struct razor_transaction *trans;
  1060 	struct razor_error *error = NULL;
  1061 	struct razor_atomic *atomic;
  1062 	struct razor_root *root;
  1063 	int i, retval, len, dependencies = 1;
  1064 	char *oldpath;
  1065 
  1066 	for (i = 0; i < argc; i++) {
  1067 		if (strcmp(argv[i], "--no-dependencies") == 0)
  1068 			dependencies = 0;
  1069 		else if (strcmp(argv[i], "--relocate") == 0) {
  1070 			i++;
  1071 			if (i >= argc || strchr(argv[i], '=') == NULL) {
  1072 				fprintf(stderr,
  1073 				    "Usage: razor %s [OPTION...] RPM\n",
  1074 				    do_update ? "update" : "install");
  1075 				fprintf(stderr, "Options:\n");
  1076 				fprintf(stderr, "    [--no-dependencies]\n");
  1077 				fprintf(stderr,
  1078 				    "    [--relocate OLDPATH=NEWPATH] RPM\n");
  1079 				return -1;
  1080 			}
  1081 			len = strchr(argv[i], '=') - argv[i];
  1082 			oldpath = malloc(len + 1);
  1083 			strncpy(oldpath, argv[i], len);
  1084 			oldpath[len] = '\0';
  1085 			if (!relocations)
  1086 			       relocations = razor_relocations_create();
  1087 			razor_relocations_add(relocations, oldpath,
  1088 					      argv[i] + len + 1);
  1089 			free(oldpath);
  1090 		} else
  1091 			break;
  1092 	}
  1093 
  1094 	upstream = razor_set_open(rawhide_repo_filename, 0, &error);
  1095 	if (upstream == NULL) {
  1096 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1097 		razor_error_free(error);
  1098 		return 1;
  1099 	}
  1100 
  1101 	if (do_update)
  1102 		atomic = razor_atomic_open("Update packages");
  1103 	else
  1104 		atomic = razor_atomic_open("Install packages");
  1105 
  1106 	if (relocations) {
  1107 		set = relocate_packages(upstream, atomic, relocations);
  1108 		if (set == NULL) {
  1109 			fprintf(stderr, "%s\n",
  1110 				razor_atomic_get_error_msg(atomic));
  1111 			razor_atomic_destroy(atomic);
  1112 			razor_set_unref(upstream);
  1113 			return 1;
  1114 		}
  1115 		razor_set_unref(upstream);
  1116 		upstream = set;
  1117 	}
  1118 
  1119 	root = razor_root_open(install_root, &error);
  1120 	if (root == NULL) {
  1121 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1122 		razor_error_free(error);
  1123 		razor_atomic_destroy(atomic);
  1124 		razor_set_unref(upstream);
  1125 		if (relocations)
  1126 			razor_relocations_destroy(relocations);
  1127 		return 1;
  1128 	}
  1129 
  1130 	system = razor_root_get_system_set(root);
  1131 	trans = razor_transaction_create(system, upstream);
  1132 
  1133 	if (i == argc && do_update)
  1134 		razor_transaction_update_all(trans);
  1135 	for (; i < argc; i++) {
  1136 		if (do_update &&
  1137 		    mark_packages_for_update(trans, system, argv[i]))
  1138 			continue;
  1139 		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  1140 			fprintf(stderr, "no package matched %s\n", argv[i]);
  1141 			razor_transaction_destroy(trans);
  1142 			razor_root_close(root);
  1143 			razor_set_unref(upstream);
  1144 			razor_atomic_destroy(atomic);
  1145 			if (relocations)
  1146 				razor_relocations_destroy(relocations);
  1147 			return 1;
  1148 		}
  1149 	}
  1150 
  1151 	if (dependencies) {
  1152 		razor_transaction_resolve(trans);
  1153 		if (razor_transaction_describe(trans) > 0) {
  1154 			razor_transaction_destroy(trans);
  1155 			razor_set_unref(upstream);
  1156 			razor_root_close(root);
  1157 			razor_atomic_destroy(atomic);
  1158 			if (relocations)
  1159 				razor_relocations_destroy(relocations);
  1160 			return 1;
  1161 		}
  1162 	}
  1163 
  1164 	if (razor_atomic_create_dir(atomic, "rpms",
  1165 				    S_IRWXU | S_IRWXG | S_IRWXO) ||
  1166 	    razor_atomic_commit(atomic)) {
  1167 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
  1168 		razor_transaction_destroy(trans);
  1169 		razor_set_unref(upstream);
  1170 		razor_root_close(root);
  1171 		razor_atomic_destroy(atomic);
  1172 		if (relocations)
  1173 			razor_relocations_destroy(relocations);
  1174 		return 1;
  1175 	}
  1176 
  1177 	razor_atomic_destroy(atomic);
  1178 
  1179 	next = razor_transaction_commit(trans);
  1180 
  1181 	if (download_packages(system, next) < 0) {
  1182 		razor_set_unref(next);
  1183 		razor_transaction_destroy(trans);
  1184 		razor_set_unref(upstream);
  1185 		razor_root_close(root);
  1186 		razor_atomic_destroy(atomic);
  1187 		if (relocations)
  1188 			razor_relocations_destroy(relocations);
  1189                 return 1;
  1190         }
  1191 
  1192 	retval = update_system(root, relocations, trans, next,
  1193 			       do_update ? "Update" : "Install");
  1194 
  1195 	razor_set_unref(upstream);
  1196 	razor_root_close(root);
  1197 
  1198 	razor_transaction_destroy(trans);
  1199 	if (relocations)
  1200 		razor_relocations_destroy(relocations);
  1201 
  1202 	razor_set_unref(next);
  1203 
  1204 	return retval;
  1205 }
  1206 
  1207 static int
  1208 command_update(int argc, const char *argv[])
  1209 {
  1210 	return command_install_or_update(argc, argv, 1);
  1211 }
  1212 
  1213 static int
  1214 command_install(int argc, const char *argv[])
  1215 {
  1216 	return command_install_or_update(argc, argv, 0);
  1217 }
  1218 
  1219 static int
  1220 command_init(int argc, const char *argv[])
  1221 {
  1222 	int retval;
  1223 	struct razor_error *error = NULL;
  1224 
  1225 	retval = razor_root_create(install_root, &error);
  1226 	if (retval) {
  1227 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1228 		razor_error_free(error);
  1229 	} else
  1230 		printf("Created install root\n");
  1231 
  1232 	return retval;
  1233 }
  1234 
  1235 static int
  1236 command_download(int argc, const char *argv[])
  1237 {
  1238 	struct razor_error *error = NULL;
  1239 	struct razor_atomic *atomic;
  1240 	struct razor_set *set;
  1241 	struct razor_package_iterator *pi;
  1242 	struct razor_package *package;
  1243 	const char *pattern = argv[0], *name, *version, *arch;
  1244 	char url[256], file[256];
  1245 	int matches = 0;
  1246 
  1247 	set = razor_set_open(rawhide_repo_filename, 0, &error);
  1248 	if (set == NULL) {
  1249 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1250 		razor_error_free(error);
  1251 		return 1;
  1252 	}
  1253 
  1254 	atomic = razor_atomic_open("Download packages");
  1255 
  1256 	if (razor_atomic_create_dir(atomic, "rpms", 
  1257 				    S_IRWXU | S_IRWXG | S_IRWXO)) {
  1258 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
  1259 		razor_atomic_destroy(atomic);
  1260 		return 1;
  1261 	}
  1262 
  1263 	if (razor_atomic_commit(atomic)) {
  1264 		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
  1265 		razor_atomic_destroy(atomic);
  1266 		return 1;
  1267 	}
  1268 	razor_atomic_destroy(atomic);
  1269 
  1270 	pi = razor_package_iterator_create(set);
  1271 	while (razor_package_iterator_next(pi, &package,
  1272 					   RAZOR_DETAIL_NAME, &name,
  1273 					   RAZOR_DETAIL_VERSION, &version,
  1274 					   RAZOR_DETAIL_ARCH, &arch,
  1275 					   RAZOR_DETAIL_LAST)) {
  1276 		if (pattern && fnmatch(pattern, name, 0) != 0)
  1277 			continue;
  1278 
  1279 		matches++;
  1280 		snprintf(url, sizeof url,
  1281 			 "%s/Packages/%s-%s.%s.rpm",
  1282 			 yum_url, name, version, arch);
  1283 		snprintf(file, sizeof file,
  1284 			 "rpms/%s-%s.%s.rpm", name, version, arch);
  1285 		download_if_missing(url, file);
  1286 	}
  1287 	razor_package_iterator_destroy(pi);
  1288 	razor_set_unref(set);
  1289 
  1290 	if (matches == 0)
  1291 		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
  1292 	else if (matches == 1)
  1293 		fprintf(stderr, "downloaded 1 package\n");
  1294 	else
  1295 		fprintf(stderr, "downloaded %d packages\n", matches);
  1296 
  1297 	return 0;
  1298 }
  1299 
  1300 static int
  1301 command_info(int argc, const char *argv[])
  1302 {
  1303 	struct razor_error *error = NULL;
  1304 	struct razor_set *set;
  1305 	struct razor_package_iterator *pi;
  1306 	struct razor_package *package;
  1307 	const char *pattern = argv[0], *name, *version, *arch;
  1308 	const char *summary, *description, *url, *license;
  1309 
  1310 	set = razor_root_open_read_only(install_root, &error);
  1311 	if (set == NULL) {
  1312 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1313 		razor_error_free(error);
  1314 		return 1;
  1315 	}
  1316 
  1317 	pi = razor_package_iterator_create(set);
  1318 	while (razor_package_iterator_next(pi, &package,
  1319 					   RAZOR_DETAIL_NAME, &name,
  1320 					   RAZOR_DETAIL_VERSION, &version,
  1321 					   RAZOR_DETAIL_ARCH, &arch,
  1322 					   RAZOR_DETAIL_LAST)) {
  1323 		if (pattern && fnmatch(pattern, name, 0) != 0)
  1324 			continue;
  1325 
  1326 		razor_package_get_details (set, package,
  1327 					   RAZOR_DETAIL_SUMMARY, &summary,
  1328 					   RAZOR_DETAIL_DESCRIPTION, &description,
  1329 					   RAZOR_DETAIL_URL, &url,
  1330 					   RAZOR_DETAIL_LICENSE, &license,
  1331 					   RAZOR_DETAIL_LAST);
  1332 
  1333 		printf ("Name:        %s\n", name);
  1334 		printf ("Arch:        %s\n", arch);
  1335 		printf ("Version:     %s\n", version);
  1336 		printf ("URL:         %s\n", url);
  1337 		printf ("License:     %s\n", license);
  1338 		printf ("Summary:     %s\n", summary);
  1339 		printf ("Description:\n");
  1340 		printf ("%s\n", description);
  1341 		printf ("\n");
  1342 	}
  1343 	razor_package_iterator_destroy(pi);
  1344 	razor_set_unref(set);
  1345 
  1346 	return 0;
  1347 }
  1348 
  1349 #define SEARCH_MAX 256
  1350 
  1351 static int
  1352 command_search(int argc, const char *argv[])
  1353 {
  1354 	struct razor_error *error = NULL;
  1355 	struct razor_set *set;
  1356 	struct razor_package_iterator *pi;
  1357 	struct razor_package *package;
  1358 	char pattern[SEARCH_MAX];
  1359 	const char *name, *version, *arch;
  1360 	const char *summary, *description, *url, *license;
  1361 
  1362 	if (!argv[0]) {
  1363 		fprintf(stderr, "must specify a search term\n");
  1364 		return 1;
  1365 	}
  1366 
  1367 	snprintf(pattern, sizeof pattern, "*%s*", argv[0]);
  1368 
  1369 	set = razor_set_open(rawhide_repo_filename, 0, &error);
  1370 	if (set == NULL) {
  1371 		fprintf(stderr, "%s\n", razor_error_get_msg(error));
  1372 		razor_error_free(error);
  1373 		return 1;
  1374 	}
  1375 
  1376 	pi = razor_package_iterator_create(set);
  1377 	while (razor_package_iterator_next(pi, &package,
  1378 					   RAZOR_DETAIL_NAME, &name,
  1379 					   RAZOR_DETAIL_VERSION, &version,
  1380 					   RAZOR_DETAIL_ARCH, &arch,
  1381 					   RAZOR_DETAIL_SUMMARY, &summary,
  1382 					   RAZOR_DETAIL_DESCRIPTION, &description,
  1383 					   RAZOR_DETAIL_URL, &url,
  1384 					   RAZOR_DETAIL_LICENSE, &license,
  1385 					   RAZOR_DETAIL_LAST)) {
  1386 		if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
  1387 		    !fnmatch(pattern, url, FNM_CASEFOLD) ||
  1388 		    !fnmatch(pattern, summary, FNM_CASEFOLD) ||
  1389 		    !fnmatch(pattern, description, FNM_CASEFOLD))
  1390 			printf("%s-%s.%s: %s\n", name, version, arch, summary);
  1391 	}
  1392 	razor_package_iterator_destroy(pi);
  1393 	razor_set_unref(set);
  1394 
  1395 	return 0;
  1396 }
  1397 
  1398 static struct {
  1399 	const char *name;
  1400 	const char *description;
  1401 	int (*func)(int argc, const char *argv[]);
  1402 } razor_commands[] = {
  1403 	{ "list", "list all packages", command_list },
  1404 	{ "list-requires", "list all requires for the given package", command_list_requires },
  1405 	{ "list-provides", "list all provides for the given package", command_list_provides },
  1406 	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
  1407 	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
  1408 	{ "list-scripts", "list all scripts for the given package", command_list_scripts },
  1409 	{ "list-files", "list files for package set", command_list_files },
  1410 	{ "list-file-packages", "list packages owning file", command_list_file_packages },
  1411 	{ "list-package-files", "list files in package", command_list_package_files },
  1412 	{ "what-requires", "list the packages that have the given requires", command_what_requires },
  1413 	{ "what-provides", "list the packages that have the given provides", command_what_provides },
  1414 	{ "import-yum", "import yum metadata files", command_import_yum },
  1415 #if HAVE_RPMLIB
  1416 	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
  1417 #endif
  1418 	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
  1419 	{ "update", "update all or specified packages", command_update },
  1420 	{ "remove", "remove specified packages", command_remove },
  1421 	{ "diff", "show diff between two package sets", command_diff },
  1422 	{ "install", "install rpm", command_install },
  1423 	{ "init", "init razor root", command_init },
  1424 	{ "download", "download packages", command_download },
  1425 	{ "info", "display package details", command_info },
  1426 	{ "search", "search package details", command_search }
  1427 };
  1428 
  1429 static int
  1430 usage(void)
  1431 {
  1432 	int i;
  1433 
  1434 	printf("usage:\n");
  1435 	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  1436 		printf("  %-20s%s\n",
  1437 		       razor_commands[i].name, razor_commands[i].description);
  1438 
  1439 	return 1;
  1440 }
  1441 
  1442 int
  1443 main(int argc, const char *argv[])
  1444 {
  1445 	char *repo, *root;
  1446 	int i;
  1447 
  1448 	repo = getenv("RAZOR_REPO");
  1449 	if (repo != NULL)
  1450 		repo_filename = repo;
  1451 
  1452 	root = getenv("RAZOR_ROOT");
  1453 	if (root != NULL)
  1454 		install_root = root;
  1455 
  1456 	yum_url = getenv("YUM_URL");
  1457 	if (yum_url == NULL)
  1458 		yum_url = YUM_URL;
  1459 
  1460 	if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
  1461 		razor_disable_root_name_checks(1);
  1462 
  1463 	if (argc < 2)
  1464 		return usage();
  1465 
  1466 	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  1467 		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  1468 			return razor_commands[i].func(argc - 2, argv + 2);
  1469 
  1470 	return usage();
  1471 }