Browse Source

Solaris: Backport our mkdtemp code paths to SunOS 5.10 i386

`mkdtemp` is not available on this architecture until SunOS 5.11.
Look up the symbol at runtime, and if missing, fall back to an
approximate implementation.
Brad King 1 year ago
parent
commit
4db9e1009d

+ 4 - 0
Source/CMakeLists.txt

@@ -1030,6 +1030,10 @@ if(WIN32 AND NOT CYGWIN)
   list(APPEND _tools cmcldeps)
 endif()
 
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION STREQUAL "5.10" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")
+  set_property(SOURCE cmSystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_NO_MKDTEMP)
+endif()
+
 # Some atomic instructions are implemented using libatomic on some platforms.
 if(CMake_HAVE_CXX_ATOMIC_LIB)
   target_link_libraries(CMakeLib PUBLIC atomic)

+ 32 - 1
Source/cmSystemTools.cxx

@@ -141,6 +141,14 @@
 #  include <sys/utsname.h>
 #endif
 
+#if defined(CMAKE_BOOTSTRAP) && defined(__sun) && defined(__i386)
+#  define CMAKE_NO_MKDTEMP
+#endif
+
+#ifdef CMAKE_NO_MKDTEMP
+#  include <dlfcn.h>
+#endif
+
 #if defined(_MSC_VER) && _MSC_VER >= 1800
 #  define CM_WINDOWS_DEPRECATED_GetVersionEx
 #endif
@@ -1369,6 +1377,29 @@ inline int Mkdir(char const* dir, mode_t const* mode)
 #endif
 }
 
+#ifdef CMAKE_NO_MKDTEMP
+namespace {
+char* cm_mkdtemp_fallback(char* template_)
+{
+  if (mktemp(template_) == nullptr || mkdir(template_, 0700) != 0) {
+    return nullptr;
+  }
+  return template_;
+}
+using cm_mkdtemp_t = char* (*)(char*);
+cm_mkdtemp_t const cm_mkdtemp = []() -> cm_mkdtemp_t {
+  cm_mkdtemp_t f = (cm_mkdtemp_t)dlsym(RTLD_DEFAULT, "mkdtemp");
+  dlerror(); // Ignore/cleanup dlsym errors.
+  if (!f) {
+    f = cm_mkdtemp_fallback;
+  }
+  return f;
+}();
+}
+#else
+#  define cm_mkdtemp mkdtemp
+#endif
+
 cmsys::Status cmSystemTools::MakeTempDirectory(std::string& path,
                                                mode_t const* mode)
 {
@@ -1422,7 +1453,7 @@ cmsys::Status cmSystemTools::MakeTempDirectory(char* path, mode_t const* mode)
   }
   return cmsys::Status::POSIX(EAGAIN);
 #else
-  if (mkdtemp(path)) {
+  if (cm_mkdtemp(path)) {
     if (mode) {
       chmod(path, *mode);
     }

+ 4 - 0
Utilities/cmlibuv/CMakeLists.txt

@@ -302,6 +302,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
   endif()
   if(CMAKE_SYSTEM_VERSION STREQUAL "5.10")
     list(APPEND uv_defines SUNOS_NO_IFADDRS)
+    if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")
+      list(APPEND uv_defines CMAKE_NO_MKDTEMP)
+    endif()
   endif()
   list(APPEND uv_sources
     src/unix/no-proctitle.c
@@ -318,6 +321,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
     )
   list(APPEND uv_defines
     _XOPEN_SOURCE_EXTENDED
+    CMAKE_NO_MKDTEMP
     )
   list(APPEND uv_sources
     src/unix/hpux.c

+ 20 - 3
Utilities/cmlibuv/src/unix/fs.c

@@ -282,13 +282,30 @@ static ssize_t uv__fs_futime(uv_fs_t* req) {
 #endif
 }
 
-#if (defined(__sun) || defined(__hpux)) && (_XOPEN_SOURCE < 600 || defined(CMAKE_BOOTSTRAP))
-static char* uv__mkdtemp(char *template)
-{
+#if defined(CMAKE_BOOTSTRAP) && defined(__sun) && defined(__i386)
+#  define CMAKE_NO_MKDTEMP
+#endif
+
+#if defined(CMAKE_NO_MKDTEMP)
+static char* uv__mkdtemp_fallback(char *template) {
   if (!mktemp(template) || mkdir(template, 0700))
     return NULL;
   return template;
 }
+static char* (*uv__mkdtemp_f)(char*);
+static void uv__mkdtemp_initonce(void) {
+  uv__mkdtemp_f = (char* (*)(char*)) dlsym(RTLD_DEFAULT, "mkdtemp");
+  dlerror(); /* Ignore/cleanup dlsym errors.  */
+  if (uv__mkdtemp_f == NULL) {
+    uv__mkdtemp_f = uv__mkdtemp_fallback;
+  }
+}
+static char* uv__mkdtemp(char *template)
+{
+  static uv_once_t once = UV_ONCE_INIT;
+  uv_once(&once, uv__mkdtemp_initonce);
+  return uv__mkdtemp_f(template);
+}
 #else
 #define uv__mkdtemp mkdtemp
 #endif