src/main.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Oct 04 18:12:58 2014 +0100 (2014-10-04)
changeset 454 56ff755c268c
parent 445 aada48958b92
child 455 df914f383f5c
permissions -rw-r--r--
Only export symbols starting with razor_ in dynamic library.

Apart from being good practice to avoid clashes with higher-level
libraries and the application, this also fixes an obscure bug: The
gnulib library is used both by librazor (the dynamic library) and
by razor (the executable). In doing so, we want to have two separate
copies of the library despite the code duplication this involves.
Without the explicit limit to export only razor_ symbols, the razor
executable under mingw64 was picking up the getopt_long function
from librazor and the optind variable from libgnu which meant that
it did not see optind changing. Hiding librazor's copy of getopt
causes the linker to find libgnu's copy and everything works.

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