src/main.c
author ali <j.a.harlow@letterboxes.org>
Thu Apr 14 11:59:56 2016 +0100 (2016-04-14)
changeset 467 4b7270fd3201
parent 458 3f841a46eab5
child 475 008c75a5e08d
permissions -rw-r--r--
Release version 0.6.1
rhughes@241
     1
/*
rhughes@241
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
rhughes@241
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@445
     4
 * Copyright (C) 2009, 2011-2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
rhughes@241
     5
 *
rhughes@241
     6
 * This program is free software; you can redistribute it and/or modify
rhughes@241
     7
 * it under the terms of the GNU General Public License as published by
rhughes@241
     8
 * the Free Software Foundation; either version 2 of the License, or
rhughes@241
     9
 * (at your option) any later version.
rhughes@241
    10
 *
rhughes@241
    11
 * This program is distributed in the hope that it will be useful,
rhughes@241
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rhughes@241
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rhughes@241
    14
 * GNU General Public License for more details.
rhughes@241
    15
 *
rhughes@241
    16
 * You should have received a copy of the GNU General Public License along
rhughes@241
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
rhughes@241
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
rhughes@241
    19
 */
rhughes@241
    20
krh@305
    21
#define _GNU_SOURCE
krh@305
    22
ali@321
    23
#include "config.h"
ali@321
    24
rhughes@241
    25
#include <stdlib.h>
rhughes@241
    26
#include <stddef.h>
rhughes@241
    27
#include <stdio.h>
rhughes@241
    28
#include <stdint.h>
rhughes@241
    29
#include <string.h>
rhughes@241
    30
#include <sys/stat.h>
rhughes@241
    31
#include <unistd.h>
rhughes@241
    32
#include <fcntl.h>
rhughes@241
    33
#include <dirent.h>
ali@325
    34
#include <limits.h>
ali@455
    35
#ifdef MSWIN_API
ali@455
    36
#include <windows.h>
ali@455
    37
#include <shlwapi.h>
ali@455
    38
#endif
ali@321
    39
#ifdef HAVE_CURL
rhughes@241
    40
#include <curl/curl.h>
ali@321
    41
#endif
ali@455
    42
#if !defined(HAVE_CURL) && !defined(MSWIN_API)
ali@455
    43
#include <ctype.h>
ali@455
    44
#endif
rhughes@241
    45
#include <fnmatch.h>
rhughes@241
    46
#include <errno.h>
ali@445
    47
#include <getopt.h>
rhughes@241
    48
#include "razor.h"
rhughes@241
    49
richard@310
    50
static const char system_repo_filename[] = "system.rzdb";
richard@310
    51
static const char next_repo_filename[] = "system-next.rzdb";
richard@310
    52
static const char rawhide_repo_filename[] = "rawhide.rzdb";
krh@317
    53
static const char *install_root = "";
rhughes@241
    54
static const char *repo_filename = system_repo_filename;
rhughes@241
    55
static const char *yum_url;
rhughes@241
    56
ali@445
    57
#ifndef FALSE
ali@445
    58
#define FALSE 0
ali@445
    59
#endif
ali@445
    60
ali@445
    61
#ifndef TRUE
ali@445
    62
#define TRUE (!FALSE)
ali@445
    63
#endif
ali@445
    64
krh@271
    65
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
krh@271
    66
ali@363
    67
static int
ali@403
    68
update_packages(struct razor_transaction *trans,
ali@403
    69
		struct razor_install_iterator *ii, struct razor_set *system,
ali@403
    70
		struct razor_set *next, struct razor_atomic *atomic,
ali@403
    71
		struct razor_relocations *relocations,
ali@418
    72
		enum razor_stage_type stage);
ali@418
    73
static int
ali@424
    74
update_system(struct razor_root *root, struct razor_relocations *relocations,
ali@424
    75
	      struct razor_transaction *trans, struct razor_set *next,
ali@424
    76
	      const char *verb);
ali@363
    77
ali@445
    78
static int command_help(int argc, char * const argv[]);
ali@445
    79
ali@445
    80
struct razor_option {
ali@445
    81
	char *name;
ali@445
    82
	int has_arg;
ali@445
    83
	int val;
ali@445
    84
	char *description;
ali@445
    85
	char *arg_description;
ali@445
    86
};
ali@445
    87
ali@445
    88
static void
ali@445
    89
razor_usage(const char *command, int n_options, struct razor_option *options,
ali@445
    90
	    const char *parameter_string)
ali@445
    91
{
ali@445
    92
	int i, help_printed = FALSE;
ali@445
    93
	char buf[19];
ali@445
    94
ali@445
    95
	printf("Usage: razor %s [options] %s\n", command, parameter_string);
ali@445
    96
	printf("(Specify the --help global option for a list of other "
ali@445
    97
	       "help options)\n");
ali@445
    98
	printf("\nOptions:\n");
ali@445
    99
ali@445
   100
	for(i = 0; i < n_options; i++) {
ali@445
   101
		if (!help_printed && strcmp(options[i].name, "help") > 0) {
ali@445
   102
			printf("  --help              "
ali@445
   103
			       "Show this help message and exit\n");
ali@445
   104
			help_printed = TRUE;
ali@445
   105
		}
ali@445
   106
ali@445
   107
		if (options[i].has_arg != no_argument)
ali@445
   108
			snprintf(buf, sizeof(buf), "%s=%s", options[i].name,
ali@445
   109
				 options[i].arg_description);
ali@445
   110
		else
ali@445
   111
			strncpy(buf, options[i].name, sizeof(buf));
ali@445
   112
		buf[18] = '\0';
ali@445
   113
ali@445
   114
		printf("  --%-18s%s\n", buf, options[i].description);
ali@445
   115
	}
ali@445
   116
ali@445
   117
	if (!help_printed)
ali@445
   118
		printf("  --help              "
ali@445
   119
		       "Show this help message and exit\n");
ali@445
   120
}
ali@445
   121
ali@445
   122
/**
ali@445
   123
 * razor_getopt:
ali@445
   124
 *
ali@445
   125
 *
ali@445
   126
 * Returns: The next option found or -2 on handled or -1 on error
ali@445
   127
 *          or 0 on end of option list.
ali@445
   128
 **/
ali@445
   129
static int
ali@445
   130
razor_getopt(int argc, char * const argv[], int n_options,
ali@445
   131
	     struct razor_option *options, const char *parameter_string,
ali@445
   132
	     const char **arg)
ali@445
   133
{
ali@445
   134
	int i, opt, do_help = 0, retval;
ali@445
   135
	struct option *longopts;
ali@445
   136
ali@445
   137
	longopts = calloc((n_options + 2), sizeof(*longopts));
ali@445
   138
ali@445
   139
	for(i = 0; i < n_options; i++) {
ali@445
   140
		longopts[i].name = options[i].name;
ali@445
   141
		longopts[i].has_arg = options[i].has_arg;
ali@445
   142
		longopts[i].flag = &retval;
ali@445
   143
		longopts[i].val = options[i].val;
ali@445
   144
	}
ali@445
   145
ali@445
   146
	longopts[i].name = "help";
ali@445
   147
	longopts[i].has_arg = no_argument;
ali@445
   148
	longopts[i].flag = &do_help;
ali@445
   149
	longopts[i].val = TRUE;
ali@445
   150
ali@445
   151
	opterr = 0;
ali@445
   152
ali@445
   153
	opt = getopt_long(argc, argv, "+", longopts, NULL);
ali@445
   154
ali@445
   155
	switch (opt)
ali@445
   156
	{
ali@445
   157
		case 0:
ali@445
   158
			if (do_help) {
ali@445
   159
				razor_usage(argv[0], n_options, options,
ali@445
   160
					    parameter_string);
ali@445
   161
				retval = -2;
ali@445
   162
			} else if (arg)
ali@445
   163
				*arg = optarg;
ali@445
   164
			break;
ali@445
   165
ali@445
   166
		case -1:
ali@445
   167
			retval = 0;
ali@445
   168
			break;
ali@445
   169
ali@445
   170
		default:
ali@445
   171
			razor_usage(argv[0], n_options, options,
ali@445
   172
				    parameter_string);
ali@445
   173
			retval = -1;
ali@445
   174
	}
ali@445
   175
ali@445
   176
	free(longopts);
ali@445
   177
	return retval;
ali@445
   178
}
ali@445
   179
krh@281
   180
static struct razor_package_iterator *
ali@445
   181
create_iterator_from_argv(struct razor_set *set, int argc, char * const argv[])
rhughes@241
   182
{
krh@281
   183
	struct razor_package_query *query;
krh@281
   184
	struct razor_package_iterator *iter;
rhughes@241
   185
	struct razor_package *package;
richard@302
   186
	const char *name, *pattern;
krh@281
   187
	int i, count;
rhughes@241
   188
krh@281
   189
	if (argc == 0)
krh@281
   190
		return razor_package_iterator_create(set);
krh@281
   191
krh@281
   192
	query = razor_package_query_create(set);
krh@281
   193
krh@281
   194
	for (i = 0; i < argc; i++) {
krh@281
   195
		iter = razor_package_iterator_create(set);
krh@281
   196
		pattern = argv[i];
krh@281
   197
		count = 0;
richard@307
   198
		while (razor_package_iterator_next(iter, &package,
richard@307
   199
						   RAZOR_DETAIL_NAME, &name,
richard@307
   200
						   RAZOR_DETAIL_LAST)) {
krh@281
   201
			if (fnmatch(pattern, name, 0) != 0)
krh@281
   202
				continue;
krh@281
   203
krh@281
   204
			razor_package_query_add_package(query, package);
krh@281
   205
			count++;
krh@281
   206
		}
krh@281
   207
		razor_package_iterator_destroy(iter);
krh@281
   208
krh@281
   209
		if (count == 0)
krh@281
   210
			fprintf(stderr,
krh@281
   211
				"no package matches \"%s\"\n", pattern);
rhughes@241
   212
	}
rhughes@241
   213
krh@281
   214
	return razor_package_query_finish(query);
krh@281
   215
}
krh@281
   216
krh@281
   217
#define LIST_PACKAGES_ONLY_NAMES 0x01
krh@281
   218
krh@281
   219
static void
krh@281
   220
list_packages(struct razor_package_iterator *iter, uint32_t flags)
krh@281
   221
{
krh@281
   222
	struct razor_package *package;
krh@281
   223
	const char *name, *version, *arch;
krh@281
   224
krh@281
   225
	while (razor_package_iterator_next(iter, &package,
richard@302
   226
					   RAZOR_DETAIL_NAME, &name,
richard@302
   227
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   228
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   229
					   RAZOR_DETAIL_LAST)) {
krh@281
   230
		if (flags & LIST_PACKAGES_ONLY_NAMES)
rhughes@241
   231
			printf("%s\n", name);
rhughes@241
   232
		else
rhughes@241
   233
			printf("%s-%s.%s\n", name, version, arch);
rhughes@241
   234
	}
krh@281
   235
}
krh@281
   236
krh@281
   237
static int
ali@445
   238
