main.c
author Kristian H?gsberg <krh@redhat.com>
Tue Jan 08 12:55:34 2008 -0500 (2008-01-08)
changeset 93 f173765f7623
parent 77 3d14834c56ea
child 94 0aa93cfbcb3f
permissions -rw-r--r--
Add missing test.xml.
     1 #include <stdlib.h>
     2 #include <stddef.h>
     3 #include <stdio.h>
     4 #include <string.h>
     5 #include <sys/types.h>
     6 #include <sys/stat.h>
     7 #include <unistd.h>
     8 #include <dirent.h>
     9 #include <curl/curl.h>
    10 #include "razor.h"
    11 
    12 static const char *repo_filename = "system.repo";
    13 static const char *rawhide_repo_filename = "rawhide.repo";
    14 static const char *updated_repo_filename = "system-updated.repo";
    15 
    16 static int
    17 command_list(int argc, const char *argv[])
    18 {
    19 	struct razor_set *set;
    20 	struct razor_package_iterator *pi;
    21 	struct razor_package *package;
    22 	const char *pattern = argv[0], *name, *version;
    23 
    24 	set = razor_set_open(repo_filename);
    25 	pi = razor_package_iterator_create(set);
    26 	while (razor_package_iterator_next(pi, &package, &name, &version)) {
    27 		if (pattern && fnmatch(pattern, name, 0) != 0)
    28 			continue;
    29 
    30 		printf("%s-%s\n", name, version);
    31 	}
    32 	razor_package_iterator_destroy(pi);
    33 	razor_set_destroy(set);
    34 
    35 	return 0;
    36 }
    37 
    38 static int
    39 list_properties(const char *package_name,
    40 		enum razor_property_type required_type)
    41 {
    42 	struct razor_set *set;
    43 	struct razor_property *property;
    44 	struct razor_package *package;
    45 	struct razor_property_iterator *pi;
    46 	const char *name, *version;
    47 	enum razor_property_type type;
    48 
    49 	set = razor_set_open(repo_filename);
    50 	if (package_name)
    51 		package = razor_set_get_package(set, package_name);
    52 	else
    53 		package = NULL;
    54 
    55 	pi = razor_property_iterator_create(set, package);
    56 	while (razor_property_iterator_next(pi, &property,
    57 					    &name, &version, &type)) {
    58 		if (type != required_type)
    59 			continue;
    60 		if (version[0] == '\0')
    61 			printf("%s\n", name);
    62 		else
    63 			printf("%s-%s\n", name, version);
    64 	}
    65 	razor_property_iterator_destroy(pi);
    66 
    67 	razor_set_destroy(set);
    68 
    69 	return 0;
    70 }
    71 
    72 static int
    73 command_list_requires(int argc, const char *argv[])
    74 {
    75 	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
    76 }
    77 
    78 static int
    79 command_list_provides(int argc, const char *argv[])
    80 {
    81 	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
    82 }
    83 
    84 static int
    85 command_list_obsoletes(int argc, const char *argv[])
    86 {
    87 	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
    88 }
    89 
    90 static int
    91 command_list_conflicts(int argc, const char *argv[])
    92 {
    93 	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
    94 }
    95 
    96 static int
    97 command_list_files(int argc, const char *argv[])
    98 {
    99 	struct razor_set *set;
   100 
   101 	set = razor_set_open(repo_filename);
   102 	if (set == NULL)
   103 		return 1;
   104 	razor_set_list_files(set, argv[0]);
   105 	razor_set_destroy(set);
   106 
   107 	return 0;
   108 }
   109 
   110 static int
   111 command_list_file_packages(int argc, const char *argv[])
   112 {
   113 	struct razor_set *set;
   114 
   115 	set = razor_set_open(repo_filename);
   116 	if (set == NULL)
   117 		return 1;
   118 	razor_set_list_file_packages(set, argv[0]);
   119 	razor_set_destroy(set);
   120 
   121 	return 0;
   122 }
   123 
   124 static int
   125 command_list_package_files(int argc, const char *argv[])
   126 {
   127 	struct razor_set *set;
   128 
   129 	set = razor_set_open(repo_filename);
   130 	if (set == NULL)
   131 		return 1;
   132 	razor_set_list_package_files(set, argv[0]);
   133 	razor_set_destroy(set);
   134 
   135 	return 0;
   136 }
   137 
   138 static int
   139 command_what_requires(int argc, const char *argv[])
   140 {
   141 	struct razor_set *set;
   142 
   143 	set = razor_set_open(repo_filename);
   144 	razor_set_list_property_packages(set, argv[0], argv[1],
   145 					 RAZOR_PROPERTY_REQUIRES);
   146 	razor_set_destroy(set);
   147 
   148 	return 0;
   149 }
   150 
   151 static int
   152 command_what_provides(int argc, const char *argv[])
   153 {
   154 	struct razor_set *set;
   155 
   156 	set = razor_set_open(repo_filename);
   157 	razor_set_list_property_packages(set, argv[0], argv[1],
   158 					 RAZOR_PROPERTY_PROVIDES);
   159 	razor_set_destroy(set);
   160 
   161 	return 0;
   162 }
   163 
   164 static int
   165 show_progress(void *clientp,
   166 	      double dltotal, double dlnow, double ultotal, double ulnow)
   167 {
   168 	const char *file = clientp;
   169 
   170 	if (!dlnow < dltotal)
   171 		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
   172 			file, (int) dlnow / 1024, (int) dltotal / 1024);
   173 	else
   174 		fprintf(stderr, "\n");
   175 
   176 	return 0;
   177 }
   178 
   179 static int
   180 download_if_missing(CURL *curl, const char *url, const char *file)
   181 {
   182 	struct stat buf;
   183 	char error[256];
   184 	FILE *fp;
   185 	CURLcode res;
   186 	char buffer[256];
   187 
   188 	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
   189 	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
   190 	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
   191 	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
   192 
   193 	if (stat(file, &buf) < 0) {
   194 		fp = fopen(file, "w");
   195 		snprintf(buffer, sizeof buffer, "%s/%s", url, file);
   196 		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
   197 		curl_easy_setopt(curl, CURLOPT_URL, buffer);
   198 		res = curl_easy_perform(curl);
   199 		fclose(fp);
   200 		if (res != CURLE_OK) {
   201 			fprintf(stderr, "curl error: %s\n", error);
   202 			unlink(file);
   203 			return -1;
   204 		}
   205 	}
   206 
   207 	return 0;
   208 }
   209 
   210 #define REPO_URL "http://download.fedora.redhat.com" \
   211 	"/pub/fedora/linux/development/i386/os/repodata"
   212 
   213 static int
   214 command_import_yum(int argc, const char *argv[])
   215 {
   216 	struct razor_set *set;
   217 	CURL *curl;
   218 
   219 	curl = curl_easy_init();
   220 	if (curl == NULL)
   221 		return 1;
   222 
   223 	if (download_if_missing(curl, REPO_URL, "primary.xml.gz") < 0)
   224 		return -1;
   225 	if (download_if_missing(curl, REPO_URL, "filelists.xml.gz") < 0)
   226 		return -1;
   227 	curl_easy_cleanup(curl);
   228 
   229 	set = razor_set_create_from_yum();
   230 	if (set == NULL)
   231 		return 1;
   232 	razor_set_write(set, rawhide_repo_filename);
   233 	razor_set_destroy(set);
   234 	printf("wrote %s\n", rawhide_repo_filename);
   235 
   236 	return 0;
   237 }
   238 
   239 static int
   240 command_import_rpmdb(int argc, const char *argv[])
   241 {
   242 	struct razor_set *set;
   243 
   244 	set = razor_set_create_from_rpmdb();
   245 	if (set == NULL)
   246 		return 1;
   247 	razor_set_write(set, repo_filename);
   248 	razor_set_destroy(set);
   249 	printf("wrote %s\n", repo_filename);
   250 
   251 	return 0;
   252 }
   253 
   254 static int
   255 command_validate(int argc, const char *argv[])
   256 {
   257 	struct razor_set *set;
   258 
   259 	set = razor_set_open(repo_filename);
   260 	if (set == NULL)
   261 		return 1;
   262 	razor_set_list_unsatisfied(set);
   263 	razor_set_destroy(set);
   264 
   265 	return 0;
   266 }
   267 
   268 static int
   269 command_update(int argc, const char *argv[])
   270 {
   271 	struct razor_set *set, *upstream;
   272 
   273 	set = razor_set_open(repo_filename);
   274 	upstream = razor_set_open(rawhide_repo_filename);
   275 	if (set == NULL || upstream == NULL)
   276 		return 1;
   277 	set = razor_set_update(set, upstream, argc, argv);
   278 	razor_set_write(set, updated_repo_filename);
   279 	razor_set_destroy(set);
   280 	razor_set_destroy(upstream);
   281 	printf("wrote system-updated.repo\n");
   282 
   283 	return 0;
   284 }
   285 
   286 static void
   287 print_diff(const char *name,
   288 	   const char *old_version, const char *new_version, void *data)
   289 {
   290 	if (old_version)
   291 		printf("removing %s %s\n", name, old_version);
   292 	else
   293 		printf("install %s %s\n", name, new_version);
   294 }
   295 
   296 static int
   297 command_diff(int argc, const char *argv[])
   298 {
   299 	struct razor_set *set, *updated;
   300 
   301 	set = razor_set_open(repo_filename);
   302 	updated = razor_set_open(updated_repo_filename);
   303 	if (set == NULL || updated == NULL)
   304 		return 1;
   305 
   306 	razor_set_diff(set, updated, print_diff, NULL);	
   307 
   308 	razor_set_destroy(set);
   309 	razor_set_destroy(updated);
   310 
   311 	return 0;
   312 }
   313 
   314 static int
   315 command_import_rpms(int argc, const char *argv[])
   316 {
   317 	DIR *dir;
   318 	struct dirent *de;
   319 	struct razor_importer *importer;
   320 	struct razor_set *set;
   321 	struct razor_rpm *rpm;
   322 	int len;
   323 	char filename[256];
   324 	const char *dirname = argv[0];
   325 
   326 	if (dirname == NULL) {
   327 		fprintf(stderr, "usage: razor import-rpms DIR\n");
   328 		return -1;
   329 	}
   330 
   331 	dir = opendir(dirname);
   332 	if (dir == NULL) {
   333 		fprintf(stderr, "couldn't read dir %s\n", dirname);
   334 		return -1;
   335 	}
   336 
   337 	importer = razor_importer_new();
   338 
   339 	while (de = readdir(dir), de != NULL) {
   340 		len = strlen(de->d_name);
   341 		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
   342 		    continue;
   343 		snprintf(filename, sizeof filename,
   344 			 "%s/%s", dirname, de->d_name);
   345 		rpm = razor_rpm_open(filename);
   346 		if (rpm == NULL) {
   347 			fprintf(stderr,
   348 				"failed to open rpm \"%s\"\n", filename);
   349 			continue;
   350 		}
   351 		if (razor_importer_add_rpm(importer, rpm)) {
   352 			fprintf(stderr, "couldn't import %s\n", filename);
   353 			break;
   354 		}
   355 		razor_rpm_close(rpm);
   356 	}
   357 
   358 	if (de != NULL) {
   359 		razor_importer_destroy(importer);
   360 		return -1;
   361 	}
   362 
   363 	set = razor_importer_finish(importer);
   364 
   365 	razor_set_write(set, repo_filename);
   366 	razor_set_destroy(set);
   367 	printf("wrote %s\n", repo_filename);
   368 
   369 	return 0;
   370 }
   371 
   372 static int
   373 command_install(int argc, const char *argv[])
   374 {
   375 	struct razor_rpm *rpm;
   376 	const char *filename = argv[0];
   377 	struct stat buf;
   378 	const char root[] = "install";
   379 
   380 	if (stat(root, &buf) < 0) {
   381 		if (mkdir(root, 0777) < 0) {
   382 			fprintf(stderr,
   383 				"could not create install root \"%s\"\n",
   384 				root);
   385 			return -1;
   386 		}
   387 		fprintf(stderr, "created install root \"%s\"\n", root);
   388 	} else if (!S_ISDIR(buf.st_mode)) {
   389 		fprintf(stderr,
   390 			"install root \"%s\" exists, but is not a directory\n",
   391 			root);
   392 		return -1;
   393 	}
   394 
   395 	rpm = razor_rpm_open(filename);
   396 	if (rpm == NULL) {
   397 		fprintf(stderr, "failed to open rpm %s\n", filename);
   398 		return -1;
   399 	}
   400 	if (razor_rpm_install(rpm, root) < 0) {
   401 		fprintf(stderr, "failed to install rpm %s\n", filename);
   402 		return -1;
   403 	}
   404 	
   405 	razor_rpm_close(rpm);
   406 
   407 	return 0;
   408 }
   409 
   410 static struct {
   411 	const char *name;
   412 	const char *description;
   413 	int (*func)(int argc, const char *argv[]);
   414 } razor_commands[] = {
   415 	{ "list", "list all packages", command_list },
   416 	{ "list-requires", "list all requires for the given package", command_list_requires },
   417 	{ "list-provides", "list all provides for the given package", command_list_provides },
   418 	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
   419 	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
   420 	{ "list-files", "list files for package set", command_list_files },
   421 	{ "list-file-packages", "list packages owning file", command_list_file_packages },
   422 	{ "list-package-files", "list files in package", command_list_package_files },
   423 	{ "what-requires", "list the packages that have the given requires", command_what_requires },
   424 	{ "what-provides", "list the packages that have the given provides", command_what_provides },
   425 	{ "import-yum", "import yum metadata files", command_import_yum },
   426 	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
   427 	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
   428 	{ "validate", "validate a package set", command_validate },
   429 	{ "update", "update all or specified packages", command_update },
   430 	{ "diff", "show diff between two package sets", command_diff },
   431 	{ "install", "install rpm", command_install }
   432 };
   433 
   434 static int
   435 usage(void)
   436 {
   437 	int i;
   438 
   439 	printf("usage:\n");
   440 	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
   441 		printf("  %-20s%s\n",
   442 		       razor_commands[i].name, razor_commands[i].description);
   443 
   444 	return 1;
   445 }
   446 
   447 int
   448 main(int argc, const char *argv[])
   449 {
   450 	char *repo;
   451 	int i;
   452 
   453 	repo = getenv("RAZOR_REPO");
   454 	if (repo != NULL)
   455 		repo_filename = repo;
   456 
   457 	if (argc < 2)
   458 		return usage();
   459 
   460 	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
   461 		if (strcmp(razor_commands[i].name, argv[1]) == 0)
   462 			return razor_commands[i].func(argc - 2, argv + 2);
   463 
   464 	return usage();
   465 }