Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Dec 1997 06:25:00 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bugs@freebsd.org
Subject:   cp mishandles short writes
Message-ID:  <199712191925.GAA23848@godzilla.zeta.org.au>

index | next in thread | raw e-mail

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;


help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199712191925.GAA23848>