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
2 changes: 1 addition & 1 deletion Sources/ContainerizationArchive/ArchiveReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ extension ArchiveReader {
}

private func setFileAttributes(fd: Int32, entry: WriteEntry) {
fchmod(fd, entry.permissions & 0o777)
fchmod(fd, entry.permissions & 0o7777)
if let owner = entry.owner, let group = entry.group {
fchown(fd, owner, group)
}
Expand Down
30 changes: 30 additions & 0 deletions Tests/ContainerizationArchiveTests/ArchiveReaderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,36 @@ struct ArchiveReaderTests {
#expect((perms & permMask) == 0o755, "Permissions should be preserved")
}

@Test func preserveSpecialPermissionBits() throws {
let testDirectory = createTemporaryDirectory(baseName: "ArchiveReaderTests")!
let archiveURL = testDirectory.appendingPathComponent("special-permissions.tar")
let archiver = try ArchiveWriter(format: .paxRestricted, filter: .none, file: archiveURL)

let writeEntry = WriteEntry()
writeEntry.path = "sticky"
writeEntry.fileType = .directory
writeEntry.permissions = 0o1777
writeEntry.size = 0
try archiver.writeEntry(entry: writeEntry, data: nil)
try archiver.finishEncoding()

defer { try? FileManager.default.removeItem(at: testDirectory) }

let extractDir = try createExtractionDirectory(name: "special-permissions")
defer { try? FileManager.default.removeItem(at: extractDir.deletingLastPathComponent()) }

let reader = try ArchiveReader(format: .paxRestricted, filter: .none, file: archiveURL)
let rejectedPaths = try reader.extractContents(to: extractDir)

#expect(rejectedPaths.isEmpty)

let directoryPath = extractDir.appendingPathComponent("sticky").path
let attrs = try FileManager.default.attributesOfItem(atPath: directoryPath)
let perms = (attrs[.posixPermissions] as? NSNumber)?.uint16Value ?? 0
let permMask: UInt16 = 0o7777
#expect((perms & permMask) == 0o1777, "Special permission bits should be preserved")
}

// MARK: - Duplicate Entry Tests

@Test func duplicateRegularFiles() throws {
Expand Down