mirror of
https://github.com/samsonjs/arq_restore.git
synced 2026-03-25 09:25:53 +00:00
103 lines
3.2 KiB
Objective-C
103 lines
3.2 KiB
Objective-C
//
|
|
// PackIndexWriter.m
|
|
// Arq
|
|
//
|
|
// Created by Stefan Reitshamer on 3/3/10.
|
|
// Copyright 2010 __MyCompanyName__. All rights reserved.
|
|
//
|
|
|
|
#import "PackIndexWriter.h"
|
|
#import "DiskPack.h"
|
|
#import "FileInputStream.h"
|
|
#import "FileOutputStream.h"
|
|
#import "IntegerIO.h"
|
|
#import "StringIO.h"
|
|
#import "SetNSError.h"
|
|
#import "SHA1Hash.h"
|
|
#import "NSString_extra.h"
|
|
#import "PackIndexEntry.h"
|
|
|
|
@interface PackIndexWriter (internal)
|
|
- (BOOL)writeEntries:(NSArray *)entries toStream:(id <OutputStream>)os error:(NSError **)error;
|
|
@end
|
|
|
|
@implementation PackIndexWriter
|
|
- (id)initWithPack:(DiskPack *)theDiskPack destination:(NSString *)theDestination {
|
|
if (self = [super init]) {
|
|
diskPack = [theDiskPack retain];
|
|
destination = [theDestination copy];
|
|
}
|
|
return self;
|
|
}
|
|
- (void)dealloc {
|
|
[diskPack release];
|
|
[destination release];
|
|
[super dealloc];
|
|
}
|
|
- (BOOL)writeIndex:(NSError **)error {
|
|
NSArray *entries = [diskPack sortedPackIndexEntries:error];
|
|
if (entries == nil) {
|
|
return NO;
|
|
}
|
|
FileOutputStream *fos = [[FileOutputStream alloc] initWithPath:destination append:NO];
|
|
BOOL ret = [self writeEntries:entries toStream:fos error:error];
|
|
[fos release];
|
|
if (!ret) {
|
|
return NO;
|
|
}
|
|
NSString *indexSHA1 = [SHA1Hash hashFile:destination error:error];
|
|
NSData *sha1Data = [indexSHA1 hexStringToData];
|
|
fos = [[FileOutputStream alloc] initWithPath:destination append:YES];
|
|
ret = [fos write:[sha1Data bytes] length:[sha1Data length] error:error];
|
|
[fos release];
|
|
return ret;
|
|
}
|
|
@end
|
|
|
|
@implementation PackIndexWriter (internal)
|
|
- (BOOL)writeEntries:(NSArray *)entries toStream:(id <OutputStream>)os error:(NSError **)error {
|
|
// Write header to index.
|
|
if (![IntegerIO writeUInt32:0xff744f63 to:os error:error]) { // Magic number.
|
|
return NO;
|
|
}
|
|
if (![IntegerIO writeUInt32:0x00000002 to:os error:error]) { // Version 2.
|
|
return NO;
|
|
}
|
|
unsigned int firstByte = 0;
|
|
NSUInteger index = 0;
|
|
for (index = 0; index < [entries count]; index++) {
|
|
PackIndexEntry *pie = [entries objectAtIndex:index];
|
|
NSData *sha1Hex = [[pie objectSHA1] hexStringToData];
|
|
unsigned char myFirstByte = ((unsigned char *)[sha1Hex bytes])[0];
|
|
while ((unsigned int)myFirstByte > firstByte) {
|
|
if (![IntegerIO writeUInt32:index to:os error:error]) {
|
|
return NO;
|
|
}
|
|
firstByte++;
|
|
}
|
|
}
|
|
while (firstByte <= 0xff) {
|
|
if (![IntegerIO writeUInt32:index to:os error:error]) {
|
|
return NO;
|
|
}
|
|
firstByte++;
|
|
}
|
|
for (index = 0; index < [entries count]; index++) {
|
|
PackIndexEntry *pie = [entries objectAtIndex:index];
|
|
if (![IntegerIO writeUInt64:[pie offset] to:os error:error]
|
|
|| ![IntegerIO writeUInt64:[pie dataLength] to:os error:error]) {
|
|
return NO;
|
|
}
|
|
// Write sha1 to index.
|
|
NSData *sha1Data = [[pie objectSHA1] hexStringToData];
|
|
if (![os write:[sha1Data bytes] length:[sha1Data length] error:error]) {
|
|
break;
|
|
}
|
|
// Write 4 bytes (for alignment) to index.
|
|
if (![IntegerIO writeUInt32:0 to:os error:error]) {
|
|
return NO;
|
|
}
|
|
}
|
|
return YES;
|
|
}
|
|
@end
|