src/main.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 09 17:27:41 2014 +0100 (2014-10-09)
changeset 455 df914f383f5c
parent 447 0a5e583393e1
child 457 51a084acef49
permissions -rw-r--r--
Support downloading from local repository even without libcurl

Using the --url option of the razor executable, it is possible
to specify a yum repository on the local machine (eg., on installation
media) and import from there, eg.,:

C> razor --url file:///d:/ import-yum

This will be handled by libcurl if available but if not, an internal
copy routine will be used.

Note that if Microsoft's KTM implementation of atomic transactions is
used, then the current directory must support atomic transactions
(also improve error messages for this, and other, cases).
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@424
  1378
	razor_set_unref(system);
ali@424
  1379
ali@418
  1380
	free(description);
ali@418
  1381
ali@418
  1382
	return retval;
ali@418
  1383
}
ali@418
  1384
ali@418
  1385
static int
ali@445
  1386
command_install_or_update(int argc, char * const argv[], int do_update)
rhughes@241
  1387
{
ali@424
  1388
	struct razor_relocations *relocations = NULL;
ali@351
  1389
	struct razor_set *system, *upstream, *next, *set;
rhughes@241
  1390
	struct razor_transaction *trans;
ali@424
  1391
	struct razor_error *error = NULL;
ali@403
  1392
	struct razor_atomic *atomic;
ali@424
  1393
	struct razor_root *root;
ali@445
  1394
	int opt, i, retval = 0, len, dependencies = 1;
ali@351
  1395
	char *oldpath;
ali@445
  1396
	const char *arg;
ali@445
  1397
	enum {
ali@445
  1398
		opt_no_dependencies = 1,
ali@445
  1399
		opt_relocate = 2,
ali@445
  1400
	};
ali@445
  1401
	static struct razor_option options[] = {
ali@445
  1402
		{ .name = "no-dependencies", .has_arg = no_argument,
ali@445
  1403
		  .val = opt_no_dependencies,
ali@445
  1404
		  .description = "Do not verify package dependencies" },
ali@445
  1405
		{ .name = "relocate", .has_arg = required_argument,
ali@445
  1406
		  .val = opt_relocate,
ali@445
  1407
		  .description = "Relocate files from path OLD to NEW",
ali@445
  1408
		  .arg_description = "OLD=NEW" },
ali@445
  1409
	};
rhughes@241
  1410
ali@445
  1411
	do {
ali@445
  1412
		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
ali@445
  1413
				   "rpm ...", &arg);
ali@445
  1414
		switch (opt) {
ali@445
  1415
			case -2:
ali@445
  1416
				return 0;
ali@445
  1417
			case -1:
ali@445
  1418
				return 1;
ali@445
  1419
			case opt_no_dependencies:
ali@445
  1420
				dependencies = 0;
ali@445
  1421
				break;
ali@445
  1422
			case opt_relocate:
ali@445
  1423
				if (strchr(arg, '=') == NULL) {
ali@445
  1424
					razor_usage(argv[0],
ali@445
  1425
						    ARRAY_SIZE(options),
ali@445
  1426
						    options, "rpm ...");
ali@445
  1427
					return 1;
ali@445
  1428
				}
ali@445
  1429
				len = strchr(arg, '=') - arg;
ali@445
  1430
				oldpath = malloc(len + 1);
ali@445
  1431
				strncpy(oldpath, arg, len);
ali@445
  1432
				oldpath[len] = '\0';
ali@445
  1433
				if (!relocations)
ali@445
  1434
				       relocations = razor_relocations_create();
ali@445
  1435
				razor_relocations_add(relocations, oldpath,
ali@445
  1436
						      arg + len + 1);
ali@445
  1437
				free(oldpath);
ali@445
  1438
				break;
ali@445
  1439
		}
ali@445
  1440
	} while (opt);
ali@351
  1441
ali@424
  1442
	upstream = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1443
	if (upstream == NULL) {
ali@424
  1444
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1445
		razor_error_free(error);
ali@424
  1446
		return 1;
ali@424
  1447
	}
ali@424
  1448
