]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Improve the output when a negotiation fails.
authorWayne Davison <wayne@opencoder.net>
Sat, 27 Jun 2020 17:39:16 +0000 (10:39 -0700)
committerWayne Davison <wayne@opencoder.net>
Sat, 27 Jun 2020 17:51:29 +0000 (10:51 -0700)
cleanup.c
compat.c

index cf8330ac9fcf5743b32cd96f74de3513277ebe87..ab981ec7b92c3539e11c76a3af2c2dd3950b5e71 100644 (file)
--- a/cleanup.c
+++ b/cleanup.c
@@ -221,8 +221,13 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
                /* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
                 * we don't want to output a duplicate error. */
                if ((exit_code && line > 0)
-                || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
+                || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) {
+#ifdef HAVE_USLEEP /* Try for a teeny delay if both sender & receiver are sending a msg at the same time. */
+                       if (am_server && exit_code)
+                               usleep(50);
+#endif
                        log_exit(exit_code, exit_file, exit_line);
+               }
 
 #include "case_N.h"
                switch_step++;
index bf0b4e6d149f2179112887ed0f375c092fade02a..6d260f0dd8551bdd7106b2f07c2a22bc05756a86 100644 (file)
--- a/compat.c
+++ b/compat.c
@@ -313,6 +313,9 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
        return to - tobuf;
 }
 
+/* This routine is always called with a tmpbuf of MAX_NSTR_STRLEN length, but the
+ * buffer may be pre-populated with a "len" length string to use OR a len of -1
+ * to tell us to read a string from the fd. */
 static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf, int len)
 {
        struct name_num_item *ret = NULL;
@@ -328,23 +331,26 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
        }
 
        if (len > 0) {
+               struct name_num_item *nni;
                int best = nno->saw_len; /* We want best == 1 from the client list, so start with a big number. */
-               char *tok;
-               if (am_server) {
-                       int j;
-                       /* Since we're parsing client names, anything in our list that we parse first is #1. */
-                       for (j = 0; j < nno->saw_len; j++) {
-                               if (nno->saw[j])
-                                       nno->saw[j] = 1;
-                       }
-               }
-               for (tok = strtok(tmpbuf, " \t"); tok; tok = strtok(NULL, " \t")) {
-                       struct name_num_item *nni = get_nni_by_name(nno, tok, -1);
+               char *space, *tok = tmpbuf;
+               while (tok) {
+                       while (*tok == ' ') tok++; /* Should be unneeded... */
+                       if (!*tok)
+                               break;
+                       if ((space = strchr(tok, ' ')) != NULL)
+                               *space = '\0';
+                       nni = get_nni_by_name(nno, tok, -1);
+                       if (space) {
+                               *space = ' ';
+                               tok = space + 1;
+                       } else
+                               tok = NULL;
                        if (!nni || !nno->saw[nni->num] || best <= nno->saw[nni->num])
                                continue;
                        ret = nni;
                        best = nno->saw[nni->num];
-                       if (best == 1)
+                       if (best == 1 || am_server) /* The server side stops at the first acceptable client choice */
                                break;
                }
                if (ret) {
@@ -356,8 +362,26 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
                }
        }
 
-       if (!am_server || !do_negotiated_strings)
+       if (!am_server || !do_negotiated_strings) {
+               char *cp = tmpbuf;
+               int j;
                rprintf(FERROR, "Failed to negotiate a %s choice.\n", nno->type);
+               rprintf(FERROR, "%s list: %s\n", am_server ? "Client" : "Server", tmpbuf);
+               /* Recreate our original list from the saw values. This can't overflow our huge
+                * buffer because we don't have enough valid entries to get anywhere close. */
+               for (j = 1; j <= nno->saw_len; j++) {
+                       struct name_num_item *nni;
+                       for (nni = nno->list; nni->name; nni++) {
+                               if (nno->saw[nni->num] == j) {
+                                       *cp++ = ' ';
+                                       cp += strlcpy(cp, nni->name, MAX_NSTR_STRLEN - (cp - tmpbuf));
+                                       break;
+                               }
+                       }
+               }
+               rprintf(FERROR, "%s list:%s\n", am_server ? "Server" : "Client", tmpbuf);
+       }
+
        exit_cleanup(RERR_UNSUPPORTED);
 }