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