gwyn@smoke.BRL.MIL (Doug Gwyn) (08/17/89)
We just discovered that the UNIX System V stdio writing routines, in three out of four uses of the write() system call, fail to properly deal with a short write count return, and in one case doesn't even detect an I/O error. Here are the fixes we applied: In libc/port/stdio/flsbuf.c: /* @(#)flsbuf.c 2.8 */ ... int _flsbuf(c, iop) unsigned char c; register FILE *iop; { unsigned char c1; register int w; /* DAG -- write() return count */ ... /* write out an unbuffered file, if have write perm, but no EOF */ if ( (iop->_flag & (_IONBF | _IOWRT | _IOEOF)) == (_IONBF | _IOWRT) ) { c1 = c; iop->_cnt = 0; while ((w = write(fileno(iop), (char *) &c1, 1)) == 0) ; /* DAG -- loop! */ if (w > 0) return(c); iop->_flag |= _IOERR; return(EOF); } ... int _xflsbuf(iop) register FILE *iop; { register unsigned char *base; register int n; register int w; /* DAG -- write() return count */ ... _BUFSYNC(iop); while (n > 0) /* DAG -- loop! */ if ((w = write(fileno(iop),(char*)base,(unsigned)n)) < 0) { iop->_flag |= _IOERR; return(EOF); } else { base += w; n -= w; } return(0); In libc/port/stdio/fputs.c: /* <@(#)fputs.c 3.5> */ ... int fputs(ptr, iop) char *ptr; register FILE *iop; { ... } else { /* write out to an unbuffered file */ register unsigned int cnt = strlen(ptr); register unsigned int r = cnt; /* DAG -- bytes remaining */ register int w; /* DAG -- write() return count */ while (r > 0) /* DAG -- loop! */ if ((w = write(iop->_file, ptr, r)) < 0) { iop->_flag |= _IOERR; return(EOF); /* DAG -- report error! */ } else { ptr += w; r -= w; } return cnt; }