Only set POSIX permissions if needed

Only callers of PathUtils.setPosixPermissions(...) are affected:

- PathUtils.setReadOnly(...)
- PathUtils.deleteFile(..., DeleteOption...)
- CleaningPathVisitor
- DeletingPathVisitor
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ddf8e1c..91700dd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -108,6 +108,11 @@
       <action dev="ggregory" type="fix" issue="IO-469" due-to="Grigory Fadeev, Kristian Rosenvold, Elliotte Rusty Harold">"Self-suppression not permitted" while using BrokenOutput and BrokenInput streams with try-with-resources.</action>
       <action dev="ggregory" type="fix" issue="IO-405" due-to="Elliotte Rusty Harold">Handle zero and negative thresholds #587.</action>
       <action dev="ggregory" type="fix"                due-to="Gary Gregory">Deprecate CountingInputStream in favor of BoundedInputStream.</action>
+      <action dev="ggregory" type="fix"                due-to="Gary Gregory">PathUtils.setPosixPermissions(...) only sets permissions if needed.</action>
+      <action dev="ggregory" type="fix"                due-to="Gary Gregory">PathUtils.setReadOnly(...) only sets permissions if needed.</action>
+      <action dev="ggregory" type="fix"                due-to="Gary Gregory">PathUtils.deleteFile(..., DeleteOption...) only sets permissions if needed.</action>
+      <action dev="ggregory" type="fix"                due-to="Gary Gregory">CleaningPathVisitor only sets permissions if needed.</action>
+      <action dev="ggregory" type="fix"                due-to="Gary Gregory">DeletingPathVisitor only sets permissions if needed.</action>
       <!-- Add -->
       <action dev="ggregory" type="add"                due-to="Gary Gregory">Add and use PathUtils.getFileName(Path, Function&lt;Path, R&gt;).</action>
       <action dev="ggregory" type="add"                due-to="Gary Gregory">Add and use PathUtils.getFileNameString().</action>
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 9d3a30f..f7b118c 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -60,6 +60,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -1518,6 +1519,9 @@
 
     /**
      * Low-level POSIX permission operation to set permissions.
+     * <p>
+     * If the permissions to update are already set, then make no additional calls.
+     * </p>
      *
      * @param path              Set this path's permissions.
      * @param addPermissions    true to add, false to remove.
@@ -1530,12 +1534,15 @@
             final LinkOption... linkOptions) throws IOException {
         if (path != null) {
             final Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(path, linkOptions);
+            final Set<PosixFilePermission> newPermissions = new HashSet<>(permissions);
             if (addPermissions) {
-                permissions.addAll(updatePermissions);
+                newPermissions.addAll(updatePermissions);
             } else {
-                permissions.removeAll(updatePermissions);
+                newPermissions.removeAll(updatePermissions);
             }
-            Files.setPosixFilePermissions(path, permissions);
+            if (!newPermissions.equals(permissions)) {
+                Files.setPosixFilePermissions(path, newPermissions);
+            }
             return true;
         }
         return false;