| 1 | # getcwd.m4 - check for working getcwd that is compatible with glibc |
| 2 | |
| 3 | # Copyright (C) 2001, 2003-2007, 2009-2016 Free Software Foundation, Inc. |
| 4 | # This file is free software; the Free Software Foundation |
| 5 | # gives unlimited permission to copy and/or distribute it, |
| 6 | # with or without modifications, as long as this notice is preserved. |
| 7 | |
| 8 | # Written by Paul Eggert. |
| 9 | # serial 13 |
| 10 | |
| 11 | AC_DEFUN([gl_FUNC_GETCWD_NULL], |
| 12 | [ |
| 13 | AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles |
| 14 | AC_CHECK_HEADERS_ONCE([unistd.h]) |
| 15 | AC_CACHE_CHECK([whether getcwd (NULL, 0) allocates memory for result], |
| 16 | [gl_cv_func_getcwd_null], |
| 17 | [AC_RUN_IFELSE([AC_LANG_PROGRAM([[ |
| 18 | # include <stdlib.h> |
| 19 | # if HAVE_UNISTD_H |
| 20 | # include <unistd.h> |
| 21 | # else /* on Windows with MSVC */ |
| 22 | # include <direct.h> |
| 23 | # endif |
| 24 | # ifndef getcwd |
| 25 | char *getcwd (); |
| 26 | # endif |
| 27 | ]], [[ |
| 28 | #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
| 29 | /* mingw cwd does not start with '/', but getcwd does allocate. |
| 30 | However, mingw fails to honor non-zero size. */ |
| 31 | #else |
| 32 | if (chdir ("/") != 0) |
| 33 | return 1; |
| 34 | else |
| 35 | { |
| 36 | char *f = getcwd (NULL, 0); |
| 37 | if (! f) |
| 38 | return 2; |
| 39 | if (f[0] != '/') |
| 40 | return 3; |
| 41 | if (f[1] != '\0') |
| 42 | return 4; |
| 43 | free (f); |
| 44 | return 0; |
| 45 | } |
| 46 | #endif |
| 47 | ]])], |
| 48 | [gl_cv_func_getcwd_null=yes], |
| 49 | [gl_cv_func_getcwd_null=no], |
| 50 | [[case "$host_os" in |
| 51 | # Guess yes on glibc systems. |
| 52 | *-gnu*) gl_cv_func_getcwd_null="guessing yes";; |
| 53 | # Guess yes on Cygwin. |
| 54 | cygwin*) gl_cv_func_getcwd_null="guessing yes";; |
| 55 | # If we don't know, assume the worst. |
| 56 | *) gl_cv_func_getcwd_null="guessing no";; |
| 57 | esac |
| 58 | ]])]) |
| 59 | ]) |
| 60 | |
| 61 | AC_DEFUN([gl_FUNC_GETCWD_SIGNATURE], |
| 62 | [ |
| 63 | AC_CACHE_CHECK([for getcwd with POSIX signature], |
| 64 | [gl_cv_func_getcwd_posix_signature], |
| 65 | [AC_COMPILE_IFELSE( |
| 66 | [AC_LANG_PROGRAM( |
| 67 | [[#include <unistd.h>]], |
| 68 | [[extern |
| 69 | #ifdef __cplusplus |
| 70 | "C" |
| 71 | #endif |
| 72 | char *getcwd (char *, size_t); |
| 73 | ]]) |
| 74 | ], |
| 75 | [gl_cv_func_getcwd_posix_signature=yes], |
| 76 | [gl_cv_func_getcwd_posix_signature=no]) |
| 77 | ]) |
| 78 | ]) |
| 79 | |
| 80 | dnl Guarantee that getcwd will malloc with a NULL first argument. Assumes |
| 81 | dnl that either the system getcwd is robust, or that calling code is okay |
| 82 | dnl with spurious failures when run from a directory with an absolute name |
| 83 | dnl larger than 4k bytes. |
| 84 | dnl |
| 85 | dnl Assumes that getcwd exists; if you are worried about obsolete |
| 86 | dnl platforms that lacked getcwd(), then you need to use the GPL module. |
| 87 | AC_DEFUN([gl_FUNC_GETCWD_LGPL], |
| 88 | [ |
| 89 | AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) |
| 90 | AC_REQUIRE([gl_FUNC_GETCWD_NULL]) |
| 91 | AC_REQUIRE([gl_FUNC_GETCWD_SIGNATURE]) |
| 92 | |
| 93 | case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_posix_signature in |
| 94 | *yes,yes) ;; |
| 95 | *) |
| 96 | dnl Minimal replacement lib/getcwd-lgpl.c. |
| 97 | REPLACE_GETCWD=1 |
| 98 | ;; |
| 99 | esac |
| 100 | ]) |
| 101 | |
| 102 | dnl Check for all known getcwd bugs; useful for a program likely to be |
| 103 | dnl executed from an arbitrary location. |
| 104 | AC_DEFUN([gl_FUNC_GETCWD], |
| 105 | [ |
| 106 | AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) |
| 107 | AC_REQUIRE([gl_FUNC_GETCWD_NULL]) |
| 108 | AC_REQUIRE([gl_FUNC_GETCWD_SIGNATURE]) |
| 109 | AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles |
| 110 | |
| 111 | gl_abort_bug=no |
| 112 | case "$host_os" in |
| 113 | mingw*) |
| 114 | gl_cv_func_getcwd_path_max=yes |
| 115 | ;; |
| 116 | *) |
| 117 | gl_FUNC_GETCWD_PATH_MAX |
| 118 | case "$gl_cv_func_getcwd_null" in |
| 119 | *yes) |
| 120 | gl_FUNC_GETCWD_ABORT_BUG([gl_abort_bug=yes]) |
| 121 | ;; |
| 122 | esac |
| 123 | ;; |
| 124 | esac |
| 125 | dnl Define HAVE_MINIMALLY_WORKING_GETCWD and HAVE_PARTLY_WORKING_GETCWD |
| 126 | dnl if appropriate. |
| 127 | case "$gl_cv_func_getcwd_path_max" in |
| 128 | "no"|"no, it has the AIX bug") ;; |
| 129 | *) |
| 130 | AC_DEFINE([HAVE_MINIMALLY_WORKING_GETCWD], [1], |
| 131 | [Define to 1 if getcwd minimally works, that is, its result can be |
| 132 | trusted when it succeeds.]) |
| 133 | ;; |
| 134 | esac |
| 135 | case "$gl_cv_func_getcwd_path_max" in |
| 136 | "no, but it is partly working") |
| 137 | AC_DEFINE([HAVE_PARTLY_WORKING_GETCWD], [1], |
| 138 | [Define to 1 if getcwd works, except it sometimes fails when it |
| 139 | shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.]) |
| 140 | ;; |
| 141 | "yes, but with shorter paths") |
| 142 | AC_DEFINE([HAVE_GETCWD_SHORTER], [1], |
| 143 | [Define to 1 if getcwd works, but with shorter paths |
| 144 | than is generally tested with the replacement.]) |
| 145 | ;; |
| 146 | esac |
| 147 | |
| 148 | if { case "$gl_cv_func_getcwd_null" in *yes) false;; *) true;; esac; } \ |
| 149 | || test $gl_cv_func_getcwd_posix_signature != yes \ |
| 150 | || { case "$gl_cv_func_getcwd_path_max" in *yes*) false;; *) true;; esac; } \ |
| 151 | || test $gl_abort_bug = yes; then |
| 152 | REPLACE_GETCWD=1 |
| 153 | fi |
| 154 | ]) |
| 155 | |
| 156 | # Prerequisites of lib/getcwd.c, when full replacement is in effect. |
| 157 | AC_DEFUN([gl_PREREQ_GETCWD], |
| 158 | [ |
| 159 | AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) |
| 160 | AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_INO]) |
| 161 | : |
| 162 | ]) |