From: J. Ali Harlow Date: Mon, 8 Sep 2014 09:26:39 +0000 (+0100) Subject: Add control over database location X-Git-Tag: 0.6~18 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=972e9afd5eb2e7e6247a86f624c59f1875b89105;p=razor.git Add control over database location --- diff --git a/gl/.gitignore b/gl/.gitignore index 4b5a26b..ddd53d3 100644 --- a/gl/.gitignore +++ b/gl/.gitignore @@ -74,3 +74,7 @@ /sys_types.in.h /unistd.c /wctype-h.c +/getopt.c +/getopt.in.h +/getopt1.c +/getopt_int.h diff --git a/gl/m4/.gitignore b/gl/m4/.gitignore index 7ce22dd..f48d441 100644 --- a/gl/m4/.gitignore +++ b/gl/m4/.gitignore @@ -71,3 +71,5 @@ /ssize_t.m4 /sys_socket_h.m4 /sys_types_h.m4 +/getopt.m4 +/nocrash.m4 diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4 index daed511..b6e11d9 100644 --- a/gl/m4/gnulib-cache.m4 +++ b/gl/m4/gnulib-cache.m4 @@ -27,7 +27,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-conditional-dependencies --libtool --macro-prefix=gl fnmatch fnmatch-posix fsync mkdir mkdtemp +# gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --doc-base=doc --tests-base=tests --aux-dir=. --no-conditional-dependencies --libtool --macro-prefix=gl fnmatch fnmatch-posix fsync getopt-gnu mkdir mkdtemp # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -35,6 +35,7 @@ gl_MODULES([ fnmatch fnmatch-posix fsync + getopt-gnu mkdir mkdtemp ]) diff --git a/librazor/razor.h b/librazor/razor.h index 55bbe63..521f809 100644 --- a/librazor/razor.h +++ b/librazor/razor.h @@ -555,6 +555,8 @@ struct razor_set *razor_set_create_from_rpmdb(void); **/ struct razor_root; +const char *razor_get_database_path(); +void razor_set_database_path(const char *database_path); int razor_root_create(const char *root, struct razor_error **error); struct razor_root * razor_root_open(const char *root, struct razor_error **error); diff --git a/librazor/root.c b/librazor/root.c index 7db364a..9061bcc 100644 --- a/librazor/root.c +++ b/librazor/root.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Kristian Høgsberg * Copyright (C) 2008 Red Hat, Inc - * Copyright (C) 2009, 2011, 2012 J. Ali Harlow + * Copyright (C) 2009, 2011, 2012, 2014 J. Ali Harlow * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,14 @@ #define O_BINARY 0 #endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + static const char system_repo_filename[] = "system.rzdb"; /* * system_lock_filename is chosen to be the same as the pre v0.3 @@ -50,11 +58,12 @@ static const char system_repo_filename[] = "system.rzdb"; */ static const char system_lock_filename[] = "system-next.rzdb"; #ifdef MSWIN_API -#define RAZOR_ROOT_PATH NULL +#define RAZOR_DATABASE_PATH NULL #else -#define RAZOR_ROOT_PATH "/var/lib/razor" +#define RAZOR_DATABASE_PATH "/var/lib/razor" #endif -static const char *razor_root_path = RAZOR_ROOT_PATH; +static char *razor_database_path = RAZOR_DATABASE_PATH; +static int razor_database_path_alloced = FALSE; struct razor_root { struct razor_set *system; @@ -65,17 +74,41 @@ static void razor_root_init(void) { #ifdef MSWIN_API - static char root_path[MAX_PATH]; - if (!razor_root_path) { + static char database_path[MAX_PATH]; + if (!razor_database_path) { SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0, - root_path); - strcat(root_path, "\\Razor"); - razor_root_path = root_path; + database_path); + strcat(database_path, "\\Razor"); + razor_database_path = database_path; + razor_database_path_alloced = FALSE; } #endif } +RAZOR_EXPORT const char * +razor_get_database_path() +{ + razor_root_init(); + + return razor_database_path; +} + +RAZOR_EXPORT void +razor_set_database_path(const char *database_path) +{ + if (razor_database_path_alloced) + free(razor_database_path); + + if (database_path) { + razor_database_path = strdup(database_path); + razor_database_path_alloced = TRUE; + } else { + razor_database_path = RAZOR_DATABASE_PATH; + razor_database_path_alloced = FALSE; + } +} + RAZOR_EXPORT int razor_root_create(const char *root, struct razor_error **error) { @@ -101,7 +134,8 @@ razor_root_create(const char *root, struct razor_error **error) return -1; } - file = razor_concat(razor_root_path, "/", system_repo_filename, NULL); + file = razor_concat(razor_database_path, "/", system_repo_filename, + NULL); path = razor_path_add_root(file, root); retval = !stat(path, &buf); if (retval) { @@ -152,7 +186,7 @@ razor_root_open(const char *root, struct razor_error **error) return NULL; } - s = razor_concat(razor_root_path, "/", system_lock_filename, NULL); + s = razor_concat(razor_database_path, "/", system_lock_filename, NULL); lock_path = razor_path_add_root(s, root); free(s); @@ -168,7 +202,7 @@ razor_root_open(const char *root, struct razor_error **error) return NULL; } - s = razor_concat(razor_root_path, "/", system_repo_filename, NULL); + s = razor_concat(razor_database_path, "/", system_repo_filename, NULL); image->path = razor_path_add_root(s, root); free(s); @@ -198,7 +232,7 @@ razor_root_open_read_only(const char *root, struct razor_error **error) return NULL; } - s = razor_concat(razor_root_path, "/", system_lock_filename, NULL); + s = razor_concat(razor_database_path, "/", system_lock_filename, NULL); path = razor_path_add_root(s, root); free(s); @@ -212,7 +246,7 @@ razor_root_open_read_only(const char *root, struct razor_error **error) free(path); - s = razor_concat(razor_root_path, "/", system_repo_filename, NULL); + s = razor_concat(razor_database_path, "/", system_repo_filename, NULL); path = razor_path_add_root(s, root); free(s); diff --git a/src/main.c b/src/main.c index c307e89..d7e7f69 100644 --- a/src/main.c +++ b/src/main.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Kristian Høgsberg * Copyright (C) 2008 Red Hat, Inc - * Copyright (C) 2009, 2011-2012 J. Ali Harlow + * Copyright (C) 2009, 2011-2012, 2014 J. Ali Harlow * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ #endif #include #include +#include #include "razor.h" static const char system_repo_filename[] = "system.rzdb"; @@ -46,6 +47,14 @@ static const char *install_root = ""; static const char *repo_filename = system_repo_filename; static const char *yum_url; +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static int @@ -59,8 +68,110 @@ update_system(struct razor_root *root, struct razor_relocations *relocations, struct razor_transaction *trans, struct razor_set *next, const char *verb); +static int command_help(int argc, char * const argv[]); + +struct razor_option { + char *name; + int has_arg; + int val; + char *description; + char *arg_description; +}; + +static void +razor_usage(const char *command, int n_options, struct razor_option *options, + const char *parameter_string) +{ + int i, help_printed = FALSE; + char buf[19]; + + printf("Usage: razor %s [options] %s\n", command, parameter_string); + printf("(Specify the --help global option for a list of other " + "help options)\n"); + printf("\nOptions:\n"); + + for(i = 0; i < n_options; i++) { + if (!help_printed && strcmp(options[i].name, "help") > 0) { + printf(" --help " + "Show this help message and exit\n"); + help_printed = TRUE; + } + + if (options[i].has_arg != no_argument) + snprintf(buf, sizeof(buf), "%s=%s", options[i].name, + options[i].arg_description); + else + strncpy(buf, options[i].name, sizeof(buf)); + buf[18] = '\0'; + + printf(" --%-18s%s\n", buf, options[i].description); + } + + if (!help_printed) + printf(" --help " + "Show this help message and exit\n"); +} + +/** + * razor_getopt: + * + * + * Returns: The next option found or -2 on handled or -1 on error + * or 0 on end of option list. + **/ +static int +razor_getopt(int argc, char * const argv[], int n_options, + struct razor_option *options, const char *parameter_string, + const char **arg) +{ + int i, opt, do_help = 0, retval; + struct option *longopts; + + longopts = calloc((n_options + 2), sizeof(*longopts)); + + for(i = 0; i < n_options; i++) { + longopts[i].name = options[i].name; + longopts[i].has_arg = options[i].has_arg; + longopts[i].flag = &retval; + longopts[i].val = options[i].val; + } + + longopts[i].name = "help"; + longopts[i].has_arg = no_argument; + longopts[i].flag = &do_help; + longopts[i].val = TRUE; + + opterr = 0; + + opt = getopt_long(argc, argv, "+", longopts, NULL); + + switch (opt) + { + case 0: + if (do_help) { + razor_usage(argv[0], n_options, options, + parameter_string); + retval = -2; + } else if (arg) + *arg = optarg; + break; + + case -1: + retval = 0; + break; + + default: + razor_usage(argv[0], n_options, options, + parameter_string); + retval = -1; + } + + free(longopts); + return retval; +} + static struct razor_package_iterator * -create_iterator_from_argv(struct razor_set *set, int argc, const char *argv[]) +create_iterator_from_argv(struct razor_set *set, int argc, char * const argv[]) { struct razor_package_query *query; struct razor_package_iterator *iter; @@ -117,18 +228,35 @@ list_packages(struct razor_package_iterator *iter, uint32_t flags) } static int -command_list(int argc, const char *argv[]) +command_list(int argc, char * const argv[]) { + int opt; struct razor_package_iterator *pi; struct razor_error *error = NULL; struct razor_set *set; uint32_t flags = 0; - int i = 0; + enum { + opt_only_names = 1, + }; + static struct razor_option options[] = { + { .name = "only-names", .has_arg = no_argument, + .val = opt_only_names, + .description = "Only list package names" }, + }; - if (i < argc && strcmp(argv[i], "--only-names") == 0) { - flags |= LIST_PACKAGES_ONLY_NAMES; - i++; - } + do { + opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options, + "pattern ...", NULL); + switch (opt) { + case -2: + return 0; + case -1: + return 1; + case opt_only_names: + flags |= LIST_PACKAGES_ONLY_NAMES; + break; + } + } while (opt); set = razor_root_open_read_only(install_root, &error); if (set == NULL) { @@ -137,7 +265,7 @@ command_list(int argc, const char *argv[]) return 1; } - pi = create_iterator_from_argv(set, argc - i, argv + i); + pi = create_iterator_from_argv(set, argc - optind, argv + optind); list_packages(pi, flags); razor_package_iterator_destroy(pi); razor_set_unref(set); @@ -183,7 +311,7 @@ list_package_properties(struct razor_set *set, } static int -list_properties(int argc, const char *argv[], uint32_t type) +list_properties(int argc, char * const argv[], uint32_t type) { struct razor_set *set; struct razor_error *error = NULL; @@ -191,6 +319,13 @@ list_properties(int argc, const char *argv[], uint32_t type) struct razor_package_iterator *pi; const char *name, *version, *arch; + switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -198,7 +333,7 @@ list_properties(int argc, const char *argv[], uint32_t type) return 1; } - pi = create_iterator_from_argv(set, argc, argv); + pi = create_iterator_from_argv(set, argc - optind, argv + optind); while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_NAME, &name, RAZOR_DETAIL_VERSION, &version, @@ -212,31 +347,31 @@ list_properties(int argc, const char *argv[], uint32_t type) } static int -command_list_requires(int argc, const char *argv[]) +command_list_requires(int argc, char * const argv[]) { return list_properties(argc, argv, RAZOR_PROPERTY_REQUIRES); } static int -command_list_provides(int argc, const char *argv[]) +command_list_provides(int argc, char * const argv[]) { return list_properties(argc, argv, RAZOR_PROPERTY_PROVIDES); } static int -command_list_obsoletes(int argc, const char *argv[]) +command_list_obsoletes(int argc, char * const argv[]) { return list_properties(argc, argv, RAZOR_PROPERTY_OBSOLETES); } static int -command_list_conflicts(int argc, const char *argv[]) +command_list_conflicts(int argc, char * const argv[]) { return list_properties(argc, argv, RAZOR_PROPERTY_CONFLICTS); } static int -command_list_scripts(int argc, const char *argv[]) +command_list_scripts(int argc, char * const argv[]) { struct razor_set *set; struct razor_error *error = NULL; @@ -244,6 +379,13 @@ command_list_scripts(int argc, const char *argv[]) struct razor_package_iterator *pi; const char *preunprog, *preun, *postunprog, *postun; + switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -251,7 +393,7 @@ command_list_scripts(int argc, const char *argv[]) return 1; } - pi = create_iterator_from_argv(set, argc, argv); + pi = create_iterator_from_argv(set, argc - optind, argv + optind); while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_PREUNPROG, &preunprog, RAZOR_DETAIL_PREUN, &preun, @@ -278,11 +420,23 @@ command_list_scripts(int argc, const char *argv[]) } static int -command_list_files(int argc, const char *argv[]) +command_list_files(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set; + switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 1) { + razor_usage(argv[0], 0, NULL, "[pattern]"); + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -290,19 +444,31 @@ command_list_files(int argc, const char *argv[]) return 1; } - razor_set_list_files(set, argv[0]); + razor_set_list_files(set, argv[optind]); razor_set_unref(set); return 0; } static int -command_list_file_packages(int argc, const char *argv[]) +command_list_file_packages(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set; struct razor_package_iterator *pi; + switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind != 1) { + razor_usage(argv[0], 0, NULL, "pattern"); + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -310,7 +476,7 @@ command_list_file_packages(int argc, const char *argv[]) return 1; } - pi = razor_package_iterator_create_for_file(set, argv[0]); + pi = razor_package_iterator_create_for_file(set, argv[optind]); list_packages(pi, 0); razor_package_iterator_destroy(pi); @@ -320,7 +486,7 @@ command_list_file_packages(int argc, const char *argv[]) } static int -command_list_package_files(int argc, const char *argv[]) +command_list_package_files(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set; @@ -328,6 +494,13 @@ command_list_package_files(int argc, const char *argv[]) struct razor_package *package; const char *name, *version, *arch; + switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -335,7 +508,7 @@ command_list_package_files(int argc, const char *argv[]) return 1; } - pi = create_iterator_from_argv(set, argc, argv); + pi = create_iterator_from_argv(set, argc - optind, argv + optind); while (razor_package_iterator_next(pi, &package, RAZOR_DETAIL_NAME, &name, RAZOR_DETAIL_VERSION, &version, @@ -362,9 +535,6 @@ list_property_packages(const char *ref_name, const char *name, *version; uint32_t flags; - if (ref_name == NULL) - return 0; - set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -398,16 +568,42 @@ list_property_packages(const char *ref_name, } static int -command_what_requires(int argc, const char *argv[]) +command_what_requires(int argc, char * const argv[]) { - return list_property_packages(argv[0], argv[1], + switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]", + NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind < 1 || argc - optind > 2) { + razor_usage(argv[0], 0, NULL, "name [version-release]"); + return 1; + } + + return list_property_packages(argv[optind], argv[optind + 1], RAZOR_PROPERTY_REQUIRES); } static int -command_what_provides(int argc, const char *argv[]) +command_what_provides(int argc, char * const argv[]) { - return list_property_packages(argv[0], argv[1], + switch (razor_getopt(argc, argv, 0, NULL, "name [version-release]", + NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind < 1 || argc - optind > 2) { + razor_usage(argv[0], 0, NULL, "name [version-release]"); + return 1; + } + + return list_property_packages(argv[optind], argv[optind + 1], RAZOR_PROPERTY_PROVIDES); } @@ -489,13 +685,25 @@ download_if_missing(const char *url, const char *file) "/pub/fedora/linux/development/i386/os" static int -command_import_yum(int argc, const char *argv[]) +command_import_yum(int argc, char * const argv[]) { int retval; struct razor_set *set; struct razor_atomic *atomic; char buffer[512]; + switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 0) { + razor_usage(argv[0], 0, NULL, ""); + return 1; + } + printf("downloading from %s.\n", yum_url); snprintf(buffer, sizeof buffer, "%s/repodata/primary.xml.gz", yum_url); @@ -524,7 +732,7 @@ command_import_yum(int argc, const char *argv[]) #if HAVE_RPMLIB static int -command_import_rpmdb(int argc, const char *argv[]) +command_import_rpmdb(int argc, char * const argv[]) { struct razor_set *set; struct razor_root *root; @@ -532,6 +740,18 @@ command_import_rpmdb(int argc, const char *argv[]) struct razor_atomic *atomic; int retval; + switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 0) { + razor_usage(argv[0], 0, NULL, ""); + return 1; + } + root = razor_root_open(install_root, &error); if (root == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -605,7 +825,7 @@ mark_packages_for_removal(struct razor_transaction *trans, } static int -command_remove(int argc, const char *argv[]) +command_remove(int argc, char * const argv[]) { struct razor_set *system, *upstream, *next; struct razor_transaction *trans; @@ -613,6 +833,13 @@ command_remove(int argc, const char *argv[]) struct razor_root *root; int i, retval; + switch (razor_getopt(argc, argv, 0, NULL, "pattern ...", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + root = razor_root_open(install_root, &error); if (root == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -624,7 +851,7 @@ command_remove(int argc, const char *argv[]) upstream = razor_set_create_without_root(); trans = razor_transaction_create(system, upstream); razor_set_unref(upstream); - for (i = 0; i < argc; i++) { + for (i = optind; i < argc; i++) { if (mark_packages_for_removal(trans, system, argv[i]) == 0) { fprintf(stderr, "no match for %s\n", argv[i]); razor_transaction_destroy(trans); @@ -667,11 +894,23 @@ print_diff(enum razor_diff_action action, } static int -command_diff(int argc, const char *argv[]) +command_diff(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set, *updated; + switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 0) { + razor_usage(argv[0], 0, NULL, ""); + return 1; + } + set = razor_root_open_read_only(install_root, &error); if (set) updated = razor_set_open(rawhide_repo_filename, 0, &error); @@ -694,7 +933,7 @@ command_diff(int argc, const char *argv[]) } static int -command_import_rpms(int argc, const char *argv[]) +command_import_rpms(int argc, char * const argv[]) { DIR *dir; struct dirent *de; @@ -705,14 +944,23 @@ command_import_rpms(int argc, const char *argv[]) struct razor_atomic *atomic; int len, imported_count = 0; char filename[256]; - const char *dirname = argv[0]; + const char *dirname; int retval; - if (dirname == NULL) { - fprintf(stderr, "usage: razor import-rpms DIR\n"); - return -1; + switch (razor_getopt(argc, argv, 0, NULL, "dir", NULL)) { + case -2: + return 0; + case -1: + return 1; } + if (argc - optind != 1) { + razor_usage(argv[0], 0, NULL, "dir"); + return 1; + } + + dirname = argv[optind]; + dir = opendir(dirname); if (dir == NULL) { fprintf(stderr, "couldn't read dir %s\n", dirname); @@ -1054,7 +1302,7 @@ update_system(struct razor_root *root, struct razor_relocations *relocations, } static int -command_install_or_update(int argc, const char *argv[], int do_update) +command_install_or_update(int argc, char * const argv[], int do_update) { struct razor_relocations *relocations = NULL; struct razor_set *system, *upstream, *next, *set; @@ -1062,36 +1310,53 @@ command_install_or_update(int argc, const char *argv[], int do_update) struct razor_error *error = NULL; struct razor_atomic *atomic; struct razor_root *root; - int i, retval, len, dependencies = 1; + int opt, i, retval = 0, len, dependencies = 1; char *oldpath; + const char *arg; + enum { + opt_no_dependencies = 1, + opt_relocate = 2, + }; + static struct razor_option options[] = { + { .name = "no-dependencies", .has_arg = no_argument, + .val = opt_no_dependencies, + .description = "Do not verify package dependencies" }, + { .name = "relocate", .has_arg = required_argument, + .val = opt_relocate, + .description = "Relocate files from path OLD to NEW", + .arg_description = "OLD=NEW" }, + }; - for (i = 0; i < argc; i++) { - if (strcmp(argv[i], "--no-dependencies") == 0) - dependencies = 0; - else if (strcmp(argv[i], "--relocate") == 0) { - i++; - if (i >= argc || strchr(argv[i], '=') == NULL) { - fprintf(stderr, - "Usage: razor %s [OPTION...] RPM\n", - do_update ? "update" : "install"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " [--no-dependencies]\n"); - fprintf(stderr, - " [--relocate OLDPATH=NEWPATH] RPM\n"); - return -1; - } - len = strchr(argv[i], '=') - argv[i]; - oldpath = malloc(len + 1); - strncpy(oldpath, argv[i], len); - oldpath[len] = '\0'; - if (!relocations) - relocations = razor_relocations_create(); - razor_relocations_add(relocations, oldpath, - argv[i] + len + 1); - free(oldpath); - } else - break; - } + do { + opt = razor_getopt(argc, argv, ARRAY_SIZE(options), options, + "rpm ...", &arg); + switch (opt) { + case -2: + return 0; + case -1: + return 1; + case opt_no_dependencies: + dependencies = 0; + break; + case opt_relocate: + if (strchr(arg, '=') == NULL) { + razor_usage(argv[0], + ARRAY_SIZE(options), + options, "rpm ..."); + return 1; + } + len = strchr(arg, '=') - arg; + oldpath = malloc(len + 1); + strncpy(oldpath, arg, len); + oldpath[len] = '\0'; + if (!relocations) + relocations = razor_relocations_create(); + razor_relocations_add(relocations, oldpath, + arg + len + 1); + free(oldpath); + break; + } + } while (opt); upstream = razor_set_open(rawhide_repo_filename, 0, &error); if (upstream == NULL) { @@ -1132,9 +1397,9 @@ command_install_or_update(int argc, const char *argv[], int do_update) system = razor_root_get_system_set(root); trans = razor_transaction_create(system, upstream); - if (i == argc && do_update) + if (optind == argc && do_update) razor_transaction_update_all(trans); - for (; i < argc; i++) { + for (i = optind; i < argc; i++) { if (do_update && mark_packages_for_update(trans, system, argv[i])) continue; @@ -1207,23 +1472,35 @@ command_install_or_update(int argc, const char *argv[], int do_update) } static int -command_update(int argc, const char *argv[]) +command_update(int argc, char * const argv[]) { return command_install_or_update(argc, argv, 1); } static int -command_install(int argc, const char *argv[]) +command_install(int argc, char * const argv[]) { return command_install_or_update(argc, argv, 0); } static int -command_init(int argc, const char *argv[]) +command_init(int argc, char * const argv[]) { int retval; struct razor_error *error = NULL; + switch (razor_getopt(argc, argv, 0, NULL, "", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 0) { + razor_usage(argv[0], 0, NULL, ""); + return 1; + } + retval = razor_root_create(install_root, &error); if (retval) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -1235,17 +1512,31 @@ command_init(int argc, const char *argv[]) } static int -command_download(int argc, const char *argv[]) +command_download(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_atomic *atomic; struct razor_set *set; struct razor_package_iterator *pi; struct razor_package *package; - const char *pattern = argv[0], *name, *version, *arch; + const char *pattern, *name, *version, *arch; char url[256], file[256]; int matches = 0; + switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 1) { + razor_usage(argv[0], 0, NULL, "[pattern]"); + return 1; + } + + pattern = argv[optind]; + set = razor_set_open(rawhide_repo_filename, 0, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -1300,15 +1591,29 @@ command_download(int argc, const char *argv[]) } static int -command_info(int argc, const char *argv[]) +command_info(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set; struct razor_package_iterator *pi; struct razor_package *package; - const char *pattern = argv[0], *name, *version, *arch; + const char *pattern, *name, *version, *arch; const char *summary, *description, *url, *license; + switch (razor_getopt(argc, argv, 0, NULL, "[pattern]", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc - optind > 1) { + razor_usage(argv[0], 0, NULL, "[pattern]"); + return 1; + } + + pattern = argv[optind]; + set = razor_root_open_read_only(install_root, &error); if (set == NULL) { fprintf(stderr, "%s\n", razor_error_get_msg(error)); @@ -1351,7 +1656,7 @@ command_info(int argc, const char *argv[]) #define SEARCH_MAX 256 static int -command_search(int argc, const char *argv[]) +command_search(int argc, char * const argv[]) { struct razor_error *error = NULL; struct razor_set *set; @@ -1361,12 +1666,19 @@ command_search(int argc, const char *argv[]) const char *name, *version, *arch; const char *summary, *description, *url, *license; - if (!argv[0]) { - fprintf(stderr, "must specify a search term\n"); + switch (razor_getopt(argc, argv, 0, NULL, "pattern", NULL)) { + case -2: + return 0; + case -1: + return 1; + } + + if (argc != 2) { + razor_usage(argv[0], 0, NULL, "pattern"); return 1; } - snprintf(pattern, sizeof pattern, "*%s*", argv[0]); + snprintf(pattern, sizeof pattern, "*%s*", argv[1]); set = razor_set_open(rawhide_repo_filename, 0, &error); if (set == NULL) { @@ -1400,52 +1712,86 @@ command_search(int argc, const char *argv[]) static struct { const char *name; const char *description; - int (*func)(int argc, const char *argv[]); + int (*func)(int argc, char * const argv[]); } razor_commands[] = { - { "list", "list all packages", command_list }, - { "list-requires", "list all requires for the given package", command_list_requires }, - { "list-provides", "list all provides for the given package", command_list_provides }, - { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes }, - { "list-conflicts", "list all conflicts for the given package", command_list_conflicts }, - { "list-scripts", "list all scripts for the given package", command_list_scripts }, - { "list-files", "list files for package set", command_list_files }, - { "list-file-packages", "list packages owning file", command_list_file_packages }, - { "list-package-files", "list files in package", command_list_package_files }, - { "what-requires", "list the packages that have the given requires", command_what_requires }, - { "what-provides", "list the packages that have the given provides", command_what_provides }, - { "import-yum", "import yum metadata files", command_import_yum }, + { "diff", "Show diff between two package sets", command_diff }, + { "download", "Download packages", command_download }, + { "help", "List available commands", command_help }, #if HAVE_RPMLIB - { "import-rpmdb", "import the system rpm database", command_import_rpmdb }, + { "import-rpmdb", "Import the system rpm database", + command_import_rpmdb }, #endif - { "import-rpms", "import rpms from the given directory", command_import_rpms }, - { "update", "update all or specified packages", command_update }, - { "remove", "remove specified packages", command_remove }, - { "diff", "show diff between two package sets", command_diff }, - { "install", "install rpm", command_install }, - { "init", "init razor root", command_init }, - { "download", "download packages", command_download }, - { "info", "display package details", command_info }, - { "search", "search package details", command_search } + { "import-rpms", "Import rpms from the given directory", + command_import_rpms }, + { "import-yum", "Import yum metadata files", command_import_yum }, + { "info", "Display package details", command_info }, + { "init", "Init razor root", command_init }, + { "install", "Install rpm", command_install }, + { "list", "List all packages", command_list }, + { "list-conflicts", "List all conflicts for the given package", + command_list_conflicts }, + { "list-file-packages", "List packages owning file", + command_list_file_packages }, + { "list-files", "List files for package set", command_list_files }, + { "list-obsoletes", "List all obsoletes for the given package", + command_list_obsoletes }, + { "list-package-files", "List files in package", + command_list_package_files }, + { "list-provides", "List all provides for the given package", + command_list_provides }, + { "list-requires", "List all requires for the given package", + command_list_requires }, + { "list-scripts", "List all scripts for the given package", + command_list_scripts }, + { "remove", "Remove specified packages", command_remove }, + { "search", "Search package details", command_search }, + { "update", "Update all or specified packages", command_update }, + { "what-provides", "List the packages that have the given provides", + command_what_provides }, + { "what-requires", "List the packages that have the given requires", + command_what_requires }, }; static int -usage(void) +command_help(int argc, char * const argv[]) { int i; - printf("usage:\n"); + printf("Available commands:\n"); for (i = 0; i < ARRAY_SIZE(razor_commands); i++) printf(" %-20s%s\n", razor_commands[i].name, razor_commands[i].description); + printf("\nType \"razor --help\" for help about global options\n" + "or \"razor --help\" for help about a particular " + "command's options.\n"); - return 1; + return 0; } int -main(int argc, const char *argv[]) +main(int argc, char *argv[]) { char *repo, *root; - int i; + int i, opt, main_optind; + int do_help_commands = 0; + enum { + opt_database = 1, + opt_help, + opt_help_commands, + opt_root, + opt_url, + }; + struct option options[] = { + { .name = "database", .has_arg = required_argument, + .val = opt_database }, + { .name = "help", .has_arg = no_argument, .val = opt_help }, + { .name = "help-commands", .has_arg = no_argument, + .flag = &do_help_commands, .val = TRUE }, + { .name = "root", .has_arg = required_argument, + .val = opt_root }, + { .name = "url", .has_arg = required_argument, .val = opt_url }, + { 0, } + }; repo = getenv("RAZOR_REPO"); if (repo != NULL) @@ -1462,12 +1808,53 @@ main(int argc, const char *argv[]) if (getenv("RAZOR_NO_ROOT_NAME_CHECKS")) razor_disable_root_name_checks(1); - if (argc < 2) - return usage(); + optind = 1; + opterr = 0; + + while ((opt = getopt_long(argc, argv, "+", options, NULL)) != -1) { + switch (opt) { + case opt_database: + razor_set_database_path(optarg); + break; + case opt_help: + default: + printf("Usage: razor [global-options] command " + "[command-options-and-arguments]\n\n"); + printf("Options:\n"); + printf(" --help " + "Show this help message and exit\n"); + printf(" --help-commands List commands\n"); + printf(" --database=PATH " + "Use alternative database\n"); + printf(" --root=ROOT " + "Use ROOT as top level directory\n"); + printf(" --url=URL " + "Use URL as upstream repository\n"); + return opt != opt_help; + case opt_root: + install_root = optarg; + break; + case opt_url: + yum_url = optarg; + break; + case 0: + break; + } + } + + main_optind = optind; + optind = 1; + + if (do_help_commands || argc - main_optind < 1) { + command_help(argc - main_optind, argv + main_optind); + return 1; + } for (i = 0; i < ARRAY_SIZE(razor_commands); i++) - if (strcmp(razor_commands[i].name, argv[1]) == 0) - return razor_commands[i].func(argc - 2, argv + 2); + if (strcmp(razor_commands[i].name, argv[main_optind]) == 0) + return razor_commands[i].func(argc - main_optind, + argv + main_optind); - return usage(); + command_help(argc - main_optind, argv + main_optind); + return 1; }