This is an automated email from the ASF dual-hosted git repository. rzo1 pushed a commit to branch files-tmpdir-atomic in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 9df2a27d4e32af0d5af2d713884c4ee99c78a0a7 Author: Richard Zowalla <[email protected]> AuthorDate: Mon Oct 5 19:30:59 2026 +0200 create Files.tmpdir() directories atomically Use Files.createTempDirectory instead of createTempFile/delete/mkdir, which raced in a shared temp dir, and get owner-only permissions. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../main/java/org/apache/openejb/loader/Files.java | 12 +++------- .../java/org/apache/openejb/loader/FilesTest.java | 26 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/container/openejb-loader/src/main/java/org/apache/openejb/loader/Files.java b/container/openejb-loader/src/main/java/org/apache/openejb/loader/Files.java index cc97b3b1ef..d045a17aab 100644 --- a/container/openejb-loader/src/main/java/org/apache/openejb/loader/Files.java +++ b/container/openejb-loader/src/main/java/org/apache/openejb/loader/Files.java @@ -192,7 +192,8 @@ public class Files { try { File file; try { - file = File.createTempFile("temp", "dir"); + // created atomically with owner-only permissions on POSIX file systems + file = java.nio.file.Files.createTempDirectory("temp").toFile(); } catch (final Throwable e) { //Use a local tmp directory final File tmp = new File("tmp"); @@ -203,16 +204,9 @@ public class Files { throw new IOException("Failed to create local tmp directory: " + tmp.getAbsolutePath()); } - file = File.createTempFile("temp", "dir", tmp); + file = java.nio.file.Files.createTempDirectory(tmp.toPath(), "temp").toFile(); } - hackJDK4715154(); - - if (!file.delete()) { - throw new IOException("Failed to create temp dir. Delete failed"); - } - - mkdir(file); deleteOnExit(file); return file; diff --git a/container/openejb-loader/src/test/java/org/apache/openejb/loader/FilesTest.java b/container/openejb-loader/src/test/java/org/apache/openejb/loader/FilesTest.java index daca321feb..86a11a711f 100644 --- a/container/openejb-loader/src/test/java/org/apache/openejb/loader/FilesTest.java +++ b/container/openejb-loader/src/test/java/org/apache/openejb/loader/FilesTest.java @@ -20,11 +20,15 @@ import org.junit.Test; import java.io.File; import java.io.IOException; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; public class FilesTest { @@ -72,4 +76,24 @@ public class FilesTest { final long time = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS); Logger.getLogger(this.getClass().getName()).log(Level.INFO, String.format("Completed File.%1$s in %2$sms" , remove ? "remove" : "delete", String.valueOf(time))); } -} \ No newline at end of file + + @Test + public void tmpdirCreatesDistinctPrivateDirectories() throws Exception { + final File dir1 = Files.tmpdir(); + final File dir2 = Files.tmpdir(); + + assertTrue(dir1.isDirectory()); + assertTrue(dir2.isDirectory()); + assertNotEquals(dir1.getAbsoluteFile(), dir2.getAbsoluteFile()); + + for (final File dir : new File[]{dir1, dir2}) { + if (java.nio.file.Files.getFileStore(dir.toPath()).supportsFileAttributeView(PosixFileAttributeView.class)) { + final Set<PosixFilePermission> permissions = java.nio.file.Files.getPosixFilePermissions(dir.toPath()); + for (final PosixFilePermission permission : permissions) { + assertFalse("tmpdir must be owner-only but has " + permission, + permission.name().startsWith("GROUP_") || permission.name().startsWith("OTHERS_")); + } + } + } + } +}
