gunzip.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibCompress/Gzip.h>
  7. #include <LibCore/ArgsParser.h>
  8. #include <LibCore/FileStream.h>
  9. #include <LibCore/System.h>
  10. #include <LibMain/Main.h>
  11. #include <unistd.h>
  12. static ErrorOr<void> decompress_file(NonnullOwnPtr<Core::Stream::File> input_stream, Buffered<Core::OutputFileStream>& output_stream)
  13. {
  14. auto gzip_stream = Compress::GzipDecompressor { move(input_stream) };
  15. auto buffer = TRY(ByteBuffer::create_uninitialized(4096));
  16. while (!gzip_stream.is_eof()) {
  17. auto span = TRY(gzip_stream.read(buffer));
  18. output_stream.write_or_error(span);
  19. }
  20. return {};
  21. }
  22. ErrorOr<int> serenity_main(Main::Arguments args)
  23. {
  24. Vector<StringView> filenames;
  25. bool keep_input_files { false };
  26. bool write_to_stdout { false };
  27. Core::ArgsParser args_parser;
  28. args_parser.add_option(keep_input_files, "Keep (don't delete) input files", "keep", 'k');
  29. args_parser.add_option(write_to_stdout, "Write to stdout, keep original files unchanged", "stdout", 'c');
  30. args_parser.add_positional_argument(filenames, "File to decompress", "FILE");
  31. args_parser.parse(args);
  32. if (write_to_stdout)
  33. keep_input_files = true;
  34. for (auto filename : filenames) {
  35. DeprecatedString input_filename;
  36. DeprecatedString output_filename;
  37. if (filename.ends_with(".gz"sv)) {
  38. input_filename = filename;
  39. output_filename = filename.substring_view(0, filename.length() - 3);
  40. } else {
  41. input_filename = DeprecatedString::formatted("{}.gz", filename);
  42. output_filename = filename;
  43. }
  44. auto input_stream_result = TRY(Core::Stream::File::open(input_filename, Core::Stream::OpenMode::Read));
  45. if (write_to_stdout) {
  46. auto stdout = Core::OutputFileStream::stdout_buffered();
  47. TRY(decompress_file(move(input_stream_result), stdout));
  48. } else {
  49. auto output_stream_result = TRY(Core::OutputFileStream::open_buffered(output_filename));
  50. TRY(decompress_file(move(input_stream_result), output_stream_result));
  51. }
  52. if (!keep_input_files)
  53. TRY(Core::System::unlink(input_filename));
  54. }
  55. return 0;
  56. }