Jelajahi Sumber

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 10 bulan lalu
induk
melakukan
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