added arq_verify utility which verifies that all SHA1s referenced by all backups are available in your S3 account

This commit is contained in:
Stefan Reitshamer 2010-06-18 08:14:01 -04:00
parent ac79ae41ec
commit 4884a60a9d
14 changed files with 751 additions and 2 deletions

23
ArqVerifyCommand.h Normal file
View file

@ -0,0 +1,23 @@
//
// ArqVerifyCommand.h
// arq_restore
//
// Created by Stefan Reitshamer on 6/17/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class S3Service;
@interface ArqVerifyCommand : NSObject {
NSString *accessKey;
NSString *secretKey;
NSString *encryptionPassword;
S3Service *s3;
}
- (id)initWithAccessKey:(NSString *)theAccessKey secretKey:(NSString *)theSecretKey encryptionPassword:(NSString *)theEncryptionPassword;
- (BOOL)verifyAll:(NSError **)error;
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName error:(NSError **)error;
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID error:(NSError **)error;
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID bucketUUID:(NSString *)bucketUUID error:(NSError **)error;
@end

139
ArqVerifyCommand.m Normal file
View file

@ -0,0 +1,139 @@
//
// ArqVerifyCommand.m
// arq_restore
//
// Created by Stefan Reitshamer on 6/17/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "ArqVerifyCommand.h"
#import "S3AuthorizationProvider.h"
#import "S3Service.h"
#import "HTTP.h"
#import "RegexKitLite.h"
#import "BucketVerifier.h"
#import "PackSet.h"
@interface ArqVerifyCommand (internal)
- (NSArray *)objectSHA1sForS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID error:(NSError **)error;
@end
@implementation ArqVerifyCommand
- (id)initWithAccessKey:(NSString *)theAccessKey secretKey:(NSString *)theSecretKey encryptionPassword:(NSString *)theEncryptionPassword {
if (self = [super init]) {
accessKey = [theAccessKey retain];
secretKey = [theSecretKey retain];
encryptionPassword = [theEncryptionPassword retain];
S3AuthorizationProvider *sap = [[S3AuthorizationProvider alloc] initWithAccessKey:accessKey secretKey:secretKey];
s3 = [[S3Service alloc] initWithS3AuthorizationProvider:sap useSSL:NO retryOnNetworkError:YES];
[sap release];
}
return self;
}
- (void)dealloc {
[accessKey release];
[secretKey release];
[encryptionPassword release];
[s3 release];
[super dealloc];
}
- (BOOL)verifyAll:(NSError **)error {
NSArray *s3BucketNames = [S3Service s3BucketNamesForAccessKeyID:accessKey];
for (NSString *s3BucketName in s3BucketNames) {
printf("s3bucket name: %s\n", [s3BucketName UTF8String]);
}
for (NSString *s3BucketName in s3BucketNames) {
if (![self verifyS3BucketName:s3BucketName error:error]) {
return NO;
}
}
return YES;
}
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName error:(NSError **)error {
printf("verifying s3Bucket %s\n", [s3BucketName UTF8String]);
NSString *computerUUIDPrefix = [NSString stringWithFormat:@"/%@/", s3BucketName];
NSError *myError = nil;
NSArray *computerUUIDs = [s3 commonPrefixesForPathPrefix:computerUUIDPrefix delimiter:@"/" error:&myError];
if (computerUUIDs == nil) {
if ([[myError domain] isEqualToString:[S3Service serverErrorDomain]] && [myError code] == HTTP_NOT_FOUND) {
// Skip.
printf("no computer UUIDs found in bucket %s\n", [s3BucketName UTF8String]);
return YES;
} else {
if (error != NULL) {
*error = myError;
}
return NO;
}
}
for (NSString *computerUUID in computerUUIDs) {
printf("found computer UUID %s\n", [computerUUID UTF8String]);
}
for (NSString *computerUUID in computerUUIDs) {
if (![self verifyS3BucketName:s3BucketName computerUUID:computerUUID error:error]) {
return NO;
}
}
return YES;
}
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID error:(NSError **)error {
printf("verifying computerUUID %s s3Bucket %s\n", [computerUUID UTF8String], [s3BucketName UTF8String]);
NSString *computerBucketsPrefix = [NSString stringWithFormat:@"/%@/%@/buckets", s3BucketName, computerUUID];
NSArray *s3BucketUUIDPaths = [s3 pathsWithPrefix:computerBucketsPrefix error:error];
if (s3BucketUUIDPaths == nil) {
return NO;
}
NSArray *objectSHA1s = [self objectSHA1sForS3BucketName:s3BucketName computerUUID:computerUUID error:error];
if (objectSHA1s == nil) {
return NO;
}
for (NSString *s3BucketUUIDPath in s3BucketUUIDPaths) {
NSString *bucketUUID = [s3BucketUUIDPath lastPathComponent];
printf("verifying bucketUUID %s computerUUID %s s3Bucket %s\n", [bucketUUID UTF8String], [computerUUID UTF8String], [s3BucketName UTF8String]);
BucketVerifier *bucketVerifier = [[[BucketVerifier alloc] initWithS3Service:s3
s3BucketName:s3BucketName
computerUUID:computerUUID
bucketUUID:bucketUUID
s3ObjectSHA1s:objectSHA1s
encryptionKey:encryptionPassword] autorelease];
if (![bucketVerifier verify:error]) {
return NO;
}
}
return YES;
}
- (BOOL)verifyS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID bucketUUID:(NSString *)bucketUUID error:(NSError **)error {
NSArray *objectSHA1s = [self objectSHA1sForS3BucketName:s3BucketName computerUUID:computerUUID error:error];
if (objectSHA1s == nil) {
return NO;
}
printf("verifying bucketUUID %s computerUUID %s s3Bucket %s\n", [bucketUUID UTF8String], [computerUUID UTF8String], [s3BucketName UTF8String]);
BucketVerifier *bucketVerifier = [[[BucketVerifier alloc] initWithS3Service:s3
s3BucketName:s3BucketName
computerUUID:computerUUID
bucketUUID:bucketUUID
s3ObjectSHA1s:objectSHA1s
encryptionKey:encryptionPassword] autorelease];
if (![bucketVerifier verify:error]) {
return NO;
}
return YES;
}
@end
@implementation ArqVerifyCommand (internal)
- (NSArray *)objectSHA1sForS3BucketName:(NSString *)s3BucketName computerUUID:(NSString *)computerUUID error:(NSError **)error {
NSString *objectsPrefix = [NSString stringWithFormat:@"/%@/%@/objects", s3BucketName, computerUUID];
printf("loading S3 object SHA1s with prefix %s\n", [objectsPrefix UTF8String]);
NSArray *objectPaths = [s3 pathsWithPrefix:objectsPrefix error:error];
if (objectPaths == nil) {
return NO;
}
printf("loaded %u object SHA1s with prefix %s\n", [objectPaths count], [objectsPrefix UTF8String]);
NSMutableArray *objectSHA1s = [NSMutableArray array];
for (NSString *objectPath in objectPaths) {
[objectSHA1s addObject:[objectPath lastPathComponent]];
}
return objectSHA1s;
}
@end

