Skip to content

Commit

Permalink
Add extensions to URL to read/write extended file attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveWoodCom committed Apr 5, 2017
1 parent 216fe75 commit bfa9fbf
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
10 changes: 10 additions & 0 deletions Sources/XCGLogger.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@
55C4DD5D1D781D850074C21F /* Base64LogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C4DD5B1D781D850074C21F /* Base64LogFormatter.swift */; };
55C4DD5E1D781D850074C21F /* Base64LogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C4DD5B1D781D850074C21F /* Base64LogFormatter.swift */; };
55C4DD5F1D781D850074C21F /* Base64LogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C4DD5B1D781D850074C21F /* Base64LogFormatter.swift */; };
55D780981E9372F600A51489 /* URL+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D780971E9372F600A51489 /* URL+XCGAdditions.swift */; };
55D780991E9372F600A51489 /* URL+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D780971E9372F600A51489 /* URL+XCGAdditions.swift */; };
55D7809A1E9372F600A51489 /* URL+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D780971E9372F600A51489 /* URL+XCGAdditions.swift */; };
55D7809B1E9372F600A51489 /* URL+XCGAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D780971E9372F600A51489 /* URL+XCGAdditions.swift */; };
55DD51981D915C2C0025B5AD /* PrePostFixLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DD51971D915C2C0025B5AD /* PrePostFixLogFormatter.swift */; };
55DD51991D915C2C0025B5AD /* PrePostFixLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DD51971D915C2C0025B5AD /* PrePostFixLogFormatter.swift */; };
55DD519A1D915C2C0025B5AD /* PrePostFixLogFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DD51971D915C2C0025B5AD /* PrePostFixLogFormatter.swift */; };
Expand Down Expand Up @@ -172,6 +176,7 @@
55AC33DE1D8FB4FE00614D28 /* UserInfoHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfoHelpers.swift; sourceTree = "<group>"; };
55BB1F011B79DC7500709779 /* XCGLoggerTests (OS X).xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "XCGLoggerTests (OS X).xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
55C4DD5B1D781D850074C21F /* Base64LogFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Base64LogFormatter.swift; sourceTree = "<group>"; };
55D780971E9372F600A51489 /* URL+XCGAdditions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+XCGAdditions.swift"; sourceTree = "<group>"; };
55DD51971D915C2C0025B5AD /* PrePostFixLogFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PrePostFixLogFormatter.swift; path = XCGLogger/LogFormatters/PrePostFixLogFormatter.swift; sourceTree = SOURCE_ROOT; };
55E37F5D1BFC646800392B9C /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
55E37F5E1BFC647400392B9C /* Info-OSX.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-OSX.plist"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -267,6 +272,7 @@
isa = PBXGroup;
children = (
5501A3A91D76282F00CB8ABE /* DispatchQueue+XCGAdditions.swift */,
55D780971E9372F600A51489 /* URL+XCGAdditions.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -729,6 +735,7 @@
5501A3EB1D77506F00CB8ABE /* ANSIColorLogFormatter.swift in Sources */,
5501A3871D761F9A00CB8ABE /* BaseQueuedDestination.swift in Sources */,
5506D85B1E90D356004DA6A2 /* BaseDestination.swift in Sources */,
55D7809B1E9372F600A51489 /* URL+XCGAdditions.swift in Sources */,
55A4B4F11D7AADA00006463B /* UserInfoFilter.swift in Sources */,
5501A3A81D7625DA00CB8ABE /* TestDestination.swift in Sources */,
556DA1821D78B41600C7E546 /* FileNameFilter.swift in Sources */,
Expand Down Expand Up @@ -759,6 +766,7 @@
5501A3E91D77506F00CB8ABE /* ANSIColorLogFormatter.swift in Sources */,
5501A3851D761F9A00CB8ABE /* BaseQueuedDestination.swift in Sources */,
5506D8591E90D356004DA6A2 /* BaseDestination.swift in Sources */,
55D780991E9372F600A51489 /* URL+XCGAdditions.swift in Sources */,
55A4B4EF1D7AADA00006463B /* UserInfoFilter.swift in Sources */,
5501A3A61D7625D900CB8ABE /* TestDestination.swift in Sources */,
556DA1801D78B41600C7E546 /* FileNameFilter.swift in Sources */,
Expand Down Expand Up @@ -813,6 +821,7 @@
5501A3E81D77506F00CB8ABE /* ANSIColorLogFormatter.swift in Sources */,
5501A3841D761F9A00CB8ABE /* BaseQueuedDestination.swift in Sources */,
5506D8581E90D356004DA6A2 /* BaseDestination.swift in Sources */,
55D780981E9372F600A51489 /* URL+XCGAdditions.swift in Sources */,
55A4B4EE1D7AADA00006463B /* UserInfoFilter.swift in Sources */,
5501A3A51D7625D900CB8ABE /* TestDestination.swift in Sources */,
556DA17F1D78B41600C7E546 /* FileNameFilter.swift in Sources */,
Expand Down Expand Up @@ -851,6 +860,7 @@
5501A3EA1D77506F00CB8ABE /* ANSIColorLogFormatter.swift in Sources */,
5501A3861D761F9A00CB8ABE /* BaseQueuedDestination.swift in Sources */,
5506D85A1E90D356004DA6A2 /* BaseDestination.swift in Sources */,
55D7809A1E9372F600A51489 /* URL+XCGAdditions.swift in Sources */,
55A4B4F01D7AADA00006463B /* UserInfoFilter.swift in Sources */,
5501A3A71D7625D900CB8ABE /* TestDestination.swift in Sources */,
556DA1811D78B41600C7E546 /* FileNameFilter.swift in Sources */,
Expand Down
82 changes: 82 additions & 0 deletions Sources/XCGLogger/Extensions/URL+XCGAdditions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// URL+ExtendedAttributes.swift
// XCGLogger: https://github.com/DaveWoodCom/XCGLogger
//
// Created by Dave Wood on 2017-04-04.
// Copyright © 2017 Dave Wood, Cerebral Gardens.
// Some rights reserved: https://github.com/DaveWoodCom/XCGLogger/blob/master/LICENSE.txt
//
// Based on code by Martin-R here: https://stackoverflow.com/a/38343753/144857

