2 * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
3 * Copyright (C) 2008 Red Hat, Inc
4 * Copyright (C) 2009, 2011-2012, 2014, 2016 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.
40 #include <curl/curl.h>
42 #if !defined(HAVE_CURL) && !defined(MSWIN_API)
51 static const char system_repo_filename[] = "system.rzdb";
52 static const char next_repo_filename[] = "system-next.rzdb";
53 static const char rawhide_repo_uri[] = "file:rawhide.rzdb";
54 static const char *install_root = "";
55 static const char *repo_filename = system_repo_filename;
56 static const char *yum_url;
66 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
69 update_packages(struct razor_transaction *trans,
70 struct razor_install_iterator *ii, struct razor_set *system,
71 struct razor_set *next, struct razor_atomic *atomic,
72 struct razor_relocations *relocations,
73 enum razor_stage_type stage);
75 update_system(struct razor_root *root, struct razor_relocations *relocations,
76 struct razor_transaction *trans, struct razor_set *next,
79 static int command_help(int argc, char * const argv[]);
86 char *arg_description;
90 razor_usage(const char *command, int n_options, struct razor_option *options,
91 const char *parameter_string)
93 int i, help_printed = FALSE;
96 printf("Usage: razor %s [options] %s\n", command, parameter_string);
97 printf("(Specify the --help global option for a list of other "
99 printf("\nOptions:\n");
101 for(i = 0; i < n_options; i++) {
102 if (!help_printed && strcmp(options[i].name, "help") > 0) {
104 "Show this help message and exit\n");
108 if (options[i].has_arg != no_argument)
109 snprintf(buf, sizeof(buf), "%s=%s", options[i].name,
110 options[i].arg_description);
112 strncpy(buf, options[i].name, sizeof(buf));
115 printf(" --%-18s%s\n", buf, options[i].description);
120 "Show this help message and exit\n");
127 * Returns: The next option found or -2 on handled or -1 on error
128 * or 0 on end of option list.
131 razor_getopt(int argc, char * const argv[], int n_options,
132 struct razor_option *options, const char *parameter_string,
135 int i, opt, do_help = 0, retval;
136 struct option *longopts;
138 longopts = calloc((n_options + 2), sizeof(*longopts));
140 for(i = 0; i < n_options; i++) {
141 longopts[i].name = options[i].name;
142 longopts[i].has_arg = options[i].has_arg;
143 longopts[i].flag = &retval;
144 longopts[i].val = options[i].val;
147 longopts[i].name = "help";
148 longopts[i].has_arg = no_argument;
149 longopts[i].flag = &do_help;
150 longopts[i].val = TRUE;
154 opt = getopt_long(argc, (char **)argv, "+", longopts, NULL);
160 razor_usage(argv[0], n_options, options,
172 razor_usage(argv[0], n_options, options,
181 static struct razor_package_iterator *
182 create_iterator_from_argv(struct razor_set *set, int argc, char * const argv[])
184 struct razor_package_query *query;
185 struct razor_package_iterator *iter;
186 struct razor_package *package;
187 const char *name, *pattern;
191 return razor_package_iterator_create(set);
193 query = razor_package_query_create(set);
195 for (i = 0; i < argc; i++) {
196 iter = razor_package_iterator_create(set);
199 while (razor_package_iterator_next(iter, &package,
200 RAZOR_DETAIL_NAME, &name,
201 RAZOR_DETAIL_LAST)) {
202 if (fnmatch(pattern, name, 0) != 0)
205 razor_package_query_add_package(query, package);
208 razor_package_iterator_destroy(iter);
212 "no package matches \"%s\"\n", pattern);
215 return razor_package_query_finish(query);
218 #define LIST_PACKAGES_ONLY_NAMES 0x01
221 list_packages(struct razor_package_iterator *iter, uint32_t flags)
223 struct razor_package *package;
224 const char *name, *version, *arch;
226 while (razor_package_iterator_next(iter, &package,
227 RAZOR_DETAIL_NAME, &name,
228 RAZOR_DETAIL_VERSION, &version,
229 RAZOR_DETAIL_ARCH, &arch,
230 RAZOR_DETAIL_LAST)) {
231 if (flags & LIST_PACKAGES_ONLY_NAMES)
232 printf("%s\n", name);
234 printf("%s-%s.%s\n", name, version, arch);
239 command_list(int argc, char * const argv[])
242 struct razor_package_iterator *pi;
243 struct razor_error *error = NULL;
244 struct razor_set *set;
249 static struct razor_option options[] = {
250 { .name = "only-names", .has_arg = no_argument,
251 .val = opt_only_names,
252 .description = "Only list package names" },
256 opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
257 "pattern ...", NULL);
264 flags |= LIST_PACKAGES_ONLY_NAMES;
269 set = razor_root_open_read_only(install_root, &error);
271 fprintf(stderr, "%s\n", razor_error_get_msg(error));
272 razor_error_free(error);
276 pi = create_iterator_from_argv(set, argc - optind, argv + optind);
277 list_packages(pi, flags);
278 razor_package_iterator_destroy(pi);
279 razor_set_unref(set);
285 list_package_properties(struct razor_set *set,
286 struct razor_package *package, uint32_t type)
288 struct razor_property_iterator *pi;
289 struct razor_property *property;
290 const char *name, *version;
293 pi = razor_property_iterator_create(set, package);
294 while (razor_property_iterator_next(pi, &property,
295 &name, &flags, &version)) {
296 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
299 if (version[0] != '\0')
301 razor_property_relation_to_string(property),
304 if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
306 if (flags & RAZOR_PROPERTY_PRE)
308 if (flags & RAZOR_PROPERTY_POST)
310 if (flags & RAZOR_PROPERTY_PREUN)
312 if (flags & RAZOR_PROPERTY_POSTUN)
318 razor_property_iterator_destroy(pi);
322 list_properties(int argc, char * const argv[], uint32_t type)
324 struct razor_set *set;
325 struct razor_error *error = NULL;
326 struct razor_package *package;
327 struct razor_package_iterator *pi;
328 const char *name, *version, *arch;
330 switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
337 set = razor_root_open_read_only(install_root, &error);
339 fprintf(stderr, "%s\n", razor_error_get_msg(error));
340 razor_error_free(error);
344 pi = create_iterator_from_argv(set, argc - optind, argv + optind);
345 while (razor_package_iterator_next(pi, &package,
346 RAZOR_DETAIL_NAME, &name,
347 RAZOR_DETAIL_VERSION, &version,
348 RAZOR_DETAIL_ARCH, &arch,
350 list_package_properties(set, package, type);
351 razor_package_iterator_destroy(pi);
352 razor_set_unref(set);
358 command_list_requires(int argc, char * const argv[])
360 return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES);
364 command_list_provides(int argc, char * const argv[])
366 return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES);
370 command_list_obsoletes(int argc, char * const argv[])
372 return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES);
376 command_list_conflicts(int argc, char * const argv[])
378 return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS);
382 command_list_scripts(int argc, char * const argv[])
384 struct razor_set *set;
385 struct razor_error *error = NULL;
386 struct razor_package *package;
387 struct razor_package_iterator *pi;
388 const char *preunprog, *preun, *postunprog, *postun;
390 switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
397 set = razor_root_open_read_only(install_root, &error);
399 fprintf(stderr, "%s\n", razor_error_get_msg(error));
400 razor_error_free(error);
404 pi = create_iterator_from_argv(set, argc - optind, argv + optind);
405 while (razor_package_iterator_next(pi, &package,
406 RAZOR_DETAIL_PREUNPROG, &preunprog,
407 RAZOR_DETAIL_PREUN, &preun,
408 RAZOR_DETAIL_POSTUNPROG, &postunprog,
409 RAZOR_DETAIL_POSTUN, &postun,
410 RAZOR_DETAIL_LAST)) {
411 if (preun && *preun) {
412 printf("preuninstall scriptlet");
413 if (preunprog && *preunprog)
414 printf(" (using %s)",preunprog);
415 printf(":\n%s\n",preun);
417 if (postun && *postun) {
418 printf("postuninstall scriptlet");
419 if (postunprog && *postunprog)
420 printf(" (using %s)",postunprog);
421 printf(":\n%s\n",postun);
424 razor_package_iterator_destroy(pi);
425 razor_set_unref(set);
431 command_list_files(int argc, char * const argv[])
433 struct razor_error *error = NULL;
434 struct razor_set *set;
436 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
443 if (argc - optind > 1) {
444 razor_usage(argv[0], 0, NULL, "[pattern]");
448 set = razor_root_open_read_only(install_root, &error);
450 fprintf(stderr, "%s\n", razor_error_get_msg(error));
451 razor_error_free(error);
455 razor_set_list_files(set, argv[optind]);
456 razor_set_unref(set);
462 command_list_file_packages(int argc, char * const argv[])
464 struct razor_error *error = NULL;
465 struct razor_set *set;
466 struct razor_package_iterator *pi;
468 switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
475 if (argc - optind != 1) {
476 razor_usage(argv[0], 0, NULL, "pattern");
480 set = razor_root_open_read_only(install_root, &error);
482 fprintf(stderr, "%s\n", razor_error_get_msg(error));
483 razor_error_free(error);
487 pi = razor_package_iterator_create_for_file(set, argv[optind]);
488 list_packages(pi, 0);
489 razor_package_iterator_destroy(pi);
491 razor_set_unref(set);
497 command_list_package_files(int argc, char * const argv[])
499 struct razor_error *error = NULL;
500 struct razor_set *set;
501 struct razor_package_iterator *pi;
502 struct razor_package *package;
503 const char *name, *version, *arch;
505 switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
512 set = razor_root_open_read_only(install_root, &error);
514 fprintf(stderr, "%s\n", razor_error_get_msg(error));
515 razor_error_free(error);
519 pi = create_iterator_from_argv(set, argc - optind, argv + optind);
520 while (razor_package_iterator_next(pi, &package,
521 RAZOR_DETAIL_NAME, &name,
522 RAZOR_DETAIL_VERSION, &version,
523 RAZOR_DETAIL_ARCH, &arch,
525 razor_set_list_package_files(set, package);
526 razor_package_iterator_destroy(pi);
528 razor_set_unref(set);
534 list_property_packages(const char *ref_name,
535 const char *ref_version,
538 struct razor_error *error = NULL;
539 struct razor_set *set;
540 struct razor_property *property;
541 struct razor_property_iterator *prop_iter;
542 struct razor_package_iterator *pkg_iter;
543 const char *name, *version;
546 set = razor_root_open_read_only(install_root, &error);
548 fprintf(stderr, "%s\n", razor_error_get_msg(error));
549 razor_error_free(error);
553 prop_iter = razor_property_iterator_create(set, NULL);
554 while (razor_property_iterator_next(prop_iter, &property,
555 &name, &flags, &version)) {
556 if (strcmp(ref_name, name) != 0)
559 (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
560 strcmp(ref_version, version) != 0)
562 if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
566 razor_package_iterator_create_for_property(set,
568 list_packages(pkg_iter, 0);
569 razor_package_iterator_destroy(pkg_iter);
571 razor_property_iterator_destroy(prop_iter);
573 razor_set_unref(set);
579 command_what_requires(int argc, char * const argv[])
581 switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
589 if (argc - optind < 1 || argc - optind > 2) {
590 razor_usage(argv[0], 0, NULL, "name [version-release]");
594 return list_property_packages(argv[optind], argv[optind + 1],
595 RAZOR_PROPERTY_REQUIRES);
599 command_what_provides(int argc, char * const argv[])
601 switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]",
609 if (argc - optind < 1 || argc - optind > 2) {
610 razor_usage(argv[0], 0, NULL, "name [version-release]");
614 return list_property_packages(argv[optind], argv[optind + 1],
615 RAZOR_PROPERTY_PROVIDES);
619 struct get_contents_with_curl_baton {
625 get_contents_with_curl_callback(void *contents, size_t size, size_t nmemb,
628 size_t nb = size * nmemb;
629 struct get_contents_with_curl_baton *baton = data;
631 baton->buf = realloc(baton->buf, baton->buflen + nb);
633 fprintf(stderr, "Not enough memory to read file\n");
637 memcpy((char *)baton->buf + baton->buflen, contents, nb);
643 static void *get_contents_with_curl(const char *uri, size_t *length,
644 int private, struct razor_error **error)
649 struct get_contents_with_curl_baton baton = {0,};
651 curl = curl_easy_init();
653 razor_set_error(error, RAZOR_GENERAL_ERROR,
654 RAZOR_GENERAL_ERROR_FAILED, uri,
655 "Failed to initialize libcurl");
659 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
660 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
661 get_contents_with_curl_callback);
662 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&baton);
663 curl_easy_setopt(curl, CURLOPT_URL, uri);
664 curl_easy_setopt(curl, CURLOPT_USERAGENT, "razor/" VERSION);
665 res = curl_easy_perform(curl);
666 curl_easy_cleanup(curl);
668 if (res != CURLE_OK) {
669 razor_set_error(error, RAZOR_GENERAL_ERROR,
670 RAZOR_GENERAL_ERROR_FAILED, uri, errbuf);
675 *length = baton.buflen;
679 int free_contents_with_curl(void *addr, size_t length)
685 static void init_uri_handler(void)
688 struct razor_uri_vtable uri_vtable={0,};
689 uri_vtable.structure_size=sizeof(uri_vtable);
690 uri_vtable.get_contents=get_contents_with_curl;
691 uri_vtable.free_contents=free_contents_with_curl;
692 razor_uri_set_vtable(NULL, &uri_vtable, NULL);
697 download_if_missing(const char *uri, const char *file)
703 struct razor_error *error = NULL;
706 if (stat(file, &buf) >= 0)
709 contents = razor_uri_get_contents(uri, &length, 0, &error);
712 fprintf(stderr, "%s: %s\n", uri, razor_error_get_msg(error));
713 razor_error_free(error);
717 fp = fopen(file, "wb");
720 razor_uri_free_contents(contents, length);
724 if (fwrite(contents, 1, length, fp) != length) {
730 razor_uri_free_contents(contents, length);
735 #define YUM_URL "http://download.fedora.redhat.com" \
736 "/pub/fedora/linux/development/i386/os"
739 command_import_yum(int argc, char * const argv[])
742 struct razor_set *set;
743 struct razor_atomic *atomic;
745 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
752 if (argc - optind > 0) {
753 razor_usage(argv[0], 0, NULL, "");
757 printf("importing from '%s'.\n", yum_url);
759 set = razor_set_create_from_yum(yum_url);
762 atomic = razor_atomic_open("Yum import repository");
763 razor_set_write(set, atomic, rawhide_repo_uri, RAZOR_SECTION_ALL);
764 retval = razor_atomic_commit(atomic);
765 razor_set_unref(set);
767 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
769 printf("wrote %s\n", rawhide_repo_uri);
770 razor_atomic_destroy(atomic);
777 command_import_rpmdb(int argc, char * const argv[])
779 struct razor_set *set;
780 struct razor_root *root;
781 struct razor_error *error = NULL;
782 struct razor_atomic *atomic;
785 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
792 if (argc - optind > 0) {
793 razor_usage(argv[0], 0, NULL, "");
797 root = razor_root_open(install_root, &error);
799 fprintf(stderr, "%s\n", razor_error_get_msg(error));
800 razor_error_free(error);
804 set = razor_set_create_from_rpmdb();
808 atomic = razor_atomic_open("Import RPM database");
810 retval = razor_root_update(root, set, atomic);
813 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
815 razor_atomic_destroy(atomic);
817 razor_root_close(root);
824 mark_packages_for_update(struct razor_transaction *trans,
825 struct razor_set *set, const char *pattern)
827 struct razor_package_iterator *pi;
828 struct razor_package *package;
832 pi = razor_package_iterator_create(set);
833 while (razor_package_iterator_next(pi, &package,
834 RAZOR_DETAIL_NAME, &name,
835 RAZOR_DETAIL_LAST)) {
836 if (pattern && fnmatch(pattern, name, 0) == 0) {
837 razor_transaction_update_package(trans, package);
841 razor_package_iterator_destroy(pi);
847 mark_packages_for_removal(struct razor_transaction *trans,
848 struct razor_set *set, const char *pattern)
850 struct razor_package_iterator *pi;
851 struct razor_package *package;
855 pi = razor_package_iterator_create(set);
856 while (razor_package_iterator_next(pi, &package,
857 RAZOR_DETAIL_NAME, &name,
858 RAZOR_DETAIL_LAST)) {
859 if (pattern && fnmatch(pattern, name, 0) == 0) {
860 razor_transaction_remove_package(trans, package);
864 razor_package_iterator_destroy(pi);
870 command_remove(int argc, char * const argv[])
872 struct razor_set *system, *upstream, *next;
873 struct razor_transaction *trans;
874 struct razor_error *error = NULL;
875 struct razor_root *root;
878 switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
885 root = razor_root_open(install_root, &error);
887 fprintf(stderr, "%s\n", razor_error_get_msg(error));
888 razor_error_free(error);
892 system = razor_root_get_system_set(root);
893 upstream = razor_set_create_without_root();
894 trans = razor_transaction_create(system, upstream);
895 razor_set_unref(upstream);
896 for (i = optind; i < argc; i++) {
897 if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
898 fprintf(stderr, "no match for %s\n", argv[i]);
899 razor_transaction_destroy(trans);
900 razor_root_close(root);
905 razor_transaction_resolve(trans);
906 retval = razor_transaction_describe(trans);
908 razor_transaction_destroy(trans);
909 razor_root_close(root);
913 next = razor_transaction_commit(trans);
915 retval = update_system(root, NULL, trans, next, "Remove");
917 razor_transaction_destroy(trans);
918 razor_root_close(root);
919 razor_set_unref(next);
925 print_diff(enum razor_diff_action action,
926 struct razor_package *package,
932 if (action == RAZOR_DIFF_ACTION_ADD)
933 printf("install %s-%s.%s\n", name, version, arch);
934 if (action == RAZOR_DIFF_ACTION_REMOVE)
935 printf("remove %s-%s.%s\n", name, version, arch);
939 command_diff(int argc, char * const argv[])
941 struct razor_error *error = NULL;
942 struct razor_set *set, *updated;
944 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
951 if (argc - optind > 0) {
952 razor_usage(argv[0], 0, NULL, "");
956 set = razor_root_open_read_only(install_root, &error);
958 updated = razor_set_open(rawhide_repo_uri, 0, &error);
961 if (updated == NULL) {
962 fprintf(stderr, "%s\n", razor_error_get_msg(error));
963 razor_error_free(error);
965 razor_set_unref(set);
969 razor_set_diff(set, updated, print_diff, NULL);
971 razor_set_unref(set);
972 razor_set_unref(updated);
978 command_import_rpms(int argc, char * const argv[])
982 struct razor_importer *importer;
983 struct razor_set *set;
984 struct razor_rpm *rpm;
985 struct razor_error *error=NULL;
986 struct razor_atomic *atomic;
987 int len, imported_count = 0;
992 switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) {
999 if (argc - optind != 1) {
1000 razor_usage(argv[0], 0, NULL, "dir");
1004 dirname = argv[optind];
1006 dir = opendir(dirname);
1008 fprintf(stderr, "couldn't read dir %s\n", dirname);
1012 importer = razor_importer_create();
1014 while (de = readdir(dir), de != NULL) {
1015 len = strlen(de->d_name);
1016 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
1018 snprintf(filename, sizeof filename,
1019 "%s/%s", dirname, de->d_name);
1020 rpm = razor_rpm_open(filename, &error);
1022 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1023 razor_error_free(error);
1027 if (razor_importer_add_rpm(importer, rpm)) {
1028 fprintf(stderr, "couldn't import %s\n", filename);
1031 razor_rpm_close(rpm);
1033 printf("\rimporting %d", ++imported_count);
1038 razor_importer_destroy(importer);
1042 printf("\nsaving\n");
1043 set = razor_importer_finish(importer);
1045 atomic = razor_atomic_open("Update system database");
1046 razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
1047 razor_set_unref(set);
1048 retval = razor_atomic_commit(atomic);
1050 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1052 printf("wrote %s\n", repo_filename);
1053 razor_atomic_destroy(atomic);
1059 rpm_filename(const char *name, const char *version, const char *arch)
1064 v = strchr(version, ':');
1070 return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
1073 static struct razor_set *
1074 relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
1075 struct razor_relocations *relocations)
1078 struct razor_importer *importer;
1079 struct razor_property_iterator *prop_iter;
1080 struct razor_package_iterator *pkg_iter;
1081 struct razor_file_iterator *file_iter;
1082 struct razor_package *package;
1083 struct razor_property *property;
1084 struct razor_rpm *rpm;
1085 struct razor_error *error=NULL;
1086 const char *name, *version, *arch, *summary, *desc, *url, *license;
1087 const char *preunprog, *preun, *postunprog, *postun;
1088 const char *install_prefix;
1089 const char *const *prefixes;
1090 char *s, *uri, *filename;
1093 importer = razor_importer_create();
1094 pkg_iter = razor_package_iterator_create(set);
1096 while (razor_package_iterator_next(pkg_iter, &package,
1097 RAZOR_DETAIL_NAME, &name,
1098 RAZOR_DETAIL_VERSION, &version,
1099 RAZOR_DETAIL_ARCH, &arch,
1100 RAZOR_DETAIL_SUMMARY, &summary,
1101 RAZOR_DETAIL_DESCRIPTION, &desc,
1102 RAZOR_DETAIL_URL, &url,
1103 RAZOR_DETAIL_LICENSE, &license,
1104 RAZOR_DETAIL_PREUNPROG, &preunprog,
1105 RAZOR_DETAIL_PREUN, &preun,
1106 RAZOR_DETAIL_POSTUNPROG, &postunprog,
1107 RAZOR_DETAIL_POSTUN, &postun,
1108 RAZOR_DETAIL_LAST)) {
1109 filename = rpm_filename(name, version, arch);
1110 s = razor_concat("Packages/", filename, NULL);
1111 uri = razor_path_relative_to_uri(yum_url, s, NULL);
1114 rpm = razor_rpm_open(uri, &error);
1117 razor_atomic_propagate_error(atomic, error, NULL);
1118 razor_package_iterator_destroy(pkg_iter);
1119 razor_importer_destroy(importer);
1123 razor_relocations_set_rpm(relocations, rpm);
1125 razor_importer_begin_package(importer, name, version, arch);
1126 razor_importer_add_details(importer,
1127 summary, desc, url, license);
1129 razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
1131 for (i = 0; prefixes && prefixes[i]; i++) {
1132 install_prefix = razor_relocations_apply(relocations,
1134 razor_importer_add_install_prefix(importer,
1138 razor_rpm_close(rpm);
1140 prop_iter = razor_property_iterator_create(set, package);
1141 while (razor_property_iterator_next(prop_iter, &property,
1142 &name, &flags, &version))
1143 razor_importer_add_property(importer,
1144 name, flags, version);
1145 razor_property_iterator_destroy(prop_iter);
1147 file_iter = razor_file_iterator_create(set, package, 0);
1148 while (razor_file_iterator_next(file_iter, &name)) {
1149 name = razor_relocations_apply(relocations, name);
1150 razor_importer_add_file(importer, name);
1152 razor_file_iterator_destroy(file_iter);
1154 razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
1156 razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
1157 postunprog, postun);
1159 razor_importer_finish_package(importer);
1162 razor_package_iterator_destroy(pkg_iter);
1163 return razor_importer_finish(importer);
1167 install_package(struct razor_transaction *trans, struct razor_set *set,
1168 struct razor_atomic *atomic, struct razor_package *package,
1169 struct razor_relocations *relocations, int install_count,
1170 enum razor_stage_type stage)
1173 const char *name, *version, *arch;
1174 char *file, *s, *uri;
1175 struct razor_rpm *rpm;
1176 struct razor_error *error=NULL;
1178 razor_package_get_details(set, package,
1179 RAZOR_DETAIL_NAME, &name,
1180 RAZOR_DETAIL_VERSION, &version,
1181 RAZOR_DETAIL_ARCH, &arch,
1184 s = rpm_filename(name, version, arch);
1185 file = razor_concat("Packages/", s, NULL);
1187 uri = razor_path_relative_to_uri(yum_url, file, NULL);
1190 if (stage & RAZOR_STAGE_SCRIPTS_PRE)
1191 printf("install %s\n", uri);
1193 rpm = razor_rpm_open(uri, &error);
1196 razor_atomic_propagate_error(atomic, error, NULL);
1197 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1201 razor_rpm_set_relocations(rpm, relocations);
1202 razor_transaction_fixup_package(trans, package, rpm);
1203 retval = razor_rpm_install(rpm, atomic, install_root, install_count,
1206 s = rpm_filename(name, version, arch);
1207 fprintf(stderr, "%s: %s\n", s,
1208 razor_atomic_get_error_msg(atomic));
1211 razor_rpm_close(rpm);
1216 * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
1217 * is met (in which case the action is consumed).
1220 update_packages(struct razor_transaction *trans,
1221 struct razor_install_iterator *ii, struct razor_set *system,
1222 struct razor_set *next, struct razor_atomic *atomic,
1223 struct razor_relocations *relocations,
1224 enum razor_stage_type stage)
1226 struct razor_package *package;
1227 enum razor_install_action action;
1228 int retval = 0, count;
1230 while (!retval && razor_install_iterator_next(ii, &package, &action,
1232 if (action == RAZOR_INSTALL_ACTION_ADD) {
1233 if (install_package(trans, next, atomic, package,
1234 relocations, count, stage))
1236 } else if (action == RAZOR_INSTALL_ACTION_REMOVE) {
1237 if (razor_package_remove(system, next, atomic, package,
1238 install_root, count, stage))
1240 } else if (action == RAZOR_INSTALL_ACTION_COMMIT)
1248 update_system(struct razor_root *root, struct razor_relocations *relocations,
1249 struct razor_transaction *trans, struct razor_set *next,
1252 struct razor_set *system, *set;
1253 struct razor_atomic *atomic;
1254 struct razor_install_iterator *ii;
1259 description = razor_concat(verb, " packages", NULL);
1261 system = razor_set_ref(razor_root_get_system_set(root));
1263 ii = razor_set_create_install_iterator(system, next);
1266 pos = razor_install_iterator_tell(ii);
1268 atomic = razor_atomic_open(description);
1270 r = update_packages(trans, ii, system, next, atomic,
1271 relocations, RAZOR_STAGE_SCRIPTS_PRE);
1273 fprintf(stderr, "%s aborted\n", verb);
1276 razor_install_iterator_seek(ii, pos);
1277 r = update_packages(trans, ii, system, next, atomic,
1278 relocations, RAZOR_STAGE_FILES);
1281 set = razor_install_iterator_commit_set(ii);
1282 razor_root_update(root, set, atomic);
1283 razor_set_unref(set);
1285 razor_root_update(root, next, atomic);
1287 retval = razor_atomic_commit(atomic);
1289 fprintf(stderr, "%s\n",
1290 razor_atomic_get_error_msg(atomic));
1292 razor_install_iterator_seek(ii, pos);
1293 update_packages(trans, ii, system, next,
1294 atomic, relocations,
1295 RAZOR_STAGE_SCRIPTS_POST);
1299 razor_atomic_destroy(atomic);
1300 } while(!retval && r == 1);
1302 razor_install_iterator_destroy(ii);
1304 razor_set_unref(system);
1312 command_install_or_update(int argc, char * const argv[], int do_update)
1314 struct razor_relocations *relocations = NULL;
1315 struct razor_set *system, *upstream, *next, *set;
1316 struct razor_transaction *trans;
1317 struct razor_error *error = NULL;
1318 struct razor_atomic *atomic;
1319 struct razor_root *root;
1320 int opt, i, retval = 0, len, dependencies = 1;
1324 opt_no_dependencies = 1,
1327 static struct razor_option options[] = {
1328 { .name = "no-dependencies", .has_arg = no_argument,
1329 .val = opt_no_dependencies,
1330 .description = "Do not verify package dependencies" },
1331 { .name = "relocate", .has_arg = required_argument,
1332 .val = opt_relocate,
1333 .description = "Relocate files from path OLD to NEW",
1334 .arg_description = "OLD=NEW" },
1338 opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
1345 case opt_no_dependencies:
1349 if (strchr(arg, '=') == NULL) {
1350 razor_usage(argv[0],
1351 ARRAY_SIZE(options),
1352 options, "rpm ...");
1355 len = strchr(arg, '=') - arg;
1356 oldpath = malloc(len + 1);
1357 strncpy(oldpath, arg, len);
1358 oldpath[len] = '\0';
1360 relocations = razor_relocations_create();
1361 razor_relocations_add(relocations, oldpath,
1368 upstream = razor_set_open(rawhide_repo_uri, 0, &error);
1369 if (upstream == NULL) {
1370 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1371 razor_error_free(error);
1373 razor_relocations_destroy(relocations);
1378 atomic = razor_atomic_open("Update packages");
1380 atomic = razor_atomic_open("Install packages");
1383 set = relocate_packages(upstream, atomic, relocations);
1385 fprintf(stderr, "%s\n",
1386 razor_atomic_get_error_msg(atomic));
1387 razor_atomic_destroy(atomic);
1388 razor_set_unref(upstream);
1391 razor_set_unref(upstream);
1395 root = razor_root_open(install_root, &error);
1397 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1398 razor_error_free(error);
1399 razor_atomic_destroy(atomic);
1400 razor_set_unref(upstream);
1402 razor_relocations_destroy(relocations);
1406 system = razor_root_get_system_set(root);
1407 trans = razor_transaction_create(system, upstream);
1409 if (optind == argc && do_update)
1410 razor_transaction_update_all(trans);
1411 for (i = optind; i < argc; i++) {
1413 mark_packages_for_update(trans, system, argv[i]))
1415 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
1416 fprintf(stderr, "no package matched %s\n", argv[i]);
1417 razor_transaction_destroy(trans);
1418 razor_root_close(root);
1419 razor_set_unref(upstream);
1420 razor_atomic_destroy(atomic);
1422 razor_relocations_destroy(relocations);
1428 razor_transaction_resolve(trans);
1429 if (razor_transaction_describe(trans) > 0) {
1430 razor_transaction_destroy(trans);
1431 razor_set_unref(upstream);
1432 razor_root_close(root);
1433 razor_atomic_destroy(atomic);
1435 razor_relocations_destroy(relocations);
1440 razor_atomic_destroy(atomic);
1442 next = razor_transaction_commit(trans);
1444 retval = update_system(root, relocations, trans, next,
1445 do_update ? "Update" : "Install");
1447 razor_set_unref(upstream);
1448 razor_root_close(root);
1450 razor_transaction_destroy(trans);
1452 razor_relocations_destroy(relocations);
1454 razor_set_unref(next);
1460 command_update(int argc, char * const argv[])
1462 return command_install_or_update(argc, argv, 1);
1466 command_install(int argc, char * const argv[])
1468 return command_install_or_update(argc, argv, 0);
1472 command_init(int argc, char * const argv[])
1475 struct razor_error *error = NULL;
1477 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
1484 if (argc - optind > 0) {
1485 razor_usage(argv[0], 0, NULL, "");
1489 retval = razor_root_create(install_root, &error);
1491 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1492 razor_error_free(error);
1494 printf("Created install root\n");
1500 command_download(int argc, char * const argv[])
1502 struct razor_error *error = NULL;
1503 struct razor_atomic *atomic;
1504 struct razor_set *set;
1505 struct razor_package_iterator *pi;
1506 struct razor_package *package;
1507 const char *pattern, *name, *version, *arch;
1508 char *url, *file, *s, filename[256];
1511 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
1518 if (argc - optind > 1) {
1519 razor_usage(argv[0], 0, NULL, "[pattern]");
1523 pattern = argv[optind];
1525 set = razor_set_open(rawhide_repo_uri, 0, &error);
1527 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1528 razor_error_free(error);
1532 atomic = razor_atomic_open("Download packages");
1534 if (razor_atomic_create_dir(atomic, "file:rpms",
1535 S_IRWXU | S_IRWXG | S_IRWXO)) {
1536 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1537 razor_atomic_destroy(atomic);
1541 if (razor_atomic_commit(atomic)) {
1542 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1543 razor_atomic_destroy(atomic);
1546 razor_atomic_destroy(atomic);
1548 pi = razor_package_iterator_create(set);
1549 while (razor_package_iterator_next(pi, &package,
1550 RAZOR_DETAIL_NAME, &name,
1551 RAZOR_DETAIL_VERSION, &version,
1552 RAZOR_DETAIL_ARCH, &arch,
1553 RAZOR_DETAIL_LAST)) {
1554 if (pattern && fnmatch(pattern, name, 0) != 0)
1558 snprintf(filename, sizeof filename,
1559 "%s-%s.%s.rpm", name, version, arch);
1560 s = razor_concat("Packages/", filename, NULL);
1561 url = razor_path_relative_to_uri(yum_url, s, NULL);
1563 file = razor_concat("rpms/", filename, NULL);
1564 download_if_missing(url, file);
1568 razor_package_iterator_destroy(pi);
1569 razor_set_unref(set);
1572 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
1573 else if (matches == 1)
1574 fprintf(stderr, "downloaded 1 package\n");
1576 fprintf(stderr, "downloaded %d packages\n", matches);
1582 command_dump(int argc, char * const argv[])
1584 struct razor_error *error = NULL;
1585 const char *filename;
1587 switch (razor_getopt(argc, argv, 0, NULL, "[filename]", NULL)) {
1594 if (argc - optind > 1) {
1595 razor_usage(argv[0], 0, NULL, "[filename]");
1599 filename = argv[optind];
1601 if (razor_dump_database(stdout, install_root, filename, &error)) {
1602 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1603 razor_error_free(error);
1611 command_info(int argc, char * const argv[])
1613 struct razor_error *error = NULL;
1614 struct razor_set *set;
1615 struct razor_package_iterator *pi;
1616 struct razor_package *package;
1617 struct razor_string_iterator *si;
1618 const char *pattern, *name, *version, *arch;
1619 const char *summary, *description, *url, *license;
1622 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
1629 if (argc - optind > 1) {
1630 razor_usage(argv[0], 0, NULL, "[pattern]");
1634 pattern = argv[optind];
1636 set = razor_root_open_read_only(install_root, &error);
1638 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1639 razor_error_free(error);
1643 pi = razor_package_iterator_create(set);
1644 while (razor_package_iterator_next(pi, &package,
1645 RAZOR_DETAIL_NAME, &name,
1646 RAZOR_DETAIL_VERSION, &version,
1647 RAZOR_DETAIL_ARCH, &arch,
1648 RAZOR_DETAIL_LAST)) {
1649 if (pattern && fnmatch(pattern, name, 0) != 0)
1652 printf ("Name: %s\n", name);
1653 printf ("Arch: %s\n", arch);
1654 printf ("Version: %s\n", version);
1656 si = razor_install_prefix_iterator_create(set, package);
1657 if (razor_string_iterator_next(si, &prefix)) {
1658 printf ("Relocations: %s\n", prefix);
1659 while (razor_string_iterator_next(si, &prefix))
1660 printf (" : %s\n", prefix);
1662 razor_string_iterator_destroy(si);
1664 razor_package_get_details (set, package,
1665 RAZOR_DETAIL_SUMMARY, &summary,
1666 RAZOR_DETAIL_DESCRIPTION, &description,
1667 RAZOR_DETAIL_URL, &url,
1668 RAZOR_DETAIL_LICENSE, &license,
1671 printf ("URL: %s\n", url);
1672 printf ("License: %s\n", license);
1673 printf ("Summary: %s\n", summary);
1674 printf ("Description:\n");
1675 printf ("%s\n", description);
1678 razor_package_iterator_destroy(pi);
1679 razor_set_unref(set);
1684 #define SEARCH_MAX 256
1687 command_search(int argc, char * const argv[])
1689 struct razor_error *error = NULL;
1690 struct razor_set *set;
1691 struct razor_package_iterator *pi;
1692 struct razor_package *package;
1693 char pattern[SEARCH_MAX];
1694 const char *name, *version, *arch;
1695 const char *summary, *description, *url, *license;
1697 switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
1705 razor_usage(argv[0], 0, NULL, "pattern");
1709 snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
1711 set = razor_set_open(rawhide_repo_uri, 0, &error);
1713 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1714 razor_error_free(error);
1718 pi = razor_package_iterator_create(set);
1719 while (razor_package_iterator_next(pi, &package,
1720 RAZOR_DETAIL_NAME, &name,
1721 RAZOR_DETAIL_VERSION, &version,
1722 RAZOR_DETAIL_ARCH, &arch,
1723 RAZOR_DETAIL_SUMMARY, &summary,
1724 RAZOR_DETAIL_DESCRIPTION, &description,
1725 RAZOR_DETAIL_URL, &url,
1726 RAZOR_DETAIL_LICENSE, &license,
1727 RAZOR_DETAIL_LAST)) {
1728 if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
1729 !fnmatch(pattern, url, FNM_CASEFOLD) ||
1730 !fnmatch(pattern, summary, FNM_CASEFOLD) ||
1731 !fnmatch(pattern, description, FNM_CASEFOLD))
1732 printf("%s-%s.%s: %s\n", name, version, arch, summary);
1734 razor_package_iterator_destroy(pi);
1735 razor_set_unref(set);
1742 const char *description;
1743 int (*func)(int argc, char * const argv[]);
1744 } razor_commands[] = {
1745 { "diff", "Show diff between two package sets", command_diff },
1746 { "download", "Download packages", command_download },
1747 { "dump", "Low-level database dump (for debugging)", command_dump },
1748 { "help", "List available commands", command_help },
1750 { "import-rpmdb", "Import the system rpm database",
1751 command_import_rpmdb },
1753 { "import-rpms", "Import rpms from the given directory",
1754 command_import_rpms },
1755 { "import-yum", "Import yum metadata files", command_import_yum },
1756 { "info", "Display package details", command_info },
1757 { "init", "Init razor root", command_init },
1758 { "install", "Install rpm", command_install },
1759 { "list", "List all packages", command_list },
1760 { "list-conflicts", "List all conflicts for the given package",
1761 command_list_conflicts },
1762 { "list-file-packages", "List packages owning file",
1763 command_list_file_packages },
1764 { "list-files", "List files for package set", command_list_files },
1765 { "list-obsoletes", "List all obsoletes for the given package",
1766 command_list_obsoletes },
1767 { "list-package-files", "List files in package",
1768 command_list_package_files },
1769 { "list-provides", "List all provides for the given package",
1770 command_list_provides },
1771 { "list-requires", "List all requires for the given package",
1772 command_list_requires },
1773 { "list-scripts", "List all scripts for the given package",
1774 command_list_scripts },
1775 { "remove", "Remove specified packages", command_remove },
1776 { "search", "Search package details", command_search },
1777 { "update", "Update all or specified packages", command_update },
1778 { "what-provides", "List the packages that have the given provides",
1779 command_what_provides },
1780 { "what-requires", "List the packages that have the given requires",
1781 command_what_requires },
1785 command_help(int argc, char * const argv[])
1789 printf("Available commands:\n");
1790 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1791 printf(" %-20s%s\n",
1792 razor_commands[i].name, razor_commands[i].description);
1793 printf("\nType \"razor --help\" for help about global options\n"
1794 "or \"razor <command> --help\" for help about a particular "
1795 "command's options.\n");
1801 main(int argc, char *argv[])
1804 int i, opt, main_optind;
1805 int do_help_commands = 0;
1813 struct option options[] = {
1814 { .name = "database", .has_arg = required_argument,
1815 .val = opt_database },
1816 { .name = "help", .has_arg = no_argument, .val = opt_help },
1817 { .name = "help-commands", .has_arg = no_argument,
1818 .flag = &do_help_commands, .val = TRUE },
1819 { .name = "root", .has_arg = required_argument,
1821 { .name = "url", .has_arg = required_argument, .val = opt_url },
1825 repo = getenv("RAZOR_REPO");
1827 repo_filename = repo;
1829 root = getenv("RAZOR_ROOT");
1831 install_root = root;
1833 yum_url = getenv("YUM_URL");
1834 if (yum_url == NULL)
1837 if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
1838 razor_disable_root_name_checks(1);
1843 while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
1846 razor_set_database_uri(optarg);
1850 printf("Usage: razor [global-options] command "
1851 "[command-options-and-arguments]\n\n");
1852 printf("Options:\n");
1854 "Show this help message and exit\n");
1855 printf(" --help-commands List commands\n");
1856 printf(" --database=URI "
1857 "Use alternative database\n");
1858 printf(" --root=URI "
1859 "Use URI as top level directory\n");
1860 printf(" --url=URI "
1861 "Use URI as upstream repository\n");
1862 return opt != opt_help;
1864 install_root = optarg;
1874 main_optind = optind;
1877 if (do_help_commands || argc - main_optind < 1) {
1878 command_help(argc - main_optind, argv + main_optind);
1884 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1885 if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
1886 return razor_commands[i].func(argc - main_optind,
1887 argv + main_optind);
1889 command_help(argc - main_optind, argv + main_optind);