View file

@ -63,4 +63,5 @@
- (NSString *)name;
- (ServerBlob *)newServerBlobForSHA1:(NSString *)sha1 error:(NSError **)error;
- (BOOL)containsBlobForSHA1:(NSString *)sha1;
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)blobSHA1;
@end

View file

@ -153,6 +153,13 @@ static double DEFAULT_MAX_REUSABLE_PACK_FILE_SIZE_FRACTION = 0.6;
- (BOOL)containsBlobForSHA1:(NSString *)sha1 {
return [packIndexEntries objectForKey:sha1] != nil;
}
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)blobSHA1 {
PackIndexEntry *pie = [packIndexEntries objectForKey:blobSHA1];
if (pie == nil) {
return nil;
}
return [pie packSHA1];
}
@end
@implementation PackSet (internal)

View file

@ -48,6 +48,7 @@
computerUUID:(NSString *)theComputerUUID;
- (ServerBlob *)newServerBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName error:(NSError **)error;
- (BOOL)containsBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName;
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName;
// Sync local cache files to S3 data; reload PackIndexEntries from local cache files.
- (BOOL)resetFromS3:(NSError **)error;

View file

@ -82,6 +82,15 @@
BOOL contains = [[packSets objectForKey:packSetName] containsBlobForSHA1:sha1];
return contains;
}
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName {
NSError *myError = nil;
PackSet *packSet = [self packSetForName:packSetName error:&myError];
if (packSet == nil) {
HSLogError(@"%@", [myError localizedDescription]);
return nil;
}
return [packSet packSHA1ForPackedBlobSHA1:sha1];
}
- (BOOL)resetFromS3:(NSError **)error {
HSLogDebug(@"resetting pack sets from S3");
[packSets removeAllObjects];

View file

@ -49,5 +49,6 @@
- (NSData *)dataForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName searchPackOnly:(BOOL)searchPackOnly error:(NSError **)error;
- (ServerBlob *)newServerBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName searchPackOnly:(BOOL)searchPackOnly error:(NSError **)error;
- (BOOL)containsBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName searchPackOnly:(BOOL)searchPackOnly;
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName;
- (BOOL)reloadPacksFromS3:(NSError **)error;
@end

View file

@ -96,6 +96,9 @@
}
return contains;
}
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName {
return [packSetSet packSHA1ForPackedBlobSHA1:sha1 packSetName:packSetName];
}
- (BOOL)reloadPacksFromS3:(NSError **)error {
NSAssert([NSThread currentThread] == creatorThread, @"must be on same thread!");
return [packSetSet resetFromS3:error];

View file

@ -71,6 +71,7 @@
- (BOOL)tree:(Tree **)tree forSHA1:(NSString *)theSHA1 error:(NSError **)error;
- (BOOL)containsBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName searchPackOnly:(BOOL)searchPackOnly;
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName;
- (NSData *)dataForSHA1:(NSString *)sha1 error:(NSError **)error;
- (ServerBlob *)newServerBlobForSHA1:(NSString *)sha1 error:(NSError **)error;
- (NSData *)dataForSHA1s:(NSArray *)sha1s error:(NSError **)error;

View file

@ -139,6 +139,9 @@ static NSString *ERROR_DOMAIN = @"S3RepoErrorDomain";
- (BOOL)containsBlobForSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName searchPackOnly:(BOOL)searchPackOnly {
return [fark containsBlobForSHA1:sha1 packSetName:packSetName searchPackOnly:searchPackOnly];
}
- (NSString *)packSHA1ForPackedBlobSHA1:(NSString *)sha1 packSetName:(NSString *)packSetName {
return [fark packSHA1ForPackedBlobSHA1:sha1 packSetName:packSetName];
}
- (NSData *)dataForSHA1:(NSString *)sha1 error:(NSError **)error {
NSData *data = [fark dataForSHA1:sha1 packSetName:treesPackSetName searchPackOnly:YES error:error];
if (data == nil) {

View file

@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
8DD76F9A0486AA7600D96B5E /* arq_restore.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* arq_restore.m */; settings = {ATTRIBUTES = (); }; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
F805B54D1160D3E6007EC01E /* ArqRestoreCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B54C1160D3E6007EC01E /* ArqRestoreCommand.m */; };
F805B7211160D9C2007EC01E /* HSLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7201160D9C2007EC01E /* HSLog.m */; };
@ -64,6 +63,103 @@
F805B8A11160EBAA007EC01E /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8A01160EBAA007EC01E /* CoreFoundation.framework */; };
F805B8C21160EC41007EC01E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8C11160EC41007EC01E /* Security.framework */; };
F805B8CE1160ECD7007EC01E /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8CD1160ECD7007EC01E /* CoreServices.framework */; };
F83C1A7411CA7C170001958F /* ArqRestoreCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B54C1160D3E6007EC01E /* ArqRestoreCommand.m */; };
F83C1A7511CA7C170001958F /* HSLog.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7201160D9C2007EC01E /* HSLog.m */; };
F83C1A7611CA7C170001958F /* ArqFolder.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B72F1160DBE9007EC01E /* ArqFolder.m */; };
F83C1A7711CA7C170001958F /* ArrayNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7421160DCFE007EC01E /* ArrayNode.m */; };
F83C1A7811CA7C170001958F /* BooleanNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7441160DCFE007EC01E /* BooleanNode.m */; };
F83C1A7911CA7C170001958F /* DictNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7461160DCFE007EC01E /* DictNode.m */; };
F83C1A7A11CA7C170001958F /* IntegerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7481160DCFE007EC01E /* IntegerNode.m */; };
F83C1A7B11CA7C170001958F /* RealNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B74C1160DCFE007EC01E /* RealNode.m */; };
F83C1A7C11CA7C170001958F /* StringNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B74E1160DCFE007EC01E /* StringNode.m */; };
F83C1A7D11CA7C170001958F /* XMLPListReader.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7501160DCFE007EC01E /* XMLPListReader.m */; };
F83C1A7E11CA7C170001958F /* XMLPListWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7521160DCFE007EC01E /* XMLPListWriter.m */; };
F83C1A7F11CA7C170001958F /* HTTPConnection_S3.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7691160DD60007EC01E /* HTTPConnection_S3.m */; };
F83C1A8011CA7C170001958F /* NSError_S3.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B76B1160DD60007EC01E /* NSError_S3.m */; };
F83C1A8111CA7C170001958F /* PathReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B76D1160DD60007EC01E /* PathReceiver.m */; };
F83C1A8211CA7C170001958F /* S3AuthorizationParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B76F1160DD60007EC01E /* S3AuthorizationParameters.m */; };
F83C1A8311CA7C170001958F /* S3AuthorizationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7711160DD60007EC01E /* S3AuthorizationProvider.m */; };
F83C1A8411CA7C170001958F /* S3Lister.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7731160DD60007EC01E /* S3Lister.m */; };
F83C1A8511CA7C170001958F /* S3ObjectMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7751160DD60007EC01E /* S3ObjectMetadata.m */; };
F83C1A8611CA7C170001958F /* S3ObjectReceiver.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7771160DD60007EC01E /* S3ObjectReceiver.m */; };
F83C1A8711CA7C170001958F /* S3Request.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B77C1160DD60007EC01E /* S3Request.m */; };
F83C1A8811CA7C170001958F /* S3Service.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B77E1160DD60007EC01E /* S3Service.m */; };
F83C1A8911CA7C170001958F /* S3Signature.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7801160DD60007EC01E /* S3Signature.m */; };
F83C1A8A11CA7C170001958F /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7A81160DEF2007EC01E /* RegexKitLite.m */; };
F83C1A8B11CA7C170001958F /* Blob.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7B91160E3AF007EC01E /* Blob.m */; };
F83C1A8C11CA7C170001958F /* HTTPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7CC1160E445007EC01E /* HTTPConnection.m */; };
F83C1A8D11CA7C170001958F /* HTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7CE1160E445007EC01E /* HTTPRequest.m */; };
F83C1A8E11CA7C170001958F /* HTTPResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7D01160E445007EC01E /* HTTPResponse.m */; };
F83C1A8F11CA7C170001958F /* BlobACL.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7D71160E456007EC01E /* BlobACL.m */; };
F83C1A9011CA7C170001958F /* ServerBlob.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7E01160E48B007EC01E /* ServerBlob.m */; };
F83C1A9111CA7C170001958F /* RFC2616DateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7FA1160E73D007EC01E /* RFC2616DateFormatter.m */; };
F83C1A9211CA7C170001958F /* RFC822.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B7FD1160E764007EC01E /* RFC822.m */; };
F83C1A9311CA7C170001958F /* InputStreams.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B81A1160E838007EC01E /* InputStreams.m */; };
F83C1A9411CA7C170001958F /* ChunkedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8221160E857007EC01E /* ChunkedInputStream.m */; };
F83C1A9511CA7C170001958F /* FixedLengthInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8241160E857007EC01E /* FixedLengthInputStream.m */; };
F83C1A9611CA7C170001958F /* FDInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8281160E861007EC01E /* FDInputStream.m */; };
F83C1A9711CA7C170001958F /* FDOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B82A1160E861007EC01E /* FDOutputStream.m */; };
F83C1A9811CA7C170001958F /* DataInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B82E1160E86E007EC01E /* DataInputStream.m */; };
F83C1A9911CA7C170001958F /* Writer.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8311160E878007EC01E /* Writer.m */; };
F83C1A9A11CA7C170001958F /* NSData-InputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B83A1160E8DD007EC01E /* NSData-InputStream.m */; };
F83C1A9B11CA7C170001958F /* StreamPairFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B83E1160E900007EC01E /* StreamPairFactory.m */; };
F83C1A9C11CA7C170001958F /* Streams.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8411160E90F007EC01E /* Streams.m */; };
F83C1A9D11CA7C170001958F /* CFStreamPair.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8521160E9B0007EC01E /* CFStreamPair.m */; };
F83C1A9E11CA7C170001958F /* CFStreamInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8571160E9C9007EC01E /* CFStreamInputStream.m */; };
F83C1A9F11CA7C170001958F /* CFStreamOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8591160E9C9007EC01E /* CFStreamOutputStream.m */; };
F83C1AA011CA7C170001958F /* DNS_SDErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B85F1160E9F0007EC01E /* DNS_SDErrors.m */; };
F83C1AA111CA7C170001958F /* NSXMLNode_extra.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8641160EA15007EC01E /* NSXMLNode_extra.m */; };
F83C1AA211CA7C170001958F /* NSData-Base64Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B8691160EA83007EC01E /* NSData-Base64Extensions.m */; };
F83C1AA311CA7C170001958F /* DataInputStreamFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = F805B86E1160EAC1007EC01E /* DataInputStreamFactory.m */; };
F83C1AA411CA7C170001958F /* Restorer.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D677FF1160F26A00CC270E /* Restorer.m */; };
F83C1AA511CA7C170001958F /* S3Fark.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678141160F4E300CC270E /* S3Fark.m */; };
F83C1AA611CA7C170001958F /* S3Repo.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678161160F4E300CC270E /* S3Repo.m */; };
F83C1AA711CA7C170001958F /* SHA1Hash.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6781C1160F4FD00CC270E /* SHA1Hash.m */; };
F83C1AA811CA7C170001958F /* PackSetSet.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6782A1160F5D000CC270E /* PackSetSet.m */; };
F83C1AA911CA7C170001958F /* PackSet.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6782C1160F5D000CC270E /* PackSet.m */; };
F83C1AAA11CA7C170001958F /* ArqUserLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678321160F62E00CC270E /* ArqUserLibrary.m */; };
F83C1AAB11CA7C170001958F /* PackIndexEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6783B1160F70100CC270E /* PackIndexEntry.m */; };
F83C1AAC11CA7C170001958F /* DiskPack.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678421160F74A00CC270E /* DiskPack.m */; };
F83C1AAD11CA7C170001958F /* DiskPackIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678441160F74A00CC270E /* DiskPackIndex.m */; };
F83C1AAE11CA7C170001958F /* Commit.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6785C1160F7CF00CC270E /* Commit.m */; };
F83C1AAF11CA7C170001958F /* Tree.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6785E1160F7CF00CC270E /* Tree.m */; };
F83C1AB011CA7C170001958F /* NSData-Encrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678641160F7FE00CC270E /* NSData-Encrypt.m */; };
F83C1AB111CA7C170001958F /* OpenSSL.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678691160F81100CC270E /* OpenSSL.m */; };
F83C1AB211CA7C170001958F /* DecryptedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6786E1160F84600CC270E /* DecryptedInputStream.m */; };
F83C1AB311CA7C170001958F /* CryptInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678731160F85D00CC270E /* CryptInputStream.m */; };
F83C1AB411CA7C170001958F /* FileInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678761160F86E00CC270E /* FileInputStream.m */; };
F83C1AB511CA7C170001958F /* DataIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678791160F8A000CC270E /* DataIO.m */; };
F83C1AB611CA7C170001958F /* DateIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6787B1160F8A000CC270E /* DateIO.m */; };
F83C1AB711CA7C170001958F /* DoubleIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6787D1160F8A000CC270E /* DoubleIO.m */; };
F83C1AB811CA7C170001958F /* IntegerIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6787F1160F8A000CC270E /* IntegerIO.m */; };
F83C1AB911CA7C170001958F /* StringIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678811160F8A000CC270E /* StringIO.m */; };
F83C1ABA11CA7C170001958F /* NSString_extra.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678881160F8CD00CC270E /* NSString_extra.m */; };
F83C1ABB11CA7C170001958F /* BinarySHA1.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6788B1160F8E500CC270E /* BinarySHA1.m */; };
F83C1ABC11CA7C170001958F /* NSFileManager_extra.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678991160FA2A00CC270E /* NSFileManager_extra.m */; };
F83C1ABD11CA7C170001958F /* FileOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6789C1160FA3900CC270E /* FileOutputStream.m */; };
F83C1ABE11CA7C170001958F /* FileInputStreamFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D6789F1160FA4800CC270E /* FileInputStreamFactory.m */; };
F83C1ABF11CA7C170001958F /* BooleanIO.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678A41160FA5F00CC270E /* BooleanIO.m */; };
F83C1AC011CA7C170001958F /* EncryptedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678A71160FA6A00CC270E /* EncryptedInputStream.m */; };
F83C1AC111CA7C170001958F /* CommitFailedFile.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678AE1160FAD900CC270E /* CommitFailedFile.m */; };
F83C1AC211CA7C170001958F /* Node.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678B71160FB2100CC270E /* Node.m */; };
F83C1AC311CA7C170001958F /* FileAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D67CEA1161363A00CC270E /* FileAttributes.m */; };
F83C1AC411CA7C170001958F /* XAttrSet.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D67CF11161366100CC270E /* XAttrSet.m */; };
F83C1AC511CA7C170001958F /* FileACL.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D67D041161384100CC270E /* FileACL.m */; };
F83C1AC611CA7C170001958F /* OSStatusDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D67D061161384100CC270E /* OSStatusDescription.m */; };
F83C1AC711CA7C170001958F /* RestoreNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D67F6F1161443600CC270E /* RestoreNode.m */; };
F83C1AC811CA7C170001958F /* arq_verify.m in Sources */ = {isa = PBXBuildFile; fileRef = F83C1A5F11CA7A6B0001958F /* arq_verify.m */; };
F83C1AC911CA7C170001958F /* ArqVerifyCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = F83C1A6211CA7BD20001958F /* ArqVerifyCommand.m */; };
F83C1ACB11CA7C170001958F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
F83C1ACC11CA7C170001958F /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8881160EB39007EC01E /* libcrypto.dylib */; };
F83C1ACD11CA7C170001958F /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B88A1160EB39007EC01E /* libicucore.dylib */; };
F83C1ACE11CA7C170001958F /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B88E1160EB45007EC01E /* libssl.dylib */; };
F83C1ACF11CA7C170001958F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8921160EB4E007EC01E /* SystemConfiguration.framework */; };
F83C1AD011CA7C170001958F /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8A01160EBAA007EC01E /* CoreFoundation.framework */; };
F83C1AD111CA7C170001958F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8C11160EC41007EC01E /* Security.framework */; };
F83C1AD211CA7C170001958F /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F805B8CD1160ECD7007EC01E /* CoreServices.framework */; };
F83C1AE311CA7C7C0001958F /* arq_restore.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* arq_restore.m */; };
F83C1D0A11CA929D0001958F /* BucketVerifier.m in Sources */ = {isa = PBXBuildFile; fileRef = F83C1D0911CA929D0001958F /* BucketVerifier.m */; };
F83C1D1D11CA95AF0001958F /* BucketVerifier.m in Sources */ = {isa = PBXBuildFile; fileRef = F83C1D0911CA929D0001958F /* BucketVerifier.m */; };
F8D678001160F26A00CC270E /* Restorer.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D677FF1160F26A00CC270E /* Restorer.m */; };
F8D678171160F4E300CC270E /* S3Fark.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678141160F4E300CC270E /* S3Fark.m */; };
F8D678181160F4E300CC270E /* S3Repo.m in Sources */ = {isa = PBXBuildFile; fileRef = F8D678161160F4E300CC270E /* S3Repo.m */; };
@ -112,6 +208,15 @@
);
runOnlyForDeploymentPostprocessing = 1;
};
F83C1AD311CA7C170001958F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@ -235,6 +340,12 @@
F805B8C11160EC41007EC01E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
F805B8C51160EC4E007EC01E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
F805B8CD1160ECD7007EC01E /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
F83C1A5F11CA7A6B0001958F /* arq_verify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = arq_verify.m; sourceTree = "<group>"; };
F83C1A6111CA7BD20001958F /* ArqVerifyCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArqVerifyCommand.h; sourceTree = "<group>"; };
F83C1A6211CA7BD20001958F /* ArqVerifyCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArqVerifyCommand.m; sourceTree = "<group>"; };
F83C1AD711CA7C170001958F /* arq_verify */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = arq_verify; sourceTree = BUILT_PRODUCTS_DIR; };
F83C1D0811CA929D0001958F /* BucketVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BucketVerifier.h; path = s3/BucketVerifier.h; sourceTree = "<group>"; };
F83C1D0911CA929D0001958F /* BucketVerifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BucketVerifier.m; path = s3/BucketVerifier.m; sourceTree = "<group>"; };
F8D6763E1160F22800CC270E /* SetNSError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetNSError.h; sourceTree = "<group>"; };
F8D677FE1160F26A00CC270E /* Restorer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Restorer.h; sourceTree = "<group>"; };
F8D677FF1160F26A00CC270E /* Restorer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Restorer.m; sourceTree = "<group>"; };
@ -326,6 +437,21 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
F83C1ACA11CA7C170001958F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
F83C1ACB11CA7C170001958F /* Foundation.framework in Frameworks */,
F83C1ACC11CA7C170001958F /* libcrypto.dylib in Frameworks */,
F83C1ACD11CA7C170001958F /* libicucore.dylib in Frameworks */,
F83C1ACE11CA7C170001958F /* libssl.dylib in Frameworks */,
F83C1ACF11CA7C170001958F /* SystemConfiguration.framework in Frameworks */,
F83C1AD011CA7C170001958F /* CoreFoundation.framework in Frameworks */,
F83C1AD111CA7C170001958F /* Security.framework in Frameworks */,
F83C1AD211CA7C170001958F /* CoreServices.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -354,6 +480,11 @@
F8D678321160F62E00CC270E /* ArqUserLibrary.m */,
F805B54B1160D3E6007EC01E /* ArqRestoreCommand.h */,
F805B54C1160D3E6007EC01E /* ArqRestoreCommand.m */,
F83C1A5F11CA7A6B0001958F /* arq_verify.m */,
F83C1A6111CA7BD20001958F /* ArqVerifyCommand.h */,
F83C1A6211CA7BD20001958F /* ArqVerifyCommand.m */,
F83C1D0811CA929D0001958F /* BucketVerifier.h */,
F83C1D0911CA929D0001958F /* BucketVerifier.m */,
F805B72E1160DBE9007EC01E /* ArqFolder.h */,
F805B72F1160DBE9007EC01E /* ArqFolder.m */,
F8D6785B1160F7CE00CC270E /* Commit.h */,
@ -414,6 +545,7 @@
isa = PBXGroup;
children = (
8DD76FA10486AA7600D96B5E /* arq_restore */,
F83C1AD711CA7C170001958F /* arq_verify */,
);
name = Products;
sourceTree = "<group>";
@ -622,6 +754,24 @@
productReference = 8DD76FA10486AA7600D96B5E /* arq_restore */;
productType = "com.apple.product-type.tool";
};
F83C1A7111CA7C170001958F /* arq_verify */ = {
isa = PBXNativeTarget;
buildConfigurationList = F83C1AD411CA7C170001958F /* Build configuration list for PBXNativeTarget "arq_verify" */;
buildPhases = (
F83C1A7211CA7C170001958F /* Sources */,
F83C1ACA11CA7C170001958F /* Frameworks */,
F83C1AD311CA7C170001958F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = arq_verify;
productInstallPath = "$(HOME)/bin";
productName = arq_restore;
productReference = F83C1AD711CA7C170001958F /* arq_verify */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -635,6 +785,7 @@
projectRoot = "";
targets = (
8DD76F960486AA7600D96B5E /* arq_restore */,
F83C1A7111CA7C170001958F /* arq_verify */,
);
};
/* End PBXProject section */
@ -644,7 +795,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8DD76F9A0486AA7600D96B5E /* arq_restore.m in Sources */,
F805B54D1160D3E6007EC01E /* ArqRestoreCommand.m in Sources */,
F805B7211160D9C2007EC01E /* HSLog.m in Sources */,
F805B7301160DBE9007EC01E /* ArqFolder.m in Sources */,
@ -729,6 +879,102 @@
F8D67D071161384100CC270E /* FileACL.m in Sources */,
F8D67D081161384100CC270E /* OSStatusDescription.m in Sources */,
F8D67F701161443600CC270E /* RestoreNode.m in Sources */,
F83C1AE311CA7C7C0001958F /* arq_restore.m in Sources */,
F83C1D0A11CA929D0001958F /* BucketVerifier.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F83C1A7211CA7C170001958F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F83C1AC811CA7C170001958F /* arq_verify.m in Sources */,
F83C1A7411CA7C170001958F /* ArqRestoreCommand.m in Sources */,
F83C1A7511CA7C170001958F /* HSLog.m in Sources */,
F83C1A7611CA7C170001958F /* ArqFolder.m in Sources */,
F83C1A7711CA7C170001958F /* ArrayNode.m in Sources */,
F83C1A7811CA7C170001958F /* BooleanNode.m in Sources */,
F83C1A7911CA7C170001958F /* DictNode.m in Sources */,
F83C1A7A11CA7C170001958F /* IntegerNode.m in Sources */,
F83C1A7B11CA7C170001958F /* RealNode.m in Sources */,
F83C1A7C11CA7C170001958F /* StringNode.m in Sources */,
F83C1A7D11CA7C170001958F /* XMLPListReader.m in Sources */,
F83C1A7E11CA7C170001958F /* XMLPListWriter.m in Sources */,
F83C1A7F11CA7C170001958F /* HTTPConnection_S3.m in Sources */,
F83C1A8011CA7C170001958F /* NSError_S3.m in Sources */,
F83C1A8111CA7C170001958F /* PathReceiver.m in Sources */,
F83C1A8211CA7C170001958F /* S3AuthorizationParameters.m in Sources */,
F83C1A8311CA7C170001958F /* S3AuthorizationProvider.m in Sources */,
F83C1A8411CA7C170001958F /* S3Lister.m in Sources */,
F83C1A8511CA7C170001958F /* S3ObjectMetadata.m in Sources */,
F83C1A8611CA7C170001958F /* S3ObjectReceiver.m in Sources */,
F83C1A8711CA7C170001958F /* S3Request.m in Sources */,
F83C1A8811CA7C170001958F /* S3Service.m in Sources */,
F83C1A8911CA7C170001958F /* S3Signature.m in Sources */,
F83C1A8A11CA7C170001958F /* RegexKitLite.m in Sources */,
F83C1A8B11CA7C170001958F /* Blob.m in Sources */,
F83C1A8C11CA7C170001958F /* HTTPConnection.m in Sources */,
F83C1A8D11CA7C170001958F /* HTTPRequest.m in Sources */,
F83C1A8E11CA7C170001958F /* HTTPResponse.m in Sources */,
F83C1A8F11CA7C170001958F /* BlobACL.m in Sources */,
F83C1A9011CA7C170001958F /* ServerBlob.m in Sources */,
F83C1A9111CA7C170001958F /* RFC2616DateFormatter.m in Sources */,
F83C1A9211CA7C170001958F /* RFC822.m in Sources */,
F83C1A9311CA7C170001958F /* InputStreams.m in Sources */,
F83C1A9411CA7C170001958F /* ChunkedInputStream.m in Sources */,
F83C1A9511CA7C170001958F /* FixedLengthInputStream.m in Sources */,
F83C1A9611CA7C170001958F /* FDInputStream.m in Sources */,
F83C1A9711CA7C170001958F /* FDOutputStream.m in Sources */,
F83C1A9811CA7C170001958F /* DataInputStream.m in Sources */,
F83C1A9911CA7C170001958F /* Writer.m in Sources */,
F83C1A9A11CA7C170001958F /* NSData-InputStream.m in Sources */,
F83C1A9B11CA7C170001958F /* StreamPairFactory.m in Sources */,
F83C1A9C11CA7C170001958F /* Streams.m in Sources */,
F83C1A9D11CA7C170001958F /* CFStreamPair.m in Sources */,
F83C1A9E11CA7C170001958F /* CFStreamInputStream.m in Sources */,
F83C1A9F11CA7C170001958F /* CFStreamOutputStream.m in Sources */,
F83C1AA011CA7C170001958F /* DNS_SDErrors.m in Sources */,
F83C1AA111CA7C170001958F /* NSXMLNode_extra.m in Sources */,
F83C1AA211CA7C170001958F /* NSData-Base64Extensions.m in Sources */,
F83C1AA311CA7C170001958F /* DataInputStreamFactory.m in Sources */,
F83C1AA411CA7C170001958F /* Restorer.m in Sources */,
F83C1AA511CA7C170001958F /* S3Fark.m in Sources */,
F83C1AA611CA7C170001958F /* S3Repo.m in Sources */,
F83C1AA711CA7C170001958F /* SHA1Hash.m in Sources */,
F83C1AA811CA7C170001958F /* PackSetSet.m in Sources */,
F83C1AA911CA7C170001958F /* PackSet.m in Sources */,
F83C1AAA11CA7C170001958F /* ArqUserLibrary.m in Sources */,
F83C1AAB11CA7C170001958F /* PackIndexEntry.m in Sources */,
F83C1AAC11CA7C170001958F /* DiskPack.m in Sources */,
F83C1AAD11CA7C170001958F /* DiskPackIndex.m in Sources */,
F83C1AAE11CA7C170001958F /* Commit.m in Sources */,
F83C1AAF11CA7C170001958F /* Tree.m in Sources */,
F83C1AB011CA7C170001958F /* NSData-Encrypt.m in Sources */,
F83C1AB111CA7C170001958F /* OpenSSL.m in Sources */,
F83C1AB211CA7C170001958F /* DecryptedInputStream.m in Sources */,
F83C1AB311CA7C170001958F /* CryptInputStream.m in Sources */,
F83C1AB411CA7C170001958F /* FileInputStream.m in Sources */,
F83C1AB511CA7C170001958F /* DataIO.m in Sources */,
F83C1AB611CA7C170001958F /* DateIO.m in Sources */,
F83C1AB711CA7C170001958F /* DoubleIO.m in Sources */,
F83C1AB811CA7C170001958F /* IntegerIO.m in Sources */,
F83C1AB911CA7C170001958F /* StringIO.m in Sources */,
F83C1ABA11CA7C170001958F /* NSString_extra.m in Sources */,
F83C1ABB11CA7C170001958F /* BinarySHA1.m in Sources */,
F83C1ABC11CA7C170001958F /* NSFileManager_extra.m in Sources */,
F83C1ABD11CA7C170001958F /* FileOutputStream.m in Sources */,
F83C1ABE11CA7C170001958F /* FileInputStreamFactory.m in Sources */,
F83C1ABF11CA7C170001958F /* BooleanIO.m in Sources */,
F83C1AC011CA7C170001958F /* EncryptedInputStream.m in Sources */,
F83C1AC111CA7C170001958F /* CommitFailedFile.m in Sources */,
F83C1AC211CA7C170001958F /* Node.m in Sources */,
F83C1AC311CA7C170001958F /* FileAttributes.m in Sources */,
F83C1AC411CA7C170001958F /* XAttrSet.m in Sources */,
F83C1AC511CA7C170001958F /* FileACL.m in Sources */,
F83C1AC611CA7C170001958F /* OSStatusDescription.m in Sources */,
F83C1AC711CA7C170001958F /* RestoreNode.m in Sources */,
F83C1AC911CA7C170001958F /* ArqVerifyCommand.m in Sources */,
F83C1D1D11CA95AF0001958F /* BucketVerifier.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -798,6 +1044,43 @@
};
name = Release;
};
F83C1AD511CA7C170001958F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = arq_restore_Prefix.pch;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = arq_verify;
SDKROOT = macosx10.5;
};
name = Debug;
};
F83C1AD611CA7C170001958F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = arq_restore_Prefix.pch;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = arq_restore;
SDKROOT = macosx10.5;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -819,6 +1102,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
F83C1AD411CA7C170001958F /* Build configuration list for PBXNativeTarget "arq_verify" */ = {
isa = XCConfigurationList;
buildConfigurations = (
F83C1AD511CA7C170001958F /* Debug */,
F83C1AD611CA7C170001958F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;

100
arq_verify.m Normal file
View file

@ -0,0 +1,100 @@
/*
Copyright (c) 2010, Stefan Reitshamer http://www.haystacksoftware.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the names of PhotoMinds LLC or Haystack Software, nor the names of
their contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <libgen.h>
#import <Foundation/Foundation.h>
#import "ArqVerifyCommand.h"
static void printUsage(const char *exeName) {
fprintf(stderr, "usage: %s [s3_bucket_name [computer_uuid [folder_uuid]]]\n", exeName);
}
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
setHSLogLevel(HSLOG_LEVEL_ERROR);
char *exePath = strdup(argv[0]);
char *exeName = basename(exePath);
char *cAccessKey = getenv("ARQ_ACCESS_KEY");
if (cAccessKey == NULL) {
fprintf(stderr, "%s: missing ARQ_ACCESS_KEY environment variable\n", exeName);
}
char *cSecretKey = getenv("ARQ_SECRET_KEY");
if (cSecretKey == NULL) {
fprintf(stderr, "%s: missing ARQ_SECRET_KEY environment variable\n", exeName);
}
char *cEncryptionPassword = getenv("ARQ_ENCRYPTION_PASSWORD");
if (cEncryptionPassword == NULL) {
fprintf(stderr, "%s: missing ARQ_ENCRYPTION_PASSWORD environment variable\n", exeName);
}
if (cAccessKey == NULL || cSecretKey == NULL || cEncryptionPassword == NULL) {
goto main_error;
}
NSString *accessKey = [NSString stringWithUTF8String:cAccessKey];
NSString *secretKey = [NSString stringWithUTF8String:cSecretKey];
NSString *encryptionPassword = [[NSString alloc] initWithUTF8String:cEncryptionPassword];
ArqVerifyCommand *cmd = [[[ArqVerifyCommand alloc] initWithAccessKey:accessKey secretKey:secretKey encryptionPassword:encryptionPassword] autorelease];
NSError *error = nil;
BOOL ret = NO;
if (argc == 1) {
if (![cmd verifyAll:&error]) {
NSLog(@"%@", [error localizedDescription]);
goto main_error;
}
} else if (argc == 2) {
if (!strcmp(argv[1], "-?") || !strcmp(argv[1], "-h")) {
printUsage(exeName);
goto main_error;
} else if (![cmd verifyS3BucketName:[NSString stringWithUTF8String:argv[1]] error:&error]) {
NSLog(@"%@", [error localizedDescription]);
goto main_error;
}
} else if (argc == 3) {
if (![cmd verifyS3BucketName:[NSString stringWithUTF8String:argv[1]] computerUUID:[NSString stringWithUTF8String:argv[2]] error:&error]) {
NSLog(@"%@", [error localizedDescription]);
goto main_error;
}
} else if (argc == 4) {
if (![cmd verifyS3BucketName:[NSString stringWithUTF8String:argv[1]] computerUUID:[NSString stringWithUTF8String:argv[2]] bucketUUID:[NSString stringWithUTF8String:argv[3]] error:&error]) {
NSLog(@"%@", [error localizedDescription]);
goto main_error;
}
} else {
printUsage(exeName);
goto main_error;
}
ret = YES;
main_error:
[pool drain];
free(exePath);
return ret ? 0 : 1;
}

25
s3/BucketVerifier.h Normal file
View file

@ -0,0 +1,25 @@
//
// BucketVerifier.h
// arq_restore
//
// Created by Stefan Reitshamer on 6/17/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class S3Service;
@class S3Fark;
@class S3Repo;
@interface BucketVerifier : NSObject {
S3Service *s3;
NSString *s3BucketName;
NSString *computerUUID;
NSString *bucketUUID;
NSArray *objectSHA1s;
S3Fark *fark;
S3Repo *repo;
}
- (id)initWithS3Service:(S3Service *)theS3 s3BucketName:(NSString *)theS3BucketName computerUUID:(NSString *)theComputerUUID bucketUUID:(NSString *)theBucketUUID s3ObjectSHA1s:(NSArray *)theObjectSHA1s encryptionKey:(NSString *)encryptionKey;
- (BOOL)verify:(NSError **)error;
@end

144
s3/BucketVerifier.m Normal file
View file

@ -0,0 +1,144 @@
//
// BucketVerifier.m
// arq_restore
//
// Created by Stefan Reitshamer on 6/17/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "BucketVerifier.h"
#import "S3Service.h"
#import "S3Fark.h"
#import "S3Repo.h"
#import "Commit.h"
#import "Tree.h"
#import "Node.h"
#import "SetNSError.h"
@interface BucketVerifier (internal)
- (BOOL)verifyTree:(NSString *)treeSHA1 path:(NSString *)path error:(NSError **)error;
- (BOOL)verify:(NSString *)sha1 error:(NSError **)error;
@end
@implementation BucketVerifier
- (id)initWithS3Service:(S3Service *)theS3 s3BucketName:(NSString *)theS3BucketName computerUUID:(NSString *)theComputerUUID bucketUUID:(NSString *)theBucketUUID s3ObjectSHA1s:(NSArray *)theObjectSHA1s encryptionKey:(NSString *)encryptionKey {
if (self = [super init]) {
s3 = [theS3 retain];
s3BucketName = [theS3BucketName retain];
computerUUID = [theComputerUUID retain];
bucketUUID = [theBucketUUID retain];
objectSHA1s = [theObjectSHA1s retain];
fark = [[S3Fark alloc] initWithS3Service:s3 s3BucketName:s3BucketName computerUUID:computerUUID];
repo = [[S3Repo alloc] initWithS3Service:s3 s3BucketName:s3BucketName computerUUID:computerUUID bucketUUID:bucketUUID encrypted:YES encryptionKey:encryptionKey fark:fark ensureCacheIntegrity:YES];
}
return self;
}
- (void)dealloc {
[s3 release];
[s3BucketName release];
[computerUUID release];
[bucketUUID release];
[objectSHA1s release];
[fark release];
[repo release];
[super dealloc];
}
- (BOOL)verify:(NSError **)error {
printf("reloading packs from S3 for s3Bucket %s computerUUID %s bucketUUID %s\n", [s3BucketName UTF8String], [computerUUID UTF8String], [bucketUUID UTF8String]);
if (![fark reloadPacksFromS3:error]) {
return NO;
}
NSString *headSHA1 = nil;
if (![repo localHeadSHA1:&headSHA1 error:error]) {
return NO;
}
if (headSHA1 == nil) {
printf("no head commit for s3Bucket %s computerUUID %s bucketUUID %s\n", [s3BucketName UTF8String], [computerUUID UTF8String], [bucketUUID UTF8String]);
return YES;
}
printf("head commit for s3Bucket %s computerUUID %s bucketUUID %s is %s\n", [s3BucketName UTF8String], [computerUUID UTF8String], [bucketUUID UTF8String], [headSHA1 UTF8String]);
NSString *commitSHA1 = headSHA1;
while (commitSHA1 != nil) {
printf("verifying commit %s bucketUUID %s\n", [commitSHA1 UTF8String], [bucketUUID UTF8String]);
Commit *commit = nil;
if (![repo commit:&commit forSHA1:commitSHA1 error:error]) {
return NO;
}
printf("commit %s's tree is %s\n", [commitSHA1 UTF8String], [[commit treeSHA1] UTF8String]);
if (![self verifyTree:[commit treeSHA1] path:@"/" error:error]) {
return NO;
}
commitSHA1 = [[commit parentCommitSHA1s] anyObject];
}
return YES;
}
@end
@implementation BucketVerifier (internal)
- (BOOL)verifyTree:(NSString *)treeSHA1 path:(NSString *)path error:(NSError **)error {
printf("verifying tree %s (path %s)\n", [treeSHA1 UTF8String], [path UTF8String]);
Tree *tree = nil;
if (![repo tree:&tree forSHA1:treeSHA1 error:error]) {
fprintf(stderr, "tree %s not found\n", [treeSHA1 UTF8String]);
return NO;
}
if (![self verify:[tree xattrsSHA1] error:error]) {
fprintf(stderr, "tree %s's xattrsSHA1 %s not found", [treeSHA1 UTF8String], [[tree xattrsSHA1] UTF8String]);
return NO;
}
if (![self verify:[tree aclSHA1] error:error]) {
fprintf(stderr, "tree %s's aclSHA1 %s not found", [treeSHA1 UTF8String], [[tree aclSHA1] UTF8String]);
return NO;
}
for (NSString *childNodeName in [tree childNodeNames]) {
Node *node = [tree childNodeWithName:childNodeName];
NSArray *dataSHA1s = [node dataSHA1s];
NSString *childPath = [path stringByAppendingPathComponent:childNodeName];
if ([node isTree]) {
NSAssert([dataSHA1s count] == 1, ([NSString stringWithFormat:@"tree %@ node %@ must have exactly 1 dataSHA1", treeSHA1, childNodeName]));
if (![self verifyTree:[dataSHA1s objectAtIndex:0] path:childPath error:error]) {
return NO;
}
} else {
printf("verifying node %s\n", [childPath UTF8String]);
for (NSString *dataSHA1 in dataSHA1s) {
if (![self verify:dataSHA1 error:error]) {
HSLogError(@"missing data sha1 %@ for node %@ in tree %@", dataSHA1, childNodeName, treeSHA1);
return NO;
}
}
if (![self verify:[node thumbnailSHA1] error:error]) {
HSLogError(@"missing thumbnail sha1 %@ for node %@ in tree %@", [node thumbnailSHA1], childNodeName, treeSHA1);
return NO;
}
if (![self verify:[node previewSHA1] error:error]) {
HSLogError(@"missing preview sha1 %@ for node %@ in tree %@", [node previewSHA1], childNodeName, treeSHA1);
return NO;
}
if (![self verify:[node xattrsSHA1] error:error]) {
HSLogError(@"missing xattrs sha1 %@ for node %@ in tree %@", [node xattrsSHA1], childNodeName, treeSHA1);
return NO;
}
if (![self verify:[node aclSHA1] error:error]) {
HSLogError(@"missing acl sha1 %@ for node %@ in tree %@", [node aclSHA1], childNodeName, treeSHA1);
return NO;
}
}
}
return YES;
}
- (BOOL)verify:(NSString *)sha1 error:(NSError **)error {
if (sha1 != nil) {
if ([objectSHA1s containsObject:sha1]) {
printf("sha1 %s: blob\n", [sha1 UTF8String]);
} else if ([repo containsBlobForSHA1:sha1 packSetName:[repo blobsPackSetName] searchPackOnly:YES]) {
printf("sha1 %s: pack set %s, packSHA1 %s\n", [sha1 UTF8String], [[repo blobsPackSetName] UTF8String], [[repo packSHA1ForPackedBlobSHA1:sha1 packSetName:[repo blobsPackSetName]] UTF8String]);
} else {
SETNSERROR(@"VerifierErrorDomain", -1, @"sha1 %@ not found", sha1);
return NO;
}
}
return YES;
}
@end