src/main.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Jul 04 10:48:18 2016 +0100 (2016-07-04)
changeset 475 008c75a5e08d
parent 462 94d7459828ba
child 476 48e45439fd9a
permissions -rw-r--r--
Switch to a URI-based API
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@475
     4
 * Copyright (C) 2009, 2011-2012, 2014, 2016  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";
ali@475
    52
static const char rawhide_repo_uri[] = "file: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@475
   153
	opt = getopt_long(argc, (char **)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@475
   624
	struct razor_error *error = NULL;
ali@455
   625
ali@475
   626
	local = razor_path_from_uri(url, &error);
ali@455
   627
ali@455
   628
	if (local == NULL) {
ali@475
   629
		fprintf(stderr, "%s: %s\n", file, razor_error_get_msg(error));
ali@475
   630
		razor_error_free(error);
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@475
   726
	putc('\n', stderr);
ali@455
   727
	if (res != CURLE_OK) {
ali@455
   728
		fprintf(stderr, "curl error: %s\n", error);
ali@455
   729
		unlink(file);
ali@455
   730
		return -1;
ali@455
   731
	}
rhughes@241
   732
	curl_easy_cleanup(curl);
rhughes@241
   733
rhughes@241
   734
	return 0;
ali@455
   735
}
ali@321
   736
#endif	/* HAVE_CURL */
ali@455
   737
ali@455
   738
static int
ali@455
   739
download_if_missing(const char *url, const char *file)
ali@455
   740
{
ali@455
   741
	struct stat buf;
ali@455
   742
ali@455
   743
	if (stat(file, &buf) >= 0)
ali@455
   744
		return 0;
ali@455
   745
ali@455
   746
#ifndef HAVE_CURL
ali@455
   747
	return download_local(url, file);
ali@455
   748
#else
ali@455
   749
	return download_with_curl(url, file);
ali@455
   750
#endif
rhughes@241
   751
}
rhughes@241
   752
rhughes@241
   753
#define YUM_URL "http://download.fedora.redhat.com" \
rhughes@241
   754
	"/pub/fedora/linux/development/i386/os"
rhughes@241
   755
rhughes@241
   756
static int
ali@445
   757
command_import_yum(int argc, char * const argv[])
rhughes@241
   758
{
ali@403
   759
	int retval;
rhughes@241
   760
	struct razor_set *set;
ali@403
   761
	struct razor_atomic *atomic;
rhughes@241
   762
	char buffer[512];
rhughes@241
   763
ali@445
   764
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   765
		case -2:
ali@445
   766
			return 0;
ali@445
   767
		case -1:
ali@445
   768
			return 1;
ali@445
   769
	}
ali@445
   770
ali@445
   771
	if (argc - optind > 0) {
ali@445
   772
		razor_usage(argv[0], 0, NULL, "");
ali@445
   773
		return 1;
ali@445
   774
	}
ali@445
   775
ali@455
   776
	printf("downloading from '%s'.\n", yum_url);
rhughes@241
   777
	snprintf(buffer, sizeof buffer,
rhughes@241
   778
		 "%s/repodata/primary.xml.gz", yum_url);
rhughes@241
   779
	if (download_if_missing(buffer, "primary.xml.gz") < 0)
rhughes@241
   780
		return -1;
rhughes@241
   781
	snprintf(buffer, sizeof buffer,
rhughes@241
   782
		 "%s/repodata/filelists.xml.gz", yum_url);
rhughes@241
   783
	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
rhughes@241
   784
		return -1;
rhughes@241
   785
rhughes@241
   786
	set = razor_set_create_from_yum();
rhughes@241
   787
	if (set == NULL)
rhughes@241
   788
		return 1;
ali@403
   789
	atomic = razor_atomic_open("Yum import repository");
ali@475
   790
	razor_set_write(set, atomic, rawhide_repo_uri, RAZOR_SECTION_ALL);
ali@403
   791
	retval = razor_atomic_commit(atomic);
ali@403
   792
	razor_set_unref(set);
ali@403
   793
	if (retval)
ali@403
   794
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
   795
	else
ali@475
   796
		printf("wrote %s\n", rawhide_repo_uri);
ali@403
   797
	razor_atomic_destroy(atomic);
rhughes@241
   798
ali@403
   799
	return retval;
rhughes@241
   800
}
rhughes@241
   801
ali@320
   802
#if HAVE_RPMLIB
rhughes@241
   803
static int
ali@445
   804
command_import_rpmdb(int argc, char * const argv[])
rhughes@241
   805
{
rhughes@241
   806
	struct razor_set *set;
krh@317
   807
	struct razor_root *root;
ali@424
   808
	struct razor_error *error = NULL;
ali@403
   809
	struct razor_atomic *atomic;
ali@403
   810
	int retval;
krh@317
   811
ali@445
   812
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   813
		case -2:
ali@445
   814
			return 0;
ali@445
   815
		case -1:
ali@445
   816
			return 1;
ali@445
   817
	}
ali@445
   818
ali@445
   819
	if (argc - optind > 0) {
ali@445
   820
		razor_usage(argv[0], 0, NULL, "");
ali@445
   821
		return 1;
ali@445
   822
	}
ali@445
   823
ali@424
   824
	root = razor_root_open(install_root, &error);
ali@403
   825
	if (root == NULL) {
ali@424
   826
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   827
		razor_error_free(error);
krh@317
   828
		return 1;
ali@403
   829
	}
rhughes@241
   830
rhughes@241
   831
	set = razor_set_create_from_rpmdb();
rhughes@241
   832
	if (set == NULL)
rhughes@241
   833
		return 1;
rhughes@241
   834
ali@424
   835
	atomic = razor_atomic_open("Import RPM database");
krh@317
   836
ali@424
   837
	retval = razor_root_update(root, set, atomic);
ali@424
   838
ali@403
   839
	if (retval)
ali@403
   840
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
   841
ali@403
   842
	razor_atomic_destroy(atomic);
ali@403
   843
ali@424
   844
	razor_root_close(root);
ali@424
   845
ali@403
   846
	return retval;
rhughes@241
   847
}
ali@320
   848
#endif
rhughes@241
   849
rhughes@241
   850
static int
rhughes@241
   851
mark_packages_for_update(struct razor_transaction *trans,
rhughes@241
   852
			 struct razor_set *set, const char *pattern)
rhughes@241
   853
{
rhughes@241
   854
	struct razor_package_iterator *pi;
rhughes@241
   855
	struct razor_package *package;
richard@302
   856
	const char *name;
rhughes@241
   857
	int matches = 0;
rhughes@241
   858
rhughes@241
   859
	pi = razor_package_iterator_create(set);
rhughes@241
   860
	while (razor_package_iterator_next(pi, &package,
richard@307
   861
					   RAZOR_DETAIL_NAME, &name,
richard@307
   862
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   863
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   864
			razor_transaction_update_package(trans, package);
rhughes@241
   865
			matches++;
rhughes@241
   866
		}
rhughes@241
   867
	}
rhughes@241
   868
	razor_package_iterator_destroy(pi);
rhughes@241
   869
rhughes@241
   870
	return matches;
rhughes@241
   871
}
rhughes@241
   872
rhughes@241
   873
static int
rhughes@241
   874
mark_packages_for_removal(struct razor_transaction *trans,
rhughes@241
   875
			  struct razor_set *set, const char *pattern)
rhughes@241
   876
{
rhughes@241
   877
	struct razor_package_iterator *pi;
rhughes@241
   878
	struct razor_package *package;
richard@302
   879
	const char *name;
rhughes@241
   880
	int matches = 0;
rhughes@241
   881
rhughes@241
   882
	pi = razor_package_iterator_create(set);
richard@307
   883
	while (razor_package_iterator_next(pi, &package,
richard@307
   884
					   RAZOR_DETAIL_NAME, &name,
richard@307
   885
					   RAZOR_DETAIL_LAST)) {
rhughes@241
   886
		if (pattern && fnmatch(pattern, name, 0) == 0) {
rhughes@241
   887
			razor_transaction_remove_package(trans, package);
rhughes@241
   888
			matches++;
rhughes@241
   889
		}
rhughes@241
   890
	}
rhughes@241
   891
	razor_package_iterator_destroy(pi);
rhughes@241
   892
rhughes@241
   893
	return matches;
rhughes@241
   894
}
rhughes@241
   895
