1# fcntl.m4 serial 9 2dnl Copyright (C) 2009-2019 Free Software Foundation, Inc. 3dnl This file is free software; the Free Software Foundation 4dnl gives unlimited permission to copy and/or distribute it, 5dnl with or without modifications, as long as this notice is preserved. 6 7# For now, this module ensures that fcntl() 8# - supports F_DUPFD correctly 9# - supports or emulates F_DUPFD_CLOEXEC 10# - supports F_GETFD 11# Still to be ported to mingw: 12# - F_SETFD 13# - F_GETFL, F_SETFL 14# - F_GETOWN, F_SETOWN 15# - F_GETLK, F_SETLK, F_SETLKW 16AC_DEFUN([gl_FUNC_FCNTL], 17[ 18 dnl Persuade glibc to expose F_DUPFD_CLOEXEC. 19 AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) 20 AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) 21 AC_REQUIRE([AC_CANONICAL_HOST]) 22 AC_CHECK_FUNCS_ONCE([fcntl]) 23 if test $ac_cv_func_fcntl = no; then 24 gl_REPLACE_FCNTL 25 else 26 dnl cygwin 1.5.x F_DUPFD has wrong errno, and allows negative target 27 dnl haiku alpha 2 F_DUPFD has wrong errno 28 AC_CACHE_CHECK([whether fcntl handles F_DUPFD correctly], 29 [gl_cv_func_fcntl_f_dupfd_works], 30 [AC_RUN_IFELSE( 31 [AC_LANG_PROGRAM( 32 [[#include <errno.h> 33 #include <fcntl.h> 34 #include <limits.h> 35 #include <sys/resource.h> 36 #include <unistd.h> 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 66 close (fd); 67 } 68 return result;]])], 69 [gl_cv_func_fcntl_f_dupfd_works=yes], 70 [gl_cv_func_fcntl_f_dupfd_works=no], 71 [case $host_os in 72 aix* | cygwin* | haiku*) 73 gl_cv_func_fcntl_f_dupfd_works="guessing no" ;; 74 *) gl_cv_func_fcntl_f_dupfd_works="guessing yes" ;; 75 esac])]) 76 case $gl_cv_func_fcntl_f_dupfd_works in 77 *yes) ;; 78 *) gl_REPLACE_FCNTL 79 AC_DEFINE([FCNTL_DUPFD_BUGGY], [1], [Define this to 1 if F_DUPFD 80 behavior does not match POSIX]) ;; 81 esac 82 83 dnl Many systems lack F_DUPFD_CLOEXEC 84 AC_CACHE_CHECK([whether fcntl understands F_DUPFD_CLOEXEC], 85 [gl_cv_func_fcntl_f_dupfd_cloexec], 86 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 87#include <fcntl.h> 88#ifndef F_DUPFD_CLOEXEC 89choke me 90#endif 91 ]])], 92 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 93#ifdef __linux__ 94/* The Linux kernel only added F_DUPFD_CLOEXEC in 2.6.24, so we always replace 95 it to support the semantics on older kernels that failed with EINVAL. */ 96choke me 97#endif 98 ]])], 99 [gl_cv_func_fcntl_f_dupfd_cloexec=yes], 100 [gl_cv_func_fcntl_f_dupfd_cloexec="needs runtime check"])], 101 [gl_cv_func_fcntl_f_dupfd_cloexec=no])]) 102 if test "$gl_cv_func_fcntl_f_dupfd_cloexec" != yes; then 103 gl_REPLACE_FCNTL 104 dnl No witness macro needed for this bug. 105 fi 106 fi 107 dnl Replace fcntl() for supporting the gnulib-defined fchdir() function, 108 dnl to keep fchdir's bookkeeping up-to-date. 109 m4_ifdef([gl_FUNC_FCHDIR], [ 110 gl_TEST_FCHDIR 111 if test $HAVE_FCHDIR = 0; then 112 gl_REPLACE_FCNTL 113 fi 114 ]) 115]) 116 117AC_DEFUN([gl_REPLACE_FCNTL], 118[ 119 AC_REQUIRE([gl_FCNTL_H_DEFAULTS]) 120 AC_CHECK_FUNCS_ONCE([fcntl]) 121 if test $ac_cv_func_fcntl = no; then 122 HAVE_FCNTL=0 123 else 124 REPLACE_FCNTL=1 125 fi 126]) 127