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 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