From 3f8998a4fc2153f9a82374cf6ec22979e27a0585 Mon Sep 17 00:00:00 2001 From: JBYoshi <12983479+JBYoshi@users.noreply.github.com> Date: Mon, 3 Apr 2023 20:21:37 -0500 Subject: [PATCH] Reset extended attributes of the base directories. --- Library/Homebrew/cask/artifact/moved.rb | 5 +- Library/Homebrew/cask/quarantine.rb | 14 ++++ Library/Homebrew/cask/utils/copy-xattrs.swift | 80 +++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100755 Library/Homebrew/cask/utils/copy-xattrs.swift diff --git a/Library/Homebrew/cask/artifact/moved.rb b/Library/Homebrew/cask/artifact/moved.rb index 2ec672683e..fa1915364a 100644 --- a/Library/Homebrew/cask/artifact/moved.rb +++ b/Library/Homebrew/cask/artifact/moved.rb @@ -2,6 +2,7 @@ # frozen_string_literal: true require "cask/artifact/relocated" +require "cask/quarantine" module Cask module Artifact @@ -97,7 +98,9 @@ module Cask command.run!("/bin/cp", args: ["-pR", "#{source}/*", "#{source}/.*", "#{target}/"], sudo: true) end - # TODO: copy extended attributes + unless Quarantine.copy_xattrs(source, target) + opoo "Unable to transfer extended attributes on the root directory" + end source.rmtree elsif target.dirname.writable? FileUtils.move(source, target) diff --git a/Library/Homebrew/cask/quarantine.rb b/Library/Homebrew/cask/quarantine.rb index 7333b4e231..ed36a41d82 100644 --- a/Library/Homebrew/cask/quarantine.rb +++ b/Library/Homebrew/cask/quarantine.rb @@ -14,6 +14,7 @@ module Cask QUARANTINE_ATTRIBUTE = "com.apple.quarantine" QUARANTINE_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/utils/quarantine.swift").freeze + COPY_XATTRS_SCRIPT = (HOMEBREW_LIBRARY_PATH/"cask/utils/copy-xattrs.swift").freeze def self.swift @swift ||= DevelopmentTools.locate("swift") @@ -174,5 +175,18 @@ module Cask raise CaskQuarantinePropagationError.new(to, quarantiner.stderr) end + + def self.copy_xattrs(from, to) + odebug "Copying xattrs from #{from} to #{to}" + + copier = system_command!(swift, + args: [ + *swift_target_args, + COPY_XATTRS_SCRIPT, + from, + to, + ]) + copier.success? + end end end diff --git a/Library/Homebrew/cask/utils/copy-xattrs.swift b/Library/Homebrew/cask/utils/copy-xattrs.swift new file mode 100755 index 0000000000..f118290c81 --- /dev/null +++ b/Library/Homebrew/cask/utils/copy-xattrs.swift @@ -0,0 +1,80 @@ +#!/usr/bin/swift + +import Foundation + +struct SwiftErr: TextOutputStream { + public static var stream = SwiftErr() + + mutating func write(_ string: String) { + fputs(string, stderr) + } +} + +guard CommandLine.arguments.count >= 3 else { + print("Usage: swift copy-xattrs.swift ") + exit(2) +} + +CommandLine.arguments[2].withCString { destPath in + let destNamesLen = listxattr(destPath, nil, 0, 0) + if destNamesLen == -1 { + print("listxattr for destination failed: \(errno)", to: &SwiftErr.stream) + exit(1) + } + let destNamesBuf = UnsafeMutablePointer.allocate(capacity: destNamesLen) + if listxattr(destPath, destNamesBuf, destNamesLen, 0) != destNamesLen { + print("Attributes changed during system call", to: &SwiftErr.stream) + exit(1) + } + + var destNamesIdx = 0 + while destNamesIdx < destNamesLen { + let attribute = destNamesBuf + destNamesIdx + + if removexattr(destPath, attribute, 0) != 0 { + print("removexattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream) + exit(1) + } + + destNamesIdx += strlen(attribute) + 1 + } + destNamesBuf.deallocate() + + CommandLine.arguments[1].withCString { sourcePath in + let sourceNamesLen = listxattr(sourcePath, nil, 0, 0) + if sourceNamesLen == -1 { + print("listxattr for source failed: \(errno)", to: &SwiftErr.stream) + exit(1) + } + let sourceNamesBuf = UnsafeMutablePointer.allocate(capacity: sourceNamesLen) + if listxattr(sourcePath, sourceNamesBuf, sourceNamesLen, 0) != sourceNamesLen { + print("Attributes changed during system call", to: &SwiftErr.stream) + exit(1) + } + + var sourceNamesIdx = 0 + while sourceNamesIdx < sourceNamesLen { + let attribute = sourceNamesBuf + sourceNamesIdx + + let valueLen = getxattr(sourcePath, attribute, nil, 0, 0, 0) + if valueLen == -1 { + print("getxattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream) + exit(1) + } + let valueBuf = UnsafeMutablePointer.allocate(capacity: valueLen) + if getxattr(sourcePath, attribute, valueBuf, valueLen, 0, 0) != valueLen { + print("Attributes changed during system call", to: &SwiftErr.stream) + exit(1) + } + + if setxattr(destPath, attribute, valueBuf, valueLen, 0, 0) != 0 { + print("setxattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream) + exit(1) + } + + valueBuf.deallocate() + sourceNamesIdx += strlen(attribute) + 1 + } + sourceNamesBuf.deallocate() + } +}