1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */
2ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman/*
36fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell * Copyright (c) 2006 Damien Miller. All rights reserved.
46fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner * All rights reserved.
7ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman *
86fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell * Redistribution and use in source and binary forms, with or without
9ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman * modification, are permitted provided that the following conditions
10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner * are met:
11c3aae25116e66c177579b0b79182b09340b19753Chris Lattner * 1. Redistributions of source code must retain the above copyright
12ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman *    notice, this list of conditions and the following disclaimer.
13cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner * 2. Redistributions in binary form must reproduce the above copyright
14cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner *    notice, this list of conditions and the following disclaimer in the
15cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner *    documentation and/or other materials provided with the distribution.
16cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner *
17cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
214b84086e89d86fb16f562166d9fea8df37db6be7Dan Gohman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24acaf09dbe4a6781163857db1321bbd5795e7d410Dan Gohman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255892d47a625638a90afeb31dd4f6f80a2f9bacdeChris Lattner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26322812e603705e1c2037313633e72f689524b163Evan Cheng * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27eb19e40efbd3cae80c908a30cdf4d33450733c45Chris Lattner */
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
29d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke#include <sys/param.h>
30fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
31fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman#include <errno.h>
32fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman#include <poll.h>
33fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman#include <unistd.h>
34fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
356e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel#include "atomicio.h"
36fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
37fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman/*
38fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman * ensure all of data on socket comes through. f==read || f==vwrite
39fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman */
408e4018e2de52c534405d7155c7009d0b35afb861Cedric Venetsize_t
418e4018e2de52c534405d7155c7009d0b35afb861Cedric Venetatomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
42c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif{
43fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman	char *s = _s;
44fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman	size_t pos = 0;
45c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif	ssize_t res;
46fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman	struct pollfd pfd;
47fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
48fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman	pfd.fd = fd;
49c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif	pfd.events = f == read ? POLLIN : POLLOUT;
50c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif	while (n > pos) {
51c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif		res = (f) (fd, s + pos, n - pos);
52fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman		switch (res) {
53fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman		case -1:
54fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman			if (errno == EINTR)
55fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman				continue;
56fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman			if ((errno == EAGAIN) || (errno == ENOBUFS)) {
57fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman				(void)poll(&pfd, 1, -1);
58c3aae25116e66c177579b0b79182b09340b19753Chris Lattner				continue;
5925cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands			}
6025cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands			return 0;
6125cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands		case 0:
6225cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands			errno = EPIPE;
6325cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands			return pos;
6425cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands		default:
65c3aae25116e66c177579b0b79182b09340b19753Chris Lattner			pos += (size_t)res;
66c3aae25116e66c177579b0b79182b09340b19753Chris Lattner		}
67c3aae25116e66c177579b0b79182b09340b19753Chris Lattner	}
68c3aae25116e66c177579b0b79182b09340b19753Chris Lattner	return (pos);
69c3aae25116e66c177579b0b79182b09340b19753Chris Lattner}
70c3aae25116e66c177579b0b79182b09340b19753Chris Lattner