Changeset: d7ebe028b522 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/d7ebe028b522 Modified Files: clients/examples/C/testsfile.c clients/mapilib/connect.c clients/mapilib/msettings.c clients/mapilib/msettings.h Branch: monetdburl Log Message:
More precise error messages diffs (truncated from 321 to 300 lines): diff --git a/clients/examples/C/testsfile.c b/clients/examples/C/testsfile.c --- a/clients/examples/C/testsfile.c +++ b/clients/examples/C/testsfile.c @@ -42,9 +42,10 @@ handle_accept_command(const char *locati return false; } - const char *msg = msettings_validate(mp); - if (msg != NULL) { + char *msg = NULL; + if (!msettings_validate(mp, &msg)) { fprintf(stderr, "%s: URL invalid: %s\n", location, msg); + free(msg); return false; } return true; @@ -57,9 +58,11 @@ handle_reject_command(const char *locati if (!ok) return true; - const char *msg = msettings_validate(mp); - if (msg != NULL) + char *msg = NULL; + if (!msettings_validate(mp, &msg)) { + free(msg); return true; + } fprintf(stderr, "%s: expected URL to be rejected.\n", location); return false; @@ -78,10 +81,11 @@ handle_set_command(const char *location, static bool ensure_valid(const char *location) { - const char *msg = msettings_validate(mp); - if (msg == NULL) + char *msg = NULL; + if (msettings_validate(mp, &msg)) return true; fprintf(stderr, "%s: invalid parameter state: %s\n", location, msg); + free(msg); return false; } @@ -172,14 +176,16 @@ handle_expect_command(const char *locati fprintf(stderr, "%s: invalid boolean value: %s\n", location, value); return false; } - bool expected = x > 0; - msettings_error msg = msettings_validate(mp); - bool actual = msg == NULL; - if (actual != expected) { + bool expected_valid = x > 0; + + char * msg = NULL; + bool actually_valid = msettings_validate(mp, &msg); + free(msg); + if (actually_valid != expected_valid) { fprintf(stderr, "%s: expected '%s', found '%s'\n", location, - expected ? "true" : "false", - actual ? "true" : "false" + expected_valid ? "true" : "false", + actually_valid ? "true" : "false" ); return false; } diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c --- a/clients/mapilib/connect.c +++ b/clients/mapilib/connect.c @@ -36,9 +36,12 @@ static MapiMsg mapi_handshake(Mapi mid); MapiMsg mapi_reconnectx(Mapi mid) { - msettings_error err = msettings_validate(mid->settings); - if (err) - return mapi_setError(mid, err, __func__, MERROR); + char *err = NULL; + if (!msettings_validate(mid->settings, &err)) { + mapi_setError(mid, err, __func__, MERROR); + free(err); + return MERROR; + } // If neither host nor port are given, scan the Unix domain sockets in // /tmp and see if any of them serve this database. @@ -103,10 +106,13 @@ scan_unix_sockets(Mapi mid) return mapi_setError(mid, "malloc failed", __func__, MERROR); } msettings_error errmsg = msetting_set_long(mid->settings, MP_PORT, candidates[i].port); - if (!errmsg) - errmsg = msettings_validate(mid->settings); + char *allocated_errmsg = NULL; + if (!errmsg && !msettings_validate(mid->settings, &allocated_errmsg)) { + errmsg = allocated_errmsg; + } if (errmsg) { mapi_setError(mid, errmsg, __func__, MERROR); + free(allocated_errmsg); msettings_destroy(mid->settings); mid->settings = original; return MERROR; @@ -232,7 +238,7 @@ connect_socket_unix(Mapi mid, const char { struct sockaddr_un userver; if (strlen(sockname) >= sizeof(userver.sun_path)) { - mapi_setError(mid, "path name too long", __func__, MERROR); + mapi_PrintError(mid, __func__, MERROR, "path name '%s' too long", sockname); return INVALID_SOCKET; } @@ -246,7 +252,7 @@ connect_socket_unix(Mapi mid, const char if (s == INVALID_SOCKET) { mapi_PrintError( mid, __func__, MERROR, - "could not create Unix domain socket: %s", strerror(errno)); + "could not create Unix domain socket '%s': %s", sockname, strerror(errno)); return INVALID_SOCKET; } #if !defined(SOCK_CLOEXEC) && defined(HAVE_FCNTL) @@ -264,7 +270,7 @@ connect_socket_unix(Mapi mid, const char closesocket(s); mapi_PrintError( mid, __func__, MERROR, - "connect to Unix domain socket failed: %s", strerror(errno)); + "connect to Unix domain socket '%s' failed: %s", sockname, strerror(errno)); return INVALID_SOCKET; } @@ -290,9 +296,13 @@ static SOCKET connect_socket_tcp(Mapi mid, const char *host, int port) { int ret; + assert(host); char portbuf[10]; snprintf(portbuf, sizeof(portbuf), "%d", port); + if (host[0] == '/') + return mapi_setError(mid, "Setting the socket dir is not supported yet", __func__, MERROR); + struct addrinfo hints = (struct addrinfo) { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, @@ -303,7 +313,7 @@ connect_socket_tcp(Mapi mid, const char if (ret != 0) { mapi_PrintError( mid, __func__, MERROR, - "getaddrinfo failed: %s", gai_strerror(ret)); + "getaddrinfo %s:%s failed: %s", host, portbuf, gai_strerror(ret)); return INVALID_SOCKET; } if (addresses == NULL) { diff --git a/clients/mapilib/msettings.c b/clients/mapilib/msettings.c --- a/clients/mapilib/msettings.c +++ b/clients/mapilib/msettings.c @@ -5,6 +5,7 @@ #include <assert.h> #include <ctype.h> #include <limits.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -28,6 +29,32 @@ int msetting_parse_bool(const char *text return -1; } +char* allocprintf(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); + +char * +allocprintf(const char *fmt, ...) +{ + size_t buflen = 80; + while (1) { + char *buf = malloc(buflen); + if (buf == NULL) + return NULL; + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + if (n >= 0 && (size_t)n < buflen) + return buf; + free(buf); + if (n < 0) + return NULL; + buflen = n + 1; + } +} + + + static const struct { const char *name; mparm parm; } by_name[] = { @@ -530,19 +557,24 @@ validate_identifier(const char *name) return true; } -msettings_error -msettings_validate(msettings *mp) +bool +msettings_validate(msettings *mp, char **errmsg) { if (mp->validated) - return NULL; + return true; // 1. The parameters have the types listed in the table in [Section // Parameters](#parameters). // (this has already been checked) // 2. At least one of **sock** and **host** must be empty. - if (nonempty(mp, MP_SOCK) && nonempty(mp, MP_HOST)) - return "With sock=, host must be 'localhost'"; + if (nonempty(mp, MP_SOCK) && nonempty(mp, MP_HOST)) { + *errmsg = allocprintf( + "With sock='%s', host must be 'localhost', not '%s'", + msetting_string(mp, MP_SOCK), + msetting_string(mp, MP_HOST)); + return false; + } // 3. The string parameter **binary** must either parse as a boolean or as a // non-negative integer. @@ -550,49 +582,64 @@ msettings_validate(msettings *mp) mp->validated = true; long level = msettings_connect_binary(mp); mp->validated = false; - if (level < 0) - return "invalid value for parameter 'binary'"; + if (level < 0) { + *errmsg = allocprintf("invalid value '%s' for parameter 'binary'", msetting_string(mp, MP_BINARY)); + return false; + } // 4. If **sock** is not empty, **tls** must be 'off'. - if (nonempty(mp, MP_SOCK) && msetting_bool(mp, MP_TLS)) - return "TLS cannot be used with Unix domain sockets"; + if (nonempty(mp, MP_SOCK) && msetting_bool(mp, MP_TLS)) { + *errmsg = allocprintf("TLS cannot be used with Unix domain sockets"); + return false; + } // 5. If **certhash** is not empty, it must be of the form `{sha256}hexdigits` // where hexdigits is a non-empty sequence of 0-9, a-f, A-F and colons. const char *certhash_msg = validate_certhash(mp); - if (certhash_msg) - return certhash_msg; - + if (certhash_msg) { + *errmsg = strdup(certhash_msg); + return false; + } // 6. If **tls** is 'off', **cert** and **certhash** must be 'off' as well. if (nonempty(mp, MP_CERT) || nonempty(mp, MP_CERTHASH)) - if (!msetting_bool(mp, MP_TLS)) - return "'cert' and 'certhash' can only be used with monetdbs:"; + if (!msetting_bool(mp, MP_TLS)) { + *errmsg = strdup("'cert' and 'certhash' can only be used with monetdbs:"); + return false; + } // 7. Parameters **database**, **tableschema** and **table** must consist only of // upper- and lowercase letters, digits, dashes and underscores. They must not // start with a dash. const char *database = msetting_string(mp, MP_DATABASE); - if (!validate_identifier(database)) - return "invalid database name"; + if (!validate_identifier(database)) { + *errmsg = allocprintf("invalid database name '%s'", database); + return false; + } const char *tableschema = msetting_string(mp, MP_TABLESCHEMA); - if (!validate_identifier(tableschema)) - return "invalid schema name"; + if (!validate_identifier(tableschema)) { + *errmsg = allocprintf("invalid schema name '%s'", tableschema); + return false; + } const char *table = msetting_string(mp, MP_TABLE); - if (!validate_identifier(table)) - return "invalid table name"; + if (!validate_identifier(table)) { + *errmsg = allocprintf("invalid table name '%s'", table); + return false; + } // 8. Parameter **port** must be -1 or in the range 1-65535. long port = msetting_long(mp, MP_PORT); bool port_ok = (port == -1 || (port >= 1 && port <= 65535)); - if (!port_ok) - return "invalid port"; + if (!port_ok) { + *errmsg = allocprintf("invalid port '%ld'", port); + return false; + } // compute this here so the getter function can take const msettings* _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org