1 // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2 package org
.rocksdb
.util
;
5 import java
.io
.IOException
;
7 public class Environment
{
8 private static String OS
= System
.getProperty("os.name").toLowerCase();
9 private static String ARCH
= System
.getProperty("os.arch").toLowerCase();
10 private static String MUSL_ENVIRONMENT
= System
.getenv("ROCKSDB_MUSL_LIBC");
13 * Will be lazily initialised by {@link #isMuslLibc()} instead of the previous static
14 * initialisation. The lazy initialisation prevents Windows from reporting suspicious behaviour of
15 * the JVM attempting IO on Unix paths.
17 private static Boolean MUSL_LIBC
= null;
19 public static boolean isAarch64() {
20 return ARCH
.contains("aarch64");
23 public static boolean isPowerPC() {
24 return ARCH
.contains("ppc");
27 public static boolean isS390x() {
28 return ARCH
.contains("s390x");
31 public static boolean isWindows() {
32 return (OS
.contains("win"));
35 public static boolean isFreeBSD() {
36 return (OS
.contains("freebsd"));
39 public static boolean isMac() {
40 return (OS
.contains("mac"));
43 public static boolean isAix() {
44 return OS
.contains("aix");
47 public static boolean isUnix() {
48 return OS
.contains("nix") ||
53 * Determine if the environment has a musl libc.
55 * @return true if the environment has a musl libc, false otherwise.
57 public static boolean isMuslLibc() {
58 if (MUSL_LIBC
== null) {
59 MUSL_LIBC
= initIsMuslLibc();
65 * Determine if the environment has a musl libc.
67 * The initialisation counterpart of {@link #isMuslLibc()}.
69 * Intentionally package-private for testing.
71 * @return true if the environment has a musl libc, false otherwise.
73 static boolean initIsMuslLibc() {
74 // consider explicit user setting from environment first
75 if ("true".equalsIgnoreCase(MUSL_ENVIRONMENT
)) {
78 if ("false".equalsIgnoreCase(MUSL_ENVIRONMENT
)) {
82 // check if ldd indicates a muslc lib
85 new ProcessBuilder("/usr/bin/env", "sh", "-c", "ldd /usr/bin/env | grep -q musl").start();
86 if (p
.waitFor() == 0) {
89 } catch (final IOException
| InterruptedException e
) {
90 // do nothing, and move on to the next check
93 final File lib
= new File("/lib");
94 if (lib
.exists() && lib
.isDirectory() && lib
.canRead()) {
95 // attempt the most likely musl libc name first
96 final String possibleMuslcLibName
;
98 possibleMuslcLibName
= "libc.musl-ppc64le.so.1";
99 } else if (isAarch64()) {
100 possibleMuslcLibName
= "libc.musl-aarch64.so.1";
101 } else if (isS390x()) {
102 possibleMuslcLibName
= "libc.musl-s390x.so.1";
104 possibleMuslcLibName
= "libc.musl-x86_64.so.1";
106 final File possibleMuslcLib
= new File(lib
, possibleMuslcLibName
);
107 if (possibleMuslcLib
.exists() && possibleMuslcLib
.canRead()) {
111 // fallback to scanning for a musl libc
112 final File
[] libFiles
= lib
.listFiles();
113 if (libFiles
== null) {
116 for (final File f
: libFiles
) {
117 if (f
.getName().startsWith("libc.musl")) {
126 public static boolean isSolaris() {
127 return OS
.contains("sunos");
130 public static boolean isOpenBSD() {
131 return (OS
.contains("openbsd"));
134 public static boolean is64Bit() {
135 if (ARCH
.indexOf("sparcv9") >= 0) {
138 return (ARCH
.indexOf("64") > 0);
141 public static String
getSharedLibraryName(final String name
) {
145 public static String
getSharedLibraryFileName(final String name
) {
146 return appendLibOsSuffix("lib" + getSharedLibraryName(name
), true);
150 * Get the name of the libc implementation
152 * @return the name of the implementation,
153 * or null if the default for that platform (e.g. glibc on Linux).
155 public static /* @Nullable */ String
getLibcName() {
163 private static String
getLibcPostfix() {
164 final String libcName
= getLibcName();
165 if (libcName
== null) {
168 return "-" + libcName
;
171 public static String
getJniLibraryName(final String name
) {
173 final String arch
= is64Bit() ?
"64" : "32";
174 if (isPowerPC() || isAarch64()) {
175 return String
.format("%sjni-linux-%s%s", name
, ARCH
, getLibcPostfix());
176 } else if (isS390x()) {
177 return String
.format("%sjni-linux-%s", name
, ARCH
);
179 return String
.format("%sjni-linux%s%s", name
, arch
, getLibcPostfix());
181 } else if (isMac()) {
189 return String
.format("%sjni-osx-%s", name
, arch
);
191 return String
.format("%sjni-osx", name
);
193 } else if (isFreeBSD()) {
194 return String
.format("%sjni-freebsd%s", name
, is64Bit() ?
"64" : "32");
195 } else if (isAix() && is64Bit()) {
196 return String
.format("%sjni-aix64", name
);
197 } else if (isSolaris()) {
198 final String arch
= is64Bit() ?
"64" : "32";
199 return String
.format("%sjni-solaris%s", name
, arch
);
200 } else if (isWindows() && is64Bit()) {
201 return String
.format("%sjni-win64", name
);
202 } else if (isOpenBSD()) {
203 return String
.format("%sjni-openbsd%s", name
, is64Bit() ?
"64" : "32");
206 throw new UnsupportedOperationException(String
.format("Cannot determine JNI library name for ARCH='%s' OS='%s' name='%s'", ARCH
, OS
, name
));
209 public static /*@Nullable*/ String
getFallbackJniLibraryName(final String name
) {
210 if (isMac() && is64Bit()) {
211 return String
.format("%sjni-osx", name
);
216 public static String
getJniLibraryFileName(final String name
) {
217 return appendLibOsSuffix("lib" + getJniLibraryName(name
), false);
220 public static /*@Nullable*/ String
getFallbackJniLibraryFileName(final String name
) {
221 final String fallbackJniLibraryName
= getFallbackJniLibraryName(name
);
222 if (fallbackJniLibraryName
== null) {
225 return appendLibOsSuffix("lib" + fallbackJniLibraryName
, false);
228 private static String
appendLibOsSuffix(final String libraryFileName
, final boolean shared
) {
229 if (isUnix() || isAix() || isSolaris() || isFreeBSD() || isOpenBSD()) {
230 return libraryFileName
+ ".so";
231 } else if (isMac()) {
232 return libraryFileName
+ (shared ?
".dylib" : ".jnilib");
233 } else if (isWindows()) {
234 return libraryFileName
+ ".dll";
236 throw new UnsupportedOperationException();
239 public static String
getJniLibraryExtension() {
243 return (isMac()) ?
".jnilib" : ".so";