command_list(int argc, char * const argv[])
krh@281
   239
{
ali@445
   240
	int opt;
krh@281
   241
	struct razor_package_iterator *pi;
ali@424
   242
	struct razor_error *error = NULL;
krh@281
   243
	struct razor_set *set;
krh@281
   244
	uint32_t flags = 0;
ali@445
   245
	enum {
ali@445
   246
		opt_only_names = 1,
ali@445
   247
	};
ali@445
   248
	static struct razor_option options[] = {
ali@445
   249
		{ .name = "only-names", .has_arg = no_argument,
ali@445
   250
		  .val = opt_only_names,
ali@445
   251
		  .description = "Only list package names" },
ali@445
   252
	};
krh@281
   253
ali@445
   254
	do {
ali@445
   255
		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
ali@445
   256
				   "pattern ...", NULL);
ali@445
   257
		switch (opt) {
ali@445
   258
			case -2:
ali@445
   259
				return 0;
ali@445
   260
			case -1:
ali@445
   261
				return 1;
ali@445
   262
			case opt_only_names:
ali@445
   263
				flags |= LIST_PACKAGES_ONLY_NAMES;
ali@445
   264
				break;
ali@445
   265
		}
ali@445
   266
	} while (opt);
krh@281
   267
ali@424
   268
	set = razor_root_open_read_only(install_root, &error);
ali@403
   269
	if (set == NULL) {
ali@424
   270
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   271
		razor_error_free(error);
krh@317
   272
		return 1;
ali@403
   273
	}
krh@317
   274
ali@445
   275
	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
krh@281
   276
	list_packages(pi, flags);
rhughes@241
   277
	razor_package_iterator_destroy(pi);
ali@403
   278
	razor_set_unref(set);
rhughes@241
   279
rhughes@241
   280
	return 0;
rhughes@241
   281
}
rhughes@241
   282
krh@306
   283
static void
krh@306
   284
list_package_properties(struct razor_set *set,
krh@306
   285
			struct razor_package *package, uint32_t type)
rhughes@241
   286
{
krh@306
   287
	struct razor_property_iterator *pi;
rhughes@241
   288
	struct razor_property *property;
rhughes@241
   289
	const char *name, *version;
krh@247
   290
	uint32_t flags;
rhughes@241
   291
rhughes@241
   292
	pi = razor_property_iterator_create(set, package);
rhughes@241
   293
	while (razor_property_iterator_next(pi, &property,
krh@247
   294
					    &name, &flags, &version)) {
krh@247
   295
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
rhughes@241
   296
			continue;
krh@247
   297
		printf("%s", name);
krh@247
   298
		if (version[0] != '\0')
krh@247
   299
			printf(" %s %s",
krh@247
   300
			       razor_property_relation_to_string(property),
krh@247
   301
			       version);
krh@247
   302
krh@247
   303
		if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
krh@247
   304
			printf(" [");
krh@247
   305
			if (flags & RAZOR_PROPERTY_PRE)
krh@247
   306
				printf(" pre");
krh@247
   307
			if (flags & RAZOR_PROPERTY_POST)
krh@247
   308
				printf(" post");
krh@247
   309
			if (flags & RAZOR_PROPERTY_PREUN)
krh@247
   310
				printf(" preun");
krh@247
   311
			if (flags & RAZOR_PROPERTY_POSTUN)
krh@247
   312
				printf(" postun");
krh@247
   313
			printf(" ]");
krh@247
   314
		}
krh@247
   315
		printf("\n");
rhughes@241
   316
	}
rhughes@241
   317
	razor_property_iterator_destroy(pi);
krh@306
   318
}
rhughes@241
   319
krh@306
   320
static int
ali@445
   321
list_properties(int argc, char * const argv[], uint32_t type)
krh@306
   322
{
krh@306
   323
	struct razor_set *set;
ali@424
   324
	struct razor_error *error = NULL;
krh@306
   325
	struct razor_package *package;
krh@306
   326
	struct razor_package_iterator *pi;
krh@306
   327
	const char *name, *version, *arch;
krh@306
   328
ali@445
   329
	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
ali@445
   330
		case -2:
ali@445
   331
			return 0;
ali@445
   332
		case -1:
ali@445
   333
			return 1;
ali@445
   334
	}
ali@445
   335
ali@424
   336
	set = razor_root_open_read_only(install_root, &error);
ali@403
   337
	if (set == NULL) {
ali@424
   338
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   339
		razor_error_free(error);
krh@317
   340
		return 1;
ali@403
   341
	}
krh@317
   342
ali@445
   343
	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
krh@306
   344
	while (razor_package_iterator_next(pi, &package,
richard@307
   345
					   RAZOR_DETAIL_NAME, &name,
richard@307
   346
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   347
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   348
					   RAZOR_DETAIL_LAST))
krh@306
   349
		list_package_properties(set, package, type);
krh@306
   350
	razor_package_iterator_destroy(pi);
ali@403
   351
	razor_set_unref(set);
rhughes@241
   352
rhughes@241
   353
	return 0;
rhughes@241
   354
}
rhughes@241
   355
rhughes@241
   356
static int
ali@445
   357
command_list_requires(int argc, char * const argv[])
rhughes@241
   358
{
krh@306
   359
	return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES);
rhughes@241
   360
}
rhughes@241
   361
rhughes@241
   362
static int
ali@445
   363
command_list_provides(int argc, char * const argv[])
rhughes@241
   364
{
krh@306
   365
	return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES);
rhughes@241
   366
}
rhughes@241
   367
rhughes@241
   368
static int
ali@445
   369
command_list_obsoletes(int argc, char * const argv[])
rhughes@241
   370
{
krh@306
   371
	return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES);
rhughes@241
   372
}
rhughes@241
   373
rhughes@241
   374
static int
ali@445
   375
command_list_conflicts(int argc, char * const argv[])
rhughes@241
   376
{
krh@306
   377
	return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS);
rhughes@241
   378
}
rhughes@241
   379
rhughes@241
   380
static int
ali@445
   381
command_list_scripts(int argc, char * const argv[])
ali@369
   382
{
ali@369
   383
	struct razor_set *set;
ali@424
   384
	struct razor_error *error = NULL;
ali@369
   385
	struct razor_package *package;
ali@369
   386
	struct razor_package_iterator *pi;
ali@369
   387
	const char *preunprog, *preun, *postunprog, *postun;
ali@369
   388
ali@445
   389
	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
ali@445
   390
		case -2:
ali@445
   391
			return 0;
ali@445
   392
		case -1:
ali@445
   393
			return 1;
ali@445
   394
	}
ali@445
   395
ali@424
   396
	set = razor_root_open_read_only(install_root, &error);
ali@403
   397
	if (set == NULL) {
ali@424
   398
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   399
		razor_error_free(error);
ali@369
   400
		return 1;
ali@403
   401
	}
ali@369
   402
ali@445
   403
	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
ali@369
   404
	while (razor_package_iterator_next(pi, &package,
ali@369
   405
					   RAZOR_DETAIL_PREUNPROG, &preunprog,
ali@369
   406
					   RAZOR_DETAIL_PREUN, &preun,
ali@369
   407
					   RAZOR_DETAIL_POSTUNPROG, &postunprog,
ali@369
   408
					   RAZOR_DETAIL_POSTUN, &postun,
ali@369
   409
					   RAZOR_DETAIL_LAST)) {
ali@369
   410
		if (preun && *preun) {
ali@369
   411
			printf("preuninstall scriptlet");
ali@369
   412
			if (preunprog && *preunprog)
ali@369
   413
				printf(" (using %s)",preunprog);
ali@369
   414
			printf(":\n%s\n",preun);
ali@369
   415
		}
ali@369
   416
		if (postun && *postun) {
ali@369
   417
			printf("postuninstall scriptlet");
ali@369
   418
			if (postunprog && *postunprog)
ali@369
   419
				printf(" (using %s)",postunprog);
ali@369
   420
			printf(":\n%s\n",postun);
ali@369
   421
		}
ali@369
   422
	}
ali@369
   423
	razor_package_iterator_destroy(pi);
ali@403
   424
	razor_set_unref(set);
ali@369
   425
ali@369
   426
	return 0;
ali@369
   427
}
ali@369
   428
ali@369
   429
static int
ali@445
   430
command_list_files(int argc, char * const argv[])
rhughes@241
   431
{
ali@424
   432
	struct razor_error *error = NULL;
rhughes@241
   433
	struct razor_set *set;
rhughes@241
   434
ali@445
   435
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
   436
		case -2:
ali@445
   437
			return 0;
ali@445
   438
		case -1:
ali@445
   439
			return 1;
ali@445
   440
	}
ali@445
   441
ali@445
   442
	if (argc - optind > 1) {
ali@445
   443
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
   444
		return 1;
ali@445
   445
	}
ali@445
   446
ali@424
   447
	set = razor_root_open_read_only(install_root, &error);
ali@403
   448
	if (set == NULL) {
ali@424
   449
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   450
		razor_error_free(error);
rhughes@241
   451
		return 1;
ali@403
   452
	}
krh@317
   453
ali@445
   454
	razor_set_list_files(set, argv[optind]);
ali@403
   455
	razor_set_unref(set);
rhughes@241
   456
rhughes@241
   457
	return 0;
rhughes@241
   458
}
rhughes@241
   459
rhughes@241
   460
static int
ali@445
   461
command_list_file_packages(int argc, char * const argv[])
rhughes@241
   462
{
ali@424
   463
	struct razor_error *error = NULL;
rhughes@241
   464
	struct razor_set *set;
rhughes@241
   465
	struct razor_package_iterator *pi;
rhughes@241
   466
ali@445
   467
	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
ali@445
   468
		case -2:
ali@445
   469
			return 0;
ali@445
   470
		case -1:
ali@445
   471
			return 1;
ali@445
   472
	}
ali@445
   473
ali@445
   474
	if (argc - optind != 1) {
ali@445
   475
		razor_usage(argv[0], 0, NULL, "pattern");
ali@445
   476
		return 1;
ali@445
   477
	}
ali@445
   478
ali@424
   479
	set = razor_root_open_read_only(install_root, &error);
ali@403
   480
	if (set == NULL) {
ali@424
   481
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   482
		razor_error_free(error);
rhughes@241
   483
		return 1;
ali@403
   484
	}
rhughes@241
   485
ali@445
   486
	pi = razor_package_iterator_create_for_file(set, argv[optind]);
krh@281
   487
	list_packages(pi, 0);
rhughes@241
   488
	razor_package_iterator_destroy(pi);
rhughes@241
   489
ali@403
   490
	razor_set_unref(set);
rhughes@241
   491
rhughes@241
   492
	return 0;
rhughes@241
   493
}
rhughes@241
   494
rhughes@241
   495
static int
ali@445
   496
command_list_package_files(int argc, char * const argv[])
rhughes@241
   497
{
ali@424
   498
	struct razor_error *error = NULL;
rhughes@241
   499
	struct razor_set *set;
krh@306
   500
	struct razor_package_iterator *pi;
krh@306
   501
	struct razor_package *package;
krh@306
   502
	const char *name, *version, *arch;
rhughes@241
   503
ali@445
   504
	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
ali@445
   505
		case -2:
ali@445
   506
			return 0;
ali@445
   507
		case -1:
ali@445
   508
			return 1;
ali@445
   509
	}
ali@445
   510
ali@424
   511
	set = razor_root_open_read_only(install_root, &error);
ali@403
   512
	if (set == NULL) {
ali@424
   513
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   514
		razor_error_free(error);
rhughes@241
   515
		return 1;
ali@403
   516
	}
jbowes@288
   517
ali@445
   518
	pi = create_iterator_from_argv(set, argc - optind, argv + optind);
krh@306
   519
	while (razor_package_iterator_next(pi, &package,
richard@307
   520
					   RAZOR_DETAIL_NAME, &name,
richard@307
   521
					   RAZOR_DETAIL_VERSION, &version,
richard@307
   522
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
   523
					   RAZOR_DETAIL_LAST))
krh@306
   524
		razor_set_list_package_files(set, package);
