main.c
author Kristian H?gsberg <krh@jiraiya.boston.redhat.com>
Wed Apr 09 02:41:03 2008 -0400 (2008-04-09)
changeset 211 cf0ca962262b
parent 210 c78f677d96b8
child 212 e8f493d8ff9a
permissions -rw-r--r--
Use the cpio headers instead of the rpm headers when unpacking.

The files in the cpio payload doesn't actually follow the file order
in the rpm headers, so we need to decode the cpio header and use the
information there.
krh@43
     1
#include <stdlib.h>
krh@43
     2
#include <stddef.h>
krh@43
     3
#include <stdio.h>
krh@186
     4
#include <stdint.h>
krh@43
     5
#include <string.h>
krh@72
     6
#include <sys/stat.h>
krh@43
     7
#include <unistd.h>
krh@197
     8
#include <fcntl.h>
krh@75
     9
#include <dirent.h>
krh@71
    10
#include <curl/curl.h>
krh@94
    11
#include <fnmatch.h>
krh@206
    12
#include <errno.h>
krh@43
    13
#include "razor.h"
krh@151
    14
#include "razor-internal.h"
krh@43
    15
krh@152
    16
static const char system_repo_filename[] = "system.repo";
krh@171
    17
static const char next_repo_filename[] = "system-next.repo";
krh@152
    18
static const char rawhide_repo_filename[] = "rawhide.repo";
krh@152
    19
static const char updated_repo_filename[] = "system-updated.repo";
krh@152
    20
static const char razor_root_path[] = "/var/lib/razor";
krh@152
    21
static const char root[] = "install";
krh@152
    22
static const char *repo_filename = system_repo_filename;
krh@43
    23
krh@43
    24
static int
krh@43
    25
command_list(int argc, const char *argv[])
krh@43
    26
{
krh@43
    27
	struct razor_set *set;
krh@92
    28
	struct razor_package_iterator *pi;
krh@92
    29
	struct razor_package *package;
krh@192
    30
	const char *pattern, *name, *version, *arch;
krh@187
    31
	int only_names = 0, i = 0;
krh@43
    32
krh@193
    33
	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
krh@187
    34
		only_names = 1;
krh@187
    35
		i++;
krh@187
    36
	}
krh@187
    37
krh@187
    38
	pattern = argv[i];
krh@43
    39
	set = razor_set_open(repo_filename);
krh@92
    40
	pi = razor_package_iterator_create(set);
krh@192
    41
	while (razor_package_iterator_next(pi, &package,
krh@192
    42
					   &name, &version, &arch)) {
krh@92
    43
		if (pattern && fnmatch(pattern, name, 0) != 0)
krh@92
    44
			continue;
krh@92
    45
krh@187
    46
		if (only_names)
krh@187
    47
			printf("%s\n", name);
krh@187
    48
		else
krh@192
    49
			printf("%s-%s.%s\n", name, version, arch);
krh@92
    50
	}
krh@92
    51
	razor_package_iterator_destroy(pi);
krh@92
    52
	razor_set_destroy(set);
krh@92
    53
krh@92
    54
	return 0;
krh@92
    55
}
krh@92
    56
krh@92
    57
static int
krh@92
    58
list_properties(const char *package_name,
krh@92
    59
		enum razor_property_type required_type)
krh@92
    60
{
krh@92
    61
	struct razor_set *set;
krh@92
    62
	struct razor_property *property;
krh@92
    63
	struct razor_package *package;
krh@92
    64
	struct razor_property_iterator *pi;
krh@92
    65
	const char *name, *version;
krh@92
    66
	enum razor_property_type type;
danw@109
    67
	enum razor_version_relation relation;
krh@92
    68
krh@92
    69
	set = razor_set_open(repo_filename);
krh@92
    70
	if (package_name)
krh@92
    71
		package = razor_set_get_package(set, package_name);
krh@92
    72
	else
krh@92
    73
		package = NULL;
krh@92
    74
krh@92
    75
	pi = razor_property_iterator_create(set, package);
krh@92
    76
	while (razor_property_iterator_next(pi, &property,
danw@109
    77
					    &name, &relation, &version,
danw@109
    78
					    &type)) {
krh@92
    79
		if (type != required_type)
krh@92
    80
			continue;
krh@92
    81
		if (version[0] == '\0')
krh@92
    82
			printf("%s\n", name);
krh@92
    83
		else
danw@137
    84
			printf("%s %s %s\n", name,
danw@137
    85
			       razor_version_relations[relation], version);
krh@92
    86
	}
krh@92
    87
	razor_property_iterator_destroy(pi);
krh@92
    88
krh@43
    89
	razor_set_destroy(set);
krh@43
    90
krh@43
    91
	return 0;
krh@43
    92
}
krh@43
    93
krh@43
    94
static int
krh@43
    95
