1*f4faee91Sderaadt /* $OpenBSD: atomicio.c,v 1.11 2012/12/04 02:24:47 deraadt Exp $ */
246842ea9Sericj /*
362f5b9b7Stobias * Copyright (c) 2006 Damien Miller. All rights reserved.
462f5b9b7Stobias * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
546842ea9Sericj * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
646842ea9Sericj * All rights reserved.
746842ea9Sericj *
846842ea9Sericj * Redistribution and use in source and binary forms, with or without
946842ea9Sericj * modification, are permitted provided that the following conditions
1046842ea9Sericj * are met:
1146842ea9Sericj * 1. Redistributions of source code must retain the above copyright
1246842ea9Sericj * notice, this list of conditions and the following disclaimer.
1346842ea9Sericj * 2. Redistributions in binary form must reproduce the above copyright
1446842ea9Sericj * notice, this list of conditions and the following disclaimer in the
1546842ea9Sericj * documentation and/or other materials provided with the distribution.
1646842ea9Sericj *
1746842ea9Sericj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1846842ea9Sericj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1946842ea9Sericj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2046842ea9Sericj * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2146842ea9Sericj * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2246842ea9Sericj * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2346842ea9Sericj * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2446842ea9Sericj * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2546842ea9Sericj * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2646842ea9Sericj * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2746842ea9Sericj */
2846842ea9Sericj
2946842ea9Sericj #include <errno.h>
3062f5b9b7Stobias #include <poll.h>
3146842ea9Sericj #include <unistd.h>
3262f5b9b7Stobias
33dcb0a6f6Savsm #include "atomicio.h"
34d33b10b9Sderaadt
3546842ea9Sericj /*
36dcb0a6f6Savsm * ensure all of data on socket comes through. f==read || f==vwrite
3746842ea9Sericj */
38dcb0a6f6Savsm size_t
atomicio(ssize_t (* f)(int,void *,size_t),int fd,void * _s,size_t n)3962f5b9b7Stobias atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
4046842ea9Sericj {
4146842ea9Sericj char *s = _s;
42dcb0a6f6Savsm size_t pos = 0;
43dcb0a6f6Savsm ssize_t res;
4462f5b9b7Stobias struct pollfd pfd;
4546842ea9Sericj
4662f5b9b7Stobias pfd.fd = fd;
4762f5b9b7Stobias pfd.events = f == read ? POLLIN : POLLOUT;
48dcb0a6f6Savsm while (n > pos) {
4946842ea9Sericj res = (f) (fd, s + pos, n - pos);
5046842ea9Sericj switch (res) {
5146842ea9Sericj case -1:
5262f5b9b7Stobias if (errno == EINTR)
5346842ea9Sericj continue;
5481dc5f33Sjeremy if ((errno == EAGAIN) || (errno == ENOBUFS)) {
5562f5b9b7Stobias (void)poll(&pfd, 1, -1);
5662f5b9b7Stobias continue;
5762f5b9b7Stobias }
58dcb0a6f6Savsm return 0;
5946842ea9Sericj case 0:
60dcb0a6f6Savsm errno = EPIPE;
61dcb0a6f6Savsm return pos;
6246842ea9Sericj default:
63f24b2c8aSotto pos += (size_t)res;
6446842ea9Sericj }
6546842ea9Sericj }
6662f5b9b7Stobias return (pos);
6746842ea9Sericj }
68