krh@306
   525
	razor_package_iterator_destroy(pi);
krh@306
   526
ali@403
   527
	razor_set_unref(set);
rhughes@241
   528
rhughes@241
   529
	return 0;
rhughes@241
   530
}
rhughes@241
   531
rhughes@241
   532
static int
rhughes@241
   533
list_property_packages(const char *ref_name,
rhughes@241
   534
		       const char *ref_version,
krh@247
   535
		       uint32_t type)
rhughes@241
   536
{
ali@424
   537
	struct razor_error *error = NULL;
rhughes@241
   538
	struct razor_set *set;
rhughes@241
   539
	struct razor_property *property;
krh@281
   540
	struct razor_property_iterator *prop_iter;
krh@281
   541
	struct razor_package_iterator *pkg_iter;
rhughes@241
   542
	const char *name, *version;
krh@247
   543
	uint32_t flags;
rhughes@241
   544
ali@424
   545
	set = razor_root_open_read_only(install_root, &error);
ali@403
   546
	if (set == NULL) {
ali@424
   547
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   548
		razor_error_free(error);
rhughes@241
   549
		return 1;
ali@403
   550
	}
rhughes@241
   551
krh@281
   552
	prop_iter = razor_property_iterator_create(set, NULL);
krh@281
   553
	while (razor_property_iterator_next(prop_iter, &property,
krh@247
   554
					    &name, &flags, &version)) {
rhughes@241
   555
		if (strcmp(ref_name, name) != 0)
rhughes@241
   556
			continue;
krh@247
   557
		if (ref_version &&
krh@247
   558
		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
rhughes@241
   559
		    strcmp(ref_version, version) != 0)
rhughes@241
   560
			continue;
krh@247
   561
		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
rhughes@241
   562
			continue;
rhughes@241
   563
krh@281
   564
		pkg_iter =
krh@281
   565
			razor_package_iterator_create_for_property(set,
krh@281
   566
								   property);
krh@281
   567
		list_packages(pkg_iter, 0);
krh@281
   568
		razor_package_iterator_destroy(pkg_iter);
rhughes@241
   569
	}
krh@281
   570
	razor_property_iterator_destroy(prop_iter);
rhughes@241
   571
ali@403
   572
	razor_set_unref(set);
krh@317
   573
rhughes@241
   574
	return 0;
rhughes@241
   575
}
rhughes@241
   576
rhughes@241
   577
static int
ali@445
   578
command_what_requires(int argc, char * const argv[])
rhughes@241
   579
{
ali@445
   580
	switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
ali@445
   581
			     NULL)) {
ali@445
   582
		case -2:
ali@445
   583
			return 0;
ali@445
   584
		case -1:
ali@445
   585
			return 1;
ali@445
   586
	}
ali@445
   587
ali@445
   588
	if (argc - optind < 1 || argc - optind > 2) {
ali@445
   589
		razor_usage(argv[0], 0, NULL, "name [version-release]");
ali@445
   590
		return 1;
ali@445
   591
	}
ali@445
   592
ali@445
   593
	return list_property_packages(argv[optind], argv[optind + 1],
rhughes@241
   594
				      RAZOR_PROPERTY_REQUIRES);
rhughes@241
   595
}
rhughes@241
   596
rhughes@241
   597
static int
ali@445
   598
command_what_provides(int argc, char * const argv[])
rhughes@241
   599
{
ali@445
   600
	switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
ali@445
   601
			     NULL)) {
ali@445
   602
		case -2:
ali@445
   603
			return 0;
ali@445
   604
		case -1:
ali@445
   605
			return 1;
ali@445
   606
	}
ali@445
   607
ali@445
   608
	if (argc - optind < 1 || argc - optind > 2) {
ali@445
   609
		razor_usage(argv[0], 0, NULL, "name [version-release]");
ali@445
   610
		return 1;
ali@445
   611
	}
ali@445
   612
ali@445
   613
	return list_property_packages(argv[optind], argv[optind + 1],
rhughes@241
   614
				      RAZOR_PROPERTY_PROVIDES);
rhughes@241
   615
}
rhughes@241
   616
ali@455
   617
#ifndef HAVE_CURL
ali@455
   618
static int
ali@455
   619
download_local(const char *url, const char *file)
ali@455
   620
{
ali@455
   621
	FILE *wfp, *rfp;
ali@455
   622
	char buffer[256], *ptr, *local;
ali@455
   623
	size_t nb, n;
ali@455
   624
ali@455
   625
	local = razor_path_from_url(url);
ali@455
   626
ali@455
   627
	if (local == NULL) {
ali@455
   628
		fprintf(stderr,
ali@455
   629
			"%s: download manually (curl not available)\n",
ali@455
   630
			file);
ali@455
   631
		return -1;
ali@455
   632
	} else {
ali@455
   633
		rfp = fopen(local, "rb");
ali@455
   634
		if (rfp == NULL) {
ali@455
   635
			perror(local);
ali@455
   636
			free(local);
ali@455
   637
			return -1;
ali@455
   638
		}
ali@455
   639
ali@455
   640
		wfp = fopen(file, "wb");
ali@455
   641
		if (wfp == NULL) {
ali@455
   642
			perror(file);
ali@455
   643
			fclose(rfp);
ali@455
   644
			free(local);
ali@455
   645
			return -1;
ali@455
   646
		}
ali@455
   647
ali@455
   648
		while((nb = fread(buffer, 1, sizeof(buffer), rfp)) > 0) {
ali@455
   649
			ptr = buffer;
ali@455
   650
			while (nb > 0 && (n = fwrite(ptr, 1, nb, wfp)) > 0) {
ali@455
   651
				ptr += n;
ali@455
   652
				nb -= n;
ali@455
   653
			}
ali@455
   654
ali@455
   655
			if (nb != 0) {
ali@455
   656
				perror(file);
ali@455
   657
				fclose(wfp);
ali@455
   658
				fclose(rfp);
ali@455
   659
				unlink(file);
ali@455
   660
				free(local);
ali@455
   661
				return -1;
ali@455
   662
			}
ali@455
   663
		}
ali@455
   664
ali@455
   665
		if (ferror(rfp)) {
ali@455
   666
			perror(local);
ali@455
   667
			fclose(wfp);
ali@455
   668
			fclose(rfp);
ali@455
   669
			unlink(file);
ali@455
   670
			free(local);
ali@455
   671
			return -1;
ali@455
   672
		}
ali@455
   673
ali@455
   674
		fclose(wfp);
ali@455
   675
		fclose(rfp);
ali@455
   676
		free(local);
ali@455
   677
		return 0;
ali@455
   678
	}
ali@455
   679
}
ali@455
   680
#endif /* !HAVE_CURL */
ali@455
   681
ali@442
   682
#ifdef HAVE_CURL
rhughes@241
   683
static int
rhughes@241
   684
show_progress(void *clientp,
rhughes@241
   685
	      double dltotal, double dlnow, double ultotal, double ulnow)
rhughes@241
   686
{
rhughes@241
   687
	const char *file = clientp;
rhughes@241
   688
rhughes@241
   689
	if (!dlnow < dltotal)
rhughes@241
   690
		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
rhughes@241
   691
			file, (int) dlnow / 1024, (int) dltotal / 1024);
rhughes@241
   692
rhughes@241
   693
	return 0;
rhughes@241
   694
}
rhughes@241
   695
rhughes@241
   696
static int
ali@455
   697
download_with_curl(const char *url, const char *file)
rhughes@241
   698
{
ali@455
   699
	FILE *fp;
rhughes@241
   700
	CURL *curl;
rhughes@241
   701
	char error[256];
rhughes@241
   702
	CURLcode res;
rhughes@241
   703
	long response;
rhughes@241
   704
rhughes@241
   705
	curl = curl_easy_init();
ali@455
   706
	if (curl == NULL) {
ali@455
   707
		fprintf(stderr,
ali@455
   708
			"%s: download manually (curl failed)\n", file);
ali@455
   709
		return -1;
ali@455
   710
	}
rhughes@241
   711
rhughes@241
   712
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
rhughes@241
   713
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
rhughes@241
   714
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
rhughes@241
   715
	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
rhughes@241
   716
ali@455
   717
	fp = fopen(file, "wb");
ali@455
   718
	if (fp == NULL) {
ali@455
   719
		perror(file);
ali@455
   720
		return -1;
rhughes@241
   721
	}
ali@455
   722
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
ali@455
   723
	curl_easy_setopt(curl, CURLOPT_URL, url);
ali@455
   724
	res = curl_easy_perform(curl);
ali@455
   725
	fclose(fp);
ali@455
   726
	if (res != CURLE_OK) {
ali@455
   727
		fprintf(stderr, "curl error: %s\n", error);
ali@455
   728
		unlink(file);
ali@455
   729
		return -1;
ali@455
   730
	}
ali@455
   731
	res = curl_easy_getinfo(curl,
ali@455
   732
				CURLINFO_RESPONSE_CODE, &response);
ali@455
   733
	if (res != CURLE_OK) {
ali@455
   734
		fprintf(stderr, "curl error: %s\n", error);
ali@455
   735
		unlink(file);
ali@455
   736
		return -1;
ali@455
   737
	}
ali@455
   738
	if (response != 200) {
ali@455
   739
		fprintf(stderr, " - failed %ld\n", response);
ali@455
   740
		unlink(file);
ali@455
   741
		return -1;
ali@455
   742
	}
ali@455
   743
	fprintf(stderr, "\n");
rhughes@241
   744
	curl_easy_cleanup(curl);
rhughes@241
   745
rhughes@241
   746
	return 0;
ali@455
   747
}
ali@321
   748
#endif	/* HAVE_CURL */
ali@455
   749
ali@455
   750
static int
ali@455
   751
download_if_missing(const char *url, const char *file)
ali@455
   752
{
ali@455
   753
	struct stat buf;
ali@455
   754
ali@455
   755
	if (stat(file, &buf) >= 0)
ali@455
   756
		return 0;
ali@455
   757
ali@455
   758
#ifndef HAVE_CURL
ali@455
   759
	return download_local(url, file);
ali@455
   760
#else
ali@455
   761
	return download_with_curl(url, file);
ali@455
   762
#endif
rhughes@241
   763
}
rhughes@241
   764
rhughes@241
   765
#define YUM_URL "http://download.fedora.redhat.com" \
rhughes@241
   766
	"/pub/fedora/linux/development/i386/os"
rhughes@241
   767
rhughes@241
   768
static int
ali@445
   769
command_import_yum(int argc, char * const argv[])
rhughes@241
   770
{
ali@403
   771
	int retval;
rhughes@241
   772
	struct razor_set *set;
ali@403
   773
	struct razor_atomic *atomic;
rhughes@241
   774
	char buffer[512];
rhughes@241
   775
ali@445
   776
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   777
		case -2:
ali@445
   778
			return 0;
ali@445
   779
		case -1:
ali@445
   780
			return 1;
ali@445
   781
	}
ali@445
   782
ali@445
   783
	if (argc - optind > 0) {
ali@445
   784
		razor_usage(argv[0], 0, NULL, "");
ali@445
   785
		return 1;
ali@445
   786
	}
ali@445
   787
ali@455
   788
	printf("downloading from '%s'.\n", yum_url);
rhughes@241
   789
	snprintf(buffer, sizeof buffer,
rhughes@241
   790
		 "%s/repodata/primary.xml.gz", yum_url);
rhughes@241
   791
	if (download_if_missing(buffer, "primary.xml.gz") < 0)
