Skip to content

Commit

Permalink
Bug 1108 - Fix difficulties to determine executable access permission…
Browse files Browse the repository at this point in the history
… on Windows via BATCH file execution

Batch file execution test via direct call, i.e.'a.bat',
does not work on some Windows machine, not reproducible here!

A workaround would be to call the batch file explicit via 'CMD /c a.bat':
  - works when using 'Software Restriction Policies' (Bug 1015 Comment 2)
  - does _not_ work when denying ACL "Traverse Folder / Execute File" permission (Bug 1015 Comment 3)

Due to this bug, we need to use a native execution:

- Performing executable test w/ native exe file instead of batch file
  on Windows x86 32bit and 64bit,

- using [1] TinyPE XP-W8 Compatible - x86 32bit and 64bit - 268 bytes
  - Tested on: WinXP-32bit, Win7-64bit and Win8-64bit
  - Author/License: Ange Albertini, BSD Licence, 2010-2013

- On all other Windows machines (ARM, ..),
  we still use direct execution of 'a.bat'
  but may add native exe files for missing platforms.

+++

This patch injects said binaries within the java jar file
and copies it into the 'to be tested' temp folder for execution.

[1] TinyPE XP-W8 Compatible - x86 32bit and 64bit - 268 bytes
is included within 'src/native/tinype-corkami',
build manually and imported as 'src/java/com/jogamp/common/util/bin/exe-windows-i586-268b.bin'.

+++
  • Loading branch information
sgothel committed Dec 13, 2014
1 parent f26fcc9 commit 181dc8a
Show file tree
Hide file tree
Showing 8 changed files with 1,020 additions and 21 deletions.
9 changes: 9 additions & 0 deletions make/build.xml
Expand Up @@ -59,6 +59,7 @@
<property name="project.root" value=".." />
<property name="src.java" value="${project.root}/src/java" />
<property name="src.antlr" value="${project.root}/src/antlr" />

<property name="build" location="${project.root}/${rootrel.build}" />
<property name="javadoc.root.path" location="${build}/javadoc" />
<property name="javadoc.gluegen.path" location="${javadoc.root.path}/gluegen/javadoc" />
Expand Down Expand Up @@ -138,6 +139,7 @@

<!-- property name="java.part.awt" value="com/jogamp/common/util/awt/** jogamp/common/awt/**"/-->
<property name="java.part.awt" value="com/jogamp/common/util/awt/**"/>
<property name="java.part.nonjava" value="com/jogamp/common/util/bin/*" />
<property name="gluegen-rt.classes" value="com/jogamp/gluegen/runtime/**"/>
<property name="jogamp.common.classes" value="com/jogamp/common/** jogamp/common/**"/>

Expand Down Expand Up @@ -718,6 +720,13 @@
<classpath refid="cc_gluegen.classpath" />
</javac>

<!-- make non-java code available in classpath -->
<copy todir="${classes}">
<fileset dir="${src.java}"
includes="${java.part.nonjava}"
excludes="**/*.java"/>
</copy>

<!-- Compile gluegen (compile time).
Uses host.rt.jar, since we require 'com.sun.tools.doclets.Taglet',
Expand Down
100 changes: 79 additions & 21 deletions src/java/com/jogamp/common/util/IOUtil.java
Expand Up @@ -39,6 +39,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.net.URISyntaxException;
import java.net.URL;
Expand Down Expand Up @@ -652,31 +653,91 @@ public static URLConnection openURL(final URL url, final String dbgmsg) {
return null;
}