command_list_requires(int argc, const char *argv[])
krh@43
    96
{
krh@92
    97
	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
krh@43
    98
}
krh@43
    99
krh@43
   100
static int
krh@43
   101
command_list_provides(int argc, const char *argv[])
krh@43
   102
{
krh@92
   103
	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
krh@43
   104
}
krh@43
   105
krh@43
   106
static int
krh@67
   107
command_list_obsoletes(int argc, const char *argv[])
krh@67
   108
{
krh@92
   109
	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
krh@67
   110
}
krh@67
   111
krh@67
   112
static int
krh@67
   113
command_list_conflicts(int argc, const char *argv[])
krh@67
   114
{
krh@92
   115
	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
krh@67
   116
}
krh@67
   117
krh@67
   118
static int
krh@48
   119
command_list_files(int argc, const char *argv[])
krh@48
   120
{
krh@48
   121
	struct razor_set *set;
krh@48
   122
krh@48
   123
	set = razor_set_open(repo_filename);
krh@48
   124
	if (set == NULL)
krh@48
   125
		return 1;
krh@49
   126
	razor_set_list_files(set, argv[0]);
krh@48
   127
	razor_set_destroy(set);
krh@48
   128
krh@48
   129
	return 0;
krh@48
   130
}
krh@48
   131
krh@48
   132
static int
krh@52
   133
command_list_file_packages(int argc, const char *argv[])
krh@52
   134
{
krh@52
   135
	struct razor_set *set;
krh@102
   136
	struct razor_package_iterator *pi;
krh@102
   137
	struct razor_package *package;
krh@192
   138
	const char *name, *version, *arch;
krh@52
   139
krh@52
   140
	set = razor_set_open(repo_filename);
krh@52
   141
	if (set == NULL)
krh@52
   142
		return 1;
krh@102
   143
krh@102
   144
	pi = razor_package_iterator_create_for_file(set, argv[0]);
krh@192
   145
	while (razor_package_iterator_next(pi, &package,
krh@192
   146
					   &name, &version, &arch))
krh@102
   147
		printf("%s-%s\n", name, version);
krh@102
   148
	razor_package_iterator_destroy(pi);
krh@102
   149
krh@52
   150
	razor_set_destroy(set);
krh@52
   151
krh@52
   152
	return 0;
krh@52
   153
}
krh@52
   154
krh@56
   155
static int
krh@56
   156
command_list_package_files(int argc, const char *argv[])
krh@56
   157
{
krh@56
   158
	struct razor_set *set;
krh@56
   159
krh@56
   160
	set = razor_set_open(repo_filename);
krh@56
   161
	if (set == NULL)
krh@56
   162
		return 1;
krh@56
   163
	razor_set_list_package_files(set, argv[0]);
krh@56
   164
	razor_set_destroy(set);
krh@56
   165
krh@56
   166
	return 0;
krh@56
   167
}
krh@52
   168
krh@101
   169
static void
krh@101
   170
list_packages_for_property(struct razor_set *set,
krh@101
   171
			   struct razor_property *property)
krh@101
   172
{
krh@101
   173
	struct razor_package_iterator *pi;
krh@101
   174
	struct razor_package *package;
krh@192
   175
	const char *name, *version, *arch;
krh@101
   176
krh@101
   177
	pi = razor_package_iterator_create_for_property(set, property);
krh@192
   178
	while (razor_package_iterator_next(pi, &package,
krh@192
   179
					   &name, &version, &arch))
krh@192
   180
		printf("%s-%s.%s\n", name, version, arch);
krh@101
   181
	razor_package_iterator_destroy(pi);
krh@101
   182
}
krh@101
   183
krh@52
   184
static int
krh@100
   185
list_property_packages(const char *ref_name,
krh@100
   186
		       const char *ref_version,
krh@100
   187
		       enum razor_property_type ref_type)
krh@43
   188
{
krh@43
   189
	struct razor_set *set;
krh@100
   190
	struct razor_property *property;
krh@100
   191
	struct razor_property_iterator *pi;
krh@100
   192
	const char *name, *version;
krh@100
   193
	enum razor_property_type type;
danw@109
   194
	enum razor_version_relation relation;
krh@100
   195
krh@100
   196
	if (ref_name == NULL)
krh@100
   197
		return 0;
krh@43
   198
krh@43
   199
	set = razor_set_open(repo_filename);
krh@100
   200
	if (set == NULL)
krh@100
   201
		return 1;
krh@100
   202
krh@100
   203
	pi = razor_property_iterator_create(set, NULL);
krh@100
   204
	while (razor_property_iterator_next(pi, &property,
danw@109
   205
					    &name, &relation, &version,
danw@109
   206
					    &type)) {
krh@100
   207
		if (strcmp(ref_name, name) != 0)
krh@100
   208
			continue;
danw@109
   209
		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
danw@109
   210
		    strcmp(ref_version, version) != 0)
krh@100
   211
			continue;
krh@100
   212
		if (ref_type != type)
krh@100
   213
			continue;
krh@100
   214
krh@101
   215
		list_packages_for_property(set, property);
krh@100
   216
	}
