@@ -1,7 +1,7 @@ /* - * Copyright (c) 2008-2021 Jonathan Schleifer + * Copyright (c) 2008-2022 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 @@ -40,10 +40,11 @@ #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" #import "OFSeekFailedException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedVersionException.h" +#import "OFWriteFailedException.h" /* * FIXME: Current limitations: * - Split archives are not supported. * - Encrypted files cannot be read. @@ -432,10 +433,13 @@ void *pool = objc_autoreleasePoolPush(); OFZIPArchiveEntry *entry; OFZIPArchiveLocalFileHeader *localFileHeader; int64_t offset64; + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; + if (_mode != modeRead) @throw [OFInvalidArgumentException exception]; if ((entry = [_pathToEntryMap objectForKey: path]) == nil) @throw [OFOpenItemFailedException exceptionWithPath: path @@ -482,10 +486,13 @@ OFMutableZIPArchiveEntry *entry; OFString *fileName; OFData *extraField; uint16_t fileNameLength, extraFieldLength; + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; + if (_mode != modeWrite && _mode != modeAppend) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); entry = [[entry_ mutableCopy] autorelease]; @@ -874,26 +881,36 @@ [super dealloc]; } - (size_t)lowlevelWriteBuffer: (const void *)buffer length: (size_t)length { - size_t bytesWritten; - #if SIZE_MAX >= INT64_MAX if (length > INT64_MAX) @throw [OFOutOfRangeException exception]; #endif if (INT64_MAX - _bytesWritten < (int64_t)length) @throw [OFOutOfRangeException exception]; - bytesWritten = [_stream writeBuffer: buffer length: length]; + @try { + [_stream writeBuffer: buffer length: length]; + } @catch (OFWriteFailedException *e) { + OFEnsure(e.bytesWritten <= length); + + _bytesWritten += (int64_t)e.bytesWritten; + _CRC32 = OFCRC32(_CRC32, buffer, e.bytesWritten); + + if (e.errNo == EWOULDBLOCK || e.errNo == EAGAIN) + return e.bytesWritten; + + @throw e; + } - _bytesWritten += (int64_t)bytesWritten; + _bytesWritten += (int64_t)length; _CRC32 = OFCRC32(_CRC32, buffer, length); - return bytesWritten; + return length; } - (void)close { if (_stream == nil)