1*680a9cb8SJohn Marino /* An interface to read and write that retries after interrupts. 2*680a9cb8SJohn Marino 3*680a9cb8SJohn Marino Copyright (C) 1993-1994, 1998, 2002-2006, 2009-2014 Free Software 4*680a9cb8SJohn Marino Foundation, Inc. 5*680a9cb8SJohn Marino 6*680a9cb8SJohn Marino This program is free software: you can redistribute it and/or modify 7*680a9cb8SJohn Marino it under the terms of the GNU General Public License as published by 8*680a9cb8SJohn Marino the Free Software Foundation; either version 3 of the License, or 9*680a9cb8SJohn Marino (at your option) any later version. 10*680a9cb8SJohn Marino 11*680a9cb8SJohn Marino This program is distributed in the hope that it will be useful, 12*680a9cb8SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 13*680a9cb8SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*680a9cb8SJohn Marino GNU General Public License for more details. 15*680a9cb8SJohn Marino 16*680a9cb8SJohn Marino You should have received a copy of the GNU General Public License 17*680a9cb8SJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18*680a9cb8SJohn Marino 19*680a9cb8SJohn Marino #include <config.h> 20*680a9cb8SJohn Marino 21*680a9cb8SJohn Marino /* Specification. */ 22*680a9cb8SJohn Marino #ifdef SAFE_WRITE 23*680a9cb8SJohn Marino # include "safe-write.h" 24*680a9cb8SJohn Marino #else 25*680a9cb8SJohn Marino # include "safe-read.h" 26*680a9cb8SJohn Marino #endif 27*680a9cb8SJohn Marino 28*680a9cb8SJohn Marino /* Get ssize_t. */ 29*680a9cb8SJohn Marino #include <sys/types.h> 30*680a9cb8SJohn Marino #include <unistd.h> 31*680a9cb8SJohn Marino 32*680a9cb8SJohn Marino #include <errno.h> 33*680a9cb8SJohn Marino 34*680a9cb8SJohn Marino #ifdef EINTR 35*680a9cb8SJohn Marino # define IS_EINTR(x) ((x) == EINTR) 36*680a9cb8SJohn Marino #else 37*680a9cb8SJohn Marino # define IS_EINTR(x) 0 38*680a9cb8SJohn Marino #endif 39*680a9cb8SJohn Marino 40*680a9cb8SJohn Marino #include <limits.h> 41*680a9cb8SJohn Marino 42*680a9cb8SJohn Marino #ifdef SAFE_WRITE 43*680a9cb8SJohn Marino # define safe_rw safe_write 44*680a9cb8SJohn Marino # define rw write 45*680a9cb8SJohn Marino #else 46*680a9cb8SJohn Marino # define safe_rw safe_read 47*680a9cb8SJohn Marino # define rw read 48*680a9cb8SJohn Marino # undef const 49*680a9cb8SJohn Marino # define const /* empty */ 50*680a9cb8SJohn Marino #endif 51*680a9cb8SJohn Marino 52*680a9cb8SJohn Marino /* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if 53*680a9cb8SJohn Marino interrupted. Return the actual number of bytes read(written), zero for EOF, 54*680a9cb8SJohn Marino or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ 55*680a9cb8SJohn Marino size_t 56*680a9cb8SJohn Marino safe_rw (int fd, void const *buf, size_t count) 57*680a9cb8SJohn Marino { 58*680a9cb8SJohn Marino /* Work around a bug in Tru64 5.1. Attempting to read more than 59*680a9cb8SJohn Marino INT_MAX bytes fails with errno == EINVAL. See 60*680a9cb8SJohn Marino <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>. 61*680a9cb8SJohn Marino When decreasing COUNT, keep it block-aligned. */ 62*680a9cb8SJohn Marino enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; 63*680a9cb8SJohn Marino 64*680a9cb8SJohn Marino for (;;) 65*680a9cb8SJohn Marino { 66*680a9cb8SJohn Marino ssize_t result = rw (fd, buf, count); 67*680a9cb8SJohn Marino 68*680a9cb8SJohn Marino if (0 <= result) 69*680a9cb8SJohn Marino return result; 70*680a9cb8SJohn Marino else if (IS_EINTR (errno)) 71*680a9cb8SJohn Marino continue; 72*680a9cb8SJohn Marino else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) 73*680a9cb8SJohn Marino count = BUGGY_READ_MAXIMUM; 74*680a9cb8SJohn Marino else 75*680a9cb8SJohn Marino return result; 76*680a9cb8SJohn Marino } 77*680a9cb8SJohn Marino } 78