krh@100
   217
	razor_property_iterator_destroy(pi);
krh@43
   218
krh@43
   219
	return 0;
krh@43
   220
}
krh@43
   221
krh@43
   222
static int
krh@100
   223
command_what_requires(int argc, const char *argv[])
krh@100
   224
{
krh@100
   225
	return list_property_packages(argv[0], argv[1],
krh@100
   226
				      RAZOR_PROPERTY_REQUIRES);
krh@100
   227
}
krh@100
   228
krh@100
   229
static int
krh@43
   230
command_what_provides(int argc, const char *argv[])
krh@43
   231
{
krh@100
   232
	return list_property_packages(argv[0], argv[1],
krh@100
   233
				      RAZOR_PROPERTY_PROVIDES);
krh@43
   234
}
krh@43
   235
krh@73
   236
static int
krh@73
   237
show_progress(void *clientp,
krh@73
   238
	      double dltotal, double dlnow, double ultotal, double ulnow)
krh@73
   239
{
krh@73
   240
	const char *file = clientp;
krh@73
   241
krh@73
   242
	if (!dlnow < dltotal)
krh@73
   243
		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
krh@73
   244
			file, (int) dlnow / 1024, (int) dltotal / 1024);
krh@73
   245
krh@73
   246
	return 0;
krh@73
   247
}
krh@73
   248
krh@73
   249
static int
krh@194
   250
download_if_missing(const char *url, const char *file)
krh@73
   251
{
krh@194
   252
	CURL *curl;
krh@73
   253
	struct stat buf;
krh@73
   254
	char error[256];
krh@73
   255
	FILE *fp;
krh@73
   256
	CURLcode res;
krh@204
   257
	long response;
krh@73
   258
krh@194
   259
	curl = curl_easy_init();
krh@194
   260
	if (curl == NULL)
krh@194
   261
		return 1;
krh@194
   262
krh@73
   263
	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
krh@73
   264
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
krh@73
   265
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
krh@73
   266
	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
krh@73
   267
krh@73
   268
	if (stat(file, &buf) < 0) {
krh@73
   269
		fp = fopen(file, "w");
krh@207
   270
		if (fp == NULL) {
krh@207
   271
			fprintf(stderr,
krh@207
   272
				"failed to open %s for writing\n", file);
krh@207
   273
			return -1;
krh@207
   274
		}
krh@73
   275
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
krh@187
   276
		curl_easy_setopt(curl, CURLOPT_URL, url);
krh@73
   277
		res = curl_easy_perform(curl);
krh@73
   278
		fclose(fp);
krh@73
   279
		if (res != CURLE_OK) {
krh@73
   280
			fprintf(stderr, "curl error: %s\n", error);
krh@73
   281
			unlink(file);
krh@73
   282
			return -1;
krh@73
   283
		}
krh@204
   284
		res = curl_easy_getinfo(curl,
krh@204
   285
					CURLINFO_RESPONSE_CODE, &response);
krh@204
   286
		if (res != CURLE_OK) {
krh@204
   287
			fprintf(stderr, "curl error: %s\n", error);
krh@204
   288
                        unlink(file);
krh@204
   289
                        return -1;
krh@204
   290
		}
krh@204
   291
		if (response != 200) {
krh@204
   292
			fprintf(stderr, " - failed %ld\n", response);
krh@204
   293
                        unlink(file);
krh@204
   294
                        return -1;
krh@204
   295
		}
krh@188
   296
		fprintf(stderr, "\n");
krh@73
   297
	}
krh@73
   298
krh@194
   299
	curl_easy_cleanup(curl);
krh@194
   300
krh@73
   301
	return 0;
krh@73
   302
}
krh@73
   303
krh@71
   304
#define REPO_URL "http://download.fedora.redhat.com" \
krh@187
   305
	"/pub/fedora/linux/development/i386/os"
krh@71
   306
krh@43
   307
static int
krh@43
   308
command_import_yum(int argc, const char *argv[])
krh@43
   309
{
krh@43
   310
	struct razor_set *set;
krh@71
   311
krh@194
   312
	if (download_if_missing(REPO_URL "/repodata/primary.xml.gz",
krh@187
   313
				"primary.xml.gz") < 0)
krh@73
   314
		return -1;
krh@194
   315
	if (download_if_missing(REPO_URL "/repodata/filelists.xml.gz",
krh@187
   316
				"filelists.xml.gz") < 0)
krh@73
   317
		return -1;
krh@43
   318
krh@70
   319
	set = razor_set_create_from_yum();
krh@43
   320
	if (set == NULL)
krh@43
   321
		return 1;
krh@43
   322
	razor_set_write(set, rawhide_repo_filename);
krh@43
   323
	razor_set_destroy(set);
krh@43
   324
	printf("wrote %s\n", rawhide_repo_filename);
krh@43
   325
krh@43
   326
	return 0;
krh@43
   327
}
krh@43
   328
