Index: src/OFTarArchive.h ================================================================== --- src/OFTarArchive.h +++ src/OFTarArchive.h @@ -36,10 +36,14 @@ OFTarArchiveModeRead, OFTarArchiveModeWrite, OFTarArchiveModeAppend } _mode; OFStringEncoding _encoding; + OFTarArchiveEntry *_Nullable _currentEntry; +#ifdef OF_TAR_ARCHIVE_M +@public +#endif OFStream *_Nullable _lastReturnedStream; } /** * @brief The encoding to use for the archive. Defaults to UTF-8. Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -11,10 +11,12 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ +#define OF_TAR_ARCHIVE_M + #include "config.h" #include #import "OFTarArchive.h" @@ -34,31 +36,35 @@ #import "OFWriteFailedException.h" OF_DIRECT_MEMBERS @interface OFTarArchiveFileReadStream: OFStream { + OFTarArchive *_archive; OFTarArchiveEntry *_entry; OFStream *_stream; unsigned long long _toRead; bool _atEndOfStream, _skipped; } -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFTarArchiveEntry *)entry; +- (instancetype)of_initWithArchive: (OFTarArchive *)archive + stream: (OFStream *)stream + entry: (OFTarArchiveEntry *)entry; - (void)of_skip; @end OF_DIRECT_MEMBERS @interface OFTarArchiveFileWriteStream: OFStream { + OFTarArchive *_archive; OFTarArchiveEntry *_entry; OFStream *_stream; unsigned long long _toWrite; } -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFTarArchiveEntry *)entry; +- (instancetype)of_initWithArchive: (OFTarArchive *)archive + stream: (OFStream *)stream + entry: (OFTarArchiveEntry *)entry; @end @implementation OFTarArchive: OFObject @synthesize encoding = _encoding; @@ -153,29 +159,32 @@ - (void)dealloc { [self close]; + [_currentEntry release]; + [super dealloc]; } - (OFTarArchiveEntry *)nextEntry { - OFTarArchiveEntry *entry; uint32_t buffer[512 / sizeof(uint32_t)]; bool empty = true; if (_mode != OFTarArchiveModeRead) @throw [OFInvalidArgumentException exception]; + + [_currentEntry release]; + _currentEntry = nil; [(OFTarArchiveFileReadStream *)_lastReturnedStream of_skip]; @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; if (_stream.atEndOfStream) return nil; @@ -193,60 +202,55 @@ @throw [OFInvalidFormatException exception]; return nil; } - entry = [[[OFTarArchiveEntry alloc] + _currentEntry = [[OFTarArchiveEntry alloc] of_initWithHeader: (unsigned char *)buffer - encoding: _encoding] autorelease]; + encoding: _encoding]; - _lastReturnedStream = [[OFTarArchiveFileReadStream alloc] - of_initWithStream: _stream - entry: entry]; - - return entry; + return _currentEntry; } - (OFStream *)streamForReadingCurrentEntry { if (_mode != OFTarArchiveModeRead) @throw [OFInvalidArgumentException exception]; - if (_lastReturnedStream == nil) + if (_currentEntry == nil) @throw [OFInvalidArgumentException exception]; - return [[(OFTarArchiveFileReadStream *)_lastReturnedStream - retain] autorelease]; + _lastReturnedStream = [[[OFTarArchiveFileReadStream alloc] + of_initWithArchive: self + stream: _stream + entry: _currentEntry] autorelease]; + [_currentEntry release]; + _currentEntry = nil; + + return _lastReturnedStream; } - (OFStream *)streamForWritingEntry: (OFTarArchiveEntry *)entry { - void *pool; - if (_mode != OFTarArchiveModeWrite && _mode != OFTarArchiveModeAppend) @throw [OFInvalidArgumentException exception]; - pool = objc_autoreleasePoolPush(); - @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; [entry of_writeToStream: _stream encoding: _encoding]; - _lastReturnedStream = [[OFTarArchiveFileWriteStream alloc] - of_initWithStream: _stream - entry: entry]; - - objc_autoreleasePoolPop(pool); - - return [[(OFTarArchiveFileWriteStream *)_lastReturnedStream - retain] autorelease]; + _lastReturnedStream = [[[OFTarArchiveFileWriteStream alloc] + of_initWithArchive: self + stream: _stream + entry: entry] autorelease]; + + return _lastReturnedStream; } - (void)close { if (_stream == nil) @@ -255,11 +259,10 @@ @try { [_lastReturnedStream close]; } @catch (OFNotOpenException *e) { /* Might have already been closed by the user - that's fine. */ } - [_lastReturnedStream release]; _lastReturnedStream = nil; if (_mode == OFTarArchiveModeWrite || _mode == OFTarArchiveModeAppend) { char buffer[1024]; memset(buffer, '\0', 1024); @@ -270,16 +273,18 @@ _stream = nil; } @end @implementation OFTarArchiveFileReadStream -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFTarArchiveEntry *)entry +- (instancetype)of_initWithArchive: (OFTarArchive *)archive + stream: (OFStream *)stream + entry: (OFTarArchiveEntry *)entry { self = [super init]; @try { + _archive = [archive retain]; _entry = [entry copy]; _stream = [stream retain]; _toRead = entry.uncompressedSize; } @catch (id e) { [self release]; @@ -294,15 +299,17 @@ if (_stream != nil) [self close]; [_entry release]; + if (_archive->_lastReturnedStream == self) + _archive->_lastReturnedStream = nil; + [super dealloc]; } -- (size_t)lowlevelReadIntoBuffer: (void *)buffer - length: (size_t)length +- (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { size_t ret; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; @@ -406,16 +413,18 @@ _skipped = true; } @end @implementation OFTarArchiveFileWriteStream -- (instancetype)of_initWithStream: (OFStream *)stream - entry: (OFTarArchiveEntry *)entry +- (instancetype)of_initWithArchive: (OFTarArchive *)archive + stream: (OFStream *)stream + entry: (OFTarArchiveEntry *)entry { self = [super init]; @try { + _archive = [archive retain]; _entry = [entry copy]; _stream = [stream retain]; _toWrite = entry.uncompressedSize; } @catch (id e) { [self release]; @@ -429,10 +438,13 @@ { if (_stream != nil) [self close]; [_entry release]; + + if (_archive->_lastReturnedStream == self) + _archive->_lastReturnedStream = nil; [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -310,10 +310,11 @@ } - (void)of_writeToStream: (OFStream *)stream encoding: (OFStringEncoding)encoding { + void *pool = objc_autoreleasePoolPush(); unsigned char buffer[512]; unsigned long long modificationDate; uint16_t checksum = 0; stringToBuffer(buffer, _fileName, 100, encoding); @@ -361,7 +362,9 @@ stringToBuffer(buffer + 148, [OFString stringWithFormat: @"%06" PRIo16, checksum], 7, OFStringEncodingASCII); [stream writeBuffer: buffer length: sizeof(buffer)]; + + objc_autoreleasePoolPop(pool); } @end