@@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2022 Jonathan Schleifer + * Copyright (c) 2008-2024 Jonathan Schleifer * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in @@ -31,10 +31,11 @@ #import "OFArc.h" #import "OFInvalidFormatException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" +#import "OFSetItemAttributesFailedException.h" static OFArc *app; static void setPermissions(OFString *path, OFZIPArchiveEntry *entry) @@ -64,39 +65,49 @@ return; attributes = [OFDictionary dictionaryWithObject: modificationDate forKey: OFFileModificationDate]; - [[OFFileManager defaultManager] setAttributes: attributes - ofItemAtPath: path]; + @try { + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; + } @catch (OFSetItemAttributesFailedException *e) { + if (e.errNo != EISDIR) + @throw e; + } } @implementation ZIPArchive + (void)initialize { if (self == [ZIPArchive class]) app = (OFArc *)[OFApplication sharedApplication].delegate; } -+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding ++ (instancetype)archiveWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { - return [[[self alloc] initWithStream: stream - mode: mode - encoding: encoding] autorelease]; + return [[[self alloc] initWithPath: path + stream: stream + mode: mode + encoding: encoding] autorelease]; } -- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream - mode: (OFString *)mode - encoding: (OFStringEncoding)encoding +- (instancetype)initWithPath: (OFString *)path + stream: (OF_KINDOF(OFStream *))stream + mode: (OFString *)mode + encoding: (OFStringEncoding)encoding { self = [super init]; @try { + _path = [path copy]; _archive = [[OFZIPArchive alloc] initWithStream: stream mode: mode]; + _archive.delegate = self; } @catch (id e) { [self release]; @throw e; } @@ -103,14 +114,37 @@ return self; } - (void)dealloc { + [_path release]; [_archive release]; [super dealloc]; } + +- (OFSeekableStream *)archive: (OFZIPArchive *)archive + wantsPartNumbered: (unsigned int)partNumber + lastPartNumber: (unsigned int)lastPartNumber +{ + OFString *path; + + if ([_path.pathExtension caseInsensitiveCompare: @"zip"] != + OFOrderedSame) + return nil; + + if (partNumber > 98) + return nil; + + if (partNumber == lastPartNumber) + path = _path; + else + path = [_path.stringByDeletingPathExtension + stringByAppendingFormat: @".z%02u", partNumber + 1]; + + return [OFFile fileWithPath: path mode: @"r"]; +} - (void)listFiles { for (OFZIPArchiveEntry *entry in _archive.entries) { void *pool = objc_autoreleasePoolPush();