| 
									
										
										
										
											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
										 |  |  |     } | 
					
						
							|  |  |  | } |