private static String getShellSuffix() {
private static String getExeTestFileSuffix() {
switch(PlatformPropsImpl.OS_TYPE) {
case WINDOWS:
return ".bat";
if( Platform.CPUFamily.X86 == PlatformPropsImpl.CPU_ARCH.family ) {
return ".exe";
} else {
return ".bat";
}
default:
return ".sh";
}
}
private static String getShellCode() {
private static String getExeTestShellCode() {
switch(PlatformPropsImpl.OS_TYPE) {
case WINDOWS:
return "echo off"+PlatformPropsImpl.NEWLINE;
default:
return null;
}
}
private static String[] getShellCommandArgs(final String scriptFile) {
private static String[] getExeTestCommandArgs(final String scriptFile) {
switch(PlatformPropsImpl.OS_TYPE) {
case WINDOWS:
return new String[] { "cmd", "/c", scriptFile };
// return new String[] { "cmd", "/c", scriptFile };
default:
return new String[] { scriptFile };
}
}

private static final byte[] getBytesFromRelFile(final byte[] res, final String fname, final int size) throws IOException {
final URLConnection con = IOUtil.getResource(IOUtil.class, fname);
final InputStream in = con.getInputStream();
int numBytes = 0;
try {
while (true) {
final int remBytes = size - numBytes;
int count;
if ( 0 >= remBytes || (count = in.read(res, numBytes, remBytes)) == -1 ) {
break;
}
numBytes += count;
}
} finally {
in.close();
}
if( size != numBytes ) {
throw new IOException("Got "+numBytes+" bytes != expected "+size);
}
return res;
}
private static final Object exeTestBytesLock = new Object();
private static WeakReference<byte[]> exeTestBytesRef = null;

private static void fillExeTestFile(final File exefile) throws IOException {
if( Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE &&
Platform.CPUFamily.X86 == PlatformPropsImpl.CPU_ARCH.family
) {
final int codeSize = 268;
final byte[] code;
synchronized ( exeTestBytesLock ) {
byte[] _code;
if( null == exeTestBytesRef || null == ( _code = exeTestBytesRef.get() ) ) {
code = getBytesFromRelFile(new byte[512], "bin/exe-windows-i586-268b.bin", codeSize);
exeTestBytesRef = new WeakReference<byte[]>(code);
} else {
code = _code;
}
}
final OutputStream out = new FileOutputStream(exefile);
try {
out.write(code, 0, codeSize);
} finally {
out.close();
}
} else {
final String shellCode = getExeTestShellCode();
if( isStringSet(shellCode) ) {
final FileWriter fout = new FileWriter(exefile);
try {
fout.write(shellCode);
} finally {
fout.close();
}
}
}
}
private static boolean getOSHasNoexecFS() {
switch(PlatformPropsImpl.OS_TYPE) {
case OPENKODE:
Expand Down Expand Up @@ -808,9 +869,9 @@ public static boolean testDirExec(final File dir)
}

final long t0 = DEBUG ? System.currentTimeMillis() : 0;
File exetst;
final File exeTestFile;
try {
exetst = File.createTempFile("jogamp_exe_tst", getShellSuffix(), dir);
exeTestFile = File.createTempFile("jogamp_exe_tst", getExeTestFileSuffix(), dir);
} catch (final SecurityException se) {
throw se; // fwd Security exception
} catch (final IOException e) {
Expand All @@ -821,17 +882,13 @@ public static boolean testDirExec(final File dir)
}
final long t1 = DEBUG ? System.currentTimeMillis() : 0;
int res = -1;
if(exetst.setExecutable(true /* exec */, true /* ownerOnly */)) {
final String shellCode = getShellCode();
if(exeTestFile.setExecutable(true /* exec */, true /* ownerOnly */)) {
try {
if( isStringSet(shellCode) ) {
final FileWriter fout = new FileWriter(exetst);
fout.write(shellCode);
fout.close();
}
fillExeTestFile(exeTestFile);

// Using 'Process.exec(String[])' avoids StringTokenizer of 'Process.exec(String)'
// and hence splitting up command by spaces!
final Process pr = Runtime.getRuntime().exec( getShellCommandArgs( exetst.getCanonicalPath() ) );
final Process pr = Runtime.getRuntime().exec( getExeTestCommandArgs( exeTestFile.getCanonicalPath() ) );
/**
* Disable StreamMonitor, which throttles exec-test performance a lot!
*
Expand All @@ -846,18 +903,19 @@ public static boolean testDirExec(final File dir)
} catch (final Throwable t) {
res = -2;
if(DEBUG) {
System.err.println("IOUtil.testDirExec: <"+exetst.getAbsolutePath()+">: Caught "+t.getClass().getSimpleName()+": "+t.getMessage());
// t.printStackTrace();
System.err.println("IOUtil.testDirExec: <"+exeTestFile.getAbsolutePath()+">: Caught "+t.getClass().getSimpleName()+": "+t.getMessage());
t.printStackTrace();
}
}
}
final boolean ok = 0 == res;
final long t2 = DEBUG ? System.currentTimeMillis() : 0;
exetst.delete();
exeTestFile.delete();
if( DEBUG) {
System.err.println("IOUtil.testDirExec(): <"+dir.getAbsolutePath()+">: res "+res);
System.err.println("IOUtil.testDirExec(): <"+dir.getAbsolutePath()+">: res "+res+" -> "+ok);
System.err.println("IOUtil.testDirExec(): total "+(t2-t0)+"ms, create "+(t1-t0)+"ms, execute "+(t2-t1)+"ms");
}
return 0 == res;
return ok;
}

private static File testDirImpl(final File dir, final boolean create, final boolean executable, final String dbgMsg)
Expand Down
Binary file not shown.

0 comments on commit 181dc8a

Please sign in to comment.