Module Name:    src
Committed By:   rin
Date:           Mon Jul 18 13:02:00 UTC 2022

Modified Files:
        src/bin/rcp: rcp.c

Log Message:
Fix bug revealed by SIGINFO support; Do not treat short read(2)/write(2)
as error (*). This occurs typically when signal is received.

(*) For older version, we already deal with short read(2) from remote
host in sink(). But for other cases, i.e., write(2) to local file in
sink(), read(2)/write(2) in source(), error was raised.

This version of rcp(1) can successfully send/receive files with older
version, even if short read(2)/write(2) occurs by SIGINFO.

Also, when real error occurs, give up immediately instead of continue to
send/receive wrong data.

Clean up the mess a little bit as well...


To generate a diff of this commit:
cvs rdiff -u -r1.51 -r1.52 src/bin/rcp/rcp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/rcp/rcp.c
diff -u src/bin/rcp/rcp.c:1.51 src/bin/rcp/rcp.c:1.52
--- src/bin/rcp/rcp.c:1.51	Sun Jun 26 09:29:59 2022
+++ src/bin/rcp/rcp.c	Mon Jul 18 13:01:59 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: rcp.c,v 1.51 2022/06/26 09:29:59 rin Exp $	*/
+/*	$NetBSD: rcp.c,v 1.52 2022/07/18 13:01:59 rin Exp $	*/
 
 /*
  * Copyright (c) 1983, 1990, 1992, 1993
@@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 19
 #if 0
 static char sccsid[] = "@(#)rcp.c	8.2 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: rcp.c,v 1.51 2022/06/26 09:29:59 rin Exp $");
+__RCSID("$NetBSD: rcp.c,v 1.52 2022/07/18 13:01:59 rin Exp $");
 #endif
 #endif /* not lint */
 
@@ -335,8 +335,10 @@ source(int argc, char *argv[])
 	BUF *bp;
 	off_t i;
 	off_t amt;
-	int fd, haderr, indx, result;
-	char *last, *name, buf[BUFSIZ];
+	size_t resid;
+	ssize_t result;
+	int fd, haderr, indx;
+	char *last, *name, *cp, buf[BUFSIZ];
 
 	for (indx = 0; indx < argc; ++indx) {
 		name = argv[indx];
@@ -396,19 +398,24 @@ next:			(void)close(fd);
 			amt = bp->cnt;
 			if (i + amt > stb.st_size)
 				amt = stb.st_size - i;
-			if (!haderr) {
-				result = read(fd, bp->buf, (size_t)amt);
-				if (result != amt)
-					haderr = result >= 0 ? EIO : errno;
-			}
-			if (haderr)
-				(void)write(rem, bp->buf, (size_t)amt);
-			else {
-				result = write(rem, bp->buf, (size_t)amt);
-				if (result != amt)
-					haderr = result >= 0 ? EIO : errno;
+			for (resid = (size_t)amt, cp = bp->buf; resid > 0;
+			    resid -= result, cp += result) {
+				result = read(fd, cp, resid);
+				if (result == -1) {
+					haderr = errno;
+					goto error;
+				}
+			}
+			for (resid = (size_t)amt, cp = bp->buf; resid > 0;
+			    resid -= result, cp += result) {
+				result = write(rem, cp, resid);
+				if (result == -1) {
+					haderr = errno;
+					goto error;
+				}
 			}
 		}
+ error:
 		if (close(fd) && !haderr)
 			haderr = errno;
 		if (!haderr)
@@ -479,10 +486,10 @@ sink(int argc, char *argv[])
 	struct stat stb;
 	struct timeval tv[2];
 	BUF *bp;
-	ssize_t j;
+	size_t resid;
+	ssize_t result;
 	off_t i;
 	off_t amt;
-	off_t count;
 	int exists, first, ofd;
 	mode_t mask;
 	mode_t mode;
@@ -649,7 +656,6 @@ bad:			run_err("%s: %s", np, strerror(er
 			(void)close(ofd);
 			continue;
 		}
-		cp = bp->buf;
 		wrerr = 0;
 
 /*
@@ -664,44 +670,33 @@ bad:			run_err("%s: %s", np, strerror(er
 	}								\
 } while(0)
 
-		count = 0;
-		for (i = 0; i < size; i += BUFSIZ) {
+		for (i = 0; i < size; i += bp->cnt) {
 			if (print_info)
 				progress(np, i, size);
-			amt = BUFSIZ;
+			amt = bp->cnt;
 			if (i + amt > size)
 				amt = size - i;
-			count += amt;
-			do {
-				j = read(rem, cp, (size_t)amt);
-				if (j == -1) {
-					run_err("%s", j ? strerror(errno) :
-					    "dropped connection");
+			for (resid = (size_t)amt, cp = bp->buf; resid > 0;
+			    resid -= result, cp += result) {
+				result = read(rem, cp, resid);
+				if (result == -1) {
+					run_err("%s", strerror(errno));
 					exit(1);
 				}
-				amt -= j;
-				cp += j;
-			} while (amt > 0);
-			if (count == bp->cnt) {
+			}
+			for (resid = (size_t)amt, cp = bp->buf; resid > 0;
+			    resid -= result, cp += result) {
 				/* Keep reading so we stay sync'd up. */
 				if (!wrerr) {
-					j = write(ofd, bp->buf, (size_t)count);
-					if (j != count) {
-						if (j >= 0)
-							errno = EIO;
+					result = write(ofd, cp, resid);
+					if (result == -1) {
 						RUN_ERR("write");
+						goto error;
 					}
 				}
-				count = 0;
-				cp = bp->buf;
 			}
 		}
-		if (count != 0 && !wrerr &&
-		    (j = write(ofd, bp->buf, (size_t)count)) != count) {
-			if (j >= 0)
-				errno = EIO;
-			RUN_ERR("write");
-		}
+ error:
 		if (ftruncate(ofd, size))
 			RUN_ERR("truncate");
 

Reply via email to