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.
10 #include <curl/curl.h>
14 #include "razor-internal.h"
16 static const char system_repo_filename[] = "system.repo";
17 static const char next_repo_filename[] = "system-next.repo";
18 static const char rawhide_repo_filename[] = "rawhide.repo";
19 static const char updated_repo_filename[] = "system-updated.repo";
20 static const char razor_root_path[] = "/var/lib/razor";
21 static const char root[] = "install";
22 static const char *repo_filename = system_repo_filename;
25 command_list(int argc, const char *argv[])
27 struct razor_set *set;
28 struct razor_package_iterator *pi;
29 struct razor_package *package;
30 const char *pattern, *name, *version, *arch;
31 int only_names = 0, i = 0;
33 if (i < argc && strcmp(argv[i], "--only-names") == 0) {
39 set = razor_set_open(repo_filename);
40 pi = razor_package_iterator_create(set);
41 while (razor_package_iterator_next(pi, &package,
42 &name, &version, &arch)) {
43 if (pattern && fnmatch(pattern, name, 0) != 0)
49 printf("%s-%s.%s\n", name, version, arch);
51 razor_package_iterator_destroy(pi);
52 razor_set_destroy(set);
58 list_properties(const char *package_name,
59 enum razor_property_type required_type)
61 struct razor_set *set;
62 struct razor_property *property;
63 struct razor_package *package;
64 struct razor_property_iterator *pi;
65 const char *name, *version;
66 enum razor_property_type type;
67 enum razor_version_relation relation;
69 set = razor_set_open(repo_filename);
71 package = razor_set_get_package(set, package_name);
75 pi = razor_property_iterator_create(set, package);
76 while (razor_property_iterator_next(pi, &property,
77 &name, &relation, &version,
79 if (type != required_type)
81 if (version[0] == '\0')
84 printf("%s %s %s\n", name,
85 razor_version_relations[relation], version);
87 razor_property_iterator_destroy(pi);
89 razor_set_destroy(set);
95 command_list_requires(int argc, const char *argv[])
97 return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
101 command_list_provides(int argc, const char *argv[])
103 return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
107 command_list_obsoletes(int argc, const char *argv[])
109 return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
113 command_list_conflicts(int argc, const char *argv[])
115 return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
119 command_list_files(int argc, const char *argv[])
121 struct razor_set *set;
123 set = razor_set_open(repo_filename);
126 razor_set_list_files(set, argv[0]);
127 razor_set_destroy(set);
133 command_list_file_packages(int argc, const char *argv[])
135 struct razor_set *set;
136 struct razor_package_iterator *pi;
137 struct razor_package *package;
138 const char *name, *version, *arch;
140 set = razor_set_open(repo_filename);
144 pi = razor_package_iterator_create_for_file(set, argv[0]);
145 while (razor_package_iterator_next(pi, &package,
146 &name, &version, &arch))
147 printf("%s-%s\n", name, version);
148 razor_package_iterator_destroy(pi);
150 razor_set_destroy(set);
156 command_list_package_files(int argc, const char *argv[])
158 struct razor_set *set;
160 set = razor_set_open(repo_filename);
163 razor_set_list_package_files(set, argv[0]);
164 razor_set_destroy(set);
170 list_packages_for_property(struct razor_set *set,
171 struct razor_property *property)
173 struct razor_package_iterator *pi;
174 struct razor_package *package;
175 const char *name, *version, *arch;
177 pi = razor_package_iterator_create_for_property(set, property);
178 while (razor_package_iterator_next(pi, &package,
179 &name, &version, &arch))
180 printf("%s-%s.%s\n", name, version, arch);
181 razor_package_iterator_destroy(pi);
185 list_property_packages(const char *ref_name,
186 const char *ref_version,
187 enum razor_property_type ref_type)
189 struct razor_set *set;
190 struct razor_property *property;
191 struct razor_property_iterator *pi;
192 const char *name, *version;
193 enum razor_property_type type;
194 enum razor_version_relation relation;
196 if (ref_name == NULL)
199 set = razor_set_open(repo_filename);
203 pi = razor_property_iterator_create(set, NULL);
204 while (razor_property_iterator_next(pi, &property,
205 &name, &relation, &version,
207 if (strcmp(ref_name, name) != 0)
209 if (ref_version && relation == RAZOR_VERSION_EQUAL &&
210 strcmp(ref_version, version) != 0)
212 if (ref_type != type)
215 list_packages_for_property(set, property);
217 razor_property_iterator_destroy(pi);
223 command_what_requires(int argc, const char *argv[])
225 return list_property_packages(argv[0], argv[1],
226 RAZOR_PROPERTY_REQUIRES);
230 command_what_provides(int argc, const char *argv[])
232 return list_property_packages(argv[0], argv[1],
233 RAZOR_PROPERTY_PROVIDES);
237 show_progress(void *clientp,
238 double dltotal, double dlnow, double ultotal, double ulnow)
240 const char *file = clientp;
242 if (!dlnow < dltotal)
243 fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
244 file, (int) dlnow / 1024, (int) dltotal / 1024);
250 download_if_missing(const char *url, const char *file)
259 curl = curl_easy_init();
263 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
264 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
265 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
266 curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
268 if (stat(file, &buf) < 0) {
269 fp = fopen(file, "w");
272 "failed to open %s for writing\n", file);
275 curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
276 curl_easy_setopt(curl, CURLOPT_URL, url);
277 res = curl_easy_perform(curl);
279 if (res != CURLE_OK) {
280 fprintf(stderr, "curl error: %s\n", error);
284 res = curl_easy_getinfo(curl,
285 CURLINFO_RESPONSE_CODE, &response);
286 if (res != CURLE_OK) {
287 fprintf(stderr, "curl error: %s\n", error);
291 if (response != 200) {
292 fprintf(stderr, " - failed %ld\n", response);
296 fprintf(stderr, "\n");
299 curl_easy_cleanup(curl);
304 #define REPO_URL "http://download.fedora.redhat.com" \
305 "/pub/fedora/linux/development/i386/os"
308 command_import_yum(int argc, const char *argv[])
310 struct razor_set *set;
312 if (download_if_missing(REPO_URL "/repodata/primary.xml.gz",
313 "primary.xml.gz") < 0)
315 if (download_if_missing(REPO_URL "/repodata/filelists.xml.gz",
316 "filelists.xml.gz") < 0)
319 set = razor_set_create_from_yum();
322 razor_set_write(set, rawhide_repo_filename);
323 razor_set_destroy(set);
324 printf("wrote %s\n", rawhide_repo_filename);
330 command_import_rpmdb(int argc, const char *argv[])
332 struct razor_set *set;
334 set = razor_set_create_from_rpmdb();
337 razor_set_write(set, repo_filename);
338 razor_set_destroy(set);
339 printf("wrote %s\n", repo_filename);
345 command_validate(int argc, const char *argv[])
347 struct razor_set *set;
349 set = razor_set_open(repo_filename);
352 razor_set_list_unsatisfied(set);
353 razor_set_destroy(set);
359 mark_packages_for_update(struct razor_transaction *trans,
360 struct razor_set *set, const char *pattern)
362 struct razor_package_iterator *pi;
363 struct razor_package *package;
364 const char *name, *version, *arch;
367 pi = razor_package_iterator_create(set);
368 while (razor_package_iterator_next(pi, &package,
369 &name, &version, &arch)) {
370 if (pattern && fnmatch(pattern, name, 0) == 0) {
371 razor_transaction_install_package(trans, package);
375 razor_package_iterator_destroy(pi);
381 mark_packages_for_removal(struct razor_transaction *trans,
382 struct razor_set *set, const char *pattern)
384 struct razor_package_iterator *pi;
385 struct razor_package *package;
386 const char *name, *version, *arch;
389 pi = razor_package_iterator_create(set);
390 while (razor_package_iterator_next(pi, &package,
391 &name, &version, &arch)) {
392 if (pattern && fnmatch(pattern, name, 0) == 0) {
393 razor_transaction_remove_package(trans, package);
397 razor_package_iterator_destroy(pi);
403 command_update(int argc, const char *argv[])
405 struct razor_set *set, *upstream;
406 struct razor_transaction *trans;
409 set = razor_set_open(repo_filename);
410 upstream = razor_set_open(rawhide_repo_filename);
411 if (set == NULL || upstream == NULL)
414 trans = razor_transaction_create(set, upstream);
416 razor_transaction_update_all(trans);
417 for (i = 0; i < argc; i++) {
418 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
419 fprintf(stderr, "no match for %s\n", argv[i]);
424 errors = razor_transaction_resolve(trans);
428 set = razor_transaction_finish(trans);
429 razor_set_write(set, updated_repo_filename);
430 razor_set_destroy(set);
431 razor_set_destroy(upstream);
432 printf("wrote system-updated.repo\n");
438 command_remove(int argc, const char *argv[])
440 struct razor_set *set;
441 struct razor_transaction *trans;
444 set = razor_set_open(repo_filename);
448 trans = razor_transaction_create(set, NULL);
449 for (i = 0; i < argc; i++) {
450 if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
451 fprintf(stderr, "no match for %s\n", argv[i]);
456 errors = razor_transaction_resolve(trans);
460 set = razor_transaction_finish(trans);
461 razor_set_write(set, updated_repo_filename);
462 razor_set_destroy(set);
463 printf("wrote system-updated.repo\n");
469 print_diff(const char *name,
470 const char *old_version, const char *new_version, const char *arch,
474 printf("removing %s %s\n", name, old_version);
476 printf("install %s %s\n", name, new_version);
480 command_diff(int argc, const char *argv[])
482 struct razor_set *set, *updated;
484 set = razor_set_open(repo_filename);
485 updated = razor_set_open(updated_repo_filename);
486 if (set == NULL || updated == NULL)
489 razor_set_diff(set, updated, print_diff, NULL);
491 razor_set_destroy(set);
492 razor_set_destroy(updated);
498 command_import_rpms(int argc, const char *argv[])
502 struct razor_importer *importer;
503 struct razor_set *set;
504 struct razor_rpm *rpm;
507 const char *dirname = argv[0];
509 if (dirname == NULL) {
510 fprintf(stderr, "usage: razor import-rpms DIR\n");
514 dir = opendir(dirname);
516 fprintf(stderr, "couldn't read dir %s\n", dirname);
520 importer = razor_importer_new();
522 while (de = readdir(dir), de != NULL) {
523 len = strlen(de->d_name);
524 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
526 snprintf(filename, sizeof filename,
527 "%s/%s", dirname, de->d_name);
528 rpm = razor_rpm_open(filename);
531 "failed to open rpm \"%s\"\n", filename);
534 if (razor_importer_add_rpm(importer, rpm)) {
535 fprintf(stderr, "couldn't import %s\n", filename);
538 razor_rpm_close(rpm);
542 razor_importer_destroy(importer);
546 set = razor_importer_finish(importer);
548 razor_set_write(set, repo_filename);
549 razor_set_destroy(set);
550 printf("wrote %s\n", repo_filename);
556 download_package(const char *name,
557 const char *old_version,
558 const char *new_version,
562 char file[PATH_MAX], url[256];
570 v = strchr(new_version, ':');
576 snprintf(url, sizeof url,
577 REPO_URL "/Packages/%s-%s.%s.rpm", name, v, arch);
578 snprintf(file, sizeof file,
579 "rpms/%s-%s.%s.rpm", name, v, arch);
580 if (download_if_missing(url, file) < 0)
585 install_package(const char *name,
586 const char *old_version,
587 const char *new_version,
591 const char *v, *root = data;
593 struct razor_rpm *rpm;
596 printf("removing %s %s not handled\n", name, old_version);
601 v = strchr(new_version, ':');
607 printf("install %s %s\n", name, v);
608 snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
610 rpm = razor_rpm_open(file);
612 fprintf(stderr, "failed to open rpm %s\n", file);
615 if (razor_rpm_install(rpm, root) < 0) {
617 "failed to install rpm %s\n", file);
620 razor_rpm_close(rpm);
624 command_install(int argc, const char *argv[])
626 struct razor_set *system, *upstream, *next;
627 struct razor_transaction *trans;
628 char path[PATH_MAX], new_path[PATH_MAX];
629 int i = 0, errors, fd, dependencies = 1;
631 if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
636 /* Create the new next repo file up front to ensure exclusive
638 snprintf(new_path, sizeof new_path,
639 "%s%s/%s", root, razor_root_path, next_repo_filename);
640 fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
642 fprintf(stderr, "failed to get lock file, "
643 "maybe previous operation crashed?\n");
645 /* FIXME: Use fcntl advisory locking to figure out
646 * whether previous operation crashed or is still in
652 upstream = razor_set_open(rawhide_repo_filename);
653 snprintf(path, sizeof path,
654 "%s%s/%s", root, razor_root_path, system_repo_filename);
655 system = razor_set_open(path);
656 if (system == NULL || upstream == NULL) {
660 trans = razor_transaction_create(system, upstream);
661 for (; i < argc; i++) {
662 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
663 fprintf(stderr, "no package matched %s\n", argv[i]);
670 errors = razor_transaction_resolve(trans);
677 next = razor_transaction_finish(trans);
679 razor_set_write_to_fd(next, fd);
680 printf("wrote %s\n", new_path);
682 if (mkdir("rpms", 0777) && errno != EEXIST) {
683 fprintf(stderr, "failed to create rpms directory.\n");
687 razor_set_diff(system, next, download_package, &errors);
689 fprintf(stderr, "failed to download %d packages\n", errors);
694 /* FIXME: We need to figure out the right install order here,
695 * so the post and pre scripts can run. */
696 razor_set_diff(system, next, install_package, (void *) root);
698 razor_set_destroy(next);
699 razor_set_destroy(system);
700 razor_set_destroy(upstream);
703 rename(new_path, path);
704 printf("renamed %s to %s\n", new_path, path);
710 command_init(int argc, const char *argv[])
713 struct razor_set *set;
716 if (stat(root, &buf) < 0) {
717 if (mkdir(root, 0777) < 0) {
719 "could not create install root \"%s\"\n",
723 fprintf(stderr, "created install root \"%s\"\n", root);
724 } else if (!S_ISDIR(buf.st_mode)) {
726 "install root \"%s\" exists, but is not a directory\n",
731 snprintf(path, sizeof path, "%s/%s",
732 razor_root_path, system_repo_filename);
733 if (razor_create_dir(root, path) < 0) {
734 fprintf(stderr, "could not create %s%s\n",
735 root, razor_root_path);
739 set = razor_set_create();
740 snprintf(path, sizeof path, "%s%s/%s",
741 root, razor_root_path, system_repo_filename);
742 if (razor_set_write(set, path) < 0) {
743 fprintf(stderr, "could not write initial package set\n");
746 razor_set_destroy(set);
752 command_download(int argc, const char *argv[])
754 struct razor_set *set;
755 struct razor_package_iterator *pi;
756 struct razor_package *package;
757 const char *pattern = argv[0], *name, *version, *arch;
758 char url[256], file[256];
761 if (mkdir("rpms", 0777) && errno != EEXIST) {
762 fprintf(stderr, "failed to create rpms directory.\n");
766 set = razor_set_open(rawhide_repo_filename);
767 pi = razor_package_iterator_create(set);
768 while (razor_package_iterator_next(pi, &package,
769 &name, &version, &arch)) {
770 if (pattern && fnmatch(pattern, name, 0) != 0)
774 snprintf(url, sizeof url,
775 REPO_URL "/Packages/%s-%s.%s.rpm",
776 name, version, arch);
777 snprintf(file, sizeof file,
778 "rpms/%s-%s.%s.rpm", name, version, arch);
779 download_if_missing(url, file);
781 razor_package_iterator_destroy(pi);
782 razor_set_destroy(set);
785 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
786 else if (matches == 1)
787 fprintf(stderr, "downloaded 1 package\n");
789 fprintf(stderr, "downloaded %d packages\n", matches);
796 const char *description;
797 int (*func)(int argc, const char *argv[]);
798 } razor_commands[] = {
799 { "list", "list all packages", command_list },
800 { "list-requires", "list all requires for the given package", command_list_requires },
801 { "list-provides", "list all provides for the given package", command_list_provides },
802 { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
803 { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
804 { "list-files", "list files for package set", command_list_files },
805 { "list-file-packages", "list packages owning file", command_list_file_packages },
806 { "list-package-files", "list files in package", command_list_package_files },
807 { "what-requires", "list the packages that have the given requires", command_what_requires },
808 { "what-provides", "list the packages that have the given provides", command_what_provides },
809 { "import-yum", "import yum metadata files", command_import_yum },
810 { "import-rpmdb", "import the system rpm database", command_import_rpmdb },
811 { "import-rpms", "import rpms from the given directory", command_import_rpms },
812 { "validate", "validate a package set", command_validate },
813 { "update", "update all or specified packages", command_update },
814 { "remove", "remove specified packages", command_remove },
815 { "diff", "show diff between two package sets", command_diff },
816 { "install", "install rpm", command_install },
817 { "init", "init razor root", command_init },
818 { "download", "download packages", command_download }
827 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
829 razor_commands[i].name, razor_commands[i].description);
835 main(int argc, const char *argv[])
840 repo = getenv("RAZOR_REPO");
842 repo_filename = repo;
847 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
848 if (strcmp(razor_commands[i].name, argv[1]) == 0)
849 return razor_commands[i].func(argc - 2, argv + 2);