ali@418
  1449
	if (do_update)
ali@418
  1450
		atomic = razor_atomic_open("Update packages");
ali@418
  1451
	else
ali@418
  1452
		atomic = razor_atomic_open("Install packages");
ali@418
  1453
ali@351
  1454
	if (relocations) {
ali@403
  1455
		set = relocate_packages(upstream, atomic, relocations);
ali@403
  1456
		if (set == NULL) {
ali@403
  1457
			fprintf(stderr, "%s\n",
ali@403
  1458
				razor_atomic_get_error_msg(atomic));
ali@403
  1459
			razor_atomic_destroy(atomic);
ali@403
  1460
			razor_set_unref(upstream);
ali@403
  1461
			return 1;
ali@403
  1462
		}
ali@403
  1463
		razor_set_unref(upstream);
ali@351
  1464
		upstream = set;
ali@351
  1465
	}
ali@351
  1466
ali@424
  1467
	root = razor_root_open(install_root, &error);
ali@424
  1468
	if (root == NULL) {
ali@424
  1469
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1470
		razor_error_free(error);
ali@424
  1471
		razor_atomic_destroy(atomic);
ali@424
  1472
		razor_set_unref(upstream);
ali@424
  1473
		if (relocations)
ali@424
  1474
			razor_relocations_destroy(relocations);
ali@424
  1475
		return 1;
ali@424
  1476
	}
ali@403
  1477
ali@424
  1478
	system = razor_root_get_system_set(root);
krh@250
  1479
	trans = razor_transaction_create(system, upstream);
rhughes@241
  1480
ali@445
  1481
	if (optind == argc && do_update)
ali@382
  1482
		razor_transaction_update_all(trans);
ali@445
  1483
	for (i = optind; i < argc; i++) {
ali@389
  1484
		if (do_update &&
ali@389
  1485
		    mark_packages_for_update(trans, system, argv[i]))
ali@389
  1486
			continue;
rhughes@241
  1487
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
rhughes@241
  1488
			fprintf(stderr, "no package matched %s\n", argv[i]);
ali@369
  1489
			razor_transaction_destroy(trans);
ali@424
  1490
			razor_root_close(root);
ali@403
  1491
			razor_set_unref(upstream);
ali@403
  1492
			razor_atomic_destroy(atomic);
ali@424
  1493
			if (relocations)
ali@424
  1494
				razor_relocations_destroy(relocations);
rhughes@241
  1495
			return 1;
rhughes@241
  1496
		}
rhughes@241
  1497
	}
rhughes@241
  1498
rhughes@241
  1499
	if (dependencies) {
krh@245
  1500
		razor_transaction_resolve(trans);
krh@245
  1501
		if (razor_transaction_describe(trans) > 0) {
ali@369
  1502
			razor_transaction_destroy(trans);
ali@403
  1503
			razor_set_unref(upstream);
ali@424
  1504
			razor_root_close(root);
ali@403
  1505
			razor_atomic_destroy(atomic);
ali@424
  1506
			if (relocations)
ali@424
  1507
				razor_relocations_destroy(relocations);
rhughes@241
  1508
			return 1;
rhughes@241
  1509
		}
rhughes@241
  1510
	}
rhughes@241
  1511
ali@403
  1512
	if (razor_atomic_create_dir(atomic, "rpms",
ali@418
  1513
				    S_IRWXU | S_IRWXG | S_IRWXO) ||
ali@418
  1514
	    razor_atomic_commit(atomic)) {
ali@403
  1515
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@369
  1516
		razor_transaction_destroy(trans);
ali@403
  1517
		razor_set_unref(upstream);
ali@424
  1518
		razor_root_close(root);
ali@403
  1519
		razor_atomic_destroy(atomic);
ali@424
  1520
		if (relocations)
ali@424
  1521
			razor_relocations_destroy(relocations);
rhughes@241
  1522
		return 1;
rhughes@241
  1523
	}
rhughes@241
  1524
ali@418
  1525
	razor_atomic_destroy(atomic);
ali@418
  1526
