From cb5f02b05b97dc05a3f7d4d3e3821e1fc3ae2c59 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 13 Dec 2014 06:38:59 +0100 Subject: Bug 1108 - Fix difficulties to determine executable access permission 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'. +++ Conflicts: src/java/com/jogamp/common/util/IOUtil.java --- src/java/com/jogamp/common/util/IOUtil.java | 104 +++++++++++++++++---- .../common/util/bin/exe-windows-i586-268b.bin | Bin 0 -> 268 bytes 2 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 src/java/com/jogamp/common/util/bin/exe-windows-i586-268b.bin (limited to 'src/java') diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java index d5a9544..1eaf46f 100644 --- a/src/java/com/jogamp/common/util/IOUtil.java +++ b/src/java/com/jogamp/common/util/IOUtil.java @@ -39,6 +39,7 @@ import java.io.IOException; 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.URI; import java.net.URISyntaxException; @@ -951,15 +952,19 @@ public class IOUtil { 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; @@ -967,7 +972,71 @@ public class IOUtil { return null; } } - + private static String[] getExeTestCommandArgs(final String scriptFile) { + switch(PlatformPropsImpl.OS_TYPE) { + case WINDOWS: + // 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 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(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: @@ -1099,9 +1168,9 @@ public class IOUtil { } 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) { @@ -1112,17 +1181,13 @@ public class IOUtil { } 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(new String[] { exetst.getCanonicalPath() } ); + final Process pr = Runtime.getRuntime().exec( getExeTestCommandArgs( exeTestFile.getCanonicalPath() ) ); /** * Disable StreamMonitor, which throttles exec-test performance a lot! * @@ -1137,18 +1202,19 @@ public class IOUtil { } 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) diff --git a/src/java/com/jogamp/common/util/bin/exe-windows-i586-268b.bin b/src/java/com/jogamp/common/util/bin/exe-windows-i586-268b.bin new file mode 100644 index 0000000..b0d5f63 Binary files /dev/null and b/src/java/com/jogamp/common/util/bin/exe-windows-i586-268b.bin differ -- cgit v1.2.3