diff --git a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java index bf55aaf..7efe33e 100644 --- a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java +++ b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java @@ -160,10 +160,7 @@ public class FileOperations { } target.setLastModified(source.lastModified()); - // Simple permission sync if possible - if (source.canExecute()) target.setExecutable(true); - if (source.canRead()) target.setReadable(true); - if (source.canWrite()) target.setWritable(true); + copyPermissions(source, target); } private static void copyDirectory(File source, File target, long totalItems, final long[] currentItem, ProgressCallback callback, final OverwriteResponse[] globalResponse) throws IOException { @@ -211,6 +208,25 @@ public class FileOperations { } } } + target.setLastModified(source.lastModified()); + copyPermissions(source, target); + } + + private static void copyPermissions(File source, File target) { + if (source == null || target == null || !source.exists() || !target.exists()) return; + if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) { + try { + Set permissions = Files.getPosixFilePermissions(source.toPath()); + Files.setPosixFilePermissions(target.toPath(), permissions); + return; + } catch (Exception ignore) { + // Best effort; fall back to java.io.File below. + } + } + + target.setReadable(source.canRead(), false); + target.setWritable(source.canWrite(), false); + target.setExecutable(source.canExecute(), false); } private static void deleteDirectoryInternal(File path) throws IOException { @@ -1462,12 +1478,16 @@ public class FileOperations { } try (org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(is)) { org.apache.commons.compress.archivers.tar.TarArchiveEntry entry; + java.util.Map directoryModes = new java.util.LinkedHashMap<>(); // Tar doesn't easily give total count without pre-scanning while ((entry = tais.getNextTarEntry()) != null) { if (callback != null && callback.isCancelled()) break; File targetFile = new File(targetDir, entry.getName()); if (entry.isDirectory()) { targetFile.mkdirs(); + if (entry.getMode() > 0) { + directoryModes.put(targetFile, entry.getMode()); + } } else { targetFile.getParentFile().mkdirs(); try (OutputStream out = new BufferedOutputStream(new FileOutputStream(targetFile), 65536)) { @@ -1481,7 +1501,7 @@ public class FileOperations { // Preserve permissions for Linux/Unix int mode = entry.getMode(); - if (mode > 0) { + if (mode > 0 && !entry.isDirectory()) { // For TAR entries, if high bits are set (directory/file type info), // we ensure we are looking at the standard permission bits. applyPosixPermissions(targetFile, mode); @@ -1491,6 +1511,9 @@ public class FileOperations { callback.onProgress(0, 0, entry.getName()); // 0/0 because we don't know total } } + for (java.util.Map.Entry directoryMode : directoryModes.entrySet()) { + applyPosixPermissions(directoryMode.getKey(), directoryMode.getValue()); + } } }