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>
