You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/01/15 00:49:31 UTC

[commons-io] branch master updated: [IO-701] Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git


The following commit(s) were added to refs/heads/master by this push:
     new 186e999  [IO-701] Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186.
186e999 is described below

commit 186e999374f0ff249b37d75100f05b7c7acb14b7
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Jan 14 19:49:26 2021 -0500

    [IO-701] Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView
    #186.
    
    Clean ups post PR merge.
---
 src/changes/changes.xml                            |   3 +
 src/main/java/org/apache/commons/io/FileUtils.java |   2 +-
 .../java/org/apache/commons/io/file/PathUtils.java |  16 +--
 .../io/FileUtilsDeleteDirectoryBaseTestCase.java   | 123 ++++++++++-----------
 .../io/FileUtilsDeleteDirectoryLinuxTestCase.java  |  94 ++++++++--------
 .../io/FileUtilsDeleteDirectoryWinTestCase.java    |  43 +++----
 6 files changed, 141 insertions(+), 140 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ba34b86..8fad977 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -90,6 +90,9 @@ The <action> type attribute can be add,update,fix,remove.
       <action issue="IO-688" dev="ggregory" type="fix" due-to="Michael Ernst, Gary Gregory">
         CopyUtils deprecation message gives wrong version.
       </action>
+      <action issue="IO-701" dev="ggregory" type="fix" due-to="Gary Gregory">
+        Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186.
+      </action>
       <!-- ADD -->
       <action dev="ggregory" type="add" due-to="Gary Gregory">
         Add FileSystemProviders class.
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 7df6290..4aa0756 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -1167,7 +1167,7 @@ public class FileUtils {
      */
     public static File delete(final File file) throws IOException {
         Objects.requireNonNull(file, "file");
-        java.nio.file.Files.delete(file.toPath());
+        Files.delete(file.toPath());
         return file;
     }
 
diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java
index 9cb1ec1..06474b2 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -870,21 +870,21 @@ public final class PathUtils {
      * @since 2.8.0
      */
     public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions)
-            throws IOException {
+        throws IOException {
         final List<Exception> causeList = new ArrayList<>(2);
         final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class,
-                linkOptions);
+            linkOptions);
         if (fileAttributeView != null) {
             try {
                 fileAttributeView.setReadOnly(readOnly);
                 return path;
             } catch (IOException e) {
-                //ignore for now, retry with PosixFileAttributeView
+                // ignore for now, retry with PosixFileAttributeView
                 causeList.add(e);
             }
         }
         final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path,
-                PosixFileAttributeView.class, linkOptions);
+            PosixFileAttributeView.class, linkOptions);
         if (posixFileAttributeView != null) {
             // Works on Windows but not on Ubuntu:
             // Files.setAttribute(path, "unix:readonly", readOnly, options);
@@ -895,17 +895,17 @@ public final class PathUtils {
             permissions.remove(PosixFilePermission.GROUP_WRITE);
             permissions.remove(PosixFilePermission.OTHERS_WRITE);
             try {
-                 return Files.setPosixFilePermissions(path, permissions);
+                return Files.setPosixFilePermissions(path, permissions);
             } catch (IOException e) {
                 causeList.add(e);
             }
         }
         if (!causeList.isEmpty()) {
-             throw new IOExceptionList(causeList);
+            throw new IOExceptionList(causeList);
         }
         throw new IOException(
-                String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path,
-                        Arrays.toString(linkOptions)));
+            String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path,
+                Arrays.toString(linkOptions)));
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
index 3aacbe8..b99c1dd 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java
@@ -22,8 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 import java.nio.file.Files;
-import java.nio.file.attribute.FileAttribute;
-
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
@@ -35,72 +33,41 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase {
     @TempDir
     public File top;
 
-    // -----------------------------------------------------------------------
-
-    @Test
-    public void testDeletesRegular() throws Exception {
-        final File nested = new File(top, "nested");
-        assertTrue(nested.mkdirs());
-
-        assertEquals(1, top.list().length);
-
-        assertEquals(0, nested.list().length);
-
-        FileUtils.deleteDirectory(nested);
-
-        assertEquals(0, top.list().length);
-    }
+    protected abstract boolean setupSymlink(final File res, final File link) throws Exception;
 
     @Test
-    public void testDeletesNested() throws Exception {
-        final File nested = new File(top, "nested");
-        assertTrue(nested.mkdirs());
-
-        assertEquals(1, top.list().length);
-
-        FileUtils.touch(new File(nested, "regular"));
-        FileUtils.touch(new File(nested, ".hidden"));
-
-        assertEquals(2, nested.list().length);
-
-		FileUtils.deleteDirectory(nested);
-
-        assertEquals(0, top.list().length);
-    }
+    public void testDeleteDirWithASymlinkDir() throws Exception {
 
-    @Test
-    public void testDeleteDirWithSymlinkFile() throws Exception {
         final File realOuter = new File(top, "realouter");
         assertTrue(realOuter.mkdirs());
 
         final File realInner = new File(realOuter, "realinner");
         assertTrue(realInner.mkdirs());
 
-        final File realFile = new File(realInner, "file1");
-        FileUtils.touch(realFile);
-
+        FileUtils.touch(new File(realInner, "file1"));
         assertEquals(1, realInner.list().length);
 
-        final File randomFile = new File(top, "randomfile");
-        FileUtils.touch(randomFile);
+        final File randomDirectory = new File(top, "randomDir");
+        assertTrue(randomDirectory.mkdirs());
 
-        final File symlinkFile = new File(realInner, "fakeinner");
-        assertTrue(setupSymlink(randomFile, symlinkFile));
+        FileUtils.touch(new File(randomDirectory, "randomfile"));
+        assertEquals(1, randomDirectory.list().length);
 
-        assertEquals(2, realInner.list().length);
-        assertEquals(2, top.list().length);
+        final File symlinkDirectory = new File(realOuter, "fakeinner");
+        assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
 
-        // assert the real directory were removed including the symlink
+        assertEquals(1, symlinkDirectory.list().length);
+
+        // assert contents of the real directory were removed including the symlink
         FileUtils.deleteDirectory(realOuter);
         assertEquals(1, top.list().length);
 
         // ensure that the contents of the symlink were NOT removed.
-        assertTrue(randomFile.exists());
-        assertFalse(symlinkFile.exists());
+        assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
     }
 
     @Test
-    public void testDeleteDirWithASymlinkDir() throws Exception {
+    public void testDeleteDirWithASymlinkDir2() throws Exception {
 
         final File realOuter = new File(top, "realouter");
         assertTrue(realOuter.mkdirs());
@@ -118,7 +85,7 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase {
         assertEquals(1, randomDirectory.list().length);
 
         final File symlinkDirectory = new File(realOuter, "fakeinner");
-        assertTrue(setupSymlink(randomDirectory, symlinkDirectory));
+        Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath());
 
         assertEquals(1, symlinkDirectory.list().length);
 
@@ -131,36 +98,36 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase {
     }
 
     @Test
-    public void testDeleteDirWithASymlinkDir2() throws Exception {
-
+    public void testDeleteDirWithSymlinkFile() throws Exception {
         final File realOuter = new File(top, "realouter");
         assertTrue(realOuter.mkdirs());
 
         final File realInner = new File(realOuter, "realinner");
         assertTrue(realInner.mkdirs());
 
-        FileUtils.touch(new File(realInner, "file1"));
-        assertEquals(1, realInner.list().length);
+        final File realFile = new File(realInner, "file1");
+        FileUtils.touch(realFile);
 
-        final File randomDirectory = new File(top, "randomDir");
-        assertTrue(randomDirectory.mkdirs());
+        assertEquals(1, realInner.list().length);
 
-        FileUtils.touch(new File(randomDirectory, "randomfile"));
-        assertEquals(1, randomDirectory.list().length);
+        final File randomFile = new File(top, "randomfile");
+        FileUtils.touch(randomFile);
 
-        final File symlinkDirectory = new File(realOuter, "fakeinner");
-        Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath());
+        final File symlinkFile = new File(realInner, "fakeinner");
+        assertTrue(setupSymlink(randomFile, symlinkFile));
 
-        assertEquals(1, symlinkDirectory.list().length);
+        assertEquals(2, realInner.list().length);
+        assertEquals(2, top.list().length);
 
-        // assert contents of the real directory were removed including the symlink
+        // assert the real directory were removed including the symlink
         FileUtils.deleteDirectory(realOuter);
         assertEquals(1, top.list().length);
 
         // ensure that the contents of the symlink were NOT removed.
-        assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
+        assertTrue(randomFile.exists());
+        assertFalse(symlinkFile.exists());
     }
-    
+
     @Test
     public void testDeleteParentSymlink() throws Exception {
         final File realParent = new File(top, "realparent");
@@ -227,7 +194,35 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase {
         assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed");
     }
 
-    protected abstract boolean setupSymlink(final File res, final File link) throws Exception;
+    @Test
+    public void testDeletesNested() throws Exception {
+        final File nested = new File(top, "nested");
+        assertTrue(nested.mkdirs());
 
-}
+        assertEquals(1, top.list().length);
 
+        FileUtils.touch(new File(nested, "regular"));
+        FileUtils.touch(new File(nested, ".hidden"));
+
+        assertEquals(2, nested.list().length);
+
+        FileUtils.deleteDirectory(nested);
+
+        assertEquals(0, top.list().length);
+    }
+
+    @Test
+    public void testDeletesRegular() throws Exception {
+        final File nested = new File(top, "nested");
+        assertTrue(nested.mkdirs());
+
+        assertEquals(1, top.list().length);
+
+        assertEquals(0, nested.list().length);
+
+        FileUtils.deleteDirectory(nested);
+
+        assertEquals(0, top.list().length);
+    }
+
+}
diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java
index ad54483..22857b9 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java
@@ -33,27 +33,42 @@ import org.junit.jupiter.api.condition.OS;
 @DisabledOnOs(OS.WINDOWS)
 public class FileUtilsDeleteDirectoryLinuxTestCase extends FileUtilsDeleteDirectoryBaseTestCase {
 
-	@Test
-	public void testThrowsOnNullList() throws Exception {
-		final File nested = new File(top, "nested");
-		assertTrue(nested.mkdirs());
+	/** Only runs on Linux. */
+	private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException {
+		final List<String> args = new ArrayList<>();
+		args.add("chmod");
 
-		// test wont work if we can't restrict permissions on the
-		// directory, so skip it.
-		assumeTrue(chmod(nested, 0, false));
+		if (recurse) {
+			args.add("-R");
+		}
+
+		args.add(Integer.toString(mode));
+		args.add(file.getAbsolutePath());
+
+		final Process proc;
 
 		try {
-			// cleanDirectory calls forceDelete
-			FileUtils.deleteDirectory(nested);
-			fail("expected IOException");
+			proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
 		} catch (final IOException e) {
-			assertEquals("Unknown I/O error listing contents of directory: " + nested.getAbsolutePath(),
-					e.getMessage());
-		} finally {
-			chmod(nested, 755, false);
-			FileUtils.deleteDirectory(nested);
+			return false;
 		}
-		assertEquals(0, top.list().length);
+		return proc.waitFor() == 0;
+	}
+
+	@Override
+	protected boolean setupSymlink(final File res, final File link) throws Exception {
+		// create symlink
+		final List<String> args = new ArrayList<>();
+		args.add("ln");
+		args.add("-s");
+
+		args.add(res.getAbsolutePath());
+		args.add(link.getAbsolutePath());
+
+		final Process proc;
+
+		proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
+		return proc.waitFor() == 0;
 	}
 
 	@Test
@@ -80,41 +95,26 @@ public class FileUtilsDeleteDirectoryLinuxTestCase extends FileUtilsDeleteDirect
 		assertEquals(0, top.list().length);
 	}
 
-	@Override
-	protected boolean setupSymlink(File res, File link) throws Exception {
-		// create symlink
-		final List<String> args = new ArrayList<>();
-		args.add("ln");
-		args.add("-s");
-
-		args.add(res.getAbsolutePath());
-		args.add(link.getAbsolutePath());
-
-		final Process proc;
-
-		proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
-		return proc.waitFor() == 0;
-	}
-
-	/** Only runs on Linux. */
-	private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException {
-		final List<String> args = new ArrayList<>();
-		args.add("chmod");
-
-		if (recurse) {
-			args.add("-R");
-		}
-
-		args.add(Integer.toString(mode));
-		args.add(file.getAbsolutePath());
+	@Test
+	public void testThrowsOnNullList() throws Exception {
+		final File nested = new File(top, "nested");
+		assertTrue(nested.mkdirs());
 
-		final Process proc;
+		// test wont work if we can't restrict permissions on the
+		// directory, so skip it.
+		assumeTrue(chmod(nested, 0, false));
 
 		try {
-			proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
+			// cleanDirectory calls forceDelete
+			FileUtils.deleteDirectory(nested);
+			fail("expected IOException");
 		} catch (final IOException e) {
-			return false;
+			assertEquals("Unknown I/O error listing contents of directory: " + nested.getAbsolutePath(),
+					e.getMessage());
+		} finally {
+			chmod(nested, 755, false);
+			FileUtils.deleteDirectory(nested);
 		}
-		return proc.waitFor() == 0;
+		assertEquals(0, top.list().length);
 	}
 }
diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java
index 4ed4eda..5ae3171 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java
@@ -17,6 +17,8 @@
 package org.apache.commons.io;
 
 import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -26,25 +28,26 @@ import org.junit.jupiter.api.condition.OS;
 @EnabledOnOs(OS.WINDOWS)
 public class FileUtilsDeleteDirectoryWinTestCase extends FileUtilsDeleteDirectoryBaseTestCase {
 
-	@Override
-	protected boolean setupSymlink(File res, File link) throws Exception {
-		// create symlink
-		final List<String> args = new ArrayList<>();
-		args.add("cmd");
-		args.add("/C");
-		args.add("mklink");
-
-		if (res.isDirectory()) {
-			args.add("/D");
-		}
-
-		args.add(link.getAbsolutePath());
-		args.add(res.getAbsolutePath());
-
-		final Process proc;
-
-		proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
-		return proc.waitFor() == 0;
-	}
+    @Override
+    protected boolean setupSymlink(final File res, final File link) throws Exception {
+        // create symlink
+        final List<String> args = new ArrayList<>();
+        args.add("cmd");
+        args.add("/C");
+        args.add("mklink");
+
+        if (res.isDirectory()) {
+            args.add("/D");
+        }
+
+        args.add(link.getAbsolutePath());
+        args.add(res.getAbsolutePath());
+
+        final Process proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()]));
+        final InputStream errorStream = proc.getErrorStream();
+        final int rc = proc.waitFor();
+        System.err.println(IOUtils.toString(errorStream, Charset.defaultCharset()));
+        return rc == 0;
+    }
 
 }