import Foundation

extension URL {

/// Get extended attribute.
func extendedAttribute(forName name: String) throws -> Data? {
let data: Data? = try self.withUnsafeFileSystemRepresentation { (fileSystemPath: (UnsafePointer<Int8>?)) -> Data? in
// Determine attribute size
let length = getxattr(fileSystemPath, name, nil, 0, 0, 0)
guard length >= 0 else { return nil }

// Create buffer with required size
var data = Data(count: length)

// Retrieve attribute
let result = data.withUnsafeMutableBytes {
getxattr(fileSystemPath, name, $0, data.count, 0, 0)
}
guard result >= 0 else { throw URL.posixError(errno) }
return data
}

return data
}

/// Set extended attribute.
func setExtendedAttribute(data: Data, forName name: String) throws {
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
let result = data.withUnsafeBytes {
setxattr(fileSystemPath, name, $0, data.count, 0, 0)
}
guard result >= 0 else { throw URL.posixError(errno) }
}
}

/// Remove extended attribute.
func removeExtendedAttribute(forName name: String) throws {
try self.withUnsafeFileSystemRepresentation { fileSystemPath in
let result = removexattr(fileSystemPath, name, 0)
guard result >= 0 else { throw URL.posixError(errno) }
}
}

/// Get list of all extended attributes.
func listExtendedAttributes() throws -> [String] {
let list = try self.withUnsafeFileSystemRepresentation { (fileSystemPath: (UnsafePointer<Int8>?)) -> [String] in
let length = listxattr(fileSystemPath, nil, 0, 0)
guard length >= 0 else { throw URL.posixError(errno) }

// Create buffer with required size
var data = Data(count: length)

// Retrieve attribute list
let result = data.withUnsafeMutableBytes {
listxattr(fileSystemPath, $0, data.count, 0)
}
guard result >= 0 else { throw URL.posixError(errno) }

// Extract attribute names
let list = data.split(separator: 0).flatMap {
String(data: Data($0), encoding: .utf8)
}
return list
}
return list
}

/// Helper function to create an NSError from a Unix errno.
private static func posixError(_ err: Int32) -> NSError {
return NSError(domain: NSPOSIXErrorDomain, code: Int(err), userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))])
}
}

0 comments on commit bfa9fbf

Please sign in to comment.