From owner-freebsd-bugs Fri Dec 19 11:26:03 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id LAA10717 for bugs-outgoing; Fri, 19 Dec 1997 11:26:03 -0800 (PST) (envelope-from owner-freebsd-bugs) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id LAA10703 for ; Fri, 19 Dec 1997 11:25:49 -0800 (PST) (envelope-from bde@zeta.org.au) Received: (from bde@localhost) by godzilla.zeta.org.au (8.8.7/8.6.9) id GAA23848 for bugs@freebsd.org; Sat, 20 Dec 1997 06:25:00 +1100 Date: Sat, 20 Dec 1997 06:25:00 +1100 From: Bruce Evans Message-Id: <199712191925.GAA23848@godzilla.zeta.org.au> To: bugs@freebsd.org Subject: cp mishandles short writes Sender: owner-freebsd-bugs@freebsd.org X-Loop: FreeBSD.org Precedence: bulk cp of all programs mishandles short writes. It aborts the copy and prints a bogus error message using warn() although there has been no error. Short write occur for example when a tty device hangs up while a write is in progress (and SIGHUP is not delivered). Then the count of the data that has been written is returned and the next write would return -1/EIO. Please review these fixes. They haven't been tested for the unused VM_AND_BUFFER_CACHE_SYNCHRONIZED case. They don't change the behaviour if write() returns the short count of 0, but that should not happen. Bruce diff -c2 src/bin/cp/utils.c~ src/bin/cp/utils.c *** src/bin/cp/utils.c~ Sun Oct 5 18:49:22 1997 --- src/bin/cp/utils.c Tue Dec 16 05:53:06 1997 *************** *** 61,65 **** static char buf[MAXBSIZE]; struct stat to_stat, *fs; ! int ch, checkch, from_fd, rcount, rval, to_fd, wcount; #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; --- 61,66 ---- static char buf[MAXBSIZE]; struct stat to_stat, *fs; ! int ch, checkch, from_fd, rcount, rval, to_fd, wcount, wresid; ! char *bufp; #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED char *p; *************** *** 129,133 **** rval = 1; } else { ! if (write(to_fd, p, fs->st_size) != fs->st_size) { warn("%s", to.p_path); rval = 1; --- 130,140 ---- rval = 1; } else { ! for (bufp = p, wresid = fs->st_size; ; ! bufp += wcount, wresid -= wcount) ! wcount = write(to_fd, bufp, wresid); ! if (wcount >= wresid || wcount <= 0) ! break; ! } ! if (wcount != wresid) { warn("%s", to.p_path); rval = 1; *************** *** 143,148 **** { while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { ! wcount = write(to_fd, buf, rcount); ! if (rcount != wcount || wcount == -1) { warn("%s", to.p_path); rval = 1; --- 150,160 ---- { while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { ! for (bufp = buf, wresid = rcount; ; ! bufp += wcount, wresid -= wcount) { ! wcount = write(to_fd, bufp, wresid); ! if (wcount >= wresid || wcount <= 0) ! break; ! } ! if (wcount != wresid) { warn("%s", to.p_path); rval = 1;