From 47b334746e9ba1ead996894c09ce53aa05418c98 Mon Sep 17 00:00:00 2001 From: rdavidek Date: Tue, 3 Feb 2026 09:59:03 +0100 Subject: [PATCH] fixed archive permissions --- .../kfmanager/service/FileOperations.java | 118 +++++++++++------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java index 2baddc7..b5bb876 100644 --- a/src/main/java/cz/kamma/kfmanager/service/FileOperations.java +++ b/src/main/java/cz/kamma/kfmanager/service/FileOperations.java @@ -566,6 +566,28 @@ public class FileOperations { throw new IOException("Failed to create file (maybe it already exists?)"); } } + + private static void setPermissionsFromMode(Path path, int mode) { + if (mode <= 0 || (cz.kamma.kfmanager.MainApp.CURRENT_OS != cz.kamma.kfmanager.MainApp.OS.LINUX && + cz.kamma.kfmanager.MainApp.CURRENT_OS != cz.kamma.kfmanager.MainApp.OS.MACOS)) { + return; + } + try { + Set perms = new HashSet<>(); + if ((mode & 0400) != 0) perms.add(PosixFilePermission.OWNER_READ); + if ((mode & 0200) != 0) perms.add(PosixFilePermission.OWNER_WRITE); + if ((mode & 0100) != 0) perms.add(PosixFilePermission.OWNER_EXECUTE); + if ((mode & 0040) != 0) perms.add(PosixFilePermission.GROUP_READ); + if ((mode & 0020) != 0) perms.add(PosixFilePermission.GROUP_WRITE); + if ((mode & 0010) != 0) perms.add(PosixFilePermission.GROUP_EXECUTE); + if ((mode & 0004) != 0) perms.add(PosixFilePermission.OTHERS_READ); + if ((mode & 0002) != 0) perms.add(PosixFilePermission.OTHERS_WRITE); + if ((mode & 0001) != 0) perms.add(PosixFilePermission.OTHERS_EXECUTE); + if (!perms.isEmpty()) { + Files.setPosixFilePermissions(path, perms); + } + } catch (Exception ignore) {} + } /** * Delete directory recursively @@ -954,7 +976,7 @@ public class FileOperations { long totalItems = calculateTotalItems(cleanedItems); long[] currentItem = {0}; - try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetZipFile))) { + try (org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream zos = new org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream(targetZipFile)) { for (FileItem item : cleanedItems) { if (callback != null && callback.isCancelled()) break; addToZip(item.getFile(), item.getName(), zos, totalItems, currentItem, callback); @@ -962,7 +984,7 @@ public class FileOperations { } } - private static void addToZip(File fileToZip, String fileName, ZipOutputStream zos, long totalItems, long[] currentItem, ProgressCallback callback) throws IOException { + private static void addToZip(File fileToZip, String fileName, org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream zos, long totalItems, long[] currentItem, ProgressCallback callback) throws IOException { if (fileToZip.isHidden()) { return; } @@ -972,32 +994,48 @@ public class FileOperations { callback.onProgress(currentItem[0], totalItems, fileName); } + org.apache.commons.compress.archivers.zip.ZipArchiveEntry zipEntry = new org.apache.commons.compress.archivers.zip.ZipArchiveEntry(fileToZip, fileName); + + // Try to set POSIX permissions + if (cz.kamma.kfmanager.MainApp.CURRENT_OS == cz.kamma.kfmanager.MainApp.OS.LINUX || + cz.kamma.kfmanager.MainApp.CURRENT_OS == cz.kamma.kfmanager.MainApp.OS.MACOS) { + try { + Set perms = Files.getPosixFilePermissions(fileToZip.toPath()); + int mode = 0; + if (perms.contains(PosixFilePermission.OWNER_READ)) mode |= 0400; + if (perms.contains(PosixFilePermission.OWNER_WRITE)) mode |= 0200; + if (perms.contains(PosixFilePermission.OWNER_EXECUTE)) mode |= 0100; + if (perms.contains(PosixFilePermission.GROUP_READ)) mode |= 0040; + if (perms.contains(PosixFilePermission.GROUP_WRITE)) mode |= 0020; + if (perms.contains(PosixFilePermission.GROUP_EXECUTE)) mode |= 0010; + if (perms.contains(PosixFilePermission.OTHERS_READ)) mode |= 0004; + if (perms.contains(PosixFilePermission.OTHERS_WRITE)) mode |= 0002; + if (perms.contains(PosixFilePermission.OTHERS_EXECUTE)) mode |= 0001; + zipEntry.setUnixMode(mode); + } catch (Exception ignore) {} + } + if (fileToZip.isDirectory()) { - if (fileName.endsWith("/")) { - zos.putNextEntry(new ZipEntry(fileName)); - zos.closeEntry(); - } else { - zos.putNextEntry(new ZipEntry(fileName + "/")); - zos.closeEntry(); - } + zos.putArchiveEntry(zipEntry); + zos.closeArchiveEntry(); File[] children = fileToZip.listFiles(); if (children != null) { for (File childFile : children) { - addToZip(childFile, fileName + "/" + childFile.getName(), zos, totalItems, currentItem, callback); + addToZip(childFile, fileName + (fileName.endsWith("/") ? "" : "/") + childFile.getName(), zos, totalItems, currentItem, callback); } } return; } - try (FileInputStream fis = new FileInputStream(fileToZip)) { - ZipEntry zipEntry = new ZipEntry(fileName); - zos.putNextEntry(zipEntry); + + try (InputStream is = Files.newInputStream(fileToZip.toPath())) { + zos.putArchiveEntry(zipEntry); long fileSize = fileToZip.length(); long bytesCopied = 0; - byte[] bytes = new byte[24576]; - int length; - while ((length = fis.read(bytes)) >= 0) { - zos.write(bytes, 0, length); - bytesCopied += length; + byte[] buffer = new byte[24576]; + int len; + while ((len = is.read(buffer)) >= 0) { + zos.write(buffer, 0, len); + bytesCopied += len; if (callback != null) { callback.onFileProgress(bytesCopied, fileSize); } @@ -1005,7 +1043,7 @@ public class FileOperations { if (callback != null) { callback.onFileProgress(fileSize, fileSize); } - zos.closeEntry(); + zos.closeArchiveEntry(); } } @@ -1058,9 +1096,11 @@ public class FileOperations { File newFile = new File(targetDir, entry.getName()); if (entry.isDirectory()) { newFile.mkdirs(); + setPermissionsFromMode(newFile.toPath(), entry.getMode()); } else { newFile.getParentFile().mkdirs(); Files.copy(tais, newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + setPermissionsFromMode(newFile.toPath(), entry.getMode()); } } } @@ -1121,17 +1161,12 @@ public class FileOperations { Files.createDirectories(targetDirectory.toPath()); } - long totalItems = 0; - try (ZipFile zf = new ZipFile(zipFile)) { - totalItems = zf.size(); - } catch (IOException e) { - // fallback if ZipFile fails - } + try (org.apache.commons.compress.archivers.zip.ZipFile zf = new org.apache.commons.compress.archivers.zip.ZipFile(zipFile)) { + java.util.List entries = java.util.Collections.list(zf.getEntries()); + long totalItems = entries.size(); + long currentItem = 0; - long currentItem = 0; - try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { - ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { + for (org.apache.commons.compress.archivers.zip.ZipArchiveEntry entry : entries) { currentItem++; File newFile = new File(targetDirectory, entry.getName()); @@ -1143,36 +1178,23 @@ public class FileOperations { if (!newFile.isDirectory() && !newFile.mkdirs()) { throw new IOException("Failed to create directory " + newFile); } + setPermissionsFromMode(newFile.toPath(), entry.getUnixMode()); } else { // create parent directories if they don't exist File parent = newFile.getParentFile(); - if (!parent.isDirectory() && !parent.mkdirs()) { - throw new IOException("Failed to create directory " + parent); + if (parent != null && !parent.exists()) { + parent.mkdirs(); } if (newFile.exists() && newFile.isDirectory()) { deleteDirectoryInternal(newFile.toPath()); } - // write file content - long fileSize = entry.getSize(); - long bytesCopied = 0; - try (FileOutputStream fos = new FileOutputStream(newFile)) { - byte[] buffer = new byte[24576]; - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - bytesCopied += len; - if (callback != null && fileSize > 0) { - callback.onFileProgress(bytesCopied, fileSize); - } - } - } - if (callback != null && fileSize > 0) { - callback.onFileProgress(fileSize, fileSize); + try (InputStream is = zf.getInputStream(entry)) { + Files.copy(is, newFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } + setPermissionsFromMode(newFile.toPath(), entry.getUnixMode()); } - zis.closeEntry(); } } } -- 2.47.2