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 dc3dd7c15 [IO-808] non writeable destinations are I/O errors (#582)
dc3dd7c15 is described below

commit dc3dd7c15fdfe76f7c78f43f8e48cc9e8f3744dc
Author: Elliotte Rusty Harold <elh...@users.noreply.github.com>
AuthorDate: Thu Feb 8 20:57:51 2024 -0500

    [IO-808] non writeable destinations are I/O errors (#582)
    
    * non writeable destinations are I/O errors
    
    * remove requireCanWrite
---
 src/main/java/org/apache/commons/io/FileUtils.java | 50 +++++++---------------
 .../java/org/apache/commons/io/FileUtilsTest.java  | 12 ++++++
 2 files changed, 28 insertions(+), 34 deletions(-)

diff --git a/src/main/java/org/apache/commons/io/FileUtils.java 
b/src/main/java/org/apache/commons/io/FileUtils.java
index 02a0c2dde..8a9926003 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -518,9 +518,9 @@ public class FileUtils {
      * @param destDir the new directory, must not be {@code null}.
      * @throws NullPointerException if any of the given {@link File}s are 
{@code null}.
      * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory,
-     *     the source and the destination directory are the same, or the 
destination is not writable
+     *     the source and the destination directory are the same
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IOException if an error occurs or setting the last-modified 
time didn't succeed.
+     * @throws IOException if an error occurs, the destination is not 
writable, or setting the last-modified time didn't succeed
      * @since 1.1
      */
     public static void copyDirectory(final File srcDir, final File destDir) 
throws IOException {
@@ -545,10 +545,10 @@ public class FileUtils {
      * @param srcDir an existing directory to copy, must not be {@code null}.
      * @param destDir the new directory, must not be {@code null}.
      * @param preserveFileDate true if the file date of the copy should be the 
same as the original.
-     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory,
-     *     the source and the destination directory are the same, or the 
destination is not writable
+     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory, or
+     *     the source and the destination directory are the same
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IOException if an error occurs or setting the last-modified 
time didn't succeed.
+     * @throws IOException if an error occurs, the destination is not 
writable, or setting the last-modified time didn't succeed
      * @since 1.1
      */
     public static void copyDirectory(final File srcDir, final File destDir, 
final boolean preserveFileDate)
@@ -595,10 +595,10 @@ public class FileUtils {
      * @param destDir the new directory, must not be {@code null}.
      * @param filter the filter to apply, null means copy all directories and 
files should be the same as the original.
      * @throws NullPointerException if any of the given {@link File}s are 
{@code null}.
-     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory,
-     *     the source and the destination directory are the same, or the 
destination is not writable
+     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory, or
+     *     the source and the destination directory are the same
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IOException if an error occurs or setting the last-modified 
time didn't succeed.
+     * @throws IOException if an error occurs, the destination is not 
writable, or setting the last-modified time didn't succeed
      * @since 1.4
      */
     public static void copyDirectory(final File srcDir, final File destDir, 
final FileFilter filter)
@@ -699,10 +699,10 @@ public class FileUtils {
      * @param preserveFileDate true if the file date of the copy should be the 
same as the original
      * @param copyOptions options specifying how the copy should be done, for 
example {@link StandardCopyOption}.
      * @throws NullPointerException if any of the given {@link File}s are 
{@code null}.
-     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory,
-     *     the source and the destination directory are the same, or the 
destination is not writable
+     * @throws IllegalArgumentException if {@code srcDir} exists but is not a 
directory, or
+     *     the source and the destination directory are the same
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IOException if an error occurs or setting the last-modified 
time didn't succeed.
+     * @throws IOException if an error occurs, the destination is not 
writable, or setting the last-modified time didn't succeed
      * @since 2.8.0
      */
     public static void copyDirectory(final File srcDir, final File destDir, 
final FileFilter fileFilter, final boolean preserveFileDate,
@@ -749,7 +749,7 @@ public class FileUtils {
      * @throws NullPointerException if any of the given {@link File}s are 
{@code null}.
      * @throws IllegalArgumentException if the source or destination is 
invalid.
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IOException if an error occurs or setting the last-modified 
time didn't succeed.
+     * @throws IOException if an error occurs, the destination is not 
writable, or setting the last-modified time didn't succeed
      * @since 1.2
      */
     public static void copyDirectoryToDirectory(final File sourceDir, final 
File destinationDir) throws IOException {
@@ -838,9 +838,10 @@ public class FileUtils {
      * @param copyOptions options specifying how the copy should be done, for 
example {@link StandardCopyOption}.
      * @throws NullPointerException if any of the given {@link File}s are 
{@code null}.
      * @throws FileNotFoundException if the source does not exist.
-     * @throws IllegalArgumentException if {@code srcFile} or {@code destFile} 
is not a file, or {@code destFile} is not writable
+     * @throws IllegalArgumentException if {@code srcFile} or {@code destFile} 
is not a file
      * @throws IOException if the output file length is not the same as the 
input file length after the copy completes.
-     * @throws IOException if an I/O error occurs, or setting the 
last-modified time didn't succeed.
+     * @throws IOException if an I/O error occurs, setting the last-modified 
time didn't succeed,
+     *     or the destination is not writable
      * @see #copyFileToDirectory(File, File, boolean)
      * @since 2.8.0
      */
@@ -851,7 +852,6 @@ public class FileUtils {
         createParentDirectories(destFile);
         if (destFile.exists()) {
             checkFileExists(destFile, "destFile");
-            requireCanWrite(destFile, "destFile");
         }
 
         final Path srcPath = srcFile.toPath();
@@ -1347,7 +1347,6 @@ public class FileUtils {
         final File[] srcFiles = listFiles(srcDir, fileFilter);
         requireDirectoryIfExists(destDir, "destDir");
         mkdirs(destDir);
-        requireCanWrite(destDir, "destDir");
         for (final File srcFile : srcFiles) {
             final File dstFile = new File(destDir, srcFile.getName());
             if (exclusionList == null || 
!exclusionList.contains(srcFile.getCanonicalPath())) {
@@ -2623,15 +2622,13 @@ public class FileUtils {
      * @return a new {@link FileOutputStream} for the specified file
      * @throws NullPointerException if the file object is {@code null}.
      * @throws IllegalArgumentException if the file object is a directory
-     * @throws IllegalArgumentException if the file is not writable.
-     * @throws IOException if the directories could not be created.
+     * @throws IOException if the directories could not be created, or the 
file is not writable
      * @since 2.1
      */
     public static FileOutputStream openOutputStream(final File file, final 
boolean append) throws IOException {
         Objects.requireNonNull(file, "file");
         if (file.exists()) {
             checkIsFile(file, "file");
-            requireCanWrite(file, "file");
         } else {
             createParentDirectories(file);
         }
@@ -2774,21 +2771,6 @@ public class FileUtils {
         }
     }
 
-    /**
-     * Throws an {@link IllegalArgumentException} if the file is not writable. 
This provides a more precise exception
-     * message than a plain access denied.
-     *
-     * @param file The file to test.
-     * @param name The parameter name to use in the exception message.
-     * @throws NullPointerException if the given {@link File} is {@code null}.
-     * @throws IllegalArgumentException if the file is not writable.
-     */
-    private static void requireCanWrite(final File file, final String name) {
-        if (!file.canWrite()) {
-            throw new IllegalArgumentException("File parameter '" + name + " 
is not writable: '" + file + "'");
-        }
-    }
-
     /**
      * Requires that the given {@link File} exists and is a directory.
      *
diff --git a/src/test/java/org/apache/commons/io/FileUtilsTest.java 
b/src/test/java/org/apache/commons/io/FileUtilsTest.java
index 53f00d0b4..efd139228 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsTest.java
@@ -1242,6 +1242,18 @@ public class FileUtilsTest extends AbstractTempDirTest {
             "Should not be able to copy a file into the same directory as 
itself");
     }
 
+    @Test
+    public void testCopyFileToReadOnlyDirectory() throws Exception {
+        final File directory = new File(tempDirFile, "readonly");
+        if (!directory.exists()) {
+            assumeTrue(directory.mkdirs());
+        }
+        assumeTrue(directory.setWritable(false));
+
+        assertThrows(IOException.class, () -> 
FileUtils.copyFileToDirectory(testFile1, directory),
+            "Should not be able to copy a file into a readonly directory");
+    }
+
     @Test
     public void testCopyFile2() throws Exception {
         final File destination = new File(tempDirFile, "copy2.txt");

Reply via email to