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

Reply via email to