rhughes@241
   896
static int
ali@445
   897
command_remove(int argc, char * const argv[])
rhughes@241
   898
{
ali@363
   899
	struct razor_set *system, *upstream, *next;
rhughes@241
   900
	struct razor_transaction *trans;
ali@424
   901
	struct razor_error *error = NULL;
ali@424
   902
	struct razor_root *root;
ali@403
   903
	int i, retval;
rhughes@241
   904
ali@445
   905
	switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
ali@445
   906
		case -2:
ali@445
   907
			return 0;
ali@445
   908
		case -1:
ali@445
   909
			return 1;
ali@445
   910
	}
ali@445
   911
ali@424
   912
	root = razor_root_open(install_root, &error);
ali@424
   913
	if (root == NULL) {
ali@424
   914
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   915
		razor_error_free(error);
rhughes@241
   916
		return 1;
ali@363
   917
	}
rhughes@241
   918
ali@424
   919
	system = razor_root_get_system_set(root);
ali@363
   920
	upstream = razor_set_create_without_root();
ali@363
   921
	trans = razor_transaction_create(system, upstream);
ali@403
   922
	razor_set_unref(upstream);
ali@445
   923
	for (i = optind; i < argc; i++) {
ali@363
   924
		if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
rhughes@241
   925
			fprintf(stderr, "no match for %s\n", argv[i]);
ali@363
   926
			razor_transaction_destroy(trans);
ali@424
   927
			razor_root_close(root);
rhughes@241
   928
			return 1;
rhughes@241
   929
		}
rhughes@241
   930
	}
rhughes@241
   931
ali@350
   932
	razor_transaction_resolve(trans);
ali@403
   933
	retval = razor_transaction_describe(trans);
ali@403
   934
	if (retval) {
ali@363
   935
		razor_transaction_destroy(trans);
ali@424
   936
		razor_root_close(root);
rhughes@241
   937
		return 1;
ali@363
   938
	}
rhughes@241
   939
ali@369
   940
	next = razor_transaction_commit(trans);
ali@403
   941
ali@424
   942
	retval = update_system(root, NULL, trans, next, "Remove");
ali@363
   943
ali@369
   944
	razor_transaction_destroy(trans);
ali@424
   945
	razor_root_close(root);
ali@403
   946
	razor_set_unref(next);
rhughes@241
   947
ali@403
   948
	return retval;
rhughes@241
   949
}
rhughes@241
   950
rhughes@241
   951
static void
krh@253
   952
print_diff(enum razor_diff_action action,
krh@253
   953
	   struct razor_package *package,
krh@253
   954
	   const char *name,
krh@253
   955
	   const char *version,
krh@253
   956
	   const char *arch,
rhughes@241
   957
	   void *data)
rhughes@241
   958
{
krh@253
   959
	if (action == RAZOR_DIFF_ACTION_ADD)
krh@253
   960
		printf("install %s-%s.%s\n", name, version, arch);
krh@253
   961
	if (action == RAZOR_DIFF_ACTION_REMOVE)
krh@253
   962
		printf("remove %s-%s.%s\n", name, version, arch);
rhughes@241
   963
}
rhughes@241
   964
rhughes@241
   965
static int
ali@445
   966
command_diff(int argc, char * const argv[])
rhughes@241
   967
{
ali@424
   968
	struct razor_error *error = NULL;
rhughes@241
   969
	struct razor_set *set, *updated;
rhughes@241
   970
ali@445
   971
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
   972
		case -2:
ali@445
   973
			return 0;
ali@445
   974
		case -1:
ali@445
   975
			return 1;
ali@445
   976
	}
ali@445
   977
ali@445
   978
	if (argc - optind > 0) {
ali@445
   979
		razor_usage(argv[0], 0, NULL, "");
ali@445
   980
		return 1;
ali@445
   981
	}
ali@445
   982
ali@424
   983
	set = razor_root_open_read_only(install_root, &error);
ali@424
   984
	if (set)
ali@475
   985
		updated = razor_set_open(rawhide_repo_uri, 0, &error);
ali@424
   986
	else
ali@424
   987
		updated = NULL;
ali@424
   988
	if (updated == NULL) {
ali@424
   989
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
   990
		razor_error_free(error);
ali@424
   991
		if (set)
ali@424
   992
			razor_set_unref(set);
rhughes@241
   993
		return 1;
ali@403
   994
	}
rhughes@241
   995
rhughes@241
   996
	razor_set_diff(set, updated, print_diff, NULL);
rhughes@241
   997
ali@403
   998
	razor_set_unref(set);
ali@403
   999
	razor_set_unref(updated);
rhughes@241
  1000
rhughes@241
  1001
	return 0;
rhughes@241
  1002
}
rhughes@241
  1003
rhughes@241
  1004
static int
ali@445
  1005
command_import_rpms(int argc, char * const argv[])
rhughes@241
  1006
{
rhughes@241
  1007
	DIR *dir;
rhughes@241
  1008
	struct dirent *de;
rhughes@241
  1009
	struct razor_importer *importer;
rhughes@241
  1010
	struct razor_set *set;
rhughes@241
  1011
	struct razor_rpm *rpm;
ali@426
  1012
	struct razor_error *error=NULL;
ali@403
  1013
	struct razor_atomic *atomic;
jbowes@263
  1014
	int len, imported_count = 0;
rhughes@241
  1015
	char filename[256];
ali@445
  1016
	const char *dirname;
ali@403
  1017
	int retval;
rhughes@241
  1018
ali@445
  1019
	switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) {
ali@445
  1020
		case -2:
ali@445
  1021
			return 0;
ali@445
  1022
		case -1:
ali@445
  1023
			return 1;
rhughes@241
  1024
	}
rhughes@241
  1025
ali@445
  1026
	if (argc - optind != 1) {
ali@445
  1027
		razor_usage(argv[0], 0, NULL, "dir");
ali@445
  1028
		return 1;
ali@445
  1029
	}
ali@445
  1030
ali@445
  1031
	dirname = argv[optind];
ali@445
  1032
rhughes@241
  1033
	dir = opendir(dirname);
rhughes@241
  1034
	if (dir == NULL) {
rhughes@241
  1035
		fprintf(stderr, "couldn't read dir %s\n", dirname);
rhughes@241
  1036
		return -1;
rhughes@241
  1037
	}
rhughes@241
  1038
krh@249
  1039
	importer = razor_importer_create();
rhughes@241
  1040
rhughes@241
  1041
	while (de = readdir(dir), de != NULL) {
rhughes@241
  1042
		len = strlen(de->d_name);
rhughes@241
  1043
		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
ali@403
  1044
			continue;
rhughes@241
  1045
		snprintf(filename, sizeof filename,
rhughes@241
  1046
			 "%s/%s", dirname, de->d_name);
ali@426
  1047
		rpm = razor_rpm_open(filename, &error);
ali@426
  1048
		if (rpm == NULL) {
ali@426
  1049
			fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@426
  1050
			razor_error_free(error);
ali@426
  1051
			error=NULL;
rhughes@241
  1052
			continue;
ali@426
  1053
		}
rhughes@241
  1054
		if (razor_importer_add_rpm(importer, rpm)) {
rhughes@241
  1055
			fprintf(stderr, "couldn't import %s\n", filename);
rhughes@241
  1056
			break;
rhughes@241
  1057
		}
rhughes@241
  1058
		razor_rpm_close(rpm);
jbowes@263
  1059
jbowes@263
  1060
		printf("\rimporting %d", ++imported_count);
jbowes@263
  1061
		fflush(stdout);
rhughes@241
  1062
	}