rhughes@241
   792
		return -1;
rhughes@241
   793
	snprintf(buffer, sizeof buffer,
rhughes@241
   794
		 "%s/repodata/filelists.xml.gz", yum_url);
rhughes@241
   795
	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
rhughes@241
   796
		return -1;
rhughes@241
   797
rhughes@241
   798
	set = razor_set_create_from_yum();
rhughes@241
   799
	if (set == NULL)
rhughes@241
   800
		return 1;
ali@403
   801
	atomic = razor_atomic_open("Yum import repository");
ali@403
   802
	razor_set_write(set, atomic, rawhide_repo_filename, RAZOR_SECTION_ALL);
ali@403
   803
	retval = razor_atomic_commit(atomic);
ali@403
   804
	razor_set_unref(set);
ali@403
   805
	if (retval)
ali@403
   806
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
   807
	else
ali@403
   808
		printf("wrote %s\n", rawhide_repo_filename);
ali@403
   809
	razor_atomic_destroy(atomic);
rhughes@241
   810
ali@403
   811
	return retval;
rhughes@241
   812
}
rhughes@241
   813
ali@320
   814
#if HAVE_RPMLIB
rhughes@241
   815
static int
ali@445
   816
command_import_rpmdb(int argc, char * const argv[])
rhughes@241
   817
{
rhughes@241
   818
	struct razor_set *set;
krh@317
   819
	struct razor_root *root;
ali@424
   820
	struct razor_error *error = NULL;
ali@403
   821
	struct razor_atomic *atomic;
ali@403
   822
	int retval;
krh@317
   823
ali@445
   824
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   825
		case -2:
ali@445
   826
			return 0;
ali@445
   827
		case -1:
ali@445
   828
			return 1;
ali@445
   829
	}
ali@445
   830
ali@445
   831
	if (argc - optind > 0) {
ali@445
   832
		razor_usage(argv[0], 0, NULL, "");
ali@445
   833
		return 1;
ali@445
   834
	}
ali@445
   835
ali@424
   836
	root = razor_root_open(install_root, &error);
ali@403
   837
	if (root == NULL) {
ali@424
   838
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   839
		razor_error_free(error);
krh@317
   840
		return 1;
ali@403
   841
	}
rhughes@241
   842
rhughes@241
   843
	set = razor_set_create_from_rpmdb();
rhughes@241
   844
	if (set == NULL)
rhughes@241
   845
		return 1;
rhughes@241
   846
ali@424
   847
	atomic = razor_atomic_open("Import RPM database");
krh@317
   848
ali@424
   849
	retval = razor_root_update(root, set, atomic);
ali@424
   850
ali@403
   851
	if (retval)
ali@403
   852
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
   853
ali@403
   854
	razor_atomic_destroy(atomic);
ali@403
   855
ali@424
   856
	razor_root_close(root);
ali@424
   857
ali@403
   858
	return retval;
rhughes@241
   859
}
ali@320
   860
#endif
rhughes@241
   861
rhughes@241
   862
static int
rhughes@241
   863
mark_packages_for_update(struct razor_transaction *trans,
rhughes@241
   864
			 struct razor_set *set, const char *pattern)
rhughes@241
   865
{
rhughes@241
   866
	struct razor_package_iterator *pi;
rhughes@241
   867
	struct razor_package *package;
richard@302
   868
	const char *name;
rhughes@241
   869
	int matches = 0;
rhughes@241
   870
rhughes@241
   871
	pi = razor_package_iterator_create(set);
rhughes@241
   872
	while (razor_package_iterator_next(pi, &package,
richard@307
   873
					   RAZOR_DETAIL_NAME, &name,
richard@307
   874
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   875
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   876
			razor_transaction_update_package(trans, package);
rhughes@241
   877
			matches++;
rhughes@241
   878
		}
rhughes@241
   879
	}
rhughes@241
   880
	razor_package_iterator_destroy(pi);
rhughes@241
   881
rhughes@241
   882
	return matches;
rhughes@241
   883
}
rhughes@241
   884
rhughes@241
   885
static int
rhughes@241
   886
mark_packages_for_removal(struct razor_transaction *trans,
rhughes@241
   887
			  struct razor_set *set, const char *pattern)
rhughes@241
   888
{
rhughes@241
   889
	struct razor_package_iterator *pi;
rhughes@241
   890
	struct razor_package *package;
richard@302
   891
	const char *name;
rhughes@241
   892
	int matches = 0;
rhughes@241
   893
rhughes@241
   894
	pi = razor_package_iterator_create(set);
richard@307
   895
	while (razor_package_iterator_next(pi, &package,
richard@307
   896
					   RAZOR_DETAIL_NAME, &name,
richard@307
   897
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   898
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   899
			razor_transaction_remove_package(trans, package);
rhughes@241
   900
			matches++;
rhughes@241
   901
		}
rhughes@241
   902
	}
rhughes@241
   903
	razor_package_iterator_destroy(pi);
rhughes@241
   904
rhughes@241
   905
	return matches;
rhughes@241
   906
}
rhughes@241
   907
rhughes@241
   908
static int
ali@445
   909
command_remove(int argc, char * const argv[])
rhughes@241
   910
{
ali@363
   911
	struct razor_set *system, *upstream, *next;
rhughes@241
   912
	struct razor_transaction *trans;
ali@424
   913
	struct razor_error *error = NULL;
ali@424
   914
	struct razor_root *root;
ali@403
   915
	int i, retval;
rhughes@241
   916
ali@445
   917
	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
ali@445
   918
		case -2:
ali@445
   919
			return 0;
ali@445
   920
		case -1:
ali@445
   921
			return 1;
ali@445
   922
	}
ali@445
   923
ali@424
   924
	root = razor_root_open(install_root, &error);
ali@424
   925
	if (root == NULL) {
ali@424
   926
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   927
		razor_error_free(error);
rhughes@241
   928
		return 1;
ali@363
   929
	}
rhughes@241
   930
ali@424
   931
	system = razor_root_get_system_set(root);
ali@363
   932
	upstream = razor_set_create_without_root();
ali@363
   933
	trans = razor_transaction_create(system, upstream);
ali@403
   934
	razor_set_unref(upstream);
ali@445
   935
	for (i = optind; i < argc; i++) {
ali@363
   936
		if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
rhughes@241
   937
			fprintf(stderr, "no match for %s\n", argv[i]);
ali@363
   938
			razor_transaction_destroy(trans);
ali@424
   939
			razor_root_close(root);
rhughes@241
   940
			return 1;
rhughes@241
   941
		}
rhughes@241
   942
	}
rhughes@241
   943
ali@350
   944
	razor_transaction_resolve(trans);
ali@403
   945
	retval = razor_transaction_describe(trans);
ali@403
   946
	if (retval) {
ali@363
   947
		razor_transaction_destroy(trans);
ali@424
   948
		razor_root_close(root);
rhughes@241
   949
		return 1;
ali@363
   950
	}
rhughes@241
   951
ali@369
   952
	next = razor_transaction_commit(trans);
ali@403
   953
ali@424
   954
	retval = update_system(root, NULL, trans, next, "Remove");
ali@363
   955
ali@369
   956
	razor_transaction_destroy(trans);
ali@424
   957
	razor_root_close(root);
ali@403
   958
	razor_set_unref(next);
rhughes@241
   959
ali@403
   960
	return retval;
rhughes@241
   961
}
rhughes@241
   962
rhughes@241
   963
static void
krh@253
   964
print_diff(enum razor_diff_action action,
krh@253
   965
	   struct razor_package *package,
krh@253
   966
	   const char *name,
krh@253
   967
	   const char *version,
krh@253
   968
	   const char *arch,
rhughes@241
   969
	   void *data)
rhughes@241
   970
{
krh@253
   971
	if (action == RAZOR_DIFF_ACTION_ADD)
krh@253
   972
		printf("install %s-%s.%s\n", name, version, arch);
krh@253
   973
	if (action == RAZOR_DIFF_ACTION_REMOVE)
krh@253
   974
		printf("remove %s-%s.%s\n", name, version, arch);
rhughes@241
   975
}
rhughes@241
   976
rhughes@241
   977
static int
ali@445
   978
command_diff(int argc, char * const argv[])
rhughes@241
   979
{
ali@424
   980
	struct razor_error *error = NULL;
rhughes@241
   981
	struct razor_set *set, *updated;
rhughes@241
   982
ali@445
   983
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   984
		case -2:
ali@445
   985
			return 0;
ali@445
   986
		case -1:
ali@445
   987
			return 1;
ali@445
   988
	}
ali@445
   989
ali@445
   990
	if (argc - optind > 0) {
ali@445
   991
		razor_usage(argv[0], 0, NULL, "");
ali@445
   992
		return 1;
ali@445
   993
	}
ali@445
   994
ali@424
   995
	set = razor_root_open_read_only(install_root, &error);
ali@424
   996
	if (set)
ali@424
   997
		updated = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
   998
	else
ali@424
   999
		updated = NULL;
ali@424
  1000
	if (updated == NULL) {
ali@424
  1001
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1002
		razor_error_free(error);
ali@424
  1003
		if (set)
ali@424
  1004
			razor_set_unref(set);
rhughes@241
  1005
		return 1;
ali@403
  1006
	}
rhughes@241
  1007
rhughes@241
  1008
	razor_set_diff(set, updated, print_diff, NULL);
rhughes@241
  1009
ali@403
  1010
	razor_set_unref(set);
ali@403
  1011
	razor_set_unref(updated);
rhughes@241
  1012
rhughes@241
  1013
	return 0;
rhughes@241
  1014
}
rhughes@241
  1015
rhughes@241
  1016
static int
ali@445
  1017
command_import_rpms(int argc, char * const argv[])
rhughes@241
  1018
{
rhughes@241
  1019
	DIR *dir;
rhughes@241
  1020
	struct dirent *de;
rhughes@241
  1021
	struct razor_importer *importer;
rhughes@241
  1022
	struct razor_set *set;
rhughes@241
  1023
	struct razor_rpm *rpm;
ali@426
  1024
	struct razor_error *error=NULL;
ali@403
  1025
	struct razor_atomic *atomic;
jbowes@263
  1026
	int len, imported_count = 0;
rhughes@241
  1027
	char filename[256];
ali@445
  1028
	const char *dirname;
ali@403
  1029
	int retval;
rhughes@241
  1030
ali@445
  1031
	switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) {
ali@445
  1032
		case -2:
ali@445
  1033
			return 0;
ali@445
  1034
		case -1:
ali@445
  1035
			return 1;
rhughes@241
  1036
	}
rhughes@241
  1037
ali@445
  1038
	if (argc - optind != 1) {
ali@445
  1039
		razor_usage(argv[0], 0, NULL, "dir");
ali@445
  1040
		return 1;
ali@445
  1041
	}
ali@445
  1042
ali@445
  1043
	dirname = argv[optind];
ali@445
  1044
rhughes@241
  1045
	dir = opendir(dirname);
rhughes@241
  1046
	if (dir == NULL) {
rhughes@241
  1047
		fprintf(stderr, "couldn't read dir %s\n", dirname);
rhughes@241
  1048
		return -1;
rhughes@241
  1049
	}
rhughes@241
  1050
krh@249
  1051
	importer = razor_importer_create();
rhughes@241
  1052
