Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.UUID;
import org.apache.fesod.common.util.IoUtils;
import org.apache.fesod.sheet.exception.ExcelAnalysisException;
Expand Down Expand Up @@ -188,15 +191,30 @@ public static File createDirectory(File directory) {

/**
* delete file
* <p>
* Symbolic links and directory junctions are deleted themselves and never followed, so the deletion cannot
* escape the given directory.
*
* @param file
*/
public static void delete(File file) {
if (file.isFile()) {
BasicFileAttributes attributes;
try {
attributes = Files.readAttributes(file.toPath(), BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
} catch (IOException e) {
return;
}
// Read attributes without following links: File#isDirectory() resolves a Windows directory junction, while
// "no follow" attributes report it as "other" (a regular directory reports isOther() = false).
if (attributes.isSymbolicLink() || attributes.isOther()) {
file.delete();
return;
}
if (attributes.isRegularFile()) {
file.delete();
return;
}
if (file.isDirectory()) {
if (attributes.isDirectory()) {
File[] childFiles = file.listFiles();
if (childFiles == null || childFiles.length == 0) {
file.delete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import org.apache.fesod.sheet.testkit.builders.TestDataBuilder;
import org.apache.fesod.sheet.testkit.models.SimpleData;
import org.apache.fesod.sheet.util.FileUtils;
import org.apache.poi.util.TempFile;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -139,10 +138,11 @@ public void readWithCacheAfterTempDeletion() throws Exception {
FesodSheet.read(file).readCache(new Ehcache(null, 20)).sheet().doReadSync();
Assertions.assertEquals(10L, list.size());

// Save file content before deleting the system temp dir (which also removes @TempDir)
// Save file content before deleting Fesod's temp dir
byte[] fileContent = Files.readAllBytes(file.toPath());

FileUtils.delete(new File(System.getProperty(TempFile.JAVA_IO_TMPDIR)));
// Only delete Fesod's own temp dir, never the whole system temp dir shared with other processes
FileUtils.delete(new File(FileUtils.getTempFilePrefix()));

// Recreate the file after temp dir deletion to continue the test
file.getParentFile().mkdirs();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.apache.fesod.sheet.exception.ExcelAnalysisException;
import org.apache.fesod.sheet.exception.ExcelCommonException;
import org.apache.fesod.sheet.testkit.Tags;
import org.apache.poi.util.TempFile;
import org.apache.poi.util.TempFileCreationStrategy;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -270,6 +273,79 @@ void test_delete_directory() {
Assertions.assertFalse(root.exists());
}

@Test
void test_delete_doesNotFollowSymbolicLinks() throws IOException {
// outside/
// - keep.txt
// root/
// - link -> outside/
File outside = tempDir.resolve("outside").toFile();
FileUtils.createDirectory(outside);
File keep = new File(outside, "keep.txt");
Files.write(keep.toPath(), "content".getBytes());

File root = tempDir.resolve("root").toFile();
FileUtils.createDirectory(root);
Path link = root.toPath().resolve("link");
try {
Files.createSymbolicLink(link, outside.toPath());
} catch (IOException | UnsupportedOperationException e) {
Assumptions.assumeTrue(false, "Symbolic links are not supported: " + e.getMessage());
}

FileUtils.delete(root);

Assertions.assertFalse(root.exists());
Assertions.assertFalse(Files.exists(link, LinkOption.NOFOLLOW_LINKS));
Assertions.assertTrue(keep.exists());
}

@Test
void test_delete_doesNotFollowDirectoryJunctions() throws IOException {
Assumptions.assumeTrue(isWindows(), "Directory junctions are only available on Windows");
// outside/
// - keep.txt
// root/
// - junction -> outside/
File outside = tempDir.resolve("junction-outside").toFile();
FileUtils.createDirectory(outside);
File keep = new File(outside, "keep.txt");
Files.write(keep.toPath(), "content".getBytes(StandardCharsets.UTF_8));

File root = tempDir.resolve("junction-root").toFile();
FileUtils.createDirectory(root);
Path junction = root.toPath().resolve("junction");
Assumptions.assumeTrue(createJunction(junction, outside), "Directory junctions are not supported");

FileUtils.delete(root);

Assertions.assertFalse(root.exists());
Assertions.assertFalse(Files.exists(junction, LinkOption.NOFOLLOW_LINKS));
Assertions.assertTrue(keep.exists());
}

private static boolean isWindows() {
return System.getProperty("os.name").startsWith("Windows");
}

private static boolean createJunction(Path link, File target) {
try {
Process process = new ProcessBuilder("cmd", "/c", "mklink", "/J", link.toString(), target.getAbsolutePath())
.redirectErrorStream(true)
.start();
if (!process.waitFor(30, TimeUnit.SECONDS)) {
process.destroyForcibly();
return false;
}
return process.exitValue() == 0;
} catch (IOException e) {
return false;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}

@Test
void test_GetterSetter() {
String originalPrefix = FileUtils.getTempFilePrefix();
Expand Down
Loading