rhughes@241
  1063
rhughes@241
  1064
	if (de != NULL) {
rhughes@241
  1065
		razor_importer_destroy(importer);
rhughes@241
  1066
		return -1;
rhughes@241
  1067
	}
rhughes@241
  1068
jbowes@263
  1069
	printf("\nsaving\n");
rhughes@241
  1070
	set = razor_importer_finish(importer);
rhughes@241
  1071
ali@403
  1072
	atomic = razor_atomic_open("Update system database");
ali@403
  1073
	razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
ali@403
  1074
	razor_set_unref(set);
ali@403
  1075
	retval = razor_atomic_commit(atomic);
ali@403
  1076
	if (retval)
ali@403
  1077
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1078
	else
ali@403
  1079
		printf("wrote %s\n", repo_filename);
ali@403
  1080
	razor_atomic_destroy(atomic);
rhughes@241
  1081
ali@403
  1082
	return retval;
rhughes@241
  1083
}
rhughes@241
  1084
ali@403
  1085
static char *
krh@254
  1086
rpm_filename(const char *name, const char *version, const char *arch)
rhughes@241
  1087
{
krh@254
  1088
 	const char *v;
krh@254
  1089
 
krh@254
  1090
 	/* Skip epoch */
krh@253
  1091
	v = strchr(version, ':');
krh@254
  1092
 	if (v != NULL)
krh@254
  1093
 		v = v + 1;
krh@254
  1094
 	else
krh@253
  1095
		v = version;
rhughes@241
  1096
ali@403
  1097
	return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
rhughes@241
  1098
}
rhughes@241
  1099
krh@254
  1100
static int
krh@254
  1101
download_packages(struct razor_set *system, struct razor_set *next)
rhughes@241
  1102
{
krh@316
  1103
	struct razor_install_iterator *ii;
krh@254
  1104
	struct razor_package *package;
krh@316
  1105
	enum razor_install_action action;
krh@254
  1106
	const char *name, *version, *arch;
ali@403
  1107
	char *file, *url, *s;
krh@316
  1108
	int errors = 0, count;
krh@316
  1109
krh@316
  1110
	ii = razor_set_create_install_iterator(system, next);
ali@382
  1111
	while (razor_install_iterator_next(ii, &package, &action, &count)) {
ali@418
  1112
		if (action != RAZOR_INSTALL_ACTION_ADD)
krh@316
  1113
			continue;
krh@316
  1114
ali@382
  1115
		razor_package_get_details(next, package,
krh@316
  1116
					  RAZOR_DETAIL_NAME, &name,
krh@316
  1117
					  RAZOR_DETAIL_VERSION, &version,
krh@316
  1118
					  RAZOR_DETAIL_ARCH, &arch,
krh@316
  1119
					  RAZOR_DETAIL_LAST);
krh@316
  1120
		
ali@403
  1121
		s = rpm_filename(name, version, arch);
ali@475
  1122
		file = razor_concat("Packages/", s, NULL);
ali@475
  1123
		url = razor_path_relative_to_uri(yum_url, file, NULL);
ali@475
  1124
		free(file);
ali@403
  1125
		file = razor_concat("rpms/", s, NULL);
ali@403
  1126
		free(s);
krh@254
  1127
		if (download_if_missing(url, file) < 0)
krh@254
  1128
			errors++;
ali@403
  1129
		free(file);
ali@403
  1130
		free(url);
krh@254
  1131
	}
krh@316
  1132
	razor_install_iterator_destroy(ii);
krh@254
  1133
krh@254
  1134
	if (errors > 0) {
krh@254
  1135
		fprintf(stderr, "failed to download %d packages\n", errors);
krh@254
  1136
                return -1;
krh@254
  1137
        }
krh@254
  1138
krh@254
  1139
	return 0;
krh@254
  1140
}
krh@254
  1141
ali@351
  1142
static struct razor_set *
ali@403
  1143
relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
ali@403
  1144
		  struct razor_relocations *relocations)
ali@351
  1145
{
ali@372
  1146
	int i;
ali@351
  1147
	struct razor_importer *importer;
ali@351
  1148
	struct razor_property_iterator *prop_iter;
ali@351
  1149
	struct razor_package_iterator *pkg_iter;
ali@351
  1150
 	struct razor_file_iterator *file_iter;
ali@351
  1151
 	struct razor_package *package;
ali@351
  1152
	struct razor_property *property;
ali@351
  1153
	struct razor_rpm *rpm;
ali@426
  1154
	struct razor_error *error=NULL;
ali@351
  1155
	const char *name, *version, *arch, *summary, *desc, *url, *license;
ali@369
  1156
	const char *preunprog, *preun, *postunprog, *postun;
ali@372
  1157
	const char *install_prefix;
ali@372
  1158
	const char *const *prefixes;
ali@475
  1159
	char *file, *s, *uri, *filename;
ali@351
  1160
	uint32_t flags;
ali@351
  1161
ali@351
  1162
	importer = razor_importer_create();
ali@351
  1163
	pkg_iter = razor_package_iterator_create(set);
ali@351
  1164
ali@351
  1165
	while (razor_package_iterator_next(pkg_iter, &package,
ali@351
  1166
					   RAZOR_DETAIL_NAME, &name,
ali@351
  1167
					   RAZOR_DETAIL_VERSION, &version,
ali@351
  1168
					   RAZOR_DETAIL_ARCH, &arch,
ali@351
  1169
					   RAZOR_DETAIL_SUMMARY, &summary,
ali@351
  1170
					   RAZOR_DETAIL_DESCRIPTION, &desc,
ali@351
  1171
					   RAZOR_DETAIL_URL, &url,
ali@351
  1172
					   RAZOR_DETAIL_LICENSE, &license,
ali@369
  1173
					   RAZOR_DETAIL_PREUNPROG, &preunprog,
ali@369
  1174
					   RAZOR_DETAIL_PREUN, &preun,
ali@369
  1175
					   RAZOR_DETAIL_POSTUNPROG, &postunprog,
ali@369
  1176
					   RAZOR_DETAIL_POSTUN, &postun,
ali@351
  1177
					   RAZOR_DETAIL_LAST)) {
ali@475
  1178
		filename = rpm_filename(name, version, arch);
ali@475
  1179
		s = razor_concat("Packages/", filename, NULL);
ali@475
  1180
		uri = razor_path_relative_to_uri(yum_url, s, NULL);
ali@403
  1181
		free(s);
ali@475
  1182
		file = razor_concat("rpms/", filename, NULL);
ali@475
  1183
		free(filename);
ali@475
  1184
		download_if_missing(uri, file);
ali@475
  1185
		free(uri);
ali@475
  1186
		uri = razor_path_to_uri(file);
ali@403
  1187
		free(file);
ali@475
  1188
		rpm = razor_rpm_open(uri, &error);
ali@475
  1189
		free(uri);
ali@351
  1190
		if (rpm == NULL) {
ali@447
  1191
			razor_atomic_propagate_error(atomic, error, NULL);
ali@351
  1192
			razor_package_iterator_destroy(pkg_iter);
ali@351
  1193
			razor_importer_destroy(importer);
ali@351
  1194
			return NULL;
ali@351
  1195
		}
ali@351
  1196
ali@351
  1197
		razor_relocations_set_rpm(relocations, rpm);
ali@351
  1198
ali@351
  1199
		razor_importer_begin_package(importer, name, version, arch);
ali@351
  1200
		razor_importer_add_details(importer,
ali@351
  1201
					   summary, desc, url, license);
ali@351
  1202
ali@372
  1203
		razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
ali@372
  1204
				      RAZOR_DETAIL_LAST);
ali@372
  1205
		for (i = 0; prefixes && prefixes[i]; i++) {
ali@372
  1206
			install_prefix = razor_relocations_apply(relocations,
ali@372
  1207
								 prefixes[i]);
ali@372
  1208
			razor_importer_add_install_prefix(importer,
ali@372
  1209
							  install_prefix);
ali@372
  1210
		}
ali@372
  1211
ali@372
  1212
		razor_rpm_close(rpm);
ali@372
  1213
ali@351
  1214
		prop_iter = razor_property_iterator_create(set, package);
ali@351
  1215
		while (razor_property_iterator_next(prop_iter, &property,
ali@351
  1216
						    &name, &flags, &version))
ali@351
  1217
			razor_importer_add_property(importer,
ali@351
  1218
						    name, flags, version);
ali@351
  1219
		razor_property_iterator_destroy(prop_iter);
ali@351
  1220
ali@377
  1221
		file_iter = razor_file_iterator_create(set, package, 0);
ali@351
  1222
		while (razor_file_iterator_next(file_iter, &name)) {
ali@351
  1223
			name = razor_relocations_apply(relocations, name);
ali@351
  1224
			razor_importer_add_file(importer, name);
ali@351
  1225
		}
ali@351
  1226
		razor_file_iterator_destroy(file_iter);
ali@351
  1227
ali@369
  1228
		razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
ali@369
  1229
					  preunprog, preun);
