summaryrefslogtreecommitdiffstats
path: root/m4/getcwd.m4
blob: ba68c5fb0af87d89b3192b29ab6dfe153b5b8d94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# getcwd.m4 - check for working getcwd that is compatible with glibc

# Copyright (C) 2001, 2003-2007, 2009-2020 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.

# Written by Paul Eggert.
# serial 18

AC_DEFUN([gl_FUNC_GETCWD_NULL],
  [
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
   AC_CHECK_HEADERS_ONCE([unistd.h])
   AC_CACHE_CHECK([whether getcwd (NULL, 0) allocates memory for result],
     [gl_cv_func_getcwd_null],
     [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#	 include <stdlib.h>
#        if HAVE_UNISTD_H
#         include <unistd.h>
#        else /* on Windows with MSVC */
#         include <direct.h>
#        endif
#        ifndef getcwd
         char *getcwd ();
#        endif
]], [[
#if defined _WIN32 && ! defined __CYGWIN__
/* mingw cwd does not start with '/', but getcwd does allocate.
   However, mingw fails to honor non-zero size.  */
#else
           if (chdir ("/") != 0)
             return 1;
           else
             {
               char *f = getcwd (NULL, 0);
               if (! f)
                 return 2;
               if (f[0] != '/')
                 { free (f); return 3; }
               if (f[1] != '\0')
                 { free (f); return 4; }
               free (f);
               return 0;
             }
#endif
         ]])],
        [gl_cv_func_getcwd_null=yes],
        [gl_cv_func_getcwd_null=no],
        [[case "$host_os" in
                           # Guess yes on glibc systems.
            *-gnu* | gnu*) gl_cv_func_getcwd_null="guessing yes";;
                           # Guess yes on musl systems.
            *-musl*)       gl_cv_func_getcwd_null="guessing yes";;
                           # Guess yes on Cygwin.
            cygwin*)       gl_cv_func_getcwd_null="guessing yes";;
                           # If we don't know, obey --enable-cross-guesses.
            *)             gl_cv_func_getcwd_null="$gl_cross_guess_normal";;
          esac
        ]])])
])

AC_DEFUN([gl_FUNC_GETCWD_SIGNATURE],
[
  AC_CACHE_CHECK([for getcwd with POSIX signature],
    [gl_cv_func_getcwd_posix_signature],
    [AC_COMPILE_IFELSE(
      [AC_LANG_PROGRAM(
         [[#include <unistd.h>]],
         [[extern
           #ifdef __cplusplus
           "C"
           #endif
           char *getcwd (char *, size_t);
         ]])
      ],
      [gl_cv_func_getcwd_posix_signature=yes],
      [gl_cv_func_getcwd_posix_signature=no])
   ])
])

dnl Guarantee that getcwd will malloc with a NULL first argument.  Assumes
dnl that either the system getcwd is robust, or that calling code is okay
dnl with spurious failures when run from a directory with an absolute name
dnl larger than 4k bytes.
dnl
dnl Assumes that getcwd exists; if you are worried about obsolete
dnl platforms that lacked getcwd(), then you need to use the GPL module.
AC_DEFUN([gl_FUNC_GETCWD_LGPL],
[
  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
  AC_REQUIRE([gl_FUNC_GETCWD_NULL])
  AC_REQUIRE([gl_FUNC_GETCWD_SIGNATURE])

  case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_posix_signature in
  *yes,yes) ;;
  *)
    dnl Minimal replacement lib/getcwd-lgpl.c.
    REPLACE_GETCWD=1
    ;;
  esac
])

dnl Check for all known getcwd bugs; useful for a program likely to be
dnl executed from an arbitrary location.
AC_DEFUN([gl_FUNC_GETCWD],
[
  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
  AC_REQUIRE([gl_FUNC_GETCWD_NULL])
  AC_REQUIRE([gl_FUNC_GETCWD_SIGNATURE])
  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles

  gl_abort_bug=no
  case "$host_os" in
    mingw*)
      gl_cv_func_getcwd_path_max=yes
      ;;
    *)
      gl_FUNC_GETCWD_PATH_MAX
      case "$gl_cv_func_getcwd_null" in
        *yes)
          gl_FUNC_GETCWD_ABORT_BUG([gl_abort_bug=yes])
          ;;
      esac
      ;;
  esac
  dnl Define HAVE_MINIMALLY_WORKING_GETCWD and HAVE_PARTLY_WORKING_GETCWD
  dnl if appropriate.
  case "$gl_cv_func_getcwd_path_max" in
    *"no" | *"no, it has the AIX bug") ;;
    *)
      AC_DEFINE([HAVE_MINIMALLY_WORKING_GETCWD], [1],
        [Define to 1 if getcwd minimally works, that is, its result can be
         trusted when it succeeds.])
      ;;
  esac
  case "$gl_cv_func_getcwd_path_max" in
    *"no, but it is partly working")
      AC_DEFINE([HAVE_PARTLY_WORKING_GETCWD], [1],
        [Define to 1 if getcwd works, except it sometimes fails when it
         shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.])
      ;;
    *"yes, but with shorter paths")
      AC_DEFINE([HAVE_GETCWD_SHORTER], [1],
        [Define to 1 if getcwd works, but with shorter paths
         than is generally tested with the replacement.])
      ;;
  esac

  if { case "$gl_cv_func_getcwd_null" in *yes) false;; *) true;; esac; } \
     || test $gl_cv_func_getcwd_posix_signature != yes \
     || { case "$gl_cv_func_getcwd_path_max" in *yes*) false;; *) true;; esac; } \
     || test $gl_abort_bug = yes; then
    REPLACE_GETCWD=1
  fi
])

# Prerequisites of lib/getcwd.c, when full replacement is in effect.
AC_DEFUN([gl_PREREQ_GETCWD],
[
  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
  AC_REQUIRE([gl_CHECK_TYPE_STRUCT_DIRENT_D_INO])
  :
])