Skip to content

Commit

Permalink
core: Backport symlink fix from 4.x
Browse files Browse the repository at this point in the history
Correctly follow symlinks when writing out files
  • Loading branch information
zml2008 committed Aug 9, 2020
1 parent ea961c7 commit 5de6e7c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,19 @@ public static Callable<BufferedWriter> createAtomicWriterFactory(@NonNull Path p
*/
@NonNull
public static BufferedWriter createAtomicBufferedWriter(@NonNull Path path, @NonNull Charset charset) throws IOException {
// absolute
path = path.toAbsolutePath();

Path writePath = getTemporaryPath(path.getParent(), path.getFileName().toString());
// unwrap any symbolic links
try {
while (Files.isSymbolicLink(path)) {
path = Files.readSymbolicLink(path);
}
} catch (final UnsupportedOperationException | IOException ex) {
// ignore, FS probably doesn't support symlinks
}

final Path writePath = getTemporaryPath(path.getParent(), path.getFileName().toString());
if (Files.exists(path)) {
Files.copy(path, writePath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@
*/
package ninja.leaping.configurate.loader;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junitpioneer.jupiter.TempDirectory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;

@ExtendWith(TempDirectory.class)
public class AbstractConfigurationLoaderTest {
Expand All @@ -40,4 +48,30 @@ public void testLoadNonexistantFile(@TempDirectory.TempDir Path tempDir) throws
TestConfigurationLoader loader = TestConfigurationLoader.builder().setFile(tempFile).build();
loader.load();
}

@Test
public void testSaveFollowsSymbolicLinks(final @TempDirectory.TempDir Path tempDir) throws IOException {
final Path actualFile = tempDir.resolve(Paths.get("first", "second", "third.json"));
Files.createDirectories(actualFile.getParent());
final Path layerOne = tempDir.resolve("general.json");
final Path layerTwo = tempDir.resolve("general2.json");

Files.createFile(actualFile);
Files.createSymbolicLink(layerOne, actualFile);
Files.createSymbolicLink(layerTwo, layerOne);

try (BufferedWriter writer = AtomicFiles.createAtomicBufferedWriter(layerTwo, StandardCharsets.UTF_8)) {
writer.write("I should follow symlinks!\n");
}

// We expect links are preserved, and the underlying file is written to
assertTrue(Files.isSymbolicLink(layerTwo));
assertTrue(Files.isSymbolicLink(layerOne));
assertEquals(layerOne, Files.readSymbolicLink(layerTwo));
assertEquals(actualFile, Files.readSymbolicLink(layerOne));
assertEquals("I should follow symlinks!", Files.readAllLines(layerTwo, StandardCharsets.UTF_8).stream()
.collect(Collectors.joining("\n")));
assertEquals("I should follow symlinks!", Files.readAllLines(actualFile, StandardCharsets.UTF_8).stream()
.collect(Collectors.joining("\n")));
}
}

0 comments on commit 5de6e7c

Please sign in to comment.