Permalink
Browse files

Added DTExtendedFileAttributes

  • Loading branch information...
1 parent 5f64daa commit afcd6234db0a5fbc6465dccb355c7d4bc86c337c @odrobnik odrobnik committed Mar 6, 2012
@@ -0,0 +1,61 @@
+//
+// DTExtendedFileAttributes.h
+// DTFoundation
+//
+// Created by Oliver Drobnik on 3/6/12.
+// Copyright (c) 2012 Cocoanetics. All rights reserved.
+//
+
+/**
+ This class providse read/write access to extended file attributes of a file or folder. It wraps the standard xattr Posix functions to do that.
+
+ Because the file system does not keep track of the data types saved in extended attributes this API so far reads and writes strings.
+*/
+@interface DTExtendedFileAttributes : NSObject
+
+
+/**
+ @name Creating an Extended File Attribute Manager
+ */
+
+
+/**
+ Creates an Extended File Attribute Manager.
+
+ @param path The file path
+ */
+- (id)initWithPath:(NSString *)path;
+
+
+/**
+ @name: Reading/Writing extended attributes
+ */
+
+/**
+ Removes an extended file attribute from the receiver.
+
+ @returns `YES` if successful.
+ */
+- (BOOL)removeAttribute:(NSString *)attribute;
+
+
+/**
+ Sets the value of an extended file attribute for the receiver.
+
+ If the value is `nil` then this is the same as calling <removeAttribute:>.
+
+ @param attribute The name of the attribute.
+ @returns `YES` if successful.
+ */
+- (BOOL)setValue:(NSString *)value forAttribute:(NSString *)attribute;
+
+
+/**
+ Gets the value of an extended file attribute from the receiver.
+
+ @param attribute The name of the attribute.
+ @returns The string for the value or `nil` if the value is not set.
+ */
+- (NSString *)valueForAttribute:(NSString *)attribute;
+
+@end
@@ -0,0 +1,100 @@
+//
+// DTExtendedFileAttributes.m
+// DTFoundation
+//
+// Created by Oliver Drobnik on 3/6/12.
+// Copyright (c) 2012 Cocoanetics. All rights reserved.
+//
+
+#import "DTExtendedFileAttributes.h"
+
+#import <sys/xattr.h>
+
+@implementation DTExtendedFileAttributes
+{
+ NSString *_path;
+}
+
+- (id)initWithPath:(NSString *)path
+{
+ self = [super init];
+ if (self)
+ {
+ if (![path length])
+ {
+ return nil;
+ }
+
+ _path = path;
+ }
+
+ return self;
+}
+
+- (BOOL)removeAttribute:(NSString *)attribute
+{
+ const char *attrName = [attribute UTF8String];
+ const char *filePath = [_path fileSystemRepresentation];
+
+ int result = removexattr(filePath, attrName, 0);
+
+ return (result==0);
+}
+
+- (BOOL)setValue:(NSString *)value forAttribute:(NSString *)attribute
+{
+ if (![attribute length])
+ {
+ return NO;
+ }
+
+ if (!value)
+ {
+ // remove it instead
+ return [self removeAttribute:attribute];
+ }
+
+ const char *attrName = [attribute UTF8String];
+ const char *filePath = [_path fileSystemRepresentation];
+
+ const char *val = [value UTF8String];
+
+ int result = setxattr(filePath, attrName, val, strlen(val), 0, 0);
+
+ return (result==0);
+}
+
+- (NSString *)valueForAttribute:(NSString *)attribute
+{
+ if (![attribute length])
+ {
+ return nil;
+ }
+
+ const char *attrName = [attribute UTF8String];
+ const char *filePath = [_path fileSystemRepresentation];
+
+ // get size of needed buffer
+ int bufferLength = getxattr(filePath, attrName, NULL, 0, 0, 0);
+
+ if (bufferLength<=0)
+ {
+ return nil;
+ }
+
+ // make a buffer of sufficient length
+ char *buffer = malloc(bufferLength);
+
+ // now actually get the attribute string
+ getxattr(filePath, attrName, buffer, 255, 0, 0);
+
+ // convert to NSString
+ NSString *retString = [[NSString alloc] initWithBytes:buffer length:bufferLength encoding:NSUTF8StringEncoding];
+
+ // release buffer
+ free(buffer);
+
+ return retString;
+}
+
+@end
@@ -83,6 +83,10 @@
A7A7CC7A14866CAF00EC2EE4 /* NSString+DTFormatNumbers.m in Sources */ = {isa = PBXBuildFile; fileRef = A70B4CCB1486621B00873A4A /* NSString+DTFormatNumbers.m */; };
A7A7CC7B14866CAF00EC2EE4 /* NSURL+DTAppLinks.m in Sources */ = {isa = PBXBuildFile; fileRef = A70B4CCD1486621B00873A4A /* NSURL+DTAppLinks.m */; };
A7A7CC7C14866CAF00EC2EE4 /* NSURL+DTPrefLinks.m in Sources */ = {isa = PBXBuildFile; fileRef = A70B4CCF1486621B00873A4A /* NSURL+DTPrefLinks.m */; };
+ A7D6F2E515063448001CACDD /* DTExtendedFileAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6F2E315063448001CACDD /* DTExtendedFileAttributes.h */; };
+ A7D6F2E615063448001CACDD /* DTExtendedFileAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D6F2E315063448001CACDD /* DTExtendedFileAttributes.h */; };
+ A7D6F2E715063448001CACDD /* DTExtendedFileAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D6F2E415063448001CACDD /* DTExtendedFileAttributes.m */; };
+ A7D6F2E815063448001CACDD /* DTExtendedFileAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D6F2E415063448001CACDD /* DTExtendedFileAttributes.m */; };
A7D8628114EBF65C001436AF /* NSString+DTPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8627F14EBF65C001436AF /* NSString+DTPaths.h */; };
A7D8628214EBF65C001436AF /* NSString+DTPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8627F14EBF65C001436AF /* NSString+DTPaths.h */; };
A7D8628314EBF65C001436AF /* NSString+DTPaths.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8628014EBF65C001436AF /* NSString+DTPaths.m */; };
@@ -125,6 +129,8 @@
A7949A3814C963F500A8CCDE /* DTHTMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTHTMLParser.h; sourceTree = "<group>"; };
A7949A3914C963F500A8CCDE /* DTHTMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTHTMLParser.m; sourceTree = "<group>"; };
A7BAD10E1483F934000E2B6A /* DTFoundation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DTFoundation.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ A7D6F2E315063448001CACDD /* DTExtendedFileAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTExtendedFileAttributes.h; sourceTree = "<group>"; };
+ A7D6F2E415063448001CACDD /* DTExtendedFileAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTExtendedFileAttributes.m; sourceTree = "<group>"; };
A7D8627F14EBF65C001436AF /* NSString+DTPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+DTPaths.h"; sourceTree = "<group>"; };
A7D8628014EBF65C001436AF /* NSString+DTPaths.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+DTPaths.m"; sourceTree = "<group>"; };
A7F4DFF8147FD08900F4059A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@@ -186,6 +192,8 @@
A77DD40714E81AEE00F34B03 /* DTZipArchive.m */,
A7D8627F14EBF65C001436AF /* NSString+DTPaths.h */,
A7D8628014EBF65C001436AF /* NSString+DTPaths.m */,
+ A7D6F2E315063448001CACDD /* DTExtendedFileAttributes.h */,
+ A7D6F2E415063448001CACDD /* DTExtendedFileAttributes.m */,
);
path = Source;
sourceTree = "<group>";
@@ -276,6 +284,7 @@
A77DD42714E825FC00F34B03 /* zip.h in Headers */,
A7D8628214EBF65C001436AF /* NSString+DTPaths.h in Headers */,
A760F52D14F24B9F00AD1B0E /* DTASN1Parser.h in Headers */,
+ A7D6F2E615063448001CACDD /* DTExtendedFileAttributes.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -301,6 +310,7 @@
A77DD42614E825FC00F34B03 /* zip.h in Headers */,
A7D8628114EBF65C001436AF /* NSString+DTPaths.h in Headers */,
A760F52C14F24B9F00AD1B0E /* DTASN1Parser.h in Headers */,
+ A7D6F2E515063448001CACDD /* DTExtendedFileAttributes.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -350,7 +360,7 @@
A7F4DF9A147FB61500F4059A /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0420;
+ LastUpgradeCheck = 0430;
ORGANIZATIONNAME = Cocoanetics;
};
buildConfigurationList = A7F4DF9D147FB61500F4059A /* Build configuration list for PBXProject "DTFoundation" */;
@@ -445,6 +455,7 @@
A77DD42514E825FC00F34B03 /* zip.c in Sources */,
A7D8628414EBF65C001436AF /* NSString+DTPaths.m in Sources */,
A760F52F14F24B9F00AD1B0E /* DTASN1Parser.m in Sources */,
+ A7D6F2E815063448001CACDD /* DTExtendedFileAttributes.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -466,6 +477,7 @@
A77DD42414E825FC00F34B03 /* zip.c in Sources */,
A7D8628314EBF65C001436AF /* NSString+DTPaths.m in Sources */,
A760F52E14F24B9F00AD1B0E /* DTASN1Parser.m in Sources */,
+ A7D6F2E715063448001CACDD /* DTExtendedFileAttributes.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -482,6 +494,7 @@
DSTROOT = /tmp/DTFoundation.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Core/DTFoundation-Prefix.pch";
+ GCC_THUMB_SUPPORT = NO;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = DTFoundation;
PUBLIC_HEADERS_FOLDER_PATH = ../../DTFoundation;
@@ -499,6 +512,7 @@
DSTROOT = /tmp/DTFoundation.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Core/DTFoundation-Prefix.pch";
+ GCC_THUMB_SUPPORT = NO;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = DTFoundation;
PUBLIC_HEADERS_FOLDER_PATH = ../../DTFoundation;
@@ -572,6 +586,7 @@
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
@@ -593,6 +608,7 @@
CLANG_ENABLE_OBJC_ARC = YES;
COPY_PHASE_STRIP = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_THUMB_SUPPORT = NO;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
@@ -607,13 +623,15 @@
A7F4DFEF147FBAC600F4059A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ GCC_THUMB_SUPPORT = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
A7F4DFF0147FBAC600F4059A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ GCC_THUMB_SUPPORT = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;

0 comments on commit afcd623

Please sign in to comment.