Skip to content

Commit dc3dd7c

Browse files
authored
[IO-808] non writeable destinations are I/O errors (#582)
* non writeable destinations are I/O errors * remove requireCanWrite
1 parent 4acc361 commit dc3dd7c

2 files changed

Lines changed: 28 additions & 34 deletions

File tree

src/main/java/org/apache/commons/io/FileUtils.java

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -518,9 +518,9 @@ public static File[] convertFileCollectionToFileArray(final Collection<File> fil
518518
* @param destDir the new directory, must not be {@code null}.
519519
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
520520
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
521-
* the source and the destination directory are the same, or the destination is not writable
521+
* the source and the destination directory are the same
522522
* @throws FileNotFoundException if the source does not exist.
523-
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
523+
* @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
524524
* @since 1.1
525525
*/
526526
public static void copyDirectory(final File srcDir, final File destDir) throws IOException {
@@ -545,10 +545,10 @@ public static void copyDirectory(final File srcDir, final File destDir) throws I
545545
* @param srcDir an existing directory to copy, must not be {@code null}.
546546
* @param destDir the new directory, must not be {@code null}.
547547
* @param preserveFileDate true if the file date of the copy should be the same as the original.
548-
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
549-
* the source and the destination directory are the same, or the destination is not writable
548+
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
549+
* the source and the destination directory are the same
550550
* @throws FileNotFoundException if the source does not exist.
551-
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
551+
* @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
552552
* @since 1.1
553553
*/
554554
public static void copyDirectory(final File srcDir, final File destDir, final boolean preserveFileDate)
@@ -595,10 +595,10 @@ public static void copyDirectory(final File srcDir, final File destDir, final bo
595595
* @param destDir the new directory, must not be {@code null}.
596596
* @param filter the filter to apply, null means copy all directories and files should be the same as the original.
597597
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
598-
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
599-
* the source and the destination directory are the same, or the destination is not writable
598+
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
599+
* the source and the destination directory are the same
600600
* @throws FileNotFoundException if the source does not exist.
601-
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
601+
* @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
602602
* @since 1.4
603603
*/
604604
public static void copyDirectory(final File srcDir, final File destDir, final FileFilter filter)
@@ -699,10 +699,10 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
699699
* @param preserveFileDate true if the file date of the copy should be the same as the original
700700
* @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.
701701
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
702-
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
703-
* the source and the destination directory are the same, or the destination is not writable
702+
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
703+
* the source and the destination directory are the same
704704
* @throws FileNotFoundException if the source does not exist.
705-
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
705+
* @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
706706
* @since 2.8.0
707707
*/
708708
public static void copyDirectory(final File srcDir, final File destDir, final FileFilter fileFilter, final boolean preserveFileDate,
@@ -749,7 +749,7 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
749749
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
750750
* @throws IllegalArgumentException if the source or destination is invalid.
751751
* @throws FileNotFoundException if the source does not exist.
752-
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
752+
* @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
753753
* @since 1.2
754754
*/
755755
public static void copyDirectoryToDirectory(final File sourceDir, final File destinationDir) throws IOException {
@@ -838,9 +838,10 @@ public static void copyFile(final File srcFile, final File destFile, final boole
838838
* @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.
839839
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
840840
* @throws FileNotFoundException if the source does not exist.
841-
* @throws IllegalArgumentException if {@code srcFile} or {@code destFile} is not a file, or {@code destFile} is not writable
841+
* @throws IllegalArgumentException if {@code srcFile} or {@code destFile} is not a file
842842
* @throws IOException if the output file length is not the same as the input file length after the copy completes.
843-
* @throws IOException if an I/O error occurs, or setting the last-modified time didn't succeed.
843+
* @throws IOException if an I/O error occurs, setting the last-modified time didn't succeed,
844+
* or the destination is not writable
844845
* @see #copyFileToDirectory(File, File, boolean)
845846
* @since 2.8.0
846847
*/
@@ -851,7 +852,6 @@ public static void copyFile(final File srcFile, final File destFile, final boole
851852
createParentDirectories(destFile);
852853
if (destFile.exists()) {
853854
checkFileExists(destFile, "destFile");
854-
requireCanWrite(destFile, "destFile");
855855
}
856856

857857
final Path srcPath = srcFile.toPath();
@@ -1347,7 +1347,6 @@ private static void doCopyDirectory(final File srcDir, final File destDir, final
13471347
final File[] srcFiles = listFiles(srcDir, fileFilter);
13481348
requireDirectoryIfExists(destDir, "destDir");
13491349
mkdirs(destDir);
1350-
requireCanWrite(destDir, "destDir");
13511350
for (final File srcFile : srcFiles) {
13521351
final File dstFile = new File(destDir, srcFile.getName());
13531352
if (exclusionList == null || !exclusionList.contains(srcFile.getCanonicalPath())) {
@@ -2623,15 +2622,13 @@ public static FileOutputStream openOutputStream(final File file) throws IOExcept
26232622
* @return a new {@link FileOutputStream} for the specified file
26242623
* @throws NullPointerException if the file object is {@code null}.
26252624
* @throws IllegalArgumentException if the file object is a directory
2626-
* @throws IllegalArgumentException if the file is not writable.
2627-
* @throws IOException if the directories could not be created.
2625+
* @throws IOException if the directories could not be created, or the file is not writable
26282626
* @since 2.1
26292627
*/
26302628
public static FileOutputStream openOutputStream(final File file, final boolean append) throws IOException {
26312629
Objects.requireNonNull(file, "file");
26322630
if (file.exists()) {
26332631
checkIsFile(file, "file");
2634-
requireCanWrite(file, "file");
26352632
} else {
26362633
createParentDirectories(file);
26372634
}
@@ -2774,21 +2771,6 @@ private static void requireCanonicalPathsNotEquals(final File file1, final File
27742771
}
27752772
}
27762773

2777-
/**
2778-
* Throws an {@link IllegalArgumentException} if the file is not writable. This provides a more precise exception
2779-
* message than a plain access denied.
2780-
*
2781-
* @param file The file to test.
2782-
* @param name The parameter name to use in the exception message.
2783-
* @throws NullPointerException if the given {@link File} is {@code null}.
2784-
* @throws IllegalArgumentException if the file is not writable.
2785-
*/
2786-
private static void requireCanWrite(final File file, final String name) {
2787-
if (!file.canWrite()) {
2788-
throw new IllegalArgumentException("File parameter '" + name + " is not writable: '" + file + "'");
2789-
}
2790-
}
2791-
27922774
/**
27932775
* Requires that the given {@link File} exists and is a directory.
27942776
*

src/test/java/org/apache/commons/io/FileUtilsTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,6 +1242,18 @@ public void testCopyFile1ToDir() throws Exception {
12421242
"Should not be able to copy a file into the same directory as itself");
12431243
}
12441244

1245+
@Test
1246+
public void testCopyFileToReadOnlyDirectory() throws Exception {
1247+
final File directory = new File(tempDirFile, "readonly");
1248+
if (!directory.exists()) {
1249+
assumeTrue(directory.mkdirs());
1250+
}
1251+
assumeTrue(directory.setWritable(false));
1252+
1253+
assertThrows(IOException.class, () -> FileUtils.copyFileToDirectory(testFile1, directory),
1254+
"Should not be able to copy a file into a readonly directory");
1255+
}
1256+
12451257
@Test
12461258
public void testCopyFile2() throws Exception {
12471259
final File destination = new File(tempDirFile, "copy2.txt");

0 commit comments

Comments
 (0)