From ac61a4a32d767b787b4098e9f1fc6540f6677588 Mon Sep 17 00:00:00 2001 From: Isabell Cowan Date: Sat, 2 Sep 2017 19:24:49 -0500 Subject: [PATCH] Unlink temp file after loading on POSIX. * Unlink the temporary library file after the last file descriptor to it is opened (`System.load(temp.getAbsolutePath())`) on systems that appear to be POSIX compliant. --- src/main/java/cz/adamh/utils/NativeUtils.java | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/main/java/cz/adamh/utils/NativeUtils.java b/src/main/java/cz/adamh/utils/NativeUtils.java index e4a02f3..59d0334 100644 --- a/src/main/java/cz/adamh/utils/NativeUtils.java +++ b/src/main/java/cz/adamh/utils/NativeUtils.java @@ -24,7 +24,11 @@ package cz.adamh.utils; import java.io.*; - +import java.net.URI; +import java.nio.file.FileSystemNotFoundException; +import java.nio.file.FileSystems; +import java.nio.file.ProviderNotFoundException; + /** * A simple library class which helps with loading dynamic libraries stored in the * JAR archive. These libraries usualy contain implementation of some methods in @@ -79,35 +83,59 @@ public class NativeUtils { // Prepare temporary file File temp = File.createTempFile(prefix, suffix); - temp.deleteOnExit(); - + if (!temp.exists()) { throw new FileNotFoundException("File " + temp.getAbsolutePath() + " does not exist."); } - + + boolean tempFileIsPosix = false; + try { + if (FileSystems.getDefault() + .supportedFileAttributeViews() + .contains("posix")) { + // Assume POSIX compliant file system, can be deleted after loading. + tempFileIsPosix = true; + } + } catch (FileSystemNotFoundException + | ProviderNotFoundException + | SecurityException e) { + // Assume non-POSIX, and don't delete until last file descriptor closed. + } + // Prepare buffer for data copying byte[] buffer = new byte[1024]; int readBytes; - + // Open and check input stream InputStream is = NativeUtils.class.getResourceAsStream(path); if (is == null) { + temp.delete(); throw new FileNotFoundException("File " + path + " was not found inside JAR."); } - + // Open output stream and copy data between source file in JAR and the temporary file OutputStream os = new FileOutputStream(temp); try { while ((readBytes = is.read(buffer)) != -1) { os.write(buffer, 0, readBytes); } + } catch (Exception e) { + temp.delete(); + throw e; } finally { // If read/write fails, close streams safely before throwing an exception os.close(); is.close(); } - - // Finally, load the library - System.load(temp.getAbsolutePath()); + + try { + // Load the library + System.load(temp.getAbsolutePath()); + } finally { + if (tempFileIsPosix) + temp.delete(); + else + temp.deleteOnExit(); + } } }