rhughes@241
  1053
	while (de = readdir(dir), de != NULL) {
rhughes@241
  1054
		len = strlen(de->d_name);
rhughes@241
  1055
		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
ali@403
  1056
			continue;
rhughes@241
  1057
		snprintf(filename, sizeof filename,
rhughes@241
  1058
			 "%s/%s", dirname, de->d_name);
ali@426
  1059
		rpm = razor_rpm_open(filename, &error);
ali@426
  1060
		if (rpm == NULL) {
ali@426
  1061
			fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@426
  1062
			razor_error_free(error);
ali@426
  1063
			error=NULL;
rhughes@241
  1064
			continue;
ali@426
  1065
		}
rhughes@241
  1066
		if (razor_importer_add_rpm(importer, rpm)) {
rhughes@241
  1067
			fprintf(stderr, "couldn't import %s\n", filename);
rhughes@241
  1068
			break;
rhughes@241
  1069
		}
rhughes@241
  1070
		razor_rpm_close(rpm);
jbowes@263
  1071
jbowes@263
  1072
		printf("\rimporting %d", ++imported_count);
jbowes@263
  1073
		fflush(stdout);
rhughes@241
  1074
	}
rhughes@241
  1075
rhughes@241
  1076
	if (de != NULL) {
rhughes@241
  1077
		razor_importer_destroy(importer);
rhughes@241
  1078
		return -1;
rhughes@241
  1079
	}
rhughes@241
  1080
jbowes@263
  1081
	printf("\nsaving\n");
rhughes@241
  1082
	set = razor_importer_finish(importer);
rhughes@241
  1083
ali@403
  1084
	atomic = razor_atomic_open("Update system database");
ali@403
  1085
	razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
ali@403
  1086
	razor_set_unref(set);
ali@403
  1087
	retval = razor_atomic_commit(atomic);
ali@403
  1088
	if (retval)
ali@403
  1089
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1090
	else
ali@403
  1091
		printf("wrote %s\n", repo_filename);
ali@403
  1092
	razor_atomic_destroy(atomic);
rhughes@241
  1093
ali@403
  1094
	return retval;
rhughes@241
  1095
}
rhughes@241
  1096
ali@403
  1097
static char *
krh@254
  1098
rpm_filename(const char *name, const char *version, const char *arch)
rhughes@241
  1099
{
krh@254
  1100
 	const char *v;
krh@254
  1101
 
krh@254
  1102
 	/* Skip epoch */
krh@253
  1103
	v = strchr(version, ':');
krh@254
  1104
 	if (v != NULL)
krh@254
  1105
 		v = v + 1;
krh@254
  1106
 	else
krh@253
  1107
		v = version;
rhughes@241
  1108
ali@403
  1109
	return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
rhughes@241
  1110
}
rhughes@241
  1111
krh@254
  1112
static int
krh@254
  1113
download_packages(struct razor_set *system, struct razor_set *next)
rhughes@241
  1114
{
krh@316
  1115
	struct razor_install_iterator *ii;
krh@254
  1116
	struct razor_package *package;
krh@316
  1117
	enum razor_install_action action;
krh@254
  1118
	const char *name, *version, *arch;
ali@403
  1119
	char *file, *url, *s;
krh@316
  1120
	int errors = 0, count;
krh@316
  1121
krh@316
  1122
	ii = razor_set_create_install_iterator(system, next);
ali@382
  1123
	while (razor_install_iterator_next(ii, &package, &action, &count)) {
ali@418
  1124
		if (action != RAZOR_INSTALL_ACTION_ADD)
krh@316
  1125
			continue;
krh@316
  1126
ali@382
  1127
		razor_package_get_details(next, package,
krh@316
  1128
					  RAZOR_DETAIL_NAME, &name,
krh@316
  1129
					  RAZOR_DETAIL_VERSION, &version,
krh@316
  1130
					  RAZOR_DETAIL_ARCH, &arch,
krh@316
  1131
					  RAZOR_DETAIL_LAST);
krh@316
  1132
		
ali@403
  1133
		s = rpm_filename(name, version, arch);
ali@403
  1134
		url = razor_concat(yum_url, "/Packages/", s, NULL);
ali@403
  1135
		file = razor_concat("rpms/", s, NULL);
ali@403
  1136
		free(s);
krh@254
  1137
		if (download_if_missing(url, file) < 0)
krh@254
  1138
			errors++;
ali@403
  1139
		free(file);
ali@403
  1140
		free(url);
krh@254
  1141
	}
krh@316
  1142
	razor_install_iterator_destroy(ii);
krh@254
  1143
krh@254
  1144
	if (errors > 0) {
krh@254
  1145
		fprintf(stderr, "failed to download %d packages\n", errors);
krh@254
  1146
                return -1;
krh@254
  1147
        }
krh@254
  1148
krh@254
  1149
	return 0;
krh@254
  1150
}
krh@254
  1151
ali@351
  1152
static struct razor_set *
ali@403
  1153
relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
ali@403
  1154
		  struct razor_relocations *relocations)
ali@351
  1155
{
ali@372
  1156
	int i;
ali@351
  1157
	struct razor_importer *importer;
ali@351
  1158
	struct razor_property_iterator *prop_iter;
ali@351
  1159
	struct razor_package_iterator *pkg_iter;
ali@351
  1160
 	struct razor_file_iterator *file_iter;
ali@351
  1161
 	struct razor_package *package;
ali@351
  1162
	struct razor_property *property;
ali@351
  1163
	struct razor_rpm *rpm;
ali@426
  1164
	struct razor_error *error=NULL;
ali@351
  1165
	const char *name, *version, *arch, *summary, *desc, *url, *license;
ali@369
  1166
	const char *preunprog, *preun, *postunprog, *postun;
ali@372
  1167
	const char *install_prefix;
ali@372
  1168
	const char *const *prefixes;
ali@403
  1169
	char *file, *s;
ali@351
  1170
	uint32_t flags;
ali@351
  1171
ali@351
  1172
	importer = razor_importer_create();
ali@351
  1173
	pkg_iter = razor_package_iterator_create(set);
ali@351
  1174
ali@351
  1175
	while (razor_package_iterator_next(pkg_iter, &package,
ali@351
  1176
					   RAZOR_DETAIL_NAME, &name,
ali@351
  1177
					   RAZOR_DETAIL_VERSION, &version,
ali@351
  1178
					   RAZOR_DETAIL_ARCH, &arch,
ali@351
  1179
					   RAZOR_DETAIL_SUMMARY, &summary,
ali@351
  1180
					   RAZOR_DETAIL_DESCRIPTION, &desc,
ali@351
  1181
					   RAZOR_DETAIL_URL, &url,
ali@351
  1182
					   RAZOR_DETAIL_LICENSE, &license,
ali@369
  1183
					   RAZOR_DETAIL_PREUNPROG, &preunprog,
ali@369
  1184
					   RAZOR_DETAIL_PREUN, &preun,
ali@369
  1185
					   RAZOR_DETAIL_POSTUNPROG, &postunprog,
ali@369
  1186
					   RAZOR_DETAIL_POSTUN, &postun,
ali@351
  1187
					   RAZOR_DETAIL_LAST)) {
ali@403
  1188
		s = rpm_filename(name, version, arch);
ali@403
  1189
		file = razor_concat("rpms/", s, NULL);
ali@403
  1190
		free(s);
ali@426
  1191
		rpm = razor_rpm_open(file, &error);
ali@403
  1192
		free(file);
ali@351
  1193
		if (rpm == NULL) {
ali@447
  1194
			razor_atomic_propagate_error(atomic, error, NULL);
ali@426
  1195
			razor_error_free(error);
ali@351
  1196
			razor_package_iterator_destroy(pkg_iter);
ali@351
  1197
			razor_importer_destroy(importer);
ali@351
  1198
			return NULL;
ali@351
  1199
		}
ali@351
  1200
ali@351
  1201
		razor_relocations_set_rpm(relocations, rpm);
ali@351
  1202
ali@351
  1203
		razor_importer_begin_package(importer, name, version, arch);
ali@351
  1204
		razor_importer_add_details(importer,
ali@351
  1205
					   summary, desc, url, license);
ali@351
  1206
ali@372
  1207
		razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
ali@372
  1208
				      RAZOR_DETAIL_LAST);
ali@372
  1209
		for (i = 0; prefixes && prefixes[i]; i++) {
ali@372
  1210
			install_prefix = razor_relocations_apply(relocations,
ali@372
  1211
								 prefixes[i]);
ali@372
  1212
			razor_importer_add_install_prefix(importer,
ali@372
  1213
							  install_prefix);
ali@372
  1214
		}
ali@372
  1215
ali@372
  1216
		razor_rpm_close(rpm);
ali@372
  1217
ali@351
  1218
		prop_iter = razor_property_iterator_create(set, package);
ali@351
  1219
		while (razor_property_iterator_next(prop_iter, &property,
ali@351
  1220
						    &name, &flags, &version))
ali@351
  1221
			razor_importer_add_property(importer,
ali@351
  1222
						    name, flags, version);
ali@351
  1223
		razor_property_iterator_destroy(prop_iter);
ali@351
  1224
ali@377
  1225
		file_iter = razor_file_iterator_create(set, package, 0);
ali@351
  1226
		while (razor_file_iterator_next(file_iter, &name)) {
ali@351
  1227
			name = razor_relocations_apply(relocations, name);
ali@351
  1228
			razor_importer_add_file(importer, name);
ali@351
  1229
		}
ali@351
  1230
		razor_file_iterator_destroy(file_iter);
ali@351
  1231
ali@369
  1232
		razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
ali@369
  1233
					  preunprog, preun);
ali@369
  1234
		razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
ali@369
  1235
					  postunprog, postun);
ali@369
  1236
ali@351
  1237
		razor_importer_finish_package(importer);
ali@351
  1238
	}
ali@351
  1239
ali@351
  1240
	razor_package_iterator_destroy(pkg_iter);
ali@351
  1241
	return razor_importer_finish(importer);
ali@351
  1242
}
ali@351
  1243
krh@254
  1244
static int
ali@369
  1245
install_package(struct razor_transaction *trans, struct razor_set *set,
ali@403
  1246
		struct razor_atomic *atomic, struct razor_package *package,
ali@403
  1247
		struct razor_relocations *relocations, int install_count,
ali@403
  1248
		enum razor_stage_type stage)
ali@363
  1249
{
ali@363
  1250
	int retval;
ali@363
  1251
	const char *name, *version, *arch;
ali@403
  1252
	char *file, *s;
ali@363
  1253
	struct razor_rpm *rpm;
ali@426
  1254
	struct razor_error *error=NULL;
ali@363
  1255
ali@363
  1256
	razor_package_get_details(set, package,
ali@363
  1257
				  RAZOR_DETAIL_NAME, &name,
ali@363
  1258
				  RAZOR_DETAIL_VERSION, &version,
ali@363
  1259
				  RAZOR_DETAIL_ARCH, &arch,
ali@363
  1260
				  RAZOR_DETAIL_LAST);
ali@363
  1261
ali@403
  1262
	if (stage & RAZOR_STAGE_SCRIPTS_PRE)
ali@403
  1263
		printf("install %s-%s\n", name, version);
ali@363
  1264
ali@403
  1265
	s = rpm_filename(name, version, arch);
ali@403
  1266
	file = razor_concat("rpms/", s, NULL);
ali@403
  1267
	free(s);
ali@426
  1268
	rpm = razor_rpm_open(file, &error);
ali@403
  1269
	free(file);
ali@363
  1270
	if (rpm == NULL) {
ali@447
  1271
		razor_atomic_propagate_error(atomic, error, NULL);
ali@426
  1272
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@426
  1273
		razor_error_free(error);
ali@363
  1274
		return -1;
ali@363
  1275
	}
ali@363
  1276
	if (relocations)
ali@363
  1277
		razor_rpm_set_relocations(rpm, relocations);
ali@369
  1278
	razor_transaction_fixup_package(trans, package, rpm);
ali@403
  1279
	retval = razor_rpm_install(rpm, atomic, install_root, install_count,
ali@403
  1280
				   stage);
ali@403
  1281
	if (retval < 0) {
ali@403
  1282
		s = rpm_filename(name, version, arch);
ali@403
  1283
		fprintf(stderr, "%s: %s\n", s,
ali@403
  1284
			razor_atomic_get_error_msg(atomic));
ali@403
  1285
		free(s);
ali@403
  1286
	}
ali@363
  1287
	razor_rpm_close(rpm);
ali@363
  1288
	return retval;
ali@363
  1289
}
ali@363
  1290
