From: Alberto Leiva Popper Date: Tue, 5 Mar 2019 16:51:46 +0000 (-0600) Subject: Add '--output-file-name-format' option X-Git-Tag: v0.0.2~76 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e364ceee63d977a59c4f9bfadcf2a5b906a40c2;p=thirdparty%2FFORT-validator.git Add '--output-file-name-format' option Decides which version of the file name should be printed during most debug and error messages. Also found myself starting the manpage. --- diff --git a/man/rpki-validator.8 b/man/rpki-validator.8 new file mode 100644 index 00000000..9ff8eac9 --- /dev/null +++ b/man/rpki-validator.8 @@ -0,0 +1,150 @@ +.TH rpki-validator 8 2019-03-5 v0.0.1-beta "RPKI certificate path validator" + +.SH NAME +rpki-validator - Actually still unnamed officially. + +.SH OPTIONS + +--help +.RS 4 +Print long usage message. +.RE +.P + +--usage +.RS 4 +Print short usage message. +.RE +.P + +--version +.RS 4 +Print program version. +.RE +.P + +--configuration-file= +.RS 4 +Path to a TOML file from which additional configuration will be read. +.RE +.P + +--local-repository= +.RS 4 +Path to a directory where the local cache of the repository will be stored +and/or read. +.RE +.P + +--sync-strategy=(off|strict|root) +.RS 4 +RSYNC download strategy. +.P +off +.RS 4 +Skip all RSYNCs. (Validate the existing cache repository pointed by --local-repository.) +.RE +.P +strict +.RS 4 +RSYNC every repository publication point separately. Only skip publication +points that have already been downloaded during the current validation cycle. +(Assuming each synchronization is recursive.) +.P +For example, suppose the validator gets certificates whose caRepository access +methods (in their Subject Information Access extensions) point to the following +publication points: +.P +1. rsync://rpki.example.com/foo/bar/ +.br +2. rsync://rpki.example.com/foo/qux/ +.br +3. rsync://rpki.example.com/foo/bar/ +.br +4. rsync://rpki.example.com/foo/corge/grault/ +.br +5. rsync://rpki.example.com/foo/corge/ +.br +6. rsync://rpki.example.com/foo/corge/waldo/ +.P +A validator following the `strict` strategy would download `bar`, download +`qux`, skip `bar`, download `corge/grault`, download `corge` and skip +`corge/waldo`. +.P +This is the slowest, but also the strictly correct sync strategy. +.RE +.P +root +.RS 4 +For each publication point found, guess the root of its repository and RSYNC +that instead. Then skip any subsequent children of said root. +.P +(To guess the root of a repository, the validator counts four slashes, and +prunes the rest of the URL.) +.P +Reusing the caRepository URLs from the `strict` strategy (above) as example, a +validator following the `root` strategy would download +`rsync://rpki.example.com/foo`, and then skip everything else. +.P +Assuming that the repository is specifically structured to be found within as +few roots as possible, and they contain minimal RPKI-unrelated noise files, this +is the fastest synchronization strategy. At time of writing, this is true for +all the current official repositories. +.RE +.RE +.P + +--maximum-certificate-depth= +.RS 4 +Maximum allowable certificate chain length. +.P +(Required to prevent loops and "other degenerate forms of the logical RPKI +hierarchy." (RFC 6481)) +.RE +.P + +--tal= +.RS 4 +Path to the TAL file the validation will sprawl from. +.P +The TAL ("Trust Anchor Locator") is a text file that lists a few URLs which can +be used to access the "Trust Anchor" (the root of a particular RPKI tree) and +its public key. (See RFC 7730.) +.RE +.P + +--shuffle-uris +.RS 4 +Shuffle URIs in the TAL before accessing them. +.RE +.P + +--color-output +.RS 4 +Print ANSI color codes? +.RE +.P + +--output-file-name-format=(global-url|local-path|file-name) +.RS 4 +Decides which version of file names should be printed during most debug/error +messages. +.P +Suppose a certificate was downloaded from `rsync://rpki.example.com/foo/bar/baz.cer` into the local cache `repository/`: +.P +global-url +.RS 4 +will print the certificate's name as `rsync://rpki.example.com/foo/bar/baz.cer`. +.RE +.P +local-path +.RS 4 +will print the certificate's name as `repository/rpki.example.com/foo/bar/baz.cer`. +.RE +.P +file-name +.RS 4 +will print the certificate's name as `baz.cer`. +.RE +.P +.RE \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index a9bb0410..0d521a44 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -122,7 +122,7 @@ GCC_WARNS += -Whsa # I don't mind too much increasing these. # Just make sure that you know what you're doing. -GCC_WARNS += -Wlarger-than=1024 -Walloc-size-larger-than=4096 +GCC_WARNS += -Wlarger-than=2048 -Walloc-size-larger-than=4096 GCC_WARNS += -Wframe-larger-than=1024 -Wstack-usage=1024 # Can't use because of dependencies: -Waggregate-return diff --git a/src/asn1/signed_data.c b/src/asn1/signed_data.c index 26790feb..745f5db6 100644 --- a/src/asn1/signed_data.c +++ b/src/asn1/signed_data.c @@ -397,8 +397,8 @@ validate(struct SignedData *sdata, struct signed_object_args *args) * * So, nothing to do for now. * - * TODO "In the certificate, the OID appears in the signature and - * signatureAlgorithm fields [RFC4055]." So it has to be the same as + * TODO (field) "In the certificate, the OID appears in the signature + * and signatureAlgorithm fields [RFC4055]." So it has to be the same as * some other field? */ diff --git a/src/config.c b/src/config.c index 87a8cd87..e787d05e 100644 --- a/src/config.c +++ b/src/config.c @@ -48,15 +48,19 @@ struct rpki_config { * Prevents arbitrarily long paths and loops. */ unsigned int maximum_certificate_depth; - /** Print ANSI color codes? */ - bool color_output; struct { char *program; struct string_array args; } rsync; -}; + struct { + /** Print ANSI color codes? */ + bool color; + /** Format in which file names will be printed. */ + enum filename_format filename_format; + } output; +}; static void print_usage(FILE *, bool); @@ -71,6 +75,7 @@ DECLARE_PRINT_FN(print_u_int); DECLARE_PRINT_FN(print_string); DECLARE_PRINT_FN(print_string_array); DECLARE_PRINT_FN(print_sync_strategy); +DECLARE_PRINT_FN(print_filename_format); #define DECLARE_PARSE_ARGV_FN(name) \ static int name( \ @@ -82,6 +87,7 @@ DECLARE_PARSE_ARGV_FN(parse_argv_bool); DECLARE_PARSE_ARGV_FN(parse_argv_u_int); DECLARE_PARSE_ARGV_FN(parse_argv_string); DECLARE_PARSE_ARGV_FN(parse_argv_sync_strategy); +DECLARE_PARSE_ARGV_FN(parse_argv_filename_format); #define DECLARE_PARSE_TOML_FN(name) \ static int name( \ @@ -94,6 +100,7 @@ DECLARE_PARSE_TOML_FN(parse_toml_u_int); DECLARE_PARSE_TOML_FN(parse_toml_string); DECLARE_PARSE_TOML_FN(parse_toml_sync_strategy); DECLARE_PARSE_TOML_FN(parse_toml_string_array); +DECLARE_PARSE_TOML_FN(parse_toml_filename_format); #define DECLARE_HANDLE_FN(name) \ static int name( \ @@ -158,6 +165,15 @@ static const struct global_type gt_sync_strategy = { .arg_doc = SYNC_VALUE_OFF "|" SYNC_VALUE_STRICT "|" SYNC_VALUE_ROOT, }; +static const struct global_type gt_filename_format = { + .has_arg = required_argument, + .size = sizeof(enum filename_format), + .print = print_filename_format, + .parse.argv = parse_argv_filename_format, + .parse.toml = parse_toml_filename_format, + .arg_doc = FNF_VALUE_GLOBAL "|" FNF_VALUE_LOCAL "|" FNF_VALUE_NAME, +}; + /** * An option that takes no arguments, is not correlated to any rpki_config * fields, and is entirely managed by its handler function. @@ -193,7 +209,7 @@ static const struct option_field global_fields[] = { .name = "configuration-file", .type = >_string, .handler = handle_toml, - .doc = "TOML file the configuration will be read from.", + .doc = "TOML file additional configuration will be read from", .arg_doc = "", .availability = AVAILABILITY_GETOPT, }, { @@ -201,21 +217,27 @@ static const struct option_field global_fields[] = { .name = "local-repository", .type = >_string, .offset = offsetof(struct rpki_config, local_repository), - .doc = "Local repository path.", + .doc = "Directory where the repository local cache will be stored/read", .arg_doc = "", }, { .id = 1001, .name = "sync-strategy", .type = >_sync_strategy, .offset = offsetof(struct rpki_config, sync_strategy), - .doc = "RSYNC download strategy.", + .doc = "RSYNC download strategy", }, { - .id = 'c', - .name = "color-output", - .type = >_bool, - .offset = offsetof(struct rpki_config, color_output), - .doc = "Print ANSI color codes?", - .availability = AVAILABILITY_GETOPT, + .id = 1002, + .name = "maximum-certificate-depth", + .type = >_u_int, + .offset = offsetof(struct rpki_config, + maximum_certificate_depth), + .doc = "Maximum allowable certificate chain length", + .min = 1, + /** + * It cannot be UINT_MAX, because then the actual number will + * overflow and will never be bigger than this. + */ + .max = UINT_MAX - 1, }, { 0 }, }; @@ -226,27 +248,14 @@ static const struct option_field tal_fields[] = { .name = "tal", .type = >_string, .offset = offsetof(struct rpki_config, tal), - .doc = "TAL file path", - .arg_doc = "", + .doc = "Path to the TAL file", + .arg_doc = "", }, { .id = 2000, .name = "shuffle-uris", .type = >_bool, .offset = offsetof(struct rpki_config, shuffle_uris), - .doc = "Shuffle URIs in the TAL.", - }, { - .id = 2001, - .name = "maximum-certificate-depth", - .type = >_u_int, - .offset = offsetof(struct rpki_config, - maximum_certificate_depth), - .doc = "Prevents arbitrarily long paths and loops.", - .min = 1, - /** - * It cannot be UINT_MAX, because then the actual number will - * overflow and will never be bigger than this. - */ - .max = UINT_MAX - 1, + .doc = "Shuffle URIs in the TAL before accessing them", }, { 0 }, }; @@ -257,7 +266,7 @@ static const struct option_field rsync_fields[] = { .name = "program", .type = >_string, .offset = offsetof(struct rpki_config, rsync.program), - .doc = "Name of the program needed to execute an RSYNC.", + .doc = "Name of the program needed to execute an RSYNC", .arg_doc = "", .availability = AVAILABILITY_TOML, }, { @@ -265,12 +274,29 @@ static const struct option_field rsync_fields[] = { .name = "arguments", .type = >_string_array, .offset = offsetof(struct rpki_config, rsync.args), - .doc = "Arguments to send to the RSYNC program call.", + .doc = "Arguments to send to the RSYNC program call", .availability = AVAILABILITY_TOML, }, { 0 }, }; +static const struct option_field output_fields[] = { + { + .id = 'c', + .name = "color-output", + .type = >_bool, + .offset = offsetof(struct rpki_config, output.color), + .doc = "Print ANSI color codes?", + }, { + .id = 4000, + .name = "output-file-name-format", + .type = >_filename_format, + .offset = offsetof(struct rpki_config, output.filename_format), + .doc = "File name variant to print during debug/error messages", + }, + { 0 }, +}; + static const struct group_fields groups[] = { { .name = "root", @@ -281,6 +307,9 @@ static const struct group_fields groups[] = { }, { .name = "rsync", .options = rsync_fields, + }, { + .name = "output", + .options = output_fields, }, { NULL }, }; @@ -366,6 +395,28 @@ print_sync_strategy(struct group_fields const *group, pr_info("%s.%s: %s", group->name, field->name, str); } +void +print_filename_format(struct group_fields const *group, + struct option_field const *field, void *value) +{ + enum filename_format *format = value; + char const *str = ""; + + switch (*format) { + case FNF_GLOBAL: + str = FNF_VALUE_GLOBAL; + break; + case FNF_LOCAL: + str = FNF_VALUE_LOCAL; + break; + case FNF_NAME: + str = FNF_VALUE_NAME; + break; + } + + pr_info("%s.%s: %s", group->name, field->name, str); +} + static int parse_argv_bool(struct option_field const *field, char const *str, void *result) { @@ -451,6 +502,24 @@ parse_argv_sync_strategy(struct option_field const *field, char const *str, return 0; } +static int +parse_argv_filename_format(struct option_field const *field, char const *str, + void *_result) +{ + enum filename_format *result = _result; + + if (strcmp(str, FNF_VALUE_GLOBAL) == 0) + *result = FNF_GLOBAL; + else if (strcmp(str, FNF_VALUE_LOCAL) == 0) + *result = FNF_LOCAL; + else if (strcmp(str, FNF_VALUE_NAME) == 0) + *result = FNF_NAME; + else + return pr_err("Unknown file name format: '%s'", str); + + return 0; +} + static int parse_toml_bool(struct option_field const *opt, struct toml_table_t *toml, void *_result) @@ -577,6 +646,23 @@ fail: return error; } +static int +parse_toml_filename_format(struct option_field const *opt, + struct toml_table_t *toml, void *_result) +{ + int error; + char *string; + + error = parse_toml_string(opt, toml, &string); + if (error) + return error; + + error = parse_argv_filename_format(opt, string, _result); + + free(string); + return error; +} + static int handle_help(struct option_field const *field, char *arg) { @@ -737,7 +823,6 @@ set_default_values(void) rpki_config.sync_strategy = SYNC_STRICT; rpki_config.shuffle_uris = false; rpki_config.maximum_certificate_depth = 32; - rpki_config.color_output = false; rpki_config.rsync.program = strdup("rsync"); if (rpki_config.rsync.program == NULL) @@ -755,6 +840,9 @@ set_default_values(void) goto revert_rsync_args; } + rpki_config.output.color = false; + rpki_config.output.filename_format = FNF_GLOBAL; + return 0; revert_rsync_args: @@ -784,7 +872,6 @@ print_usage(FILE *stream, bool print_doc) char const *arg_doc; fprintf(stream, "Usage: %s\n", program_name); - FOREACH_OPTION(groups, group, option, AVAILABILITY_GETOPT) { fprintf(stream, "\t["); fprintf(stream, "--%s", option->name); @@ -923,9 +1010,14 @@ config_get_max_cert_depth(void) bool config_get_color_output(void) { - return rpki_config.color_output; + return rpki_config.output.color; } +enum filename_format +config_get_filename_format(void) +{ + return rpki_config.output.filename_format; +} char * config_get_rsync_program(void) diff --git a/src/config.h b/src/config.h index f127798b..4243a0c7 100644 --- a/src/config.h +++ b/src/config.h @@ -58,6 +58,19 @@ enum sync_strategy { #define SYNC_VALUE_STRICT "strict" #define SYNC_VALUE_ROOT "root" +enum filename_format { + /** Example: "rsync://repository.lacnic.net/rpki/foo/bar/baz.cer" */ + FNF_GLOBAL, + /** Example: "/tmp/repo/repository.lacnic.net/rpki/foo/bar/baz.cer" */ + FNF_LOCAL, + /** Example: "baz.cer" */ + FNF_NAME, +}; + +#define FNF_VALUE_GLOBAL "global-url" +#define FNF_VALUE_LOCAL "local-path" +#define FNF_VALUE_NAME "file-name" + struct rpki_config; struct group_fields; @@ -166,7 +179,9 @@ struct option_field { handler_function handler; /** - * Explanation of the field, for user consumption. + * Explanation of the field, for user consumption during --help. + * Meant to be short; the bulk of it should be found in the manpage. + * Probably should not include punctuation at the end. * Mandatory. */ const char *doc; @@ -203,6 +218,7 @@ enum sync_strategy config_get_sync_strategy(void); bool config_get_shuffle_uris(void); unsigned int config_get_max_cert_depth(void); bool config_get_color_output(void); +enum filename_format config_get_filename_format(void); char *config_get_rsync_program(void); struct string_array const *config_get_rsync_args(void); diff --git a/src/main.c b/src/main.c index a6a067b9..049b3390 100644 --- a/src/main.c +++ b/src/main.c @@ -47,11 +47,11 @@ handle_tal_uri(struct tal *tal, struct rpki_uri const *uri) if (error) return -abs(error); - pr_debug_add("TAL URI %s {", uri->global); + pr_debug_add("TAL URI '%s' {", uri_get_printable(uri)); if (!uri_is_certificate(uri)) { pr_err("TAL file does not point to a certificate. (Expected .cer, got '%s')", - uri->global); + uri_get_printable(uri)); error = -EINVAL; goto end; } diff --git a/src/object/certificate.c b/src/object/certificate.c index 629cc6c4..6602c1dc 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -584,7 +584,7 @@ handle_rpkiManifest(struct rpki_uri *uri, void *arg) static int handle_caRepository(struct rpki_uri *uri, void *arg) { - pr_debug("caRepository: %s", uri->global); + pr_debug("caRepository: %s", uri_get_printable(uri)); return download_files(uri); } @@ -592,7 +592,7 @@ static int handle_signedObject(struct rpki_uri *uri, void *arg) { struct certificate_refs *refs = arg; - pr_debug("signedObject: %s", uri->global); + pr_debug("signedObject: %s", uri_get_printable(uri)); refs->signedObject = uri->global; uri->global = NULL; return 0; @@ -1152,9 +1152,9 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri const *cert_uri, if (sk_X509_num(validation_certs(state)) >= config_get_max_cert_depth()) return pr_err("Certificate chain maximum depth exceeded."); - pr_debug_add("%s Certificate %s {", is_ta ? "TA" : "CA", - cert_uri->global); - fnstack_push(cert_uri->global); + pr_debug_add("%s Certificate '%s' {", is_ta ? "TA" : "CA", + uri_get_printable(cert_uri)); + fnstack_push_uri(cert_uri); memset(&refs, 0, sizeof(refs)); /* -- Validate the certificate (@cert) -- */ diff --git a/src/object/crl.c b/src/object/crl.c index 10808ad9..e36b49f6 100644 --- a/src/object/crl.c +++ b/src/object/crl.c @@ -138,7 +138,7 @@ int crl_load(struct rpki_uri const *uri, X509_CRL **result) { int error; - pr_debug_add("CRL %s {", uri->global); + pr_debug_add("CRL '%s' {", uri_get_printable(uri)); error = __crl_load(uri, result); if (!error) diff --git a/src/object/ghostbusters.c b/src/object/ghostbusters.c index 26ea77b5..e39634fb 100644 --- a/src/object/ghostbusters.c +++ b/src/object/ghostbusters.c @@ -22,8 +22,8 @@ handle_ghostbusters(struct rpki_uri const *uri, struct rpp *pp, struct signed_object_args sobj_args; int error; - pr_debug_add("Ghostbusters %s {", uri->global); - fnstack_push(uri->global); + pr_debug_add("Ghostbusters '%s' {", uri->global); + fnstack_push_uri(uri); error = signed_object_args_init(&sobj_args, uri, crls, true); if (error) diff --git a/src/object/manifest.c b/src/object/manifest.c index c9f766ce..21211eb0 100644 --- a/src/object/manifest.c +++ b/src/object/manifest.c @@ -185,8 +185,8 @@ handle_manifest(struct rpki_uri const *uri, STACK_OF(X509_CRL) *crls, struct manifest mft; int error; - pr_debug_add("Manifest %s {", uri->global); - fnstack_push(uri->global); + pr_debug_add("Manifest '%s' {", uri_get_printable(uri)); + fnstack_push_uri(uri); error = signed_object_args_init(&sobj_args, uri, crls, false); if (error) diff --git a/src/object/roa.c b/src/object/roa.c index b3aee4e2..05f82d56 100644 --- a/src/object/roa.c +++ b/src/object/roa.c @@ -211,8 +211,8 @@ handle_roa(struct rpki_uri const *uri, struct rpp *pp, struct RouteOriginAttestation *roa; int error; - pr_debug_add("ROA %s {", uri->global); - fnstack_push(uri->global); + pr_debug_add("ROA '%s' {", uri_get_printable(uri)); + fnstack_push_uri(uri); error = signed_object_args_init(&sobj_args, uri, crls, false); if (error) diff --git a/src/rpp.c b/src/rpp.c index 289fa334..be3a0291 100644 --- a/src/rpp.c +++ b/src/rpp.c @@ -91,7 +91,6 @@ rpp_add_crl(struct rpp *pp, struct rpki_uri *uri) pp->crl = *uri; pp->crl_set = true; - pr_debug("Manifest CRL: %s", uri->global); return 0; } @@ -102,7 +101,7 @@ add_crl_to_stack(struct rpp *pp, STACK_OF(X509_CRL) *crls) int error; int idx; - fnstack_push(pp->crl.global); + fnstack_push_uri(&pp->crl); error = crl_load(&pp->crl, &crl); if (error) diff --git a/src/str.c b/src/str.c index 1ae6170c..8d6991ae 100644 --- a/src/str.c +++ b/src/str.c @@ -7,7 +7,7 @@ /** * Does not assume that @string is NULL-terminated. */ -int +static int string_clone(void const *string, size_t size, char **clone) { char *result; diff --git a/src/str.h b/src/str.h index acfd301e..ec1db1c6 100644 --- a/src/str.h +++ b/src/str.h @@ -6,7 +6,6 @@ #include #include -int string_clone(void const *, size_t, char **); int ia5s2string(ASN1_IA5STRING *, char **); int BN2string(BIGNUM *, char **); diff --git a/src/thread_var.c b/src/thread_var.c index 7b0ab8b5..16ced79c 100644 --- a/src/thread_var.c +++ b/src/thread_var.c @@ -6,9 +6,10 @@ #include #include #include - #include +#include "config.h" + static pthread_key_t state_key; static pthread_key_t filenames_key; @@ -113,20 +114,14 @@ get_file_stack(void) return files; } -static char const * -get_filename(char const *file_path) -{ - /* char *slash = strrchr(file_path, '/'); */ - return /* (slash != NULL) ? (slash + 1) : */ file_path; -} - /** * Call this function every time you're about to start processing a new file. * Any pr_err()s and friends will now include the new file name. * Use fnstack_pop() to revert back to the previously stacked file name. + * @file is not cloned; it's expected to outlive the push/pop operation. */ void -fnstack_push(char const *file_path) +fnstack_push(char const *file) { struct filename_stack *files; char const **tmp; @@ -148,7 +143,14 @@ fnstack_push(char const *file_path) files->size *= 2; } - files->filenames[files->len++] = get_filename(file_path); + files->filenames[files->len++] = file; +} + +/** See fnstack_push(). */ +void +fnstack_push_uri(struct rpki_uri const *uri) +{ + fnstack_push(uri_get_printable(uri)); } /* Returns the file name on the top of the file name stack. */ diff --git a/src/thread_var.h b/src/thread_var.h index 074148a7..fe53f72d 100644 --- a/src/thread_var.h +++ b/src/thread_var.h @@ -10,6 +10,7 @@ struct validation *state_retrieve(void); void fnstack_store(void); void fnstack_push(char const *); +void fnstack_push_uri(struct rpki_uri const *); char const *fnstack_peek(void); void fnstack_pop(void); diff --git a/src/uri.c b/src/uri.c index da645ec3..55b0bc1d 100644 --- a/src/uri.c +++ b/src/uri.c @@ -49,22 +49,22 @@ validate_url_character(int character) * This function does not assume that @str is null-terminated. */ static int -str2global(void const *str, size_t str_len, struct rpki_uri *uri) +str2global(char const *str, size_t str_len, struct rpki_uri *uri) { int error; size_t i; - error = string_clone(str, str_len, &uri->global); - if (error) - return error; - uri->global_len = str_len; - for (i = 0; i < str_len; i++) { - error = validate_url_character(uri->global[i]); + error = validate_url_character(str[i]); if (error) return error; } + uri->global = strdup(str); + if (uri->global == NULL) + return pr_enomem(); + uri->global_len = str_len; + return 0; } @@ -318,3 +318,29 @@ uri_is_certificate(struct rpki_uri const *uri) { return uri_has_extension(uri, ".cer"); } + +static char const * +get_filename(char const *file_path) +{ + char *slash = strrchr(file_path, '/'); + return (slash != NULL) ? (slash + 1) : file_path; +} + +char const * +uri_get_printable(struct rpki_uri const *uri) +{ + enum filename_format format; + + format = config_get_filename_format(); + switch (format) { + case FNF_GLOBAL: + return uri->global; + case FNF_LOCAL: + return uri->local; + case FNF_NAME: + return get_filename(uri->global); + } + + pr_crit("Unknown file name format: %u", format); + return uri->global; +} diff --git a/src/uri.h b/src/uri.h index 757589aa..abd41d14 100644 --- a/src/uri.h +++ b/src/uri.h @@ -15,7 +15,7 @@ * Because we need to generate @local from @global, @global's allowed character * set must be a subset of @local. Because this is Unix, @local must never * contain NULL (except as a terminating character). Therefore, even though IA5 - * allows NULL, @global won't. TODO (NOW) validate this on constructors. + * allows NULL, @global won't. * * Because we will simply embed @global (minus "rsync://") into @local, @local's * encoding must be IA5-compatible. In other words, UTF-16 and UTF-32 are out of @@ -64,5 +64,6 @@ void uri_cleanup(struct rpki_uri *); bool uri_has_extension(struct rpki_uri const *, char const *); bool uri_is_certificate(struct rpki_uri const *); +char const *uri_get_printable(struct rpki_uri const *); #endif /* SRC_URI_H_ */