UKXattrMetadataStore
Language: Objective-C, Author: Uli Kusterer
License: MIT/X11
A wrapper around the MacOS X 10.4 xattr APIs for attaching metadata to files. Also offers convenience methods for dealing with UTF8 strings and property-list-objects as the metadata values.
UKXattrMetadataStore source preview
//
// UKXattrMetadataStore.m
// BubbleBrowser
// LICENSE: MIT License
//
// Created by Uli Kusterer on 12.03.06.
// Copyright 2006 Uli Kusterer. All rights reserved.
//
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
// -----------------------------------------------------------------------------
// Headers:
// -----------------------------------------------------------------------------
#import "UKXattrMetadataStore.h"
#import <sys/xattr.h>
@implementation UKXattrMetadataStore
// -----------------------------------------------------------------------------
// allKeysAtPath:traverseLink:
// Return an NSArray of NSStrings containing all xattr names currently set
// for the file at the specified path.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(NSArray*) allKeysAtPath: (NSString*)path traverseLink:(BOOL)travLnk
{
NSMutableArray* allKeys = [NSMutableArray array];
size_t dataSize = listxattr( [path fileSystemRepresentation],
NULL, ULONG_MAX,
(travLnk ? 0 : XATTR_NOFOLLOW) );
if( dataSize == ULONG_MAX )
return allKeys; // Empty list.
NSMutableData* listBuffer = [NSMutableData dataWithLength: dataSize];
dataSize = listxattr( [path fileSystemRepresentation],
[listBuffer mutableBytes], [listBuffer length],
(travLnk ? 0 : XATTR_NOFOLLOW) );
char* nameStart = [listBuffer mutableBytes];
int x;
for( x = 0; x < dataSize; x++ )
{
if( ((char*)[listBuffer mutableBytes])[x] == 0 ) // End of string.
{
NSString* str = [NSString stringWithUTF8String: nameStart];
nameStart = [listBuffer mutableBytes] +x +1;
[allKeys addObject: str];
}
}
return allKeys;
}
// -----------------------------------------------------------------------------
// setData:forKey:atPath:traverseLink:
// Set the xattr with name key to a block of raw binary data.
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(void) setData: (NSData*)data forKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
setxattr( [path fileSystemRepresentation], [key UTF8String],
[data bytes], [data length],
0, (travLnk ? 0 : XATTR_NOFOLLOW) );
}
// -----------------------------------------------------------------------------
// setObject:forKey:atPath:traverseLink:
// Set the xattr with name key to an XML property list representation of
// the specified object (or object graph).
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(void) setObject: (id)obj forKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
// Serialize our objects into a property list XML string:
NSString* errMsg = nil;
NSData* plistData = [NSPropertyListSerialization dataFromPropertyList: obj
format: NSPropertyListXMLFormat_v1_0
errorDescription: &errMsg];
if( errMsg )
{
[errMsg autorelease];
[NSException raise: @"UKXattrMetastoreCantSerialize" format: @"%@", errMsg];
}
else
[[self class] setData: plistData forKey: key atPath: path traverseLink: travLnk];
}
// -----------------------------------------------------------------------------
// setString:forKey:atPath:traverseLink:
// Set the xattr with name key to an XML property list representation of
// the specified object (or object graph).
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(void) setString: (NSString*)str forKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
NSData* data = [str dataUsingEncoding: NSUTF8StringEncoding];
if( !data )
[NSException raise: NSCharacterConversionException format: @"Couldn't convert string to UTF8 for xattr storage."];
[[self class] setData: data forKey: key atPath: path traverseLink: travLnk];
}
// -----------------------------------------------------------------------------
// dataForKey:atPath:traverseLink:
// Retrieve the xattr with name key as a raw block of data.
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(NSMutableData*) dataForKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
size_t dataSize = getxattr( [path fileSystemRepresentation], [key UTF8String],
NULL, ULONG_MAX, 0, (travLnk ? 0 : XATTR_NOFOLLOW) );
if( dataSize == ULONG_MAX )
return nil;
NSMutableData* data = [NSMutableData dataWithLength: dataSize];
getxattr( [path fileSystemRepresentation], [key UTF8String],
[data mutableBytes], [data length], 0, (travLnk ? 0 : XATTR_NOFOLLOW) );
return data;
}
// -----------------------------------------------------------------------------
// objectForKey:atPath:traverseLink:
// Retrieve the xattr with name key, which is an XML property list
// and unserialize it back into an object or object graph.
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(id) objectForKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
NSString* errMsg = nil;
NSMutableData* data = [[self class] dataForKey: key atPath: path traverseLink: travLnk];
NSPropertyListFormat outFormat = NSPropertyListXMLFormat_v1_0;
id obj = [NSPropertyListSerialization propertyListFromData: data
mutabilityOption: NSPropertyListImmutable
format: &outFormat
errorDescription: &errMsg];
if( errMsg )
{
[errMsg autorelease];
[NSException raise: @"UKXattrMetastoreCantUnserialize" format: @"%@", errMsg];
}
return obj;
}
// -----------------------------------------------------------------------------
// stringForKey:atPath:traverseLink:
// Retrieve the xattr with name key, which is an XML property list
// and unserialize it back into an object or object graph.
// path is the file whose xattr you want to set.
// If travLnk == YES, it follows symlinks.
// -----------------------------------------------------------------------------
+(id) stringForKey: (NSString*)key atPath: (NSString*)path traverseLink:(BOOL)travLnk
{
NSMutableData* data = [[self class] dataForKey: key atPath: path traverseLink: travLnk];
return [[[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding] autorelease];
}
@end
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4*/
UKXattrMetadataStore header preview
//
// UKXattrMetadataStore.h
// BubbleBrowser
// LICENSE: MIT License
//
// Created by Uli Kusterer on 12.03.06.
// Copyright 2006 Uli Kusterer. All rights reserved.
//
// -----------------------------------------------------------------------------
// Headers:
// -----------------------------------------------------------------------------
#import <Cocoa/Cocoa.h>
/*
This is a wrapper around The Mac OS X 10.4 and later xattr API that lets
you attach arbitrary metadata to a file. Currently it allows querying and
changing the attributes of a file, as well as retrieving a list of attribute
names.
It also includes some conveniences for storing/retrieving UTF8 strings,
and objects as XML property lists in addition to the raw data.
NOTE: keys (i.e. xattr names) are strings of 127 characters or less and
should be made like bundle identifiers, e.g. @"de.zathras.myattribute".
*/
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
// -----------------------------------------------------------------------------
// Class declaration:
// -----------------------------------------------------------------------------
@interface UKXattrMetadataStore : NSObject
{
}
+(NSArray*) allKeysAtPath: (NSString*)path traverseLink:(BOOL)travLnk;
// Store UTF8 strings:
+(void) setString: (NSString*)str forKey: (NSString*)key
atPath: (NSString*)path traverseLink:(BOOL)travLnk;
+(id) stringForKey: (NSString*)key atPath: (NSString*)path
traverseLink:(BOOL)travLnk;
// Store raw data:
+(void) setData: (NSData*)data forKey: (NSString*)key
atPath: (NSString*)path traverseLink:(BOOL)travLnk;
+(NSMutableData*) dataForKey: (NSString*)key atPath: (NSString*)path
traverseLink:(BOOL)travLnk;
// Store objects: (Only can get/set plist-type objects for now)â
+(void) setObject: (id)obj forKey: (NSString*)key atPath: (NSString*)path
traverseLink:(BOOL)travLnk;
+(id) objectForKey: (NSString*)key atPath: (NSString*)path
traverseLink:(BOOL)travLnk;
@end
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4*/
Download Archive
Compatible with:
- Mac OS X 10.4 PPC
- Mac OS X 10.4 Intel
- Mac OS X 10.5 PPC
- Mac OS X 10.5 Intel
Comments
Comment feed