ali@382
  1527
	next = razor_transaction_commit(trans);
ali@382
  1528
krh@254
  1529
	if (download_packages(system, next) < 0) {
ali@403
  1530
		razor_set_unref(next);
ali@369
  1531
		razor_transaction_destroy(trans);
ali@403
  1532
		razor_set_unref(upstream);
ali@424
  1533
		razor_root_close(root);
ali@424
  1534
		if (relocations)
ali@424
  1535
			razor_relocations_destroy(relocations);
rhughes@241
  1536
                return 1;
rhughes@241
  1537
        }
rhughes@241
  1538
ali@424
  1539
	retval = update_system(root, relocations, trans, next,
ali@418
  1540
			       do_update ? "Update" : "Install");
ali@403
  1541
ali@418
  1542
	razor_set_unref(upstream);
ali@424
  1543
	razor_root_close(root);
ali@403
  1544
ali@369
  1545
	razor_transaction_destroy(trans);
ali@351
  1546
	if (relocations)
ali@351
  1547
		razor_relocations_destroy(relocations);
ali@403
  1548
ali@403
  1549
	razor_set_unref(next);
ali@403
  1550
ali@403
  1551
	return retval;
rhughes@241
  1552
}
rhughes@241
  1553
rhughes@241
  1554
static int
ali@445
  1555
command_update(int argc, char * const argv[])
ali@382
  1556
{
ali@382
  1557
	return command_install_or_update(argc, argv, 1);
ali@382
  1558
}
ali@382
  1559
ali@382
  1560
static int
ali@445
  1561
command_install(int argc, char * const argv[])
ali@382
  1562
{
ali@382
  1563
	return command_install_or_update(argc, argv, 0);
ali@382
  1564
}
ali@382
  1565
ali@382
  1566
static int
ali@445
  1567
command_init(int argc, char * const argv[])
rhughes@241
  1568
{
ali@425
  1569
	int retval;
ali@425
  1570
	struct razor_error *error = NULL;
ali@425
  1571
ali@445
  1572
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
  1573
		case -2:
ali@445
  1574
			return 0;
ali@445
  1575
		case -1:
ali@445
  1576
			return 1;
ali@445
  1577
	}
ali@445
  1578
ali@445
  1579
	if (argc - optind > 0) {
ali@445
  1580
		razor_usage(argv[0], 0, NULL, "");
ali@445
  1581
		return 1;
ali@445
  1582
	}
ali@445
  1583
ali@425
  1584
	retval = razor_root_create(install_root, &error);
ali@425
  1585
	if (retval) {
ali@425
  1586
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@425
  1587
		razor_error_free(error);
ali@425
  1588
	} else
ali@425
  1589
		printf("Created install root\n");
ali@425
  1590
ali@425
  1591
	return retval;
rhughes@241
  1592
}
rhughes@241
  1593
rhughes@241
  1594
static int
ali@445
  1595
command_download(int argc, char * const argv[])
rhughes@241
  1596
{
ali@424
  1597
	struct razor_error *error = NULL;
ali@403
  1598
	struct razor_atomic *atomic;
rhughes@241
  1599
	struct razor_set *set;
rhughes@241
  1600
	struct razor_package_iterator *pi;
rhughes@241
  1601
	struct razor_package *package;
ali@445
  1602
	const char *pattern, *name, *version, *arch;
rhughes@241
  1603
	char url[256], file[256];
rhughes@241
  1604
	int matches = 0;
rhughes@241
  1605
ali@445
  1606
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1607
		case -2:
ali@445
  1608
			return 0;
ali@445
  1609
		case -1:
ali@445
  1610
			return 1;
ali@445
  1611
	}
ali@445
  1612
ali@445
  1613
	if (argc - optind > 1) {
ali@445
  1614
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1615
		return 1;
ali@445
  1616
	}
ali@445
  1617
ali@445
  1618
	pattern = argv[optind];
ali@445
  1619
ali@424
  1620
	set = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1621
	if (set == NULL) {
ali@424
  1622
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1623
		razor_error_free(error);
ali@424
  1624
		return 1;
ali@424
  1625
	}
