diff --git a/src/main/org/apache/tools/ant/MagicNames.java b/src/main/org/apache/tools/ant/MagicNames.java index 5cf2fa8fa..8ced50578 100644 --- a/src/main/org/apache/tools/ant/MagicNames.java +++ b/src/main/org/apache/tools/ant/MagicNames.java @@ -337,5 +337,15 @@ public final class MagicNames { * @since Ant 1.10.8 */ public static final String TMPDIR = "ant.tmpdir"; + + /** + * Magic property that will be set to override java.io.tmpdir + * system property as the location for Ant's default temporary + * directory if a temp file is created and {@link #TMPDIR} is not + * set. + * Value: {@value} + * @since Ant 1.10.9 + */ + public static final String AUTO_TMPDIR = "ant.auto.tmpdir"; } diff --git a/src/main/org/apache/tools/ant/util/FileUtils.java b/src/main/org/apache/tools/ant/util/FileUtils.java index 46671848c..d835438fe 100644 --- a/src/main/org/apache/tools/ant/util/FileUtils.java +++ b/src/main/org/apache/tools/ant/util/FileUtils.java @@ -110,6 +110,11 @@ public class FileUtils { PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)) }; + private static final FileAttribute[] TMPDIR_ATTRIBUTES = + new FileAttribute[] { + PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE)) + }; private static final FileAttribute[] NO_TMPFILE_ATTRIBUTES = new FileAttribute[0]; /** @@ -991,14 +996,35 @@ public class FileUtils { public File createTempFile(final Project project, String prefix, String suffix, final File parentDir, final boolean deleteOnExit, final boolean createFile) { File result; - final String parent; + String p = null; if (parentDir != null) { - parent = parentDir.getPath(); + p = parentDir.getPath(); } else if (project != null && project.getProperty(MagicNames.TMPDIR) != null) { - parent = project.getProperty(MagicNames.TMPDIR); - } else { - parent = System.getProperty("java.io.tmpdir"); + p = project.getProperty(MagicNames.TMPDIR); + } else if (project != null && deleteOnExit) { + if (project.getProperty(MagicNames.AUTO_TMPDIR) != null) { + p = project.getProperty(MagicNames.AUTO_TMPDIR); + } else { + final Path systemTempDirPath = + new File(System.getProperty("java.io.tmpdir")).toPath(); + final PosixFileAttributeView systemTempDirPosixAttributes = + Files.getFileAttributeView(systemTempDirPath, PosixFileAttributeView.class); + if (systemTempDirPosixAttributes != null) { + // no reason to create an extra temp dir if we cannot set permissions + try { + final File projectTempDir = Files.createTempDirectory(systemTempDirPath, + "ant", TMPDIR_ATTRIBUTES) + .toFile(); + projectTempDir.deleteOnExit(); + p = projectTempDir.getAbsolutePath(); + project.setProperty(MagicNames.AUTO_TMPDIR, p); + } catch (IOException ex) { + // silently fall back to system temp directory + } + } + } } + final String parent = p != null ? p : System.getProperty("java.io.tmpdir"); if (prefix == null) { prefix = NULL_PLACEHOLDER; } diff --git a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java index da4652003..d5448a6ac 100644 --- a/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java +++ b/src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java @@ -50,6 +50,8 @@ import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; @@ -450,6 +452,68 @@ public class FileUtilsTest { tmp2.getAbsolutePath())); } + @Test + public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsTrue() throws IOException { + final Project project = new Project(); + final File projectTmpDir = folder.newFolder("subdir"); + project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath()); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true); + assertTrue(tmpFile + " must be child of " + projectTmpDir, + tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath())); + } + + @Test + public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsFalse() throws IOException { + final Project project = new Project(); + final File projectTmpDir = folder.newFolder("subdir"); + project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath()); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true); + assertTrue(tmpFile + " must be child of " + projectTmpDir, + tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath())); + } + + @Test + public void createTempFileCreatesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException { + assumeFalse("Test doesn't run on DOS", Os.isFamily("dos")); + final Project project = new Project(); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true); + final String autoTempDir = project.getProperty("ant.auto.tmpdir"); + assertNotNull(autoTempDir); + assertTrue(tmpFile + " must be child of " + autoTempDir, + tmpFile.getAbsolutePath().startsWith(autoTempDir)); + } + + @Test + public void createTempFileDoesntCreateAutoTmpDirIfDeleteOnExitIsFalse() throws IOException { + final Project project = new Project(); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true); + assertNull(project.getProperty("ant.auto.tmpdir")); + } + + @Test + public void createTempFileReusesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException { + assumeFalse("Test doesn't run on DOS", Os.isFamily("dos")); + final Project project = new Project(); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true); + final String autoTempDir = project.getProperty("ant.auto.tmpdir"); + assertNotNull(autoTempDir); + final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, true, true); + assertTrue(tmpFile2 + " must be child of " + autoTempDir, + tmpFile2.getAbsolutePath().startsWith(autoTempDir)); + } + + @Test + public void createTempFileDoesntReusesAutoTmpDirIfDeleteOnExitIsFalse() throws IOException { + assumeFalse("Test doesn't run on DOS", Os.isFamily("dos")); + final Project project = new Project(); + final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true); + final String autoTempDir = project.getProperty("ant.auto.tmpdir"); + assertNotNull(autoTempDir); + final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, false, true); + assertFalse(tmpFile2 + " must not be child of " + autoTempDir, + tmpFile2.getAbsolutePath().startsWith(autoTempDir)); + } + /** * Test contentEquals */