diff --git a/manual/Types/selectors.html b/manual/Types/selectors.html
index 955a1b28d..e3289af7f 100644
--- a/manual/Types/selectors.html
+++ b/manual/Types/selectors.html
@@ -86,7 +86,7 @@
by a given user.
<posixGroup>
—Select
files if they have a given POSIX group.
- <posixPermissions>
—Select
+ <posixPermissions>
—Select
files if they have given POSIX permissions.
@@ -925,6 +925,11 @@
Username of the expected owner |
Yes |
+
+ followlinks |
+ Must the selector follow symbolic links? |
+ No; defaults to false (was true before Ant 1.10.4) |
+
PosixGroup Selector
@@ -937,16 +942,21 @@
Since Ant 1.10.4
-
- Attribute |
- Description |
- Required |
-
-
- group |
- POSIX group name |
- Yes |
-
+
+ Attribute |
+ Description |
+ Required |
+
+
+ group |
+ POSIX group name |
+ Yes |
+
+
+ followlinks |
+ Must the selector follow symbolic links? |
+ No; defaults to false |
+
PosixPermissions Selector
@@ -959,16 +969,21 @@
Since Ant 1.10.4
-
- Attribute |
- Description |
- Required |
-
-
- permissions |
- POSIX permissions in string (rwxrwxrwx ) or octal (777 ) format |
- Yes |
-
+
+ Attribute |
+ Description |
+ Required |
+
+
+ permissions |
+ POSIX permissions in string (rwxrwxrwx ) or octal (777 ) format |
+ Yes |
+
+
+ followlinks |
+ Must the selector follow symbolic links? |
+ No; defaults to false |
+
Script Selector
diff --git a/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java b/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
index d37fd2f64..cb21de485 100644
--- a/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
@@ -21,9 +21,11 @@ package org.apache.tools.ant.types.selectors;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.LinkOption;
import java.nio.file.attribute.UserPrincipal;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.PropertyHelper;
/**
* A selector that selects files based on their owner.
@@ -40,14 +42,24 @@ public class OwnedBySelector implements FileSelector {
private String owner;
+ private boolean followLinks = false;
+
/**
- * Sets the User-Name to look for.
+ * Sets the user name to look for.
* @param owner the user name
*/
public void setOwner(String owner) {
this.owner = owner;
}
+ /**
+ * Sets the "follow links" flag.
+ * @param followLinks the user name
+ */
+ public void setFollowLinks(String followLinks) {
+ this.followLinks = PropertyHelper.toBoolean(followLinks);
+ }
+
@Override
public boolean isSelected(File basedir, String filename, File file) {
if (owner == null) {
@@ -55,7 +67,8 @@ public class OwnedBySelector implements FileSelector {
}
if (file != null) {
try {
- UserPrincipal user = Files.getOwner(file.toPath());
+ UserPrincipal user = followLinks ? Files.getOwner(file.toPath())
+ : Files.getOwner(file.toPath(), LinkOption.NOFOLLOW_LINKS);
return user != null && owner.equals(user.getName());
} catch (UnsupportedOperationException | IOException ex) {
// => not the expected owner
diff --git a/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java b/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
index 9c7498531..a72d0fd15 100644
--- a/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
@@ -19,6 +19,7 @@
package org.apache.tools.ant.types.selectors;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.PropertyHelper;
import java.io.File;
import java.io.IOException;
@@ -41,6 +42,8 @@ public class PosixGroupSelector implements FileSelector {
private String group;
+ private boolean followLinks = false;
+
/**
* Sets the group name to look for.
* @param group the group name
@@ -49,13 +52,22 @@ public class PosixGroupSelector implements FileSelector {
this.group = group;
}
+ /**
+ * Sets the "follow links" flag.
+ * @param followLinks the user name
+ */
+ public void setFollowLinks(String followLinks) {
+ this.followLinks = PropertyHelper.toBoolean(followLinks);
+ }
+
@Override
public boolean isSelected(File basedir, String filename, File file) {
if (group == null) {
throw new BuildException("the group attribute is required");
}
try {
- GroupPrincipal actualGroup = Files.readAttributes(file.toPath(),
+ GroupPrincipal actualGroup = followLinks ? Files.readAttributes(file.toPath(),
+ PosixFileAttributes.class).group() : Files.readAttributes(file.toPath(),
PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS).group();
return actualGroup != null && actualGroup.getName().equals(group);
} catch (IOException e) {
diff --git a/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java b/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
index 8cd60ab73..fd6cef71b 100644
--- a/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
+++ b/src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
@@ -19,6 +19,7 @@
package org.apache.tools.ant.types.selectors;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.PropertyHelper;
import org.apache.tools.ant.util.PermissionUtils;
import java.io.File;
@@ -40,6 +41,8 @@ public class PosixPermissionsSelector implements FileSelector {
private String permissions;
+ private boolean followLinks = false;
+
/**
* Sets the permissions to look for.
* @param permissions the permissions string (rwxrwxrwx or octal)
@@ -59,14 +62,23 @@ public class PosixPermissionsSelector implements FileSelector {
}
}
+ /**
+ * Sets the "follow links" flag.
+ * @param followLinks the user name
+ */
+ public void setFollowLinks(String followLinks) {
+ this.followLinks = PropertyHelper.toBoolean(followLinks);
+ }
+
@Override
public boolean isSelected(File basedir, String filename, File file) {
if (permissions == null) {
throw new BuildException("the permissions attribute is required");
}
try {
- return PosixFilePermissions.toString(
- Files.getPosixFilePermissions(file.toPath(), LinkOption.NOFOLLOW_LINKS))
+ return PosixFilePermissions.toString(followLinks
+ ? Files.getPosixFilePermissions(file.toPath())
+ : Files.getPosixFilePermissions(file.toPath(), LinkOption.NOFOLLOW_LINKS))
.equals(permissions);
} catch (IOException e) {
// => not the expected permissions
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
index d73626f20..e8619e4ed 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
@@ -19,14 +19,19 @@
package org.apache.tools.ant.types.selectors;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import java.io.File;
+import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
import java.nio.file.attribute.UserPrincipal;
import org.apache.tools.ant.taskdefs.condition.Os;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -36,18 +41,46 @@ public class OwnedBySelectorTest {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
- @Test
- public void ownedByIsTrueForSelf() throws Exception {
+ private final File TEST_FILE = new File("/etc/passwd");
+
+ private final String SELF = System.getProperty("user.name");
+
+ private final String ROOT = "root";
+
+ private OwnedBySelector s;
+
+ @Before
+ public void setUp() {
// at least on Jenkins the file is owned by "BUILTIN\Administrators"
assumeFalse(Os.isFamily("windows"));
- String self = System.getProperty("user.name");
+
+ s = new OwnedBySelector();
+ }
+
+ @Test
+ public void ownedByIsTrueForSelf() throws Exception {
File file = folder.newFile("f.txt");
UserPrincipal user = Files.getOwner(file.toPath());
- assertEquals(self, user.getName());
+ assertEquals(SELF, user.getName());
- OwnedBySelector s = new OwnedBySelector();
- s.setOwner(self);
+ s.setOwner(SELF);
assertTrue(s.isSelected(null, null, file));
}
+ @Test
+ public void ownedByFollowSymlinks() throws IOException {
+ File target = new File(folder.getRoot(), "link");
+ Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+
+ UserPrincipal root = Files.getOwner(symbolicLink);
+ assertEquals(ROOT, root.getName());
+
+ UserPrincipal user = Files.getOwner(symbolicLink, LinkOption.NOFOLLOW_LINKS);
+ assertEquals(SELF, user.getName());
+
+ s.setOwner(SELF);
+ assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
+ s.setFollowLinks("yes");
+ assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+ }
}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
index 8d4e28ff4..2cb0a213a 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
@@ -9,10 +9,14 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.LinkOption;
+import java.nio.file.Path;
import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributes;
import java.util.Map;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue;
@@ -24,13 +28,15 @@ public class PosixGroupSelectorTest {
private final String GROUP_GETTER = "getGid";
+ private final File TEST_FILE = new File("/etc/passwd");
+
private Class> jaasProviderClass;
private PosixGroupSelector s;
@Before
public void setUp() {
- assumeTrue(Os.isFamily("unix"));
+ assumeTrue("Not POSIX", Os.isFamily("unix"));
String osName = System.getProperty("os.name", "unknown").toLowerCase();
String jaasProviderClassName = osName.contains("sunos")
? "com.sun.security.auth.module.SolarisSystem"
@@ -46,7 +52,7 @@ public class PosixGroupSelectorTest {
}
@Test
- public void PosixGroupIsTrueForSelf() throws Exception {
+ public void posixGroupIsTrueForSelf() throws Exception {
long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER)
.invoke(jaasProviderClass.newInstance());
@@ -61,4 +67,27 @@ public class PosixGroupSelectorTest {
assertTrue(s.isSelected(null, null, file));
}
+ @Test
+ public void posixGroupFollowSymlinks() throws Exception {
+ long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER)
+ .invoke(jaasProviderClass.newInstance());
+
+ File target = new File(folder.getRoot(), "link");
+ Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+ Map linkAttributes = Files.readAttributes(target.toPath(),
+ "unix:group,gid", LinkOption.NOFOLLOW_LINKS);
+ long linkGid = (int) linkAttributes.get("gid");
+ assertEquals("Different GIDs", gid, linkGid);
+
+ GroupPrincipal targetGroup = Files.readAttributes(target.toPath(),
+ PosixFileAttributes.class).group();
+ GroupPrincipal linkGroup = (GroupPrincipal) linkAttributes.get("group");
+ assertNotEquals("Same group name", linkGroup.getName(),
+ targetGroup.getName());
+
+ s.setGroup(linkGroup.getName());
+ assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
+ s.setFollowLinks("yes");
+ assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+ }
}
diff --git a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java
index c72b61ae6..1dde9c482 100644
--- a/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java
+++ b/src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java
@@ -10,9 +10,16 @@ import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.PosixFilePermission;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -35,7 +42,7 @@ public class PosixPermissionsSelectorTest {
@Before
public void setUp() {
- assumeTrue("no POSIX", Os.isFamily("unix"));
+ assumeTrue("Not POSIX", Os.isFamily("unix"));
s = new PosixPermissionsSelector();
}
@@ -54,9 +61,9 @@ public class PosixPermissionsSelectorTest {
public TemporaryFolder folder = new TemporaryFolder();
// requires JUnit 4.12
- @Parameterized.Parameters(name = "legal argument: |{0}|")
+ @Parameterized.Parameters(name = "legal argument (self): |{0}|")
public static Collection data() {
- return Arrays.asList("755", "rwxr-xr-x");
+ return Arrays.asList("750", "rwxr-x---");
}
@Parameterized.Parameter
@@ -64,14 +71,62 @@ public class PosixPermissionsSelectorTest {
@Before
public void setUp() {
- assumeTrue("No POSIX", Os.isFamily("unix"));
+ assumeTrue("Not POSIX", Os.isFamily("unix"));
s = new PosixPermissionsSelector();
}
@Test
- public void PosixPermissionsIsTrueForSelf() throws Exception {
+ public void test() throws Exception {
+ // do not depend on default umask
+ File subFolder = folder.newFolder();
+ Set permissions = new HashSet<>();
+ permissions.add(PosixFilePermission.OWNER_READ);
+ permissions.add(PosixFilePermission.OWNER_WRITE);
+ permissions.add(PosixFilePermission.OWNER_EXECUTE);
+ permissions.add(PosixFilePermission.GROUP_READ);
+ permissions.add(PosixFilePermission.GROUP_EXECUTE);
+ Files.setPosixFilePermissions(subFolder.toPath(), permissions);
+
+ s.setPermissions(argument);
+ assertTrue(s.isSelected(null, null, subFolder));
+ }
+ }
+
+ @RunWith(Parameterized.class)
+ public static class LegalSymbolicLinkArgumentTest {
+
+ private final File TEST_FILE = new File("/etc/passwd");
+
+ private PosixPermissionsSelector s;
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ // requires JUnit 4.12
+ @Parameterized.Parameters(name = "legal argument (link): |{0}|")
+ public static Collection data() {
+ return Arrays.asList("644", "rw-r--r--");
+ }
+
+ @Parameterized.Parameter
+ public String argument;
+
+ @Before
+ public void setUp() {
+ assumeTrue("Not POSIX", Os.isFamily("unix"));
+ s = new PosixPermissionsSelector();
+ }
+
+ @Test
+ public void test() throws Exception {
+ // symlinks have execute bit set by default
+ File target = new File(folder.getRoot(), "link");
+ Path symbolicLink = Files.createSymbolicLink(target.toPath(), TEST_FILE.toPath());
+
s.setPermissions(argument);
- assertTrue(s.isSelected(null, null, folder.newFolder()));
+ assertFalse(s.isSelected(null, null, symbolicLink.toFile()));
+ s.setFollowLinks("yes");
+ assertTrue(s.isSelected(null, null, symbolicLink.toFile()));
}
}