hotspot/src/share/vm/runtime/os.cpp
changeset 47089 27050b653624
parent 46969 d4db878f22f3
--- a/hotspot/src/share/vm/runtime/os.cpp	Mon Aug 28 23:46:22 2017 +0000
+++ b/hotspot/src/share/vm/runtime/os.cpp	Thu Aug 17 17:26:02 2017 +0200
@@ -235,6 +235,82 @@
   return OS_OK;
 }
 
+bool os::dll_build_name(char* buffer, size_t size, const char* fname) {
+  int n = jio_snprintf(buffer, size, "%s%s%s", JNI_LIB_PREFIX, fname, JNI_LIB_SUFFIX);
+  return (n != -1);
+}
+
+// Helper for dll_locate_lib.
+// Pass buffer and printbuffer as we already printed the path to buffer
+// when we called get_current_directory. This way we avoid another buffer
+// of size MAX_PATH.
+static bool conc_path_file_and_check(char *buffer, char *printbuffer, size_t printbuflen,
+                                     const char* pname, char lastchar, const char* fname) {
+
+  // Concatenate path and file name, but don't print double path separators.
+  const char *filesep = (WINDOWS_ONLY(lastchar == ':' ||) lastchar == os::file_separator()[0]) ?
+                        "" : os::file_separator();
+  int ret = jio_snprintf(printbuffer, printbuflen, "%s%s%s", pname, filesep, fname);
+  // Check whether file exists.
+  if (ret != -1) {
+    struct stat statbuf;
+    return os::stat(buffer, &statbuf) == 0;
+  }
+  return false;
+}
+
+bool os::dll_locate_lib(char *buffer, size_t buflen,
+                        const char* pname, const char* fname) {
+  bool retval = false;
+
+  size_t fullfnamelen = strlen(JNI_LIB_PREFIX) + strlen(fname) + strlen(JNI_LIB_SUFFIX);
+  char* fullfname = (char*)NEW_C_HEAP_ARRAY(char, fullfnamelen + 1, mtInternal);
+  if (dll_build_name(fullfname, fullfnamelen + 1, fname)) {
+    const size_t pnamelen = pname ? strlen(pname) : 0;
+
+    if (pnamelen == 0) {
+      // If no path given, use current working directory.
+      const char* p = get_current_directory(buffer, buflen);
+      if (p != NULL) {
+        const size_t plen = strlen(buffer);
+        const char lastchar = buffer[plen - 1];
+        retval = conc_path_file_and_check(buffer, &buffer[plen], buflen - plen,
+                                          "", lastchar, fullfname);
+      }
+    } else if (strchr(pname, *os::path_separator()) != NULL) {
+      // A list of paths. Search for the path that contains the library.
+      int n;
+      char** pelements = split_path(pname, &n);
+      if (pelements != NULL) {
+        for (int i = 0; i < n; i++) {
+          char* path = pelements[i];
+          // Really shouldn't be NULL, but check can't hurt.
+          size_t plen = (path == NULL) ? 0 : strlen(path);
+          if (plen == 0) {
+            continue; // Skip the empty path values.
+          }
+          const char lastchar = path[plen - 1];
+          retval = conc_path_file_and_check(buffer, buffer, buflen, path, lastchar, fullfname);
+          if (retval) break;
+        }
+        // Release the storage allocated by split_path.
+        for (int i = 0; i < n; i++) {
+          if (pelements[i] != NULL) {
+            FREE_C_HEAP_ARRAY(char, pelements[i]);
+          }
+        }
+        FREE_C_HEAP_ARRAY(char*, pelements);
+      }
+    } else {
+      // A definite path.
+      const char lastchar = pname[pnamelen-1];
+      retval = conc_path_file_and_check(buffer, buffer, buflen, pname, lastchar, fullfname);
+    }
+  }
+
+  FREE_C_HEAP_ARRAY(char*, fullfname);
+  return retval;
+}
 
 // --------------------- sun.misc.Signal (optional) ---------------------
 
@@ -427,13 +503,13 @@
     // Try to load verify dll first. In 1.3 java dll depends on it and is not
     // always able to find it when the loading executable is outside the JDK.
     // In order to keep working with 1.2 we ignore any loading errors.
-    if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(),
+    if (dll_locate_lib(buffer, sizeof(buffer), Arguments::get_dll_dir(),
                        "verify")) {
       dll_load(buffer, ebuf, sizeof(ebuf));
     }
 
     // Load java dll
-    if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(),
+    if (dll_locate_lib(buffer, sizeof(buffer), Arguments::get_dll_dir(),
                        "java")) {
       _native_java_library = dll_load(buffer, ebuf, sizeof(ebuf));
     }
@@ -444,7 +520,7 @@
 #if defined(__OpenBSD__)
     // Work-around OpenBSD's lack of $ORIGIN support by pre-loading libnet.so
     // ignore errors
-    if (dll_build_name(buffer, sizeof(buffer), Arguments::get_dll_dir(),
+    if (dll_locate_lib(buffer, sizeof(buffer), Arguments::get_dll_dir(),
                        "net")) {
       dll_load(buffer, ebuf, sizeof(ebuf));
     }