atomicio.c revision 162852
1219019Sgabor/* $OpenBSD: atomicio.c,v 1.23 2006/08/03 03:34:41 deraadt Exp $ */ 2264497Stijl/* 3219019Sgabor * Copyright (c) 2006 Damien Miller. All rights reserved. 4219019Sgabor * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. 5219019Sgabor * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. 6219019Sgabor * All rights reserved. 7219019Sgabor * 8219019Sgabor * Redistribution and use in source and binary forms, with or without 9219019Sgabor * modification, are permitted provided that the following conditions 10219019Sgabor * are met: 11219019Sgabor * 1. Redistributions of source code must retain the above copyright 12219019Sgabor * notice, this list of conditions and the following disclaimer. 13219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright 14219019Sgabor * notice, this list of conditions and the following disclaimer in the 15219019Sgabor * documentation and/or other materials provided with the distribution. 16219019Sgabor * 17219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18219019Sgabor * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19219019Sgabor * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20219019Sgabor * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21219019Sgabor * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22219019Sgabor * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23219019Sgabor * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24219019Sgabor * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25219019Sgabor * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26219019Sgabor * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27219019Sgabor */ 28219019Sgabor 29219019Sgabor#include "includes.h" 30219019Sgabor 31219019Sgabor#include <sys/param.h> 32219019Sgabor#include <sys/uio.h> 33219019Sgabor 34219019Sgabor#include <errno.h> 35219019Sgabor#include <string.h> 36219019Sgabor 37219019Sgabor#include "atomicio.h" 38219019Sgabor 39219019Sgabor/* 40219019Sgabor * ensure all of data on socket comes through. f==read || f==vwrite 41219019Sgabor */ 42219019Sgaborsize_t 43219019Sgaboratomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) 44219019Sgabor{ 45219019Sgabor char *s = _s; 46219019Sgabor size_t pos = 0; 47219019Sgabor ssize_t res; 48219019Sgabor 49219019Sgabor while (n > pos) { 50219019Sgabor res = (f) (fd, s + pos, n - pos); 51219019Sgabor switch (res) { 52219019Sgabor case -1: 53219019Sgabor#ifdef EWOULDBLOCK 54219019Sgabor if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) 55219019Sgabor#else 56219019Sgabor if (errno == EINTR || errno == EAGAIN) 57219019Sgabor#endif 58219019Sgabor continue; 59219019Sgabor return 0; 60219019Sgabor case 0: 61219019Sgabor errno = EPIPE; 62219019Sgabor return pos; 63219019Sgabor default: 64219019Sgabor pos += (size_t)res; 65219019Sgabor } 66219019Sgabor } 67219019Sgabor return (pos); 68219019Sgabor} 69219019Sgabor 70219019Sgabor/* 71219019Sgabor * ensure all of data on socket comes through. f==readv || f==writev 72219019Sgabor */ 73219019Sgaborsize_t 74219019Sgaboratomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd, 75219019Sgabor const struct iovec *_iov, int iovcnt) 76219019Sgabor{ 77219019Sgabor size_t pos = 0, rem; 78260264Sdim ssize_t res; 79219019Sgabor struct iovec iov_array[IOV_MAX], *iov = iov_array; 80219019Sgabor 81219019Sgabor if (iovcnt > IOV_MAX) { 82219019Sgabor errno = EINVAL; 83219019Sgabor return 0; 84219019Sgabor } 85219019Sgabor /* Make a copy of the iov array because we may modify it below */ 86219019Sgabor memcpy(iov, _iov, iovcnt * sizeof(*_iov)); 87219019Sgabor 88219019Sgabor for (; iovcnt > 0 && iov[0].iov_len > 0;) { 89219019Sgabor res = (f) (fd, iov, iovcnt); 90219019Sgabor switch (res) { 91219019Sgabor case -1: 92219019Sgabor if (errno == EINTR || errno == EAGAIN) 93219019Sgabor continue; 94219019Sgabor return 0; 95219019Sgabor case 0: 96260264Sdim errno = EPIPE; 97219019Sgabor return pos; 98219019Sgabor default: 99219019Sgabor rem = (size_t)res; 100219019Sgabor pos += rem; 101219019Sgabor /* skip completed iov entries */ 102219019Sgabor while (iovcnt > 0 && rem >= iov[0].iov_len) { 103219019Sgabor rem -= iov[0].iov_len; 104219019Sgabor iov++; 105219019Sgabor iovcnt--; 106219019Sgabor } 107219019Sgabor /* This shouldn't happen... */ 108219019Sgabor if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) { 109219019Sgabor errno = EFAULT; 110219019Sgabor return 0; 111219019Sgabor } 112219019Sgabor if (iovcnt == 0) 113219019Sgabor break; 114219019Sgabor /* update pointer in partially complete iov */ 115219019Sgabor iov[0].iov_base = ((char *)iov[0].iov_base) + rem; 116219019Sgabor iov[0].iov_len -= rem; 117219019Sgabor } 118219019Sgabor } 119219019Sgabor return pos; 120219019Sgabor} 121219019Sgabor