From 733e2f6d7fb4feeaea5465ff00be3e293a26bbf9 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 5 Jan 2025 18:06:16 +0100 Subject: [PATCH] diff: Fix failure of --no-dereference option (regression 2023-07-01) * configure.ac: Move system-related tests closer together. Define O_PATH_SUPPORTS_FSTAT if O_PATH exists and is supported by fstat(). * src/diff.c (O_PATHSEARCH): Don't use O_PATH if it is defined but not supported by fstat(). --- configure.ac | 53 +++++++++++++++++++++++++++++++++++++++------------- src/diff.c | 5 +++-- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index c0441cc..a427e3f 100644 --- a/configure.ac +++ b/configure.ac @@ -60,6 +60,46 @@ AC_DEFINE([GNULIB_MBRTOC32_REGULAR], [1], [Do not worry about rare encodings like CP864, EBCDIC, Johab, and Shift JIS that glibc does not support.]) +AC_C_INLINE + +AC_CHECK_MEMBERS([struct stat.st_rdev]) +AC_HEADER_DIRENT +AC_HEADER_SYS_WAIT +AC_TYPE_PID_T + +AC_CHECK_FUNCS_ONCE([sigaction sigprocmask]) +if test $ac_cv_func_sigprocmask = no; then + AC_CHECK_FUNCS([sigblock]) +fi +AC_FUNC_FORK + +dnl O_PATH exists since Linux 2.6.39, but is supported with fstat() only since +dnl Linux 3.6. Use a configure test rather than testing `uname -sr`. +AC_CACHE_CHECK([whether O_PATH supports fstat], + [du_cv_O_PATH_fstat], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + #include + ]], [[ + struct stat statbuf; + int fd = openat (AT_FDCWD, "conftest.c", O_RDONLY|O_PATH); + return !(fd >= 0 && fstat (fd, &statbuf) == 0); + ]]) + ], + [du_cv_O_PATH_fstat=yes], + [du_cv_O_PATH_fstat=no], + [du_cv_O_PATH_fstat="guessing no"]) + ]) +case "$du_cv_O_PATH_fstat" in + yes) + AC_DEFINE([O_PATH_SUPPORTS_FSTAT], [1], + [Define to 1 if defines O_PATH and file descriptors + created with this flag are supported by fstat().]) + ;; +esac + # gl_GCC_VERSION_IFELSE([major], [minor], [run-if-found], [run-if-not-found]) # ------------------------------------------------ # If $CPP is gcc-MAJOR.MINOR or newer, then run RUN-IF-FOUND. @@ -137,25 +177,12 @@ if test $gl_gcc_warnings != no; then AC_DEFINE([GNULIB_PORTCHECK], [1], [enable some gnulib portability checks]) fi -AC_C_INLINE - AC_DEFINE([DEFAULT_EDITOR_PROGRAM], ["ed"], [Name of editor program, unless overridden.]) AC_PATH_PROG([PR_PROGRAM], [pr], [""]) AC_DEFINE_UNQUOTED([PR_PROGRAM], ["$PR_PROGRAM"], [Name of "pr" program.]) -AC_CHECK_MEMBERS([struct stat.st_rdev]) -AC_HEADER_DIRENT -AC_HEADER_SYS_WAIT -AC_TYPE_PID_T - -AC_CHECK_FUNCS_ONCE([sigaction sigprocmask]) -if test $ac_cv_func_sigprocmask = no; then - AC_CHECK_FUNCS([sigblock]) -fi -AC_FUNC_FORK - # When .tarball-version exists, we're building from a tarball # and must not make man/*.1 files depend on the generated src/version.c, # because that would induce a requirement to run the help2man perl script. diff --git a/src/diff.c b/src/diff.c index bdcf545..c465d40 100644 --- a/src/diff.c +++ b/src/diff.c @@ -102,8 +102,9 @@ static bool binary; enum { binary = true }; #endif -/* Use Linux-style O_PATH if available, POSIX-style O_SEARCH otherwise. */ -#ifdef O_PATH +/* Use Linux-style O_PATH if available and supported by fstat(), + POSIX-style O_SEARCH otherwise. */ +#if O_PATH_SUPPORTS_FSTAT enum { O_PATH_DEFINED = true }; enum { O_PATHSEARCH = O_PATH }; #else