From efaf31342214c869287bac6ebdef23b8b4eaa0ee Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sat, 14 Aug 2021 16:58:10 +0100 Subject: [PATCH] When creating an ArbitraryDataFile from a path, make sure to move the file to the correct location within the data directory. This bug was introduced now that the temp directory is contained within the data directory. Without this, it would leave it in the temp folder and then fail at a later stage. --- .../qortal/arbitrary/ArbitraryDataFile.java | 8 +- .../org/qortal/utils/FilesystemUtils.java | 103 ++++++++++++++++++ 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java b/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java index 75417546..ecc3e147 100644 --- a/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java +++ b/src/main/java/org/qortal/arbitrary/ArbitraryDataFile.java @@ -112,11 +112,17 @@ public class ArbitraryDataFile { byte[] digest = Crypto.digest(fileContent); ArbitraryDataFile arbitraryDataFile = ArbitraryDataFile.fromHash(digest); - // Copy file to base directory if needed + // Copy file to data directory if needed Path filePath = Paths.get(path); if (Files.exists(filePath) && !arbitraryDataFile.isInBaseDirectory(path)) { arbitraryDataFile.copyToDataDirectory(filePath); } + // Or, if it's already in the data directory, we may need to move it + else if (!filePath.equals(arbitraryDataFile.getFilePath())) { + // Wrong path, so relocate + Path dest = Paths.get(arbitraryDataFile.getFilePath()); + FilesystemUtils.moveFile(filePath, dest, true); + } return arbitraryDataFile; } catch (IOException e) { diff --git a/src/main/java/org/qortal/utils/FilesystemUtils.java b/src/main/java/org/qortal/utils/FilesystemUtils.java index 54054c2d..0325cb60 100644 --- a/src/main/java/org/qortal/utils/FilesystemUtils.java +++ b/src/main/java/org/qortal/utils/FilesystemUtils.java @@ -1,7 +1,9 @@ package org.qortal.utils; +import org.apache.commons.io.FileUtils; import org.qortal.settings.Settings; +import java.io.File; import java.io.IOException; import java.nio.file.*; @@ -30,6 +32,107 @@ public class FilesystemUtils { }); } + + /** + * moveFile + * Allows files to be moved between filesystems + * + * @param source + * @param dest + * @param cleanup + * @throws IOException + */ + public static void moveFile(Path source, Path dest, boolean cleanup) throws IOException { + if (source.compareTo(dest) == 0) { + // Source path matches destination path already + return; + } + + File sourceFile = new File(source.toString()); + File destFile = new File(dest.toString()); + if (sourceFile == null || !sourceFile.exists()) { + throw new IOException("Source file doesn't exist"); + } + if (!sourceFile.isFile()) { + throw new IOException("Source isn't a file"); + } + + // Ensure parent folders exist in the destination + File destParentFile = destFile.getParentFile(); + if (destParentFile != null) { + destParentFile.mkdirs(); + } + if (destParentFile == null || !destParentFile.exists()) { + throw new IOException("Destination directory doesn't exist"); + } + + // Copy to destination + Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); + + // Delete existing + if (FilesystemUtils.pathInsideDataOrTempPath(source)) { + System.out.println(String.format("Deleting file %s", source.toString())); + Files.delete(source); + } + + if (cleanup) { + // ... and delete its parent directory if empty + Path parentDirectory = source.getParent(); + if (FilesystemUtils.pathInsideDataOrTempPath(parentDirectory)) { + Files.deleteIfExists(parentDirectory); + } + } + } + + /** + * moveDirectory + * Allows directories to be moved between filesystems + * + * @param source + * @param dest + * @param cleanup + * @throws IOException + */ + public static void moveDirectory(Path source, Path dest, boolean cleanup) throws IOException { + if (source.compareTo(dest) == 0) { + // Source path matches destination path already + return; + } + + File sourceFile = new File(source.toString()); + File destFile = new File(dest.toString()); + if (sourceFile == null || !sourceFile.exists()) { + throw new IOException("Source directory doesn't exist"); + } + if (!sourceFile.isDirectory()) { + throw new IOException("Source isn't a directory"); + } + + // Ensure parent folders exist in the destination + destFile.mkdirs(); + if (destFile == null || !destFile.exists()) { + throw new IOException("Destination directory doesn't exist"); + } + + // Copy to destination + FilesystemUtils.copyAndReplaceDirectory(source.toString(), dest.toString()); + + // Delete existing + if (FilesystemUtils.pathInsideDataOrTempPath(source)) { + File directory = new File(source.toString()); + System.out.println(String.format("Deleting directory %s", directory.toString())); + FileUtils.deleteDirectory(directory); + } + + if (cleanup) { + // ... and delete its parent directory if empty + Path parentDirectory = source.getParent(); + if (FilesystemUtils.pathInsideDataOrTempPath(parentDirectory)) { + Files.deleteIfExists(parentDirectory); + } + } + } + public static boolean pathInsideDataOrTempPath(Path path) { if (path == null) { return false;