ali@412
  1291
/*
ali@418
  1292
 * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
ali@418
  1293
 * is met (in which case the action is consumed).
ali@412
  1294
 */
ali@363
  1295
static int
ali@403
  1296
update_packages(struct razor_transaction *trans,
ali@403
  1297
		struct razor_install_iterator *ii, struct razor_set *system,
ali@403
  1298
		struct razor_set *next, struct razor_atomic *atomic,
ali@403
  1299
		struct razor_relocations *relocations,
ali@418
  1300
		enum razor_stage_type stage)
krh@254
  1301
{
krh@254
  1302
	struct razor_package *package;
krh@316
  1303
	enum razor_install_action action;
ali@363
  1304
	int retval = 0, count;
ali@403
  1305
ali@412
  1306
	while (!retval && razor_install_iterator_next(ii, &package, &action,
ali@412
  1307
						      &count)) {
ali@418
  1308
		if (action == RAZOR_INSTALL_ACTION_ADD) {
ali@418
  1309
			if (install_package(trans, next, atomic, package,
ali@418
  1310
					    relocations, count, stage))
ali@418
  1311
				retval = -1;
ali@418
  1312
		} else if (action == RAZOR_INSTALL_ACTION_REMOVE) {
ali@418
  1313
			if (razor_package_remove(system, next, atomic, package,
ali@418
  1314
						 install_root, count, stage))
ali@418
  1315
				retval = -1;
ali@418
  1316
		} else if (action == RAZOR_INSTALL_ACTION_COMMIT)
ali@418
  1317
				retval = 1;
rhughes@241
  1318
	}
rhughes@241
  1319
ali@363
  1320
	return retval;
rhughes@241
  1321
}
rhughes@241
  1322
rhughes@241
  1323
static int
ali@424
  1324
update_system(struct razor_root *root, struct razor_relocations *relocations,
ali@424
  1325
	      struct razor_transaction *trans, struct razor_set *next,
ali@424
  1326
	      const char *verb)
ali@418
  1327
{
ali@424
  1328
	struct razor_set *system, *set;
ali@418
  1329
	struct razor_atomic *atomic;
ali@418
  1330
	struct razor_install_iterator *ii;
ali@418
  1331
	int r, retval = 0;
ali@418
  1332
	char *description;
ali@418
  1333
	size_t pos;
ali@418
  1334
ali@418
  1335
	description = razor_concat(verb, " packages", NULL);
ali@418
  1336
ali@424
  1337
	system = razor_set_ref(razor_root_get_system_set(root));
ali@424
  1338
ali@418
  1339
	ii = razor_set_create_install_iterator(system, next);
ali@418
  1340
ali@418
  1341
	do {
ali@418
  1342
		pos = razor_install_iterator_tell(ii);
ali@418
  1343
ali@418
  1344
		atomic = razor_atomic_open(description);
ali@418
  1345
ali@418
  1346
		r = update_packages(trans, ii, system, next, atomic,
ali@418
  1347
				    relocations, RAZOR_STAGE_SCRIPTS_PRE);
ali@418
  1348
		if (r < 0) {
ali@418
  1349
			fprintf(stderr, "%s aborted\n", verb);
ali@418
  1350
			retval = r;
ali@418
  1351
		} else {
ali@418
  1352
			razor_install_iterator_seek(ii, pos);
ali@418
  1353
			r = update_packages(trans, ii, system, next, atomic,
ali@418
  1354
					    relocations, RAZOR_STAGE_FILES);
ali@418
  1355
ali@418
  1356
			if (r == 1) {
ali@418
  1357
				set = razor_install_iterator_commit_set(ii);
ali@424
  1358
				razor_root_update(root, set, atomic);
ali@418
  1359
				razor_set_unref(set);
ali@418
  1360
			} else if (r == 0)
ali@424
  1361
				razor_root_update(root, next, atomic);
ali@418
  1362
ali@418
  1363
			retval = razor_atomic_commit(atomic);
ali@421
  1364
			if (retval)
ali@418
  1365
				fprintf(stderr, "%s\n",
ali@418
  1366
					razor_atomic_get_error_msg(atomic));
ali@421
  1367
			else {
ali@418
  1368
				razor_install_iterator_seek(ii, pos);
ali@418
  1369
				update_packages(trans, ii, system, next,
ali@418
  1370
						atomic, relocations,
ali@418
  1371
						RAZOR_STAGE_SCRIPTS_POST);
ali@418
  1372
			}
ali@418
  1373
		}
ali@418
  1374
ali@418
  1375
		razor_atomic_destroy(atomic);
ali@418
  1376
	} while(!retval && r == 1);
ali@418
  1377
ali@458
  1378
	razor_install_iterator_destroy(ii);
ali@458
  1379
ali@424
  1380
	razor_set_unref(system);
ali@424
  1381
ali@418
  1382
	free(description);
ali@418
  1383
ali@418
  1384
	return retval;
ali@418
  1385
}
ali@418
  1386
ali@418
  1387
static int
ali@445
  1388
command_install_or_update(int argc, char * const argv[], int do_update)
rhughes@241
  1389
{
ali@424
  1390
	struct razor_relocations *relocations = NULL;
ali@351
  1391
	struct razor_set *system, *upstream, *next, *set;
rhughes@241
  1392
	struct razor_transaction *trans;
ali@424
  1393
	struct razor_error *error = NULL;
ali@403
  1394
	struct razor_atomic *atomic;
ali@424
  1395
	struct razor_root *root;
ali@445
  1396
	int opt, i, retval = 0, len, dependencies = 1;
ali@351
  1397
	char *oldpath;
ali@445
  1398
	const char *arg;
ali@445
  1399
	enum {
ali@445
  1400
		opt_no_dependencies = 1,
ali@445
  1401
		opt_relocate = 2,
ali@445
  1402
	};
ali@445
  1403
	static struct razor_option options[] = {
ali@445
  1404
		{ .name = "no-dependencies", .has_arg = no_argument,
ali@445
  1405
		  .val = opt_no_dependencies,
ali@445
  1406
		  .description = "Do not verify package dependencies" },
ali@445
  1407
		{ .name = "relocate", .has_arg = required_argument,
ali@445
  1408
		  .val = opt_relocate,
ali@445
  1409
		  .description = "Relocate files from path OLD to NEW",
ali@445
  1410
		  .arg_description = "OLD=NEW" },
ali@445
  1411
	};
rhughes@241
  1412
ali@445
  1413
	do {
ali@445
  1414
		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
ali@445
  1415
				   "rpm ...", &arg);
ali@445
  1416
		switch (opt) {
ali@445
  1417
			case -2:
ali@445
  1418
				return 0;
ali@445
  1419
			case -1:
ali@445
  1420
				return 1;
ali@445
  1421
			case opt_no_dependencies:
ali@445
  1422
				dependencies = 0;
ali@445
  1423
				break;
ali@445
  1424
			case opt_relocate:
ali@445
  1425
				if (strchr(arg, '=') == NULL) {
ali@445
  1426
					razor_usage(argv[0],
ali@445
  1427
						    ARRAY_SIZE(options),
ali@445
  1428
						    options, "rpm ...");
ali@445
  1429
					return 1;
ali@445
  1430
				}
ali@445
  1431
				len = strchr(arg, '=') - arg;
ali@445
  1432
				oldpath = malloc(len + 1);
ali@445
  1433
				strncpy(oldpath, arg, len);
ali@445
  1434
				oldpath[len] = '\0';
ali@445
  1435
				if (!relocations)
ali@445
  1436
				       relocations = razor_relocations_create();
ali@445
  1437
				razor_relocations_add(relocations, oldpath,
ali@445
  1438
						      arg + len + 1);
ali@445
  1439
				free(oldpath);
ali@445
  1440
				break;
ali@445
  1441
		}
ali@445
  1442
	} while (opt);
ali@351
  1443
ali@424
  1444
	upstream = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1445
	if (upstream == NULL) {
ali@424
  1446
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1447
		razor_error_free(error);
ali@458
  1448
		if (relocations)
ali@458
  1449
			razor_relocations_destroy(relocations);
ali@424
  1450
		return 1;
ali@424
  1451
	}
ali@424
  1452
ali@418
  1453
	if (do_update)
ali@418
  1454
		atomic = razor_atomic_open("Update packages");
ali@418
  1455
	else
ali@418
  1456
		atomic = razor_atomic_open("Install packages");
ali@418
  1457
ali@351
  1458
	if (relocations) {
ali@403
  1459
		set = relocate_packages(upstream, atomic, relocations);
ali@403
  1460
		if (set == NULL) {
ali@403
  1461
			fprintf(stderr, "%s\n",
ali@403
  1462
				razor_atomic_get_error_msg(atomic));
ali@403
  1463
			razor_atomic_destroy(atomic);
ali@403
  1464
			razor_set_unref(upstream);
ali@403
  1465
			return 1;
ali@403
  1466
		}
ali@403
  1467
		razor_set_unref(upstream);
ali@351
  1468
		upstream = set;
ali@351
  1469
	}
ali@351
  1470
ali@424
  1471
	root = razor_root_open(install_root, &error);
ali@424
  1472
	if (root == NULL) {
ali@424
  1473
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1474
		razor_error_free(error);
ali@424
  1475
		razor_atomic_destroy(atomic);
ali@424
  1476
		razor_set_unref(upstream);
ali@424
  1477
		if (relocations)
ali@424
  1478
			razor_relocations_destroy(relocations);
ali@424
  1479
		return 1;
ali@424
  1480
	}
ali@403
  1481
ali@424
  1482
	system = razor_root_get_system_set(root);
krh@250
  1483
	trans = razor_transaction_create(system, upstream);
rhughes@241
  1484
ali@445
  1485
	if (optind == argc && do_update)
ali@382
  1486
		razor_transaction_update_all(trans);
ali@445
  1487
	for (i = optind; i < argc; i++) {
ali@389
  1488
		if (do_update &&
ali@389
  1489
		    mark_packages_for_update(trans, system, argv[i]))
ali@389
  1490
			continue;
rhughes@241
  1491
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
rhughes@241
  1492
			fprintf(stderr, "no package matched %s\n", argv[i]);
ali@369
  1493
			razor_transaction_destroy(trans);
ali@424
  1494
			razor_root_close(root);
ali@403
  1495
			razor_set_unref(upstream);
ali@403
  1496
			razor_atomic_destroy(atomic);
ali@424
  1497
			if (relocations)
ali@424
  1498
				razor_relocations_destroy(relocations);
rhughes@241
  1499
			return 1;
rhughes@241
  1500
		}
rhughes@241
  1501
	}
rhughes@241
  1502
