safe-read.c 2.1 KB

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