read.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* POSIX compatible read() function.
  2. Copyright (C) 2008-2021 Free Software Foundation, Inc.
  3. Written by Bruno Haible <bruno@clisp.org>, 2011.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) 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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <unistd.h>
  17. #if defined _WIN32 && ! defined __CYGWIN__
  18. # include <errno.h>
  19. # include <io.h>
  20. # define WIN32_LEAN_AND_MEAN /* avoid including junk */
  21. # include <windows.h>
  22. # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  23. # include "msvc-inval.h"
  24. # endif
  25. # if GNULIB_MSVC_NOTHROW
  26. # include "msvc-nothrow.h"
  27. # else
  28. # include <io.h>
  29. # endif
  30. /* Don't assume that UNICODE is not defined. */
  31. # undef GetNamedPipeHandleState
  32. # define GetNamedPipeHandleState GetNamedPipeHandleStateA
  33. # undef read
  34. # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
  35. static ssize_t
  36. read_nothrow (int fd, void *buf, size_t count)
  37. {
  38. ssize_t result;
  39. TRY_MSVC_INVAL
  40. {
  41. result = _read (fd, buf, count);
  42. }
  43. CATCH_MSVC_INVAL
  44. {
  45. result = -1;
  46. errno = EBADF;
  47. }
  48. DONE_MSVC_INVAL;
  49. return result;
  50. }
  51. # else
  52. # define read_nothrow _read
  53. # endif
  54. ssize_t
  55. rpl_read (int fd, void *buf, size_t count)
  56. {
  57. ssize_t ret = read_nothrow (fd, buf, count);
  58. # if GNULIB_NONBLOCKING
  59. if (ret < 0
  60. && GetLastError () == ERROR_NO_DATA)
  61. {
  62. HANDLE h = (HANDLE) _get_osfhandle (fd);
  63. if (GetFileType (h) == FILE_TYPE_PIPE)
  64. {
  65. /* h is a pipe or socket. */
  66. DWORD state;
  67. if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL, NULL, 0)
  68. && (state & PIPE_NOWAIT) != 0)
  69. /* h is a pipe in non-blocking mode.
  70. Change errno from EINVAL to EAGAIN. */
  71. errno = EAGAIN;
  72. }
  73. }
  74. # endif
  75. return ret;
  76. }
  77. #endif