ali@369
  1230
		razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
ali@369
  1231
					  postunprog, postun);
ali@369
  1232
ali@351
  1233
		razor_importer_finish_package(importer);
ali@351
  1234
	}
ali@351
  1235
ali@351
  1236
	razor_package_iterator_destroy(pkg_iter);
ali@351
  1237
	return razor_importer_finish(importer);
ali@351
  1238
}
ali@351
  1239
krh@254
  1240
static int
ali@369
  1241
install_package(struct razor_transaction *trans, struct razor_set *set,
ali@403
  1242
		struct razor_atomic *atomic, struct razor_package *package,
ali@403
  1243
		struct razor_relocations *relocations, int install_count,
ali@403
  1244
		enum razor_stage_type stage)
ali@363
  1245
{
ali@363
  1246
	int retval;
ali@363
  1247
	const char *name, *version, *arch;
ali@475
  1248
	char *file, *s, *uri;
ali@363
  1249
	struct razor_rpm *rpm;
ali@426
  1250
	struct razor_error *error=NULL;
ali@363
  1251
ali@363
  1252
	razor_package_get_details(set, package,
ali@363
  1253
				  RAZOR_DETAIL_NAME, &name,
ali@363
  1254
				  RAZOR_DETAIL_VERSION, &version,
ali@363
  1255
				  RAZOR_DETAIL_ARCH, &arch,
ali@363
  1256
				  RAZOR_DETAIL_LAST);
ali@363
  1257
ali@403
  1258
	if (stage & RAZOR_STAGE_SCRIPTS_PRE)
ali@403
  1259
		printf("install %s-%s\n", name, version);
ali@363
  1260
ali@403
  1261
	s = rpm_filename(name, version, arch);
ali@403
  1262
	file = razor_concat("rpms/", s, NULL);
ali@403
  1263
	free(s);
ali@475
  1264
	uri = razor_path_to_uri(file);
ali@403
  1265
	free(file);
ali@475
  1266
	rpm = razor_rpm_open(uri, &error);
ali@475
  1267
	free(uri);
ali@363
  1268
	if (rpm == NULL) {
ali@447
  1269
		razor_atomic_propagate_error(atomic, error, NULL);
ali@426
  1270
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@363
  1271
		return -1;
ali@363
  1272
	}
ali@363
  1273
	if (relocations)
ali@363
  1274
		razor_rpm_set_relocations(rpm, relocations);
ali@369
  1275
	razor_transaction_fixup_package(trans, package, rpm);
ali@403
  1276
	retval = razor_rpm_install(rpm, atomic, install_root, install_count,
ali@403
  1277
				   stage);
ali@403
  1278
	if (retval < 0) {
ali@403
  1279
		s = rpm_filename(name, version, arch);
ali@403
  1280
		fprintf(stderr, "%s: %s\n", s,
ali@403
  1281
			razor_atomic_get_error_msg(atomic));
ali@403
  1282
		free(s);
ali@403
  1283
	}
ali@363
  1284
	razor_rpm_close(rpm);
ali@363
  1285
	return retval;
ali@363
  1286
}
ali@363
  1287
ali@412
  1288
/*
ali@418
  1289
 * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
ali@418
  1290
 * is met (in which case the action is consumed).
ali@412
  1291
 */
ali@363
  1292
static int
ali@403
  1293
update_packages(struct razor_transaction *trans,
ali@403
  1294
		struct razor_install_iterator *ii, struct razor_set *system,
ali@403
  1295
		struct razor_set *next, struct razor_atomic *atomic,
ali@403
  1296
		struct razor_relocations *relocations,
ali@418
  1297
		enum razor_stage_type stage)
krh@254
  1298
{
krh@254
  1299
	struct razor_package *package;
krh@316
  1300
	enum razor_install_action action;
ali@363
  1301
	int retval = 0, count;
ali@403
  1302
ali@412
  1303
	while (!retval && razor_install_iterator_next(ii, &package, &action,
ali@412
  1304
						      &count)) {
ali@418
  1305
		if (action == RAZOR_INSTALL_ACTION_ADD) {
ali@418
  1306
			if (install_package(trans, next, atomic, package,
ali@418
  1307
					    relocations, count, stage))
ali@418
  1308
				retval = -1;
ali@418
  1309
		} else if (action == RAZOR_INSTALL_ACTION_REMOVE) {
ali@418
  1310
			if (razor_package_remove(system, next, atomic, package,
ali@418
  1311
						 install_root, count, stage))
ali@418
  1312
				retval = -1;
ali@418
  1313
		} else if (action == RAZOR_INSTALL_ACTION_COMMIT)
ali@418
  1314
				retval = 1;
rhughes@241
  1315
	}
rhughes@241
  1316
ali@363
  1317
	return retval;
rhughes@241
  1318
}
rhughes@241
  1319
rhughes@241
  1320
static int
ali@424
  1321
update_system(struct razor_root *root, struct razor_relocations *relocations,
ali@424
  1322
	      struct razor_transaction *trans, struct razor_set *next,
ali@424
  1323
	      const char *verb)
ali@418
  1324
{
ali@424
  1325
	struct razor_set *system, *set;
ali@418
  1326
	struct razor_atomic *atomic;
ali@418
  1327
	struct razor_install_iterator *ii;
ali@418
  1328
	int r, retval = 0;
ali@418
  1329
	char *description;
ali@418
  1330
	size_t pos;
ali@418
  1331
ali@418
  1332
	description = razor_concat(verb, " packages", NULL);
ali@418
  1333
ali@424
  1334
	system = razor_set_ref(razor_root_get_system_set(root));
ali@424
  1335
ali@418
  1336
	ii = razor_set_create_install_iterator(system, next);
ali@418
  1337
ali@418
  1338
	do {
ali@418
  1339
		pos = razor_install_iterator_tell(ii);
ali@418
  1340
ali@418
  1341
		atomic = razor_atomic_open(description);
ali@418
  1342
ali@418
  1343
		r = update_packages(trans, ii, system, next, atomic,
ali@418
  1344
				    relocations, RAZOR_STAGE_SCRIPTS_PRE);
ali@418
  1345
		if (r < 0) {
ali@418
  1346
			fprintf(stderr, "%s aborted\n", verb);
ali@418
  1347
			retval = r;
ali@418
  1348
		} else {
ali@418
  1349
			razor_install_iterator_seek(ii, pos);
ali@418
  1350
			r = update_packages(trans, ii, system, next, atomic,
ali@418
  1351
					    relocations, RAZOR_STAGE_FILES);
ali@418
  1352
ali@418
  1353
			if (r == 1) {
ali@418
  1354
				set = razor_install_iterator_commit_set(ii);
ali@424
  1355
				razor_root_update(root, set, atomic);
ali@418
  1356
				razor_set_unref(set);
ali@418
  1357
			} else if (r == 0)
ali@424
  1358
				razor_root_update(root, next, atomic);
ali@418
  1359
ali@418
  1360
			retval = razor_atomic_commit(atomic);
ali@421
  1361
			if (retval)
ali@418
  1362
				fprintf(stderr, "%s\n",
ali@418
  1363
					razor_atomic_get_error_msg(atomic));
ali@421
  1364
			else {
ali@418
  1365
				razor_install_iterator_seek(ii, pos);
ali@418
  1366
				update_packages(trans, ii, system, next,
ali@418
  1367
						atomic, relocations,
ali@418
  1368
						RAZOR_STAGE_SCRIPTS_POST);
ali@418
  1369
			}
ali@418
  1370
		}
ali@418
  1371
ali@418
  1372
		razor_atomic_destroy(atomic);
ali@418
  1373
	} while(!retval && r == 1);
ali@418
  1374
ali@458
  1375
	razor_install_iterator_destroy(ii);
ali@458
  1376
ali@424
  1377
	razor_set_unref(system);
ali@424
  1378
ali@418
  1379
	free(description);
ali@418
  1380
ali@418
  1381
	return retval;
ali@418
  1382
}
ali@418
  1383
