From bf419d1b9fecbf7d2f62147fabe7ad1bb20256e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
<grubba@grubba.org>
Date: Mon, 30 Apr 2018 12:39:35 +0200
Subject: [PATCH] I/O [Solaris]: Fix getcwd() on Solaris.
On Solaris getcwd(NULL, x) only works if x is > 0.
Fixes building issues on Solaris.
---
src/acconfig.h | 9 ++++-
src/configure.in | 90 ++++++++++++++++++++++++++++++++++++++++++++++--
src/fdlib.h | 28 +++++++++++++--
3 files changed, 120 insertions(+), 7 deletions(-)
diff --git a/src/acconfig.h b/src/acconfig.h
index 2bd41b04e6..9e3cb9e8d4 100644
--- a/src/acconfig.h
+++ b/src/acconfig.h
@@ -153,7 +153,14 @@
* __chkstk. */
#undef HAVE_BROKEN_CHKSTK
-/* Define if you have a working getcwd */
+/* Define if you have a working getcwd(3) (ie one that returns a malloc()ed
+ * buffer if the first argument is NULL).
+ *
+ * Define to 1 if the second argument being 0 causes getcwd(3) to allocate
+ * a buffer of suitable size (ie never fail with ERANGE).
+ *
+ * Define to 0 if the second argument MUST be > 0.
+ */
#undef HAVE_WORKING_GETCWD
/* Define for solaris */
diff --git a/src/configure.in b/src/configure.in
index b68c937692..3d5d154835 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -4705,6 +4705,82 @@ AC_DEFINE_UNQUOTED(ACCEPT_SIZE_T, $pike_cv_accept_size_t)
AC_MSG_CHECKING(for working getcwd)
AC_CACHE_VAL(pike_cv_func_working_getcwd,
[
+# First try getcwd(NULL, 0).
+# This is the working == yes case, and is true on glibc and win32.
+AC_TRY_RUN([
+#ifndef _LARGEFILE_SOURCE
+# define _FILE_OFFSET_BITS 64
+# define _LARGEFILE_SOURCE
+# define _LARGEFILE64_SOURCE 1
+#endif
+/* HPUX needs these too... */
+#ifndef __STDC_EXT__
+# define __STDC_EXT__
+#endif /* !__STDC_EXT__ */
+
+#ifndef POSIX_SOURCE
+#define POSIX_SOURCE
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif /* HAVE_DIRECT_H */
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#include <signal.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef __NT__
+int sig_child(int arg)
+{
+#ifdef HAVE_WAITPID
+ waitpid(-1,0,WNOHANG);
+#else
+#ifdef HAVE_WAIT3
+ wait3(0,WNOHANG,0);
+#else
+#ifdef HAVE_WAIT4
+ wait3(-1,0,WNOHANG,0);
+#else
+
+ /* Leave them hanging */
+
+#endif /* HAVE_WAIT4 */
+#endif /* HAVE_WAIT3 */
+#endif /* HAVE_WAITPID */
+
+#ifdef SIGNAL_ONESHOT
+ signal(SIGCHLD, sig_child);
+#endif
+}
+
+int sig_alarm() { exit(1); }
+#endif /* !__NT__ */
+
+int main()
+{
+ char *tmp;
+#ifndef __NT__
+ signal(SIGCHLD,sig_child);
+ signal(SIGALRM,sig_alarm);
+ alarm(4);
+#endif /* !__NT__ */
+ tmp=getcwd(0,0);
+ if(tmp && tmp[0] && (strlen(tmp) < 10000)) {
+ free(tmp);
+ exit(0);
+ }
+ exit(1);
+}
+],pike_cv_func_working_getcwd=yes,
+# The getcwd(NULL, 0) case failed.
+# Retry with getcwd(NULL, 10000).
+# This is the working == some case, and is true on Solaris.
AC_TRY_RUN([
#ifndef _LARGEFILE_SOURCE
# define _FILE_OFFSET_BITS 64
@@ -4775,12 +4851,20 @@ int main()
}
exit(1);
}
-],pike_cv_func_working_getcwd=yes,pike_cv_func_working_getcwd=no,
- pike_cv_func_working_getcwd=yes)])
+],pike_cv_func_working_getcwd=some,
+ pike_cv_func_working_getcwd=no,
+ # NB: This should be unreachable.
+ pike_cv_func_working_getcwd=no),
+ # Assume that getcwd(NULL, val) works.
+ pike_cv_func_working_getcwd=some)
+])
if test "$pike_cv_func_working_getcwd" = yes; then
AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_WORKING_GETCWD)
+ AC_DEFINE(HAVE_WORKING_GETCWD, [1])
+elif test "$pike_cv_func_working_getcwd" = some; then
+ AC_MSG_RESULT(some)
+ AC_DEFINE(HAVE_WORKING_GETCWD, [0])
else
AC_MSG_RESULT(no)
fi
diff --git a/src/fdlib.h b/src/fdlib.h
index a2988c85d7..076de7d8e4 100644
--- a/src/fdlib.h
+++ b/src/fdlib.h
@@ -387,13 +387,35 @@ static int PIKE_UNUSED_ATTRIBUTE debug_fd_mkdir(const char *dir, int mode)
/* Glibc extension... */
#define fd_get_current_dir_name() get_current_dir_name()
#elif defined(HAVE_WORKING_GETCWD)
-/* getcwd(NULL, 0) gives malloced buffer. */
+#if HAVE_WORKING_GETCWD
+/* Glibc and win32 (HAVE_WORKING_GETCWD == 1).
+ *
+ * getcwd(NULL, 0) gives malloced buffer.
+ */
#define fd_get_current_dir_name() getcwd(NULL, 0)
#else
+/* Solaris-style (HAVE_WORKING_GETCWD == 0).
+ *
+ * getcwd(NULL, x) gives malloced buffer as long as x > 0, and the path fits.
+ */
static char PIKE_UNUSED_ATTRIBUTE *debug_get_current_dir_name(void)
{
char *buf;
- size_t buf_size = 1000;
+ size_t buf_size = 128;
+ do {
+ buf = getcwd(NULL, buf_size);
+ if (buf) return buf;
+ buf_size <<= 1;
+ } while (errno == ERANGE);
+ return NULL;
+}
+#define fd_get_current_dir_name() debug_get_current_dir_name()
+#endif
+#else
+static char PIKE_UNUSED_ATTRIBUTE *debug_get_current_dir_name(void)
+{
+ char *buf;
+ size_t buf_size = 128;
do {
buf = malloc(buf_size);
@@ -406,7 +428,7 @@ static char PIKE_UNUSED_ATTRIBUTE *debug_get_current_dir_name(void)
free(buf);
if (errno == ERANGE) {
- bufsize <<= 1;
+ buf_size <<= 1;
continue;
}
--
GitLab