Index: src/OFZooArchive.h ================================================================== --- src/OFZooArchive.h +++ src/OFZooArchive.h @@ -50,11 +50,12 @@ /** * @brief Creates a new OFZooArchive object with the specified stream. * * @param stream A stream from which the Zoo archive will be read. - * For read mode, this needs to be an OFSeekableStream. + * This needs to be an OFSeekableStream. For writing, the stream + * needs to support both reading and writing at the same time. * @param mode The mode for the Zoo file. Valid modes are "r" for reading and * "w" for creating a new file. * @return A new, autoreleased OFZooArchive */ + (instancetype)archiveWithStream: (OFStream *)stream mode: (OFString *)mode; @@ -85,11 +86,12 @@ /** * @brief Initializes an already allocated OFZooArchive object with the * specified stream. * * @param stream A stream from which the Zoo archive will be read. - * For read mode, this needs to be an OFSeekableStream. + * This needs to be an OFSeekableStream. For writing, the stream + * needs to support both reading and writing at the same time. * @param mode The mode for the Zoo file. Valid modes are "r" for reading and * "w" for creating a new file. * @return An initialized OFZooArchive */ - (instancetype)initWithStream: (OFStream *)stream Index: utils/ofarc/OFArc.m ================================================================== --- utils/ofarc/OFArc.m +++ utils/ofarc/OFArc.m @@ -510,11 +510,12 @@ case 'a': modeString = @"a"; fileModeString = @"r+"; break; case 'c': - modeString = fileModeString = @"w"; + modeString = @"w"; + fileModeString = @"w+"; break; case 'l': case 'p': case 'x': modeString = fileModeString = @"r"; Index: utils/ofarc/ZooArchive.m ================================================================== --- utils/ofarc/ZooArchive.m +++ utils/ofarc/ZooArchive.m @@ -432,6 +432,112 @@ @"File %[file] is not in the archive!", @"file", file)]; app->_exitStatus = 1; } } + +- (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files +{ + OFFileManager *fileManager = [OFFileManager defaultManager]; + + if (files.count < 1) { + [OFStdErr writeLine: OF_LOCALIZED(@"add_no_file_specified", + @"Need one or more files to add!")]; + app->_exitStatus = 1; + return; + } + + for (OFString *fileName in files) { + void *pool = objc_autoreleasePoolPush(); + OFFileAttributes attributes; + OFFileAttributeType type; + OFMutableZooArchiveEntry *entry; + OFStream *output; + + if (app->_outputLevel >= 0) + [OFStdOut writeString: OF_LOCALIZED(@"adding_file", + @"Adding %[file]...", + @"file", fileName)]; + + attributes = [fileManager attributesOfItemAtPath: fileName]; + type = attributes.fileType; + + if ([type isEqual: OFFileTypeDirectory]) { + if (app->_outputLevel >= 0) { + [OFStdOut writeString: @"\r"]; + [OFStdOut writeLine: OF_LOCALIZED( + @"adding_file_skipped", + @"Adding %[file]... skipped", + @"file", fileName)]; + } + + continue; + } + + entry = [OFMutableZooArchiveEntry entryWithFileName: fileName]; + entry.timeZone = [OFNumber numberWithFloat: 0]; + entry.modificationDate = attributes.fileModificationDate; +#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS + entry.POSIXPermissions = + [attributes objectForKey: OFFilePOSIXPermissions]; +#endif + + output = [_archive streamForWritingEntry: entry]; + + if ([type isEqual: OFFileTypeRegular]) { + unsigned long long written = 0; + unsigned long long size = attributes.fileSize; + int8_t percent = -1, newPercent; + + OFFile *input = [OFFile fileWithPath: fileName + mode: @"r"]; + + while (!input.atEndOfStream) { + ssize_t length = [app + copyBlockFromStream: input + toStream: output + fileName: fileName]; + + if (length < 0) { + app->_exitStatus = 1; + goto outer_loop_end; + } + + written += length; + newPercent = (written == size + ? 100 : (int8_t)(written * 100 / size)); + + if (app->_outputLevel >= 0 && + percent != newPercent) { + OFString *percentString; + + percent = newPercent; + percentString = [OFString + stringWithFormat: @"%3u", percent]; + + [OFStdOut writeString: @"\r"]; + [OFStdOut writeString: OF_LOCALIZED( + @"adding_file_percent", + @"Adding %[file]... %[percent]%", + @"file", fileName, + @"percent", percentString)]; + } + } + } + + if (app->_outputLevel >= 0) { + [OFStdOut writeString: @"\r"]; + [OFStdOut writeLine: OF_LOCALIZED( + @"adding_file_done", + @"Adding %[file]... done", + @"file", fileName)]; + } + + [output close]; + +outer_loop_end: + objc_autoreleasePoolPop(pool); + } + + [_archive close]; +} @end Index: utils/ofarc/localization/de.json ================================================================== --- utils/ofarc/localization/de.json +++ utils/ofarc/localization/de.json @@ -146,6 +146,7 @@ "Benötige eine oder mehrere Dateien zum Hinzufügen!" ], adding_file: "Füge %[file] hinzu...", adding_file_percent: "Füge %[file] hinzu... %[percent]%", adding_file_done: "Füge %[file] hinzu... fertig", + adding_file_skipped: "Füge %[file] hinzu... übersprungen", }