krh@43
   329
static int
krh@43
   330
command_import_rpmdb(int argc, const char *argv[])
krh@43
   331
{
krh@43
   332
	struct razor_set *set;
krh@43
   333
krh@43
   334
	set = razor_set_create_from_rpmdb();
krh@43
   335
	if (set == NULL)
krh@43
   336
		return 1;
krh@43
   337
	razor_set_write(set, repo_filename);
krh@43
   338
	razor_set_destroy(set);
krh@43
   339
	printf("wrote %s\n", repo_filename);
krh@43
   340
krh@43
   341
	return 0;
krh@43
   342
}
krh@43
   343
krh@43
   344
static int
krh@43
   345
command_validate(int argc, const char *argv[])
krh@43
   346
{
krh@43
   347
	struct razor_set *set;
krh@43
   348
krh@43
   349
	set = razor_set_open(repo_filename);
krh@43
   350
	if (set == NULL)
krh@43
   351
		return 1;
krh@43
   352
	razor_set_list_unsatisfied(set);
krh@43
   353
	razor_set_destroy(set);
krh@43
   354
krh@43
   355
	return 0;
krh@43
   356
}
krh@43
   357
krh@43
   358
static int
krh@208
   359
mark_packages_for_update(struct razor_transaction *trans,
krh@208
   360
			 struct razor_set *set, const char *pattern)
krh@208
   361
{
krh@208
   362
	struct razor_package_iterator *pi;
krh@208
   363
	struct razor_package *package;
krh@208
   364
	const char *name, *version, *arch;
krh@208
   365
	int matches = 0;
krh@208
   366
krh@208
   367
	pi = razor_package_iterator_create(set);
krh@208
   368
	while (razor_package_iterator_next(pi, &package,
krh@208
   369
					   &name, &version, &arch)) {
krh@208
   370
		if (pattern && fnmatch(pattern, name, 0) == 0) {
krh@208
   371
			razor_transaction_install_package(trans, package);
krh@208
   372
			matches++;
krh@208
   373
		}
krh@208
   374
	}
krh@208
   375
	razor_package_iterator_destroy(pi);
krh@208
   376
krh@208
   377
	return matches;
krh@208
   378
}
krh@208
   379
krh@208
   380
static int
krh@208
   381
mark_packages_for_removal(struct razor_transaction *trans,
krh@208
   382
			  struct razor_set *set, const char *pattern)
krh@208
   383
{
krh@208
   384
	struct razor_package_iterator *pi;
krh@208
   385
	struct razor_package *package;
krh@208
   386
	const char *name, *version, *arch;
krh@208
   387
	int matches = 0;
krh@208
   388
krh@208
   389
	pi = razor_package_iterator_create(set);
krh@208
   390
	while (razor_package_iterator_next(pi, &package,
krh@208
   391
					   &name, &version, &arch)) {
krh@208
   392
		if (pattern && fnmatch(pattern, name, 0) == 0) {
krh@208
   393
			razor_transaction_remove_package(trans, package);
krh@208
   394
			matches++;
krh@208
   395
		}
krh@208
   396
	}
krh@208
   397
	razor_package_iterator_destroy(pi);
krh@208
   398
krh@208
   399
	return matches;
krh@208
   400
}
krh@208
   401
krh@208
   402
static int
krh@43
   403
command_update(int argc, const char *argv[])
krh@43
   404
{
krh@43
   405
	struct razor_set *set, *upstream;
danw@137
   406
	struct razor_transaction *trans;
krh@208
   407
	int i, errors;
krh@43
   408
krh@43
   409
	set = razor_set_open(repo_filename);
krh@43
   410
	upstream = razor_set_open(rawhide_repo_filename);
krh@43
   411
	if (set == NULL || upstream == NULL)
krh@43
   412
		return 1;
krh@208
   413
krh@208
   414
	trans = razor_transaction_create(set, upstream);
krh@208
   415
	if (argc == 0)
krh@208
   416
		razor_transaction_update_all(trans);
krh@208
   417
	for (i = 0; i < argc; i++) {
krh@208
   418
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
krh@208
   419
			fprintf(stderr, "no match for %s\n", argv[i]);
krh@208
   420
			return 1;
krh@208
   421
		}
krh@208
   422
	}
krh@208
   423
		
krh@210
   424
	errors = razor_transaction_resolve(trans);
krh@190
   425
	if (errors)
danw@137
   426
		return 1;
danw@137
   427
krh@196
   428
	set = razor_transaction_finish(trans);
krh@44
   429
	razor_set_write(set, updated_repo_filename);
