Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -293,10 +293,13 @@ return [[_lastReturnedStream retain] autorelease]; } - (void)close { + if (_stream == nil) + return; + [_lastReturnedStream close]; [_lastReturnedStream release]; _lastReturnedStream = nil; if (_mode == OF_TAR_ARCHIVE_MODE_WRITE || @@ -475,10 +478,13 @@ return [_stream fileDescriptorForWriting]; } - (void)close { + if (_stream == nil) + return; + uint64_t remainder = 512 - [_entry size] % 512; if (_toWrite > 0) @throw [OFTruncatedDataException exception]; Index: utils/ofzip/OFZIP.m ================================================================== --- utils/ofzip/OFZIP.m +++ utils/ofzip/OFZIP.m @@ -274,16 +274,35 @@ if (outputDir != nil) [[OFFileManager defaultManager] changeCurrentDirectoryPath: outputDir]; switch (mode) { + case 'a': + case 'c': + if ([remainingArguments count] < 1) + help(of_stderr, false, 1); + + files = [remainingArguments objectsInRange: + of_range(1, [remainingArguments count] - 1)]; + + [archive addFiles: files]; + break; case 'l': if ([remainingArguments count] != 1) help(of_stderr, false, 1); [archive listFiles]; break; + case 'p': + if ([remainingArguments count] < 1) + help(of_stderr, false, 1); + + files = [remainingArguments objectsInRange: + of_range(1, [remainingArguments count] - 1)]; + + [archive printFiles: files]; + break; case 'x': if ([remainingArguments count] < 1) help(of_stderr, false, 1); files = [remainingArguments objectsInRange: @@ -314,19 +333,10 @@ @"error", error)]; _exitStatus = 1; } break; - case 'p': - if ([remainingArguments count] < 1) - help(of_stderr, false, 1); - - files = [remainingArguments objectsInRange: - of_range(1, [remainingArguments count] - 1)]; - - [archive printFiles: files]; - break; default: help(of_stderr, true, 1); break; } Index: utils/ofzip/TarArchive.m ================================================================== --- utils/ofzip/TarArchive.m +++ utils/ofzip/TarArchive.m @@ -424,6 +424,119 @@ @"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) { + [of_stderr 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(); + OFMutableTarArchiveEntry *entry; + OFStream *output; + + if (app->_outputLevel >= 0) + [of_stdout writeString: OF_LOCALIZED(@"adding_file", + @"Adding %[file]...", + @"file", fileName)]; + + entry = [OFMutableTarArchiveEntry entryWithFileName: fileName]; + +#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS + [entry setMode: + [fileManager permissionsOfItemAtPath: fileName]]; +#endif + [entry setSize: [fileManager sizeOfFileAtPath: fileName]]; + [entry setModificationDate: + [fileManager modificationTimeOfItemAtPath: fileName]]; + +#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER + OFString *owner, *group; + [fileManager getOwner: &owner + group: &group + ofItemAtPath: fileName]; + [entry setOwner: owner]; + [entry setGroup: group]; +#endif + + if ([fileManager fileExistsAtPath: fileName]) + [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_FILE]; + else if ([fileManager directoryExistsAtPath: fileName]) { + [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY]; + [entry setSize: 0]; + } else if ([fileManager symbolicLinkExistsAtPath: fileName]) { + [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK]; + [entry setTargetFileName: [fileManager + destinationOfSymbolicLinkAtPath: fileName]]; + [entry setSize: 0]; + } + + [entry makeImmutable]; + + output = [_archive streamForWritingEntry: entry]; + + if ([entry type] == OF_TAR_ARCHIVE_ENTRY_TYPE_FILE) { + uint64_t written = 0, size = [entry size]; + int8_t percent = -1, newPercent; + + OFFile *input = [OFFile fileWithPath: fileName + mode: @"r"]; + + while (![input isAtEndOfStream]) { + 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]; + + [of_stdout writeString: @"\r"]; + [of_stdout writeString: OF_LOCALIZED( + @"adding_file_percent", + @"Adding %[file]... %[percent]%", + @"file", fileName, + @"percent", percentString)]; + } + } + } + + if (app->_outputLevel >= 0) { + [of_stdout writeString: @"\r"]; + [of_stdout writeLine: OF_LOCALIZED( + @"adding_file_done", + @"Adding %[file]... done", + @"file", fileName)]; + } + + [output close]; + +outer_loop_end: + objc_autoreleasePoolPop(pool); + } + + [_archive close]; +} @end Index: utils/ofzip/lang/de.json ================================================================== --- utils/ofzip/lang/de.json +++ utils/ofzip/lang/de.json @@ -88,7 +88,13 @@ "list_comment": "Kommentar: %[comment]", "refusing_to_extract_file": "Verweigere Entpacken von %[file]!", "file_not_in_archive": "Datei %[file] ist nicht im Archiv!", "print_no_file_specified": [ "Benötige eine oder mehrere Dateien zum Ausgeben!" - ] + ], + "add_no_file_specified": [ + "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" }