ali@424
  1626
ali@403
  1627
	atomic = razor_atomic_open("Download packages");
ali@403
  1628
ali@403
  1629
	if (razor_atomic_create_dir(atomic, "rpms", 
ali@403
  1630
				    S_IRWXU | S_IRWXG | S_IRWXO)) {
ali@403
  1631
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1632
		razor_atomic_destroy(atomic);
rhughes@241
  1633
		return 1;
rhughes@241
  1634
	}
rhughes@241
  1635
ali@403
  1636
	if (razor_atomic_commit(atomic)) {
ali@403
  1637
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1638
		razor_atomic_destroy(atomic);
ali@403
  1639
		return 1;
ali@403
  1640
	}
ali@403
  1641
	razor_atomic_destroy(atomic);
ali@403
  1642
rhughes@241
  1643
	pi = razor_package_iterator_create(set);
rhughes@241
  1644
	while (razor_package_iterator_next(pi, &package,
richard@302
  1645
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1646
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1647
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1648
					   RAZOR_DETAIL_LAST)) {
rhughes@241
  1649
		if (pattern && fnmatch(pattern, name, 0) != 0)
rhughes@241
  1650
			continue;
rhughes@241
  1651
rhughes@241
  1652
		matches++;
rhughes@241
  1653
		snprintf(url, sizeof url,
rhughes@241
  1654
			 "%s/Packages/%s-%s.%s.rpm",
rhughes@241
  1655
			 yum_url, name, version, arch);
rhughes@241
  1656
		snprintf(file, sizeof file,
rhughes@241
  1657
			 "rpms/%s-%s.%s.rpm", name, version, arch);
rhughes@241
  1658
		download_if_missing(url, file);
rhughes@241
  1659
	}
rhughes@241
  1660
	razor_package_iterator_destroy(pi);
ali@403
  1661
	razor_set_unref(set);
rhughes@241
  1662
rhughes@241
  1663
	if (matches == 0)
rhughes@241
  1664
		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
rhughes@241
  1665
	else if (matches == 1)
rhughes@241
  1666
		fprintf(stderr, "downloaded 1 package\n");
rhughes@241
  1667
	else
rhughes@241
  1668
		fprintf(stderr, "downloaded %d packages\n", matches);
rhughes@241
  1669
rhughes@241
  1670
	return 0;
rhughes@241
  1671
}
rhughes@241
  1672
jbowes@258
  1673
static int
ali@445
  1674
command_info(int argc, char * const argv[])
jbowes@258
  1675
{
ali@424
  1676
	struct razor_error *error = NULL;
jbowes@258
  1677
	struct razor_set *set;
jbowes@258
  1678
	struct razor_package_iterator *pi;
jbowes@258
  1679
	struct razor_package *package;
ali@445
  1680
	const char *pattern, *name, *version, *arch;
jbowes@258
  1681
	const char *summary, *description, *url, *license;
jbowes@258
  1682
ali@445
  1683
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1684
		case -2:
ali@445
  1685
			return 0;
ali@445
  1686
		case -1:
ali@445
  1687
			return 1;
ali@445
  1688
	}
ali@445
  1689
ali@445
  1690
	if (argc - optind > 1) {
ali@445
  1691
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1692
		return 1;
ali@445
  1693
	}
ali@445
  1694
ali@445
  1695
	pattern = argv[optind];
ali@445
  1696
ali@424
  1697
	set = razor_root_open_read_only(install_root, &error);
ali@403
  1698
	if (set == NULL) {
ali@424
  1699
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1700
		razor_error_free(error);
jbowes@288
  1701
		return 1;
ali@403
  1702
	}
krh@317
  1703
jbowes@258
  1704
	pi = razor_package_iterator_create(set);