krh@43
   430
	razor_set_destroy(set);
krh@43
   431
	razor_set_destroy(upstream);
krh@43
   432
	printf("wrote system-updated.repo\n");
krh@43
   433
krh@43
   434
	return 0;
krh@43
   435
}
krh@43
   436
danw@129
   437
static int
danw@129
   438
command_remove(int argc, const char *argv[])
danw@129
   439
{
danw@129
   440
	struct razor_set *set;
danw@137
   441
	struct razor_transaction *trans;
krh@208
   442
	int i, errors;
danw@129
   443
danw@129
   444
	set = razor_set_open(repo_filename);
danw@129
   445
	if (set == NULL)
danw@129
   446
		return 1;
krh@208
   447
krh@208
   448
	trans = razor_transaction_create(set, NULL);
krh@208
   449
	for (i = 0; i < argc; i++) {
krh@208
   450
		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
krh@208
   451
			fprintf(stderr, "no match for %s\n", argv[i]);
krh@208
   452
			return 1;
krh@208
   453
		}
krh@208
   454
	}
krh@208
   455
krh@210
   456
	errors = razor_transaction_resolve(trans);
krh@190
   457
	if (errors)
danw@137
   458
		return 1;
danw@137
   459
krh@196
   460
	set = razor_transaction_finish(trans);
danw@129
   461
	razor_set_write(set, updated_repo_filename);
danw@129
   462
	razor_set_destroy(set);
danw@129
   463
	printf("wrote system-updated.repo\n");
danw@129
   464
danw@129
   465
	return 0;
danw@129
   466
}
danw@129
   467
krh@44
   468
static void
krh@44
   469
print_diff(const char *name,
krh@192
   470
	   const char *old_version, const char *new_version, const char *arch,
krh@192
   471
	   void *data)
krh@44
   472
{
krh@44
   473
	if (old_version)
krh@44
   474
		printf("removing %s %s\n", name, old_version);
krh@44
   475
	else
krh@44
   476
		printf("install %s %s\n", name, new_version);
krh@44
   477
}
krh@44
   478
krh@44
   479
static int
krh@44
   480
command_diff(int argc, const char *argv[])
krh@44
   481
{
krh@44
   482
	struct razor_set *set, *updated;
krh@44
   483
krh@44
   484
	set = razor_set_open(repo_filename);
krh@44
   485
	updated = razor_set_open(updated_repo_filename);
krh@44
   486
	if (set == NULL || updated == NULL)
krh@44
   487
		return 1;
krh@44
   488
krh@44
   489
	razor_set_diff(set, updated, print_diff, NULL);	
krh@44
   490
krh@44
   491
	razor_set_destroy(set);
krh@44
   492
	razor_set_destroy(updated);
krh@44
   493
krh@44
   494
	return 0;
krh@44
   495
}
krh@44
   496
krh@74
   497
static int
krh@75
   498
command_import_rpms(int argc, const char *argv[])
krh@74
   499
{
krh@75
   500
	DIR *dir;
krh@75
   501
	struct dirent *de;
krh@75
   502
	struct razor_importer *importer;
krh@75
   503
	struct razor_set *set;
krh@77
   504
	struct razor_rpm *rpm;
krh@75
   505
	int len;
krh@75
   506
	char filename[256];
krh@75
   507
	const char *dirname = argv[0];
krh@75
   508
krh@75
   509
	if (dirname == NULL) {
krh@75
   510
		fprintf(stderr, "usage: razor import-rpms DIR\n");
krh@75
   511
		return -1;
krh@75
   512
	}
krh@75
   513
krh@75
   514
	dir = opendir(dirname);
krh@75
   515
	if (dir == NULL) {
krh@75
   516
		fprintf(stderr, "couldn't read dir %s\n", dirname);
krh@75
   517
		return -1;
krh@75
   518
	}
krh@75
   519
krh@75
   520
	importer = razor_importer_new();
krh@75
   521
krh@75
   522
	while (de = readdir(dir), de != NULL) {
krh@75
   523
		len = strlen(de->d_name);
krh@75
   524
		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
krh@75
   525
		    continue;
krh@75
   526
		snprintf(filename, sizeof filename,
krh@75
   527
			 "%s/%s", dirname, de->d_name);
krh@77
   528
		rpm = razor_rpm_open(filename);
krh@77
   529
		if (rpm == NULL) {
krh@77
   530
			fprintf(stderr,
krh@77
   531
				"failed to open rpm \"%s\"\n", filename);
krh@77
   532
			continue;
krh@77
   533
		}
krh@77
   534
		if (razor_importer_add_rpm(importer, rpm)) {
krh@75
   535
			fprintf(stderr, "couldn't import %s\n", filename);
krh@75
   536
			break;
krh@75
   537
		}
krh@77
   538
		razor_rpm_close(rpm);
krh@75
   539
	}
krh@75
   540
krh@75
   541
	if (de != NULL) {
krh@75
   542
		razor_importer_destroy(importer);
krh@75
   543
		return -1;
krh@75
   544
	}
krh@75
   545
krh@75
   546
	set = razor_importer_finish(importer);
krh@75
   547
krh@75
   548
	razor_set_write(set, repo_filename);
krh@75
   549
	razor_set_destroy(set);
krh@75
   550
	printf("wrote %s\n", repo_filename);
krh@74
   551
krh@74
   552
	return 0;
krh@74
   553
}
krh@74
   554
