Skip to content

Commit 4f71ae0

Browse files
authored
Make copyFile copy symbolic links by value rather than reference (#565)
* Make copyFile copy symbolic links by value rather than reference * inline variable
1 parent 5e8fdba commit 4f71ae0

2 files changed

Lines changed: 20 additions & 19 deletions

File tree

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

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
import java.time.chrono.ChronoLocalDateTime;
5858
import java.time.chrono.ChronoZonedDateTime;
5959
import java.util.ArrayList;
60-
import java.util.Arrays;
6160
import java.util.Collection;
6261
import java.util.Collections;
6362
import java.util.Date;
@@ -652,7 +651,7 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
652651
* @since 1.4
653652
*/
654653
public static void copyDirectory(final File srcDir, final File destDir, final FileFilter filter, final boolean preserveFileDate) throws IOException {
655-
copyDirectory(srcDir, destDir, filter, preserveFileDate, StandardCopyOption.REPLACE_EXISTING);
654+
copyDirectory(srcDir, destDir, filter, preserveFileDate, StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS);
656655
}
657656

658657
/**
@@ -760,13 +759,13 @@ public static void copyDirectoryToDirectory(final File sourceDir, final File des
760759
* <p>
761760
* This method copies the contents of the specified source file to the specified destination file. The directory
762761
* holding the destination file is created if it does not exist. If the destination file exists, then this method
763-
* will overwrite it.
762+
* overwrites it. A symbolic link is resolved before copying so the new file is not a link.
764763
* </p>
765764
* <p>
766765
* <strong>Note:</strong> This method tries to preserve the file's last modified date/times using
767766
* {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is not guaranteed that the
768-
* operation will succeed. If the modification operation fails it falls back to
769-
* {@link File#setLastModified(long)} and if that fails, the method throws IOException.
767+
* operation will succeed. If the modification operation fails, it falls back to
768+
* {@link File#setLastModified(long)}, and if that fails, the method throws IOException.
770769
* </p>
771770
*
772771
* @param srcFile an existing file to copy, must not be {@code null}.
@@ -787,13 +786,13 @@ public static void copyFile(final File srcFile, final File destFile) throws IOEx
787786
* <p>
788787
* This method copies the contents of the specified source file to the specified destination file. The directory
789788
* holding the destination file is created if it does not exist. If the destination file exists, then this method
790-
* will overwrite it.
789+
* overwrites it. A symbolic link is resolved before copying so the new file is not a link.
791790
* </p>
792791
* <p>
793792
* <strong>Note:</strong> Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last
794793
* modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is
795-
* not guaranteed that the operation will succeed. If the modification operation fails it falls back to
796-
* {@link File#setLastModified(long)} and if that fails, the method throws IOException.
794+
* not guaranteed that the operation will succeed. If the modification operation fails, it falls back to
795+
* {@link File#setLastModified(long)}, and if that fails, the method throws IOException.
797796
* </p>
798797
*
799798
* @param srcFile an existing file to copy, must not be {@code null}.
@@ -810,17 +809,23 @@ public static void copyFile(final File srcFile, final File destFile, final boole
810809
}
811810

812811
/**
813-
* Copies a file to a new location.
812+
* Copies the contents of a file to a new location.
814813
* <p>
815814
* This method copies the contents of the specified source file to the specified destination file. The directory
816815
* holding the destination file is created if it does not exist. If the destination file exists, you can overwrite
817816
* it with {@link StandardCopyOption#REPLACE_EXISTING}.
818817
* </p>
818+
*
819+
* <p>
820+
* By default, a symbolic link is resolved before copying so the new file is not a link.
821+
* To copy symbolic links as links, you can pass {@code LinkOption.NO_FOLLOW_LINKS} as the last argument.
822+
* </p>
823+
*
819824
* <p>
820825
* <strong>Note:</strong> Setting {@code preserveFileDate} to {@code true} tries to preserve the file's last
821826
* modified date/times using {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is
822-
* not guaranteed that the operation will succeed. If the modification operation fails it falls back to
823-
* {@link File#setLastModified(long)} and if that fails, the method throws IOException.
827+
* not guaranteed that the operation will succeed. If the modification operation fails, it falls back to
828+
* {@link File#setLastModified(long)}, and if that fails, the method throws IOException.
824829
* </p>
825830
*
826831
* @param srcFile an existing file to copy, must not be {@code null}.
@@ -846,17 +851,11 @@ public static void copyFile(final File srcFile, final File destFile, final boole
846851
}
847852

848853
final Path srcPath = srcFile.toPath();
849-
final boolean isSymLink = Files.isSymbolicLink(srcPath);
850-
if (isSymLink && !Arrays.asList(copyOptions).contains(LinkOption.NOFOLLOW_LINKS)) {
851-
final List<CopyOption> list = new ArrayList<>(Arrays.asList(copyOptions));
852-
list.add(LinkOption.NOFOLLOW_LINKS);
853-
copyOptions = list.toArray(PathUtils.EMPTY_COPY_OPTIONS);
854-
}
855854

856855
Files.copy(srcPath, destFile.toPath(), copyOptions);
857856

858857
// On Windows, the last modified time is copied by default.
859-
if (preserveFileDate && !isSymLink && !setTimes(srcFile, destFile)) {
858+
if (preserveFileDate && !Files.isSymbolicLink(srcPath) && !setTimes(srcFile, destFile)) {
860859
throw new IOException("Cannot set the file time.");
861860
}
862861
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,9 @@ public void testCopyFile_symLink() throws Exception {
11151115
// Now copy symlink to another directory
11161116
final File destination = new File(tempDirFile, "destination");
11171117
FileUtils.copyFile(linkPath.toFile(), destination);
1118-
assertTrue(Files.isSymbolicLink(destination.toPath()));
1118+
assertFalse(Files.isSymbolicLink(destination.toPath()));
1119+
final String contents = FileUtils.readFileToString(destination, StandardCharsets.UTF_8);
1120+
assertEquals("HELLO WORLD", contents);
11191121
}
11201122

11211123

0 commit comments

Comments
 (0)