jbowes@258
  1705
	while (razor_package_iterator_next(pi, &package,
richard@302
  1706
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1707
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1708
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1709
					   RAZOR_DETAIL_LAST)) {
jbowes@258
  1710
		if (pattern && fnmatch(pattern, name, 0) != 0)
jbowes@258
  1711
			continue;
jbowes@258
  1712
richard@302
  1713
		razor_package_get_details (set, package,
richard@302
  1714
					   RAZOR_DETAIL_SUMMARY, &summary,
richard@302
  1715
					   RAZOR_DETAIL_DESCRIPTION, &description,
richard@302
  1716
					   RAZOR_DETAIL_URL, &url,
richard@302
  1717
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1718
					   RAZOR_DETAIL_LAST);
jbowes@258
  1719
jbowes@258
  1720
		printf ("Name:        %s\n", name);
jbowes@258
  1721
		printf ("Arch:        %s\n", arch);
jbowes@258
  1722
		printf ("Version:     %s\n", version);
jbowes@258
  1723
		printf ("URL:         %s\n", url);
jbowes@258
  1724
		printf ("License:     %s\n", license);
jbowes@258
  1725
		printf ("Summary:     %s\n", summary);
jbowes@258
  1726
		printf ("Description:\n");
jbowes@258
  1727
		printf ("%s\n", description);
jbowes@258
  1728
		printf ("\n");
jbowes@258
  1729
	}
jbowes@258
  1730
	razor_package_iterator_destroy(pi);
ali@403
  1731
	razor_set_unref(set);
jbowes@258
  1732
jbowes@258
  1733
	return 0;
jbowes@258
  1734
}
jbowes@258
  1735
jbowes@292
  1736
#define SEARCH_MAX 256
jbowes@292
  1737
jbowes@292
  1738
static int
ali@445
  1739
command_search(int argc, char * const argv[])
jbowes@292
  1740
{
ali@424
  1741
	struct razor_error *error = NULL;
jbowes@292
  1742
	struct razor_set *set;
jbowes@292
  1743
	struct razor_package_iterator *pi;
jbowes@292
  1744
	struct razor_package *package;
jbowes@292
  1745
	char pattern[SEARCH_MAX];
jbowes@292
  1746
	const char *name, *version, *arch;
jbowes@292
  1747
	const char *summary, *description, *url, *license;
jbowes@292
  1748
ali@445
  1749
	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
ali@445
  1750
		case -2:
ali@445
  1751
			return 0;
ali@445
  1752
		case -1:
ali@445
  1753
			return 1;
ali@445
  1754
	}
ali@445
  1755
ali@445
  1756
	if (argc != 2) {
ali@445
  1757
		razor_usage(argv[0], 0, NULL, "pattern");
jbowes@292
  1758
		return 1;
jbowes@292
  1759
	}
jbowes@292
  1760
ali@445
  1761
	snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
jbowes@292
  1762
ali@424
  1763
	set = razor_set_open(rawhide_repo_filename, 0, &error);
ali@424
  1764
	if (set == NULL) {
ali@424
  1765
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1766
		razor_error_free(error);
jbowes@292
  1767
		return 1;
ali@403
  1768
	}
richard@310
  1769
jbowes@292
  1770
	pi = razor_package_iterator_create(set);
jbowes@292
  1771
	while (razor_package_iterator_next(pi, &package,
richard@304
  1772
					   RAZOR_DETAIL_NAME, &name,
richard@304
  1773
					   RAZOR_DETAIL_VERSION, &version,
krh@305
  1774
					   RAZOR_DETAIL_ARCH, &arch,
krh@305
  1775
					   RAZOR_DETAIL_SUMMARY, &summary,
krh@305
  1776
					   RAZOR_DETAIL_DESCRIPTION, &description,
krh@305
  1777
					   RAZOR_DETAIL_URL, &url,
krh@305
  1778
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1779
					   RAZOR_DETAIL_LAST)) {
krh@305
  1780
		if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
krh@305
  1781
		    !fnmatch(pattern, url, FNM_CASEFOLD) ||
krh@305
  1782
		    !fnmatch(pattern, summary, FNM_CASEFOLD) ||
krh@305
  1783
		    !fnmatch(pattern, description, FNM_CASEFOLD))
krh@305
  1784
			printf("%s-%s.%s: %s\n", name, version, arch, summary);
jbowes@292
  1785
	}