krh@194
   555
static void
krh@194
   556
download_package(const char *name,
krh@194
   557
		 const char *old_version,
krh@194
   558
		 const char *new_version,
krh@194
   559
		 const char *arch,
krh@194
   560
		 void *data)
krh@152
   561
{
krh@194
   562
	char file[PATH_MAX], url[256];
krh@201
   563
	const char *v;
krh@204
   564
	int *errors = data;
krh@194
   565
krh@194
   566
	if (old_version)
krh@194
   567
		return;
krh@194
   568
krh@201
   569
	/* Skip epoch */
krh@201
   570
	v = strchr(new_version, ':');
krh@201
   571
	if (v != NULL)
krh@201
   572
		v = v + 1;
krh@201
   573
	else
krh@201
   574
		v = new_version;
krh@201
   575
krh@194
   576
	snprintf(url, sizeof url,
krh@201
   577
		 REPO_URL "/Packages/%s-%s.%s.rpm", name, v, arch);
krh@194
   578
	snprintf(file, sizeof file,
krh@201
   579
		 "rpms/%s-%s.%s.rpm", name, v, arch);
krh@194
   580
	if (download_if_missing(url, file) < 0)
krh@204
   581
		(*errors)++;
krh@194
   582
}
krh@194
   583
krh@194
   584
static void
krh@194
   585
install_package(const char *name,
krh@194
   586
		const char *old_version,
krh@194
   587
		const char *new_version,
krh@194
   588
		const char *arch,
krh@194
   589
		void *data)
krh@194
   590
{
krh@201
   591
	const char *v, *root = data;
krh@194
   592
	char file[PATH_MAX];
krh@152
   593
	struct razor_rpm *rpm;
krh@152
   594
krh@194
   595
	if (old_version) {
krh@194
   596
		printf("removing %s %s not handled\n", name, old_version);
krh@194
   597
		return;
krh@152
   598
	}
krh@152
   599
krh@201
   600
	/* Skip epoch */
krh@201
   601
	v = strchr(new_version, ':');
krh@201
   602
	if (v != NULL)
krh@201
   603
		v = v + 1;
krh@201
   604
	else
krh@201
   605
		v = new_version;
krh@201
   606
krh@201
   607
	printf("install %s %s\n", name, v);
krh@201
   608
	snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
krh@152
   609
krh@194
   610
 	rpm = razor_rpm_open(file);
krh@194
   611
	if (rpm == NULL) {
krh@194
   612
		fprintf(stderr, "failed to open rpm %s\n", file);
krh@194
   613
		return;
krh@194
   614
	}
krh@194
   615
	if (razor_rpm_install(rpm, root) < 0) {
krh@194
   616
		fprintf(stderr,
krh@194
   617
			"failed to install rpm %s\n", file);
krh@194
   618
		return;
krh@194
   619
	}
krh@194
   620
	razor_rpm_close(rpm);
krh@152
   621
}
krh@151
   622
krh@77
   623
static int
krh@77
   624
command_install(int argc, const char *argv[])
krh@77
   625
{
krh@171
   626
	struct razor_set *system, *upstream, *next;
krh@152
   627
	struct razor_transaction *trans;
krh@194
   628
	char path[PATH_MAX], new_path[PATH_MAX];
krh@210
   629
	int i = 0, errors, fd, dependencies = 1;
krh@210
   630
krh@210
   631
	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
krh@210
   632
		dependencies = 0;
krh@210
   633
		i++;
krh@210
   634
	}
krh@197
   635
krh@197
   636
	/* Create the new next repo file up front to ensure exclusive
krh@197
   637
	 * access. */
krh@197
   638
	snprintf(new_path, sizeof new_path,
krh@197
   639
		 "%s%s/%s", root, razor_root_path, next_repo_filename);
krh@197
   640
	fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
krh@197
   641
	if (fd < 0) {
krh@197
   642
		fprintf(stderr, "failed to get lock file, "
krh@197
   643
			"maybe previous operation crashed?\n");
krh@197
   644
krh@197
   645
		/* FIXME: Use fcntl advisory locking to figure out
krh@197
   646
		 * whether previous operation crashed or is still in
krh@197
   647
		 * progress. */
krh@197
   648
krh@197
   649
		return -1;
krh@197
   650
	}