ali@418
  1384
static int
ali@445
  1385
command_install_or_update(int argc, char * const argv[], int do_update)
rhughes@241
  1386
{
ali@424
  1387
	struct razor_relocations *relocations = NULL;
ali@351
  1388
	struct razor_set *system, *upstream, *next, *set;
rhughes@241
  1389
	struct razor_transaction *trans;
ali@424
  1390
	struct razor_error *error = NULL;
ali@403
  1391
	struct razor_atomic *atomic;
ali@424
  1392
	struct razor_root *root;
ali@445
  1393
	int opt, i, retval = 0, len, dependencies = 1;
ali@351
  1394
	char *oldpath;
ali@445
  1395
	const char *arg;
ali@445
  1396
	enum {
ali@445
  1397
		opt_no_dependencies = 1,
ali@445
  1398
		opt_relocate = 2,
ali@445
  1399
	};
ali@445
  1400
	static struct razor_option options[] = {
ali@445
  1401
		{ .name = "no-dependencies", .has_arg = no_argument,
ali@445
  1402
		  .val = opt_no_dependencies,
ali@445
  1403
		  .description = "Do not verify package dependencies" },
ali@445
  1404
		{ .name = "relocate", .has_arg = required_argument,
ali@445
  1405
		  .val = opt_relocate,
ali@445
  1406
		  .description = "Relocate files from path OLD to NEW",
ali@445
  1407
		  .arg_description = "OLD=NEW" },
ali@445
  1408
	};
rhughes@241
  1409
ali@445
  1410
	do {
ali@445
  1411
		opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
ali@445
  1412
				   "rpm ...", &arg);
ali@445
  1413
		switch (opt) {
ali@445
  1414
			case -2:
ali@445
  1415
				return 0;
ali@445
  1416
			case -1:
ali@445
  1417
				return 1;
ali@445
  1418
			case opt_no_dependencies:
ali@445
  1419
				dependencies = 0;
ali@445
  1420
				break;
ali@445
  1421
			case opt_relocate:
ali@445
  1422
				if (strchr(arg, '=') == NULL) {
ali@445
  1423
					razor_usage(argv[0],
ali@445
  1424
						    ARRAY_SIZE(options),
ali@445
  1425
						    options, "rpm ...");
ali@445
  1426
					return 1;
ali@445
  1427
				}
ali@445
  1428
				len = strchr(arg, '=') - arg;
ali@445
  1429
				oldpath = malloc(len + 1);
ali@445
  1430
				strncpy(oldpath, arg, len);
ali@445
  1431
				oldpath[len] = '\0';
ali@445
  1432
				if (!relocations)
ali@445
  1433
				       relocations = razor_relocations_create();
ali@445
  1434
				razor_relocations_add(relocations, oldpath,
ali@445
  1435
						      arg + len + 1);
ali@445
  1436
				free(oldpath);
ali@445
  1437
				break;
ali@445
  1438
		}
ali@445
  1439
	} while (opt);
ali@351
  1440
ali@475
  1441
	upstream = razor_set_open(rawhide_repo_uri, 0, &error);
ali@424
  1442
	if (upstream == NULL) {
ali@424
  1443
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1444
		razor_error_free(error);
ali@458
  1445
		if (relocations)
ali@458
  1446
			razor_relocations_destroy(relocations);
ali@424
  1447
		return 1;
ali@424
  1448
	}
ali@424
  1449
ali@418
  1450
	if (do_update)
ali@418
  1451
		atomic = razor_atomic_open("Update packages");
ali@418
  1452
	else
ali@418
  1453
		atomic = razor_atomic_open("Install packages");
ali@418
  1454
ali@351
  1455
	if (relocations) {
ali@403
  1456
		set = relocate_packages(upstream, atomic, relocations);
ali@403
  1457
		if (set == NULL) {
ali@403
  1458
			fprintf(stderr, "%s\n",
ali@403
  1459
				razor_atomic_get_error_msg(atomic));
ali@403
  1460
			razor_atomic_destroy(atomic);
ali@403
  1461
			razor_set_unref(upstream);
ali@403
  1462
			return 1;
ali@403
  1463
		}
ali@403
  1464
		razor_set_unref(upstream);
ali@351
  1465
		upstream = set;
ali@351
  1466
	}
ali@351
  1467
ali@424
  1468
	root = razor_root_open(install_root, &error);
ali@424
  1469
	if (root == NULL) {
ali@424
  1470
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1471
		razor_error_free(error);
ali@424
  1472
		razor_atomic_destroy(atomic);
ali@424
  1473
		razor_set_unref(upstream);
ali@424
  1474
		if (relocations)
ali@424
  1475
			razor_relocations_destroy(relocations);
ali@424
  1476
		return 1;
ali@424
  1477
	}
ali@403
  1478
ali@424
  1479
	system = razor_root_get_system_set(root);
krh@250
  1480
	trans = razor_transaction_create(system, upstream);
rhughes@241
  1481
ali@445
  1482
	if (optind == argc && do_update)
ali@382
  1483
		razor_transaction_update_all(trans);
ali@445
  1484
	for (i = optind; i < argc; i++) {
ali@389
  1485
		if (do_update &&
ali@389
  1486
		    mark_packages_for_update(trans, system, argv[i]))
ali@389
  1487
			continue;
rhughes@241
  1488
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
rhughes@241
  1489
			fprintf(stderr, "no package matched %s\n", argv[i]);
ali@369
  1490
			razor_transaction_destroy(trans);
ali@424
  1491
			razor_root_close(root);
ali@403
  1492
			razor_set_unref(upstream);
ali@403
  1493
			razor_atomic_destroy(atomic);
ali@424
  1494
			if (relocations)
ali@424
  1495
				razor_relocations_destroy(relocations);
rhughes@241
  1496
			return 1;
rhughes@241
  1497
		}
rhughes@241
  1498
	}
rhughes@241
  1499
rhughes@241
  1500
	if (dependencies) {
krh@245
  1501
		razor_transaction_resolve(trans);
krh@245
  1502
		if (razor_transaction_describe(trans) > 0) {
ali@369
  1503
			razor_transaction_destroy(trans);
ali@403
  1504
			razor_set_unref(upstream);
ali@424
  1505
			razor_root_close(root);
ali@403
  1506
			razor_atomic_destroy(atomic);
ali@424
  1507
			if (relocations)
ali@424
  1508
				razor_relocations_destroy(relocations);
rhughes@241
  1509
			return 1;
rhughes@241
  1510
		}
rhughes@241
  1511
	}