jbowes@292
  1786
	razor_package_iterator_destroy(pi);
ali@403
  1787
	razor_set_unref(set);
jbowes@292
  1788
jbowes@292
  1789
	return 0;
jbowes@292
  1790
}
jbowes@292
  1791
rhughes@241
  1792
static struct {
rhughes@241
  1793
	const char *name;
rhughes@241
  1794
	const char *description;
ali@445
  1795
	int (*func)(int argc, char * const argv[]);
rhughes@241
  1796
} razor_commands[] = {
ali@445
  1797
	{ "diff", "Show diff between two package sets", command_diff },
ali@445
  1798
	{ "download", "Download packages", command_download },
ali@445
  1799
	{ "help", "List available commands", command_help },
ali@320
  1800
#if HAVE_RPMLIB
ali@445
  1801
	{ "import-rpmdb", "Import the system rpm database",
ali@445
  1802
	  command_import_rpmdb },
ali@320
  1803
#endif
ali@445
  1804
	{ "import-rpms", "Import rpms from the given directory",
ali@445
  1805
	  command_import_rpms },
ali@445
  1806
	{ "import-yum", "Import yum metadata files", command_import_yum },
ali@445
  1807
	{ "info", "Display package details", command_info },
ali@445
  1808
	{ "init", "Init razor root", command_init },
ali@445
  1809
	{ "install", "Install rpm", command_install },
ali@445
  1810
	{ "list", "List all packages", command_list },
ali@445
  1811
	{ "list-conflicts", "List all conflicts for the given package",
ali@445
  1812
	  command_list_conflicts },
ali@445
  1813
	{ "list-file-packages", "List packages owning file",
ali@445
  1814
	  command_list_file_packages },
ali@445
  1815
	{ "list-files", "List files for package set", command_list_files },
ali@445
  1816
	{ "list-obsoletes", "List all obsoletes for the given package",
ali@445
  1817
	  command_list_obsoletes },
ali@445
  1818
	{ "list-package-files", "List files in package",
ali@445
  1819
	  command_list_package_files },
ali@445
  1820
	{ "list-provides", "List all provides for the given package",
ali@445
  1821
	  command_list_provides },
ali@445
  1822
	{ "list-requires", "List all requires for the given package",
ali@445
  1823
	  command_list_requires },
ali@445
  1824
	{ "list-scripts", "List all scripts for the given package",
ali@445
  1825
	  command_list_scripts },
ali@445
  1826
	{ "remove", "Remove specified packages", command_remove },
ali@445
  1827
	{ "search", "Search package details", command_search },
ali@445
  1828
	{ "update", "Update all or specified packages", command_update },
ali@445
  1829
	{ "what-provides", "List the packages that have the given provides",
ali@445
  1830
	  command_what_provides },
ali@445
  1831
	{ "what-requires", "List the packages that have the given requires",
ali@445
  1832
	  command_what_requires },
rhughes@241
  1833
};
rhughes@241
  1834
rhughes@241
  1835
static int
ali@445
  1836
command_help(int argc, char * const argv[])
rhughes@241
  1837
{
rhughes@241
  1838
	int i;
rhughes@241
  1839
ali@445
  1840
	printf("Available commands:\n");
rhughes@241
  1841
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
rhughes@241
  1842
		printf("  %-20s%s\n",
rhughes@241
  1843
		       razor_commands[i].name, razor_commands[i].description);
ali@445
  1844
	printf("\nType \"razor --help\" for help about global options\n"
ali@445
  1845
	       "or \"razor <command> --help\" for help about a particular "
ali@445
  1846
	       "command's options.\n");
rhughes@241
  1847
ali@445
  1848
	return 0;
rhughes@241
  1849
}
rhughes@241
  1850
rhughes@241
  1851
int
ali@445
  1852
