Getting and Setting a File's Extended Attributes
One last code snippet....
This'll let you get and set the extended attributes on a file in OS X. It uses setxattr() / getxattr() / listxattr(), but it's all wrapped up in ARC-dependent Objective-C. When setting a value you can pass in either an NSString or an NSData.
Enjoy.
#import <errno.h>
#import <stdio.h>
#import <sys/xattr.h>
+ (BOOL)setValue:(NSObject *)value forName:(NSString *)name onFile:(NSString *)filePath
{
int err;
const void *bytes = NULL;
size_t length = 0;
if ([value isKindOfClass:[NSString class]]) {
bytes = [(NSString *)value UTF8String];
length = [(NSString *)value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
}
else if ([value isKindOfClass:[NSData class]]) {
bytes = [(NSData *)value bytes];
length = [(NSData *)value length];
}
else {
NSLog(@"%s.. unsupported data type, %@", __PRETTY_FUNCTION__, NSStringFromClass([value class]));
return FALSE;
}
if (0 != (err = setxattr([filePath UTF8String], [name UTF8String], bytes, length, 0, 0))) {
NSLog(@"%s.. failed to setxattr(%@), %s", __PRETTY_FUNCTION__, filePath, strerror(errno));
}
return TRUE;
}
+ (NSData *)getDataValueForName:(NSString *)name onFile:(NSString *)filePath
{
ssize_t size;
void *buffer[4096];
if (0 > (size = getxattr([filePath UTF8String], [name UTF8String], buffer, sizeof(buffer), 0, 0)) || size > sizeof(buffer)) {
NSLog(@"%s.. failed to getxattr(%@), %s", __PRETTY_FUNCTION__, filePath, strerror(errno));
return nil;
}
return [[NSData alloc] initWithBytes:buffer length:size];
}
+ (NSDictionary *)getAllValuesOnFile:(NSString *)filePath
{
ssize_t size;
char buffer[4096], *bufferPtr;
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
if (0 > (size = listxattr([filePath UTF8String], buffer, sizeof(buffer), 00)) || size > sizeof(buffer)) {
NSLog(@"%s.. failed to listxattr(%@), %s", __PRETTY_FUNCTION__, filePath, strerror(errno));
return nil;
}
bufferPtr = buffer;
for (ssize_t bufferNdx = 0; bufferNdx < size; ) {
NSString *name = [NSString stringWithCString:bufferPtr encoding:NSUTF8StringEncoding];
NSData *value = [self getDataValueForName:name onFile:filePath];
unsigned long namelen = strlen(bufferPtr);
if (name && value)
[attributes setValue:value forKey:name];
bufferPtr += namelen + 1;
bufferNdx += namelen + 1;
}
return attributes;
}