rhughes@241
  1512
ali@475
  1513
	if (razor_atomic_create_dir(atomic, "file:rpms",
ali@418
  1514
				    S_IRWXU | S_IRWXG | S_IRWXO) ||
ali@418
  1515
	    razor_atomic_commit(atomic)) {
ali@403
  1516
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@369
  1517
		razor_transaction_destroy(trans);
ali@403
  1518
		razor_set_unref(upstream);
ali@424
  1519
		razor_root_close(root);
ali@403
  1520
		razor_atomic_destroy(atomic);
ali@424
  1521
		if (relocations)
ali@424
  1522
			razor_relocations_destroy(relocations);
rhughes@241
  1523
		return 1;
rhughes@241
  1524
	}
rhughes@241
  1525
ali@418
  1526
	razor_atomic_destroy(atomic);
ali@418
  1527
ali@382
  1528
	next = razor_transaction_commit(trans);
ali@382
  1529
krh@254
  1530
	if (download_packages(system, next) < 0) {
ali@403
  1531
		razor_set_unref(next);
ali@369
  1532
		razor_transaction_destroy(trans);
ali@403
  1533
		razor_set_unref(upstream);
ali@424
  1534
		razor_root_close(root);
ali@424
  1535
		if (relocations)
ali@424
  1536
			razor_relocations_destroy(relocations);
rhughes@241
  1537
                return 1;
rhughes@241
  1538
        }
rhughes@241
  1539
ali@424
  1540
	retval = update_system(root, relocations, trans, next,
ali@418
  1541
			       do_update ? "Update" : "Install");
ali@403
  1542
ali@418
  1543
	razor_set_unref(upstream);
ali@424
  1544
	razor_root_close(root);
ali@403
  1545
ali@369
  1546
	razor_transaction_destroy(trans);
ali@351
  1547
	if (relocations)
ali@351
  1548
		razor_relocations_destroy(relocations);
ali@403
  1549
ali@403
  1550
	razor_set_unref(next);
ali@403
  1551
ali@403
  1552
	return retval;
rhughes@241
  1553
}
rhughes@241
  1554
rhughes@241
  1555
static int
ali@445
  1556
command_update(int argc, char * const argv[])
ali@382
  1557
{
ali@382
  1558
	return command_install_or_update(argc, argv, 1);
ali@382
  1559
}
ali@382
  1560
ali@382
  1561
static int
ali@445
  1562
command_install(int argc, char * const argv[])
ali@382
  1563
{
ali@382
  1564
	return command_install_or_update(argc, argv, 0);
ali@382
  1565
}
ali@382
  1566
ali@382
  1567
static int
ali@445
  1568
command_init(int argc, char * const argv[])
rhughes@241
  1569
{
ali@425
  1570
	int retval;
ali@425
  1571
	struct razor_error *error = NULL;
ali@425
  1572
ali@445
  1573
	switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
ali@445
  1574
		case -2:
ali@445
  1575
			return 0;
ali@445
  1576
		case -1:
ali@445
  1577
			return 1;
ali@445
  1578
	}
ali@445
  1579
ali@445
  1580
	if (argc - optind > 0) {
ali@445
  1581
		razor_usage(argv[0], 0, NULL, "");
ali@445
  1582
		return 1;
ali@445
  1583
	}
ali@445
  1584
ali@425
  1585
	retval = razor_root_create(install_root, &error);
ali@425
  1586
	if (retval) {
ali@425
  1587
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@425
  1588
		razor_error_free(error);
ali@425
  1589
	} else
ali@425
  1590
		printf("Created install root\n");
ali@425
  1591
ali@425
  1592
	return retval;
rhughes@241
  1593
}
rhughes@241
  1594
rhughes@241
  1595
static int
ali@445
  1596
command_download(int argc, char * const argv[])
rhughes@241
  1597
{
ali@424
  1598
	struct razor_error *error = NULL;
ali@403
  1599
	struct razor_atomic *atomic;
rhughes@241
  1600
	struct razor_set *set;
rhughes@241
  1601
	struct razor_package_iterator *pi;
rhughes@241
  1602
	struct razor_package *package;
ali@445
  1603
	const char *pattern, *name, *version, *arch;
ali@475
  1604
	char *url, *file, *s, filename[256];
rhughes@241
  1605
	int matches = 0;
rhughes@241
  1606
ali@445
  1607
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1608
		case -2:
ali@445
  1609
			return 0;
ali@445
  1610
		case -1:
ali@445
  1611
			return 1;
ali@445
  1612
	}
ali@445
  1613
ali@445
  1614
	if (argc - optind > 1) {
ali@445
  1615
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1616
		return 1;
ali@445
  1617
	}
ali@445
  1618
ali@445
  1619
	pattern = argv[optind];
ali@445
  1620
ali@475
  1621
	set = razor_set_open(rawhide_repo_uri, 0, &error);
ali@424
  1622
	if (set == NULL) {
ali@424
  1623
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1624
		razor_error_free(error);
ali@424
  1625
		return 1;
ali@424
  1626
	}
ali@424
  1627
ali@403
  1628
	atomic = razor_atomic_open("Download packages");
ali@403
  1629
ali@475
  1630
	if (razor_atomic_create_dir(atomic, "file:rpms", 
ali@403
  1631
				    S_IRWXU | S_IRWXG | S_IRWXO)) {
ali@403
  1632
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1633
		razor_atomic_destroy(atomic);
rhughes@241
  1634
		return 1;
rhughes@241
  1635
	}
rhughes@241
  1636
ali@403
  1637
	if (razor_atomic_commit(atomic)) {
ali@403
  1638
		fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
ali@403
  1639
		razor_atomic_destroy(atomic);
ali@403
  1640
		return 1;
ali@403
  1641
	}
ali@403
  1642
	razor_atomic_destroy(atomic);
ali@403
  1643
rhughes@241
  1644
	pi = razor_package_iterator_create(set);
rhughes@241
  1645
	while (razor_package_iterator_next(pi, &package,
richard@302
  1646
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1647
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1648
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1649
					   RAZOR_DETAIL_LAST)) {
rhughes@241
  1650
		if (pattern && fnmatch(pattern, name, 0) != 0)
rhughes@241
  1651
			continue;
rhughes@241
  1652
rhughes@241
  1653
		matches++;
ali@475
  1654
		snprintf(filename, sizeof filename,
ali@475
  1655
			 "%s-%s.%s.rpm", name, version, arch);
ali@475
  1656
		s = razor_concat("Packages/", filename, NULL);
ali@475
  1657
		url = razor_path_relative_to_uri(yum_url, s, NULL);
ali@475
  1658
		free(s);
ali@475
  1659
		file = razor_concat("rpms/", filename, NULL);
rhughes@241
  1660
		download_if_missing(url, file);
ali@475
  1661
		free(url);
ali@475
  1662
		free(file);
rhughes@241
  1663
	}
rhughes@241
  1664
	razor_package_iterator_destroy(pi);
ali@403
  1665
	razor_set_unref(set);
rhughes@241
  1666
rhughes@241
  1667
	if (matches == 0)
rhughes@241
  1668
		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
rhughes@241
  1669
	else if (matches == 1)
rhughes@241
  1670
		fprintf(stderr, "downloaded 1 package\n");
rhughes@241
  1671
	else
rhughes@241
  1672
		fprintf(stderr, "downloaded %d packages\n", matches);
rhughes@241
  1673
rhughes@241
  1674
	return 0;
rhughes@241
  1675
}
rhughes@241
  1676
jbowes@258
  1677
static int
ali@457
  1678