main(int argc, char *argv[])
rhughes@241
  1853
{
krh@317
  1854
	char *repo, *root;
ali@445
  1855
	int i, opt, main_optind;
ali@445
  1856
	int do_help_commands = 0;
ali@445
  1857
	enum {
ali@445
  1858
		opt_database = 1,
ali@445
  1859
		opt_help,
ali@445
  1860
		opt_help_commands,
ali@445
  1861
		opt_root,
ali@445
  1862
		opt_url,
ali@445
  1863
	};
ali@445
  1864
	struct option options[] = {
ali@445
  1865
		{ .name = "database", .has_arg = required_argument,
ali@445
  1866
		  .val = opt_database },
ali@445
  1867
		{ .name = "help", .has_arg = no_argument, .val = opt_help },
ali@445
  1868
		{ .name = "help-commands", .has_arg = no_argument,
ali@445
  1869
		  .flag = &do_help_commands, .val = TRUE },
ali@445
  1870
		{ .name = "root", .has_arg = required_argument,
ali@445
  1871
		  .val = opt_root },
ali@445
  1872
		{ .name = "url", .has_arg = required_argument, .val = opt_url },
ali@445
  1873
		{ 0, }
ali@445
  1874
	};
rhughes@241
  1875
rhughes@241
  1876
	repo = getenv("RAZOR_REPO");
rhughes@241
  1877
	if (repo != NULL)
rhughes@241
  1878
		repo_filename = repo;
rhughes@241
  1879
krh@317
  1880
	root = getenv("RAZOR_ROOT");
krh@317
  1881
	if (root != NULL)
krh@317
  1882
		install_root = root;
krh@317
  1883
rhughes@241
  1884
	yum_url = getenv("YUM_URL");
rhughes@241
  1885
	if (yum_url == NULL)
rhughes@241
  1886
		yum_url = YUM_URL;
rhughes@241
  1887
ali@359
  1888
	if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
ali@359
  1889
		razor_disable_root_name_checks(1);
ali@359
  1890
ali@445
  1891
	optind = 1;
ali@445
  1892
	opterr = 0;
ali@445
  1893
ali@445
  1894
	while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
ali@445
  1895
		switch (opt) {
ali@445
  1896
			case opt_database:
ali@445
  1897
				razor_set_database_path(optarg);
ali@445
  1898
				break;
ali@445
  1899
			case opt_help:
ali@445
  1900
			default:
ali@445
  1901
				printf("Usage: razor [global-options] command "
ali@445
  1902
				       "[command-options-and-arguments]\n\n");
ali@445
  1903
				printf("Options:\n");
ali@445
  1904
				printf("  --help              "
ali@445
  1905
				       "Show this help message and exit\n");
ali@445
  1906
				printf("  --help-commands     List commands\n");
ali@445
  1907
				printf("  --database=PATH     "
ali@445
  1908
				       "Use alternative database\n");
ali@445
  1909
				printf("  --root=ROOT         "
ali@445
  1910
				       "Use ROOT as top level directory\n");
ali@445
  1911
				printf("  --url=URL           "
ali@445
  1912
				       "Use URL as upstream repository\n");
ali@445
  1913
				return opt != opt_help;
ali@445
  1914
			case opt_root:
ali@445
  1915
				install_root = optarg;
ali@445
  1916
				break;
ali@445
  1917
			case opt_url:
ali@445
  1918
				yum_url = optarg;
ali@445
  1919
				break;
ali@445
  1920
			case 0:
ali@445
  1921
				break;
ali@445
  1922
		}
ali@445
  1923
	}
ali@445
  1924
ali@445
  1925
	main_optind = optind;
ali@445
  1926
	optind = 1;
ali@445
  1927
ali@445
  1928
	if (do_help_commands || argc - main_optind < 1) {
ali@445
  1929
		command_help(argc - main_optind, argv + main_optind);
ali@445
  1930
		return 1;
ali@445
  1931
	}
rhughes@241
  1932
rhughes@241
  1933
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
ali@445
  1934
		if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
ali@445
  1935
			return razor_commands[i].func(argc - main_optind,
ali@445
  1936
						      argv + main_optind);
rhughes@241
  1937
ali@445
  1938
	command_help(argc - main_optind, argv + main_optind);
ali@445
  1939
	return 1;
rhughes@241
  1940
}