- djm@cvs.openbsd.org 2006/04/16 00:52:55

[atomicio.c atomicio.h]
     introduce atomiciov() function that wraps readv/writev to retry
     interrupted transfers like atomicio() does for read/write;
     feedback deraadt@ dtucker@ stevesk@ ok deraadt@
This commit is contained in:
Damien Miller 2006-04-23 12:06:20 +10:00
parent 499a0d5ada
commit 6aa139c41f
3 changed files with 77 additions and 3 deletions

View File

@ -26,6 +26,11 @@
channels code can use to propsectivly check whether an incremental
allocation will succeed. bz #1131, debugged with the assistance of
cove AT wildpackets.com; ok dtucker@ deraadt@
- djm@cvs.openbsd.org 2006/04/16 00:52:55
[atomicio.c atomicio.h]
introduce atomiciov() function that wraps readv/writev to retry
interrupted transfers like atomicio() does for read/write;
feedback deraadt@ dtucker@ stevesk@ ok deraadt@
20060421
- (djm) [Makefile.in configure.ac session.c sshpty.c]
@ -4537,4 +4542,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.4307 2006/04/23 02:06:03 djm Exp $
$Id: ChangeLog,v 1.4308 2006/04/23 02:06:20 djm Exp $

View File

@ -1,5 +1,6 @@
/* $OpenBSD: atomicio.c,v 1.17 2006/04/01 05:51:34 djm Exp $ */
/* $OpenBSD: atomicio.c,v 1.18 2006/04/16 00:52:55 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
@ -59,3 +60,55 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
}
return (pos);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
{
size_t pos = 0, rem;
ssize_t res;
struct iovec iov_array[IOV_MAX], *iov = iov_array;
if (iovcnt > IOV_MAX) {
errno = EINVAL;
return 0;
}
/* Make a copy of the iov array because we may modify it below */
memcpy(iov, _iov, iovcnt * sizeof(*_iov));
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
if (errno == EINTR || errno == EAGAIN)
continue;
return 0;
case 0:
errno = EPIPE;
return pos;
default:
rem = (size_t)res;
pos += rem;
/* skip completed iov entries */
while (iovcnt > 0 && rem >= iov[0].iov_len) {
rem -= iov[0].iov_len;
iov++;
iovcnt--;
}
/* This shouldn't happen... */
if (rem > iov[0].iov_len || (rem > 0 && iovcnt <= 0)) {
errno = EFAULT;
return 0;
}
if (iovcnt == 0)
break;
/* update pointer in partially complete iov */
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
}
return pos;
}

View File

@ -1,6 +1,7 @@
/* $OpenBSD: atomicio.h,v 1.7 2006/03/25 22:22:42 djm Exp $ */
/* $OpenBSD: atomicio.h,v 1.8 2006/04/16 00:52:55 djm Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
@ -25,9 +26,24 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ATOMICIO_H
#define _ATOMICIO_H
#include <sys/types.h>
#include <unistd.h>
#include <sys/uio.h>
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
int, const struct iovec *, int);
#endif /* _ATOMICIO_H */