2023-04-03 20:21:37 -05:00
|
|
|
#!/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 <source> <dest>")
|
|
|
|
exit(2)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
CommandLine.arguments[2].withCString { destinationPath in
|
|
|
|
let destinationNamesLength = listxattr(destinationPath, nil, 0, 0)
|
|
|
|
if destinationNamesLength == -1 {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("listxattr for destination failed: \(errno)", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
2023-05-03 11:29:01 -05:00
|
|
|
let destinationNamesBuffer = UnsafeMutablePointer<Int8>.allocate(capacity: destinationNamesLength)
|
|
|
|
if listxattr(destinationPath, destinationNamesBuffer, destinationNamesLength, 0) != destinationNamesLength {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("Attributes changed during system call", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
var destinationNamesIndex = 0
|
|
|
|
while destinationNamesIndex < destinationNamesLength {
|
|
|
|
let attribute = destinationNamesBuffer + destinationNamesIndex
|
2023-04-03 20:21:37 -05:00
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
if removexattr(destinationPath, attribute, 0) != 0 {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("removexattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
destinationNamesIndex += strlen(attribute) + 1
|
2023-04-03 20:21:37 -05:00
|
|
|
}
|
2023-05-03 11:29:01 -05:00
|
|
|
destinationNamesBuffer.deallocate()
|
2023-04-03 20:21:37 -05:00
|
|
|
|
|
|
|
CommandLine.arguments[1].withCString { sourcePath in
|
2023-05-03 11:29:01 -05:00
|
|
|
let sourceNamesLength = listxattr(sourcePath, nil, 0, 0)
|
|
|
|
if sourceNamesLength == -1 {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("listxattr for source failed: \(errno)", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
2023-05-03 11:29:01 -05:00
|
|
|
let sourceNamesBuffer = UnsafeMutablePointer<Int8>.allocate(capacity: sourceNamesLength)
|
|
|
|
if listxattr(sourcePath, sourceNamesBuffer, sourceNamesLength, 0) != sourceNamesLength {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("Attributes changed during system call", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
var sourceNamesIndex = 0
|
|
|
|
while sourceNamesIndex < sourceNamesLength {
|
|
|
|
let attribute = sourceNamesBuffer + sourceNamesIndex
|
2023-04-03 20:21:37 -05:00
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
let valueLength = getxattr(sourcePath, attribute, nil, 0, 0, 0)
|
|
|
|
if valueLength == -1 {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("getxattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
2023-05-03 11:29:01 -05:00
|
|
|
let valueBuffer = UnsafeMutablePointer<Int8>.allocate(capacity: valueLength)
|
|
|
|
if getxattr(sourcePath, attribute, valueBuffer, valueLength, 0, 0) != valueLength {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("Attributes changed during system call", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
if setxattr(destinationPath, attribute, valueBuffer, valueLength, 0, 0) != 0 {
|
2023-04-03 20:21:37 -05:00
|
|
|
print("setxattr for \(String(cString: attribute)) failed: \(errno)", to: &SwiftErr.stream)
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
2023-05-03 11:29:01 -05:00
|
|
|
valueBuffer.deallocate()
|
|
|
|
sourceNamesIndex += strlen(attribute) + 1
|
2023-04-03 20:21:37 -05:00
|
|
|
}
|
2023-05-03 11:29:01 -05:00
|
|
|
sourceNamesBuffer.deallocate()
|
2023-04-03 20:21:37 -05:00
|
|
|
}
|
|
|
|
}
|