1170754Sdelphij/* Buffer primitives for comparison operations. 2170754Sdelphij 3170754Sdelphij Copyright (C) 1993, 1995, 1998, 2001, 2002 Free Software Foundation, Inc. 4170754Sdelphij 5170754Sdelphij This program is free software; you can redistribute it and/or modify 6170754Sdelphij it under the terms of the GNU General Public License as published by 7170754Sdelphij the Free Software Foundation; either version 2, or (at your option) 8170754Sdelphij any later version. 9170754Sdelphij 10170754Sdelphij This program is distributed in the hope that it will be useful, 11170754Sdelphij but WITHOUT ANY WARRANTY; without even the implied warranty of 12170754Sdelphij MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13170754Sdelphij GNU General Public License for more details. 14170754Sdelphij 15170754Sdelphij You should have received a copy of the GNU General Public License 16170754Sdelphij along with this program; see the file COPYING. 17170754Sdelphij If not, write to the Free Software Foundation, 18170754Sdelphij 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19170754Sdelphij 20170754Sdelphij#if HAVE_CONFIG_H 21170754Sdelphij# include <config.h> 22170754Sdelphij#endif 23170754Sdelphij 24170754Sdelphij#include <errno.h> 25170754Sdelphij#include <limits.h> 26170754Sdelphij 27170754Sdelphij#include <signal.h> 28170754Sdelphij#ifndef SA_RESTART 29170754Sdelphij# ifdef SA_INTERRUPT /* e.g. SunOS 4.1.x */ 30170754Sdelphij# define SA_RESTART SA_INTERRUPT 31170754Sdelphij# else 32170754Sdelphij# define SA_RESTART 0 33170754Sdelphij# endif 34170754Sdelphij#endif 35170754Sdelphij 36170754Sdelphij#if HAVE_UNISTD_H 37170754Sdelphij# include <unistd.h> 38170754Sdelphij#endif 39170754Sdelphij 40170754Sdelphij#if HAVE_INTTYPES_H 41170754Sdelphij# include <inttypes.h> 42170754Sdelphij#endif 43170754Sdelphij 44170754Sdelphij#include <sys/types.h> 45170754Sdelphij#include "cmpbuf.h" 46170754Sdelphij 47170754Sdelphij/* Determine whether an integer type is signed, and its bounds. 48170754Sdelphij This code assumes two's (or one's!) complement with no holes. */ 49170754Sdelphij 50170754Sdelphij/* The extra casts work around common compiler bugs, 51170754Sdelphij e.g. Cray C 5.0.3.0 when t == time_t. */ 52170754Sdelphij#ifndef TYPE_SIGNED 53170754Sdelphij# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) 54170754Sdelphij#endif 55170754Sdelphij#ifndef TYPE_MINIMUM 56170754Sdelphij# define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \ 57170754Sdelphij ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) \ 58170754Sdelphij : (t) 0)) 59170754Sdelphij#endif 60170754Sdelphij#ifndef TYPE_MAXIMUM 61170754Sdelphij# define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t))) 62170754Sdelphij#endif 63170754Sdelphij 64170754Sdelphij#ifndef PTRDIFF_MAX 65170754Sdelphij# define PTRDIFF_MAX TYPE_MAXIMUM (ptrdiff_t) 66170754Sdelphij#endif 67170754Sdelphij#ifndef SIZE_MAX 68170754Sdelphij# define SIZE_MAX TYPE_MAXIMUM (size_t) 69170754Sdelphij#endif 70170754Sdelphij#ifndef SSIZE_MAX 71170754Sdelphij# define SSIZE_MAX TYPE_MAXIMUM (ssize_t) 72170754Sdelphij#endif 73170754Sdelphij 74170754Sdelphij#undef MIN 75170754Sdelphij#define MIN(a, b) ((a) <= (b) ? (a) : (b)) 76170754Sdelphij 77170754Sdelphij/* Read NBYTES bytes from descriptor FD into BUF. 78170754Sdelphij NBYTES must not be SIZE_MAX. 79170754Sdelphij Return the number of characters successfully read. 80170754Sdelphij On error, return SIZE_MAX, setting errno. 81170754Sdelphij The number returned is always NBYTES unless end-of-file or error. */ 82170754Sdelphij 83170754Sdelphijsize_t 84170754Sdelphijblock_read (int fd, char *buf, size_t nbytes) 85170754Sdelphij{ 86170754Sdelphij char *bp = buf; 87170754Sdelphij char const *buflim = buf + nbytes; 88170754Sdelphij size_t readlim = SSIZE_MAX; 89170754Sdelphij 90170754Sdelphij do 91170754Sdelphij { 92170754Sdelphij size_t bytes_to_read = MIN (buflim - bp, readlim); 93170754Sdelphij ssize_t nread = read (fd, bp, bytes_to_read); 94170754Sdelphij if (nread <= 0) 95170754Sdelphij { 96170754Sdelphij if (nread == 0) 97170754Sdelphij break; 98170754Sdelphij 99170754Sdelphij /* Accommodate Tru64 5.1, which can't read more than INT_MAX 100170754Sdelphij bytes at a time. They call that a 64-bit OS? */ 101170754Sdelphij if (errno == EINVAL && INT_MAX < bytes_to_read) 102170754Sdelphij { 103170754Sdelphij readlim = INT_MAX; 104170754Sdelphij continue; 105170754Sdelphij } 106170754Sdelphij 107170754Sdelphij /* This is needed for programs that have signal handlers on 108170754Sdelphij older hosts without SA_RESTART. It also accommodates 109170754Sdelphij ancient AIX hosts that set errno to EINTR after uncaught 110170754Sdelphij SIGCONT. See <news:1r77ojINN85n@ftp.UU.NET> 111170754Sdelphij (1993-04-22). */ 112170754Sdelphij if (! SA_RESTART && errno == EINTR) 113170754Sdelphij continue; 114170754Sdelphij 115170754Sdelphij return SIZE_MAX; 116170754Sdelphij } 117170754Sdelphij bp += nread; 118170754Sdelphij } 119170754Sdelphij while (bp < buflim); 120170754Sdelphij 121170754Sdelphij return bp - buf; 122170754Sdelphij} 123170754Sdelphij 124170754Sdelphij/* Least common multiple of two buffer sizes A and B. However, if 125170754Sdelphij either A or B is zero, or if the multiple is greater than LCM_MAX, 126170754Sdelphij return a reasonable buffer size. */ 127170754Sdelphij 128170754Sdelphijsize_t 129170754Sdelphijbuffer_lcm (size_t a, size_t b, size_t lcm_max) 130170754Sdelphij{ 131170754Sdelphij size_t lcm, m, n, q, r; 132170754Sdelphij 133170754Sdelphij /* Yield reasonable values if buffer sizes are zero. */ 134170754Sdelphij if (!a) 135170754Sdelphij return b ? b : 8 * 1024; 136170754Sdelphij if (!b) 137170754Sdelphij return a; 138170754Sdelphij 139170754Sdelphij /* n = gcd (a, b) */ 140170754Sdelphij for (m = a, n = b; (r = m % n) != 0; m = n, n = r) 141170754Sdelphij continue; 142170754Sdelphij 143170754Sdelphij /* Yield a if there is an overflow. */ 144170754Sdelphij q = a / n; 145170754Sdelphij lcm = q * b; 146170754Sdelphij return lcm <= lcm_max && lcm / b == q ? lcm : a; 147170754Sdelphij} 148