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 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;
746 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
753 if (argc - optind > 0) {
754 razor_usage(argv[0], 0, NULL, "");
758 printf("importing from '%s'.\n", yum_url);
760 set = razor_set_create_from_yum(yum_url);
763 atomic = razor_atomic_open("Yum import repository");
764 razor_set_write(set, atomic, rawhide_repo_uri, RAZOR_SECTION_ALL);
765 retval = razor_atomic_commit(atomic);
766 razor_set_unref(set);
768 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
770 printf("wrote %s\n", rawhide_repo_uri);
771 razor_atomic_destroy(atomic);
778 command_import_rpmdb(int argc, char * const argv[])
780 struct razor_set *set;
781 struct razor_root *root;
782 struct razor_error *error = NULL;
783 struct razor_atomic *atomic;
786 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
793 if (argc - optind > 0) {
794 razor_usage(argv[0], 0, NULL, "");
798 root = razor_root_open(install_root, &error);
800 fprintf(stderr, "%s\n", razor_error_get_msg(error));
801 razor_error_free(error);
805 set = razor_set_create_from_rpmdb();
809 atomic = razor_atomic_open("Import RPM database");
811 retval = razor_root_update(root, set, atomic);
814 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
816 razor_atomic_destroy(atomic);
818 razor_root_close(root);
825 mark_packages_for_update(struct razor_transaction *trans,
826 struct razor_set *set, const char *pattern)
828 struct razor_package_iterator *pi;
829 struct razor_package *package;
833 pi = razor_package_iterator_create(set);
834 while (razor_package_iterator_next(pi, &package,
835 RAZOR_DETAIL_NAME, &name,
836 RAZOR_DETAIL_LAST)) {
837 if (pattern && fnmatch(pattern, name, 0) == 0) {
838 razor_transaction_update_package(trans, package);
842 razor_package_iterator_destroy(pi);
848 mark_packages_for_removal(struct razor_transaction *trans,
849 struct razor_set *set, const char *pattern)
851 struct razor_package_iterator *pi;
852 struct razor_package *package;
856 pi = razor_package_iterator_create(set);
857 while (razor_package_iterator_next(pi, &package,
858 RAZOR_DETAIL_NAME, &name,
859 RAZOR_DETAIL_LAST)) {
860 if (pattern && fnmatch(pattern, name, 0) == 0) {
861 razor_transaction_remove_package(trans, package);
865 razor_package_iterator_destroy(pi);
871 command_remove(int argc, char * const argv[])
873 struct razor_set *system, *upstream, *next;
874 struct razor_transaction *trans;
875 struct razor_error *error = NULL;
876 struct razor_root *root;
879 switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) {
886 root = razor_root_open(install_root, &error);
888 fprintf(stderr, "%s\n", razor_error_get_msg(error));
889 razor_error_free(error);
893 system = razor_root_get_system_set(root);
894 upstream = razor_set_create_without_root();
895 trans = razor_transaction_create(system, upstream);
896 razor_set_unref(upstream);
897 for (i = optind; i < argc; i++) {
898 if (mark_packages_for_removal(trans, system, argv[i]) == 0) {
899 fprintf(stderr, "no match for %s\n", argv[i]);
900 razor_transaction_destroy(trans);
901 razor_root_close(root);
906 razor_transaction_resolve(trans);
907 retval = razor_transaction_describe(trans);
909 razor_transaction_destroy(trans);
910 razor_root_close(root);
914 next = razor_transaction_commit(trans);
916 retval = update_system(root, NULL, trans, next, "Remove");
918 razor_transaction_destroy(trans);
919 razor_root_close(root);
920 razor_set_unref(next);
926 print_diff(enum razor_diff_action action,
927 struct razor_package *package,
933 if (action == RAZOR_DIFF_ACTION_ADD)
934 printf("install %s-%s.%s\n", name, version, arch);
935 if (action == RAZOR_DIFF_ACTION_REMOVE)
936 printf("remove %s-%s.%s\n", name, version, arch);
940 command_diff(int argc, char * const argv[])
942 struct razor_error *error = NULL;
943 struct razor_set *set, *updated;
945 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
952 if (argc - optind > 0) {
953 razor_usage(argv[0], 0, NULL, "");
957 set = razor_root_open_read_only(install_root, &error);
959 updated = razor_set_open(rawhide_repo_uri, 0, &error);
962 if (updated == NULL) {
963 fprintf(stderr, "%s\n", razor_error_get_msg(error));
964 razor_error_free(error);
966 razor_set_unref(set);
970 razor_set_diff(set, updated, print_diff, NULL);
972 razor_set_unref(set);
973 razor_set_unref(updated);
979 command_import_rpms(int argc, char * const argv[])
983 struct razor_importer *importer;
984 struct razor_set *set;
985 struct razor_rpm *rpm;
986 struct razor_error *error=NULL;
987 struct razor_atomic *atomic;
988 int len, imported_count = 0;
993 switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) {
1000 if (argc - optind != 1) {
1001 razor_usage(argv[0], 0, NULL, "dir");
1005 dirname = argv[optind];
1007 dir = opendir(dirname);
1009 fprintf(stderr, "couldn't read dir %s\n", dirname);
1013 importer = razor_importer_create();
1015 while (de = readdir(dir), de != NULL) {
1016 len = strlen(de->d_name);
1017 if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
1019 snprintf(filename, sizeof filename,
1020 "%s/%s", dirname, de->d_name);
1021 rpm = razor_rpm_open(filename, &error);
1023 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1024 razor_error_free(error);
1028 if (razor_importer_add_rpm(importer, rpm)) {
1029 fprintf(stderr, "couldn't import %s\n", filename);
1032 razor_rpm_close(rpm);
1034 printf("\rimporting %d", ++imported_count);
1039 razor_importer_destroy(importer);
1043 printf("\nsaving\n");
1044 set = razor_importer_finish(importer);
1046 atomic = razor_atomic_open("Update system database");
1047 razor_set_write(set, atomic, repo_filename, RAZOR_SECTION_ALL);
1048 razor_set_unref(set);
1049 retval = razor_atomic_commit(atomic);
1051 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1053 printf("wrote %s\n", repo_filename);
1054 razor_atomic_destroy(atomic);
1060 rpm_filename(const char *name, const char *version, const char *arch)
1065 v = strchr(version, ':');
1071 return razor_concat(name, "-", v, ".", arch, ".rpm", NULL);
1074 static struct razor_set *
1075 relocate_packages(struct razor_set *set, struct razor_atomic *atomic,
1076 struct razor_relocations *relocations)
1079 struct razor_importer *importer;
1080 struct razor_property_iterator *prop_iter;
1081 struct razor_package_iterator *pkg_iter;
1082 struct razor_file_iterator *file_iter;
1083 struct razor_package *package;
1084 struct razor_property *property;
1085 struct razor_rpm *rpm;
1086 struct razor_error *error=NULL;
1087 const char *name, *version, *arch, *summary, *desc, *url, *license;
1088 const char *preunprog, *preun, *postunprog, *postun;
1089 const char *install_prefix;
1090 const char *const *prefixes;
1091 char *file, *s, *uri, *filename;
1094 importer = razor_importer_create();
1095 pkg_iter = razor_package_iterator_create(set);
1097 while (razor_package_iterator_next(pkg_iter, &package,
1098 RAZOR_DETAIL_NAME, &name,
1099 RAZOR_DETAIL_VERSION, &version,
1100 RAZOR_DETAIL_ARCH, &arch,
1101 RAZOR_DETAIL_SUMMARY, &summary,
1102 RAZOR_DETAIL_DESCRIPTION, &desc,
1103 RAZOR_DETAIL_URL, &url,
1104 RAZOR_DETAIL_LICENSE, &license,
1105 RAZOR_DETAIL_PREUNPROG, &preunprog,
1106 RAZOR_DETAIL_PREUN, &preun,
1107 RAZOR_DETAIL_POSTUNPROG, &postunprog,
1108 RAZOR_DETAIL_POSTUN, &postun,
1109 RAZOR_DETAIL_LAST)) {
1110 filename = rpm_filename(name, version, arch);
1111 s = razor_concat("Packages/", filename, NULL);
1112 uri = razor_path_relative_to_uri(yum_url, s, NULL);
1115 rpm = razor_rpm_open(uri, &error);
1118 razor_atomic_propagate_error(atomic, error, NULL);
1119 razor_package_iterator_destroy(pkg_iter);
1120 razor_importer_destroy(importer);
1124 razor_relocations_set_rpm(relocations, rpm);
1126 razor_importer_begin_package(importer, name, version, arch);
1127 razor_importer_add_details(importer,
1128 summary, desc, url, license);
1130 razor_rpm_get_details(rpm, RAZOR_DETAIL_PREFIXES, &prefixes,
1132 for (i = 0; prefixes && prefixes[i]; i++) {
1133 install_prefix = razor_relocations_apply(relocations,
1135 razor_importer_add_install_prefix(importer,
1139 razor_rpm_close(rpm);
1141 prop_iter = razor_property_iterator_create(set, package);
1142 while (razor_property_iterator_next(prop_iter, &property,
1143 &name, &flags, &version))
1144 razor_importer_add_property(importer,
1145 name, flags, version);
1146 razor_property_iterator_destroy(prop_iter);
1148 file_iter = razor_file_iterator_create(set, package, 0);
1149 while (razor_file_iterator_next(file_iter, &name)) {
1150 name = razor_relocations_apply(relocations, name);
1151 razor_importer_add_file(importer, name);
1153 razor_file_iterator_destroy(file_iter);
1155 razor_importer_add_script(importer, RAZOR_PROPERTY_PREUN,
1157 razor_importer_add_script(importer, RAZOR_PROPERTY_POSTUN,
1158 postunprog, postun);
1160 razor_importer_finish_package(importer);
1163 razor_package_iterator_destroy(pkg_iter);
1164 return razor_importer_finish(importer);
1168 install_package(struct razor_transaction *trans, struct razor_set *set,
1169 struct razor_atomic *atomic, struct razor_package *package,
1170 struct razor_relocations *relocations, int install_count,
1171 enum razor_stage_type stage)
1174 const char *name, *version, *arch;
1175 char *file, *s, *uri;
1176 struct razor_rpm *rpm;
1177 struct razor_error *error=NULL;
1179 razor_package_get_details(set, package,
1180 RAZOR_DETAIL_NAME, &name,
1181 RAZOR_DETAIL_VERSION, &version,
1182 RAZOR_DETAIL_ARCH, &arch,
1185 s = rpm_filename(name, version, arch);
1186 file = razor_concat("Packages/", s, NULL);
1188 uri = razor_path_relative_to_uri(yum_url, file, NULL);
1191 if (stage & RAZOR_STAGE_SCRIPTS_PRE)
1192 printf("install %s\n", uri);
1194 rpm = razor_rpm_open(uri, &error);
1197 razor_atomic_propagate_error(atomic, error, NULL);
1198 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1202 razor_rpm_set_relocations(rpm, relocations);
1203 razor_transaction_fixup_package(trans, package, rpm);
1204 retval = razor_rpm_install(rpm, atomic, install_root, install_count,
1207 s = rpm_filename(name, version, arch);
1208 fprintf(stderr, "%s: %s\n", s,
1209 razor_atomic_get_error_msg(atomic));
1212 razor_rpm_close(rpm);
1217 * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
1218 * is met (in which case the action is consumed).
1221 update_packages(struct razor_transaction *trans,
1222 struct razor_install_iterator *ii, struct razor_set *system,
1223 struct razor_set *next, struct razor_atomic *atomic,
1224 struct razor_relocations *relocations,
1225 enum razor_stage_type stage)
1227 struct razor_package *package;
1228 enum razor_install_action action;
1229 int retval = 0, count;
1231 while (!retval && razor_install_iterator_next(ii, &package, &action,
1233 if (action == RAZOR_INSTALL_ACTION_ADD) {
1234 if (install_package(trans, next, atomic, package,
1235 relocations, count, stage))
1237 } else if (action == RAZOR_INSTALL_ACTION_REMOVE) {
1238 if (razor_package_remove(system, next, atomic, package,
1239 install_root, count, stage))
1241 } else if (action == RAZOR_INSTALL_ACTION_COMMIT)
1249 update_system(struct razor_root *root, struct razor_relocations *relocations,
1250 struct razor_transaction *trans, struct razor_set *next,
1253 struct razor_set *system, *set;
1254 struct razor_atomic *atomic;
1255 struct razor_install_iterator *ii;
1260 description = razor_concat(verb, " packages", NULL);
1262 system = razor_set_ref(razor_root_get_system_set(root));
1264 ii = razor_set_create_install_iterator(system, next);
1267 pos = razor_install_iterator_tell(ii);
1269 atomic = razor_atomic_open(description);
1271 r = update_packages(trans, ii, system, next, atomic,
1272 relocations, RAZOR_STAGE_SCRIPTS_PRE);
1274 fprintf(stderr, "%s aborted\n", verb);
1277 razor_install_iterator_seek(ii, pos);
1278 r = update_packages(trans, ii, system, next, atomic,
1279 relocations, RAZOR_STAGE_FILES);
1282 set = razor_install_iterator_commit_set(ii);
1283 razor_root_update(root, set, atomic);
1284 razor_set_unref(set);
1286 razor_root_update(root, next, atomic);
1288 retval = razor_atomic_commit(atomic);
1290 fprintf(stderr, "%s\n",
1291 razor_atomic_get_error_msg(atomic));
1293 razor_install_iterator_seek(ii, pos);
1294 update_packages(trans, ii, system, next,
1295 atomic, relocations,
1296 RAZOR_STAGE_SCRIPTS_POST);
1300 razor_atomic_destroy(atomic);
1301 } while(!retval && r == 1);
1303 razor_install_iterator_destroy(ii);
1305 razor_set_unref(system);
1313 command_install_or_update(int argc, char * const argv[], int do_update)
1315 struct razor_relocations *relocations = NULL;
1316 struct razor_set *system, *upstream, *next, *set;
1317 struct razor_transaction *trans;
1318 struct razor_error *error = NULL;
1319 struct razor_atomic *atomic;
1320 struct razor_root *root;
1321 int opt, i, retval = 0, len, dependencies = 1;
1325 opt_no_dependencies = 1,
1328 static struct razor_option options[] = {
1329 { .name = "no-dependencies", .has_arg = no_argument,
1330 .val = opt_no_dependencies,
1331 .description = "Do not verify package dependencies" },
1332 { .name = "relocate", .has_arg = required_argument,
1333 .val = opt_relocate,
1334 .description = "Relocate files from path OLD to NEW",
1335 .arg_description = "OLD=NEW" },
1339 opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options,
1346 case opt_no_dependencies:
1350 if (strchr(arg, '=') == NULL) {
1351 razor_usage(argv[0],
1352 ARRAY_SIZE(options),
1353 options, "rpm ...");
1356 len = strchr(arg, '=') - arg;
1357 oldpath = malloc(len + 1);
1358 strncpy(oldpath, arg, len);
1359 oldpath[len] = '\0';
1361 relocations = razor_relocations_create();
1362 razor_relocations_add(relocations, oldpath,
1369 upstream = razor_set_open(rawhide_repo_uri, 0, &error);
1370 if (upstream == NULL) {
1371 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1372 razor_error_free(error);
1374 razor_relocations_destroy(relocations);
1379 atomic = razor_atomic_open("Update packages");
1381 atomic = razor_atomic_open("Install packages");
1384 set = relocate_packages(upstream, atomic, relocations);
1386 fprintf(stderr, "%s\n",
1387 razor_atomic_get_error_msg(atomic));
1388 razor_atomic_destroy(atomic);
1389 razor_set_unref(upstream);
1392 razor_set_unref(upstream);
1396 root = razor_root_open(install_root, &error);
1398 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1399 razor_error_free(error);
1400 razor_atomic_destroy(atomic);
1401 razor_set_unref(upstream);
1403 razor_relocations_destroy(relocations);
1407 system = razor_root_get_system_set(root);
1408 trans = razor_transaction_create(system, upstream);
1410 if (optind == argc && do_update)
1411 razor_transaction_update_all(trans);
1412 for (i = optind; i < argc; i++) {
1414 mark_packages_for_update(trans, system, argv[i]))
1416 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
1417 fprintf(stderr, "no package matched %s\n", argv[i]);
1418 razor_transaction_destroy(trans);
1419 razor_root_close(root);
1420 razor_set_unref(upstream);
1421 razor_atomic_destroy(atomic);
1423 razor_relocations_destroy(relocations);
1429 razor_transaction_resolve(trans);
1430 if (razor_transaction_describe(trans) > 0) {
1431 razor_transaction_destroy(trans);
1432 razor_set_unref(upstream);
1433 razor_root_close(root);
1434 razor_atomic_destroy(atomic);
1436 razor_relocations_destroy(relocations);
1441 razor_atomic_destroy(atomic);
1443 next = razor_transaction_commit(trans);
1445 retval = update_system(root, relocations, trans, next,
1446 do_update ? "Update" : "Install");
1448 razor_set_unref(upstream);
1449 razor_root_close(root);
1451 razor_transaction_destroy(trans);
1453 razor_relocations_destroy(relocations);
1455 razor_set_unref(next);
1461 command_update(int argc, char * const argv[])
1463 return command_install_or_update(argc, argv, 1);
1467 command_install(int argc, char * const argv[])
1469 return command_install_or_update(argc, argv, 0);
1473 command_init(int argc, char * const argv[])
1476 struct razor_error *error = NULL;
1478 switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) {
1485 if (argc - optind > 0) {
1486 razor_usage(argv[0], 0, NULL, "");
1490 retval = razor_root_create(install_root, &error);
1492 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1493 razor_error_free(error);
1495 printf("Created install root\n");
1501 command_download(int argc, char * const argv[])
1503 struct razor_error *error = NULL;
1504 struct razor_atomic *atomic;
1505 struct razor_set *set;
1506 struct razor_package_iterator *pi;
1507 struct razor_package *package;
1508 const char *pattern, *name, *version, *arch;
1509 char *url, *file, *s, filename[256];
1512 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
1519 if (argc - optind > 1) {
1520 razor_usage(argv[0], 0, NULL, "[pattern]");
1524 pattern = argv[optind];
1526 set = razor_set_open(rawhide_repo_uri, 0, &error);
1528 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1529 razor_error_free(error);
1533 atomic = razor_atomic_open("Download packages");
1535 if (razor_atomic_create_dir(atomic, "file:rpms",
1536 S_IRWXU | S_IRWXG | S_IRWXO)) {
1537 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1538 razor_atomic_destroy(atomic);
1542 if (razor_atomic_commit(atomic)) {
1543 fprintf(stderr, "%s\n", razor_atomic_get_error_msg(atomic));
1544 razor_atomic_destroy(atomic);
1547 razor_atomic_destroy(atomic);
1549 pi = razor_package_iterator_create(set);
1550 while (razor_package_iterator_next(pi, &package,
1551 RAZOR_DETAIL_NAME, &name,
1552 RAZOR_DETAIL_VERSION, &version,
1553 RAZOR_DETAIL_ARCH, &arch,
1554 RAZOR_DETAIL_LAST)) {
1555 if (pattern && fnmatch(pattern, name, 0) != 0)
1559 snprintf(filename, sizeof filename,
1560 "%s-%s.%s.rpm", name, version, arch);
1561 s = razor_concat("Packages/", filename, NULL);
1562 url = razor_path_relative_to_uri(yum_url, s, NULL);
1564 file = razor_concat("rpms/", filename, NULL);
1565 download_if_missing(url, file);
1569 razor_package_iterator_destroy(pi);
1570 razor_set_unref(set);
1573 fprintf(stderr, "no packages matched \"%s\"\n", pattern);
1574 else if (matches == 1)
1575 fprintf(stderr, "downloaded 1 package\n");
1577 fprintf(stderr, "downloaded %d packages\n", matches);
1583 command_dump(int argc, char * const argv[])
1585 struct razor_error *error = NULL;
1586 const char *filename;
1588 switch (razor_getopt(argc, argv, 0, NULL, "[filename]", NULL)) {
1595 if (argc - optind > 1) {
1596 razor_usage(argv[0], 0, NULL, "[filename]");
1600 filename = argv[optind];
1602 if (razor_dump_database(stdout, install_root, filename, &error)) {
1603 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1604 razor_error_free(error);
1612 command_info(int argc, char * const argv[])
1614 struct razor_error *error = NULL;
1615 struct razor_set *set;
1616 struct razor_package_iterator *pi;
1617 struct razor_package *package;
1618 struct razor_string_iterator *si;
1619 const char *pattern, *name, *version, *arch;
1620 const char *summary, *description, *url, *license;
1623 switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) {
1630 if (argc - optind > 1) {
1631 razor_usage(argv[0], 0, NULL, "[pattern]");
1635 pattern = argv[optind];
1637 set = razor_root_open_read_only(install_root, &error);
1639 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1640 razor_error_free(error);
1644 pi = razor_package_iterator_create(set);
1645 while (razor_package_iterator_next(pi, &package,
1646 RAZOR_DETAIL_NAME, &name,
1647 RAZOR_DETAIL_VERSION, &version,
1648 RAZOR_DETAIL_ARCH, &arch,
1649 RAZOR_DETAIL_LAST)) {
1650 if (pattern && fnmatch(pattern, name, 0) != 0)
1653 printf ("Name: %s\n", name);
1654 printf ("Arch: %s\n", arch);
1655 printf ("Version: %s\n", version);
1657 si = razor_install_prefix_iterator_create(set, package);
1658 if (razor_string_iterator_next(si, &prefix)) {
1659 printf ("Relocations: %s\n", prefix);
1660 while (razor_string_iterator_next(si, &prefix))
1661 printf (" : %s\n", prefix);
1663 razor_string_iterator_destroy(si);
1665 razor_package_get_details (set, package,
1666 RAZOR_DETAIL_SUMMARY, &summary,
1667 RAZOR_DETAIL_DESCRIPTION, &description,
1668 RAZOR_DETAIL_URL, &url,
1669 RAZOR_DETAIL_LICENSE, &license,
1672 printf ("URL: %s\n", url);
1673 printf ("License: %s\n", license);
1674 printf ("Summary: %s\n", summary);
1675 printf ("Description:\n");
1676 printf ("%s\n", description);
1679 razor_package_iterator_destroy(pi);
1680 razor_set_unref(set);
1685 #define SEARCH_MAX 256
1688 command_search(int argc, char * const argv[])
1690 struct razor_error *error = NULL;
1691 struct razor_set *set;
1692 struct razor_package_iterator *pi;
1693 struct razor_package *package;
1694 char pattern[SEARCH_MAX];
1695 const char *name, *version, *arch;
1696 const char *summary, *description, *url, *license;
1698 switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) {
1706 razor_usage(argv[0], 0, NULL, "pattern");
1710 snprintf(pattern, sizeof pattern, "*%s*", argv[1]);
1712 set = razor_set_open(rawhide_repo_uri, 0, &error);
1714 fprintf(stderr, "%s\n", razor_error_get_msg(error));
1715 razor_error_free(error);
1719 pi = razor_package_iterator_create(set);
1720 while (razor_package_iterator_next(pi, &package,
1721 RAZOR_DETAIL_NAME, &name,
1722 RAZOR_DETAIL_VERSION, &version,
1723 RAZOR_DETAIL_ARCH, &arch,
1724 RAZOR_DETAIL_SUMMARY, &summary,
1725 RAZOR_DETAIL_DESCRIPTION, &description,
1726 RAZOR_DETAIL_URL, &url,
1727 RAZOR_DETAIL_LICENSE, &license,
1728 RAZOR_DETAIL_LAST)) {
1729 if (!fnmatch(pattern, name, FNM_CASEFOLD) ||
1730 !fnmatch(pattern, url, FNM_CASEFOLD) ||
1731 !fnmatch(pattern, summary, FNM_CASEFOLD) ||
1732 !fnmatch(pattern, description, FNM_CASEFOLD))
1733 printf("%s-%s.%s: %s\n", name, version, arch, summary);
1735 razor_package_iterator_destroy(pi);
1736 razor_set_unref(set);
1743 const char *description;
1744 int (*func)(int argc, char * const argv[]);
1745 } razor_commands[] = {
1746 { "diff", "Show diff between two package sets", command_diff },
1747 { "download", "Download packages", command_download },
1748 { "dump", "Low-level database dump (for debugging)", command_dump },
1749 { "help", "List available commands", command_help },
1751 { "import-rpmdb", "Import the system rpm database",
1752 command_import_rpmdb },
1754 { "import-rpms", "Import rpms from the given directory",
1755 command_import_rpms },
1756 { "import-yum", "Import yum metadata files", command_import_yum },
1757 { "info", "Display package details", command_info },
1758 { "init", "Init razor root", command_init },
1759 { "install", "Install rpm", command_install },
1760 { "list", "List all packages", command_list },
1761 { "list-conflicts", "List all conflicts for the given package",
1762 command_list_conflicts },
1763 { "list-file-packages", "List packages owning file",
1764 command_list_file_packages },
1765 { "list-files", "List files for package set", command_list_files },
1766 { "list-obsoletes", "List all obsoletes for the given package",
1767 command_list_obsoletes },
1768 { "list-package-files", "List files in package",
1769 command_list_package_files },
1770 { "list-provides", "List all provides for the given package",
1771 command_list_provides },
1772 { "list-requires", "List all requires for the given package",
1773 command_list_requires },
1774 { "list-scripts", "List all scripts for the given package",
1775 command_list_scripts },
1776 { "remove", "Remove specified packages", command_remove },
1777 { "search", "Search package details", command_search },
1778 { "update", "Update all or specified packages", command_update },
1779 { "what-provides", "List the packages that have the given provides",
1780 command_what_provides },
1781 { "what-requires", "List the packages that have the given requires",
1782 command_what_requires },
1786 command_help(int argc, char * const argv[])
1790 printf("Available commands:\n");
1791 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1792 printf(" %-20s%s\n",
1793 razor_commands[i].name, razor_commands[i].description);
1794 printf("\nType \"razor --help\" for help about global options\n"
1795 "or \"razor <command> --help\" for help about a particular "
1796 "command's options.\n");
1802 main(int argc, char *argv[])
1805 int i, opt, main_optind;
1806 int do_help_commands = 0;
1814 struct option options[] = {
1815 { .name = "database", .has_arg = required_argument,
1816 .val = opt_database },
1817 { .name = "help", .has_arg = no_argument, .val = opt_help },
1818 { .name = "help-commands", .has_arg = no_argument,
1819 .flag = &do_help_commands, .val = TRUE },
1820 { .name = "root", .has_arg = required_argument,
1822 { .name = "url", .has_arg = required_argument, .val = opt_url },
1826 repo = getenv("RAZOR_REPO");
1828 repo_filename = repo;
1830 root = getenv("RAZOR_ROOT");
1832 install_root = root;
1834 yum_url = getenv("YUM_URL");
1835 if (yum_url == NULL)
1838 if (getenv("RAZOR_NO_ROOT_NAME_CHECKS"))
1839 razor_disable_root_name_checks(1);
1844 while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) {
1847 razor_set_database_uri(optarg);
1851 printf("Usage: razor [global-options] command "
1852 "[command-options-and-arguments]\n\n");
1853 printf("Options:\n");
1855 "Show this help message and exit\n");
1856 printf(" --help-commands List commands\n");
1857 printf(" --database=URI "
1858 "Use alternative database\n");
1859 printf(" --root=URI "
1860 "Use URI as top level directory\n");
1861 printf(" --url=URI "
1862 "Use URI as upstream repository\n");
1863 return opt != opt_help;
1865 install_root = optarg;
1875 main_optind = optind;
1878 if (do_help_commands || argc - main_optind < 1) {
1879 command_help(argc - main_optind, argv + main_optind);
1885 for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
1886 if (strcmp(razor_commands[i].name, argv[main_optind]) == 0)
1887 return razor_commands[i].func(argc - main_optind,
1888 argv + main_optind);
1890 command_help(argc - main_optind, argv + main_optind);