rhughes@241
  1503
	if (dependencies) {
krh@245
  1504
		razor_transaction_resolve(trans);
krh@245
  1505
		if (razor_transaction_describe(trans) > 0) {
ali@369
  1506
			razor_transaction_destroy(trans);
ali@403
  1507
			razor_set_unref(upstream);
ali@424
  1508
			razor_root_close(root);
ali@403
  1509
			razor_atomic_destroy(atomic);
ali@424
  1510
			if (relocations)
ali@424
  1511
				razor_relocations_destroy(relocations);
rhughes@241
  1512
			return 1;
rhughes@241
  1513
		}
rhughes@241
  1514
	}
rhughes@241
  1515
ali@403
  1516
	if (razor_atomic_create_dir(atomic, "rpms",
ali@418
  1517
				    S_IRWXU | S_IRWXG | S_IRWXO) ||
ali@418
  1518
	    razor_atomic_commit(atomic)) {
ali@403
  1519
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@369
  1520
		razor_transaction_destroy(trans);
ali@403
  1521
		razor_set_unref(upstream);
ali@424
  1522
		razor_root_close(root);
ali@403
  1523
		razor_atomic_destroy(atomic);
ali@424
  1524
		if (relocations)
ali@424
  1525
			razor_relocations_destroy(relocations);
rhughes@241
  1526
		return 1;
rhughes@241
  1527
	}
rhughes@241
  1528
ali@418
  1529
	razor_atomic_destroy(atomic);
ali@418
  1530
ali@382
  1531
	next = razor_transaction_commit(trans);
ali@382
  1532
krh@254
  1533
	if (download_packages(system, next) < 0) {
ali@403
  1534
		razor_set_unref(next);
ali@369
  1535
		razor_transaction_destroy(trans);
ali@403
  1536
		razor_set_unref(upstream);
ali@424
  1537
		razor_root_close(root);
ali@424
  1538
		if (relocations)
ali@424
  1539
			razor_relocations_destroy(relocations);
rhughes@241
  1540
                return 1;
rhughes@241
  1541
        }
rhughes@241
  1542
ali@424
  1543
	retval = update_system(root, relocations, trans, next,
ali@418
  1544
			       do_update ? "Update" : "Install");
ali@403
  1545
ali@418
  1546
	razor_set_unref(upstream);
ali@424
  1547
	razor_root_close(root);
ali@403
  1548
ali@369
  1549
	razor_transaction_destroy(trans);
ali@351
  1550
	if (relocations)
ali@351
  1551
		razor_relocations_destroy(relocations);
ali@403
  1552
ali@403
  1553
	razor_set_unref(next);
ali@403
  1554
ali@403
  1555
	return retval;
rhughes@241
  1556
}
rhughes@241
  1557
rhughes@241
  1558
static int
ali@445
  1559
command_update(int argc, char * const argv[])
ali@382
  1560
{
ali@382
  1561
	return command_install_or_update(argc, argv, 1);
ali@382
  1562
}
ali@382
  1563
ali@382
  1564
static int
ali@445
  1565
command_install(int argc, char * const argv[])
ali@382
  1566
{
ali@382
  1567
	return command_install_or_update(argc, argv, 0);
ali@382
  1568
}
ali@382
  1569
ali@382
  1570
static int
ali@445
  1571
command_init(int argc, char * const argv[])
rhughes@241
  1572
{
ali@425
  1573
	int retval;
ali@425
  1574
	struct razor_error *error = NULL;
ali@425
  1575
ali@445
  1576
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
  1577
		case -2:
ali@445
  1578
			return 0;
ali@445
  1579
		case -1:
ali@445
  1580
			return 1;
ali@445
  1581
	}
ali@445
  1582
ali@445
  1583
	if (argc - optind > 0) {
ali@445
  1584
		razor_usage(argv[0], 0, NULL, "");
ali@445
  1585
		return 1;
ali@445
  1586
	}
ali@445
  1587
ali@425
  1588
	retval = razor_root_create(install_root, &error);
ali@425
  1589
	if (retval) {
ali@425
  1590
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@425
  1591
		razor_error_free(error);
ali@425
  1592
	} else
ali@425
  1593
		printf("Created install root\n");
ali@425
  1594
ali@425
  1595
	return retval;
rhughes@241
  1596
}
rhughes@241
  1597
rhughes@241
  1598
static int
ali@445
  1599
command_download(int argc, char * const argv[])
rhughes@241
  1600
{
ali@424
  1601
	struct razor_error *error = NULL;
ali@403
  1602
	struct razor_atomic *atomic;
rhughes@241
  1603
	struct razor_set *set;
rhughes@241
  1604
	struct razor_package_iterator *pi;
rhughes@241
  1605
	struct razor_package *package;
ali@445
  1606
	const char *pattern, *name, *version, *arch;
rhughes@241
  1607
	char url[256], file[256];
rhughes@241
  1608
	int matches = 0;
rhughes@241
  1609
ali@445
  1610
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1611
		case -2:
ali@445
  1612
			return 0;
ali@445
  1613
		case -1:
ali@445
  1614
			return 1;
ali@445
  1615
	}
ali@445
  1616
ali@445
  1617
	if (argc - optind > 1) {
ali@445
  1618
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1619
		return 1;
ali@445
  1620
	}
ali@445
  1621
ali@445
  1622
	pattern = argv[optind];
ali@445
  1623
ali@424
  1624
	set = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1625
	if (set == NULL) {
ali@424
  1626
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1627
		razor_error_free(error);
ali@424
  1628
		return 1;
ali@424
  1629
	}
ali@424
  1630
ali@403
  1631
	atomic = razor_atomic_open("Download packages");
ali@403
  1632
ali@403
  1633
	if (razor_atomic_create_dir(atomic, "rpms", 
ali@403
  1634
				    S_IRWXU | S_IRWXG | S_IRWXO)) {
ali@403
  1635
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1636
		razor_atomic_destroy(atomic);
rhughes@241
  1637
		return 1;
rhughes@241
  1638
	}
rhughes@241
  1639
ali@403
  1640
	if (razor_atomic_commit(atomic)) {
ali@403
  1641
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1642
		razor_atomic_destroy(atomic);
ali@403
  1643
		return 1;
ali@403
  1644
	}
ali@403
  1645
	razor_atomic_destroy(atomic);
ali@403
  1646
rhughes@241
  1647
	pi = razor_package_iterator_create(set);
rhughes@241
  1648
	while (razor_package_iterator_next(pi, &package,
richard@302
  1649
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1650
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1651
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1652
					   RAZOR_DETAIL_LAST)) {
rhughes@241
  1653
		if (pattern && fnmatch(pattern, name, 0) != 0)
rhughes@241
  1654
			continue;
rhughes@241
  1655
rhughes@241
  1656
		matches++;
rhughes@241
  1657
		snprintf(url, sizeof url,
rhughes@241
  1658
			 "%s/Packages/%s-%s.%s.rpm",
rhughes@241
  1659
			 yum_url, name, version, arch);
rhughes@241
  1660
		snprintf(file, sizeof file,
rhughes@241
  1661
			 "rpms/%s-%s.%s.rpm", name, version, arch);
rhughes@241
  1662
		download_if_missing(url, file);
rhughes@241
  1663
	}
rhughes@241
  1664
	razor_package_iterator_destroy(pi);
ali@403
  1665
	razor_set_unref(set);
rhughes@241
  1666
rhughes@241
  1667
	if (matches == 0)
rhughes@241
  1668
		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
rhughes@241
  1669
	else if (matches == 1)
rhughes@241
  1670
		fprintf(stderr, "downloaded 1 package\n");
rhughes@241
  1671
	else
rhughes@241
  1672
		fprintf(stderr, "downloaded %d packages\n", matches);
rhughes@241
  1673
rhughes@241
  1674
	return 0;
rhughes@241
  1675
}
rhughes@241
  1676
jbowes@258
  1677
static int
ali@457
  1678
command_dump(int argc, char * const argv[])
ali@457
  1679
{
ali@457
  1680
	struct razor_error *error = NULL;
ali@457
  1681
	const char *filename;
ali@457
  1682
ali@457
  1683
	switch (razor_getopt(argc, argv, 0, NULL, "[filename]", NULL)) {
ali@457
  1684
		case -2:
ali@457
  1685
			return 0;
ali@457
  1686
		case -1:
ali@457
  1687
			return 1;
ali@457
  1688
	}
ali@457
  1689
ali@457
  1690
	if (argc - optind > 1) {
ali@457
  1691
		razor_usage(argv[0], 0, NULL, "[filename]");
ali@457
  1692
		return 1;
ali@457
  1693
	}
ali@457
  1694
ali@457
  1695
	filename = argv[optind];
ali@457
  1696
ali@457
  1697
	if (razor_dump_database(stdout, install_root, filename, &error)) {
ali@457
  1698
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@457
  1699
		razor_error_free(error);
ali@457
  1700
		return 1;
ali@457
  1701
	}
ali@457
  1702
ali@457
  1703
	return 0;
ali@457
  1704
}
ali@457
  1705
ali@457
  1706
static int
ali@445
  1707
command_info(int argc, char * const argv[])
jbowes@258
  1708
{
ali@424
  1709
	struct razor_error *error = NULL;
jbowes@258
  1710
	struct razor_set *set;
jbowes@258
  1711
	struct razor_package_iterator *pi;
jbowes@258
  1712
	struct razor_package *package;
ali@462
  1713
	struct razor_string_iterator *si;
ali@445
  1714
	const char *pattern, *name, *version, *arch;
jbowes@258
  1715
	const char *summary, *description, *url, *license;
ali@462
  1716
	const char *prefix;
jbowes@258
  1717
ali@445
  1718
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1719
		case -2:
ali@445
  1720
			return 0;
ali@445
  1721
		case -1:
ali@445
  1722
			return 1;
ali@445
  1723
	}
ali@445
  1724
ali@445
  1725
	if (argc - optind > 1) {
ali@445
  1726
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1727
		return 1;
ali@445
  1728
	}
ali@445
  1729
ali@445
  1730
	pattern = argv[optind];
ali@445
  1731
ali@424
  1732
	set = razor_root_open_read_only(install_root, &error);
ali@403
  1733
	if (set == NULL) {
ali@424
  1734
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1735
		razor_error_free(error);
jbowes@288
  1736
		return 1;
ali@403
  1737
	}
krh@317
  1738
jbowes@258
  1739
	pi = razor_package_iterator_create(set);
jbowes@258
  1740
	while (razor_package_iterator_next(pi, &package,
richard@302
  1741
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1742
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1743
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1744
					   RAZOR_DETAIL_LAST)) {
jbowes@258
  1745
		if (pattern && fnmatch(pattern, name, 0) != 0)
jbowes@258
  1746
			continue;
jbowes@258
  1747
ali@462
  1748
		printf ("Name:        %s\n", name);
ali@462
  1749
		printf ("Arch:        %s\n", arch);
ali@462
  1750
		printf ("Version:     %s\n", version);
ali@462
  1751
ali@462
  1752
		si = razor_install_prefix_iterator_create(set, package);
ali@462
  1753
		if (razor_string_iterator_next(si, &prefix)) {
ali@462
  1754
			printf ("Relocations: %s\n", prefix);
ali@462
  1755
			while (razor_string_iterator_next(si, &prefix))
ali@462
  1756
				printf ("           : %s\n", prefix);
ali@462
  1757
		}
ali@462
  1758
		razor_string_iterator_destroy(si);
ali@462
  1759
richard@302
  1760
		razor_package_get_details (set, package,
richard@302
  1761
					   RAZOR_DETAIL_SUMMARY, &summary,
richard@302
  1762
					   RAZOR_DETAIL_DESCRIPTION, &description,
richard@302
  1763
					   RAZOR_DETAIL_URL, &url,
richard@302
  1764
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1765
					   RAZOR_DETAIL_LAST);
jbowes@258
  1766
jbowes@258
  1767
		printf ("URL:         %s\n", url);
jbowes@258
  1768
		printf ("License:     %s\n", license);
jbowes@258
  1769
		printf ("Summary:     %s\n", summary);
jbowes@258
  1770
		printf ("Description:\n");
jbowes@258
  1771
		printf ("%s\n", description);
jbowes@258
  1772
		printf ("\n");
jbowes@258
  1773
	}
