mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
8244224: Implementation of JEP 381: Remove the Solaris and SPARC Ports
Reviewed-by: alanb, bchristi, dcubed, dfuchs, eosterlund, erikj, glaubitz, ihse, iignatyev, jjiang, kbarrett, ksrini, kvn, naoto, prr, rriggs, serb, sspitsyn, stefank, tschatzl, valeriep, weijun, weijun
This commit is contained in:
parent
9fe4b69c1a
commit
071bd521bc
954 changed files with 1093 additions and 127816 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -40,7 +40,7 @@ import sun.security.action.GetPropertyAction;
|
|||
|
||||
public final class SdpSupport {
|
||||
private static final String os = GetPropertyAction.privilegedGetProperty("os.name");
|
||||
private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
|
||||
private static final boolean isSupported = os.equals("Linux");
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -495,7 +495,7 @@ public class Net {
|
|||
private static native boolean isReusePortAvailable0();
|
||||
|
||||
/*
|
||||
* Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
|
||||
* Returns 1 for Windows and -1 for Linux/Mac OS
|
||||
*/
|
||||
private static native int isExclusiveBindAvailable();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
|
@ -43,8 +43,6 @@
|
|||
#define SO_REUSEPORT 0
|
||||
#elif defined(__linux__)
|
||||
#define SO_REUSEPORT 15
|
||||
#elif defined(__solaris__)
|
||||
#define SO_REUSEPORT 0x100e
|
||||
#elif defined(AIX) || defined(MACOSX)
|
||||
#define SO_REUSEPORT 0x0200
|
||||
#else
|
||||
|
@ -52,10 +50,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* On Solaris, "sun" is defined as a macro. Undefine to make package
|
||||
declaration valid */
|
||||
#undef sun
|
||||
|
||||
/* To be able to name the Java constants the same as the C constants without
|
||||
having the preprocessor rewrite those identifiers, add PREFIX_ to all
|
||||
identifiers matching a C constant. The PREFIX_ is filtered out in the
|
||||
|
|
|
@ -300,14 +300,11 @@ public class KeyStoreUtil {
|
|||
public static void loadProviderByClass(
|
||||
String provClass, String arg, ClassLoader cl) {
|
||||
|
||||
// For compatibility, SunPKCS11, OracleUcrypto, and SunMSCAPI
|
||||
// For compatibility, SunPKCS11, and SunMSCAPI
|
||||
// can still be loadable with -providerClass.
|
||||
if (provClass.equals("sun.security.pkcs11.SunPKCS11")) {
|
||||
loadProviderByName("SunPKCS11", arg);
|
||||
return;
|
||||
} else if (provClass.equals("com.oracle.security.crypto.UcryptoProvider")) {
|
||||
loadProviderByName("OracleUcrypto", arg);
|
||||
return;
|
||||
} else if (provClass.equals("sun.security.mscapi.SunMSCAPI")) {
|
||||
loadProviderByName("SunMSCAPI", arg);
|
||||
return;
|
||||
|
|
|
@ -226,7 +226,6 @@ public final class KeyUtil {
|
|||
return providerName != null &&
|
||||
(providerName.equals("SunJCE") ||
|
||||
providerName.equals("SunMSCAPI") ||
|
||||
providerName.equals("OracleUcrypto") ||
|
||||
providerName.startsWith("SunPKCS11"));
|
||||
}
|
||||
|
||||
|
|
|
@ -60,12 +60,6 @@
|
|||
#
|
||||
# List of providers and their preference orders (see above):
|
||||
#
|
||||
#ifdef solaris
|
||||
# Note: The OracleUcrypto provider is deprecated and subject to removal in
|
||||
# a future version of the JDK.
|
||||
security.provider.tbd=OracleUcrypto
|
||||
security.provider.tbd=SunPKCS11 ${java.home}/conf/security/sunpkcs11-solaris.cfg
|
||||
#endif
|
||||
security.provider.tbd=SUN
|
||||
security.provider.tbd=SunRsaSign
|
||||
security.provider.tbd=SunEC
|
||||
|
@ -83,9 +77,7 @@ security.provider.tbd=SunMSCAPI
|
|||
#ifdef macosx
|
||||
security.provider.tbd=Apple
|
||||
#endif
|
||||
#ifndef solaris
|
||||
security.provider.tbd=SunPKCS11
|
||||
#endif
|
||||
|
||||
#
|
||||
# A list of preferred providers for specific algorithms. These providers will
|
||||
|
@ -119,12 +111,6 @@ security.provider.tbd=SunPKCS11
|
|||
# jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \
|
||||
# MessageDigest.SHA-256:SUN, Group.HmacSHA2:SunJCE
|
||||
#
|
||||
#ifdef solaris-sparc
|
||||
# Optional Solaris-SPARC configuration for non-FIPS 140 configurations.
|
||||
# jdk.security.provider.preferred=AES:SunJCE, SHA1:SUN, Group.SHA2:SUN, \
|
||||
# HmacSHA1:SunJCE, Group.HmacSHA2:SunJCE
|
||||
#
|
||||
#endif
|
||||
#jdk.security.provider.preferred=
|
||||
|
||||
|
||||
|
@ -135,7 +121,7 @@ security.provider.tbd=SunPKCS11
|
|||
# and "DRBG" SecureRandom implementations in the "Sun" provider.
|
||||
# (Other SecureRandom implementations might also use this property.)
|
||||
#
|
||||
# On Unix-like systems (for example, Solaris/Linux/MacOS), the
|
||||
# On Unix-like systems (for example, Linux/MacOS), the
|
||||
# "NativePRNG", "SHA1PRNG" and "DRBG" implementations obtains seed data from
|
||||
# special device files such as file:/dev/random.
|
||||
#
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -60,7 +60,6 @@
|
|||
|
||||
#define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR
|
||||
#define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR
|
||||
#define JVM_ERROR3 "Error: SPARC V8 processor detected; Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1
|
||||
|
||||
#define JAR_ERROR1 "Error: Failed to load Main-Class manifest attribute from\n%s\n%s"
|
||||
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
|
||||
|
@ -94,7 +93,7 @@
|
|||
#define JRE_ERROR3 "Error: Improper value at line %d."
|
||||
#define JRE_ERROR4 "Error: trying to exec %s.\nCheck if file exists and permissions are set correctly."
|
||||
#define JRE_ERROR5 "Error: Failed to start a %d-bit JVM process from a %d-bit JVM."
|
||||
#define JRE_ERROR6 "Error: Verify all necessary Java SE components have been installed.\n(Solaris SPARC 64-bit components must be installed after 32-bit components.)"
|
||||
#define JRE_ERROR6 "Error: Verify all necessary Java SE components have been installed."
|
||||
#define JRE_ERROR7 "Error: Either 64-bit processes are not supported by this platform\nor the 64-bit components have not been installed."
|
||||
#define JRE_ERROR8 "Error: could not find "
|
||||
#define JRE_ERROR9 "Error: Unable to resolve %s"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -104,9 +104,6 @@ JLI_CmdToArgs(char *cmdline);
|
|||
#define JLI_Open open
|
||||
#define JLI_PutEnv putenv
|
||||
#define JLI_GetPid getpid
|
||||
#ifdef __solaris__
|
||||
#define JLI_Lseek llseek
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#define _LARGFILE64_SOURCE
|
||||
#define JLI_Lseek lseek64
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -81,7 +81,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
|
|||
/* check if SO_REUSEPORT is supported on this platform */
|
||||
REUSEPORT_available = reuseport_supported();
|
||||
platformInit();
|
||||
parseExclusiveBindProperty(env);
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -156,8 +156,6 @@ NET_SockaddrToInetAddress(JNIEnv *env, SOCKETADDRESS *sa, int *port);
|
|||
|
||||
void platformInit();
|
||||
|
||||
void parseExclusiveBindProperty(JNIEnv *env);
|
||||
|
||||
JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(SOCKETADDRESS *sa);
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
exports sun.nio.ch to jdk.crypto.ucrypto;
|
||||
exports sun.security.action to jdk.crypto.ucrypto;
|
||||
exports sun.security.internal.spec to jdk.crypto.ucrypto;
|
||||
exports sun.security.jca to jdk.crypto.ucrypto;
|
||||
exports sun.security.rsa to jdk.crypto.ucrypto;
|
||||
exports sun.security.util to jdk.crypto.ucrypto;
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
|
||||
/**
|
||||
* Creates this platform's default AsynchronousChannelProvider
|
||||
*/
|
||||
|
||||
public class DefaultAsynchronousChannelProvider {
|
||||
|
||||
/**
|
||||
* Prevent instantiation.
|
||||
*/
|
||||
private DefaultAsynchronousChannelProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the default AsynchronousChannelProvider.
|
||||
*/
|
||||
public static AsynchronousChannelProvider create() {
|
||||
return new SolarisAsynchronousChannelProvider();
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* Creates this platform's default SelectorProvider
|
||||
*/
|
||||
|
||||
public class DefaultSelectorProvider {
|
||||
private static final SelectorProviderImpl INSTANCE;
|
||||
static {
|
||||
PrivilegedAction<SelectorProviderImpl> pa = DevPollSelectorProvider::new;
|
||||
INSTANCE = AccessController.doPrivileged(pa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent instantiation.
|
||||
*/
|
||||
private DefaultSelectorProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the default SelectorProvider implementation.
|
||||
*/
|
||||
public static SelectorProviderImpl get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Manipulates a native array of pollfd structs on Solaris:
|
||||
*
|
||||
* typedef struct pollfd {
|
||||
* int fd;
|
||||
* short events;
|
||||
* short revents;
|
||||
* } pollfd_t;
|
||||
*
|
||||
* @author Mike McCloskey
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
class DevPollArrayWrapper {
|
||||
|
||||
// special event to remove a file descriptor from the driver
|
||||
static final short POLLREMOVE = 0x0800;
|
||||
|
||||
// struct pollfd constants
|
||||
static final short SIZE_POLLFD = 8;
|
||||
static final short FD_OFFSET = 0;
|
||||
static final short EVENT_OFFSET = 4;
|
||||
static final short REVENT_OFFSET = 6;
|
||||
|
||||
// maximum number of pollfd structure to poll or update at a time
|
||||
// dpwrite/ioctl(DP_POLL) allows up to file descriptor limit minus 1
|
||||
static final int NUM_POLLFDS = Math.min(IOUtil.fdLimit()-1, 1024);
|
||||
|
||||
// The pollfd array for results from devpoll driver
|
||||
private final AllocatedNativeObject pollArray;
|
||||
|
||||
// Base address of the native pollArray
|
||||
private final long pollArrayAddress;
|
||||
|
||||
// The fd of the devpoll driver
|
||||
private int wfd;
|
||||
|
||||
DevPollArrayWrapper() throws IOException {
|
||||
this.wfd = init();
|
||||
|
||||
int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
|
||||
this.pollArray = new AllocatedNativeObject(allocationSize, true);
|
||||
this.pollArrayAddress = pollArray.address();
|
||||
}
|
||||
|
||||
void close() throws IOException {
|
||||
FileDispatcherImpl.closeIntFD(wfd);
|
||||
pollArray.free();
|
||||
}
|
||||
|
||||
void register(int fd, int ops) throws IOException {
|
||||
register(wfd, fd, ops);
|
||||
}
|
||||
|
||||
void registerMultiple(int numfds) throws IOException {
|
||||
registerMultiple(wfd, pollArrayAddress, numfds);
|
||||
}
|
||||
|
||||
int poll(long timeout) throws IOException {
|
||||
return poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
|
||||
}
|
||||
|
||||
int getDescriptor(int i) {
|
||||
int offset = SIZE_POLLFD * i + FD_OFFSET;
|
||||
return pollArray.getInt(offset);
|
||||
}
|
||||
|
||||
short getEventOps(int i) {
|
||||
int offset = SIZE_POLLFD * i + EVENT_OFFSET;
|
||||
return pollArray.getShort(offset);
|
||||
}
|
||||
|
||||
short getReventOps(int i) {
|
||||
int offset = SIZE_POLLFD * i + REVENT_OFFSET;
|
||||
return pollArray.getShort(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the pollfd structure at the given index
|
||||
*/
|
||||
void putPollFD(int index, int fd, short event) {
|
||||
int structIndex = SIZE_POLLFD * index;
|
||||
pollArray.putInt(structIndex + FD_OFFSET, fd);
|
||||
pollArray.putShort(structIndex + EVENT_OFFSET, event);
|
||||
pollArray.putShort(structIndex + REVENT_OFFSET, (short)0);
|
||||
}
|
||||
|
||||
private native int init() throws IOException;
|
||||
private native void register(int wfd, int fd, int mask) throws IOException;
|
||||
private native void registerMultiple(int wfd, long address, int len)
|
||||
throws IOException;
|
||||
private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
|
||||
throws IOException;
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
}
|
|
@ -1,263 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.ClosedSelectorException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS;
|
||||
import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE;
|
||||
|
||||
/**
|
||||
* Solaris /dev/poll based Selector implementation
|
||||
*/
|
||||
|
||||
class DevPollSelectorImpl
|
||||
extends SelectorImpl
|
||||
{
|
||||
// provides access to /dev/poll driver
|
||||
private final DevPollArrayWrapper pollWrapper;
|
||||
|
||||
// file descriptors used for interrupt
|
||||
private final int fd0;
|
||||
private final int fd1;
|
||||
|
||||
// maps file descriptor to selection key, synchronize on selector
|
||||
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
|
||||
|
||||
// pending new registrations/updates, queued by setEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
private boolean interruptTriggered;
|
||||
|
||||
DevPollSelectorImpl(SelectorProvider sp) throws IOException {
|
||||
super(sp);
|
||||
this.pollWrapper = new DevPollArrayWrapper();
|
||||
try {
|
||||
long fds = IOUtil.makePipe(false);
|
||||
this.fd0 = (int) (fds >>> 32);
|
||||
this.fd1 = (int) fds;
|
||||
} catch (IOException ioe) {
|
||||
pollWrapper.close();
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
// register one end of the socket pair for wakeups
|
||||
pollWrapper.register(fd0, Net.POLLIN);
|
||||
}
|
||||
|
||||
private void ensureOpen() {
|
||||
if (!isOpen())
|
||||
throw new ClosedSelectorException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doSelect(Consumer<SelectionKey> action, long timeout)
|
||||
throws IOException
|
||||
{
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
long to = timeout;
|
||||
boolean blocking = (to != 0);
|
||||
boolean timedPoll = (to > 0);
|
||||
|
||||
int numEntries;
|
||||
processUpdateQueue();
|
||||
processDeregisterQueue();
|
||||
try {
|
||||
begin(blocking);
|
||||
|
||||
do {
|
||||
long startTime = timedPoll ? System.nanoTime() : 0;
|
||||
numEntries = pollWrapper.poll(to);
|
||||
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
|
||||
// timed poll interrupted so need to adjust timeout
|
||||
long adjust = System.nanoTime() - startTime;
|
||||
to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
|
||||
if (to <= 0) {
|
||||
// timeout expired so no retry
|
||||
numEntries = 0;
|
||||
}
|
||||
}
|
||||
} while (numEntries == IOStatus.INTERRUPTED);
|
||||
assert IOStatus.check(numEntries);
|
||||
|
||||
} finally {
|
||||
end(blocking);
|
||||
}
|
||||
processDeregisterQueue();
|
||||
return processEvents(numEntries, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process changes to the interest ops.
|
||||
*/
|
||||
private void processUpdateQueue() throws IOException {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
|
||||
// Translate the queued updates to changes to the set of monitored
|
||||
// file descriptors. The changes are written to the /dev/poll driver
|
||||
// in bulk.
|
||||
int index = 0;
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
if (newEvents != registeredEvents) {
|
||||
if (registeredEvents != 0)
|
||||
pollWrapper.putPollFD(index++, fd, POLLREMOVE);
|
||||
if (newEvents != 0)
|
||||
pollWrapper.putPollFD(index++, fd, (short)newEvents);
|
||||
ski.registeredEvents(newEvents);
|
||||
|
||||
// write to /dev/poll
|
||||
if (index > (NUM_POLLFDS-2)) {
|
||||
pollWrapper.registerMultiple(index);
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write any remaining changes
|
||||
if (index > 0)
|
||||
pollWrapper.registerMultiple(index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the polled events.
|
||||
* If the interrupt fd has been selected, drain it and clear the interrupt.
|
||||
*/
|
||||
private int processEvents(int numEntries, Consumer<SelectionKey> action)
|
||||
throws IOException
|
||||
{
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
boolean interrupted = false;
|
||||
int numKeysUpdated = 0;
|
||||
for (int i=0; i<numEntries; i++) {
|
||||
int fd = pollWrapper.getDescriptor(i);
|
||||
if (fd == fd0) {
|
||||
interrupted = true;
|
||||
} else {
|
||||
SelectionKeyImpl ski = fdToKey.get(fd);
|
||||
if (ski != null) {
|
||||
int rOps = pollWrapper.getReventOps(i);
|
||||
numKeysUpdated += processReadyEvents(rOps, ski, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted) {
|
||||
clearInterrupt();
|
||||
}
|
||||
|
||||
return numKeysUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implClose() throws IOException {
|
||||
assert !isOpen();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
// prevent further wakeup
|
||||
synchronized (interruptLock) {
|
||||
interruptTriggered = true;
|
||||
}
|
||||
|
||||
pollWrapper.close();
|
||||
FileDispatcherImpl.closeIntFD(fd0);
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.getFDVal();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (ski.registeredEvents() != 0) {
|
||||
pollWrapper.register(fd, POLLREMOVE);
|
||||
ski.registeredEvents(0);
|
||||
}
|
||||
} else {
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector wakeup() {
|
||||
synchronized (interruptLock) {
|
||||
if (!interruptTriggered) {
|
||||
try {
|
||||
IOUtil.write1(fd1, (byte)0);
|
||||
} catch (IOException ioe) {
|
||||
throw new InternalError(ioe);
|
||||
}
|
||||
interruptTriggered = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearInterrupt() throws IOException {
|
||||
synchronized (interruptLock) {
|
||||
IOUtil.drain(fd0);
|
||||
interruptTriggered = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
|
||||
public class DevPollSelectorProvider
|
||||
extends SelectorProviderImpl
|
||||
{
|
||||
public AbstractSelector openSelector() throws IOException {
|
||||
return new DevPollSelectorImpl(this);
|
||||
}
|
||||
|
||||
public Channel inheritedChannel() throws IOException {
|
||||
return InheritedChannel.getChannel();
|
||||
}
|
||||
}
|
|
@ -1,308 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.ClosedSelectorException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_FD;
|
||||
import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_USER;
|
||||
import static sun.nio.ch.SolarisEventPort.SIZEOF_PORT_EVENT;
|
||||
import static sun.nio.ch.SolarisEventPort.OFFSETOF_EVENTS;
|
||||
import static sun.nio.ch.SolarisEventPort.OFFSETOF_SOURCE;
|
||||
import static sun.nio.ch.SolarisEventPort.OFFSETOF_OBJECT;
|
||||
import static sun.nio.ch.SolarisEventPort.port_create;
|
||||
import static sun.nio.ch.SolarisEventPort.port_close;
|
||||
import static sun.nio.ch.SolarisEventPort.port_associate;
|
||||
import static sun.nio.ch.SolarisEventPort.port_dissociate;
|
||||
import static sun.nio.ch.SolarisEventPort.port_getn;
|
||||
import static sun.nio.ch.SolarisEventPort.port_send;
|
||||
|
||||
/**
|
||||
* Selector implementation based on the Solaris event port mechanism.
|
||||
*/
|
||||
|
||||
class EventPortSelectorImpl
|
||||
extends SelectorImpl
|
||||
{
|
||||
// maximum number of events to retrive in one call to port_getn
|
||||
static final int MAX_EVENTS = Math.min(IOUtil.fdLimit()-1, 1024);
|
||||
|
||||
// port file descriptor
|
||||
private final int pfd;
|
||||
|
||||
// the poll array (populated by port_getn)
|
||||
private final long pollArrayAddress;
|
||||
private final AllocatedNativeObject pollArray;
|
||||
|
||||
// maps file descriptor to selection key, synchronize on selector
|
||||
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
|
||||
|
||||
// the last update operation, incremented by processUpdateQueue
|
||||
private int lastUpdate;
|
||||
|
||||
// pending new registrations/updates, queued by setEventOps and
|
||||
// updateSelectedKeys
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
private boolean interruptTriggered;
|
||||
|
||||
EventPortSelectorImpl(SelectorProvider sp) throws IOException {
|
||||
super(sp);
|
||||
|
||||
this.pfd = port_create();
|
||||
|
||||
int allocationSize = MAX_EVENTS * SIZEOF_PORT_EVENT;
|
||||
this.pollArray = new AllocatedNativeObject(allocationSize, false);
|
||||
this.pollArrayAddress = pollArray.address();
|
||||
}
|
||||
|
||||
private void ensureOpen() {
|
||||
if (!isOpen())
|
||||
throw new ClosedSelectorException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doSelect(Consumer<SelectionKey> action, long timeout)
|
||||
throws IOException
|
||||
{
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
long to = timeout;
|
||||
boolean blocking = (to != 0);
|
||||
boolean timedPoll = (to > 0);
|
||||
|
||||
int numEvents;
|
||||
processUpdateQueue();
|
||||
processDeregisterQueue();
|
||||
try {
|
||||
begin(blocking);
|
||||
|
||||
do {
|
||||
long startTime = timedPoll ? System.nanoTime() : 0;
|
||||
numEvents = port_getn(pfd, pollArrayAddress, MAX_EVENTS, to);
|
||||
if (numEvents == IOStatus.INTERRUPTED && timedPoll) {
|
||||
// timed poll interrupted so need to adjust timeout
|
||||
long adjust = System.nanoTime() - startTime;
|
||||
to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
|
||||
if (to <= 0) {
|
||||
// timeout also expired so no retry
|
||||
numEvents = 0;
|
||||
}
|
||||
}
|
||||
} while (numEvents == IOStatus.INTERRUPTED);
|
||||
assert IOStatus.check(numEvents);
|
||||
|
||||
} finally {
|
||||
end(blocking);
|
||||
}
|
||||
processDeregisterQueue();
|
||||
return processPortEvents(numEvents, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new registrations and changes to the interest ops.
|
||||
*/
|
||||
private void processUpdateQueue() throws IOException {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
// bump lastUpdate to ensure that the interest ops are changed at most
|
||||
// once per bulk update
|
||||
lastUpdate++;
|
||||
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
if (newEvents != ski.registeredEvents()) {
|
||||
if (newEvents == 0) {
|
||||
port_dissociate(pfd, PORT_SOURCE_FD, fd);
|
||||
} else {
|
||||
port_associate(pfd, PORT_SOURCE_FD, fd, newEvents);
|
||||
}
|
||||
ski.registeredEvents(newEvents);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the polled events and re-queue the selected keys so the file
|
||||
* descriptors are re-associated at the next select operation.
|
||||
*/
|
||||
private int processPortEvents(int numEvents, Consumer<SelectionKey> action)
|
||||
throws IOException
|
||||
{
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int numKeysUpdated = 0;
|
||||
boolean interrupted = false;
|
||||
|
||||
// Process the polled events while holding the update lock. This allows
|
||||
// keys to be queued for ready file descriptors so they can be
|
||||
// re-associated at the next select. The selected-key can be updated
|
||||
// in this pass.
|
||||
synchronized (updateLock) {
|
||||
for (int i = 0; i < numEvents; i++) {
|
||||
short source = getSource(i);
|
||||
if (source == PORT_SOURCE_FD) {
|
||||
int fd = getDescriptor(i);
|
||||
SelectionKeyImpl ski = fdToKey.get(fd);
|
||||
if (ski != null) {
|
||||
ski.registeredEvents(0);
|
||||
updateKeys.addLast(ski);
|
||||
|
||||
// update selected-key set if no action specified
|
||||
if (action == null) {
|
||||
int rOps = getEventOps(i);
|
||||
numKeysUpdated += processReadyEvents(rOps, ski, null);
|
||||
}
|
||||
|
||||
}
|
||||
} else if (source == PORT_SOURCE_USER) {
|
||||
interrupted = true;
|
||||
} else {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if an action specified then iterate over the polled events again so
|
||||
// that the action is performed without holding the update lock.
|
||||
if (action != null) {
|
||||
for (int i = 0; i < numEvents; i++) {
|
||||
short source = getSource(i);
|
||||
if (source == PORT_SOURCE_FD) {
|
||||
int fd = getDescriptor(i);
|
||||
SelectionKeyImpl ski = fdToKey.get(fd);
|
||||
if (ski != null) {
|
||||
int rOps = getEventOps(i);
|
||||
numKeysUpdated += processReadyEvents(rOps, ski, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted) {
|
||||
clearInterrupt();
|
||||
}
|
||||
return numKeysUpdated;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implClose() throws IOException {
|
||||
assert !isOpen();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
// prevent further wakeup
|
||||
synchronized (interruptLock) {
|
||||
interruptTriggered = true;
|
||||
}
|
||||
|
||||
port_close(pfd);
|
||||
pollArray.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.getFDVal();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (ski.registeredEvents() != 0) {
|
||||
port_dissociate(pfd, PORT_SOURCE_FD, fd);
|
||||
ski.registeredEvents(0);
|
||||
}
|
||||
} else {
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Selector wakeup() {
|
||||
synchronized (interruptLock) {
|
||||
if (!interruptTriggered) {
|
||||
try {
|
||||
port_send(pfd, 0);
|
||||
} catch (IOException ioe) {
|
||||
throw new InternalError(ioe);
|
||||
}
|
||||
interruptTriggered = true;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void clearInterrupt() throws IOException {
|
||||
synchronized (interruptLock) {
|
||||
interruptTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
private short getSource(int i) {
|
||||
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE;
|
||||
return pollArray.getShort(offset);
|
||||
}
|
||||
|
||||
private int getEventOps(int i) {
|
||||
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS;
|
||||
return pollArray.getInt(offset);
|
||||
}
|
||||
|
||||
private int getDescriptor(int i) {
|
||||
//assert Unsafe.getUnsafe().addressSize() == 8;
|
||||
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
|
||||
return (int) pollArray.getLong(offset);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
|
||||
public class EventPortSelectorProvider
|
||||
extends SelectorProviderImpl
|
||||
{
|
||||
public AbstractSelector openSelector() throws IOException {
|
||||
return new EventPortSelectorImpl(this);
|
||||
}
|
||||
|
||||
public Channel inheritedChannel() throws IOException {
|
||||
return InheritedChannel.getChannel();
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.io.IOException;
|
||||
|
||||
public class SolarisAsynchronousChannelProvider
|
||||
extends AsynchronousChannelProvider
|
||||
{
|
||||
private static volatile SolarisEventPort defaultEventPort;
|
||||
|
||||
private SolarisEventPort defaultEventPort() throws IOException {
|
||||
if (defaultEventPort == null) {
|
||||
synchronized (SolarisAsynchronousChannelProvider.class) {
|
||||
if (defaultEventPort == null) {
|
||||
defaultEventPort =
|
||||
new SolarisEventPort(this, ThreadPool.getDefault()).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultEventPort;
|
||||
}
|
||||
|
||||
public SolarisAsynchronousChannelProvider() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory factory)
|
||||
throws IOException
|
||||
{
|
||||
return new SolarisEventPort(this, ThreadPool.create(nThreads, factory)).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize)
|
||||
throws IOException
|
||||
{
|
||||
return new SolarisEventPort(this, ThreadPool.wrap(executor, initialSize)).start();
|
||||
}
|
||||
|
||||
private SolarisEventPort toEventPort(AsynchronousChannelGroup group)
|
||||
throws IOException
|
||||
{
|
||||
if (group == null) {
|
||||
return defaultEventPort();
|
||||
} else {
|
||||
if (!(group instanceof SolarisEventPort))
|
||||
throw new IllegalChannelGroupException();
|
||||
return (SolarisEventPort)group;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group)
|
||||
throws IOException
|
||||
{
|
||||
return new UnixAsynchronousServerSocketChannelImpl(toEventPort(group));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group)
|
||||
throws IOException
|
||||
{
|
||||
return new UnixAsynchronousSocketChannelImpl(toEventPort(group));
|
||||
}
|
||||
}
|
|
@ -1,268 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.channels.spi.AsynchronousChannelProvider;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Provides an AsynchronousChannelGroup implementation based on the Solaris 10
|
||||
* event port framework and also provides direct access to that framework.
|
||||
*/
|
||||
|
||||
class SolarisEventPort
|
||||
extends Port
|
||||
{
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static final int addressSize = unsafe.addressSize();
|
||||
|
||||
private static int dependsArch(int value32, int value64) {
|
||||
return (addressSize == 4) ? value32 : value64;
|
||||
}
|
||||
|
||||
/*
|
||||
* typedef struct port_event {
|
||||
* int portev_events;
|
||||
* ushort_t portev_source;
|
||||
* ushort_t portev_pad;
|
||||
* uintptr_t portev_object;
|
||||
* void *portev_user;
|
||||
* } port_event_t;
|
||||
*/
|
||||
static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
|
||||
static final int OFFSETOF_EVENTS = 0;
|
||||
static final int OFFSETOF_SOURCE = 4;
|
||||
static final int OFFSETOF_OBJECT = 8;
|
||||
|
||||
// port sources
|
||||
static final short PORT_SOURCE_USER = 3;
|
||||
static final short PORT_SOURCE_FD = 4;
|
||||
|
||||
// file descriptor to event port.
|
||||
private final int port;
|
||||
|
||||
// true when port is closed
|
||||
private boolean closed;
|
||||
|
||||
SolarisEventPort(AsynchronousChannelProvider provider, ThreadPool pool)
|
||||
throws IOException
|
||||
{
|
||||
super(provider, pool);
|
||||
|
||||
// create event port
|
||||
this.port = port_create();
|
||||
}
|
||||
|
||||
SolarisEventPort start() {
|
||||
startThreads(new EventHandlerTask());
|
||||
return this;
|
||||
}
|
||||
|
||||
// releass resources
|
||||
private void implClose() {
|
||||
synchronized (this) {
|
||||
if (closed)
|
||||
return;
|
||||
closed = true;
|
||||
}
|
||||
port_close(port);
|
||||
}
|
||||
|
||||
private void wakeup() {
|
||||
try {
|
||||
port_send(port, 0);
|
||||
} catch (IOException x) {
|
||||
throw new AssertionError(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void executeOnHandlerTask(Runnable task) {
|
||||
synchronized (this) {
|
||||
if (closed)
|
||||
throw new RejectedExecutionException();
|
||||
offerTask(task);
|
||||
wakeup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void shutdownHandlerTasks() {
|
||||
/*
|
||||
* If no tasks are running then just release resources; otherwise
|
||||
* write to the one end of the socketpair to wakeup any polling threads..
|
||||
*/
|
||||
int nThreads = threadCount();
|
||||
if (nThreads == 0) {
|
||||
implClose();
|
||||
} else {
|
||||
// send user event to wakeup each thread
|
||||
while (nThreads-- > 0) {
|
||||
try {
|
||||
port_send(port, 0);
|
||||
} catch (IOException x) {
|
||||
throw new AssertionError(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void startPoll(int fd, int events) {
|
||||
// (re-)associate file descriptor
|
||||
// no need to translate events
|
||||
try {
|
||||
port_associate(port, PORT_SOURCE_FD, fd, events);
|
||||
} catch (IOException x) {
|
||||
throw new AssertionError(); // should not happen
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Task to read a single event from the port and dispatch it to the
|
||||
* channel's onEvent handler.
|
||||
*/
|
||||
private class EventHandlerTask implements Runnable {
|
||||
public void run() {
|
||||
Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
|
||||
Invoker.getGroupAndInvokeCount();
|
||||
final boolean isPooledThread = (myGroupAndInvokeCount != null);
|
||||
boolean replaceMe = false;
|
||||
long address = unsafe.allocateMemory(SIZEOF_PORT_EVENT);
|
||||
try {
|
||||
for (;;) {
|
||||
// reset invoke count
|
||||
if (isPooledThread)
|
||||
myGroupAndInvokeCount.resetInvokeCount();
|
||||
|
||||
// wait for I/O completion event
|
||||
// A error here is fatal (thread will not be replaced)
|
||||
replaceMe = false;
|
||||
try {
|
||||
int n;
|
||||
do {
|
||||
n = port_get(port, address);
|
||||
} while (n == IOStatus.INTERRUPTED);
|
||||
} catch (IOException x) {
|
||||
x.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// event source
|
||||
short source = unsafe.getShort(address + OFFSETOF_SOURCE);
|
||||
if (source != PORT_SOURCE_FD) {
|
||||
// user event is trigger to invoke task or shutdown
|
||||
if (source == PORT_SOURCE_USER) {
|
||||
Runnable task = pollTask();
|
||||
if (task == null) {
|
||||
// shutdown request
|
||||
return;
|
||||
}
|
||||
// run task (may throw error/exception)
|
||||
replaceMe = true;
|
||||
task.run();
|
||||
}
|
||||
// ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
// pe->portev_object is file descriptor
|
||||
int fd = (int)unsafe.getAddress(address + OFFSETOF_OBJECT);
|
||||
// pe->portev_events
|
||||
int events = unsafe.getInt(address + OFFSETOF_EVENTS);
|
||||
|
||||
// lookup channel
|
||||
PollableChannel ch;
|
||||
fdToChannelLock.readLock().lock();
|
||||
try {
|
||||
ch = fdToChannel.get(fd);
|
||||
} finally {
|
||||
fdToChannelLock.readLock().unlock();
|
||||
}
|
||||
|
||||
// notify channel
|
||||
if (ch != null) {
|
||||
replaceMe = true;
|
||||
// no need to translate events
|
||||
ch.onEvent(events, isPooledThread);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// free per-thread resources
|
||||
unsafe.freeMemory(address);
|
||||
// last task to exit when shutdown release resources
|
||||
int remaining = threadExit(this, replaceMe);
|
||||
if (remaining == 0 && isShutdown())
|
||||
implClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event port
|
||||
*/
|
||||
static native int port_create() throws IOException;
|
||||
|
||||
/**
|
||||
* Associates specific events of a given object with a port
|
||||
*/
|
||||
static native boolean port_associate(int port, int source, long object, int events)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Removes the association of an object with a port.
|
||||
*/
|
||||
static native boolean port_dissociate(int port, int source, long object)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Retrieves a single event from a port
|
||||
*/
|
||||
static native int port_get(int port, long address) throws IOException;
|
||||
|
||||
/**
|
||||
* Retrieves at most {@code max} events from a port.
|
||||
*/
|
||||
static native int port_getn(int port, long address, int max, long timeout)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Sends a user-defined eventto a specified port.
|
||||
*/
|
||||
static native void port_send(int port, int events) throws IOException;
|
||||
|
||||
/**
|
||||
* Closes a port.
|
||||
*/
|
||||
static native void port_close(int port);
|
||||
|
||||
|
||||
static {
|
||||
IOUtil.load();
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.FileSystem;
|
||||
|
||||
/**
|
||||
* Creates this platform's default FileSystemProvider.
|
||||
*/
|
||||
|
||||
public class DefaultFileSystemProvider {
|
||||
private static final SolarisFileSystemProvider INSTANCE
|
||||
= new SolarisFileSystemProvider();
|
||||
|
||||
private DefaultFileSystemProvider() { }
|
||||
|
||||
/**
|
||||
* Returns the platform's default file system provider.
|
||||
*/
|
||||
public static SolarisFileSystemProvider instance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform's default file system.
|
||||
*/
|
||||
public static FileSystem theFileSystem() {
|
||||
return INSTANCE.theFileSystem();
|
||||
}
|
||||
}
|
|
@ -1,413 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
import static sun.nio.fs.SolarisConstants.*;
|
||||
import static sun.nio.fs.SolarisNativeDispatcher.*;
|
||||
|
||||
|
||||
/**
|
||||
* Solaris implementation of AclFileAttributeView with native support for
|
||||
* NFSv4 ACLs on ZFS.
|
||||
*/
|
||||
|
||||
class SolarisAclFileAttributeView
|
||||
extends AbstractAclFileAttributeView
|
||||
{
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
// Maximum number of entries allowed in an ACL
|
||||
private static final int MAX_ACL_ENTRIES = 1024;
|
||||
|
||||
/**
|
||||
* typedef struct ace {
|
||||
* uid_t a_who;
|
||||
* uint32_t a_access_mask;
|
||||
* uint16_t a_flags;
|
||||
* uint16_t a_type;
|
||||
* } ace_t;
|
||||
*/
|
||||
private static final short SIZEOF_ACE_T = 12;
|
||||
private static final short OFFSETOF_UID = 0;
|
||||
private static final short OFFSETOF_MASK = 4;
|
||||
private static final short OFFSETOF_FLAGS = 8;
|
||||
private static final short OFFSETOF_TYPE = 10;
|
||||
|
||||
private final UnixPath file;
|
||||
private final boolean followLinks;
|
||||
|
||||
SolarisAclFileAttributeView(UnixPath file, boolean followLinks) {
|
||||
this.file = file;
|
||||
this.followLinks = followLinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission checks to access file
|
||||
*/
|
||||
private void checkAccess(UnixPath file,
|
||||
boolean checkRead,
|
||||
boolean checkWrite)
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
if (checkRead)
|
||||
file.checkRead();
|
||||
if (checkWrite)
|
||||
file.checkWrite();
|
||||
sm.checkPermission(new RuntimePermission("accessUserInformation"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the ACL to the given buffer
|
||||
*/
|
||||
private static void encode(List<AclEntry> acl, long address) {
|
||||
long offset = address;
|
||||
for (AclEntry ace: acl) {
|
||||
int flags = 0;
|
||||
|
||||
// map UserPrincipal to uid and flags
|
||||
UserPrincipal who = ace.principal();
|
||||
if (!(who instanceof UnixUserPrincipals.User))
|
||||
throw new ProviderMismatchException();
|
||||
UnixUserPrincipals.User user = (UnixUserPrincipals.User)who;
|
||||
int uid;
|
||||
if (user.isSpecial()) {
|
||||
uid = -1;
|
||||
if (who == UnixUserPrincipals.SPECIAL_OWNER)
|
||||
flags |= ACE_OWNER;
|
||||
else if (who == UnixUserPrincipals.SPECIAL_GROUP)
|
||||
flags |= (ACE_GROUP | ACE_IDENTIFIER_GROUP);
|
||||
else if (who == UnixUserPrincipals.SPECIAL_EVERYONE)
|
||||
flags |= ACE_EVERYONE;
|
||||
else
|
||||
throw new AssertionError("Unable to map special identifier");
|
||||
} else {
|
||||
if (user instanceof UnixUserPrincipals.Group) {
|
||||
uid = user.gid();
|
||||
flags |= ACE_IDENTIFIER_GROUP;
|
||||
} else {
|
||||
uid = user.uid();
|
||||
}
|
||||
}
|
||||
|
||||
// map ACE type
|
||||
int type;
|
||||
switch (ace.type()) {
|
||||
case ALLOW:
|
||||
type = ACE_ACCESS_ALLOWED_ACE_TYPE;
|
||||
break;
|
||||
case DENY:
|
||||
type = ACE_ACCESS_DENIED_ACE_TYPE;
|
||||
break;
|
||||
case AUDIT:
|
||||
type = ACE_SYSTEM_AUDIT_ACE_TYPE;
|
||||
break;
|
||||
case ALARM:
|
||||
type = ACE_SYSTEM_ALARM_ACE_TYPE;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Unable to map ACE type");
|
||||
}
|
||||
|
||||
// map permissions
|
||||
Set<AclEntryPermission> aceMask = ace.permissions();
|
||||
int mask = 0;
|
||||
if (aceMask.contains(AclEntryPermission.READ_DATA))
|
||||
mask |= ACE_READ_DATA;
|
||||
if (aceMask.contains(AclEntryPermission.WRITE_DATA))
|
||||
mask |= ACE_WRITE_DATA;
|
||||
if (aceMask.contains(AclEntryPermission.APPEND_DATA))
|
||||
mask |= ACE_APPEND_DATA;
|
||||
if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS))
|
||||
mask |= ACE_READ_NAMED_ATTRS;
|
||||
if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS))
|
||||
mask |= ACE_WRITE_NAMED_ATTRS;
|
||||
if (aceMask.contains(AclEntryPermission.EXECUTE))
|
||||
mask |= ACE_EXECUTE;
|
||||
if (aceMask.contains(AclEntryPermission.DELETE_CHILD))
|
||||
mask |= ACE_DELETE_CHILD;
|
||||
if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES))
|
||||
mask |= ACE_READ_ATTRIBUTES;
|
||||
if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES))
|
||||
mask |= ACE_WRITE_ATTRIBUTES;
|
||||
if (aceMask.contains(AclEntryPermission.DELETE))
|
||||
mask |= ACE_DELETE;
|
||||
if (aceMask.contains(AclEntryPermission.READ_ACL))
|
||||
mask |= ACE_READ_ACL;
|
||||
if (aceMask.contains(AclEntryPermission.WRITE_ACL))
|
||||
mask |= ACE_WRITE_ACL;
|
||||
if (aceMask.contains(AclEntryPermission.WRITE_OWNER))
|
||||
mask |= ACE_WRITE_OWNER;
|
||||
if (aceMask.contains(AclEntryPermission.SYNCHRONIZE))
|
||||
mask |= ACE_SYNCHRONIZE;
|
||||
|
||||
// FIXME - it would be desirable to know here if the file is a
|
||||
// directory or not. Solaris returns EINVAL if an ACE has a directory
|
||||
// -only flag and the file is not a directory.
|
||||
Set<AclEntryFlag> aceFlags = ace.flags();
|
||||
if (aceFlags.contains(AclEntryFlag.FILE_INHERIT))
|
||||
flags |= ACE_FILE_INHERIT_ACE;
|
||||
if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT))
|
||||
flags |= ACE_DIRECTORY_INHERIT_ACE;
|
||||
if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
|
||||
flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
|
||||
if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY))
|
||||
flags |= ACE_INHERIT_ONLY_ACE;
|
||||
|
||||
unsafe.putInt(offset + OFFSETOF_UID, uid);
|
||||
unsafe.putInt(offset + OFFSETOF_MASK, mask);
|
||||
unsafe.putShort(offset + OFFSETOF_FLAGS, (short)flags);
|
||||
unsafe.putShort(offset + OFFSETOF_TYPE, (short)type);
|
||||
|
||||
offset += SIZEOF_ACE_T;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the buffer, returning an ACL
|
||||
*/
|
||||
private static List<AclEntry> decode(long address, int n) {
|
||||
ArrayList<AclEntry> acl = new ArrayList<>(n);
|
||||
for (int i=0; i<n; i++) {
|
||||
long offset = address + i*SIZEOF_ACE_T;
|
||||
|
||||
int uid = unsafe.getInt(offset + OFFSETOF_UID);
|
||||
int mask = unsafe.getInt(offset + OFFSETOF_MASK);
|
||||
int flags = (int)unsafe.getShort(offset + OFFSETOF_FLAGS);
|
||||
int type = (int)unsafe.getShort(offset + OFFSETOF_TYPE);
|
||||
|
||||
// map uid and flags to UserPrincipal
|
||||
UnixUserPrincipals.User who = null;
|
||||
if ((flags & ACE_OWNER) > 0) {
|
||||
who = UnixUserPrincipals.SPECIAL_OWNER;
|
||||
} else if ((flags & ACE_GROUP) > 0) {
|
||||
who = UnixUserPrincipals.SPECIAL_GROUP;
|
||||
} else if ((flags & ACE_EVERYONE) > 0) {
|
||||
who = UnixUserPrincipals.SPECIAL_EVERYONE;
|
||||
} else if ((flags & ACE_IDENTIFIER_GROUP) > 0) {
|
||||
who = UnixUserPrincipals.fromGid(uid);
|
||||
} else {
|
||||
who = UnixUserPrincipals.fromUid(uid);
|
||||
}
|
||||
|
||||
AclEntryType aceType = null;
|
||||
switch (type) {
|
||||
case ACE_ACCESS_ALLOWED_ACE_TYPE:
|
||||
aceType = AclEntryType.ALLOW;
|
||||
break;
|
||||
case ACE_ACCESS_DENIED_ACE_TYPE:
|
||||
aceType = AclEntryType.DENY;
|
||||
break;
|
||||
case ACE_SYSTEM_AUDIT_ACE_TYPE:
|
||||
aceType = AclEntryType.AUDIT;
|
||||
break;
|
||||
case ACE_SYSTEM_ALARM_ACE_TYPE:
|
||||
aceType = AclEntryType.ALARM;
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
Set<AclEntryPermission> aceMask = EnumSet.noneOf(AclEntryPermission.class);
|
||||
if ((mask & ACE_READ_DATA) > 0)
|
||||
aceMask.add(AclEntryPermission.READ_DATA);
|
||||
if ((mask & ACE_WRITE_DATA) > 0)
|
||||
aceMask.add(AclEntryPermission.WRITE_DATA);
|
||||
if ((mask & ACE_APPEND_DATA ) > 0)
|
||||
aceMask.add(AclEntryPermission.APPEND_DATA);
|
||||
if ((mask & ACE_READ_NAMED_ATTRS) > 0)
|
||||
aceMask.add(AclEntryPermission.READ_NAMED_ATTRS);
|
||||
if ((mask & ACE_WRITE_NAMED_ATTRS) > 0)
|
||||
aceMask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
|
||||
if ((mask & ACE_EXECUTE) > 0)
|
||||
aceMask.add(AclEntryPermission.EXECUTE);
|
||||
if ((mask & ACE_DELETE_CHILD ) > 0)
|
||||
aceMask.add(AclEntryPermission.DELETE_CHILD);
|
||||
if ((mask & ACE_READ_ATTRIBUTES) > 0)
|
||||
aceMask.add(AclEntryPermission.READ_ATTRIBUTES);
|
||||
if ((mask & ACE_WRITE_ATTRIBUTES) > 0)
|
||||
aceMask.add(AclEntryPermission.WRITE_ATTRIBUTES);
|
||||
if ((mask & ACE_DELETE) > 0)
|
||||
aceMask.add(AclEntryPermission.DELETE);
|
||||
if ((mask & ACE_READ_ACL) > 0)
|
||||
aceMask.add(AclEntryPermission.READ_ACL);
|
||||
if ((mask & ACE_WRITE_ACL) > 0)
|
||||
aceMask.add(AclEntryPermission.WRITE_ACL);
|
||||
if ((mask & ACE_WRITE_OWNER) > 0)
|
||||
aceMask.add(AclEntryPermission.WRITE_OWNER);
|
||||
if ((mask & ACE_SYNCHRONIZE) > 0)
|
||||
aceMask.add(AclEntryPermission.SYNCHRONIZE);
|
||||
|
||||
Set<AclEntryFlag> aceFlags = EnumSet.noneOf(AclEntryFlag.class);
|
||||
if ((flags & ACE_FILE_INHERIT_ACE) > 0)
|
||||
aceFlags.add(AclEntryFlag.FILE_INHERIT);
|
||||
if ((flags & ACE_DIRECTORY_INHERIT_ACE) > 0)
|
||||
aceFlags.add(AclEntryFlag.DIRECTORY_INHERIT);
|
||||
if ((flags & ACE_NO_PROPAGATE_INHERIT_ACE) > 0)
|
||||
aceFlags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
|
||||
if ((flags & ACE_INHERIT_ONLY_ACE) > 0)
|
||||
aceFlags.add(AclEntryFlag.INHERIT_ONLY);
|
||||
|
||||
// build the ACL entry and add it to the list
|
||||
AclEntry ace = AclEntry.newBuilder()
|
||||
.setType(aceType)
|
||||
.setPrincipal(who)
|
||||
.setPermissions(aceMask).setFlags(aceFlags).build();
|
||||
acl.add(ace);
|
||||
}
|
||||
|
||||
return acl;
|
||||
}
|
||||
|
||||
// Returns true if NFSv4 ACLs not enabled on file system
|
||||
private static boolean isAclsEnabled(int fd) {
|
||||
try {
|
||||
long enabled = fpathconf(fd, _PC_ACL_ENABLED);
|
||||
if (enabled == _ACL_ACE_ENABLED)
|
||||
return true;
|
||||
} catch (UnixException x) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AclEntry> getAcl()
|
||||
throws IOException
|
||||
{
|
||||
// permission check
|
||||
checkAccess(file, true, false);
|
||||
|
||||
// open file (will fail if file is a link and not following links)
|
||||
int fd = -1;
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
}
|
||||
try {
|
||||
long address = unsafe.allocateMemory(SIZEOF_ACE_T * MAX_ACL_ENTRIES);
|
||||
try {
|
||||
// read ACL and decode it
|
||||
int n = facl(fd, ACE_GETACL, MAX_ACL_ENTRIES, address);
|
||||
assert n >= 0;
|
||||
return decode(address, n);
|
||||
} catch (UnixException x) {
|
||||
if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
|
||||
}
|
||||
x.rethrowAsIOException(file);
|
||||
return null; // keep compiler happy
|
||||
} finally {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAcl(List<AclEntry> acl) throws IOException {
|
||||
// permission check
|
||||
checkAccess(file, false, true);
|
||||
|
||||
// open file (will fail if file is a link and not following links)
|
||||
int fd = -1;
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
}
|
||||
try {
|
||||
// SECURITY: need to copy list as can change during processing
|
||||
acl = new ArrayList<AclEntry>(acl);
|
||||
int n = acl.size();
|
||||
|
||||
long address = unsafe.allocateMemory(SIZEOF_ACE_T * n);
|
||||
try {
|
||||
encode(acl, address);
|
||||
facl(fd, ACE_SETACL, n, address);
|
||||
} catch (UnixException x) {
|
||||
if ((x.errno() == ENOSYS) || !isAclsEnabled(fd)) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, x.getMessage() + " (file system does not support NFSv4 ACLs)");
|
||||
}
|
||||
if (x.errno() == EINVAL && (n < 3))
|
||||
throw new IOException("ACL must contain at least 3 entries");
|
||||
x.rethrowAsIOException(file);
|
||||
} finally {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserPrincipal getOwner()
|
||||
throws IOException
|
||||
{
|
||||
checkAccess(file, true, false);
|
||||
|
||||
try {
|
||||
UnixFileAttributes attrs =
|
||||
UnixFileAttributes.get(file, followLinks);
|
||||
return UnixUserPrincipals.fromUid(attrs.uid());
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
return null; // keep compile happy
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwner(UserPrincipal owner) throws IOException {
|
||||
checkAccess(file, true, false);
|
||||
|
||||
if (!(owner instanceof UnixUserPrincipals.User))
|
||||
throw new ProviderMismatchException();
|
||||
if (owner instanceof UnixUserPrincipals.Group)
|
||||
throw new IOException("'owner' parameter is a group");
|
||||
int uid = ((UnixUserPrincipals.User)owner).uid();
|
||||
|
||||
try {
|
||||
if (followLinks) {
|
||||
lchown(file, uid, -1);
|
||||
} else {
|
||||
chown(file, uid, -1);
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(file);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
@@END_COPYRIGHT@@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/acl.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* On Solaris, "sun" is defined as a macro. Undefine to make package
|
||||
declaration valid */
|
||||
#undef sun
|
||||
|
||||
/* To be able to name the Java constants the same as the C constants without
|
||||
having the preprocessor rewrite those identifiers, add PREFIX_ to all
|
||||
identifiers matching a C constant. The PREFIX_ is filtered out in the
|
||||
makefile. */
|
||||
|
||||
@@START_HERE@@
|
||||
|
||||
package sun.nio.fs;
|
||||
class SolarisConstants {
|
||||
|
||||
private SolarisConstants() { }
|
||||
|
||||
static final int PREFIX_O_XATTR = O_XATTR;
|
||||
static final int PREFIX__PC_XATTR_ENABLED = _PC_XATTR_ENABLED;
|
||||
static final int PREFIX__PC_ACL_ENABLED = _PC_ACL_ENABLED;
|
||||
static final int PREFIX__ACL_ACE_ENABLED = _ACL_ACE_ENABLED;
|
||||
static final int PREFIX_ACE_GETACL = ACE_GETACL;
|
||||
static final int PREFIX_ACE_SETACL = ACE_SETACL;
|
||||
static final int PREFIX_ACE_ACCESS_ALLOWED_ACE_TYPE = ACE_ACCESS_ALLOWED_ACE_TYPE;
|
||||
static final int PREFIX_ACE_ACCESS_DENIED_ACE_TYPE = ACE_ACCESS_DENIED_ACE_TYPE;
|
||||
static final int PREFIX_ACE_SYSTEM_AUDIT_ACE_TYPE = ACE_SYSTEM_AUDIT_ACE_TYPE;
|
||||
static final int PREFIX_ACE_SYSTEM_ALARM_ACE_TYPE = ACE_SYSTEM_ALARM_ACE_TYPE;
|
||||
static final int PREFIX_ACE_READ_DATA = ACE_READ_DATA;
|
||||
static final int PREFIX_ACE_LIST_DIRECTORY = ACE_LIST_DIRECTORY;
|
||||
static final int PREFIX_ACE_WRITE_DATA = ACE_WRITE_DATA;
|
||||
static final int PREFIX_ACE_ADD_FILE = ACE_ADD_FILE;
|
||||
static final int PREFIX_ACE_APPEND_DATA = ACE_APPEND_DATA;
|
||||
static final int PREFIX_ACE_ADD_SUBDIRECTORY = ACE_ADD_SUBDIRECTORY;
|
||||
static final int PREFIX_ACE_READ_NAMED_ATTRS = ACE_READ_NAMED_ATTRS;
|
||||
static final int PREFIX_ACE_WRITE_NAMED_ATTRS = ACE_WRITE_NAMED_ATTRS;
|
||||
static final int PREFIX_ACE_EXECUTE = ACE_EXECUTE;
|
||||
static final int PREFIX_ACE_DELETE_CHILD = ACE_DELETE_CHILD;
|
||||
static final int PREFIX_ACE_READ_ATTRIBUTES = ACE_READ_ATTRIBUTES;
|
||||
static final int PREFIX_ACE_WRITE_ATTRIBUTES = ACE_WRITE_ATTRIBUTES;
|
||||
static final int PREFIX_ACE_DELETE = ACE_DELETE;
|
||||
static final int PREFIX_ACE_READ_ACL = ACE_READ_ACL;
|
||||
static final int PREFIX_ACE_WRITE_ACL = ACE_WRITE_ACL;
|
||||
static final int PREFIX_ACE_WRITE_OWNER = ACE_WRITE_OWNER;
|
||||
static final int PREFIX_ACE_SYNCHRONIZE = ACE_SYNCHRONIZE;
|
||||
static final int PREFIX_ACE_FILE_INHERIT_ACE = ACE_FILE_INHERIT_ACE;
|
||||
static final int PREFIX_ACE_DIRECTORY_INHERIT_ACE = ACE_DIRECTORY_INHERIT_ACE;
|
||||
static final int PREFIX_ACE_NO_PROPAGATE_INHERIT_ACE = ACE_NO_PROPAGATE_INHERIT_ACE;
|
||||
static final int PREFIX_ACE_INHERIT_ONLY_ACE = ACE_INHERIT_ONLY_ACE;
|
||||
static final int PREFIX_ACE_SUCCESSFUL_ACCESS_ACE_FLAG = ACE_SUCCESSFUL_ACCESS_ACE_FLAG;
|
||||
static final int PREFIX_ACE_FAILED_ACCESS_ACE_FLAG = ACE_FAILED_ACCESS_ACE_FLAG;
|
||||
static final int PREFIX_ACE_IDENTIFIER_GROUP = ACE_IDENTIFIER_GROUP;
|
||||
static final int PREFIX_ACE_OWNER = ACE_OWNER;
|
||||
static final int PREFIX_ACE_GROUP = ACE_GROUP;
|
||||
static final int PREFIX_ACE_EVERYONE = ACE_EVERYONE;
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||||
import static sun.nio.fs.SolarisConstants.*;
|
||||
|
||||
/**
|
||||
* Solaris implementation of FileStore
|
||||
*/
|
||||
|
||||
class SolarisFileStore
|
||||
extends UnixFileStore
|
||||
{
|
||||
private final boolean xattrEnabled;
|
||||
|
||||
SolarisFileStore(UnixPath file) throws IOException {
|
||||
super(file);
|
||||
this.xattrEnabled = xattrEnabled();
|
||||
}
|
||||
|
||||
SolarisFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException {
|
||||
super(fs, entry);
|
||||
this.xattrEnabled = xattrEnabled();
|
||||
}
|
||||
|
||||
// returns true if extended attributes enabled
|
||||
private boolean xattrEnabled() {
|
||||
long res = 0L;
|
||||
try {
|
||||
res = pathconf(file(), _PC_XATTR_ENABLED);
|
||||
} catch (UnixException x) {
|
||||
// ignore
|
||||
}
|
||||
return (res != 0L);
|
||||
}
|
||||
|
||||
@Override
|
||||
UnixMountEntry findMountEntry() throws IOException {
|
||||
// On Solaris iterate over the entries in the mount table to find device
|
||||
for (UnixMountEntry entry: file().getFileSystem().getMountEntries()) {
|
||||
if (entry.dev() == dev()) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
throw new IOException("Device not found in mnttab");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) {
|
||||
if (type == AclFileAttributeView.class) {
|
||||
// lookup fstypes.properties
|
||||
FeatureStatus status = checkIfFeaturePresent("nfsv4acl");
|
||||
switch (status) {
|
||||
case PRESENT : return true;
|
||||
case NOT_PRESENT : return false;
|
||||
default :
|
||||
// AclFileAttributeView available on ZFS
|
||||
return (type().equals("zfs"));
|
||||
}
|
||||
}
|
||||
if (type == UserDefinedFileAttributeView.class) {
|
||||
// lookup fstypes.properties
|
||||
FeatureStatus status = checkIfFeaturePresent("xattr");
|
||||
switch (status) {
|
||||
case PRESENT : return true;
|
||||
case NOT_PRESENT : return false;
|
||||
default :
|
||||
// UserDefinedFileAttributeView available if extended
|
||||
// attributes supported
|
||||
return xattrEnabled;
|
||||
}
|
||||
}
|
||||
return super.supportsFileAttributeView(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsFileAttributeView(String name) {
|
||||
if (name.equals("acl"))
|
||||
return supportsFileAttributeView(AclFileAttributeView.class);
|
||||
if (name.equals("user"))
|
||||
return supportsFileAttributeView(UserDefinedFileAttributeView.class);
|
||||
return super.supportsFileAttributeView(name);
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import static sun.nio.fs.SolarisNativeDispatcher.*;
|
||||
|
||||
/**
|
||||
* Solaris implementation of FileSystem
|
||||
*/
|
||||
|
||||
class SolarisFileSystem extends UnixFileSystem {
|
||||
private final boolean hasSolaris11Features;
|
||||
|
||||
SolarisFileSystem(UnixFileSystemProvider provider, String dir) {
|
||||
super(provider, dir);
|
||||
|
||||
// check os.version
|
||||
String osversion = GetPropertyAction.privilegedGetProperty("os.version");
|
||||
String[] vers = Util.split(osversion, '.');
|
||||
assert vers.length >= 2;
|
||||
int majorVersion = Integer.parseInt(vers[0]);
|
||||
int minorVersion = Integer.parseInt(vers[1]);
|
||||
this.hasSolaris11Features =
|
||||
(majorVersion > 5 || (majorVersion == 5 && minorVersion >= 11));
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSolaris() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WatchService newWatchService()
|
||||
throws IOException
|
||||
{
|
||||
// FEN available since Solaris 11
|
||||
if (hasSolaris11Features) {
|
||||
return new SolarisWatchService(this);
|
||||
} else {
|
||||
return new PollingWatchService();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// lazy initialization of the list of supported attribute views
|
||||
private static class SupportedFileFileAttributeViewsHolder {
|
||||
static final Set<String> supportedFileAttributeViews =
|
||||
supportedFileAttributeViews();
|
||||
private static Set<String> supportedFileAttributeViews() {
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(standardFileAttributeViews());
|
||||
// additional Solaris-specific views
|
||||
result.add("acl");
|
||||
result.add("user");
|
||||
return Collections.unmodifiableSet(result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> supportedFileAttributeViews() {
|
||||
return SupportedFileFileAttributeViewsHolder.supportedFileAttributeViews;
|
||||
}
|
||||
|
||||
@Override
|
||||
void copyNonPosixAttributes(int ofd, int nfd) {
|
||||
SolarisUserDefinedFileAttributeView.copyExtendedAttributes(ofd, nfd);
|
||||
// TDB: copy ACL from source to target
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns object to iterate over entries in /etc/mnttab
|
||||
*/
|
||||
@Override
|
||||
Iterable<UnixMountEntry> getMountEntries() {
|
||||
ArrayList<UnixMountEntry> entries = new ArrayList<>();
|
||||
try {
|
||||
UnixPath mnttab = new UnixPath(this, "/etc/mnttab");
|
||||
long fp = fopen(mnttab, "r");
|
||||
try {
|
||||
for (;;) {
|
||||
UnixMountEntry entry = new UnixMountEntry();
|
||||
int res = getextmntent(fp, entry);
|
||||
if (res < 0)
|
||||
break;
|
||||
entries.add(entry);
|
||||
}
|
||||
} finally {
|
||||
fclose(fp);
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
// nothing we can do
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
FileStore getFileStore(UnixMountEntry entry) throws IOException {
|
||||
return new SolarisFileStore(this, entry);
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileTypeDetector;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.util.StaticProperty;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* Solaris implementation of FileSystemProvider
|
||||
*/
|
||||
|
||||
class SolarisFileSystemProvider extends UnixFileSystemProvider {
|
||||
public SolarisFileSystemProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
SolarisFileSystem newFileSystem(String dir) {
|
||||
return new SolarisFileSystem(this, dir);
|
||||
}
|
||||
|
||||
@Override
|
||||
SolarisFileStore getFileStore(UnixPath path) throws IOException {
|
||||
return new SolarisFileStore(path);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V extends FileAttributeView> V getFileAttributeView(Path obj,
|
||||
Class<V> type,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (type == AclFileAttributeView.class) {
|
||||
return (V) new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
}
|
||||
if (type == UserDefinedFileAttributeView.class) {
|
||||
return(V) new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
}
|
||||
return super.getFileAttributeView(obj, type, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicFileAttributeView getFileAttributeView(Path obj,
|
||||
String name,
|
||||
LinkOption... options)
|
||||
{
|
||||
if (name.equals("acl"))
|
||||
return new SolarisAclFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
if (name.equals("user"))
|
||||
return new SolarisUserDefinedFileAttributeView(UnixPath.toUnixPath(obj),
|
||||
Util.followLinks(options));
|
||||
return super.getFileAttributeView(obj, name, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
FileTypeDetector getFileTypeDetector() {
|
||||
Path userMimeTypes = Path.of(StaticProperty.userHome(), ".mime.types");
|
||||
Path etcMimeTypes = Path.of("/etc/mime.types");
|
||||
|
||||
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new MimeTypesFileTypeDetector(etcMimeTypes));
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
/**
|
||||
* Solaris specific system calls.
|
||||
*/
|
||||
|
||||
class SolarisNativeDispatcher extends UnixNativeDispatcher {
|
||||
private SolarisNativeDispatcher() { }
|
||||
|
||||
/**
|
||||
* int getextmntent(FILE *fp, struct extmnttab *mp, int len);
|
||||
*/
|
||||
static native int getextmntent(long fp, UnixMountEntry entry)
|
||||
throws UnixException;
|
||||
|
||||
/**
|
||||
* int facl(int filedes, int cmd, int nentries, void aclbufp)
|
||||
*/
|
||||
static native int facl(int fd, int cmd, int nentries, long aclbufp)
|
||||
throws UnixException;
|
||||
|
||||
|
||||
// initialize
|
||||
private static native void init();
|
||||
|
||||
static {
|
||||
jdk.internal.loader.BootLoader.loadLibrary("nio");
|
||||
init();
|
||||
}
|
||||
}
|
|
@ -1,305 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static sun.nio.fs.UnixNativeDispatcher.*;
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
import static sun.nio.fs.SolarisConstants.*;
|
||||
|
||||
/**
|
||||
* Solaris emulation of NamedAttributeView using extended attributes.
|
||||
*/
|
||||
|
||||
class SolarisUserDefinedFileAttributeView
|
||||
extends AbstractUserDefinedFileAttributeView
|
||||
{
|
||||
private static final byte[] HERE = { '.' };
|
||||
|
||||
private byte[] nameAsBytes(UnixPath file, String name) throws IOException {
|
||||
byte[] bytes = Util.toBytes(name);
|
||||
// "", "." and ".." not allowed
|
||||
if (bytes.length == 0 || bytes[0] == '.') {
|
||||
if (bytes.length <= 1 ||
|
||||
(bytes.length == 2 && bytes[1] == '.'))
|
||||
{
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "'" + name + "' is not a valid name");
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private final UnixPath file;
|
||||
private final boolean followLinks;
|
||||
|
||||
SolarisUserDefinedFileAttributeView(UnixPath file, boolean followLinks) {
|
||||
this.file = file;
|
||||
this.followLinks = followLinks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> list() throws IOException {
|
||||
if (System.getSecurityManager() != null)
|
||||
checkAccess(file.getPathForPermissionCheck(), true, false);
|
||||
|
||||
int fd = -1;
|
||||
try {
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
|
||||
// open extended attribute directory
|
||||
int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0);
|
||||
long dp;
|
||||
try {
|
||||
dp = fdopendir(dfd);
|
||||
} catch (UnixException x) {
|
||||
close(dfd);
|
||||
throw x;
|
||||
}
|
||||
|
||||
// read list of extended attributes
|
||||
List<String> list = new ArrayList<>();
|
||||
try {
|
||||
byte[] name;
|
||||
while ((name = readdir(dp)) != null) {
|
||||
String s = Util.toString(name);
|
||||
if (!s.equals(".") && !s.equals(".."))
|
||||
list.add(s);
|
||||
}
|
||||
} finally {
|
||||
closedir(dp);
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
} catch (UnixException x) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "Unable to get list of extended attributes: " +
|
||||
x.getMessage());
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size(String name) throws IOException {
|
||||
if (System.getSecurityManager() != null)
|
||||
checkAccess(file.getPathForPermissionCheck(), true, false);
|
||||
|
||||
int fd = -1;
|
||||
try {
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
|
||||
// open attribute file
|
||||
int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
|
||||
try {
|
||||
// read attribute's attributes
|
||||
UnixFileAttributes attrs = UnixFileAttributes.get(afd);
|
||||
long size = attrs.size();
|
||||
if (size > Integer.MAX_VALUE)
|
||||
throw new ArithmeticException("Extended attribute value too large");
|
||||
return (int)size;
|
||||
} finally {
|
||||
close(afd);
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "Unable to get size of extended attribute '" + name +
|
||||
"': " + x.getMessage());
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(String name, ByteBuffer dst) throws IOException {
|
||||
if (System.getSecurityManager() != null)
|
||||
checkAccess(file.getPathForPermissionCheck(), true, false);
|
||||
|
||||
int fd = -1;
|
||||
try {
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
|
||||
// open attribute file
|
||||
int afd = openat(fd, nameAsBytes(file,name), (O_RDONLY|O_XATTR), 0);
|
||||
|
||||
// wrap with channel
|
||||
FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), true, false);
|
||||
|
||||
// read to EOF (nothing we can do if I/O error occurs)
|
||||
try {
|
||||
if (fc.size() > dst.remaining())
|
||||
throw new IOException("Extended attribute file too large");
|
||||
int total = 0;
|
||||
while (dst.hasRemaining()) {
|
||||
int n = fc.read(dst);
|
||||
if (n < 0)
|
||||
break;
|
||||
total += n;
|
||||
}
|
||||
return total;
|
||||
} finally {
|
||||
fc.close();
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "Unable to read extended attribute '" + name +
|
||||
"': " + x.getMessage());
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(String name, ByteBuffer src) throws IOException {
|
||||
if (System.getSecurityManager() != null)
|
||||
checkAccess(file.getPathForPermissionCheck(), false, true);
|
||||
|
||||
int fd = -1;
|
||||
try {
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
|
||||
// open/create attribute file
|
||||
int afd = openat(fd, nameAsBytes(file,name),
|
||||
(O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
|
||||
UnixFileModeAttribute.ALL_PERMISSIONS);
|
||||
|
||||
// wrap with channel
|
||||
FileChannel fc = UnixChannelFactory.newFileChannel(afd, file.toString(), false, true);
|
||||
|
||||
// write value (nothing we can do if I/O error occurs)
|
||||
try {
|
||||
int rem = src.remaining();
|
||||
while (src.hasRemaining()) {
|
||||
fc.write(src);
|
||||
}
|
||||
return rem;
|
||||
} finally {
|
||||
fc.close();
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "Unable to write extended attribute '" + name +
|
||||
"': " + x.getMessage());
|
||||
}
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String name) throws IOException {
|
||||
if (System.getSecurityManager() != null)
|
||||
checkAccess(file.getPathForPermissionCheck(), false, true);
|
||||
|
||||
int fd = -1;
|
||||
try {
|
||||
fd = file.openForAttributeAccess(followLinks);
|
||||
|
||||
int dfd = openat(fd, HERE, (O_RDONLY|O_XATTR), 0);
|
||||
try {
|
||||
unlinkat(dfd, nameAsBytes(file,name), 0);
|
||||
} finally {
|
||||
close(dfd);
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
throw new FileSystemException(file.getPathForExceptionMessage(),
|
||||
null, "Unable to delete extended attribute '" + name +
|
||||
"': " + x.getMessage());
|
||||
} finally {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by copyTo/moveTo to copy extended attributes from source to target.
|
||||
*
|
||||
* @param ofd
|
||||
* file descriptor for source file
|
||||
* @param nfd
|
||||
* file descriptor for target file
|
||||
*/
|
||||
static void copyExtendedAttributes(int ofd, int nfd) {
|
||||
try {
|
||||
// open extended attribute directory
|
||||
int dfd = openat(ofd, HERE, (O_RDONLY|O_XATTR), 0);
|
||||
long dp = 0L;
|
||||
try {
|
||||
dp = fdopendir(dfd);
|
||||
} catch (UnixException x) {
|
||||
close(dfd);
|
||||
throw x;
|
||||
}
|
||||
|
||||
// copy each extended attribute
|
||||
try {
|
||||
byte[] name;
|
||||
while ((name = readdir(dp)) != null) {
|
||||
// ignore "." and ".."
|
||||
if (name[0] == '.') {
|
||||
if (name.length == 1)
|
||||
continue;
|
||||
if (name.length == 2 && name[1] == '.')
|
||||
continue;
|
||||
}
|
||||
copyExtendedAttribute(ofd, name, nfd);
|
||||
}
|
||||
} finally {
|
||||
closedir(dp);
|
||||
}
|
||||
} catch (UnixException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyExtendedAttribute(int ofd, byte[] name, int nfd)
|
||||
throws UnixException
|
||||
{
|
||||
// open source attribute file
|
||||
int src = openat(ofd, name, (O_RDONLY|O_XATTR), 0);
|
||||
try {
|
||||
// create target attribute file
|
||||
int dst = openat(nfd, name, (O_CREAT|O_WRONLY|O_TRUNC|O_XATTR),
|
||||
UnixFileModeAttribute.ALL_PERMISSIONS);
|
||||
try {
|
||||
UnixCopyFile.transfer(dst, src, 0L);
|
||||
} finally {
|
||||
close(dst);
|
||||
}
|
||||
} finally {
|
||||
close(src);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,821 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
import static sun.nio.fs.UnixConstants.*;
|
||||
|
||||
/**
|
||||
* Solaris implementation of WatchService based on file events notification
|
||||
* facility.
|
||||
*/
|
||||
|
||||
class SolarisWatchService
|
||||
extends AbstractWatchService
|
||||
{
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private static int addressSize = unsafe.addressSize();
|
||||
|
||||
private static int dependsArch(int value32, int value64) {
|
||||
return (addressSize == 4) ? value32 : value64;
|
||||
}
|
||||
|
||||
/*
|
||||
* typedef struct port_event {
|
||||
* int portev_events;
|
||||
* ushort_t portev_source;
|
||||
* ushort_t portev_pad;
|
||||
* uintptr_t portev_object;
|
||||
* void *portev_user;
|
||||
* } port_event_t;
|
||||
*/
|
||||
private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24);
|
||||
private static final int OFFSETOF_EVENTS = 0;
|
||||
private static final int OFFSETOF_SOURCE = 4;
|
||||
private static final int OFFSETOF_OBJECT = 8;
|
||||
|
||||
/*
|
||||
* typedef struct file_obj {
|
||||
* timestruc_t fo_atime;
|
||||
* timestruc_t fo_mtime;
|
||||
* timestruc_t fo_ctime;
|
||||
* uintptr_t fo_pad[3];
|
||||
* char *fo_name;
|
||||
* } file_obj_t;
|
||||
*/
|
||||
private static final int SIZEOF_FILEOBJ = dependsArch(40, 80);
|
||||
private static final int OFFSET_FO_NAME = dependsArch(36, 72);
|
||||
|
||||
// port sources
|
||||
private static final short PORT_SOURCE_USER = 3;
|
||||
private static final short PORT_SOURCE_FILE = 7;
|
||||
|
||||
// user-watchable events
|
||||
private static final int FILE_MODIFIED = 0x00000002;
|
||||
private static final int FILE_ATTRIB = 0x00000004;
|
||||
private static final int FILE_NOFOLLOW = 0x10000000;
|
||||
|
||||
// exception events
|
||||
private static final int FILE_DELETE = 0x00000010;
|
||||
private static final int FILE_RENAME_TO = 0x00000020;
|
||||
private static final int FILE_RENAME_FROM = 0x00000040;
|
||||
private static final int UNMOUNTED = 0x20000000;
|
||||
private static final int MOUNTEDOVER = 0x40000000;
|
||||
|
||||
// background thread to read change events
|
||||
private final Poller poller;
|
||||
|
||||
SolarisWatchService(UnixFileSystem fs) throws IOException {
|
||||
int port = -1;
|
||||
try {
|
||||
port = portCreate();
|
||||
} catch (UnixException x) {
|
||||
throw new IOException(x.errorString());
|
||||
}
|
||||
|
||||
this.poller = new Poller(fs, this, port);
|
||||
this.poller.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
WatchKey register(Path dir,
|
||||
WatchEvent.Kind<?>[] events,
|
||||
WatchEvent.Modifier... modifiers)
|
||||
throws IOException
|
||||
{
|
||||
// delegate to poller
|
||||
return poller.register(dir, events, modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
void implClose() throws IOException {
|
||||
// delegate to poller
|
||||
poller.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* WatchKey implementation
|
||||
*/
|
||||
private class SolarisWatchKey extends AbstractWatchKey
|
||||
implements DirectoryNode
|
||||
{
|
||||
private final UnixFileKey fileKey;
|
||||
|
||||
// pointer to native file_obj object
|
||||
private final long object;
|
||||
|
||||
// events (may be changed). set to null when watch key is invalid
|
||||
private volatile Set<? extends WatchEvent.Kind<?>> events;
|
||||
|
||||
// map of entries in directory; created lazily; accessed only by
|
||||
// poller thread.
|
||||
private Map<Path,EntryNode> children = new HashMap<>();
|
||||
|
||||
SolarisWatchKey(SolarisWatchService watcher,
|
||||
UnixPath dir,
|
||||
UnixFileKey fileKey,
|
||||
long object,
|
||||
Set<? extends WatchEvent.Kind<?>> events)
|
||||
{
|
||||
super(dir, watcher);
|
||||
this.fileKey = fileKey;
|
||||
this.object = object;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
UnixPath getDirectory() {
|
||||
return (UnixPath)watchable();
|
||||
}
|
||||
|
||||
UnixFileKey getFileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long object() {
|
||||
return object;
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
events = null;
|
||||
}
|
||||
|
||||
Set<? extends WatchEvent.Kind<?>> events() {
|
||||
return events;
|
||||
}
|
||||
|
||||
void setEvents(Set<? extends WatchEvent.Kind<?>> events) {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
Map<Path,EntryNode> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return events != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (isValid()) {
|
||||
// delegate to poller
|
||||
poller.cancel(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChild(Path name, EntryNode node) {
|
||||
children.put(name, node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeChild(Path name) {
|
||||
children.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntryNode getChild(Path name) {
|
||||
return children.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Background thread to read from port
|
||||
*/
|
||||
private class Poller extends AbstractPoller {
|
||||
|
||||
// maximum number of events to read per call to port_getn
|
||||
private static final int MAX_EVENT_COUNT = 128;
|
||||
|
||||
// events that map to ENTRY_DELETE
|
||||
private static final int FILE_REMOVED =
|
||||
(FILE_DELETE|FILE_RENAME_TO|FILE_RENAME_FROM);
|
||||
|
||||
// events that tell us not to re-associate the object
|
||||
private static final int FILE_EXCEPTION =
|
||||
(FILE_REMOVED|UNMOUNTED|MOUNTEDOVER);
|
||||
|
||||
// address of event buffers (used to receive events with port_getn)
|
||||
private final long bufferAddress;
|
||||
|
||||
private final SolarisWatchService watcher;
|
||||
|
||||
// the I/O port
|
||||
private final int port;
|
||||
|
||||
// maps file key (dev/inode) to WatchKey
|
||||
private final Map<UnixFileKey,SolarisWatchKey> fileKey2WatchKey;
|
||||
|
||||
// maps file_obj object to Node
|
||||
private final Map<Long,Node> object2Node;
|
||||
|
||||
/**
|
||||
* Create a new instance
|
||||
*/
|
||||
Poller(UnixFileSystem fs, SolarisWatchService watcher, int port) {
|
||||
this.watcher = watcher;
|
||||
this.port = port;
|
||||
this.bufferAddress =
|
||||
unsafe.allocateMemory(SIZEOF_PORT_EVENT * MAX_EVENT_COUNT);
|
||||
this.fileKey2WatchKey = new HashMap<UnixFileKey,SolarisWatchKey>();
|
||||
this.object2Node = new HashMap<Long,Node>();
|
||||
}
|
||||
|
||||
@Override
|
||||
void wakeup() throws IOException {
|
||||
// write to port to wakeup polling thread
|
||||
try {
|
||||
portSend(port, 0);
|
||||
} catch (UnixException x) {
|
||||
throw new IOException(x.errorString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
Object implRegister(Path obj,
|
||||
Set<? extends WatchEvent.Kind<?>> events,
|
||||
WatchEvent.Modifier... modifiers)
|
||||
{
|
||||
// no modifiers supported at this time
|
||||
if (modifiers.length > 0) {
|
||||
for (WatchEvent.Modifier modifier: modifiers) {
|
||||
if (modifier == null)
|
||||
return new NullPointerException();
|
||||
if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) &&
|
||||
!ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) &&
|
||||
!ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) {
|
||||
return new UnsupportedOperationException("Modifier not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnixPath dir = (UnixPath)obj;
|
||||
|
||||
// check file is directory
|
||||
UnixFileAttributes attrs = null;
|
||||
try {
|
||||
attrs = UnixFileAttributes.get(dir, true);
|
||||
} catch (UnixException x) {
|
||||
return x.asIOException(dir);
|
||||
}
|
||||
if (!attrs.isDirectory()) {
|
||||
return new NotDirectoryException(dir.getPathForExceptionMessage());
|
||||
}
|
||||
|
||||
// if already registered then update the events and return existing key
|
||||
UnixFileKey fileKey = attrs.fileKey();
|
||||
SolarisWatchKey watchKey = fileKey2WatchKey.get(fileKey);
|
||||
if (watchKey != null) {
|
||||
try {
|
||||
updateEvents(watchKey, events);
|
||||
} catch (UnixException x) {
|
||||
return x.asIOException(dir);
|
||||
}
|
||||
return watchKey;
|
||||
}
|
||||
|
||||
// register directory
|
||||
long object = 0L;
|
||||
try {
|
||||
object = registerImpl(dir, (FILE_MODIFIED | FILE_ATTRIB));
|
||||
} catch (UnixException x) {
|
||||
return x.asIOException(dir);
|
||||
}
|
||||
|
||||
// create watch key and insert it into maps
|
||||
watchKey = new SolarisWatchKey(watcher, dir, fileKey, object, events);
|
||||
object2Node.put(object, watchKey);
|
||||
fileKey2WatchKey.put(fileKey, watchKey);
|
||||
|
||||
// register all entries in directory
|
||||
registerChildren(dir, watchKey, false, false);
|
||||
|
||||
return watchKey;
|
||||
}
|
||||
|
||||
// release resources for single entry
|
||||
void releaseChild(EntryNode node) {
|
||||
long object = node.object();
|
||||
if (object != 0L) {
|
||||
object2Node.remove(object);
|
||||
releaseObject(object, true);
|
||||
node.setObject(0L);
|
||||
}
|
||||
}
|
||||
|
||||
// release resources for entries in directory
|
||||
void releaseChildren(SolarisWatchKey key) {
|
||||
for (EntryNode node: key.children().values()) {
|
||||
releaseChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
// cancel single key
|
||||
@Override
|
||||
void implCancelKey(WatchKey obj) {
|
||||
SolarisWatchKey key = (SolarisWatchKey)obj;
|
||||
if (key.isValid()) {
|
||||
fileKey2WatchKey.remove(key.getFileKey());
|
||||
|
||||
// release resources for entries
|
||||
releaseChildren(key);
|
||||
|
||||
// release resources for directory
|
||||
long object = key.object();
|
||||
object2Node.remove(object);
|
||||
releaseObject(object, true);
|
||||
|
||||
// and finally invalidate the key
|
||||
key.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
// close watch service
|
||||
@Override
|
||||
void implCloseAll() {
|
||||
// release all native resources
|
||||
for (Long object: object2Node.keySet()) {
|
||||
releaseObject(object, true);
|
||||
}
|
||||
|
||||
// invalidate all keys
|
||||
for (Map.Entry<UnixFileKey,SolarisWatchKey> entry: fileKey2WatchKey.entrySet()) {
|
||||
entry.getValue().invalidate();
|
||||
}
|
||||
|
||||
// clean-up
|
||||
object2Node.clear();
|
||||
fileKey2WatchKey.clear();
|
||||
|
||||
// free global resources
|
||||
unsafe.freeMemory(bufferAddress);
|
||||
UnixNativeDispatcher.close(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Poller main loop. Blocks on port_getn waiting for events and then
|
||||
* processes them.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (;;) {
|
||||
int n = portGetn(port, bufferAddress, MAX_EVENT_COUNT);
|
||||
assert n > 0;
|
||||
|
||||
long address = bufferAddress;
|
||||
for (int i=0; i<n; i++) {
|
||||
boolean shutdown = processEvent(address);
|
||||
if (shutdown)
|
||||
return;
|
||||
address += SIZEOF_PORT_EVENT;
|
||||
}
|
||||
}
|
||||
} catch (UnixException x) {
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single port_event
|
||||
*
|
||||
* Returns true if poller thread is requested to shutdown.
|
||||
*/
|
||||
boolean processEvent(long address) {
|
||||
// pe->portev_source
|
||||
short source = unsafe.getShort(address + OFFSETOF_SOURCE);
|
||||
// pe->portev_object
|
||||
long object = unsafe.getAddress(address + OFFSETOF_OBJECT);
|
||||
// pe->portev_events
|
||||
int events = unsafe.getInt(address + OFFSETOF_EVENTS);
|
||||
|
||||
// user event is trigger to process pending requests
|
||||
if (source != PORT_SOURCE_FILE) {
|
||||
if (source == PORT_SOURCE_USER) {
|
||||
// process any pending requests
|
||||
boolean shutdown = processRequests();
|
||||
if (shutdown)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// lookup object to get Node
|
||||
Node node = object2Node.get(object);
|
||||
if (node == null) {
|
||||
// should not happen
|
||||
return false;
|
||||
}
|
||||
|
||||
// As a workaround for 6642290 and 6636438/6636412 we don't use
|
||||
// FILE_EXCEPTION events to tell use not to register the file.
|
||||
// boolean reregister = (events & FILE_EXCEPTION) == 0;
|
||||
boolean reregister = true;
|
||||
|
||||
// If node is EntryNode then event relates to entry in directory
|
||||
// If node is a SolarisWatchKey (DirectoryNode) then event relates
|
||||
// to a watched directory.
|
||||
boolean isDirectory = (node instanceof SolarisWatchKey);
|
||||
if (isDirectory) {
|
||||
processDirectoryEvents((SolarisWatchKey)node, events);
|
||||
} else {
|
||||
boolean ignore = processEntryEvents((EntryNode)node, events);
|
||||
if (ignore)
|
||||
reregister = false;
|
||||
}
|
||||
|
||||
// need to re-associate to get further events
|
||||
if (reregister) {
|
||||
try {
|
||||
events = FILE_MODIFIED | FILE_ATTRIB;
|
||||
if (!isDirectory) events |= FILE_NOFOLLOW;
|
||||
portAssociate(port,
|
||||
PORT_SOURCE_FILE,
|
||||
object,
|
||||
events);
|
||||
} catch (UnixException x) {
|
||||
// unable to re-register
|
||||
reregister = false;
|
||||
}
|
||||
}
|
||||
|
||||
// object is not re-registered so release resources. If
|
||||
// object is a watched directory then signal key
|
||||
if (!reregister) {
|
||||
// release resources
|
||||
object2Node.remove(object);
|
||||
releaseObject(object, false);
|
||||
|
||||
// if watch key then signal it
|
||||
if (isDirectory) {
|
||||
SolarisWatchKey key = (SolarisWatchKey)node;
|
||||
fileKey2WatchKey.remove( key.getFileKey() );
|
||||
key.invalidate();
|
||||
key.signal();
|
||||
} else {
|
||||
// if entry then remove it from parent
|
||||
EntryNode entry = (EntryNode)node;
|
||||
SolarisWatchKey key = (SolarisWatchKey)entry.parent();
|
||||
key.removeChild(entry.name());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process directory events. If directory is modified then re-scan
|
||||
* directory to register any new entries
|
||||
*/
|
||||
void processDirectoryEvents(SolarisWatchKey key, int mask) {
|
||||
if ((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) {
|
||||
registerChildren(key.getDirectory(), key,
|
||||
key.events().contains(StandardWatchEventKinds.ENTRY_CREATE),
|
||||
key.events().contains(StandardWatchEventKinds.ENTRY_DELETE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process events for entries in registered directories. Returns {@code
|
||||
* true} if events are ignored because the watch key has been cancelled.
|
||||
*/
|
||||
boolean processEntryEvents(EntryNode node, int mask) {
|
||||
SolarisWatchKey key = (SolarisWatchKey)node.parent();
|
||||
Set<? extends WatchEvent.Kind<?>> events = key.events();
|
||||
if (events == null) {
|
||||
// key has been cancelled so ignore event
|
||||
return true;
|
||||
}
|
||||
|
||||
// entry modified
|
||||
if (((mask & (FILE_MODIFIED | FILE_ATTRIB)) != 0) &&
|
||||
events.contains(StandardWatchEventKinds.ENTRY_MODIFY))
|
||||
{
|
||||
key.signalEvent(StandardWatchEventKinds.ENTRY_MODIFY, node.name());
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all entries in the given directory
|
||||
*
|
||||
* The {@code sendCreateEvents} and {@code sendDeleteEvents} parameters
|
||||
* indicates if ENTRY_CREATE and ENTRY_DELETE events should be queued
|
||||
* when new entries are found. When initially registering a directory
|
||||
* they will always be false. When re-scanning a directory then it
|
||||
* depends on if the events are enabled or not.
|
||||
*/
|
||||
void registerChildren(UnixPath dir,
|
||||
SolarisWatchKey parent,
|
||||
boolean sendCreateEvents,
|
||||
boolean sendDeleteEvents)
|
||||
{
|
||||
boolean isModifyEnabled =
|
||||
parent.events().contains(StandardWatchEventKinds.ENTRY_MODIFY) ;
|
||||
|
||||
// reset visited flag on entries so that we can detect file deletes
|
||||
for (EntryNode node: parent.children().values()) {
|
||||
node.setVisited(false);
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
for (Path entry: stream) {
|
||||
Path name = entry.getFileName();
|
||||
|
||||
// skip entry if already registered
|
||||
EntryNode node = parent.getChild(name);
|
||||
if (node != null) {
|
||||
node.setVisited(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// new entry found
|
||||
|
||||
long object = 0L;
|
||||
int errno = 0;
|
||||
boolean addNode = false;
|
||||
|
||||
// if ENTRY_MODIFY enabled then we register the entry for events
|
||||
if (isModifyEnabled) {
|
||||
try {
|
||||
UnixPath path = (UnixPath)entry;
|
||||
int events = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
|
||||
object = registerImpl(path, events);
|
||||
addNode = true;
|
||||
} catch (UnixException x) {
|
||||
errno = x.errno();
|
||||
}
|
||||
} else {
|
||||
addNode = true;
|
||||
}
|
||||
|
||||
if (addNode) {
|
||||
// create node
|
||||
node = new EntryNode(object, (UnixPath)entry.getFileName(), parent);
|
||||
node.setVisited(true);
|
||||
// tell the parent about it
|
||||
parent.addChild(entry.getFileName(), node);
|
||||
if (object != 0L)
|
||||
object2Node.put(object, node);
|
||||
}
|
||||
|
||||
// send ENTRY_CREATE event for the new file
|
||||
// send ENTRY_DELETE event for files that were deleted immediately
|
||||
boolean deleted = (errno == ENOENT);
|
||||
if (sendCreateEvents && (addNode || deleted))
|
||||
parent.signalEvent(StandardWatchEventKinds.ENTRY_CREATE, name);
|
||||
if (sendDeleteEvents && deleted)
|
||||
parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, name);
|
||||
|
||||
}
|
||||
} catch (DirectoryIteratorException | IOException x) {
|
||||
// queue OVERFLOW event so that user knows to re-scan directory
|
||||
parent.signalEvent(StandardWatchEventKinds.OVERFLOW, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// clean-up and send ENTRY_DELETE events for any entries that were
|
||||
// not found
|
||||
Iterator<Map.Entry<Path,EntryNode>> iterator =
|
||||
parent.children().entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<Path,EntryNode> entry = iterator.next();
|
||||
EntryNode node = entry.getValue();
|
||||
if (!node.isVisited()) {
|
||||
long object = node.object();
|
||||
if (object != 0L) {
|
||||
object2Node.remove(object);
|
||||
releaseObject(object, true);
|
||||
}
|
||||
if (sendDeleteEvents)
|
||||
parent.signalEvent(StandardWatchEventKinds.ENTRY_DELETE, node.name());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update watch key's events. If ENTRY_MODIFY changes to be enabled
|
||||
* then register each file in the directory; If ENTRY_MODIFY changed to
|
||||
* be disabled then unregister each file.
|
||||
*/
|
||||
void updateEvents(SolarisWatchKey key, Set<? extends WatchEvent.Kind<?>> events)
|
||||
throws UnixException
|
||||
{
|
||||
|
||||
// update events, remembering if ENTRY_MODIFY was previously
|
||||
// enabled or disabled.
|
||||
boolean oldModifyEnabled = key.events()
|
||||
.contains(StandardWatchEventKinds.ENTRY_MODIFY);
|
||||
key.setEvents(events);
|
||||
|
||||
// check if ENTRY_MODIFY has changed
|
||||
boolean newModifyEnabled = events
|
||||
.contains(StandardWatchEventKinds.ENTRY_MODIFY);
|
||||
if (newModifyEnabled != oldModifyEnabled) {
|
||||
UnixException ex = null;
|
||||
for (EntryNode node: key.children().values()) {
|
||||
if (newModifyEnabled) {
|
||||
// register
|
||||
UnixPath path = key.getDirectory().resolve(node.name());
|
||||
int ev = (FILE_NOFOLLOW | FILE_MODIFIED | FILE_ATTRIB);
|
||||
try {
|
||||
long object = registerImpl(path, ev);
|
||||
object2Node.put(object, node);
|
||||
node.setObject(object);
|
||||
} catch (UnixException x) {
|
||||
// if file has been deleted then it will be detected
|
||||
// as a FILE_MODIFIED event on the directory
|
||||
if (x.errno() != ENOENT) {
|
||||
ex = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// unregister
|
||||
releaseChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
// an error occurred
|
||||
if (ex != null) {
|
||||
releaseChildren(key);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls port_associate to register the given path.
|
||||
* Returns pointer to fileobj structure that is allocated for
|
||||
* the registration.
|
||||
*/
|
||||
long registerImpl(UnixPath dir, int events)
|
||||
throws UnixException
|
||||
{
|
||||
// allocate memory for the path (file_obj->fo_name field)
|
||||
byte[] path = dir.getByteArrayForSysCalls();
|
||||
int len = path.length;
|
||||
long name = unsafe.allocateMemory(len+1);
|
||||
unsafe.copyMemory(path, Unsafe.ARRAY_BYTE_BASE_OFFSET, null,
|
||||
name, (long)len);
|
||||
unsafe.putByte(name + len, (byte)0);
|
||||
|
||||
// allocate memory for filedatanode structure - this is the object
|
||||
// to port_associate
|
||||
long object = unsafe.allocateMemory(SIZEOF_FILEOBJ);
|
||||
unsafe.setMemory(null, object, SIZEOF_FILEOBJ, (byte)0);
|
||||
unsafe.putAddress(object + OFFSET_FO_NAME, name);
|
||||
|
||||
// associate the object with the port
|
||||
try {
|
||||
portAssociate(port,
|
||||
PORT_SOURCE_FILE,
|
||||
object,
|
||||
events);
|
||||
} catch (UnixException x) {
|
||||
// debugging
|
||||
if (x.errno() == EAGAIN) {
|
||||
System.err.println("The maximum number of objects associated "+
|
||||
"with the port has been reached");
|
||||
}
|
||||
|
||||
unsafe.freeMemory(name);
|
||||
unsafe.freeMemory(object);
|
||||
throw x;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees all resources for an file_obj object; optionally remove
|
||||
* association from port
|
||||
*/
|
||||
void releaseObject(long object, boolean dissociate) {
|
||||
// remove association
|
||||
if (dissociate) {
|
||||
try {
|
||||
portDissociate(port, PORT_SOURCE_FILE, object);
|
||||
} catch (UnixException x) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// free native memory
|
||||
long name = unsafe.getAddress(object + OFFSET_FO_NAME);
|
||||
unsafe.freeMemory(name);
|
||||
unsafe.freeMemory(object);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node with native (file_obj) resources
|
||||
*/
|
||||
private static interface Node {
|
||||
long object();
|
||||
}
|
||||
|
||||
/**
|
||||
* A directory node with a map of the entries in the directory
|
||||
*/
|
||||
private static interface DirectoryNode extends Node {
|
||||
void addChild(Path name, EntryNode node);
|
||||
void removeChild(Path name);
|
||||
EntryNode getChild(Path name);
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of a node that is an entry in a directory.
|
||||
*/
|
||||
private static class EntryNode implements Node {
|
||||
private long object;
|
||||
private final UnixPath name;
|
||||
private final DirectoryNode parent;
|
||||
private boolean visited;
|
||||
|
||||
EntryNode(long object, UnixPath name, DirectoryNode parent) {
|
||||
this.object = object;
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long object() {
|
||||
return object;
|
||||
}
|
||||
|
||||
void setObject(long ptr) {
|
||||
this.object = ptr;
|
||||
}
|
||||
|
||||
UnixPath name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
DirectoryNode parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
boolean isVisited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
void setVisited(boolean v) {
|
||||
this.visited = v;
|
||||
}
|
||||
}
|
||||
|
||||
// -- native methods --
|
||||
|
||||
private static native void init();
|
||||
|
||||
private static native int portCreate() throws UnixException;
|
||||
|
||||
private static native void portAssociate(int port, int source, long object, int events)
|
||||
throws UnixException;
|
||||
|
||||
private static native void portDissociate(int port, int source, long object)
|
||||
throws UnixException;
|
||||
|
||||
private static native void portSend(int port, int events)
|
||||
throws UnixException;
|
||||
|
||||
private static native int portGetn(int port, long address, int max)
|
||||
throws UnixException;
|
||||
|
||||
static {
|
||||
jdk.internal.loader.BootLoader.loadLibrary("nio");
|
||||
init();
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
grant codeBase "jrt:/jdk.crypto.ucrypto" {
|
||||
permission java.lang.RuntimePermission
|
||||
"accessClassInPackage.sun.security.*";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
|
||||
permission java.lang.RuntimePermission "loadLibrary.j2ucrypto";
|
||||
// need "com.oracle.security.ucrypto.debug" for debugging
|
||||
permission java.util.PropertyPermission "com.oracle.security.ucrypto.debug", "read";
|
||||
permission java.util.PropertyPermission "file.separator", "read";
|
||||
permission java.util.PropertyPermission "java.home", "read";
|
||||
permission java.util.PropertyPermission "os.name", "read";
|
||||
permission java.security.SecurityPermission
|
||||
"putProviderProperty.OracleUcrypto";
|
||||
permission java.security.SecurityPermission
|
||||
"clearProviderProperties.OracleUcrypto";
|
||||
permission java.security.SecurityPermission
|
||||
"removeProviderProperty.OracleUcrypto";
|
||||
// Needed for reading Ucrypto config file
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read";
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include "ProcessHandleImpl_unix.h"
|
||||
|
||||
#include <procfs.h>
|
||||
|
||||
/*
|
||||
* Implementation of native ProcessHandleImpl functions for Solaris.
|
||||
* See ProcessHandleImpl_unix.c for more details.
|
||||
*/
|
||||
|
||||
void os_initNative(JNIEnv *env, jclass clazz) {}
|
||||
|
||||
jint os_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
|
||||
jlongArray jparentArray, jlongArray jstimesArray) {
|
||||
return unix_getChildren(env, jpid, jarray, jparentArray, jstimesArray);
|
||||
}
|
||||
|
||||
pid_t os_getParentPidAndTimings(JNIEnv *env, pid_t pid, jlong *total, jlong *start) {
|
||||
return unix_getParentPidAndTimings(env, pid, total, start);
|
||||
}
|
||||
|
||||
void os_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
|
||||
unix_getCmdlineAndUserInfo(env, jinfo, pid);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OS_SOLARIS_DTRACE_LIBJVM_DB_H
|
||||
#define OS_SOLARIS_DTRACE_LIBJVM_DB_H
|
||||
|
||||
#include <proc_service.h>
|
||||
#include "jni.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct jvm_agent jvm_agent_t;
|
||||
|
||||
#define JVM_DB_VERSION 1
|
||||
|
||||
JNIEXPORT jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers);
|
||||
|
||||
/*
|
||||
* Called from Jframe_iter() for each java frame. If it returns 0, then
|
||||
* Jframe_iter() proceeds to the next frame. Otherwise, the return value is
|
||||
* immediately returned to the caller of Jframe_iter().
|
||||
*
|
||||
* Parameters:
|
||||
* 'cld' is client supplied data (to maintain iterator state, if any).
|
||||
* 'name' is java method name.
|
||||
* 'bci' is byte code index. it will be -1 if not available.
|
||||
* 'line' is java source line number. it will be 0 if not available.
|
||||
* 'handle' is an abstract client handle, reserved for future expansions
|
||||
*/
|
||||
|
||||
typedef int java_stack_f(void *cld, const prgregset_t regs, const char* name, int bci, int line, void *handle);
|
||||
|
||||
/*
|
||||
* Iterates over the java frames at the current location. Returns -1 if no java
|
||||
* frames were found, or if there was some unrecoverable error. Otherwise,
|
||||
* returns the last value returned from 'func'.
|
||||
*/
|
||||
JNIEXPORT int Jframe_iter(jvm_agent_t *agent, prgregset_t gregs, java_stack_f *func, void* cld);
|
||||
|
||||
JNIEXPORT void Jagent_destroy(jvm_agent_t *J);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif // OS_SOLARIS_DTRACE_LIBJVM_DB_H
|
|
@ -1,562 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <door.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <thread.h>
|
||||
#include <unistd.h>
|
||||
#include "jvm_dtrace.h"
|
||||
|
||||
// NOTE: These constants are used in JVM code as well.
|
||||
// KEEP JVM CODE IN SYNC if you are going to change these...
|
||||
|
||||
#define DTRACE_ALLOC_PROBES 0x1
|
||||
#define DTRACE_METHOD_PROBES 0x2
|
||||
#define DTRACE_MONITOR_PROBES 0x4
|
||||
#define DTRACE_ALL_PROBES -1
|
||||
|
||||
// generic error messages
|
||||
#define JVM_ERR_OUT_OF_MEMORY "out of memory (native heap)"
|
||||
#define JVM_ERR_INVALID_PARAM "invalid input parameter(s)"
|
||||
#define JVM_ERR_NULL_PARAM "input paramater is NULL"
|
||||
|
||||
// error messages for attach
|
||||
#define JVM_ERR_CANT_OPEN_DOOR "cannot open door file"
|
||||
#define JVM_ERR_CANT_CREATE_ATTACH_FILE "cannot create attach file"
|
||||
#define JVM_ERR_DOOR_FILE_PERMISSION "door file is not secure"
|
||||
#define JVM_ERR_CANT_SIGNAL "cannot send SIGQUIT to target"
|
||||
|
||||
// error messages for enable probe
|
||||
#define JVM_ERR_DOOR_CMD_SEND "door command send failed"
|
||||
#define JVM_ERR_DOOR_CANT_READ_STATUS "cannot read door command status"
|
||||
#define JVM_ERR_DOOR_CMD_STATUS "door command error status"
|
||||
|
||||
// error message for detach
|
||||
#define JVM_ERR_CANT_CLOSE_DOOR "cannot close door file"
|
||||
|
||||
#define RESTARTABLE(_cmd, _result) do { \
|
||||
do { \
|
||||
_result = _cmd; \
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
} while(0)
|
||||
|
||||
struct _jvm_t {
|
||||
pid_t pid;
|
||||
int door_fd;
|
||||
};
|
||||
|
||||
static int libjvm_dtrace_debug;
|
||||
static void print_debug(const char* fmt,...) {
|
||||
if (libjvm_dtrace_debug) {
|
||||
va_list alist;
|
||||
va_start(alist, fmt);
|
||||
fputs("libjvm_dtrace DEBUG: ", stderr);
|
||||
vfprintf(stderr, fmt, alist);
|
||||
va_end(alist);
|
||||
}
|
||||
}
|
||||
|
||||
/* Key for thread local error message */
|
||||
static thread_key_t jvm_error_key;
|
||||
|
||||
/* init function for this library */
|
||||
static void init_jvm_dtrace() {
|
||||
/* check for env. var for debug mode */
|
||||
libjvm_dtrace_debug = getenv("LIBJVM_DTRACE_DEBUG") != NULL;
|
||||
/* create key for thread local error message */
|
||||
if (thr_keycreate(&jvm_error_key, NULL) != 0) {
|
||||
print_debug("can't create thread_key_t for jvm error key\n");
|
||||
// exit(1); ?
|
||||
}
|
||||
}
|
||||
|
||||
#pragma init(init_jvm_dtrace)
|
||||
|
||||
/* set thread local error message */
|
||||
static void set_jvm_error(const char* msg) {
|
||||
thr_setspecific(jvm_error_key, (void*)msg);
|
||||
}
|
||||
|
||||
/* clear thread local error message */
|
||||
static void clear_jvm_error() {
|
||||
thr_setspecific(jvm_error_key, NULL);
|
||||
}
|
||||
|
||||
/* file handling functions that can handle interrupt */
|
||||
|
||||
static int file_open(const char* path, int flag) {
|
||||
int ret;
|
||||
RESTARTABLE(open(path, flag), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int file_close(int fd) {
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
static int file_read(int fd, char* buf, int len) {
|
||||
int ret;
|
||||
RESTARTABLE(read(fd, buf, len), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* send SIGQUIT signal to given process */
|
||||
static int send_sigquit(pid_t pid) {
|
||||
int ret;
|
||||
RESTARTABLE(kill(pid, SIGQUIT), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* called to check permissions on attach file */
|
||||
static int check_permission(const char* path) {
|
||||
struct stat64 sb;
|
||||
uid_t uid, gid;
|
||||
int res;
|
||||
|
||||
/*
|
||||
* Check that the path is owned by the effective uid/gid of this
|
||||
* process. Also check that group/other access is not allowed.
|
||||
*/
|
||||
uid = geteuid();
|
||||
gid = getegid();
|
||||
|
||||
res = stat64(path, &sb);
|
||||
if (res != 0) {
|
||||
print_debug("stat failed for %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((sb.st_uid != uid) || (sb.st_gid != gid) ||
|
||||
((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0)) {
|
||||
print_debug("well-known file %s is not secure\n", path);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
|
||||
|
||||
/* fill-in the name of attach file name in given buffer */
|
||||
static void fill_attach_file_name(char* path, int len, pid_t pid) {
|
||||
memset(path, 0, len);
|
||||
sprintf(path, ATTACH_FILE_PATTERN, pid);
|
||||
}
|
||||
|
||||
#define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
|
||||
|
||||
/* open door file for the given JVM */
|
||||
static int open_door(pid_t pid) {
|
||||
char path[PATH_MAX + 1];
|
||||
int fd;
|
||||
|
||||
sprintf(path, DOOR_FILE_PATTERN, pid);
|
||||
fd = file_open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
|
||||
print_debug("cannot open door file %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
print_debug("opened door file %s\n", path);
|
||||
if (check_permission(path) != 0) {
|
||||
set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
|
||||
print_debug("check permission failed for %s\n", path);
|
||||
file_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* create attach file for given process */
|
||||
static int create_attach_file(pid_t pid) {
|
||||
char path[PATH_MAX + 1];
|
||||
int fd;
|
||||
fill_attach_file_name(path, sizeof(path), pid);
|
||||
fd = file_open(path, O_CREAT | O_RDWR);
|
||||
if (fd < 0) {
|
||||
set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
|
||||
print_debug("cannot create file %s\n", path);
|
||||
} else {
|
||||
print_debug("created attach file %s\n", path);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* delete attach file for given process */
|
||||
static void delete_attach_file(pid_t pid) {
|
||||
char path[PATH_MAX + 1];
|
||||
fill_attach_file_name(path, sizeof(path), pid);
|
||||
int res = unlink(path);
|
||||
if (res) {
|
||||
print_debug("cannot delete attach file %s\n", path);
|
||||
} else {
|
||||
print_debug("deleted attach file %s\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
/* attach to given JVM */
|
||||
jvm_t* jvm_attach(pid_t pid) {
|
||||
jvm_t* jvm;
|
||||
int door_fd, attach_fd, i = 0;
|
||||
|
||||
jvm = (jvm_t*) calloc(1, sizeof(jvm_t));
|
||||
if (jvm == NULL) {
|
||||
set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
|
||||
print_debug("calloc failed in %s at %d\n", __FILE__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
jvm->pid = pid;
|
||||
attach_fd = -1;
|
||||
|
||||
door_fd = open_door(pid);
|
||||
if (door_fd < 0) {
|
||||
print_debug("trying to create attach file\n");
|
||||
if ((attach_fd = create_attach_file(pid)) < 0) {
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* send QUIT signal to the target so that it will
|
||||
* check for the attach file.
|
||||
*/
|
||||
if (send_sigquit(pid) != 0) {
|
||||
set_jvm_error(JVM_ERR_CANT_SIGNAL);
|
||||
print_debug("sending SIGQUIT failed\n");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* give the target VM time to start the attach mechanism */
|
||||
do {
|
||||
int res;
|
||||
RESTARTABLE(poll(0, 0, 200), res);
|
||||
door_fd = open_door(pid);
|
||||
i++;
|
||||
} while (i <= 50 && door_fd == -1);
|
||||
if (door_fd < 0) {
|
||||
print_debug("Unable to open door to process %d\n", pid);
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
quit:
|
||||
if (attach_fd >= 0) {
|
||||
file_close(attach_fd);
|
||||
delete_attach_file(jvm->pid);
|
||||
}
|
||||
if (door_fd >= 0) {
|
||||
jvm->door_fd = door_fd;
|
||||
clear_jvm_error();
|
||||
} else {
|
||||
free(jvm);
|
||||
jvm = NULL;
|
||||
}
|
||||
return jvm;
|
||||
}
|
||||
|
||||
/* return the last thread local error message */
|
||||
const char* jvm_get_last_error() {
|
||||
const char* res = NULL;
|
||||
thr_getspecific(jvm_error_key, (void**)&res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* detach the givenb JVM */
|
||||
int jvm_detach(jvm_t* jvm) {
|
||||
if (jvm) {
|
||||
int res = 0;
|
||||
if (jvm->door_fd != -1) {
|
||||
if (file_close(jvm->door_fd) != 0) {
|
||||
set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR);
|
||||
res = -1;
|
||||
} else {
|
||||
clear_jvm_error();
|
||||
}
|
||||
}
|
||||
free(jvm);
|
||||
return res;
|
||||
} else {
|
||||
set_jvm_error(JVM_ERR_NULL_PARAM);
|
||||
print_debug("jvm_t* is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple table to translate some known errors into reasonable
|
||||
* error messages
|
||||
*/
|
||||
static struct {
|
||||
int err;
|
||||
const char* msg;
|
||||
} const error_messages[] = {
|
||||
{ 100, "Bad request" },
|
||||
{ 101, "Protocol mismatch" },
|
||||
{ 102, "Resource failure" },
|
||||
{ 103, "Internal error" },
|
||||
{ 104, "Permission denied" },
|
||||
};
|
||||
|
||||
/*
|
||||
* Lookup the given error code and return the appropriate
|
||||
* message. If not found return NULL.
|
||||
*/
|
||||
static const char* translate_error(int err) {
|
||||
int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
|
||||
int i;
|
||||
|
||||
for (i=0; i<table_size; i++) {
|
||||
if (err == error_messages[i].err) {
|
||||
return error_messages[i].msg;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Current protocol version
|
||||
*/
|
||||
static const char* PROTOCOL_VERSION = "1";
|
||||
|
||||
#define RES_BUF_SIZE 128
|
||||
|
||||
/*
|
||||
* Enqueue attach-on-demand command to the given JVM
|
||||
*/
|
||||
static
|
||||
int enqueue_command(jvm_t* jvm, const char* cstr, int arg_count, const char** args) {
|
||||
size_t size;
|
||||
door_arg_t door_args;
|
||||
char res_buffer[RES_BUF_SIZE];
|
||||
int rc, i;
|
||||
char* buf = NULL;
|
||||
int result = -1;
|
||||
|
||||
/*
|
||||
* First we get the command string and create the start of the
|
||||
* argument string to send to the target VM:
|
||||
* <ver>\0<cmd>\0
|
||||
*/
|
||||
if (cstr == NULL) {
|
||||
print_debug("command name is NULL\n");
|
||||
goto quit;
|
||||
}
|
||||
size = strlen(PROTOCOL_VERSION) + strlen(cstr) + 2;
|
||||
buf = (char*)malloc(size);
|
||||
if (buf != NULL) {
|
||||
char* pos = buf;
|
||||
strcpy(buf, PROTOCOL_VERSION);
|
||||
pos += strlen(PROTOCOL_VERSION)+1;
|
||||
strcpy(pos, cstr);
|
||||
} else {
|
||||
set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
|
||||
print_debug("malloc failed at %d in %s\n", __LINE__, __FILE__);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next we iterate over the arguments and extend the buffer
|
||||
* to include them.
|
||||
*/
|
||||
for (i=0; i<arg_count; i++) {
|
||||
cstr = args[i];
|
||||
if (cstr != NULL) {
|
||||
size_t len = strlen(cstr);
|
||||
char* newbuf = (char*)realloc(buf, size+len+1);
|
||||
if (newbuf == NULL) {
|
||||
set_jvm_error(JVM_ERR_OUT_OF_MEMORY);
|
||||
print_debug("realloc failed in %s at %d\n", __FILE__, __LINE__);
|
||||
goto quit;
|
||||
}
|
||||
buf = newbuf;
|
||||
strcpy(buf+size, cstr);
|
||||
size += len+1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The arguments to the door function are in 'buf' so we now
|
||||
* do the door call
|
||||
*/
|
||||
door_args.data_ptr = buf;
|
||||
door_args.data_size = size;
|
||||
door_args.desc_ptr = NULL;
|
||||
door_args.desc_num = 0;
|
||||
door_args.rbuf = (char*)&res_buffer;
|
||||
door_args.rsize = sizeof(res_buffer);
|
||||
|
||||
RESTARTABLE(door_call(jvm->door_fd, &door_args), rc);
|
||||
|
||||
/*
|
||||
* door_call failed
|
||||
*/
|
||||
if (rc == -1) {
|
||||
print_debug("door_call failed\n");
|
||||
} else {
|
||||
/*
|
||||
* door_call succeeded but the call didn't return the expected jint.
|
||||
*/
|
||||
if (door_args.data_size < sizeof(int)) {
|
||||
print_debug("Enqueue error - reason unknown as result is truncated!");
|
||||
} else {
|
||||
int* res = (int*)(door_args.data_ptr);
|
||||
if (*res != 0) {
|
||||
const char* msg = translate_error(*res);
|
||||
if (msg == NULL) {
|
||||
print_debug("Unable to enqueue command to target VM: %d\n", *res);
|
||||
} else {
|
||||
print_debug("Unable to enqueue command to target VM: %s\n", msg);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* The door call should return a file descriptor to one end of
|
||||
* a socket pair
|
||||
*/
|
||||
if ((door_args.desc_ptr != NULL) &&
|
||||
(door_args.desc_num == 1) &&
|
||||
(door_args.desc_ptr->d_attributes & DOOR_DESCRIPTOR)) {
|
||||
result = door_args.desc_ptr->d_data.d_desc.d_descriptor;
|
||||
} else {
|
||||
print_debug("Reply from enqueue missing descriptor!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
quit:
|
||||
if (buf) free(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* read status code for a door command */
|
||||
static int read_status(int fd) {
|
||||
char ch, buf[16];
|
||||
int index = 0;
|
||||
|
||||
while (1) {
|
||||
if (file_read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
|
||||
set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
|
||||
print_debug("door cmd status: read status failed\n");
|
||||
return -1;
|
||||
}
|
||||
buf[index++] = ch;
|
||||
if (ch == '\n') {
|
||||
buf[index - 1] = '\0';
|
||||
return atoi(buf);
|
||||
}
|
||||
if (index == sizeof(buf)) {
|
||||
set_jvm_error(JVM_ERR_DOOR_CANT_READ_STATUS);
|
||||
print_debug("door cmd status: read status overflow\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* ENABLE_DPROBES_CMD = "enabledprobes";
|
||||
|
||||
/* enable one or more DTrace probes for a given JVM */
|
||||
int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types) {
|
||||
int fd, status = 0;
|
||||
char ch;
|
||||
const char* args[1];
|
||||
char buf[16];
|
||||
int probe_type = 0, index;
|
||||
int count = 0;
|
||||
|
||||
if (jvm == NULL) {
|
||||
set_jvm_error(JVM_ERR_NULL_PARAM);
|
||||
print_debug("jvm_t* is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (num_probe_types == 0 || probe_types == NULL ||
|
||||
probe_types[0] == NULL) {
|
||||
set_jvm_error(JVM_ERR_INVALID_PARAM);
|
||||
print_debug("invalid probe type argument(s)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_probe_types; index++) {
|
||||
const char* p = probe_types[index];
|
||||
if (strcmp(p, JVM_DTPROBE_OBJECT_ALLOC) == 0) {
|
||||
probe_type |= DTRACE_ALLOC_PROBES;
|
||||
count++;
|
||||
} else if (strcmp(p, JVM_DTPROBE_METHOD_ENTRY) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_METHOD_RETURN) == 0) {
|
||||
probe_type |= DTRACE_METHOD_PROBES;
|
||||
count++;
|
||||
} else if (strcmp(p, JVM_DTPROBE_MONITOR_ENTER) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_ENTERED) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_EXIT) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_WAIT) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_WAITED) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_NOTIFY) == 0 ||
|
||||
strcmp(p, JVM_DTPROBE_MONITOR_NOTIFYALL) == 0) {
|
||||
probe_type |= DTRACE_MONITOR_PROBES;
|
||||
count++;
|
||||
} else if (strcmp(p, JVM_DTPROBE_ALL) == 0) {
|
||||
probe_type |= DTRACE_ALL_PROBES;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return count;
|
||||
}
|
||||
sprintf(buf, "%d", probe_type);
|
||||
args[0] = buf;
|
||||
|
||||
fd = enqueue_command(jvm, ENABLE_DPROBES_CMD, 1, args);
|
||||
if (fd < 0) {
|
||||
set_jvm_error(JVM_ERR_DOOR_CMD_SEND);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = read_status(fd);
|
||||
// non-zero status is error
|
||||
if (status) {
|
||||
set_jvm_error(JVM_ERR_DOOR_CMD_STATUS);
|
||||
print_debug("%s command failed (status: %d) in target JVM\n",
|
||||
ENABLE_DPROBES_CMD, status);
|
||||
file_close(fd);
|
||||
return -1;
|
||||
}
|
||||
// read from stream until EOF
|
||||
while (file_read(fd, &ch, sizeof(ch)) == sizeof(ch)) {
|
||||
if (libjvm_dtrace_debug) {
|
||||
printf("%c", ch);
|
||||
}
|
||||
}
|
||||
|
||||
file_close(fd);
|
||||
clear_jvm_error();
|
||||
return count;
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _JVM_DTRACE_H_
|
||||
#define _JVM_DTRACE_H_
|
||||
|
||||
/*
|
||||
* Interface to dynamically turn on probes in Hotspot JVM. Currently,
|
||||
* this interface can be used to dynamically enable certain DTrace
|
||||
* probe points that are costly to have "always on".
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "jni.h"
|
||||
|
||||
struct _jvm_t;
|
||||
typedef struct _jvm_t jvm_t;
|
||||
|
||||
|
||||
/* Attach to the given JVM process. Returns NULL on failure.
|
||||
jvm_get_last_error() returns last error message. */
|
||||
JNIEXPORT jvm_t* jvm_attach(pid_t pid);
|
||||
|
||||
/* Returns the last error message from this library or NULL if none. */
|
||||
JNIEXPORT const char* jvm_get_last_error();
|
||||
|
||||
/* few well-known probe type constants for 'probe_types' param below */
|
||||
|
||||
#define JVM_DTPROBE_METHOD_ENTRY "method-entry"
|
||||
#define JVM_DTPROBE_METHOD_RETURN "method-return"
|
||||
#define JVM_DTPROBE_MONITOR_ENTER "monitor-contended-enter"
|
||||
#define JVM_DTPROBE_MONITOR_ENTERED "monitor-contended-entered"
|
||||
#define JVM_DTPROBE_MONITOR_EXIT "monitor-contended-exit"
|
||||
#define JVM_DTPROBE_MONITOR_WAIT "monitor-wait"
|
||||
#define JVM_DTPROBE_MONITOR_WAITED "monitor-waited"
|
||||
#define JVM_DTPROBE_MONITOR_NOTIFY "monitor-notify"
|
||||
#define JVM_DTPROBE_MONITOR_NOTIFYALL "monitor-notifyall"
|
||||
#define JVM_DTPROBE_OBJECT_ALLOC "object-alloc"
|
||||
#define JVM_DTPROBE_ALL "*"
|
||||
|
||||
/* Enable the specified DTrace probes of given probe types on
|
||||
* the specified JVM. Returns >= 0 on success, -1 on failure.
|
||||
* On success, this returns number of probe_types enabled.
|
||||
* On failure, jvm_get_last_error() returns the last error message.
|
||||
*/
|
||||
JNIEXPORT int jvm_enable_dtprobes(jvm_t* jvm, int num_probe_types, const char** probe_types);
|
||||
|
||||
/* Note: There is no jvm_disable_dtprobes function. Probes are automatically
|
||||
* disabled when there are no more clients requiring those probes.
|
||||
*/
|
||||
|
||||
/* Detach the given JVM. Returns 0 on success, -1 on failure.
|
||||
* jvm_get_last_error() returns the last error message.
|
||||
*/
|
||||
JNIEXPORT int jvm_detach(jvm_t* jvm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _JVM_DTRACE_H_ */
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stropts.h>
|
||||
#include <unistd.h>
|
||||
#include "jvm.h"
|
||||
#include "net_util.h"
|
||||
|
||||
/* Support for restartable system calls on Solaris. */
|
||||
|
||||
#define RESTARTABLE_RETURN_INT(_cmd) do { \
|
||||
int _result; \
|
||||
if (1) { \
|
||||
do { \
|
||||
_result = _cmd; \
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
return _result; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int NET_Read(int s, void* buf, size_t len) {
|
||||
RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
|
||||
}
|
||||
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len) {
|
||||
RESTARTABLE_RETURN_INT(recv(s, buf, len, MSG_DONTWAIT));
|
||||
}
|
||||
|
||||
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen) {
|
||||
RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
|
||||
}
|
||||
|
||||
int NET_Send(int s, void *msg, int len, unsigned int flags) {
|
||||
RESTARTABLE_RETURN_INT(send(s, msg, len, flags));
|
||||
}
|
||||
|
||||
int NET_SendTo(int s, const void *msg, int len, unsigned int flags,
|
||||
const struct sockaddr *to, int tolen) {
|
||||
RESTARTABLE_RETURN_INT(sendto(s, msg, len, flags, to, tolen));
|
||||
}
|
||||
|
||||
int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
|
||||
RESTARTABLE_RETURN_INT(connect(s, addr, addrlen));
|
||||
}
|
||||
|
||||
int NET_Accept(int s, struct sockaddr *addr, socklen_t *addrlen) {
|
||||
RESTARTABLE_RETURN_INT(accept(s, addr, addrlen));
|
||||
}
|
||||
|
||||
int NET_SocketClose(int fd) {
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
int NET_Dup2(int fd, int fd2) {
|
||||
return dup2(fd, fd2);
|
||||
}
|
||||
|
||||
int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
|
||||
RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
|
||||
}
|
||||
|
||||
int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
|
||||
int result;
|
||||
jlong prevNanoTime = nanoTimeStamp;
|
||||
jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = s;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
for(;;) {
|
||||
result = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
|
||||
if (result < 0 && errno == EINTR) {
|
||||
jlong newNanoTime = JVM_NanoTime(env, 0);
|
||||
nanoTimeout -= newNanoTime - prevNanoTime;
|
||||
if (nanoTimeout < NET_NSEC_PER_MSEC)
|
||||
return 0;
|
||||
prevNanoTime = newNanoTime;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <sys/devpoll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
|
||||
#include "sun_nio_ch_DevPollArrayWrapper.h"
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_init(JNIEnv *env, jobject this)
|
||||
{
|
||||
int wfd = open("/dev/poll", O_RDWR);
|
||||
if (wfd < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error opening driver");
|
||||
return -1;
|
||||
}
|
||||
return wfd;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_register(JNIEnv *env, jobject this,
|
||||
jint wfd, jint fd, jint mask)
|
||||
{
|
||||
struct pollfd a[1];
|
||||
int n;
|
||||
|
||||
a[0].fd = fd;
|
||||
a[0].events = mask;
|
||||
a[0].revents = 0;
|
||||
|
||||
n = write(wfd, &a[0], sizeof(a));
|
||||
if (n != sizeof(a)) {
|
||||
if (n < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
|
||||
} else {
|
||||
JNU_ThrowIOException(env, "Unexpected number of bytes written");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple(JNIEnv *env, jobject this,
|
||||
jint wfd, jlong address,
|
||||
jint len)
|
||||
{
|
||||
unsigned char *pollBytes = (unsigned char *)jlong_to_ptr(address);
|
||||
unsigned char *pollEnd = pollBytes + sizeof(struct pollfd) * len;
|
||||
while (pollBytes < pollEnd) {
|
||||
int bytesWritten = write(wfd, pollBytes, (int)(pollEnd - pollBytes));
|
||||
if (bytesWritten < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error writing pollfds");
|
||||
return;
|
||||
}
|
||||
pollBytes += bytesWritten;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
|
||||
jlong address, jint numfds,
|
||||
jlong timeout, jint wfd)
|
||||
{
|
||||
struct dvpoll a;
|
||||
void *pfd = (void *) jlong_to_ptr(address);
|
||||
int result;
|
||||
|
||||
a.dp_fds = pfd;
|
||||
a.dp_nfds = numfds;
|
||||
a.dp_timeout = (int)timeout;
|
||||
result = ioctl(wfd, DP_POLL, &a);
|
||||
if (result < 0) {
|
||||
if (errno == EINTR) {
|
||||
return IOS_INTERRUPTED;
|
||||
} else {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <port.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
|
||||
#include "sun_nio_ch_SolarisEventPort.h"
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1create
|
||||
(JNIEnv* env, jclass clazz)
|
||||
{
|
||||
int port = port_create();
|
||||
if (port == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_create");
|
||||
}
|
||||
return (jint)port;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1close
|
||||
(JNIEnv* env, jclass clazz, jint port)
|
||||
{
|
||||
int res = close(port);
|
||||
if (res < 0 && res != EINTR) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "close failed");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1associate
|
||||
(JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
|
||||
{
|
||||
uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
|
||||
if (port_associate((int)port, (int)source, object, (int)events, NULL) == 0) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
if (errno != EBADFD)
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_associate");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1dissociate
|
||||
(JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
|
||||
{
|
||||
uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
|
||||
|
||||
if (port_dissociate((int)port, (int)source, object) == 0) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
if (errno != ENOENT)
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
|
||||
jint port, jint events)
|
||||
{
|
||||
if (port_send((int)port, (int)events, NULL) == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_send");
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
|
||||
jint port, jlong eventAddress)
|
||||
{
|
||||
int res;
|
||||
port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
|
||||
|
||||
res = port_get((int)port, ev, NULL);
|
||||
if (res == -1) {
|
||||
if (errno == EINTR) {
|
||||
return IOS_INTERRUPTED;
|
||||
} else {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
|
||||
jint port, jlong arrayAddress, jint max, jlong timeout)
|
||||
{
|
||||
int res;
|
||||
uint_t n = 1;
|
||||
port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
|
||||
timespec_t ts;
|
||||
timespec_t* tsp;
|
||||
|
||||
if (timeout >= 0L) {
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = 1000000 * (timeout % 1000);
|
||||
tsp = &ts;
|
||||
} else {
|
||||
tsp = NULL;
|
||||
}
|
||||
|
||||
res = port_getn((int)port, list, (uint_t)max, &n, tsp);
|
||||
if (res == -1 && errno != ETIME) {
|
||||
if (errno == EINTR) {
|
||||
return IOS_INTERRUPTED;
|
||||
} else {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
}
|
||||
|
||||
return (jint)n;
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/mkdev.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include "sun_nio_fs_SolarisNativeDispatcher.h"
|
||||
|
||||
static jfieldID entry_name;
|
||||
static jfieldID entry_dir;
|
||||
static jfieldID entry_fstype;
|
||||
static jfieldID entry_options;
|
||||
static jfieldID entry_dev;
|
||||
|
||||
static void throwUnixException(JNIEnv* env, int errnum) {
|
||||
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
|
||||
"(I)V", errnum);
|
||||
if (x != NULL) {
|
||||
(*env)->Throw(env, x);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_SolarisNativeDispatcher_init(JNIEnv *env, jclass clazz) {
|
||||
clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
|
||||
CHECK_NULL(clazz);
|
||||
entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
|
||||
CHECK_NULL(entry_name);
|
||||
entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
|
||||
CHECK_NULL(entry_dir);
|
||||
entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
|
||||
CHECK_NULL(entry_fstype);
|
||||
entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
|
||||
CHECK_NULL(entry_options);
|
||||
entry_dev = (*env)->GetFieldID(env, clazz, "dev", "J");
|
||||
CHECK_NULL(entry_dev);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_fs_SolarisNativeDispatcher_facl(JNIEnv* env, jclass this, jint fd,
|
||||
jint cmd, jint nentries, jlong address)
|
||||
{
|
||||
void* aclbufp = jlong_to_ptr(address);
|
||||
int n = -1;
|
||||
|
||||
n = facl((int)fd, (int)cmd, (int)nentries, aclbufp);
|
||||
if (n == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
return (jint)n;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_fs_SolarisNativeDispatcher_getextmntent(JNIEnv* env, jclass this,
|
||||
jlong value, jobject entry)
|
||||
{
|
||||
struct extmnttab ent;
|
||||
FILE* fp = jlong_to_ptr(value);
|
||||
jsize len;
|
||||
jbyteArray bytes;
|
||||
char* name;
|
||||
char* dir;
|
||||
char* fstype;
|
||||
char* options;
|
||||
dev_t dev;
|
||||
|
||||
if (getextmntent(fp, &ent, 0))
|
||||
return -1;
|
||||
name = ent.mnt_special;
|
||||
dir = ent.mnt_mountp;
|
||||
fstype = ent.mnt_fstype;
|
||||
options = ent.mnt_mntopts;
|
||||
dev = makedev(ent.mnt_major, ent.mnt_minor);
|
||||
if (dev == NODEV) {
|
||||
throwUnixException(env, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(name);
|
||||
bytes = (*env)->NewByteArray(env, len);
|
||||
if (bytes == NULL)
|
||||
return -1;
|
||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
|
||||
(*env)->SetObjectField(env, entry, entry_name, bytes);
|
||||
|
||||
len = strlen(dir);
|
||||
bytes = (*env)->NewByteArray(env, len);
|
||||
if (bytes == NULL)
|
||||
return -1;
|
||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
|
||||
(*env)->SetObjectField(env, entry, entry_dir, bytes);
|
||||
|
||||
len = strlen(fstype);
|
||||
bytes = (*env)->NewByteArray(env, len);
|
||||
if (bytes == NULL)
|
||||
return -1;
|
||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
|
||||
(*env)->SetObjectField(env, entry, entry_fstype, bytes);
|
||||
|
||||
len = strlen(options);
|
||||
bytes = (*env)->NewByteArray(env, len);
|
||||
if (bytes == NULL)
|
||||
return -1;
|
||||
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
|
||||
(*env)->SetObjectField(env, entry, entry_options, bytes);
|
||||
|
||||
if (dev != 0)
|
||||
(*env)->SetLongField(env, entry, entry_dev, (jlong)dev);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <port.h> // Solaris 10
|
||||
|
||||
#include "sun_nio_fs_SolarisWatchService.h"
|
||||
|
||||
static void throwUnixException(JNIEnv* env, int errnum) {
|
||||
jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
|
||||
"(I)V", errnum);
|
||||
if (x != NULL) {
|
||||
(*env)->Throw(env, x);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_init(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_portCreate
|
||||
(JNIEnv* env, jclass clazz)
|
||||
{
|
||||
int port = port_create();
|
||||
if (port == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
return (jint)port;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_portAssociate
|
||||
(JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events)
|
||||
{
|
||||
uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
|
||||
|
||||
if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_portDissociate
|
||||
(JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress)
|
||||
{
|
||||
uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress);
|
||||
|
||||
if (port_dissociate((int)port, (int)source, object) == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_portSend(JNIEnv* env, jclass clazz,
|
||||
jint port, jint events)
|
||||
{
|
||||
if (port_send((int)port, (int)events, NULL) == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_fs_SolarisWatchService_portGetn(JNIEnv* env, jclass clazz,
|
||||
jint port, jlong arrayAddress, jint max)
|
||||
{
|
||||
uint_t n = 1;
|
||||
port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress);
|
||||
|
||||
if (port_getn((int)port, list, (uint_t)max, &n, NULL) == -1) {
|
||||
throwUnixException(env, errno);
|
||||
}
|
||||
return (jint)n;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -77,9 +77,6 @@ final class ProcessImpl extends Process {
|
|||
private /* final */ InputStream stdout;
|
||||
private /* final */ InputStream stderr;
|
||||
|
||||
// only used on Solaris
|
||||
private /* final */ DeferredCloseInputStream stdout_inner_stream;
|
||||
|
||||
private static enum LaunchMechanism {
|
||||
// order IS important!
|
||||
FORK,
|
||||
|
@ -93,8 +90,6 @@ final class ProcessImpl extends Process {
|
|||
|
||||
BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
|
||||
|
||||
final LaunchMechanism defaultLaunchMechanism;
|
||||
|
@ -139,7 +134,6 @@ final class ProcessImpl extends Process {
|
|||
|
||||
if (osName.equals("Linux")) { return LINUX; }
|
||||
if (osName.contains("OS X")) { return BSD; }
|
||||
if (osName.equals("SunOS")) { return SOLARIS; }
|
||||
if (osName.equals("AIX")) { return AIX; }
|
||||
|
||||
throw new Error(osName + " is not a supported OS platform.");
|
||||
|
@ -385,41 +379,6 @@ final class ProcessImpl extends Process {
|
|||
});
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new BufferedOutputStream(
|
||||
new FileOutputStream(newFileDescriptor(fds[0])));
|
||||
|
||||
stdout = (fds[1] == -1 || forceNullOutputStream) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new BufferedInputStream(
|
||||
stdout_inner_stream =
|
||||
new DeferredCloseInputStream(
|
||||
newFileDescriptor(fds[1])));
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseInputStream(newFileDescriptor(fds[2]));
|
||||
|
||||
/*
|
||||
* For each subprocess forked a corresponding reaper task
|
||||
* is submitted. That task is the only thread which waits
|
||||
* for the subprocess to terminate and it doesn't hold any
|
||||
* locks while doing so. This design allows waitFor() and
|
||||
* exitStatus() to be safely executed in parallel (and they
|
||||
* need no native code).
|
||||
*/
|
||||
ProcessHandleImpl.completion(pid, true).handle((exitcode, throwable) -> {
|
||||
synchronized (this) {
|
||||
this.exitcode = (exitcode == null) ? -1 : exitcode.intValue();
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
break;
|
||||
|
||||
case AIX:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
|
@ -522,29 +481,6 @@ final class ProcessImpl extends Process {
|
|||
try { stderr.close(); } catch (IOException ignored) {}
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
||||
// there is an unavoidable race condition here, but the window
|
||||
// is very small, and OSes try hard to not recycle pids too
|
||||
// soon, so this is quite safe.
|
||||
synchronized (this) {
|
||||
if (!hasExited)
|
||||
processHandle.destroyProcess(force);
|
||||
try {
|
||||
stdin.close();
|
||||
if (stdout_inner_stream != null)
|
||||
stdout_inner_stream.closeDeferred(stdout);
|
||||
if (stderr instanceof DeferredCloseInputStream)
|
||||
((DeferredCloseInputStream) stderr)
|
||||
.closeDeferred(stderr);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: throw new AssertionError("Unsupported platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -46,9 +46,6 @@ public final class PortConfig {
|
|||
if (os.startsWith("Linux")) {
|
||||
defaultLower = 32768;
|
||||
defaultUpper = 61000;
|
||||
} else if (os.startsWith("SunOS")) {
|
||||
defaultLower = 32768;
|
||||
defaultUpper = 65535;
|
||||
} else if (os.contains("OS X")) {
|
||||
defaultLower = 49152;
|
||||
defaultUpper = 65535;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -177,16 +177,6 @@ public class ResolverConfigurationImpl
|
|||
|
||||
// No search keyword so use local domain
|
||||
|
||||
|
||||
// LOCALDOMAIN has absolute priority on Solaris
|
||||
|
||||
String localDomain = localDomain0();
|
||||
if (localDomain != null && !localDomain.isEmpty()) {
|
||||
sl = new LinkedList<>();
|
||||
sl.add(localDomain);
|
||||
return sl;
|
||||
}
|
||||
|
||||
// try domain keyword in /etc/resolv.conf
|
||||
|
||||
sl = java.security.AccessController.doPrivileged(
|
||||
|
@ -254,8 +244,6 @@ public class ResolverConfigurationImpl
|
|||
|
||||
// --- Native methods --
|
||||
|
||||
static native String localDomain0();
|
||||
|
||||
static native String fallbackDomain0();
|
||||
|
||||
static {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -31,10 +31,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* On Solaris, "sun" is defined as a macro. Undefine to make package
|
||||
declaration valid */
|
||||
#undef sun
|
||||
|
||||
/* To be able to name the Java constants the same as the C constants without
|
||||
having the preprocessor rewrite those identifiers, add PREFIX_ to all
|
||||
identifiers matching a C constant. The PREFIX_ is filtered out in the
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -92,10 +92,6 @@ abstract class UnixFileSystem
|
|||
return rootDirectory;
|
||||
}
|
||||
|
||||
boolean isSolaris() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static List<String> standardFileAttributeViews() {
|
||||
return Arrays.asList("basic", "posix", "unix", "owner");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -801,15 +801,7 @@ class UnixPath implements Path {
|
|||
("NOFOLLOW_LINKS is not supported on this platform");
|
||||
flags |= O_NOFOLLOW;
|
||||
}
|
||||
try {
|
||||
return open(this, flags, 0);
|
||||
} catch (UnixException x) {
|
||||
// HACK: EINVAL instead of ELOOP on Solaris 10 prior to u4 (see 6460380)
|
||||
if (getFileSystem().isSolaris() && x.errno() == EINVAL)
|
||||
x.setError(ELOOP);
|
||||
|
||||
throw x;
|
||||
}
|
||||
return open(this, flags, 0);
|
||||
}
|
||||
|
||||
void checkRead() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -33,7 +33,7 @@ import java.util.Arrays;
|
|||
import sun.security.util.Debug;
|
||||
|
||||
/**
|
||||
* Native PRNG implementation for Solaris/Linux/MacOS.
|
||||
* Native PRNG implementation for Linux/MacOS.
|
||||
* <p>
|
||||
* It obtains seed and random numbers by reading system files such as
|
||||
* the special device files /dev/random and /dev/urandom. This
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -45,20 +45,10 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
/* For POSIX-compliant getpwuid_r on Solaris */
|
||||
#if defined(__solaris__)
|
||||
#define _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
|
||||
#ifdef _AIX
|
||||
#include <sys/procfs.h>
|
||||
#endif
|
||||
#ifdef __solaris__
|
||||
#include <procfs.h>
|
||||
#endif
|
||||
|
||||
#if defined(_AIX)
|
||||
#include <sys/procfs.h>
|
||||
#define DIR DIR64
|
||||
#define dirent dirent64
|
||||
#define opendir opendir64
|
||||
|
@ -138,18 +128,13 @@
|
|||
#define WTERMSIG(status) ((status)&0x7F)
|
||||
#endif
|
||||
|
||||
#ifdef __solaris__
|
||||
/* The child exited because of a signal.
|
||||
* The best value to return is 0x80 + signal number,
|
||||
* because that is what all Unix shells do, and because
|
||||
* it allows callers to distinguish between process exit and
|
||||
* process death by signal.
|
||||
* Unfortunately, the historical behavior on Solaris is to return
|
||||
* the signal number, and we preserve this for compatibility. */
|
||||
#define WTERMSIG_RETURN(status) WTERMSIG(status)
|
||||
#else
|
||||
*/
|
||||
#define WTERMSIG_RETURN(status) (WTERMSIG(status) + 0x80)
|
||||
#endif
|
||||
|
||||
#define RESTARTABLE(_cmd, _result) do { \
|
||||
do { \
|
||||
|
@ -503,7 +488,7 @@ void unix_getUserInfo(JNIEnv* env, jobject jinfo, uid_t uid) {
|
|||
* The following functions are common on Solaris, Linux and AIX.
|
||||
*/
|
||||
|
||||
#if defined(__solaris__) || defined (__linux__) || defined(_AIX)
|
||||
#if defined (__linux__) || defined(_AIX)
|
||||
|
||||
/*
|
||||
* Returns the children of the requested pid and optionally each parent and
|
||||
|
@ -622,13 +607,13 @@ jint unix_getChildren(JNIEnv *env, jlong jpid, jlongArray jarray,
|
|||
return count;
|
||||
}
|
||||
|
||||
#endif // defined(__solaris__) || defined (__linux__) || defined(_AIX)
|
||||
#endif // defined (__linux__) || defined(_AIX)
|
||||
|
||||
/*
|
||||
* The following functions are common on Solaris and AIX.
|
||||
* The following functions are for AIX.
|
||||
*/
|
||||
|
||||
#if defined(__solaris__) || defined(_AIX)
|
||||
#if defined(_AIX)
|
||||
|
||||
/**
|
||||
* Helper function to get the 'psinfo_t' data from "/proc/%d/psinfo".
|
||||
|
@ -691,19 +676,6 @@ void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
|
|||
jstring cmdexe = NULL;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* On Solaris, the full path to the executable command is the link in
|
||||
* /proc/<pid>/paths/a.out. But it is only readable for processes we own.
|
||||
*/
|
||||
#if defined(__solaris__)
|
||||
snprintf(fn, sizeof fn, "/proc/%d/path/a.out", pid);
|
||||
if ((ret = readlink(fn, exePath, PATH_MAX - 1)) > 0) {
|
||||
// null terminate and create String to store for command
|
||||
exePath[ret] = '\0';
|
||||
CHECK_NULL(cmdexe = JNU_NewStringPlatform(env, exePath));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now try to open /proc/%d/psinfo
|
||||
*/
|
||||
|
@ -733,4 +705,4 @@ void unix_getCmdlineAndUserInfo(JNIEnv *env, jobject jinfo, pid_t pid) {
|
|||
prargs[0] == '\0' ? NULL : prargs);
|
||||
}
|
||||
|
||||
#endif // defined(__solaris__) || defined(_AIX)
|
||||
#endif // defined(_AIX)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -29,7 +29,7 @@
|
|||
* Declaration of ProcessHandleImpl functions common on all Unix platforms.
|
||||
* 'unix_' functions have a single implementation in ProcessHandleImpl_unix.c
|
||||
* 'os_' prefixed functions have different, os-specific implementations in the
|
||||
* various ProcessHandleImpl_{linux,macosx,solaris,aix}.c files.
|
||||
* various ProcessHandleImpl_{linux,macosx,aix}.c files.
|
||||
* See ProcessHandleImpl_unix.c for more details.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -230,14 +230,7 @@ xmalloc(JNIEnv *env, size_t size)
|
|||
static const char*
|
||||
defaultPath(void)
|
||||
{
|
||||
#ifdef __solaris__
|
||||
/* These really are the Solaris defaults! */
|
||||
return (geteuid() == 0 || getuid() == 0) ?
|
||||
"/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
|
||||
"/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
|
||||
#else
|
||||
return ":/bin:/usr/bin"; /* glibc */
|
||||
#endif
|
||||
return ":/bin:/usr/bin";
|
||||
}
|
||||
|
||||
static const char*
|
||||
|
@ -452,7 +445,6 @@ __attribute_noinline__
|
|||
#endif
|
||||
|
||||
/* vfork(2) is deprecated on Solaris */
|
||||
#ifndef __solaris__
|
||||
static pid_t
|
||||
vforkChild(ChildStuff *c) {
|
||||
volatile pid_t resultPid;
|
||||
|
@ -471,7 +463,6 @@ vforkChild(ChildStuff *c) {
|
|||
assert(resultPid != 0); /* childProcess never returns */
|
||||
return resultPid;
|
||||
}
|
||||
#endif
|
||||
|
||||
static pid_t
|
||||
forkChild(ChildStuff *c) {
|
||||
|
@ -583,10 +574,8 @@ static pid_t
|
|||
startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
|
||||
switch (c->mode) {
|
||||
/* vfork(2) is deprecated on Solaris */
|
||||
#ifndef __solaris__
|
||||
case MODE_VFORK:
|
||||
return vforkChild(c);
|
||||
#endif
|
||||
case MODE_FORK:
|
||||
return forkChild(c);
|
||||
case MODE_POSIX_SPAWN:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -35,9 +35,6 @@
|
|||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__solaris__)
|
||||
#include <libscf.h>
|
||||
#endif
|
||||
|
||||
#include "jvm.h"
|
||||
#include "TimeZone_md.h"
|
||||
|
@ -52,11 +49,9 @@ static char *isFileIdentical(char* buf, size_t size, char *pathname);
|
|||
} while((_result == -1) && (errno == EINTR)); \
|
||||
} while(0)
|
||||
|
||||
#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
|
||||
#define fileopen fopen
|
||||
#define filegets fgets
|
||||
#define fileclose fclose
|
||||
#endif
|
||||
|
||||
#if defined(_ALLBSD_SOURCE)
|
||||
#define stat64 stat
|
||||
|
@ -80,7 +75,7 @@ static const char popularZones[][4] = {"UTC", "GMT"};
|
|||
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
|
||||
#if defined(__linux__) || defined(MACOSX)
|
||||
|
||||
/*
|
||||
* Returns a pointer to the zone ID portion of the given zoneinfo file
|
||||
|
@ -164,13 +159,6 @@ findZoneinfoFile(char *buf, size_t size, const char *dir)
|
|||
*/
|
||||
if ((strcmp(dp->d_name, "ROC") == 0)
|
||||
|| (strcmp(dp->d_name, "posixrules") == 0)
|
||||
#if defined(__solaris__)
|
||||
/*
|
||||
* Skip the "src" and "tab" directories on Solaris.
|
||||
*/
|
||||
|| (strcmp(dp->d_name, "src") == 0)
|
||||
|| (strcmp(dp->d_name, "tab") == 0)
|
||||
#endif
|
||||
|| (strcmp(dp->d_name, "localtime") == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -242,8 +230,6 @@ isFileIdentical(char *buf, size_t size, char *pathname)
|
|||
return possibleMatch;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(MACOSX)
|
||||
|
||||
/*
|
||||
* Performs Linux specific mapping and returns a zone ID
|
||||
* if found. Otherwise, NULL is returned.
|
||||
|
@ -353,311 +339,6 @@ getPlatformTimeZoneID()
|
|||
return tz;
|
||||
}
|
||||
|
||||
#elif defined(__solaris__)
|
||||
|
||||
#if !defined(__sparcv9) && !defined(amd64)
|
||||
|
||||
/*
|
||||
* Those file* functions mimic the UNIX stream io functions. This is
|
||||
* because of the limitation of the number of open files on Solaris
|
||||
* (32-bit mode only) due to the System V ABI.
|
||||
*/
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
static struct iobuffer {
|
||||
int magic; /* -1 to distinguish from the real FILE */
|
||||
int fd; /* file descriptor */
|
||||
char *buffer; /* pointer to buffer */
|
||||
char *ptr; /* current read pointer */
|
||||
char *endptr; /* end pointer */
|
||||
};
|
||||
|
||||
static int
|
||||
fileclose(FILE *stream)
|
||||
{
|
||||
struct iobuffer *iop = (struct iobuffer *) stream;
|
||||
|
||||
if (iop->magic != -1) {
|
||||
return fclose(stream);
|
||||
}
|
||||
|
||||
if (iop == NULL) {
|
||||
return 0;
|
||||
}
|
||||
close(iop->fd);
|
||||
free((void *)iop->buffer);
|
||||
free((void *)iop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FILE *
|
||||
fileopen(const char *fname, const char *fmode)
|
||||
{
|
||||
FILE *fp;
|
||||
int fd;
|
||||
struct iobuffer *iop;
|
||||
|
||||
if ((fp = fopen(fname, fmode)) != NULL) {
|
||||
return fp;
|
||||
}
|
||||
|
||||
/*
|
||||
* It assumes read open.
|
||||
*/
|
||||
RESTARTABLE(open(fname, O_RDONLY), fd);
|
||||
if (fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate struct iobuffer and its buffer
|
||||
*/
|
||||
iop = malloc(sizeof(struct iobuffer));
|
||||
if (iop == NULL) {
|
||||
(void) close(fd);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
iop->magic = -1;
|
||||
iop->fd = fd;
|
||||
iop->buffer = malloc(BUFFER_SIZE);
|
||||
if (iop->buffer == NULL) {
|
||||
(void) close(fd);
|
||||
free((void *) iop);
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
iop->ptr = iop->buffer;
|
||||
iop->endptr = iop->buffer;
|
||||
return (FILE *)iop;
|
||||
}
|
||||
|
||||
/*
|
||||
* This implementation assumes that n is large enough and the line
|
||||
* separator is '\n'.
|
||||
*/
|
||||
static char *
|
||||
filegets(char *s, int n, FILE *stream)
|
||||
{
|
||||
struct iobuffer *iop = (struct iobuffer *) stream;
|
||||
char *p;
|
||||
|
||||
if (iop->magic != -1) {
|
||||
return fgets(s, n, stream);
|
||||
}
|
||||
|
||||
p = s;
|
||||
for (;;) {
|
||||
char c;
|
||||
|
||||
if (iop->ptr == iop->endptr) {
|
||||
ssize_t len;
|
||||
|
||||
RESTARTABLE(read(iop->fd, (void *)iop->buffer, BUFFER_SIZE), len);
|
||||
if (len == -1) {
|
||||
return NULL;
|
||||
}
|
||||
if (len == 0) {
|
||||
*p = 0;
|
||||
if (s == p) {
|
||||
return NULL;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
iop->ptr = iop->buffer;
|
||||
iop->endptr = iop->buffer + len;
|
||||
}
|
||||
c = *iop->ptr++;
|
||||
*p++ = c;
|
||||
if ((p - s) == (n - 1)) {
|
||||
*p = 0;
|
||||
return s;
|
||||
}
|
||||
if (c == '\n') {
|
||||
*p = 0;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif /* !defined(__sparcv9) && !defined(amd64) */
|
||||
|
||||
/*
|
||||
* Performs Solaris dependent mapping. Returns a zone ID if
|
||||
* found. Otherwise, NULL is returned. Solaris libc looks up
|
||||
* "/etc/default/init" to get the default TZ value if TZ is not defined
|
||||
* as an environment variable.
|
||||
*/
|
||||
static char *
|
||||
getPlatformTimeZoneID()
|
||||
{
|
||||
char *tz = NULL;
|
||||
FILE *fp;
|
||||
|
||||
/*
|
||||
* Try the TZ entry in /etc/default/init.
|
||||
*/
|
||||
if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) {
|
||||
char line[256];
|
||||
char quote = '\0';
|
||||
|
||||
while (filegets(line, sizeof(line), fp) != NULL) {
|
||||
char *p = line;
|
||||
char *s;
|
||||
char c;
|
||||
|
||||
/* quick check for comment lines */
|
||||
if (*p == '#') {
|
||||
continue;
|
||||
}
|
||||
if (strncmp(p, "TZ=", 3) == 0) {
|
||||
p += 3;
|
||||
SKIP_SPACE(p);
|
||||
c = *p;
|
||||
if (c == '"' || c == '\'') {
|
||||
quote = c;
|
||||
p++;
|
||||
}
|
||||
|
||||
/*
|
||||
* PSARC/2001/383: quoted string support
|
||||
*/
|
||||
for (s = p; (c = *s) != '\0' && c != '\n'; s++) {
|
||||
/* No '\\' is supported here. */
|
||||
if (c == quote) {
|
||||
quote = '\0';
|
||||
break;
|
||||
}
|
||||
if (c == ' ' && quote == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (quote != '\0') {
|
||||
jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n");
|
||||
}
|
||||
*s = '\0';
|
||||
tz = strdup(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
(void) fileclose(fp);
|
||||
}
|
||||
return tz;
|
||||
}
|
||||
|
||||
#define TIMEZONE_FMRI "svc:/system/timezone:default"
|
||||
#define TIMEZONE_PG "timezone"
|
||||
#define LOCALTIME_PROP "localtime"
|
||||
|
||||
static void
|
||||
cleanupScf(scf_handle_t *h,
|
||||
scf_snapshot_t *snap,
|
||||
scf_instance_t *inst,
|
||||
scf_propertygroup_t *pg,
|
||||
scf_property_t *prop,
|
||||
scf_value_t *val,
|
||||
char *buf) {
|
||||
if (buf != NULL) {
|
||||
free(buf);
|
||||
}
|
||||
if (snap != NULL) {
|
||||
scf_snapshot_destroy(snap);
|
||||
}
|
||||
if (val != NULL) {
|
||||
scf_value_destroy(val);
|
||||
}
|
||||
if (prop != NULL) {
|
||||
scf_property_destroy(prop);
|
||||
}
|
||||
if (pg != NULL) {
|
||||
scf_pg_destroy(pg);
|
||||
}
|
||||
if (inst != NULL) {
|
||||
scf_instance_destroy(inst);
|
||||
}
|
||||
if (h != NULL) {
|
||||
scf_handle_destroy(h);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a zone ID of Solaris when the TZ value is "localtime".
|
||||
* First, it tries scf. If scf fails, it looks for the same file as
|
||||
* /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
|
||||
*/
|
||||
static char *
|
||||
getSolarisDefaultZoneID() {
|
||||
char *tz = NULL;
|
||||
struct stat64 statbuf;
|
||||
size_t size;
|
||||
char *buf;
|
||||
int fd;
|
||||
int res;
|
||||
/* scf specific variables */
|
||||
scf_handle_t *h = NULL;
|
||||
scf_snapshot_t *snap = NULL;
|
||||
scf_instance_t *inst = NULL;
|
||||
scf_propertygroup_t *pg = NULL;
|
||||
scf_property_t *prop = NULL;
|
||||
scf_value_t *val = NULL;
|
||||
|
||||
if ((h = scf_handle_create(SCF_VERSION)) != NULL
|
||||
&& scf_handle_bind(h) == 0
|
||||
&& (inst = scf_instance_create(h)) != NULL
|
||||
&& (snap = scf_snapshot_create(h)) != NULL
|
||||
&& (pg = scf_pg_create(h)) != NULL
|
||||
&& (prop = scf_property_create(h)) != NULL
|
||||
&& (val = scf_value_create(h)) != NULL
|
||||
&& scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
|
||||
NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
|
||||
&& scf_instance_get_snapshot(inst, "running", snap) == 0
|
||||
&& scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
|
||||
&& scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
|
||||
&& scf_property_get_value(prop, val) == 0) {
|
||||
ssize_t len;
|
||||
|
||||
/* Gets the length of the zone ID string */
|
||||
len = scf_value_get_astring(val, NULL, 0);
|
||||
if (len != -1) {
|
||||
tz = malloc(++len); /* +1 for a null byte */
|
||||
if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
|
||||
cleanupScf(h, snap, inst, pg, prop, val, NULL);
|
||||
return tz;
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanupScf(h, snap, inst, pg, prop, val, tz);
|
||||
|
||||
RESTARTABLE(stat64(DEFAULT_ZONEINFO_FILE, &statbuf), res);
|
||||
if (res == -1) {
|
||||
return NULL;
|
||||
}
|
||||
size = (size_t) statbuf.st_size;
|
||||
buf = malloc(size);
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
RESTARTABLE(open(DEFAULT_ZONEINFO_FILE, O_RDONLY), fd);
|
||||
if (fd == -1) {
|
||||
free((void *) buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RESTARTABLE(read(fd, buf, size), res);
|
||||
if (res != (ssize_t) size) {
|
||||
(void) close(fd);
|
||||
free((void *) buf);
|
||||
return NULL;
|
||||
}
|
||||
(void) close(fd);
|
||||
tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
|
||||
free((void *) buf);
|
||||
return tz;
|
||||
}
|
||||
|
||||
#endif /* defined(__solaris__) */
|
||||
|
||||
#elif defined(_AIX)
|
||||
|
||||
static char *
|
||||
|
@ -824,15 +505,6 @@ findJavaTZ_md(const char *java_home_dir)
|
|||
free((void *) freetz);
|
||||
}
|
||||
#else
|
||||
#if defined(__solaris__)
|
||||
/* Solaris might use localtime, so handle it here. */
|
||||
if (strcmp(tz, "localtime") == 0) {
|
||||
javatz = getSolarisDefaultZoneID();
|
||||
if (freetz != NULL) {
|
||||
free((void *) freetz);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (freetz == NULL) {
|
||||
/* strdup if we are still working on getenv result. */
|
||||
javatz = strdup(tz);
|
||||
|
@ -890,19 +562,7 @@ getGMTOffsetID()
|
|||
{
|
||||
time_t offset;
|
||||
char sign, buf[32];
|
||||
#if defined(__solaris__)
|
||||
struct tm localtm;
|
||||
time_t currenttime;
|
||||
|
||||
currenttime = time(NULL);
|
||||
if (localtime_r(¤ttime, &localtm) == NULL) {
|
||||
return strdup("GMT");
|
||||
}
|
||||
|
||||
offset = localtm.tm_isdst ? altzone : timezone;
|
||||
#else
|
||||
offset = timezone;
|
||||
#endif
|
||||
|
||||
if (offset == 0) {
|
||||
return strdup("GMT");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -63,10 +63,6 @@
|
|||
#define stat stat64
|
||||
#endif
|
||||
|
||||
#if defined(__solaris__) && !defined(NAME_MAX)
|
||||
#define NAME_MAX MAXNAMLEN
|
||||
#endif
|
||||
|
||||
#if defined(_ALLBSD_SOURCE)
|
||||
#ifndef MACOSX
|
||||
#define statvfs64 statvfs
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __solaris__
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -313,27 +313,6 @@ static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_s
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef __solaris__
|
||||
if (strcmp(p,"eucJP") == 0) {
|
||||
/* For Solaris use customized vendor defined character
|
||||
* customized EUC-JP converter
|
||||
*/
|
||||
*std_encoding = "eucJP-open";
|
||||
} else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
|
||||
/*
|
||||
* Remap the encoding string to Big5_Solaris which augments
|
||||
* the default converter for Solaris Big5 locales to include
|
||||
* seven additional ideographic characters beyond those included
|
||||
* in the Java "Big5" converter.
|
||||
*/
|
||||
*std_encoding = "Big5_Solaris";
|
||||
} else if (strcmp(p, "Big5-HKSCS") == 0) {
|
||||
/*
|
||||
* Solaris uses HKSCS2001
|
||||
*/
|
||||
*std_encoding = "Big5-HKSCS-2001";
|
||||
}
|
||||
#endif
|
||||
#ifdef MACOSX
|
||||
/*
|
||||
* For the case on MacOS X where encoding is set to US-ASCII, but we
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,11 +27,7 @@
|
|||
#define JDK_UTIL_MD_H
|
||||
|
||||
// checking for nanness
|
||||
#ifdef __solaris__
|
||||
#include <ieeefp.h>
|
||||
#define ISNANF(f) isnanf(f)
|
||||
#define ISNAND(d) isnand(d)
|
||||
#elif defined(MACOSX)
|
||||
#if defined(MACOSX)
|
||||
#include <math.h>
|
||||
#define ISNANF(f) isnan(f)
|
||||
#define ISNAND(d) isnan(d)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -23,8 +23,8 @@
|
|||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef _SOLARIS_JLONG_MD_H_
|
||||
#define _SOLARIS_JLONG_MD_H_
|
||||
#ifndef _UNIX_JLONG_MD_H_
|
||||
#define _UNIX_JLONG_MD_H_
|
||||
|
||||
/* Make sure ptrdiff_t is defined */
|
||||
#include <stddef.h>
|
||||
|
@ -97,4 +97,4 @@
|
|||
#define size_to_jlong(a) ((jlong)(a))
|
||||
#define long_to_jlong(a) ((jlong)(a))
|
||||
|
||||
#endif /* !_SOLARIS_JLONG_MD_H_ */
|
||||
#endif /* !_UNIX_JLONG_MD_H_ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,7 +27,7 @@
|
|||
#define JAVA_MD_H
|
||||
|
||||
/*
|
||||
* This file contains common defines and includes for Solaris, Linux and MacOSX.
|
||||
* This file contains common defines and includes for unix.
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -51,12 +51,6 @@
|
|||
#define SETENV_REQUIRED
|
||||
#endif
|
||||
|
||||
#ifdef __solaris__
|
||||
# include <sys/systeminfo.h>
|
||||
# include <sys/elf.h>
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flowchart of launcher execs and options processing on unix
|
||||
*
|
||||
|
@ -242,9 +236,6 @@ RequiresSetenv(const char *jvmpath) {
|
|||
#endif
|
||||
|
||||
llp = getenv("LD_LIBRARY_PATH");
|
||||
#ifdef __solaris__
|
||||
dmllp = getenv("LD_LIBRARY_PATH_64");
|
||||
#endif /* __solaris__ */
|
||||
/* no environment variable is a good environment variable */
|
||||
if (llp == NULL && dmllp == NULL) {
|
||||
return JNI_FALSE;
|
||||
|
@ -304,9 +295,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
|||
|
||||
#ifdef SETENV_REQUIRED
|
||||
jboolean mustsetenv = JNI_FALSE;
|
||||
#ifdef __solaris__
|
||||
char *llp64 = NULL; /* existing LD_LIBRARY_PATH_64 setting */
|
||||
#endif // __solaris__
|
||||
char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */
|
||||
char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */
|
||||
char* newpath = NULL; /* path on new LD_LIBRARY_PATH */
|
||||
|
@ -371,12 +359,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
|||
* any.
|
||||
*/
|
||||
|
||||
#ifdef __solaris__
|
||||
llp64 = getenv("LD_LIBRARY_PATH_64");
|
||||
runpath = (llp64 == NULL) ? getenv(LD_LIBRARY_PATH) : llp64;
|
||||
#else
|
||||
runpath = getenv(LD_LIBRARY_PATH);
|
||||
#endif /* __solaris__ */
|
||||
|
||||
/* runpath contains current effective LD_LIBRARY_PATH setting */
|
||||
{ /* New scope to declare local variable */
|
||||
|
@ -449,14 +432,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
|||
* once at startup, so we have to re-exec the current executable
|
||||
* to get the changed environment variable to have an effect.
|
||||
*/
|
||||
#ifdef __solaris__
|
||||
/*
|
||||
* new LD_LIBRARY_PATH took over for LD_LIBRARY_PATH_64
|
||||
*/
|
||||
if (llp64 != NULL) {
|
||||
UnsetEnv("LD_LIBRARY_PATH_64");
|
||||
}
|
||||
#endif // __solaris__
|
||||
|
||||
newenvp = environ;
|
||||
}
|
||||
|
@ -556,51 +531,6 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
|
|||
|
||||
libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
|
||||
if (libjvm == NULL) {
|
||||
#if defined(__solaris__) && defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */
|
||||
FILE * fp;
|
||||
Elf32_Ehdr elf_head;
|
||||
int count;
|
||||
int location;
|
||||
|
||||
fp = fopen(jvmpath, "r");
|
||||
if (fp == NULL) {
|
||||
JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/* read in elf header */
|
||||
count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp);
|
||||
fclose(fp);
|
||||
if (count < 1) {
|
||||
JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for running a server vm (compiled with -xarch=v8plus)
|
||||
* on a stock v8 processor. In this case, the machine type in
|
||||
* the elf header would not be included the architecture list
|
||||
* provided by the isalist command, which is turn is gotten from
|
||||
* sysinfo. This case cannot occur on 64-bit hardware and thus
|
||||
* does not have to be checked for in binaries with an LP64 data
|
||||
* model.
|
||||
*/
|
||||
if (elf_head.e_machine == EM_SPARC32PLUS) {
|
||||
char buf[257]; /* recommended buffer size from sysinfo man
|
||||
page */
|
||||
long length;
|
||||
char* location;
|
||||
|
||||
length = sysinfo(SI_ISALIST, buf, 257);
|
||||
if (length > 0) {
|
||||
location = JLI_StrStr(buf, "sparcv8plus ");
|
||||
if (location == NULL) {
|
||||
JLI_ReportErrorMessage(JVM_ERROR3);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
|
||||
JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
|
||||
return JNI_FALSE;
|
||||
|
@ -647,28 +577,7 @@ const char*
|
|||
SetExecname(char **argv)
|
||||
{
|
||||
char* exec_path = NULL;
|
||||
#if defined(__solaris__)
|
||||
{
|
||||
Dl_info dlinfo;
|
||||
int (*fptr)();
|
||||
|
||||
fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
|
||||
if (fptr == NULL) {
|
||||
JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (dladdr((void*)fptr, &dlinfo)) {
|
||||
char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
|
||||
if (resolved != NULL) {
|
||||
exec_path = realpath(dlinfo.dli_fname, resolved);
|
||||
if (exec_path == NULL) {
|
||||
JLI_MemFree(resolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
#if defined(__linux__)
|
||||
{
|
||||
const char* self = "/proc/self/exe";
|
||||
char buf[PATH_MAX+1];
|
||||
|
@ -678,7 +587,7 @@ SetExecname(char **argv)
|
|||
exec_path = JLI_StringDup(buf);
|
||||
}
|
||||
}
|
||||
#else /* !__solaris__ && !__linux__ */
|
||||
#else /* !__linux__ */
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
@ -740,7 +649,6 @@ static void* ThreadJavaMain(void* args) {
|
|||
int
|
||||
CallJavaMainInNewThread(jlong stack_size, void* args) {
|
||||
int rslt;
|
||||
#ifndef __solaris__
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
|
@ -766,18 +674,6 @@ CallJavaMainInNewThread(jlong stack_size, void* args) {
|
|||
}
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
#else /* __solaris__ */
|
||||
thread_t tid;
|
||||
long flags = 0;
|
||||
if (thr_create(NULL, stack_size, ThreadJavaMain, args, flags, &tid) == 0) {
|
||||
void* tmp;
|
||||
thr_join(tid, NULL, &tmp);
|
||||
rslt = (int)(intptr_t)tmp;
|
||||
} else {
|
||||
/* See above. Continue in current thread if thr_create() failed */
|
||||
rslt = JavaMain(args);
|
||||
}
|
||||
#endif /* !__solaris__ */
|
||||
return rslt;
|
||||
}
|
||||
|
||||
|
@ -814,8 +710,6 @@ ProcessPlatformOption(const char *arg)
|
|||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#ifndef __solaris__
|
||||
|
||||
/*
|
||||
* Provide a CounterGet() implementation based on gettimeofday() which
|
||||
* is universally available, even though it may not be 'high resolution'
|
||||
|
@ -832,5 +726,3 @@ uint64_t CounterGet() {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !__solaris__
|
||||
|
|
|
@ -27,16 +27,8 @@
|
|||
#define JAVA_MD_SOLINUX_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#ifdef __solaris__
|
||||
/*
|
||||
* Support for doing cheap, accurate interval timing.
|
||||
*/
|
||||
#define CounterGet() (gethrtime()/1000)
|
||||
#define Counter2Micros(counts) (counts)
|
||||
#else /* ! __solaris__ */
|
||||
uint64_t CounterGet(void);
|
||||
#define Counter2Micros(counts) (counts)
|
||||
#endif /* __solaris__ */
|
||||
|
||||
/* pointer to environment */
|
||||
extern char **environ;
|
||||
|
@ -45,17 +37,9 @@ extern char **environ;
|
|||
* A collection of useful strings. One should think of these as #define
|
||||
* entries, but actual strings can be more efficient (with many compilers).
|
||||
*/
|
||||
#ifdef __solaris__
|
||||
static const char *user_dir = "/jdk";
|
||||
#else /* !__solaris__, i.e. Linux, AIX,.. */
|
||||
static const char *user_dir = "/java";
|
||||
#endif
|
||||
static const char *user_dir = "/java";
|
||||
|
||||
#include <dlfcn.h>
|
||||
#ifdef __solaris__
|
||||
#include <thread.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#endif /* JAVA_MD_SOLINUX_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
|
@ -33,16 +33,6 @@
|
|||
|
||||
#include "jni.h"
|
||||
|
||||
#ifdef SOLARIS
|
||||
/* Our redeclarations of the system functions must not have a less
|
||||
* restrictive linker scoping, so we have to declare them as JNIEXPORT
|
||||
* before including signal.h */
|
||||
#include "sys/signal.h"
|
||||
JNIEXPORT void (*signal(int sig, void (*disp)(int)))(int);
|
||||
JNIEXPORT void (*sigset(int sig, void (*disp)(int)))(int);
|
||||
JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
@ -59,16 +49,9 @@ JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *
|
|||
#define false 0
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
#define MAX_SIGNALS (SIGRTMAX+1)
|
||||
|
||||
/* On solaris, MAX_SIGNALS is a macro, not a constant, so we must allocate sact dynamically. */
|
||||
static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
|
||||
#else
|
||||
#define MAX_SIGNALS NSIG
|
||||
|
||||
static struct sigaction sact[MAX_SIGNALS]; /* saved signal handlers */
|
||||
#endif
|
||||
|
||||
static sigset_t jvmsigs; /* Signals used by jvm. */
|
||||
|
||||
|
@ -93,20 +76,6 @@ static bool jvm_signal_installing = false;
|
|||
static bool jvm_signal_installed = false;
|
||||
|
||||
|
||||
/* assume called within signal_lock */
|
||||
static void allocate_sact() {
|
||||
#ifdef SOLARIS
|
||||
if (sact == NULL) {
|
||||
sact = (struct sigaction *)malloc((MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
|
||||
if (sact == NULL) {
|
||||
printf("%s\n", "libjsig.so unable to allocate memory");
|
||||
exit(0);
|
||||
}
|
||||
memset(sact, 0, (MAX_SIGNALS) * (size_t)sizeof(struct sigaction));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void signal_lock() {
|
||||
pthread_mutex_lock(&mutex);
|
||||
/* When the jvm is installing its set of signal handlers, threads
|
||||
|
@ -162,18 +131,7 @@ static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
|
|||
sact[sig].sa_handler = disp;
|
||||
sigemptyset(&set);
|
||||
sact[sig].sa_mask = set;
|
||||
if (!is_sigset) {
|
||||
#ifdef SOLARIS
|
||||
sact[sig].sa_flags = SA_NODEFER;
|
||||
if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
|
||||
sact[sig].sa_flags |= SA_RESETHAND;
|
||||
}
|
||||
#else
|
||||
sact[sig].sa_flags = 0;
|
||||
#endif
|
||||
} else {
|
||||
sact[sig].sa_flags = 0;
|
||||
}
|
||||
sact[sig].sa_flags = 0;
|
||||
}
|
||||
|
||||
static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
|
||||
|
@ -182,7 +140,6 @@ static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
|
|||
bool sigblocked;
|
||||
|
||||
signal_lock();
|
||||
allocate_sact();
|
||||
|
||||
sigused = sigismember(&jvmsigs, sig);
|
||||
if (jvm_signal_installed && sigused) {
|
||||
|
@ -194,13 +151,6 @@ static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
|
|||
oldhandler = sact[sig].sa_handler;
|
||||
save_signal_handler(sig, disp, is_sigset);
|
||||
|
||||
#ifdef SOLARIS
|
||||
if (is_sigset && sigblocked) {
|
||||
/* We won't honor the SIG_HOLD request to change the signal mask */
|
||||
oldhandler = SIG_HOLD;
|
||||
}
|
||||
#endif
|
||||
|
||||
signal_unlock();
|
||||
return oldhandler;
|
||||
} else if (jvm_signal_installing) {
|
||||
|
@ -278,7 +228,6 @@ JNIEXPORT int sigaction(int sig, const struct sigaction *act, struct sigaction *
|
|||
|
||||
signal_lock();
|
||||
|
||||
allocate_sact();
|
||||
sigused = sigismember(&jvmsigs, sig);
|
||||
if (jvm_signal_installed && sigused) {
|
||||
/* jvm has installed its signal handler for this signal. */
|
||||
|
@ -334,7 +283,6 @@ JNIEXPORT void JVM_end_signal_setting() {
|
|||
}
|
||||
|
||||
JNIEXPORT struct sigaction *JVM_get_signal_action(int sig) {
|
||||
allocate_sact();
|
||||
/* Does race condition make sense here? */
|
||||
if (sigismember(&jvmsigs, sig)) {
|
||||
return &sact[sig];
|
||||
|
|
|
@ -64,27 +64,8 @@ Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
|||
if (gethostname(hostname, sizeof(hostname)) != 0) {
|
||||
strcpy(hostname, "localhost");
|
||||
} else {
|
||||
#if defined(__solaris__)
|
||||
// try to resolve hostname via nameservice
|
||||
// if it is known but getnameinfo fails, hostname will still be the
|
||||
// value from gethostname
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
// make sure string is null-terminated
|
||||
hostname[NI_MAXHOST] = '\0';
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
|
||||
getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
|
||||
NULL, 0, NI_NAMEREQD);
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
#else
|
||||
// make sure string is null-terminated
|
||||
hostname[NI_MAXHOST] = '\0';
|
||||
#endif
|
||||
}
|
||||
return (*env)->NewStringUTF(env, hostname);
|
||||
}
|
||||
|
|
|
@ -65,27 +65,8 @@ Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
|||
if (gethostname(hostname, sizeof(hostname)) != 0) {
|
||||
strcpy(hostname, "localhost");
|
||||
} else {
|
||||
#if defined(__solaris__)
|
||||
// try to resolve hostname via nameservice
|
||||
// if it is known but getnameinfo fails, hostname will still be the
|
||||
// value from gethostname
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
// make sure string is null-terminated
|
||||
hostname[NI_MAXHOST] = '\0';
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
if (getaddrinfo(hostname, NULL, &hints, &res) == 0) {
|
||||
getnameinfo(res->ai_addr, res->ai_addrlen, hostname, sizeof(hostname),
|
||||
NULL, 0, NI_NAMEREQD);
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
#else
|
||||
// make sure string is null-terminated
|
||||
hostname[NI_MAXHOST] = '\0';
|
||||
#endif
|
||||
}
|
||||
return (*env)->NewStringUTF(env, hostname);
|
||||
}
|
||||
|
|
|
@ -37,12 +37,6 @@
|
|||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#if defined(__solaris__)
|
||||
#include <stropts.h>
|
||||
#include <sys/dlpi.h>
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#if defined(_ALLBSD_SOURCE)
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if_dl.h>
|
||||
|
@ -55,11 +49,6 @@
|
|||
|
||||
#if defined(__linux__)
|
||||
#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
|
||||
#elif defined(__solaris__)
|
||||
#ifndef SIOCGLIFHWADDR
|
||||
#define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
|
||||
#endif
|
||||
#define DEV_PREFIX "/dev/"
|
||||
#endif
|
||||
|
||||
#ifdef LIFNAMSIZ
|
||||
|
@ -147,11 +136,6 @@ static int getMacAddress(JNIEnv *env, const char *ifname,
|
|||
const struct in_addr *addr, unsigned char *buf);
|
||||
static int getMTU(JNIEnv *env, int sock, const char *ifname);
|
||||
|
||||
#if defined(__solaris__)
|
||||
static int getMacFromDevice(JNIEnv *env, const char *ifname,
|
||||
unsigned char *retbuf);
|
||||
#endif
|
||||
|
||||
/******************* Java entry points *****************************/
|
||||
|
||||
/*
|
||||
|
@ -1672,372 +1656,6 @@ static int getFlags(int sock, const char *ifname, int *flags) {
|
|||
|
||||
#endif /* _AIX */
|
||||
|
||||
/** Solaris **/
|
||||
#if defined(__solaris__)
|
||||
|
||||
/*
|
||||
* Opens a socket for further ioctl calls. Tries AF_INET socket first and
|
||||
* if it fails return AF_INET6 socket.
|
||||
*/
|
||||
static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
|
||||
int sock, alreadyV6 = 0;
|
||||
struct lifreq if2;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
if (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
|
||||
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
alreadyV6 = 1;
|
||||
} else { // errno is not NOSUPPORT
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Solaris requires that we have an IPv6 socket to query an interface
|
||||
// without an IPv4 address - check it here. POSIX 1 require the kernel to
|
||||
// return ENOTTY if the call is inappropriate for a device e.g. the NETMASK
|
||||
// for a device having IPv6 only address but not all devices follow the
|
||||
// standard so fall back on any error. It's not an ecologically friendly
|
||||
// gesture but more reliable.
|
||||
if (!alreadyV6) {
|
||||
memset((char *)&if2, 0, sizeof(if2));
|
||||
strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
|
||||
if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
|
||||
close(sock);
|
||||
if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerates and returns all IPv4 interfaces on Solaris.
|
||||
*/
|
||||
static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
|
||||
struct lifconf ifc;
|
||||
struct lifreq *ifreqP;
|
||||
struct lifnum numifs;
|
||||
char *buf = NULL;
|
||||
unsigned i;
|
||||
|
||||
// call SIOCGLIFNUM to get the interface count
|
||||
numifs.lifn_family = AF_INET;
|
||||
numifs.lifn_flags = 0;
|
||||
if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
|
||||
return ifs;
|
||||
}
|
||||
|
||||
// call SIOCGLIFCONF to enumerate the interfaces
|
||||
ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
|
||||
CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
|
||||
ifc.lifc_buf = buf;
|
||||
ifc.lifc_family = AF_INET;
|
||||
ifc.lifc_flags = 0;
|
||||
if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
|
||||
// iterate through each interface
|
||||
ifreqP = ifc.lifc_req;
|
||||
for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
|
||||
struct sockaddr addr, *broadaddrP = NULL;
|
||||
|
||||
// ignore non IPv4 addresses
|
||||
if (ifreqP->lifr_addr.ss_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// save socket address
|
||||
memcpy(&addr, &(ifreqP->lifr_addr), sizeof(struct sockaddr));
|
||||
|
||||
// determine broadcast address, if applicable
|
||||
if ((ioctl(sock, SIOCGLIFFLAGS, ifreqP) == 0) &&
|
||||
ifreqP->lifr_flags & IFF_BROADCAST) {
|
||||
|
||||
// restore socket address to ifreqP
|
||||
memcpy(&(ifreqP->lifr_addr), &addr, sizeof(struct sockaddr));
|
||||
|
||||
// query broadcast address and set pointer to it
|
||||
if (ioctl(sock, SIOCGLIFBRDADDR, ifreqP) == 0) {
|
||||
broadaddrP = (struct sockaddr *)&(ifreqP->lifr_broadaddr);
|
||||
}
|
||||
}
|
||||
|
||||
// add to the list
|
||||
ifs = addif(env, sock, ifreqP->lifr_name, ifs,
|
||||
&addr, broadaddrP, AF_INET, (short)ifreqP->lifr_addrlen);
|
||||
|
||||
// if an exception occurred we return immediately
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
}
|
||||
|
||||
// free buffer
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerates and returns all IPv6 interfaces on Solaris.
|
||||
*/
|
||||
static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
|
||||
struct lifconf ifc;
|
||||
struct lifreq *ifreqP;
|
||||
struct lifnum numifs;
|
||||
char *buf = NULL;
|
||||
unsigned i;
|
||||
|
||||
// call SIOCGLIFNUM to get the interface count
|
||||
numifs.lifn_family = AF_INET6;
|
||||
numifs.lifn_flags = 0;
|
||||
if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFNUM) failed");
|
||||
return ifs;
|
||||
}
|
||||
|
||||
// call SIOCGLIFCONF to enumerate the interfaces
|
||||
ifc.lifc_len = numifs.lifn_count * sizeof(struct lifreq);
|
||||
CHECKED_MALLOC3(buf, char *, ifc.lifc_len);
|
||||
ifc.lifc_buf = buf;
|
||||
ifc.lifc_family = AF_INET6;
|
||||
ifc.lifc_flags = 0;
|
||||
if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFCONF) failed");
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
|
||||
// iterate through each interface
|
||||
ifreqP = ifc.lifc_req;
|
||||
for (i = 0; i < numifs.lifn_count; i++, ifreqP++) {
|
||||
|
||||
// ignore non IPv6 addresses
|
||||
if (ifreqP->lifr_addr.ss_family != AF_INET6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// set scope ID to interface index
|
||||
((struct sockaddr_in6 *)&(ifreqP->lifr_addr))->sin6_scope_id =
|
||||
getIndex(sock, ifreqP->lifr_name);
|
||||
|
||||
// add to the list
|
||||
ifs = addif(env, sock, ifreqP->lifr_name, ifs,
|
||||
(struct sockaddr *)&(ifreqP->lifr_addr),
|
||||
NULL, AF_INET6, (short)ifreqP->lifr_addrlen);
|
||||
|
||||
// if an exception occurred we return immediately
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
}
|
||||
|
||||
// free buffer
|
||||
free(buf);
|
||||
return ifs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get the interface index.
|
||||
* (Not supported on Solaris 2.6 or 7)
|
||||
*/
|
||||
static int getIndex(int sock, const char *name) {
|
||||
struct lifreq if2;
|
||||
memset((char *)&if2, 0, sizeof(if2));
|
||||
strncpy(if2.lifr_name, name, sizeof(if2.lifr_name) - 1);
|
||||
|
||||
if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return if2.lifr_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Solaris specific DLPI code to get hardware address from a device.
|
||||
* Unfortunately, at least up to Solaris X, you have to have special
|
||||
* privileges (i.e. be root).
|
||||
*/
|
||||
static int getMacFromDevice
|
||||
(JNIEnv *env, const char *ifname, unsigned char *retbuf)
|
||||
{
|
||||
char style1dev[MAXPATHLEN];
|
||||
int fd;
|
||||
dl_phys_addr_req_t dlpareq;
|
||||
dl_phys_addr_ack_t *dlpaack;
|
||||
dl_error_ack_t *dlerack;
|
||||
struct strbuf msg;
|
||||
char buf[128];
|
||||
int flags = 0;
|
||||
|
||||
// Device is in /dev. e.g.: /dev/bge0
|
||||
strcpy(style1dev, DEV_PREFIX);
|
||||
strcat(style1dev, ifname);
|
||||
if ((fd = open(style1dev, O_RDWR)) < 0) {
|
||||
// Can't open it. We probably are missing the privilege.
|
||||
// We'll have to try something else
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
|
||||
dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
|
||||
|
||||
msg.buf = (char *)&dlpareq;
|
||||
msg.len = DL_PHYS_ADDR_REQ_SIZE;
|
||||
|
||||
if (putmsg(fd, &msg, NULL, 0) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "putmsg() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dlpaack = (dl_phys_addr_ack_t *)buf;
|
||||
|
||||
msg.buf = (char *)buf;
|
||||
msg.len = 0;
|
||||
msg.maxlen = sizeof (buf);
|
||||
if (getmsg(fd, &msg, NULL, &flags) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "getmsg() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dlpaack->dl_primitive == DL_ERROR_ACK) {
|
||||
dlerack = (dl_error_ack_t *)buf;
|
||||
if (dlerack->dl_error_primitive != DL_PHYS_ADDR_REQ) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Couldn't obtain physical address\n");
|
||||
return -1;
|
||||
}
|
||||
if (dlerack->dl_errno == DL_UNSUPPORTED) {
|
||||
// fallback to lookup in the ARP table
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Couldn't obtain phys addr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
|
||||
return dlpaack->dl_addr_length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the Hardware address (usually MAC address) for the named interface.
|
||||
* On return puts the data in buf, and returns the length, in byte, of the
|
||||
* MAC address. Returns -1 if there is no hardware address on that interface.
|
||||
*/
|
||||
static int getMacAddress
|
||||
(JNIEnv *env, const char *ifname, const struct in_addr *addr,
|
||||
unsigned char *buf)
|
||||
{
|
||||
struct lifreq if2;
|
||||
int len, i, sock;
|
||||
|
||||
if ((sock = openSocketWithFallback(env, ifname)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
|
||||
// try the old way.
|
||||
memset((char *)&if2, 0, sizeof(if2));
|
||||
strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
|
||||
|
||||
if (ioctl(sock, SIOCGLIFHWADDR, &if2) != -1) {
|
||||
struct sockaddr_dl *sp;
|
||||
sp = (struct sockaddr_dl *)&if2.lifr_addr;
|
||||
memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
|
||||
close(sock);
|
||||
return sp->sdl_alen;
|
||||
}
|
||||
|
||||
// On Solaris we have to use DLPI, but it will only work if we have
|
||||
// privileged access (i.e. root). If that fails, we try a lookup
|
||||
// in the ARP table, which requires an IPv4 address.
|
||||
if (((len = getMacFromDevice(env, ifname, buf)) == 0) && (addr != NULL)) {
|
||||
struct arpreq arpreq;
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr_in ipAddr;
|
||||
|
||||
len = 6; //???
|
||||
|
||||
sin = (struct sockaddr_in *)&arpreq.arp_pa;
|
||||
memset((char *)&arpreq, 0, sizeof(struct arpreq));
|
||||
ipAddr.sin_port = 0;
|
||||
ipAddr.sin_family = AF_INET;
|
||||
memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
|
||||
memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
|
||||
arpreq.arp_flags= ATF_PUBL;
|
||||
|
||||
if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(buf, &arpreq.arp_ha.sa_data[0], len);
|
||||
}
|
||||
close(sock);
|
||||
|
||||
// all bytes to 0 means no hardware address
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] != 0)
|
||||
return len;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int getMTU(JNIEnv *env, int sock, const char *ifname) {
|
||||
struct lifreq if2;
|
||||
memset((char *)&if2, 0, sizeof(if2));
|
||||
strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
|
||||
|
||||
if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl(SIOCGLIFMTU) failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return if2.lifr_mtu;
|
||||
}
|
||||
|
||||
static int getFlags(int sock, const char *ifname, int *flags) {
|
||||
struct lifreq if2;
|
||||
memset((char *)&if2, 0, sizeof(if2));
|
||||
strncpy(if2.lifr_name, ifname, sizeof(if2.lifr_name) - 1);
|
||||
|
||||
if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*flags = if2.lifr_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* __solaris__ */
|
||||
|
||||
/** BSD **/
|
||||
#if defined(_ALLBSD_SOURCE)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,10 +27,6 @@
|
|||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(__solaris__)
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_PlainDatagramSocketImpl.h"
|
||||
|
@ -52,12 +48,6 @@
|
|||
#endif
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef __solaris__
|
||||
#ifndef BSD_COMP
|
||||
#define BSD_COMP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef IPTOS_TOS_MASK
|
||||
#define IPTOS_TOS_MASK 0x1e
|
||||
#endif
|
||||
|
@ -498,14 +488,6 @@ Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
|
|||
n = NET_RecvFrom(fd, buf, 1, MSG_PEEK, &rmtaddr.sa, &slen);
|
||||
|
||||
if (n == -1) {
|
||||
|
||||
#ifdef __solaris__
|
||||
if (errno == ECONNREFUSED) {
|
||||
int orig_errno = errno;
|
||||
recv(fd, buf, 1, 0);
|
||||
errno = orig_errno;
|
||||
}
|
||||
#endif
|
||||
if (errno == ECONNREFUSED) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
|
||||
"ICMP Port Unreachable");
|
||||
|
@ -632,14 +614,6 @@ Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this,
|
|||
n = packetBufferLen;
|
||||
}
|
||||
if (n == -1) {
|
||||
|
||||
#ifdef __solaris__
|
||||
if (errno == ECONNREFUSED) {
|
||||
int orig_errno = errno;
|
||||
(void) recv(fd, fullPacket, 1, 0);
|
||||
errno = orig_errno;
|
||||
}
|
||||
#endif
|
||||
(*env)->SetIntField(env, packet, dp_offsetID, 0);
|
||||
(*env)->SetIntField(env, packet, dp_lengthID, 0);
|
||||
if (errno == ECONNREFUSED) {
|
||||
|
@ -1853,10 +1827,9 @@ Java_java_net_PlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) {
|
|||
* we must use the IPv4 socket options. This is because the IPv6 socket options
|
||||
* don't support IPv4-mapped addresses. This is true as per 2.2.19 and 2.4.7
|
||||
* kernel releases. In the future it's possible that IP_ADD_MEMBERSHIP
|
||||
* will be updated to return ENOPROTOOPT if uses with an IPv6 socket (Solaris
|
||||
* already does this). Thus to cater for this we first try with the IPv4
|
||||
* socket options and if they fail we use the IPv6 socket options. This
|
||||
* seems a reasonable failsafe solution.
|
||||
* will be updated to return ENOPROTOOPT if uses with an IPv6 socket. Thus to
|
||||
* cater for this we first try with the IPv4 socket options and if they fail we
|
||||
* use the IPv6 socket options. This seems a reasonable failsafe solution.
|
||||
*/
|
||||
static void mcast_join_leave(JNIEnv *env, jobject this,
|
||||
jobject iaObj, jobject niObj,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -266,45 +266,6 @@ Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
|
|||
|
||||
if (timeout <= 0) {
|
||||
connect_rv = NET_Connect(fd, &sa.sa, len);
|
||||
#ifdef __solaris__
|
||||
if (connect_rv == -1 && errno == EINPROGRESS ) {
|
||||
|
||||
/* This can happen if a blocking connect is interrupted by a signal.
|
||||
* See 6343810.
|
||||
*/
|
||||
while (1) {
|
||||
struct pollfd pfd;
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
connect_rv = NET_Poll(&pfd, 1, -1);
|
||||
|
||||
if (connect_rv == -1) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connect_rv > 0) {
|
||||
socklen_t optlen;
|
||||
/* has connection been established */
|
||||
optlen = sizeof(connect_rv);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
|
||||
(void*)&connect_rv, &optlen) <0) {
|
||||
connect_rv = errno;
|
||||
}
|
||||
|
||||
if (connect_rv != 0) {
|
||||
/* restore errno */
|
||||
errno = connect_rv;
|
||||
connect_rv = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* A timeout was specified. We put the socket into non-blocking
|
||||
|
@ -893,16 +854,16 @@ Java_java_net_PlainSocketImpl_socketSetOption0
|
|||
}
|
||||
|
||||
if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
|
||||
#if defined(__solaris__) || defined(_AIX)
|
||||
#if defined(_AIX)
|
||||
if (errno == EINVAL) {
|
||||
// On Solaris setsockopt will set errno to EINVAL if the socket
|
||||
// On AIX setsockopt will set errno to EINVAL if the socket
|
||||
// is closed. The default error message is then confusing
|
||||
char fullMsg[128];
|
||||
jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
|
||||
return;
|
||||
}
|
||||
#endif /* __solaris__ */
|
||||
#endif /* _AIX */
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -28,10 +28,6 @@
|
|||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __solaris__
|
||||
#include <sys/systeminfo.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "jni.h"
|
||||
|
@ -41,30 +37,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_net_dns_ResolverConfigurationImpl
|
||||
* Method: localDomain0
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_sun_net_dns_ResolverConfigurationImpl_localDomain0(JNIEnv *env, jclass cls)
|
||||
{
|
||||
/*
|
||||
* On Solaris the LOCALDOMAIN environment variable has absolute
|
||||
* priority.
|
||||
*/
|
||||
#ifdef __solaris__
|
||||
{
|
||||
char *cp = getenv("LOCALDOMAIN");
|
||||
if (cp != NULL) {
|
||||
jstring s = (*env)->NewStringUTF(env, cp);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return (jstring)NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_net_dns_ResolverConfigurationImpl
|
||||
* Method: loadConfig0
|
||||
|
@ -76,36 +48,10 @@ Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0(JNIEnv *env, jclass c
|
|||
char buf[MAXDNAME];
|
||||
|
||||
/*
|
||||
* On Solaris if domain or search directives aren't specified
|
||||
* in /etc/resolv.conf then sysinfo or gethostname is used to
|
||||
* determine the domain name.
|
||||
*
|
||||
* On Linux if domain or search directives aren't specified
|
||||
* If domain or search directives aren't specified
|
||||
* then gethostname is used.
|
||||
*/
|
||||
|
||||
#ifdef __solaris__
|
||||
{
|
||||
int ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf));
|
||||
|
||||
if ((ret > 0) && (ret<sizeof(buf))) {
|
||||
char *cp;
|
||||
jstring s;
|
||||
|
||||
if (buf[0] == '+') {
|
||||
buf[0] = '.';
|
||||
}
|
||||
cp = strchr(buf, '.');
|
||||
if (cp == NULL) {
|
||||
s = (*env)->NewStringUTF(env, buf);
|
||||
} else {
|
||||
s = (*env)->NewStringUTF(env, cp+1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gethostname(buf, sizeof(buf)) == 0) {
|
||||
char *cp;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -27,11 +27,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(__solaris__)
|
||||
#if !defined(PROTO_SDP)
|
||||
#define PROTO_SDP 257
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#if defined(__linux__)
|
||||
#if !defined(AF_INET_SDP)
|
||||
#define AF_INET_SDP 27
|
||||
#endif
|
||||
|
@ -55,10 +51,7 @@ static int create(JNIEnv* env)
|
|||
{
|
||||
int s;
|
||||
|
||||
#if defined(__solaris__)
|
||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||
s = socket(domain, SOCK_STREAM, PROTO_SDP);
|
||||
#elif defined(__linux__)
|
||||
#if defined(__linux__)
|
||||
/**
|
||||
* IPv6 not supported by SDP on Linux
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -37,14 +37,6 @@
|
|||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#if defined(__solaris__)
|
||||
#include <inet/nd.h>
|
||||
#include <limits.h>
|
||||
#include <stropts.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/sockio.h>
|
||||
#endif
|
||||
|
||||
#if defined(MACOSX)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
@ -59,20 +51,6 @@
|
|||
#define IPV6_FLOWINFO_SEND 33
|
||||
#endif
|
||||
|
||||
#if defined(__solaris__) && !defined(MAXINT)
|
||||
#define MAXINT INT_MAX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* EXCLBIND socket options only on Solaris
|
||||
*/
|
||||
#if defined(__solaris__) && !defined(TCP_EXCLBIND)
|
||||
#define TCP_EXCLBIND 0x21
|
||||
#endif
|
||||
#if defined(__solaris__) && !defined(UDP_EXCLBIND)
|
||||
#define UDP_EXCLBIND 0x0101
|
||||
#endif
|
||||
|
||||
#define RESTARTABLE(_cmd, _result) do { \
|
||||
do { \
|
||||
_result = _cmd; \
|
||||
|
@ -85,94 +63,6 @@ int NET_SocketAvailable(int s, int *pbytes) {
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef __solaris__
|
||||
static int init_tcp_max_buf, init_udp_max_buf;
|
||||
static int tcp_max_buf;
|
||||
static int udp_max_buf;
|
||||
static int useExclBind = 0;
|
||||
|
||||
/*
|
||||
* Get the specified parameter from the specified driver. The value
|
||||
* of the parameter is assumed to be an 'int'. If the parameter
|
||||
* cannot be obtained return -1
|
||||
*/
|
||||
int net_getParam(char *driver, char *param)
|
||||
{
|
||||
struct strioctl stri;
|
||||
char buf [64];
|
||||
int s;
|
||||
int value;
|
||||
|
||||
s = open (driver, O_RDWR);
|
||||
if (s < 0) {
|
||||
return -1;
|
||||
}
|
||||
strncpy (buf, param, sizeof(buf));
|
||||
stri.ic_cmd = ND_GET;
|
||||
stri.ic_timout = 0;
|
||||
stri.ic_dp = buf;
|
||||
stri.ic_len = sizeof(buf);
|
||||
if (ioctl (s, I_STR, &stri) < 0) {
|
||||
value = -1;
|
||||
} else {
|
||||
value = atoi(buf);
|
||||
}
|
||||
close (s);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
|
||||
* for Solaris versions that do not support the ioctl() in net_getParam().
|
||||
* Ugly, but only called once (for each sotype).
|
||||
*
|
||||
* As an optimization, we make a guess using the default values for Solaris
|
||||
* assuming they haven't been modified with ndd.
|
||||
*/
|
||||
|
||||
#define MAX_TCP_GUESS 1024 * 1024
|
||||
#define MAX_UDP_GUESS 2 * 1024 * 1024
|
||||
|
||||
#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
|
||||
|
||||
static int findMaxBuf(int fd, int opt, int sotype) {
|
||||
int a = 0;
|
||||
int b = MAXINT;
|
||||
int initial_guess;
|
||||
int limit = -1;
|
||||
|
||||
if (sotype == SOCK_DGRAM) {
|
||||
initial_guess = MAX_UDP_GUESS;
|
||||
} else {
|
||||
initial_guess = MAX_TCP_GUESS;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
|
||||
initial_guess++;
|
||||
if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
|
||||
FAIL_IF_NOT_ENOBUFS;
|
||||
return initial_guess - 1;
|
||||
}
|
||||
a = initial_guess;
|
||||
} else {
|
||||
FAIL_IF_NOT_ENOBUFS;
|
||||
b = initial_guess - 1;
|
||||
}
|
||||
do {
|
||||
int mid = a + (b-a)/2;
|
||||
if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
|
||||
limit = mid;
|
||||
a = mid + 1;
|
||||
} else {
|
||||
FAIL_IF_NOT_ENOBUFS;
|
||||
b = mid - 1;
|
||||
}
|
||||
} while (b >= a);
|
||||
|
||||
return limit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
|
||||
const char *defaultDetail) {
|
||||
|
@ -283,50 +173,6 @@ jint IPv6_supported()
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* On Solaris 8 it's possible to create INET6 sockets even
|
||||
* though IPv6 is not enabled on all interfaces. Thus we
|
||||
* query the number of IPv6 addresses to verify that IPv6
|
||||
* has been configured on at least one interface.
|
||||
*
|
||||
* On Linux it doesn't matter - if IPv6 is built-in the
|
||||
* kernel then IPv6 addresses will be bound automatically
|
||||
* to all interfaces.
|
||||
*/
|
||||
#ifdef __solaris__
|
||||
|
||||
#ifdef SIOCGLIFNUM
|
||||
{
|
||||
struct lifnum numifs;
|
||||
|
||||
numifs.lifn_family = AF_INET6;
|
||||
numifs.lifn_flags = 0;
|
||||
if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
|
||||
/**
|
||||
* SIOCGLIFNUM failed - assume IPv6 not configured
|
||||
*/
|
||||
close(fd);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/**
|
||||
* If no IPv6 addresses then return false. If count > 0
|
||||
* it's possible that all IPv6 addresses are "down" but
|
||||
* that's okay as they may be brought "up" while the
|
||||
* VM is running.
|
||||
*/
|
||||
if (numifs.lifn_count == 0) {
|
||||
close(fd);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* SIOCGLIFNUM not defined in build environment ??? */
|
||||
close(fd);
|
||||
return JNI_FALSE;
|
||||
#endif
|
||||
|
||||
#endif /* __solaris */
|
||||
|
||||
/*
|
||||
* OK we may have the stack available in the kernel,
|
||||
* we should also check if the APIs are available.
|
||||
|
@ -403,26 +249,6 @@ void platformInit () {}
|
|||
|
||||
#endif
|
||||
|
||||
void parseExclusiveBindProperty(JNIEnv *env) {
|
||||
#ifdef __solaris__
|
||||
jstring s, flagSet;
|
||||
jclass iCls;
|
||||
jmethodID mid;
|
||||
|
||||
s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
|
||||
CHECK_NULL(s);
|
||||
iCls = (*env)->FindClass(env, "java/lang/System");
|
||||
CHECK_NULL(iCls);
|
||||
mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
|
||||
"(Ljava/lang/String;)Ljava/lang/String;");
|
||||
CHECK_NULL(mid);
|
||||
flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
|
||||
if (flagSet != NULL) {
|
||||
useExclBind = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
NET_EnableFastTcpLoopback(int fd) {
|
||||
return 0;
|
||||
|
@ -588,7 +414,7 @@ NET_MapSocketOption(jint cmd, int *level, int *optname) {
|
|||
*level = IPPROTO_IPV6;
|
||||
*optname = IPV6_MULTICAST_LOOP;
|
||||
return 0;
|
||||
#if (defined(__solaris__) || defined(MACOSX))
|
||||
#if defined(MACOSX)
|
||||
// Map IP_TOS request to IPV6_TCLASS
|
||||
case java_net_SocketOptions_IP_TOS:
|
||||
*level = IPPROTO_IPV6;
|
||||
|
@ -737,65 +563,6 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
|
|||
*iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
|
||||
* the value when it exceeds the system limit.
|
||||
*/
|
||||
#ifdef __solaris__
|
||||
if (level == SOL_SOCKET) {
|
||||
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
|
||||
int sotype=0;
|
||||
socklen_t arglen;
|
||||
int *bufsize, maxbuf;
|
||||
int ret;
|
||||
|
||||
/* Attempt with the original size */
|
||||
ret = setsockopt(fd, level, opt, arg, len);
|
||||
if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
|
||||
return ret;
|
||||
|
||||
/* Exceeded system limit so clamp and retry */
|
||||
|
||||
arglen = sizeof(sotype);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
|
||||
&arglen) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We try to get tcp_maxbuf (and udp_max_buf) using
|
||||
* an ioctl() that isn't available on all versions of Solaris.
|
||||
* If that fails, we use the search algorithm in findMaxBuf()
|
||||
*/
|
||||
if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
|
||||
tcp_max_buf = net_getParam("/dev/tcp", "tcp_max_buf");
|
||||
if (tcp_max_buf == -1) {
|
||||
tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
|
||||
if (tcp_max_buf == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
init_tcp_max_buf = 1;
|
||||
} else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
|
||||
udp_max_buf = net_getParam("/dev/udp", "udp_max_buf");
|
||||
if (udp_max_buf == -1) {
|
||||
udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
|
||||
if (udp_max_buf == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
init_udp_max_buf = 1;
|
||||
}
|
||||
|
||||
maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
|
||||
bufsize = (int *)arg;
|
||||
if (*bufsize > maxbuf) {
|
||||
*bufsize = maxbuf;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
if (level == SOL_SOCKET) {
|
||||
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
|
||||
|
@ -908,19 +675,10 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
|
|||
*
|
||||
* Linux allows a socket to bind to 127.0.0.255 which must be
|
||||
* caught.
|
||||
*
|
||||
* On Solaris with IPv6 enabled we must use an exclusive
|
||||
* bind to guarantee a unique port number across the IPv4 and
|
||||
* IPv6 port spaces.
|
||||
*
|
||||
*/
|
||||
int
|
||||
NET_Bind(int fd, SOCKETADDRESS *sa, int len)
|
||||
{
|
||||
#if defined(__solaris__)
|
||||
int level = -1;
|
||||
int exclbind = -1;
|
||||
#endif
|
||||
int rv;
|
||||
int arg, alen;
|
||||
|
||||
|
@ -938,61 +696,8 @@ NET_Bind(int fd, SOCKETADDRESS *sa, int len)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(__solaris__)
|
||||
/*
|
||||
* Solaris has separate IPv4 and IPv6 port spaces so we
|
||||
* use an exclusive bind when SO_REUSEADDR is not used to
|
||||
* give the illusion of a unified port space.
|
||||
* This also avoids problems with IPv6 sockets connecting
|
||||
* to IPv4 mapped addresses whereby the socket conversion
|
||||
* results in a late bind that fails because the
|
||||
* corresponding IPv4 port is in use.
|
||||
*/
|
||||
alen = sizeof(arg);
|
||||
|
||||
if (useExclBind ||
|
||||
getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg, &alen) == 0)
|
||||
{
|
||||
if (useExclBind || arg == 0) {
|
||||
/*
|
||||
* SO_REUSEADDR is disabled or sun.net.useExclusiveBind
|
||||
* property is true so enable TCP_EXCLBIND or
|
||||
* UDP_EXCLBIND
|
||||
*/
|
||||
alen = sizeof(arg);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg, &alen) == 0)
|
||||
{
|
||||
if (arg == SOCK_STREAM) {
|
||||
level = IPPROTO_TCP;
|
||||
exclbind = TCP_EXCLBIND;
|
||||
} else {
|
||||
level = IPPROTO_UDP;
|
||||
exclbind = UDP_EXCLBIND;
|
||||
}
|
||||
}
|
||||
|
||||
arg = 1;
|
||||
setsockopt(fd, level, exclbind, (char *)&arg, sizeof(arg));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
rv = bind(fd, &sa->sa, len);
|
||||
|
||||
#if defined(__solaris__)
|
||||
if (rv < 0) {
|
||||
int en = errno;
|
||||
/* Restore *_EXCLBIND if the bind fails */
|
||||
if (exclbind != -1) {
|
||||
int arg = 0;
|
||||
setsockopt(fd, level, exclbind, (char *)&arg,
|
||||
sizeof(arg));
|
||||
}
|
||||
errno = en;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -47,8 +47,6 @@
|
|||
#ifndef SO_REUSEPORT
|
||||
#ifdef __linux__
|
||||
#define SO_REUSEPORT 15
|
||||
#elif defined(__solaris__)
|
||||
#define SO_REUSEPORT 0x100e
|
||||
#elif defined(AIX) || defined(MACOSX)
|
||||
#define SO_REUSEPORT 0x0200
|
||||
#else
|
||||
|
@ -98,8 +96,4 @@ void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
|
|||
const char *defaultDetail);
|
||||
void NET_SetTrafficClass(SOCKETADDRESS *sa, int trafficClass);
|
||||
|
||||
#ifdef __solaris__
|
||||
int net_getParam(char *driver, char *param);
|
||||
#endif
|
||||
|
||||
#endif /* NET_UTILS_MD_H */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -60,13 +60,6 @@ static int getPortRange(struct portrange *range)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__solaris__)
|
||||
{
|
||||
range->higher = net_getParam("/dev/tcp", "tcp_largest_anon_port");
|
||||
range->lower = net_getParam("/dev/tcp", "tcp_smallest_anon_port");
|
||||
return 0;
|
||||
}
|
||||
#elif defined(_ALLBSD_SOURCE)
|
||||
{
|
||||
int ret;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -50,9 +50,6 @@ Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jclass clazz,
|
|||
jint fd = fdval(env, fdo);
|
||||
int rv;
|
||||
|
||||
#if defined(__solaris__)
|
||||
rv = connect(fd, 0, 0);
|
||||
#else
|
||||
SOCKETADDRESS sa;
|
||||
socklen_t len = isIPv6 ? sizeof(struct sockaddr_in6) :
|
||||
sizeof(struct sockaddr_in);
|
||||
|
@ -78,8 +75,6 @@ Java_sun_nio_ch_DatagramChannelImpl_disconnect0(JNIEnv *env, jclass clazz,
|
|||
rv = errno = 0;
|
||||
#endif // defined(_ALLBSD_SOURCE) || defined(_AIX)
|
||||
|
||||
#endif // defined(__solaris__)
|
||||
|
||||
if (rv < 0)
|
||||
handleSocketError(env, errno);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -29,7 +29,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(__linux__) || defined(__solaris__)
|
||||
#if defined(__linux__)
|
||||
#include <sys/sendfile.h>
|
||||
#elif defined(_AIX)
|
||||
#include <string.h>
|
||||
|
@ -182,36 +182,6 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
|
|||
return IOS_THROWN;
|
||||
}
|
||||
return n;
|
||||
#elif defined (__solaris__)
|
||||
sendfilevec64_t sfv;
|
||||
size_t numBytes = 0;
|
||||
jlong result;
|
||||
|
||||
sfv.sfv_fd = srcFD;
|
||||
sfv.sfv_flag = 0;
|
||||
sfv.sfv_off = (off64_t)position;
|
||||
sfv.sfv_len = count;
|
||||
|
||||
result = sendfilev64(dstFD, &sfv, 1, &numBytes);
|
||||
|
||||
/* Solaris sendfilev() will return -1 even if some bytes have been
|
||||
* transferred, so we check numBytes first.
|
||||
*/
|
||||
if (numBytes > 0)
|
||||
return numBytes;
|
||||
if (result < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return IOS_UNAVAILABLE;
|
||||
if (errno == EOPNOTSUPP)
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
if ((errno == EINVAL) && ((ssize_t)count >= 0))
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
if (errno == EINTR)
|
||||
return IOS_INTERRUPTED;
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
return result;
|
||||
#elif defined(__APPLE__)
|
||||
off_t numBytes;
|
||||
int result;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -41,9 +41,6 @@
|
|||
#include <pthread.h>
|
||||
/* Also defined in net/aix_close.c */
|
||||
#define INTERRUPT_SIGNAL (SIGRTMAX - 1)
|
||||
#elif defined(__solaris__)
|
||||
#include <thread.h>
|
||||
#define INTERRUPT_SIGNAL (SIGRTMAX - 2)
|
||||
#elif defined(_ALLBSD_SOURCE)
|
||||
#include <pthread.h>
|
||||
/* Also defined in net/bsd_close.c */
|
||||
|
@ -79,22 +76,14 @@ Java_sun_nio_ch_NativeThread_init(JNIEnv *env, jclass cl)
|
|||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_NativeThread_current(JNIEnv *env, jclass cl)
|
||||
{
|
||||
#ifdef __solaris__
|
||||
return (jlong)thr_self();
|
||||
#else
|
||||
return (jlong)pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_NativeThread_signal(JNIEnv *env, jclass cl, jlong thread)
|
||||
{
|
||||
int ret;
|
||||
#ifdef __solaris__
|
||||
ret = thr_kill((thread_t)thread, INTERRUPT_SIGNAL);
|
||||
#else
|
||||
ret = pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL);
|
||||
#endif
|
||||
#ifdef MACOSX
|
||||
if (ret != 0 && ret != ESRCH)
|
||||
#else
|
||||
|
|
|
@ -170,7 +170,7 @@ Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
|
|||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__) || defined(__solaris__)
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
/* IPv6 sockets can join IPv4 multicast groups */
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
|
@ -182,7 +182,7 @@ Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl)
|
|||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(__solaris__)
|
||||
#if defined(__APPLE__)
|
||||
/* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -40,8 +40,6 @@
|
|||
#ifndef SO_REUSEPORT
|
||||
#ifdef __linux__
|
||||
#define SO_REUSEPORT 15
|
||||
#elif defined(__solaris__)
|
||||
#define SO_REUSEPORT 0x100e
|
||||
#elif defined(AIX) || defined(MACOSX)
|
||||
#define SO_REUSEPORT 0x0200
|
||||
#else
|
||||
|
|
|
@ -41,17 +41,10 @@
|
|||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
/* For POSIX-compliant getpwuid_r, getgrgid_r on Solaris */
|
||||
#if defined(__solaris__)
|
||||
#define _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* For POSIX-compliant getpwuid_r */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#ifdef __solaris__
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
@ -263,8 +256,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
|
|||
|
||||
/* system calls that might not be available at run time */
|
||||
|
||||
#if (defined(__solaris__) && defined(_LP64)) || defined(_ALLBSD_SOURCE)
|
||||
/* Solaris 64-bit does not have openat64/fstatat64 */
|
||||
#if defined(_ALLBSD_SOURCE)
|
||||
my_openat64_func = (openat64_func*)dlsym(RTLD_DEFAULT, "openat");
|
||||
my_fstatat64_func = (fstatat64_func*)dlsym(RTLD_DEFAULT, "fstatat");
|
||||
#else
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -127,7 +127,6 @@ DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
|
|||
}
|
||||
|
||||
void platformInit() {}
|
||||
void parseExclusiveBindProperty(JNIEnv *env) {}
|
||||
|
||||
/*
|
||||
* Since winsock doesn't have the equivalent of strerror(errno)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue