xref: /onnv-gate/usr/src/cmd/ssh/libssh/common/atomicio.c (revision 5087:929c96aa57f2)
10Sstevel@tonic-gate /*
2*5087Sjp161948  * Copyright (c) 2006 Damien Miller. All rights reserved.
3*5087Sjp161948  * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
40Sstevel@tonic-gate  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
50Sstevel@tonic-gate  * All rights reserved.
60Sstevel@tonic-gate  *
70Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
80Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
90Sstevel@tonic-gate  * are met:
100Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
110Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
120Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
140Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
170Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
180Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
190Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
200Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
210Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
220Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
230Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
240Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
250Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include "includes.h"
290Sstevel@tonic-gate RCSID("$OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp $");
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include "atomicio.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  * ensure all of data on socket comes through. f==read || f==write
370Sstevel@tonic-gate  */
380Sstevel@tonic-gate ssize_t
390Sstevel@tonic-gate atomicio(f, fd, _s, n)
400Sstevel@tonic-gate 	ssize_t (*f) ();
410Sstevel@tonic-gate 	int fd;
420Sstevel@tonic-gate 	void *_s;
430Sstevel@tonic-gate 	size_t n;
440Sstevel@tonic-gate {
450Sstevel@tonic-gate 	char *s = _s;
460Sstevel@tonic-gate 	ssize_t res, pos = 0;
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 	while (n > pos) {
490Sstevel@tonic-gate 		res = (f) (fd, s + pos, n - pos);
500Sstevel@tonic-gate 		switch (res) {
510Sstevel@tonic-gate 		case -1:
520Sstevel@tonic-gate #ifdef EWOULDBLOCK
530Sstevel@tonic-gate 			if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
540Sstevel@tonic-gate #else
550Sstevel@tonic-gate 			if (errno == EINTR || errno == EAGAIN)
560Sstevel@tonic-gate #endif
570Sstevel@tonic-gate 				continue;
580Sstevel@tonic-gate 			/* FALLTHROUGH */
590Sstevel@tonic-gate 		case 0:
600Sstevel@tonic-gate 			return (res);
610Sstevel@tonic-gate 		default:
620Sstevel@tonic-gate 			pos += res;
630Sstevel@tonic-gate 		}
640Sstevel@tonic-gate 	}
650Sstevel@tonic-gate 	return (pos);
660Sstevel@tonic-gate }
67*5087Sjp161948 
68*5087Sjp161948 /*
69*5087Sjp161948  * ensure all of data on socket comes through. f==readv || f==writev
70*5087Sjp161948  */
71*5087Sjp161948 size_t
atomiciov(ssize_t (* f)(int,const struct iovec *,int),int fd,const struct iovec * _iov,int iovcnt)72*5087Sjp161948 atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
73*5087Sjp161948     const struct iovec *_iov, int iovcnt)
74*5087Sjp161948 {
75*5087Sjp161948 	size_t pos = 0, rem;
76*5087Sjp161948 	ssize_t res;
77*5087Sjp161948 	struct iovec iov_array[IOV_MAX], *iov = iov_array;
78*5087Sjp161948 
79*5087Sjp161948 	if (iovcnt > IOV_MAX) {
80*5087Sjp161948 		errno = EINVAL;
81*5087Sjp161948 		return 0;
82*5087Sjp161948 	}
83*5087Sjp161948 	/* Make a copy of the iov array because we may modify it below */
84*5087Sjp161948 	memcpy(iov, _iov, iovcnt * sizeof(*_iov));
85*5087Sjp161948 
86*5087Sjp161948 	for (; iovcnt > 0 && iov[0].iov_len > 0;) {
87*5087Sjp161948 		res = (f) (fd, iov, iovcnt);
88*5087Sjp161948 		switch (res) {
89*5087Sjp161948 		case -1:
90*5087Sjp161948 			if (errno == EINTR || errno == EAGAIN)
91*5087Sjp161948 				continue;
92*5087Sjp161948 			return 0;
93*5087Sjp161948 		case 0:
94*5087Sjp161948 			errno = EPIPE;
95*5087Sjp161948 			return pos;
96*5087Sjp161948 		default:
97*5087Sjp161948 			rem = (size_t)res;
98*5087Sjp161948 			pos += rem;
99*5087Sjp161948 			/* skip completed iov entries */
100*5087Sjp161948 			while (iovcnt > 0 && rem >= iov[0].iov_len) {
101*5087Sjp161948 				rem -= iov[0].iov_len;
102*5087Sjp161948 				iov++;
103*5087Sjp161948 				iovcnt--;
104*5087Sjp161948 			}
105*5087Sjp161948 			/* This shouldn't happen... */
106*5087Sjp161948 			if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
107*5087Sjp161948 				errno = EFAULT;
108*5087Sjp161948 				return 0;
109*5087Sjp161948 			}
110*5087Sjp161948 			if (iovcnt == 0)
111*5087Sjp161948 				break;
112*5087Sjp161948 			/* update pointer in partially complete iov */
113*5087Sjp161948 			iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
114*5087Sjp161948 			iov[0].iov_len -= rem;
115*5087Sjp161948 		}
116*5087Sjp161948 	}
117*5087Sjp161948 	return pos;
118*5087Sjp161948 }
119