jbowes@258
  1774
	razor_package_iterator_destroy(pi);
ali@403
  1775
	razor_set_unref(set);
jbowes@258
  1776
jbowes@258
  1777
	return 0;
jbowes@258
  1778
}
jbowes@258
  1779
jbowes@292
  1780
#define SEARCH_MAX 256
jbowes@292
  1781
jbowes@292
  1782
static int
ali@445
  1783
command_search(int argc, char * const argv[])
jbowes@292
  1784
{
ali@424
  1785
	struct razor_error *error = NULL;
jbowes@292
  1786
	struct razor_set *set;
jbowes@292
  1787
	struct razor_package_iterator *pi;
jbowes@292
  1788
	struct razor_package *package;
jbowes@292
  1789
	char pattern[SEARCH_MAX];
jbowes@292
  1790
	const char *name, *version, *arch;
jbowes@292
  1791
	const char *summary, *description, *url, *license;
jbowes@292
  1792
ali@445
  1793
	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
ali@445
  1794
		case -2:
ali@445
  1795
			return 0;
ali@445
  1796
		case -1:
ali@445
  1797
			return 1;
ali@445
  1798
	}
ali@445
  1799
ali@445
  1800
	if (argc != 2) {
ali@445
  1801
		razor_usage(argv[0], 0, NULL, "pattern");
jbowes@292
  1802
		return 1;
jbowes@292
  1803
	}
jbowes@292
  1804
ali@445
  1805
	snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
jbowes@292
  1806
ali@424
  1807
	set = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1808
	if (set == NULL) {
ali@424
  1809
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1810
		razor_error_free(error);
jbowes@292
  1811
		return 1;
ali@403
  1812
	}
richard@310
  1813
jbowes@292
  1814
	pi = razor_package_iterator_create(set);
jbowes@292
  1815
	while (razor_package_iterator_next(pi, &package,
richard@304
  1816
					   RAZOR_DETAIL_NAME, &name,
richard@304
  1817
					   RAZOR_DETAIL_VERSION, &version,
krh@305
  1818
					   RAZOR_DETAIL_ARCH, &arch,
krh@305
  1819
					   RAZOR_DETAIL_SUMMARY, &summary,
krh@305
  1820
					   RAZOR_DETAIL_DESCRIPTION, &description,
krh@305
  1821
					   RAZOR_DETAIL_URL, &url,
krh@305
  1822
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1823
					   RAZOR_DETAIL_LAST)) {
krh@305
  1824
		if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
krh@305
  1825
		    !fnmatch(pattern, url, FNM_CASEFOLD) ||
krh@305
  1826
		    !fnmatch(pattern, summary, FNM_CASEFOLD) ||
krh@305
  1827
		    !fnmatch(pattern, description, FNM_CASEFOLD))
krh@305
  1828
			printf("%s-%s.%s: %s\n", name, version, arch, summary);
jbowes@292
  1829
	}
jbowes@292
  1830
	razor_package_iterator_destroy(pi);
ali@403
  1831
	razor_set_unref(set);
jbowes@292
  1832
jbowes@292
  1833
	return 0;
jbowes@292
  1834
}
jbowes@292
  1835
rhughes@241
  1836
static struct {
rhughes@241
  1837
	const char *name;
rhughes@241
  1838
	const char *description;
ali@445
  1839
	int (*func)(int argc, char * const argv[]);
rhughes@241
  1840
} razor_commands[] = {
ali@445
  1841
	{ "diff", "Show diff between two package sets", command_diff },
ali@445
  1842
	{ "download", "Download packages", command_download },
ali@457
  1843
	{ "dump", "Low-level database dump (for debugging)", command_dump },
ali@445
  1844
	{ "help", "List available commands", command_help },
ali@320
  1845
#if HAVE_RPMLIB
ali@445
  1846
	{ "import-rpmdb", "Import the system rpm database",
ali@445
  1847
	  command_import_rpmdb },
ali@320
  1848
#endif
ali@445
  1849
	{ "import-rpms", "Import rpms from the given directory",
ali@445
  1850
	  command_import_rpms },
ali@445
  1851
	{ "import-yum", "Import yum metadata files", command_import_yum },
ali@445
  1852
	{ "info", "Display package details", command_info },
ali@445
  1853
	{ "init", "Init razor root", command_init },
ali@445
  1854
	{ "install", "Install rpm", command_install },
ali@445
  1855
	{ "list", "List all packages", command_list },
ali@445
  1856
	{ "list-conflicts", "List all conflicts for the given package",
ali@445
  1857
	  command_list_conflicts },
ali@445
  1858
	{ "list-file-packages", "List packages owning file",
ali@445
  1859
	  command_list_file_packages },
ali@445
  1860
	{ "list-files", "List files for package set", command_list_files },
ali@445
  1861
	{ "list-obsoletes", "List all obsoletes for the given package",
ali@445
  1862
	  command_list_obsoletes },
ali@445
  1863
	{ "list-package-files", "List files in package",
ali@445
  1864
	  command_list_package_files },
ali@445
  1865
	{ "list-provides", "List all provides for the given package",
ali@445
  1866
	  command_list_provides },
ali@445
  1867
	{ "list-requires", "List all requires for the given package",
ali@445
  1868
	  command_list_requires },
ali@445
  1869
	{ "list-scripts", "List all scripts for the given package",
ali@445
  1870
	  command_list_scripts },
ali@445
  1871
	{ "remove", "Remove specified packages", command_remove },
ali@445
  1872
	{ "search", "Search package details", command_search },
ali@445
  1873
	{ "update", "Update all or specified packages", command_update },
ali@445
  1874
	{ "what-provides", "List the packages that have the given provides",
ali@445
  1875
	  command_what_provides },
ali@445
  1876
	{ "what-requires", "List the packages that have the given requires",
ali@445
  1877
	  command_what_requires },
rhughes@241
  1878
};
rhughes@241
  1879
rhughes@241
  1880
static int
ali@445
  1881
command_help(int argc, char * const argv[])
rhughes@241
  1882
{
rhughes@241
  1883
	int i;
rhughes@241
  1884
ali@445
  1885
	printf("Available commands:\n");
rhughes@241
  1886
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
rhughes@241
  1887
		printf("  %-20s%s\n",
rhughes@241
  1888
		       razor_commands[i].name, razor_commands[i].description);
ali@445
  1889
	printf("\nType \"razor --help\" for help about global options\n"
ali@445
  1890
	       "or \"razor <command> --help\" for help about a particular "
ali@445
  1891
	       "command's options.\n");
rhughes@241
  1892
ali@445
  1893
	return 0;
rhughes@241
  1894
}
rhughes@241
  1895
rhughes@241
  1896
int
ali@445
  1897
main(int argc, char *argv[])
rhughes@241
  1898
{
krh@317
  1899
	char *repo, *root;
ali@445
  1900
	int i, opt, main_optind;
ali@445
  1901
	int do_help_commands = 0;
ali@445
  1902
	enum {
ali@445
  1903
		opt_database = 1,
ali@445
  1904
		opt_help,
ali@445
  1905
		opt_help_commands,
ali@445
  1906
		opt_root,
ali@445
  1907
		opt_url,
ali@445
  1908
	};
ali@445
  1909
	struct option options[] = {
ali@445
  1910
		{ .name = "database", .has_arg = required_argument,
ali@445
  1911
		  .val = opt_database },
ali@445
  1912
		{ .name = "help", .has_arg = no_argument, .val = opt_help },
ali@445
  1913
		{ .name = "help-commands", .has_arg = no_argument,
ali@445
  1914
		  .flag = &do_help_commands, .val = TRUE },
ali@445
  1915
		{ .name = "root", .has_arg = required_argument,
ali@445
  1916
		  .val = opt_root },
ali@445
  1917
		{ .name = "url", .has_arg = required_argument, .val = opt_url },
ali@445
  1918
		{ 0, }
ali@445
  1919
	};
rhughes@241
  1920
rhughes@241
  1921
	repo = getenv("RAZOR_REPO");
rhughes@241
  1922
	if (repo != NULL)
rhughes@241
  1923
		repo_filename = repo;
rhughes@241
  1924
krh@317
  1925
	root = getenv("RAZOR_ROOT");
krh@317
  1926
	if (root != NULL)
krh@317
  1927
		install_root = root;
krh@317
  1928
rhughes@241
  1929
	yum_url = getenv("YUM_URL");
rhughes@241
  1930
	if (yum_url == NULL)
rhughes@241
  1931
		yum_url = YUM_URL;
rhughes@241
  1932
ali@359
  1933
	if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
ali@359
  1934
		razor_disable_root_name_checks(1);
ali@359
  1935
ali@445
  1936
	optind = 1;
ali@445
  1937
	opterr = 0;
ali@445
  1938
ali@445
  1939
	while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
ali@445
  1940
		switch (opt) {
ali@445
  1941
			case opt_database:
ali@445
  1942
				razor_set_database_path(optarg);
ali@445
  1943
				break;
ali@445
  1944
			case opt_help:
ali@445
  1945
			default:
ali@445
  1946
				printf("Usage: razor [global-options] command "
ali@445
  1947
				       "[command-options-and-arguments]\n\n");
ali@445
  1948
				printf("Options:\n");
ali@445
  1949
				printf("  --help              "
ali@445
  1950
				       "Show this help message and exit\n");
ali@445
  1951
				printf("  --help-commands     List commands\n");
ali@445
  1952
				printf("  --database=PATH     "
ali@445
  1953
				       "Use alternative database\n");
ali@445
  1954
				printf("  --root=ROOT         "
ali@445
  1955
				       "Use ROOT as top level directory\n");
ali@445
  1956
				printf("  --url=URL           "
ali@445
  1957
				       "Use URL as upstream repository\n");
ali@445
  1958
				return opt != opt_help;
ali@445
  1959
			case opt_root:
ali@445
  1960
				install_root = optarg;
ali@445
  1961
				break;
ali@445
  1962
			case opt_url:
ali@445
  1963
				yum_url = optarg;
ali@445
  1964
				break;
ali@445
  1965
			case 0:
ali@445
  1966
				break;
ali@445
  1967
		}
ali@445
  1968
	}
ali@445
  1969
ali@445
  1970
	main_optind = optind;
ali@445
  1971
	optind = 1;
ali@445
  1972
ali@445
  1973
	if (do_help_commands || argc - main_optind < 1) {
ali@445
  1974
		command_help(argc - main_optind, argv + main_optind);
ali@445
  1975
		return 1;
ali@445
  1976
	}
rhughes@241
  1977
rhughes@241
  1978
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
ali@445
  1979
		if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
ali@445
  1980
			return razor_commands[i].func(argc - main_optind,
ali@445
  1981
						      argv + main_optind);
rhughes@241
  1982
ali@445
  1983
	command_help(argc - main_optind, argv + main_optind);
ali@445
  1984
	return 1;
rhughes@241
  1985
}