Browse Source

Bz 22370: followlinks attribute

master
Gintas Grigelionis 7 years ago
parent
commit
35a84fea1a
7 changed files with 209 additions and 40 deletions
  1. +36
    -21
      manual/Types/selectors.html
  2. +15
    -2
      src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java
  3. +13
    -1
      src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java
  4. +14
    -2
      src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java
  5. +39
    -6
      src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java
  6. +31
    -2
      src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java
  7. +61
    -6
      src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java

+ 36
- 21
manual/Types/selectors.html View File

@@ -86,7 +86,7 @@
by a given user.</li> by a given user.</li>
<li><a href="#posixGroup"><code>&lt;posixGroup&gt;</code>&mdash;Select <li><a href="#posixGroup"><code>&lt;posixGroup&gt;</code>&mdash;Select
files if they have a given POSIX group.</li> files if they have a given POSIX group.</li>
<li><a href="#posixPermissions"><code>&lt;posixPermissions&gt;</code>&mdash;Select
<li><a href="#posixPermissions"><code>&lt;posixPermissions&gt;</code></a>&mdash;Select
files if they have given POSIX permissions.</li> files if they have given POSIX permissions.</li>
</ul> </ul>


@@ -925,6 +925,11 @@
<td>Username of the expected owner</td> <td>Username of the expected owner</td>
<td>Yes</td> <td>Yes</td>
</tr> </tr>
<tr>
<td>followlinks</td>
<td>Must the selector follow symbolic links?</td>
<td>No; defaults to <q>false</q> (was <q>true</q> before Ant 1.10.4)</td>
</tr>
</table> </table>


<h4 id="posixGroup">PosixGroup Selector</h4> <h4 id="posixGroup">PosixGroup Selector</h4>
@@ -937,16 +942,21 @@
<p><em>Since Ant 1.10.4</em></p> <p><em>Since Ant 1.10.4</em></p>


<table class="attr"> <table class="attr">
<tr>
<th scope="col">Attribute</th>
<th scope="col">Description</th>
<th scope="col">Required</th>
</tr>
<tr>
<td>group</td>
<td>POSIX group name</td>
<td>Yes</td>
</tr>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Description</th>
<th scope="col">Required</th>
</tr>
<tr>
<td>group</td>
<td>POSIX group name</td>
<td>Yes</td>
</tr>
<tr>
<td>followlinks</td>
<td>Must the selector follow symbolic links?</td>
<td>No; defaults to <q>false</q></td>
</tr>
</table> </table>


<h4 id="posixPermissions">PosixPermissions Selector</h4> <h4 id="posixPermissions">PosixPermissions Selector</h4>
@@ -959,16 +969,21 @@
<p><em>Since Ant 1.10.4</em></p> <p><em>Since Ant 1.10.4</em></p>


<table class="attr"> <table class="attr">
<tr>
<th scope="col">Attribute</th>
<th scope="col">Description</th>
<th scope="col">Required</th>
</tr>
<tr>
<td>permissions</td>
<td>POSIX permissions in string (<q>rwxrwxrwx</q>) or octal (<q>777</q>) format</td>
<td>Yes</td>
</tr>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Description</th>
<th scope="col">Required</th>
</tr>
<tr>
<td>permissions</td>
<td>POSIX permissions in string (<q>rwxrwxrwx</q>) or octal (<q>777</q>) format</td>
<td>Yes</td>
</tr>
<tr>
<td>followlinks</td>
<td>Must the selector follow symbolic links?</td>
<td>No; defaults to <q>false</q></td>
</tr>
</table> </table>


<h4 id="scriptselector">Script Selector</h4> <h4 id="scriptselector">Script Selector</h4>


+ 15
- 2
src/main/org/apache/tools/ant/types/selectors/OwnedBySelector.java View File

@@ -21,9 +21,11 @@ package org.apache.tools.ant.types.selectors;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.attribute.UserPrincipal; import java.nio.file.attribute.UserPrincipal;


import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.PropertyHelper;


