Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/rcp In sink(), upon error, avoid multiple replies to the...



details:   https://anonhg.NetBSD.org/src/rev/32e7437f289c
branches:  trunk
changeset: 971852:32e7437f289c
user:      aymeric <aymeric%NetBSD.org@localhost>
date:      Wed May 06 18:15:40 2020 +0000

description:
In sink(), upon error, avoid multiple replies to the source as this
would lead to a desynchronization of the protocol and further files or
directories to be ignored or corrupted.

Reported by Daniel Goujot, Georges-Axel Jaloyan, Ryan Lahfa, and David Naccache.

diffstat:

 bin/rcp/rcp.c |  84 ++++++++++++++++++++++++++++------------------------------
 1 files changed, 41 insertions(+), 43 deletions(-)

diffs (162 lines):

diff -r c83db4753cf4 -r 32e7437f289c bin/rcp/rcp.c
--- a/bin/rcp/rcp.c     Wed May 06 17:28:26 2020 +0000
+++ b/bin/rcp/rcp.c     Wed May 06 18:15:40 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $     */
+/*     $NetBSD: rcp.c,v 1.50 2020/05/06 18:15:40 aymeric Exp $ */
 
 /*
  * Copyright (c) 1983, 1990, 1992, 1993
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)rcp.c      8.2 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $");
+__RCSID("$NetBSD: rcp.c,v 1.50 2020/05/06 18:15:40 aymeric Exp $");
 #endif
 #endif /* not lint */
 
@@ -470,7 +470,6 @@
        static BUF buffer;
        struct stat stb;
        struct timeval tv[2];
-       enum { YES, NO, DISPLAYED } wrerr;
        BUF *bp;
        ssize_t j;
        off_t i;
@@ -480,8 +479,9 @@
        mode_t mask;
        mode_t mode;
        mode_t omode;
-       int setimes, targisdir;
+       int setimes, targisdir, wrerr;
        int wrerrno = 0;        /* pacify gcc */
+       const char *wrcontext = NULL;
        char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ];
        const char *why;
        off_t size;
@@ -624,9 +624,7 @@
                        sink(1, vect);
                        if (setimes) {
                                setimes = 0;
-                               if (utimes(np, tv) < 0)
-                                   run_err("%s: set times: %s",
-                                       np, strerror(errno));
+                               (void) utimes(np, tv);
                        }
                        if (mod_flag)
                                (void)chmod(np, mode);
@@ -644,7 +642,20 @@
                        continue;
                }
                cp = bp->buf;
-               wrerr = NO;
+               wrerr = 0;
+
+/*
+ * Like run_err(), but don't send any message to the remote end.
+ * Instead, record the first error and send that in the end.
+ */
+#define RUN_ERR(w_context) do { \
+       if (!wrerr) {                                                   \
+               wrerrno = errno;                                        \
+               wrcontext = w_context;                                  \
+               wrerr = 1;                                              \
+       }                                                               \
+} while(0)
+
                count = 0;
                for (i = 0; i < size; i += BUFSIZ) {
                        amt = BUFSIZ;
@@ -663,69 +674,56 @@
                        } while (amt > 0);
                        if (count == bp->cnt) {
                                /* Keep reading so we stay sync'd up. */
-                               if (wrerr == NO) {
+                               if (!wrerr) {
                                        j = write(ofd, bp->buf, (size_t)count);
                                        if (j != count) {
-                                               wrerr = YES;
-                                               wrerrno = j >= 0 ? EIO : errno; 
+                                               if (j >= 0)
+                                                       errno = EIO;
+                                               RUN_ERR("write");
                                        }
                                }
                                count = 0;
                                cp = bp->buf;
                        }
                }
-               if (count != 0 && wrerr == NO &&
+               if (count != 0 && !wrerr &&
                    (j = write(ofd, bp->buf, (size_t)count)) != count) {
-                       wrerr = YES;
-                       wrerrno = j >= 0 ? EIO : errno; 
+                       if (j >= 0)
+                               errno = EIO;
+                       RUN_ERR("write");
                }
-               if (ftruncate(ofd, size)) {
-                       run_err("%s: truncate: %s", np, strerror(errno));
-                       wrerr = DISPLAYED;
-               }
+               if (ftruncate(ofd, size))
+                       RUN_ERR("truncate");
+
                if (pflag) {
                        if (exists || omode != mode)
                                if (fchmod(ofd, omode))
-                                       run_err("%s: set mode: %s",
-                                           np, strerror(errno));
+                                       RUN_ERR("set mode");
                } else {
                        if (!exists && omode != mode)
                                if (fchmod(ofd, omode & ~mask))
-                                       run_err("%s: set mode: %s",
-                                           np, strerror(errno));
+                                       RUN_ERR("set mode");
                }
 #ifndef __SVR4
-               if (setimes && wrerr == NO) {
+               if (setimes && !wrerr) {
                        setimes = 0;
-                       if (futimes(ofd, tv) < 0) {
-                               run_err("%s: set times: %s",
-                                   np, strerror(errno));
-                               wrerr = DISPLAYED;
-                       }
+                       if (futimes(ofd, tv) < 0)
+                               RUN_ERR("set times");
                }
 #endif
                (void)close(ofd);
 #ifdef __SVR4
-               if (setimes && wrerr == NO) {
+               if (setimes && !wrerr) {
                        setimes = 0;
-                       if (utimes(np, tv) < 0) {
-                               run_err("%s: set times: %s",
-                                   np, strerror(errno));
-                               wrerr = DISPLAYED;
-                       }
+                       if (utimes(np, tv) < 0)
+                               RUN_ERR("set times");
                }
 #endif
                (void)response();
-               switch(wrerr) {
-               case YES:
-                       run_err("%s: write: %s", np, strerror(wrerrno));
-                       break;
-               case NO:
+               if (wrerr)
+                       run_err("%s: %s: %s", np, wrcontext, strerror(wrerrno));
+               else
                        (void)write(rem, "", 1);
-                       break;
-               case DISPLAYED:
-                       break;
-               }
        }
 
 out:



Home | Main Index | Thread Index | Old Index