static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; const PRIOVec *tmp_iov; #define LOCAL_MAXIOV 8 PRIOVec local_iov[LOCAL_MAXIOV]; PRIOVec *iov_copy = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* * Assume the first writev will succeed. Copy iov's only on * failure. */ tmp_iov = iov; for (index = 0; index < iov_size; index++) sz += iov[index].iov_len; iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ if (tmp_iov == iov) { /* * The first writev failed so we * must copy iov's around. * Avoid calloc/free if there * are few enough iov's. */ if (iov_size - index <= LOCAL_MAXIOV) iov_copy = local_iov; else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) * sizeof *iov_copy)) == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } tmp_iov = iov_copy; } PR_ASSERT(tmp_iov == iov_copy); /* fill in the first partial read */ iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); iov_copy[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { iov_copy[iov_cnt].iov_base = iov[index].iov_base; iov_copy[iov_cnt].iov_len = iov[index].iov_len; } } } if (iov_copy != local_iov) PR_DELETE(iov_copy); return count; }
static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; PRIOVec *tmp_iov = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ #if defined(XP_UNIX) struct timeval tv, *tvp; fd_set wd; FD_ZERO(&wd); if (timeout == PR_INTERVAL_NO_TIMEOUT) tvp = NULL; else if (timeout != PR_INTERVAL_NO_WAIT) { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } tmp_iov = (PRIOVec *)PR_CALLOC(iov_size * sizeof(PRIOVec)); if (!tmp_iov) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } for (index=0; index<iov_size; index++) { sz += iov[index].iov_len; tmp_iov[index].iov_base = iov[index].iov_base; tmp_iov[index].iov_len = iov[index].iov_len; } iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ /* fill in the first partial read */ tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); tmp_iov[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { tmp_iov[iov_cnt].iov_base = iov[index].iov_base; tmp_iov[iov_cnt].iov_len = iov[index].iov_len; } } } if (tmp_iov) PR_DELETE(tmp_iov); return count; }