command_dump(int argc, char * const argv[])
ali@457
  1679
{
ali@457
  1680
	struct razor_error *error = NULL;
ali@457
  1681
	const char *filename;
ali@457
  1682
ali@457
  1683
	switch (razor_getopt(argc, argv, 0, NULL, "[filename]", NULL)) {
ali@457
  1684
		case -2:
ali@457
  1685
			return 0;
ali@457
  1686
		case -1:
ali@457
  1687
			return 1;
ali@457
  1688
	}
ali@457
  1689
ali@457
  1690
	if (argc - optind > 1) {
ali@457
  1691
		razor_usage(argv[0], 0, NULL, "[filename]");
ali@457
  1692
		return 1;
ali@457
  1693
	}
ali@457
  1694
ali@457
  1695
	filename = argv[optind];
ali@457
  1696
ali@457
  1697
	if (razor_dump_database(stdout, install_root, filename, &error)) {
ali@457
  1698
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@457
  1699
		razor_error_free(error);
ali@457
  1700
		return 1;
ali@457
  1701
	}
ali@457
  1702
ali@457
  1703
	return 0;
ali@457
  1704
}
ali@457
  1705
ali@457
  1706
static int
ali@445
  1707
command_info(int argc, char * const argv[])
jbowes@258
  1708
{
ali@424
  1709
	struct razor_error *error = NULL;
jbowes@258
  1710
	struct razor_set *set;
jbowes@258
  1711
	struct razor_package_iterator *pi;
jbowes@258
  1712
	struct razor_package *package;
ali@462
  1713
	struct razor_string_iterator *si;
ali@445
  1714
	const char *pattern, *name, *version, *arch;
jbowes@258
  1715
	const char *summary, *description, *url, *license;
ali@462
  1716
	const char *prefix;
jbowes@258
  1717
ali@445
  1718
	switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
ali@445
  1719
		case -2:
ali@445
  1720
			return 0;
ali@445
  1721
		case -1:
ali@445
  1722
			return 1;
ali@445
  1723
	}
ali@445
  1724
ali@445
  1725
	if (argc - optind > 1) {
ali@445
  1726
		razor_usage(argv[0], 0, NULL, "[pattern]");
ali@445
  1727
		return 1;
ali@445
  1728
	}
ali@445
  1729
ali@445
  1730
	pattern = argv[optind];
ali@445
  1731
ali@424
  1732
	set = razor_root_open_read_only(install_root, &error);
ali@403
  1733
	if (set == NULL) {
ali@424
  1734
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1735
		razor_error_free(error);
jbowes@288
  1736
		return 1;
ali@403
  1737
	}
krh@317
  1738
jbowes@258
  1739
	pi = razor_package_iterator_create(set);
jbowes@258
  1740
	while (razor_package_iterator_next(pi, &package,
richard@302
  1741
					   RAZOR_DETAIL_NAME, &name,
richard@302
  1742
					   RAZOR_DETAIL_VERSION, &version,
richard@307
  1743
					   RAZOR_DETAIL_ARCH, &arch,
richard@307
  1744
					   RAZOR_DETAIL_LAST)) {
jbowes@258
  1745
		if (pattern && fnmatch(pattern, name, 0) != 0)
jbowes@258
  1746
			continue;
jbowes@258
  1747
ali@462
  1748
		printf ("Name:        %s\n", name);
ali@462
  1749
		printf ("Arch:        %s\n", arch);
ali@462
  1750
		printf ("Version:     %s\n", version);
ali@462
  1751
ali@462
  1752
		si = razor_install_prefix_iterator_create(set, package);
ali@462
  1753
		if (razor_string_iterator_next(si, &prefix)) {
ali@462
  1754
			printf ("Relocations: %s\n", prefix);
ali@462
  1755
			while (razor_string_iterator_next(si, &prefix))
ali@462
  1756
				printf ("           : %s\n", prefix);
ali@462
  1757
		}
ali@462
  1758
		razor_string_iterator_destroy(si);
ali@462
  1759
richard@302
  1760
		razor_package_get_details (set, package,
richard@302
  1761
					   RAZOR_DETAIL_SUMMARY, &summary,
richard@302
  1762
					   RAZOR_DETAIL_DESCRIPTION, &description,
richard@302
  1763
					   RAZOR_DETAIL_URL, &url,
richard@302
  1764
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1765
					   RAZOR_DETAIL_LAST);
jbowes@258
  1766
jbowes@258
  1767
		printf ("URL:         %s\n", url);
jbowes@258
  1768
		printf ("License:     %s\n", license);
jbowes@258
  1769
		printf ("Summary:     %s\n", summary);
jbowes@258
  1770
		printf ("Description:\n");
jbowes@258
  1771
		printf ("%s\n", description);
jbowes@258
  1772
		printf ("\n");
jbowes@258
  1773
	}
jbowes@258
  1774
	razor_package_iterator_destroy(pi);
ali@403
  1775
	razor_set_unref(set);
jbowes@258
  1776
jbowes@258
  1777
	return 0;
jbowes@258
  1778
}
jbowes@258
  1779
jbowes@292
  1780
#define SEARCH_MAX 256
jbowes@292
  1781
jbowes@292
  1782
static int
ali@445
  1783
command_search(int argc, char * const argv[])
jbowes@292
  1784
{
ali@424
  1785
	struct razor_error *error = NULL;
jbowes@292
  1786
	struct razor_set *set;
jbowes@292
  1787
	struct razor_package_iterator *pi;
jbowes@292
  1788
	struct razor_package *package;
jbowes@292
  1789
	char pattern[SEARCH_MAX];
jbowes@292
  1790
	const char *name, *version, *arch;
jbowes@292
  1791
	const char *summary, *description, *url, *license;
jbowes@292
  1792
ali@445
  1793
	switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
ali@445
  1794
		case -2:
ali@445
  1795
			return 0;
ali@445
  1796
		case -1:
ali@445
  1797
			return 1;
ali@445
  1798
	}
ali@445
  1799
ali@445
  1800
	if (argc != 2) {
ali@445
  1801
		razor_usage(argv[0], 0, NULL, "pattern");
jbowes@292
  1802
		return 1;
jbowes@292
  1803
	}
jbowes@292
  1804
ali@445
  1805
	snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
jbowes@292
  1806
ali@475
  1807
	set = razor_set_open(rawhide_repo_uri, 0, &error);
ali@424
  1808
	if (set == NULL) {
ali@424
  1809
		fprintf(stderr, "%s\n", razor_error_get_msg(error));
ali@424
  1810
		razor_error_free(error);
jbowes@292
  1811
		return 1;
ali@403
  1812
	}
richard@310
  1813
jbowes@292
  1814
	pi = razor_package_iterator_create(set);
jbowes@292
  1815
	while (razor_package_iterator_next(pi, &package,
richard@304
  1816
					   RAZOR_DETAIL_NAME, &name,
richard@304
  1817
					   RAZOR_DETAIL_VERSION, &version,
krh@305
  1818
					   RAZOR_DETAIL_ARCH, &arch,
krh@305
  1819
					   RAZOR_DETAIL_SUMMARY, &summary,
krh@305
  1820
					   RAZOR_DETAIL_DESCRIPTION, &description,
krh@305
  1821
					   RAZOR_DETAIL_URL, &url,
krh@305
  1822
					   RAZOR_DETAIL_LICENSE, &license,
richard@307
  1823
					   RAZOR_DETAIL_LAST)) {
krh@305
  1824
		if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
krh@305
  1825
		    !fnmatch(pattern, url, FNM_CASEFOLD) ||
krh@305
  1826
		    !fnmatch(pattern, summary, FNM_CASEFOLD) ||
krh@305
  1827
		    !fnmatch(pattern, description, FNM_CASEFOLD))
krh@305
  1828
			printf("%s-%s.%s: %s\n", name, version, arch, summary);
jbowes@292
  1829
	}
jbowes@292
  1830
	razor_package_iterator_destroy(pi);
ali@403
  1831
	razor_set_unref(set);
jbowes@292
  1832
jbowes@292
  1833
	return 0;
