2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009, 2011 J. Ali Harlow <ali@juiblex.co.uk>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include <curl/curl.h>
42 static const char system_repo_filename[] = "system.rzdb";
43 static const char next_repo_filename[] = "system-next.rzdb";
44 static const char rawhide_repo_filename[] = "rawhide.rzdb";
45 static const char *install_root = "";
46 static const char *repo_filename = system_repo_filename;
47 static const char *yum_url;
49 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
51 enum update_pass_type {
52 UPDATE_PASS_PRE_REMOVE,
54 UPDATE_PASS_POST_INSTALL,
58 update_packages(struct razor_transaction *trans,
59 struct razor_install_iterator *ii, struct razor_set *system,
60 struct razor_set *next, struct razor_atomic *atomic,
61 struct razor_relocations *relocations,
62 enum update_pass_type stage);
64 static struct razor_package_iterator *
65 create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[])
67 struct razor_package_query *query;
68 struct razor_package_iterator *iter;
69 struct razor_package *package;
70 const char *name, *pattern;
74 return razor_package_iterator_create(set);
76 query = razor_package_query_create(set);
78 for (i = 0; i < argc; i++) {
79 iter = razor_package_iterator_create(set);
82 while (razor_package_iterator_next(iter, &package,
83 RAZOR_DETAIL_NAME, &name,
85 if (fnmatch(pattern, name, 0) != 0)
88 razor_package_query_add_package(query, package);
91 razor_package_iterator_destroy(iter);
95 "no package matches \"%s\"\n", pattern);
98 return razor_package_query_finish(query);
101 #define LIST_PACKAGES_ONLY_NAMES 0x01
104 list_packages(struct razor_package_iterator *iter, uint32_t flags)
106 struct razor_package *package;
107 const char *name, *version, *arch;
109 while (razor_package_iterator_next(iter, &package,
110 RAZOR_DETAIL_NAME, &name,
111 RAZOR_DETAIL_VERSION, &version,
112 RAZOR_DETAIL_ARCH, &arch,
113 RAZOR_DETAIL_LAST)) {
114 if (flags & LIST_PACKAGES_ONLY_NAMES)
115 printf("%s\n", name);
117 printf("%s-%s.%s\n", name, version, arch);
122 command_list(int argc, const char *argv[])
124 struct razor_package_iterator *pi;
125 struct razor_atomic *atomic;
126 struct razor_set *set;
130 if (i < argc && strcmp(argv[i], "--only-names") == 0) {
131 flags |= LIST_PACKAGES_ONLY_NAMES;
135 atomic = razor_atomic_open("List installed packages");
136 set = razor_root_open_read_only(install_root, atomic);
138 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
139 razor_atomic_destroy(atomic);
143 pi = create_iterator_from_argv(set, argc - i, argv + i);
144 list_packages(pi, flags);
145 razor_package_iterator_destroy(pi);
146 razor_set_unref(set);
147 razor_atomic_destroy(atomic);
153 list_package_properties(struct razor_set *set,
154 struct razor_package *package, uint32_t type)
156 struct razor_property_iterator *pi;
157 struct razor_property *property;
158 const char *name, *version;
161 pi = razor_property_iterator_create(set, package);
162 while (razor_property_iterator_next(pi, &property,
163 &name, &flags, &version)) {
164 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
167 if (version[0] != '\0')
169 razor_property_relation_to_string(property),
172 if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
174 if (flags & RAZOR_PROPERTY_PRE)
176 if (flags & RAZOR_PROPERTY_POST)
178 if (flags & RAZOR_PROPERTY_PREUN)
180 if (flags & RAZOR_PROPERTY_POSTUN)
186 razor_property_iterator_destroy(pi);
190 list_properties(int argc, const char *argv[], uint32_t type)
192 struct razor_set *set;
193 struct razor_atomic *atomic;
194 struct razor_package *package;
195 struct razor_package_iterator *pi;
196 const char *name, *version, *arch;
198 atomic = razor_atomic_open("List package properties");
199 set = razor_root_open_read_only(install_root, atomic);
201 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
202 razor_atomic_destroy(atomic);
206 pi = create_iterator_from_argv(set, argc, argv);
207 while (razor_package_iterator_next(pi, &package,
208 RAZOR_DETAIL_NAME, &name,
209 RAZOR_DETAIL_VERSION, &version,
210 RAZOR_DETAIL_ARCH, &arch,
212 list_package_properties(set, package, type);
213 razor_package_iterator_destroy(pi);
214 razor_set_unref(set);
215 razor_atomic_destroy(atomic);
221 command_list_requires(int argc, const char *argv[])
223 return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES);
227 command_list_provides(int argc, const char *argv[])
229 return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES);
233 command_list_obsoletes(int argc, const char *argv[])
235 return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES);
239 command_list_conflicts(int argc, const char *argv[])
241 return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS);
245 command_list_scripts(int argc, const char *argv[])
247 struct razor_set *set;
248 struct razor_atomic *atomic;
249 struct razor_package *package;
250 struct razor_package_iterator *pi;
251 const char *preunprog, *preun, *postunprog, *postun;
253 atomic = razor_atomic_open("List package scripts");
254 set = razor_root_open_read_only(install_root, atomic);
256 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
257 razor_atomic_destroy(atomic);
261 pi = create_iterator_from_argv(set, argc, argv);
262 while (razor_package_iterator_next(pi, &package,
263 RAZOR_DETAIL_PREUNPROG, &preunprog,
264 RAZOR_DETAIL_PREUN, &preun,
265 RAZOR_DETAIL_POSTUNPROG, &postunprog,
266 RAZOR_DETAIL_POSTUN, &postun,
267 RAZOR_DETAIL_LAST)) {
268 if (preun && *preun) {
269 printf("preuninstall scriptlet");
270 if (preunprog && *preunprog)
271 printf(" (using %s)",preunprog);
272 printf(":\n%s\n",preun);
274 if (postun && *postun) {
275 printf("postuninstall scriptlet");
276 if (postunprog && *postunprog)
277 printf(" (using %s)",postunprog);
278 printf(":\n%s\n",postun);
281 razor_package_iterator_destroy(pi);
282 razor_set_unref(set);
283 razor_atomic_destroy(atomic);
289 command_list_files(int argc, const char *argv[])
291 struct razor_atomic *atomic;
292 struct razor_set *set;
294 atomic = razor_atomic_open("List package files");
295 set = razor_root_open_read_only(install_root, atomic);
297 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
298 razor_atomic_destroy(atomic);
302 razor_set_list_files(set, argv[0]);
303 razor_set_unref(set);
304 razor_atomic_destroy(atomic);
310 command_list_file_packages(int argc, const char *argv[])
312 struct razor_atomic *atomic;
313 struct razor_set *set;
314 struct razor_package_iterator *pi;
316 atomic = razor_atomic_open("List file packages");
317 set = razor_root_open_read_only(install_root, atomic);
319 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
320 razor_atomic_destroy(atomic);
324 pi = razor_package_iterator_create_for_file(set, argv[0]);
325 list_packages(pi, 0);
326 razor_package_iterator_destroy(pi);
328 razor_set_unref(set);
329 razor_atomic_destroy(atomic);
335 command_list_package_files(int argc, const char *argv[])
337 struct razor_atomic *atomic;
338 struct razor_set *set;
339 struct razor_package_iterator *pi;
340 struct razor_package *package;
341 const char *name, *version, *arch;
343 atomic = razor_atomic_open("List package files");
344 set = razor_root_open_read_only(install_root, atomic);
346 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
347 razor_atomic_destroy(atomic);
351 pi = create_iterator_from_argv(set, argc, argv);
352 while (razor_package_iterator_next(pi, &package,
353 RAZOR_DETAIL_NAME, &name,
354 RAZOR_DETAIL_VERSION, &version,
355 RAZOR_DETAIL_ARCH, &arch,
357 razor_set_list_package_files(set, package);
358 razor_package_iterator_destroy(pi);
360 razor_set_unref(set);
361 razor_atomic_destroy(atomic);
367 list_property_packages(const char *ref_name,
368 const char *ref_version,
371 struct razor_atomic *atomic;
372 struct razor_set *set;
373 struct razor_property *property;
374 struct razor_property_iterator *prop_iter;
375 struct razor_package_iterator *pkg_iter;
376 const char *name, *version;
379 if (ref_name == NULL)
382 atomic = razor_atomic_open("List package properties");
383 set = razor_root_open_read_only(install_root, atomic);
385 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
386 razor_atomic_destroy(atomic);
390 prop_iter = razor_property_iterator_create(set, NULL);
391 while (razor_property_iterator_next(prop_iter, &property,
392 &name, &flags, &version)) {
393 if (strcmp(ref_name, name) != 0)
396 (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
397 strcmp(ref_version, version) != 0)
399 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
403 razor_package_iterator_create_for_property(set,
405 list_packages(pkg_iter, 0);
406 razor_package_iterator_destroy(pkg_iter);
408 razor_property_iterator_destroy(prop_iter);
410 razor_set_unref(set);
411 razor_atomic_destroy(atomic);
417 command_what_requires(int argc, const char *argv[])
419 return list_property_packages(argv[0], argv[1],
420 RAZOR_PROPERTY_REQUIRES);
424 command_what_provides(int argc, const char *argv[])
426 return list_property_packages(argv[0], argv[1],
427 RAZOR_PROPERTY_PROVIDES);
431 show_progress(void *clientp,
432 double dltotal, double dlnow, double ultotal, double ulnow)
434 const char *file = clientp;
436 if (!dlnow < dltotal)
437 fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
438 file, (int) dlnow / 1024, (int) dltotal / 1024);
444 download_if_missing(const char *url, const char *file)
456 curl = curl_easy_init();
460 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
461 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
462 curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
463 curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
465 if (stat(file, &buf) < 0) {
466 fp = fopen(file, "wb");
469 "failed to open %s for writing\n", file);
472 curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
473 curl_easy_setopt(curl, CURLOPT_URL, url);
474 res = curl_easy_perform(curl);
476 if (res != CURLE_OK) {
477 fprintf(stderr, "curl error: %s\n", error);
481 res = curl_easy_getinfo(curl,
482 CURLINFO_RESPONSE_CODE, &response);
483 if (res != CURLE_OK) {
484 fprintf(stderr, "curl error: %s\n", error);
488 if (response != 200) {
489 fprintf(stderr, " - failed %ld\n", response);
493 fprintf(stderr, "\n");
496 curl_easy_cleanup(curl);
499 #endif /* HAVE_CURL */
502 #define YUM_URL "http://download.fedora.redhat.com" \
503 "/pub/fedora/linux/development/i386/os"
506 command_import_yum(int argc, const char *argv[])
509 struct razor_set *set;
510 struct razor_atomic *atomic;
513 printf("downloading from %s.\n", yum_url);
514 snprintf(buffer, sizeof buffer,
515 "%s/repodata/primary.xml.gz", yum_url);
516 if (download_if_missing(buffer, "primary.xml.gz") < 0)
518 snprintf(buffer, sizeof buffer,
519 "%s/repodata/filelists.xml.gz", yum_url);
520 if (download_if_missing(buffer, "filelists.xml.gz") < 0)
523 set = razor_set_create_from_yum();
526 atomic = razor_atomic_open("Yum import repository");
527 razor_set_write(set, atomic, rawhide_repo_filename, RAZOR_SECTION_ALL);
528 retval = razor_atomic_commit(atomic);
529 razor_set_unref(set);
531 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
533 printf("wrote %s\n", rawhide_repo_filename);
534 razor_atomic_destroy(atomic);
541 command_import_rpmdb(int argc, const char *argv[])
543 struct razor_set *set;
544 struct razor_root *root;
545 struct razor_atomic *atomic;
548 atomic = razor_atomic_open("Import RPM database");
550 root = razor_root_open(install_root, atomic);
552 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
553 razor_atomic_destroy(atomic);
557 set = razor_set_create_from_rpmdb();
561 razor_root_update(root, set);
563 retval = razor_root_commit(root);
565 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
567 razor_atomic_destroy(atomic);
574 mark_packages_for_update(struct razor_transaction *trans,
575 struct razor_set *set, const char *pattern)
577 struct razor_package_iterator *pi;
578 struct razor_package *package;
582 pi = razor_package_iterator_create(set);
583 while (razor_package_iterator_next(pi, &package,
584 RAZOR_DETAIL_NAME, &name,
585 RAZOR_DETAIL_LAST)) {
586 if (pattern && fnmatch(pattern, name, 0) == 0) {
587 razor_transaction_update_package(trans, package);
591 razor_package_iterator_destroy(pi);
597 mark_packages_for_removal(struct razor_transaction *trans,
598 struct razor_set *set, const char *pattern)
600 struct razor_package_iterator *pi;
601 struct razor_package *package;
605 pi = razor_package_iterator_create(set);
606 while (razor_package_iterator_next(pi, &package,
607 RAZOR_DETAIL_NAME, &name,
608 RAZOR_DETAIL_LAST)) {
609 if (pattern && fnmatch(pattern, name, 0) == 0) {
610 razor_transaction_remove_package(trans, package);
614 razor_package_iterator_destroy(pi);
620 command_remove(int argc, const char *argv[])
622 struct razor_root *root;
623 struct razor_set *system, *upstream, *next;
624 struct razor_transaction *trans;
625 struct razor_atomic *atomic;
626 struct razor_install_iterator *ii;
629 atomic = razor_atomic_open("Remove packages");
631 root = razor_root_open(install_root, atomic);
632 system = razor_set_ref(razor_root_get_system_set(root));
633 if (system == NULL) {
634 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
635 razor_root_close(root);
636 razor_atomic_destroy(atomic);
640 upstream = razor_set_create_without_root();
641 trans = razor_transaction_create(system, upstream);
642 razor_set_unref(upstream);
643 for (i = 0; i < argc; i++) {
644 if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
645 fprintf(stderr, "no match for %s\n", argv[i]);
646 razor_transaction_destroy(trans);
647 razor_set_unref(system);
648 razor_root_close(root);
649 razor_atomic_destroy(atomic);
654 razor_transaction_resolve(trans);
655 retval = razor_transaction_describe(trans);
657 razor_transaction_destroy(trans);
658 razor_set_unref(system);
659 razor_root_close(root);
660 razor_atomic_destroy(atomic);
664 next = razor_transaction_commit(trans);
665 ii = razor_set_create_install_iterator(system, next);
666 retval = update_packages(trans, ii, system, next, atomic, NULL,
667 UPDATE_PASS_PRE_REMOVE);
669 fprintf(stderr, "Remove aborted\n");
671 update_packages(trans, ii, system, next, atomic, NULL,
674 razor_root_update(root, next);
676 (void)razor_root_commit(root);
677 retval = razor_atomic_commit(atomic);
679 fprintf(stderr, "%s\n",
680 razor_atomic_get_error_msg(atomic));
683 razor_install_iterator_destroy(ii);
684 razor_transaction_destroy(trans);
685 razor_atomic_destroy(atomic);
686 razor_set_unref(system);
687 razor_set_unref(next);
693 print_diff(enum razor_diff_action action,
694 struct razor_package *package,
700 if (action == RAZOR_DIFF_ACTION_ADD)
701 printf("install %s-%s.%s\n", name, version, arch);
702 if (action == RAZOR_DIFF_ACTION_REMOVE)
703 printf("remove %s-%s.%s\n", name, version, arch);
707 command_diff(int argc, const char *argv[])
709 struct razor_atomic *atomic;
710 struct razor_set *set, *updated;
712 atomic = razor_atomic_open("Show package differences");
713 set = razor_root_open_read_only(install_root, atomic);
714 updated = razor_set_open(rawhide_repo_filename, atomic);
715 if (set == NULL || updated == NULL) {
716 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
717 razor_atomic_destroy(atomic);
721 razor_set_diff(set, updated, print_diff, NULL);
723 razor_set_unref(set);
724 razor_set_unref(updated);
725 razor_atomic_destroy(atomic);
731 command_import_rpms(int argc, const char *argv[])
735 struct razor_importer *importer;
736 struct razor_set *set;
737 struct razor_rpm *rpm;
738 struct razor_atomic *atomic;
739 int len, imported_count = 0;
741 const char *dirname = argv[0];
744 if (dirname == NULL) {
745 fprintf(stderr, "usage: razor import-rpms DIR\n");
749 dir = opendir(dirname);
751 fprintf(stderr, "couldn't read dir %s\n", dirname);
755 importer = razor_importer_create();
757 while (de = readdir(dir), de != NULL) {
758 len = strlen(de->d_name);
759 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
761 snprintf(filename, sizeof filename,
762 "%s/%s", dirname, de->d_name);
763 atomic = razor_atomic_open("Read RPM");
764 rpm = razor_rpm_open(filename, atomic);
766 fprintf(stderr, "%s\n",
767 razor_atomic_get_error_msg(atomic));
768 razor_atomic_destroy(atomic);
771 if (razor_importer_add_rpm(importer, rpm)) {
772 fprintf(stderr, "couldn't import %s\n", filename);
775 razor_rpm_close(rpm);
777 printf("\rimporting %d", ++imported_count);
782 razor_importer_destroy(importer);
786 printf("\nsaving\n");
787 set = razor_importer_finish(importer);
789 atomic = razor_atomic_open("Update system database");
790 razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
791 razor_set_unref(set);
792 retval = razor_atomic_commit(atomic);
794 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
796 printf("wrote %s\n", repo_filename);
797 razor_atomic_destroy(atomic);
803 rpm_filename(const char *name, const char *version, const char *arch)
808 v = strchr(version, ':');
814 return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
818 download_packages(struct razor_set *system, struct razor_set *next)
820 struct razor_install_iterator *ii;
821 struct razor_package *package;
822 enum razor_install_action action;
823 const char *name, *version, *arch;
824 char *file, *url, *s;
825 int errors = 0, count;
827 ii = razor_set_create_install_iterator(system, next);
828 while (razor_install_iterator_next(ii, &package, &action, &count)) {
829 if (action == RAZOR_INSTALL_ACTION_REMOVE)
832 razor_package_get_details(next, package,
833 RAZOR_DETAIL_NAME, &name,
834 RAZOR_DETAIL_VERSION, &version,
835 RAZOR_DETAIL_ARCH, &arch,
838 s = rpm_filename(name, version, arch);
839 url = razor_concat(yum_url, "/Packages/", s, NULL);
840 file = razor_concat("rpms/", s, NULL);
842 if (download_if_missing(url, file) < 0)
847 razor_install_iterator_destroy(ii);
850 fprintf(stderr, "failed to download %d packages\n", errors);
857 static struct razor_set *
858 relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
859 struct razor_relocations *relocations)
862 struct razor_importer *importer;
863 struct razor_property_iterator *prop_iter;
864 struct razor_package_iterator *pkg_iter;
865 struct razor_file_iterator *file_iter;
866 struct razor_package *package;
867 struct razor_property *property;
868 struct razor_rpm *rpm;
869 const char *name, *version, *arch, *summary, *desc, *url, *license;
870 const char *preunprog, *preun, *postunprog, *postun;
871 const char *install_prefix;
872 const char *const *prefixes;
876 importer = razor_importer_create();
877 pkg_iter = razor_package_iterator_create(set);
879 while (razor_package_iterator_next(pkg_iter, &package,
880 RAZOR_DETAIL_NAME, &name,
881 RAZOR_DETAIL_VERSION, &version,
882 RAZOR_DETAIL_ARCH, &arch,
883 RAZOR_DETAIL_SUMMARY, &summary,
884 RAZOR_DETAIL_DESCRIPTION, &desc,
885 RAZOR_DETAIL_URL, &url,
886 RAZOR_DETAIL_LICENSE, &license,
887 RAZOR_DETAIL_PREUNPROG, &preunprog,
888 RAZOR_DETAIL_PREUN, &preun,
889 RAZOR_DETAIL_POSTUNPROG, &postunprog,
890 RAZOR_DETAIL_POSTUN, &postun,
891 RAZOR_DETAIL_LAST)) {
892 s = rpm_filename(name, version, arch);
893 file = razor_concat("rpms/", s, NULL);
895 rpm = razor_rpm_open(file, atomic);
898 razor_package_iterator_destroy(pkg_iter);
899 razor_importer_destroy(importer);
903 razor_relocations_set_rpm(relocations, rpm);
905 razor_importer_begin_package(importer, name, version, arch);
906 razor_importer_add_details(importer,
907 summary, desc, url, license);
909 razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
911 for (i = 0; prefixes && prefixes[i]; i++) {
912 install_prefix = razor_relocations_apply(relocations,
914 razor_importer_add_install_prefix(importer,
918 razor_rpm_close(rpm);
920 prop_iter = razor_property_iterator_create(set, package);
921 while (razor_property_iterator_next(prop_iter, &property,
922 &name, &flags, &version))
923 razor_importer_add_property(importer,
924 name, flags, version);
925 razor_property_iterator_destroy(prop_iter);
927 file_iter = razor_file_iterator_create(set, package, 0);
928 while (razor_file_iterator_next(file_iter, &name)) {
929 name = razor_relocations_apply(relocations, name);
930 razor_importer_add_file(importer, name);
932 razor_file_iterator_destroy(file_iter);
934 razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
936 razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
939 razor_importer_finish_package(importer);
942 razor_package_iterator_destroy(pkg_iter);
943 return razor_importer_finish(importer);
947 install_package(struct razor_transaction *trans, struct razor_set *set,
948 struct razor_atomic *atomic, struct razor_package *package,
949 struct razor_relocations *relocations, int install_count,
950 enum razor_stage_type stage)
953 const char *name, *version, *arch;
955 struct razor_rpm *rpm;
957 razor_package_get_details(set, package,
958 RAZOR_DETAIL_NAME, &name,
959 RAZOR_DETAIL_VERSION, &version,
960 RAZOR_DETAIL_ARCH, &arch,
963 if (stage & RAZOR_STAGE_SCRIPTS_PRE)
964 printf("install %s-%s\n", name, version);
966 s = rpm_filename(name, version, arch);
967 file = razor_concat("rpms/", s, NULL);
969 rpm = razor_rpm_open(file, atomic);
972 fprintf(stderr, "%s\n",
973 razor_atomic_get_error_msg(atomic));
977 razor_rpm_set_relocations(rpm, relocations);
978 razor_transaction_fixup_package(trans, package, rpm);
979 retval = razor_rpm_install(rpm, atomic, install_root, install_count,
982 s = rpm_filename(name, version, arch);
983 fprintf(stderr, "%s: %s\n", s,
984 razor_atomic_get_error_msg(atomic));
987 razor_rpm_close(rpm);
992 * In the most general case, there should be three passes:
994 * 1) For each package to be removed, run %preun
996 * 2) For each package:
997 * If the package is to be installed, run %pre
998 * Update the files on disk
999 * If the package has been removed, run %postun
1001 * 3) For each packge installed, run %post
1003 * This guarantees that:
1004 * a) Save where dependency loops make it impossible, at the time
1005 * %pre is run, all required packages are installed (although
1006 * their %post script may not have been run). We should support
1007 * Requires(%pre) to allow packagers to describe their requirements
1008 * more accurately and avoid unnecessary dependency loops.
1009 * b) At the time %preun is run, all required packages are installed.
1010 * Supporting Requires(%preun) would make this more complicated
1011 * since we might have to install a package in order to remove
1012 * another one. For now, treating Requires(%preun) as Requires
1013 * seems more sensible.
1014 * c) At the time %post is run, all required packages are installed.
1015 * Supporting Requires(%post) would allow us to remove a package
1016 * that was only needed to install another, but there seems no
1017 * obvious advantage.
1018 * d) Save where dependency loops make it impossible, at the time
1019 * %postun is run, all required packages are installed. Again,
1020 * we should support Requires(%postun) to avoid unnecessary
1024 * rpm treats %pre and %preun script failures as fatal errors
1025 * and %post and %postun failures as warnings.
1028 update_packages(struct razor_transaction *trans,
1029 struct razor_install_iterator *ii, struct razor_set *system,
1030 struct razor_set *next, struct razor_atomic *atomic,
1031 struct razor_relocations *relocations,
1032 enum update_pass_type pass)
1034 struct razor_package *package;
1035 enum razor_install_action action;
1036 int retval = 0, count;
1037 enum razor_stage_type remove_stage, add_stage;
1040 case UPDATE_PASS_PRE_REMOVE:
1042 remove_stage = RAZOR_STAGE_SCRIPTS_PRE;
1044 case UPDATE_PASS_MAIN:
1045 add_stage = RAZOR_STAGE_SCRIPTS_PRE | RAZOR_STAGE_FILES;
1046 remove_stage = RAZOR_STAGE_FILES | RAZOR_STAGE_SCRIPTS_POST;
1048 case UPDATE_PASS_POST_INSTALL:
1049 add_stage = RAZOR_STAGE_SCRIPTS_POST;
1054 razor_install_iterator_rewind(ii);
1056 while (!retval && razor_install_iterator_next(ii, &package, &action,
1058 if (action == RAZOR_INSTALL_ACTION_ADD && add_stage)
1059 retval = install_package(trans, next, atomic, package,
1060 relocations, count, add_stage);
1061 else if (action == RAZOR_INSTALL_ACTION_REMOVE && remove_stage)
1062 retval = razor_package_remove(system, next, atomic,
1063 package, install_root,
1064 count, remove_stage);
1071 command_install_or_update(int argc, const char *argv[], int do_update)
1073 struct razor_root *root;
1074 struct razor_relocations *relocations=NULL;
1075 struct razor_set *system, *upstream, *next, *set;
1076 struct razor_transaction *trans;
1077 struct razor_atomic *atomic;
1078 struct razor_install_iterator *ii;
1079 int i, retval, len, dependencies = 1;
1083 atomic = razor_atomic_open("Update packages");
1085 atomic = razor_atomic_open("Install packages");
1087 root = razor_root_open(install_root, atomic);
1089 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1090 razor_atomic_destroy(atomic);
1094 for (i = 0; i < argc; i++) {
1095 if (strcmp(argv[i], "--no-dependencies") == 0)
1097 else if (strcmp(argv[i], "--relocate") == 0) {
1099 if (i >= argc || strchr(argv[i], '=') == NULL) {
1101 "Usage: razor %s [OPTION...] RPM\n",
1102 do_update ? "update" : "install");
1103 fprintf(stderr, "Options:\n");
1104 fprintf(stderr, " [--no-dependencies]\n");
1106 " [--relocate OLDPATH=NEWPATH] RPM\n");
1109 len = strchr(argv[i], '=') - argv[i];
1110 oldpath = malloc(len + 1);
1111 strncpy(oldpath, argv[i], len);
1112 oldpath[len] = '\0';
1114 relocations = razor_relocations_create();
1115 razor_relocations_add(relocations, oldpath,
1122 upstream = razor_set_open(rawhide_repo_filename, atomic);
1123 if (upstream == NULL) {
1124 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1125 razor_root_close(root);
1126 razor_atomic_destroy(atomic);
1131 set = relocate_packages(upstream, atomic, relocations);
1133 fprintf(stderr, "%s\n",
1134 razor_atomic_get_error_msg(atomic));
1135 razor_root_close(root);
1136 razor_atomic_destroy(atomic);
1137 razor_set_unref(upstream);
1140 razor_set_unref(upstream);
1144 system = razor_set_ref(razor_root_get_system_set(root));
1146 trans = razor_transaction_create(system, upstream);
1148 if (i == argc && do_update)
1149 razor_transaction_update_all(trans);
1150 for (; i < argc; i++) {
1152 mark_packages_for_update(trans, system, argv[i]))
1154 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
1155 fprintf(stderr, "no package matched %s\n", argv[i]);
1156 razor_transaction_destroy(trans);
1157 razor_set_unref(upstream);
1158 razor_set_unref(system);
1159 razor_root_close(root);
1160 razor_atomic_destroy(atomic);
1166 razor_transaction_resolve(trans);
1167 if (razor_transaction_describe(trans) > 0) {
1168 razor_transaction_destroy(trans);
1169 razor_set_unref(upstream);
1170 razor_set_unref(system);
1171 razor_root_close(root);
1172 razor_atomic_destroy(atomic);
1177 if (razor_atomic_create_dir(atomic, "rpms",
1178 S_IRWXU | S_IRWXG | S_IRWXO)) {
1179 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1180 razor_transaction_destroy(trans);
1181 razor_set_unref(upstream);
1182 razor_set_unref(system);
1183 razor_root_close(root);
1184 razor_atomic_destroy(atomic);
1188 next = razor_transaction_commit(trans);
1190 if (download_packages(system, next) < 0) {
1191 razor_set_unref(next);
1192 razor_transaction_destroy(trans);
1193 razor_set_unref(upstream);
1194 razor_set_unref(system);
1195 razor_root_close(root);
1196 razor_atomic_destroy(atomic);
1200 ii = razor_set_create_install_iterator(system, next);
1202 retval = update_packages(trans, ii, system, next, atomic, relocations,
1203 UPDATE_PASS_PRE_REMOVE);
1205 fprintf(stderr, "%s aborted\n",
1206 do_update ? "Update" : "Install");
1208 update_packages(trans, ii, system, next, atomic, relocations,
1211 razor_root_update(root, next);
1213 razor_set_unref(upstream);
1215 (void)razor_root_commit(root);
1216 retval = razor_atomic_commit(atomic);
1218 fprintf(stderr, "%s\n",
1219 razor_atomic_get_error_msg(atomic));
1221 (void)update_packages(trans, ii, system, next, atomic,
1223 UPDATE_PASS_POST_INSTALL);
1226 razor_transaction_destroy(trans);
1228 razor_relocations_destroy(relocations);
1229 razor_install_iterator_destroy(ii);
1231 razor_atomic_destroy(atomic);
1233 razor_set_unref(next);
1234 razor_set_unref(system);
1240 command_update(int argc, const char *argv[])
1242 return command_install_or_update(argc, argv, 1);
1246 command_install(int argc, const char *argv[])
1248 return command_install_or_update(argc, argv, 0);
1252 command_init(int argc, const char *argv[])
1254 return razor_root_create(install_root);
1258 command_download(int argc, const char *argv[])
1260 struct razor_atomic *atomic;
1261 struct razor_set *set;
1262 struct razor_package_iterator *pi;
1263 struct razor_package *package;
1264 const char *pattern = argv[0], *name, *version, *arch;
1265 char url[256], file[256];
1268 atomic = razor_atomic_open("Download packages");
1270 if (razor_atomic_create_dir(atomic, "rpms",
1271 S_IRWXU | S_IRWXG | S_IRWXO)) {
1272 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1273 razor_atomic_destroy(atomic);
1277 set = razor_set_open(rawhide_repo_filename, atomic);
1279 if (razor_atomic_commit(atomic)) {
1280 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1281 razor_atomic_destroy(atomic);
1284 razor_atomic_destroy(atomic);
1286 pi = razor_package_iterator_create(set);
1287 while (razor_package_iterator_next(pi, &package,
1288 RAZOR_DETAIL_NAME, &name,
1289 RAZOR_DETAIL_VERSION, &version,
1290 RAZOR_DETAIL_ARCH, &arch,
1291 RAZOR_DETAIL_LAST)) {
1292 if (pattern && fnmatch(pattern, name, 0) != 0)
1296 snprintf(url, sizeof url,
1297 "%s/Packages/%s-%s.%s.rpm",
1298 yum_url, name, version, arch);
1299 snprintf(file, sizeof file,
1300 "rpms/%s-%s.%s.rpm", name, version, arch);
1301 download_if_missing(url, file);
1303 razor_package_iterator_destroy(pi);
1304 razor_set_unref(set);
1307 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
1308 else if (matches == 1)
1309 fprintf(stderr, "downloaded 1 package\n");
1311 fprintf(stderr, "downloaded %d packages\n", matches);
1317 command_info(int argc, const char *argv[])
1319 struct razor_atomic *atomic;
1320 struct razor_set *set;
1321 struct razor_package_iterator *pi;
1322 struct razor_package *package;
1323 const char *pattern = argv[0], *name, *version, *arch;
1324 const char *summary, *description, *url, *license;
1326 atomic = razor_atomic_open("Package info");
1327 set = razor_root_open_read_only(install_root, atomic);
1329 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1330 razor_atomic_destroy(atomic);
1334 pi = razor_package_iterator_create(set);
1335 while (razor_package_iterator_next(pi, &package,
1336 RAZOR_DETAIL_NAME, &name,
1337 RAZOR_DETAIL_VERSION, &version,
1338 RAZOR_DETAIL_ARCH, &arch,
1339 RAZOR_DETAIL_LAST)) {
1340 if (pattern && fnmatch(pattern, name, 0) != 0)
1343 razor_package_get_details (set, package,
1344 RAZOR_DETAIL_SUMMARY, &summary,
1345 RAZOR_DETAIL_DESCRIPTION, &description,
1346 RAZOR_DETAIL_URL, &url,
1347 RAZOR_DETAIL_LICENSE, &license,
1350 printf ("Name: %s\n", name);
1351 printf ("Arch: %s\n", arch);
1352 printf ("Version: %s\n", version);
1353 printf ("URL: %s\n", url);
1354 printf ("License: %s\n", license);
1355 printf ("Summary: %s\n", summary);
1356 printf ("Description:\n");
1357 printf ("%s\n", description);
1360 razor_package_iterator_destroy(pi);
1361 razor_set_unref(set);
1362 razor_atomic_destroy(atomic);
1367 #define SEARCH_MAX 256
1370 command_search(int argc, const char *argv[])
1372 struct razor_atomic *atomic;
1373 struct razor_set *set;
1374 struct razor_package_iterator *pi;
1375 struct razor_package *package;
1376 char pattern[SEARCH_MAX];
1377 const char *name, *version, *arch;
1378 const char *summary, *description, *url, *license;
1381 fprintf(stderr, "must specify a search term\n");
1385 snprintf(pattern, sizeof pattern, "*%s*", argv[0]);
1387 atomic = razor_atomic_open("Search packages");
1388 set = razor_set_open(rawhide_repo_filename, atomic);
1389 if (set == NULL || razor_atomic_commit(atomic)) {
1390 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1391 razor_atomic_destroy(atomic);
1394 razor_atomic_destroy(atomic);
1396 pi = razor_package_iterator_create(set);
1397 while (razor_package_iterator_next(pi, &package,
1398 RAZOR_DETAIL_NAME, &name,
1399 RAZOR_DETAIL_VERSION, &version,
1400 RAZOR_DETAIL_ARCH, &arch,
1401 RAZOR_DETAIL_SUMMARY, &summary,
1402 RAZOR_DETAIL_DESCRIPTION, &description,
1403 RAZOR_DETAIL_URL, &url,
1404 RAZOR_DETAIL_LICENSE, &license,
1405 RAZOR_DETAIL_LAST)) {
1406 if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
1407 !fnmatch(pattern, url, FNM_CASEFOLD) ||
1408 !fnmatch(pattern, summary, FNM_CASEFOLD) ||
1409 !fnmatch(pattern, description, FNM_CASEFOLD))
1410 printf("%s-%s.%s: %s\n", name, version, arch, summary);
1412 razor_package_iterator_destroy(pi);
1413 razor_set_unref(set);
1420 const char *description;
1421 int (*func)(int argc, const char *argv[]);
1422 } razor_commands[] = {
1423 { "list", "list all packages", command_list },
1424 { "list-requires", "list all requires for the given package", command_list_requires },
1425 { "list-provides", "list all provides for the given package", command_list_provides },
1426 { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
1427 { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
1428 { "list-scripts", "list all scripts for the given package", command_list_scripts },
1429 { "list-files", "list files for package set", command_list_files },
1430 { "list-file-packages", "list packages owning file", command_list_file_packages },
1431 { "list-package-files", "list files in package", command_list_package_files },
1432 { "what-requires", "list the packages that have the given requires", command_what_requires },
1433 { "what-provides", "list the packages that have the given provides", command_what_provides },
1434 { "import-yum", "import yum metadata files", command_import_yum },
1436 { "import-rpmdb", "import the system rpm database", command_import_rpmdb },
1438 { "import-rpms", "import rpms from the given directory", command_import_rpms },
1439 { "update", "update all or specified packages", command_update },
1440 { "remove", "remove specified packages", command_remove },
1441 { "diff", "show diff between two package sets", command_diff },
1442 { "install", "install rpm", command_install },
1443 { "init", "init razor root", command_init },
1444 { "download", "download packages", command_download },
1445 { "info", "display package details", command_info },
1446 { "search", "search package details", command_search }
1455 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1456 printf(" %-20s%s\n",
1457 razor_commands[i].name, razor_commands[i].description);
1463 main(int argc, const char *argv[])
1468 repo = getenv("RAZOR_REPO");
1470 repo_filename = repo;
1472 root = getenv("RAZOR_ROOT");
1474 install_root = root;
1476 yum_url = getenv("YUM_URL");
1477 if (yum_url == NULL)
1480 if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
1481 razor_disable_root_name_checks(1);
1486 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1487 if (strcmp(razor_commands[i].name, argv[1]) == 0)
1488 return razor_commands[i].func(argc - 2, argv + 2);