From 32e1a24f7daa1dd705753fac4ab8b35e36a3520b Mon Sep 17 00:00:00 2001 From: Bartosz Polaczyk Date: Thu, 28 Apr 2022 22:55:40 +0200 Subject: [PATCH] Store file permissions --- Zip/Zip.swift | 16 ++++++++++++++-- ZipTests/Resources/execution | 0 ZipTests/XCTestManifests.swift | 1 + ZipTests/ZipTests.swift | 20 ++++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100755 ZipTests/Resources/execution diff --git a/Zip/Zip.swift b/Zip/Zip.swift index af2d453e..10460982 100644 --- a/Zip/Zip.swift +++ b/Zip/Zip.swift @@ -231,10 +231,10 @@ public class Zip { throw ZipError.unzipFail } - //Set file permissions from current fileInfo + // Set file permissions from current fileInfo if fileInfo.external_fa != 0 { let permissions = (fileInfo.external_fa >> 16) & 0x1FF - //We will devifne a valid permission range between Owner read only to full access + // We will define a valid permission range between Owner read only to full access if permissions >= 0o400 && permissions <= 0o777 { do { try fileManager.setAttributes([.posixPermissions : permissions], ofItemAtPath: fullPath) @@ -348,6 +348,18 @@ public class Zip { if let fileSize = fileAttributes[FileAttributeKey.size] as? Double { currentPosition += fileSize } + if let permissions = fileAttributes[FileAttributeKey.posixPermissions] as? UInt { + // We will store a valid permission range between Owner read only to full access + if permissions >= 0o400 && permissions <= 0o777 { + var new_external_fa: UInt = zipInfo.external_fa + let permissionsBits: UInt = 0o777 << 16 + // set bits responsible for permissions + new_external_fa = new_external_fa & ~permissionsBits + new_external_fa = new_external_fa | (permissions << UInt(16)) + + zipInfo.external_fa = new_external_fa + } + } } catch {} guard let buffer = malloc(chunkSize) else { diff --git a/ZipTests/Resources/execution b/ZipTests/Resources/execution new file mode 100755 index 00000000..e69de29b diff --git a/ZipTests/XCTestManifests.swift b/ZipTests/XCTestManifests.swift index 46dff196..9d8725bf 100644 --- a/ZipTests/XCTestManifests.swift +++ b/ZipTests/XCTestManifests.swift @@ -26,6 +26,7 @@ extension ZipTests { ("testUnzipPermissions", testUnzipPermissions), ("testUnzipWithUnsupportedPermissions", testUnzipWithUnsupportedPermissions), ("testZip", testZip), + ("testZipPermissions", testZipPermissions), ("testZipUnzipPassword", testZipUnzipPassword), ] } diff --git a/ZipTests/ZipTests.swift b/ZipTests/ZipTests.swift index 70f689ff..c90f2203 100644 --- a/ZipTests/ZipTests.swift +++ b/ZipTests/ZipTests.swift @@ -271,4 +271,24 @@ class ZipTests: XCTestCase { XCTAssertTrue(Zip.isValidFileExtension("zip")) XCTAssertTrue(Zip.isValidFileExtension("cbz")) } + + func testZipPermissions() throws { + let executionURL = url(forResource: "execution")! + let zipDestination = try Zip.quickZipFiles([executionURL], fileName: "execution.zip") + addTeardownBlock { + try? FileManager.default.removeItem(at: zipDestination) + } + let unzipDestination = try Zip.quickUnzipFile(zipDestination) + addTeardownBlock { + try? FileManager.default.removeItem(at: unzipDestination) + } + + let fileManager = FileManager.default + let unzippedFile = unzipDestination.appendingPathComponent("execution") + let unzippedFileAttributes = try fileManager.attributesOfItem(atPath: unzippedFile.path) + let permissions = unzippedFileAttributes[.posixPermissions] as? Int ?? 0 + // Git stores only the owner execution bit - observe only that + let ownerExecutionBit = 0o100 + XCTAssertEqual(permissions & ownerExecutionBit, ownerExecutionBit) + } }