1e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */
2e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich/*
3e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * Copyright (c) 2006 Damien Miller. All rights reserved.
4e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
5e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
6e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * All rights reserved.
7e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich *
8e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * Redistribution and use in source and binary forms, with or without
9e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * modification, are permitted provided that the following conditions
10e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * are met:
11e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * 1. Redistributions of source code must retain the above copyright
12e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich *    notice, this list of conditions and the following disclaimer.
13e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * 2. Redistributions in binary form must reproduce the above copyright
14e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich *    notice, this list of conditions and the following disclaimer in the
15e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich *    documentation and/or other materials provided with the distribution.
16e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich *
17e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich */
28e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich
29e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich#include <sys/param.h>
30e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich
31e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich#include <errno.h>
32e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich#include <poll.h>
33e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich#include <unistd.h>
34e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich
35e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich#include "atomicio.h"
36e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich
37e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich/*
38e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich * ensure all of data on socket comes through. f==read || f==vwrite
39e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich */
40e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevichsize_t
41e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevichatomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
42e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich{
43e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	char *s = _s;
44e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	size_t pos = 0;
45e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	ssize_t res;
46e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	struct pollfd pfd;
47e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich
48e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	pfd.fd = fd;
49e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	pfd.events = f == read ? POLLIN : POLLOUT;
50e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	while (n > pos) {
51e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		res = (f) (fd, s + pos, n - pos);
52e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		switch (res) {
53e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		case -1:
54e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			if (errno == EINTR)
55e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich				continue;
56e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			if ((errno == EAGAIN) || (errno == ENOBUFS)) {
57e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich				(void)poll(&pfd, 1, -1);
58e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich				continue;
59e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			}
60e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			return 0;
61e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		case 0:
62e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			errno = EPIPE;
63e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			return pos;
64e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		default:
65e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich			pos += (size_t)res;
66e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich		}
67e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	}
68e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich	return (pos);
69e4e83f8147f92141cd02cc46cccca088c527ea2aNick Kralevich}
70