fcntl.m4 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. # fcntl.m4 serial 11
  2. dnl Copyright (C) 2009-2021 Free Software Foundation, Inc.
  3. dnl This file is free software; the Free Software Foundation
  4. dnl gives unlimited permission to copy and/or distribute it,
  5. dnl with or without modifications, as long as this notice is preserved.
  6. # For now, this module ensures that fcntl()
  7. # - supports F_DUPFD correctly
  8. # - supports or emulates F_DUPFD_CLOEXEC
  9. # - supports F_GETFD
  10. # Still to be ported to mingw:
  11. # - F_SETFD
  12. # - F_GETFL, F_SETFL
  13. # - F_GETOWN, F_SETOWN
  14. # - F_GETLK, F_SETLK, F_SETLKW
  15. AC_DEFUN([gl_FUNC_FCNTL],
  16. [
  17. dnl Persuade glibc to expose F_DUPFD_CLOEXEC.
  18. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
  19. AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
  20. AC_REQUIRE([AC_CANONICAL_HOST])
  21. AC_CHECK_FUNCS_ONCE([fcntl])
  22. if test $ac_cv_func_fcntl = no; then
  23. gl_REPLACE_FCNTL
  24. else
  25. dnl cygwin 1.5.x F_DUPFD has wrong errno, and allows negative target
  26. dnl haiku alpha 2 F_DUPFD has wrong errno
  27. AC_CACHE_CHECK([whether fcntl handles F_DUPFD correctly],
  28. [gl_cv_func_fcntl_f_dupfd_works],
  29. [AC_RUN_IFELSE(
  30. [AC_LANG_PROGRAM(
  31. [[#include <errno.h>
  32. #include <fcntl.h>
  33. #include <limits.h>
  34. #include <sys/resource.h>
  35. #include <unistd.h>
  36. ]GL_MDA_DEFINES[
  37. #ifndef RLIM_SAVED_CUR
  38. # define RLIM_SAVED_CUR RLIM_INFINITY
  39. #endif
  40. #ifndef RLIM_SAVED_MAX
  41. # define RLIM_SAVED_MAX RLIM_INFINITY
  42. #endif
  43. ]],
  44. [[int result = 0;
  45. int bad_fd = INT_MAX;
  46. struct rlimit rlim;
  47. if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
  48. && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX
  49. && rlim.rlim_cur != RLIM_INFINITY
  50. && rlim.rlim_cur != RLIM_SAVED_MAX
  51. && rlim.rlim_cur != RLIM_SAVED_CUR)
  52. bad_fd = rlim.rlim_cur;
  53. if (fcntl (0, F_DUPFD, -1) != -1) result |= 1;
  54. if (errno != EINVAL) result |= 2;
  55. if (fcntl (0, F_DUPFD, bad_fd) != -1) result |= 4;
  56. if (errno != EINVAL) result |= 8;
  57. /* On OS/2 kLIBC, F_DUPFD does not work on a directory fd */
  58. {
  59. int fd;
  60. fd = open (".", O_RDONLY);
  61. if (fd == -1)
  62. result |= 16;
  63. else if (fcntl (fd, F_DUPFD, STDERR_FILENO + 1) == -1)
  64. result |= 32;
  65. close (fd);
  66. }
  67. return result;]])],
  68. [gl_cv_func_fcntl_f_dupfd_works=yes],
  69. [gl_cv_func_fcntl_f_dupfd_works=no],
  70. [case $host_os in
  71. aix* | cygwin* | haiku*)
  72. gl_cv_func_fcntl_f_dupfd_works="guessing no" ;;
  73. *) gl_cv_func_fcntl_f_dupfd_works="guessing yes" ;;
  74. esac])])
  75. case $gl_cv_func_fcntl_f_dupfd_works in
  76. *yes) ;;
  77. *) gl_REPLACE_FCNTL
  78. AC_DEFINE([FCNTL_DUPFD_BUGGY], [1], [Define this to 1 if F_DUPFD
  79. behavior does not match POSIX]) ;;
  80. esac
  81. dnl Many systems lack F_DUPFD_CLOEXEC.
  82. dnl NetBSD 9.0 declares F_DUPFD_CLOEXEC but it works only like F_DUPFD.
  83. AC_CACHE_CHECK([whether fcntl understands F_DUPFD_CLOEXEC],
  84. [gl_cv_func_fcntl_f_dupfd_cloexec],
  85. [AC_RUN_IFELSE(
  86. [AC_LANG_SOURCE(
  87. [[#include <fcntl.h>
  88. #include <unistd.h>
  89. int main (int argc, char *argv[])
  90. {
  91. if (argc == 1)
  92. /* parent process */
  93. {
  94. if (fcntl (1, F_DUPFD_CLOEXEC, 10) < 0)
  95. return 1;
  96. return execl ("./conftest", "./conftest", "child", NULL);
  97. }
  98. else
  99. /* child process */
  100. return (fcntl (10, F_GETFL) < 0 ? 0 : 42);
  101. }
  102. ]])
  103. ],
  104. [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
  105. #ifdef __linux__
  106. /* The Linux kernel only added F_DUPFD_CLOEXEC in 2.6.24, so we always replace
  107. it to support the semantics on older kernels that failed with EINVAL. */
  108. choke me
  109. #endif
  110. ]])],
  111. [gl_cv_func_fcntl_f_dupfd_cloexec=yes],
  112. [gl_cv_func_fcntl_f_dupfd_cloexec="needs runtime check"])
  113. ],
  114. [gl_cv_func_fcntl_f_dupfd_cloexec=no],
  115. [case "$host_os" in
  116. # Guess no on NetBSD.
  117. netbsd*) gl_cv_func_fcntl_f_dupfd_cloexec="guessing no" ;;
  118. *) gl_cv_func_fcntl_f_dupfd_cloexec="$gl_cross_guess_normal" ;;
  119. esac
  120. ])
  121. ])
  122. case "$gl_cv_func_fcntl_f_dupfd_cloexec" in
  123. *yes) ;;
  124. *) gl_REPLACE_FCNTL
  125. dnl No witness macro needed for this bug.
  126. ;;
  127. esac
  128. fi
  129. dnl Replace fcntl() for supporting the gnulib-defined fchdir() function,
  130. dnl to keep fchdir's bookkeeping up-to-date.
  131. m4_ifdef([gl_FUNC_FCHDIR], [
  132. gl_TEST_FCHDIR
  133. if test $HAVE_FCHDIR = 0; then
  134. gl_REPLACE_FCNTL
  135. fi
  136. ])
  137. ])
  138. AC_DEFUN([gl_REPLACE_FCNTL],
  139. [
  140. AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
  141. AC_CHECK_FUNCS_ONCE([fcntl])
  142. if test $ac_cv_func_fcntl = no; then
  143. HAVE_FCNTL=0
  144. else
  145. REPLACE_FCNTL=1
  146. fi
  147. ])