jbowes@292
  1834
}
jbowes@292
  1835
rhughes@241
  1836
static struct {
rhughes@241
  1837
	const char *name;
rhughes@241
  1838
	const char *description;
ali@445
  1839
	int (*func)(int argc, char * const argv[]);
rhughes@241
  1840
} razor_commands[] = {
ali@445
  1841
	{ "diff", "Show diff between two package sets", command_diff },
ali@445
  1842
	{ "download", "Download packages", command_download },
ali@457
  1843
	{ "dump", "Low-level database dump (for debugging)", command_dump },
ali@445
  1844
	{ "help", "List available commands", command_help },
ali@320
  1845
#if HAVE_RPMLIB
ali@445
  1846
	{ "import-rpmdb", "Import the system rpm database",
ali@445
  1847
	  command_import_rpmdb },
ali@320
  1848
#endif
ali@445
  1849
	{ "import-rpms", "Import rpms from the given directory",
ali@445
  1850
	  command_import_rpms },
ali@445
  1851
	{ "import-yum", "Import yum metadata files", command_import_yum },
ali@445
  1852
	{ "info", "Display package details", command_info },
ali@445
  1853
	{ "init", "Init razor root", command_init },
ali@445
  1854
	{ "install", "Install rpm", command_install },
ali@445
  1855
	{ "list", "List all packages", command_list },
ali@445
  1856
	{ "list-conflicts", "List all conflicts for the given package",
ali@445
  1857
	  command_list_conflicts },
ali@445
  1858
	{ "list-file-packages", "List packages owning file",
ali@445
  1859
	  command_list_file_packages },
ali@445
  1860
	{ "list-files", "List files for package set", command_list_files },
ali@445
  1861
	{ "list-obsoletes", "List all obsoletes for the given package",
ali@445
  1862
	  command_list_obsoletes },
ali@445
  1863
	{ "list-package-files", "List files in package",
ali@445
  1864
	  command_list_package_files },
ali@445
  1865
	{ "list-provides", "List all provides for the given package",
ali@445
  1866
	  command_list_provides },
ali@445
  1867
	{ "list-requires", "List all requires for the given package",
ali@445
  1868
	  command_list_requires },
ali@445
  1869
	{ "list-scripts", "List all scripts for the given package",
ali@445
  1870
	  command_list_scripts },
ali@445
  1871
	{ "remove", "Remove specified packages", command_remove },
ali@445
  1872
	{ "search", "Search package details", command_search },
ali@445
  1873
	{ "update", "Update all or specified packages", command_update },
ali@445
  1874
	{ "what-provides", "List the packages that have the given provides",
ali@445
  1875
	  command_what_provides },
ali@445
  1876
	{ "what-requires", "List the packages that have the given requires",
ali@445
  1877
	  command_what_requires },
rhughes@241
  1878
};
rhughes@241
  1879
rhughes@241
  1880
static int
ali@445
  1881
command_help(int argc, char * const argv[])
rhughes@241
  1882
{
rhughes@241
  1883
	int i;
rhughes@241
  1884
ali@445
  1885
	printf("Available commands:\n");
rhughes@241
  1886
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
rhughes@241
  1887
		printf("  %-20s%s\n",
rhughes@241
  1888
		       razor_commands[i].name, razor_commands[i].description);
ali@445
  1889
	printf("\nType \"razor --help\" for help about global options\n"
ali@445
  1890
	       "or \"razor <command> --help\" for help about a particular "
ali@445
  1891
	       "command's options.\n");
rhughes@241
  1892
ali@445
  1893
	return 0;
rhughes@241
  1894
}
rhughes@241
  1895
rhughes@241
  1896
int
ali@445
  1897
main(int argc, char *argv[])
rhughes@241
  1898
{
krh@317
  1899
	char *repo, *root;
ali@445
  1900
	int i, opt, main_optind;
ali@445
  1901
	int do_help_commands = 0;
ali@445
  1902
	enum {
ali@445
  1903
		opt_database = 1,
ali@445
  1904
		opt_help,
ali@445
  1905
		opt_help_commands,
ali@445
  1906
		opt_root,
ali@445
  1907
		opt_url,
ali@445
  1908
	};
ali@445
  1909
	struct option options[] = {
ali@445
  1910
		{ .name = "database", .has_arg = required_argument,
ali@445
  1911
		  .val = opt_database },
ali@445
  1912
		{ .name = "help", .has_arg = no_argument, .val = opt_help },
ali@445
  1913
		{ .name = "help-commands", .has_arg = no_argument,
ali@445
  1914
		  .flag = &do_help_commands, .val = TRUE },
ali@445
  1915
		{ .name = "root", .has_arg = required_argument,
ali@445
  1916
		  .val = opt_root },
ali@445
  1917
		{ .name = "url", .has_arg = required_argument, .val = opt_url },
ali@445
  1918
		{ 0, }
ali@445
  1919
	};
rhughes@241
  1920
rhughes@241
  1921
	repo = getenv("RAZOR_REPO");
rhughes@241
  1922
	if (repo != NULL)
rhughes@241
  1923
		repo_filename = repo;
rhughes@241
  1924
krh@317
  1925
	root = getenv("RAZOR_ROOT");
krh@317
  1926
	if (root != NULL)
krh@317
  1927
		install_root = root;
krh@317
  1928
rhughes@241
  1929
	yum_url = getenv("YUM_URL");
rhughes@241
  1930
	if (yum_url == NULL)
rhughes@241
  1931
		yum_url = YUM_URL;
rhughes@241
  1932
ali@359
  1933
	if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
ali@359
  1934
		razor_disable_root_name_checks(1);
ali@359
  1935
ali@445
  1936
	optind = 1;
ali@445
  1937
	opterr = 0;
ali@445
  1938
ali@445
  1939
	while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
ali@445
  1940
		switch (opt) {
ali@445
  1941
			case opt_database:
ali@475
  1942
				razor_set_database_uri(optarg);
ali@445
  1943
				break;
ali@445
  1944
			case opt_help:
ali@445
  1945
			default:
ali@445
  1946
				printf("Usage: razor [global-options] command "
ali@445
  1947
				       "[command-options-and-arguments]\n\n");
ali@445
  1948
				printf("Options:\n");
ali@445
  1949
				printf("  --help              "
ali@445
  1950
				       "Show this help message and exit\n");
ali@445
  1951
				printf("  --help-commands     List commands\n");
ali@475
  1952
				printf("  --database=URI      "
ali@445
  1953
				       "Use alternative database\n");
ali@475
  1954
				printf("  --root=URI          "
ali@475
  1955
				       "Use URI as top level directory\n");
ali@475
  1956
				printf("  --url=URI           "
ali@475
  1957
				       "Use URI as upstream repository\n");
ali@445
  1958
				return opt != opt_help;
ali@445
  1959
			case opt_root:
ali@445
  1960
				install_root = optarg;
ali@445
  1961
				break;
ali@445
  1962
			case opt_url:
ali@445
  1963
				yum_url = optarg;
ali@445
  1964
				break;
ali@445
  1965
			case 0:
ali@445
  1966
				break;
ali@445
  1967
		}
ali@445
  1968
	}
ali@445
  1969
ali@445
  1970
	main_optind = optind;
ali@445
  1971
	optind = 1;
ali@445
  1972
ali@445
  1973
	if (do_help_commands || argc - main_optind < 1) {
ali@445
  1974
		command_help(argc - main_optind, argv + main_optind);
ali@445
  1975
		return 1;
ali@445
  1976
	}
rhughes@241
  1977
rhughes@241
  1978
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
ali@445
  1979
		if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
ali@445
  1980
			return razor_commands[i].func(argc - main_optind,
ali@445
  1981
						      argv + main_optind);
rhughes@241
  1982
ali@445
  1983
	command_help(argc - main_optind, argv + main_optind);
ali@445
  1984
	return 1;
rhughes@241
  1985
}