/** /**
* A selector that selects files based on their owner. * A selector that selects files based on their owner.
@@ -40,14 +42,24 @@ public class OwnedBySelector implements FileSelector {


private String owner; 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 * @param owner the user name
*/ */
public void setOwner(String owner) { public void setOwner(String owner) {
this.owner = 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 @Override
public boolean isSelected(File basedir, String filename, File file) { public boolean isSelected(File basedir, String filename, File file) {
if (owner == null) { if (owner == null) {
@@ -55,7 +67,8 @@ public class OwnedBySelector implements FileSelector {
} }
if (file != null) { if (file != null) {
try { 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()); return user != null && owner.equals(user.getName());
} catch (UnsupportedOperationException | IOException ex) { } catch (UnsupportedOperationException | IOException ex) {
// => not the expected owner // => not the expected owner


+ 13
- 1
src/main/org/apache/tools/ant/types/selectors/PosixGroupSelector.java View File

@@ -19,6 +19,7 @@
package org.apache.tools.ant.types.selectors; package org.apache.tools.ant.types.selectors;


import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.PropertyHelper;


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -41,6 +42,8 @@ public class PosixGroupSelector implements FileSelector {


private String group; private String group;


private boolean followLinks = false;

/** /**
* Sets the group name to look for. * Sets the group name to look for.
* @param group the group name * @param group the group name
@@ -49,13 +52,22 @@ public class PosixGroupSelector implements FileSelector {
this.group = group; this.group = group;
} }


/**
* Sets the "follow links" flag.
* @param followLinks the user name
*/
public void setFollowLinks(String followLinks) {
this.followLinks = PropertyHelper.toBoolean(followLinks);
}

@Override @Override
public boolean isSelected(File basedir, String filename, File file) { public boolean isSelected(File basedir, String filename, File file) {
if (group == null) { if (group == null) {
throw new BuildException("the group attribute is required"); throw new BuildException("the group attribute is required");
} }
try { 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(); PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS).group();
return actualGroup != null && actualGroup.getName().equals(group); return actualGroup != null && actualGroup.getName().equals(group);
} catch (IOException e) { } catch (IOException e) {


+ 14
- 2
src/main/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java View File

@@ -19,6 +19,7 @@
package org.apache.tools.ant.types.selectors; package org.apache.tools.ant.types.selectors;


import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.PropertyHelper;
import org.apache.tools.ant.util.PermissionUtils; import org.apache.tools.ant.util.PermissionUtils;


import java.io.File; import java.io.File;
@@ -40,6 +41,8 @@ public class PosixPermissionsSelector implements FileSelector {


private String permissions; private String permissions;


private boolean followLinks = false;

/** /**
* Sets the permissions to look for. * Sets the permissions to look for.
* @param permissions the permissions string (rwxrwxrwx or octal) * @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 @Override
public boolean isSelected(File basedir, String filename, File file) { public boolean isSelected(File basedir, String filename, File file) {
if (permissions == null) { if (permissions == null) {
throw new BuildException("the permissions attribute is required"); throw new BuildException("the permissions attribute is required");
} }
try { 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); .equals(permissions);
} catch (IOException e) { } catch (IOException e) {
// => not the expected permissions // => not the expected permissions


+ 39
- 6
src/tests/junit/org/apache/tools/ant/types/selectors/OwnedBySelectorTest.java View File

@@ -19,14 +19,19 @@
package org.apache.tools.ant.types.selectors; package org.apache.tools.ant.types.selectors;


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeFalse;


import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.UserPrincipal; import java.nio.file.attribute.UserPrincipal;


import org.apache.tools.ant.taskdefs.condition.Os; import org.apache.tools.ant.taskdefs.condition.Os;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@@ -36,18 +41,46 @@ public class OwnedBySelectorTest {
@Rule @Rule
public TemporaryFolder folder = new TemporaryFolder(); 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" // at least on Jenkins the file is owned by "BUILTIN\Administrators"
assumeFalse(Os.isFamily("windows")); 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"); File file = folder.newFile("f.txt");
UserPrincipal user = Files.getOwner(file.toPath()); 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)); 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()));
}
} }

+ 31
- 2
src/tests/junit/org/apache/tools/ant/types/selectors/PosixGroupSelectorTest.java View File

@@ -9,10 +9,14 @@ import org.junit.rules.TemporaryFolder;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.LinkOption; import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.attribute.GroupPrincipal; import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributes;
import java.util.Map; import java.util.Map;


import static org.junit.Assert.assertEquals; 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.Assert.assertTrue;
import static org.junit.Assume.assumeNoException; import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeTrue; import static org.junit.Assume.assumeTrue;
@@ -24,13 +28,15 @@ public class PosixGroupSelectorTest {


private final String GROUP_GETTER = "getGid"; private final String GROUP_GETTER = "getGid";


private final File TEST_FILE = new File("/etc/passwd");

private Class<?> jaasProviderClass; private Class<?> jaasProviderClass;


private PosixGroupSelector s; private PosixGroupSelector s;


@Before @Before
public void setUp() { public void setUp() {
assumeTrue(Os.isFamily("unix"));
assumeTrue("Not POSIX", Os.isFamily("unix"));
String osName = System.getProperty("os.name", "unknown").toLowerCase(); String osName = System.getProperty("os.name", "unknown").toLowerCase();
String jaasProviderClassName = osName.contains("sunos") String jaasProviderClassName = osName.contains("sunos")
? "com.sun.security.auth.module.SolarisSystem" ? "com.sun.security.auth.module.SolarisSystem"
@@ -46,7 +52,7 @@ public class PosixGroupSelectorTest {
} }


@Test @Test
public void PosixGroupIsTrueForSelf() throws Exception {
public void posixGroupIsTrueForSelf() throws Exception {
long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER) long gid = (long) jaasProviderClass.getMethod(GROUP_GETTER)
.invoke(jaasProviderClass.newInstance()); .invoke(jaasProviderClass.newInstance());


@@ -61,4 +67,27 @@ public class PosixGroupSelectorTest {
assertTrue(s.isSelected(null, null, file)); 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<String, Object> 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()));
}
} }

+ 61
- 6
src/tests/junit/org/apache/tools/ant/types/selectors/PosixPermissionsSelectorTest.java View File

@@ -10,9 +10,16 @@ import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Parameterized; 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.Arrays;
import java.util.Collection; 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.Assert.assertTrue;
import static org.junit.Assume.assumeTrue; import static org.junit.Assume.assumeTrue;


@@ -35,7 +42,7 @@ public class PosixPermissionsSelectorTest {


@Before @Before
public void setUp() { public void setUp() {
assumeTrue("no POSIX", Os.isFamily("unix"));
assumeTrue("Not POSIX", Os.isFamily("unix"));
s = new PosixPermissionsSelector(); s = new PosixPermissionsSelector();
} }


@@ -54,9 +61,9 @@ public class PosixPermissionsSelectorTest {
public TemporaryFolder folder = new TemporaryFolder(); public TemporaryFolder folder = new TemporaryFolder();


// requires JUnit 4.12 // requires JUnit 4.12
@Parameterized.Parameters(name = "legal argument: |{0}|")
@Parameterized.Parameters(name = "legal argument (self): |{0}|")
public static Collection<String> data() { public static Collection<String> data() {
return Arrays.asList("755", "rwxr-xr-x");
return Arrays.asList("750", "rwxr-x---");
} }


@Parameterized.Parameter @Parameterized.Parameter
@@ -64,14 +71,62 @@ public class PosixPermissionsSelectorTest {


@Before @Before
public void setUp() { public void setUp() {
assumeTrue("No POSIX", Os.isFamily("unix"));
assumeTrue("Not POSIX", Os.isFamily("unix"));
s = new PosixPermissionsSelector(); s = new PosixPermissionsSelector();
} }


@Test @Test
public void PosixPermissionsIsTrueForSelf() throws Exception {
public void test() throws Exception {
// do not depend on default umask
File subFolder = folder.newFolder();
Set<PosixFilePermission> 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<String> 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); 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()));
} }
} }




Loading…
Cancel
Save