krh@151
   651
krh@194
   652
	upstream = razor_set_open(rawhide_repo_filename);
krh@152
   653
	snprintf(path, sizeof path,
krh@152
   654
		 "%s%s/%s", root, razor_root_path, system_repo_filename);
krh@152
   655
	system = razor_set_open(path);
krh@197
   656
	if (system == NULL || upstream == NULL) {
krh@197
   657
		unlink(new_path);
krh@194
   658
		return 1;
krh@197
   659
	}
krh@208
   660
	trans = razor_transaction_create(system, upstream);
krh@210
   661
	for (; i < argc; i++) {
krh@208
   662
		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
krh@208
   663
			fprintf(stderr, "no package matched %s\n", argv[i]);
krh@208
   664
			unlink(new_path);
krh@208
   665
			return 1;
krh@208
   666
		}
krh@208
   667
	}
krh@208
   668
krh@210
   669
	if (dependencies) {
krh@210
   670
		errors = razor_transaction_resolve(trans);
krh@210
   671
		if (errors) {
krh@210
   672
			unlink(new_path);
krh@210
   673
			return 1;
krh@210
   674
		}
krh@197
   675
	}
krh@152
   676
krh@196
   677
	next = razor_transaction_finish(trans);
krh@152
   678
krh@197
   679
	razor_set_write_to_fd(next, fd);
krh@194
   680
	printf("wrote %s\n", new_path);
krh@194
   681
krh@206
   682
	if (mkdir("rpms", 0777) && errno != EEXIST) {
krh@206
   683
		fprintf(stderr, "failed to create rpms directory.\n");
krh@206
   684
		return 1;
krh@206
   685
	}
krh@206
   686
krh@204
   687
	razor_set_diff(system, next, download_package, &errors);
krh@204
   688
	if (errors > 0) {
krh@204
   689
		fprintf(stderr, "failed to download %d packages\n", errors);
krh@204
   690
		unlink(new_path);
krh@204
   691
                return 1;
krh@204
   692
        }
krh@194
   693
krh@200
   694
	/* FIXME: We need to figure out the right install order here,
krh@200
   695
	 * so the post and pre scripts can run. */
krh@194
   696
	razor_set_diff(system, next, install_package, (void *) root);
krh@171
   697
krh@171
   698
	razor_set_destroy(next);
krh@171
   699
	razor_set_destroy(system);
krh@171
   700
	razor_set_destroy(upstream);
krh@171
   701
krh@171
   702
	/* Make it so. */
krh@171
   703
	rename(new_path, path);
krh@171
   704
	printf("renamed %s to %s\n", new_path, path);
krh@171
   705
krh@151
   706
	return 0;
krh@151
   707
}
krh@151
   708
krh@151
   709
static int
krh@151
   710
command_init(int argc, const char *argv[])
krh@151
   711
{
krh@77
   712
	struct stat buf;
krh@151
   713
	struct razor_set *set;
krh@151
   714
	char path[PATH_MAX];
krh@77
   715
krh@77
   716
	if (stat(root, &buf) < 0) {
krh@77
   717
		if (mkdir(root, 0777) < 0) {
krh@77
   718
			fprintf(stderr,
krh@77
   719
				"could not create install root \"%s\"\n",
krh@77
   720
				root);
krh@77
   721
			return -1;
krh@77
   722
		}
krh@77
   723
		fprintf(stderr, "created install root \"%s\"\n", root);
krh@77
   724
	} else if (!S_ISDIR(buf.st_mode)) {
krh@77
   725
		fprintf(stderr,
krh@77
   726
			"install root \"%s\" exists, but is not a directory\n",
krh@77
   727
			root);
krh@77
   728
		return -1;
krh@77
   729
	}
krh@77
   730
krh@211
   731
	snprintf(path, sizeof path, "%s/%s",
krh@211
   732
		 razor_root_path, system_repo_filename);
krh@211
   733
	if (razor_create_dir(root, path) < 0) {
krh@151
   734
		fprintf(stderr, "could not create %s%s\n",
krh@151
   735
			root, razor_root_path);
krh@77
   736
		return -1;
krh@77
   737
	}
krh@151
   738
krh@151
   739
	set = razor_set_create();
krh@151
   740
	snprintf(path, sizeof path, "%s%s/%s",
krh@152
   741
		 root, razor_root_path, system_repo_filename);
krh@151
   742
	if (razor_set_write(set, path) < 0) {
krh@151
   743
		fprintf(stderr, "could not write initial package set\n");
krh@77
   744
		return -1;
krh@77
   745
	}
krh@151
   746
	razor_set_destroy(set);
krh@77
   747
krh@77
   748
	return 0;
krh@77
   749
}
krh@77
   750
krh@187
   751
static int
krh@187
   752
command_download(int argc, const char *argv[])
krh@187
   753
{
krh@187
   754
	struct razor_set *set;
krh@187
   755
	struct razor_package_iterator *pi;
krh@187
   756
	struct razor_package *package;
krh@192
   757
	const char *pattern = argv[0], *name, *version, *arch;
krh@187
   758
	char url[256], file[256];
krh@203
   759
	int matches = 0;
krh@187
   760
krh@206
   761
	if (mkdir("rpms", 0777) && errno != EEXIST) {
krh@206
   762
		fprintf(stderr, "failed to create rpms directory.\n");
krh@206
   763
		return 1;
krh@206
   764
	}
krh@206
   765
krh@187
   766
	set = razor_set_open(rawhide_repo_filename);
krh@187
   767
	pi = razor_package_iterator_create(set);
krh@192
   768
	while (razor_package_iterator_next(pi, &package,
krh@192
   769
					   &name, &version, &arch)) {
krh@187
   770
		if (pattern && fnmatch(pattern, name, 0) != 0)
krh@187
   771
			continue;
krh@187
   772
krh@203
   773
		matches++;
krh@187
   774
		snprintf(url, sizeof url,
krh@203
   775
			 REPO_URL "/Packages/%s-%s.%s.rpm",
krh@203
   776
			 name, version, arch);
krh@187
   777
		snprintf(file, sizeof file,
krh@203
   778
			 "rpms/%s-%s.%s.rpm", name, version, arch);
krh@204
   779
		download_if_missing(url, file);
krh@187
   780
	}
krh@187
   781
	razor_package_iterator_destroy(pi);
krh@187
   782
	razor_set_destroy(set);
krh@187
   783
krh@203
   784
	if (matches == 0)
krh@203
   785
		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
krh@203
   786
	else if (matches == 1)
krh@203
   787
		fprintf(stderr, "downloaded 1 package\n");
krh@203
   788
	else
krh@205
   789
		fprintf(stderr, "downloaded %d packages\n", matches);
krh@203
   790
krh@187
   791
	return 0;
krh@187
   792
}
krh@187
   793
krh@43
   794
static struct {
krh@43
   795
	const char *name;
krh@43
   796
	const char *description;
krh@43
   797
	int (*func)(int argc, const char *argv[]);
krh@43
   798
} razor_commands[] = {
krh@43
   799
	{ "list", "list all packages", command_list },
krh@67
   800
	{ "list-requires", "list all requires for the given package", command_list_requires },
krh@75
   801
	{ "list-provides", "list all provides for the given package", command_list_provides },
krh@75
   802
	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
krh@75
   803
	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
krh@48
   804
	{ "list-files", "list files for package set", command_list_files },
krh@52
   805
	{ "list-file-packages", "list packages owning file", command_list_file_packages },
krh@56
   806
	{ "list-package-files", "list files in package", command_list_package_files },
krh@43
   807
	{ "what-requires", "list the packages that have the given requires", command_what_requires },
krh@43
   808
	{ "what-provides", "list the packages that have the given provides", command_what_provides },
krh@75
   809
	{ "import-yum", "import yum metadata files", command_import_yum },
krh@43
   810
	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
krh@75
   811
	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
krh@43
   812
	{ "validate", "validate a package set", command_validate },
krh@44
   813
	{ "update", "update all or specified packages", command_update },
danw@129
   814
	{ "remove", "remove specified packages", command_remove },
krh@77
   815
	{ "diff", "show diff between two package sets", command_diff },
krh@151
   816
	{ "install", "install rpm", command_install },
krh@187
   817
	{ "init", "init razor root", command_init },
krh@187
   818
	{ "download", "download packages", command_download }
krh@43
   819
};
krh@43
   820
krh@43
   821
static int
krh@43
   822
usage(void)
krh@43
   823
{
krh@43
   824
	int i;
krh@43
   825
krh@43
   826
	printf("usage:\n");
krh@43
   827
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
krh@43
   828
		printf("  %-20s%s\n",
krh@43
   829
		       razor_commands[i].name, razor_commands[i].description);
krh@43
   830
krh@43
   831
	return 1;
krh@43
   832
}
krh@43
   833
krh@43
   834
int
krh@43
   835
main(int argc, const char *argv[])
krh@43
   836
{
krh@43
   837
	char *repo;
krh@43
   838
	int i;
krh@43
   839
krh@43
   840
	repo = getenv("RAZOR_REPO");
krh@43
   841
	if (repo != NULL)
krh@43
   842
		repo_filename = repo;
krh@43
   843
krh@43
   844
	if (argc < 2)
krh@43
   845
		return usage();
krh@43
   846
krh@43
   847
	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
krh@43
   848
		if (strcmp(razor_commands[i].name, argv[1]) == 0)
krh@43
   849
			return razor_commands[i].func(argc - 2, argv + 2);
krh@43
   850
krh@43
   851
	return usage();
krh@43
   852
}